/* ============================================================
   ALBERTO PAROLIN — sito personale
   Palette: mono editoriale + 1 accento (--pop)
   Tipografia: Inter Tight (testi/titoli) + Geist Mono (label/dettagli)
   ============================================================ */

/* -------- 1. RESET & VARIABILI -------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Palette */
  --bg:         #FAFAF7;
  --fg:         #0A0A0A;
  --fg-soft:    #6B6B6B;
  --fg-softer:  #7A7A7A; /* alza il contrasto: era #999, sotto la soglia WCAG su BG chiaro */
  --accent:     #1A1A1A;
  --divider:    #E5E5E0;

  /* Accento: UN solo colore forte, usato con parsimonia (punto del logo,
     hover, blocchi-ritmo). Per provarne un altro basta cambiare queste due righe.
     --pop-ink = colore del testo da usare SOPRA un fondo --pop. */
  --pop:        #2B44FF;   /* blu cobalto — scelto da Alberto il 2026-11-05 */
  --pop-ink:    #FAFAF7;

  /* Vetro della navbar fluttuante. I temi scuri ridefiniscono solo queste. */
  --glass:        rgba(250, 250, 247, 0.62);
  --glass-strong: rgba(250, 250, 247, 0.82);
  --glass-line:   rgba(10, 10, 10, 0.08);

  /* Tipografia */
  --font-sans:  'Inter Tight', 'Helvetica Neue', Helvetica, Arial, system-ui, sans-serif;
  --font-mono:  'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;

  /* Spaziature (scale a step di 4px) */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-6:  24px;
  --s-8:  32px;
  --s-12: 48px;
  --s-16: 64px;
  --s-20: 80px;
  --s-24: 96px;
  --s-32: 128px;

  /* Layout: a tutta larghezza su desktop (prima 1200px → colonna stretta
     e tanto vuoto ai lati). 1680px copre bene anche i monitor 27".
     Il margine laterale scala con lo schermo ma resta fra 20 e 72px. */
  --max-w:    1680px;
  --pad-x:    clamp(20px, 4vw, 72px);
  /* larghezza "di lettura" per paragrafi lunghi: il testo non va a tutta riga */
  --read-w:   68ch;

  /* Motion (per ora minimal, animazioni vere dopo) */
  --ease:     cubic-bezier(0.22, 1, 0.36, 1);
  --t-fast:   180ms;
  --t-base:   300ms;
}

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

/* Smooth scroll Lenis: classi richieste dalla lib */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }

body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 17px;
  line-height: 1.5;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "kern", "calt";
  overflow-x: hidden;
  /* niente "rubber band" orizzontale su iOS: se l'utente swipea verso destra
     la pagina NON deve trascinarsi né far comparire spazio bianco. */
  overscroll-behavior-x: contain;
}
/* lo stesso vincolo va messo anche sull'<html>, altrimenti su Safari mobile
   un transform / posizionamento può comunque generare scroll orizzontale. */
html {
  overflow-x: hidden;
  overscroll-behavior-x: contain;
}

img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; background: none; border: none; color: inherit; }
ul, ol { list-style: none; }

::selection {
  background: var(--pop);
  color: var(--pop-ink);
}

/* -------- FOCUS VISIBLE — accessibilità keyboard --------
   Rendo i focus visibili solo via tastiera (non al click del mouse).
   Anello sottile in alto contrasto, offset per non toccare il contenuto. */
:where(a, button, [role="button"], [tabindex]):focus { outline: none; }
:where(a, button, [role="button"], [tabindex]):focus-visible {
  outline: 2px solid var(--fg);
  outline-offset: 3px;
  border-radius: 6px;
}

/* -------- SKIP LINK — primo elemento, salta direttamente al contenuto -------- */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  padding: 12px 18px;
  background: var(--fg);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 600;
  z-index: 10000;
  transform: translateY(-150%);
  transition: transform 200ms var(--ease);
  border-radius: 0 0 8px 0;
}
.skip-link:focus { transform: translateY(0); }

/* -------- 2. LAYOUT BASE -------- */
.container {
  max-width: var(--max-w);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

/* -------- 3. NAV (fluttuante, "pillola" di vetro) --------
   .nav è solo un binario trasparente a tutta larghezza (non intercetta i click);
   la barra visibile è .nav-inner: una pillola di vetro staccata dai bordi.
   Quando scrolli (.scrolled) la pillola si stringe e diventa più opaca. */
.nav {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  left: 0; right: 0;
  z-index: 50;
  padding: 0 var(--pad-x);
  pointer-events: none;
}
.nav-inner {
  pointer-events: auto;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 8px 10px 8px 22px;
  display: flex;
  align-items: center;
  gap: var(--s-6);
  min-height: 58px;
  border-radius: 999px;
  position: relative;
  isolation: isolate;
  border: 1px solid var(--glass-line);
  box-shadow:
    0 12px 40px -20px rgba(10, 10, 10, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.55);
  transition:
    max-width 700ms var(--ease),
    background var(--t-base) var(--ease),
    box-shadow var(--t-base) var(--ease);
}
/* Il vetro sta su uno strato dietro (::before) e NON sulla pillola stessa:
   un backdrop-filter sul contenitore "cattura" i figli position:fixed
   (il menu mobile) e li disegna male fuori dai bordi. */
.nav-inner::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--glass);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  transition: background var(--t-base) var(--ease);
}
.nav.scrolled .nav-inner::before { background: var(--glass-strong); }
.nav.scrolled .nav-inner {
  max-width: min(var(--max-w), 1080px);
  box-shadow:
    0 18px 50px -22px rgba(10, 10, 10, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.55);
}
.nav-brand {
  display: inline-flex;
  align-items: baseline;
  font-weight: 700;
  letter-spacing: -0.025em;
  font-size: 1.15rem;
  margin-right: auto;
  white-space: nowrap;
  color: var(--fg);
}
.nav-brand .brand-a {
  font-weight: inherit;
  color: var(--fg);
}
.nav-brand .brand-rest {
  display: inline-block;
  overflow: hidden;
  max-width: 0;
  opacity: 0;
  transform: translateX(-4px);
  white-space: nowrap;
  transition:
    max-width 550ms var(--ease),
    opacity 350ms var(--ease),
    transform 550ms var(--ease);
}
.nav-brand .brand-dot {
  color: var(--pop);
  font-weight: inherit;
}
/* All'iniziale (top page) si vede solo "A." compatto.
   Appena .nav diventa .scrolled, "lberto Parolin" si svela orizzontalmente. */
.nav.scrolled .nav-brand .brand-rest {
  max-width: 220px;
  opacity: 1;
  transform: translateX(0);
}
@media (prefers-reduced-motion: reduce) {
  .nav-brand .brand-rest {
    transition: none;
  }
}
.nav-links {
  display: flex;
  gap: var(--s-6);
  font-size: 0.92rem;
  font-weight: 500;
}
.nav-links a {
  position: relative;
  padding: 10px 4px;
  color: var(--fg-soft);
  transition: color var(--t-fast) var(--ease);
}
.nav-links a:hover { color: var(--fg); }
.nav-links a::after {
  content: '';
  position: absolute;
  left: 50%; bottom: 4px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--pop);
  transform: translateX(-50%) scale(0);
  transition: transform var(--t-base) var(--ease);
}
.nav-links a:hover::after { transform: translateX(-50%) scale(1); }

/* Hamburger button: visibile solo sotto i 640px */
.nav-toggle {
  display: none;
  position: relative;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  margin-left: var(--s-2);
  border-radius: 8px;
  color: var(--fg);
  background: transparent;
  transition: background 180ms var(--ease);
}
.nav-toggle:hover { background: var(--divider); }
.nav-toggle .bar {
  display: block;
  width: 20px;
  height: 2px;
  background: currentColor;
  position: relative;
  transition: transform 240ms var(--ease), opacity 200ms var(--ease);
}
.nav-toggle .bar::before,
.nav-toggle .bar::after {
  content: '';
  position: absolute;
  left: 0;
  width: 20px;
  height: 2px;
  background: currentColor;
  transition: transform 240ms var(--ease), top 240ms var(--ease);
}
.nav-toggle .bar::before { top: -6px; }
.nav-toggle .bar::after  { top:  6px; }
.nav-toggle.is-open .bar { background: transparent; }
.nav-toggle.is-open .bar::before { top: 0; transform: rotate(45deg); }
.nav-toggle.is-open .bar::after  { top: 0; transform: rotate(-45deg); }

.lang-switcher {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
}
.lang-switcher button,
.lang-switcher a,
.lang-switcher .lang-current {
  position: relative;
  padding: 8px 6px;
  min-width: 28px;
  color: var(--fg-softer);
  transition: color var(--t-fast) var(--ease);
  text-decoration: none;
}
.lang-switcher button::before,
.lang-switcher a::before {
  content: '';
  position: absolute;
  inset: -6px -2px;
}
.lang-switcher button.active,
.lang-switcher .lang-current {
  color: var(--fg);
  cursor: default;
}
.lang-switcher button:hover,
.lang-switcher a:hover {
  color: var(--fg);
}
.lang-divider {
  color: var(--fg-softer);
}

/* Menu a tendina: sotto i 900px i link non stanno nella pillola →
   hamburger + pannello che scende, con voci grandi e numerate. */
