/* =====================================================================
   Portfolio BTS SIO — feuille de style principale
   Sommaire :
     1. Réinitialisation et base
     2. Accessibilité
     3. Mise en page et primitives
     4. Décors (grille, halos, profondeur)
     5. En-tête et navigation
     6. Pied de page
     7. Composants (boutons, cartes, badges, formulaires…)
     8. Compositions de pages
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Réinitialisation et base
   ------------------------------------------------------------------ */

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

* { margin: 0; }

/* L'attribut hidden doit toujours l'emporter. Sans cette règle, la moindre
   classe posant un display (grid, flex, block) le neutralise en silence :
   c'est ainsi que le message « aucune réalisation ne correspond » restait
   affiché sous une grille pleine, et que le voile du menu floutait la page
   entière sur téléphone. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* La barre latérale ne recouvre rien horizontalement : seule la marge de
     confort reste. Sous 1080 px, le bouton flottant occupe le coin haut. */
  scroll-padding-top: var(--space-6);
}

body {
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, picture, video, canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Les icônes vivent dans le texte : en display:block elles passeraient à la
   ligne au milieu d'un titre ou d'un lien. */
svg {
  display: inline-block;
  vertical-align: -0.14em;
  max-width: 100%;
  flex: none;
}

/* Une illustration en SVG occupe en revanche tout son conteneur. */
.scene-fallback svg { display: block; vertical-align: baseline; }

input, button, textarea, select { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

p, li { text-wrap: pretty; }

a {
  color: var(--primary);
  text-decoration-color: var(--primary-line);
  text-underline-offset: 3px;
  transition: color var(--duration-fast) var(--ease-out);
}

a:hover { color: var(--primary-hover); }

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--space-6) 0;
}

code, kbd, samp, pre { font-family: var(--font-mono); font-size: 0.92em; }

::selection { background: var(--primary-soft); color: var(--text); }

/* ---------------------------------------------------------------------
   2. Accessibilité (§81)
   ------------------------------------------------------------------ */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  z-index: 200;
  padding: var(--space-3) var(--space-5);
  background: var(--primary);
  color: var(--on-primary);
  border-radius: var(--radius-md);
  font-weight: 600;
  text-decoration: none;
  transition: top var(--duration-base) var(--ease-out);
}

.skip-link:focus { top: var(--space-4); color: var(--on-primary); }

/* Lisible par les lecteurs d’écran, invisible à l’œil. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Respect de prefers-reduced-motion (§80) : les animations décoratives
   disparaissent, aucune fonctionnalité n’est perdue. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal { opacity: 1 !important; transform: none !important; }
}

/* ---------------------------------------------------------------------
   3. Mise en page et primitives
   ------------------------------------------------------------------ */

.container {
  width: 100%;
  max-width: var(--width-content);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.container--wide { max-width: var(--width-wide); }
.container--prose { max-width: var(--width-prose); }

.section { padding-block: clamp(var(--space-7), 6vw, var(--space-10)); position: relative; }
.section--tight { padding-block: var(--space-7); }

.stack > * + * { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-6); }

.grid { display: grid; gap: var(--space-5); }
.grid > * { min-width: 0; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fill, minmax(min(210px, 100%), 1fr)); }

.cluster { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.cluster--between { justify-content: space-between; }

.prose { max-width: var(--width-prose); }
.prose p + p { margin-top: var(--space-4); }
.prose p { color: var(--text-muted); }
.prose strong { color: var(--text); font-weight: 600; }

.text-muted { color: var(--text-muted); }
.text-subtle { color: var(--text-subtle); }
.text-sm { font-size: var(--text-sm); }
.text-lg { font-size: var(--text-lg); }

/* Sur-titre de section : petit, espacé, discret */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

.eyebrow::before {
  content: '';
  width: 24px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--primary));
}

.section-head { margin-bottom: var(--space-6); max-width: var(--width-prose); }
.section-head h2 { margin-top: var(--space-3); }
.section-head p { margin-top: var(--space-3); color: var(--text-muted); }

/* ---------------------------------------------------------------------
   4. Décors : grille, halos, profondeur (§62, §63)
   ------------------------------------------------------------------ */

/* Trame technique très discrète, posée derrière le contenu. */
.backdrop {
  position: fixed;
  inset: 0;
  /* Quand une page contient un bloc à défilement horizontal (la matrice),
     Chrome dimensionne les éléments fixes sur la largeur de défilement du
     document et non sur celle de la fenêtre : la trame et le menu mobile se
     retrouvaient larges de 715 px au lieu de 390. Ce plafond les ramène à la
     fenêtre sans rien changer là où le problème ne se pose pas. */
  right: auto;
  width: 100vw;
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0 / 64px 64px,
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0 / 64px 64px;
  mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 25%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 25%, transparent 78%);
}

.backdrop::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(760px 460px at 12% -6%, var(--halo-1), transparent 62%),
    radial-gradient(620px 420px at 88% 4%, var(--halo-2), transparent 60%);
}

/* Surface vitrée, employée avec parcimonie (§63) */
.glass {
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
}

@supports not (backdrop-filter: blur(1px)) {
  .glass { background: var(--surface); }
}

/* ---------------------------------------------------------------------
   5. Barre latérale (§66)

   Le portfolio tient sur une page unique : la navigation n'est donc pas un
   bandeau qui suit le défilement, mais une colonne fixe qui reste lisible
   en permanence — identité, sections, pages du dossier, thème.
   Sous 1080 px elle devient un tiroir, ouvert par un bouton flottant.
   ------------------------------------------------------------------ */

.sidebar {
  position: fixed;
  inset-block: 0;
  left: 0;
  width: var(--sidebar-width);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-5);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  border-right: 1px solid var(--border);
}

@supports not (backdrop-filter: blur(1px)) {
  .sidebar { background: var(--bg-elevated); }
}

/* Le contenu se décale d'autant : la barre étant fixe, elle est sortie du
   flux et recouvrirait sinon le début de chaque ligne. */
.shell { margin-left: var(--sidebar-width); min-width: 0; }

/* --- Identité --------------------------------------------------------- */

.sidebar__identity { display: grid; justify-items: center; text-align: center; gap: var(--space-1); }

.sidebar__brand {
  display: grid;
  justify-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: var(--text);
}

.sidebar__photo,
.sidebar__mark {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-full);
  object-fit: cover;
  border: 2px solid color-mix(in srgb, var(--primary) 40%, transparent);
}

.sidebar__mark {
  display: grid;
  place-items: center;
  background: linear-gradient(140deg, var(--primary), var(--secondary));
  color: #06070D;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-xl);
  letter-spacing: var(--tracking-tight);
}

.sidebar__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.sidebar__role { font-size: var(--text-sm); color: var(--text-muted); }

/* --- Navigation ------------------------------------------------------- */

.sidebar__nav ul { list-style: none; padding: 0; display: grid; gap: 2px; }

.sidebar__heading {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-2);
  padding-inline: var(--space-3);
}

/* Huit sections plus quatre pages : la colonne doit tenir dans un écran
   d'ordinateur portable sans repousser le sélecteur de thème hors champ.
   La cible reste à 44 px au doigt, où le tiroir défile de toute façon. */
.sidebar__link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 38px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: 500;
  transition: background-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.sidebar__link svg { color: var(--text-subtle); transition: color var(--duration-fast) var(--ease-out); }

.sidebar__link:hover { background: var(--surface-hover); color: var(--text); }
.sidebar__link:hover svg { color: var(--primary); }

/* La section en cours de lecture, désignée par le suivi au défilement, et
   la page ouverte : même marquage, puisque c'est la même idée. */
.sidebar__link[aria-current] {
  background: var(--primary-soft);
  color: var(--primary-on-soft);
}

.sidebar__link[aria-current] svg { color: var(--primary-on-soft); }

.sidebar__nav--sub { margin-top: var(--space-2); }
.sidebar__link--sub { min-height: 34px; font-size: var(--text-xs); }

@media (pointer: coarse) {
  .sidebar__link { min-height: 44px; }
  .sidebar__link--sub { min-height: 40px; }
}

/* --- Pied de la barre ------------------------------------------------- */

