/*
 * asmo : styles de base.
 * Direction artistique : épure (pas de bordure décorative, séparation par l'espace),
 * menu latéral fixe à gauche, rouge réservé à l'action principale de la page.
 * Thème sombre par défaut, clair si le système le demande (prefers-color-scheme).
 * Contrastes mesurés (WCAG AA) : voir la mémoire frontend-ux « ui-conventions ».
 */

/* Inter (SIL OFL 1.1, voir fonts/inter/OFL.txt), police variable hébergée ici, graisses 100 à 900. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-wght-normal.260c81a4759b.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Lettres accentuées hors français courant : téléchargé seulement si la page en contient. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter/inter-latin-ext-wght-normal.1ad231aac0a8.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Fonds */
  --bg: #0f0f0f;
  --sidebar-bg: #181818;
  --sidebar-border: #262626;
  --surface: #171717;
  --surface-hover: #1f1f1f;
  --hover-bg: #262626;
  --nav-current-bg: #262626;
  --input-bg: #0f0f0f;
  /* Textes */
  --text-strong: #ffffff;
  --text: #e5e5e5;
  --text-muted: #a3a3a3;
  /* Contours : --border pour les champs (3:1 minimum, WCAG 1.4.11), --border-subtle décoratif. */
  --border: #6b6b6b;
  --border-subtle: #262626;
  /* Boutons */
  --primary: #dc2626;
  --primary-hover: #b91c1c;
  --primary-text: #ffffff;
  --secondary-bg: #262626;
  --secondary-hover: #333333;
  --secondary-text: #f5f5f5;
  --danger: #f87171;
  --danger-hover-bg: #2a1515;
  /* États */
  --focus: #60a5fa;
  --error: #f87171;
  --success: #4ade80;
  /* Pastille d'une réussite (« À créer », « Importé », US-05.4) : texte sur son fond
     8,8:1 en sombre, 6,5:1 en clair. */
  --success-bg: #132a1c;
  --success-text: #4ade80;
  --control-accent: #e5e5e5;
  /* Tâches : priorité (texte >= 5,4:1 sur tous les fonds, y compris celui des pastilles)
     et trait d'arborescence (décoratif : la hiérarchie passe par l'indentation et les listes). */
  --priority-urgent: #f87171;
  --priority-high: #fdba74;
  --tree-line: #333333;
  /* Kanban (mesures dans la mémoire frontend-ux) : carte un cran plus claire que la colonne
     (--surface), alerte de limite dépassée (texte >= 9:1 sur tous les fonds, y compris le
     sien), fond de la liste survolée pendant un glisser. */
  --card-bg: #1f1f1f;
  --card-hover-bg: #262626;
  --warning: #fbbf24;
  --warning-bg: #2a2110;
  --drop-target-bg: #141414;
  /* Vidéos dans le calendrier (US-05.2) : fond orangé, barre et icône caméra orange ; une
     couleur fixe, que les projets n'utilisent jamais en fond (leur couleur n'est qu'une
     pastille sur le gris des tâches). Sur le fond et au survol : --text-strong >= 12,3:1,
     --text-muted >= 4,9:1, barre et icône >= 5,4:1, coche --success >= 7,1:1. */
  --video-bg: #3a2412;
  --video-hover-bg: #4a2e17;
  --video-accent: #fb923c;
  /* Streams (US-05.3) : fond violet, barre et icône antenne violettes, sur le même modèle
     que les vidéos (couleur fixe, jamais un fond de projet). Sur le fond et au survol :
     --text-strong >= 12,7:1, --text >= 10,1:1, --text-muted >= 5:1, barre et icône
     >= 4,7:1 (>= 5,5:1 sur les fonds de la page). */
  --stream-bg: #2a1f45;
  --stream-hover-bg: #372a5a;
  --stream-accent: #a78bfa;
  /* Notes (US-02.14) : traits des tableaux et ligne de séparation d'une note (décoratifs :
     la structure d'un tableau passe par ses en-têtes, en gras). Police à chasse fixe du
     code : polices du système, aucune téléchargée. */
  --rule: #404040;
  --font-mono: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  /* Couleurs de projet : au moins 5,7:1 sur --bg, --surface et --secondary-bg (WCAG 1.4.11 : 3:1). */
  --project-blue: #8ab4f8;
  --project-green: #81c995;
  --project-red: #f28b82;
  --project-orange: #fcad70;
  --project-yellow: #fdd663;
  --project-purple: #c58af9;
  --project-pink: #ff8bcb;
  --project-teal: #78d9ec;
  --project-gray: #9aa0a6;
  /* Types de temps (rapports, US-04.3) : une couleur fixe par type, dans le graphique et en
     pastille carrée dans le tableau. Au moins 4:1 sur --bg et 3,7:1 sur --surface ; écart
     de couleur (CIE76) d'au moins 20 entre deux types, en vision normale comme pour les
     trois formes de daltonisme simulées (Machado 2009). Mêmes teintes dans les deux thèmes. */
  --kind-preparation: #fde047;
  --kind-shooting: #93c5fd;
  --kind-live: #a855f7;
  --kind-editing: #22c55e;
  --kind-publishing: #fda4af;
  --kind-other: #737373;
  /* Mesures */
  --radius: 6px;
  --space: 1rem;
  --sidebar-width: 15rem;
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.5;
  color-scheme: dark;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #ffffff;
    --sidebar-bg: #f5f5f5;
    --sidebar-border: #e5e5e5;
    --surface: #f5f5f5;
    --surface-hover: #ebebeb;
    --hover-bg: #e5e5e5;
    --nav-current-bg: #e5e5e5;
    --input-bg: #ffffff;
    --text-strong: #0a0a0a;
    --text: #262626;
    --text-muted: #525252;
    --border: #8a8a8a;
    --border-subtle: #e5e5e5;
    --primary: #dc2626;
    --primary-hover: #b91c1c;
    --primary-text: #ffffff;
    --secondary-bg: #ebebeb;
    --secondary-hover: #dcdcdc;
    --secondary-text: #171717;
    --danger: #b91c1c;
    --danger-hover-bg: #fef2f2;
    --focus: #1d4ed8;
    --error: #b91c1c;
    --success: #15803d;
    --success-bg: #dcfce7;
    --success-text: #166534;
    --control-accent: #171717;
    --priority-urgent: #b91c1c;
    --priority-high: #9a3412;
    --tree-line: #d4d4d4;
    --card-bg: #ffffff;
    --card-hover-bg: #fafafa;
    --warning: #92400e;
    --warning-bg: #fff7e6;
    --drop-target-bg: #ebebeb;
    /* Vidéos : --text-strong >= 14,6:1, --text-muted >= 5,7:1, barre et icône >= 3,8:1,
       coche --success >= 3,7:1, sur le fond et au survol. */
    --video-bg: #ffedd5;
    --video-hover-bg: #fed7aa;
    --video-accent: #c2410c;
    /* Streams : --text-strong >= 14,2:1, --text >= 10,9:1, --text-muted >= 5,6:1, barre et
       icône >= 5,1:1 (>= 5,9:1 sur les fonds de la page), sur le fond et au survol. */
    --stream-bg: #ede9fe;
    --stream-hover-bg: #ddd6fe;
    --stream-accent: #6d28d9;
    --rule: #d4d4d4;
    /* Couleurs de projet : au moins 3,4:1 sur --bg, --surface et --secondary-bg (WCAG 1.4.11 : 3:1). */
    --project-blue: #1a73e8;
    --project-green: #188038;
    --project-red: #d93025;
    --project-orange: #c26401;
    --project-yellow: #8f6c00;
    --project-purple: #8430ce;
    --project-pink: #c2185b;
    --project-teal: #00838f;
    --project-gray: #6b7178;
    /* Types de temps : au moins 3,3:1 sur --bg et 3:1 sur --surface (vert, le plus clair),
       les autres >= 4,3:1 ; écart de couleur >= 20, daltonismes compris. */
    --kind-preparation: #854d0e;
    --kind-shooting: #2563eb;
    --kind-live: #6b21a8;
    --kind-editing: #16a34a;
    --kind-publishing: #9f1239;
    --kind-other: #737373;
    color-scheme: light;
  }
}

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

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Liens : soulignés (pas d'information portée par la seule couleur). */
a {
  color: var(--text-strong);
  text-decoration-color: var(--text-muted);
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-color: currentColor;
}

/* Focus toujours bien visible au clavier, dans les deux thèmes (au moins 6:1 sur tous les fonds). */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  left: var(--space);
  top: -3rem;
  padding: 0.5rem 1rem;
  font-weight: 600;
  color: var(--bg);
  background: var(--text-strong);
  border-radius: var(--radius);
  z-index: 10;
}

.skip-link:focus {
  top: var(--space);
}

/* Icônes Lucide (sprite static/icons/lucide.svg) : décoratives, toujours à côté d'un texte. */
.icon {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
  vertical-align: -0.2em;
}

.icon--xl {
  width: 2.5rem;
  height: 2.5rem;
}

/* Logo d'asmo (includes/logo.html) : la montagne au-dessus du mot, en rouge (--primary),
   dessinés sur la taille du mot comme sur le logo fourni. Le mot : Inter 600, lettres
   serrées. La montagne : 378 × 148 unités (1 unité = 1 px de l'image, où le mot est en
   corps 311 px), décalée de 0,067 em vers la droite, sa base à 0,656 em au-dessus de la
   ligne de base du mot (marge négative : elle mord sur l'interligne, réduit à 0,75 pour que
   la boîte suive le dessin). Rouge >= 3,6:1 sur le fond du menu, >= 3,9:1 sur celui des pages et
   >= 3,1:1 sur celui du survol, dans les deux thèmes (élément graphique : 3:1 au moins). */
.brand {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 0.375rem 0.625rem;
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 0.75;
  letter-spacing: -0.03em;
  color: var(--primary);
  text-decoration: none;
  border-radius: var(--radius);
}

/* Survol : le fond des entrées du menu (le logo n'est pas souligné). */
.brand:hover {
  background: var(--hover-bg);
}

/* Positionnée : peinte après le mot, donc devant le fond uni que le mode contraste élevé
   pose derrière chaque ligne de texte (il cachait le bas de la montagne) et devant la
   sélection du texte. */
.brand-mark {
  position: relative;
  display: block;
  flex: none;
  width: 1.215em;
  height: 0.476em;
  margin: 0 0 -0.081em 0.067em;
}

.brand-name {
  white-space: nowrap;
}

.container {
  width: 100%;
  max-width: 28rem;
  margin: 2rem auto;
  padding: 0 var(--space);
}

.container:focus {
  outline: none;
}

/* Pages métier : colonne plus large que celle des pages de connexion. */
.container--wide {
  max-width: 64rem;
}

/* Kanban : toute la largeur disponible, les colonnes défilent si elles dépassent.
   min-width: 0 empêche le tableau d'élargir la page (élément de grille de .app-shell). */
.container--board {
  min-width: 0;
  max-width: none;
}

h1,
h2,
h3 {
  color: var(--text-strong);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
}

h1 {
  font-size: 1.5rem;
  margin-top: 0;
}

h2 {
  font-size: 1.0625rem;
}

/* Formulaires générés par allauth (éléments label, input, button). */
form p,
form > div {
  margin: 0 0 var(--space);
}

label {
  display: block;
  margin-bottom: 0.375rem;
  font-weight: 500;
  color: var(--text-strong);
}

/* Champs : seul élément à garder un contour, contrasté à 3:1 (WCAG 1.4.11).
   Spécificité nulle (:where) pour que survol, focus et erreur puissent la surcharger. */
:where(
  input[type="email"],
  input[type="password"],
  input[type="text"],
  input[type="url"],
  input[type="search"],
  input[type="number"],
  input[type="date"],
  input[type="time"],
  textarea,
  select
) {
  width: 100%;
  padding: 0.55rem 0.75rem;
  font: inherit;
  color: var(--text-strong);
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

/* :where() garde une spécificité faible : le contour d'erreur ci-dessous reste prioritaire. */
:where(input, textarea, select):hover {
  border-color: var(--text-muted);
}

:where(input, textarea, select):focus-visible {
  border-color: var(--focus);
  outline-offset: 1px;
}

::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
  vertical-align: middle;
}

textarea {
  min-height: 8rem;
  resize: vertical;
}

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--control-accent);
}

label:has(input[type="checkbox"]) {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
}

/* Bouton primaire (par défaut) : rouge, réservé à l'action principale de la page. */
button,
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.5rem;
  padding: 0.5rem 1rem;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--primary-text);
  background: var(--primary);
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
}

a.button {
  text-decoration: none;
}

button:hover,
.button:hover {
  background: var(--primary-hover);
}

/* Bouton secondaire : gris sobre, pour toutes les autres actions (Modifier, Archiver, Annuler). */
/* Pendant une requête HTMX (hx-disabled-elt) : le bouton ne peut pas partir deux fois. */
button:disabled {
  cursor: progress;
  opacity: 0.7;
}

.button--secondary {
  color: var(--secondary-text);
  background: var(--secondary-bg);
}

.button--secondary:hover {
  background: var(--secondary-hover);
}

/* Bouton dangereux : texte et contour rouges sur fond transparent, jamais plein comme le primaire.
   Le libellé dit toujours ce qu'il fait (« Supprimer définitivement ») et porte une icône corbeille. */
.button--danger {
  color: var(--danger);
  background: transparent;
  border-color: currentColor;
}

.button--danger:hover {
  background: var(--danger-hover-bg);
}

/* Petit bouton (commandes d'une carte du kanban) : cible de 2rem de haut. */
.button--small {
  gap: 0.375rem;
  min-height: 2rem;
  padding: 0.25rem 0.625rem;
  font-size: 0.875rem;
}

.button--small .icon {
  width: 1rem;
  height: 1rem;
}

.button-link {
  min-height: 0;
  padding: 0;
  font-weight: 400;
  color: var(--text-strong);
  background: none;
  border: none;
  text-decoration: underline;
}

.button-link:hover {
  background: none;
}

.helptext,
small {
  display: block;
  color: var(--text-muted);
  font-size: 0.875rem;
}

/* Erreurs : signalées par le texte et un contour plus épais, pas par la seule couleur. */
.errorlist {
  margin: 0.25rem 0 0;
  padding-left: 1.2rem;
  color: var(--error);
}

[aria-invalid="true"] {
  border: 2px solid var(--error);
}

.messages {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
}

/* Messages et encarts : fond légèrement relevé et fine barre à gauche, sans cadre. */
.message {
  padding: 0.75rem var(--space);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: inset 3px 0 0 var(--text-muted);
}

.message + .message {
  margin-top: 0.5rem;
}

.message-error {
  box-shadow: inset 3px 0 0 var(--error);
}

.message-success {
  box-shadow: inset 3px 0 0 var(--success);
}

.message-warning {
  box-shadow: inset 3px 0 0 var(--warning);
}

/* Adresse écrite dans un message (les connexions de Twitch après « Délier », US-01.7) :
   coupée où il faut plutôt que de déborder sur un téléphone. */
.message a {
  overflow-wrap: anywhere;
}

/* Texte lu par les lecteurs d'écran mais masqué à l'écran. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.muted {
  color: var(--text-muted);
}

/* L'attribut hidden l'emporte toujours, même sur un composant en display: flex
   (boutons du chrono d'une tâche, encarts d'erreur). */
[hidden] {
  display: none !important;
}

/* ---------- Mise en page ---------- */

.app-shell,
.page {
  flex: 1;
}

/* Visiteur non connecté (connexion, inscription) : logo centré au-dessus du formulaire. */
.site-header {
  display: flex;
  justify-content: center;
  padding: 3rem var(--space) 0;
}

.site-header .brand {
  padding: 0.5rem 0.75rem;
  font-size: 2.75rem;
}

/* Connecté : menu latéral + contenu. Écran étroit : le menu devient une barre au-dessus du contenu. */
.app-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
}

