/* ==========================================================================
   Fonts — auto-hébergées (sous-ensemble latin, suffisant pour le français),
   pour éviter toute dépendance/tierce requête vers Google Fonts (cf. RGPD
   et fondations/01-Regle-codage/typographie-images-performance.md).
   ========================================================================== */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/Inter-variable-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/Inter-variable-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/SpaceGrotesk-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

/* ==========================================================================
   Tokens
   ========================================================================== */
:root {
  --font-body: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: 'Space Grotesk', 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --color-bg: #121212;
  /* Bande « en creux », plus sombre que le fond : sépare la preuve sociale
     du hero (au-dessus) et de --color-bg-secondary (prestations, dessous). */
  --color-bg-creux: #0b0d10;
  --color-bg-secondary: #1a1e24;
  --color-bg-secondary-hover: #212630;
  --color-border: #2a2f38;

  --color-primary: #4c8dff;
  --color-accent: #4ac4c8;
  --color-accent-hover: #63cfd3;
  --color-bolt: #f9b233; /* ambre du logo, pas l'orange générique de l'ancienne vidéo de présentation */

  --color-text: #e8e4d9;
  --color-text-secondary: #adb0b6;
  --color-text-discret: #8a8d93;

  --color-success: #4caf7d;
  --color-error: #e0615a;
  --color-on-accent: #0d1a1b; /* texte sombre sur fond accent (CTA, skip-link) */

  /* Teintes de fond dérivées des couleurs sémantiques (tints) :
     single source of truth — une modification de palette n'édite plus
     qu'un seul triplet RGBA au lieu d'être ressassée dans chaque composant. */
  --tint-accent-06: rgba(74, 196, 200, 0.06);
  --tint-accent-08: rgba(74, 196, 200, 0.08);
  --tint-accent-12: rgba(74, 196, 200, 0.12);
  --tint-error-12: rgba(224, 97, 90, 0.12);
  --tint-error-14: rgba(224, 97, 90, 0.14);
  --tint-success-12: rgba(76, 175, 125, 0.12);
  --tint-success-14: rgba(76, 175, 125, 0.14);
  --tint-bolt-14: rgba(249, 178, 51, 0.14);

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-24: 6rem;

  --radius-sm: 0.5rem;
  --radius-pill: 2rem;

  --container-max: 75rem;
  --header-height: 4.5rem;

  --ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body,
h1,
h2,
h3,
p,
ul,
ol,
figure,
fieldset {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

fieldset {
  border: none;
  padding: 0;
}

img,
svg {
  display: block;
  max-width: 100%;
}

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

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  line-height: 1.6;
  min-height: 100vh;
}

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

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .chargement {
    display: none;
  }
}

.sr-only,
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Champ piège anti-robot du formulaire de devis : jamais affiché. */
.champ-piege {
  display: none;
}

.skip-link {
  position: absolute;
  top: -3rem;
  left: var(--space-4);
  background: var(--color-accent);
  color: var(--color-on-accent);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  z-index: 100;
  transition: top 150ms var(--ease-standard);
}

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

/* ==========================================================================
   Écran de bienvenue — accueil uniquement (cf. templates/frontoffice.php,
   condition !isset($titre)). Toujours visible par défaut : l'animation
   GSAP (script.js) ne fait qu'ajouter la mise en scène par-dessus ; si
   GSAP ne s'exécute jamais, ce fondu CSS seul referme l'écran après
   quelques secondes, cf. règle prefers-reduced-motion plus haut.
   ========================================================================== */
.chargement {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  background: var(--color-bg);
  animation: chargement-repli 4.5s forwards;
}

.chargement__scene {
  width: clamp(13rem, 40vw, 19rem);
  height: auto;
  color: var(--color-accent);
}

.chargement__marque {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.375rem;
  letter-spacing: 0.02em;
  color: var(--color-text);
}