.sidebar__foot {
  margin-top: auto;
  display: grid;
  gap: var(--space-3);
  justify-items: center;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.sidebar__jury { width: 100%; justify-content: center; }

.sidebar__social { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; }

/* --- Sélecteur de thème ------------------------------------------------
   Trois états côte à côte : le visiteur voit d'un coup d'œil lequel est
   actif, ce qu'une bascule à deux ne montre jamais. */

.theme-switch {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
}

.theme-switch__option {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 30px;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-subtle);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out);
}

.theme-switch__option:hover { color: var(--text); }

.theme-switch__option[aria-checked='true'] {
  background: var(--primary-soft);
  color: var(--primary-on-soft);
}

/* Au doigt, trois cibles de 34 px collées sont trop serrées. */
@media (pointer: coarse) {
  .theme-switch__option { width: 44px; height: 40px; }
}

/* --- Bouton de thème cyclique (barres étroites) -------------------------
   Une seule icône est peinte : celle de la préférence en cours, choisie
   par le CSS d'après l'attribut posé sur la racine avant le premier rendu. */

[data-theme-icon] { display: none; }

:root[data-theme-preference='system'] [data-theme-icon='system'],
:root[data-theme-preference='light']  [data-theme-icon='light'],
:root[data-theme-preference='dark']   [data-theme-icon='dark'] {
  display: inline-flex;
}

/* --- Fondu au changement de thème --------------------------------------

   Basculer tout un site d'un coup est brutal. Les couleurs se croisent
   donc en un quart de seconde — jamais la mise en page, qui doit rester
   parfaitement immobile.

   La règle est universelle et marquée !important, pour une raison précise :
   énumérer des sélecteurs ne suffit pas. Les composants qui animent déjà
   quelque chose au survol — les cartes, par exemple — déclarent leur propre
   transition plus loin dans la feuille et remplacent purement et simplement
   celle du thème ; ils basculaient d'un coup pendant que le fond se fondait.

   La classe n'est posée que le temps du basculement, par le script, et
   jamais au premier rendu : hors de ce court instant, elle ne pèse sur
   aucune transition de survol. */

:root.theme-changing *,
:root.theme-changing *::before,
:root.theme-changing *::after {
  transition: background-color var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out),
              fill var(--duration-base) var(--ease-out) !important;
}

@media (prefers-reduced-motion: reduce) {
  :root.theme-changing *,
  :root.theme-changing *::before,
  :root.theme-changing *::after { transition: none !important; }
}

.sidebar__copy { font-size: var(--text-2xs); color: var(--text-subtle); text-align: center; }

/* --- Tiroir sous 1080 px ---------------------------------------------- */

/* Le bouton d'ouverture n'existe que là où la barre se referme : au-delà,
   elle est toujours visible et un bouton « ouvrir » n'aurait aucun sens. */
.sidebar-toggle { display: none; }

/* Le voile n'est jamais peint tant qu'il porte l'attribut hidden. Le
   déclarer display:block dans la requête média l'emportait sur le style
   par défaut de [hidden] : le voile restait affiché en permanence sur
   téléphone et floutait toute la page. */
.sidebar-overlay {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: color-mix(in srgb, #04060C 62%, transparent);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.sidebar-overlay[hidden] { display: none; }

@media (max-width: 1080px) {
  .shell { margin-left: 0; }

  .sidebar {
    width: min(320px, 86vw);
    transform: translateX(-100%);
    visibility: hidden;
    box-shadow: none;
    transition: transform var(--duration-base) var(--ease-out),
                visibility var(--duration-base);
  }

  .sidebar[data-open='true'] {
    transform: none;
    visibility: visible;
    box-shadow: var(--shadow-lg);
  }

  .sidebar-toggle {
    position: fixed;
    top: var(--space-4);
    left: var(--space-4);
    z-index: 110;
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--bg-elevated) 88%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    color: var(--text);
    cursor: pointer;
  }

  .sidebar[data-open='true'] ~ .sidebar-toggle,
  .sidebar-toggle[aria-expanded='true'] { color: var(--primary); }

  /* Le contenu commence sous le bouton flottant, jamais dessous. */
  .shell { padding-top: calc(44px + var(--space-5)); }
}

/* ---------------------------------------------------------------------
   6. Pied de page (§93)
   ------------------------------------------------------------------ */

.site-footer {
  margin-top: var(--space-9);
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
  padding-block: var(--space-7) var(--space-5);
}

/* Les minimums sont bornés par la largeur disponible : sinon, sur un
   téléphone étroit, 240 + 160 px de colonnes dépassent l'écran et font
   défiler toute la page horizontalement. */
.site-footer__grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
}

.site-footer__grid > * { min-width: 0; }

@media (min-width: 720px) {
  .site-footer__grid {
    grid-template-columns: minmax(min(100%, 240px), 1.3fr) repeat(auto-fit, minmax(min(100%, 160px), 1fr));
  }
}

.site-footer h2 {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-3);
}

.site-footer ul { list-style: none; padding: 0; display: grid; gap: var(--space-1); }
.site-footer a { color: var(--text-muted); text-decoration: none; font-size: var(--text-sm); }
.site-footer a:hover { color: var(--text); }

/* Un lien de pied de page ne faisait que 17 px de haut : sous le minimum de
   24 px du WCAG 2.2, et impossible à viser au pouce. La zone cliquable est
   portée à 28 px à la souris et 44 px au doigt, sans toucher à la taille du
   texte ; l'écart de la liste est réduit d'autant pour ne rien décaler. */
.site-footer li > a,
.site-footer__bottom a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  min-width: 28px;
}

@media (pointer: coarse) {
  .site-footer ul { gap: 0; }
  .site-footer li > a,
  .site-footer__bottom a { min-height: 44px; min-width: 44px; }
}

.site-footer__bottom {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  align-items: center;
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

/* Accès administration : présent, discret, jamais mis en avant. */
.footer-admin-link { color: var(--text-subtle); }
.footer-admin-link:hover { color: var(--text); }

/* ---------------------------------------------------------------------
   7. Composants
   ------------------------------------------------------------------ */

/* --- Bouton à icône --------------------------------------------------- */

.icon-button {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}

.icon-button:hover {
  color: var(--text);
  border-color: var(--border-strong);
  background: var(--surface-hover);
}

.icon-button svg { width: 18px; height: 18px; }

/* Au doigt, une cible de 38 px est trop petite : on l'élargit sans
   changer l'aspect visuel du bouton sur les écrans à pointeur précis. */
@media (pointer: coarse) {
  .icon-button { width: 44px; height: 44px; }
}

/* --- Boutons ---------------------------------------------------------- */

.button {
  --button-bg: var(--surface);
  --button-fg: var(--text);
  --button-border: var(--border);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.68rem 1.15rem;
  border: 1px solid var(--button-border);
  border-radius: var(--radius-md);
  background: var(--button-bg);
  color: var(--button-fg);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--duration-fast) var(--ease-out),
              background-color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.button:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.button:active { transform: translateY(0); }
.button svg { width: 17px; height: 17px; flex: none; }

.button--primary {
  --button-bg: var(--primary);
  --button-fg: var(--on-primary);
  --button-border: transparent;
}

.button--primary:hover { --button-bg: var(--primary-hover); box-shadow: var(--shadow-glow); }

.button--ghost {
  --button-bg: transparent;
  --button-border: var(--border);
}

.button--ghost:hover { --button-bg: var(--surface-hover); --button-border: var(--border-strong); }

.button--quiet {
  --button-bg: transparent;
  --button-border: transparent;
  --button-fg: var(--text-muted);
  padding-inline: var(--space-3);
}

.button--quiet:hover { --button-fg: var(--text); --button-bg: var(--surface-hover); box-shadow: none; }

.button--danger { --button-fg: var(--danger); --button-border: color-mix(in srgb, var(--danger) 35%, transparent); }
.button--danger:hover { --button-bg: var(--danger-bg); }

.button--sm { padding: 0.42rem 0.8rem; font-size: var(--text-xs); }
.button--lg { padding: 0.85rem 1.5rem; font-size: var(--text-base); }

.button[disabled], .button[aria-disabled='true'] {
  opacity: 0.5;
  pointer-events: none;
}

/* --- Badges et pastilles d’état --------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.24rem 0.6rem;
  border-radius: var(--radius-full);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.015em;
  white-space: nowrap;
}

.badge--outline { background: transparent; box-shadow: inset 0 0 0 1px var(--border); }
.badge--primary { background: var(--primary-soft); color: var(--primary-on-soft); }
.badge--secondary { background: var(--secondary-soft); color: var(--secondary); }

/* États du référentiel : chaque état a une couleur ET une forme propre,
   pour rester distinguable sans perception des couleurs (§81). */
.state {
  display: inline-flex;
  align-items: center;
  gap: 0.42em;
  padding: 0.24rem 0.62rem;
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  font-weight: 600;
  white-space: nowrap;
}

.state::before {
  content: '';
  width: 8px; height: 8px;
  flex: none;
  background: currentColor;
}

.state--none      { background: var(--state-none-bg); color: var(--state-none-fg); }
.state--none::before { border-radius: 50%; opacity: 0.55; }

.state--proposed  { background: var(--state-proposed-bg); color: var(--state-proposed-fg); }
/* losange */
.state--proposed::before { transform: rotate(45deg); border-radius: 1px; }

.state--validated { background: var(--state-validated-bg); color: var(--state-validated-fg); }
/* pastille pleine + coche portée par le texte */
.state--validated::before { border-radius: 50%; }

/* Statuts de publication */
.status { display: inline-flex; align-items: center; gap: 0.4em; font-size: var(--text-2xs); font-weight: 600; }
.status::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.status--brouillon    { color: var(--text-subtle); }
.status--a_completer  { color: var(--warning); }
.status--pret         { color: var(--secondary); }
.status--publie       { color: var(--success); }
.status--archive      { color: var(--text-subtle); opacity: 0.7; }

/* --- Cartes ----------------------------------------------------------- */

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  transition: transform var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

.card--flat { background: var(--surface-2); }
.card--bordered { background: transparent; }

.card--interactive { cursor: pointer; }
.card--interactive:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}