.sidebar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  padding: 0.5rem 0.75rem;
  background: var(--sidebar-bg);
  border-bottom: 1px solid var(--sidebar-border);
}

.sidebar-nav {
  flex: 1 1 auto;
}

.nav-list,
.nav-sublist,
.nav-list > li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Lien du menu (aussi utilisé pour le bouton de déconnexion). */
.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.625rem;
  min-height: 2.25rem;
  padding: 0.375rem 0.625rem;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 400;
  color: var(--text-muted);
  text-align: left;
  text-decoration: none;
  background: transparent;
  border: none;
  border-radius: var(--radius);
}

.nav-link:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

/* Entrée active : texte en gras et plus clair, fond et barre, pas seulement une couleur. */
.nav-link[aria-current] {
  font-weight: 600;
  color: var(--text-strong);
  background: var(--nav-current-bg);
}

.nav-link[aria-current]::before {
  content: "";
  position: absolute;
  left: 0.625rem;
  right: 0.625rem;
  bottom: -0.25rem;
  height: 2px;
  border-radius: 2px;
  background: var(--text-strong);
}

/* Pied du menu : « Importer depuis Notion », « Connexions », « Sécurité du compte » (des
   liens), puis la déconnexion (un formulaire). */
.sidebar-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem;
  margin: 0;
}

.sidebar-footer form {
  margin: 0;
}

@media (forced-colors: active) {
  .nav-link[aria-current]::before {
    forced-color-adjust: none;
    background: CanvasText;
  }
}

@media (min-width: 48rem) {
  .app-shell {
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  }

  /* Menu fixe : il reste visible pendant que le contenu défile. */
  .sidebar {
    position: sticky;
    top: 0;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 1.25rem;
    height: 100vh;
    height: 100dvh;
    padding: 1rem 0.75rem;
    overflow-y: auto;
    border-bottom: none;
    border-right: 1px solid var(--sidebar-border);
  }

  /* Logo un peu plus grand dans le menu latéral ; le début du mot reste aligné sur les
     icônes des entrées (même marge intérieure que .nav-link : 0.625rem). */
  .sidebar .brand {
    font-size: 1.75rem;
  }

  .nav-list,
  .nav-sublist,
  .nav-list > li {
    flex-direction: column;
    flex-wrap: nowrap;
  }

  .nav-link--sub {
    padding-left: 2.375rem;
  }

  .nav-link[aria-current]::before {
    left: -0.75rem;
    right: auto;
    top: 0.375rem;
    bottom: 0.375rem;
    width: 3px;
    height: auto;
    border-radius: 0 2px 2px 0;
  }

  /* Compte et déconnexion en bas du menu, l'un sous l'autre. */
  .sidebar-footer {
    flex-direction: column;
    flex-wrap: nowrap;
    margin-top: auto;
  }

  .sidebar-footer .nav-link {
    width: 100%;
  }

  .app-shell .container {
    margin: 2.5rem auto;
    padding: 0 2rem;
  }
}

/* ---------- Composants des pages ---------- */

/* En-tête de page : titre et action principale. */
.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
  margin-bottom: 2rem;
}

.page-header h1 {
  margin: 0;
  overflow-wrap: anywhere;
}

.title-with-swatch {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.lead {
  margin: 0 0 1.5rem;
  color: var(--text-muted);
}

.page-footer-link {
  margin-top: 2.5rem;
}

/* Lien discret de bas de page (retour, archives), précédé d'une icône. */
.subtle-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  color: var(--text-muted);
  font-size: 0.9375rem;
}

.subtle-link:hover {
  color: var(--text-strong);
}

/* Pastille de couleur d'un projet. Toujours accompagnée du nom du projet ou de la couleur. */
.swatch {
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  vertical-align: middle;
  border-radius: 50%;
  background: var(--swatch, var(--project-gray));
}

.swatch--lg {
  width: 1rem;
  height: 1rem;
}

.swatch--blue { --swatch: var(--project-blue); }
.swatch--green { --swatch: var(--project-green); }
.swatch--red { --swatch: var(--project-red); }
.swatch--orange { --swatch: var(--project-orange); }
.swatch--yellow { --swatch: var(--project-yellow); }
.swatch--purple { --swatch: var(--project-purple); }
.swatch--pink { --swatch: var(--project-pink); }
.swatch--teal { --swatch: var(--project-teal); }
.swatch--gray { --swatch: var(--project-gray); }

/* Mode contraste élevé de Windows : on garde la couleur de la pastille, avec un contour. */
@media (forced-colors: active) {
  .swatch {
    forced-color-adjust: none;
    border: 1px solid CanvasText;
  }
}

/* Statut : une étiquette en texte, neutre, sans cadre. */
.badge {
  display: inline-block;
  align-self: flex-start;
  margin: 0;
  padding: 0.125rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 999px;
}

/* Cartes de projet : fond à peine relevé, sans bordure ni ombre. */
.card-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: 1.125rem 1.25rem;
  background: var(--surface);
  border-radius: 8px;
}

.card p {
  margin: 0;
}

.card-title {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0;
  font-size: 1rem;
  overflow-wrap: anywhere;
}

.card-link {
  color: var(--text-strong);
  text-decoration: none;
}

.card-link:hover {
  text-decoration: underline;
}

/* Carte entièrement cliquable quand elle ne contient pas d'autre action. */
.card--linked .card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 8px;
}

.card--linked:hover {
  background: var(--surface-hover);
}

.card-meta {
  font-size: 0.875rem;
  color: var(--text-muted);
}

.card-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  font-size: 0.9375rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.card-actions {
  margin-top: auto;
  padding-top: 0.5rem;
}

/* État vide : icône discrète, à quoi sert l'écran et première action. Pas de cadre. */
.empty-state {
  padding: 4rem var(--space);
  text-align: center;
}

.empty-state .icon--xl {
  margin-bottom: 1rem;
  color: var(--text-muted);
}

.empty-state h2,
.empty-state h3 {
  margin-top: 0;
  font-size: 1.125rem;
}

.empty-state p {
  max-width: 30rem;
  margin: 0 auto 1.5rem;
  color: var(--text-muted);
}

/* Rangée de boutons ; les boutons en POST sont de petits formulaires en ligne. */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.inline-form,
form.actions {
  margin: 0;
}

/* Encart d'information (projet archivé) ou d'avertissement (suppression, erreurs) ;
   .preview-throttled : trop d'aperçus d'une note dans la minute (US-01.10, réponse 429). */
.notice,
.form-alert,
.preview-throttled {
  margin: 0 0 1.5rem;
  padding: 0.875rem var(--space);
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--text-muted);
}

.notice p {
  margin: 0;
}

.notice p + p {
  margin-top: 0.25rem;
  color: var(--text-muted);
}

.notice strong {
  color: var(--text-strong);
}

.notice--danger,
.form-alert,
.preview-throttled {
  box-shadow: inset 3px 0 0 var(--danger);
}

/* Avertissement (textes de pages non rattachés d'un import, US-05.4) : barre --warning. */
.notice--warning {
  box-shadow: inset 3px 0 0 var(--warning);
}

/* Une seule phrase, en clair comme les erreurs citées dans .form-alert-list. */
.preview-throttled {
  color: var(--text-strong);
}

/* Fiche projet : statut et couleur. */
.meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space) 3rem;
  margin: 0 0 2.5rem;
}

.meta dt {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* flex-wrap : sur écran étroit, un lien posé à côté de la valeur (« Voir dans le
   calendrier ») passe dessous au lieu de déborder. */
.meta dd {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
  margin: 0.375rem 0 0;
}

.section {
  margin-bottom: 2.5rem;
}

.section h2 {
  margin: 0 0 0.75rem;
}

/* Texte long : description, concept, mémo (paragraphes) et note rendue depuis le Markdown
   (US-02.14 : titres h2 à h6, listes, citations, code, tableaux, images, liens). Rien ne
   déborde sur téléphone : les mots trop longs se coupent, un bloc de code défile seul, une
   image ne dépasse jamais la largeur, un tableau resserre ses colonnes (il garde sa
   sémantique de tableau : pas de display: block). Dans les deux thèmes, tout le texte
   reste sur les jetons mesurés (--text, --text-strong, --text-muted). */
.prose {
  max-width: 44rem;
  overflow-wrap: anywhere;
}

.prose p {
  margin: 0 0 0.75rem;
}

.prose > :first-child {
  margin-top: 0;
}

.prose > :last-child {
  margin-bottom: 0;
}

.prose :is(h2, h3, h4, h5, h6) {
  margin: 1.75rem 0 0.625rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--text-strong);
}

.prose h2 {
  font-size: 1.375rem;
}

.prose h3 {
  font-size: 1.1875rem;
}

.prose h4 {
  font-size: 1.0625rem;
}

.prose h5 {
  font-size: 1rem;
}

.prose h6 {
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.prose strong {
  font-weight: 600;
  color: var(--text-strong);
}

/* Liens d'une note : soulignés en plein (le soulignement, pas la couleur, les signale). */
.prose a {
  text-decoration-color: currentColor;
}

.prose :is(ul, ol) {
  margin: 0 0 0.75rem;
  padding-left: 1.5rem;
}

.prose li + li {
  margin-top: 0.25rem;
}

.prose li > :is(ul, ol) {
  margin: 0.25rem 0 0;
}

.prose li > p {
  margin: 0 0 0.375rem;
}

.prose li::marker {
  color: var(--text-muted);
}

.prose blockquote {
  margin: 0 0 0.75rem;
  padding: 0.125rem 0 0.125rem 1rem;
  color: var(--text-muted);
  box-shadow: inset 3px 0 0 var(--border);
}

.prose blockquote > :last-child {
  margin-bottom: 0;
}

/* Code en ligne : texte --text sur --secondary-bg (12:1 en sombre, 12,7:1 en clair). */
.prose code,
.markdown-help code {
  padding: 0.0625em 0.35em;
  font-family: var(--font-mono);
  font-size: 0.875em;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 4px;
}

/* Bloc de code : il défile seul en largeur, la page ne bouge pas. Fond plus clair dans
   l'aperçu (posé sur --surface) : --prose-block-bg. */
.prose pre {
  margin: 0 0 0.75rem;
  padding: 0.75rem 1rem;
  overflow-x: auto;
  overflow-wrap: normal;
  line-height: 1.5;
  background: var(--prose-block-bg, var(--surface));
  border-radius: var(--radius);
}

.prose pre code {
  padding: 0;
  font-size: 0.875rem;
  white-space: pre;
  background: none;
}

.prose hr {
  margin: 1.5rem 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

/* Images (https seulement, chargées en différé) : jamais plus larges que le texte. */
.prose img {
  max-width: 100%;
  height: auto;
  vertical-align: middle;
  border-radius: var(--radius);
}

.prose table {
  margin: 0 0 0.75rem;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

/* Un mot coupé dans une colonne étroite (téléphone) l'est avec un trait d'union (lang="fr"). */
.prose :is(th, td) {
  padding: 0.375rem 0.75rem;
  text-align: start;
  vertical-align: top;
  border: 1px solid var(--rule);
  hyphens: auto;
}

.prose th {
  font-weight: 600;
  color: var(--text-strong);
  background: var(--prose-block-bg, var(--surface));
}

/* Alignement des colonnes (« :-- », « :-: », « --: » dans le Markdown), posé en classe
   par apps/notes/markdown.py (jamais d'attribut style). */
.prose .align-left {
  text-align: left;
}

.prose .align-center {
  text-align: center;
}

.prose .align-right {
  text-align: right;
}

@media (max-width: 29.99rem) {
  .prose table {
    font-size: 0.875rem;
  }

  .prose :is(th, td) {
    padding: 0.375rem 0.5rem;
  }
}

@media (forced-colors: active) {
  .prose blockquote {
    border-left: 3px solid CanvasText;
  }
}

/* Formulaire de projet. */
.form {
  max-width: 40rem;
}

.form .field {
  margin: 0 0 1.5rem;
}

.form > .actions {
  margin-top: 2rem;
}

fieldset.field {
  min-width: 0;
  padding: 0;
  border: none;
}

fieldset.field legend {
  margin-bottom: 0.5rem;
  padding: 0;
  font-weight: 500;
  color: var(--text-strong);
}

/* Sélecteur de couleur : radios natives (flèches du clavier), pastille et nom en texte. */
.color-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.color-option {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 0.375rem 0.75rem;
  font-weight: 400;
  color: var(--text);
  background: var(--surface);
  border-radius: 999px;
  cursor: pointer;
}

.color-option:hover {
  background: var(--hover-bg);
}

/* Couleur choisie : gras, fond plus marqué et anneau, en plus du bouton radio coché. */
.color-option:has(input:checked) {
  font-weight: 600;
  color: var(--text-strong);
  background: var(--secondary-bg);
  box-shadow: inset 0 0 0 2px var(--text-strong);
}

.color-option input {
  margin: 0;
}

@supports selector(:has(*)) {
  .color-option:has(input:focus-visible) {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
  }

  .color-option input:focus-visible {
    outline: none;
  }
}

/* Lien d'action sous un champ (fusion quand le nom d'une étiquette est déjà pris). */
.field-action {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0.5rem 0 0;
  font-size: 0.9375rem;
}

/* ---------- Étiquettes ---------- */

/* Pastille d'étiquette : point de couleur (décoratif) + nom en texte, fond neutre sans cadre.
   Texte --text sur --secondary-bg : 12:1 en sombre, 12,7:1 en clair. */
.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tag-list > li {
  display: flex;
  min-width: 0;
}

.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  padding: 0.0625rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 999px;
  overflow-wrap: anywhere;
}

.tag-chip .swatch {
  width: 0.5rem;
  height: 0.5rem;
}

/* Ligne de tâche : pastilles plus petites, qui passent sous le titre si la place manque. */
.tag-list--compact .tag-chip {
  padding: 0 0.4375rem;
  font-size: 0.75rem;
}

/* Saisie : les étiquettes existantes reprennent le style du sélecteur de couleur
   (.color-option : case native visible, gras et anneau quand cochée, focus sur la pastille). */
.tag-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-bottom: 1rem;
}

.tag-option {
  overflow-wrap: anywhere;
}

.tag-new label {
  margin-bottom: 0.125rem;
}

.tag-new .helptext {
  margin-bottom: 0.375rem;
}

.tag-manage {
  margin: 0.75rem 0 0;
}

.tag-manage .subtle-link {
  font-size: 0.875rem;
}

/* Page Étiquettes : une ligne par étiquette (nom, usages, actions), séparées par l'espace.
   Même liste pour les colonnes d'un projet et les liens d'une vidéo. */
.tag-rows,
.column-rows,
.link-rows {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1rem;
  padding: 0.375rem 0.5rem 0.375rem 0.75rem;
  border-radius: var(--radius);
}

.tag-row:hover {
  background: var(--surface);
}

.tag-row-name {
  display: flex;
  flex: 1 1 12rem;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
  font-weight: 500;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.tag-row-usage {
  flex: none;
  min-width: 6.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.tag-row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

/* Action d'une ligne : icône + verbe, discrète jusqu'au survol (cible de 2rem de haut).
   --text-muted >= 6:1 et --danger >= 5,1:1 sur tous les fonds de la ligne, dans les deux thèmes. */
.row-action {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius);
}

.row-action:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
  text-decoration: underline;
}

.row-action .icon {
  width: 1rem;
  height: 1rem;
}

.row-action--danger,
.row-action--danger:hover {
  color: var(--danger);
}

.row-action--danger:hover {
  background: var(--danger-hover-bg);
}

@media (max-width: 47.99rem) {
  .tag-row-actions {
    flex-basis: 100%;
    margin-left: -0.5rem;
  }
}

/* ---------- Filtre par étiquette (US-02.10) ---------- */

/* En tête de chaque vue filtrable, sous le titre et ses onglets (includes/tag_filter.html) :
   le bandeau du filtre actif, puis « Filtrer par étiquette » qui ouvre son volet (details
   natif, sans JavaScript). Tout passe à la ligne : rien ne déborde sur un téléphone. */
.tag-filter {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0 0 1.5rem;
}

/* Bandeau du filtre actif : fond relevé et barre à gauche, comme .notice ; « Filtré : »,
   une pastille par étiquette avec son « ✕ », puis « Tout afficher ». */
.tag-filter-active {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-self: stretch;
  gap: 0.375rem 0.75rem;
  min-width: 0;
  padding: 0.5rem 0.75rem 0.5rem 1rem;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--text-muted);
}

