/* =========================================================================
   PORTFOLIO — Hugo Colicchia, Designer UI
   Direction : « le portfolio est une interface »

   Le site n'est pas une affiche, c'est un produit : barre de navigation
   persistante, contenu en panneaux, système d'espacement strict, une seule
   couleur réservée à l'interaction. La compétence UI se démontre par la
   forme du site plutôt qu'elle ne se raconte dans le texte.

   Sommaire
     01. Variables
     02. Base
     03. Typographie
     04. Layout — la coque applicative
     05. Composants
     06. Utilitaires
     07. Media queries

   Deux règles tenues partout dans ce fichier
     - Une famille pour la lecture, une pour la donnée. Si c'est une phrase,
       c'est en sans ; si c'est un identifiant, une mesure ou un sélecteur,
       c'est en mono. Aucune exception.
     - Une seule couleur de marque, et elle ne sert qu'à l'interaction :
       liens, boutons, entrée active du menu, anneau de focus. Jamais de
       décoration colorée.

   Unités
     Les px ne servent qu'aux ombres portées. Bordures et filets sont en rem
     pour rester solidaires du zoom texte.
   ========================================================================= */


/* =========================================================================
   01. VARIABLES
   ========================================================================= */

:root {
  /* Le navigateur teinte ses propres widgets — barre de défilement, champs
     natifs, menus déroulants — selon le thème actif. */
  color-scheme: light dark;

  /* --- Échelle de neutres, teinte 165° -----------------------------------
     Des gris légèrement verts, pas des gris bleus. C'est un choix, pas un
     défaut : la teinte 240° est celle que servent toutes les échelles
     livrées avec les frameworks, et elle se reconnaît au premier coup
     d'œil. Ici la teinte est tenue sur toute l'échelle, du papier à
     l'encre.                                                          */
  --n-0: #FFFFFF;
  --n-25: #F8FAF9;
  --n-50: #F1F5F3;
  --n-100: #E3EAE6;
  --n-200: #CBD6D0;
  --n-300: #A8B8B0;
  --n-450: #789185;
  --n-400: #7A8B83;
  --n-500: #4C5B54;
  --n-900: #141C18;
  --n-950: #0D1310;

  /* --- Couleur de marque : un cuivre, et rien d'autre --------------------
     Chaque valeur est calée pour rester lisible sur les trois fonds clairs
     du site — 5,61:1 sur blanc, 5,10:1 sur le fond de page, 4,59:1 sur la
     surface sourde. Un lien reste donc conforme où qu'il tombe.        */
  --brand-500: #A05318;
  --brand-600: #884511;
  --brand-300: #DC7418;

  /* --- Neutres sombres, même teinte 165° --------------------------------- */
  --d-bg: #0D1310;
  --d-surface: #151E19;
  --d-surface-2: #1F2B24;
  --d-border: #2A3830;
  --d-border-strong: #3B4C42;
  --d-border-control: #556D67;
  --d-text: #E8EFEA;
  --d-text-muted: #9AAAA1;
  --d-text-faint: #6E7D75;

  /* --- Rôles : thème clair ---------------------------------------------- */
  --bg: var(--n-50);
  --surface: var(--n-0);
  --surface-2: var(--n-100);
  --surface-sunken: var(--n-25);
  --border: var(--n-200);
  --border-strong: var(--n-300);
  /* Limite d'un composant interactif — bouton fantôme, champ, bascule du
     menu. WCAG 1.4.11 exige 3:1 : c'est ce que --border-strong ne fournit
     pas, et c'est pourquoi ce rôle existe séparément. */
  --border-control: var(--n-450);
  --text: var(--n-900);
  --text-muted: var(--n-500);
  --text-faint: var(--n-400);
  --accent: var(--brand-500);
  --accent-hover: var(--brand-600);
  --accent-contrast: var(--n-0);
  --focus: var(--brand-500);

  /* --- Typographie ------------------------------------------------------- */
  --font-ui: "Roboto", system-ui, "Segoe UI", Arial, sans-serif;
  --font-data: "DM Mono", Consolas, monospace;

  --w-regular: 400;
  --w-medium: 500;
  --w-semi: 600;
  --w-bold: 700;

  --text-2xs: 0.6875rem;
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-md: 1rem;
  --text-lg: 1.125rem;
  --text-xl: clamp(1.25rem, 1.12rem + 0.6vw, 1.5rem);
  --text-2xl: clamp(1.5rem, 1.28rem + 1vw, 2rem);
  --text-3xl: clamp(1.75rem, 1.4rem + 1.8vw, 2.5rem);
  --text-4xl: clamp(2.125rem, 1.6rem + 2.6vw, 3.25rem);

  --leading-tight: 1.12;
  --leading-snug: 1.3;
  --leading-normal: 1.6;
  --leading-loose: 1.72;

  --tracking-tight: -0.018em;
  --tracking-label: 0.08em;

  --measure: 66ch;
  --prose-max: 52rem;

  /* --- Espacement, base 0.25rem ------------------------------------------ */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;

  --space-section: clamp(3rem, 2rem + 4.5vw, var(--space-20));
  --space-gutter: clamp(1.25rem, 0.7rem + 2.2vw, 2.5rem);

  /* --- Structure ---------------------------------------------------------- */
  --content-max: 74rem;

  /* --- Rayons -------------------------------------------------------------
     Un rayon discret et constant sur les panneaux et les contrôles. La
     pastille pleine est réservée aux étiquettes, qui ne sont pas cliquables
     et ne doivent jamais être prises pour des boutons.                 */
  --radius-sm: 0.375rem;
  --radius-md: 0.625rem;
  --radius-full: 62.5rem;

  /* --- Filets et ombres ---------------------------------------------------- */
  --line: 0.0625rem;
  --line-thick: 0.125rem;
  --shadow-md: 0 2px 4px rgba(18, 18, 20, 0.05), 0 10px 28px rgba(18, 18, 20, 0.07);

  /* --- Mouvement -----------------------------------------------------------
     Durées, décalage au survol et échelle de zoom passent tous par ces
     variables : la section 07 les neutralise d'un bloc pour le réglage
     système de mouvement réduit, sans une seule déclaration forcée.  */
  --dur-1: 120ms;
  --dur-2: 200ms;
  --dur-3: 320ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);
  --lift: -0.125rem;
  --zoom: 1.03;
}


