/* =============================================================================
   Pointio — feuille de style.
   
   Reproduit le design system des maquettes Stitch (thème « high-density
   terminal ») sans Tailwind : les maquettes chargeaient cdn.tailwindcss.com, ce
   que la règle « tout sur le VPS » interdit. Plutôt que de réinventer un
   vocabulaire de classes, les utilitaires employés par les maquettes sont
   réimplémentés ici sous leur nom d'origine : le balisage de référence peut
   ainsi être repris presque tel quel, et la fidélité visuelle reste vérifiable
   en comparant les deux rendus.
   
   Les valeurs (couleurs, tailles, interlignes, rayons, espacements) sont
   copiées de tailwind.config des maquettes, pas estimées à l'œil.
   ============================================================================= */

/* ------------------------------------------------------------------ tokens */
:root {
  /* Couleurs — relevées dans tailwind.config des maquettes */
  --background: #0c141e;
  --surface: #0c141e;
  --surface-dim: #0c141e;
  --surface-container-lowest: #070f19;
  --surface-container-low: #141c27;
  --surface-container: #18202b;
  --surface-container-high: #232a36;
  --surface-container-highest: #2d3541;
  --surface-bright: #323a45;
  --surface-variant: #2d3541;
  --surface-tint: #a2d801;

  --on-surface: #dbe3f2;
  --on-surface-variant: #c3c9ae;
  --on-background: #dbe3f2;
  --outline: #8d937b;
  --outline-variant: #434934;

  --primary: #ffffff;
  --primary-container: #bdf532;
  --primary-fixed: #bdf532;
  --primary-fixed-dim: #a2d801;
  --on-primary: #263500;
  --on-primary-container: #516e00;
  --on-primary-fixed: #141f00;
  --on-primary-fixed-variant: #384e00;
  --inverse-primary: #4c6700;

  --secondary: #43e188;
  --secondary-container: #02c16d;
  --secondary-fixed: #66fea2;
  --secondary-fixed-dim: #43e188;
  --on-secondary: #00391c;
  --on-secondary-container: #004825;
  --on-secondary-fixed: #00210e;
  --on-secondary-fixed-variant: #00522b;

  --error: #ffb4ab;
  --error-container: #93000a;
  --on-error: #690005;
  --on-error-container: #ffdad6;

  --inverse-surface: #dbe3f2;
  --inverse-on-surface: #29313c;

  /* Rayons */
  --r: 0.25rem;
  --r-md: 0.375rem;
  --r-lg: 0.5rem;
  --r-xl: 0.75rem;

  /* Espacements nommés */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 0.75rem;
  --space-lg: 1rem;
  --space-xl: 1.5rem;
  --gutter: 1rem;
  --gutter-sm: 0.5rem;
  --margin: 1.5rem;

  /* Typographie */
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Largeur de la barre latérale — pilotée par le redimensionneur */
  --sidebar-w: 18rem;
}

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

html, body { margin: 0; padding: 0; }

body {
  background: var(--background);
  color: var(--on-surface);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 20px;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overscroll-behavior: none;
}

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

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--surface-container-lowest); }
::-webkit-scrollbar-thumb { background: var(--surface-container-high); border-radius: 9999px; }
::-webkit-scrollbar-thumb:hover { background: var(--surface-container-highest); }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  margin: 0;
}
button { cursor: pointer; }
input, textarea, select { outline: none; }
input::placeholder, textarea::placeholder { color: var(--outline); }

/* ---------------------------------------------------------------------------
   Boutons « verre » — glassmorphism

   Le composant « shiny button » fourni est du React + Tailwind compilé +
   TypeScript. Le projet est en JavaScript pur avec un CSS écrit à la main :
   installer une chaîne de build React + Tailwind pour un seul bouton serait
   disproportionné, et §2.1 interdit de toute façon tout CDN au chargement.
   L'effet est donc transposé ici en CSS pur — liseré conique animé, balayage
   de lumière, motif de points — pour un rendu équivalent, sans une seule
   dépendance supplémentaire.

   `.btn-glass`       : verre dépoli, pour tous les boutons.
   `.btn-glass-shine` : ajoute le liseré animé. Réservé à Save et aux actions
                        importantes — c'est un accent, pas une décoration.
--------------------------------------------------------------------------- */

/* Les angles animés doivent être déclarés pour être interpolables : sans
   @property, le navigateur ne sait pas qu'il manipule un <angle> et la
   transition saute d'un coup au lieu de tourner. */
@property --gradient-angle {
  syntax: "<angle>"; initial-value: 0deg; inherits: false;
}
@property --gradient-angle-offset {
  syntax: "<angle>"; initial-value: 0deg; inherits: false;
}
@property --gradient-percent {
  syntax: "<percentage>"; initial-value: 5%; inherits: false;
}
@property --gradient-shine {
  syntax: "<color>"; initial-value: #ffffff; inherits: false;
}

/* Ce bloc est volontairement placé AVANT les utilitaires : à spécificité
   égale, ce sont eux qui doivent gagner (`px-6`, `font-bold`, `w-full`…),
   sinon le padding par défaut écraserait celui de chaque bouton. Et il doit
   rester une classe normale — pas de `:where()` — pour battre le reset
   `button { background: none }` de la feuille de base. */
/* Le chevron de repli. Toujours à la même place — au bout de l'en-tête du bloc
   qu'il range : c'est un repère de lecture, pas un bouton d'action. */
.collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 0.375rem;
  flex: 0 0 auto;
  color: var(--on-surface-variant);
  transition: background-color 150ms ease, color 150ms ease;
}

.collapse-btn:hover { background: var(--surface-container-high); color: var(--on-surface); }
.collapse-btn:focus-visible { outline: 2px solid var(--primary-container); outline-offset: 1px; }
.collapse-btn[aria-expanded="false"] { color: var(--outline); }

.btn-glass {
  --glass-bg: rgba(17, 23, 31, 0.55);
  --glass-edge: rgba(255, 255, 255, 0.14);
  --glass-highlight: var(--primary-container);
  --glass-highlight-soft: #e6ffa8;
  --glass-radius: var(--r);
  --glass-duration: 3s;
  --shadow-size: 2px;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--glass-radius);
  border: 1px solid var(--glass-edge);
  color: var(--on-surface);
  font-weight: 600;
  /* Verre dépoli : un fond translucide, un liseré qui capte la lumière en
     haut à gauche, et le fond de page qui diffuse au travers. */
  background:
    linear-gradient(var(--glass-bg), var(--glass-bg)) padding-box,
    linear-gradient(140deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.02) 45%, rgba(198, 255, 61, 0.14)) border-box;
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.15),
    inset 0 -1px 0 rgba(0, 0, 0, 0.3),
    0 6px 18px -10px rgba(0, 0, 0, 0.8);
  transition: transform 0.18s ease, color 0.2s ease, box-shadow 0.25s ease,
              background-color 0.2s ease;
}
.btn-glass:hover {
  color: var(--primary);
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 12px 26px -12px rgba(198, 255, 61, 0.4);
}
.btn-glass:active { transform: translateY(1px); }
.btn-glass:disabled,
.btn-glass[disabled] { opacity: 0.45; cursor: not-allowed; transform: none; }
.btn-glass:focus-visible { outline: 2px solid var(--primary-container); outline-offset: 2px; }
/* Le lien « Points » de la barre supérieure marque la vue active.
   `--primary` vaut blanc dans cette palette : l'accent doit venir de
   `--primary-container`, sinon l'état actif est indiscernable du repos. */
