/* ==========================================================================
   FEDEVERSE — Design System
   Stile: Modern Dark / Cinematic + Aurora Mesh + Glassmorphism
   Font: Space Grotesk (display) + DM Sans (body)
   ========================================================================== */

/* I font sono caricati con <link rel="preconnect"> + <link rel="stylesheet">
   nell'<head> di ogni pagina: evita il blocco di rendering di @import. */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
/* Il sito nasce scuro: il tema scuro sta in :root ed è il default.
   Il chiaro arriva in due modi, definiti piu sotto:
     1. automatico, se il sistema dell'utente preferisce il chiaro
     2. manuale, con l'attributo data-theme sull'elemento <html>
   La scelta manuale vince sempre su quella di sistema. */
:root {
  color-scheme: dark;

  /* Superfici — mai #000 puro (smear su OLED) */
  --bg:              #05060f;
  --bg-elevated:     #0a0c1a;
  --surface:         rgba(255, 255, 255, 0.035);
  --surface-strong:  rgba(255, 255, 255, 0.06);
  --border:          rgba(255, 255, 255, 0.09);
  --border-strong:   rgba(255, 255, 255, 0.16);

  /* Terne RGB per velature e scrim: --ink e il colore dei tratti sottili
     (bianco sul tema scuro, quasi-nero sul chiaro). */
  --bg-rgb:          5 6 15;
  --ink-rgb:         255 255 255;

  /* Testo */
  --fg:              #eef1fb;   /* contrasto ~17:1 su --bg */
  --fg-muted:        #a4adc8;   /* contrasto ~7.5:1  */
  --fg-subtle:       #6f7896;   /* solo per label decorative */

  /* Colori del brand, presi dal logo Fedeverse — uguali nei due temi */
  --brand-blue:      #3b5bf5;   /* blu elettrico della "V" */
  --brand-violet:    #7c3aed;
  --brand-purple:    #a855f7;   /* porpora della "E" finale */
  --brand-navy:      #1a2138;   /* navy scuro del simbolo */
  --lime:            #a3e635;   /* solo stato "disponibile" */

  /* Il blu pieno non basta su fondo scuro: per testo e bordi si usa
     una sua tinta piu chiara (contrasto ~7:1 su --bg). */
  --accent:          #7c9cff;
  --accent-ink:      #060a1a;   /* testo su fondo accent */
  --accent-rgb:      124 156 255;

  /* Stati */
  --danger:          #ff8095;   /* ~6:1 su fondo scuro */
  --danger-rgb:      255 128 149;
  --success:         #d9f99d;

  /* Gradienti */
  --grad-brand:  linear-gradient(120deg, #3b5bf5 0%, #7c3aed 55%, #a855f7 100%);
  --grad-soft:   linear-gradient(180deg, rgba(59,91,245,.14), rgba(124,58,237,.06) 60%, transparent);
  --grad-line:   linear-gradient(90deg, transparent, rgb(var(--ink-rgb) / .22), transparent);

  /* Glow */
  --glow-accent:  0 0 40px rgb(var(--accent-rgb) / .30);
  --glow-violet:  0 0 48px rgba(124, 58, 237, .32);

  /* Intensita degli effetti di sfondo */
  --blob-opacity: .5;
  --noise-opacity: .028;
  --grid-opacity: .045;

  /* Sfera dell'hero: segue il tema come il logo, cosi il braccio scuro
     del simbolo resta sempre leggibile. */
  --orb-bg: #0a0c1a;

  /* Ombre / elevazione */
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 8px 24px -8px rgba(0,0,0,.6);
  --shadow-lg: 0 28px 70px -24px rgba(0,0,0,.85);

  /* Raggi */
  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 22px;
  --r-xl: 32px;
  --r-pill: 999px;

  /* Spaziatura — scala 4/8 (density 4/10, "standard") */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --space-10: 128px;

  /* Tipografia */
  --font-display: 'Space Grotesk', system-ui, sans-serif;
  --font-body: 'DM Sans', system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, monospace;

  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.125rem;
  --text-xl:   1.375rem;
  --text-2xl:  1.75rem;
  --text-3xl:  clamp(2rem, 4vw, 2.75rem);
  --text-4xl:  clamp(2.5rem, 6vw, 4rem);
  --text-5xl:  clamp(3rem, 9vw, 6.5rem);

  /* Motion — token unici, stesso ritmo ovunque */
  --ease-out:   cubic-bezier(0.16, 1, 0.3, 1);   /* expo.out */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast:   150ms;
  --dur-base:   250ms;
  --dur-slow:   400ms;
  --dur-reveal: 800ms;

  /* Layout */
  --container: 1200px;
  --nav-h: 72px;

  /* Z-index scale */
  --z-bg: 0;
  --z-content: 10;
  --z-nav: 100;
  --z-overlay: 400;
  --z-cursor: 1000;
}

/* --------------------------------------------------------------------------
   1b. TEMA CHIARO
   I valori del brand non cambiano; cambiano superfici, testo e intensita
   degli effetti. L'accento passa al blu pieno perche la tinta chiara non
   avrebbe contrasto sufficiente su fondo bianco.
   -------------------------------------------------------------------------- */
:root[data-theme="light"] {
  color-scheme: light;

  --bg:              #f6f7fc;
  --bg-elevated:     #ffffff;
  --surface:         rgba(12, 15, 29, 0.028);
  --surface-strong:  rgba(12, 15, 29, 0.055);
  --border:          rgba(12, 15, 29, 0.11);
  --border-strong:   rgba(12, 15, 29, 0.20);

  --bg-rgb:          246 247 252;
  --ink-rgb:         12 15 29;

  --fg:              #0c0f1d;   /* ~17:1 su --bg */
  --fg-muted:        #4c5570;   /* ~7.6:1 */
  --fg-subtle:       #666f8a;   /* 4.7:1 — usato anche per helper e copyright */

  --accent:          #2f45d4;   /* ~7.4:1 su --bg */
  --accent-ink:      #ffffff;
  --accent-rgb:      47 69 212;

  --danger:          #c2183c;
  --danger-rgb:      194 24 60;
  --success:         #2f6d1f;

  --orb-bg:          #ffffff;

  --grad-soft:   linear-gradient(180deg, rgba(59,91,245,.10), rgba(124,58,237,.05) 60%, transparent);
  --glow-violet: 0 0 48px rgba(124, 58, 237, .18);

  --blob-opacity:  .30;
  --noise-opacity: .020;
  --grid-opacity:  .055;

  /* Su fondo chiaro le ombre nere sono troppo dure */
  --shadow-sm: 0 1px 2px rgba(12,15,29,.08);
  --shadow-md: 0 8px 24px -8px rgba(12,15,29,.14);
  --shadow-lg: 0 24px 60px -24px rgba(12,15,29,.26);
}

/* Stessa cosa in automatico, quando l'utente non ha ancora scelto a mano */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --bg:              #f6f7fc;
    --bg-elevated:     #ffffff;
    --surface:         rgba(12, 15, 29, 0.028);
    --surface-strong:  rgba(12, 15, 29, 0.055);
    --border:          rgba(12, 15, 29, 0.11);
    --border-strong:   rgba(12, 15, 29, 0.20);

    --bg-rgb:          246 247 252;
    --ink-rgb:         12 15 29;

    --fg:              #0c0f1d;
    --fg-muted:        #4c5570;
    --fg-subtle:       #666f8a;

    --accent:          #2f45d4;
    --accent-ink:      #ffffff;
    --accent-rgb:      47 69 212;

    --danger:          #c2183c;
    --danger-rgb:      194 24 60;
    --success:         #2f6d1f;

    --orb-bg:          #ffffff;

    --grad-soft:   linear-gradient(180deg, rgba(59,91,245,.10), rgba(124,58,237,.05) 60%, transparent);
    --glow-violet: 0 0 48px rgba(124, 58, 237, .18);

    --blob-opacity:  .30;
    --noise-opacity: .020;
    --grid-opacity:  .055;

    --shadow-sm: 0 1px 2px rgba(12,15,29,.08);
    --shadow-md: 0 8px 24px -8px rgba(12,15,29,.14);
    --shadow-lg: 0 24px 60px -24px rgba(12,15,29,.26);
  }
}