/* =========================================================================
   02. BASE
   ========================================================================= */

html {
  scroll-behavior: smooth;
}

body {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--text-md);
  font-weight: var(--w-regular);
  line-height: var(--leading-normal);
  overflow-wrap: break-word;
}

/* La barre de navigation est collante : les ancres doivent se poser en
   dessous d'elle, pas derrière. */
:target {
  scroll-margin-top: 5rem;
}

a {
  color: var(--accent);
}

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

/* L'anneau de focus n'est jamais supprimé, seulement renforcé. */
:focus-visible {
  outline: var(--line-thick) solid var(--focus);
  outline-offset: 0.1875rem;
  border-radius: var(--radius-sm);
}

::selection {
  background-color: var(--accent);
  color: var(--accent-contrast);
}


/* =========================================================================
   03. TYPOGRAPHIE
   ========================================================================= */

h1,
h2,
h3,
h4 {
  color: var(--text);
  font-weight: var(--w-semi);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}

h2 {
  font-size: var(--text-2xl);
}

h3 {
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
}

h4 {
  font-size: var(--text-md);
  line-height: var(--leading-snug);
}

p {
  max-width: var(--measure);
}

strong {
  font-weight: var(--w-semi);
}

/* Toute donnée passe en chasse fixe : identifiants, mesures, sélecteurs. */
code {
  font-family: var(--font-data);
  font-size: 0.9em;
  font-variant-numeric: tabular-nums;
}

code {
  padding: 0.1em 0.3em;
  background-color: var(--surface-2);
  border-radius: var(--radius-sm);
  color: var(--text);
}

/* =========================================================================
   04. LAYOUT
   ========================================================================= */

/* Le contenu occupe la place laissée par la barre et le pied : c'est lui qui
   pousse le pied de page en bas, même sur une page courte. */
main {
  flex: 1 1 auto;
  min-width: 0;
}

.shell {
  width: 100%;
  max-width: var(--content-max);
  margin-right: auto;
  margin-left: auto;
  padding-right: var(--space-gutter);
  padding-left: var(--space-gutter);
}

.band {
  padding-top: var(--space-section);
  padding-bottom: var(--space-section);
  border-top: var(--line) solid var(--border);
}