.tag-filter-label {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-strong);
}

.tag-filter-label .icon {
  width: 1rem;
  height: 1rem;
}

.tag-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Pastille d'une étiquette du filtre : point (décoratif), nom en texte, puis le lien « ✕ »
   (cible ronde de 1,5rem = 24 px, WCAG 2.5.8). --text-muted sur --secondary-bg : 6:1 en
   sombre, 6,5:1 en clair ; au survol, --text-strong. */
.tag-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  min-height: 1.75rem;
  padding: 0.125rem 0.125rem 0.125rem 0.625rem;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 999px;
}

.tag-filter-chip .swatch {
  width: 0.5rem;
  height: 0.5rem;
}

.tag-filter-chip-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

.tag-filter-remove {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--text-muted);
  border-radius: 50%;
}

.tag-filter-remove:hover {
  color: var(--text-strong);
  background: var(--secondary-hover);
}

.tag-filter-remove .icon {
  width: 0.875rem;
  height: 0.875rem;
}

.tag-filter-clear {
  font-size: 0.875rem;
  white-space: nowrap;
}

/* « Filtrer par étiquette » : un bouton secondaire, chevron qui pivote quand le volet est
   ouvert (l'état ne tient pas à la couleur). */
.tag-filter-toggle {
  list-style: none;
}

.tag-filter-toggle::-webkit-details-marker {
  display: none;
}

.tag-filter-toggle .tag-filter-chevron {
  width: 0.875rem;
  height: 0.875rem;
  transition: transform 0.15s ease;
}

.tag-filter-picker[open] .tag-filter-chevron {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .tag-filter-toggle .tag-filter-chevron {
    transition: none;
  }
}

/* Volet : les étiquettes en pastilles à cocher, comme dans les formulaires (.color-option),
   une phrase qui dit la règle, puis « Appliquer ». */
.tag-filter-form {
  max-width: 48rem;
  margin: 0.75rem 0 0;
}

.tag-filter-fieldset {
  min-width: 0;
  margin: 0 0 0.75rem;
  padding: 0;
  border: none;
}

.tag-filter-fieldset .tag-options {
  margin-bottom: 0.5rem;
}

.tag-filter-hint {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Aucune étiquette dans le compte : une phrase discrète vers la page Étiquettes. */
.tag-filter-none {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
  margin: 0 0 1.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.tag-filter-none .icon {
  width: 1rem;
  height: 1rem;
  margin-top: 0.1875rem;
}

/* Remarque sous le bandeau (rapport, temps : le temps à ranger n'a pas d'étiquette). */
.tag-filter-note {
  margin: -0.75rem 0 1.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

@media (forced-colors: active) {
  .tag-filter-active,
  .tag-filter-chip {
    border: 1px solid CanvasText;
  }

  .tag-filter-remove:hover {
    outline: 1px solid CanvasText;
  }
}

/* ---------- Tâches (fiche projet, fiche tâche) ---------- */

/* Titre de section avec un lien discret à droite (« Tâche détaillée »). */
.section-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin-bottom: 0.75rem;
}

.section .section-header h2 {
  margin: 0;
}

.section-footer {
  margin: 1rem 0 0;
}

/* Ajout rapide : un champ et un bouton sur une ligne. */
.quick-form {
  max-width: 40rem;
  margin: 0 0 1.25rem;
}

.quick-form label {
  font-size: 0.875rem;
}

.quick-form-row {
  display: flex;
  gap: 0.5rem;
}

.quick-form-row input {
  flex: 1 1 auto;
  min-width: 0;
}

.quick-form-row button {
  flex: none;
}

/* État vide d'une section (moins haut que celui d'une page). */
.empty-state--compact {
  padding: 2rem var(--space);
}

.empty-state .empty-state-title {
  margin-bottom: 0.25rem;
  font-weight: 600;
  color: var(--text-strong);
}

/* Arbre : listes imbriquées. Chaque niveau est décalé et relié par un trait vertical
   aligné sur la case du parent ; au-delà du 4e niveau le décalage se resserre pour
   rester lisible en profondeur et sur écran étroit. */
.task-tree {
  margin: 0;
  padding: 0;
  list-style: none;
}

.task-tree .task-tree {
  margin-left: 1.25rem;
  padding-left: 0.5rem;
  border-left: 1px solid var(--tree-line);
}

.task-tree .task-tree .task-tree .task-tree .task-tree {
  margin-left: 0.5rem;
  padding-left: 0.25rem;
}

@media (max-width: 47.99rem) {
  .task-tree .task-tree {
    margin-left: 0.75rem;
    padding-left: 0.25rem;
  }

  .task-tree .task-tree .task-tree .task-tree .task-tree {
    margin-left: 0.25rem;
    padding-left: 0.125rem;
  }
}

/* Ligne de tâche : case, titre en lien, puis priorité et échéance (sous le titre si la place manque). */
.task-row {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
  padding: 0.125rem 0.5rem 0.125rem 0.25rem;
  border-radius: var(--radius);
}

.task-row:hover {
  background: var(--surface);
}

.task-check-form {
  flex: none;
  margin: 0;
}

/* Case à cocher : un vrai bouton (cible de 2rem), cercle vide ou coché. */
.task-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  min-height: 2rem;
  padding: 0;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-radius: 50%;
}

button.task-check:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.task-check .icon {
  width: 1.25rem;
  height: 1.25rem;
}

.task-row--done .task-check {
  color: var(--success);
}

.task-main {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.125rem 0.75rem;
  min-width: 0;
  padding: 0.25rem 0;
}

.task-title {
  color: var(--text-strong);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.task-title:hover {
  text-decoration: underline;
}

/* Tâche terminée : barrée et atténuée (et « terminée » lu par les lecteurs d'écran). */
.task-row--done .task-title {
  color: var(--text-muted);
  text-decoration: line-through;
}

.task-row--done .task-title:hover {
  text-decoration: line-through underline;
}

/* Tâche gardée « hors filtre » (US-02.10) : parente d'une sous-tâche qui correspond au
   filtre, montrée pour garder l'arbre lisible. Titre atténué et en italique (pas la seule
   couleur : --text-muted >= 6:1 partout) ; « (hors filtre) » est lu par les lecteurs
   d'écran. Rien n'est estompé par opacité : les petits textes passeraient sous 4,5:1. */
.task-row--outside .task-title {
  font-style: italic;
  color: var(--text-muted);
}

.task-meta {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.task-due,
.task-state {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.375rem;
}

.task-meta .icon {
  width: 0.875rem;
  height: 0.875rem;
}

/* En retard : le mot est écrit, en gras, la couleur ne fait que le souligner. */
.task-due--overdue {
  color: var(--danger);
}

.task-overdue {
  font-weight: 600;
}

.task-state--done .icon {
  color: var(--success);
}

.task-heading--done {
  color: var(--text-muted);
  text-decoration: line-through;
}

/* Priorité : toujours écrite ; Urgente et Haute ajoutent un drapeau et leur couleur. */
.badge--urgent,
.badge--high {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.badge--urgent {
  font-weight: 600;
  color: var(--priority-urgent);
}

.badge--high {
  color: var(--priority-high);
}

.badge--low {
  color: var(--text-muted);
}

.badge .icon {
  width: 0.8125rem;
  height: 0.8125rem;
}

/* Fil d'Ariane : projet › tâche(s) parente(s) › page courante. */
.breadcrumb {
  margin: 0 0 1rem;
  font-size: 0.875rem;
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.breadcrumb li {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.breadcrumb a {
  color: var(--text-muted);
}

.breadcrumb a:hover {
  color: var(--text-strong);
}

.breadcrumb [aria-current="page"] {
  color: var(--text-strong);
  text-decoration: none;
}

.breadcrumb .icon {
  width: 0.875rem;
  height: 0.875rem;
}

/* ---------- Vues d'un projet (onglets Liste / Kanban) ---------- */

.page-header--with-tabs {
  margin-bottom: 1rem;
}

/* Onglets à gauche, lien secondaire (« Colonnes ») à droite, sur une ligne de base commune. */
.view-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin: 0 0 1.5rem;
  border-bottom: 1px solid var(--border-subtle);
}

.view-tabs ul {
  display: flex;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.view-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius) var(--radius) 0 0;
}

.view-tab:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

/* Vue courante : gras, texte plus clair et barre dessous, pas seulement une couleur.
   aria-current="true" : choix courant qui n'est pas exactement la page (Semaine | Mois des
   rapports, dont l'adresse garde aussi la date). */
.view-tab[aria-current="page"],
.view-tab[aria-current="true"] {
  font-weight: 600;
  color: var(--text-strong);
}

.view-tab[aria-current="page"]::after,
.view-tab[aria-current="true"]::after {
  content: "";
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--text-strong);
}

.view-bar .subtle-link {
  padding: 0.5rem 0;
}

/* ---------- Kanban ---------- */

.kanban-hint {
  margin: 0 0 1rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* Colonnes côte à côte. Si elles dépassent (écran étroit, beaucoup de colonnes), seul le
   tableau défile horizontalement, avec un arrêt doux au début de chaque colonne. */
/* position: relative : les textes masqués (.visually-hidden, en position absolue) restent
   dans la zone qui défile au lieu d'élargir la page. */
.kanban {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(min(17rem, 82vw), 1fr);
  align-items: stretch;
  gap: 0.75rem;
  margin: 0 -0.25rem;
  padding: 0.25rem 0.25rem 0.75rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 0.25rem;
}

.kanban-column {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  padding: 0.75rem 0.5rem 0.5rem;
  background: var(--surface);
  border-radius: 8px;
  scroll-snap-align: start;
}

/* Limite dépassée : barre en haut de la colonne, compteur et alerte écrite (pas la seule couleur). */
.kanban-column--over-limit {
  box-shadow: inset 0 3px 0 var(--warning);
}

/* Le compteur passe sous le nom s'ils ne tiennent pas ensemble (sous un filtre par
   étiquette, US-02.10, il dit « 2 affichées sur 5 · limite 8 »). */
.kanban-column-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 0.5rem;
  padding: 0 0.25rem;
}

.kanban-column-title {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  margin: 0;
  font-size: 0.9375rem;
  overflow-wrap: anywhere;
}

/* Colonne « terminé » : icône cochée devant le nom, et une phrase qui dit ce qu'elle fait. */
.kanban-column--done .kanban-column-title .icon {
  color: var(--success);
}

.kanban-count {
  flex: none;
  padding: 0.0625rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  background: var(--secondary-bg);
  border-radius: 999px;
}

.kanban-column--over-limit .kanban-count {
  font-weight: 600;
  color: var(--warning);
}

.kanban-column-note {
  margin: 0;
  padding: 0 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* --warning sur --warning-bg : 9,5:1 en sombre, 6,6:1 en clair. */
.kanban-alert {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  padding: 0.375rem 0.625rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--warning);
  background: var(--warning-bg);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--warning);
}

.kanban-alert .icon {
  width: 1rem;
  height: 1rem;
}

/* Liste des cartes : toujours une zone de dépôt, même vide, sur toute la hauteur de la colonne
   (les colonnes s'alignent sur la plus haute). */
.kanban-column-body {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
}

.kanban-cards {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.5rem;
  min-height: 4.5rem;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  border-radius: var(--radius);
}

.kanban-cards:not(:has(> li)) {
  outline: 1px dashed var(--border);
  outline-offset: -1px;
}

/* « Aucune tâche » posé sur la zone vide ; les clics la traversent, et le texte disparaît
   dès qu'une carte y entre pendant un glisser. */
.kanban-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  margin: 0;
  padding-top: 1.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  pointer-events: none;
}

.kanban-cards:has(> li) + .kanban-empty {
  display: none;
}

/* Carte : fond un cran plus clair que la colonne (--card-bg), sans bordure ni ombre. */
.kanban-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.625rem 0.75rem;
  background: var(--card-bg);
  border-radius: var(--radius);
}

/* Carte déplaçable : tâche (data-move-url) ou vidéo (data-status-url, US-05.2). */
.kanban-card[data-move-url],
.kanban-card[data-status-url] {
  cursor: grab;
}

.kanban-card[data-move-url]:hover,
.kanban-card[data-status-url]:hover {
  background: var(--card-hover-bg);
}

.kanban-card-head {
  display: flex;
  align-items: flex-start;
  gap: 0.25rem;
}

/* Poignée décorative : montre que la carte se saisit ; toute la carte peut être glissée. */
.kanban-grip {
  display: inline-flex;
  flex: none;
  margin: 0.1875rem 0 0 -0.375rem;
  color: var(--text-muted);
}

.kanban-grip .icon {
  width: 1rem;
  height: 1rem;
}

.kanban-card-title {
  font-weight: 500;
  color: var(--text-strong);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.kanban-card-title:hover {
  text-decoration: underline;
}

.kanban-progress {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-variant-numeric: tabular-nums;
}

/* « Déplacer » : volet natif (details), ouvert au clavier par Entrée ou Espace. */
.kanban-move {
  margin: -0.25rem -0.375rem -0.375rem;
}

.kanban-move-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 2rem;
  padding: 0.25rem 0.375rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
  border-radius: var(--radius);
  cursor: pointer;
  list-style: none;
}

.kanban-move-toggle::-webkit-details-marker {
  display: none;
}

.kanban-move-toggle:hover {
  color: var(--text-strong);
  text-decoration: underline;
}

.kanban-move-toggle .icon {
  width: 0.875rem;
  height: 0.875rem;
  transition: transform 0.15s ease;
}

.kanban-move[open] .kanban-move-toggle .icon {
  transform: rotate(90deg);
}

.kanban-move-panel {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.25rem 0.375rem 0.375rem;
}

.kanban-move-form {
  margin: 0;
}

.kanban-move-form label {
  margin-bottom: 0.25rem;
  font-size: 0.8125rem;
}

.kanban-move-row {
  display: flex;
  gap: 0.375rem;
  margin: 0;
}

.kanban-move-row select {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.25rem 0.5rem;
  font-size: 0.875rem;
}

.kanban-move-row button {
  flex: none;
}