/* --------------------------------------------------------------------------
   2. RESET & BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.08;
  letter-spacing: -0.025em;
  margin: 0 0 var(--space-4);
  font-weight: 600;
  text-wrap: balance;
  /* Una parola sola piu' larga della colonna non va a capo da sola: esce, e
     con l'overflow-x: hidden del body esce senza lasciare traccia.
     Su "Missione stratosferica" succedeva davvero: a 320 px il titolo e' alto
     48 px (il minimo di --text-5xl, uguale su tutti i telefoni) e
     "stratosferica" misura 347 px in una colonna da 288 — le ultime lettere
     finivano fuori dallo schermo, irraggiungibili.
     hyphens fa il taglio bello, con il trattino, dove il browser conosce le
     regole dell'italiano; overflow-wrap e' la rete di sicurezza per quando non
     le conosce. Nessuno dei due fa niente finche' la parola ci sta. */
  hyphens: auto;
  overflow-wrap: break-word;
}
h1 { font-size: var(--text-5xl); font-weight: 700; }
h2 { font-size: var(--text-4xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }

p { margin: 0 0 var(--space-4); max-width: 68ch; }

a { color: inherit; text-decoration: none; }

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

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

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

::selection { background: var(--brand-violet); color: #fff; }

/* Focus visibile ovunque (a11y CRITICAL) */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

/* Scrollbar */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb {
  background: rgb(var(--ink-rgb) / .16);
  border-radius: var(--r-pill);
  border: 2px solid var(--bg);
}
::-webkit-scrollbar-thumb:hover { background: rgb(var(--ink-rgb) / .3); }

/* Skip link */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  z-index: var(--z-overlay);
  padding: var(--space-3) var(--space-5);
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: var(--r-sm);
  font-weight: 700;
  transition: top var(--dur-base) var(--ease-out);
}
.skip-link:focus { top: var(--space-4); }

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

/* --------------------------------------------------------------------------
   3. BACKGROUND FX — aurora, griglia, grana
   -------------------------------------------------------------------------- */
.fx {
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  pointer-events: none;
  overflow: hidden;
}

/* Blob aurora animati */
.fx__blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: var(--blob-opacity);
  will-change: transform;
}
.fx__blob--1 {
  width: 620px; height: 620px;
  background: radial-gradient(circle, rgba(124,156,255,.55), transparent 68%);
  top: -18%; left: -12%;
  animation: drift1 26s ease-in-out infinite alternate;
}
.fx__blob--2 {
  width: 560px; height: 560px;
  background: radial-gradient(circle, rgba(124,58,237,.55), transparent 68%);
  top: 14%; right: -14%;
  animation: drift2 32s ease-in-out infinite alternate;
}
.fx__blob--3 {
  width: 480px; height: 480px;
  background: radial-gradient(circle, rgba(168,85,247,.38), transparent 68%);
  bottom: -16%; left: 32%;
  animation: drift3 38s ease-in-out infinite alternate;
}

@keyframes drift1 {
  0%   { transform: translate3d(0,0,0) scale(1); }
  100% { transform: translate3d(160px, 90px, 0) scale(1.18); }
}
@keyframes drift2 {
  0%   { transform: translate3d(0,0,0) scale(1.1); }
  100% { transform: translate3d(-140px, 130px, 0) scale(.9); }
}
@keyframes drift3 {
  0%   { transform: translate3d(0,0,0) scale(.95); }
  100% { transform: translate3d(120px, -110px, 0) scale(1.2); }
}

/* Griglia prospettica */
.fx__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgb(var(--ink-rgb) / var(--grid-opacity)) 1px, transparent 1px),
    linear-gradient(90deg, rgb(var(--ink-rgb) / var(--grid-opacity)) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 30%, transparent 78%);
}

/* Grana film */
.fx__noise {
  position: absolute;
  inset: -200%;
  opacity: var(--noise-opacity);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 800ms steps(4) infinite;
}
@keyframes grain {
  0%,100% { transform: translate(0,0); }
  25% { transform: translate(-2%, 1%); }
  50% { transform: translate(1%, -2%); }
  75% { transform: translate(2%, 2%); }
}

/* Vignetta */
.fx__vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 100% 80% at 50% 50%, transparent 45%, rgb(var(--bg-rgb) / .85) 100%);
}

/* --------------------------------------------------------------------------
   4. CURSORE CUSTOM (solo puntatore fine)
   -------------------------------------------------------------------------- */
.cursor, .cursor-ring { display: none; }

@media (pointer: fine) {
  .cursor {
    display: block;
    position: fixed;
    top: 0; left: 0;
    width: 7px; height: 7px;
    margin: -3.5px 0 0 -3.5px;
    background: var(--accent);
    border-radius: 50%;
    z-index: var(--z-cursor);
    pointer-events: none;
    box-shadow: var(--glow-accent);
  }
  .cursor-ring {
    display: block;
    position: fixed;
    top: 0; left: 0;
    width: 38px; height: 38px;
    margin: -19px 0 0 -19px;
    border: 1px solid rgba(124,156,255,.45);
    border-radius: 50%;
    z-index: var(--z-cursor);
    pointer-events: none;
    transition: width var(--dur-base) var(--ease-out),
                height var(--dur-base) var(--ease-out),
                margin var(--dur-base) var(--ease-out),
                background-color var(--dur-base) var(--ease-out),
                border-color var(--dur-base) var(--ease-out);
  }
  .cursor-ring.is-hover {
    width: 66px; height: 66px;
    margin: -33px 0 0 -33px;
    background: rgba(124,156,255,.10);
    border-color: rgba(124,156,255,.7);
  }
}

/* --------------------------------------------------------------------------
   5. BARRA DI PROGRESSO SCROLL
   -------------------------------------------------------------------------- */
.progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--grad-brand);
  z-index: var(--z-nav);
  will-change: transform;
}

/* --------------------------------------------------------------------------
   6. LAYOUT
   -------------------------------------------------------------------------- */
/* Rete di sicurezza: nessuna animazione può generare scroll orizzontale.
   `clip` (non `hidden`) non crea un contenitore di scroll. */
main { overflow-x: clip; }

/* Saltando a un'ancora, l'header fisso coprirebbe l'inizio della sezione */
[id] { scroll-margin-top: calc(var(--nav-h) + var(--space-5)); }

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

.section {
  position: relative;
  z-index: var(--z-content);
  padding-block: var(--space-9);
}
.section--tight { padding-block: var(--space-8); }

.section__head {
  max-width: 720px;
  margin-bottom: var(--space-7);
}
.section__head--center {
  margin-inline: auto;
  text-align: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-4);
}
.eyebrow::before {
  content: '';
  width: 24px; height: 1px;
  background: currentColor;
}

.lead {
  font-size: var(--text-lg);
  color: var(--fg-muted);
}

.grad-text {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.divider {
  height: 1px;
  background: var(--grad-line);
  border: 0;
  margin: 0;
}

/* --------------------------------------------------------------------------
   7. BOTTONI
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 48px;               /* touch target >= 44px */
  padding: var(--space-3) var(--space-6);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--fg);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-sm);
  letter-spacing: .01em;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out);
}
.btn:hover { transform: translateY(-2px); border-color: var(--accent); }
.btn:active { transform: translateY(0) scale(.975); }

.btn--primary {
  border-color: transparent;
  background: var(--grad-brand);
  color: #ffffff;
  font-weight: 700;
  box-shadow: 0 10px 40px -12px rgba(124,58,237,.9);
}
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(120deg, #a855f7, #3b5bf5);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.btn--primary:hover::after { opacity: 1; }
.btn--primary:hover { color: #ffffff; box-shadow: 0 16px 50px -12px rgba(124,156,255,.85); }

.btn--ghost { background: var(--surface); backdrop-filter: blur(12px); }
.btn--ghost:hover { background: var(--surface-strong); box-shadow: var(--glow-accent); }

.btn--lg { min-height: 56px; padding: var(--space-4) var(--space-7); font-size: var(--text-base); }

.btn__icon { width: 18px; height: 18px; transition: transform var(--dur-base) var(--ease-out); }
.btn:hover .btn__icon { transform: translateX(4px); }

/* Su un pulsante di scaricamento la freccia deve scendere, non scorrere a
   destra: il movimento predefinito di .btn__icon racconta "vai avanti", che
   qui direbbe la cosa sbagliata. */
.btn:hover .btn__icon--giu { transform: translateY(3px); }

.btn[disabled] { opacity: .45; cursor: not-allowed; transform: none; }

/* Conferma dopo una copia riuscita — stessa coppia di .icon-btn.is-fatto */
.btn.is-fatto { color: var(--accent); border-color: var(--accent); }

/* --------------------------------------------------------------------------
   8. NAVBAR
   -------------------------------------------------------------------------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  transition: background-color var(--dur-slow) var(--ease-out),
              border-color var(--dur-slow) var(--ease-out),
              backdrop-filter var(--dur-slow) var(--ease-out);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: rgb(var(--bg-rgb) / .78);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border-bottom-color: var(--border);
}
.nav__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}

/* ---- SLOT LOGO ----
   Il lockup esiste in due versioni: logo-dark.png (FEDE e secondo braccio
   della F in bianco, per fondo scuro) e logo-light.png (l'originale).
   Usiamo background-image invece di <img> cosi il browser scarica solo
   quella effettivamente in uso. Il nome del sito e gia annunciato
   dall'aria-label del link che le contiene. */
/* Il lockup e' alto 21 px sul telefono, ma e' il collegamento alla home ed
   e' fra i piu' toccati del sito: sotto i 44 px si sbaglia mira.
   Il bersaglio si allarga con del padding vero — non con un ::after, cosi'
   funziona anche se il dito arriva di taglio — e il margine negativo annulla
   l'ingombro, quindi la barra in alto resta alta esattamente come prima.
   Stesso trucco su .post__link. */
.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  flex-shrink: 0;
  padding-block: 12px;
  margin-block: -12px;
}
.logo__img {
  display: block;
  height: 34px;
  aspect-ratio: 1035 / 132;
  background: url('../img/logo-dark.png') left center / contain no-repeat;
  transition: filter var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
:root[data-theme="light"] .logo__img {
  background-image: url('../img/logo-light.png');
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .logo__img {
    background-image: url('../img/logo-light.png');
  }
}
.logo:hover .logo__img {
  filter: drop-shadow(0 0 12px rgb(var(--accent-rgb) / .7));
  transform: scale(1.04);
}
.logo__text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-lg);
  letter-spacing: -.02em;
}

/* ---- Selettore di tema ---- */
.theme-toggle {
  position: relative;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  color: var(--fg-muted);
  cursor: pointer;
  overflow: hidden;
  transition: color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}
