/* ==========================================================================
   Dev Lepsor — système graphique
   Modernisme suisse / affiche 60-70 — exécution contemporaine.
   HTML / CSS / JS pur, sans build. Une seule feuille de style pour tout le
   site : c'est délibéré pour un portfolio de cette taille (5 pages) plutôt
   que de fragmenter en plusieurs petits fichiers à recharger.
   ========================================================================== */

/* ---- Police auto-hébergée (Archivo Variable, axes weight + width) ---- */
@font-face {
  font-family: 'Archivo Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  src: url('../fonts/archivo-latin-wdth-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ---- Couleurs ---- */
  --color-cream: #f2e8d8;
  --color-cream-tint: #e9ddc7;
  --color-ink: #1e1e1e;
  --color-ink-soft: rgba(30, 30, 30, 0.66);
  --color-ink-faint: rgba(30, 30, 30, 0.14);
  --color-bordeaux: #7c2d2d;
  --color-bordeaux-dark: #5e2222;
  --color-terracotta: #c46a3a;
  --color-terracotta-dark: #a4552b;

  --surface: var(--color-cream);
  --ink: var(--color-ink);
  --ink-soft: var(--color-ink-soft);

  /* ---- Typographie ---- */
  --font-sans: 'Archivo Variable', 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --fs-display: clamp(2.75rem, 2rem + 5.2vw, 6.75rem);
  --fs-h1: clamp(2.25rem, 1.7rem + 3.6vw, 4.25rem);
  --fs-h2: clamp(1.75rem, 1.4rem + 2vw, 2.75rem);
  --fs-h3: clamp(1.25rem, 1.1rem + 0.8vw, 1.625rem);
  --fs-index: clamp(3.5rem, 2rem + 8vw, 8rem);
  --fs-index-sm: clamp(1.75rem, 1.4rem + 1.5vw, 2.5rem);
  --fs-lg: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
  --fs-body: 1.0625rem;
  --fs-small: 0.875rem;
  --fs-micro: 0.75rem;

  --lh-tight: 1.02;
  --lh-snug: 1.2;
  --lh-body: 1.6;

  /* ---- Espacement (échelle éditoriale) ---- */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;
  --sp-10: 8rem;
  --sp-11: 11rem;

  --margin: clamp(1.25rem, 0.7rem + 2.6vw, 4rem);
  --gutter: clamp(0.75rem, 0.5rem + 1vw, 1.5rem);
  --container-max: 90rem;

  /* ---- Mouvement ---- */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast: 150ms;
  --dur-base: 260ms;
  --dur-slow: 480ms;

  --radius: 3px;
  --hairline: 1px solid var(--color-ink-faint);
  --hairline-dark: 1px solid rgba(242, 232, 216, 0.18);

  color-scheme: light;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Réserve toujours la place de la barre de scroll verticale, même sur une
     page assez courte pour ne pas en avoir besoin. Sinon, changer de page
     entre une page longue et une page courte décale tout le contenu de
     quelques pixels à l'horizontale au moment du changement. */
  scrollbar-gutter: stable;
  overflow-y: scroll;
}

html,
body {
  /* Filet de sécurité : aucune section ne doit pouvoir pousser la page en
     scroll horizontal (mot trop long, grille mal contrainte, etc). */
  overflow-x: hidden;
}

/* Bloque le scroll de la page pendant qu'une fenêtre de démo est ouverte
   par-dessus (voir setupProjectDemo dans main.js). */
html.modal-open,
html.modal-open body {
  overflow: hidden;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh; /* tient compte de la barre d'adresse mobile qui apparaît/disparaît */
  display: flex;
  flex-direction: column;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-feature-settings: 'tnum' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: inherit;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

h1,
h2,
h3,
h4,
p,
figure {
  margin: 0;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

input,
textarea {
  font: inherit;
}

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

::selection {
  background: var(--color-bordeaux);
  color: var(--color-cream);
}

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

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  background: var(--color-ink);
  color: var(--color-cream);
  padding: var(--sp-3) var(--sp-5);
  z-index: 100;
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease);
}