/* --- Carte de réalisation (§19) ---------------------------------------
   Élévation légère, zoom discret de l’image, halo de lumière qui suit le
   curseur, informations complémentaires révélées au survol. Rien de plus. */

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: transform var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

.project-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    420px circle at var(--pointer-x, 50%) var(--pointer-y, 0%),
    var(--primary-soft),
    transparent 62%
  );
  transition: opacity var(--duration-base) var(--ease-out);
}

.project-card:hover,
.project-card:focus-within {
  transform: translateY(-4px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}

.project-card:hover::before,
.project-card:focus-within::before { opacity: 1; }

.project-card__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: linear-gradient(150deg, var(--surface-2), var(--surface-3));
  border-bottom: 1px solid var(--border);
}

.project-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out);
}

.project-card:hover .project-card__media img { transform: scale(1.045); }

/* Sans visuel, un motif géométrique tient la place — jamais une image
   d’illustration générique qui n’aurait rien à voir avec la réalisation. */
.project-card__placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--text-subtle);
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0 / 28px 28px,
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0 / 28px 28px;
}

.project-card__placeholder svg { width: 34px; height: 34px; opacity: 0.5; }

.project-card__body {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  flex: 1;
}

.project-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  font-size: var(--text-2xs);
  color: var(--text-subtle);
}

.project-card__title { font-size: var(--text-lg); }

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

/* La carte entière devient cliquable sans piéger le lecteur d’écran :
   seul le titre porte le lien, son étendue couvre la carte. */
.project-card__title a::after { content: ''; position: absolute; inset: 0; z-index: 3; }
.project-card__title a:hover { color: var(--primary); }

.project-card__summary {
  color: var(--text-muted);
  font-size: var(--text-sm);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.project-card__footer {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

/* Détail révélé au survol sur les pointeurs précis ; toujours visible
   ailleurs, car un écran tactile n’a pas de survol (§19, §77). */
.project-card__reveal { display: contents; }

@media (hover: hover) and (min-width: 900px) {
  .project-card__reveal {
    display: block;
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height var(--duration-base) var(--ease-out),
                opacity var(--duration-base) var(--ease-out);
  }

  .project-card:hover .project-card__reveal,
  .project-card:focus-within .project-card__reveal { max-height: 140px; opacity: 1; }
}

/* --- Puces de technologie --------------------------------------------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.2rem 0.58rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: 500;
  /* Une étiquette est courte par nature et ne doit pas se couper en deux.
     Mais si une valeur trop longue arrive quand même — une saisie qui aurait
     dû tenir sur plusieurs lignes —, elle doit céder plutôt que de pousser
     toute la colonne hors de l'écran : c'est ainsi que la colonne latérale
     de la veille se retrouvait large de 1 400 px. */
  white-space: nowrap;
  max-width: 100%;
  overflow-wrap: anywhere;
}


.chip-list { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* --- Filtres (§18) ----------------------------------------------------- */

.filters {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.filter-group { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

.filter-group__label {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
  margin-right: var(--space-2);
  min-width: 74px;
}

.filter {
  padding: 0.36rem 0.78rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: all var(--duration-fast) var(--ease-out);
}

.filter:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface-hover); }

.filter[aria-pressed='true'], .filter.is-active {
  background: var(--primary-soft);
  border-color: var(--primary-line);
  color: var(--primary-on-soft);
  font-weight: 600;
}

/* --- Formulaires ------------------------------------------------------- */

.field { display: grid; gap: var(--space-2); }
.field + .field { margin-top: var(--space-4); }

.field__label { font-size: var(--text-sm); font-weight: 600; }
.field__label .required { color: var(--danger); }

.field__hint { font-size: var(--text-xs); color: var(--text-subtle); }
.field__error { font-size: var(--text-xs); color: var(--danger); font-weight: 500; }

.input, .select, .textarea {
  width: 100%;
  padding: 0.62rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  color: var(--text);
  font-size: var(--text-sm);
  transition: border-color var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); }

.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}

.input[aria-invalid='true'], .textarea[aria-invalid='true'] { border-color: var(--danger); }

.textarea { min-height: 130px; resize: vertical; line-height: 1.6; }

.select {
  appearance: none;
  padding-right: 2.2rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239AA5C2' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 16px;
}

.checkbox, .radio {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out),
              background-color var(--duration-fast) var(--ease-out);
}

.checkbox:hover, .radio:hover { border-color: var(--border-strong); background: var(--surface-hover); }
.checkbox input, .radio input { margin-top: 0.22rem; accent-color: var(--primary); flex: none; }
.checkbox__text { display: grid; gap: 0.15rem; font-size: var(--text-sm); }
.checkbox__text small { color: var(--text-subtle); font-size: var(--text-xs); }

/* --- Messages --------------------------------------------------------- */

.alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-sm);
}

.alert svg { width: 18px; height: 18px; flex: none; margin-top: 0.15rem; }
.alert--success { border-left-color: var(--success); background: var(--success-bg); }
.alert--error   { border-left-color: var(--danger);  background: var(--danger-bg); }
.alert--warning { border-left-color: var(--warning); background: var(--warning-bg); }
.alert--info    { border-left-color: var(--primary); background: var(--primary-soft); }

/* État vide : on explique, on n’invente pas de contenu de démonstration (§98) */
.empty-state {
  display: grid;
  gap: var(--space-3);
  justify-items: center;
  text-align: center;
  padding: var(--space-8) var(--space-5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--text-muted);
}

.empty-state svg { width: 34px; height: 34px; opacity: 0.4; }
.empty-state h3 { font-size: var(--text-lg); color: var(--text); }
.empty-state p { max-width: 46ch; font-size: var(--text-sm); }

/* --- Tableaux ---------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }

.table th, .table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
  white-space: nowrap;
}

.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-hover); }

/* --- Apparition au défilement (§64) -------------------------------------

   Un seul mécanisme, quatre variantes, et un décalage calculé plutôt
   qu'écrit à la main. Auparavant chaque gabarit portait un data-delay
   choisi au jugé, plafonné à quatre valeurs : la vue devait connaître
   l'animation, et une grille de cinq cartes voyait la cinquième repartir
   à zéro. Le rang vient maintenant du DOM, posé par le script.

   L'état masqué n'est appliqué que si le JavaScript s'exécute réellement :
   sans lui, ou s'il échoue, le contenu reste visible. Une animation ne doit
   jamais pouvoir faire disparaître de l'information (§97, §81).
   ------------------------------------------------------------------ */