.theme-toggle:hover {
  color: var(--fg);
  border-color: var(--border-strong);
  background: var(--surface-strong);
}
.theme-toggle svg {
  grid-area: 1 / 1;
  width: 19px; height: 19px;
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
/* Scuro attivo: mostra il sole (cliccando si va al chiaro) */
.theme-toggle .icon-moon { opacity: 0; transform: rotate(-90deg) scale(.4); }
.theme-toggle .icon-sun  { opacity: 1; transform: rotate(0) scale(1); }

:root[data-theme="light"] .theme-toggle .icon-sun  { opacity: 0; transform: rotate(90deg) scale(.4); }
:root[data-theme="light"] .theme-toggle .icon-moon { opacity: 1; transform: rotate(0) scale(1); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle .icon-sun  { opacity: 0; transform: rotate(90deg) scale(.4); }
  :root:not([data-theme="dark"]) .theme-toggle .icon-moon { opacity: 1; transform: rotate(0) scale(1); }
}

/* Sfumatura dei colori solo durante il cambio tema: una transizione
   permanente su tutto renderebbe pigra ogni altra interazione. */
:root.theme-switching *,
:root.theme-switching *::before,
:root.theme-switching *::after {
  transition: background-color 280ms var(--ease-out),
              border-color 280ms var(--ease-out),
              color 280ms var(--ease-out),
              fill 280ms var(--ease-out) !important;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.nav__link {
  position: relative;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--fg-muted);
  border-radius: var(--r-pill);
  transition: color var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.nav__link:hover { color: var(--fg); background: var(--surface); }
.nav__link::after {
  content: '';
  position: absolute;
  left: 50%; bottom: 2px;
  width: 0; height: 2px;
  border-radius: 2px;
  background: var(--grad-brand);
  transform: translateX(-50%);
  transition: width var(--dur-base) var(--ease-out);
}
.nav__link:hover::after { width: 22px; }
/* Stato attivo — pagina corrente (nav-state-active) */
.nav__link[aria-current="page"] { color: var(--fg); }
.nav__link[aria-current="page"]::after { width: 22px; }

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

.nav__toggle {
  display: none;
  width: 48px; height: 48px;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
}
.nav__toggle span {
  display: block;
  width: 18px; height: 2px;
  background: var(--fg);
  border-radius: 2px;
  position: relative;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.nav__toggle span::before,
.nav__toggle span::after {
  content: '';
  position: absolute;
  left: 0;
  width: 18px; height: 2px;
  background: var(--fg);
  border-radius: 2px;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav__toggle span::before { top: -6px; }
.nav__toggle span::after { top: 6px; }
.nav__toggle[aria-expanded="true"] span { background: transparent; }
.nav__toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span::after { transform: translateY(-6px) rotate(-45deg); }

/* Menu mobile */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-8) var(--space-5);
  background: rgb(var(--bg-rgb) / .97);
  backdrop-filter: blur(28px);
  -webkit-backdrop-filter: blur(28px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-slow) var(--ease-out), visibility var(--dur-slow);
}
.mobile-menu.is-open { opacity: 1; visibility: visible; }
.mobile-menu a {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  padding: var(--space-3) 0;
  color: var(--fg-muted);
  border-bottom: 1px solid var(--border);
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out),
              color var(--dur-base) var(--ease-out);
}
.mobile-menu a:hover, .mobile-menu a[aria-current="page"] { color: var(--fg); }
.mobile-menu.is-open a { opacity: 1; transform: translateY(0); }
.mobile-menu.is-open a:nth-child(1) { transition-delay: 60ms; }
.mobile-menu.is-open a:nth-child(2) { transition-delay: 110ms; }
.mobile-menu.is-open a:nth-child(3) { transition-delay: 160ms; }
.mobile-menu.is-open a:nth-child(4) { transition-delay: 210ms; }
.mobile-menu.is-open a:nth-child(5) { transition-delay: 260ms; }

/* --------------------------------------------------------------------------
   9. HERO
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  z-index: var(--z-content);
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-top: var(--nav-h);
  padding-bottom: var(--space-8);
}
.hero--compact { min-height: 62svh; }

.hero__inner {
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: var(--space-8);
  align-items: center;
  width: 100%;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  backdrop-filter: blur(12px);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: var(--space-5);
}
.badge__dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: 0 0 10px var(--lime);
  animation: pulse 2.4s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.8); }
}

.hero__title { margin-bottom: var(--space-5); }

/* Split-text: animazione carattere per carattere */
.split-char {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.55em) rotateX(-45deg);
  transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out);
}
.split-char.is-in { opacity: 1; transform: translateY(0) rotateX(0); }

/* I .split-char sono inline-block: escono dall'area di background-clip:text
   del genitore e resterebbero invisibili. Ogni carattere riceve quindi il
   proprio gradiente, ancorato al viewport (background-attachment: fixed)
   così la sfumatura resta continua da una lettera all'altra. */
.grad-text .split-char {
  background-image: var(--grad-brand);
  background-attachment: fixed;
  background-size: 100vw 100vh;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__role {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  color: var(--accent);
  min-height: 1.8em;
  margin-bottom: var(--space-5);
}
.hero__role .caret {
  display: inline-block;
  width: 9px;
  margin-left: 2px;
  background: var(--accent);
  animation: blink 1s steps(2) infinite;
  color: transparent;
}
@keyframes blink { 50% { opacity: 0; } }

.hero__desc { font-size: var(--text-lg); color: var(--fg-muted); margin-bottom: var(--space-6); }

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

/* ---- SLOT LOGO / RITRATTO nell'hero ---- */
.hero__visual {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
}
.orb {
  position: relative;
  width: 100%;
  max-width: 380px;
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    radial-gradient(circle at 30% 25%, rgba(59,91,245,.34), transparent 55%),
    radial-gradient(circle at 70% 75%, rgba(168,85,247,.30), transparent 55%),
    var(--orb-bg);
  border: 1px solid var(--border-strong);
  backdrop-filter: blur(14px);
  box-shadow: var(--shadow-lg), inset 0 0 80px rgba(124,58,237,.18);
  animation: float 7s ease-in-out infinite;
}
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-18px); }
}
.orb__ring {
  position: absolute;
  inset: -22px;
  border: 1px dashed rgba(255,255,255,.16);
  border-radius: 50%;
  animation: spin 26s linear infinite;
}
.orb__ring--2 {
  inset: -52px;
  border-style: solid;
  border-color: rgba(124,58,237,.22);
  animation-duration: 40s;
  animation-direction: reverse;
}
@keyframes spin { to { transform: rotate(360deg); } }

.orb__slot {
  width: 62%;
  display: grid;
  place-items: center;
  text-align: center;
}
.orb__slot img { width: 100%; }

/* Il simbolo ha due versioni come il lockup dell'header: braccio scuro
   sul tema chiaro, braccio bianco sul tema scuro. Blu e porpora non
   cambiano mai. Anche qui background-image, per scaricarne una sola. */
.orb__mark {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  background: url('../img/logo-mark-dark.png') center / contain no-repeat;
}
:root[data-theme="light"] .orb__mark {
  background-image: url('../img/logo-mark-light.png');
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .orb__mark {
    background-image: url('../img/logo-mark-light.png');
  }
}

/* --------------------------------------------------------------------------
   10. MARQUEE
   -------------------------------------------------------------------------- */
.marquee {
  position: relative;
  z-index: var(--z-content);
  overflow: hidden;
  padding-block: var(--space-5);
  border-block: 1px solid var(--border);
  background: rgb(var(--ink-rgb) / .025);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee__track {
  display: flex;
  width: max-content;
  animation: scrollx 34s linear infinite;
}
.marquee__group {
  display: flex;
  gap: var(--space-7);
  padding-right: var(--space-7);   /* il distacco anche sull'ultima parola */
}
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes scrollx { to { transform: translateX(-50%); } }
.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--fg-subtle);
  white-space: nowrap;
}
.marquee__item::after {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: .6;
}

/* --------------------------------------------------------------------------
   11. CARD / GRID
   -------------------------------------------------------------------------- */
/* minmax(0, 1fr) e non 1fr.
   "1fr" e' l'abbreviazione di "minmax(auto, 1fr)", e quell'auto come minimo
   vuol dire min-content: una colonna non scende mai sotto la larghezza
   minima del suo contenuto, e se quel contenuto e' rigido allarga la griglia
   oltre il contenitore. Con minmax(0, 1fr) la colonna puo' stringersi quanto
   serve e il contenuto si adatta.
   Non e' teoria: a 320 px la <textarea> di contatti.html (larghezza
   intrinseca di 20 caratteri, ~347 px) spingeva la colonna a 347 px dentro un
   contenitore da 288, e modulo, etichette e pulsanti finivano tagliati fuori
   dallo schermo. Non si vedeva perche' l'overflow-x: hidden del body nasconde
   il taglio invece di segnalarlo con una barra di scorrimento. */
.grid { display: grid; gap: var(--space-5); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Celle alte quanto il loro contenuto invece che quanto la piu' alta della
   riga. Serve alle immagini affiancate: due foto con proporzioni diverse,
   allungate alla stessa altezza, lasciano una striscia vuota sotto quella
   piu' bassa — con i segnaposto non si vedeva perche' hanno tutti la stessa
   forma. */
.grid--top { align-items: start; }

.card {
  position: relative;
  padding: var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  overflow: hidden;
  transition: transform var(--dur-slow) var(--ease-out),
              border-color var(--dur-slow) var(--ease-out),
              box-shadow var(--dur-slow) var(--ease-out);
}
/* Glow che segue il puntatore (impostato da JS: --mx / --my) */
.card::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  background: radial-gradient(400px circle at var(--mx, 50%) var(--my, 50%),
              rgba(124,156,255,.13), transparent 42%);
  transition: opacity var(--dur-slow) var(--ease-out);
  pointer-events: none;
}
.card:hover::before { opacity: 1; }
.card:hover {
  transform: translateY(-6px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}
.card__icon {
  width: 46px; height: 46px;
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, rgba(124,156,255,.2), rgba(124,58,237,.2));
  border: 1px solid var(--border);
  margin-bottom: var(--space-5);
  color: var(--accent);
}
.card__icon svg { width: 22px; height: 22px; }
.card h3 { margin-bottom: var(--space-3); font-size: var(--text-xl); }
.card p { color: var(--fg-muted); font-size: var(--text-sm); margin: 0; }

