/* ─────────────────────────────────────────────────────────────────────────
   Mahdi Mcheik — portfolio
   Direction : « event display ». Un vertex, six traces, rien de superflu.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  color-scheme: light;

  /* Plaque photographique : gris froid, jamais crème. */
  --plate: #edeef0;
  --plate-deep: #e3e5e9;
  --ink: #14181f;
  --graphite: #5a6270;
  --hairline: #cfd3da;
  --trace: #0a5c9e;
  --event: #c6316b; /* deux usages sur toute la page. Pas trois. */

  --on-trace: #fff; /* texte posé sur --trace */
  --noise: 0.28; /* coups non reconstruits : présents, pas lisibles */
  --halo: 18%; /* auréole du point d'origine */

  --display: "IBM Plex Sans Condensed", "Arial Narrow", sans-serif;
  --body: "IBM Plex Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --measure: 60ch;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --rule: 1px solid var(--hairline);

  /* Largeur maximale de la colonne de contenu. */
  --page: 1480px;

  /* Marge de chaque bande pleine largeur : la gouttière tant que l'écran est
     étroit, puis ce qu'il faut pour centrer une colonne de --page. Les filets
     continuent de traverser l'écran de bord à bord ; seul le contenu est bridé. */
  --edge: max(var(--gutter), (100% - var(--page)) / 2);
}

/* ── Thème sombre ────────────────────────────────────────────────────────────
   Non pas la plaque inversée, mais l'écran de contrôle : le fond s'éteint, les
   traces s'allument. Le bleu et le magenta remontent en luminosité — sur fond
   noir, les teintes de la plaque perdraient tout contraste.

   Le script d'en-tête pose toujours `data-theme`. Le bloc `:not([data-theme])`
   ne sert donc qu'au cas sans JS, où le bouton est de toute façon masqué. */

:root[data-theme="dark"] {
  color-scheme: dark;

  --plate: #111318;
  --plate-deep: #191c23;
  --ink: #e9ebef;
  --graphite: #949cab;
  --hairline: #2a2e37;
  --trace: #5fa8dd;
  --event: #e8578f;

  --on-trace: #0d1117;
  --noise: 0.45;
  --halo: 28%;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;

    --plate: #111318;
    --plate-deep: #191c23;
    --ink: #e9ebef;
    --graphite: #949cab;
    --hairline: #2a2e37;
    --trace: #5fa8dd;
    --event: #e8578f;

    --on-trace: #0d1117;
    --noise: 0.45;
    --halo: 28%;
  }
}

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--plate);
  color: var(--graphite);
  font: 400 1.0625rem/1.65 var(--body);
  -webkit-font-smoothing: antialiased;
}

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

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0;
}

p {
  margin: 0;
}

/* ── Primitives ──────────────────────────────────────────────────────────── */

.kicker {
  font: 500 0.75rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--graphite);
}

.link {
  color: var(--trace);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}

.link:hover {
  text-decoration-thickness: 2px;
}

a:focus-visible,
.btn:focus-visible,
.burger:focus-visible,
.theme-toggle:focus-visible {
  outline: 2px solid var(--trace);
  outline-offset: 3px;
  border-radius: 1px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--plate);
  padding: 0.75rem 1rem;
  z-index: 10;
}

.skip:focus {
  left: 0;
}

/* ── Masthead ────────────────────────────────────────────────────────────── */

.masthead {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: center;
  justify-content: space-between;
  padding: 1.75rem var(--edge);
  border-bottom: var(--rule);
}

.masthead-name {
  font: 500 0.8125rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink);
  margin-right: auto; /* nav et boutons restent groupés à droite */
}

.masthead-tools {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  /* Absorbe le padding des cibles tactiles sans décaler l'alignement. */
  margin: -0.75rem -0.75rem -0.75rem 0;
}

.masthead-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.masthead-nav a {
  display: block;
  font: 400 0.875rem/1 var(--body);
  color: var(--graphite);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}

.masthead-nav a:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

/* ── Bouton burger ───────────────────────────────────────────────────────────
   Trois filets, à l'image des lignes de la page. Il n'apparaît que sur écran
   étroit, et seulement si le JS a pu s'exécuter. */