@keyframes chargement-repli {
  0%, 85% {
    opacity: 1;
    visibility: visible;
  }

  100% {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
}

/* ==========================================================================
   Layout
   ========================================================================== */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

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

.section--alt {
  background: var(--color-bg-secondary);
}

.section h2 {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 7vw, 4rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 0.98;
  margin-top: var(--space-2);
}

.section-lead {
  color: var(--color-text-secondary);
  margin-top: var(--space-4);
  max-width: 40rem;
}

@media (min-width: 48rem) {
  .container {
    padding-inline: 2rem;
  }

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

/* ==========================================================================
   Pages juridiques (prose) — mentions légales, CGU, politique de confidentialité
   Rythme vertical, largeur de lecture et table. Scope par classe pour ne pas
   toucher le reste du site : les éléments h3/p/ul/table n'ont pas de style
   global ailleurs (reset des marges à 0), d'où une colonne de lecture dédiée.
   ========================================================================== */
.prose-legal {
  max-width: 46rem;
}

.prose-legal h3 {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text);
  margin-top: var(--space-12);
  margin-bottom: var(--space-3);
}

.prose-legal p {
  margin-top: var(--space-4);
  color: var(--color-text-secondary);
}

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

.prose-legal li {
  position: relative;
  padding-inline-start: var(--space-4);
  color: var(--color-text-secondary);
}

.prose-legal li::before {
  content: "";
  position: absolute;
  inset-block-start: 0.65em;
  inset-inline-start: 0;
  width: 0.35rem;
  height: 0.35rem;
  border-radius: 50%;
  background: var(--color-accent);
}

.prose-legal a {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.prose-legal table {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--space-4);
  font-size: 0.9375rem;
}

.prose-legal th,
.prose-legal td {
  text-align: start;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  vertical-align: top;
}

.prose-legal thead th {
  color: var(--color-text);
  font-weight: 600;
}

/* ==========================================================================
   Header & navigation
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-height);
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--color-border);
}

/* Fond flouté sur un pseudo-élément plutôt que directement sur
   .site-header : `backdrop-filter` crée un containing block pour tout
   descendant en `position: fixed` (ex. `.nav` en mobile), ce qui le
   piégeait dans la hauteur de la barre d'en-tête (--header-height) au
   lieu de la fenêtre — top et bottom se résolvaient au même endroit,
   hauteur nulle, menu invisible. Un pseudo-élément n'a pas de vrais
   descendants, donc `.nav` reste positionné par rapport à la fenêtre. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(18, 18, 18, 0.85);
  backdrop-filter: blur(8px);
}

.site-header__inner {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.logo {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: 0.02em;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
}

.logo__accent,
.admin-sidebar__logo span,
.auth-card__logo span {
  color: var(--color-accent);
}

.logo__icone {
  height: 2.75rem;
  width: auto;
  flex-shrink: 0;
}

/* Téléphone + bouton devis à droite du header : ordinateur uniquement (sur
   mobile, le bouton devis est dans le menu burger). */
.site-header__actions {
  display: none;
  align-items: center;
  gap: var(--space-6);
}

.phone-cta {
  display: none;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  color: var(--color-text);
  font-weight: 600;
  white-space: nowrap;
}

.burger {
  background: none;
  border: none;
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 5px;
  cursor: pointer;
  margin-inline-start: auto;
}

.burger__bar {
  width: 22px;
  height: 2px;
  background: var(--color-text);
  border-radius: 2px;
  transition: transform 200ms var(--ease-standard), opacity 200ms var(--ease-standard);
}

.burger[aria-expanded="true"] .burger__bar:nth-child(2) {
  transform: translateY(7px) rotate(45deg);
}

.burger[aria-expanded="true"] .burger__bar:nth-child(3) {
  opacity: 0;
}

.burger[aria-expanded="true"] .burger__bar:nth-child(4) {
  transform: translateY(-7px) rotate(-45deg);
}

.nav {
  position: fixed;
  inset: var(--header-height) 0 0 0;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  transform: translateY(-110%);
  /* visibility : menu fermé hors de la tabulation et des lecteurs d'écran ;
     masqué seulement après la fin de la transition de fermeture. */
  visibility: hidden;
  transition: transform 300ms var(--ease-standard), visibility 0s linear 300ms;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.nav.is-open {
  transform: translateY(0);
  visibility: visible;
  transition: transform 300ms var(--ease-standard);
}

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

/* Bouton « Demander un devis » du header (ordinateur). */
.nav__cta {
  display: inline-block;
  color: var(--color-on-accent) !important;
  background: var(--color-accent);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-pill);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

/* Menu mobile : grandes lignes séparées par des filets, page courante en
   accent, apparition en cascade ; actions (devis, appel) groupées en bas
   du panneau. */
@media (max-width: 63.999rem) {
  html.menu-ouvert {
    overflow: hidden;
  }

  .nav__list {
    display: flex;
    flex-direction: column;
    padding: var(--space-4) 1.25rem 0;
  }

  .nav__list li {
    border-bottom: 1px solid var(--color-border);
    opacity: 0;
    transform: translateY(-0.5rem);
    transition: opacity 250ms var(--ease-standard), transform 250ms var(--ease-standard);
  }

  .nav.is-open .nav__list li {
    opacity: 1;
    transform: none;
  }

  .nav.is-open .nav__list li:nth-child(2) { transition-delay: 40ms; }
  .nav.is-open .nav__list li:nth-child(3) { transition-delay: 80ms; }
  .nav.is-open .nav__list li:nth-child(4) { transition-delay: 120ms; }

  .nav__list a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 3.75rem;
    font-family: var(--font-display);
    font-size: 1.375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
  }

  /* Préfixe .nav.is-open : l'emporte sur le soulignement animé des liens
     (règle hover: hover plus bas), actif aussi sur une fenêtre d'ordinateur
     étroite. */
  .nav.is-open .nav__list a::after {
    content: "→";
    position: static;
    height: auto;
    background: none;
    transform: none;
    color: var(--color-text-secondary);
    font-family: var(--font-body);
    transition: transform 150ms var(--ease-standard), color 150ms var(--ease-standard);
  }

  .nav.is-open .nav__list a:hover::after,
  .nav.is-open .nav__list a:focus-visible::after {
    transform: translateX(0.25rem);
    color: var(--color-accent);
  }

  .nav__list a[aria-current="page"] {
    color: var(--color-accent);
  }

  .nav__actions {
    margin-top: auto;
    display: grid;
    gap: var(--space-3);
    padding: var(--space-8) 1.25rem calc(var(--space-6) + env(safe-area-inset-bottom));
    border-top: 1px solid var(--color-border);
    background: var(--color-bg-secondary);
  }

  .nav__appel svg {
    flex-shrink: 0;
  }

  .nav__infos {
    margin-top: var(--space-2);
    text-align: center;
    color: var(--color-text-secondary);
    font-size: 0.875rem;
  }
}

@media (min-width: 64rem) {
  /* Logo | liens centrés | actions : la colonne centrale absorbe l'espace,
     les liens y sont centrés. */
  .site-header__inner {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: var(--space-6);
  }

  .burger,
  .nav__actions {
    display: none;
  }

  .site-header__actions,
  .phone-cta {
    display: inline-flex;
  }

  .nav {
    position: static;
    inset: auto;
    transform: none;
    background: none;
    overflow: visible;
    visibility: visible;
    justify-self: center;
  }

  .nav__list {
    display: flex;
    flex-direction: row;
    align-items: center;
    padding: 0;
    gap: var(--space-6);
    font-size: 1rem;
  }

  .nav__cta {
    padding: var(--space-2) var(--space-6);
  }
}

/* Entre 1024 et 1280 px, logo + liens + numéro complet + bouton ne tiennent
   pas : le téléphone passe en icône seule, le numéro reste lu par les
   lecteurs d'écran (masquage visuel, pas display: none). */
@media (min-width: 64rem) and (max-width: 79.999rem) {
  .phone-cta span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-8);
  border-radius: var(--radius-pill);
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 150ms var(--ease-standard), transform 150ms var(--ease-standard);
  min-height: 44px;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.btn--accent {
  background: var(--color-accent);
  color: var(--color-on-accent);
}

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

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

.btn--ghost:hover {
  background: var(--color-bg-secondary-hover);
}

/* Effets "électriques" au survol — liens texte et boutons. Reprend la
   palette de l'étincelle du titre hero (blanc chaud + accent teal +
   primary bleu), en version discrète/réversible pour du hover plutôt
   qu'une séquence animée (cf. gsap-recettes.md — micro-interactions
   rapides et réversibles). Scopé à `hover: hover` : sur tactile, l'état
   hover resterait "collé" après le tap, donc pas de pointeur fin = pas
   d'effet. */
@media (hover: hover) and (pointer: fine) {

  .nav__list a:not(.nav__cta),
  .legal-links a,
  .consent a {
    position: relative;
  }

  .nav__list a:not(.nav__cta)::after,
  .legal-links a::after,
  .consent a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -0.2em;
    height: 2px;
    background: linear-gradient(90deg, var(--color-accent), var(--color-primary));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 180ms var(--ease-standard);
  }

  .nav__list a:not(.nav__cta):hover,
  .nav__list a:not(.nav__cta):focus-visible,
  .legal-links a:hover,
  .legal-links a:focus-visible,
  .consent a:hover,
  .consent a:focus-visible {
    text-shadow: 0 0 10px rgba(74, 196, 200, 0.7);
  }

  .nav__list a:not(.nav__cta):hover::after,
  .nav__list a:not(.nav__cta):focus-visible::after,
  .legal-links a:hover::after,
  .legal-links a:focus-visible::after,
  .consent a:hover::after,
  .consent a:focus-visible::after {
    transform: scaleX(1);
  }

  .btn:hover,
  .btn:focus-visible,
  .nav__cta:hover,
  .nav__cta:focus-visible {
    box-shadow:
      0 0 0 1px rgba(255, 255, 255, 0.25),
      0 0 16px rgba(74, 196, 200, 0.55),
      0 0 32px rgba(76, 141, 255, 0.3);
  }

  .nav__cta:hover,
  .nav__cta:focus-visible {
    background: var(--color-accent-hover);
  }

  .btn--ghost:hover,
  .btn--ghost:focus-visible {
    border-color: var(--color-accent);
  }

  .social-link:hover,
  .social-link:focus-visible {
    box-shadow:
      0 0 0 1px rgba(255, 255, 255, 0.2),
      0 0 14px rgba(74, 196, 200, 0.5);
    border-color: var(--color-accent);
  }
}