.js .reveal {
  opacity: 0;
  transform: translate3d(var(--reveal-x, 0), var(--reveal-y, 16px), 0)
             scale(var(--reveal-scale, 1));
  transition: opacity var(--duration-reveal) var(--ease-entrance) var(--reveal-delay, 0ms),
              transform var(--duration-reveal) var(--ease-entrance) var(--reveal-delay, 0ms);
}

.js .reveal.is-visible { opacity: 1; transform: none; }

/* Rang dans la série, posé par le script sur chaque élément d'un groupe.
   Il est plafonné à la source : sans borne, le dernier élément d'une longue
   liste attendrait plusieurs secondes avant d'apparaître. */
.js .reveal {
  --reveal-index: 0;
  --reveal-delay: calc(var(--reveal-index) * var(--stagger));
}

/* Variantes : la direction sert le propos. Une colonne latérale entre par
   le côté, une carte de série grandit à peine, un texte monte. */
.js .reveal[data-reveal='left']  { --reveal-x: -20px; --reveal-y: 0; }
.js .reveal[data-reveal='right'] { --reveal-x: 20px;  --reveal-y: 0; }
.js .reveal[data-reveal='scale'] { --reveal-y: 10px;  --reveal-scale: 0.97; }
.js .reveal[data-reveal='fade']  { --reveal-y: 0; }

/* --- Curseur personnalisé (§68) ---------------------------------------
   Desktop et pointeur précis uniquement, désactivable, jamais sur mobile. */

.cursor-dot, .cursor-ring {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}

.cursor-dot { width: 5px; height: 5px; background: var(--primary); }

.cursor-ring {
  width: 30px; height: 30px;
  border: 1px solid var(--primary-line);
  transition: opacity var(--duration-base) var(--ease-out),
              width var(--duration-fast) var(--ease-out),
              height var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out);
}

body[data-cursor='on'][data-cursor-seen='true'] .cursor-dot,
body[data-cursor='on'][data-cursor-seen='true'] .cursor-ring { opacity: 1; }

body[data-cursor='on'] .cursor-ring[data-hover='true'] {
  width: 46px; height: 46px;
  border-color: var(--primary);
  background: var(--primary-soft);
}

@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cursor-dot, .cursor-ring { display: none !important; }
}

/* ---------------------------------------------------------------------
   8. Compositions de pages
   ------------------------------------------------------------------ */

/* --- Hero (§9) --------------------------------------------------------
   Composition en deux colonnes : identité et accès à gauche, objet 3D à
   droite. Pas de titre centré avec deux boutons. */

.hero {
  position: relative;
  padding-block: clamp(var(--space-7), 7vw, var(--space-10)) var(--space-9);
  overflow: hidden;
}

.hero__grid {
  display: grid;
  gap: clamp(var(--space-6), 5vw, var(--space-8));
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: center;
}

@media (max-width: 1080px) {
  .hero__grid { grid-template-columns: 1fr; }
}

.hero__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.3rem 0.75rem 0.3rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.hero__status .pulse {
  position: relative;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--success);
}

.hero__status .pulse::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid var(--success);
  opacity: 0;
  animation: pulse-ring 2.8s var(--ease-out) infinite;
}

@keyframes pulse-ring {
  0%   { opacity: 0.7; transform: scale(0.7); }
  70%  { opacity: 0;   transform: scale(1.5); }
  100% { opacity: 0;   transform: scale(1.5); }
}

.hero__name {
  margin-top: var(--space-4);
  font-size: var(--text-4xl);
  font-weight: 700;
  letter-spacing: -0.03em;
}

/* Identité en une ligne de faits, lisible d’un coup d’œil par le jury. */
.hero__facts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--text-muted);
}

.hero__facts .sep { width: 4px; height: 4px; border-radius: 50%; background: var(--border-strong); }
.hero__facts strong { color: var(--text); font-weight: 600; }

/* Identité en micro-faits étiquetés : le jury retrouve chaque information
   à sa place, et rien ne se casse en fin de ligne. */
.hero__identity {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-5);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.hero__identity div { display: grid; gap: 0.2rem; }

.hero__identity dt {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
}

.hero__identity dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
}

.hero__text { margin-top: var(--space-5); max-width: 60ch; color: var(--text-muted); }
.hero__text p + p { margin-top: var(--space-4); }

.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }

/* Scène 3D : ratio stable pour éviter tout décalage de mise en page. */
.hero__scene {
  position: relative;
  aspect-ratio: 1 / 1;
  max-height: 560px;
  border-radius: var(--radius-xl);
  overflow: hidden;
}

@media (max-width: 1080px) {
  .hero__scene { aspect-ratio: 4 / 3; max-height: 380px; }
}

.scene-canvas { width: 100%; height: 100%; display: block; }

/* Repli 2D : affiché tant que la 3D n’a pas démarré, et définitivement
   si WebGL est absent ou trop lent (§76). */
.scene-fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.scene-fallback svg { width: 100%; height: 100%; }
.hero__scene[data-mode='3d'] .scene-fallback { opacity: 0; pointer-events: none; }
.hero__scene[data-mode='2d'] .scene-canvas { display: none; }

/* --- Sections de la page unique ----------------------------------------
   Chaque section occupe une bande à part entière, séparée par une ligne et
   une alternance de fond : sur une page qui défile longtemps, c'est ce qui
   permet de savoir d'un coup d'œil qu'on a changé de sujet.
   ------------------------------------------------------------------ */

.section-block {
  padding-block: clamp(var(--space-8), 7vw, var(--space-10));
  position: relative;
  scroll-margin-top: var(--space-6);
}

.section-block + .section-block { border-top: 1px solid var(--border); }

.section-block--alt { background: color-mix(in srgb, var(--bg-elevated) 55%, transparent); }

/* La première bande occupe la hauteur de l'écran : le nom, le statut et les
   actions sont vus avant tout défilement. */