.skip-link:focus {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Typographie — hiérarchie
   ========================================================================== */

.type-display,
.type-h1,
.type-h2,
.type-h3 {
  overflow-wrap: break-word;
}

.type-display {
  font-family: var(--font-sans);
  font-variation-settings: 'wght' 800, 'wdth' 118;
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.type-h1 {
  font-variation-settings: 'wght' 750, 'wdth' 112;
  font-size: var(--fs-h1);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

.type-h2 {
  font-variation-settings: 'wght' 700, 'wdth' 108;
  font-size: var(--fs-h2);
  line-height: var(--lh-snug);
  letter-spacing: -0.005em;
  text-transform: uppercase;
}

.type-h3 {
  font-variation-settings: 'wght' 650, 'wdth' 100;
  font-size: var(--fs-h3);
  line-height: var(--lh-snug);
}

.type-lg {
  font-variation-settings: 'wght' 440, 'wdth' 100;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
}

.type-body {
  font-variation-settings: 'wght' 420, 'wdth' 100;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.type-small {
  font-variation-settings: 'wght' 500, 'wdth' 100;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
}

.type-micro {
  font-size: var(--fs-micro);
  letter-spacing: 0.04em;
}

.type-label {
  font-variation-settings: 'wght' 600, 'wdth' 105;
  font-size: var(--fs-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ==========================================================================
   Mise en page
   ========================================================================== */

.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.grid-12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
}

.grid-12 > * {
  min-width: 0;
}

.section {
  position: relative;
  padding-block: var(--sp-10);
  border-top: var(--hairline);
}

.section--dark {
  background: var(--color-ink);
  color: var(--color-cream);
  border-top: none;
}

.section--dark .type-label {
  color: rgba(242, 232, 216, 0.55);
}

/* ---- Apparition du contenu (voir revealPage dans main.js) ----
   #main et le footer commencent invisibles et passent à opacity: 1 quand
   la page est prête — au tout premier chargement comme après un changement
   de page (voir setupPageTransitions), exactement de la même façon à
   chaque fois. Un seul mécanisme d'entrée, rien qui puisse se chevaucher
   avec autre chose. Scopé à html.js : sans JavaScript, ces règles ne
   s'appliquent jamais et le contenu reste simplement visible. */
html.js #main,
html.js .site-footer {
  opacity: 0;
}

html.js #main.is-visible,
html.js .site-footer.is-visible {
  opacity: 1;
}

#main {
  flex: 1 0 auto; /* pousse le footer en bas même quand une page a peu de contenu */
  transition: opacity 320ms var(--ease);
}

.site-footer {
  flex-shrink: 0;
  transition: opacity 320ms var(--ease);
}

/* ==========================================================================
   Composants partagés
   ========================================================================== */

.link-underline {
  position: relative;
  text-decoration: none;
  padding-bottom: 0.15em;
}

.link-underline::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease);
}

.link-underline:hover::after,
.link-underline:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* Page courante dans la nav (posé en JS, voir setupActiveNav dans main.js) :
   le soulignement reste affiché, et le lien n'est plus cliquable pour éviter
   de relancer une navigation vers la page déjà affichée. */
.link-underline[aria-current='page'] {
  pointer-events: none;
}

.link-underline[aria-current='page']::after {
  transform: scaleX(1);
  transform-origin: left;
}

.mobile-nav a[aria-current='page'] {
  color: var(--color-bordeaux);
  pointer-events: none;
}

.eyebrow {
  color: var(--color-bordeaux);
}

.section--dark .eyebrow {
  color: var(--color-terracotta);
}

/* ==========================================================================
   Aplats — blocs de couleur pleine avec un rôle (contenir, séparer, marquer)
   ========================================================================== */

.panel {
  padding: var(--sp-6);
}

.panel--bordeaux {
  background: var(--color-bordeaux);
  color: var(--color-cream);
}

.panel--terracotta {
  background: var(--color-terracotta);
  color: var(--color-cream);
}

.panel--ink {
  background: var(--color-ink);
  color: var(--color-cream);
}

.panel--tint {
  background: var(--color-cream-tint);
  color: var(--ink);
}

.panel .eyebrow,
.panel--bordeaux .type-label,
.panel--terracotta .type-label,
.panel--ink .type-label {
  color: inherit;
  opacity: 0.72;
}

.panel--cut-bl {
  --cut: clamp(1.5rem, 1rem + 2vw, 3rem);
  clip-path: polygon(0 0, 100% 0, 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
}

.num-block {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  min-width: 3.5rem;
  padding: var(--sp-2);
  font-variation-settings: 'wght' 800, 'wdth' 112;
  font-size: var(--fs-h3);
  line-height: 1;
}

/* ==========================================================================
   En-tête
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--surface);
  border-bottom: var(--hairline);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--sp-4);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  font-variation-settings: 'wght' 750, 'wdth' 112;
  font-size: var(--fs-small);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
}

.wordmark__mark {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  background: var(--color-bordeaux);
  flex-shrink: 0;
}

.site-nav ul {
  display: flex;
  gap: var(--sp-7);
}

.site-nav {
  display: none;
}

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
}

.menu-toggle__bars,
.menu-toggle__bars::before,
.menu-toggle__bars::after {
  display: block;
  width: 1.4rem;
  height: 1.5px;
  background: var(--color-ink);
}

.menu-toggle__bars::before,
.menu-toggle__bars::after {
  content: '';
  position: relative;
}

.menu-toggle__bars::before {
  top: 0.4rem;
}

.menu-toggle__bars::after {
  top: -0.4rem;
}

.mobile-nav {
  border-top: var(--hairline);
  padding: var(--sp-6) var(--margin) var(--sp-8);
}

.mobile-nav ul {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

.mobile-nav a {
  text-decoration: none;
  text-transform: uppercase;
}

@media (min-width: 56rem) {
  .site-nav {
    display: block;
  }
  .menu-toggle {
    display: none;
  }
}

/* ==========================================================================
   Pied de page
   ========================================================================== */

.site-footer {
  padding-block: var(--sp-9) var(--sp-6);
}

.footer-grid {
  display: grid;
  gap: var(--sp-7);
  padding-bottom: var(--sp-8);
}

.footer-tagline {
  margin-top: var(--sp-3);
  color: rgba(242, 232, 216, 0.66);
  max-width: 24rem;
}

.footer-nav ul {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.footer-contact a {
  text-decoration: none;
}

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

/* ==========================================================================
   Motifs graphiques réutilisés (arc, visuel de projet, vague)
   ========================================================================== */

.project-visual {
  margin: 0;
  overflow: hidden;
}

.project-visual svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* Cadre neutre pour les projets de la liste, en attendant de vraies
   captures (voir projets.html) — pas de composition générée pour ceux-là,
   juste un aplat. */
.project-visual--placeholder {
  width: 100%;
  background: var(--color-cream-tint);
}

/* Carrousel de captures d'écran, pour un projet avec plusieurs visuels.
   Le défilement tactile/trackpad marche nativement grâce à scroll-snap ;
   flèches et points (voir setupProjectCarousels dans main.js) sont sous
   l'image, pas dessus — voir .project-carousel plus bas. */
.project-visual--carousel {
  width: 100%;
  border: var(--hairline);
}

.project-carousel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.project-carousel__track {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.project-carousel__track::-webkit-scrollbar {
  display: none;
}

.project-carousel__slide {
  flex: 0 0 100%;
  height: 100%;
  margin: 0;
  scroll-snap-align: start;
  background: var(--color-cream-tint);
}

.project-carousel__slide img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.project-carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}

.project-carousel__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: 1.5px solid var(--color-ink-faint);
  border-radius: 50%;
  background: none;
  color: var(--ink-soft);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.project-carousel__nav:hover,
.project-carousel__nav:focus-visible {
  border-color: var(--color-bordeaux);
  color: var(--color-bordeaux);
}

.project-carousel__dots {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.project-carousel__dot {
  width: 0.4rem;
  height: 0.4rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-ink-faint);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}

.project-carousel__dot.is-active {
  background: var(--color-bordeaux);
  transform: scale(1.3);
}

.projet[data-accent='terracotta'] .project-carousel__nav:hover,
.projet[data-accent='terracotta'] .project-carousel__nav:focus-visible {
  border-color: var(--color-terracotta-dark);
  color: var(--color-terracotta-dark);
}

.projet[data-accent='terracotta'] .project-carousel__dot.is-active {
  background: var(--color-terracotta-dark);
}


/* ==========================================================================
   Page : Accueil
   ========================================================================== */

.hero {
  border-top: none;
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100dvh; /* tient compte de la barre d'adresse mobile qui apparaît/disparaît */
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.hero__layout {
  display: grid;
  row-gap: var(--sp-8);
  padding-block: var(--sp-8) var(--sp-9);
}

.hero__text {
  padding-top: var(--sp-4);
  min-width: 0;
}

.hero__text h1 {
  margin-top: var(--sp-4);
  font-size: clamp(2.5rem, 1.7rem + 4vw, 4.75rem);
}

.hero__subhead {
  max-width: 32rem;
  margin-top: var(--sp-6);
  color: var(--ink-soft);
}

.hero__panel {
  min-width: 0;
  aspect-ratio: 4 / 3;
}

.hero__panel .project-visual {
  height: 100%;
}

@media (min-width: 64rem) {
  .hero__layout {
    grid-template-columns: repeat(12, 1fr);
    column-gap: var(--gutter);
    align-items: center;
    padding-block: var(--sp-9) var(--sp-10);
  }
  .hero__text {
    grid-column: 1 / span 7;
  }
  .hero__panel {
    grid-column: 8 / -1;
  }
}

/* ---- Hero "titre + visuel" réutilisé sur Projets, Skills et FAQ ----
   Même principe que .hero__layout sur l'accueil (texte à gauche, visuel à
   droite dès le desktop), mais en plus compact : ces pages n'ont pas besoin
   d'un hero plein écran comme la home. */
.page-hero__layout {
  display: grid;
  row-gap: var(--sp-6);
  align-items: center;
}

.page-hero__text h1 {
  /* Même réduction que .hero__text h1 sur l'accueil : --fs-display seul est
     dimensionné pour toute la largeur du conteneur, pas pour une colonne
     de 7/12 à côté d'un visuel — sans ça, un mot un peu long ("réalisations")
     retombe seul sur sa ligne. */
  font-size: clamp(2.5rem, 1.7rem + 4vw, 4.75rem);
}

.page-hero__visual {
  min-width: 0;
  aspect-ratio: 4 / 3;
}

.page-hero__visual .project-visual {
  height: 100%;
}

@media (min-width: 64rem) {
  .page-hero__layout {
    grid-template-columns: repeat(12, 1fr);
    column-gap: var(--gutter);
  }
  .page-hero__text {
    grid-column: 1 / span 7;
  }
  .page-hero__visual {
    grid-column: 8 / -1;
  }
}

/* ==========================================================================
   Page : Projets
   ========================================================================== */

.projets-hero {
  border-top: none;
  padding-block: var(--sp-9) var(--sp-8);
}

.projets__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-10);
}

.projet:not(:first-child) {
  padding-top: var(--sp-10);
  border-top: var(--hairline);
}

.projet__grid {
  row-gap: var(--sp-6);
}

.projet__marker {
  grid-column: 1 / -1;
}

.projet__visual {
  grid-column: 1 / -1;
}

.projet__visual .project-visual {
  width: 100%;
  aspect-ratio: 7 / 4;
}

.projet__content {
  grid-column: 1 / -1;
}

.projet__title {
  margin-top: var(--sp-2);
}

.projet__summary {
  margin-top: var(--sp-4);
  color: var(--ink-soft);
  max-width: 34rem;
}

.projet__details {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  margin-top: var(--sp-7);
  padding-top: var(--sp-6);
  border-top: var(--hairline);
}

.projet__details dt {
  margin-bottom: var(--sp-2);
  color: var(--color-bordeaux);
}

.projet[data-accent='terracotta'] .projet__details dt {
  color: var(--color-terracotta-dark);
}

.projet__details dd {
  margin: 0;
  max-width: 38rem;
  color: var(--ink-soft);
}

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

/* Précision honnête pour les projets réalisés à titre d'aperçu (voir
   projets.html) : pas de site/appli réellement en ligne derrière. */
.projet__concept-note {
  margin-top: var(--sp-4);
  color: var(--color-ink-faint);
  font-style: italic;
}

/* Même traitement que .skills__tag, en simple étiquette (pas de bouton ici,
   juste la technologie citée). */
.projet__tech-tag {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small);
  font-variation-settings: 'wght' 550, 'wdth' 102;
}

/* Visuel de la carte "démo interactive" : purement décoratif, seul le
   bouton "Tester la démo" plus bas déclenche l'ouverture (voir
   setupProjectDemo dans main.js). */
.project-visual--demo {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bordeaux);
}

.project-visual__demo-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--color-cream);
  color: var(--color-bordeaux);
  font-size: 1.1rem;
  padding-left: 0.2rem; /* recentre visuellement le triangle "lecture" */
}