.btn--block {
  width: 100%;
}

.btn--petit {
  padding: var(--space-2) var(--space-4);
  min-height: 36px;
  font-size: 0.875rem;
  flex-shrink: 0;
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  padding-block: clamp(7rem, 18vw, 11rem) clamp(5rem, 10vw, 8rem);
  background:
    radial-gradient(60rem 30rem at 80% -10%, rgba(76, 141, 255, 0.18), transparent 60%),
    radial-gradient(40rem 24rem at -10% 40%, rgba(74, 196, 200, 0.12), transparent 60%),
    var(--color-bg);
}

/* Empilement simple — composition façon affiche suisse : le titre
   domine, l'espace négatif à droite (colonnes plus étroites en desktop
   pour eyebrow/lead/actions/trust) est volontaire. */
.hero__grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.hero__logo {
  order: -1;
  width: clamp(8rem, 32vw, 11rem);
  height: auto;
  display: none;
}

@media (min-width: 1280px) {
  .hero__logo {
    display: inline-flex;
  }
}

.eyebrow {
  color: var(--color-text);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.875rem;
}


.hero h1 {
  font-family: var(--font-display);
  font-size: clamp(3.25rem, 12vw, 4.5rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 0.95;
}

.hero__break {
  display: none;
}

.hero__lead {
  color: var(--color-text-secondary);
  font-size: 1.125rem;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.hero__trust {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-8);
  color: var(--color-text-discret);
  font-size: 0.8125rem;
}

@media (min-width: 64rem) {
  .hero__grid {
    position: relative;
  }

  .hero__logo {
    display: block;
    position: absolute;
    right: 0;
    bottom: 0;
    width: clamp(14rem, 22vw, 20rem);
    height: auto;
    pointer-events: none;
  }

  .eyebrow {
    max-width: 58%;
  }

  .hero h1 {
    font-size: clamp(4rem, 9vw, 7rem);
    letter-spacing: -0.03em;
    line-height: 0.9;
  }

  .hero__break {
    display: block;
  }

  .hero__lead {
    max-width: 70%;
  }

  .hero__actions {
    max-width: 58%;
  }

  .hero__trust {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-4);
    max-width: 65%;
  }

  .hero__trust span:not(:last-child)::after {
    content: "·";
    margin-left: var(--space-4);
    color: var(--color-border);
  }

  /* Doublon du bouton d'appel du header (.phone-cta), visible dès ce
     même point de rupture : inutile de le répéter dans le hero. */
  .hero__call {
    display: none;
  }
}

/* ==========================================================================
   Prestations — cards
   ========================================================================== */
.card-grid,
.portfolio-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  margin-top: var(--space-12);
}

/* Socle « surface » commun aux panneaux (cards, cartes admin, auth) :
   fond, bordure et rayon identiques ; le padding reste propre à chacun. */
.card,
.admin-card,
.auth-card {
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

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

.card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-sm);
  background: var(--tint-accent-12);
  color: var(--color-accent);
  margin-bottom: var(--space-4);
}

.card h3 {
  font-size: 1.125rem;
  margin-bottom: var(--space-2);
}

.card p {
  color: var(--color-text-secondary);
}

@media (min-width: 48rem) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 64rem) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ==========================================================================
   Réalisations — portfolio
   ========================================================================== */
.portfolio-item__media {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, var(--color-bg-secondary-hover), var(--color-bg-secondary));
  border: 1px solid var(--color-border);
  overflow: hidden;
}

.portfolio-item__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.portfolio-item figcaption {
  margin-top: var(--space-3);
}

.portfolio-item h3 {
  font-size: 1.0625rem;
}

.portfolio-item p {
  color: var(--color-text-secondary);
  font-size: 0.9375rem;
}

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