.kanban-order {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

/* Pendant un glisser : toutes les listes montrent leur zone ; celle survolée est marquée
   par un contour plein (--text-muted >= 6,5:1 sur --drop-target-bg) et un fond. */
.kanban--dragging {
  cursor: grabbing;
}

.kanban--dragging .kanban-cards {
  outline: 1px dashed var(--border);
  outline-offset: -1px;
}

.kanban--dragging .kanban-cards--over {
  background: var(--drop-target-bg);
  outline: 2px solid var(--text-muted);
  outline-offset: -2px;
}

/* Carte saisie : anneau ; à sa place dans la liste, un emplacement en pointillés. */
.kanban-card--chosen {
  box-shadow: 0 0 0 2px var(--text-muted);
}

.kanban-card[data-move-url].kanban-card--ghost,
.kanban-card[data-status-url].kanban-card--ghost {
  background: var(--drop-target-bg);
  box-shadow: none;
  outline: 2px dashed var(--text-muted);
  outline-offset: -2px;
}

.kanban-card--ghost > * {
  visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .kanban-move-toggle .icon {
    transition: none;
  }
}

/* ---------- Page Colonnes ---------- */

.column-index {
  flex: none;
  min-width: 1.25rem;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.badge--done {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.badge--done .icon {
  width: 0.875rem;
  height: 0.875rem;
  color: var(--success);
}

.column-row-usage {
  min-width: 9rem;
}

.column-row-note {
  flex-basis: 100%;
  margin: 0;
  padding-left: 1.875rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Actions de ligne en POST (déplacer une colonne) : le bouton prend l'allure d'un lien d'action. */
button.row-action {
  font-weight: 400;
  line-height: inherit;
  background: transparent;
  border: none;
}

.form .field--narrow input {
  max-width: 10rem;
}

@media (forced-colors: active) {
  .kanban-column,
  .kanban-card,
  .kanban-alert,
  .kanban-count {
    border: 1px solid CanvasText;
  }

  .view-tab[aria-current="page"]::after,
  .view-tab[aria-current="true"]::after {
    forced-color-adjust: none;
    background: CanvasText;
  }

  .view-tab:hover,
  .kanban-card[data-move-url]:hover {
    outline: 1px solid CanvasText;
  }
}

/* Mode contraste élevé de Windows : fonds et ombres disparaissent, on rend des contours visibles. */
@media (forced-colors: active) {
  .message,
  .notice,
  .form-alert,
  .preview-throttled,
  .card,
  .badge,
  .tag-chip {
    border: 1px solid CanvasText;
  }

  .row-action:hover,
  .tag-row:hover {
    outline: 1px solid CanvasText;
  }

  .color-option:has(input:checked) {
    outline: 2px solid CanvasText;
  }

  button.task-check:hover,
  .task-row:hover {
    outline: 1px solid CanvasText;
  }
}

/* ---------- Chrono (US-04.1) ---------- */

/* Widget du menu, juste au-dessus de « Se déconnecter ». Aucune animation : seuls les
   chiffres de la durée changent (timer.js), rien ne clignote, prefers-reduced-motion n'a
   donc rien à couper. Contrastes : --text-muted >= 6:1 et --danger >= 4,7:1 (icônes) sur
   --card-bg, --secondary-bg et leur survol, dans les deux thèmes. */
.timer {
  min-width: 0;
}

.timer p {
  margin: 0;
}

/* En cours : petite carte posée sur le menu (--card-bg, comme une carte du kanban). */
.timer--running {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  padding: 0.625rem 0.75rem;
  background: var(--card-bg);
  border-radius: var(--radius);
}

/* « Chrono en cours » écrit en toutes lettres : l'état ne tient pas à la seule couleur. */
.timer-kicker {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
}

.timer-kicker .icon {
  width: 1rem;
  height: 1rem;
  color: var(--danger);
}

.timer-label {
  font-weight: 500;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.timer-label a {
  color: inherit;
  text-decoration: none;
}

.timer-label a:hover {
  text-decoration: underline;
}

.timer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.375rem 0.5rem;
  margin-top: 0.25rem;
}

.timer-clock {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Chiffres à chasse fixe : la durée ne « danse » pas quand les secondes défilent. */
.timer-elapsed {
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

.timer-since {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.timer-form {
  margin: 0;
}

.timer-stop .icon,
.timer-toggle--running .icon {
  color: var(--danger);
}

/* À l'arrêt : « Lancer un chrono », une entrée du menu qui déplie un petit formulaire
   (volet natif details : Entrée ou Espace l'ouvre au clavier, marche sans JavaScript). */
.timer-start-toggle {
  width: 100%;
  cursor: pointer;
  list-style: none;
}

.timer-start-toggle::-webkit-details-marker {
  display: none;
}

.timer-start[open] .timer-start-toggle {
  color: var(--text-strong);
}

.timer-start-form {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin: 0.25rem 0 0;
  padding: 0.625rem 0.75rem;
  background: var(--card-bg);
  border-radius: var(--radius);
}

.timer-start-form label {
  margin: 0;
  font-size: 0.875rem;
}

.timer-start-form input[type="text"] {
  padding: 0.4rem 0.625rem;
  font-size: 0.9375rem;
}

.timer-start-form .errorlist {
  margin: 0;
  font-size: 0.8125rem;
}

.timer-start-form button {
  align-self: flex-start;
}

.timer .timer-help {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Échec d'un lancement ou d'un arrêt (rempli par timer.js) : texte écrit et barre rouge. */
.timer .timer-alert {
  margin-top: 0.375rem;
  padding: 0.5rem 0.625rem;
  font-size: 0.8125rem;
  color: var(--text);
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--error);
}

@media (min-width: 48rem) {
  /* Le chrono descend en bas du menu, la déconnexion juste dessous. */
  .sidebar .timer {
    margin-top: auto;
  }

  .sidebar .timer + .sidebar-footer {
    margin-top: -0.75rem;
  }
}

/* Barre du haut sur mobile : le chrono tient sur une ligne (titre, durée, « Arrêter ») ;
   « Chrono en cours » et « depuis… » restent lus par les lecteurs d'écran. Le volet de
   lancement ouvert prend toute la largeur. */
@media (max-width: 47.99rem) {
  .timer--running {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.5rem;
    padding: 0.25rem 0.25rem 0.25rem 0.625rem;
  }

  .timer-kicker span,
  .timer-since {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .timer-label {
    flex: 1 1 6rem;
    min-width: 0;
    font-size: 0.875rem;
  }

  .timer-row {
    flex-wrap: nowrap;
    margin: 0;
  }

  .timer-elapsed {
    font-size: 0.9375rem;
  }

  .timer:has(.timer-start[open]) {
    flex-basis: 100%;
  }
}

/* Bouton du chrono d'une tâche (ligne, carte du kanban) : icône play discrète pour lancer ;
   pendant qu'il tourne, pastille « Arrêter » avec un carré, sur fond relevé. */
.timer-button {
  display: flex;
  flex: none;
}

.timer-button-form {
  margin: 0;
}

.timer-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  min-width: 2rem;
  height: 2rem;
  min-height: 2rem;
  padding: 0 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
  background: transparent;
  border: none;
  border-radius: 999px;
}

button.timer-toggle:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.timer-toggle .icon {
  width: 1rem;
  height: 1rem;
}

.timer-toggle.timer-toggle--running {
  padding: 0 0.625rem 0 0.5rem;
  color: var(--text-strong);
  background: var(--secondary-bg);
}

button.timer-toggle.timer-toggle--running:hover {
  background: var(--secondary-hover);
}

.task-row .timer-button {
  align-self: flex-start;
}

.kanban-card-head .kanban-card-title {
  flex: 1 1 auto;
  min-width: 0;
}

.kanban-card-head .timer-button {
  margin: -0.25rem -0.375rem -0.25rem 0;
}

/* ---------- Page Temps ---------- */

.section .section-intro {
  margin: -0.25rem 0 0.75rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.time-entries {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Une entrée : libellé et durée sur la première ligne, projet puis horaires dessous ;
   sur grand écran, tout sur une ligne en colonnes alignées. */
.time-entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "main duration"
    "project project"
    "when when"
    "actions actions";
  align-items: baseline;
  gap: 0.125rem 1rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
}

.time-entry:hover {
  background: var(--surface);
}

.time-entry-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.125rem 0.5rem;
  min-width: 0;
  grid-area: main;
}

.time-entry-label {
  font-weight: 500;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

a.time-entry-label {
  text-decoration: none;
}

a.time-entry-label:hover {
  text-decoration: underline;
}

.time-entry-note {
  font-size: 0.875rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.time-entry-project {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  font-size: 0.875rem;
  overflow-wrap: anywhere;
  grid-area: project;
}

.time-entry-project a {
  color: var(--text);
  text-decoration: none;
}

.time-entry-project a:hover {
  text-decoration: underline;
}

.time-entry-when {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 0.375rem;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  grid-area: when;
}

/* Chrono actif : « En cours » écrit, en gras, l'icône ne fait que le souligner. */
.time-entry-running {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-weight: 600;
  color: var(--text-strong);
}

.time-entry-running .icon {
  width: 0.875rem;
  height: 0.875rem;
  color: var(--danger);
}

.time-entry--running {
  background: var(--surface);
}

.time-entry-duration {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
  text-align: right;
  white-space: nowrap;
  grid-area: duration;
}

/* Actions d'une entrée (US-04.2) : liens .row-action ; sur écran étroit, sur leur propre
   ligne, icône et verbe alignés sur le texte au-dessus. */
.time-entry-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  margin-left: -0.5rem;
  grid-area: actions;
}

/* Entrée d'un projet archivé : pas d'action, « Archivé » écrit (pas la seule absence de lien). */
.time-entry-readonly {
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Le verbe d'une action peut céder la place à son icône quand l'entrée tient sur une
   ligne : il reste lu (même technique que .visually-hidden), l'infobulle le montre. */
@media (min-width: 70rem) {
  .time-entry {
    grid-template-columns: minmax(0, 1fr) minmax(0, 10rem) 12rem 4.5rem 4.25rem;
    grid-template-areas: "main project when duration actions";
    align-items: center;
    gap: 0.125rem 0.875rem;
  }

  .time-entries--unfiled .time-entry {
    grid-template-columns: minmax(0, 1fr) minmax(0, 10rem) 12rem 4.5rem 8.25rem;
  }

  .time-entry-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
    margin-left: 0;
  }

  .time-entries--icons .row-action:not(.row-action--file) .row-action-verb {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

/* Fiche tâche : période (et note), durée, actions ; une ligne dès 40rem, actions en icônes. */
.time-entries--task .time-entry {
  grid-template-areas:
    "main duration"
    "actions actions";
}

.time-entry-period {
  font-weight: 500;
  color: var(--text-strong);
}

.time-entries--task .time-entry-running {
  font-weight: 500;
}

@media (min-width: 40rem) {
  .time-entries--task .time-entry {
    grid-template-columns: minmax(0, 1fr) 4.5rem 4.25rem;
    grid-template-areas: "main duration actions";
    align-items: center;
  }

  .time-entries--task .time-entry-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
    margin-left: 0;
  }

  .time-entries--task .row-action-verb {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

.time-total {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.time-total strong {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

/* Type d'une entrée (US-04.6) : pastille neutre, plus petite et plus discrète que le
   statut, alignée sur le texte de la ligne. --text-muted sur --secondary-bg : 6:1 en
   sombre, 6,5:1 en clair. */
.badge--kind {
  align-self: auto;
  padding: 0 0.4375rem;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ---------- Totaux de temps (US-04.6) ---------- */

/* Fiche projet : le total puis chaque type qui a du temps, en petites tuiles (fond
   --surface, sans cadre). --text-muted sur --surface : 7,1:1 dans les deux thèmes. */
.kind-totals-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.5rem;
  margin: 0;
}

.kind-total {
  min-width: 0;
  padding: 0.625rem 0.875rem;
  background: var(--surface);
  border-radius: var(--radius);
}

.kind-total dt {
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.kind-total dd {
  margin: 0.125rem 0 0;
  font-size: 1.0625rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

/* Le total : libellé en gras et chiffre plus grand que ceux du détail. */
.kind-total--all dt {
  font-weight: 600;
  color: var(--text);
}

.kind-total--all dd {
  font-size: 1.25rem;
  line-height: 1.3;
}

/* Remarque sous des totaux : chrono en cours compté, lecture du tableau. */
.totals-note {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
  max-width: 44rem;
  margin: 0.75rem 0 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.totals-note .icon {
  width: 1rem;
  height: 1rem;
  margin-top: 0.15rem;
  color: var(--danger);
}

/* Page « Temps par étiquette » : sur écran étroit, seul le tableau défile, dans son cadre.
   position: relative garde dans le cadre les textes masqués des cellules (.visually-hidden,
   en position absolue), qui sinon élargiraient la page. */
.table-scroll {
  position: relative;
  max-width: 100%;
  overflow-x: auto;
  border-radius: var(--radius);
}

/* border-collapse: separate : les traits appartiennent aux cellules et suivent la colonne
   des étiquettes, qui reste en place quand le tableau défile. */
.totals-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.totals-table th,
.totals-table td {
  padding: 0.5rem 0.75rem;
  text-align: right;
  white-space: nowrap;
  vertical-align: middle;
}

/* Colonnes de durées à la largeur de leur contenu ; celle des étiquettes prend le reste. */
.totals-table td,
.totals-table thead th + th {
  width: 1%;
}

.totals-table thead th {
  padding-top: 0;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
  vertical-align: bottom;
}

/* Lignes séparées par un trait discret ; le total général par un trait plus marqué. */
.totals-table tbody > tr > *,
.totals-table tfoot > tr > * {
  border-top: 1px solid var(--border-subtle);
}

.totals-table tfoot > tr > * {
  font-weight: 600;
  color: var(--text-strong);
  border-top-color: var(--border);
}

/* Colonne des étiquettes : figée à gauche, sur le fond de la page. */
.totals-table thead th:first-child,
.totals-table th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  text-align: left;
  background: var(--bg);
}

.totals-table tbody th[scope="row"] {
  font-weight: 500;
  color: var(--text-strong);
  white-space: normal;
}

.totals-table tbody tr:hover > * {
  background: var(--surface);
}

/* Nom de l'étiquette : pastille + nom, qui passe à la ligne au-delà de 16rem. */
.totals-tag {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 7rem;
  max-width: 16rem;
  overflow-wrap: anywhere;
}

.totals-table .totals-sum {
  font-weight: 600;
  color: var(--text-strong);
}

/* Cellule sans temps : un tiret (lu « aucun temps »). */
.totals-table .totals-none {
  color: var(--text-muted);
}

/* « Sans étiquette » : nom moins appuyé, cercle vide à la place de la pastille. */
.totals-table .totals-untagged th[scope="row"] {
  font-weight: 400;
  color: var(--text);
}

.swatch--none {
  --swatch: transparent;
  box-shadow: inset 0 0 0 1px var(--text-muted);
}

/* Là où le tableau peut déborder (six types sous 62rem), un filet sépare la colonne figée
   des durées qui défilent dessous : un chiffre à demi caché ne se lit pas avec le nom. */
@media (max-width: 61.99rem) {
  .totals-table thead th:first-child,
  .totals-table th[scope="row"] {
    box-shadow: inset -1px 0 0 var(--border-subtle);
  }
}

@media (forced-colors: active) and (max-width: 61.99rem) {
  .totals-table thead th:first-child,
  .totals-table th[scope="row"] {
    border-right: 1px solid CanvasText;
  }
}

@media (max-width: 47.99rem) {
  .totals-table th,
  .totals-table td {
    padding: 0.5rem 0.625rem;
  }
}

/* ---------- Rapports (US-04.3) ---------- */

/* Titre de la période et total à gauche, navigation d'une période à l'autre à droite ;
   la navigation passe dessous quand la place manque. */
.report-period {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  margin: 0 0 1.5rem;
}

.report-period h2 {
  margin: 0;
  font-size: 1.25rem;
  overflow-wrap: anywhere;
}

.report-total {
  margin: 0.25rem 0 0;
  color: var(--text-muted);
}

.report-total strong {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

.report-steps ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Lien indisponible (pas de période au-delà, ou déjà la période actuelle) : sans href,
   role="link" + aria-disabled ; contour discret au lieu du fond, rien au survol. */
.button[aria-disabled="true"],
.button[aria-disabled="true"]:hover {
  color: var(--text-muted);
  background: transparent;
  border-color: var(--border-subtle);
  cursor: default;
}

/* Téléphone : « Semaine précédente » et « Semaine suivante » deviennent des flèches (le nom
   reste lu, même technique que .visually-hidden), en cibles carrées de 2,5rem. */
@media (max-width: 35.99rem) {
  .report-steps .button {
    min-height: 2.5rem;
  }

  .report-step {
    min-width: 2.5rem;
  }

  .report-step-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

/* Graphique : toute la largeur, hauteur posée par report-chart.js selon le nombre de
   projets (position: relative exigée par Chart.js pour suivre la taille du cadre). Les
   couleurs de --chart-* sont lues par le script : textes, grille, filet entre deux types
   (couleur du fond), infobulle en couleurs inversées (>= 19:1). */
.report-chart {
  --chart-text: var(--text-muted);
  --chart-legend: var(--text);
  --chart-grid: var(--rule);
  --chart-gap: var(--bg);
  --chart-tooltip-bg: var(--text-strong);
  --chart-tooltip-text: var(--bg);
  margin: 0 0 2rem;
}

.report-chart figcaption {
  max-width: 44rem;
  margin: 0 0 0.75rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.report-chart-frame {
  position: relative;
  width: 100%;
  min-width: 0;
  height: 12rem;
}

.report-chart-frame canvas {
  display: block;
  max-width: 100%;
}

/* Élément invisible dont report-chart.js lit la couleur calculée (variables et couleurs du
   système résolues en rgb) ; hors du contraste forcé pour garder la couleur demandée. */
.chart-color-probe {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  forced-color-adjust: none;
}

/* Pastille d'un type : CARRÉE comme dans la légende du graphique, pour ne pas la confondre
   avec la pastille ronde d'un projet. Toujours à côté du nom du type. */
.kind-swatch {
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  vertical-align: middle;
  border-radius: 2px;
  background: var(--kind-color, var(--kind-other));
}

.kind-swatch--preparation { --kind-color: var(--kind-preparation); }
.kind-swatch--shooting { --kind-color: var(--kind-shooting); }
.kind-swatch--live { --kind-color: var(--kind-live); }
.kind-swatch--editing { --kind-color: var(--kind-editing); }
.kind-swatch--publishing { --kind-color: var(--kind-publishing); }
.kind-swatch--other { --kind-color: var(--kind-other); }

/* En-tête d'une colonne de type : pastille + nom, alignés à droite comme les durées. */
.report-kind {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

/* « (archivé) » après le nom d'un projet archivé. */
.report-archived {
  font-weight: 400;
  color: var(--text-muted);
}

.report-exports {
  margin-top: 1.5rem;
}

/* Sans JavaScript : la phrase qui remplace le graphique, au-dessus du tableau. */
.report-nojs {
  margin: 0 0 1rem;
}

/* Mode contraste élevé : textes et grille du graphique aux couleurs du système, filet de
   la couleur du fond entre deux types ; les pastilles gardent leur couleur, avec un contour. */
@media (forced-colors: active) {
  .report-chart {
    --chart-text: CanvasText;
    --chart-legend: CanvasText;
    --chart-grid: GrayText;
    --chart-gap: Canvas;
    --chart-tooltip-bg: CanvasText;
    --chart-tooltip-text: Canvas;
  }

  .kind-swatch {
    forced-color-adjust: none;
    border: 1px solid CanvasText;
  }

  .button[aria-disabled="true"] {
    color: GrayText;
    border-color: GrayText;
  }
}

/* ---------- Formulaire d'une entrée de temps (US-04.2) ---------- */

/* Rappel de l'entrée modifiée : libellé, période et durée actuelle. */
.entry-summary {
  max-width: 40rem;
  margin: 0 0 1.5rem;
  padding: 0.75rem var(--space);
  background: var(--surface);
  border-radius: var(--radius);
}

.entry-summary p {
  margin: 0;
  color: var(--text-muted);
}

.entry-summary .entry-summary-label {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.125rem;
  font-weight: 600;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.entry-summary-label .icon {
  width: 1rem;
  height: 1rem;
  flex: none;
  color: var(--danger);
}

/* Alerte en tête de formulaire qui cite les erreurs générales (chevauchement). */
.form-alert p {
  margin: 0;
}

.form-alert p + p,
.form-alert-list + p {
  margin-top: 0.25rem;
}

.form-alert-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.form-alert-title strong {
  color: var(--text-strong);
}

.form-alert-title .icon {
  width: 1.125rem;
  height: 1.125rem;
  flex: none;
  color: var(--danger);
}

.form-alert-list {
  margin: 0.375rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--text-strong);
}

.form-alert-list li + li {
  margin-top: 0.25rem;
}

.form-alert-hint {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* « Quand » : date et heures natives ; date sur sa ligne puis début et fin côte à côte sur
   écran étroit, les trois sur une ligne dès 36rem. */
.when-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1rem;
}

.when-field:first-child {
  grid-column: 1 / -1;
}

.when-field label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text);
}

.when-field .errorlist {
  font-size: 0.875rem;
}

.when-fieldset .helptext {
  margin: 0.5rem 0 0;
}

/* Chevauchement : barre rouge le long du groupe, en plus du message écrit en tête. */
.when-fieldset--conflict {
  padding-left: 0.75rem;
  box-shadow: inset 3px 0 0 var(--danger);
}

@media (min-width: 36rem) {
  .when-row {
    grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  }

  .when-field:first-child {
    grid-column: auto;
  }
}

/* Lien de suppression d'un formulaire : poussé à droite, loin de « Enregistrer ». */
.actions .actions-end {
  margin-left: auto;
}

.meta-duration {
  font-variant-numeric: tabular-nums;
}

/* « Corriger » dans le widget du chrono : lien discret sous la durée. */
.timer .timer-fix-line {
  margin-top: 0.25rem;
}

.timer-fix {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 1.5rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius);
}

.timer-fix:hover {
  color: var(--text-strong);
  text-decoration: underline;
}

.timer-fix .icon {
  width: 0.875rem;
  height: 0.875rem;
}

@media (max-width: 47.99rem) {
  .timer .timer-fix-line {
    margin: 0;
  }

  .timer-fix {
    justify-content: center;
    width: 2rem;
    min-height: 2rem;
  }

  .timer-fix .icon {
    width: 1rem;
    height: 1rem;
  }

  .timer-fix-text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-top: 1.5rem;
}

.pagination-current {
  font-size: 0.875rem;
  color: var(--text-muted);
}

@media (forced-colors: active) {
  .timer--running,
  .timer-start-form,
  .timer .timer-alert,
  .timer-toggle--running,
  .time-entry--running {
    border: 1px solid CanvasText;
  }

  button.timer-toggle:hover,
  .time-entry:hover,
  .timer-fix:hover {
    outline: 1px solid CanvasText;
  }

  .entry-summary,
  .kind-total {
    border: 1px solid CanvasText;
  }

  .when-fieldset--conflict {
    border-left: 3px solid CanvasText;
  }
}

/* ---------- Calendrier (US-03.1, FullCalendar) ---------- */

/* Palette du thème « classic » de FullCalendar, à partir des couleurs de l'appli : elle suit
   donc le thème sombre et le thème clair (palette.css du paquet n'est pas chargé). Une seule
   valeur propre au calendrier : les numéros des jours des mois voisins, plus discrets que
   les autres mais lisibles (5,55:1 sur --bg en sombre, 4,74:1 en clair). Tâches : fond
   --secondary-bg ; titre >= 12,6:1, texte secondaire >= 5:1, « ! » du retard >= 4,57:1,
   y compris au survol, dans les deux thèmes. */
:root {
  --fc-classic-button: var(--secondary-bg);
  --fc-classic-button-border: var(--secondary-bg);
  --fc-classic-button-strong: var(--secondary-hover);
  --fc-classic-button-strong-border: var(--secondary-hover);
  --fc-classic-button-outline: var(--focus);
  --fc-classic-button-foreground: var(--secondary-text);
  --fc-classic-primary: var(--focus);
  --fc-classic-primary-foreground: var(--bg);
  --fc-classic-event: var(--secondary-bg);
  --fc-classic-event-contrast: var(--text-strong);
  --fc-classic-background-event: var(--secondary-bg);
  --fc-classic-background-event-opacity: 15%;
  --fc-classic-background-event-foreground-opacity: 50%;
  --fc-classic-highlight: color-mix(in srgb, var(--focus) 18%, transparent);
  --fc-classic-today: var(--surface);
  --fc-classic-now: var(--danger);
  --fc-classic-small-dot-width: 8px;
  --fc-classic-large-dot-width: 10px;
  --fc-classic-background: var(--bg);
  --fc-classic-faint: var(--surface);
  --fc-classic-muted: var(--hover-bg);
  --fc-classic-strong: var(--secondary-hover);
  --fc-classic-foreground: var(--text);
  --fc-classic-faint-foreground: #8a8a8a;
  --fc-classic-muted-foreground: var(--text-muted);
  --fc-classic-border: var(--border-subtle);
  --fc-classic-strong-border: var(--secondary-hover);
}

@media (prefers-color-scheme: light) {
  :root {
    --fc-classic-faint-foreground: #737373;
  }
}

/* Ligne de confirmation après un déplacement (remplie par le serveur) : sa hauteur est
   réservée, le calendrier ne saute pas quand elle se remplit. */
.calendar-status {
  min-height: 1.5em;
  margin: -0.75rem 0 0.75rem;
  font-size: 0.9375rem;
}

/* Les règles ci-dessous partent de #calendar : la feuille du thème est chargée après
   celle-ci, avec des sélecteurs d'une classe. */

/* Titre du mois, de la semaine ou du jour : comme un titre de section de l'appli. */
#calendar [role="heading"] {
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-strong);
}

/* Focus : le même anneau que dans le reste de l'appli. */
#calendar :focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* Barre d'outils : boutons gris de l'appli, jamais le rouge des boutons principaux. */
#calendar button {
  font-size: 0.875rem;
  font-weight: 600;
}

#calendar button:hover {
  background-color: var(--fc-classic-button-strong);
}

#calendar button:disabled {
  cursor: default;
}

/* Vue affichée : en gras, avec une barre dessous, pas seulement un fond plus marqué. */
#calendar [role="tab"][aria-selected="true"] {
  box-shadow: inset 0 -2px 0 currentColor;
}

/* Numéro du jour (lien vers la vue jour) : cible d'au moins 24 px. */
#calendar [role="link"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  min-height: 1.5rem;
  padding: 0 0.25rem;
  border-radius: 999px;
}

#calendar [role="link"]:focus-visible {
  outline-offset: 0;
}

/* Aujourd'hui : fond relevé et numéro dans une pastille pleine (une forme, pas seulement
   une couleur). */
#calendar [aria-current="date"] [role="link"] {
  font-weight: 700;
  color: var(--bg);
  background: var(--text-strong);
}

/* Une tâche : fond gris, pastille du projet, titre sur une ligne (coupé s'il est trop
   long) ; au moins 24 px de haut. */
#calendar .cal-task {
  min-height: 1.5rem;
  cursor: pointer;
}

#calendar .cal-task:hover {
  background-color: var(--secondary-hover);
}

.cal-task-body {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  padding: 0.125rem 0.25rem;
}

.cal-task .cal-task-swatch {
  width: 0.5rem;
  height: 0.5rem;
}

.cal-task-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cal-task-parent,
.cal-task-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Sous-tâche : le titre de sa parente, en petit, au-dessus du sien. */
.cal-task-parent {
  font-size: 0.75rem;
  line-height: 1.25;
  color: var(--text-muted);
}

.cal-task-title {
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-strong);
}

/* Vues semaine et jour (classe posée par calendar.js) : titres entiers, qui passent à la
   ligne ; la pastille reste sur la première ligne. La vue mois garde des titres coupés. */
.cal-task-body--full {
  align-items: flex-start;
}

.cal-task-body--full .cal-task-swatch {
  margin-top: 0.3125rem;
}

.cal-task-body--full .cal-task-parent,
.cal-task-body--full .cal-task-title {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}

.cal-task--blue { --swatch: var(--project-blue); }
.cal-task--green { --swatch: var(--project-green); }
.cal-task--red { --swatch: var(--project-red); }
.cal-task--orange { --swatch: var(--project-orange); }
.cal-task--yellow { --swatch: var(--project-yellow); }
.cal-task--purple { --swatch: var(--project-purple); }
.cal-task--pink { --swatch: var(--project-pink); }
.cal-task--teal { --swatch: var(--project-teal); }
.cal-task--gray { --swatch: var(--project-gray); }

/* Terminée : titre atténué et barré (et « terminée » lu par les lecteurs d'écran). */
.cal-task--done .cal-task-title {
  color: var(--text-muted);
  text-decoration: line-through;
}

.cal-task--done .cal-task-swatch {
  opacity: 0.5;
}

/* En retard : un « ! » devant le titre et une barre rouge à gauche (et « en retard » lu par
   les lecteurs d'écran) ; la couleur ne fait que souligner. Le « ! » n'est pas lu. */
#calendar .cal-task--overdue {
  box-shadow: inset 3px 0 0 var(--danger);
}

.cal-task--overdue .cal-task-title::before {
  content: "!" / "";
  margin-right: 0.25rem;
  font-weight: 700;
  color: var(--danger);
}

/* Fenêtre « Changer l'échéance de « … » » (dialog natif) : carte posée sur un fond assombri. */
.calendar-dialog {
  width: min(28rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  padding: 1.25rem 1.5rem 1.5rem;
  color: var(--text);
  background: var(--card-bg);
  border: none;
  border-radius: 8px;
}

.calendar-dialog::backdrop {
  background: rgb(0 0 0 / 0.6);
}

/* Le titre arrive avec le formulaire, « Fermer » vient après lui (dernier au clavier) : une
   grille les met sur la même ligne, le formulaire dessous. Le corps de la fenêtre ne fait
   pas de boîte (display: contents), ses enfants sont placés dans la grille. Seulement
   ouverte : une fenêtre fermée reste masquée. */
.calendar-dialog[open] {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  column-gap: 1rem;
}

.calendar-dialog-body {
  display: contents;
}

.calendar-dialog .due-date-title {
  grid-column: 1;
  grid-row: 1;
  margin: 0 0 1rem;
  font-size: 1.125rem;
  overflow-wrap: anywhere;
}

.calendar-dialog-close {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
}

.calendar-dialog .due-date {
  grid-column: 1 / -1;
  grid-row: 2;
}

/* Formulaire d'échéance (fenêtre et page sans JavaScript) : la date et « Enregistrer »,
   puis les raccourcis, chacun avec sa date en toutes lettres. */
.due-date-form {
  margin: 0 0 1.25rem;
}

.due-date-form input[type="date"] {
  max-width: 14rem;
}

.due-date-shortcuts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
}

.due-date-shortcut {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  min-height: 2.75rem;
  padding: 0.375rem 0.75rem;
  text-align: left;
}

.due-date-shortcut-date {
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--text-muted);
}

.due-date-link {
  margin: 0;
}

/* Écran étroit : titre un peu plus petit ; dans les cases étroites du mois, la pastille et
   le début du titre restent. */
@media (max-width: 47.99rem) {
  #calendar [role="heading"] {
    font-size: 1.125rem;
  }

  .cal-task-body {
    gap: 0.25rem;
    padding: 0.125rem;
  }
}

@media (forced-colors: active) {
  #calendar .cal-task,
  .calendar-dialog {
    border: 1px solid CanvasText;
  }

  #calendar .cal-task--overdue {
    border-left: 3px solid CanvasText;
  }

  #calendar [aria-current="date"] [role="link"] {
    forced-color-adjust: none;
    color: Canvas;
    background: CanvasText;
  }

  #calendar [role="tab"][aria-selected="true"] {
    outline: 2px solid CanvasText;
  }
}