@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .nav-inner { padding: 6px 6px 6px 18px; min-height: 54px; gap: var(--s-3); }
  .nav.scrolled .nav-inner { max-width: var(--max-w); }
  /* Pannello: card di vetro fluttuante sotto la pillola
     (14px di distacco dall alto + 54px di pillola + 10px di respiro). */
  .nav-links {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + 14px + 54px + 10px);
    left: var(--pad-x);
    right: var(--pad-x);
    flex-direction: column;
    gap: 0;
    padding: var(--s-3) var(--s-6) var(--s-4);
    border-radius: 24px;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: saturate(180%) blur(24px);
    -webkit-backdrop-filter: saturate(180%) blur(24px);
    border: 1px solid var(--glass-line);
    box-shadow: 0 30px 70px -28px rgba(10, 10, 10, 0.4);
    transform: translateY(-14px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform 380ms var(--ease), opacity 260ms var(--ease), visibility 0s linear 380ms;
    counter-reset: navn;
  }
  .nav-links.is-open {
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform 380ms var(--ease), opacity 260ms var(--ease), visibility 0s;
  }
  .nav-links a {
    counter-increment: navn;
    display: flex;
    align-items: baseline;
    gap: var(--s-4);
    padding: var(--s-4) 0;
    font-size: clamp(1.6rem, 6.5vw, 2.4rem);
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1;
    color: var(--fg);
    border-bottom: 1px solid var(--divider);
    /* le voci entrano una dopo l altra quando il menu si apre */
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 300ms var(--ease), transform 400ms var(--ease), color 200ms var(--ease);
  }
  .nav-links a::before {
    content: "0" counter(navn);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--fg-softer);
    min-width: 1.6rem;
  }
  .nav-links.is-open a { opacity: 1; transform: none; }
  .nav-links.is-open a:nth-child(2) { transition-delay: 40ms; }
  .nav-links.is-open a:nth-child(3) { transition-delay: 80ms; }
  .nav-links.is-open a:nth-child(4) { transition-delay: 120ms; }
  .nav-links.is-open a:nth-child(5) { transition-delay: 160ms; }
  .nav-links a:last-child { border-bottom: 0; }
  .nav-links a::after { display: none; }
  .nav-links a:active { color: var(--pop); }
}

/* -------- 4. HERO (a tutta pagina, viva) --------
   Struttura verticale su 100% dello schermo:
   [nome enorme, centrato in verticale]  →  [tagline + bottoni]
   L'animazione del peso delle lettere e la rotazione della tagline
   sono in assets/js/hero.js. */
.hero {
  min-height: 100vh;
  min-height: 100svh;            /* su mobile ignora la barra del browser */
  display: flex;
  position: relative;
  padding-top: calc(env(safe-area-inset-top, 0px) + 14px + 58px + var(--s-8));
  padding-bottom: var(--s-8);
}
.hero-inner {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-12);
}

/* il nome: enorme, "Alberto" a sinistra e "Parolin." a destra */
.hero-title {
  /* ~21.5vw: "Parolin." occupa quasi tutta la larghezza utile */
  font-size: clamp(4.2rem, 21.5vw, 24rem);
  font-weight: 900;
  letter-spacing: -0.06em;
  line-height: 0.8;
  will-change: transform;
  margin-block: auto;            /* centrato in verticale nello spazio della hero */
}
.hero-firstname,
.hero-lastname {
  display: block;
}
.hero-lastname { text-align: right; }
/* l entrata mette un piccolo padding a destra (per non tagliare il punto):
   qui lo azzero quasi del tutto, così il punto tocca il margine */
html.js .hero-title .hero-lastname { padding-right: 0.02em; }
/* effetto "spessore variabile" (hero.js): ogni lettera ha una casella di
   larghezza fissa e il glifo, quando si assottiglia, resta centrato lì dentro.
   Lo spessore lo anima il JS frame per frame: qui NESSUNA transizione su font-weight. */
.hero-title.is-live .char { text-align: center; }

/* il "." finale del cognome è una piccola "toy" fisica: si afferra con il
   cursore (o dito), si trascina e si lancia via. Esce dal frame, dopo poco
   ricompare. La gestione transform/opacity è fatta in JS (setupDotPhysics). */
.hero-lastname .char-dot {
  color: var(--pop);
  cursor: grab;
  display: inline-block;
  user-select: none;
  position: relative;
  touch-action: none;
}
.hero-lastname .char-dot.is-grabbed {
  cursor: grabbing;
}
html.js .hero-lastname.is-dot-loose,
html.js .hero-firstname.is-dot-loose {
  overflow: visible;
}
html.js .hero-lastname.is-dot-loose .char-dot {
  z-index: 920;
}

/* fondo hero: tagline a sinistra, bottoni a destra */
.hero-bottom {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--s-8);
}
.hero-tagline {
  font-size: clamp(1.35rem, 2.6vw, 2.4rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.15;
  max-width: 30ch;
}
.hero-tagline .symbol {
  font-family: var(--font-mono);
  font-weight: 400;
  color: var(--fg-softer);
  margin: 0 0.12em;
}
/* Il finale che ruota sta SEMPRE su una riga sua (desktop e mobile):
   così la tagline non va a capo "a volte sì a volte no" al cambio frase.
   main.js avvolge ogni pezzo in .word: rendo "block" quello che contiene il rotator. */
/* "html.js" serve a battere la regola dell entrata (html.js .hero-tagline .word {display:inline-block}) */
html.js .hero-tagline .word:has(.hero-rotator),
.hero-tagline .word:has(.hero-rotator) { display: block; }
.hero-tagline { text-wrap: nowrap; }
/* finale che ruota: esce verso l'alto, il nuovo entra dal basso */
.hero-rotator {
  display: inline-block;
  white-space: nowrap;
  color: var(--pop);
  transition: transform 380ms var(--ease), opacity 300ms var(--ease), filter 380ms var(--ease);
}
.hero-rotator.is-out { transform: translateY(-0.5em); opacity: 0; filter: blur(4px); }
.hero-rotator.is-in  { transform: translateY(0.5em);  opacity: 0; filter: blur(4px); transition: none; }
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}


@media (max-width: 560px) {
  .hero-title { font-size: 24vw; letter-spacing: -0.055em; line-height: 0.82; }
  .hero-lastname { text-align: left; padding-left: 0.4em; }
  .hero-bottom { flex-direction: column; align-items: flex-start; }
  .hero-scroll-hint { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-scroll-hint .arrow { animation: none; }
}

/* -------- 5. BOTTONI -------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 14px 24px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.005em;
  border: 1px solid transparent;
  transition:
    background-color var(--t-base) var(--ease),
    color var(--t-base) var(--ease),
    border-color var(--t-base) var(--ease),
    transform var(--t-base) var(--ease);
  cursor: pointer;
}
.btn-primary {
  background: var(--fg);
  color: var(--bg);
}
.btn-primary:hover {
  background: var(--accent);
  transform: translateY(-2px);
}
.btn-secondary {
  color: var(--fg);
  border-color: var(--fg);
}
.btn-secondary:hover {
  background: var(--fg);
  color: var(--bg);
  transform: translateY(-2px);
}

/* -------- 6. SECTION HEADER comune -------- */
.section-header {
  margin-bottom: var(--s-16);
}
.section-eyebrow {
  /* Pattern editoriale: testo mono + riga orizzontale che si estende a destra.
     Stesso peso visivo in ogni sezione → coerenza, no più "etichettina" piccola. */
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-family: var(--font-mono);
  font-size: 0.8rem;           /* stessa misura di tutte le etichette mono del sito */
  color: var(--fg-soft);
  letter-spacing: 0.08em;
  text-transform: lowercase;
  margin-bottom: var(--s-8);
  width: 100%;
}
.section-eyebrow::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--divider);
}
.section-title {
  font-size: clamp(2.2rem, 5vw, 4rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 0.95;
}
.section-lead {
  margin-top: var(--s-4);
  font-size: clamp(1rem, 1.4vw, 1.2rem);
  color: var(--fg-soft);
  max-width: 40ch;
}

/* -------- 7. ABOUT / CHI SONO --------
   [eyebrow] → [manifesto grande, parole che si accendono] →
   [4 fatti, l'ultimo è il blocco blu "cerco tirocinio"] →
   [percorso | strumenti + lingue] */
.about {
  padding: var(--s-32) 0 var(--s-24);
}
.about-header { margin-bottom: var(--s-8); }

/* manifesto */
.about-manifesto {
  font-size: clamp(1.9rem, 4.6vw, 4.6rem);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 1.04;
  max-width: 22ch;              /* righe corte = più "manifesto", meno "paragrafo" */
  text-wrap: pretty;
  margin-bottom: clamp(var(--s-16), 10vh, var(--s-32));
}
@media (min-width: 1100px) { .about-manifesto { max-width: 29ch; } }
.about-manifesto .mw {
  color: #CFCFC8;               /* parola "spenta" */
  transition: color 400ms var(--ease);
}
.about-manifesto .mw.on { color: var(--fg); }
.about-manifesto .mw-k.on { color: var(--pop); }
html:not(.js) .about-manifesto { color: var(--fg); }
.about-manifesto strong { font-weight: inherit; }

/* fatti */
.about-facts {
  display: grid;
  grid-template-columns: 1fr 1fr 1.6fr;      /* laurea · progetti · blocco blu */
  border-top: 1px solid var(--fg);
  margin-bottom: clamp(var(--s-16), 10vh, var(--s-24));
}
.fact {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-6);
  min-height: clamp(200px, 22vw, 300px);
  padding: var(--s-6) var(--s-6) var(--s-6) 0;
  border-right: 1px solid var(--divider);
}
.fact + .fact { padding-left: var(--s-6); }
.fact-big {
  font-size: clamp(3.2rem, 7vw, 7.5rem);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.85;
}
.fact-label {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--fg-soft);
  max-width: 24ch;
}
/* blocco blu: l'unico "pieno" di colore della sezione */
.fact-pop {
  position: relative;
  background: var(--pop);
  color: var(--pop-ink);
  border-right: 0;
  padding: var(--s-6) !important;
  overflow: hidden;
  isolation: isolate;
}
.fact-pop::before {            /* al passaggio del mouse un velo scuro sale dal basso */
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--fg);
  transform: translateY(101%);
  transition: transform 600ms var(--ease);
}
.fact-pop:hover::before,
.fact-pop:focus-visible::before { transform: translateY(0); }
.fact-kicker {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  opacity: 0.8;
}
.fact-roles {
  font-size: clamp(1.25rem, 2vw, 1.9rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.12;
}
.fact-arrow {
  position: absolute;
  top: var(--s-6);
  right: var(--s-6);
  font-size: 1.6rem;
  transition: transform 500ms var(--ease);
}
.fact-pop:hover .fact-arrow { transform: translate(4px, -4px) rotate(-45deg); }

/* blocchi "percorso" e "cassetta degli attrezzi" (generati da tools/build-about.mjs) */
.about-block { margin-top: clamp(var(--s-16), 9vw, var(--s-24)); }
.about-block-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-4); }
.about-col-title {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--fg-soft);
  letter-spacing: 0.04em;
  margin-bottom: var(--s-6);
}
.about-hint { font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-softer); }