.card__num {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
  letter-spacing: .18em;
  margin-bottom: var(--space-4);
  display: block;
}

/* --------------------------------------------------------------------------
   12. STATS / COUNTER
   -------------------------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-5); }
.stat { text-align: center; padding: var(--space-5) var(--space-3); }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 700;
  line-height: 1;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-variant-numeric: tabular-nums;
}
.stat__label {
  font-size: var(--text-sm);
  color: var(--fg-muted);
  margin-top: var(--space-3);
}

/* --------------------------------------------------------------------------
   13. PROGETTI
   -------------------------------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-7);
}
.filter {
  min-height: 44px;
  padding: var(--space-2) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--fg-muted);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: all var(--dur-base) var(--ease-out);
}
.filter:hover { color: var(--fg); border-color: var(--border-strong); }
.filter[aria-pressed="true"] {
  background: var(--grad-brand);
  color: #ffffff;
  border-color: transparent;
  font-weight: 700;
}

.project {
  display: block;
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-elevated);
  transition: transform var(--dur-slow) var(--ease-out),
              border-color var(--dur-slow) var(--ease-out),
              box-shadow var(--dur-slow) var(--ease-out);
}
.project:hover {
  transform: translateY(-8px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}
.project.is-hidden { display: none; }

/* ---- SLOT IMMAGINE PROGETTO ---- */
.project__media {
  position: relative;
  aspect-ratio: 16 / 10;
  background:
    radial-gradient(circle at 30% 20%, rgba(124,156,255,.25), transparent 60%),
    radial-gradient(circle at 75% 80%, rgba(124,58,237,.25), transparent 60%),
    var(--bg-elevated);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.project__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.project:hover .project__media img { transform: scale(1.06); }
.project__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgb(var(--bg-rgb) / .8));
}
.project__body { padding: var(--space-5) var(--space-6) var(--space-6); }
/* .project__riga-tag e' definita piu' avanti, insieme a .badge-collab
   (capitolo 25b): le due regole nascono insieme e restano vicine. */
.project__tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Il badge "collaborazione" — vedi .badge-collab piu' sotto, sezione 24 */
.project h3 { font-size: var(--text-xl); margin-bottom: var(--space-2); }
.project p { color: var(--fg-muted); font-size: var(--text-sm); margin-bottom: var(--space-4); }
.project__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
  font-family: var(--font-mono);
}
.project__arrow {
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--fg);
  transition: all var(--dur-base) var(--ease-out);
}
.project:hover .project__arrow {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  transform: rotate(-45deg);
}

/* Elenco degli indirizzi nella pagina contatti */
.rubrica li {
  padding-bottom: var(--space-4);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}
.rubrica li:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }

.rubrica__riga {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.rubrica__mail {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent);
  word-break: break-all;
  flex: 1 1 auto;
  min-width: 0;
}
.rubrica__azioni {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}
.rubrica__nota {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--fg-muted);
}

/* Pulsantini quadrati per copia / scrivi */
.icon-btn {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg-muted);
  cursor: pointer;
  transition: color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.icon-btn:hover {
  color: var(--fg);
  border-color: var(--border-strong);
  background: var(--surface-strong);
  transform: translateY(-2px);
}
.icon-btn:active { transform: translateY(0) scale(.95); }
.icon-btn svg { width: 17px; height: 17px; }
.icon-btn.is-fatto {
  color: var(--accent);
  border-color: var(--accent);
}

.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip {
  padding: 4px var(--space-3);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  color: var(--fg-muted);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}

/* --------------------------------------------------------------------------
   14. TIMELINE
   -------------------------------------------------------------------------- */
.timeline { position: relative; padding-left: var(--space-7); }
.timeline::before {
  content: '';
  position: absolute;
  left: 7px; top: 8px; bottom: 8px;
  width: 1px;
  background: linear-gradient(180deg, var(--accent), var(--brand-violet), transparent);
}
.timeline__item { position: relative; padding-bottom: var(--space-7); }
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before {
  content: '';
  position: absolute;
  left: calc(var(--space-7) * -1 + 3px);
  top: 9px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(124,156,255,.14);
}
.timeline__date {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .12em;
  color: var(--accent);
  text-transform: uppercase;
}
.timeline__item h3 { font-size: var(--text-lg); margin: var(--space-2) 0 var(--space-2); }
.timeline__item p { color: var(--fg-muted); font-size: var(--text-sm); margin: 0; }
.timeline__org { color: var(--fg-subtle); font-size: var(--text-sm); }

/* --------------------------------------------------------------------------
   15. SKILL BARS
   -------------------------------------------------------------------------- */
.skill { margin-bottom: var(--space-5); }
.skill__head {
  display: flex;
  justify-content: space-between;
  font-size: var(--text-sm);
  margin-bottom: var(--space-2);
}
.skill__head span:last-child { color: var(--fg-subtle); font-family: var(--font-mono); }
.skill__bar {
  height: 5px;
  border-radius: var(--r-pill);
  background: var(--surface-strong);
  overflow: hidden;
}
.skill__fill {
  height: 100%;
  width: 0;
  border-radius: var(--r-pill);
  background: var(--grad-brand);
  transition: width 1.2s var(--ease-out);
}

/* --------------------------------------------------------------------------
   16. BLOG
   -------------------------------------------------------------------------- */
.post {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: var(--space-6);
  align-items: center;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: all var(--dur-slow) var(--ease-out);
}
.post:hover {
  border-color: var(--border-strong);
  background: var(--surface-strong);
  transform: translateX(6px);
}
.post__thumb {
  aspect-ratio: 4/3;
  border-radius: var(--r-md);
  background:
    radial-gradient(circle at 35% 30%, rgba(124,58,237,.35), transparent 60%),
    radial-gradient(circle at 70% 75%, rgba(124,156,255,.3), transparent 60%),
    var(--bg-elevated);
  display: grid;
  place-items: center;
  color: var(--fg-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  overflow: hidden;
}
/* Con la copertina vera l'immagine riempie il riquadro; senza, resta il
   fondo sfumato qui sopra con dentro il segnaposto .slot. La scheda di un
   progetto aveva gia' la regola equivalente (.project__media img), quella
   di un articolo no perche' nessun articolo aveva ancora una copertina. */
.post__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.post__meta {
  display: flex;
  gap: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
  text-transform: uppercase;
  letter-spacing: .1em;
  margin-bottom: var(--space-3);
}
.post h3 { font-size: var(--text-xl); margin-bottom: var(--space-2); }
.post p { color: var(--fg-muted); font-size: var(--text-sm); margin: 0 0 var(--space-3); }
.post__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
  /* 23 px di testo portati a 45 px di bersaglio, senza spostare niente:
     lo spazio si prende in basso, dove nella scheda non c'e' altro testo,
     invece che sopra, dove finirebbe sul paragrafo. */
  padding-block: 6px 16px;
  margin-block: -6px -16px;
}
.post__link svg { width: 15px; height: 15px; transition: transform var(--dur-base) var(--ease-out); }
.post:hover .post__link svg { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   17. FORM
   -------------------------------------------------------------------------- */
.form { display: grid; gap: var(--space-5); }
.field { display: grid; gap: var(--space-2); }
.field label {
  font-size: var(--text-sm);
  font-weight: 500;
}
.field label .req { color: var(--brand-purple); margin-left: 2px; }
.field input,
.field textarea,
.field select,
.form input,
.form textarea,
.form select,
.filtri select {
  min-height: 52px;                       /* touch-friendly */
  /* I campi di modulo hanno una larghezza intrinseca loro (la <textarea>
     vale 20 caratteri, l'<input> circa 20): senza queste due righe portano
     quella misura dentro il calcolo della griglia e allargano la colonna.
     Vanno insieme al minmax(0, 1fr) delle .grid: quello permette alla
     colonna di stringersi, queste tolgono al campo la scusa per non farlo. */
  min-width: 0;
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--fg);
  font-size: var(--text-base);            /* 16px: niente auto-zoom iOS */
  transition: border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}
.field textarea { min-height: 150px; resize: vertical; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder,
.form input::placeholder { color: var(--fg-subtle); }
.field input:focus, .field textarea:focus, .field select:focus,
.form input:focus, .form select:focus, .filtri select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-strong);
  box-shadow: 0 0 0 3px rgba(124,156,255,.16);
}
.field__help { font-size: var(--text-xs); color: var(--fg-subtle); }
.field__error {
  font-size: var(--text-xs);
  color: var(--danger);
  display: none;
  align-items: center;
  gap: 6px;
}
.field.has-error input,
.field.has-error textarea { border-color: var(--danger); }
.field.has-error .field__error { display: flex; }

.form__status {
  padding: var(--space-4);
  border-radius: var(--r-md);
  border: 1px solid rgb(var(--accent-rgb) / .35);
  background: rgb(var(--accent-rgb) / .08);
  color: var(--accent);
  font-size: var(--text-sm);
  display: none;
}
.form__status.is-visible { display: block; }
.form__status a { color: inherit; text-decoration: underline; font-weight: 600; }
.form__status p { margin: 0 0 var(--space-3); max-width: none; }
.form__status p:last-child { margin-bottom: 0; }