.band__title {
  margin-bottom: var(--space-3);
}

.band__intro {
  max-width: var(--measure);
  margin-bottom: var(--space-8);
  color: var(--text-muted);
}


/* =========================================================================
   05. COMPOSANTS
   ========================================================================= */

/* --- 5.1 Lien d'évitement -------------------------------------------------- */

.skip {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  background-color: var(--text);
  border-radius: var(--radius-sm);
  color: var(--bg);
  font-size: var(--text-sm);
  font-weight: var(--w-semi);
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--dur-2) var(--ease);
}

.skip:focus-visible {
  color: var(--bg);
  transform: translateY(0);
}


/* --- 5.2 La marque : monogramme H manuscrit ---------------------------------
   Un H tracé à la plume : deux montants inclinés et bombés, une traverse qui
   monte de gauche à droite, terminaisons arrondies. Le contraste plein/délié
   vient de deux épaisseurs de trait, 3.5 pour les montants, 2.2 pour la
   traverse. Le tracé est un SVG posé dans le HTML : aucune requête, net à
   tous les zooms, et la couleur suit currentColor donc les variables de rôle.

   Une courbe ne se dessine pas avec des dégradés linéaires : c'est ce qui a
   fait abandonner la version précédente, entièrement en CSS.           */

.mark {
  display: block;
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  background-color: var(--accent);
  border-radius: var(--radius-sm);
  color: var(--accent-contrast);
}

.mark__glyph {
  width: 100%;
  height: 100%;
}


/* --- 5.3 Barre de navigation ------------------------------------------------
   Collante en haut à toutes les largeurs. En dessous de 64rem, les entrées se
   replient derrière une bascule : une case à cocher masquée, un libellé qui
   sert de bouton, et des sélecteurs frères. Aucun JavaScript — la technique
   même que je documente dans les trois études de cas.
   L'ordre case à cocher, puis libellé, puis navigation est donc imposé : les
   sélecteurs frères du CSS ne regardent qu'en avant.                     */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background-color: var(--surface);
  border-bottom: var(--line) solid var(--border);
}

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

/* La case reste focusable au clavier : elle est masquée à l'oeil, jamais
   retirée du document. */
.nav-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.burger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-4);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease);
}

.burger:hover {
  border-color: var(--text);
}

/* L'anneau de focus se pose sur le libellé : c'est lui qu'on voit. */
.nav-toggle:focus-visible + .burger {
  outline: var(--line-thick) solid var(--focus);
  outline-offset: 0.1875rem;
}

/* Les trois traits, dessinés en CSS. */
.burger__bars {
  position: relative;
  display: block;
  width: 1rem;
  height: var(--line-thick);
  background-color: var(--text);
}

.burger__bars::before,
.burger__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--line-thick);
  background-color: var(--text);
  transition:
    top var(--dur-2) var(--ease),
    transform var(--dur-2) var(--ease);
}

.burger__bars::before {
  top: -0.3125rem;
}

.burger__bars::after {
  top: 0.3125rem;
}

/* Ouverts, les trois traits deviennent une croix. */
.nav-toggle:checked + .burger .burger__bars {
  background-color: transparent;
}

.nav-toggle:checked + .burger .burger__bars::before,
.nav-toggle:checked + .burger .burger__bars::after {
  top: 0;
}

.nav-toggle:checked + .burger .burger__bars::before {
  transform: rotate(45deg);
}

.nav-toggle:checked + .burger .burger__bars::after {
  transform: rotate(-45deg);
}

/* Repliées par défaut, dépliées par la bascule. */
.nav,
.avail {
  display: none;
  flex-basis: 100%;
}

.nav-toggle:checked ~ .nav {
  display: block;
}

.nav-toggle:checked ~ .avail {
  display: flex;
}

.ident {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
}

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

.ident__name {
  color: var(--text);
  font-size: var(--text-md);
  font-weight: var(--w-semi);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
}

.ident__role {
  color: var(--text-muted);
  font-size: var(--text-xs);
  line-height: var(--leading-snug);
}

.ident:hover .ident__name {
  color: var(--accent);
}

.menu {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}

/* display: flex et non inline-flex — en colonne, l'entrée occupe toute la
   largeur de la liste : la cible tactile suit le doigt, pas le texte. */