/* ---- PERCORSO: diagramma di Gantt ---- */
.gantt {
  position: relative;
  border-top: 1px solid var(--fg);
  padding-top: var(--s-12);
  --lane-k: 9rem;                 /* larghezza dell'etichetta di corsia */
}
.g-axis {
  position: absolute;
  left: var(--lane-k); right: 0; top: var(--s-3);
  height: 1rem;
}
.g-year {
  position: absolute;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--fg-softer);
}
.g-lane {
  display: grid;
  grid-template-columns: var(--lane-k) 1fr;
  align-items: center;
  min-height: 92px;
  border-bottom: 1px solid var(--divider);
}
.g-lane--events { min-height: 120px; }
.g-lane-k { font-family: var(--font-mono); font-size: 0.74rem; color: var(--fg-soft); }
.g-track {
  position: relative;
  height: 100%;
  min-height: inherit;
  /* righe verticali leggere per ogni anno */
  background-image: linear-gradient(90deg, var(--divider) 1px, transparent 1px);
  background-size: calc(100% / var(--years, 12)) 100%;
}

/* barre degli studi */
.g-bar {
  position: absolute;
  top: 50%;
  height: 46px;
  margin-top: -23px;
  border-radius: 12px;
  background: var(--fg);
  color: var(--bg);
  display: flex;
  align-items: center;
  padding: 0 var(--s-4);
  cursor: default;
  transform-origin: left center;
  outline: none;
}
.g-bar--liceo { background: #C9C9C1; color: var(--fg); }
.g-bar--msc { background: var(--pop); color: var(--pop-ink); }
/* la magistrale "continua": sfuma verso destra */
.g-bar.is-open { border-radius: 12px 0 0 12px; background: linear-gradient(90deg, var(--pop) 65%, color-mix(in srgb, var(--pop) 0%, transparent)); }
.g-bar-t {
  font-size: clamp(0.82rem, 1.1vw, 1rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* indicatori di progetti/eventi: punto (evento), quadrato (progetto), rombo blu (tesi) */
.g-mark {
  position: absolute;
  top: calc(30% + var(--row) * 36px);
  width: 22px; height: 22px;
  margin-left: -11px;
  display: grid;
  place-items: center;
  outline: none;
  color: inherit;
}
.g-mark i {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--fg);
  box-shadow: 0 0 0 4px var(--bg);
  transition: transform 300ms var(--ease), background 300ms var(--ease);
}
.g-mark--proj i { border-radius: 2px; }
.g-mark--thesis i { border-radius: 2px; transform: rotate(45deg); background: var(--pop); width: 14px; height: 14px; }
.g-mark:hover i, .g-mark:focus-visible i { transform: scale(1.5); background: var(--pop); }
.g-mark--thesis:hover i, .g-mark--thesis:focus-visible i { transform: rotate(45deg) scale(1.5); }

/* scheda che compare al passaggio */
.g-tip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  z-index: 5;
  width: max-content;
  max-width: 17rem;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--fg);
  color: var(--bg);
  box-shadow: 0 20px 40px -20px rgba(10,10,10,0.6);
  transform: translate(-50%, 6px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--ease), transform 300ms var(--ease);
  text-align: left;
}
.g-bar .g-tip { left: var(--s-6); transform: translate(0, 6px); }
.g-tip-y { font-family: var(--font-mono); font-size: 0.68rem; opacity: 0.6; }
.g-tip strong { font-size: 0.98rem; font-weight: 700; letter-spacing: -0.02em; }
.g-tip span:last-child { font-size: 0.82rem; opacity: 0.75; }
.g-mark:hover .g-tip, .g-mark:focus-visible .g-tip { opacity: 1; transform: translate(-50%, 0); }
.g-bar:hover .g-tip, .g-bar:focus-visible .g-tip { opacity: 1; transform: none; }
.g-mark--thesis .g-tip { background: var(--pop); color: var(--pop-ink); }
/* progetto con pagina: blu come la tesi (blu = si apre) */
a.g-mark--proj i { background: var(--pop); }
a.g-mark--proj .g-tip { background: var(--pop); color: var(--pop-ink); }

/* linea "oggi" */
.g-today {
  position: absolute;
  top: var(--s-8);
  bottom: 0;
  width: 0;
  border-left: 1.5px dashed var(--pop);
  pointer-events: none;
}
.g-today span {
  position: absolute;
  top: -4px;
  left: 6px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--pop);
}

/* versione verticale (telefono) */
.g-list { display: none; }

/* ---- CASSETTA DEGLI ATTREZZI ---- */
.toolbox {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(var(--s-4), 2vw, var(--s-6));
  border-top: 1px solid var(--fg);
  padding-top: var(--s-6);
}
.tb-title { font-family: var(--font-mono); font-size: 0.74rem; font-weight: 500; color: var(--fg-soft); margin-bottom: var(--s-3); }
.tb-list { display: flex; flex-direction: column; gap: var(--s-3); }
.tool {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "n g" "u lv";
  gap: 6px var(--s-3);
  padding: var(--s-4) var(--s-4) var(--s-4) var(--s-4);
  border: 1px solid var(--divider);
  border-radius: 16px;
  background: color-mix(in srgb, #ffffff 50%, var(--bg));
  transition: transform 400ms var(--ease), border-color 300ms var(--ease), box-shadow 400ms var(--ease);
}
.tool:hover { transform: translateY(-3px); border-color: var(--fg-softer); box-shadow: 0 20px 40px -28px rgba(10,10,10,0.35); }
.tool-n { grid-area: n; font-size: clamp(1.05rem, 1.5vw, 1.3rem); font-weight: 700; letter-spacing: -0.03em; line-height: 1.15; }
.tool-u { grid-area: u; font-size: 0.85rem; color: var(--fg-soft); line-height: 1.35; }
.tool-lv { grid-area: lv; align-self: end; font-family: var(--font-mono); font-size: 0.68rem; color: var(--fg-soft); white-space: nowrap; }
/* indicatore a 3 tacche: si riempie fino al livello (attributo data-lv) */
.tool-g { grid-area: g; display: flex; gap: 3px; align-self: start; padding-top: 6px; }
.tool-g i { width: 14px; height: 6px; border-radius: 3px; background: var(--divider); position: relative; overflow: hidden; }
.tool-g i::after { content: ''; position: absolute; inset: 0; background: var(--fg); transform: scaleX(0); transform-origin: left; transition: transform 500ms var(--ease); }
.tool:hover .tool-g i::after { background: var(--pop); }
.tool-g i:nth-child(1)::after { transition-delay: calc(var(--d, 0ms) + 200ms); }
.tool-g i:nth-child(2)::after { transition-delay: calc(var(--d, 0ms) + 320ms); }
.tool-g i:nth-child(3)::after { transition-delay: calc(var(--d, 0ms) + 440ms); }
.tool.is-in .tool-g i:nth-child(1)::after { transform: scaleX(1); }
.tool.is-in[data-lv="2"] .tool-g i:nth-child(2)::after,
.tool.is-in[data-lv="3"] .tool-g i:nth-child(2)::after,
.tool.is-in[data-lv="3"] .tool-g i:nth-child(3)::after { transform: scaleX(1); }

/* entrata a cascata (classe .is-in aggiunta da about.js) */
html.js .about .fact,
html.js .about .tool,
html.js .about .about-col-title {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition: opacity 700ms var(--ease) var(--d, 0ms), transform 700ms var(--ease) var(--d, 0ms), border-color 300ms var(--ease), box-shadow 400ms var(--ease);
}
html.js .about .is-in { opacity: 1; transform: none; }
html.js .about .tool.is-in:hover { transform: translateY(-3px); }
/* Gantt: le barre si disegnano da sinistra, i punti compaiono (classe .is-in sul .gantt) */
html.js .gantt .g-bar { transform: scaleX(0); transition: transform 900ms var(--ease) var(--d, 0ms); }
html.js .gantt .g-mark { opacity: 0; transform: scale(0.4); transition: opacity 400ms var(--ease) var(--d, 0ms), transform 500ms var(--ease) var(--d, 0ms); }
html.js .gantt .g-today { opacity: 0; transition: opacity 600ms var(--ease) 1400ms; }
html.js .gantt.is-in .g-bar { transform: none; }
html.js .gantt.is-in .g-mark { opacity: 1; transform: none; }
html.js .gantt.is-in .g-today { opacity: 1; }

@media (max-width: 1100px) {
  .toolbox { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s-8); }
}
@media (max-width: 1000px) {
  .about-facts { grid-template-columns: 1fr 1fr; }
  .fact:nth-child(2) { border-right: 0; }
  .fact-pop { grid-column: 1 / -1; }
}
/* telefono e tablet stretto: il Gantt diventa una timeline verticale */
@media (max-width: 760px) {
  .gantt, .about-hint { display: none; }
  .g-list { display: block; border-top: 1px solid var(--fg); position: relative; padding-left: 22px; }
  .g-list::before { content: ''; position: absolute; left: 5px; top: 18px; bottom: 18px; width: 1.5px; background: var(--divider); }
  .g-li { position: relative; padding: var(--s-4) 0; border-bottom: 1px solid var(--divider); display: flex; flex-direction: column; gap: 3px; }
  .g-li::before { content: ''; position: absolute; left: -22px; top: calc(var(--s-4) + 4px); width: 12px; height: 12px; border-radius: 50%; background: var(--fg); box-shadow: 0 0 0 4px var(--bg); }
  .g-li--study::before { border-radius: 3px; width: 12px; height: 18px; top: calc(var(--s-4) + 1px); }
  .g-li--thesis::before { background: var(--pop); border-radius: 2px; transform: rotate(45deg); }
  .g-li--proj::before { border-radius: 2px; }
  .g-li a { display: flex; flex-direction: column; gap: 3px; color: inherit; }
  .g-li-y { font-family: var(--font-mono); font-size: 0.72rem; color: var(--fg-soft); }
  .g-li strong { font-size: 1.1rem; font-weight: 700; letter-spacing: -0.02em; }
  .g-li span:last-child { font-size: 0.9rem; color: var(--fg-soft); }
  .g-li--thesis strong { color: var(--pop); }
}
@media (max-width: 560px) {
  .about { padding: var(--s-24) 0 var(--s-16); }
  /* telefono: i 2 numeri su una riga, il blocco blu sotto a tutta larghezza */
  .about-facts { grid-template-columns: 1fr 1fr; }
  .fact { min-height: 130px; padding: var(--s-4) var(--s-3) var(--s-4) 0; border-top: 0 !important; }
  .fact + .fact { padding-left: var(--s-3); }
  .fact:nth-child(2) { border-right: 0; }
  .fact-big { font-size: clamp(2.2rem, 11vw, 3rem); }
  .fact-label { font-size: 0.68rem; }
  .fact-pop { grid-column: 1 / -1; min-height: 190px; }
  .toolbox { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  html.js .about .fact, html.js .about .tool, html.js .about .about-col-title { opacity: 1; transform: none; transition: none; }
  html.js .gantt .g-bar, html.js .gantt .g-mark, html.js .gantt .g-today { transform: none; opacity: 1; transition: none; }
  .tool-g i::after { transition: none; }
}

/* -------- 7a. PROGETTI — griglia di card (home) --------
   Le card sono generate da tools/generate-project-pages.cjs.
   Ogni card ha il colore del progetto in --c-bg (dato in i18n.js → cover.bg).
   Griglia a 2 colonne "sfalsata": la colonna destra parte più in basso. */
.projects { padding: var(--s-24) 0 var(--s-32); }
.title-count {
  font-family: var(--font-mono);
  font-size: 0.32em;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--pop);
  vertical-align: super;
  margin-left: 0.35em;
}
.pgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(var(--s-6), 3vw, var(--s-12));
  row-gap: clamp(var(--s-16), 8vw, var(--s-24));
}
.pgrid .pcard:nth-child(even) { margin-top: clamp(var(--s-16), 12vw, 220px); }
.pcard-link { display: block; color: inherit; }
.pcard-cover {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: 20px;
  overflow: hidden;
  background: var(--c-bg);
  display: grid;
  place-items: center;
  isolation: isolate;
}
/* lo screenshot "galleggia" dentro il riquadro colorato */
/* L altezza massima è espressa in cqw (= % della LARGHEZZA del riquadro),
   perché la percentuale d altezza qui non è calcolabile dal browser.
   Riquadro 4:3 → altezza = 75cqw; ne uso al massimo ~62cqw. */