/* ---------- Vidéos (US-05.1) ---------- */

/* Miniature : toujours en 16:9. La liste la recadre (cover) ; la fiche et le formulaire la
   montrent entière (contain), avec des bandes sur le fond neutre si elle n'est pas en 16:9. */
.thumb {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--secondary-bg);
  border-radius: var(--radius);
}

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

/* Sans miniature : cadre neutre, icône (et texte sur la fiche) en --text-muted (>= 6:1). */
.thumb--empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  text-align: center;
}

/* Statut d'une vidéo : toujours écrit. La marque devant dit l'étape par sa forme (anneau
   vide, rempli au tiers, aux deux tiers, coché) ; la couleur ne fait que la souligner.
   Marques >= 3:1 sur le fond de la pastille (et sur --surface, --hover-bg) dans les deux
   thèmes ; le texte reste --text (>= 12:1). */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
}

.status-mark {
  --status-color: var(--text-muted);
  --status-fill: 0%;
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  border: 1.5px solid var(--status-color);
  border-radius: 50%;
  background: conic-gradient(var(--status-color) var(--status-fill), transparent 0);
}

.status-mark--shooting {
  --status-color: var(--project-blue);
  --status-fill: 33.3%;
}

.status-mark--editing {
  --status-color: var(--project-purple);
  --status-fill: 66.7%;
}