.menu__link {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
  text-decoration: none;
  transition:
    background-color var(--dur-1) var(--ease),
    color var(--dur-1) var(--ease);
}

.menu__link:hover {
  background-color: var(--surface-2);
  color: var(--text);
}

/* L'entrée courante est signalée par trois indices simultanés : un fond, une
   graisse et un repère plein. Jamais par la couleur seule. */
.menu__link[aria-current] {
  background-color: var(--surface-2);
  color: var(--text);
  font-weight: var(--w-semi);
}

.menu__link[aria-current]::before {
  content: "";
  position: absolute;
  right: var(--space-3);
  bottom: 0.3125rem;
  left: var(--space-3);
  height: var(--line-thick);
  background-color: var(--accent);
  border-radius: var(--radius-full);
}

/* La pastille de disponibilité : le seul élément de la barre qui ne soit pas
   de la navigation, et la première chose qu'un recruteur cherche. */
.avail {
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background-color: var(--surface-2);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.avail__dot {
  flex: 0 0 auto;
  width: 0.5rem;
  height: 0.5rem;
  background-color: var(--accent);
  border-radius: var(--radius-full);
}


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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: var(--space-3) var(--space-5);
  border: var(--line) solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--w-semi);
  line-height: var(--leading-snug);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-1) var(--ease),
    border-color var(--dur-1) var(--ease),
    box-shadow var(--dur-2) var(--ease),
    color var(--dur-1) var(--ease),
    transform var(--dur-2) var(--ease);
}

.btn:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(var(--lift));
}

.btn--primary {
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

.btn--primary:hover {
  background-color: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--accent-contrast);
}

.btn--ghost {
  background-color: var(--surface);
  border-color: var(--border-control);
  color: var(--text);
}

.btn--ghost:hover {
  border-color: var(--text);
  color: var(--text);
}


/* --- 5.5 En-tête de page ---------------------------------------------------- */

.page {
  padding-top: var(--space-12);
  padding-bottom: var(--space-section);
}

.page__title {
  max-width: 20ch;
  font-size: var(--text-4xl);
  font-weight: var(--w-bold);
}

.page__title--case {
  font-size: var(--text-3xl);
}

.page__lede {
  max-width: var(--measure);
  margin-top: var(--space-5);
  color: var(--text-muted);
  font-size: var(--text-lg);
  line-height: var(--leading-loose);
}

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

/* La note qui suit les boutons n'est pas leur légende : sans cette reprise,
   elle se lit comme la suite du dernier bouton au lieu d'un paragraphe à
   part. */
.page__actions + .muted {
  margin-top: var(--space-6);
}


/* --- 5.5b Bandeau d'ouverture -----------------------------------------------
   Le portrait est remonté ici, au-dessus de la ligne de flottaison : sur une
   candidature, un visage vu tout de suite change la lecture de ce qui suit.
   Il n'apparaît qu'une fois sur la page - la section À propos n'en porte plus. */

.intro {
  display: grid;
  gap: var(--space-8);
}

.intro__media {
  overflow: hidden;
  aspect-ratio: 4 / 5;
  max-width: 13rem;
  background-color: var(--surface-2);
}

.intro__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}


/* --- 5.6 Fiche de caractéristiques ------------------------------------------
   Le composant de données du site. Il sert pour les repères du profil comme
   pour les métadonnées des études de cas.                              */

.spec {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-10);
  padding-top: var(--space-6);
  border-top: var(--line) solid var(--border);
}

/* Variante en pile : dans une colonne étroite, la fiche garde une seule
   colonne quelle que soit la largeur de la fenêtre. Deux classes pour passer
   devant la règle à deux colonnes de la media query, sans monter en poids. */
.spec.spec--stack {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

/* Variante collée : quand la fiche suit immédiatement un sous-titre, elle
   n'a pas besoin de son propre filet de séparation. */
.spec--flush {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Collée sous un sous-titre, oui : celui-ci porte déjà l'écart. Collée sous
   un paragraphe, non - il faut alors rendre la respiration que la variante
   supprime, sans pour autant remettre le filet. */
.prose + .spec--flush {
  margin-top: var(--space-8);
}

/* Variante en ligne. Le contenu ne change pas ; c'est la forme qui change.
   Le libellé et sa valeur partagent la même ligne de base au lieu d'être
   empilés, et les entrées se suivent au fil de la ligne au lieu de s'aligner
   en tableau : la fiche se lit comme une signature, plus comme un formulaire. */
.spec--inline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-7);
}