.pcard-cover { container-type: inline-size; }
.pcard-cover img {
  width: auto;
  height: auto;
  max-width: 84%;
  max-height: 62cqw;
  border-radius: 10px;
  box-shadow: 0 30px 60px -25px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.06);
  transform: translateY(6%);
  transition: transform 900ms var(--ease);
}
.pcard[data-ink="dark"] .pcard-cover img { box-shadow: 0 30px 60px -28px rgba(40, 30, 10, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.05); }
.pcard-link:hover .pcard-cover img,
.pcard-link:focus-visible .pcard-cover img { transform: translateY(2%) scale(1.035); }

.pcard-meta {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  margin-top: var(--s-6);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--fg-soft);
  letter-spacing: 0.03em;
}
.pcard-num { color: var(--fg); }
.pcard-tags { margin-left: auto; text-align: right; }
.pcard-title {
  margin-top: var(--s-3);
  font-size: clamp(1.9rem, 3.6vw, 3.4rem);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 0.98;
}
.pcard-sub {
  margin-top: var(--s-3);
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  color: var(--fg-soft);
  max-width: 44ch;
}
/* titolo: sottolineatura blu che cresce al passaggio */
.pcard-title > span {
  background-image: linear-gradient(var(--pop), var(--pop));
  background-size: 0% 3px;
  background-position: 0 92%;
  background-repeat: no-repeat;
  transition: background-size 600ms var(--ease);
}
.pcard-link:hover .pcard-title > span { background-size: 100% 3px; }

/* pillola "apri progetto" che segue il cursore (assets/js/projects.js) */
.pcard-cursor {
  position: fixed;
  left: 0; top: 0;
  z-index: 60;
  pointer-events: none;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--pop);
  color: var(--pop-ink);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.6);
  transition: opacity 250ms var(--ease), transform 350ms var(--ease);
}
.pcard-cursor.is-on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
@media (hover: hover) and (pointer: fine) {
  .pcard:not(.is-soon) .pcard-cover { cursor: none; }
}

/* card "in arrivo": griglia tecnica + cubo 3D in wireframe che ruota */
.pcard.is-soon .pcard-link { cursor: default; }
.pcard-badge {
  position: absolute;
  top: var(--s-4);
  left: var(--s-4);
  z-index: 2;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--pop);
  color: var(--pop-ink);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
}
.bp {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background-image:
    linear-gradient(rgba(255,255,255,0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.06) 1px, transparent 1px),
    linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
  background-size: 80px 80px, 80px 80px, 16px 16px, 16px 16px;
  perspective: 900px;
}
.bp-note {
  position: absolute;
  bottom: var(--s-4);
  right: var(--s-4);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: rgba(250, 250, 247, 0.6);
}
.bp-cube {
  --s: clamp(90px, 12vw, 160px);
  width: var(--s);
  height: calc(var(--s) * 0.55);       /* "scatola" bassa e larga: allude a un paraurti */
  position: relative;
  transform-style: preserve-3d;
  animation: bp-spin 14s linear infinite;
}
.bp-cube i {
  position: absolute;
  inset: 0;
  border: 1.5px solid rgba(250, 250, 247, 0.75);
  background: rgba(43, 68, 255, 0.06);
}
.bp-cube i:nth-child(1) { transform: translateZ(calc(var(--s) * 0.3)); }
.bp-cube i:nth-child(2) { transform: rotateY(180deg) translateZ(calc(var(--s) * 0.3)); }
.bp-cube i:nth-child(3) { width: calc(var(--s) * 0.6); left: calc(var(--s) * 0.2); transform: rotateY(90deg) translateZ(calc(var(--s) * 0.5)); }
.bp-cube i:nth-child(4) { width: calc(var(--s) * 0.6); left: calc(var(--s) * 0.2); transform: rotateY(-90deg) translateZ(calc(var(--s) * 0.5)); }
.bp-cube i:nth-child(5) { height: calc(var(--s) * 0.6); top: calc(var(--s) * -0.025); transform: rotateX(90deg) translateZ(calc(var(--s) * 0.275)); border-color: var(--pop); }
.bp-cube i:nth-child(6) { height: calc(var(--s) * 0.6); top: calc(var(--s) * -0.025); transform: rotateX(-90deg) translateZ(calc(var(--s) * 0.275)); }
@keyframes bp-spin { from { transform: rotateX(-22deg) rotateY(0deg); } to { transform: rotateX(-22deg) rotateY(360deg); } }
@media (prefers-reduced-motion: reduce) { .bp-cube { animation: none; transform: rotateX(-22deg) rotateY(35deg); } }

@media (max-width: 760px) {
  .pgrid { grid-template-columns: 1fr; row-gap: var(--s-16); }
  .pgrid .pcard:nth-child(even) { margin-top: 0; }
  .pcard-cover { border-radius: 16px; }
  .pcard-tags { display: none; }
}

/* -------- COPERTINE GRAFICHE DEI PROGETTI (tools/project-covers.cjs) --------
   SVG disegnati in codice, tutti nello stesso stile; animazioni leggere e lente.
   Riempiono il riquadro colorato della card (home) e della testata (pagina). */