.icon.status-check {
  width: 0.875rem;
  height: 0.875rem;
  color: var(--success);
}

/* Liste : une ligne par vidéo, miniature à gauche puis titre, statut, date et projet ;
   toute la ligne est cliquable, comme une carte de projet. */
.video-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.video-card {
  flex-direction: row;
  align-items: flex-start;
  gap: 1rem;
  padding: 0.75rem;
}

.video-card-thumb {
  flex: none;
  width: 7rem;
}

.video-card-thumb .icon {
  width: 1.5rem;
  height: 1.5rem;
}

.video-card-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  padding-top: 0.125rem;
}

/* Même ligne d'informations sur les cartes des idées (US-05.5). */
.video-card-meta,
.idea-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem 1rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.video-meta-item,
.idea-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

.video-meta-item .icon,
.idea-meta-item .icon {
  width: 0.875rem;
  height: 0.875rem;
}

@media (min-width: 40rem) {
  .video-card-thumb {
    width: 10rem;
  }
}

/* Fiche : la miniature, grande et entière, à côté des informations ; l'une sous l'autre sur
   écran étroit. */
.video-hero {
  display: grid;
  gap: 1.5rem;
  margin: 0 0 2.5rem;
}

.video-hero-media {
  min-width: 0;
}

.video-hero-actions {
  margin: 0.5rem 0 0;
}

.meta--stacked {
  flex-direction: column;
  gap: 1rem;
  margin: 0;
}

@media (min-width: 60rem) {
  .video-hero {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: start;
    gap: 2rem;
  }
}

/* Liens d'une vidéo : le libellé (lien), le site, « Retirer ». */
.link-fieldset {
  margin: 0;
}

.link-row-site {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Ajout d'un lien : libellé, adresse et « Ajouter » sur une ligne dès 40rem ; la grille
   garde alignés les libellés, les champs et les erreurs. Les uns sous les autres avant. */
.link-form {
  max-width: 44rem;
  margin: 1rem 0 0;
}

.link-form-field {
  margin: 0 0 0.75rem;
}

.link-form-field label {
  font-size: 0.875rem;
}

.link-form-field .errorlist {
  font-size: 0.875rem;
}

@media (min-width: 40rem) {
  .link-form-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) auto;
    column-gap: 0.75rem;
  }

  .link-form-field {
    display: contents;
  }

  .link-form-field--label > label { grid-area: 1 / 1; }
  .link-form-field--label > input { grid-area: 2 / 1; }
  .link-form-field--label > .errorlist { grid-area: 3 / 1; }
  .link-form-field--url > label { grid-area: 1 / 2; }
  .link-form-field--url > input { grid-area: 2 / 2; }
  .link-form-field--url > .errorlist { grid-area: 3 / 2; }

  .link-form-submit {
    grid-area: 2 / 3;
  }
}

/* Tâches d'une vidéo, regroupées sous leur projet. */
.task-group-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
  margin: 1.25rem 0 0.375rem;
  font-size: 0.9375rem;
  overflow-wrap: anywhere;
}

.section-header + .task-group-title {
  margin-top: 0;
}

.task-group-title .muted {
  font-size: 0.875rem;
  font-weight: 400;
}

/* Formulaire : date et heure côte à côte, même sur téléphone (les champs natifs tiennent). */
.when-row--pair {
  max-width: 30rem;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
}

.when-row--pair .when-field:first-child {
  grid-column: auto;
}

.when-field .helptext {
  margin: 0.25rem 0 0;
}

/* Champ « Miniature » : aperçu de l'actuelle, « Retirer la miniature », puis le sélecteur. */
.thumbnail-current {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.75rem 1rem;
  margin: 0.5rem 0 1rem;
}

.thumbnail-current .thumb {
  flex: none;
  width: 12rem;
}

.thumbnail-current-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  min-width: 0;
}

.thumbnail-current-title {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin: 0;
  font-weight: 500;
  color: var(--text-strong);
}

.thumbnail-current-title a {
  font-weight: 400;
}

.thumbnail-replace {
  font-size: 0.875rem;
}

/* Sélecteur de fichier natif : son bouton prend l'allure d'un bouton secondaire. */
input[type="file"] {
  display: block;
  width: 100%;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--text);
}

input[type="file"]::file-selector-button {
  min-height: 2.5rem;
  margin-right: 0.75rem;
  padding: 0.5rem 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--secondary-text);
  background: var(--secondary-bg);
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
}

input[type="file"]::file-selector-button:hover {
  background: var(--secondary-hover);
}

/* Envoi désactivé (non configuré) : l'aide du champ dit pourquoi. */
input[type="file"]:disabled,
input[type="file"]:disabled::file-selector-button {
  color: var(--text-muted);
  cursor: not-allowed;
}

input[type="file"]:disabled::file-selector-button:hover {
  background: var(--secondary-bg);
}

/* Confirmation de suppression : ce qui part, ce qui reste. */
.notice-list {
  margin: 0.375rem 0 0;
  padding-left: 1.25rem;
}

.notice-list li + li {
  margin-top: 0.125rem;
}

@media (forced-colors: active) {
  .thumb {
    border: 1px solid CanvasText;
  }

  .status-mark {
    forced-color-adjust: none;
    --status-color: CanvasText;
  }
}

/* ---------- Vidéos : kanban et calendrier (US-05.2) ---------- */

/* Quatre colonnes fixes : un peu plus étroites que celles des tâches, pour tenir côte à
   côte dès un écran de 1366 px ; sur téléphone, elles défilent comme celles des tâches. */
.video-kanban {
  grid-auto-columns: minmax(min(15rem, 82vw), 1fr);
}

/* Carte du kanban des vidéos : la miniature en haut, sur toute la largeur (s'il y en a
   une), la poignée et le titre, la date et le projet, puis le formulaire « Statut ». */
.video-kanban-thumb {
  width: 100%;
}

.video-kanban-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  min-width: 0;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* « Statut » au-dessus (--text-muted >= 6:1 sur --card-bg), puis le menu et « Changer »
   sur une ligne : cibles de 2rem. Les champs cachés ne prennent pas de place. */
.video-status-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.25rem 0.375rem;
  margin: 0;
}

.video-status-form label {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
}

.video-status-form select {
  min-width: 0;
  min-height: 2rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.875rem;
}

/* Calendrier, « Afficher » : la légende à gauche, puis une case par type, chacune avec un
   échantillon de son allure dans la grille (il sert aussi de légende). */
.calendar-filters {
  margin: 0 0 1.25rem;
}

.calendar-filters-fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: none;
}

.calendar-filters-legend {
  float: left;
  min-height: 2rem;
  margin: 0 1rem 0 0;
  padding: 0;
  line-height: 2rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-strong);
}

.calendar-filters-options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 1.25rem;
}

.calendar-filter {
  min-height: 2rem;
  margin: 0;
  font-size: 0.9375rem;
  color: var(--text);
  cursor: pointer;
}

.calendar-filter:has(input:disabled) {
  cursor: default;
}

.calendar-sample {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.125rem;
  border-radius: 4px;
}

.calendar-sample--taches {
  background: var(--secondary-bg);
}

.calendar-sample-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--text-muted);
}

.calendar-sample--videos {
  padding-left: 3px;
  color: var(--video-accent);
  background: var(--video-bg);
  box-shadow: inset 3px 0 0 var(--video-accent);
}

.calendar-sample--videos .icon {
  width: 0.75rem;
  height: 0.75rem;
}

.calendar-filters-hint {
  clear: left;
  margin: 0.125rem 0 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.calendar-filters-apply {
  clear: left;
  margin-top: 0.5rem;
}

/* Une vidéo : fond orangé, barre orange à gauche et icône caméra (le type ne tient pas à
   la seule couleur) ; titre --text-strong, heure --text-muted. Au moins 24 px de haut. */
#calendar .cal-video {
  min-height: 1.5rem;
  cursor: pointer;
  background-color: var(--video-bg);
  box-shadow: inset 3px 0 0 var(--video-accent);
  text-decoration: none;
}

#calendar .cal-video:hover {
  background-color: var(--video-hover-bg);
}

/* Vidéo publiée : un vrai lien vers sa fiche (elle ne se déplace plus), marqué d'une coche
   devant l'heure et le titre. */
#calendar a.cal-video:hover .cal-video-title {
  text-decoration: underline;
}

.cal-video-body {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
  padding: 0.125rem 0.25rem 0.125rem 0.4375rem;
}

.cal-video-body .icon {
  width: 0.875rem;
  height: 0.875rem;
}

.cal-video-icon {
  color: var(--video-accent);
}

.cal-video-check {
  color: var(--success);
}

.cal-video-text {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  min-width: 0;
}

.cal-video-time {
  flex: none;
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.cal-video-title {
  overflow: hidden;
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-strong);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Vues semaine et jour : l'heure sur sa ligne, le titre entier dessous. */
.cal-video-body--full {
  align-items: flex-start;
}

.cal-video-body--full .icon {
  margin-top: 0.1875rem;
}

.cal-video-body--full .cal-video-text {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}

.cal-video-body--full .cal-video-title {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Fenêtre « Changer la date de publication » : l'heure qui reste, ou pourquoi une vidéo
   publiée ne bouge pas. */
.due-date-time-note {
  margin: -0.625rem 0 1rem;
}

.calendar-dialog .notice {
  margin: 0 0 1rem;
}

/* Date d'une vidéo publiée : champ désactivé, atténué et en pointillés (pas seulement une
   couleur), sans curseur de saisie. */
.due-date-form input:disabled {
  color: var(--text-muted);
  background: var(--surface);
  border-style: dashed;
  cursor: not-allowed;
}

@media (max-width: 47.99rem) {
  .cal-video-body {
    gap: 0.1875rem;
    padding: 0.125rem 0.125rem 0.125rem 0.3125rem;
  }
}

@media (forced-colors: active) {
  #calendar .cal-video {
    border: 1px solid CanvasText;
    border-left-width: 3px;
  }

  .calendar-sample {
    border: 1px solid CanvasText;
  }
}

/* ---------- Streams (US-05.3) ---------- */

/* Liste : une ligne par stream, toute cliquable comme une carte de projet. À gauche, une
   tuile qui reprend le jour (décorative : la date est écrite à côté), violette comme les
   streams du calendrier, grise une fois le stream passé. */
.stream-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stream-card {
  flex-direction: row;
  align-items: flex-start;
  gap: 1rem;
  padding: 0.75rem;
}

.stream-card-date {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  min-height: 3.25rem;
  padding: 0.25rem 0 0.25rem 3px;
  line-height: 1.15;
  background: var(--stream-bg);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--stream-accent);
}

.stream-card-day {
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

.stream-card-month {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
}

.stream-list--past .stream-card-date {
  background: var(--secondary-bg);
  box-shadow: none;
}

.stream-card-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  padding-top: 0.125rem;
}

.stream-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.375rem 1rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.stream-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

.stream-meta-item .icon {
  width: 0.875rem;
  height: 0.875rem;
}

/* Le jour et les heures : du texte qui passe à la ligne normalement (pas des éléments
   flexibles, qui feraient une colonne par morceau sur téléphone). */
.stream-when {
  display: block;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.stream-meta-value {
  color: var(--text);
}

/* « 20 h 00 » ne se coupe jamais entre l'heure et les minutes. */
.stream-time {
  white-space: nowrap;
}

/* Fiche : le texte de notification dans un champ en lecture seule, à sélectionner pour le
   copier. Fond relevé (on ne le modifie pas ici) mais contour gardé : c'est un champ. */
.copy-field {
  max-width: 44rem;
}

.copy-field input[readonly] {
  background: var(--surface);
  cursor: text;
}

.copy-field-help {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.125rem 1rem;
  margin: 0.375rem 0 0;
}

.copy-field-count {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Formulaire du stream : les erreurs de « Début » et de « Durée » sous la ligne entière,
   pas dans une colonne étroite. */
.when-fieldset > .errorlist {
  margin-top: 0.5rem;
  font-size: 0.875rem;
}

/* Formulaire : heures et minutes côte à côte, même sur téléphone. */
.when-row--duration {
  max-width: 16rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.when-row--duration .when-field:first-child {
  grid-column: auto;
}

/* Page « Temps » : l'antenne devant le titre d'un stream. */
.time-entry-stream-icon {
  width: 0.875rem;
  height: 0.875rem;
  margin-right: 0.3125rem;
  vertical-align: -0.1em;
  color: var(--stream-accent);
}

/* Calendrier : échantillon de la case « Streams » (sert de légende). */
.calendar-sample--streams {
  padding-left: 3px;
  color: var(--stream-accent);
  background: var(--stream-bg);
  box-shadow: inset 3px 0 0 var(--stream-accent);
}

.calendar-sample--streams .icon {
  width: 0.75rem;
  height: 0.75rem;
}

/* Un stream : fond violet, barre violette à gauche et icône antenne (le type ne tient pas
   à la seule couleur) ; heures de début et de fin en --text-muted, titre --text-strong.
   Au moins 24 px de haut. Les heures prennent toute la première ligne dans toutes les vues
   (début et fin ne tiendraient pas avec le titre dans une case du mois), l'icône et le
   titre la seconde : titre coupé en vue mois, entier en semaine et en jour. */
#calendar .cal-stream {
  min-height: 1.5rem;
  cursor: pointer;
  background-color: var(--stream-bg);
  box-shadow: inset 3px 0 0 var(--stream-accent);
  text-decoration: none;
}

#calendar .cal-stream:hover {
  background-color: var(--stream-hover-bg);
}

.cal-stream-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 0.125rem 0.25rem 0.125rem 0.4375rem;
}

.cal-stream-line {
  display: flex;
  align-items: flex-start;
  gap: 0.25rem;
  min-width: 0;
}

.cal-stream-icon {
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  margin-top: 0.125rem;
  color: var(--stream-accent);
}

.cal-stream-time,
.cal-stream-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal-stream-time {
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.cal-stream-title {
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-strong);
}

/* Vues semaine et jour : le titre entier, sur plusieurs lignes. */
.cal-stream-body--full .cal-stream-title {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}

@media (max-width: 47.99rem) {
  .cal-stream-body {
    padding: 0.125rem 0.125rem 0.125rem 0.3125rem;
  }

  .cal-stream-line {
    gap: 0.1875rem;
  }

  .stream-card {
    gap: 0.75rem;
  }
}

@media (forced-colors: active) {
  #calendar .cal-stream,
  .stream-card-date {
    border: 1px solid CanvasText;
    border-left-width: 3px;
  }
}

/* ---------- Notes (US-02.14) ---------- */

/* Liste : les dossiers à gauche dès 60rem (le contenu y fait au moins 41rem), en pastilles
   au-dessus des notes sur un écran plus étroit. */
.notes-layout {
  display: grid;
  gap: 1.5rem;
}

.folder-nav-title {
  margin: 0 0 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--text-muted);
}

.folder-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.folder-list > li {
  display: flex;
  min-width: 0;
}

/* --text-muted >= 6:1 sur --surface, --hover-bg et --nav-current-bg, dans les deux thèmes. */
.folder-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  min-height: 2.25rem;
  padding: 0.375rem 0.75rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
  text-decoration: none;
  background: var(--surface);
  border-radius: 999px;
}

.folder-link:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.folder-link-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