.burger,
.theme-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px; /* cible tactile */
  height: 44px;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  color: var(--ink);
  cursor: pointer;
}

/* Sans JS, rien à persister : un bouton qui oublie son état ne vaut pas mieux
   qu'un bouton absent. Le média `prefers-color-scheme` prend le relais. */
html.js .theme-toggle {
  display: inline-flex;
}

.theme-toggle .icon {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25; /* le trait des traces */
  stroke-linecap: round;
  stroke-linejoin: round;
}

.theme-toggle .icon-sun,
:root[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .icon-sun {
  display: block;
}

.theme-toggle:hover {
  color: var(--trace);
}

.burger-lines {
  position: relative;
  display: block;
  width: 20px;
  height: 12px;
}

.burger-lines span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition:
    transform 0.2s ease,
    opacity 0.15s ease;
}

.burger-lines span:nth-child(1) {
  top: 0;
}

.burger-lines span:nth-child(2) {
  top: 5.25px;
}

.burger-lines span:nth-child(3) {
  top: 10.5px;
}

/* Les filets se croisent : le bouton dit ce qu'il fait maintenant. */
.masthead[data-open="true"] .burger-lines span:nth-child(1) {
  transform: translateY(5.25px) rotate(45deg);
}

.masthead[data-open="true"] .burger-lines span:nth-child(2) {
  opacity: 0;
}

.masthead[data-open="true"] .burger-lines span:nth-child(3) {
  transform: translateY(-5.25px) rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .burger-lines span {
    transition: none;
  }
}

/* ── Masthead, écran étroit ──────────────────────────────────────────────── */

@media (max-width: 720px) {
  html.js .burger {
    display: inline-flex;
  }

  /* order + flex-basis 100% : le menu repasse sous la ligne nom + boutons,
     alors qu'il les précède dans le DOM. Vaut aussi sans JS, où le menu
     déplié occupe simplement la seconde ligne. */
  .masthead-menu {
    order: 1;
    flex-basis: 100%;
  }

  html.js .masthead-menu {
    display: none;
  }

  html.js .masthead[data-open="true"] .masthead-menu {
    display: block;
  }

  .masthead-nav {
    flex-direction: column;
    gap: 0;
  }

  /* Des lignes pleine largeur, comme les listes de définitions plus bas. */
  .masthead-nav a,
  .masthead-nav a:hover {
    padding: 0.875rem 0;
    border-bottom: var(--rule);
  }

  .masthead-nav li:last-child a,
  .masthead-nav li:last-child a:hover {
    border-bottom: 0;
  }

  .masthead-nav a:hover {
    color: var(--ink);
  }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  padding: clamp(3rem, 8vw, 7rem) var(--edge) clamp(3rem, 7vw, 6rem);
}

.hero-text > * + * {
  margin-top: 1.5rem;
}