.cv { position: absolute; inset: 0; width: 100%; height: 100%; }
.cv-mono  { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.04em; }
.cv-sans  { font-family: var(--font-sans); font-weight: 800; font-size: 17px; letter-spacing: -0.03em; }
.cv-serif { font-family: Georgia, 'Times New Roman', serif; font-size: 24px; fill: #2f2b24; }

/* scontrino (tesi) */
.cv-receipt .cv-grid line { stroke: rgba(255,255,255,0.05); }
.cv-paper { fill: #F4F1E8; filter: drop-shadow(0 18px 24px rgba(0,0,0,0.45)); }
.cv-dash { stroke: #b8b2a2; stroke-dasharray: 3 3; }
.cv-rl { animation: cv-print 7s var(--ease) infinite; animation-delay: calc(var(--i) * 0.45s); }
/* solo dissolvenza (niente spostamenti: più stabile in tutti i browser) */
@keyframes cv-print { 0% { opacity: 0; } 8%, 82% { opacity: 1; } 92%, 100% { opacity: 0; } }

/* rete di agenti (COO) */
.cv-agents .cv-dots circle { fill: rgba(255,255,255,0.08); }
.cv-edge { stroke: rgba(255,255,255,0.18); stroke-width: 1.2; stroke-dasharray: 4 5; animation: cv-flow 2.4s linear infinite; }
@keyframes cv-flow { to { stroke-dashoffset: -18; } }
.cv-pulse { fill: var(--pop); filter: drop-shadow(0 0 6px var(--pop)); }
.cv-agent circle { fill: #0f141c; stroke: rgba(255,255,255,0.35); stroke-width: 1.2; animation: cv-blink 2.6s ease-in-out infinite; animation-delay: calc(var(--i) * 0.65s); }
.cv-agent text { fill: #cfd6e0; }
@keyframes cv-blink { 0%, 100% { stroke: rgba(255,255,255,0.35); } 20% { stroke: var(--pop); } }
.cv-core circle { fill: var(--pop); filter: drop-shadow(0 0 18px rgba(43,68,255,0.6)); }
.cv-core text { fill: #FAFAF7; }
.cv-chip { fill: rgba(43,68,255,0.18); stroke: rgba(43,68,255,0.6); }
.cv-chip-t { fill: #9fb0ff; font-size: 9px; }

/* calendario (Ripeti) */
.cv-calendar .cv-dim { fill: #8a8174; font-size: 9px; letter-spacing: 0.35em; }
.cv-cell { fill: rgba(255,255,255,0.55); stroke: rgba(47,43,36,0.08); }
.cv-les { animation: cv-pop 8s var(--ease) infinite; animation-delay: calc(var(--i) * 0.28s); transform-box: fill-box; transform-origin: center; }
.cv-les-a { fill: #3f6b52; } .cv-les-b { fill: #c0714f; } .cv-les-c { fill: #d4a95a; }
@keyframes cv-pop { 0% { opacity: 0; transform: scale(0.4); } 6%, 84% { opacity: 1; transform: none; } 94%, 100% { opacity: 0; } }

/* pianta dell'impianto (paraurti) */
.cv-plant .cv-hall { fill: rgba(255,255,255,0.03); stroke: rgba(255,255,255,0.35); stroke-width: 1.2; }
.cv-plant .cv-pil { fill: rgba(255,255,255,0.28); }
.cv-plant .cv-svc { fill: rgba(255,255,255,0.09); }
.cv-plant .cv-mac { fill: #C9C9C1; }
.cv-plant .cv-yard { fill: rgba(255,255,255,0.025); }
.cv-plant .cv-dim { fill: rgba(250,250,247,0.5); }
.cv-line { fill: none; stroke: var(--pop); stroke-width: 2.2; stroke-linejoin: round; stroke-dasharray: 6 4; animation: cv-flow 1.6s linear infinite; }
.cv-bump { fill: #FAFAF7; filter: drop-shadow(0 0 5px var(--pop)); }
.cv-truck { animation: cv-dock 9s var(--ease) infinite; }
.cv-truck rect { fill: #D9D9D2; }
.cv-truck .cv-cab { fill: #9C9C95; }
@keyframes cv-dock { 0% { transform: translateX(-90px); } 30%, 70% { transform: none; } 100% { transform: translateX(-90px); } }

/* al passaggio sulla card la copertina "respira" */
.pcard-cover .cv { transition: transform 900ms var(--ease); }
.pcard-link:hover .pcard-cover .cv { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) {
  .cv-rl, .cv-edge, .cv-agent circle, .cv-les, .cv-line, .cv-truck { animation: none; opacity: 1; }
  .cv-bump { display: none; }
  .cv-pulse { display: none; }
}

/* screenshot dentro le pagine progetto: incorniciati in una "finestra" */
.pj-win { border-radius: 12px; overflow: hidden; background: #fff; box-shadow: 0 30px 60px -28px rgba(0,0,0,0.5); max-width: 100%; }
.pj-win-bar { display: flex; gap: 6px; padding: 9px 12px; background: #f1f0ec; border-bottom: 1px solid rgba(0,0,0,0.06); }
.pj-win-bar i { width: 9px; height: 9px; border-radius: 50%; background: #d6d4cd; }
.pj-win img { display: block; border-radius: 0 !important; box-shadow: none !important; max-height: 62vh !important; width: auto; max-width: 100%; margin: 0 auto; }

/* -------- PAGINA PROGETTO v2 (stessa struttura per tutti i progetti) --------
   testata → copertina → intro → capitoli problema/immagine → numeri →
   cosa risolve → (agenti) → prova → come funziona → prossimo progetto */
.pj { padding-top: calc(env(safe-area-inset-top, 0px) + 14px + 58px + var(--s-12)); }
.pj-crumb {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--fg-soft);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--divider);
  margin-bottom: clamp(var(--s-8), 5vw, var(--s-16));
}
.pj-crumb a:hover { color: var(--pop); }
.pj-title {
  font-size: clamp(3rem, 10vw, 10rem);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.88;
  max-width: 14ch;
}
.pj-sub {
  margin-top: var(--s-6);
  font-size: clamp(1.25rem, 2.2vw, 2rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.2;
  color: var(--fg-soft);
  max-width: 34ch;
}
.pj-brief {
  display: grid;
  grid-template-columns: 0.5fr 1fr 1fr 1.2fr;
  gap: var(--s-6);
  margin: clamp(var(--s-12), 6vw, var(--s-16)) 0 var(--s-8);
  padding-top: var(--s-4);
  border-top: 1px solid var(--fg);
}
.pj-brief dt {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-softer);
  margin-bottom: 6px;
}
.pj-brief dd { font-size: 0.98rem; font-weight: 500; }

.pj-cover {
  aspect-ratio: 16 / 9;
  border-radius: 24px;
  overflow: hidden;
  background: var(--c-bg);
  display: grid;
  place-items: center;
  position: relative;
}
.pj-cover { container-type: inline-size; }
.pj-cover img {
  width: auto;
  height: auto;
  max-width: 82%;
  max-height: 46cqw;            /* 16:9 → altezza 56cqw: le immagini alte (l aereo) restano intere */
  border-radius: 12px;
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.5);
}

.pj-intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--s-8), 6vw, var(--s-24));
  padding-block: clamp(var(--s-16), 10vw, var(--s-32));
  align-items: start;
}
.pj-quote {
  font-size: clamp(1.7rem, 3.4vw, 3.2rem);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.05;
}
.pj-quote::before { content: '“'; color: var(--pop); }
.pj-quote::after  { content: '”'; color: var(--pop); }
.pj-desc { font-size: clamp(1.05rem, 1.3vw, 1.25rem); line-height: 1.6; color: var(--fg-soft); max-width: var(--read-w); }

.pj-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  color: var(--fg-soft);
  margin-bottom: var(--s-6);
}

/* capitoli: testo e immagine alternati destra/sinistra */
.pj-chapters { display: flex; flex-direction: column; gap: clamp(var(--s-16), 10vw, var(--s-32)); }
.pj-chapter {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: clamp(var(--s-8), 5vw, var(--s-20));
  align-items: center;
}
/* righe pari: immagine a sinistra ma SEMPRE nella colonna larga */
.pj-chapter:nth-child(even) { grid-template-columns: 1.2fr 0.8fr; }
.pj-chapter:nth-child(even) .pj-chapter-text { order: 2; }
.pj-chapter-text p {
  font-size: clamp(1.4rem, 2.5vw, 2.3rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.12;
}
.pj-chapter-text em { font-style: normal; color: var(--pop); }
.pj-shot {
  background: var(--c-bg);
  border-radius: 20px;
  padding: clamp(var(--s-6), 4vw, var(--s-12));
  display: grid;
  place-items: center;
}
/* screenshot intero, mai più alto del 70% dello schermo (alcuni sono "verticali") */
.pj-shot img { width: auto; height: auto; max-width: 100%; max-height: 70vh; border-radius: 10px; box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.5); }

/* numeri */
.pj-numbers {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin-block: clamp(var(--s-16), 10vw, var(--s-32));
  border-top: 1px solid var(--fg);
}
.pj-number { padding: var(--s-6) var(--s-6) 0 0; border-right: 1px solid var(--divider); display: flex; flex-direction: column; gap: var(--s-4); }
.pj-number + .pj-number { padding-left: var(--s-6); }
.pj-number:last-child { border-right: 0; }
.pj-number-big { font-size: clamp(3.5rem, 8vw, 8rem); font-weight: 800; letter-spacing: -0.06em; line-height: 0.85; }
.pj-number-label { font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg-soft); max-width: 22ch; }

.pj-block { margin-bottom: clamp(var(--s-16), 8vw, var(--s-24)); }
.pj-solves li {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: var(--s-6);
  align-items: baseline;
  padding: var(--s-6) 0;
  border-top: 1px solid var(--divider);
  font-size: clamp(1.1rem, 1.8vw, 1.6rem);
  letter-spacing: -0.02em;
}
.pj-solves li:last-child { border-bottom: 1px solid var(--divider); }
.pj-solves-p { color: var(--fg-soft); }
.pj-solves-a { color: var(--pop); font-family: var(--font-mono); }
.pj-solves-s { font-weight: 600; }

.pj-agents { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--s-12); }
.pj-agents li { display: grid; grid-template-columns: 4.5rem 1fr; gap: var(--s-4); padding: var(--s-6) 0; border-top: 1px solid var(--divider); }
.pj-agent-code { font-family: var(--font-mono); font-size: 0.9rem; color: var(--pop); padding-top: 0.25em; }
.pj-agents h3 { font-size: 1.3rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: var(--s-2); }
.pj-agents p { color: var(--fg-soft); line-height: 1.55; }

/* blocco "prova": nel colore del progetto */
.pj-try {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s-6);
  padding: clamp(var(--s-8), 5vw, var(--s-16)) !important;
  margin-bottom: clamp(var(--s-16), 8vw, var(--s-24));
  border-radius: 24px;
  background: var(--c-bg);
  color: #FAFAF7;
  max-width: calc(var(--max-w) - 2 * var(--pad-x));
  width: calc(100% - 2 * var(--pad-x));
}
.pj-try[data-ink="dark"] { color: #0A0A0A; }
.pj-try-text { position: relative; font-size: clamp(1.5rem, 3vw, 2.6rem); font-weight: 600; letter-spacing: -0.04em; }
.pj-try-success { position: absolute; left: 0; top: 0; opacity: 0; transition: opacity 400ms var(--ease); }
.pj-try-prompt { transition: opacity 400ms var(--ease); }
.pj-try.is-fired .pj-try-prompt { opacity: 0; }
.pj-try.is-fired .pj-try-success { opacity: 1; }
.pj-try-btn {
  padding: 14px 24px;
  border-radius: 999px;
  background: var(--pop);
  color: var(--pop-ink);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  transition: transform var(--t-base) var(--ease);
}
.pj-try-btn:hover { transform: translateY(-2px); }
.pj-try-btn:disabled { opacity: 0.6; }

.pj-how-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: clamp(var(--s-8), 6vw, var(--s-24)); align-items: start; }
.pj-how-text { font-size: clamp(1.05rem, 1.3vw, 1.25rem); line-height: 1.65; max-width: var(--read-w); }
.pj-stack { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.pj-stack li { font-family: var(--font-mono); font-size: 0.8rem; padding: 8px 14px; border: 1px solid var(--divider); border-radius: 999px; }

.pj-action { margin-bottom: clamp(var(--s-16), 8vw, var(--s-24)); }
.pj-soon { display: inline-block; font-family: var(--font-mono); font-size: 0.82rem; color: var(--fg-soft); padding: 12px 18px; border: 1px dashed var(--fg-softer); border-radius: 999px; }

/* prossimo progetto: grande fascia nel colore del progetto successivo */
.pj-next {
  display: block;
  background: var(--c-bg);
  color: #FAFAF7;
  padding-block: clamp(var(--s-16), 12vw, 180px);
  overflow: hidden;
}
.pj-next[data-ink="dark"] { color: #0A0A0A; }
.pj-next-inner { display: flex; flex-direction: column; gap: var(--s-4); }
.pj-next-label { font-family: var(--font-mono); font-size: 0.82rem; opacity: 0.7; }
.pj-next-title {
  font-size: clamp(2.6rem, 9vw, 9rem);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.9;
  transition: transform 800ms var(--ease);
}
.pj-next:hover .pj-next-title { transform: translateX(2vw); }

/* entrata a cascata (project-page.js aggiunge .is-visible) */
html.js .pj :is(.pj-title, .pj-sub, .pj-brief, .pj-cover, .pj-quote, .pj-desc, .pj-chapter, .pj-number, .pj-solves li, .pj-agents li, .pj-how-grid) {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition: opacity 800ms var(--ease), transform 800ms var(--ease);
}
html.js .pj .is-visible { opacity: 1 !important; transform: none !important; }

@media (max-width: 900px) {
  .pj-brief { grid-template-columns: 1fr 1fr; }
  .pj-intro, .pj-chapter, .pj-how-grid { grid-template-columns: 1fr; }
  .pj-chapter:nth-child(even) { grid-template-columns: 1fr; }
  .pj-chapter:nth-child(even) .pj-chapter-text { order: 0; }
  .pj-shot img { max-height: 60vh; }
  .pj-numbers { grid-template-columns: 1fr 1fr; }
  .pj-number:nth-child(2) { border-right: 0; }
  .pj-number:nth-child(3) { padding-left: 0; }
  .pj-number:nth-child(n+3) { padding-top: var(--s-8); }
  .pj-agents { grid-template-columns: 1fr; }
  .pj-cover { aspect-ratio: 4 / 3; border-radius: 16px; }
  .pj-cover img { max-height: 62cqw; }
}
@media (max-width: 560px) {
  .pj-solves li { grid-template-columns: 1fr; gap: var(--s-1); }
  .pj-solves-a { display: none; }
  .pj-cover img { width: 90%; }
}
@media (prefers-reduced-motion: reduce) {
  html.js .pj :is(.pj-title, .pj-sub, .pj-brief, .pj-cover, .pj-quote, .pj-desc, .pj-chapter, .pj-number, .pj-solves li, .pj-agents li, .pj-how-grid) { opacity: 1; transform: none; transition: none; }
}

/* -------- BILINGUE INLINE --------
   Pagine bilingui: ogni testo ha <span lang="it">...</span><span lang="en">...</span>.
   Mostriamo solo quello attivo, in base a <html lang>. Usa l'attributo standard. */
html[lang="it"] [lang="en"],
html[lang="en"] [lang="it"] { display: none; }

/* -------- 7c. ARTICOLI — elenco tipografico + filtri per tag --------
   Le liste (home, archivio) sono generate da tools/generate-articles-lists.cjs. */
.notes {
  padding: var(--s-24) 0;
}

/* Filtro tag in cima */
.notes-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-8);
  list-style: none;
  padding: 0;
}
.notes-filter-btn {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: lowercase;
  letter-spacing: 0.06em;
  color: var(--fg-soft);
  border: 1px solid var(--divider);
  border-radius: 100px;
  padding: 6px 14px;
  background: transparent;
  cursor: pointer;
  transition: background 220ms var(--ease), color 220ms var(--ease), border-color 220ms var(--ease);
  white-space: nowrap;
}
.notes-filter-btn:hover {
  border-color: var(--fg-softer);
  color: var(--fg);
}
.notes-filter-btn.is-active {
  background: var(--fg);
  color: var(--bg);
  border-color: var(--fg);
}

/* -------- PAGINA ARCHIVIO /articoli/ -------- */
.page-archive .archive-page {
  padding-top: var(--s-24);
  padding-bottom: var(--s-24);
}
.archive-header { margin-bottom: var(--s-12); }
.archive-tools {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  margin-bottom: var(--s-6);
}
.archive-search {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--bg);
  border: 1px solid var(--divider);
  border-radius: 14px;
  padding: 4px 14px;
  transition: border-color var(--t-fast) var(--ease);
}
.archive-search:focus-within { border-color: var(--fg); }
.archive-search-icon {
  font-size: 1.05rem;
  color: var(--fg-soft);
  margin-right: 8px;
  font-family: var(--font-mono);
}
.archive-search-input {
  flex: 1;
  border: 0;
  outline: 0;
  background: transparent;
  font-family: var(--font-sans);
  font-size: 1rem;
  padding: 12px 0;
  color: var(--fg);
}
.archive-search-input::placeholder { color: var(--fg-softer); }
.archive-search-clear {
  background: none;
  border: 0;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--fg-soft);
  cursor: pointer;
  padding: 0 6px;
}
.archive-search-clear:hover { color: var(--fg); }
.archive-count {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  color: var(--fg-soft);
  letter-spacing: 0.04em;
  margin-bottom: var(--s-6);
}
.archive-empty {
  text-align: center;
  padding: var(--s-16) 0;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--fg-soft);
  letter-spacing: 0.04em;
}

/* Elenco tipografico (home, archivio, correlati): una riga per articolo,
   titolo grande, metadati in mono. Ispirato alle liste editoriali "a riga".
   [num] [data · tempo] [titolo + sottotitolo] [tag] [freccia] */
.notes-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--fg);
}
.notes-item.is-hidden { display: none; }
.notes-link {
  position: relative;
  display: grid;
  grid-template-columns: 3rem 9.5rem minmax(0, 1fr) minmax(0, 15rem) 2.5rem;
  grid-template-areas: "num meta content tags arrow";
  column-gap: clamp(var(--s-4), 2.5vw, var(--s-12));
  align-items: baseline;
  padding: clamp(1.4rem, 2.6vw, 2.4rem) 0;
  border-bottom: 1px solid var(--divider);
  color: inherit;
  text-decoration: none;
  transition: padding 550ms var(--ease);
}
/* barra blu che cresce a sinistra al passaggio */
.notes-link::before {
  content: '';
  position: absolute;
  left: 0; top: -1px; bottom: -1px;
  width: 3px;
  background: var(--pop);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 450ms var(--ease);
}
.notes-link:focus-visible { outline: 2px solid var(--fg); outline-offset: 4px; }
.notes-num   { grid-area: num; font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg-softer); }
.notes-meta  {
  grid-area: meta;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.03em;
  color: var(--fg-soft);
}
.notes-readtime { color: var(--fg-softer); }
.notes-content { grid-area: content; min-width: 0; }
.notes-title {
  font-size: clamp(1.45rem, 2.9vw, 2.75rem);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1.03;
  color: var(--fg);
  text-wrap: balance;
  transition: color 300ms var(--ease);
}
.notes-excerpt {
  margin-top: var(--s-3);
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--fg-soft);
  max-width: 62ch;
}
.notes-tags {
  grid-area: tags;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
  list-style: none;
  padding: 0;
}
.notes-tag {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--fg-soft);
  border: 1px solid var(--divider);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}