.projet__demo-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-small);
  font-variation-settings: 'wght' 650, 'wdth' 106;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--color-bordeaux);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}

.projet__demo-trigger:hover,
.projet__demo-trigger:focus-visible {
  color: var(--color-bordeaux-dark);
}

.projet__demo-trigger span {
  transition: transform var(--dur-fast) var(--ease);
}

.projet__demo-trigger:hover span,
.projet__demo-trigger:focus-visible span {
  transform: translateX(0.3em);
}

@media (min-width: 64rem) {
  .projet__marker {
    grid-column: 1 / span 1;
    grid-row: 1;
  }
  .projet:nth-child(even) .projet__visual {
    grid-column: 8 / span 5;
    grid-row: 1 / span 2;
  }
  .projet:nth-child(even) .projet__content {
    grid-column: 2 / span 6;
    grid-row: 1;
  }
  .projet:nth-child(odd) .projet__visual {
    grid-column: 2 / span 5;
    grid-row: 1 / span 2;
  }
  .projet:nth-child(odd) .projet__content {
    grid-column: 7 / span 6;
    grid-row: 1;
  }
}

/* ---- Fenêtre de démo (voir setupProjectDemo dans main.js) ----
   Une fenêtre en avant-plan par-dessus le site, pas une nouvelle page :
   fond assombri + panneau centré, fermeture par la croix, le fond, ou
   Échap. */