.hero h1 {
  font-size: clamp(2.25rem, 6vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.025em;
}

.hero-role {
  color: var(--trace);
}

.lede {
  max-width: var(--measure);
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  line-height: 1.55;
  color: var(--ink);
}

.lede strong {
  font-weight: 600;
}

.hero-note {
  max-width: var(--measure);
  padding-left: 1.125rem;
  border-left: 2px solid var(--hairline);
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--graphite);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.btn {
  display: inline-block;
  font: 500 0.875rem/1 var(--body);
  letter-spacing: 0.01em;
  text-decoration: none;
  padding: 0.875rem 1.375rem;
  border: 1px solid var(--ink);
  color: var(--ink);
  background: transparent;
  transition:
    background-color 0.15s ease,
    color 0.15s ease;
}

.btn:hover {
  background: var(--plate-deep);
}

.btn-primary {
  background: var(--ink);
  color: var(--plate);
}

.btn-primary:hover {
  background: var(--trace);
  border-color: var(--trace);
  color: var(--on-trace);
}

/* ── Event display ───────────────────────────────────────────────────────── */

.hero-figure {
  margin: 0;
}

/* Pas d'overflow visible : les couches du détecteur se coupent net sur le cadre,
   comme un relevé recadré. Les étiquettes tiennent dans le viewBox. */
.event-display {
  display: block;
  width: 100%;
  height: auto;
}

.ed-rings circle {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 1;
  stroke-dasharray: 2 6;
}

.ed-noise circle {
  fill: var(--graphite);
  opacity: var(--noise);
}

.ed-track {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.25;
  stroke-linecap: round;
  opacity: 0.85;
}

.ed-hits circle {
  fill: var(--trace);
}

.ed-labels text {
  font: 500 20px/1 var(--mono);
  fill: var(--ink);
  letter-spacing: 0.02em;
}

.ed-vertex circle:first-child {
  fill: none;
  stroke: var(--event);
  stroke-width: 1;
  opacity: 0.5;
}

.ed-vertex circle:last-child {
  fill: var(--event); /* usage 1/2 */
}

.hero-figure figcaption {
  margin-top: 1.5rem;
  font: 400 0.75rem/1.5 var(--mono);
  color: var(--graphite);
  letter-spacing: 0.02em;
}

/* Un seul moment orchestré : les traces se tracent, puis plus rien ne bouge. */
@keyframes ed-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes ed-appear {
  to {
    opacity: 1;
  }
}

/* Le bruit se pose à --noise, pas à 1. */
@keyframes ed-appear-noise {
  to {
    opacity: var(--noise);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .ed-track {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: ed-draw 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
  }

  .ed-hits circle,
  .ed-labels text {
    opacity: 0;
    animation: ed-appear 0.4s ease forwards;
  }

  .ed-rings circle,
  .ed-noise circle,
  .ed-vertex circle {
    opacity: 0;
    animation: ed-appear 0.6s ease forwards;
  }

  .ed-noise circle {
    animation-name: ed-appear-noise;
  }

  /* Le vertex d'abord, puis chaque trace, puis son étiquette. */
  .ed-rings circle:nth-child(1) {
    animation-delay: 0.05s;
  }
  .ed-rings circle:nth-child(2) {
    animation-delay: 0.1s;
  }
  .ed-rings circle:nth-child(3) {
    animation-delay: 0.15s;
  }
  .ed-vertex circle {
    animation-delay: 0.1s;
  }

  .ed-track:nth-child(1) {
    animation-delay: 0.3s;
  }
  .ed-track:nth-child(2) {
    animation-delay: 0.38s;
  }
  .ed-track:nth-child(3) {
    animation-delay: 0.46s;
  }
  .ed-track:nth-child(4) {
    animation-delay: 0.54s;
  }
  .ed-track:nth-child(5) {
    animation-delay: 0.62s;
  }
  .ed-track:nth-child(6) {
    animation-delay: 0.7s;
  }

  .ed-hits circle:nth-child(1),
  .ed-labels text:nth-child(1) {
    animation-delay: 1.05s;
  }
  .ed-hits circle:nth-child(2),
  .ed-labels text:nth-child(2) {
    animation-delay: 1.13s;
  }
  .ed-hits circle:nth-child(3),
  .ed-labels text:nth-child(3) {
    animation-delay: 1.21s;
  }
  .ed-hits circle:nth-child(4),
  .ed-labels text:nth-child(4) {
    animation-delay: 1.29s;
  }
  .ed-hits circle:nth-child(5),
  .ed-labels text:nth-child(5) {
    animation-delay: 1.37s;
  }
  .ed-hits circle:nth-child(6),
  .ed-labels text:nth-child(6) {
    animation-delay: 1.45s;
  }

  .ed-noise circle:nth-child(odd) {
    animation-delay: 1.5s;
  }
  .ed-noise circle:nth-child(even) {
    animation-delay: 1.65s;
  }
}

/* ── Sections ────────────────────────────────────────────────────────────── */

.section {
  padding: clamp(3rem, 6vw, 5.5rem) var(--edge);
  border-top: var(--rule);
}

.section h2 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  letter-spacing: -0.015em;
  margin-bottom: 2.5rem;
}

.section-note {
  max-width: var(--measure);
  margin-top: -1.75rem;
  margin-bottom: 2.5rem;
  font-size: 0.9375rem;
}

/* ── Listes de définitions (compétences, contact) ────────────────────────── */

.stack {
  margin: 0;
  max-width: 68rem;
}

.stack-row {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: 0.5rem 2rem;
  padding: 1rem 0;
  border-top: var(--rule);
}

.stack-row:last-child {
  border-bottom: var(--rule);
}

.stack dt {
  font: 500 0.75rem/1.6 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--graphite);
  padding-top: 0.2rem;
}