.section-block--hero {
  min-height: min(100vh, 900px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(var(--space-8), 8vw, var(--space-10));
}

.hero__headline {
  margin-top: var(--space-4);
  font-size: var(--text-lg);
  color: var(--text-muted);
  max-width: 46ch;
}

/* Invitation à faire défiler : discrète, et purement complémentaire —
   la page reste parfaitement utilisable si on ne la remarque pas. */
.scroll-hint {
  margin-top: clamp(var(--space-6), 5vw, var(--space-8));
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  align-self: flex-start;
  min-height: 44px;
  color: var(--text-subtle);
  text-decoration: none;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.scroll-hint:hover { color: var(--text); }
.scroll-hint svg { animation: scroll-nudge 2.4s var(--ease-out) infinite; }

@keyframes scroll-nudge {
  0%, 100% { transform: translateY(0); opacity: 0.7; }
  50%      { transform: translateY(4px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-hint svg { animation: none; }
}

/* --- Profil ------------------------------------------------------------ */

.profile-layout {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
  align-items: start;
}

@media (min-width: 900px) {
  .profile-layout { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
}

.profile-aside { display: grid; gap: var(--space-4); align-content: start; }

/* Fiche d'identité : des paires étiquette/valeur, pour que rien ne soit
   deviné à la lecture. */
.identity-grid {
  margin-top: var(--space-6);
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

.identity-grid dt {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

.identity-grid dd {
  margin: var(--space-2) 0 0;
  font-weight: 600;
  line-height: var(--leading-tight);
}

.identity-grid__sub {
  display: block;
  margin-top: 2px;
  font-weight: 500;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* Chiffres : uniquement du réel, jamais un compteur décoratif. */
.stat-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 130px), 1fr));
}

.stat {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1;
  color: var(--primary-on-soft);
}

.stat__label { font-size: var(--text-xs); color: var(--text-muted); }

.mission-list {
  list-style: none;
  padding: 0;
  margin-top: var(--space-4);
  display: grid;
  gap: var(--space-2);
}

.mission-list li {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.mission-list svg { color: var(--state-validated-fg); margin-top: 3px; }

/* Objectifs professionnels : où je vais, à côté d'où je viens. */
.profile-goals {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

.profile-goals__title {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-4);
}

.profile-goals ul { list-style: none; padding: 0; display: grid; gap: var(--space-4); }

.profile-goals li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: baseline;
}

.profile-goals__horizon {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--primary-on-soft);
  white-space: nowrap;
}

.profile-goals__label { font-weight: 600; font-size: var(--text-sm); }
.profile-goals__detail { margin-top: 2px; font-size: var(--text-sm); color: var(--text-muted); }

/* Domaines : ils portaient une description et une icône que rien
   n'affichait. Une rangée d'étiquettes muettes est devenue une liste qui
   dit quelque chose. */
.domain-list { list-style: none; padding: 0; margin-top: var(--space-3); display: grid; gap: var(--space-3); }

.domain-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

.domain-list svg { color: var(--primary-on-soft); margin-top: 3px; }
.domain-list__name { display: block; font-size: var(--text-sm); font-weight: 500; }
.domain-list__description { display: block; margin-top: 2px; font-size: var(--text-xs); color: var(--text-subtle); }

/* --- Parcours en deux colonnes ----------------------------------------- */

.parcours-columns {
  display: grid;
  gap: clamp(var(--space-6), 5vw, var(--space-8));
}

@media (min-width: 900px) {
  .parcours-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .parcours-columns--single { grid-template-columns: minmax(0, 1fr); }
}

.parcours-column__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-5);
}

.parcours-column__title svg { color: var(--primary); }

/* --- Alternance --------------------------------------------------------- */

.alternance-layout {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
  align-items: start;
}

@media (min-width: 900px) {
  .alternance-layout { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
}

.alternance-layout > * { min-width: 0; }
.alternance-aside { display: grid; gap: var(--space-4); align-content: start; min-width: 0; }

/* Poste, contrat, période : trois faits, étiquetés, sans phrase autour. */
.alternance-facts {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--border);
}

.alternance-facts dt {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

.alternance-facts dd {
  margin: var(--space-2) 0 0;
  font-weight: 600;
  line-height: var(--leading-tight);
}

.alternance-subtitle {
  margin-top: var(--space-5);
  font-size: var(--text-base);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

.mission-list--full li { align-items: flex-start; }

.mission-list__detail {
  display: block;
  margin-top: 2px;
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.alternance-org {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.alternance-org dt {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
}

.alternance-org dd { margin: var(--space-1) 0 0; font-size: var(--text-sm); }

.alternance-projects { list-style: none; padding: 0; margin-top: var(--space-3); display: grid; gap: var(--space-1); }

.alternance-projects a {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 32px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: var(--text-sm);
}

.alternance-projects a:hover { color: var(--primary-on-soft); }
.alternance-projects svg { color: var(--text-subtle); }

@media (pointer: coarse) {
  .alternance-projects a { min-height: 44px; }
}

/* --- Technologies ------------------------------------------------------ */

.tech-block { margin-top: clamp(var(--space-7), 6vw, var(--space-9)); }

.tech-block__title {
  font-size: var(--text-base);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-5);
}

.tech-category + .tech-category { margin-top: var(--space-6); }

.tech-category__name {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}

.tech-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 160px), 1fr));
}

.tech-card {
  display: grid;
  gap: 2px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.tech-card:hover { border-color: var(--primary-line); transform: translateY(-2px); }

.tech-card__name { font-weight: 600; font-size: var(--text-sm); }
.tech-card__usage { font-size: var(--text-2xs); color: var(--text-subtle); }

@media (prefers-reduced-motion: reduce) {
  .tech-card:hover { transform: none; }
}

/* --- Contact ------------------------------------------------------------
   Les coordonnées empruntaient le composant des documents téléchargeables :
   elles s'annonçaient donc comme des fichiers. Elles ont leurs propres
   composants, et le bloc se met sur une seule colonne quand le formulaire
   est désactivé — deux colonnes dont une vide laissaient un grand trou.
   ----------------------------------------------------------------------- */

.contact {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
  align-items: start;
}

@media (min-width: 900px) {
  .contact { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
  .contact--links-only { grid-template-columns: minmax(0, 1fr); max-width: var(--width-prose); }
}

.contact__col { display: grid; gap: var(--space-5); align-content: start; min-width: 0; }
.contact__intro { max-width: var(--width-prose); }

.contact-links {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.contact-link {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  transition: border-color var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}

.contact-link:hover,
.contact-link:focus-visible {
  border-color: var(--primary-line);
  background: var(--surface-hover);
  transform: translateY(-2px);
}

.contact-link__icon {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-md);
  background: var(--primary-soft);
  color: var(--primary);
}

.contact-link__body { display: grid; gap: 2px; min-width: 0; }

.contact-link__label { font-weight: 600; font-size: var(--text-sm); }

.contact-link__target {
  font-size: var(--text-sm);
  color: var(--text-muted);
  /* Une adresse longue ne doit pas élargir la colonne : elle se coupe. */
  overflow-wrap: anywhere;
}

.contact-link__note { font-size: var(--text-2xs); color: var(--text-subtle); }

.contact-link__arrow { color: var(--text-subtle); }
.contact-link:hover .contact-link__arrow { color: var(--primary); }

/* --- Lieux et carte -----------------------------------------------------
   Une adresse ne s'ouvre pas, on s'y rend : elle a sa propre carte, plus
   large qu'un lien, avec la carte en dessous. Le cadre de la carte garde
   sa place avant chargement, sinon la page saute au clic.
   ----------------------------------------------------------------------- */

.contact-place {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  min-width: 0;
}

.contact-place__head { display: flex; align-items: flex-start; gap: var(--space-4); }

.contact-place__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-md);
  background: var(--primary-soft);
  color: var(--primary);
}

.contact-place__label { font-size: var(--text-base); font-weight: 600; }

.contact-place__address {
  margin-top: 2px;
  font-size: var(--text-sm);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.contact-place__note { margin-top: 2px; font-size: var(--text-2xs); color: var(--text-subtle); }
.contact-place__actions { margin: 0; }

.contact-map {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
}

.contact-map iframe { display: block; width: 100%; height: 100%; border: 0; }

.contact-map__prompt {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--space-3);
  height: 100%;
  padding: var(--space-5);
  text-align: center;
  color: var(--text-subtle);
}

.contact-map__text {
  max-width: 46ch;
  font-size: var(--text-2xs);
  color: var(--text-muted);
}

@media (max-width: 520px) {
  .contact-map { aspect-ratio: 4 / 3; }
}

.contact-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.contact-note svg { flex: none; margin-top: 2px; color: var(--text-subtle); }

.contact-form {
  padding: clamp(var(--space-5), 3vw, var(--space-6));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  min-width: 0;
}

.contact-form__title { font-size: var(--text-lg); }
.contact-form__hint {
  margin-top: var(--space-2);
  margin-bottom: var(--space-4);
  font-size: var(--text-2xs);
  color: var(--text-subtle);
}

.contact-form__submit { margin-top: var(--space-4); }

@media (prefers-reduced-motion: reduce) {
  .contact-link:hover,
  .contact-link:focus-visible { transform: none; }
}

/* --- Chargement (§84) -------------------------------------------------- */

.loader {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: grid;
  place-items: center;
  background: var(--bg);
  transition: opacity var(--duration-slow) var(--ease-out),
              visibility var(--duration-slow);
}

/* Exception assumée à la règle générale sur [hidden] : l'écran de
   chargement doit rester peint le temps de son fondu, sans quoi il
   disparaîtrait d'un coup. Il ne bloque plus rien : visibility:hidden le
   rend inerte au clic comme au clavier. */
.loader[hidden] { opacity: 0; visibility: hidden; display: grid !important; }

.loader__name {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.loader__bar {
  width: 160px; height: 2px;
  margin-top: var(--space-4);
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}

.loader__bar span {
  display: block;
  width: 40%;
  height: 100%;
  background: linear-gradient(90deg, transparent, var(--primary), transparent);
  animation: loader-slide 1.1s var(--ease-in-out) infinite;
}

@keyframes loader-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* --- Domaines (§11) ---------------------------------------------------- */

.domain-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(230px, 100%), 1fr)); }