/* Vie d'uscita quando il programma di posta non si apre */
.ripiego {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.ripiego a, .ripiego button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--bg-elevated);
  color: var(--fg);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.ripiego a:hover, .ripiego button:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}
.ripiego svg { width: 16px; height: 16px; }
.form__status--error {
  border-color: rgb(var(--danger-rgb) / .4);
  background: rgb(var(--danger-rgb) / .09);
  color: var(--danger);
}

/* --------------------------------------------------------------------------
   18. CTA FINALE
   -------------------------------------------------------------------------- */
.cta {
  position: relative;
  z-index: var(--z-content);
  text-align: center;
  padding: var(--space-9) var(--space-6);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background:
    radial-gradient(ellipse 70% 100% at 50% 0%, rgba(124,58,237,.20), transparent 70%),
    var(--surface);
  backdrop-filter: blur(14px);
  overflow: hidden;
}
.cta h2 { margin-bottom: var(--space-4); }
.cta p { margin-inline: auto; margin-bottom: var(--space-6); color: var(--fg-muted); }
.cta__azioni {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: center;
}

/* --------------------------------------------------------------------------
   19. FOOTER
   -------------------------------------------------------------------------- */
.footer {
  position: relative;
  z-index: var(--z-content);
  margin-top: var(--space-9);
  border-top: 1px solid var(--border);
  background: rgb(var(--bg-rgb) / .65);
  backdrop-filter: blur(14px);
}
.footer__grid {
  display: grid;
  /* l'ultima colonna piu larga: federico.lombardi@fedeverse.com e lungo
     e altrimenti andrebbe a capo spezzando la parola */
  grid-template-columns: 1.4fr 0.9fr 0.9fr 1.25fr;
  gap: var(--space-7);
  padding-block: var(--space-8) var(--space-6);
}
.footer h4 {
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--fg-subtle);
  margin-bottom: var(--space-4);
  font-family: var(--font-mono);
  font-weight: 400;
}
.footer li { margin-bottom: var(--space-3); }
.footer__mail li { margin-bottom: var(--space-4); }
.footer__mail a {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  word-break: break-all;
}
.footer__mail span {
  display: block;
  color: var(--fg-subtle);
  font-size: var(--text-xs);
  margin-top: 2px;
}
.footer li a {
  color: var(--fg-muted);
  font-size: var(--text-sm);
  transition: color var(--dur-base) var(--ease-out), padding-left var(--dur-base) var(--ease-out);
}
.footer li a:hover { color: var(--accent); padding-left: 5px; }
.footer__brand p {
  color: var(--fg-muted);
  font-size: var(--text-sm);
  max-width: 34ch;
  margin: var(--space-4) 0 var(--space-5);
}
.socials { display: flex; gap: var(--space-3); }
.social {
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--fg-muted);
  transition: all var(--dur-base) var(--ease-out);
}
.social:hover {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: var(--glow-accent);
}
.social svg { width: 19px; height: 19px; }
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  align-items: center;
  padding-block: var(--space-5);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
}

/* --------------------------------------------------------------------------
   20. SLOT PLACEHOLDER (visibili finché non arrivano gli asset definitivi)
   -------------------------------------------------------------------------- */
.slot {
  display: grid;
  place-items: center;
  gap: var(--space-2);
  padding: var(--space-5);
  border: 1px dashed rgb(var(--accent-rgb) / .45);
  border-radius: var(--r-md);
  background: repeating-linear-gradient(
    45deg,
    rgb(var(--accent-rgb) / .05) 0 10px,
    transparent 10px 20px
  );
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .1em;
  text-align: center;
  text-transform: uppercase;
}
.slot__hint { color: var(--fg-subtle); text-transform: none; letter-spacing: 0; }

/* --------------------------------------------------------------------------
   21. REVEAL ON SCROLL
   -------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(34px);
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
  will-change: opacity, transform;
}
[data-reveal="left"]  { transform: translateX(-40px); }
[data-reveal="right"] { transform: translateX(40px); }
[data-reveal="scale"] { transform: scale(.94); }
[data-reveal].is-in {
  opacity: 1;
  transform: translate(0) scale(1);
}

/* --------------------------------------------------------------------------
   22. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .hero__inner { grid-template-columns: 1fr; gap: var(--space-7); }
  .hero__visual { order: -1; max-width: 300px; margin-inline: auto; }
}

@media (max-width: 860px) {
  :root { --nav-h: 64px; }
  /* I reveal orizzontali diventano verticali: su schermi stretti
     translateX creerebbe scroll orizzontale prima dell'animazione. */
  [data-reveal="left"], [data-reveal="right"] { transform: translateY(34px); }

  /* Il lockup e largo quasi 8 volte la sua altezza: a 34px occupa 267px e
     spingeva il pulsante del menu fuori dallo schermo. Scende per gradi. */
  .logo__img { height: 30px; }
  .nav__inner { gap: var(--space-3); }
  .nav__links, .nav__actions .btn { display: none; }
  .nav__toggle { display: flex; }
  .grid--3, .grid--2 { grid-template-columns: 1fr; }
  .section { padding-block: var(--space-8); }
  .post { grid-template-columns: 1fr; }
  .post:hover { transform: none; }
  .post__thumb { aspect-ratio: 16/9; }
}

@media (max-width: 560px) {
  .container { padding-inline: var(--space-4); }
  .logo__img { height: 26px; }
  .nav__actions { gap: var(--space-2); }
  .stats { grid-template-columns: 1fr 1fr; gap: var(--space-3); }
  .grid--4 { grid-template-columns: 1fr; }
  .cta { padding: var(--space-8) var(--space-5); }
  .btn { width: 100%; }
  .hero__actions { flex-direction: column; }
  .footer__grid { grid-template-columns: 1fr; gap: var(--space-6); }
}

/* Telefoni molto stretti (iPhone SE e simili) */
@media (max-width: 380px) {
  .logo__img { height: 21px; }

  /* Sui telefoni piu' stretti il pavimento della scala tipografica e' troppo
     alto. --text-5xl non scende mai sotto i 48 px, e "stratosferica" a 48 px
     misura 347 px in una colonna che ne ha 288: la parola non ci sta, e
     l'unico modo per farcela stare e' spezzarla a meta' senza trattino
     (l'animazione data-split incapsula ogni lettera in uno <span>, e la
     sillabazione non attraversa quei confini).
     Abbassando il pavimento la parola ci sta intera e il titolo resta grande.
     Vale solo sotto i 380 px: da li' in su i 48 px vanno benissimo. */
  :root {
    --text-5xl: clamp(2.25rem, 11vw, 3rem);
    --text-4xl: clamp(2rem, 9vw, 2.5rem);
  }
}

/* --------------------------------------------------------------------------
   23. REDUCED MOTION — obbligatorio (a11y)
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal], .split-char { opacity: 1 !important; transform: none !important; }
  .fx__blob, .fx__noise, .orb, .orb__ring { animation: none !important; }
  .cursor, .cursor-ring { display: none !important; }
}

/* --------------------------------------------------------------------------
   24. PAGINE DI DETTAGLIO — progetti e articoli

   Componenti usati solo dalle pagine interne (un progetto, un articolo).
   Costruiti sui token esistenti: nessun colore fisso.
   -------------------------------------------------------------------------- */

/* Colonna stretta per il testo lungo: oltre i ~70 caratteri per riga la
   lettura peggiora, quindi le pagine di racconto usano questa invece del
   contenitore pieno. */
.container--narrow { max-width: 760px; }

.section__head--left { text-align: left; margin-inline: 0; }

/* Ritorno all'elenco. 44 px di area toccabile garantiti dal padding. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  margin-bottom: var(--space-3);
  color: var(--fg-muted);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  transition: color 200ms ease, transform 200ms ease;
}
.back-link svg { width: 16px; height: 16px; }
.back-link:hover { color: var(--accent); }
.back-link:hover svg { transform: translateX(-3px); }
.back-link svg { transition: transform 200ms ease; }

/* Scheda dei dati essenziali del progetto */
.factsheet {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-5);
  margin: var(--space-6) 0 0;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.factsheet dt {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--fg-subtle);
  margin-bottom: var(--space-1);
}
.factsheet dd { margin: 0; font-weight: 500; }

/* --------------------------------------------------------------------------
   Collaborazione BlackCubes — capitolo 25b della documentazione.

   I cinque progetti scolastici sono nati col team BlackCubes: il badge
   segnala la collaborazione ovunque il progetto compaia — sulla scheda
   dell'elenco e in cima alla pagina di dettaglio, stessa classe in
   entrambi i posti, per non dover mantenere due stili per la stessa cosa.
   -------------------------------------------------------------------------- */
/* Qui il bersaglio si allarga con un ::after e non col padding: la pillola ha
   un bordo visibile, e del padding vero le cambierebbe la forma. Il
   pseudo-elemento e' trasparente, sta sopra il testo e raccoglie il tocco
   senza che si veda niente. */
.badge-collab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px var(--space-3) 3px 3px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--fg-subtle);
  text-decoration: none;
  transition: border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