.notes-arrow {
  grid-area: arrow;
  justify-self: end;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--fg-softer);
  transform: rotate(-45deg);
  transition: transform 450ms var(--ease), color 300ms var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .notes-link:hover { padding-left: var(--s-6); }
  .notes-link:hover::before { transform: scaleY(1); }
  .notes-link:hover .notes-arrow { transform: rotate(0); color: var(--pop); }
  .notes-link:hover .notes-tag { border-color: var(--fg-softer); color: var(--fg); }
}

@media (max-width: 900px) {
  .notes-link {
    grid-template-columns: 2.5rem minmax(0, 1fr) 2rem;
    grid-template-areas:
      "num  meta    arrow"
      "num  content content"
      "num  tags    tags";
    row-gap: var(--s-3);
  }
  .notes-meta { flex-direction: row; gap: var(--s-2); }
  .notes-readtime::before { content: '·'; margin-right: var(--s-2); }
  .notes-tags { justify-content: flex-start; }
}
@media (max-width: 560px) {
  .notes-link { grid-template-columns: 0 minmax(0, 1fr) 1.8rem; column-gap: 0; }
  .notes-num { display: none; }
}

/* contatore nei filtri dell'archivio */
.notes-filter-n { opacity: 0.55; margin-left: 2px; }

/* CTA "vedi tutti gli articoli" sotto la lista */
.notes-cta {
  margin-top: var(--s-12);
  display: flex;
  justify-content: flex-start;
}
.notes-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: 14px 26px;
  border: 1px solid var(--fg);
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--fg);
  transition: background-color var(--t-base) var(--ease), color var(--t-base) var(--ease), transform var(--t-base) var(--ease);
}
.notes-cta-btn:hover { background: var(--fg); color: var(--bg); transform: translateY(-2px); }
.notes-cta-btn .notes-cta-arrow { display: inline-block; transition: transform var(--t-base) var(--ease); }
.notes-cta-btn:hover .notes-cta-arrow { transform: translateX(4px); }

/* Messaggio "nessun risultato" quando il filtro non matcha niente */
.notes-empty {
  display: none;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.88rem;
  color: var(--fg-soft);
  padding: var(--s-12) 0;
  grid-column: 1 / -1;
  letter-spacing: 0.04em;
}
.notes-list.is-empty .notes-empty { display: block; }

/* -------- 7b. VISIONE (sezione "futuro") --------
   Sezione scura a tutta pagina: nastri di nomi AI che scorrono (vision.js),
   la frase al centro. Come nel footer, le variabili colore sono ridefinite
   localmente, così gli elementi interni (eyebrow, testi) si adattano da soli. */
.vision {
  --bg:        #0A0A0A;
  --fg:        #FAFAF7;
  --fg-soft:   #A3A39B;
  --fg-softer: #85857E;
  --divider:   rgba(250, 250, 247, 0.12);
  background: var(--bg);
  color: var(--fg);
  position: relative;
  overflow: hidden;
  padding: clamp(80px, 12vh, 140px) 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(var(--s-8), 5vh, var(--s-16));
}
.vision ::selection { background: var(--pop); color: var(--pop-ink); }
.vision-header { margin-bottom: 0; }
/* dentro una sezione flex il container si restringerebbe al testo: lo allargo */
.vision > .container { width: 100%; }