.demo-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--margin);
}

.demo-modal[hidden] {
  display: none;
}

.demo-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(30, 30, 30, 0.6);
}

.demo-modal__panel {
  position: relative;
  width: 100%;
  max-width: 64rem;
  max-height: 94vh;
  overflow-y: auto;
  background: var(--color-cream);
  border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(30, 30, 30, 0.35);
}

.demo-modal__header {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--sp-6);
  background: var(--color-ink);
  color: var(--color-cream);
}

/* Accent bordeaux uniquement dans toute cette fenêtre (même accent que sur
   la carte du projet) : pas de terracotta ici, même si c'est la convention
   habituelle des éléments "eyebrow" sur fond sombre ailleurs sur le site —
   mélanger les deux accents dans une même composition n'est pas voulu. */
.demo-modal__header .eyebrow {
  color: rgba(242, 232, 216, 0.6);
}

.demo-modal__close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease);
}

.demo-modal__close:hover,
.demo-modal__close:focus-visible {
  background: rgba(242, 232, 216, 0.15);
}

.demo-modal__body {
  padding: var(--sp-6);
}

.demo-tool__hint {
  margin-top: var(--sp-3);
  color: var(--ink-soft);
}

.demo-tool {
  margin-top: var(--sp-6);
  display: grid;
  gap: var(--sp-7);
}