.domain {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.domain:hover { border-color: var(--border-strong); transform: translateY(-2px); }

.domain__dot {
  width: 6px; height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

/* --- Parcours (§14) ---------------------------------------------------- */

.timeline { position: relative; display: grid; gap: var(--space-5); }

/* Axe vertical continu, tracé derrière les repères. */
.timeline::before {
  content: '';
  position: absolute;
  left: 15px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--border-strong) 12%, var(--border-strong) 88%, transparent);
}

.timeline-entry {
  position: relative;
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.timeline-entry__marker {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 31px; height: 31px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--bg);
  color: var(--text-subtle);
  transition: border-color var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out);
}

.timeline-entry__marker svg { width: 15px; height: 15px; }

.timeline-entry:hover .timeline-entry__marker,
.timeline-entry[data-current='true'] .timeline-entry__marker {
  border-color: var(--primary);
  color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-soft);
}

.timeline-entry__card {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}

.timeline-entry:hover .timeline-entry__card { border-color: var(--border-strong); transform: translateX(3px); }

.timeline-entry__period {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--primary);
  letter-spacing: 0.02em;
}

.timeline-entry__title { margin-top: var(--space-2); font-size: var(--text-lg); }
.timeline-entry__org { margin-top: var(--space-1); color: var(--text-muted); font-size: var(--text-sm); }

/* Sur grand écran, l’axe passe au centre et les cartes alternent. */
@media (min-width: 1024px) {
  .timeline--alternating::before { left: 50%; }

  .timeline--alternating .timeline-entry {
    grid-template-columns: minmax(0, 1fr) 32px minmax(0, 1fr);
    gap: var(--space-5);
  }

  .timeline--alternating .timeline-entry:nth-child(odd) .timeline-entry__card { grid-column: 1; text-align: right; }
  .timeline--alternating .timeline-entry:nth-child(odd) .timeline-entry__marker { grid-column: 2; }
  .timeline--alternating .timeline-entry:nth-child(even) .timeline-entry__marker { grid-column: 2; }
  .timeline--alternating .timeline-entry:nth-child(even) .timeline-entry__card { grid-column: 3; }
  .timeline--alternating .timeline-entry:nth-child(odd):hover .timeline-entry__card { transform: translateX(-3px); }
}

/* --- Compétences (§70) ------------------------------------------------- */

.competency-grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }

.competency-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

.competency-card::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--state-none-fg);
  opacity: 0.5;
}

.competency-card[data-doc='documentee']::after      { background: var(--secondary); opacity: 1; }
.competency-card[data-doc='bien_documentee']::after { background: var(--success); opacity: 1; }

.competency-card:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}

.competency-card__code {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--primary);
}

.competency-card__title { font-size: var(--text-lg); }
.competency-card__title a { color: var(--text); text-decoration: none; }
.competency-card__title a::after { content: ''; position: absolute; inset: 0; }
.competency-card__title a:hover { color: var(--primary); }

.competency-card__meta {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

/* Liste des sous-compétences */
.sub-list { list-style: none; padding: 0; display: grid; gap: var(--space-2); }

.sub-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-2);
  font-size: var(--text-sm);
}

.sub-list__code {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-subtle);
  padding-top: 0.15rem;
}

/* Lien de retour : au doigt, un lien de 17 px de haut est intouchable. On lui
   donne 44 px de zone active partout, la marge négative évitant qu'il pousse
   le contenu qui suit. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  margin-block: calc(var(--space-3) * -1);
  color: var(--text-muted);
  text-decoration: none;
}
.back-link:hover { color: var(--text); }

/* --- Matrice compétences × réalisations (§36) --------------------------- */

.matrix-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

/* Indice de défilement : sur téléphone, la matrice dépasse largement de
   l'écran et rien ne le laissait deviner. Le dégradé de droite est attaché
   au contenu (background-attachment: local), il disparaît donc de lui-même
   une fois la fin du tableau atteinte. */
@media (max-width: 900px) {
  .matrix-wrap {
    background-image: linear-gradient(to left, var(--surface), color-mix(in srgb, var(--surface) 0%, transparent));
    background-repeat: no-repeat;
    background-size: 36px 100%;
    background-position: right center;
    background-attachment: local;
  }
}

.matrix { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 720px; font-size: var(--text-sm); }

.matrix th, .matrix td { padding: var(--space-3); border-bottom: 1px solid var(--border); text-align: center; }

.matrix thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Première colonne figée : le titre reste lisible pendant le défilement. */
.matrix th[scope='row'] {
  position: sticky;
  left: 0;
  z-index: 1;
  min-width: 240px;
  max-width: 340px;
  background: var(--surface);
  text-align: left;
  font-weight: 500;
  border-right: 1px solid var(--border);
}

.matrix tbody tr:hover th[scope='row'],
.matrix tbody tr:hover td { background: var(--surface-hover); }

.matrix-cell {
  display: inline-grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  cursor: default;
  color: var(--state-none-fg);
}

.matrix-cell[data-state='non_associee'] { color: var(--text-subtle); opacity: 0.35; }
.matrix-cell[data-state='proposition']  { background: var(--state-proposed-bg);  color: var(--state-proposed-fg);  border-color: color-mix(in srgb, var(--state-proposed-fg) 30%, transparent); cursor: pointer; }
.matrix-cell[data-state='validee']      { background: var(--state-validated-bg); color: var(--state-validated-fg); border-color: color-mix(in srgb, var(--state-validated-fg) 32%, transparent); cursor: pointer; }

.matrix-cell svg { width: 15px; height: 15px; }
.matrix-cell:hover { transform: scale(1.1); }

/* La colonne figée mangeait 240 px sur les 342 disponibles en 375 px de
   large : il ne restait presque rien pour les cases. */
@media (max-width: 900px) {
  .matrix th[scope='row'] { min-width: 150px; max-width: 190px; }
  .matrix th, .matrix td { padding: var(--space-2); }
}

/* Un lien de cellule ne faisait que 17 px de haut, sous le minimum de 24 px
   du WCAG 2.2. Au doigt on va plus loin : le tableau défile déjà
   horizontalement, l'élargir ne coûte rien. */
.matrix th[scope='row'] a,
.table th a,
.table td a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
}

@media (pointer: coarse) {
  .matrix-cell { width: 40px; height: 40px; }
  .matrix th[scope='row'] a,
  .table th a,
  .table td a { min-height: 40px; }
}

/* --- Étude de cas (§31) ------------------------------------------------
   Colonne de lecture + colonne latérale de faits, pour éviter le pavé. */

.case-layout {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-8));
  grid-template-columns: minmax(0, 1fr) 300px;
  align-items: start;
}

/* Un élément de grille refuse par défaut de descendre sous la largeur
   minimale de son contenu : le tableau des tests étirait donc toute la
   colonne, et la page débordait sous 640 px. Le tableau défile déjà dans
   son propre conteneur — c'est la colonne qui devait céder. */
.case-layout > * { min-width: 0; }

@media (max-width: 1024px) {
  .case-layout { grid-template-columns: 1fr; }
  .case-aside { position: static !important; order: -1; }
}

.case-aside {
  position: sticky;
  top: calc(var(--header-height) + var(--space-5));
  display: grid;
  gap: var(--space-4);
  /* Sans cela, les éléments d'une grille refusent de descendre sous leur
     largeur minimale de contenu : une seule valeur non sécable suffisait à
     étirer la colonne bien au-delà de sa piste de 300 px. */
  min-width: 0;
}

.case-aside > * { min-width: 0; }

.fact-list { display: grid; gap: var(--space-3); }