.spec--inline .spec__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.spec--inline .spec__val {
  margin-top: 0;
}

.spec__key {
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--text-2xs);
  font-weight: var(--w-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.spec__val {
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
  line-height: var(--leading-snug);
}


/* --- 5.7 Cartes projet ------------------------------------------------------ */

.projects {
  display: grid;
  gap: var(--space-6);
}

.project {
  position: relative;
  display: flex;
  flex-direction: column;
  padding-top: var(--space-4);
  border-top: var(--line-thick) solid var(--text);
  transition:
    border-color var(--dur-2) var(--ease),
    transform var(--dur-2) var(--ease);
}

.project:hover,
.project:focus-within {
  border-color: var(--accent);
  transform: translateY(var(--lift));
}

.project__media {
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background-color: var(--surface-2);
  border-bottom: var(--line) solid var(--border);
}

.project__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-3) var(--ease);
}

.project:hover .project__img,
.project:focus-within .project__img {
  transform: scale(var(--zoom));
}

.project__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-6);
}

.project__id {
  color: var(--text-muted);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-label);
}

.project__title {
  font-size: var(--text-xl);
}

.project__link {
  color: var(--text);
  text-decoration: none;
}

/* Toute la carte devient cliquable sans JavaScript : c'est le vrai lien qui
   est étiré, il reste donc atteignable et annoncé au clavier. */
.project__link::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
}

.project__link:hover {
  color: var(--accent);
}

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

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

.project__go {
  margin-top: auto;
  padding-top: var(--space-2);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: var(--w-semi);
}

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

.tag {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  background-color: var(--surface-2);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
}


/* --- 5.8 À propos ----------------------------------------------------------- */

.about {
  max-width: var(--measure);
}


/* --- 5.9 Compétences : deux colonnes denses, sans cartes -------------------- */

.cols {
  display: grid;
  gap: var(--space-8);
}

.col__title {
  padding-bottom: var(--space-3);
  border-bottom: var(--line-thick) solid var(--text);
  font-size: var(--text-sm);
}

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

.col__item {
  display: flex;
  gap: var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.col__item::before {
  content: "■";
  flex: 0 0 auto;
  color: var(--brand-300);
}

.tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: var(--line) solid var(--border);
}

.tools__title {
  font-size: var(--text-sm);
}


/* --- 5.10 Panneau et formulaire --------------------------------------------- */

.panel {
  background-color: var(--surface);
  border-radius: var(--radius-md);
}

.panel__body {
  display: grid;
  gap: var(--space-8);
  padding: var(--space-6);
}

/* --- Confirmation d'envoi ----------------------------------------------------
   Web3Forms renvoie sur #message-envoye une fois le message parti. C'est
   :target qui révèle ce bloc et masque le formulaire — aucun script, la même
   famille de technique que le menu en petit écran.

   Le lien « écrire un autre message » pointe sur #contact : changer de cible
   suffit à refermer la confirmation et à rendre le formulaire, sans recharger.

   Les deux tracés sont dessinés par animation de stroke-dashoffset. Un seul
   keyframe « to » : la valeur de départ est celle portée par l'élément, ce
   qui évite de répéter deux longueurs dans les keyframes.               */

.sent {
  display: none;
}

.sent:target {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  padding: var(--space-6);
  animation: sent-rise var(--dur-3) var(--ease) both;
}

/* On ne redemande pas ce qui vient d'être envoyé. */
.sent:target ~ .panel__body {
  display: none;
}

.sent__seal {
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--accent);
}

.sent__ring,
.sent__tick {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: sent-draw var(--dur-3) var(--ease) both;
}

.sent__ring {
  stroke-width: 2;
  stroke-dasharray: 132;
  stroke-dashoffset: 132;
}

.sent__tick {
  stroke-width: 3;
  stroke-dasharray: 28;
  stroke-dashoffset: 28;
  animation-delay: var(--dur-3);
}

.sent__title {
  font-size: var(--text-lg);
  font-weight: var(--w-semi);
  letter-spacing: var(--tracking-tight);
}