a.badge-collab::after {
  content: "";
  position: absolute;
  inset: -12px -8px;
}
a.badge-collab:hover { border-color: var(--accent); color: var(--fg); }
.badge-collab svg {
  width: 16px; height: 16px;
  padding: 3px;
  border-radius: 50%;
  background: var(--grad-brand);
  color: #fff;
}
/* Sulla card dell'elenco sta accanto a .project__tag, sulla stessa riga */
.project__riga-tag { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-3); }
.project__riga-tag .project__tag { margin-bottom: 0; }
/* In cima alla pagina di dettaglio sta sotto l'eyebrow, sopra il titolo */
.section__head--left .badge-collab { margin-bottom: var(--space-3); }

/* Il riquadro che spiega cos'e' BlackCubes, in fondo a ogni pagina che
   nasce dalla collaborazione. Stesso testo su tutti e cinque i progetti:
   e' descritto una volta al capitolo 25b, non ripetuto a mano cinque volte
   nella documentazione. */
.collab-team {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.collab-team__marchio {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  background: var(--grad-brand);
  color: #fff;
}
.collab-team__marchio svg { width: 22px; height: 22px; }
.collab-team h3 { margin: 0 0 var(--space-2); font-size: var(--text-base); }
.collab-team p { margin: 0; font-size: var(--text-sm); color: var(--fg-muted); }
.collab-team p + p { margin-top: var(--space-2); }
.collab-team a { color: var(--accent); text-decoration: underline; text-underline-offset: .15em; }

@media (max-width: 479px) {
  .collab-team { flex-direction: column; }
}

/* Contenitore di un'immagine (o di un segnaposto) */
.figura {
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--border);
}
.figura img { display: block; width: 100%; height: auto; }

/* Testo lungo: l'unico punto del sito in cui i tag HTML sono stilizzati
   direttamente, perche il contenuto di un articolo non ha classi. */
.prose { font-size: var(--text-base); line-height: 1.75; color: var(--fg-muted); }
.prose > * + * { margin-top: var(--space-5); }
.prose h2 {
  margin-top: var(--space-7);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1.25;
  color: var(--fg);
}
.prose ul, .prose ol { padding-left: 1.25em; }
.prose li + li { margin-top: var(--space-2); }
.prose strong { color: var(--fg); font-weight: 700; }
/* Scheda tecnica: etichetta a sinistra, valore a destra. Su schermo stretto
   le due colonne si impilano, perche' a 320 px una tabella a due colonne
   spezzerebbe le parole. */
.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.prose th, .prose td {
  text-align: left;
  vertical-align: top;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
}
.prose th {
  width: 38%;
  padding-right: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--fg-subtle);
  font-weight: 500;
}
.prose td { color: var(--fg); }
@media (max-width: 479px) {
  .prose th, .prose td { display: block; width: auto; }
  .prose th { border-bottom: 0; padding-bottom: var(--space-1); }
}

.prose code {
  font-family: var(--font-mono);
  font-size: .9em;
  padding: .15em .45em;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--border);
}

/* --------------------------------------------------------------------------
   Il resto di .prose: sottotitoli, collegamenti, citazioni, blocchi di
   codice, immagini con didascalia e righe di stacco.

   Le due pagine di dettaglio scritte a mano non usavano nessuna di queste
   cose, quindi non erano mai state disegnate. Il pannello di pubblicazione
   (capitolo 25) sa produrle tutte: senza queste regole genererebbe HTML
   valido che il sito disegna con i valori predefiniti del browser —
   collegamenti neri e indistinguibili (la regola globale e' `a { color:
   inherit; text-decoration: none }`), citazioni solo rientrate, immagini
   larghe quanto il file originale.
   -------------------------------------------------------------------------- */

.prose h3 {
  margin-top: var(--space-6);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: 1.3;
  color: var(--fg);
}

/* Sottolineato: e' l'unico segno che distingue un collegamento dentro un
   testo lungo, quindi il colore da solo non basterebbe (criterio 1.4.1). */
.prose a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: .18em;
  text-decoration-thickness: 1px;
  transition: color var(--dur-fast) var(--ease-out);
}
.prose a:hover { color: var(--fg); }

/* La barra sta a sinistra e non dentro il testo: a 320 px un rientro grande
   lascerebbe righe di tre parole. */
.prose blockquote {
  margin-left: 0;
  margin-right: 0;
  padding: var(--space-1) 0 var(--space-1) var(--space-5);
  border-left: 3px solid var(--accent);
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--fg);
}
.prose blockquote > * + * { margin-top: var(--space-3); }

/* Blocco di codice: scorre per conto suo invece di allargare la pagina.
   Il <code> dentro un <pre> annulla lo sfondo del codice in riga, altrimenti
   si vedrebbero due riquadri sovrapposti. */
.prose pre {
  overflow-x: auto;
  padding: var(--space-4);
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: var(--text-sm);
  line-height: 1.6;
  -webkit-overflow-scrolling: touch;
}
.prose pre code {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  border-radius: 0;
  font-size: inherit;
  color: var(--fg);
  white-space: pre;
}

/* Le immagini dentro il testo riusano .figura, come nelle pagine scritte a
   mano; qui si copre anche il caso in cui la classe manchi. */
.prose figure { margin: 0; }
.prose figure img,
.prose > img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-lg);
}
.prose figure.figura img { border-radius: 0; }
.prose figcaption {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  line-height: 1.55;
  color: var(--fg-subtle);
}
.prose figure.figura figcaption {
  margin-top: 0;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border);
}

/* Blocco di codice con il pulsante "copia" (sezione 23 di main.js).

   Il guscio lo crea il JavaScript attorno al <pre>: nell'HTML della pagina
   non c'e', quindi senza JavaScript resta un blocco di codice normale invece
   di un pulsante che non fa niente.

   Serve a chi legge, non a chi scrive: un comando in un articolo esiste per
   essere incollato in un terminale, e selezionarlo a mano su un telefono
   vuol dire prendere una riga di troppo o una di meno.

   Tre regole che il pulsante deve rispettare, ed e' per queste che e' fatto
   cosi' e non piu' grande:

   1. NON COPRE IL CODICE, MAI. Ed e' meno banale di quanto sembra: un
      `padding-right` sul <pre> non basta, perche' in un contenitore che
      scorre il testo troppo lungo attraversa il padding e passa sotto al
      pulsante. Bisogna che l'area di scorrimento sia FISICAMENTE piu'
      stretta. Quindi il riquadro — fondo, bordo, angoli — passa al guscio
      `.codeblock`, e il <pre> resta un contenitore nudo dentro al suo
      padding: il codice non puo' arrivare dove sta il pulsante nemmeno
      scorrendo.
   2. NON SI VEDE FINCHE' NON SERVE. Solo l'icona, e solo passandoci sopra.
   3. QUANDO E' NASCOSTO NON ESISTE. Con la sola opacita' a zero restava
      cliccabile e raggiungibile col puntatore: invisibile ma nel mezzo.
      Serve anche visibility, che lo toglie di scena davvero. */
.codeblock {
  position: relative;
  padding: var(--space-4);
  /* 34 px di pulsante piu' l'aria ai suoi lati */
  padding-right: calc(var(--space-4) + 44px);
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--border);
}

/* Il <pre> perde il riquadro, che adesso e' del guscio, e resta solo il
   contenitore che scorre. Questa regola sta dopo `.prose pre` nel file,
   quindi a pari specificita' vince. */
.codeblock pre {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  border-radius: 0;
}

.codeblock__copia {
  position: absolute;
  top: 10px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg-elevated);
  color: var(--fg-subtle);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-fast) var(--ease-out),
              visibility var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}

.codeblock__copia svg { width: 16px; height: 16px; }

/* Compare passandoci sopra. Resta pero' sempre visibile dove non c'e' un
   puntatore — su telefono "passare sopra" non esiste — e quando prende il
   fuoco da tastiera, altrimenti chi naviga con Tab arriverebbe su un
   pulsante che non si vede. */
/* :focus-visible e non :focus-within, e la differenza si vede.
   Con :focus-within, dopo un clic col mouse il pulsante restava acceso anche
   dopo che il puntatore se n'era andato, perche' il clic gli lascia il fuoco.
   :focus-visible scatta solo quando il fuoco arriva dalla tastiera: chi naviga
   con Tab lo vede, chi ha appena cliccato lo vede sparire come si aspetta.
   .is-fatto lo tiene acceso il secondo e mezzo della conferma. */
.codeblock:hover .codeblock__copia,
.codeblock__copia:focus-visible,
.codeblock__copia.is-fatto {
  opacity: 1;
  visibility: visible;
}

@media (hover: none) {
  .codeblock__copia { opacity: 1; visibility: visible; width: 44px; height: 44px; }
  .codeblock { padding-right: calc(var(--space-4) + 54px); }
}

.codeblock__copia:hover { color: var(--fg); border-color: var(--accent); }
.codeblock__copia:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.codeblock__copia.is-fatto { color: var(--success); border-color: var(--success); }

/* La conferma. Sta SOPRA il blocco, non dentro: cosi' nemmeno per quel
   secondo e mezzo copre una riga di codice. Sparisce da sola. */
.codeblock__eco {
  position: absolute;
  top: -12px;
  right: 8px;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--success);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .03em;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.codeblock__eco.is-visibile { opacity: 1; transform: none; }

.prose hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin-top: var(--space-7);
  margin-bottom: var(--space-7);
}

.prose ol { list-style: decimal; }
.prose ul { list-style: disc; }

/* Titolo di un articolo nell'elenco del blog: e' un collegamento, ma deve
   restare un titolo alla vista. */
.post h3 a {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 2px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size 260ms var(--ease-out);
}
.post h3 a:hover { background-size: 100% 2px; }
@media (prefers-reduced-motion: reduce) { .post h3 a { transition: none; } }