@media (min-width: 40rem) {
  /* Deux colonnes côte à côte : choix du document à gauche, résultat à
     droite, plutôt que tout empilé dans une fenêtre trop étroite. */
  .demo-tool {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }

  .demo-tool__col:last-child {
    padding-left: var(--sp-7);
    border-left: var(--hairline);
  }
}

.demo-tool__col-label {
  margin-bottom: var(--sp-4);
}

.demo-tool__docs {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.demo-tool__doc {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1.5px solid var(--color-ink-faint);
  border-radius: var(--radius);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}

.demo-tool__doc:hover,
.demo-tool__doc:focus-visible {
  border-color: var(--color-bordeaux);
}

.demo-tool__doc[aria-pressed='true'] {
  border-color: var(--color-bordeaux);
  background: var(--color-cream-tint);
}

.demo-tool__doc-label {
  flex-shrink: 0;
  font-size: var(--fs-micro);
  font-variation-settings: 'wght' 700, 'wdth' 106;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-bordeaux);
}

.demo-tool__doc-preview {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink-soft);
  font-size: var(--fs-micro);
}

.demo-tool__submit {
  display: inline-flex;
  align-items: center;
  margin-top: var(--sp-5);
  padding: var(--sp-3) var(--sp-6);
  border: 0;
  border-radius: var(--radius);
  background: var(--color-bordeaux);
  color: var(--color-cream);
  font: inherit;
  font-size: var(--fs-small);
  font-variation-settings: 'wght' 650, 'wdth' 106;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}