@media (min-width: 48rem) {
  .portfolio-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Variante galerie de la page portfolio /realisations : grille plus dense
   (un intermédiaire 2 colonnes que l'accueil n'a pas). Même item et même
   aspect 4/3 que l'accueil — cohérence + reveal au scroll existant. */
@media (min-width: 36rem) {
  .portfolio-grid--galerie {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 56rem) {
  .portfolio-grid--galerie {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* L'item média est un <button data-lightbox> sur la page portfolio :
   reset bouton + interaction clavier/souris visible. */
.portfolio-item__media[data-lightbox] {
  display: block;
  width: 100%;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: transform 0.4s var(--ease-standard), border-color 0.2s;
}

.portfolio-item__media[data-lightbox]:hover,
.portfolio-item__media[data-lightbox]:focus-visible {
  transform: scale(1.02);
  border-color: var(--color-accent);
  outline: none;
}

/* ==========================================================================
   Lightbox — visionneuse plein écran (page portfolio)
   ========================================================================== */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background: rgba(8, 10, 12, 0.92);
  backdrop-filter: blur(4px);
}

.lightbox[hidden] {
  display: none;
}

.lightbox__figure {
  max-width: min(90vw, 60rem);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.lightbox__img {
  max-width: 100%;
  max-height: 70vh;
  object-fit: contain;
  border-radius: var(--radius-sm);
  margin-inline: auto;
}

.lightbox__caption {
  text-align: center;
  color: var(--color-text);
}

.lightbox__caption h3 {
  font-size: 1.125rem;
}

.lightbox__caption p {
  color: var(--color-text-secondary);
  font-size: 0.9375rem;
}

.lightbox__fermer {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 2.5rem;
  height: 2.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: var(--color-bg-secondary);
  color: var(--color-text);
  cursor: pointer;
  font-size: 1.25rem;
  line-height: 1;
}

.lightbox__fermer:hover,
.lightbox__fermer:focus-visible {
  border-color: var(--color-accent);
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .portfolio-item__media[data-lightbox],
  .lightbox {
    transition: none;
  }
}

/* ==========================================================================
   Back-office — liste des réalisations + import Instagram
   ========================================================================== */
.admin-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}

.btn-etoile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: transparent;
  color: var(--color-text-secondary);
  cursor: pointer;
}

.btn-etoile[aria-pressed="true"] {
  color: var(--color-bolt);
  border-color: var(--color-bolt);
}

.btn-etoile:hover:not(:disabled),
.btn-etoile:focus-visible {
  border-color: var(--color-accent);
  outline: none;
}

.btn-etoile:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

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

.admin-realisation__corps {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.admin-realisation__media img {
  width: 120px;
  height: 90px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
}

.admin-realisation__titre {
  font-weight: 600;
  margin-bottom: var(--space-1);
}

.admin-realisation__meta {
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  margin-bottom: var(--space-2);
}

.admin-realisation__desc {
  font-size: 0.9375rem;
}

@media (max-width: 30rem) {
  .admin-realisation__corps {
    grid-template-columns: 1fr;
  }
}

.insta-import-grid {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

.insta-import-item img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  margin-bottom: var(--space-2);
}

.insta-import-caption {
  font-size: 0.875rem;
  margin-bottom: var(--space-1);
}

.insta-import-date {
  color: var(--color-text-secondary);
  font-size: 0.8125rem;
  margin-bottom: var(--space-3);
}

@media (min-width: 30rem) {
  .insta-import-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 56rem) {
  .insta-import-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ==========================================================================
   Zone d'intervention
   ========================================================================== */
.zone-regions {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  margin-top: var(--space-8);
}

.zone-region h3 {
  color: var(--color-accent);
  font-size: 1rem;
  margin-bottom: var(--space-2);
}

.zone-region p {
  color: var(--color-text-secondary);
  font-size: 0.9375rem;
}

@media (min-width: 48rem) {
  .zone-regions {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
  }
}

/* ==========================================================================
   Formulaire de devis
   ========================================================================== */
.devis-form {
  max-width: 48rem;
  margin-top: var(--space-12);
  display: grid;
  /* minmax(0, 1fr), pas 1fr seul — cf. .admin-card__grille pour le détail
     du piège (une piste 1fr autorise minmax(auto, 1fr) implicitement). */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  /* Après soumission, le serveur redirige vers /#contact ; le navigateur
     scroll puis focus la cible si elle a tabindex="-1". scroll-margin-top
     évite que le formulaire soit masqué sous le header sticky, et un
     outline discret signale le focus aux lecteurs d'écran. */
  scroll-margin-top: calc(var(--header-height) + var(--space-4));
}

.devis-form:focus {
  outline: none;
}

.devis-form:focus-visible,
.form-confirmation:focus,
.form-error:focus,
.form-avertissement:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: var(--space-2);
}

.devis-form:focus-visible {
  border-radius: var(--radius-sm);
}

@media (min-width: 40rem) {
  .devis-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .field--full {
    grid-column: 1 / -1;
  }

  .devis-form .btn--block {
    width: auto;
    justify-self: end;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Casse l'héritage de min-width:auto des enfants flex/grid : sans ça,
     un contrôle natif au rendu peu prévisible (ex. le bouton système
     d'<input type="file"> sur Android) peut refuser de rétrécir et
     forcer tout le viewport mobile à s'élargir — la page entière
     paraît alors déborder à droite, pas seulement ce champ. Invisible
     en redimensionnant une fenêtre desktop (rendu CSS simplifié du
     contrôle), reproductible seulement sur un vrai navigateur mobile. */
  min-width: 0;
}

.field label,
.field legend {
  font-weight: 600;
  font-size: 0.9375rem;
}

.field span[aria-hidden="true"] {
  color: var(--color-accent);
}

.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field input[type="file"],
.field input[type="url"],
.field input[type="password"],
.field input[type="date"],
.field select,
.field textarea {
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  color: var(--color-text);
  font-size: 1rem;
  min-height: 44px;
  max-width: 100%;
}

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

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

.urgence-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.urgence-option {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  font-size: 0.9375rem;
}

.urgence-option:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--tint-accent-12);
}

.urgence-option--urgent:has(input:checked) {
  border-color: var(--color-error);
  background: var(--tint-error-14);
}

.consent {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: 0.9375rem;
  color: var(--color-text-secondary);
}

.consent input {
  margin-top: 0.2rem;
}

.consent a {
  color: var(--color-primary);
}

.form-confirmation,
.form-error,
.form-avertissement {
  color: var(--color-text);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
}

.form-confirmation {
  background: var(--tint-success-12);
  border: 1px solid var(--color-success);
}

.form-error {
  background: var(--tint-error-12);
  border: 1px solid var(--color-error);
}

.form-avertissement {
  background: var(--tint-bolt-14);
  border: 1px solid var(--color-bolt);
}

/* Erreurs par champ — nécessaires avec une vraie validation serveur
   (le prototype statique ne s'appuyait que sur les bulles natives du
   navigateur, absentes une fois le formulaire réellement soumis). */
.field-erreur {
  color: var(--color-error);
  font-size: 0.8125rem;
  margin: 0;
}

.field-aide {
  color: var(--color-text-discret);
  font-size: 0.8125rem;
  margin: 0;
}

.field--invalide input,
.field--invalide select,
.field--invalide textarea {
  border-color: var(--color-error);
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  background: var(--color-bg-secondary);
  border-top: 1px solid var(--color-border);
  padding-block: var(--space-16) var(--space-8);
}

.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-12);
}

.logo--footer {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  font-size: 1.125rem;
}

.site-footer p {
  color: var(--color-text-secondary);
}

.footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Bouton à sa largeur naturelle (la colonne flex l'étirerait sinon). */
.footer__devis {
  align-self: flex-start;
}

/* Reprise réduite de la scène animée (identique à l'écran de bienvenue,
   cf. plus haut) : en accompagnement du nom de marque plutôt qu'en pièce
   maîtresse, pour ne pas écraser les colonnes légales/réseaux sociaux
   voisines qui n'ont, elles, qu'une ligne de texte. */
.footer__scene {
  width: clamp(5.5rem, 15vw, 7rem);
  height: auto;
  color: var(--color-accent);
}

.scene__ampoule-lueur--diffuse {
  filter: blur(6px);
}

.scene__courant {
  filter: drop-shadow(0 0 5px rgba(249, 178, 51, 0.85));
}

.footer__heading {
  color: var(--color-text-discret);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-4);
}

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

.legal-links a {
  color: var(--color-text-secondary);
  text-decoration: none;
  font-size: 0.9375rem;
}

.legal-links a:hover {
  color: var(--color-text);
}

.footer__social-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.social-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text);
  text-decoration: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-6);
  font-size: 0.875rem;
  transition: background-color 150ms var(--ease-standard), border-color 150ms var(--ease-standard);
}