.fact {
  display: grid;
  gap: 0.15rem;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.fact:last-child { border-bottom: 0; padding-bottom: 0; }

.fact__label {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
}

.fact__value { font-size: var(--text-sm); font-weight: 500; }

.case-section { padding-block: var(--space-6); border-top: 1px solid var(--border); }
.case-section:first-of-type { border-top: 0; padding-top: 0; }
.case-section > h2 { margin-bottom: var(--space-4); font-size: var(--text-xl); }

/* Contribution personnelle : la section que le jury cherche en premier,
   elle est visuellement distinguée du reste (§30). */
.personal-role {
  padding: var(--space-5);
  border: 1px solid var(--primary-line);
  border-radius: var(--radius-lg);
  background: var(--primary-soft);
}

.personal-role h2 { font-size: var(--text-lg); margin-bottom: var(--space-3); }

/* Étapes numérotées */
.steps { list-style: none; padding: 0; counter-reset: step; display: grid; gap: var(--space-3); }

.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  display: grid;
  place-items: center;
  width: 29px; height: 29px;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  color: var(--primary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
}

/* Difficulté : problème → analyse → solution → résultat */
.difficulty {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.difficulty__row { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: var(--space-4); }
.difficulty__row + .difficulty__row { padding-top: var(--space-3); border-top: 1px solid var(--border); }

.difficulty__key {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
  padding-top: 0.2rem;
}

@media (max-width: 640px) {
  .difficulty__row { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* Bloc technique : commande, extrait de configuration, procédure */
.code-block {
  position: relative;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  overflow-x: auto;
}

.code-block pre { margin: 0; font-size: var(--text-xs); line-height: 1.7; color: var(--text-muted); }
.code-block__label {
  display: block;
  margin-bottom: var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
}

/* --- Preuves (§32) ----------------------------------------------------- */

.evidence-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); }

.evidence {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color var(--duration-fast) var(--ease-out);
}

.evidence:hover { border-color: var(--border-strong); }
.evidence__type { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-2xs); color: var(--text-subtle); }
.evidence__type svg { width: 14px; height: 14px; }
.evidence__title { font-size: var(--text-sm); font-weight: 600; }

/* --- Technologies (§69) ------------------------------------------------
   Constellation : chaque outil est un nœud, la taille reflète le nombre
   de réalisations qui l’emploient réellement. */

.constellation {
  position: relative;
  display: grid;
  gap: var(--space-5);
}

.tech-group { display: grid; gap: var(--space-3); }

.tech-group__head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}

.tech-group__head h3 { font-size: var(--text-base); }
.tech-group__count { font-size: var(--text-xs); color: var(--text-subtle); }

.tech-nodes { display: flex; flex-wrap: wrap; gap: var(--space-3); }

.tech-node {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--surface);
  font-size: var(--text-sm);
  font-weight: 500;
  transition: all var(--duration-base) var(--ease-out);
}

.tech-node:hover {
  border-color: var(--primary-line);
  background: var(--primary-soft);
  transform: translateY(-2px);
}

.tech-node__usage {
  display: grid;
  place-items: center;
  min-width: 20px; height: 20px;
  padding-inline: 0.3rem;
  border-radius: var(--radius-full);
  background: var(--surface-3);
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--text-subtle);
}

.tech-node[data-usage='0'] { opacity: 0.62; }
.tech-node[data-usage='0'] .tech-node__usage { display: none; }

/* --- Veille technologique (§38) -----------------------------------------

   La page empruntait les composants de l'étude de cas — colonne collante,
   fiche de faits — qui ne racontent pas la même chose. C'est aussi ce qui
   avait produit une colonne large de 1 400 px dans une piste de 300 : une
   structure faite pour un autre contenu finit toujours par céder.
   ------------------------------------------------------------------ */

.section-block--tight { padding-block: clamp(var(--space-7), 5vw, var(--space-8)); }

.watch-subject {
  margin-top: var(--space-3);
  font-size: clamp(var(--text-2xl), 4vw, var(--text-4xl));
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  max-width: 22ch;
}

.watch-problematic {
  margin-top: var(--space-5);
  max-width: var(--width-prose);
  font-size: var(--text-lg);
  color: var(--text-muted);
}

/* Chiffres de la veille : la valeur d'abord, l'étiquette dessous. */
.watch-figures {
  margin-top: clamp(var(--space-6), 5vw, var(--space-8));
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}

.watch-figures > * { min-width: 0; }

.watch-figures dt {
  order: 2;
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.watch-figures dd {
  order: 1;
  margin: 0 0 var(--space-1);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: 1;
  color: var(--primary-on-soft);
}

.watch-figures > div { display: flex; flex-direction: column; }

/* --- Méthode ----------------------------------------------------------- */

.watch-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--space-4);
  max-width: var(--width-prose);
}

.watch-step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.watch-step__number {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  border: 1px solid var(--primary-line);
  background: var(--primary-soft);
  color: var(--primary-on-soft);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
}

.watch-step p { color: var(--text-muted); padding-top: 4px; }

.watch-practice {
  margin-top: clamp(var(--space-6), 5vw, var(--space-7));
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

.watch-practice > * { min-width: 0; }
.watch-practice__value { margin-top: var(--space-2); font-weight: 600; }

/* --- Sources ------------------------------------------------------------ */

.watch-source-group + .watch-source-group { margin-top: var(--space-7); }

.watch-source-group__title {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-4);
}

.watch-source-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr));
}

.watch-source {
  position: relative;
  min-width: 0;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--duration-fast) var(--ease-out);
}

.watch-source:hover,
.watch-source:focus-within { border-color: var(--primary-line); }

.watch-source__name { font-size: var(--text-base); line-height: var(--leading-tight); }
.watch-source__name a { color: var(--text); text-decoration: none; }
.watch-source__name a:hover { color: var(--primary-on-soft); }

/* Le lien couvre toute la carte : un titre de 20 px de haut est sous le
   minimum de 24 px du WCAG 2.2, et viser un titre plutôt qu'une carte n'a
   de toute façon aucun sens pour qui lit au doigt. */
.watch-source__name a::after { content: ''; position: absolute; inset: 0; }

.watch-source__description {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.watch-source__count {
  margin-top: var(--space-3);
  font-size: var(--text-2xs);
  color: var(--text-subtle);
  font-family: var(--font-mono);
}

/* --- Articles ----------------------------------------------------------- */

.watch-articles { display: grid; gap: var(--space-5); }
.watch-articles > * { min-width: 0; }

.watch-article {
  padding: clamp(var(--space-4), 3vw, var(--space-6));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.watch-article__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: baseline;
  justify-content: space-between;
}

.watch-article__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.watch-article__source { font-weight: 600; color: var(--text-muted); }

/* L'intérêt n'est pas porté par la seule couleur : le mot est écrit (§81). */
.watch-interest {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--text-subtle);
  white-space: nowrap;
}

.watch-interest[data-interest='fort'] {
  color: var(--state-validated-fg);
  background: var(--state-validated-bg);
  border-color: color-mix(in srgb, var(--state-validated-fg) 32%, transparent);
}

.watch-interest[data-interest='moyen'] {
  color: var(--state-proposed-fg);
  background: var(--state-proposed-bg);
  border-color: color-mix(in srgb, var(--state-proposed-fg) 30%, transparent);
}

.watch-article__title {
  margin-top: var(--space-3);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
}

.watch-article__title a { color: var(--text); text-decoration: none; }
.watch-article__title a:hover { color: var(--primary-on-soft); }

.watch-article__summary { margin-top: var(--space-3); color: var(--text-muted); }

/* L'analyse personnelle est ce que le jury vient chercher : elle se
   distingue du résumé, qui n'est qu'un rappel de la source. */
.watch-analysis {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border-left: 2px solid var(--primary-line);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  background: var(--surface-2);
}

.watch-analysis__label {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: var(--space-2);
}

.watch-article__tags { margin-top: var(--space-4); }

/* --- Bilan -------------------------------------------------------------- */

.watch-bilan {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
  align-items: start;
}