.sent__text {
  margin-top: var(--space-1);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.sent__again {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
}

/* Les durées passent par les variables : la section 07 les ramène à 1ms pour
   le réglage système de mouvement réduit, et le remplissage « both » laisse
   les tracés à leur état final. Rien à désactiver. */
@keyframes sent-rise {
  from {
    opacity: 0;
    transform: translateY(var(--space-2));
  }
}

@keyframes sent-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.contacts {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

.contacts__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
}

.form {
  display: grid;
  gap: var(--space-6);
}

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

.form__legend {
  padding-bottom: var(--space-3);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--w-semi);
}

.field {
  display: grid;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
}

.field__req {
  color: var(--accent);
}

.field__input {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--space-3);
  background-color: var(--surface-sunken);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: var(--text-sm);
  transition: border-color var(--dur-1) var(--ease);
}

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

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


/* --- 5.11 Pied de page ------------------------------------------------------ */

.foot {
  margin-top: auto;
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
  border-top: var(--line) solid var(--border);
}

.foot__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.foot__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-5);
}

.foot__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-size: var(--text-sm);
}

.foot__note {
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--text-xs);
}


/* --- 5.12 Fil d'Ariane ------------------------------------------------------ */

.crumbs {
  padding-top: var(--space-6);
}

.crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--text-xs);
}

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

/* Séparateur généré : il n'est pas restitué par les lecteurs d'écran. */
.crumbs__item + .crumbs__item::before {
  content: "/";
  color: var(--text-faint);
}

.crumbs__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
}

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


/* --- 5.13 Étude de cas ------------------------------------------------------ */

.case__cover {
  overflow: hidden;
  aspect-ratio: 16 / 9;
  margin-top: var(--space-10);
  background-color: var(--surface-2);
}

.case__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Sommaire : la page est longue, on en donne la carte d'entrée. */
.toc {
  margin-top: var(--space-10);
  padding-top: var(--space-4);
  padding-bottom: var(--space-4);
  border-top: var(--line) solid var(--border);
  border-bottom: var(--line) solid var(--border);
}

.toc__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-5);
  margin-top: var(--space-2);
}

.toc__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  font-size: var(--text-sm);
}

.block {
  padding-top: var(--space-section);
}

.block__title {
  padding-bottom: var(--space-4);
  border-bottom: var(--line-thick) solid var(--text);
}

.sub {
  margin-top: var(--space-10);
  margin-bottom: var(--space-4);
  font-size: var(--text-md);
}

.prose {
  max-width: var(--prose-max);
  margin-top: var(--space-6);
}

.bullets {
  display: grid;
  gap: var(--space-4);
  max-width: var(--prose-max);
  margin-top: var(--space-4);
}

.bullets__item {
  padding-left: var(--space-5);
  border-left: var(--line-thick) solid var(--border);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.figure {
  margin-top: var(--space-8);
}

.figure__frame {
  overflow: hidden;
  aspect-ratio: 8 / 5;
  background-color: var(--surface-2);
}

.figure__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

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


/* --- 5.14 Palette d'un projet ----------------------------------------------- */

.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.swatch__chip {
  display: block;
  height: 3.5rem;
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-sm);
}

.swatch__name {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--w-medium);
}

.swatch__hex {
  color: var(--text-muted);
  font-family: var(--font-data);
  font-size: var(--text-xs);
}

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

/* Valeurs relevées dans le CSS de chaque projet. L'hexadécimal est
   toujours écrit sous la pastille : la couleur ne porte rien seule. */