.demo-tool__submit:hover:not(:disabled),
.demo-tool__submit:focus-visible:not(:disabled) {
  background: var(--color-bordeaux-dark);
}

.demo-tool__submit:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Import d'un document (voir setupProjectDemo dans main.js) : un <label>
   stylé en bouton discret, qui déclenche le vrai <input type="file"> cité
   dedans (masqué en .sr-only) — pas besoin de JS pour ouvrir le sélecteur
   de fichiers du système. */
.demo-tool__upload {
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: var(--hairline);
}

.demo-tool__upload-or {
  color: var(--ink-soft);
}

.demo-tool__upload-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}

.demo-tool__upload-label {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-3) var(--sp-5);
  border: 1.5px solid var(--color-bordeaux);
  border-radius: var(--radius);
  color: var(--color-bordeaux);
  font-size: var(--fs-small);
  font-variation-settings: 'wght' 650, 'wdth' 106;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.demo-tool__upload-label:hover,
.demo-tool__upload-label:has(:focus-visible) {
  background: var(--color-bordeaux);
  color: var(--color-cream);
}

/* Import désactivé pour l'instant (voir "En maintenance" à côté) : le
   <input type="file"> est disabled en HTML, ce qui empêche déjà le clic
   d'ouvrir le sélecteur de fichiers — pointer-events retire aussi le survol
   du bouton, et l'opacité montre que ce n'est pas utilisable maintenant. */
.demo-tool__upload-label.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

.demo-tool__upload-note {
  color: var(--color-ink-faint);
  font-style: italic;
}

.demo-tool__upload-label.is-active {
  background: var(--color-bordeaux);
  color: var(--color-cream);
}

.demo-tool__empty {
  color: var(--color-ink-faint);
}

.demo-tool__empty[hidden] {
  display: none;
}

.demo-tool__result {
  margin-top: 0;
}

.demo-tool__result[hidden] {
  display: none;
}

.demo-tool__status {
  color: var(--ink-soft);
}

.demo-tool__status[data-state='loading'] {
  color: var(--color-bordeaux);
}

.demo-tool__tree {
  margin-top: var(--sp-4);
}

.demo-tool__tree-item {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  padding-block: var(--sp-1);
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}

.demo-tool__tree-item.is-visible {
  opacity: 1;
  transform: none;
}

.demo-tool__tree-item::before {
  content: '';
  flex-shrink: 0;
  width: 0.4rem;
  height: 0.4rem;
  background: var(--color-ink-faint);
}

.demo-tool__tree-item--file::before {
  background: var(--color-bordeaux);
}

.demo-tool__tree-item--file {
  font-variation-settings: 'wght' 650, 'wdth' 104;
}

.demo-tool__disclaimer {
  margin-top: var(--sp-6);
  color: var(--color-ink-faint);
}

@media (prefers-reduced-motion: reduce) {
  .demo-tool__tree-item {
    transition: none;
  }
}

/* ==========================================================================
   Page : Skills
   ========================================================================== */

.skills-hero {
  border-top: none;
  padding-block: var(--sp-9) var(--sp-8);
}