.folder-link-count {
  margin-left: auto;
  padding-left: 0.25rem;
  font-size: 0.8125rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Dossier courant : gras, texte plus clair, fond et anneau (barre à gauche dès 60rem),
   pas seulement une couleur ; icône de dossier ouvert. */
.folder-link[aria-current] {
  font-weight: 600;
  color: var(--text-strong);
  background: var(--nav-current-bg);
  box-shadow: inset 0 0 0 2px var(--text-strong);
}

/* « Sans dossier » : un dossier en pointillés (décoratif, le libellé dit tout). */
.folder-link--unfiled .icon {
  stroke-dasharray: 3 3;
}

/* « Nouveau dossier » : volet natif (details), ouvert au clavier par Entrée ou Espace. */
.folder-new {
  margin-top: 0.75rem;
}

.folder-new-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 2rem;
  padding: 0.25rem 0.625rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  list-style: none;
  border-radius: var(--radius);
  cursor: pointer;
}

.folder-new-toggle::-webkit-details-marker {
  display: none;
}

.folder-new-toggle:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.folder-new[open] .folder-new-toggle {
  color: var(--text-strong);
}

.folder-new-toggle .icon {
  width: 1rem;
  height: 1rem;
}

.folder-new-form {
  max-width: 24rem;
  margin: 0.5rem 0 0;
  padding: 0 0.625rem;
}

.folder-new-form label {
  margin-bottom: 0.25rem;
  font-size: 0.875rem;
}

.folder-new-form .quick-form-row {
  margin: 0;
}

.folder-new-form input[type="text"] {
  padding: 0.4rem 0.625rem;
  font-size: 0.9375rem;
}

.notes-main .section-header {
  margin-bottom: 1rem;
}

.notes-main h2 {
  margin: 0;
  overflow-wrap: anywhere;
}

.note-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.note-card {
  gap: 0.375rem;
  padding: 0.875rem 1.125rem;
}

/* Une icône suivie d'UN seul span de texte : sur téléphone, le texte passe à la ligne
   dans son span au lieu de faire une colonne par morceau. */
.note-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.note-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

.note-meta-item .icon {
  width: 1rem;
  height: 1rem;
}

@media (min-width: 60rem) {
  .notes-layout {
    grid-template-columns: 13rem minmax(0, 1fr);
    gap: 2.5rem;
    align-items: start;
  }

  .folder-list {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0.125rem;
  }

  .folder-link {
    flex: 1 1 auto;
    padding: 0.375rem 0.625rem;
    background: transparent;
    border-radius: var(--radius);
  }

  .folder-link[aria-current] {
    box-shadow: inset 3px 0 0 var(--text-strong);
  }

  /* Un filet sépare « Toutes les notes » et « Sans dossier » des dossiers du compte. */
  .folder-list > li:nth-child(2):not(:last-child) {
    margin-bottom: 0.375rem;
    padding-bottom: 0.375rem;
    border-bottom: 1px solid var(--border-subtle);
  }

  .folder-new-toggle {
    width: 100%;
  }
}

/* Bloc « Notes » des fiches projet, vidéo et stream : même liste que les liens d'une vidéo,
   pas plus large qu'un texte (la date reste près du titre). */
.note-rows {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  max-width: 44rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.note-row .tag-row-name .icon {
  width: 1rem;
  height: 1rem;
  color: var(--text-muted);
}

.note-row-date {
  min-width: 9.5rem;
}

/* Fiche d'une note. */
.note-meta {
  margin-bottom: 2rem;
}

.note-detail-actions {
  margin-top: 2.5rem;
}

.notice .notice-action {
  margin-top: 0.5rem;
}

/* Formulaire : plus large que les autres, pour écrire à l'aise. */
.form.note-form {
  max-width: 48rem;
}

.note-editor > label {
  margin-bottom: 0.25rem;
}

/* Onglets « Écrire | Aperçu » : deux boutons radio natifs (voir notes/note_form.html). */
.editor-tabs {
  display: flex;
  gap: 0.25rem;
  min-width: 0;
  margin: 0 0 0.625rem;
  padding: 0;
  border: none;
  border-bottom: 1px solid var(--border-subtle);
}

.editor-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.5rem;
  margin: 0;
  padding: 0.5rem 0.75rem;
  font-size: 0.9375rem;
  font-weight: 400;
  color: var(--text-muted);
  border-radius: var(--radius) var(--radius) 0 0;
  cursor: pointer;
}

.editor-tab:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.editor-panel--write textarea {
  min-height: 22rem;
  line-height: 1.6;
}

/* Aperçu : carte --surface ; blocs de code et en-têtes de tableau un cran plus clairs
   (--card-bg : --text >= 13:1 dessus en sombre). */
.editor-panel--preview {
  --prose-block-bg: var(--card-bg);
  min-height: 22rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border-radius: var(--radius);
}

.editor-panel + .editor-panel {
  margin-top: 0.75rem;
}

.editor-preview-refresh {
  margin: 0 0 1rem;
}

.note-editor .helptext {
  margin-top: 0.5rem;
}

/* Pendant la requête de l'aperçu (classe posée par htmx, hx-indicator) : l'ancien
   contenu s'estompe. */
.note-preview {
  transition: opacity 0.15s ease;
}

.editor-panel--preview.htmx-request .note-preview {
  opacity: 0.55;
}

@supports selector(:has(*)) {
  /* Le bouton radio reste focalisable et lu ; l'onglet montre l'état et le focus. */
  .editor-tab-input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
  }

  /* Onglet choisi : gras, texte plus clair et barre dessous, pas seulement une couleur. */
  .editor-tab:has(.editor-tab-input:checked) {
    font-weight: 600;
    color: var(--text-strong);
  }

  .editor-tab:has(.editor-tab-input:checked)::after {
    content: "";
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    bottom: -1px;
    height: 2px;
    border-radius: 2px;
    background: var(--text-strong);
  }

  .editor-tab:has(.editor-tab-input:focus-visible) {
    outline: 3px solid var(--focus);
    outline-offset: 0;
  }

  /* Seul le panneau de l'onglet choisi s'affiche ; l'autre reste dans la page. */
  .note-editor:has(.editor-tab-input--preview:checked) .editor-panel--write,
  .note-editor:not(:has(.editor-tab-input--preview:checked)) .editor-panel--preview {
    display: none;
  }

  .editor-panel + .editor-panel {
    margin-top: 0;
  }
}

/* Aide-mémoire Markdown, sous le texte (volet natif). */
.markdown-help {
  margin: -0.5rem 0 1.5rem;
}

.markdown-help-toggle {
  min-height: 2rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  cursor: pointer;
}

.markdown-help-toggle:hover,
.markdown-help[open] .markdown-help-toggle {
  color: var(--text-strong);
}

.markdown-help-table {
  width: 100%;
  margin-top: 0.5rem;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.markdown-help-table :is(th, td) {
  padding: 0.375rem 0.5rem;
  text-align: start;
  vertical-align: top;
  border-top: 1px solid var(--rule);
  overflow-wrap: anywhere;
}

.markdown-help-table th {
  font-weight: 600;
  color: var(--text-strong);
  border-top: none;
}

.markdown-help-table td:first-child {
  width: 45%;
}

.markdown-help-note {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: reduce) {
  .note-preview {
    transition: none;
  }
}

/* Mode contraste élevé de Windows : fonds et ombres disparaissent, on rend des contours. */
@media (forced-colors: active) {
  .folder-link,
  .editor-panel--preview {
    border: 1px solid CanvasText;
  }

  .folder-link[aria-current] {
    outline: 2px solid CanvasText;
    outline-offset: -3px;
  }

  .editor-tab:has(.editor-tab-input:checked)::after {
    forced-color-adjust: none;
    background: CanvasText;
  }
}

/* ---------- Idées (US-05.5) ---------- */

/* Choix parmi quelques valeurs d'une liste (statut des idées) : des liens en pastilles, sur
   une ou plusieurs lignes. Le choix affiché (aria-current) : gras, fond et anneau, pas
   seulement une couleur. --text-muted >= 6:1 sur --surface et --hover-bg, deux thèmes. */
.filter-pills {
  margin: 0 0 1rem;
}

.filter-pills ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  padding: 0.375rem 0.875rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
  text-decoration: none;
  background: var(--surface);
  border-radius: 999px;
}

.filter-pill:hover {
  color: var(--text-strong);
  background: var(--hover-bg);
}

.filter-pill[aria-current] {
  font-weight: 600;
  color: var(--text-strong);
  background: var(--nav-current-bg);
  box-shadow: inset 0 0 0 2px var(--text-strong);
}

/* Statut d'une idée : la marque devant le texte le dit par sa forme (anneau en pointillés,
   coche, croix, caméra des vidéos) ; la couleur ne fait que la souligner. Marques >= 3,5:1
   sur le fond de la pastille, --surface et --hover-bg, dans les deux thèmes. Six traits
   réguliers sur l'anneau (circonférence 62,8 ; les bouts arrondis prennent 2 de chaque
   vide). */
.icon.idea-mark {
  width: 0.875rem;
  height: 0.875rem;
}

.idea-mark--exploring {
  color: var(--project-blue);
  stroke-dasharray: 4.5 5.97;
}

.idea-mark--kept {
  color: var(--success);
}

.idea-mark--dropped {
  color: var(--text-muted);
}

.idea-mark--converted {
  color: var(--video-accent);
}

/* Liste : une carte par idée, entièrement cliquable comme celles des notes. */
.idea-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.idea-card {
  gap: 0.5rem;
  padding: 0.875rem 1.125rem;
}

/* Second lien d'une carte entièrement cliquable (la fiche vidéo d'une idée) : posé
   au-dessus du lien de la carte, il reste cliquable ; le remplissage vertical porte sa
   zone de clic à 24 px sans changer la ligne. */
.card-secondary-link {
  position: relative;
  z-index: 1;
  padding: 0.1875rem 0;
  color: var(--text-strong);
}

/* Fiche : le titre et son statut à gauche, « Modifier » et « Supprimer » à droite. */
.idea-header {
  align-items: flex-start;
}

.idea-heading {
  display: flex;
  flex: 1 1 20rem;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  min-width: 0;
}

/* Le projet et les étiquettes à côté du bloc « Fiche vidéo » ; l'un sous l'autre sur
   écran étroit. */
.idea-hero {
  display: grid;
  gap: 1.5rem;
  margin: 0 0 2.5rem;
}

@media (min-width: 60rem) {
  .idea-hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
    align-items: start;
    gap: 2rem;
  }
}

/* Bloc « Fiche vidéo » : ce que la fiche reprendra, puis le bouton principal de la page.
   Une fois l'idée transformée, la couleur des vidéos (fond --video-bg, barre et icône
   --video-accent) : --text >= 11,5:1, lien --text-strong >= 14,5:1, focus >= 5,7:1,
   icône >= 4,5:1, dans les deux thèmes. */
.convert-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.875rem;
  margin: 0;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border-radius: 8px;
}

.convert-panel p {
  margin: 0;
}

.convert-panel-text {
  max-width: 34rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.convert-panel-result {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

.convert-panel-result .icon {
  margin-top: 0.1875rem;
}

.convert-panel--done {
  background: var(--video-bg);
  box-shadow: inset 3px 0 0 var(--video-accent);
}

.convert-panel--done .icon {
  color: var(--video-accent);
}

/* Formulaire : valeur écrite à la place d'un champ désactivé (statut d'une idée
   transformée), avec le même libellé qu'un champ. */
.field-label {
  margin: 0 0 0.375rem;
  font-weight: 500;
  color: var(--text-strong);
}

.field-value {
  margin: 0 0 0.375rem;
}

/* Mode contraste élevé de Windows : fonds et ombres disparaissent, on rend des contours. */
@media (forced-colors: active) {
  .filter-pill,
  .convert-panel {
    border: 1px solid CanvasText;
  }

  .filter-pill[aria-current]:not(:focus-visible) {
    outline: 2px solid CanvasText;
    outline-offset: -3px;
  }

  .convert-panel--done {
    border-left-width: 3px;
  }
}

/* ---------- Sécurité du compte (US-01.3) ---------- */

/* Aide sous un champ écrit à la main (code à usage unique) : collée au champ. */
.field .helptext {
  margin: 0.375rem 0 0;
}

/* Page « Sécurité du compte » : un panneau par sujet, l'un sous l'autre. Même panneau pour
   chaque plateforme de la page « Connexions » (US-01.4). */
.security-panel + .security-panel {
  margin-top: 1rem;
}

.security-panel h2 {
  margin: 0;
}

.security-panel .actions {
  margin-top: 0.25rem;
}

/* Titre et état écrit (« Active » / « Inactive ») sur une ligne. */
.security-panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}

.security-count {
  margin: 0 0 1.5rem;
}

/* Étapes de l'activation : liste numérotée (numéros lus par les lecteurs d'écran), un titre
   par étape. */
.steps {
  margin: 0;
  padding-left: 1.5rem;
}

.steps > li + li {
  margin-top: 2rem;
}

.steps > li::marker {
  font-weight: 600;
  color: var(--text-strong);
}

.steps h2 {
  margin: 0 0 0.5rem;
}

.steps p {
  margin: 0 0 0.75rem;
}

/* QR code : modules noirs sur fond blanc quel que soit le thème (un QR code clair sur fond
   sombre n'est pas lu par toutes les applis), et en contraste élevé (forced-color-adjust :
   le navigateur ne repeint ni le fond ni les modules). La marge blanche de 4 modules fait
   partie du dessin ; le padding l'élargit un peu. 21:1 entre modules et fond. */
.qr-code {
  width: 13rem;
  max-width: 100%;
  margin: 0 0 1.25rem;
  padding: 0.5rem;
  background: #ffffff;
  border-radius: var(--radius);
  forced-color-adjust: none;
}

.qr-code svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Clé à saisir à la main : chasse fixe, groupes de 4 caractères séparés par une marge et
   un <wbr> (retour à la ligne possible), sans espace : une sélection la copie d'un bloc ;
   un clic la sélectionne en entier. */
.totp-key {
  display: inline-block;
  max-width: 100%;
  padding: 0.5rem 0.75rem;
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  letter-spacing: 0.05em;
  color: var(--text-strong);
  background: var(--surface);
  border-radius: var(--radius);
  user-select: all;
}

.totp-key span:not(:last-child) {
  margin-right: 0.75ch;
}

/* Champ d'un code à usage unique : court, chiffres à chasse fixe et espacés. */
.code-input {
  max-width: 14rem;
  font-family: var(--font-mono);
  font-size: 1.125rem;
  letter-spacing: 0.15em;
}

/* Codes de secours : deux colonnes, chasse fixe, sur un fond relevé. */
.recovery-codes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem 1.5rem;
  margin: 0 0 1.5rem;
  padding: 1rem 1.25rem;
  list-style: none;
  background: var(--surface);
  border-radius: var(--radius);
}

.recovery-codes code {
  font-family: var(--font-mono);
  font-size: 1.0625rem;
  letter-spacing: 0.08em;
  color: var(--text-strong);
}

/* Autres façons de confirmer son identité (code au lieu du mot de passe, ou l'inverse). */
.reauth-alternatives {
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;
}

@media (forced-colors: active) {
  .totp-key,
  .recovery-codes {
    border: 1px solid CanvasText;
  }
}

/* ---------- Boîte de tri (US-02.11) ---------- */

/* Champ de capture, en haut du menu sur chaque écran (inbox/includes/capture_form.html) :
   libellé court, champ et « Ajouter » sur une ligne (.quick-form-row), erreur dessous.
   Libellé --text-muted comme les entrées du menu : >= 7:1 sur --sidebar-bg dans les deux
   thèmes ; erreur --error >= 5,9:1. Sous 48rem, il prend toute la largeur de la barre du
   haut, sous le nom de l'appli. */
.capture-form {
  flex: none;
  min-width: 0;
  margin: 0;
}