.social-link:hover {
  background: var(--color-bg-secondary-hover);
  border-color: var(--color-text-discret);
}

.site-footer__bottom {
  grid-column: 1 / -1;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-6);
}

.site-footer__copyright {
  color: var(--color-text-discret);
  font-size: 0.8125rem;
}

@media (min-width: 48rem) {
  .site-footer__inner {
    grid-template-columns: repeat(12, 1fr);
    column-gap: var(--space-8);
    row-gap: var(--space-12);
    align-items: start;
  }

  .footer__brand {
    grid-column: 1 / 6;
  }

  .footer__legal {
    grid-column: 6 / 9;
  }

  .footer__social {
    grid-column: 9 / -1;
  }
}

/* ==========================================================================
   Back-office — sidebar, tableau, badges, cartes d'édition
   ========================================================================== */
.admin-layout {
  display: flex;
  min-height: 100vh;
}

.admin-sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--color-bg-secondary);
  border-right: 1px solid var(--color-border);
  padding-block: var(--space-6);
  display: flex;
  flex-direction: column;
}

/* Bouton burger réutilisé tel quel depuis le site public (.burger /
   .burger__bar déjà stylés plus haut) — masqué ici, la sidebar desktop
   reste permanente ; affiché uniquement sous 48rem (cf. media query). */
@media (min-width: 48rem) {
  .admin-sidebar .burger {
    display: none;
  }
}

.admin-sidebar__logo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--color-text);
  text-decoration: none;
  padding-inline: var(--space-6);
  margin-bottom: var(--space-8);
  display: block;
}

.admin-nav {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.admin-nav__link {
  color: var(--color-text-secondary);
  text-decoration: none;
  padding: var(--space-3) var(--space-6);
  border-left: 3px solid transparent;
  font-weight: 600;
  font-size: 0.9375rem;
}

.admin-nav__link:hover {
  color: var(--color-text);
}

.admin-nav__link--actif {
  color: var(--color-text);
  border-left-color: var(--color-accent);
  background: var(--tint-accent-08);
}

.admin-nav__deconnexion {
  margin-top: auto;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-4);
}

.admin-nav__deconnexion button {
  background: none;
  border: none;
  color: var(--color-text-secondary);
  font: inherit;
  font-weight: 600;
  font-size: 0.9375rem;
  cursor: pointer;
  padding: var(--space-3) var(--space-6);
}

.admin-nav__deconnexion button:hover {
  color: var(--color-text);
}

.admin-main {
  flex: 1;
  padding: var(--space-8);
  min-width: 0;
}

.admin-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}

.admin-header h1 {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
}

.admin-header p {
  color: var(--color-text-secondary);
}

.admin-card {
  padding: var(--space-6);
  margin-bottom: var(--space-6);
}

.admin-card__legende {
  color: var(--color-accent);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: var(--space-4);
  display: block;
}

/* Ligne de titre de carte avec une action à droite (ex. « Vider » sur
   une réalisation) : la marge basse de .admin-card__legende sert
   ici à l'usage isolé (ex. tableau-de-bord.php) ; à l'intérieur de cette
   entête, c'est le conteneur flex qui la porte, pas la légende seule. */
.admin-card__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.admin-card__entete .admin-card__legende {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 0;
}

.admin-card__grille {
  display: grid;
  /* minmax(0, 1fr) et non 1fr seul : une piste 1fr autorise implicitement
     minmax(auto, 1fr), qui refuse de rétrécir sous la largeur intrinsèque
     du contenu — même piège que min-width:auto sur les enfants flex. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

.admin-card__actions {
  margin-top: var(--space-2);
}

@media (min-width: 40rem) {
  .admin-card__actions {
    display: flex;
    justify-content: flex-end;
  }

  .admin-card__actions .btn--block {
    width: auto;
  }
}

.admin-photo-actuelle {
  width: 100px;
  height: 75px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  object-fit: cover;
  background: var(--color-bg);
  margin-bottom: var(--space-2);
}

@media (min-width: 40rem) {
  .admin-card__grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .admin-card__grille .field--full {
    grid-column: 1 / -1;
  }
}

@media (max-width: 47.99rem) {
  .admin-layout {
    flex-direction: column;
  }

  /* Même pattern que le menu burger public (.nav / .is-open dans
     script.js::initBurger, généralisé pour cibler n'importe quel
     .burger via son aria-controls) : barre compacte logo + burger,
     panneau plein écran pour les liens ET la déconnexion (comme
     .nav__cta dans le menu public), pas de défilement horizontal. */
  .admin-sidebar {
    width: 100%;
    height: var(--header-height);
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding-inline: var(--space-4);
    padding-block: 0;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    position: sticky;
    top: 0;
    z-index: 60;
  }

  .admin-sidebar__logo {
    margin-bottom: 0;
    padding-inline: 0;
  }

  .admin-nav {
    position: fixed;
    inset: var(--header-height) 0 0 0;
    z-index: 55;
    background: var(--color-bg);
    padding: var(--space-8) var(--space-6);
    gap: var(--space-1);
    transform: translateY(-110%);
    transition: transform 250ms var(--ease-standard);
    overflow-y: auto;
  }

  .admin-nav.is-open {
    transform: translateY(0);
  }

  .admin-nav__link {
    border-left: none;
    font-size: 1.125rem;
    padding: var(--space-3) 0;
  }

  .admin-nav__link--actif {
    border-left-color: transparent;
    background: none;
  }

  .admin-nav__deconnexion {
    margin-top: var(--space-6);
    border-top: 1px solid var(--color-border);
    padding-top: var(--space-6);
  }

  .admin-nav__deconnexion button {
    padding: var(--space-3) 0;
    font-size: 1.125rem;
  }

  .admin-main {
    padding: var(--space-4);
  }
}