.swatch__chip--carrot { background-color: #E67E22; }
.swatch__chip--amber { background-color: #CF711F; }
.swatch__chip--cream { background-color: #FDF2E9; }
.swatch__chip--espresso { background-color: #45260A; }
.swatch__chip--graphite { background-color: #333333; }

.swatch__chip--vermilion { background-color: #E83F43; }
.swatch__chip--slate { background-color: #213442; }
.swatch__chip--midnight { background-color: #000829; }
.swatch__chip--smoke { background-color: #4D5D68; }
.swatch__chip--mist { background-color: #E9EBED; }

.swatch__chip--black { background-color: #000000; }
.swatch__chip--charcoal { background-color: #222222; }
.swatch__chip--grey { background-color: #888888; }
.swatch__chip--linen { background-color: #E3DDDD; }
.swatch__chip--white { background-color: #FFFFFF; }

.swatch__chip--cobalt { background-color: #0125A0; }
.swatch__chip--periwinkle { background-color: #8A95D5; }
.swatch__chip--cyan { background-color: #00FDF8; }
.swatch__chip--aqua { background-color: #58CEE4; }
.swatch__chip--stone { background-color: #A59999; }

.swatch__chip--blush { background-color: #F59B90; }
.swatch__chip--petal { background-color: #FEF2F0; }
.swatch__chip--taupe { background-color: #A87E72; }
.swatch__chip--ink { background-color: #43484E; }
.swatch__chip--ash { background-color: #696D71; }


/* --- 5.15 Décisions et bilan ------------------------------------------------ */

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

.call {
  padding-left: var(--space-5);
  border-left: var(--line-thick) solid var(--border-strong);
}

.call__title {
  font-size: var(--text-md);
}

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

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

.balance__title {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: var(--line) solid var(--border);
  font-size: var(--text-sm);
}


/* --- 5.16 Navigation entre projets ------------------------------------------ */

.pager {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-16);
  margin-bottom: var(--space-section);
  padding-top: var(--space-6);
  border-top: var(--line) solid var(--border);
}

.pager__link {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-top: var(--space-4);
  border-top: var(--line-thick) solid var(--border-strong);
  text-decoration: none;
  transition:
    border-color var(--dur-2) var(--ease),
    transform var(--dur-2) var(--ease);
}

.pager__link:hover {
  border-color: var(--border-strong);
  transform: translateY(var(--lift));
}

.pager__name {
  color: var(--text);
  font-size: var(--text-lg);
  font-weight: var(--w-semi);
  letter-spacing: var(--tracking-tight);
}

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

.pager__arrow {
  color: var(--accent);
}

.pager__link--prev {
  text-align: left;
}

.pager__link--next {
  text-align: right;
}


/* --- 5.17 Mentions légales --------------------------------------------------- */

.legal {
  max-width: var(--prose-max);
  /* Même respiration avant le pied de page que sur les autres gabarits :
     les bandes de l'accueil et le pager des études de cas utilisent le
     même palier. */
  padding-bottom: var(--space-section);
}

.legal__block {
  padding-top: var(--space-10);
}

.legal__title {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--line) solid var(--border);
  font-size: var(--text-lg);
}


/* =========================================================================
   06. UTILITAIRES
   ========================================================================= */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.flow > * + * {
  margin-top: var(--flow, var(--space-4));
}

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


/* =========================================================================
   07. MEDIA QUERIES
   ========================================================================= */

/* --- 7.1 Tablette : 48rem --------------------------------------------------- */

@media (min-width: 48rem) {
  .spec {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-6);
  }

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

  /* La carte principale barre la grille : la hiérarchie vient de la surface
     occupée, aucune carte ne change de nature pour autant. */
  .project--lead {
    grid-column: span 2;
  }

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

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

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

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

  .foot__inner {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
  }

  .form__group--split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --- 7.2 Bureau : 64rem — la barre se déplie --------------------------------
   La bascule et sa case disparaissent du document : au clavier, on ne tabule
   pas sur un contrôle qui ne sert plus à rien. Les deux sélecteurs sont
   répétés pour reprendre la main sur la règle d'état de la section 05.  */

@media (min-width: 64rem) {
  .nav-toggle,
  .burger {
    display: none;
  }

  .nav,
  .nav-toggle:checked ~ .nav {
    display: block;
    flex-basis: auto;
  }

  .avail,
  .nav-toggle:checked ~ .avail {
    display: flex;
    flex-basis: auto;
  }

  .menu {
    flex-direction: row;
    gap: var(--space-2);
    padding-top: 0;
    padding-bottom: 0;
  }

  .projects {
    gap: var(--space-5);
  }

  /* Le portrait vient se poser à droite du texte d'ouverture. En dessous de
     cette largeur il reste au-dessus, à taille réduite. */
  .intro {
    grid-template-columns: minmax(0, 1fr) minmax(0, 15rem);
    align-items: start;
    gap: var(--space-12);
  }

  .intro__media {
    max-width: none;
  }

  /* Trois colonnes à partir d'ici. Avec quatre projets - un principal et
     trois secondaires - c'est la seule grille qui ne laisse pas une carte
     seule sur sa rangée : la principale barre la largeur, les trois autres
     remplissent exactement une ligne. Mesuré à 1024 px : 306 px par carte,
     ce qui tient encore le texte sur six lignes. */
  .projects {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* Sur toute la largeur, la carte principale se scinde : visuel à gauche,
     texte à droite. */
  .project--lead {
    grid-column: span 3;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .project--lead .project__media {
    height: 100%;
    aspect-ratio: auto;
    border-right: var(--line) solid var(--border);
    border-bottom: 0;
  }

  .project--lead .project__body {
    justify-content: center;
  }

  .cols {
    gap: var(--space-12);
  }

  .panel__body--split {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--space-12);
    padding: var(--space-8);
  }

  .spec--case {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* --- 7.3 Grand écran : 90rem ------------------------------------------------ */

@media (min-width: 90rem) {
  :root {
    --content-max: 80rem;
  }
}

/* --- 7.4 Thème sombre --------------------------------------------------------
   Aucune règle n'est dupliquée : seuls les rôles sont réécrits.       */

@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--d-bg);
    --surface: var(--d-surface);
    --surface-2: var(--d-surface-2);
    --surface-sunken: var(--d-bg);
    --border: var(--d-border);
    --border-strong: var(--d-border-strong);
    --border-control: var(--d-border-control);
    --text: var(--d-text);
    --text-muted: var(--d-text-muted);
    --text-faint: var(--d-text-faint);
    --accent: var(--brand-300);
    --accent-hover: #F0902E;
    --accent-contrast: var(--n-950);
    --focus: var(--brand-300);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.4), 0 10px 28px rgba(0, 0, 0, 0.45);
  }
}

/* --- 7.5 Mouvement réduit ----------------------------------------------------
   Durées, décalage et zoom passent tous par ces variables : les remettre à
   zéro neutralise l'intégralité des transitions du site.              */

@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-1: 1ms;
    --dur-2: 1ms;
    --dur-3: 1ms;
    --lift: 0rem;
    --zoom: 1;
  }

  html {
    scroll-behavior: auto;
  }
}


/* =========================================================================
   08. IMPRESSION
   Un recruteur qui enregistre la page en PDF ne veut ni la navigation, ni le
   formulaire, ni les aplats sombres. Ce bloc retire ce qui ne s'imprime pas,
   remet le texte en noir sur blanc, et fait apparaître la destination des
   liens - sur papier, un lien dont on ne voit pas l'adresse ne sert à rien.
   ========================================================================= */

@media print {
  /* Les rôles de couleur repassent en noir et blanc : l'impression couleur
     n'est pas garantie, et les aplats vident les cartouches pour rien. */
  :root {
    --bg: #FFFFFF;
    --surface: #FFFFFF;
    --surface-2: #FFFFFF;
    --surface-sunken: #FFFFFF;
    --text: #000000;
    --text-muted: #333333;
    --text-faint: #555555;
    --border: #BBBBBB;
    --border-strong: #888888;
    --border-control: #888888;
    --accent: #000000;
    --accent-hover: #000000;
    --dur-1: 0s;
    --dur-2: 0s;
    --dur-3: 0s;
  }

  .topbar,
  .crumbs,
  .toc,
  .pager,
  .page__actions,
  .panel__body,
  .skip,
  .project__go,
  .foot__links {
    display: none;
  }

  body {
    background-color: #FFFFFF;
    color: #000000;
    font-size: 11pt;
  }

  /* Les figures et les blocs ne doivent pas être coupés en deux par un saut
     de page ; un titre ne doit pas rester seul en bas de feuille. */
  .figure,
  .swatch,
  .call,
  .project {
    break-inside: avoid;
  }

  h1, h2, h3 {
    break-after: avoid;
  }

  /* La destination des liens externes, écrite à la suite du libellé. */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    font-weight: var(--w-regular);
    word-break: break-all;
  }

  /* Sauf les liens du portfolio lui-même, dont l'adresse n'apprend rien. */
  a[href^="https://hugocolicchia.fr"]::after {
    content: "";
  }

  img {
    max-width: 100%;
  }
}