/* nastri */
.vx {
  position: relative;
  /* posizione della torcia (aggiornata da vision.js) */
  --mx: 50%;
  --my: 50%;
  user-select: none;
}
.vx-layer { display: flex; flex-direction: column; gap: clamp(4px, 1vh, 12px); }
.vx-lit {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* lo strato acceso si vede solo dentro un cerchio morbido attorno alla torcia */
  -webkit-mask-image: radial-gradient(circle clamp(140px, 18vw, 280px) at var(--mx) var(--my), #000 0%, #000 35%, transparent 100%);
          mask-image: radial-gradient(circle clamp(140px, 18vw, 280px) at var(--mx) var(--my), #000 0%, #000 35%, transparent 100%);
}
.vx-row { white-space: nowrap; overflow: visible; }
.vx-track { display: inline-flex; align-items: baseline; will-change: transform; }
.vx-w, .vx-sep { display: inline-block; }
.vx-sep { opacity: 0.5; padding: 0 0.32em; }

/* stili delle righe — strato spento */
.vx-fill { font-size: clamp(2.6rem, 8.5vw, 8.5rem); font-weight: 800; letter-spacing: -0.05em; line-height: 0.98; color: #232321; }
.vx-line { font-size: clamp(2.6rem, 8.5vw, 8.5rem); font-weight: 800; letter-spacing: -0.05em; line-height: 0.98; color: transparent; -webkit-text-stroke: 1.2px #2c2c2a; }
.vx-mono { font-family: var(--font-mono); font-size: clamp(1rem, 2.2vw, 1.9rem); font-weight: 400; letter-spacing: 0.02em; color: #3a3a37; padding-block: 0.4em; }
/* strato acceso: stesse righe, colori pieni */
.vx-lit .vx-fill { color: var(--fg); }
.vx-lit .vx-line { -webkit-text-stroke-color: var(--pop); color: color-mix(in srgb, var(--pop) 18%, transparent); }
.vx-lit .vx-mono { color: var(--pop); }

/* frase al centro */
.vision-statement { position: relative; z-index: 2; }
.vision-kicker {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--fg-soft);
  letter-spacing: 0.04em;
  margin-bottom: var(--s-4);
}
.vision-text {
  font-size: clamp(1.9rem, 4.6vw, 4.8rem);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 1.04;
  max-width: 24ch;
  text-wrap: balance;
}
.vision-text em { font-style: normal; color: var(--pop); }
.vision-foot {
  margin-top: var(--s-6);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--fg-softer);
}

/* movimento ridotto: nastri fermi e tutti accesi */
.vision.vx-static .vx-lit { -webkit-mask-image: none; mask-image: none; }

@media (max-width: 700px) {
  .vision { min-height: auto; }
  .vx-line { -webkit-text-stroke-width: 1px; }
}

/* -------- 8. CONTATTI --------
   [eyebrow] → [titolo grande + contatti diretti | form in un riquadro] */
.contact { padding: var(--s-32) 0; }
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--s-12), 6vw, var(--s-24));
  align-items: start;
}
.contact-title {
  font-size: clamp(3.2rem, 9vw, 9rem);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 0.88;
}
.contact-lead {
  margin-top: var(--s-6);
  font-size: clamp(1.15rem, 1.7vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.35;
  color: var(--fg-soft);
  max-width: 30ch;
}
.contact-direct { margin-top: var(--s-12); border-top: 1px solid var(--fg); }
.contact-direct li {
  display: grid;
  grid-template-columns: 7rem 1fr;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--divider);
  font-size: clamp(1.05rem, 1.4vw, 1.3rem);
  font-weight: 600;
  letter-spacing: -0.02em;
}
.cd-k {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: var(--fg-soft);
}
.contact-direct a {
  background-image: linear-gradient(var(--pop), var(--pop));
  background-size: 0% 2px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--t-base) var(--ease), color var(--t-fast) var(--ease);
}
.contact-direct a:hover { background-size: 100% 2px; color: var(--pop); }

/* -------- 8b. FORM, in un riquadro -------- */
.contact-form {
  background: color-mix(in srgb, #ffffff 55%, var(--bg));
  border: 1px solid var(--divider);
  border-radius: 24px;
  padding: clamp(var(--s-6), 3.5vw, var(--s-12));
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
  box-shadow: 0 30px 70px -45px rgba(10, 10, 10, 0.35);
}
.form-row { display: flex; flex-direction: column; gap: var(--s-2); }
.form-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--fg-soft);
}
.form-input {
  width: 100%;
  font: inherit;
  font-size: 1.15rem;
  color: var(--fg);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--fg-softer);
  border-radius: 0;
  padding: var(--s-2) 0 var(--s-3);
  outline: none;
  transition: border-color var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease);
}
.form-input:hover { border-bottom-color: var(--fg); }
.form-input:focus { border-bottom-color: var(--pop); box-shadow: 0 1px 0 0 var(--pop); }
.form-textarea { resize: vertical; min-height: 7.5rem; line-height: 1.5; }
.form-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-actions { display: flex; flex-direction: column; align-items: stretch; gap: var(--s-3); }
.form-submit {
  width: 100%;
  padding: 18px 24px;
  border-radius: 999px;
  background: var(--pop);
  color: var(--pop-ink);
  font-weight: 600;
  font-size: 1.05rem;
  transition: transform var(--t-base) var(--ease), opacity var(--t-base) var(--ease);
}
.form-submit:hover { transform: translateY(-2px); }
.form-submit:disabled { opacity: 0.5; cursor: wait; transform: none; }
.form-status { min-height: 1.4em; font-family: var(--font-mono); font-size: 0.8rem; color: var(--fg-soft); }
.form-status.is-pending { color: var(--fg-soft); }
.form-status.is-success { color: #1F5F3E; font-weight: 600; }
.form-status.is-error   { color: #b03d3d; font-weight: 600; }

@media (max-width: 900px) {
  .contact { padding: var(--s-24) 0; }
  .contact-grid { grid-template-columns: 1fr; }
  .contact-direct { margin-top: var(--s-8); }
}
@media (max-width: 480px) {
  .contact-direct li { grid-template-columns: 5.5rem 1fr; font-size: 1rem; }
}

/* -------- 9. FOOTER (scuro, alto, con firma gigante) --------
   Il footer ridefinisce localmente le variabili colore: dentro .footer
   --bg diventa nero e --fg crema. Così tutti gli elementi interni si
   adattano da soli, e funziona uguale anche nelle pagine a tema scuro. */
.footer {
  --bg:        #0A0A0A;
  --fg:        #FAFAF7;
  --fg-soft:   #A3A39B;
  --fg-softer: #85857E;
  --divider:   rgba(250, 250, 247, 0.12);
  background: var(--bg);
  color: var(--fg);
  padding: clamp(80px, 12vh, 140px) 0 var(--s-6);
  min-height: 92vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.footer ::selection { background: var(--pop); color: var(--pop-ink); }
.footer :focus-visible { outline-color: var(--fg); }
.footer-inner {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--s-16);
}

/* riga alta: invito + 3 colonne di link */
.footer-top {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: var(--s-12);
  align-items: start;
}
.footer-lead { display: flex; flex-direction: column; gap: var(--s-6); align-items: flex-start; }
.footer-lead-text {
  font-size: clamp(1.6rem, 2.8vw, 2.6rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1.08;
}
.footer-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  padding: 14px 22px;
  border-radius: 999px;
  background: var(--pop);
  color: var(--pop-ink);
  font-weight: 600;
  font-size: 1rem;
  transition: transform var(--t-base) var(--ease), background var(--t-base) var(--ease);
}
.footer-cta:hover { transform: translateY(-2px); }
.footer-cta-arrow { transition: transform var(--t-base) var(--ease); }
.footer-cta:hover .footer-cta-arrow { transform: translateX(4px); }

.footer-col-title {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--fg-softer);
  letter-spacing: 0.05em;
  margin-bottom: var(--s-4);
  text-transform: lowercase;
}
.footer-list {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  font-size: 1.02rem;
  font-weight: 500;
}
.footer-list a {
  color: var(--fg);
  background-image: linear-gradient(var(--pop), var(--pop));
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--t-base) var(--ease), color var(--t-fast) var(--ease);
}
.footer-list a:hover,
.footer-list a:focus-visible { background-size: 100% 1px; }

/* firma gigante: la dimensione esatta la calcola footer.js per riempire la riga */
.footer-mega {
  margin-top: auto;
  align-self: flex-start;       /* largo quanto il testo → il JS può misurarlo */
  font-size: 13.4vw;            /* valore di partenza, poi lo affina il JS */
  font-weight: 800;
  letter-spacing: -0.055em;
  line-height: 0.8;
  white-space: nowrap;
  color: var(--fg);
  user-select: none;
  padding-bottom: 0.06em;       /* spazio per le discendenti */
}
.footer-mega .fm-l { display: inline-block; }
.footer-mega .fm-dot { color: var(--pop); }
/* entrata: ogni lettera sale dal basso, una dopo l'altra (--i = indice) */
html.js .footer-mega .fm-l {
  transform: translateY(60%);
  opacity: 0;
  transition:
    transform 900ms var(--ease) calc(var(--i) * 35ms),
    opacity 600ms var(--ease) calc(var(--i) * 35ms);
}
html.js .footer.is-in .footer-mega .fm-l { transform: none; opacity: 1; }
/* hover: la lettera sotto il cursore fa un piccolo salto */
@media (hover: hover) {
  html.js .footer.is-in .footer-mega .fm-l { transition: transform 450ms var(--ease), opacity 600ms var(--ease); }
  html.js .footer.is-in .footer-mega .fm-l:hover { transform: translateY(-8%); }
}
@media (prefers-reduced-motion: reduce) {
  html.js .footer-mega .fm-l { transform: none; opacity: 1; transition: none; }
}

/* barra di stato in fondo: copyright · coordinate + ora di Torino · torna su */
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3) var(--s-6);
  padding-top: var(--s-6);
  border-top: 1px solid var(--divider);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--fg-soft);
}
.footer-status { display: inline-flex; align-items: center; gap: var(--s-2); font-variant-numeric: tabular-nums; }
.footer-live {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--pop);
  box-shadow: 0 0 0 0 var(--pop);
  animation: footer-pulse 2.4s var(--ease) infinite;
}
@keyframes footer-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pop) 60%, transparent); }
  70%  { box-shadow: 0 0 0 8px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .footer-live { animation: none; } }