/* Connexion / mot de passe oublié — carte centrée, cf.
   design-system-figma/ecrans/connexion*.svg */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-4);
}

.auth-card {
  width: 100%;
  max-width: 24rem;
  padding: var(--space-8);
}

.auth-card__logo {
  display: block;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--color-text);
  text-decoration: none;
  margin-bottom: var(--space-2);
}

.auth-card__kicker {
  display: block;
  text-align: center;
  color: var(--color-text-discret);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: var(--space-6);
}

.auth-card h1 {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  margin-bottom: var(--space-4);
}

.auth-card form {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

/* ==========================================================================
   Téléversement de pièces jointes (formulaire de devis)
   - cf. classes/upload-devis.js : dropzone accessible + liste
   - la dropzone est un <label for="pieces-jointes"> qui enveloppe un
     <input type="file"> positionné en absolu (inset:0) → le clic sur
     la dropzone OUVRE LE SELECTEUR NATIF via le mécanisme label-for
     (pas de click() synthétique, plus fiable cross-browser et plus
     accessible). Le drag/drop ajoute un handler JS par-dessus.
   ========================================================================== */

.devis-upload {
  margin-top: var(--space-3);
  display: grid;
  gap: var(--space-3);
}

/* Input natif : couvre toute la dropzone, invisible mais cliquable.
   pointer-events:none sur l'input lui-même : c'est le <label> parent
   qui capte le clic, pas l'input directement. L'input reste toutefois
   focusable au clavier (Tab) — son focus ouvre aussi le sélecteur
   dans certains navigateurs. */
.devis-upload__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
  border: 0;
  padding: 0;
  margin: 0;
}

.devis-upload__dropzone {
  position: relative; /* contexte pour input absolute */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  border: 2px dashed var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-secondary);
  color: var(--color-text-secondary);
  cursor: pointer;
  text-align: center;
  transition:
    border-color 0.2s var(--ease-standard),
    background 0.2s var(--ease-standard),
    color 0.2s var(--ease-standard);
}

.devis-upload__dropzone:hover,
.devis-upload__dropzone:focus-within {
  border-color: var(--color-accent);
  color: var(--color-text);
  background: var(--color-bg-secondary-hover);
  outline: none;
}

.devis-upload__dropzone--actif {
  border-color: var(--color-accent);
  background: var(--color-bg-secondary-hover);
  color: var(--color-text);
}

.devis-upload__dropzone--inactif {
  opacity: 0.6;
  cursor: not-allowed;
}

.devis-upload__dropzone svg {
  color: var(--color-accent);
  position: relative;
  z-index: 0;
  pointer-events: none;
}

.devis-upload__dropzone-label {
  font-size: 0.95rem;
  line-height: 1.4;
  position: relative;
  z-index: 0;
  pointer-events: none;
}

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

.devis-upload__item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  animation: devis-upload-entree 0.2s var(--ease-standard);
}

@keyframes devis-upload-entree {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.devis-upload__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0; /* autorise la troncature du nom */
}

.devis-upload__nom {
  font-size: 0.95rem;
  color: var(--color-text);
}

.devis-upload__details {
  font-size: 0.8rem;
  color: var(--color-text-discret);
}

.devis-upload__retirer {
  appearance: none;
  background: transparent;
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background 0.15s var(--ease-standard),
    border-color 0.15s var(--ease-standard),
    color 0.15s var(--ease-standard);
}

.devis-upload__retirer:hover,
.devis-upload__retirer:focus-visible {
  background: var(--color-error);
  border-color: var(--color-error);
  color: var(--color-text);
  outline: none;
}

.devis-upload__statut {
  margin: 0;
  min-height: 1.2em;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
}

.devis-upload--complet .devis-upload__dropzone {
  border-style: solid;
  border-color: var(--color-accent);
  color: var(--color-text-discret);
}

@media (prefers-reduced-motion: reduce) {
  .devis-upload__item {
    animation: none;
  }
}

/* ==========================================================================
   Page d'erreur (404) — zone centrale centrée.
   Même langage que le hero : gradient radial discret (palette accent/primary),
   typographie display pour le code, boutons existants. Remplit la hauteur
   sous l'en-tête pour éviter l'impression de vide sur grand écran, sans
   toucher au header/footer ni au reste du site. Pas d'animation ajoutée.
   ========================================================================== */
.page-erreur {
  min-height: calc(100vh - var(--header-height));
  display: flex;
  align-items: center;
  background:
    radial-gradient(40rem 24rem at 78% -10%, rgba(76, 141, 255, 0.16), transparent 60%),
    radial-gradient(38rem 22rem at 18% 112%, rgba(74, 196, 200, 0.10), transparent 60%),
    var(--color-bg);
}

.erreur {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  max-width: 40rem;
  margin-inline: auto;
}

/* Code 404 en repère visuel — décoratif (aria-hidden), dégradé teal→bleu
   repris des effets de survol, jamais en couleur unique pour rester lisible
   sur le fond sombre. */