.skills-hero__intro {
  margin-top: var(--sp-5);
  color: var(--ink-soft);
  max-width: 34rem;
}

.skills__groups {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
}

.skills__group:not(:first-child) {
  padding-top: var(--sp-8);
  border-top: var(--hairline);
}

@media (min-width: 56rem) {
  /* Colonnes côte à côte plutôt qu'empilées : chaque groupe garde sa
     largeur propre (flex: 1), et la séparation passe d'un trait au-dessus
     à un trait sur le côté gauche. */
  .skills__groups {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--sp-7);
  }

  .skills__group {
    flex: 1;
    min-width: 0;
  }

  .skills__group:not(:first-child) {
    padding-top: 0;
    padding-left: var(--sp-7);
    border-top: none;
    border-left: var(--hairline);
  }
}

.skills__label {
  margin-bottom: var(--sp-5);
}

.skills__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.skills__tag {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-small);
  font-variation-settings: 'wght' 550, 'wdth' 102;
  /* .skills__tag est posé sur un <button> (voir skills.html) : on repart
     des styles par défaut du navigateur. */
  border: 0;
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  transition: opacity var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.skills__tag:hover,
.skills__tag:focus-visible {
  opacity: 0.8;
}

/* Retour tactile immédiat au clic, en plus du changement d'état ci-dessous
   (qui peut prendre un instant à se voir une fois le focus/hover retirés). */
.skills__tag:active {
  transform: scale(0.94);
}

/* Petit indicateur +/– : montre que le bouton est un interrupteur et donne
   son état actuel, en plus du liseré ci-dessous. */
.skills__tag::after {
  content: '+';
  font-variation-settings: 'wght' 700, 'wdth' 102;
  opacity: 0.7;
}

.skills__tag[aria-expanded='true']::after {
  content: '–';
}

/* Skill actuellement ouvert (voir setupSkillTags dans main.js) : un liseré
   pour que ce soit visible au premier coup d'œil, sans changer sa couleur. */
.skills__tag[aria-expanded='true'] {
  box-shadow: inset 0 0 0 1.5px var(--color-cream);
}

@media (prefers-reduced-motion: reduce) {
  .skills__tag:active {
    transform: none;
  }
}

/* Accordéon en CSS Grid : anime la hauteur "auto" du texte d'explication
   sans avoir à la mesurer en JS (contrairement au fondu entre pages plus
   haut, qui a donné du fil à retordre). .skills__tag-desc-wrap est le seul
   élément dont setupSkillTags() bascule la classe .is-open ; tout le reste
   suit par CSS. */
.skills__tag-desc-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 320ms var(--ease);
}

.skills__tag-desc-wrap.is-open {
  grid-template-rows: 1fr;
}

.skills__tag-desc-wrap > .skills__tag-desc {
  overflow: hidden; /* nécessaire pour que la ligne grid puisse aller à 0 */
  min-height: 0;
}

/* Hauteur réservée pour 2 lignes de texte une fois ouvert, que la phrase du
   skill tienne sur une ou deux lignes : sinon la taille du bloc change d'un
   skill à l'autre et ça donne une impression de gigotement à l'ouverture. */
.skills__tag-desc-wrap.is-open > .skills__tag-desc {
  min-height: calc(var(--lh-body) * 2em);
}

.skills__tag-desc {
  margin-top: var(--sp-4);
  color: var(--ink-soft);
  max-width: 34rem;
  opacity: 0;
  transition: opacity 200ms var(--ease);
}

.skills__tag-desc-wrap.is-open .skills__tag-desc {
  opacity: 1;
  transition-delay: 80ms; /* laisse la hauteur commencer à s'ouvrir avant que le texte apparaisse */
}

@media (prefers-reduced-motion: reduce) {
  .skills__tag-desc-wrap,
  .skills__tag-desc {
    transition: none;
  }
}

/* ==========================================================================
   Page : FAQ
   ========================================================================== */

.faq-hero {
  position: relative;
  padding-block: var(--sp-9) var(--sp-9);
  border-bottom: var(--hairline);
}

.faq-hero__title {
  margin-top: var(--sp-4);
  margin-bottom: var(--sp-6);
}