/* Aligné sur le texte du champ, le nom de l'appli et les icônes du menu. */
.capture-form label {
  margin-bottom: 0.25rem;
  padding: 0 0.625rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.capture-form .quick-form-row {
  margin: 0;
}

.capture-form input[type="text"] {
  padding: 0.375rem 0.625rem;
  font-size: 0.9375rem;
}

.capture-form .errorlist {
  margin: 0.375rem 0 0;
  padding: 0;
  font-size: 0.8125rem;
  list-style: none;
}

@media (max-width: 47.99rem) {
  .capture-form {
    flex-basis: 100%;
  }
}

/* Nombre d'éléments à trier, dans l'entrée « À trier » du menu : pastille discrète, poussée
   à droite dans le menu latéral ; « éléments » est lu par les lecteurs d'écran. --text sur
   --secondary-bg >= 12:1, sur --secondary-hover (survol, entrée active) >= 10:1. */
.nav-count {
  min-width: 1.375rem;
  margin-left: auto;
  padding: 0 0.375rem;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.375rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 999px;
}

.nav-link:hover .nav-count,
.nav-link[aria-current] .nav-count {
  background: var(--secondary-hover);
}

/* Message de la dernière action (rangement, corbeille, restauration), rempli hors bande par
   HTMX au-dessus de la liste : il porte le lien vers la tâche ou l'idée créée. Pas une
   région live (l'annonce passe par #live-announcer) ; vide, il ne prend aucune place. */
.inbox-feedback {
  margin: 0 0 1.5rem;
}

.inbox-feedback:empty {
  display: none;
}

/* Lignes à trier et lignes de la corbeille : une carte par élément (texte, date, puis ses
   actions, qui passent à la ligne sur un téléphone). --text-muted >= 7:1 sur --surface. */
.inbox-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.inbox-item,
.inbox-quote {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border-radius: 8px;
}

.inbox-quote {
  gap: 0.125rem;
  margin: 0 0 1.5rem;
}

.inbox-item p,
.inbox-quote p {
  margin: 0;
}

.inbox-item-text {
  font-weight: 500;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.inbox-item-meta {
  margin-top: 0.125rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Un seul formulaire par ligne : le projet (libellé à côté de la liste, erreur dessous, en
   grille pour que l'erreur n'élargisse pas le bloc), puis « En tâche », « En idée » et
   « Corbeille », alignés sur la ligne de la liste. */
.inbox-file-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.5rem 1rem;
  margin: 0;
}

.inbox-project {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.25rem 0.5rem;
  min-width: 0;
  max-width: 100%;
  margin: 0;
}

.inbox-project label {
  margin: 0;
  font-size: 0.875rem;
}

.inbox-project select {
  width: auto;
  min-width: min(12rem, 100%);
  max-width: 100%;
  min-height: 2rem;
  padding: 0.25rem 0.625rem;
  font-size: 0.9375rem;
}

.inbox-project .errorlist {
  grid-column: 2;
  margin: 0;
  padding: 0;
  font-size: 0.875rem;
  list-style: none;
}

.inbox-item-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
}

@media (forced-colors: active) {
  .nav-count,
  .inbox-item,
  .inbox-quote {
    border: 1px solid CanvasText;
  }
}

/* ---------- Import depuis Notion (US-05.4) ---------- */

/* Fil des étapes (imports/includes/steps.html), sur le modèle du fil d'Ariane : l'étape
   courante en gras et en clair, les étapes faites en liens, les autres en texte discret. */
.import-steps [aria-current="step"] {
  font-weight: 600;
  color: var(--text-strong);
}

/* Aide de l'envoi : comment exporter depuis Notion, ce qui n'est pas importé. Panneau
   --surface de la largeur du formulaire (--text-muted dessus : 7,1:1). */
.import-help {
  max-width: 40rem;
  margin: 0 0 2rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border-radius: 8px;
}

.import-help h2 {
  margin: 0 0 0.5rem;
}

.import-help h3 {
  margin: 1rem 0 0.25rem;
  font-size: 0.9375rem;
}

.import-help p {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.import-help-steps {
  margin: 0;
  padding-left: 1.25rem;
  font-size: 0.9375rem;
}

.import-help-steps li + li {
  margin-top: 0.25rem;
}

.import-help-steps li::marker {
  font-weight: 600;
  color: var(--text-strong);
}

/* Choix en cartes (cible d'un import, base d'un .zip) : radios natives (flèches du
   clavier), le nom en libellé, une phrase dessous reliée par aria-describedby. Toute la
   carte est cliquable (le ::after du libellé la couvre). Choisie : fond plus marqué,
   anneau et nom en gras, en plus du bouton radio coché, comme le sélecteur de couleur.
   --text-muted >= 6:1 sur --surface, --hover-bg et --secondary-bg, dans les deux thèmes. */
.choice-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
  gap: 0.5rem;
}

.choice-cards--list {
  grid-template-columns: minmax(0, 1fr);
}

.choice-card {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: start;
  align-items: start;
  gap: 0.125rem 0.625rem;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border-radius: 8px;
}

.choice-card:hover {
  background: var(--hover-bg);
}

.choice-card input {
  margin: 0.3rem 0 0;
}

.choice-card label {
  margin: 0;
  font-weight: 500;
  color: var(--text-strong);
  cursor: pointer;
  overflow-wrap: anywhere;
}

.choice-card label::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 8px;
}

.choice-card-text {
  grid-column: 2;
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

.choice-card:has(input:checked) {
  background: var(--secondary-bg);
  box-shadow: inset 0 0 0 2px var(--text-strong);
}

.choice-card:has(input:checked) label {
  font-weight: 600;
}

/* Aucun choix envoyé : barre rouge sur chaque carte, en plus du message écrit au-dessus. */
.choice-card:has(input[aria-invalid="true"]):not(:has(input:checked)) {
  box-shadow: inset 3px 0 0 var(--danger);
}

@supports selector(:has(*)) {
  .choice-card:has(input:focus-visible) {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
  }

  .choice-card input:focus-visible {
    outline: none;
  }
}

/* Projet (des tâches) et dossier (des notes) : chacun dans son groupe titré « Pour des
   tâches » / « Pour des notes », toujours dans la page. Là où le navigateur connaît :has(),
   seul celui de la cible cochée s'affiche, juste sous les cartes (et tout groupe qui porte
   une erreur) ; ailleurs les deux restent visibles et leur légende dit quand ils comptent.
   Aucun JavaScript. */
fieldset.import-extra {
  min-width: 0;
  padding: 0 0 0.125rem 1rem;
  border: none;
  box-shadow: inset 2px 0 0 var(--rule);
}

/* La légende flotte sur toute la largeur : elle passe dans la boîte du groupe, décalée
   comme son contenu, au lieu de rester posée sur sa bordure. */
.form fieldset.import-extra legend {
  float: left;
  width: 100%;
  margin-bottom: 0.25rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-muted);
}

.import-extra legend + * {
  clear: left;
}

.import-extra select {
  max-width: 24rem;
}

.import-extra .helptext {
  margin: 0 0 0.375rem;
}

.import-extra-empty {
  margin: 0;
  color: var(--text-muted);
}

@supports selector(:has(*)) {
  .import-extra {
    display: none;
  }

  .import-upload:has(input[name="target"][value="tasks"]:checked) .import-extra--tasks,
  .import-upload:has(input[name="target"][value="notes"]:checked) .import-extra--notes,
  .import-extra:has(.errorlist) {
    display: block;
  }
}

/* Imports des dernières 24 heures : une ligne par import (cible, état, envoi, lien). */
.import-batches-section {
  max-width: 40rem;
  margin-top: 3rem;
}

.import-batches {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin: 0 0 0.75rem;
  padding: 0;
  list-style: none;
}

.import-batch {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.75rem;
  padding: 0.375rem 0.5rem 0.375rem 0.75rem;
  border-radius: var(--radius);
}

.import-batch:hover {
  background: var(--surface);
}

.import-batch-target {
  font-weight: 500;
  color: var(--text-strong);
}

.import-batch .badge {
  align-self: center;
}

.import-batch-time {
  flex: 1 1 10rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* « Importé » : pastille verte, le mot le dit (--success-text sur --success-bg >= 6,5:1). */
.import-batch-status--done {
  color: var(--success-text);
  background: var(--success-bg);
}

.import-batches-note {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* Correspondance : un groupe par tableau, titré comme une section. */
.form.import-mapping {
  max-width: 48rem;
}

.import-fieldset {
  min-width: 0;
  margin: 0 0 2.5rem;
  padding: 0;
  border: none;
}

.import-fieldset legend {
  margin: 0 0 0.5rem;
  padding: 0;
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-strong);
}

.import-hints,
.import-fieldset-intro {
  margin: 0 0 1rem;
  font-size: 0.9375rem;
  color: var(--text-muted);
}

.import-hints {
  padding-left: 1.25rem;
}

.import-hints li + li {
  margin-top: 0.125rem;
}

/* Tableaux de l'import : traits discrets entre les lignes (border-collapse: separate : ils
   suivent la colonne figée de l'aperçu), en-têtes de colonne petits et discrets. */
.import-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}

.import-table th,
.import-table td {
  padding: 0.625rem 0.75rem;
  text-align: left;
  vertical-align: top;
}

.import-table thead th {
  padding-top: 0;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
  vertical-align: bottom;
}

.import-table tbody > tr > * {
  border-top: 1px solid var(--border-subtle);
}

.import-table tbody th {
  font-weight: 400;
}

/* Correspondance : deux colonnes seulement (la colonne ou la valeur, puis sa liste), pour
   tenir sur un téléphone sans défiler. */
.import-map-table td {
  width: 45%;
}

.import-map-table tbody th label {
  margin: 0;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.import-samples,
.import-value-count {
  display: block;
  margin-top: 0.125rem;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* Aperçu et résultat : les compteurs en tuiles ; « À créer » (ou « Créées ») marqué d'une
   barre verte, les erreurs et les avertissements d'une barre rouge ou orangée quand il y en
   a. Le libellé dit tout, la barre ne fait que le souligner. */
.import-counts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0;
}

@media (min-width: 40rem) {
  .import-counts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.import-count {
  min-width: 0;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border-radius: var(--radius);
}

.import-count dt {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text);
}

.import-count dd {
  margin: 0;
}

.import-count .import-count-value {
  margin-top: 0.125rem;
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

.import-count .import-count-hint {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.import-count--create {
  box-shadow: inset 3px 0 0 var(--success);
}

.import-count--error {
  box-shadow: inset 3px 0 0 var(--danger);
}

.import-count--warning {
  box-shadow: inset 3px 0 0 var(--warning);
}

.import-duplicate-titles {
  margin: 1rem 0 0;
}

.import-skip {
  margin: 1rem 0 0;
}

/* Aperçu : le tableau défile dans son cadre (.table-scroll) sur écran étroit, la colonne
   du titre figée à gauche sur le fond de la page. */
.import-preview-table {
  min-width: 42rem;
}

.import-preview-table thead th:first-child,
.import-preview-table tbody th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bg);
}

.import-row-title {
  display: block;
  min-width: 8rem;
  max-width: 16rem;
  font-weight: 500;
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

/* Ligne qui ne sera pas créée : titre moins appuyé (l'issue reste écrite à côté). */
.import-row:not(.import-row--create) .import-row-title {
  font-weight: 400;
  color: var(--text);
}

.import-row .import-untitled {
  font-style: italic;
  color: var(--text-muted);
}

.import-row-line {
  display: block;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Issue d'une ligne : une pastille dont le mot dit tout ; vert pour « À créer », rouge pour
   « Erreur », gris pour « Doublon » et « Ignorée » (texte >= 5,9:1 sur chaque fond). */
.import-outcome {
  display: inline-block;
  padding: 0.0625rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  color: var(--text);
  background: var(--secondary-bg);
  border-radius: 999px;
}

.import-outcome--create {
  color: var(--success-text);
  background: var(--success-bg);
}

.import-outcome--skipped {
  color: var(--text-muted);
}

.import-outcome--error {
  color: var(--danger);
  background: var(--danger-hover-bg);
}

.import-reason {
  display: block;
  min-width: 10rem;
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* Avertissements d'une ligne : icône et texte --warning (>= 7:1 sur le fond de la page). */
.import-warnings {
  min-width: 10rem;
  margin: 0.375rem 0 0;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--warning);
  list-style: none;
}

.import-warnings li {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
}

.import-warnings li + li {
  margin-top: 0.25rem;
}

.import-warnings .icon {
  flex: none;
  width: 0.875rem;
  height: 0.875rem;
  margin-top: 0.15rem;
}

/* Date puis heure dessous : chacune d'un bloc, sans coupure. */
.import-date {
  white-space: nowrap;
}

.import-time {
  display: block;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.import-text {
  min-width: 12rem;
  max-width: 26rem;
}

.import-text .badge {
  margin-bottom: 0.25rem;
}

.import-text-start {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.import-none {
  color: var(--text-muted);
}

/* Là où le tableau peut déborder de son cadre, un filet sépare la colonne figée des
   cellules qui défilent dessous. */
@media (max-width: 60.99rem) {
  .import-preview-table thead th:first-child,
  .import-preview-table tbody th[scope="row"] {
    box-shadow: inset -1px 0 0 var(--border-subtle);
  }
}

/* Confirmation (aperçu), suite après une remarque (résultat). */
.import-confirm {
  margin-top: 0.5rem;
}

.import-next-pass {
  max-width: 40rem;
  margin: 1.25rem 0 0.5rem;
}

.import-counts + .import-batches-note {
  margin-top: 1.25rem;
}

.import-result-actions {
  margin-top: 1.5rem;
}

@media (max-width: 47.99rem) {
  .import-table th,
  .import-table td {
    padding: 0.5rem;
  }

  .import-map-table td {
    width: 55%;
  }

  .import-map-table select {
    padding-left: 0.5rem;
  }
}

/* Mode contraste élevé de Windows : fonds et ombres disparaissent, on rend des contours. */
@media (forced-colors: active) {
  .import-help,
  .choice-card,
  .import-count,
  .import-outcome {
    border: 1px solid CanvasText;
  }

  .choice-card:has(input:checked) {
    outline: 2px solid CanvasText;
  }

  .import-count--create,
  .import-count--error,
  .import-count--warning {
    border-left-width: 3px;
  }

  fieldset.import-extra {
    border-left: 2px solid CanvasText;
  }
}

@media (forced-colors: active) and (max-width: 60.99rem) {
  .import-preview-table thead th:first-child,
  .import-preview-table tbody th[scope="row"] {
    border-right: 1px solid CanvasText;
  }
}

/* ---------- Connexions (US-01.4) ---------- */

/* Carte d'une plateforme (Twitch) : le panneau de « Sécurité du compte » (titre et état
   écrit sur une ligne), resserré pour que ses phrases restent lisibles ; les détails
   (pseudo, dernière vérification, autorisations) en .meta, sans sa marge de fiche. */
.connection-card {
  max-width: 42rem;
}

.connection-card .meta {
  gap: 0.75rem 2.5rem;
  margin: 0;
}

/* État « À reconnecter » : un triangle d'alerte devant le mot, comme la coche de
   « Connecté » (.badge--done). --warning >= 5,9:1 sur le fond de la pastille, deux thèmes. */
.badge--warning {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.badge--warning .icon {
  width: 0.875rem;
  height: 0.875rem;
  color: var(--warning);
}

/* Résultat de « Vérifier maintenant », dans la carte : un encart un cran plus clair que
   la carte (--card-bg), barre à gauche comme les messages. Pas une région live : l'annonce
   passe par #live-announcer. Texte --text-strong >= 16:1 dans les deux thèmes. */
.connection-result {
  padding: 0.625rem 0.875rem;
  color: var(--text-strong);
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: inset 3px 0 0 var(--text-muted);
}

@media (forced-colors: active) {
  .connection-result {
    border: 1px solid CanvasText;
  }
}