.erreur__code {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(6.5rem, 26vw, 13rem);
  line-height: 0.82;
  letter-spacing: -0.04em;
  background: linear-gradient(135deg, var(--color-accent) 10%, var(--color-primary) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.erreur .section-lead {
  margin-top: 0;
}

.erreur__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

/* Sur la 404, « Page introuvable » remplace le titre supprimé : on le grandit
   légèrement par rapport à l'eyebrow standard sans toucher au reste du site. */
.erreur .erreur__nom {
  font-size: 1.25rem;
  letter-spacing: 0.06em;
}
/* ==========================================================================
   Mise en avant (cf. 5. Mise en avant.md) — preuve sociale, devis en
   étapes, page partenaire Comptoir de l'éclairage.
   ========================================================================== */

/* Teintes LED du partenariat (ampoule du Comptoir) — réservées au logo
   animé, pas à l'interface. */
:root {
  --led-1: #e5484d;
  --led-2: #f9b233;
  --led-3: #f2e13a;
  --led-4: #46c26b;
  --led-5: #4ac4c8;
  --led-6: #8e6cf0;
  --led-7: #e04ad9;
}

/* --- Preuve sociale sous le hero ---------------------------------------- */
.preuve-sociale {
  border-block: 1px solid var(--color-border);
  background: var(--color-bg-creux);
  padding-block: var(--space-12);
}

.preuve-sociale .container {
  display: grid;
  /* minmax(0, 1fr) : la colonne ne s'élargit pas à la largeur du bandeau
     défilant (max-content), sinon la page déborde à droite. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-12);
}

.preuve-sociale__groupe {
  min-width: 0;
}

.preuve-sociale__intitule {
  color: var(--color-text-discret);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-6);
  text-align: center;
}

.preuve-sociale__logos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-8) var(--space-12);
}

/* Marques : grille régulière (3 colonnes, 6 sur grand écran), séparée
   des certifications par un filet. Disposition fixe : un défilement
   attirait trop l'œil pour une simple preuve sociale. */
.preuve-sociale__groupe--marques {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-12);
}

.preuve-sociale__groupe--marques .preuve-sociale__logos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  justify-items: center;
  gap: var(--space-8) var(--space-6);
  max-width: 64rem;
  margin-inline: auto;
}

.preuve-sociale__groupe--marques .preuve-sociale__logo img {
  max-width: 100%;
}

@media (min-width: 64rem) {
  .preuve-sociale__groupe--marques .preuve-sociale__logos {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

.preuve-sociale__logo {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  border-radius: var(--radius-sm);
  opacity: 0.9;
  transition: opacity 150ms var(--ease-standard), transform 150ms var(--ease-standard);
  text-decoration: none;
}

.preuve-sociale__logo img {
  height: 3rem;
  width: auto;
  /* Logos très horizontaux (Fontini, Meljac) : même poids visuel que les autres. */
  max-width: 8.5rem;
  object-fit: contain;
}

/* Badges de certification circulaires : texte fin, ils ont besoin de plus
   de hauteur pour rester lisibles. Classe explicite plutôt que :first-child
   (le h2 masqué précède le premier groupe). */
.preuve-sociale__groupe--certifications .preuve-sociale__logo img {
  height: 7rem;
  max-width: 15rem;
}

.preuve-sociale__texte {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--color-text);
  letter-spacing: 0.02em;
}

a.preuve-sociale__logo:hover,
a.preuve-sociale__logo:focus-visible {
  opacity: 1;
  transform: translateY(-1px);
}

@media (min-width: 64rem) {
  .preuve-sociale__logo img {
    height: 3.75rem;
    max-width: 11rem;
  }

  .preuve-sociale__groupe--certifications .preuve-sociale__logo img {
    height: 10rem;
    max-width: 22rem;
  }

  .preuve-sociale__texte {
    font-size: 1.5rem;
  }
}

/* --- Appel au devis (accueil, page partenaire) --------------------------- */
.devis-appel {
  display: grid;
  gap: var(--space-8);
  align-items: end;
}

.devis-appel__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

@media (min-width: 64rem) {
  .devis-appel {
    grid-template-columns: 1fr auto;
  }
}

/* --- Page /devis ---------------------------------------------------------- */
.devis-page {
  padding-top: calc(var(--header-height) + var(--space-12));
}

.devis-page__titre {
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 7vw, 4rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 0.98;
  margin-top: var(--space-2);
}

.devis-confirmation {
  display: grid;
  gap: var(--space-6);
  max-width: 48rem;
  margin-top: var(--space-12);
}

.devis-form--etapes {
  max-width: 56rem;
}

.devis-form [hidden] {
  display: none !important;
}

.devis-etape {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  min-width: 0;
  scroll-margin-top: calc(var(--header-height) + var(--space-4));
}

.devis-etape:focus {
  outline: none;
}

@media (min-width: 40rem) {
  .devis-etape--grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.devis-etape__titre {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  margin-bottom: var(--space-6);
  padding: 0;
}

.devis-etape__numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--tint-accent-12);
  color: var(--color-accent);
  font-size: 0.9375rem;
}

.devis-progression {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0;
  margin: 0;
  list-style: none;
  counter-reset: etape;
}

.devis-progression__etape {
  counter-increment: etape;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  color: var(--color-text-discret);
  font-size: 0.8125rem;
  font-weight: 600;
}

.devis-progression__etape::before {
  content: counter(etape);
}

.devis-progression__etape--faite {
  color: var(--color-text-secondary);
  border-color: var(--color-text-discret);
}

.devis-progression__etape[aria-current="step"] {
  color: var(--color-text);
  border-color: var(--color-accent);
  background: var(--tint-accent-12);
}

/* Cartes de choix (type de travaux) : un radio natif, visuellement
   masqué mais focusable — la carte entière est le <label>. */
.choix-grille {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

@media (min-width: 48rem) {
  .choix-grille {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.choix-carte {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  cursor: pointer;
  transition: border-color 150ms var(--ease-standard), background-color 150ms var(--ease-standard);
}

.choix-carte input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.choix-carte:hover {
  border-color: var(--color-text-discret);
}

.choix-carte:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--tint-accent-08);
}

.choix-carte:has(input:focus-visible) {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

.choix-carte__icone {
  color: var(--color-accent);
}

.choix-carte__libelle {
  font-weight: 600;
  font-size: 0.9375rem;
  line-height: 1.3;
}

.devis-recap {
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-6);
}

.devis-recap__titre {
  color: var(--color-accent);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: var(--space-3);
}

.devis-recap__liste {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-1) var(--space-4);
  margin: 0;
}

.devis-recap__liste dt {
  color: var(--color-text-discret);
}

.devis-recap__liste dd {
  margin: 0;
}

.devis-navigation {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
}

.devis-navigation [data-suivant] {
  margin-left: auto;
}

/* --- Page partenaire Comptoir de l'éclairage ---------------------------- */
.partenaire-hero {
  padding-block: calc(var(--header-height) + var(--space-12)) var(--space-16);
  background:
    radial-gradient(40rem 24rem at 85% 30%, rgba(142, 108, 240, 0.14), transparent 60%),
    radial-gradient(36rem 22rem at 0% 80%, rgba(74, 196, 200, 0.12), transparent 60%),
    var(--color-bg);
}

/* Hero centré sur une colonne : eyebrow + titre, néon en grand, puis
   les appels à l'action. */
.partenaire-hero__grille {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-8);
  text-align: center;
}