.faq-hero__intro {
  color: var(--ink-soft);
}


.faq__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

/* Une rangée autonome, façon ligne de tableau : un fond, pas de bordure ni
   de numéro pour séparer les questions entre elles. Toute la carte est
   cliquable (voir setupFAQAccordion dans main.js), pas juste la question :
   le padding est donc posé sur l'en-tête et la réponse plutôt que sur la
   carte elle-même, pour que la zone cliquable couvre bien tout l'espace. */
.faq__entry {
  background: var(--color-cream-tint);
  border-radius: var(--radius);
  scroll-margin-top: 6rem;
  cursor: pointer;
}

.faq__entry:target {
  box-shadow: inset 3px 0 0 var(--color-bordeaux);
}

.faq__entry:hover .faq__question {
  color: var(--color-bordeaux);
}

/* Question : posée sur un <button> dans le <h2> (voir faq.html) pour rester
   accessible au clavier, mais visuellement plate — le clic fonctionne
   n'importe où sur la carte, pas seulement ici. */
.faq__question {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-5);
  width: 100%;
  border: 0;
  background: none;
  padding: var(--sp-5) var(--sp-6);
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: inherit;
}

.faq__question:focus-visible {
  color: var(--color-bordeaux);
}

.faq__toggle {
  flex-shrink: 0;
  font-variation-settings: 'wght' 700, 'wdth' 102;
  color: var(--color-ink-faint);
  transition: color var(--dur-fast) var(--ease);
}

.faq__question[aria-expanded='true'] .faq__toggle {
  color: var(--color-bordeaux);
}

/* Accordéon en CSS Grid (même technique que .skills__tag-desc-wrap) :
   anime la hauteur "auto" de la réponse sans avoir à la mesurer en JS. */
.faq__answer-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 320ms var(--ease);
  padding-inline: var(--sp-6);
}

.faq__answer-wrap.is-open {
  grid-template-rows: 1fr;
}

.faq__answer-wrap > .faq__answer {
  overflow: hidden; /* nécessaire pour que la ligne grid puisse aller à 0 */
  min-height: 0;
}

.faq__answer {
  padding-top: var(--sp-1);
  padding-bottom: var(--sp-5); /* fait respirer le bas de la carte une fois ouverte */
  color: var(--ink-soft);
  max-width: 42rem;
  opacity: 0;
  transition: opacity 200ms var(--ease);
}

.faq__answer-wrap.is-open .faq__answer {
  opacity: 1;
  transition-delay: 80ms; /* laisse la hauteur commencer à s'ouvrir avant que le texte apparaisse */
}

@media (prefers-reduced-motion: reduce) {
  .faq__answer-wrap,
  .faq__answer {
    transition: none;
  }
}

/* ==========================================================================
   Page : Contact
   ========================================================================== */

.contact-stamp {
  padding-block: var(--sp-10) var(--sp-11);
  color: var(--color-cream);
}

.contact-stamp__inner {
  max-width: 42rem;
}

.contact-stamp__title {
  margin-top: var(--sp-4);
  /* Taille dédiée : le titre est contraint à 42rem (contact-stamp__inner),
     bien plus étroit que le plein-largeur pour lequel .type-display est
     prévu — sans ça "PARLONS" ne tient pas et se coupe en plein mot. */
  font-size: clamp(2.25rem, 1.5rem + 5vw, 4.5rem);
}

.contact-stamp__intro {
  margin-top: var(--sp-6);
  color: rgba(242, 232, 216, 0.85);
  max-width: 30rem;
}

.contact-stamp__email {
  display: inline-block;
  margin-top: var(--sp-8);
  font-variation-settings: 'wght' 750, 'wdth' 110;
  font-size: clamp(1.5rem, 1rem + 3vw, 2.75rem);
  color: var(--color-cream);
  text-decoration: none;
  border-bottom: 2px solid var(--color-cream);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}

.contact-stamp__email:hover,
.contact-stamp__email.is-copied {
  color: #f2c8a4;
  border-color: #f2c8a4;
}

.contact-stamp__hint {
  margin-top: var(--sp-4);
  color: rgba(242, 232, 216, 0.65);
}