/* Elenco dei file allegati a un progetto */
.downloads { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.download a {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: 44px;                 /* bersaglio tattile */
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--fg);
  text-decoration: none;
  transition: border-color 200ms ease, transform 200ms ease;
}
.download a:hover { border-color: var(--accent); transform: translateY(-2px); }
.download__icon, .download__action { flex: 0 0 auto; color: var(--accent); }
.download__icon svg { width: 22px; height: 22px; }
.download__action svg { width: 18px; height: 18px; }
.download__body { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.download__name { font-weight: 600; }
.download__meta {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
  text-transform: uppercase;
  letter-spacing: .06em;
}

@media (prefers-reduced-motion: reduce) {
  .back-link, .back-link svg, .download a { transition: none; }
  .back-link:hover svg, .download a:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   24a. TENDINE DELL'HEADER (Progetti e Blog)

   Si aprono con :hover e :focus-within, non con JavaScript di stato: cosi'
   non possono restare aperte per errore e funzionano anche mentre il
   contenuto e' ancora in caricamento. Il pannello vuoto non compare
   (:not(:empty)), quindi senza JavaScript la voce resta un link normale.
   -------------------------------------------------------------------------- */
.nav__voce { position: relative; display: inline-flex; }

.nav__panel {
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  z-index: var(--z-nav);
  display: grid;
  gap: 2px;
  width: 340px;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -6px);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out),
              visibility var(--dur-base);
}
/* zona di sicurezza: il puntatore attraversa lo spazio senza far chiudere */
.nav__panel::before {
  content: '';
  position: absolute;
  inset: -16px 0 100% 0;
}
.nav__voce:hover .nav__panel:not(:empty),
.nav__voce:focus-within .nav__panel:not(:empty) {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

.nav__panel-voce {
  display: grid;
  gap: 3px;
  padding: var(--space-3);
  border-radius: var(--r-md);
  color: var(--fg);
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.nav__panel-voce:hover, .nav__panel-voce:focus-visible {
  background: var(--surface-strong);
}
.nav__panel-titolo { font-weight: 600; font-size: var(--text-sm); }
.nav__panel-descr {
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--fg-muted);
}
.nav__panel-tutti {
  margin-top: var(--space-2);
  padding: var(--space-3);
  border-top: 1px solid var(--border);
  border-radius: 0 0 var(--r-md) var(--r-md);
  color: var(--accent);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .06em;
  text-decoration: none;
}
.nav__panel-tutti:hover { background: var(--surface-strong); }

/* Su schermi senza puntatore preciso la tendina non serve: c'e' il menu
   a tutta pagina, e un pannello al passaggio del dito darebbe fastidio. */
@media (max-width: 900px), (hover: none) {
  .nav__panel { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .nav__panel { transition: none; }
}

/* --------------------------------------------------------------------------
   24b. MENU A TENDINA

   Due problemi risolti qui.

   1) La FRECCIA di sistema non c'entra niente col resto del sito: con
      appearance:none sparisce e ne disegniamo una nostra come immagine di
      sfondo (un SVG in data: URI, gia' permesso dalla CSP).

   2) La TENDINA che si apre e' disegnata dal sistema operativo, non dal
      nostro CSS. In tema scuro ereditava il testo chiaro su un fondo chiaro:
      illeggibile. Va dato un colore esplicito alle <option>, con un fondo
      OPACO — non var(--surface), che e' semitrasparente.
   -------------------------------------------------------------------------- */
.field select,
.form select,
.filtri select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: calc(var(--space-4) + 22px);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237c9cff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  background-size: 18px 18px;
  cursor: pointer;
}
.field select option,
.form select option,
.filtri select option {
  background-color: var(--bg-elevated);   /* opaco: la tendina e' del sistema */
  color: var(--fg);
}

/* --------------------------------------------------------------------------
   25. BARRA DEI FILTRI (blog)
   -------------------------------------------------------------------------- */
.filtri {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.filtri__campo { display: flex; flex-direction: column; gap: var(--space-2); min-width: 220px; }
.filtri select { min-height: 48px; }
.filtri__campo label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--fg-subtle);
}
.filtri__esito {
  margin: 0 0 var(--space-2) auto;
  font-size: var(--text-sm);
  color: var(--fg-muted);
}
@media (max-width: 559px) {
  .filtri__campo { min-width: 100%; }
  .filtri__esito { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   26. FOTO RITRATTO NELLA SFERA
   -------------------------------------------------------------------------- */
.orb__foto {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

/* --------------------------------------------------------------------------
   27. SEGNALATORE DELL'AMBIENTE DI SVILUPPO

   Compare solo fuori da fedeverse.com (vedi sezione 17 di main.js): serve a
   non confondere una copia di lavoro col sito pubblico. Non e mai presente
   nel DOM in produzione, quindi qui non c'e niente da nascondere a mano.

   Nota: questo file arriva al browser cosi' com'e, commenti compresi. Il
   nome dell'ambiente di sviluppo non si scrive qui — vale la stessa regola
   della sezione 17 di main.js.

   pointer-events: none e deliberato: il segnalatore non deve mai intercettare
   un clic destinato al sito.
   -------------------------------------------------------------------------- */
.dev-badge {
  position: fixed;
  left: var(--space-4);
  bottom: var(--space-4);
  z-index: var(--z-cursor);
  display: flex;
  align-items: center;
  gap: .5em;
  padding: .5em .85em;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--accent-ink);          /* 7,5:1 sull'accento, in entrambi i temi */
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  box-shadow: var(--shadow-md);
  pointer-events: none;
  user-select: none;
}

.dev-badge__dot {
  width: .5em;
  height: .5em;
  border-radius: 50%;
  background: var(--accent-ink);
  flex: 0 0 auto;
}

/* Sotto i 560 px resta il solo "DEV": la fascia non deve rubare spazio
   di lettura sui telefoni. */
@media (max-width: 559px) {
  .dev-badge__text { display: none; }
}

/* --------------------------------------------------------------------------
   28. SOSTIENI — wallet crypto e finestra delle donazioni

   Una cosa sola guida tutto il componente: un indirizzo crypto sbagliato di
   un carattere manda i fondi nel vuoto, e non esiste nessun annullamento.
   Quindi l'indirizzo non va MAI ricopiato a mano. Le tre vie offerte sono
   tutte a prova di refuso: il pulsante che copia, il QR da inquadrare col
   telefono e il collegamento che apre direttamente l'app del wallet.
   -------------------------------------------------------------------------- */
.wallets {
  display: grid;
  gap: var(--space-4);
  list-style: none;
}

.wallet {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4) var(--space-5);
  align-items: start;
  padding: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}

.wallet__head {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.wallet__icon {
  width: 40px; height: 40px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: linear-gradient(135deg, rgba(124,156,255,.2), rgba(124,58,237,.2));
  color: var(--accent);
}
.wallet__icon svg { width: 21px; height: 21px; }

.wallet__nome {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
}
/* La rete e' scritta accanto al nome e non in fondo: mandare bitcoin a un
   indirizzo Ethereum e' l'errore piu' comune, e va letto prima di inviare. */
.wallet__rete {
  margin-left: auto;
  padding: 4px var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-muted);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  white-space: nowrap;
}

/* Il QR resta nero su bianco in tutti e due i temi: un QR invertito o
   colorato lo leggono solo alcuni telefoni, e qui deve leggerlo qualsiasi
   fotocamera al primo colpo. Il fondo bianco fa anche da zona di quiete. */
.wallet__qr {
  width: 132px; height: 132px;
  padding: var(--space-2);
  border-radius: var(--r-md);
  background: #ffffff;
  border: 1px solid var(--border);
}
.wallet__qr img { display: block; width: 100%; height: 100%; }

.wallet__dati { min-width: 0; }

.wallet__addr {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--fg);
  word-break: break-all;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: rgb(var(--ink-rgb) / .04);
  /* Un doppio clic seleziona l'indirizzo intero, non la singola parola */
  user-select: all;
}

.wallet__azioni {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.wallet__azioni .btn { flex: 1 1 auto; padding-inline: var(--space-5); }

.wallet__nota {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--fg-subtle);
}

/* Sotto i 560 px il QR passa sopra i dati e si centra: affiancato lascerebbe
   all'indirizzo una colonna troppo stretta per restare leggibile. */
@media (max-width: 559px) {
  .wallet { grid-template-columns: 1fr; }
  .wallet__qr { margin-inline: auto; }
  .wallet__rete { margin-left: 0; }
}