@media (min-width: 900px) {
  .watch-bilan { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}

.watch-bilan > * { min-width: 0; }

.watch-conclusion {
  padding: var(--space-5);
  border: 1px solid var(--primary-line);
  border-radius: var(--radius-lg);
  background: var(--primary-soft);
}

/* --- Mode jury (§43, §46) ----------------------------------------------
   Navigation séquentielle, plein écran possible, texte agrandi pour la
   projection, animations réduites au strict nécessaire. */

.jury {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

.jury__bar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.jury__progress { display: flex; gap: 4px; flex: 1; min-width: 0; }

/* Le repère reste un trait de 4 px, mais la zone cliquable fait 24 px de
   haut : le fond est peint sur la boîte de contenu seulement, et la marge
   négative annule la hauteur ajoutée pour ne rien décaler dans la barre. */
.jury__progress button {
  flex: 1;
  height: 4px;
  min-width: 12px;
  box-sizing: content-box;
  padding-block: 10px;
  margin-block: -10px;
  padding-inline: 0;
  border: 0;
  border-radius: 2px;
  background: var(--border);
  background-clip: content-box;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}

.jury__progress button:hover { background: var(--border-strong); }
.jury__progress button[aria-current='true'] { background: var(--primary); }
.jury__progress button[data-seen='true'] { background: var(--primary-line); }

/* Cible tactile : le retour au portfolio n'est qu'un monogramme de 28 px. */
@media (pointer: coarse) {
  .jury__bar .brand { min-height: 44px; min-width: 44px; justify-content: center; }
}

.jury__counter {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-subtle);
  white-space: nowrap;
}

.jury__slides { flex: 1; display: grid; }

.jury__slide {
  grid-area: 1 / 1;
  display: none;
  padding-block: clamp(var(--space-6), 5vw, var(--space-9));
  animation: slide-in var(--duration-base) var(--ease-out);
}

.jury__slide[data-active='true'] { display: block; }

@keyframes slide-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.jury__slide h1 { font-size: var(--text-3xl); }
.jury__slide h2 { font-size: var(--text-2xl); }

.jury__nav {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.jury__hint {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

kbd {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  padding: 0.1rem 0.35rem;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-muted);
}

@media (max-width: 720px) {
  .jury__hint { display: none; }
}

/* En projection, on agrandit tout d’un cran (§79). */
:root[data-display='projector'] .jury__slide h1 { font-size: clamp(2.6rem, 4vw, 4rem); }
:root[data-display='projector'] .jury__slide { font-size: 1.2rem; }
:root[data-display='projector'] .jury__slide .prose p { font-size: 1.15rem; }

/* --- Tableau de synthèse (§37) ------------------------------------------ */

.synthesis-header {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

/* Un avertissement explicite : la version interactive ne remplace pas le
   document officiel (§37). */
.notice-official {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--warning);
  border-radius: var(--radius-lg);
  background: var(--warning-bg);
  font-size: var(--text-sm);
}

.notice-official svg { width: 19px; height: 19px; flex: none; color: var(--warning); }

/* --- Veille (§38) -------------------------------------------------------- */

.article {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}

.article:hover { border-color: var(--border-strong); transform: translateY(-2px); }

.article__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.article__analysis {
  padding: var(--space-4);
  border-left: 2px solid var(--primary-line);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  background: var(--surface-2);
  font-size: var(--text-sm);
}

.article__analysis strong { display: block; margin-bottom: var(--space-2); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--text-subtle); }

/* --- Documents (§42) ----------------------------------------------------- */

/* --- Bibliothèque de documents (§42) ------------------------------------
   La page empruntait le composant .document, celui d'une simple ligne de
   lien. Une bibliothèque se parcourt : elle a besoin de familles lisibles,
   du format annoncé avant le clic, et de ses deux pièces maîtresses mises
   en avant. Le composant .document reste, il sert ailleurs.
   ----------------------------------------------------------------------- */

.doc-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.doc-figures__label {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
}

.doc-figures__value {
  margin: 2px 0 0;
  font-size: var(--text-lg);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.doc-featured { display: grid; gap: var(--space-4); }

@media (min-width: 860px) {
  .doc-featured { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
}

.doc-highlight {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  padding: clamp(var(--space-4), 3vw, var(--space-5));
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}

.doc-highlight:hover,
.doc-highlight:focus-visible {
  border-color: var(--primary-line);
  background: var(--surface-hover);
  transform: translateY(-2px);
  color: inherit;
}

.doc-highlight__icon {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-md);
  background: var(--primary-soft);
  color: var(--primary);
}

.doc-highlight__body { display: grid; gap: var(--space-2); min-width: 0; }

.doc-highlight__kind {
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-subtle);
}

.doc-highlight__title { font-size: var(--text-base); font-weight: 600; }
.doc-highlight__hint { font-size: var(--text-sm); color: var(--text-muted); }

.doc-highlight__action {
  grid-column: 2;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--primary);
}

.doc-group__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.doc-group__title {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-lg);
}

.doc-group__title svg { color: var(--text-subtle); flex: none; }

.doc-group__count {
  padding: 0 var(--space-3);
  border-radius: var(--radius-full);
  background: var(--surface-3);
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-muted);
}

.doc-group__hint {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-muted);
  max-width: var(--width-prose);
}

.doc-list {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  /* auto-fit et non auto-fill : une famille qui ne contient qu'une pièce
     l'affiche en pleine largeur au lieu de la coincer dans un tiers de
     colonne, le reste de la ligne restant vide. */
  .doc-list { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
}

.doc-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--space-4);
  height: 100%;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out);
}

.doc-card:hover,
.doc-card:focus-visible {
  border-color: var(--primary-line);
  background: var(--surface-hover);
  color: inherit;
}

/* Le format tient lieu de vignette : il annonce ce qui va s'ouvrir. */
.doc-card__format {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-md);
  background: var(--surface-3);
  color: var(--text-muted);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.doc-card:hover .doc-card__format { color: var(--primary); }

.doc-card__body { display: grid; gap: var(--space-2); min-width: 0; }
.doc-card__title { font-size: var(--text-sm); font-weight: 600; }
.doc-card__description { font-size: var(--text-xs); color: var(--text-muted); }
.doc-card__action {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--text-subtle);
  white-space: nowrap;
}

.doc-card:hover .doc-card__action,
.doc-card:focus-visible .doc-card__action { color: var(--primary); }

/* Sur téléphone, trois colonnes écrasent le titre en une colonne de deux
   mots et rognent la vignette. La carte se replie : format et action sur
   une ligne, le texte en dessous, sur toute la largeur. */
@media (max-width: 560px) {
  .doc-card {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      'format action'
      'body   body';
    row-gap: var(--space-3);
  }

  .doc-card__format { grid-area: format; }
  .doc-card__body   { grid-area: body; }
  .doc-card__action { grid-area: action; justify-self: end; align-self: center; }
}

.doc-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.doc-chip {
  padding: 1px var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--text-2xs);
  color: var(--text-subtle);
  white-space: nowrap;
}

.doc-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-muted);
  max-width: var(--width-prose);
}

.doc-note svg { flex: none; margin-top: 2px; color: var(--text-subtle); }

@media (prefers-reduced-motion: reduce) {
  .doc-highlight:hover,
  .doc-highlight:focus-visible { transform: none; }
}

.document {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.document:hover { border-color: var(--primary-line); transform: translateX(3px); color: inherit; }

.document__icon {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  flex: none;
  border-radius: var(--radius-md);
  background: var(--surface-3);
  color: var(--primary);
}

.document__icon svg { width: 20px; height: 20px; }
.document__body { flex: 1; min-width: 0; }
.document__title { font-size: var(--text-sm); font-weight: 600; }
.document__meta { font-size: var(--text-xs); color: var(--text-subtle); }

/* --- Recherche (§53) ------------------------------------------------------ */

.search-form { display: flex; gap: var(--space-3); }
.search-form .input { flex: 1; }

.search-result {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.search-result:last-child { border-bottom: 0; }
.search-result__kind { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--text-subtle); }
.search-result h3 { font-size: var(--text-base); }
.search-result h3 a { color: var(--text); text-decoration: none; }
.search-result h3 a:hover { color: var(--primary); }

mark { background: var(--primary-soft); color: var(--text); padding: 0 0.15em; border-radius: 2px; }

/* --- Page 404 (§94) -------------------------------------------------------- */

.error-page {
  min-height: 68vh;
  display: grid;
  place-items: center;
  text-align: center;
}

.error-page__code {
  font-family: var(--font-display);
  font-size: clamp(4rem, 14vw, 8rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.05em;
  background: linear-gradient(140deg, var(--primary), var(--secondary));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- Utilitaires ----------------------------------------------------------- */

.divider { height: 1px; background: var(--border); border: 0; }
.mt-0 { margin-top: 0 !important; }
.no-print { }

/* Un conteneur défilable est atteignable au clavier : son focus doit donc
   être visible, comme celui de n'importe quel élément interactif (§81). */
[role='region'][tabindex='0']:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}