.btn-glass[aria-current="page"] {
  color: var(--primary-container);
  box-shadow:
    inset 0 0 0 1px rgba(198, 255, 61, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
/* Le contenu passe au-dessus des pseudo-éléments décoratifs. */
.btn-glass > * { position: relative; z-index: 1; }

.btn-glass-shine {
  --gradient-angle: 0deg;
  --gradient-angle-offset: 0deg;
  --gradient-percent: 12%;
  --gradient-shine: #ffffff;
  --glass-ring: 2px;

  /* Le liseré est dessiné par ::before, jamais par une bordure en
     `border-box` : un dégradé posé ainsi transparaît sous un fond translucide
     et teinte tout le bouton en vert. Ici le cône est découpé en anneau, il ne
     peut pas déborder sous le verre. */
  border: 0;
  box-shadow:
    inset 0 0 0 1px var(--glass-edge),
    inset 0 1px 0 rgba(255, 255, 255, 0.15),
    inset 0 -1px 0 rgba(0, 0, 0, 0.3),
    0 6px 18px -10px rgba(0, 0, 0, 0.8);
  transition: transform 0.18s ease, color 0.2s ease, box-shadow 0.25s ease,
              --gradient-angle-offset 0.8s cubic-bezier(0.25, 1, 0.5, 1),
              --gradient-percent 0.8s cubic-bezier(0.25, 1, 0.5, 1),
              --gradient-shine 0.8s cubic-bezier(0.25, 1, 0.5, 1);
  animation: glass-angle var(--glass-duration) linear infinite;
}

/* Anneau lumineux : un cône qui tourne, découpé à l'épaisseur du liseré par un
   masque composite (le centre est retiré). */
.btn-glass-shine::before {
  content: "";
  pointer-events: none;
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: var(--glass-ring);
  background: conic-gradient(
    from calc(var(--gradient-angle) - var(--gradient-angle-offset)),
    transparent,
    var(--glass-highlight) var(--gradient-percent),
    var(--gradient-shine) calc(var(--gradient-percent) * 2),
    var(--glass-highlight) calc(var(--gradient-percent) * 3),
    transparent calc(var(--gradient-percent) * 4)
  );
  -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;
  z-index: 0;
  animation: glass-angle var(--glass-duration) linear infinite;
}

/* Reflet : une bande de lumière très douce qui traverse lentement le verre.
   La bande est peinte à l'intérieur du bouton (`inset: 0`) et c'est sa
   position de fond qui défile : un pseudo-élément débordant agrandirait la
   zone défilante du bouton et déclencherait les contrôles de débordement. */
.btn-glass-shine::after {
  content: "";
  pointer-events: none;
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    transparent 42%,
    rgba(255, 255, 255, 0.1) 50%,
    transparent 58%
  );
  background-size: 250% 100%;
  background-position: -120% 0;
  background-repeat: no-repeat;
  z-index: 0;
  animation: glass-sheen 4.5s ease-in-out infinite;
}

/* Au survol, l'arc s'allonge et s'éclaircit : le bouton s'anime sans bouger. */
.btn-glass-shine:is(:hover, :focus-visible) {
  --gradient-percent: 26%;
  --gradient-angle-offset: 95deg;
  --gradient-shine: var(--glass-highlight-soft);
  box-shadow:
    inset 0 0 0 1px rgba(198, 255, 61, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 12px 26px -12px rgba(198, 255, 61, 0.45);
}

@keyframes glass-angle {
  to { --gradient-angle: 360deg; }
}
@keyframes glass-sheen {
  0%, 100% { background-position: -120% 0; }
  50%      { background-position: 220% 0; }
}

/* Le mouvement est un accent, jamais une condition d'usage. */
@media (prefers-reduced-motion: reduce) {
  .btn-glass-shine,
  .btn-glass-shine::before,
  .btn-glass-shine::after {
    animation: none;
  }
  /* Sans animation, l'anneau reste : il devient un liseré fixe, pas un vide. */
  .btn-glass-shine::before { --gradient-angle: 45deg; }
  .btn-glass-shine::after { background-position: 50% 0; }
}


table { border-collapse: collapse; }

/* ----------------------------------------------------------- typographie */
.font-headline-xl { font-family: var(--font-sans); font-size: 36px; line-height: 44px; letter-spacing: -0.02em; font-weight: 600; }
.font-headline-lg { font-family: var(--font-sans); font-size: 24px; line-height: 32px; letter-spacing: -0.01em; font-weight: 600; }
.font-headline-sm { font-family: var(--font-sans); font-size: 18px; line-height: 26px; letter-spacing: -0.005em; font-weight: 600; }
.font-headline-md { font-family: var(--font-sans); font-size: 20px; line-height: 28px; font-weight: 600; }
.font-body-lg     { font-family: var(--font-sans); font-size: 16px; line-height: 24px; font-weight: 400; }
.font-body-md     { font-family: var(--font-sans); font-size: 14px; line-height: 20px; font-weight: 400; }
.font-body-sm     { font-family: var(--font-sans); font-size: 12px; line-height: 16px; font-weight: 400; }
.font-mono-label  { font-family: var(--font-mono); font-size: 11px; line-height: 14px; letter-spacing: 0.06em; font-weight: 500; }
.font-mono-address{ font-family: var(--font-mono); font-size: 12px; line-height: 16px; font-weight: 400; }
.font-metric-xl   { font-family: var(--font-mono); font-size: 32px; line-height: 40px; letter-spacing: -0.03em; font-weight: 700; }
.font-metric-lg   { font-family: var(--font-mono); font-size: 20px; line-height: 28px; font-weight: 600; }
.font-metric-md   { font-family: var(--font-mono); font-size: 14px; line-height: 20px; font-weight: 500; }
/* Cran manquant de l'échelle metric : les récapitulatifs et les listes du
   tableau de bord ont besoin d'un chiffre plus petit que `md`, mais toujours en
   chasse fixe pour que les colonnes s'alignent. */
.font-metric-sm   { font-family: var(--font-mono); font-size: 13px; line-height: 18px; font-weight: 600; }

.font-medium { font-weight: 500; }
.italic { font-style: italic; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.font-normal { font-weight: 400; }

.uppercase { text-transform: uppercase; }
.tracking-tighter { letter-spacing: -0.05em; }
.tracking-tight { letter-spacing: -0.02em; }
.tracking-normal { letter-spacing: 0; }
.tracking-wide { letter-spacing: 0.025em; }
.tracking-wider { letter-spacing: 0.06em; }
.tracking-widest { letter-spacing: 0.12em; }

.leading-none { line-height: 1; }
.leading-tight { line-height: 1.25; }
.leading-relaxed { line-height: 1.625; }
.leading-7 { line-height: 1.75rem; }

.text-center { text-align: center; }
.text-right { text-align: right; }
.text-left { text-align: left; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.whitespace-nowrap { white-space: nowrap; }

/* Tailles ponctuelles employées par les maquettes */
.text-\[9px\] { font-size: 9px; }
.text-\[10px\] { font-size: 10px; }
.text-\[11px\] { font-size: 11px; }
.text-\[13px\] { font-size: 13px; }
.text-\[14px\] { font-size: 14px; }
.text-\[15px\] { font-size: 15px; }
.text-\[16px\] { font-size: 16px; }
.text-\[18px\] { font-size: 18px; }
.text-\[20px\] { font-size: 20px; }
.text-\[24px\] { font-size: 24px; }
.text-\[28px\] { font-size: 28px; }
.text-xl { font-size: 20px; line-height: 28px; }

/* -------------------------------------------------------------- couleurs */
.bg-background { background-color: var(--background); }
.bg-surface { background-color: var(--surface); }
.bg-surface-container-lowest { background-color: var(--surface-container-lowest); }
.bg-surface-container-low { background-color: var(--surface-container-low); }
.bg-surface-container { background-color: var(--surface-container); }
.bg-surface-container-high { background-color: var(--surface-container-high); }
.bg-surface-container-highest { background-color: var(--surface-container-highest); }
.bg-surface-bright { background-color: var(--surface-bright); }
.bg-primary { background-color: var(--primary); }
.bg-primary-container { background-color: var(--primary-container); }
.bg-primary-container\/10 { background-color: color-mix(in srgb, var(--primary-container) 10%, transparent); }
.bg-primary-container\/20 { background-color: color-mix(in srgb, var(--primary-container) 20%, transparent); }
.bg-primary-container\/5 { background-color: color-mix(in srgb, var(--primary-container) 5%, transparent); }
.bg-secondary { background-color: var(--secondary); }
.bg-secondary\/20 { background-color: color-mix(in srgb, var(--secondary) 20%, transparent); }
.bg-secondary-container { background-color: var(--secondary-container); }
.bg-secondary-fixed { background-color: var(--secondary-fixed); }
.bg-error { background-color: var(--error); }
.bg-error\/20 { background-color: color-mix(in srgb, var(--error) 20%, transparent); }
.bg-error-container { background-color: var(--error-container); }
.bg-error-container\/40 { background-color: color-mix(in srgb, var(--error-container) 40%, transparent); }
.bg-on-secondary { background-color: var(--on-secondary); }
.bg-outline { background-color: var(--outline); }
.bg-transparent { background-color: transparent; }
.bg-surface-container-lowest\/90 { background-color: color-mix(in srgb, var(--surface-container-lowest) 90%, transparent); }
.bg-surface-container\/30 { background-color: color-mix(in srgb, var(--surface-container) 30%, transparent); }
.bg-surface-container\/60 { background-color: color-mix(in srgb, var(--surface-container) 60%, transparent); }
.bg-\[\#14171C\] { background-color: #14171c; }
.bg-\[\#1A1E24\] { background-color: #1a1e24; }
.bg-\[\#000000\]\/75 { background-color: rgb(0 0 0 / 0.75); }

.text-on-surface { color: var(--on-surface); }
.text-on-surface-variant { color: var(--on-surface-variant); }
.text-on-background { color: var(--on-background); }
.text-outline { color: var(--outline); }
.text-outline-variant { color: var(--outline-variant); }
.text-primary { color: var(--primary); }
.text-primary-container { color: var(--primary-container); }
.text-primary-fixed { color: var(--primary-fixed); }
.text-primary-fixed-dim { color: var(--primary-fixed-dim); }
.text-secondary { color: var(--secondary); }
.text-secondary-container { color: var(--secondary-container); }
.text-secondary-fixed { color: var(--secondary-fixed); }
.text-secondary-fixed-dim { color: var(--secondary-fixed-dim); }
.text-error { color: var(--error); }
.text-on-primary { color: var(--on-primary); }
.text-on-primary-fixed { color: var(--on-primary-fixed); }
.text-on-primary-container { color: var(--on-primary-container); }
.text-on-secondary { color: var(--on-secondary); }
.text-on-error { color: var(--on-error); }
.text-on-error-container { color: var(--on-error-container); }
.text-surface-container-highest { color: var(--surface-container-highest); }

/* ------------------------------------------------------------- disposition */
.flex { display: flex; }
.grid { display: grid; }
.hidden { display: none; }
.block { display: block; }
.inline-flex { display: inline-flex; }
.inline-block { display: inline-block; }

.flex-col { flex-direction: column; }
/* Le sens par défaut est déjà `row` ; la classe existe pour que l'utilitaire
   soit disponible partout où il est écrit — une classe employée et non définie
   ne produit aucune erreur, elle ne fait simplement rien. */
.flex-row { flex-direction: row; }
.flex-wrap { flex-wrap: wrap; }
.flex-1 { flex: 1 1 0%; }
.shrink-0 { flex-shrink: 0; }
.grow { flex-grow: 1; }
.min-w-0 { min-width: 0; }

.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.items-end { align-items: flex-end; }
.items-baseline { align-items: baseline; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }
.justify-end { justify-content: flex-end; }
.self-start { align-self: flex-start; }
.my-auto { margin-top: auto; margin-bottom: auto; }
.mx-auto { margin-left: auto; margin-right: auto; }

.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.relative { position: relative; }
.absolute { position: absolute; }
.fixed { position: fixed; }
.inset-0 { inset: 0; }
.top-0 { top: 0; }
.top-16 { top: 4rem; }
.top-1\/2 { top: 50%; }
.bottom-0 { bottom: 0; }
.bottom-6 { bottom: 1.5rem; }
.left-0 { left: 0; }
.right-0 { right: 0; }
.left-1\/2 { left: 50%; }
.left-2 { left: 0.5rem; }
.left-2\.5 { left: 0.625rem; }
.left-3 { left: 0.75rem; }
.right-2 { right: 0.5rem; }
.right-2\.5 { right: 0.625rem; }
.-translate-y-1\/2 { transform: translateY(-50%); }
.-translate-x-1\/2 { transform: translateX(-50%); }
.rotate-180 { transform: rotate(180deg); }
.z-10 { z-index: 10; }
.z-30 { z-index: 30; }
.z-40 { z-index: 40; }
.z-50 { z-index: 50; }

.overflow-hidden { overflow: hidden; }
.overflow-y-auto { overflow-y: auto; }
.overflow-x-auto { overflow-x: auto; }
.overflow-visible { overflow: visible; }
.pointer-events-none { pointer-events: none; }
.select-none { user-select: none; }
.select-all { user-select: all; }
.cursor-pointer { cursor: pointer; }
.opacity-20 { opacity: 0.2; }
.opacity-30 { opacity: 0.3; }
.opacity-90 { opacity: 0.9; }
.opacity-95 { opacity: 0.95; }
.opacity-100 { opacity: 1; }

/* Barre latérale : largeur pilotée par --sidebar-w, partagée avec la colonne
   principale et la barre supérieure pour qu'elles restent alignées. */
.w-72 { width: var(--sidebar-w); }
.pl-72 { padding-left: var(--sidebar-w); }
.left-72 { left: var(--sidebar-w); }

/* ------------------------------------------------------------ dimensions */
.w-full { width: 100%; }
.h-full { height: 100%; }
.w-auto { width: auto; }
.w-1\.5 { width: 0.375rem; } .h-1\.5 { height: 0.375rem; }
.w-2 { width: 0.5rem; } .h-2 { height: 0.5rem; }
.w-2\.5 { width: 0.625rem; } .h-2\.5 { height: 0.625rem; }
.w-3\.5 { width: 0.875rem; } .h-3\.5 { height: 0.875rem; }
.w-4 { width: 1rem; } .h-4 { height: 1rem; }
.w-6 { width: 1.5rem; } .h-6 { height: 1.5rem; }
.w-7 { width: 1.75rem; } .h-7 { height: 1.75rem; }
.w-8 { width: 2rem; } .h-8 { height: 2rem; }
.w-9 { width: 2.25rem; } .h-9 { height: 2.25rem; }
.w-10 { width: 2.5rem; } .h-10 { height: 2.5rem; }
.w-11 { width: 2.75rem; } .h-11 { height: 2.75rem; }
.w-12 { width: 3rem; } .h-12 { height: 3rem; }
.w-16 { width: 4rem; } .h-16 { height: 4rem; }
.w-20 { width: 5rem; } .h-20 { height: 5rem; }
.w-24 { width: 6rem; } .h-24 { height: 6rem; }
.w-36 { width: 9rem; }
.w-44 { width: 11rem; } .h-44 { height: 11rem; }
.w-48 { width: 12rem; } .h-48 { height: 12rem; }
.w-52 { width: 13rem; }
.w-56 { width: 14rem; } .h-56 { height: 14rem; }
.w-64 { width: 16rem; } .h-64 { height: 16rem; }
.h-28 { height: 7rem; }
.h-80 { height: 20rem; }
.w-\[72px\] { width: 72px; } .h-\[72px\] { height: 72px; }
.w-\[90\%\] { width: 90%; }
.h-\[2px\] { height: 2px; }
.h-\[calc\(100vh-4rem\)\] { height: calc(100vh - 4rem); }
.min-h-screen { min-height: 100vh; }
.min-h-\[44px\] { min-height: 44px; }
.min-h-\[300px\] { min-height: 300px; }
.max-w-md { max-width: 28rem; }
.max-w-lg { max-width: 32rem; }
.max-w-3xl { max-width: 48rem; }
.max-w-4xl { max-width: 56rem; }
.break-all { word-break: break-all; }
.pt-0\.5 { padding-top: 0.125rem; }
.max-w-xl { max-width: 36rem; }
.max-w-2xl { max-width: 42rem; }
.max-w-7xl { max-width: 80rem; }
.max-w-\[220px\] { max-width: 220px; }
.max-w-\[620px\] { max-width: 620px; }
.max-w-\[520px\] { max-width: 520px; }
.max-w-\[40%\] { max-width: 40%; }
.min-h-\[88px\] { min-height: 88px; }
.min-w-\[200px\] { min-width: 200px; }
.w-40 { width: 10rem; }
.border-outline-variant\/40 { border-color: color-mix(in srgb, var(--outline-variant) 40%, transparent); }
.text-on-secondary-container { color: var(--on-secondary-container); }
.max-h-\[320px\] { max-height: 320px; }
.overflow-auto { overflow: auto; }
.max-w-\[1440px\] { max-width: 1440px; }
.min-w-\[120px\] { min-width: 120px; }

/* ------------------------------------------------------------- espacements */
.p-0\.5 { padding: 0.125rem; }
.p-1 { padding: 0.25rem; }
.p-1\.5 { padding: 0.375rem; }
.p-2 { padding: 0.5rem; }
.p-2\.5 { padding: 0.625rem; }
.p-3 { padding: 0.75rem; }
.p-4 { padding: 1rem; }
.p-6 { padding: 1.5rem; }
.p-8 { padding: 2rem; }
.p-space-xs { padding: var(--space-xs); }
.p-space-sm { padding: var(--space-sm); }
.p-space-md { padding: var(--space-md); }
.p-space-lg { padding: var(--space-lg); }
.p-space-xl { padding: var(--space-xl); }
.pb-space-md { padding-bottom: var(--space-md); }

/* --- Utilitaires du fil X ------------------------------------------------
   `line-clamp` replie un article long : sans lui, un texte de 600 caractères
   déplié noie le fil. `aspect-square` et `grid-rows-2` reproduisent la grille
   d'images de X (la première image d'un trio occupe les deux lignes). */
.text-white { color: #ffffff; }
.bg-black\/60 { background-color: color-mix(in srgb, #000 60%, transparent); }
.bg-black\/70 { background-color: color-mix(in srgb, #000 70%, transparent); }
.pb-space-xs { padding-bottom: 0.25rem; }
.top-2 { top: 0.5rem; }
.line-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.line-clamp-6 { display: -webkit-box; -webkit-line-clamp: 6; line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
.whitespace-pre-wrap { white-space: pre-wrap; }
/* La zone d'édition d'un script : assez haute pour qu'on relise trois minutes de
   texte sans faire défiler toutes les deux lignes. */
.min-h-\[220px\] { min-height: 220px; }
/* L'étiquette d'un `<input type="file">` : le seul morceau stylable du contrôle
   natif, et le seul endroit où l'on peut dire « choisir un fichier » autrement
   qu'en anglais. */
.file\:mr-2::file-selector-button { margin-right: 0.5rem; }
.file\:px-2::file-selector-button { padding-left: 0.5rem; padding-right: 0.5rem; }
.file\:py-1::file-selector-button { padding-top: 0.25rem; padding-bottom: 0.25rem; }
.file\:rounded-lg::file-selector-button { border-radius: 0.5rem; }
.file\:border-0::file-selector-button { border: 0; }
.file\:bg-surface-container::file-selector-button { background: var(--surface-container); }
.file\:text-on-surface::file-selector-button { color: var(--on-surface); }
.file\:font-body-sm::file-selector-button { font-family: var(--font-body); font-size: 0.875rem; }

/* Le script d'une vidéo garde ses retours à la ligne : une phrase par ligne, comme
   il se lira. `pre-line` replie les lignes trop longues, `pre` ne le ferait pas. */
.whitespace-pre-line { white-space: pre-line; }
.aspect-square { aspect-ratio: 1 / 1; }
.grid-rows-2 { grid-template-rows: repeat(2, minmax(0, 1fr)); }
.row-span-2 { grid-row: span 2 / span 2; }
.max-h-\[440px\] { max-height: 440px; }
.w-0\.5 { width: 0.125rem; }
.my-1 { margin-top: 0.25rem; margin-bottom: 0.25rem; }
.p-gutter { padding: var(--gutter); }

.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; }
.px-1\.5 { padding-left: 0.375rem; padding-right: 0.375rem; }
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
.px-2\.5 { padding-left: 0.625rem; padding-right: 0.625rem; }
.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.px-space-xs { padding-left: var(--space-xs); padding-right: var(--space-xs); }
.px-space-sm { padding-left: var(--space-sm); padding-right: var(--space-sm); }
.px-space-md { padding-left: var(--space-md); padding-right: var(--space-md); }
.px-space-lg { padding-left: var(--space-lg); padding-right: var(--space-lg); }
.px-space-xl { padding-left: var(--space-xl); padding-right: var(--space-xl); }
.px-margin { padding-left: var(--margin); padding-right: var(--margin); }

.py-0\.5 { padding-top: 0.125rem; padding-bottom: 0.125rem; }
.py-0\.2 { padding-top: 0.05rem; padding-bottom: 0.05rem; }
.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
.py-1\.5 { padding-top: 0.375rem; padding-bottom: 0.375rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.py-2\.5 { padding-top: 0.625rem; padding-bottom: 0.625rem; }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.py-space-xs { padding-top: var(--space-xs); padding-bottom: var(--space-xs); }
.py-space-sm { padding-top: var(--space-sm); padding-bottom: var(--space-sm); }
.py-space-md { padding-top: var(--space-md); padding-bottom: var(--space-md); }
.py-space-lg { padding-top: var(--space-lg); padding-bottom: var(--space-lg); }
.py-space-xl { padding-top: var(--space-xl); padding-bottom: var(--space-xl); }

.pt-1 { padding-top: 0.25rem; }
.pb-1 { padding-bottom: 0.25rem; }
.pt-space-xs { padding-top: var(--space-xs); }
.pt-space-sm { padding-top: var(--space-sm); }
.pt-space-md { padding-top: var(--space-md); }
.pt-space-lg { padding-top: var(--space-lg); }
.pb-16 { padding-bottom: 4rem; }
.pb-space-sm { padding-bottom: var(--space-sm); }
.pb-space-lg { padding-bottom: var(--space-lg); }
.pl-1 { padding-left: 0.25rem; }
.pl-7 { padding-left: 1.75rem; }
.pl-8 { padding-left: 2rem; }
.pl-10 { padding-left: 2.5rem; }
.pl-3 { padding-left: 0.75rem; }
.pl-space-lg { padding-left: var(--space-lg); }
.pl-space-md { padding-left: var(--space-md); }
.pl-\[calc\(0\.5rem-2px\)\] { padding-left: calc(0.5rem - 2px); }
.pr-2\.5 { padding-right: 0.625rem; }
.pr-3 { padding-right: 0.75rem; }
.pr-4 { padding-right: 1rem; }
.pr-10 { padding-right: 2.5rem; }
.pr-space-sm { padding-right: var(--space-sm); }
.pr-space-md { padding-right: var(--space-md); }

.mt-0\.5 { margin-top: 0.125rem; }
.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-space-xs { margin-top: var(--space-xs); }
.mt-space-sm { margin-top: var(--space-sm); }
.mt-space-md { margin-top: var(--space-md); }
.mt-space-xl { margin-top: var(--space-xl); }
.mb-1 { margin-bottom: 0.25rem; }
.mb-space-xs { margin-bottom: var(--space-xs); }
.mb-space-sm { margin-bottom: var(--space-sm); }
.mb-space-md { margin-bottom: var(--space-md); }
.mb-space-lg { margin-bottom: var(--space-lg); }
.mb-space-xl { margin-bottom: var(--space-xl); }
.ml-0\.5 { margin-left: 0.125rem; }
.ml-auto { margin-left: auto; }

.gap-0\.5 { gap: 0.125rem; }
.gap-1 { gap: 0.25rem; }
.gap-1\.5 { gap: 0.375rem; }
.gap-2 { gap: 0.5rem; }
.gap-4 { gap: 1rem; }
.gap-space-xs { gap: var(--space-xs); }
.gap-space-sm { gap: var(--space-sm); }
.gap-space-md { gap: var(--space-md); }
.gap-space-lg { gap: var(--space-lg); }
.gap-space-xl { gap: var(--space-xl); }
.gap-gutter { gap: var(--gutter); }

.space-x-1 > * + * { margin-left: 0.25rem; }
.space-x-space-xs > * + * { margin-left: var(--space-xs); }
.space-x-space-sm > * + * { margin-left: var(--space-sm); }
.space-x-space-md > * + * { margin-left: var(--space-md); }
.space-y-space-xs > * + * { margin-top: var(--space-xs); }
.space-y-space-sm > * + * { margin-top: var(--space-sm); }
.space-y-space-lg > * + * { margin-top: var(--space-lg); }

.divide-y > * + * { border-top-width: 1px; border-top-style: solid; }
.divide-transparent > * + * { border-top-color: transparent; }

/* ------------------------------------------------------------------ formes */
.rounded { border-radius: var(--r); }
.rounded-md { border-radius: var(--r-md); }
.rounded-lg { border-radius: var(--r-lg); }
.rounded-xl { border-radius: var(--r-xl); }
.rounded-full { border-radius: 9999px; }
.rounded-t { border-radius: var(--r) var(--r) 0 0; }

.border-error { border-color: var(--error); }
.border-error\/40 { border-color: color-mix(in srgb, var(--error) 40%, transparent); }
.border { border: 1px solid var(--surface-container-high); }
.border-r { border-right: 1px solid var(--surface-container-high); }
.border-b { border-bottom: 1px solid var(--surface-container-high); }
.border-t { border-top: 1px solid var(--surface-container-high); }
.border-l-2 { border-left: 2px solid transparent; }
.border-t-2 { border-top: 2px solid transparent; }
.border-r-2 { border-right: 2px solid transparent; }
.border-b-2 { border-bottom: 2px solid transparent; }
.border-primary-container { border-color: var(--primary-container); }
.border-surface-container-high { border-color: var(--surface-container-high); }
.border-collapse { border-collapse: collapse; }
/* Un trait pointillé : la maquette du compte à rebours souligne son titre ainsi,
   et aucun utilitaire de style de bordure n'existait. Placé après les `.border-*`
   à raccourci, qui imposent `solid`. */
.border-dashed { border-style: dashed; }
.border-outline-variant { border-color: var(--outline-variant); }
.ring-1 { box-shadow: 0 0 0 1px var(--ring-color, var(--surface-container-high)); }
.ring-primary-container { --ring-color: var(--primary-container); }
/* L'anneau au focus, sur le modèle des variantes Tailwind : la classe porte la
   couleur, la variante porte le moment. */
.focus\:border-primary:focus { border-color: var(--primary); }
.focus\:ring-1:focus { box-shadow: 0 0 0 1px var(--ring-color, var(--primary-container)); }
.focus\:ring-primary-container:focus { --ring-color: var(--primary-container); }

.shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.35); }
.shadow-md { box-shadow: 0 4px 8px -2px rgb(0 0 0 / 0.45); }
.shadow-xl { box-shadow: 0 12px 24px -6px rgb(0 0 0 / 0.55); }
.shadow-2xl { box-shadow: 0 24px 48px -12px rgb(0 0 0 / 0.7); }
.shadow-inner { box-shadow: inset 0 1px 3px 0 rgb(0 0 0 / 0.4); }

.backdrop-blur-sm { backdrop-filter: blur(4px); }
.backdrop-blur-md { backdrop-filter: blur(12px); }

.transition-all { transition: all 0.15s ease; }
.transition-colors { transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease; }
.transition-transform { transition: transform 0.2s ease; }
.transition-opacity { transition: opacity 0.2s ease; }
.duration-300 { transition-duration: 0.3s; }
.duration-700 { transition-duration: 0.7s; }

.object-contain { object-fit: contain; }
.object-cover { object-fit: cover; }

/* ------------------------------------------------------------- interactions */
.hover\:opacity-90:hover { opacity: 0.9; }
.hover\:opacity-95:hover { opacity: 0.95; }
.hover\:underline:hover { text-decoration: underline; }
.hover\:bg-surface-container:hover { background-color: var(--surface-container); }
.hover\:bg-surface-container-high:hover { background-color: var(--surface-container-high); }
.hover\:bg-surface-container-highest:hover { background-color: var(--surface-container-highest); }
.hover\:bg-surface-bright:hover { background-color: var(--surface-bright); }
.hover\:bg-surface-container-low:hover { background-color: var(--surface-container-low); }
.hover\:bg-primary-fixed-dim:hover { background-color: var(--primary-fixed-dim); }
.hover\:bg-error-container:hover { background-color: var(--error-container); }
.hover\:bg-\[\#d6ff66\]:hover { background-color: #d6ff66; }
.hover\:text-primary:hover { color: var(--primary); }
.hover\:text-primary-container:hover { color: var(--primary-container); }
.hover\:text-on-surface:hover { color: var(--on-surface); }
.hover\:text-secondary:hover { color: var(--secondary); }
.hover\:text-error:hover { color: var(--error); }
.hover\:text-on-error:hover { color: var(--on-error); }
.hover\:text-on-error-container:hover { color: var(--on-error-container); }
.hover\:scale-105:hover { transform: scale(1.05); }

.group:hover .group-hover\:text-primary { color: var(--primary); }
.group:hover .group-hover\:text-primary-container { color: var(--primary-container); }
.group:hover .group-hover\:text-on-surface { color: var(--on-surface); }
.group:hover .group-hover\:text-error { color: var(--error); }
.group:hover .group-hover\:text-secondary { color: var(--secondary); }
.group:hover .group-hover\:translate-x-1 { transform: translateX(0.25rem); }
.group:hover .group-hover\:translate-x-0\.5 { transform: translateX(0.125rem); }
.group:hover .group-hover\:scale-105 { transform: scale(1.05); }
.group:hover .group-hover\:scale-110 { transform: scale(1.1); }
.group:hover .group-hover\:bg-primary-container\/20 { background-color: color-mix(in srgb, var(--primary-container) 20%, transparent); }
.group:hover .group-hover\:opacity-100 { opacity: 1; }

/* ==========================================================================
   Composants propres à l'application
   ========================================================================== */

/* Icône : .ms vient d'icons.css, .i-<nom> porte le glyphe. */
.ms { flex-shrink: 0; }

/* Champ de saisie — la plupart des champs des maquettes n'ont pas de bordure :
   la séparation vient de la différence de teinte avec leur conteneur. */
.field {
  width: 100%;
  background: var(--surface-container-lowest);
  color: var(--on-surface);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 16px;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--r-lg);
  border: 1px solid transparent;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.field:focus { border-color: var(--primary-container); }
.field.invalid { border-color: var(--error); }
.field.valid { border-color: var(--secondary); }

textarea.field { font-family: var(--font-mono); resize: vertical; }
select.field { cursor: pointer; }

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  background: var(--primary-container);
  color: var(--on-primary);
  font-weight: 600;
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--r);
  transition: background-color 0.15s ease, opacity 0.15s ease;
}
.btn-primary:hover { background: var(--primary-fixed-dim); }
.btn-primary:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  background: var(--surface-container);
  color: var(--on-surface);
  padding: var(--space-sm) var(--space-lg);
  border-radius: var(--r);
  transition: background-color 0.15s ease;
}
.btn-ghost:hover { background: var(--surface-container-high); }

/* Aperçu Markdown de l'onglet Referral */
.md h1, .md h2, .md h3, .md h4 { color: var(--primary); font-weight: 600; margin: 0.75rem 0 0.25rem; }
.md h1 { font-size: 20px; line-height: 28px; }
.md h2 { font-size: 18px; line-height: 26px; }
.md h3 { font-size: 16px; line-height: 24px; }
.md h4 { font-size: 14px; line-height: 20px; }
.md p { margin: 0.25rem 0; }
.md ul, .md ol { margin: 0.25rem 0; padding-left: 1.25rem; display: flex; flex-direction: column; gap: 0.25rem; }
.md ul { list-style: disc; }
.md ol { list-style: decimal; }
.md a { color: var(--secondary); font-family: var(--font-mono); font-size: 12px; }
.md a:hover { color: var(--primary); text-decoration: underline; }
.md code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--surface-container);
  color: var(--primary-container);
  padding: 0.1rem 0.25rem;
  border-radius: var(--r);
}
.md pre {
  background: var(--surface-container);
  padding: var(--space-md);
  border-radius: var(--r-lg);
  overflow-x: auto;
}
.md pre code { background: none; padding: 0; }
.md blockquote {
  border-left: 2px solid var(--primary-container);
  padding-left: var(--space-md);
  color: var(--on-surface-variant);
  margin: 0.5rem 0;
}
.md strong { color: var(--primary); font-weight: 600; }
.md hr { border: none; border-top: 1px solid var(--surface-container-high); margin: 0.75rem 0; }

/* Recadreur d'image (modales projet / farmer) */
.crop-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  max-width: 320px;
  margin: 0 auto;
  background: var(--surface-container-lowest);
  border-radius: var(--r-lg);
  overflow: hidden;
  touch-action: none;
  cursor: grab;
}
.crop-stage:active { cursor: grabbing; }
.crop-stage canvas { width: 100%; height: 100%; display: block; }

/* Bandeau de modifications non enregistrées */
.unsaved-bar { animation: rise 0.18s ease-out; }
@keyframes rise {
  from { transform: translate(-50%, 0.75rem); opacity: 0; }
  to   { transform: translate(-50%, 0); opacity: 1; }
}

/* Notification éphémère (copie dans le presse-papiers) */
.toast { animation: fade 0.15s ease-out; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* Compteur de la cloche des distributions.
   Posé en absolu sur le bouton : les utilitaires de position négative n'existent
   qu'en pas de 0.5rem, ce qui décollait la pastille du coin. */
/* Le panneau « Next Drop » : verre dépoli, et un fond plus sombre que la carte
   pour que les chiffres se détachent sans que le panneau pèse sur l'en-tête. */
.next-drop {
  min-width: 17rem;
  background: rgba(9, 13, 19, 0.66);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    0 12px 28px -20px rgba(0, 0, 0, 0.95);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
}

.notif-badge {
  position: absolute;
  top: -0.3rem;
  right: -0.3rem;
  min-width: 1rem;
  height: 1rem;
  padding: 0 0.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: var(--error-container);
  color: var(--on-error-container);
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  font-weight: 600;
  border: 1px solid var(--surface-container-lowest);
}

/* Squelette de chargement */
.skeleton {
  background: linear-gradient(90deg,
    var(--surface-container) 25%,
    var(--surface-container-high) 50%,
    var(--surface-container) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite;
  border-radius: var(--r);
}
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* Poignée de redimensionnement de la barre latérale */
/* Glisser la poignée de la barre latérale ne doit pas devenir un
   glisser-déposer natif. Sur une image ou un lien, le navigateur démarre son
   propre « drag », annule le pointeur (`pointercancel`) et le relâchement
   n'arrive jamais jusqu'à la poignée : la largeur change à l'écran mais n'est
   jamais enregistrée. Le défaut ne se voyait que sur une barre peuplée — donc
   jamais sur une base vide. */
img, a { -webkit-user-drag: none; user-drag: none; }

#sidebar-resizer {
  position: absolute;
  top: 0;
  right: -2px;
  width: 5px;
  height: 100%;
  cursor: col-resize;
  z-index: 60;
  background: transparent;
  transition: background-color 0.15s ease;
}
#sidebar-resizer:hover, #sidebar-resizer.dragging { background: var(--primary-container); }

.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { scrollbar-width: none; }

@media (max-width: 1100px) {
  .grid-cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .grid-cols-4, .grid-cols-2 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
}

/* ==========================================================================
   Complément d'utilitaires — familles utilisées par les maquettes
   --------------------------------------------------------------------------
   Les utilitaires Tailwind sont réimplémentés en CSS pur (§2.1 : aucune
   ressource externe). Une classe employée mais non définie n'échoue pas
   visiblement : le navigateur l'ignore et la mise en page retombe sans bruit
   sur sa forme mobile. Ce bloc comble les familles que les gabarits emploient
   réellement — animations, flous, opacités de surface, variantes responsives.
   ========================================================================== */

/* --- Animations ---------------------------------------------------------- */
@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
@keyframes ping-ring {
  0%   { transform: scale(1);   opacity: 0.7; }
  70%  { transform: scale(2.4); opacity: 0; }
  100% { transform: scale(2.4); opacity: 0; }
}
/* La barre « modifications non enregistrées » est centrée par -translate-x-1/2 :
   l'animation doit donc conserver cette translation, sinon elle saute à gauche. */
@keyframes bounce-subtle {
  0%, 100% { transform: translate(-50%, 0); }
  50%      { transform: translate(-50%, -6px); }
}
.animate-pulse { animation: pulse-soft 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
.animate-ping  { animation: ping-ring 1.3s cubic-bezier(0, 0, 0.2, 1) infinite; }
.animate-bounce-subtle { animation: bounce-subtle 2.6s ease-in-out infinite; }

/* --- Flous : halos des en-têtes et de l'état vide ------------------------ */
.blur-2xl { filter: blur(40px); }
.blur-3xl { filter: blur(64px); }

/* --- Opacités de surface ------------------------------------------------- */
.bg-surface-container-lowest\/50 { background-color: color-mix(in srgb, var(--surface-container-lowest) 50%, transparent); }
.bg-surface-container-lowest\/60 { background-color: color-mix(in srgb, var(--surface-container-lowest) 60%, transparent); }
.hover\:bg-surface-container\/60:hover { background-color: color-mix(in srgb, var(--surface-container) 60%, transparent); }
.opacity-40 { opacity: 0.4; }

/* --- États --------------------------------------------------------------- */
.disabled\:opacity-40:disabled { opacity: 0.4; }
.disabled\:opacity-50:disabled { opacity: 0.5; }
.hover\:bg-surface-tint:hover { background-color: var(--surface-tint); }
.group:hover .group-hover\:bg-primary-container { background-color: var(--primary-container); }
.group:hover .group-hover\:text-on-primary { color: var(--on-primary); }

/* --- Positionnement et dimensions --------------------------------------- */
.h-0\.5  { height: 0.125rem; }
.w-3     { width: 0.75rem; }
.h-3     { height: 0.75rem; }
/* Décalages négatifs : les maquettes positionnent certains décors hors cadre
   (halos, équerres d'angle). Sans ces règles, top/left/right/bottom restent à
   « auto » et les éléments s'empilent tous au même point, sans erreur. */
.-top-2    { top: -0.5rem; }
.-right-2  { right: -0.5rem; }
.-bottom-2 { bottom: -0.5rem; }
.-left-2   { left: -0.5rem; }
.-top-20   { top: -5rem; }
.-right-20 { right: -5rem; }
.bottom-1 { bottom: 0.25rem; }
.right-1  { right: 0.25rem; }
.top-20   { top: 5rem; }
.right-20 { right: 5rem; }
.pt-16    { padding-top: 4rem; }
.w-80     { width: 20rem; }
.max-h-80 { max-height: 20rem; }
.max-h-96 { max-height: 24rem; }
.max-w-full { max-width: 100%; }
.max-w-\[420px\] { max-width: 420px; }
.max-w-\[460px\] { max-width: 460px; }
.min-h-\[calc\(100vh-4rem\)\] { min-height: calc(100vh - 4rem); }
.resize-none { resize: none; }
.translate-x-1\/2 { transform: translateX(-50%); }
.translate-y-1\/2 { transform: translateY(-50%); }
.left-space-sm  { left: var(--space-sm); }
.left-space-md  { left: var(--space-md); }
.right-space-sm { right: var(--space-sm); }
.right-space-md { right: var(--space-md); }
.right-space-lg { right: var(--space-lg); }
.font-mono { font-family: var(--font-mono); }

/* --- Valeurs arbitraires des maquettes -----------------------------------
   La référence emploie directement des hexadécimaux dans ses classes
   (bg-[#14171C]…), ce que Tailwind génère automatiquement. Réimplémentés ici
   à la main : sans ces règles, les panneaux des modales et le voile
   n'auraient aucun fond. */
.bg-\[\#14171C\] { background-color: #14171c; }
.bg-\[\#1A1E24\] { background-color: #1a1e24; }
.bg-\[\#000000\]\/85 { background-color: rgb(0 0 0 / 0.85); }
.text-\[\#0B0D10\] { color: #0b0d10; }
.hover\:bg-\[\#D6FF66\]:hover { background-color: #d6ff66; }

/* --- Échelle typographique en classes `text-*` ---------------------------
   Les maquettes écrivent « font-metric-xl text-metric-lg » : la famille vient
   de la première, la taille de la seconde. Les règles .font-* portent déjà la
   taille ; ces alias, déclarés après, permettent à la seconde de gagner quand
   les deux divergent — exactement comme dans la référence. */
.text-headline-xl  { font-size: 36px; line-height: 44px; letter-spacing: -0.02em; }
.text-headline-lg  { font-size: 24px; line-height: 32px; letter-spacing: -0.01em; }
.text-headline-sm  { font-size: 18px; line-height: 26px; letter-spacing: -0.005em; }
.text-headline-md  { font-size: 20px; line-height: 28px; }
.text-body-lg      { font-size: 16px; line-height: 24px; }
.text-body-md      { font-size: 14px; line-height: 20px; }
.text-body-sm      { font-size: 12px; line-height: 16px; }
.text-mono-label   { font-size: 11px; line-height: 14px; letter-spacing: 0.06em; }
.text-mono-address { font-size: 12px; line-height: 16px; }
.text-metric-xl    { font-size: 32px; line-height: 40px; letter-spacing: -0.03em; }
.text-metric-lg    { font-size: 20px; line-height: 28px; }
.text-metric-md    { font-size: 14px; line-height: 20px; }
.text-metric-sm    { font-size: 13px; line-height: 18px; }
.text-\[12px\]     { font-size: 12px; line-height: 16px; }

/* --- Variantes responsives ----------------------------------------------
   Tailwind est « mobile d'abord » : les préfixes n'ajoutent une règle qu'au
   delà de leur seuil. Sans ces blocs, les grilles restaient en une colonne. */
@media (min-width: 640px) {
  .sm\:w-28 { width: 7rem; }
  .sm\:h-28 { height: 7rem; }
  .sm\:flex-row { flex-direction: row; }
  .sm\:items-center { align-items: center; }
  .sm\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sm\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sm\:inline { display: inline; }
  .sm\:self-auto { align-self: auto; }
  .sm\:hidden { display: none; }
  .sm\:text-headline-xl { font-size: 36px; line-height: 44px; letter-spacing: -0.02em; }
  .sm\:font-headline-xl { font-family: var(--font-sans); font-weight: 600; }
}
@media (min-width: 768px) {
  .md\:flex { display: flex; }
  .md\:flex-row { flex-direction: row; }
  .md\:items-end { align-items: flex-end; }
  .md\:hidden { display: none; }
  .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .md\:col-span-2 { grid-column: span 2 / span 2; }
}
@media (min-width: 1024px) {
  .lg\:flex-row { flex-direction: row; }
  .lg\:items-center { align-items: center; }
  .lg\:self-auto { align-self: auto; }
  .lg\:self-center { align-self: center; }
  .lg\:hidden { display: none; }
  .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .lg\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .lg\:col-span-2 { grid-column: span 2 / span 2; }
  .lg\:col-span-4 { grid-column: span 4 / span 4; }
  .lg\:col-span-5 { grid-column: span 5 / span 5; }
  .lg\:col-span-7 { grid-column: span 7 / span 7; }
  .lg\:col-span-8 { grid-column: span 8 / span 8; }
}
@media (min-width: 1280px) {
  .xl\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.xl\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* --- Aperçu d'un post, aux proportions et couleurs de X -------------------
   Valeurs figées volontairement : c'est un aperçu du rendu réel sur X, il ne
   doit pas suivre le thème de l'application, sinon il ne montre plus rien de
   fidèle. Les mesures reprennent celles de X (avatar 40 px, corps 15/20 px,
   rangée d'actions étalée sur 425 px, icônes 18,75 px). */
.x-preview {
  background: #000000;
  border: 1px solid #2f3336;
  border-radius: 16px;
  padding: 16px;
  font-family: Inter, -apple-system, "Segoe UI", Roboto, sans-serif;
}
/* Un post du brouillon. Pas de colonne d'avatar : le conteneur montre le texte à
   copier, pas un compte. Un thread sépare ses posts par un trait, sans quoi on
   ne voit plus où s'arrête chacun. */
.x-preview__row { display: flex; flex-direction: column; }
.x-preview__row + .x-preview__row { margin-top: 12px; padding-top: 12px; border-top: 1px solid #2f3336; }
.x-preview__thread-note {
  color: #71767b; font-size: 13px; line-height: 16px; font-weight: 600;
  padding-bottom: 8px; margin-bottom: 4px; border-bottom: 1px solid #2f3336;
}
.x-preview__text {
  color: #e7e9ea; font-size: 15px; line-height: 20px;
  white-space: pre-wrap; word-break: break-word;
  margin-top: 2px;
}
.x-preview__empty { color: #71767b; }
.x-preview__actions {
  display: flex; justify-content: space-between; align-items: center;
  max-width: 425px; margin-top: 12px;
}
.x-preview__action { display: flex; align-items: center; gap: 4px; color: #71767b; }
.x-preview__icon { font-size: 18.75px !important; color: #71767b; }
.x-preview__count { color: #71767b; font-size: 13px; line-height: 16px; }

/* ==========================================================================
   Fil X — rendu aux mesures de X
   --------------------------------------------------------------------------
   Comme l'aperçu de brouillon, ce bloc ne suit PAS le thème de l'application :
   il reproduit X (fond noir, séparateurs #2f3336, texte 17 px, rangée d'actions
   sur 425 px, avatar carré de 40 px). Un fil qui suit la palette maison ne
   montre plus ce que Dash verra sur X — or c'est ce qu'il vient y comparer.
   Les valeurs sont figées ici pour ne pas dériver avec la palette.
   ========================================================================== */
/* Largeur de la colonne du fil : celle de X (600 px).
   Sans elle, le fil s'étire sur toute la largeur de la grille et les proportions
   ne sont plus celles de X — image plus haute, texte sur des lignes trop
   longues, rangée d'actions perdue au milieu. Un fil qu'on compare à X doit
   avoir la largeur d'un fil X.
   La colonne est le premier élément de la page : elle commence donc à la même
   hauteur que le contenu des autres onglets. */
/* Sous 1024 px la colonne prend la largeur disponible : un fil de 600 px dans
   un écran de 380 px déborderait. Au-dessus, elle est figée à la largeur d'un
   fil X et ne bouge plus — c'est ce qui rend les proportions comparables. */
.x-column { width: 100%; }
@media (min-width: 1024px) {
  .x-column { width: 600px; flex: 0 0 600px; max-width: 600px; }
}

/* Attente de génération : un repère qui tourne, plutôt qu'une page figée.
   La génération dure des dizaines de secondes — sans mouvement, on croit que
   le clic n'a rien déclenché. */
.brief-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid var(--color-surface-container-highest, #2a3546);
  border-top-color: var(--color-primary-container, #c6ff3d);
  border-radius: 50%;
  animation: brief-spin 0.8s linear infinite;
  flex-shrink: 0;
}
@keyframes brief-spin { to { transform: rotate(360deg); } }

/* Texte d'étape de la génération. Il est mis à jour en place pendant l'attente
   (sans re-rendre la page), d'où la classe dédiée que le script cible. */
.brief-step { transition: color 0.2s ease; }

.x-feed {
  background: #000000;
  border: 1px solid #2f3336;
  border-radius: 16px;
  overflow: hidden;
  font-family: Inter, -apple-system, "Segoe UI", Roboto, sans-serif;
}
.x-feed__item { padding: 12px 16px; border-bottom: 1px solid #2f3336; }
.x-feed__item:last-child { border-bottom: 0; }
.x-feed__item:hover { background: #080808; }
/* Un fil se lit d'un seul tenant : le séparateur est porté par le bloc, pas par
   chacun de ses posts. Sinon le trait vertical d'un fil serait coupé par des
   lignes horizontales, et X n'en met aucune entre les posts d'un même fil. */
.x-feed__thread { border-bottom: 1px solid #2f3336; }
.x-feed__thread:last-child { border-bottom: 0; }
.x-feed__thread > .x-feed__item { padding: 12px 16px 0; border-bottom: 0; }
.x-feed__thread > .x-feed__item:last-child { padding-bottom: 12px; }
.x-feed__row { display: flex; gap: 12px; }
/* Colonne de gauche : l'avatar en tête, le trait qui descend vers le post suivant.
   X répète l'en-tête complet à chaque post d'un fil : c'est ce qui distingue un
   thread d'un seul bloc de texte. */
.x-feed__gutter { display: flex; flex-direction: column; align-items: center; flex: 0 0 40px; width: 40px; }
.x-feed__avatar { width: 40px; height: 40px; flex: 0 0 auto; border-radius: 8px; object-fit: cover; background: #16181c; }
.x-feed__avatar--fallback { display: flex; align-items: center; justify-content: center; color: #e7e9ea; font-weight: 700; font-size: 15px; }
.x-feed__line { flex: 1 1 auto; width: 2px; min-height: 12px; background: #2f3336; margin-top: 4px; }
.x-feed__content { flex: 1 1 auto; min-width: 0; }
.x-feed__repost { display: flex; align-items: center; gap: 6px; color: #71767b; font-size: 13px; font-weight: 600; margin-bottom: 2px; }
.x-feed__repost-icon { width: 16px; height: 16px; }
.x-feed__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.x-feed__identity { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; min-width: 0; }
.x-feed__name { color: #e7e9ea; font-weight: 700; font-size: 15px; line-height: 20px; }
.x-feed__handle { color: #71767b; font-size: 15px; line-height: 20px; }
.x-feed__position { color: #71767b; }
.x-feed__badge { width: 18px; height: 18px; flex: 0 0 auto; }
.x-feed__badge--blue { color: #1d9bf0; }
.x-feed__badge--business { color: #d4a017; }
.x-feed__badge--government { color: #8b98a5; }
.x-feed__head-right { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.x-feed__tools { display: flex; align-items: center; gap: 6px; color: #71767b; }
.x-feed__tools:hover { color: #1d9bf0; }
.x-feed__tool-icon { width: 18px; height: 18px; }
.x-feed__body { margin-top: 2px; }
.x-feed__text { color: #e7e9ea; font-size: 17px; line-height: 24px; white-space: pre-wrap; word-break: break-word; margin: 0; }
.x-feed__token { color: #1d9bf0; }
.x-feed__clamp { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden; }
.x-feed__more { color: #1d9bf0; font-size: 15px; line-height: 20px; margin-top: 4px; align-self: flex-start; }
.x-feed__more:hover { text-decoration: underline; }
.x-feed__media, .x-feed__grid { margin-top: 12px; border: 1px solid #2f3336; border-radius: 16px; overflow: hidden; }
.x-feed__media { display: flex; justify-content: center; background: #000000; }
.x-feed__media-link { display: flex; justify-content: center; position: relative; max-width: 100%; }
/* Un média seul **garde son rapport d'aspect** : X le réduit, il ne le recadre
   pas. Une vidéo verticale recadrée en bandeau large ne montre qu'une tranche du
   milieu — le fil donne alors à voir une autre image que celle publiée. */
.x-feed__media-img { display: block; width: auto; height: auto; max-width: 100%; max-height: 510px; }
/* Dans une grille, en revanche, X recadre en carré : c'est la seule façon
   d'aligner des images de formats différents. */
.x-feed__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; }
.x-feed__grid .x-feed__media-img { width: 100%; height: 100%; object-fit: cover; }
.x-feed__grid--three { grid-template-rows: 1fr 1fr; }
.x-feed__media-cell { aspect-ratio: 1 / 1; }
.x-feed__media-cell--tall { grid-row: span 2; }
.x-feed__play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.x-feed__play-disc { width: 48px; height: 48px; border-radius: 9999px; background: rgba(0, 0, 0, 0.6); display: flex; align-items: center; justify-content: center; }
.x-feed__play-icon { width: 28px; height: 28px; color: #ffffff; }
.x-feed__play-label {
  position: absolute; top: 8px; right: 8px; background: rgba(0, 0, 0, 0.7);
  color: #ffffff; border-radius: 4px; padding: 1px 6px; font-size: 10px;
  line-height: 14px; text-transform: uppercase;
}
.x-feed__lost {
  margin-top: 12px; border: 1px solid #2f3336; border-radius: 16px;
  padding: 8px 12px; color: #71767b; font-size: 13px; line-height: 16px;
  display: flex; align-items: center; gap: 8px;
}
.x-feed__card { display: block; margin-top: 12px; border: 1px solid #2f3336; border-radius: 16px; overflow: hidden; }
.x-feed__card:hover { background: #080808; }
.x-feed__card-media { border-bottom: 1px solid #2f3336; }
.x-feed__card-img { display: block; width: 100%; max-height: 240px; object-fit: cover; }
.x-feed__card-body { display: flex; flex-direction: column; gap: 2px; padding: 12px; }
.x-feed__card-domain { color: #71767b; font-size: 13px; line-height: 16px; }
.x-feed__card-title { color: #e7e9ea; font-size: 15px; line-height: 20px; }
.x-feed__card-desc { color: #71767b; font-size: 15px; line-height: 20px; }
.x-feed__actions { display: flex; justify-content: space-between; align-items: center; max-width: 425px; margin-top: 12px; }
.x-feed__actions-right { display: flex; align-items: center; gap: 20px; }
.x-feed__action { display: flex; align-items: center; gap: 4px; color: #71767b; }
.x-feed__action:hover { color: #1d9bf0; }
.x-feed__action-icon { width: 18.75px; height: 18.75px; }
.x-feed__count { color: #71767b; font-size: 13px; line-height: 16px; }

/* Utilitaires des cartes de brief. */
.border-surface-container-highest { border-color: var(--surface-container-highest); }
.h-72 { height: 18rem; }
.max-h-72 { max-height: 18rem; }
.pl-2 { padding-left: 0.5rem; }
.cursor-not-allowed { cursor: not-allowed; }
.cursor-wait { cursor: wait; }
.cursor-zoom-in { cursor: zoom-in; }
/* Un champ de saisie garde son anneau au clavier mais pas au clic : sans cette
   règle, le contour du navigateur se superpose au fond sombre. */
.outline-none { outline: none; }
.hover\:bg-error-container\/40:hover { background-color: color-mix(in srgb, var(--error-container) 40%, transparent); }

/* La zone de texte d'un contenu de base : elle doit montrer qu'elle s'agrandit, sinon
   on écrit trois lignes à l'aveugle dans un champ qui semble figé. */
.min-h-\[90px\] { min-height: 90px; }
.resize-y { resize: vertical; }

/* Une option qu'on ne peut pas encore prendre : présente, lisible, mais en retrait —
   la couleur seule ne dit pas « pas maintenant ». */
.opacity-60 { opacity: 0.6; }

/* La zone de dépôt d'un fichier : la bordure s'allume au survol, comme les autres
   zones cliquables — sans quoi rien ne dit qu'elle se clique. */
.hover\:border-primary:hover { border-color: var(--primary); }

/* La carte de style choisie : bordure pleine et fond teinté. Deux crans de surface
   seulement — une carte sélectionnée doit se distinguer d'un coup d'œil, pas crier. */
.border-primary { border-color: var(--primary); }
.bg-primary\/10 { background-color: color-mix(in srgb, var(--primary) 10%, transparent); }
.hover\:border-primary\/60:hover {
  border-color: color-mix(in srgb, var(--primary) 60%, transparent);
}

/* La liste des voix : elle défile dans une hauteur bornée — trente lignes pousseraient
   le formulaire hors de l'écran, et le dernier élément n'a pas de séparateur (le
   trait du bas fermerait une liste qui continue). */
.max-h-\[16rem\] { max-height: 16rem; }
.last\:border-b-0:last-child { border-bottom-width: 0; }

/* La colonne de gauche de l'onglet Vidéo : elle suit le défilement quand la liste des
   scripts est plus longue qu'elle. Un formulaire qu'on ne voit plus pendant qu'on relit
   un texte oblige à remonter la page à chaque correction. */
.lg\:sticky { position: static; }
.lg\:top-space { top: 1.5rem; }
@media (min-width: 1024px) {
  .lg\:sticky { position: sticky; }
}


/* « Post my X » — le champ du brouillon et le témoin d'attente.
   Le champ grandit avec le texte (« resize-y ») : un brouillon d'idée fait parfois
   dix lignes, et une zone figée oblige à écrire dans une meurtrière. Le témoin bat
   doucement pendant la génération : une pastille immobile se lit comme un blocage. */
.postx-champ {
  min-height: 128px;
  line-height: 1.55;
}
.postx-pulse {
  animation: postx-battement 1.4s ease-in-out infinite;
}
@keyframes postx-battement {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}


/* « Post my X » — les quelques utilitaires de la vue qui n'existaient pas encore.
   La palette du projet n'a pas de « tertiary » : la question de l'agent se marque
   en secondaire, comme les autres appels à l'action de l'application. */
.m-0 { margin: 0; }
.break-words { overflow-wrap: break-word; word-break: break-word; }
.h-px { height: 1px; }
.self-end { align-self: flex-end; }
.text-\[22px\] { font-size: 22px; line-height: 30px; }
.text-\[32px\] { font-size: 32px; line-height: 40px; }
.max-w-\[92\%\] { max-width: 92%; }
.max-w-\[260px\] { max-width: 260px; }
.min-h-\[360px\] { min-height: 360px; }
.w-\[132px\] { width: 132px; }
.w-\[150px\] { width: 150px; }
.bg-outline-variant\/60 { background-color: color-mix(in srgb, var(--outline-variant) 60%, transparent); }
.border-outline-variant\/60 { border-color: color-mix(in srgb, var(--outline-variant) 60%, transparent); }
.bg-secondary-container\/30 { background-color: color-mix(in srgb, var(--secondary-container) 30%, transparent); }
.bg-secondary-container\/25 { background-color: color-mix(in srgb, var(--secondary-container) 25%, transparent); }
.bg-error-container\/20 { background-color: color-mix(in srgb, var(--error-container) 20%, transparent); }
.border-secondary\/30 { border-color: color-mix(in srgb, var(--secondary) 30%, transparent); }

/* La croix d'un logo de référence, collée au coin de sa vignette.
   Les décalages négatifs n'existent qu'en pas de 0.5rem dans les utilitaires, et
   une pastille à -0.5rem sur une vignette de 4rem mangeait l'image : d'où une
   classe composant, comme `.notif-badge`, plutôt qu'un utilitaire détourné. */
.visuel-ref__retirer {
  position: absolute;
  top: -0.35rem;
  right: -0.35rem;
  width: 1.25rem;
  height: 1.25rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: var(--surface-container-highest);
  border: 1px solid var(--outline-variant);
  color: var(--on-surface-variant);
  cursor: pointer;
}
.visuel-ref__retirer:hover { color: var(--error); border-color: var(--error); }

/* La zone où l'on dépose le logo de référence.
   Le survol se peint par une classe, pas par un rendu : reconstruire l'élément sous
   le curseur déclencherait `dragleave`, et la zone clignoterait pendant le dépôt. */
.visuel-depot {
  border: 1px dashed var(--outline-variant);
  border-radius: 0.75rem;
  padding: 0.5rem;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.visuel-depot--survol {
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  border-color: var(--primary);
}


/* La barre du haut sur un écran étroit.
   Les libellés cèdent la place aux icônes : « Post my X » et « Points » restent
   reconnaissables par leur logo, et la latence se lit dans l'état du système. Sans
   cela, les deux groupes de la barre se marchaient dessus avant 900 px et la page
   prenait une barre de défilement horizontale. */
/* Le bouton du tiroir n'existe qu'à l'étroit : sur large, la barre est toujours là. */
.btn-tiroir { display: none; }
#fond-sidebar { display: none; }

/* La barre d'onglets d'une fiche projet défile sur place quand elle ne tient pas :
   à 390 px, ses cinq onglets poussaient le document à 422 px, donc toute la page
   glissait latéralement. La barre de défilement est masquée — sur téléphone elle
   mange une hauteur précieuse et le défilement se fait au doigt. */
.barre-onglets { min-width: 0; overflow-x: auto; scrollbar-width: none; }
.barre-onglets::-webkit-scrollbar { display: none; }

/* --------------------------------------------------------- écrans étroits
 *
 * À 390 px, garder 18 rem de barre latérale ne laissait qu'une centaine de pixels
 * au contenu : l'application était inutilisable sur téléphone, alors que Dash s'en
 * sert depuis le sien. Le contenu prend donc toute la largeur, et la barre devient
 * un tiroir que le bouton du haut ouvre — le fond assombri le referme.
 *
 * `--sidebar-w` est remise à zéro **en important** : la largeur choisie à la main
 * est posée en style en ligne sur `<html>` (voir `applySidebarWidth`), et un style
 * en ligne bat une règle de feuille. Sans le `!important`, un redimensionnement
 * fait sur large reviendrait pousser le contenu à l'étroit.
 */
@media (max-width: 900px) {
  :root { --sidebar-w: 0rem !important; }
  #sidebar {
    width: 17rem;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 0 0 34px rgba(0, 0, 0, 0.45);
  }
  body.sidebar-ouvert #sidebar { transform: none; }
  body.sidebar-ouvert #fond-sidebar {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 45;
    background: rgba(0, 0, 0, 0.5);
  }
  #sidebar-resizer { display: none; }
  .btn-tiroir { display: flex; }
  .bartop__mot { display: none; }
  #net-latency { display: none; }
}