/* --- Avviso prima di inviare ------------------------------------------- */
.avviso {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.avviso svg { width: 22px; height: 22px; flex: 0 0 auto; color: var(--accent); }
.avviso p { margin: 0; font-size: var(--text-sm); color: var(--fg-muted); }
.avviso p + p { margin-top: var(--space-3); }
.avviso strong { color: var(--fg); }

/* --- La finestra ------------------------------------------------------- */
/* E' un <dialog> vero: la trappola del focus, la chiusura con Esc e
   l'inerzia del resto della pagina le fa il browser, senza che il sito
   debba reimplementarle (e sbagliarle). */
.sostieni-dialog {
  width: min(640px, calc(100vw - var(--space-5) * 2));
  max-height: min(86vh, 900px);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  color: var(--fg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

/* La comparsa e' un'animazione, non una transizione.
   Un <dialog> passa da display:none al livello superiore del browser, e una
   transizione che parte da quel salto richiede @starting-style: senza, il
   primo fotogramma puo' essere saltato e la finestra comparire di colpo.
   Con @keyframes non serve, ma soprattutto lo stato di riposo resta
   "visibile": il guasto possibile diventa una finestra che appare senza
   dissolvenza (innocuo) invece di una finestra che non si vede affatto
   (dannoso). E' la stessa logica al contrario del segnalatore di ambiente.
   Le durate le azzera da solo il blocco prefers-reduced-motion. */
@keyframes sostieni-entra {
  from { opacity: 0; transform: translateY(12px) scale(.98); }
}
@keyframes sostieni-esce {
  to { opacity: 0; transform: translateY(12px) scale(.98); }
}
@keyframes sostieni-scrim {
  from { opacity: 0; }
}
.sostieni-dialog[open] { animation: sostieni-entra var(--dur-base) var(--ease-out); }
.sostieni-dialog.is-out { animation: sostieni-esce var(--dur-fast) var(--ease-in-out) forwards; }

/* Lo scrim resta scuro anche in tema chiaro: ::backdrop non eredita in modo
   affidabile le variabili del tema su tutti i browser, e uno scrim scuro
   sotto una finestra e' comunque la convenzione. */
.sostieni-dialog::backdrop {
  background: rgba(4, 5, 12, .68);
  backdrop-filter: blur(6px);
}
.sostieni-dialog[open]::backdrop { animation: sostieni-scrim var(--dur-base) var(--ease-out); }

.sostieni-dialog__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-5) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.sostieni-dialog__head h2 {
  margin: 0;
  font-size: var(--text-xl);
}
.sostieni-dialog__head p {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--fg-muted);
}
.sostieni-dialog__chiudi { margin-left: auto; flex: 0 0 auto; }

.sostieni-dialog__corpo {
  padding: var(--space-5);
  overflow-y: auto;
  max-height: calc(min(86vh, 900px) - 190px);
  overscroll-behavior: contain;
}
.sostieni-dialog__corpo .wallet { padding: var(--space-4); }

.sostieni-dialog__pie {
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border);
  font-size: var(--text-sm);
  color: var(--fg-muted);
  text-align: center;
}

/* Stato di attesa mentre la finestra legge la pagina /sostieni */
.sostieni-dialog__attesa {
  padding: var(--space-7) 0;
  text-align: center;
  color: var(--fg-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

@media (max-width: 559px) {
  .sostieni-dialog { width: 100%; max-height: 92vh; border-radius: var(--r-md); }
  .sostieni-dialog__corpo { max-height: calc(92vh - 200px); }
  /* Il pulsante di chiusura non deve diventare largo come la finestra */
  .sostieni-dialog__chiudi { width: 44px; }
}

/* --------------------------------------------------------------------------
   28b. PRESENTAZIONI — visualizzatore proprietario delle diapositive

   Le presentazioni dei progetti (capitolo 25b della documentazione) non sono
   incorporate da Canva o da altri servizi: la CSP del sito non ammette
   iframe esterni (default-src 'self', nessun frame-src aggiunto apposta), e
   un embed esterno avrebbe portato peso enorme e una dipendenza in più.

   Ogni PDF viene invece rasterizzato in JPEG leggeri e mostrato con un
   visualizzatore proprio del sito: stesso design system, stessi due temi,
   funziona con qualunque presentazione esportata in PDF — non solo Canva.

   Il trigger e' un <a> vero con href al PDF autoospitato e target="_blank":
   senza JavaScript porta comunque alla presentazione, aperta dal browser.
   Il JavaScript (sezione 24 di main.js) intercetta il clic e apre invece
   il visualizzatore proprietario. Stessa logica di .sostieni-dialog.
   -------------------------------------------------------------------------- */

/* --- Il trigger nella pagina: poster della prima diapositiva + velo --- */
.presentazione {
  position: relative;
  display: block;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  cursor: pointer;
}
.presentazione__poster {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--bg-elevated);
}

/* Il velo resta sempre leggermente visibile (non solo su :hover): su un
   telefono non esiste il passaggio del puntatore, e senza un segno
   permanente il riquadro sembrerebbe una semplice immagine, non qualcosa
   da aprire. */
.presentazione__velo {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  background: linear-gradient(180deg, rgba(4,5,12,0) 40%, rgba(4,5,12,.72) 100%);
  color: #fff;
  transition: background-color var(--dur-base) var(--ease-out);
}
.presentazione:hover .presentazione__velo,
.presentazione:focus-visible .presentazione__velo {
  background: rgba(4,5,12,.55);
}
.presentazione:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.presentazione__bottone {
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.4);
  backdrop-filter: blur(6px);
  transition: transform var(--dur-base) var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}
.presentazione__bottone svg { width: 24px; height: 24px; margin-left: 3px; }
.presentazione:hover .presentazione__bottone,
.presentazione:focus-visible .presentazione__bottone {
  transform: scale(1.08);
  background: rgba(255,255,255,.26);
}

.presentazione__testo {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: .04em;
  text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

/* Il download diretto, per chi vuole solo il file e non il visualizzatore.
   E' un pulsante e non un collegamento sottolineato: sta sotto un riquadro
   grande e scuro, e un link di testo li' sotto sembrava un residuo invece di
   un'azione. */
.presentazione__azioni {
  display: flex;
  justify-content: center;
  margin-top: var(--space-4);
}

@media (prefers-reduced-motion: reduce) {
  .presentazione__velo, .presentazione__bottone { transition: none; }
  .presentazione:hover .presentazione__bottone { transform: none; }
}

/* --- Il visualizzatore: <dialog> nativo, come .sostieni-dialog --- */
.presentazione-dialog {
  width: min(1120px, calc(100vw - var(--space-5) * 2));
  max-height: min(90vh, 980px);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  color: var(--fg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

/* Stessa animazione di comparsa di .sostieni-dialog: keyframes e non
   transizione, perche' un <dialog> salta da display:none al livello
   superiore del browser e una transizione partirebbe da uno stato che il
   primo fotogramma puo' non dipingere in tempo. */
@keyframes presentazione-entra { from { opacity: 0; transform: translateY(12px) scale(.98); } }
@keyframes presentazione-esce { to { opacity: 0; transform: translateY(12px) scale(.98); } }
@keyframes presentazione-scrim { from { opacity: 0; } }
.presentazione-dialog[open] { animation: presentazione-entra var(--dur-base) var(--ease-out); }
.presentazione-dialog.is-out { animation: presentazione-esce var(--dur-fast) var(--ease-in-out) forwards; }
.presentazione-dialog::backdrop { background: rgba(4,5,12,.78); backdrop-filter: blur(6px); }
.presentazione-dialog[open]::backdrop { animation: presentazione-scrim var(--dur-base) var(--ease-out); }

.presentazione-dialog__head {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.presentazione-dialog__titolo {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.presentazione-dialog__contatore {
  margin: 0 0 0 auto;
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
  letter-spacing: .04em;
}
.presentazione-dialog__chiudi { flex: 0 0 auto; }

.presentazione-dialog__corpo {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
  /* L'altezza segue le proporzioni reali delle diapositive (16:9), fino al
     limite dato dal <dialog> stesso: evita sia un riquadro nero vuoto sotto
     immagini piu' basse, sia uno scorrimento interno inutile. */
  max-height: calc(min(90vh, 980px) - 210px);
  overflow: hidden;
}
.presentazione-dialog__slide-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
}
.presentazione-dialog__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

.presentazione-dialog__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.3);
  background: rgba(0,0,0,.45);
  color: #fff;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.presentazione-dialog__nav:hover { background: rgba(0,0,0,.7); }
.presentazione-dialog__nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.presentazione-dialog__nav[disabled] { opacity: .25; cursor: default; }
.presentazione-dialog__nav--prev { left: var(--space-3); }
.presentazione-dialog__nav--next { right: var(--space-3); }
.presentazione-dialog__nav svg { width: 20px; height: 20px; }

.presentazione-dialog__pie {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border);
}

@media (max-width: 640px) {
  .presentazione-dialog { width: 100%; height: 100%; max-height: 100vh; border-radius: 0; }
  /* A schermo intero il riquadro nero della diapositiva (16:9) occupa poco
     piu' di 200 px: senza questo, testata, immagine e piede si accatastano in
     alto e sotto resta mezzo schermo vuoto. Impilandoli in colonna e lasciando
     crescere il corpo, la diapositiva sta al centro e il piede in fondo.
     Il display va sul selettore [open]: metterlo sul <dialog> nudo annulla il
     display:none del browser e la finestra resterebbe sempre visibile. */
  .presentazione-dialog[open] { display: flex; flex-direction: column; }
  .presentazione-dialog__head,
  .presentazione-dialog__pie { flex: 0 0 auto; }
  .presentazione-dialog__corpo { flex: 1 1 auto; max-height: none; }
  .presentazione-dialog__titolo { font-size: var(--text-xs); }
  .presentazione__bottone { width: 52px; height: 52px; }
}

@media (prefers-reduced-motion: reduce) {
  .presentazione-dialog[open],
  .presentazione-dialog.is-out,
  .presentazione-dialog[open]::backdrop,
  .presentazione-dialog__nav { animation: none; transition: none; }
}

/* --------------------------------------------------------------------------
   29. PRINT
   -------------------------------------------------------------------------- */
@media print {
  .fx, .nav, .footer, .cursor, .cursor-ring, .progress { display: none !important; }
  .dev-badge { display: none !important; }
  body { background: #fff; color: #000; }
  /* Stampando la pagina "Sostieni" servono QR e indirizzi, non lo sfondo */
  .wallet { break-inside: avoid; border-color: #999; background: #fff; }
  .wallet__addr { color: #000; background: #fff; border-color: #999; }
}