/* Le néon occupe toute la largeur disponible (sinon la colonne flex
   centrée le réduirait à sa largeur intrinsèque), en plus grand qu'ailleurs. */
.partenaire-hero .neon {
  width: 100%;
}

.partenaire-hero .neon__scene {
  max-width: 44rem;
}

.partenaire-hero__texte {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}

.partenaire-hero__actions {
  justify-content: center;
}

/* ELECDIFFUSION × logo sur une ligne ; passe à la ligne sur mobile. */
.partenaire-hero__titre {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 7vw, 3.75rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
}

.partenaire-hero__comptoir {
  display: block;
}

/* Hauteur ≈ 2 lignes de titre : même poids visuel que le mot
   ELECDIFFUSION sans écraser la ligne. */
.partenaire-hero__comptoir img {
  height: clamp(5rem, 14vw, 7.5rem);
  width: auto;
}

/* « avec » entre les deux marques : petit, en texte courant, pour ne pas
   rivaliser avec les noms. */
.partenaire-hero__liaison {
  font-family: var(--font-body);
  font-size: 0.4em;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--color-text-secondary);
}

/* Petit écran : ELECDIFFUSION / avec / logo empilés et centrés, plutôt
   qu'un « avec » accroché en fin de première ligne. */
@media (max-width: 39.999rem) {
  .partenaire-hero__titre {
    flex-direction: column;
    gap: var(--space-2);
  }
}

.partenaire-hero__texte .section-lead {
  margin-top: 0;
}

/* Logo néon (reproduction de la vidéo du partenariat). Les règles décrivent
   l'état FINAL : fil multicolore, prise verte, ampoule du Comptoir à la
   place de celle du site, éclair allumé façon LED. Sans JS ou avec
   prefers-reduced-motion, c'est ce qui s'affiche ; sinon
   classes/logo-partenaire.js part de l'état cyan et joue la séquence.
   Aucun halo : traits nets, seules les couleurs font l'effet néon. */
.neon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}

.neon__scene {
  width: 100%;
  max-width: 36rem;
  height: auto;
  overflow: visible;
}

.neon__trait,
.neon__comptoir-verre,
.neon__comptoir-culot,
.neon__rayon,
.neon__etincelle {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.neon__trait {
  stroke-width: 2.152;
}

/* Calque de départ : néon cyan. */
.neon__prise,
.neon__fil,
.neon__ampoule-origine {
  stroke: var(--color-accent);
}

.neon__ampoule-origine {
  opacity: 0;
}

/* Calque final : couleurs de la vidéo. */
.neon__fil-couleurs {
  stroke: url(#neon-arc-en-ciel);
}

.neon__prise-verte {
  stroke: var(--led-4);
}

.neon__stop--1 { stop-color: var(--led-6); }
.neon__stop--2 { stop-color: var(--led-1); }
.neon__stop--3 { stop-color: var(--led-2); }
.neon__stop--4 { stop-color: var(--led-3); }
.neon__stop--5 { stop-color: var(--led-7); }

/* Éclair final « LED » : cœur clair et contour ambre franc, sans halo. Le
   scintillement d'allumage est joué par classes/logo-partenaire.js. */
.neon__eclair {
  fill: #ffe9a8;
  stroke: var(--color-bolt);
  stroke-width: 0.9;
  stroke-linejoin: round;
}

/* Ampoule du Comptoir de l'éclairage (cf. image de référence fournie,
   sans l'anneau). */
.neon__comete-trait {
  fill: none;
}

/* Ampoule chromée et culot. */
.neon__comptoir-verre,
.neon__comptoir-culot {
  stroke: url(#neon-chrome);
  stroke-width: 1.5;
}

.neon__comptoir-pointe {
  fill: url(#neon-chrome);
}

/* Traînée rouge en comète, du bord gauche vers l'ampoule. */
.neon__comete-trait {
  stroke: #ff3b30;
  stroke-width: 1.4;
  stroke-linecap: round;
}

.neon__comete-trait--moyen {
  stroke-width: 0.95;
}

.neon__comete-trait--fin {
  stroke-width: 0.6;
}

.neon__rayon {
  stroke-width: 1.8;
}

/* Rayons LED : violet, bleu, vert, orange, rouge (référence). */
.neon__rayon:nth-child(1) { stroke: #8e5cf0; }
.neon__rayon:nth-child(2) { stroke: #3b8cff; }
.neon__rayon:nth-child(3) { stroke: #2fd27a; }
.neon__rayon:nth-child(4) { stroke: #ff9a2e; }
.neon__rayon:nth-child(5) { stroke: #ff4a3a; }

.neon__etincelle {
  stroke: #fff;
  stroke-width: 3.4;
  opacity: 0;
}

.demarche-grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-12);
  padding: 0;
  list-style: none;
}

@media (min-width: 48rem) {
  .demarche-grille {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 75rem) {
  .demarche-grille {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* Badge « Étape N » : rend explicite l'enchaînement des cartes. */
.demarche-etape .demarche-etape__numero {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-bolt);
  border-radius: var(--radius-pill);
  color: var(--color-bolt);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-4);
}

.demarche-etape__lien {
  margin-top: var(--space-4);
  font-weight: 600;
}

.demarche-etape__lien a {
  color: var(--color-accent);
}

.partenaire-vide {
  margin-top: var(--space-8);
  color: var(--color-text-secondary);
}

/* Produit à la une, accueil sous le hero (dernier post Instagram #alaune) : photo au-dessus du
   texte sur mobile, deux colonnes à partir de la tablette. */
.a-la-une__carte {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background:
    radial-gradient(30rem 18rem at 100% 0%, rgba(249, 178, 51, 0.1), transparent 60%),
    var(--color-bg-secondary);
}

.a-la-une__media {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--color-bg-secondary-hover);
}

.a-la-une__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.a-la-une__texte {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
}

.a-la-une__badge {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-bolt);
  border-radius: var(--radius-pill);
  color: var(--color-bolt);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.a-la-une__titre {
  font-size: clamp(1.5rem, 4vw, 2.25rem);
  line-height: 1.15;
}

.a-la-une__accroche {
  color: var(--color-text-secondary);
}

.a-la-une__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

@media (min-width: 48rem) {
  .a-la-une__carte {
    grid-template-columns: 1.1fr 1fr;
    align-items: center;
    gap: var(--space-12);
    padding: var(--space-8);
  }
}