@media (max-width: 900px) {
  .footer-top { grid-template-columns: 1fr 1fr; gap: var(--s-8) var(--s-6); }
  .footer-lead { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .footer { min-height: auto; }
  .footer-inner { gap: var(--s-12); }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
}

/* -------- 11. LEGAL OVERLAY (privacy / cookie / terms) -------- */
.legal-overlay {
  position: fixed;
  inset: 0;
  z-index: 950;
  background: rgba(10, 10, 10, 0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity 280ms var(--ease), visibility 280ms var(--ease);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-4);
}
.legal-overlay.is-open {
  opacity: 1;
  visibility: visible;
}
.legal-panel {
  background: var(--bg);
  color: var(--fg);
  max-width: 760px;
  width: 100%;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: 18px;
  /* respiro generoso, simmetrico — il testo NON deve toccare i bordi.
     Token tutti definiti in :root (no var inesistenti). */
  padding: var(--s-12) var(--s-12) var(--s-12);
  position: relative;
  border: 1px solid var(--divider);
  box-shadow: 0 30px 80px -30px rgba(10, 10, 10, 0.55);
  transform: translateY(12px);
  transition: transform 320ms var(--ease);
}
.legal-overlay.is-open .legal-panel {
  transform: translateY(0);
}
.legal-close {
  position: absolute;
  top: var(--s-4);
  right: var(--s-4);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--fg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 200ms var(--ease), color 200ms var(--ease);
}
.legal-close:hover {
  background: var(--divider);
  color: var(--fg);
}

/* Su schermi piccoli riduco il padding ma resta comodo (mai a filo). */
@media (max-width: 640px) {
  .legal-panel {
    padding: var(--s-8) var(--s-6) var(--s-8);
    border-radius: 14px;
    max-height: 92vh;
  }
  .legal-close {
    top: var(--s-3);
    right: var(--s-3);
    width: 36px;
    height: 36px;
  }
}
/* Tipografia coerente con le sezioni del sito:
   eyebrow mono → titolo bold Geist → body Geist soft.
   Stessi token cromatici / di spacing del resto. */
.legal-content {
  font-family: var(--font-sans);
  color: var(--fg);
}
.legal-eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--fg-soft);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  margin-bottom: var(--s-4);
}
.legal-title {
  font-size: clamp(1.9rem, 3.6vw, 2.6rem);
  font-weight: 900;
  letter-spacing: -0.035em;
  line-height: 0.95;
  color: var(--fg);
  margin-bottom: var(--s-6);
}
.legal-body {
  font-family: var(--font-sans);
  color: var(--fg-soft);
  font-size: 1rem;
  line-height: 1.65;
}
.legal-body p {
  margin-bottom: var(--s-3);
}
.legal-body p:last-child {
  margin-bottom: 0;
}
.legal-body strong {
  color: var(--fg);
  font-weight: 600;
}
.legal-body ul {
  list-style: none;
  padding-left: 0;
  margin-bottom: var(--s-4);
}
.legal-body li {
  position: relative;
  padding-left: var(--s-6);
  margin-bottom: var(--s-2);
}
.legal-body li::before {
  content: "→";
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--font-mono);
  color: var(--fg-softer);
}
.legal-body code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--divider);
  padding: 2px 7px;
  border-radius: 4px;
  color: var(--fg);
  letter-spacing: 0;
}
.legal-body a {
  color: var(--fg);
  border-bottom: 1px solid var(--fg-softer);
  transition: border-color 200ms var(--ease);
}
.legal-body a:hover {
  border-bottom-color: var(--fg);
}

/* ============================================================
   ANIMATIONS — entry, reveal, typewriter, idle motion, grain
   ============================================================ */

/* -------- GRAIN TEXTURE (always-on) -------- */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 999;
  opacity: 0.035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* -------- INITIAL STATE (only if JS) --------
   Entry stile vecchio prototipo: SLIDE-UP da sotto + fade. Niente blur,
   niente scale. Tutti gli elementi hero usano la stessa famiglia per
   coerenza, con stagger per-char sul nome e per-word sulla tagline. */
html.js .hero-firstname .char,
html.js .hero-lastname .char {
  display: inline-block;
  opacity: 0;
  transform: translateY(38px);
  transition:
    opacity 700ms ease-out,
    transform 700ms cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: var(--char-delay, 0ms);
  /* Safety: se JS non aggiunge .is-ready entro 3s, forzo la visualizzazione */
  animation: safety-reveal 1ms linear 3000ms forwards;
}
@keyframes safety-reveal {
  to { opacity: 1; transform: translateY(0); }
}
html.js .hero-firstname,
html.js .hero-lastname {
  display: block;
  /* overflow hidden serve a mascherare il "translate dal basso": il char
     emerge da sotto la propria riga come da una fessura. Rimosso a entry
     finita (entry-done) per non clippare il punto draggabile. */
  overflow: hidden;
  padding-bottom: 0.06em;
  padding-right: 0.18em;
}
html.js .hero-firstname.entry-done,
html.js .hero-lastname.entry-done {
  overflow: visible;
}
html.js .hero-title.is-ready .char {
  opacity: 1;
  transform: translateY(0);
}

html.js .hero-tagline .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 600ms ease-out,
    transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: var(--word-delay, 0ms);
  animation: safety-reveal 1ms linear 3200ms forwards;
}
html.js .hero-tagline.is-ready .word {
  opacity: 1;
  transform: translateY(0);
}

html.js .hero-meta {
  opacity: 0;
  transform: translateY(20px);
  /* Delay 400ms: parte poco dopo che il nome ha iniziato */
  transition:
    opacity 600ms ease-out 400ms,
    transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1) 400ms;
}
html.js .hero-meta.is-ready {
  opacity: 1;
  transform: translateY(0);
}

html.js .hero-cta,
html.js .hero-scroll-hint {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 600ms ease-out 200ms,
    transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1) 200ms;
  animation: safety-reveal 1ms linear 3500ms forwards;
}
html.js .hero-scroll-hint {
  transition-delay: 500ms;
}
html.js .hero.is-ready .hero-cta,
html.js .hero.is-ready .hero-scroll-hint {
  opacity: 1;
  transform: translateY(0);
}

/* -------- IDLE ANIMATIONS -------- */
.hero-scroll-hint .arrow {
  display: inline-block;
  animation: bob 2.4s ease-in-out infinite;
}
@keyframes bob {
  0%, 100% { transform: translateY(1px); }
  50%      { transform: translateY(5px); }
}

/* -------- REVEAL ON SCROLL --------
   Più snello e meno "a scatti": duration 600ms, stagger più stretto (70ms),
   translate3d per il compositing GPU, e transform/opacity con la STESSA
   curva e durata così non si sfasano tra loro. */
html.js .section-eyebrow,
html.js .section-title,
html.js .section-lead,
html.js .contact-row,
html.js .project-row {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
  /* le transition-delay specifiche sono nelle regole sotto */
}
html.js .project-row:nth-of-type(1) { transition-delay:   0ms; }
html.js .project-row:nth-of-type(2) { transition-delay:  70ms; }
html.js .project-row:nth-of-type(3) { transition-delay: 140ms; }
html.js .project-row:nth-of-type(4) { transition-delay: 210ms; }
html.js .is-visible {
  opacity: 1 !important;
  transform: none !important;
}

/* Stagger per i row di "Chi sono" / "Cantiere" / "Stack" — più stretto, niente
   attesa lunga. Stack ha 7 row, gli altri ≤4: i delay extra (5-7) servono solo
   a Stack ma non disturbano sezioni più corte. */

html.js .contact-row:nth-of-type(1) { transition-delay:   0ms; }
html.js .contact-row:nth-of-type(2) { transition-delay:  70ms; }
html.js .contact-row:nth-of-type(3) { transition-delay: 140ms; }
html.js .contact-row:nth-of-type(4) { transition-delay: 210ms; }

/* Title leggermente prima del lead */
html.js .section-title { transition-delay:  40ms; }
html.js .section-lead  { transition-delay: 120ms; }


/* ============================================================
   ACCESSIBILITY — reduce motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  html.js .hero-firstname .char,
  html.js .hero-lastname .char,
  html.js .hero-tagline .word,
  html.js .hero-meta,
  html.js .hero-cta,
  html.js .hero-scroll-hint,
  html.js .section-eyebrow,
  html.js .section-title,
  html.js .section-lead,
  html.js .contact-row,
  html.js .project-row {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .hero-tagline .symbol,
  .hero-scroll-hint .arrow {
    animation: none !important;
  }
  body::after { display: none; }
  html { scroll-behavior: auto !important; }
}

/* ============================================================
   TRANSIZIONE TRA PAGINE — nativa del browser (View Transitions).
   Chrome/Edge/Safari recenti fanno una dissolvenza morbida tra la pagina
   vecchia e la nuova; gli altri browser cambiano pagina normalmente.
   La navbar resta ferma durante il passaggio (ha un nome suo).
   ============================================================ */
@view-transition { navigation: auto; }
.nav { view-transition-name: site-nav; }
::view-transition-old(root) { animation: vt-out 260ms cubic-bezier(0.4, 0, 1, 1) both; }
::view-transition-new(root) { animation: vt-in 420ms cubic-bezier(0.22, 1, 0.36, 1) both; }
@keyframes vt-out { to { opacity: 0; transform: translateY(-12px); } }
@keyframes vt-in  { from { opacity: 0; transform: translateY(18px); } }
.page-transition { display: none; }   /* vecchia tendina: disattivata */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* ============================================================
   READING PROGRESS BAR — filo sottile nero in cima alla pagina che
   cresce man mano che si scorre. Aggiunta solo nelle pagine articolo
   (markup in /articoli/*.html). Innocuo se manca il <div>.
   ============================================================ */
.reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--divider);   /* track sempre visibile */
  z-index: 1000;
  pointer-events: none;
}
/* La fill nera vera è uno ::after che scala da 0 al --progress.
   Tenere parent + pseudo separati evita di scalare anche il track. */
.reading-progress::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--fg);
  transform-origin: 0 0;
  transform: scaleX(var(--progress, 0));
  will-change: transform;
  transition: transform 120ms linear;
}

/* ============================================================
   MAGNETIC BUTTONS — i tasti marcati [data-magnetic] seguono il
   cursore di pochi pixel in hover. Solo desktop con pointer fine.
   Lo spostamento lo calcola il JS (transform inline); qui solo
   la transizione per il rientro morbido.
   ============================================================ */
[data-magnetic] {
  /* La smoothness è gestita dal lerp in JS (per-frame, niente durate fisse).
     Lascio solo will-change per hint del compositor. */
  will-change: transform;
}
@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  /* niente magnetic su touch/reduced-motion */
  [data-magnetic] { transform: none !important; }
}