.stack dd {
  margin: 0;
  color: var(--ink);
  font-size: 1.0625rem;
}

/* Ne concerne que le bouton de la section Contact : dans le hero, l'espacement
   vient déjà de `.hero-text > * + *`. */
.section > .actions {
  margin-top: 2.25rem;
}

.aside-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 2rem;
  margin-top: 3rem;
}

.aside-body {
  margin-top: 0.625rem;
  max-width: var(--measure);
  font-size: 0.9375rem;
  line-height: 1.7;
}

/* ── Expériences ─────────────────────────────────────────────────────────── */

.entry {
  max-width: 52rem;
  padding: 2rem 0;
  border-top: var(--rule);
}

.entry:last-child {
  border-bottom: var(--rule);
}

.entry-meta {
  font: 500 0.75rem/1 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--graphite);
}

.entry h3 {
  margin-top: 0.875rem;
  font-size: clamp(1.1875rem, 2vw, 1.5rem);
}

.entry-stack {
  margin-top: 0.5rem;
  font: 400 0.8125rem/1.5 var(--mono);
  color: var(--trace);
}

.entry-body {
  margin-top: 1.125rem;
  max-width: var(--measure);
}

.entry-list {
  margin: 1.125rem 0 0;
  padding: 0;
  list-style: none;
  max-width: var(--measure);
}

.entry-list li {
  position: relative;
  padding-left: 1.375rem;
  margin-top: 0.625rem;
}

.entry-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 6px;
  height: 1px;
  background: var(--graphite);
}

/* ── Axe temporel ────────────────────────────────────────────────────────── */

.axis {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 52rem;
}

.axis-item {
  position: relative;
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 2rem;
  padding: 1.75rem 0 1.75rem 2rem;
  border-left: 1px solid var(--hairline);
}

/* La marque sur l'axe. */
.axis-item::before {
  content: "";
  position: absolute;
  left: -4px;
  top: 2.35rem;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--hairline);
}

.axis-origin::before {
  background: var(--event); /* usage 2/2 : le point de départ */
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--event) var(--halo), transparent);
}

.axis-year {
  font: 500 0.875rem/1.6 var(--mono);
  letter-spacing: 0.04em;
  color: var(--graphite);
  padding-top: 0.15rem;
}

/* Le point sur l'axe suffit à marquer l'origine — pas besoin de colorer aussi
   l'année et la note. Le magenta reste dépensé exactement deux fois. */
.axis-origin .axis-year {
  color: var(--ink);
}

.axis-dash {
  opacity: 0.5;
}

.axis-body h3 {
  font-size: 1.125rem;
  font-weight: 600;
}

.axis-org {
  margin-top: 0.3rem;
  font-size: 0.9375rem;
}

.axis-note {
  margin-top: 0.625rem;
  font: 400 0.8125rem/1 var(--mono);
  color: var(--graphite);
  letter-spacing: 0.02em;
}

/* ── Colophon ────────────────────────────────────────────────────────────── */

.colophon {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  justify-content: space-between;
  padding: 2rem var(--edge) 3rem;
  border-top: var(--rule);
  font: 400 0.8125rem/1.5 var(--mono);
  color: var(--graphite);
}

.colophon-note {
  opacity: 0.75;
}

/* ── Écrans étroits ──────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
  }

  .hero-figure {
    order: 2;
    max-width: 34rem;
  }

  .stack-row {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.375rem;
  }
}

@media (max-width: 640px) {
  /* Le graphique devient forme pure : les compétences sont juste en dessous. */
  .ed-labels {
    display: none;
  }

  .axis-item {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
    padding-left: 1.5rem;
  }

  .btn {
    flex: 1 1 auto;
    text-align: center;
  }
}
