/*
Theme Name: Semplice Child - Marco Madonna Dark
Description: Child theme per marcomadonnadesign.com - restyling dark mode con accenti viola, glass e gradienti
Author: Marco Madonna
Template: semplice5
Version: 1.3.0

NOTA: "Template" verificato via view-source sul sito live il 2026-09-01:
il tema padre carica wp-content/themes/semplice5/style.css, quindi la
cartella del tema padre in wp-content/themes/ e' "semplice5".

Selettori verificati ispezionando il markup reale generato da Semplice su
marcomadonnadesign.com. Semplice e' un page builder: il contenuto non ha
classi semantiche (niente .hero, .project, .card) ma una struttura ricorrente:

  .content-block (una sezione / "riga" della pagina)
    .container > .row > .column > .content-wrapper
      .column-content[data-module="image"]  > .ce-image > img.is-content
      .column-content[data-module="text"]   > .is-content (p/span)
      .column-content[data-module="button"] > .ce-button > .is-content > a

Sulla homepage le sezioni (.content-block, in ordine DOM) sono:
  1. Hero (nome + ruolo + intro)
  2. Etichetta "SELECTED PROJECTS"
  3-6. Un content-block per ogni progetto (immagine + titolo + descrizione + bottone "View project")
  7. Footer ("GET IN TOUCH" + Email/LinkedIn + copyright)

IMPORTANTE (scoperto in locale, 2026-09-01): Semplice genera CSS per-pagina
inline in <head> con selettori per ID, residuo del design chiaro originale -
background e colori vanno forzati con !important su selettori ampi.
.transition-wrap NON va nascosto con display:none: in modalita' "dynamic" e'
anche il contenitore del contenuto reale della pagina, non solo l'overlay
decorativo - va solo neutralizzato lo sfondo bianco.

Direzione visiva (aggiornata 2026-09-01 dopo il CV condiviso da Marco):
- Font headings: Inter (richiesta esplicita di Marco - Space Grotesk era un
  tentativo precedente basato sul CV, poi corretto)
- Accento: viola #8b5cf6, campionato per pixel dal CV di Marco (stesso viola
  usato li' per i nomi delle aziende)
- Le vecchie tinte aqua/blu (nostro accento precedente + colori inline
  ereditati dal design chiaro originale, es. i range di date "2022 - 2023"
  sulla pagina About) vengono rimappate all'accento viola via JS
  (mm-animations.js, funzione remapLegacyAccentColors) perche' Semplice le
  genera come CSS per-pagina con classi "style_xxxxx" generate a runtime,
  non prevedibili in anticipo pagina per pagina.
- Glass + gradienti "futuristici": card e nav con sfondo semi-trasparente +
  backdrop-blur, bordo sottile, alone/gradiente viola in hover.
- Card progetti "foldable": trasformate via JS (mm-animations.js,
  initFoldableProjects) in card grandi con immagine+titolo sempre visibili,
  descrizione+bottone che si aprono/chiudono al click.
*/

/* ==========================================================================
   1. Design tokens
   ========================================================================== */
:root {
  --bg-primary: #050505;
  --bg-elevated: #0d0a12;
  --text-primary: #f0f0f0;
  --text-secondary: rgba(240, 240, 240, 0.55);
  --border-subtle: rgba(255, 255, 255, 0.08);

  /* Accento viola, campionato dal CV di Marco (rgb(139,92,246)) */
  --accent: #8b5cf6;
  --accent-light: #a78bfa;
  --accent-dim: rgba(139, 92, 246, 0.15);
  --accent-glow: rgba(139, 92, 246, 0.35);

  --glass-bg: rgba(139, 92, 246, 0.06);
  --glass-bg-hover: rgba(139, 92, 246, 0.12);
  --glass-border: rgba(255, 255, 255, 0.14);

  /* Token per valori che nella prima versione dark erano hardcoded inline
     nelle singole regole (sfondo nav, griglia di puntini, aurora, ecc.) -
     estratti in variabili in occasione del tema chiaro (2026-09-03) cosi'
     ognuno puo' essere ridefinito senza duplicare le regole che lo usano.
     I toni viola sull'accento (rgba(139,92,246,...) usati per bordi/alone in
     hover in giro per il file) restano invece hardcoded e INVARIATI tra i
     due temi - sono un accento translucido, leggibile su qualunque sfondo,
     non serve ridefinirli. */
  --dot-color: rgba(255, 255, 255, 0.07);
  --aurora-a: rgba(139, 92, 246, 0.32);
  --aurora-b: rgba(167, 139, 250, 0.24);
  --aurora-c: rgba(139, 92, 246, 0.18);
  --nav-bg: rgba(8, 6, 12, 0.7);
  --overlay-menu-bg: rgba(5, 5, 5, 0.97);
  --progress-track: rgba(255, 255, 255, 0.12);
  --glass-bg-end: rgba(255, 255, 255, 0.02);
  --glass-bg-end-hover: rgba(255, 255, 255, 0.03);
  --glass-inset-highlight: rgba(255, 255, 255, 0.08);
  --shadow-strong: rgba(0, 0, 0, 0.7);
  --shadow-soft: rgba(0, 0, 0, 0.6);
  /* nucleo del bagliore "neon" sui due <svg> del logo curtain/badge (matita
     e anello, style.css sezione 4) - bianco su sfondo scuro legge come
     nucleo luminoso; sullo stesso bianco su sfondo chiaro sparirebbe, quindi
     nel tema chiaro diventa un nucleo viola piu' saturo dell'alone stesso. */
  --icon-glow-core-strong: rgba(255, 255, 255, 0.9);
  --icon-glow-core-soft: rgba(255, 255, 255, 0.8);

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 16px;

  --transition-fast: 0.2s ease;
  --transition-base: 0.3s ease;
  --transition-slow: 0.6s cubic-bezier(0.16, 1, 0.3, 1);

  /* Solo 2 famiglie in tutto il sito (richiesta esplicita di Marco,
     2026-09-01): Inter per heading/sub-heading/intro/paragrafi (usava DM
     Sans prima, rimossa), DM Mono per link e stringhe brevi (nav, bottoni,
     etichette - gia' in uso). --font-display e --font-body puntano entrambe
     a Inter, tenute separate solo per chiarezza semantica nel resto del
     file (dove serve un peso diverso per titoli vs corpo testo). */
  --font-display: 'Inter', -apple-system, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'DM Mono', 'SF Mono', monospace;

  /* Identita' UNICA del titolo di una card, ovunque nel sito (richiesta di
     Marco, 2026-09-04: "cards title, globally, should be like the titles of
     the experiences and education cards"). I valori NON sono inventati:
     sono quelli misurati sul titolo reale delle voci Experience/Education
     della pagina About (lo <span> con la classe generata da Semplice
     "style_cfi8ovt39", es. "Senior Product Designer @Swydo") - DM Mono
     24px/32px, peso 400, tracking 0.05em, colore pieno. Quelle card
     restano la sorgente perche' il loro titolo arriva dal contenuto
     WordPress e non da questo file: non si possono "puntare" al token,
     quindi il token punta a loro. Se un giorno cambiassero li', questi
     valori vanno riallineati a mano.
     ATTENZIONE ai rem: Semplice imposta il root a 18px, non 16 - 1.3333rem
     sono 24px, non 21.3 (verificato in locale sul computed style). */
  /* Facce delle illustrazioni isometriche delle card "What I do"
     (mm-animations.js: buildTrackArt). Tre valori per dare volume - la
     faccia superiore e' la piu' chiara, quella sinistra la piu' in ombra -
     piu' una variante "accent" per l'elemento in evidenza di ogni scena. */
  --iso-top: rgba(167, 139, 250, 0.16);
  --iso-right: rgba(139, 92, 246, 0.1);
  --iso-left: rgba(139, 92, 246, 0.04);
  --iso-stroke: rgba(167, 139, 250, 0.5);
  --iso-accent-top: rgba(167, 139, 250, 0.42);
  --iso-accent-right: rgba(139, 92, 246, 0.28);
  --iso-accent-left: rgba(139, 92, 246, 0.16);
  --iso-accent-stroke: rgba(167, 139, 250, 0.85);

  --card-title-font: var(--font-mono);
  --card-title-size: 1.3333rem;
  --card-title-weight: 400;
  --card-title-tracking: 0.05em;
  --card-title-line: 1.3333;
}

/* ==========================================================================
   1b. Tema chiaro - stesso linguaggio visivo (glass, aurora, gradiente/
   outline sul nome hero) ricalibrato per uno sfondo chiaro, non
   un'inversione 1:1: opacita' e nucleo del bagliore sono stati risistemati a
   mano (vedi commenti sopra), altrimenti bordi/alone sparivano o l'accento
   perdeva leggibilita' sul bianco. Attivato aggiungendo data-theme="light"
   su <html> (mm-animations.js, initThemeToggle + script sincrono in
   functions.php per applicarlo prima del primo paint). */
:root[data-theme="light"] {
  --bg-primary: #faf9fc;
  --bg-elevated: #f1edf9;
  --text-primary: #17131f;
  --text-secondary: rgba(23, 19, 31, 0.6);
  --border-subtle: rgba(23, 19, 31, 0.1);

  --accent: #7c3aed;
  --accent-light: #6d28d9;
  --accent-dim: rgba(124, 58, 237, 0.12);
  --accent-glow: rgba(124, 58, 237, 0.3);

  --glass-bg: rgba(124, 58, 237, 0.05);
  --glass-bg-hover: rgba(124, 58, 237, 0.1);
  --glass-border: rgba(23, 19, 31, 0.1);

  --dot-color: rgba(23, 19, 31, 0.06);
  --aurora-a: rgba(139, 92, 246, 0.16);
  --aurora-b: rgba(167, 139, 250, 0.14);
  --aurora-c: rgba(139, 92, 246, 0.1);
  --nav-bg: rgba(255, 255, 255, 0.72);
  --overlay-menu-bg: rgba(255, 255, 255, 0.97);
  --progress-track: rgba(23, 19, 31, 0.1);
  --glass-bg-end: rgba(255, 255, 255, 0.5);
  --glass-bg-end-hover: rgba(255, 255, 255, 0.65);
  --glass-inset-highlight: rgba(255, 255, 255, 0.7);
  --shadow-strong: rgba(23, 19, 31, 0.18);
  --shadow-soft: rgba(23, 19, 31, 0.14);
  --icon-glow-core-strong: rgba(124, 58, 237, 0.55);
  --icon-glow-core-soft: rgba(124, 58, 237, 0.4);

  /* Facce isometriche ritarate per lo sfondo chiaro: alle opacita' del tema
     scuro il viola scuro dell'accento chiaro (#7c3aed) avrebbe reso i
     volumi molto piu' pesanti di quanto siano li'. */
  --iso-top: rgba(124, 58, 237, 0.14);
  --iso-right: rgba(124, 58, 237, 0.09);
  --iso-left: rgba(124, 58, 237, 0.04);
  --iso-stroke: rgba(109, 40, 217, 0.45);
  --iso-accent-top: rgba(124, 58, 237, 0.32);
  --iso-accent-right: rgba(124, 58, 237, 0.2);
  --iso-accent-left: rgba(124, 58, 237, 0.11);
  --iso-accent-stroke: rgba(109, 40, 217, 0.8);
}

/* ==========================================================================
   2. Base / reset - forza lo sfondo del tema attivo ovunque, incluso sopra
      il CSS per-pagina generato da Semplice (vedi nota in testa al file)
   ========================================================================== */
html,
body {
  background-color: var(--bg-primary) !important;
  color: var(--text-primary) !important;
  font-family: var(--font-body) !important;
}

/* Transizione morbida al cambio tema (mm-animations.js, initThemeToggle) sui
   pochi elementi che non hanno gia' una propria transition dichiarata per
   background/border/colore (le card vetro, i bottoni ecc. piu' sotto in
   questo file la dichiarano gia' per conto proprio, sulle stesse proprieta'
   che cambiano tra i due temi - non serve ripeterla qui). */
html,
.semplice-navbar,
#overlay-menu {
  transition: background-color var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}

#content-holder,
.content-block,
.container,
.container-fluid,
.row,
.column,
.content-wrapper,
.column-content,
[id^="section_"],
[id^="content_"],
[id^="column_"] {
  background-color: transparent !important;
}

/* Sfondo: griglia di puntini + tre aloni sfocati viola (aurora).
   IMPORTANTE (bug trovato in locale, 2026-09-01): NON va messo come
   background-image su "body" - Semplice posiziona #content-holder in
   position:absolute, quindi il box di "body" stesso collassa a ALTEZZA
   ZERO (confermato: document.body.offsetHeight === 0). Il background-COLOR
   su body resta visibile lo stesso grazie alla propagazione speciale del
   background della root al canvas (regola CSS apposita), ma quella
   propagazione per il background-IMAGE con background-attachment:fixed si
   e' rivelata inaffidabile in questo layout - il pattern non si vedeva da
   nessuna parte (segnalato da Marco). Stessa soluzione gia' usata per la
   grana filmica qui sotto: uno pseudo-elemento con position:fixed + inset:0
   ha SEMPRE un box reale grande quanto il viewport, indipendente
   dall'altezza (rotta) di body. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(var(--dot-color) 1px, transparent 1px),
    radial-gradient(ellipse 1100px 700px at 12% -15%, var(--aurora-a), transparent 60%),
    radial-gradient(ellipse 900px 650px at 105% 20%, var(--aurora-b), transparent 60%),
    radial-gradient(ellipse 800px 600px at 50% 115%, var(--aurora-c), transparent 65%);
  background-size: 24px 24px, auto, auto, auto;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat;
}

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

/* Grana filmica sottile, sempre presente - dettaglio "cinematico" ripreso da
   andrewreff.com dopo lo studio in intro-prototype.html (li' e' un
   <canvas class="grain-canvas">; qui riprodotto in puro CSS/SVG per restare
   leggero e senza bisogno di JS aggiuntivo). */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9000;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* IMPORTANTE: .transition-wrap in modalita' "dynamic" NON e' solo l'overlay
   decorativo di caricamento - e' anche il contenitore che avvolge il
   contenuto reale della pagina (usato per lo swap AJAX tra pagine). NON va
   nascosto con display:none (nasconderebbe tutto il contenuto) - va solo
   neutralizzato lo sfondo bianco residuo del tema chiaro originale. */
.transition-wrap {
  background-color: transparent !important;
}

/* ==========================================================================
   Transizione pagina->pagina — View Transitions API nativa del browser
   ==========================================================================
   RISCRITTA DA ZERO il 2026-09-05 su richiesta di Marco ("delete all
   animation for page transition [...] then reinstall the page transition
   based on the streetbeat page transition"), dopo due tentativi falliti di
   riprodurla a mano con classi + transition/animation CSS pilotate da JS.

   I due tentativi precedenti simulavano a mano quello che il sito di
   riferimento (streetbeat.com, ispezionato il 2026-09-03) ottiene con la
   VIEW TRANSITIONS API NATIVA: era stato escluso di usarla perche' Semplice
   sostituisce il contenuto con un proprio fetch AJAX interno e sembrava
   impossibile agganciarla al suo ciclo di vita. Si e' rivelato falso:
   Semplice dispatcha su window l'evento "sempliceAppendContent" quando il
   contenuto nuovo e' entrato nel DOM (verificato dal vivo sul sito live,
   2026-09-05: parte ~1.2s dopo il click, cioe' a fine attesa di rete), e
   document.startViewTransition() accetta una callback che ritorna una
   Promise - quindi si puo' aprire la transizione al click e chiuderla su
   quell'evento. Vedi mm-animations.js, initPageTransitions().

   Perche' la versione nativa risolve STRUTTURALMENTE i due difetti che le
   versioni a mano continuavano a produrre (entrambi visti nel video di
   Marco, Screen Recording 2026-09-04 alle 23.52.57, analizzato frame per
   frame):
   1. NESSUNO SCHERMO NERO durante l'attesa di rete: e' il BROWSER a
      congelare e tenere in vita lo snapshot della pagina vecchia finche'
      la Promise non si risolve. Non esiste piu' un istante in cui il DOM
      vecchio e' gia' andato e il nuovo non e' ancora arrivato - era la
      causa degli ~0.8s di nero (click a 2.7s, nero da 3.0s a 3.8s).
   2. NESSUN LAMPO DELLA PAGINA "vecchia"/non stilizzata: lo snapshot NUOVO
      viene catturato dal browser solo DOPO che la callback ha finito -
      e dentro la callback chiamiamo runInit() (logo SVG, classi hero,
      marcatori di sezione) prima di risolvere. Il browser non puo'
      fotografare uno stato intermedio.
   Inoltre non c'e' piu' NIENTE da ripulire a mano: nessuna classe da
   togliere, nessun requestAnimationFrame, nessun timer di sicurezza,
   nessun MutationObserver che orchestra l'animazione. Il ciclo di vita
   dell'animazione e' interamente del browser - non esiste piu' lo stato
   "bloccata a meta'" che aveva rotto le due versioni precedenti.

   Le curve/durate qui sotto sono quelle campionate dal CSS reale di
   streetbeat il 2026-09-03 (::view-transition-old/new(root) + keyframes),
   adattate al nostro fondo scuro:
   - out: opacita' 0 + blur 20px + scale .985, origine 50% 42%
   - in:  la "card" sale da 100vh con angoli alti arrotondati e ombra, e si
          distende a schermo pieno (clip-path che si apre all'80%)
   - easing cubic-bezier(.22,1,.36,1), 1s, con .22s di ritardo sull'entrata
   NOTA: il ritardo sull'entrata e' quello di streetbeat (--pt-in-delay) -
   e' cio' che fa leggere le due meta' come due tempi invece di uno scatto.

   SUPPORTO BROWSER: Chrome/Edge/Safari 18+ hanno la API; Firefox no. Dove
   manca, initPageTransitions() non apre alcuna transizione e la
   navigazione resta istantanea (nessuna animazione, ma nemmeno nessun
   artefatto) - un fallback volutamente "niente" invece di un secondo
   sistema a mano da mantenere, che e' esattamente quello che ha creato i
   problemi finora.
   ========================================================================== */
::view-transition {
  /* il fondo dietro gli snapshot: senza, alcuni browser mostrano bianco */
  background: var(--bg-primary);
}

::view-transition-old(root) {
  animation: mm-vt-out 1s cubic-bezier(0.22, 1, 0.36, 1) both;
  transform-origin: 50% 42%;
}

::view-transition-new(root) {
  animation: mm-vt-in 1s cubic-bezier(0.22, 1, 0.36, 1) 0.22s both;
  transform-origin: 50% 100%;
}

@keyframes mm-vt-out {
  to {
    opacity: 0;
    filter: blur(20px);
    transform: scale(0.985);
  }
}

@keyframes mm-vt-in {
  from {
    transform: translateY(100vh) scale(0.92);
    clip-path: inset(0 round 20px 20px 0 0);
    box-shadow: 0 -30px 90px rgba(0, 0, 0, 0.45);
  }
  80% {
    clip-path: inset(0 round 20px 20px 0 0);
  }
  to {
    transform: none;
    clip-path: inset(0);
    box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

/* #nprogress - barra di caricamento grigia + spinner blu che Semplice
   mostra ad ogni navigazione AJAX (libreria NProgress.js nel bundle del
   tema padre). Resta rimossa: e' un indicatore spoglio, fuori dalla
   palette del sito, e con la transizione nativa che congela la pagina
   vecchia durante l'attesa non serve alcun indicatore separato. */
#nprogress {
  display: none !important;
}

/* ==========================================================================
   2b. Container a 1440px in tutto il sito (contenuto, header, pagine
   dettaglio progetto) - richiesta esplicita di Marco. Ogni sezione Semplice
   ha l'attributo "data-layout=fluid" (scelta fatta nel builder per il
   design chiaro originale, full-bleed) che porta ".container" del
   contenuto a max-width:100% - a schermi larghi il contenuto si allargava
   bordo a bordo mentre l'header restava fermo alla larghezza di default di
   Semplice (1230px, ".container" senza data-layout=fluid), disallineati fra
   loro. !important per battere entrambe le regole di Semplice (quella base
   ".container{max-width:1230px}" e quella "[data-layout=fluid]
   .container{max-width:100%}").
   ========================================================================== */
.content-block > .container,
.semplice-navbar .container {
  max-width: 1440px !important;
  margin-left: auto !important;
  margin-right: auto !important;
  float: none !important;
}

/* Eccezione al cap qui sopra per il footer (richiesta esplicita di Marco,
   2026-09-04, confrontando header e footer sul sito LIVE): la navbar li'
   usa ".container-fluid" (width:100% senza alcun cap, non toccato dalla
   regola sopra che punta solo a ".container") mentre il .container del
   footer nativo veniva comunque forzato a 1440px dalla regola generale -
   le due sezioni non combaciavano piu' in larghezza. Rimosso il cap SOLO
   qui: il footer torna fluido come la navbar (width:100% ereditato da
   Semplice, padding di base invariato), senza toccare il cap sugli altri
   .content-block del sito (hero, progetti, pagine dettaglio) non
   coinvolti in questa richiesta. */
.content-block.mm-section-get-in-touch > .container {
  max-width: none !important;
}

/* ==========================================================================
   2c. Intro curtain overlay (mm-animations.js: initIntroCurtain)
   Sostituisce il vecchio fade-cascade dell'hero: schermo nero pieno con il
   marchio SVG animato al centro + un contatore di caricamento in basso, poi
   un "wipe" a due pannelli rivela l'hero gia' nella sua posizione finale.

   Il nodo #mm-intro-curtain NON viene creato da questo JS: e' iniettato
   lato PHP (functions.php, hook su template_redirect) subito dopo <body>,
   cosi' e' gia' opaco al primissimo paint - nessuna finestra in cui l'hero
   potrebbe lampeggiare visibile prima che il JS (caricato in footer) parta.
   Stato iniziale (logo nascosto, barra a 0%) definito qui in CSS per lo
   stesso motivo, stessa filosofia della sezione 4b qui sotto.

   z-index 999999: sopra la grana filmica (body::after, 9000) e sopra il
   piu' alto z-index nativo di Semplice trovato (.transition-reveal-img,
   100001) - il curtain resta pero' completamente indipendente dalle classi
   .transition-wrap/.transition-reveal di Semplice (vedi nota sopra
   .transition-wrap piu' sotto in questo file: il suo comportamento nativo
   si e' rivelato inaffidabile in locale), non ci si aggancia in alcun modo.
   ========================================================================== */
#mm-intro-curtain {
  position: fixed;
  inset: 0;
  z-index: 999999;
  pointer-events: auto;
}

#mm-intro-curtain.mm-fade-out {
  opacity: 0;
  transition: opacity 200ms ease;
}

.mm-intro-panel-top,
.mm-intro-panel-bottom {
  position: absolute;
  left: 0;
  right: 0;
  height: 50%;
  background: var(--bg-primary);
  transition: transform 650ms cubic-bezier(0.76, 0, 0.24, 1);
}

.mm-intro-panel-top { top: 0; }
.mm-intro-panel-bottom { bottom: 0; }

#mm-intro-curtain.mm-wipe .mm-intro-panel-top { transform: translateY(-100%); }
#mm-intro-curtain.mm-wipe .mm-intro-panel-bottom { transform: translateY(100%); }

.mm-intro-seam {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--accent);
  opacity: 0;
  transform: scaleY(1);
  box-shadow: 0 0 0 var(--accent-glow);
  transition: opacity 200ms ease, box-shadow 400ms ease;
}

#mm-intro-curtain.mm-wipe .mm-intro-seam {
  opacity: 1;
  box-shadow: 0 0 24px 2px var(--accent-glow);
}

.mm-intro-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
  /* Durata avvicinata a quella dei pannelli (650ms, sotto in questo file):
     prima era 150ms - il contenuto centrale spariva quasi di scatto mentre i
     pannelli erano ancora a inizio corsa, un disallineamento di ritmo che
     contribuiva alla sensazione di "non fluido" segnalata da Marco
     (2026-09-02) sulla parte finale dell'animazione. */
  transition: opacity 500ms ease;
}

#mm-intro-curtain.mm-wipe .mm-intro-center {
  opacity: 0;
}

/* Alone morbido dietro anello+matita (richiesta di Marco: "il flair dietro
   al logo deve essere piu' grande e con un viola meno intenso") - un
   elemento SEPARATO dal canvas WebGL e dal suo mask radiale (sezione qui
   sopra), cosi' posso ingrandirlo/attenuarlo liberamente senza toccare lo
   sfondo interno necessario alla trasmissione del vetro. Stesso pattern a
   puntini dello sfondo del sito (body::before piu' in alto in questo file:
   radial-gradient di puntini bianchi 1px, passo 24px) cosi' l'alone si
   sente parte dello stesso linguaggio visivo del resto della pagina,
   invece di un semplice bagliore generico. position:absolute (non flex)
   per stare centrato indipendentemente dal layout del genitore, dietro il
   logo via z-index/ordine nel markup (functions.php la inserisce PRIMA di
   .mm-intro-logo). */
.mm-intro-flair {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200%;
  height: 200%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  border-radius: 50%;
  background-image:
    radial-gradient(var(--dot-color) 1px, transparent 1px),
    radial-gradient(circle, rgba(139, 92, 246, 0.16), transparent 68%);
  background-size: 22px 22px, 100% 100%;
  background-position: center, center;
}

/* Palco 3D per l'anello che orbita attorno alla matita (richiesta di
   Marco). "perspective" va sull'ANTENATO dell'elemento animato, non
   sull'elemento stesso - vive quindi qui sul wrapper.

   IMPORTANTE (scoperto durante l'implementazione): un transform 3D su un
   <path> DENTRO un <svg> non produce un vero scorcio prospettico in questo
   motore (verificato: il matrix3d calcolato era corretto ma il disegno
   restava visivamente piatto anche a rotateY(88deg) - un <div> HTML
   normale con lo stesso transform invece funzionava perfettamente). Anello
   e matita vivono quindi in due <svg> SEPARATI e sovrapposti (non due
   <path> nello stesso <svg>, vedi functions.php) - il transform 3D va
   sull'intero elemento <svg> dell'anello, trattato come un box qualsiasi
   (come farebbe un <img>), non su geometria interna a un <svg> - cosi'
   ottiene uno scorcio prospettico vero e "solido" a ogni angolo. */
/* Dimensione del box (non la mesh/camera in mm-intro-glass.js): +40% su
   richiesta di Marco dopo aver visto il render dal vivo, poi un ulteriore
   +50% su richiesta successiva (157/21vw/235 -> 236/31.5vw/353). Scalata
   qui, non toccando MESH_SCALE/camera in mm-intro-glass.js - la mesh
   riempie sempre la stessa FRAZIONE del frame a prescindere dalla
   dimensione in pixel del canvas (l'inquadratura dipende da FOV/distanza/
   scala mesh, non dalla risoluzione), quindi ingrandire il box CSS
   ingrandisce il render intero in output senza rischiare di reintrodurre
   il taglio ai bordi gia' risolto in precedenza. */
.mm-intro-logo {
  width: clamp(236px, 31.5vw, 353px);
  height: clamp(236px, 31.5vw, 353px);
  position: relative;
  opacity: 0;
  transform: scale(0.82);
  transition: opacity 500ms cubic-bezier(0.16, 1, 0.3, 1), transform 500ms cubic-bezier(0.16, 1, 0.3, 1);
  perspective: 480px;
}

.mm-intro-logo.mm-in {
  opacity: 1;
  transform: scale(1);
}

.mm-intro-pencil-svg,
.mm-intro-ring-svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  /* "visible", non il default "hidden" dello spec SVG: altrimenti il
     drop-shadow del bagliore neon (che sborda oltre il viewBox) e lo
     scorcio prospettico dell'anello mentre ruota verrebbero tagliati al
     bordo del viewBox. */
  overflow: visible;
}

/* Matita: ferma al centro, fill in gradiente viola->bianco (definito in
   functions.php, mm_dark_child_intro_curtain_markup) + bagliore neon a due
   strati (nucleo bianco stretto + alone viola piu' ampio - tecnica classica
   delle insegne al neon: il nucleo chiaro e' cio' che legge come "bianco",
   l'alone colorato e' cio' che legge come "viola", insieme danno
   l'impressione di un unico materiale che li mescola). */
.mm-intro-pencil-svg {
  filter:
    drop-shadow(0 0 2px var(--icon-glow-core-strong))
    drop-shadow(0 0 10px var(--accent-glow))
    drop-shadow(0 0 22px var(--accent-glow));
  /* qui sulla regola BASE, non solo dentro ".mm-glass-ready": un transition
     dichiarato SOLO in uno stato specifico smette di valere nello stesso
     istante in cui quello stato viene lasciato - dichiararla qui la rende
     valida a prescindere da quale classe e' presente. */
  transition: opacity 300ms ease;
}

/* Anello: fill quasi bianco (effetto "vetro") con lo stesso trattamento a
   bagliore, piu' tenue perche' e' l'elemento di contorno, non quello
   focale. Nessun transform-box/transform-origin da impostare qui - a
   differenza di un elemento geometria SVG, un <svg> intero e' un box CSS
   normale e ha gia' origine al proprio centro (50% 50%) di default. */
.mm-intro-ring-svg {
  filter:
    drop-shadow(0 0 1.5px var(--icon-glow-core-soft))
    drop-shadow(0 0 8px var(--accent-glow));
  /* vedi commento su .mm-intro-pencil-svg qui sopra: stessa ragione. */
  transition: opacity 300ms ease;
}

@media (prefers-reduced-motion: no-preference) {
  .mm-intro-ring-svg {
    animation: mm-ring-orbit 4.5s linear infinite;
  }
}

/* Render 3D vetro (Three.js, mm-intro-glass.js) - vive sopra i due <svg>
   piatti. Parte invisibile: i <svg> sono il fallback mostrato di default,
   il canvas si dissolve sopra di loro SOLO dopo che il modulo ha
   effettivamente renderizzato un frame (classe "mm-glass-ready" su
   .mm-intro-logo, aggiunta da mm-intro-glass.js) - se Three.js/WebGL non
   caricano per qualsiasi motivo, il canvas resta a opacita' 0 per sempre e
   l'utente vede comunque il logo SVG con bagliore, mai un buco vuoto. */
.mm-intro-glass-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 400ms ease;
  /* mm-intro-glass.js imposta scene.background su un colore (non puro nero)
     perche' la trasmissione del vetro ha bisogno di QUALCOSA da rifrangere/
     mostrare per non leggere come uniformemente opaca (vedi commento li') -
     quel colore riempie pero' l'intero canvas rettangolare, non solo la
     forma del logo, e sarebbe visibile come un riquadro sul nero del
     curtain attorno. Mascherato qui con una sfumatura radiale (stesso
     effetto in entrambi i prefissi per compatibilita' Safari) che dissolve
     i bordi del canvas fino a trasparente, cosi' resta solo un alone
     morbido invece di uno spigolo netto.

     AGGIORNAMENTO (richiesta di Marco, 2026-09-02/03: "il viola dietro il
     logo dovrebbe avere un canale alpha e non essere troppo acceso"): prima
     la zona 0-55% restava a piena opacita' (un disco viola pieno, con solo
     il bordo 55-78% sfumato) - leggeva come un cerchio pieno con un bordo
     morbido, non come un alone davvero sfumato. Ora la zona a piena
     opacita' e' molto piu' piccola (0-18%) e la sfumatura verso trasparente
     comincia molto prima e dura piu' a lungo (fino al 76%, con una tappa
     intermedia al 45%), cosi' la MAGGIOR PARTE dell'area visibile e' gia'
     parzialmente trasparente invece che un blocco di colore pieno. */
  -webkit-mask-image: radial-gradient(circle, black 18%, rgba(0, 0, 0, 0.55) 45%, transparent 76%);
  mask-image: radial-gradient(circle, black 18%, rgba(0, 0, 0, 0.55) 45%, transparent 76%);
}

.mm-intro-logo.mm-glass-ready .mm-intro-glass-canvas {
  opacity: 1;
}

.mm-intro-logo.mm-glass-ready .mm-intro-pencil-svg,
.mm-intro-logo.mm-glass-ready .mm-intro-ring-svg {
  opacity: 0;
}

@keyframes mm-ring-orbit {
  from { transform: rotateX(20deg) rotateY(0deg); }
  to   { transform: rotateX(20deg) rotateY(360deg); }
}

.mm-intro-progress {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
}

.mm-intro-counter {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
}

.mm-intro-bar {
  width: clamp(160px, 30vw, 200px);
  height: 2px;
  border-radius: 999px;
  background: var(--progress-track);
  overflow: hidden;
}

.mm-intro-bar-fill {
  width: 0%;
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
}

/* prefers-reduced-motion: nessun disegno del logo, nessun contatore - il
   curtain resta semplicemente nel suo stato iniziale (logo/barra invisibili)
   e si dissolve tutto insieme via .mm-fade-out (regola sopra), stessa
   filosofia "fade semplice sempre sicuro" della sezione 4b qui sotto. */

html.mm-intro-lock {
  overflow: hidden !important;
  height: 100%;
}

/* ==========================================================================
   3. Navbar (.semplice-navbar / nav.standard) - vetro
   ========================================================================== */
.semplice-navbar {
  background-color: var(--nav-bg) !important;
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid var(--glass-border);
}

.semplice-navbar .navbar-inner {
  position: relative;
}

.semplice-navbar .logo img {
  filter: invert(1) brightness(1.2);
}

/* Orologio dal vivo (citta' + ora locale, aggiornato al secondo da
   mm-animations.js) - dettaglio ripreso da andrewreff.com. Inserito via JS
   tra logo e menu, quindi serve solo lo stile qui. */
.mm-clock {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  white-space: nowrap;
}

@media (max-width: 767px) {
  .mm-clock {
    display: none;
  }
}

/* Switch tema chiaro/scuro - stessa identita' "vetro" di card/bottoni/back-
   to-top (bordo sottile + sfondo semi-trasparente + blur) invece di un
   controllo di sistema generico, cosi' resta coerente col resto del sito.
   Posizione (left, non right: piu' robusto - vedi commento su
   positionThemeToggle() in mm-animations.js) impostata via JS, non qui: la
   navbar di Semplice posiziona menu desktop/hamburger mobile con
   position:absolute e classi ".navbar-right" indipendenti (nessun flexbox
   comune da cui dedurre lo spazio libero), quindi lo spazio reale a
   disposizione va MISURATO dal DOM effettivo (stesso approccio gia' in uso
   per il badge in vetro della pagina About, positionAboutBadge) invece che
   assunto con un valore fisso in CSS, che si romperebbe se Marco
   aggiungesse/togliesse una voce di menu. */
.mm-theme-toggle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  width: 2.85rem;
  height: 1.55rem;
  padding: 0.2rem;
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.mm-theme-toggle:hover {
  border-color: var(--accent);
}

.mm-theme-toggle:focus-visible {
  outline: 2px solid var(--accent-light);
  outline-offset: 2px;
}

.mm-theme-toggle-thumb {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-light), var(--accent));
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateX(0);
  transition: transform var(--transition-base);
}

[data-theme="light"] .mm-theme-toggle-thumb {
  transform: translateX(1.3rem);
}

.mm-theme-toggle-thumb svg {
  width: 0.68rem;
  height: 0.68rem;
  color: #fff;
  display: block;
}

/* Switch lingua EN/IT/ES (Polylang) - stessa identita' "vetro" del toggle
   tema qui sopra (bordo sottile + sfondo semi-trasparente + blur), ma come
   gruppo segmentato di 3 invece che un interruttore a 2 stati. Posizione
   impostata via JS (positionLangSwitch() in mm-animations.js), stesso
   motivo del toggle tema: nessun flexbox comune nella navbar di Semplice da
   cui dedurre lo spazio libero. */
.mm-lang-switch {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  padding: 0.2rem;
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.mm-lang-switch-item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.7rem;
  padding: 0.15rem 0.4rem;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--text-secondary);
  text-decoration: none;
  transition: color var(--transition-fast), background var(--transition-fast);
}

.mm-lang-switch-item:hover {
  color: var(--text-primary);
}

.mm-lang-switch-item.is-active {
  color: #fff;
  background: linear-gradient(135deg, var(--accent-light), var(--accent));
}

.semplice-navbar .logo a {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono) !important;
  color: var(--text-primary) !important;
}

/* Il logo (marchio SVG fornito da Marco) viene iniettato via JS
   (mm-animations.js, initLogo) al posto di qualsiasi contenuto trovi li' -
   testo del titolo del sito in locale (l'opzione Semplice del logo non e'
   inclusa nell'export contenuti WordPress) o l'eventuale <img> reale sul
   sito live. Cosi' il marchio e' identico e garantito in entrambi gli
   ambienti, invece di un fallback CSS solo-locale. */
.semplice-navbar .logo a svg {
  display: block;
  width: 32px;
  height: 32px;
}

/* Il marchio iniettato da initLogo() (qui sopra) ha fill/stroke "white"
   FISSI nel proprio markup (MM_LOGO_SVG, mm-animations.js) - corretto sulla
   navbar scura di sempre, ma illeggibile (bianco su chiaro) col tema chiaro
   aggiunto il 2026-09-03. invert(1) sull'intero <svg> lo rende scuro senza
   toccare il file JS che lo genera - stessa tecnica gia' in uso per i loghi
   "_black.svg" nella pagina Logos (sezione 10 piu' sotto in questo file). */
:root[data-theme="light"] .semplice-navbar .logo a svg {
  filter: invert(1);
}

.semplice-navbar nav.standard .menu-item a {
  position: relative;
  font-family: var(--font-mono) !important;
  color: var(--text-secondary) !important;
  letter-spacing: 0.08em;
  transition: color var(--transition-fast);
}

/* IMPORTANTE (scoperto in locale, 2026-09-01): il tema padre Semplice ha una
   sua regola in frontend.min.css che colora di NERO lo <span> interno delle
   voci di menu attive/hover (".semplice-navbar [data-nav=...] nav ul
   li.current-menu-item a span { color: rgb(0,0,0); }") - pensata per un
   design chiaro dove l'item attivo aveva uno sfondo chiaro dietro. Sul nostro
   sfondo scuro diventa testo nero su nero, invisibile. Il colore va quindi
   forzato anche sullo <span>, non solo sul link <a> (il testo vive nello
   span, non viene ereditato perche' la regola di Semplice lo sovrascrive
   direttamente su quell'elemento). */
.semplice-navbar nav.standard .menu-item a:hover,
.semplice-navbar nav.standard .menu-item.current-menu-item a,
.semplice-navbar nav.standard .menu-item.current_page_item a,
.semplice-navbar nav.standard .menu-item a:hover span,
.semplice-navbar nav.standard .menu-item.current-menu-item a span,
.semplice-navbar nav.standard .menu-item.current_page_item a span {
  color: var(--accent-light) !important;
}

/* piccolo indicatore sotto la voce di menu attiva, per renderla inequivocabile.
   Sullo <span> del testo, non su <a>: il tema padre usa il padding-right
   dell'<a> (30px) come spaziatura tra le voci di menu invece di un gap sul
   contenitore - un ::after con left:0/right:0 su <a> copriva anche quei
   30px di padding, sporgendo ben oltre "PROJECTS" (segnalato da Marco,
   2026-09-02). Lo <span> invece avvolge stretto solo il testo. */
.semplice-navbar nav.standard .menu-item.current-menu-item a span,
.semplice-navbar nav.standard .menu-item.current_page_item a span {
  position: relative;
}

.semplice-navbar nav.standard .menu-item.current-menu-item a span::after,
.semplice-navbar nav.standard .menu-item.current_page_item a span::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
}

/* ==========================================================================
   3b. Menu mobile (hamburger + overlay a tutto schermo)
   Scoperto in locale (2026-09-03, sanity check mobile): il tema padre
   Semplice disegna le 3 barre dell'hamburger (".menu-icon span" +
   "::before"/"::after") con "background-color:#000" - stessa causa radice
   del bug gia' risolto sullo <span> del menu attivo (3. Navbar qui sopra),
   pensata per un design chiaro. Sul nostro sfondo scuro l'icona era quasi
   invisibile (nero su navbar quasi nera). Stessa regola copre anche la "X"
   di chiusura: e' lo STESSO <span>, Semplice lo trasforma via
   transform:rotate() quando l'<a> passa da classe "open-menu" a
   "close-menu", non e' un elemento diverso. */
.menu-icon span,
.menu-icon span::before,
.menu-icon span::after {
  background-color: var(--text-primary) !important;
}

/* L'overlay a tutto schermo (#overlay-menu, iniettato da Semplice) aveva
   "background:#fff" fisso nel tema padre - mai coperto dal nostro restyling
   dark, quindi si apriva come un pannello bianco/grigio chiaro con le voci
   di menu in nero, completamente fuori stile rispetto al resto del sito (e
   con "PROJECTS"/"ABOUT" praticamente illeggibili sovrapposte al contenuto
   sottostante durante la transizione di opacita'). Stessa identita' vetro
   della navbar (3. Navbar qui sopra) invece di un pannello bianco. */
#overlay-menu {
  background-color: var(--overlay-menu-bg) !important;
  backdrop-filter: blur(20px) saturate(140%);
  -webkit-backdrop-filter: blur(20px) saturate(140%);
}

#overlay-menu .overlay-menu-inner nav ul li a span {
  color: var(--text-secondary) !important;
  font-family: var(--font-mono) !important;
  letter-spacing: 0.08em;
  transition: color var(--transition-fast);
}

/* stessa causa radice del fix sullo <span> del menu desktop: il tema padre
   colora di NERO il testo della voce hover/attiva (pensato per uno sfondo
   chiaro dietro l'item), invisibile sul nostro overlay scuro. */
#overlay-menu .overlay-menu-inner nav ul li a:hover span,
#overlay-menu .overlay-menu-inner nav ul li.current-menu-item a span,
#overlay-menu .overlay-menu-inner nav ul li.current_page_item a span {
  color: var(--accent-light) !important;
}

/* stesso indicatore a gradiente sotto la voce attiva usato nella navbar
   desktop (qui sopra), per coerenza visiva tra le due versioni del menu. */
#overlay-menu .overlay-menu-inner nav ul li.current-menu-item a span,
#overlay-menu .overlay-menu-inner nav ul li.current_page_item a span {
  position: relative;
}

#overlay-menu .overlay-menu-inner nav ul li.current-menu-item a span::after,
#overlay-menu .overlay-menu-inner nav ul li.current_page_item a span::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
}

/* ==========================================================================
   4. Hero - trattamento "filled + outline" ripreso da andrewreff.com dopo lo
   studio in intro-prototype.html (li' e' uno stile statico permanente, non
   un'animazione di riempimento, riprodotto identico qui). In origine viveva
   solo nel primo .content-block della home, come DUE <p> separati ("MARCO" e
   "MADONNA" - verificato nel DOM reale il 2026-09-01).

   AGGIORNAMENTO (richiesta esplicita di Marco, 2026-09-02): la stessa
   coreografia (eyebrow + titolo grande + heading + descrizione) e' ora
   applicata anche su About, Logos e ogni pagina progetto (vedi
   initAboutHero/initLogosHero/initProjectHero in mm-animations.js), cosi'
   l'identita' visiva e' coerente su tutto il sito, non solo in home. Titoli
   su due parole/righe come "MARCO"/"MADONNA" o "ABOUT"/"MARCO" restano sullo
   split riempito+contornato (.mm-hero-name); titoli su una parola sola
   ("LOGOFOLIO", nome progetto) non hanno un secondo "nome" da contrapporre e
   usano invece un pieno riempimento a gradiente (.mm-hero-name-solid, sezione
   4a piu' sotto). */
/* IMPORTANTE (bug trovato in locale, 2026-09-01, x2):
   1. Tutte le regole di questa sezione richiedono le classi marcatrici
      .mm-hero-name / .mm-hero-name-solid / .mm-hero-role / .mm-hero-bio,
      aggiunte via JS (mm-animations.js) solo sulle pagine pertinenti
      (controllo su location.pathname, body.home si e' rivelato inaffidabile
      dopo la navigazione AJAX) - non :nth-of-type. La pagina "About" ha
      anch'essa un primo .content-block con due <p> come titolo
      ("ABOUT"/"MARCO"), quindi in origine veniva scambiata per l'hero home e
      riceveva lo stesso trattamento fuori contesto (ora invece lo riceve
      apposta, tramite la propria funzione dedicata).
   2. :nth-of-type NON e' piu' usato per individuare questi moduli nemmeno
      sulla home: conta i fratelli per TAG (div), quindi quando
      .mm-eyebrow/.mm-tagline (anch'essi <div>) vengono inseriti come
      fratelli, il conteggio si sfasa e "il primo div" smette di essere il
      modulo del nome - il nome perdeva lo stile gradiente/contorno. Le
      classi marcatrici sono stabili indipendentemente da cosa viene
      inserito accanto. */
/* Padding-top identico sulla sezione hero delle 3 pagine con questa
   coreografia (Home, About, Logos) - richiesta esplicita di Marco,
   2026-09-02: ognuna arrivava con un padding-top DIVERSO ereditato dal
   proprio valore originale nel builder Semplice (Home 120px, About/Logos
   80px, verificato in locale), non toccato finora perche' su ID di sezione
   generati a runtime, non su una classe. :has() individua la sezione hero
   su tutte e 3 le pagine tramite le classi marcatrici gia' iniettate da
   initHeroCopy()/initAboutHero()/initLogosHero() (.mm-hero-name sulle
   prime due, .mm-hero-name-solid su Logos), senza bisogno di un selettore
   per pagina. 80px scelto come valore comune perche' gia' condiviso da 2
   pagine su 3. */
.content-block:has(.mm-hero-name, .mm-hero-name-solid) {
  padding-top: 80px !important;
}

.mm-hero-name .is-content {
  color: var(--text-primary) !important;
  font-family: var(--font-display) !important;
}

/* Il contenuto originale di Marco specificava dimensione/spaziatura per un
   design chiaro piu' contenuto (inline style su <p>/<span>: font-size 3rem,
   letter-spacing 0.444rem). Per il "grande nome impattante" in stile
   andrewreff.com serve sovrascriverle esplicitamente - senza, il testo
   restava al peso/dimensione di default (font-weight 400, ~54px) invece del
   trattamento bold/grande del prototipo (segnalato da Marco confrontando
   intro-prototype.html con il sito reale). */
.mm-hero-name .is-content p {
  /* Pesi/dimensioni allineati esattamente a intro-prototype.html su
     richiesta di Marco (screenshot di confronto, 2026-09-01): li' era
     clamp(3rem, 9vw, 6.5rem), qui era piu' piccolo (5.5rem max). */
  font-weight: 700 !important;
  font-size: clamp(3rem, 9vw, 6.5rem) !important;
  line-height: 0.95 !important;
  white-space: nowrap !important;
  /* il browser applica 1em 0 di default ai <p> - a questa dimensione di
     font diventava un distacco enorme tra "MARCO" e "MADONNA" (segnalato
     da Marco). Nel prototipo erano <span> senza margini propri. */
  margin: 0 !important;
}

.mm-hero-name .is-content p span {
  letter-spacing: -0.01em !important;
}

/* "MADONNA" (home) porta ancora dal builder Semplice uno <span> annidato con
   font-family inline "Inter-VariableFont_slntwght" (font mai caricato via
   @font-face in questo child theme - nome usato internamente da Semplice per
   il proprio font-picker). Essendo specificato DIRETTAMENTE su quel figlio,
   batte per cascata il font-family ereditato da .mm-hero-name .is-content
   anche se quella regola ha !important (un valore ereditato perde sempre
   contro un valore specificato sull'elemento stesso, importante o no) - il
   browser ripiega quindi sul sans-serif di sistema. Risultato visibile:
   "MARCO" (About, senza quello span extra) mostra le lettere strette che si
   toccano/incrociano al bordo del contorno (l'effetto "vector" segnalato da
   Marco), "MADONNA" no, perche' renderizza in un font diverso con metriche
   piu' larghe. Selettore con * per coprire lo span annidato a qualunque
   profondita', cosi' anche font-family aggiunti dal builder in futuro non
   rompono piu' l'effetto. */
.mm-hero-name .is-content p span,
.mm-hero-name .is-content p span * {
  font-family: var(--font-display) !important;
}

.mm-hero-name .is-content p:nth-of-type(1) span {
  background: linear-gradient(120deg, var(--accent-light), var(--accent) 60%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--accent) !important;
}

.mm-hero-name .is-content p:nth-of-type(2) span {
  color: transparent !important;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 2px var(--text-primary);
}

/* Eyebrow + tagline iniettati da mm-animations.js (initHeroCopy) - copy non
   presente nel contenuto WordPress originale, scritta per completare la
   coreografia vista in intro-prototype.html (eyebrow sopra il nome, tagline
   tra ruolo e bio). */
.mm-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  color: var(--text-secondary);
  margin-bottom: 1.25rem;
}

.mm-tagline {
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--accent-light);
  margin-top: 0.75rem;
}

/* ==========================================================================
   4a. Variante "solida" del titolo hero (.mm-hero-name-solid) per i titoli
   su una parola sola - Logos ("LOGOFOLIO", un <h1>) e ogni pagina progetto
   (nome progetto, es. "SLIGRO", un <p> - stessa classe marcatrice, il
   selettore copre entrambi i tag). Stesso peso/dimensione/font di
   .mm-hero-name qui sopra ma senza lo split riempito/contornato: tutto il
   testo prende il riempimento a gradiente (richiesta esplicita di Marco,
   2026-09-02 - non c'e' un secondo "nome" con cui alternare il contorno).

   Selettore con ".content-block .column-content[data-module=\"text\"]"
   davanti (invece del solo ".mm-hero-name-solid .is-content span") per
   specificita': sulle pagine progetto il modulo del titolo e' anche il
   PRIMO modulo testo del blocco, gia' colpito dalla regola generica "titolo
   progetto" piu' sotto (sezione 5, ":first-of-type .is-content span",
   stessa alta specificita' + !important) - senza eguagliarla qui il colore
   mono/text-primary di quella regola avrebbe vinto sul gradiente. */
.mm-hero-name-solid .is-content {
  font-family: var(--font-display) !important;
}

/* Stessa identica scala di .mm-hero-name qui sopra - clamp(3rem, 9vw, 6.5rem),
   non piu' clamp(2.75rem, 8vw, 5.5rem) (richiesta esplicita di Marco,
   2026-09-04: "the font family and size must be consistent across all
   pages"). I due valori divergevano per un motivo puramente storico, non di
   design: .mm-hero-name era stato portato a 3rem/9vw/6.5rem il 2026-09-01
   per allinearlo a intro-prototype.html, mentre .mm-hero-name-solid e' nata
   il giorno dopo copiando i valori PRECEDENTI a quel ritocco - risultato,
   "LOGOFOLIO"/"CONTACT"/i titoli progetto renderizzavano a 99px dove
   "ABOUT"/"MARCO"/"SELECTED PROJECTS" renderizzano a 117px (stesso
   viewport). Nessun white-space:nowrap qui, a differenza di .mm-hero-name:
   i titoli delle pagine progetto sono frasi intere ("DESIGN SYSTEM
   RESTRUCTURE") e devono poter andare a capo nella loro colonna. */
.mm-hero-name-solid .is-content h1,
.mm-hero-name-solid .is-content p {
  font-weight: 700 !important;
  font-size: clamp(3rem, 9vw, 6.5rem) !important;
  line-height: 0.95 !important;
  margin: 0 !important;
  letter-spacing: -0.01em !important;
}

.content-block .column-content[data-module="text"].mm-hero-name-solid .is-content h1,
.content-block .column-content[data-module="text"].mm-hero-name-solid .is-content h1 span,
.content-block .column-content[data-module="text"].mm-hero-name-solid .is-content p,
.content-block .column-content[data-module="text"].mm-hero-name-solid .is-content p span {
  background: linear-gradient(120deg, var(--accent-light), var(--accent) 60%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--accent) !important;
  font-family: var(--font-display) !important;
  letter-spacing: -0.01em !important;
}

/* Heading (ruolo/tagline sotto il titolo) e descrizione: stessa classe
   marcatrice ovunque (home, About, Logos, pagine progetto), cosi' le
   dimensioni sono identiche indipendentemente dal font-size inline che il
   builder Semplice scrive pagina per pagina. .mm-hero-role si presenta in
   due forme diverse a seconda della pagina:
   - home/pagine progetto: la classe finisce sul modulo ESISTENTE
     (.column-content[data-module="text"]), che contiene ancora il proprio
     <p>/<span> con font-size inline scritto dal builder - serve quindi
     ripetere le stesse proprieta' anche sui discendenti ".is-content p"/
     ".is-content span", non solo sulla classe stessa, altrimenti l'inline
     style sul figlio vince (stesso motivo per cui .mm-hero-name-solid .is-
     content p esiste due sezioni sopra). Il modulo ha gia' un gap naturale
     verso il modulo precedente (la spaziatura standard tra
     .column-content dentro la stessa colonna Semplice) - non serve
     aggiungere altro margine, altrimenti si somma un doppio gap (bug
     trovato in locale, 2026-09-02, verificato via getBoundingClientRect
     su una pagina progetto: ~59px invece dei ~23px di eyebrow/titolo).
   - About/Logos: .mm-hero-role e' invece un <div> iniettato via JS senza
     alcun contenuto/stile proprio (nessun figlio da battere, nessun gap
     naturale perche' non e' un modulo Semplice) - qui il margine va
     aggiunto esplicitamente, distinto dall'altro caso con :has(.is-content)
     (gia' in uso altrove in questo file, es. .content-block:has(.mm-fold-
     col)). .mm-hero-bio segue la stessa logica di doppia forma ma e'
     SEMPRE la prima (avvolge sempre un modulo di testo gia' esistente su
     tutte e 3 le pagine dove viene usata: home, About, Logos) - nessun
     margine aggiuntivo necessario li'. */
.mm-hero-role,
.mm-hero-role .is-content,
.mm-hero-role .is-content p,
.mm-hero-role .is-content span {
  font-family: var(--font-body) !important;
  font-size: 1.125rem !important;
  font-weight: 500 !important;
  line-height: 1.4 !important;
  color: var(--accent-light) !important;
}

.mm-hero-role:not(:has(.is-content)) {
  margin: 0.9rem 0 0 !important;
}

.mm-hero-bio,
.mm-hero-bio .is-content,
.mm-hero-bio .is-content p,
.mm-hero-bio .is-content span {
  font-size: 1rem !important;
  line-height: 1.65 !important;
  /* colore esplicito qui, non solo sulla regola generica ".is-content"
     (che colora il CONTENITORE, non lo <span>): su About/Logos lo <span>
     porta ancora il colore scuro originale del builder (rgb(12,3,3) circa,
     pensato per il vecchio design chiaro) come stile inline SENZA
     !important - un valore esplicito sul figlio non viene mai sovrascritto
     dall'ereditarieta' dal genitore, indipendentemente da !important sul
     genitore, quindi senza questa riga il testo risulterebbe quasi nero e
     illeggibile sul nostro sfondo scuro. mm-animations.js
     (remapLegacyAccentColors) risolverebbe normalmente questo colore da
     solo, ma .mm-hero-bio e' esclusa apposta da quella funzione (vedi
     commento li' dentro) perche' lo rimapperebbe al bianco text-primary
     invece del grigio text-secondary coerente con la home. */
  color: var(--text-secondary) !important;
}

.mm-hero-bio {
  max-width: 640px;
  margin-top: 1.25rem !important;
}

/* 4a-cols. Pagina About: la row dell'hero ha 3 colonne nel markup Semplice
   originale (autore Marco nel builder, design chiaro) - nome/bio (345px),
   una colonna "spacer-column" VUOTA di 690px in mezzo (residuo del vecchio
   layout, nessun contenuto), poi la foto (345px). Il testo restava quindi
   schiacciato in una colonna di soli 345px (righe cortissime, es. "Hello,
   I'm Marco - a Senior / Digital Designer with a strong / focus on...")
   invece della colonna larga ~1005px del mockup Figma (nodo 11664:5167,
   confronto con screenshot condiviso da Marco, 2026-09-02 - bio su 2 righe
   lunghe li', non su 6-7 righe corte). Rimossa la colonna spacer e il
   max-width:640px di .mm-hero-bio qui sopra (pensato per la home, dove la
   riga ha 1 sola colonna piena larghezza e nessuna foto - vedi
   initHeroCopy() - non per About, che ha 3 colonne e va invece riempita).
   Scoping tramite :has(.mm-hero-photo-col) sulla row: struttura unica alla
   sola pagina About (l'unica con foto nell'hero), non tocca Home/Logos. */
.row:has(> .mm-hero-photo-col) > .column.spacer-column {
  display: none !important;
}

.row:has(> .mm-hero-photo-col) > .column:has(.mm-hero-name) {
  flex: 1 1 0% !important;
  max-width: none !important;
  width: auto !important;
}

.row:has(> .mm-hero-photo-col) .mm-hero-bio {
  max-width: none !important;
}

/* Allineamento del "container" coerente su tutto il sito (richiesta
   esplicita di Marco, 2026-09-04: "il container della prima sezione e di
   Experience/Education e' incoerente"). Causa reale: ogni .column di
   Semplice porta un gutter nativo di 0.83333rem (~15px) per lato
   (".column { padding-left/right: 0.83333rem }" nel tema padre),
   normalmente compensato da un margin-left/right NEGATIVO della stessa
   entita' sulla .row che la contiene (tecnica standard per far tornare il
   contenuto a filo nonostante il gutter interno). Quel margine negativo
   pero' NON e' presente in modo uniforme: dipende da come ogni riga e'
   stata costruita a mano nel builder originale, non da un pattern
   prevedibile per pagina/tipo di titolo - verificato in locale, 2026-09-04:
   la pagina progetto Sligro ce l'ha gia' (row a margin-left:-15px, quindi
   gia' correttamente a 270px), ma Logos no (stessa classe marcatrice
   .mm-hero-name-solid delle pagine progetto, eppure row a margin-left:0,
   quindi a 285px) - non e' quindi vero (primo tentativo di diagnosi) che
   "tutte le pagine con .mm-hero-name-solid ce l'hanno gia'". L'hero
   About/Home e GET IN TOUCH sono ugualmente a margin-left:0 sulla propria
   row. Le card Experience/Education/"What I do" (contenitori DIV iniettati
   via JS, fuori dalla griglia Semplice - initTimelineSections() in
   mm-animations.js) non hanno ne' gutter ne' compensazione e sono gia' a
   270px per conto loro, indipendenti da questo meccanismo.
   PRIMO TENTATIVO SBAGLIATO: azzerare il padding del .column invece di
   forzare il margine negativo sulla row - dove la row non aveva gia' un
   margine negativo (About/Home) funzionava, ma su una row che ce l'aveva
   gia' (Sligro) toglieva ANCHE il padding che quel margine si aspettava di
   compensare, spostando il contenuto a 255px invece di 270px - un nuovo
   disallineamento al posto del vecchio.
   SECONDO TENTATIVO, ANCH'ESSO INSUFFICIENTE: forzare solo il margine a
   -0.83333rem (senza toccare il padding), assumendo che il gutter nativo
   del .column valga sempre esattamente 0.83333rem cosi' da cancellarsi a
   vicenda - funzionava sul tema padre Semplice v5.3.2 installato in locale,
   ma il deploy sul sito live (Semplice v5.3.5, versione diversa - vedi nota
   in cima a questo file) ha mostrato un residuo di ~7px (verificato in
   produzione, 2026-09-04: eyebrow/GET IN TOUCH atterravano 7px piu' a
   sinistra del bordo del container rispetto alle card Experience/Education,
   che invece - non toccate da questa regola, mai spostate dalla griglia
   Semplice via JS - restano naturalmente a filo col padding del container
   su qualunque versione) - prova che il valore esatto del gutter nativo
   NON e' una costante affidabile tra versioni del tema padre.
   FIX DEFINITIVO: invece di cancellare un valore ignoto con un altro valore
   ipotizzato, azzera ENTRAMBI margine della row e padding della sua colonna
   - zero meno zero fa zero a prescindere da quale sia il gutter nativo in
   una data versione di Semplice, lo stesso risultato che le card
   Experience/Education ottengono di gia' semplicemente non avendo ne'
   l'uno ne' l'altro. */
.row:has(> .mm-hero-photo-col),
.row:has(> .column > .content-wrapper > .mm-hero-name),
.row:has(> .column > .content-wrapper > .mm-hero-name-solid),
.content-block.mm-section-get-in-touch .row {
  margin-left: 0 !important;
  margin-right: 0 !important;
}

.row:has(> .mm-hero-photo-col) > .column,
.row:has(> .column > .content-wrapper > .mm-hero-name) > .column,
.row:has(> .column > .content-wrapper > .mm-hero-name-solid) > .column,
.content-block.mm-section-get-in-touch .row > .column {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* 4a-photo. Foto profilo nell'hero About (mm-animations.js, initAboutHero -
   classi .mm-hero-photo/.mm-hero-photo-col). Il tema padre imposta
   "align-items: center" su ".row": con la bio lunga accanto (colonna alta
   ~2000px) la foto - card corta - veniva centrata a meta' altezza invece di
   restare ancorata in cima come nel mockup Figma (nodo 11664:5167, confronto
   in locale 2026-09-02). align-self la sgancia dal centraggio della row senza
   toccare le altre colonne. Card con bordo arrotondato + crop "cover" sulla
   foto quadrata originale, stessa proporzione ~345:329 del mockup. */
.mm-hero-photo-col {
  align-self: flex-start !important;
}

.mm-hero-photo .ce-image {
  /* 24px nel mockup - raggio dedicato, distinto dal 16px (--radius-lg) usato
     per le card timeline/education: li' e' lo stesso mockup a differenziarli.
     Ridondante con la foto attuale (image/MM_ProfilePic.png, sostituita da
     Marco il 2026-09-02: un PNG 345x345 gia' con angoli arrotondati/alpha
     trasparente esportato direttamente da Figma, non una foto quadrata
     grezza) ma tenuto come rete di sicurezza per un'eventuale foto futura
     senza maschera gia' incorporata. */
  border-radius: 24px;
  overflow: hidden;
  aspect-ratio: 1 / 1;
}

.mm-hero-photo .ce-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Sotto la soglia in cui la row va in wrap (stessa di sezione 8d/timeline,
   700px), le 3 colonne (nome+eyebrow, bio, foto) impilano nell'ordine del
   DOM originale del builder: nome, bio, foto - la foto finiva quindi in
   fondo, dopo l'intera bio, lontana dal nome che accompagna in
   desktop. :has() invece di nuove classi marcatrici via JS (stesso pattern
   gia' in uso altrove nel file, es. ".content-block:has(.mm-fold-col)")
   per riordinare via flexbox senza toccare il markup: foto subito dopo il
   blocco nome/ruolo, prima della bio lunga. */
@media (max-width: 700px) {
  .row:has(> .mm-hero-photo-col) > .column:has(.mm-hero-name) {
    order: 1;
  }

  .mm-hero-photo-col {
    order: 2;
    max-width: 320px;
  }

  .row:has(> .mm-hero-photo-col) > .column:has(.mm-hero-bio) {
    order: 3;
  }
}

/* 4a-badge. Badge cliccabile (GIF in loop fornita da Marco, link alla
   pagina Contact) nello spazio vuoto tra il titolo e la foto dell'hero
   About - richiesta esplicita di Marco (2026-09-03). Sostituisce il
   precedente badge in vetro Three.js (stesso render del curtain d'intro) -
   vedi createAboutBadge() in mm-intro-glass.js per il perche' del cambio;
   posizionamento/dimensione/comportamento a schermi stretti restano
   invariati rispetto alla versione precedente.

   position:absolute (non fixed): "fixed" nella richiesta originale del
   vecchio badge in vetro intendeva "ancorato al suo posto nella pagina",
   scorre via NORMALMENTE insieme al resto dell'hero invece di restare
   visibile a galleggiare sopra il contenuto sotto mentre si scorre. left/top
   sono calcolati in coordinate DI DOCUMENTO da createAboutBadge()
   (mm-intro-glass.js) - nessun ancestor imposta position:relative tra
   <body> e questo elemento, quindi il "containing block" e' la radice del
   documento, esattamente come un elemento normale nel flusso della pagina.

   pointer-events:auto (a differenza del vecchio badge, puramente
   decorativo): ora e' un vero link, deve poter ricevere click/hover.

   z-index sotto la navbar (che in questo file non dichiara un numero
   esplicito ma vive nel normale stacking order del documento, sopra il
   contenuto) ma sopra i .content-block normali - un valore alto ma non
   quanto il curtain (999999, che deve coprire tutto) o la grana filmica
   (9000, sempre in cima a tutto): 500 basta a stare sopra le card/timeline
   sotto di lei senza competere con overlay reali come il curtain.

   Dimensione 337px: +80% dei 110px originali (198px, richiesta per il
   vecchio badge in vetro) poi +70% ulteriore su richiesta di Marco
   (2026-09-03, dopo il passaggio alla GIF) - deve restare uguale a
   ABOUT_BADGE_SIZE in mm-intro-glass.js, che governa il posizionamento. */
.mm-about-glass-badge {
  position: absolute;
  width: 337px;
  height: 337px;
  pointer-events: auto;
  z-index: 500;
  opacity: 0;
  /* inclinato di 30deg, richiesta esplicita di Marco (2026-09-04) - stessa
     tecnica gia' in uso sul badge WhatsApp della pagina Contact
     (.mm-contact-whatsapp-badge qui sotto, rotate(-30deg)), non un tilt 3D
     (rotateX) come quello gia' presente sul carosello interno
     (mm-badge-spin, 14deg fisso - quello inclina il TESTO che gira dentro
     l'anello, questo inclina l'intero badge come un adesivo). */
  transform: rotate(30deg);
  transition: opacity 500ms ease, transform var(--transition-fast);
}

.mm-about-glass-badge.mm-badge-ready {
  opacity: 1;
}

.mm-about-glass-badge:hover {
  transform: rotate(30deg) scale(1.05);
}

.mm-about-glass-badge a {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  transition: box-shadow var(--transition-fast);
}

.mm-about-glass-badge:hover a {
  box-shadow: 0 0 32px -6px var(--accent-glow);
}

/* Carosello 3D di testo (mm-intro-glass.js, buildAboutBadgeMarkup) -
   sostituisce un primo tentativo GIF e un secondo tentativo SVG/ellisse
   (vedi commento su createAboutBadge() li' per la storia completa e il
   riferimento CodePen da cui e' ripresa questa tecnica). ".mm-badge-circle"
   stabilisce il contesto di prospettiva 3D (perspective) per i suoi figli;
   ".mm-badge-word" e' il carosello vero e proprio, che ruota (rotateY
   animato) mentre resta inclinato di un angolo fisso (rotateX) - la
   prospettiva del browser fa il resto (lettere piu' vicine piu' grandi,
   quelle sul retro piu' piccole/compresse: vera profondita' 3D, non
   un'approssimazione 2D). */
.mm-badge-circle {
  width: 100%;
  height: 100%;
  /* --mm-badge-perspective (default 600px, il valore gia' tarato per il
     badge About a 337px) puo' essere sovrascritta da un wrapper piu'
     piccolo (es. .mm-contact-whatsapp-badge) - una prospettiva fissa su un
     anello di raggio molto minore leggerebbe piatta, va scalata insieme al
     raggio (--mm-badge-radius, vedi .mm-badge-char) per mantenere la stessa
     "intensita'" di profondita' percepita a qualunque dimensione. */
  perspective: var(--mm-badge-perspective, 600px);
  perspective-origin: center;
}

.mm-badge-word {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  /* preserve-3d: senza questa, i rotateY/translateZ dei singoli
     .mm-badge-char (figli) verrebbero "appiattiti" sul piano di .word
     invece di restare in uno spazio 3D condiviso - risultato piatto,
     nessuna vera disposizione a cerchio. */
  transform-style: preserve-3d;
  animation: mm-badge-spin 20s linear infinite;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--accent-light);
}

.mm-badge-char {
  position: absolute;
  /* --char-index (inline, per-carattere) e --mm-badge-step (inline su
     .mm-badge-word, un solo valore per l'intero anello - le custom
     property CSS ereditano di default) sono impostate in JS (vedi
     buildTextRingMarkup() in mm-intro-glass.js/mm-contact-form.js - stessa
     funzione duplicata nei due file, non condivisibile: uno e' un modulo ES
     con Three.js, l'altro uno script classico, vedi nota li'): lo step e'
     360deg/numero-di-caratteri, cosi' il cerchio si richiude esattamente su
     un giro completo qualunque sia la lunghezza del testo. --mm-badge-radius
     (default 105px, il valore gia' tarato per il badge About a 337px) puo'
     essere sovrascritta da un wrapper piu' piccolo, insieme a
     --mm-badge-perspective sul suo .mm-badge-circle (vedi sopra). */
  transform: rotateY(calc(var(--char-index) * var(--mm-badge-step))) translateZ(var(--mm-badge-radius, 105px));
  /* preserve-3d: i due figli .mm-badge-char-face qui sotto hanno un proprio
     transform (rotateY(180deg) sul retro) che deve restare in uno spazio 3D
     condiviso con questo posizionamento, non venire appiattito. */
  transform-style: preserve-3d;
}

/* Ogni posizione dell'anello ha DUE copie sovrapposte dello stesso
   carattere invece di una sola (buildAboutBadgeMarkup(), mm-intro-glass.js):
   ".mm-badge-char-face" normale + una seconda ".-face-back" pre-ruotata di
   180deg su se stessa. backface-visibility:hidden su ENTRAMBE fa si' che a
   ogni istante sia visibile solo quella rivolta verso la camera - una sola
   copia per posizione mostrerebbe il proprio retro (testo A SPECCHIO) non
   appena la rotazione la portasse oltre i 90deg, lasciando meta' anello
   vuoto (segnalato da Marco: "vedo solo un lato, dovrei vederli entrambi").
   position:absolute SOLO sulla copia posteriore (non su quella frontale,
   che resta in flusso normale): e' lei a determinare la dimensione
   auto-adattata di .mm-badge-char in base al glifo, la copia posteriore le
   si sovrappone esattamente senza contribuire a sua volta alla dimensione
   (evita una dipendenza circolare - due figli assoluti in un contenitore a
   dimensione automatica non avrebbero nulla da cui derivare quella
   dimensione). */
.mm-badge-char-face {
  backface-visibility: hidden;
}

.mm-badge-char-face-back {
  position: absolute;
  top: 0;
  left: 0;
  transform: rotateY(180deg);
}

@keyframes mm-badge-spin {
  from {
    transform: rotateX(14deg) rotateY(0deg);
  }
  to {
    transform: rotateX(14deg) rotateY(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Rete di sicurezza CSS-only: aboutBadgeShouldExist() (mm-intro-glass.js)
     gia' impedisce la creazione del badge del tutto sotto reduced-motion,
     ma questa regola resta come secondo livello di difesa, stesso pattern
     gia' in uso altrove nel file. Mantiene comunque l'inclinazione fissa
     (rotateX) invece di azzerare del tutto il transform, cosi' il cerchio
     di lettere non collassa in una riga piatta per chi ha questa preferenza
     attiva. */
  .mm-badge-word {
    animation: none;
    transform: rotateX(14deg);
  }
}

/* Sotto i 700px l'hero About impila le colonne (media query sopra) - non
   c'e' piu' un "gap tra testo e foto" da riempire, quindi il badge non ha
   senso li' (initAboutBadge() lo verifica gia' via JS prima di crearlo, ma
   la regola resta come rete di sicurezza CSS-only in caso di resize). */
@media (max-width: 700px) {
  .mm-about-glass-badge {
    display: none;
  }
}

/* ==========================================================================
   4b. Scroll reveal per i .content-block dopo l'hero.

   STORIA (importante per capire perche' questa regola e' cosi' minimale):
   qui viveva un sistema di reveal-on-scroll CUSTOM completo (IntersectionObserver
   + fade/translateY), costruito perche' il sistema NATIVO di Semplice
   (ScrollReveal.js integrato nel tema padre, gia' attivo di default su ogni
   pagina - impostazione "Reveal content on scroll") sembrava restare
   bloccato per sempre a opacity:0 in QUESTO ambiente di sviluppo locale.
   Avere i DUE sistemi attivi in parallelo sugli stessi .content-block (loro
   via style inline + data-sr-id, nostro via classe .mm-visible) e' pero'
   risultato la causa piu' probabile di uno sfarfallio (flicker) visibile
   segnalato da Marco nel suo browser REALE (video, 2026-09-02) atterrando
   su About/Logos/pagine progetto - non risolto nemmeno neutralizzando
   attivamente lo style scritto dal loro script (tentativo precedente, poi
   rimosso). Deciso di tornare al sistema NATIVO come unica fonte di verita'
   per il reveal-on-scroll (richiesta esplicita di Marco), rimuovendo il
   nostro fade/translateY custom - lasciamo quindi i .content-block al loro
   comportamento normale (opacity:1, nessuno stato nascosto imposto da noi),
   il tema padre pensa gia' lui alla rivelazione progressiva.

   .mm-visible resta SOLO come rete di sicurezza (mm-animations.js,
   initScrollRevealSafetyNet): se il sistema nativo dovesse mai restare
   bloccato a opacita' quasi zero (il bug originale che aveva motivato la
   costruzione del sistema custom), questa classe lo forza visibile dopo un
   tempo generoso - ultima spiaggia, non un'animazione attiva.

   AGGIORNAMENTO (trovato in locale, 2026-09-03, sanity check mobile): la
   rete di sicurezza copriva solo "opacity", ma lo ScrollReveal nativo di
   Semplice anima anche un "transform" (scale+translateY in ingresso) sullo
   stesso elemento via style inline - quando resta bloccato a meta'
   animazione lo fa su ENTRAMBE le proprieta', non solo sull'opacita'.
   Riprodotto su /personal-projects (Logos) a 375px: piu' .content-block
   fermi a transform:scale(1.2) translateY(-120px), abbastanza da farli
   sconfinare visivamente nel blocco precedente (bottone "TO MM_DOODLES"
   sovrapposto al primo logo). Stesso "!important" applicato anche qui. */
.content-block.mm-visible {
  opacity: 1 !important;
  transform: none !important;
}

/* ==========================================================================
   5. Progetti - card grandi "foldable" (mm-animations.js: initFoldableProjects)
   Ogni progetto vive in una .column (un .content-block puo' averne 2
   affiancate = 2 progetti per riga nel layout originale) - forzata a
   larghezza piena cosi' le card si impilano una sotto l'altra, grandi,
   invece della griglia stretta a 2 colonne originale.

   IMPORTANTE (bug trovato in locale, 2026-09-01): ogni .content-block
   originale ha un padding-top/bottom SUO (64px/32px/80px...), impostato da
   Marco riga per riga nel builder per la griglia a 2 colonne originale -
   variava per dare respiro visivo nel layout a griglia. Impilate in colonna
   unica, quelle differenze diventano un "salto" vistoso ogni due progetti
   (segnalato da Marco) invece di un ritmo regolare. Normalizzato: qualsiasi
   .content-block che contiene almeno una card foldable ha lo stesso
   padding-top/bottom ridotto, la spaziatura reale tra le card la da' gia'
   il margin-bottom di .mm-fold-col qui sotto. */
.content-block:has(.mm-fold-col) {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

.column.mm-fold-col {
  position: relative;
  flex: 0 0 100% !important;
  max-width: 100% !important;
  width: 100% !important;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  /* !important: la nostra stessa regola di reset in cima al file forza
     background-color:transparent su .column con !important (serviva a
     battere gli sfondi bianchi per-pagina di Semplice) - qui la batteva a
     sua volta, lasciando le card senza sfondo solido e quindi invisibili
     una volta impilate (bug trovato in locale, 2026-09-01). */
  background-color: var(--bg-primary) !important;
  background-image: linear-gradient(160deg, var(--glass-bg), var(--glass-bg-end));
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 16px 40px -12px var(--shadow-strong);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
  overflow: hidden;
  transition: border-color var(--transition-base), background-color var(--transition-base), box-shadow var(--transition-base);
}

/* linea di accento sfumata sempre visibile in cima alla card - la "firma"
   glass/gradient che deve leggersi anche senza passarci sopra col mouse */
.column.mm-fold-col::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent) 30%, var(--accent-light) 70%, transparent);
  opacity: 0.7;
}

.column.mm-fold-col:hover {
  border-color: rgba(139, 92, 246, 0.45);
  background: linear-gradient(160deg, var(--glass-bg-hover), var(--glass-bg-end-hover));
  box-shadow: 0 8px 40px -12px var(--accent-glow), inset 0 1px 0 var(--glass-inset-highlight);
}

.mm-fold-header {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  cursor: pointer;
  user-select: none;
}

.mm-fold-header:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.mm-fold-header .column-content[data-module="image"] {
  flex: 0 0 clamp(140px, 22vw, 260px);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.mm-fold-title-group {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Brand del progetto (mockup Figma 2026-09-02, nodo 11656:5154): riga viola
   sopra al titolo, es. "SWYDO" sopra "DESIGN SYSTEM RESTRUCTURE" - aggiunta
   da initFoldableProjects() in mm-animations.js, dedotta dal testo del
   titolo (nessun campo brand dedicato nel builder Semplice). Font Inter
   Bold in entrambi (label e titolo), come nel mockup - non DM Mono, che
   nel resto del sito e' riservato a nav/bottoni/etichette brevi. */
.mm-fold-brand {
  display: block;
  color: var(--accent-light);
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.mm-fold-icon {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--transition-base), border-color var(--transition-base), background var(--transition-base);
}

.mm-fold-icon::before,
.mm-fold-icon::after {
  content: '';
  position: absolute;
  background: var(--text-primary);
  transition: transform var(--transition-base), opacity var(--transition-base);
}

.mm-fold-icon {
  position: relative;
}

.mm-fold-icon::before {
  width: 12px;
  height: 1.5px;
}

.mm-fold-icon::after {
  width: 1.5px;
  height: 12px;
}

.column.mm-fold-col.is-open .mm-fold-icon {
  border-color: var(--accent);
  background: var(--accent-dim);
}

.column.mm-fold-col.is-open .mm-fold-icon::after {
  transform: rotate(90deg);
  opacity: 0;
}

.mm-fold-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--transition-slow);
}

.mm-fold-body-inner {
  overflow: hidden;
  min-height: 0;
  /* spazio tra l'header (immagine+titolo) e la descrizione quando la card
     si apre - prima era 0, tutto appiccicato (segnalato da Marco) */
  padding-top: 1.5rem;
}

.column.mm-fold-col.is-open .mm-fold-body {
  grid-template-rows: 1fr;
}

/* spazio tra descrizione e bottone "View project" - prima 1.25rem, troppo
   poco (segnalato da Marco insieme al gap sopra) */
.mm-fold-body-inner > .column-content + .column-content {
  margin-top: 1.5rem;
}

.content-block .column-content[data-module="image"] .ce-image img {
  transition: transform var(--transition-slow), opacity var(--transition-base);
  will-change: transform;
}

.content-block .column-content[data-module="image"]:hover .ce-image img {
  transform: scale(1.03);
  opacity: 0.94;
}

/* Parallax leggero (mm-animations.js: initParallax) - sul wrapper .ce-image,
   mai sull'<img> qui sopra che ha gia' il proprio transform:scale() in
   hover: tenerli su elementi diversi evita qualsiasi conflitto tra i due
   transform (uno style inline sull'<img> batterebbe comunque la regola
   :hover esterna). --mm-parallax e' aggiornata via JS, 0px di default cosi'
   il wrapper resta fermo finche' lo script non lo raggiunge (miniature
   delle card foldable, griglia Logos - escluse via JS - restano quindi
   sempre a 0px, invariate). */
.column-content[data-module="image"] > .ce-image {
  --mm-parallax: 0px;
  transform: translateY(var(--mm-parallax));
}

.content-block .column-content[data-module="text"] .is-content {
  color: var(--text-secondary) !important;
  font-family: var(--font-body) !important;
}

/* titolo progetto = prima riga di testo dopo l'immagine, tipicamente in maiuscolo */
.content-block .column-content[data-module="text"]:first-of-type .is-content span {
  color: var(--text-primary) !important;
  font-family: var(--font-mono) !important;
  letter-spacing: 0.05em;
}

/* La regola "titolo progetto" qui sopra colpiva anche la DESCRIZIONE dell'hero
   di Logofolio (bug segnalato da Marco, 2026-09-04: "the font family and size
   must be consistent across all pages"): li' il paragrafo "One of my main
   passions is Logo Design..." vive in una SECONDA row del content-block, dove
   e' il primo <div> tra i suoi fratelli e quindi ":first-of-type" per
   definizione (quella pseudo-classe conta i fratelli per TAG, non per
   selettore - stessa trappola gia' documentata due volte in questo file). Il
   testo usciva quindi in DM Mono bianco pieno con letter-spacing 0.05em,
   mentre la stessa descrizione su Home/About usa Inter grigio senza
   spaziatura extra. Su Home/About non capitava mai perche' li' il modulo bio
   ha sempre almeno un fratello <div> prima di se'.

   Stessa specificita' della regola sopra (5 classi/attributi + 1 elemento),
   quindi conta l'ORDINE nel file - questo blocco deve restare subito DOPO
   quella regola. Non si e' invece aggiunto un :not(.mm-hero-bio) al selettore
   di sopra apposta: ne alzerebbe la specificita' a 6, pareggiandola con
   ".column.mm-fold-col .mm-fold-header ..." piu' sotto (che oggi vince
   proprio perche' e' a 6 contro 5) e rimettendo in gioco quel bug gia'
   risolto il 2026-09-03. */
.content-block .column-content[data-module="text"].mm-hero-bio .is-content span {
  color: var(--text-secondary) !important;
  font-family: var(--font-body) !important;
  letter-spacing: normal;
}

/* Card progetto "default" (chiusa) ingrandita secondo il mockup Figma del
   2026-09-02 (nodo 11655:5080): immagine e titolo molto piu' grandi
   (immagine fino a 640px, titolo Inter fino a 54px invece di DM Mono ~18px),
   stesso padding/icona/glass di prima. Applicata solo da 700px in su (stessa
   soglia gia' usata per la timeline Experience) - il mockup e' pensato per
   il frame 1920w, sotto i 700px l'header della card (gia' stretto) non ha
   spazio per immagine+testo+icona a questa scala e andrebbe in overflow;
   sotto quella soglia restano le dimensioni originali piu' compatte definite
   sopra. */
/* Titolo della card "fold" allineato all'identita' unica dei titoli di card
   (--card-title-*, vedi :root): stessa DM Mono 24px delle voci
   Experience/Education. Fuori da qualsiasi @media, a differenza della
   versione precedente (Inter 300 fino a 54px, ricavata dal mockup Figma
   11655:5080 e attiva solo da 700px in su): a 24px fissi - la misura delle
   card About, che non scala con la viewport - non c'e' piu' niente da
   differenziare per breakpoint.
   .column.mm-fold-col in testa (invece di partire da .mm-fold-header):
   specificita' 6 classi/attributi, serve a battere la regola compatta
   ":first-of-type .is-content span" qui sopra (5 classi/attributi) - a
   parita' di !important vince la specificita' piu' alta, non l'ordine nel
   file. */
.column.mm-fold-col .mm-fold-header .column-content[data-module="text"] .is-content span {
  font-family: var(--card-title-font) !important;
  font-size: var(--card-title-size) !important;
  font-weight: var(--card-title-weight) !important;
  letter-spacing: var(--card-title-tracking) !important;
  line-height: var(--card-title-line) !important;
  text-transform: none !important;
  color: var(--text-primary) !important;
}

@media (min-width: 700px) {
  .mm-fold-header .column-content[data-module="image"] {
    flex-basis: clamp(240px, 32.6vw, 640px);
    border-radius: var(--radius-lg);
  }

  .mm-fold-title-group {
    gap: 1rem;
  }

  .mm-fold-brand {
    font-size: clamp(0.9rem, 1vw, 1.05rem);
  }
}

/* ==========================================================================
   5b. "What I do" - 3 sezioni "esplose" (mm-animations.js: initIntroTracks)
   Struttura ispirata al selettore "tracks" di pleurat.com (sezione
   "Expertise" della home, studiata dal vivo: una lista verticale, contenuto
   che cambia per voce selezionata) - ma qui tutte e 3 le voci restano
   SEMPRE visibili una sotto l'altra, nessun click/stato nascosto: Marco ha
   respinto esplicitamente un primo tentativo con selettore+pannello
   ("don't add them to a carousel", 2026-09-04) - troppo vicino
   all'interazione "un contenuto alla volta dietro un gesto" appena
   eliminata col carosello 3D (rimosso lo stesso giorno, vedi
   mm-animations.js per la cronologia). */
.mm-tracks-block {
  /* Padding superiore aumentato per compensare lo spazio che occupava il
     titolo di sezione, ora rimosso (riga + il suo margin-bottom): senza
     questo la prima card si attaccherebbe al testo dell'hero. */
  padding-top: clamp(3.5rem, 8vw, 7rem) !important;
  padding-bottom: clamp(2rem, 5vw, 4rem) !important;
}

/* La sezione non ha titolo: la label "What I do" e' stata rimossa su
   richiesta esplicita di Marco (2026-09-04, "remove the what I do label").
   Con lei sono spariti .mm-tracks-heading e .mm-tracks-revealed (il reveal
   a livello di blocco, che serviva solo a far comparire quel titolo - le
   card hanno il proprio .mm-track-revealed, una per card).
   Il "width/flex 1 1 100%" qui sotto resta necessario anche senza titolo:
   il .container di Semplice e' un "display: flex; flex-wrap: wrap"
   (verificato in locale, 2026-09-04, su computed style) e senza una base
   esplicita la lista si dimensiona sul contenuto invece che sullo spazio
   disponibile. */
.mm-tracks-list {
  width: 100%;
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  /* Card staccate una dall'altra (prima erano righe separate da un solo
     bordo, attaccate): con vetro, raggio e ombra propri hanno bisogno di
     aria intorno o si leggono come un unico pannello segmentato. */
  gap: clamp(1.25rem, 2.5vw, 2rem);
}

/* Ogni voce e' una vera card in vetro - stesso linguaggio delle card
   progetto (.mm-project-card, sezione 5c) e delle card About
   (.mm-timeline-col, sezione 8c), ma con un livello in piu': filo
   d'accento in cima, alone radiale che si muove in parallasse e numerale
   gigante dietro il testo. Richiesta di Marco (2026-09-04): "make the
   cards way more premium". */
.mm-track {
  position: relative;
  /* isolation: crea un contesto di impilamento sulla card, cosi'
     l'::after con z-index -1 (l'alone) resta DENTRO la card - dipinto
     sopra il suo sfondo ma sotto il contenuto - invece di finire dietro
     l'intera sezione. */
  isolation: isolate;
  overflow: hidden;
  padding: clamp(2rem, 3.6vw, 3rem) clamp(1.5rem, 3vw, 3rem) clamp(1.75rem, 3.2vw, 2.75rem);
  border: 1px solid var(--glass-border);
  border-radius: clamp(16px, 1.8vw, 24px);
  /* Solo il gradiente translucido, nessun background-color pieno: cosi'
     l'aurora di sfondo continua a passare attraverso la card (come su
     .mm-project-card) invece di essere coperta. */
  background-image: linear-gradient(160deg, var(--glass-bg), var(--glass-bg-end));
  box-shadow: inset 0 1px 0 var(--glass-inset-highlight),
    0 18px 50px -30px var(--shadow-soft);
  backdrop-filter: blur(14px) saturate(130%);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  opacity: 0;
  transform: translateY(32px) scale(0.985);
  transition: opacity 0.7s ease, transform 0.9s var(--transition-slow),
    border-color var(--transition-base), box-shadow var(--transition-base),
    background-image var(--transition-base);
}

/* Filo d'accento sul bordo superiore - 1px invece dei 2px delle card
   About: qui la card e' molto piu' grande e un filo piu' sottile legge
   come rifinitura invece che come barra. */
.mm-track::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent) 25%, var(--accent-light) 70%, transparent);
  opacity: 0.45;
  transition: opacity var(--transition-base);
  pointer-events: none;
}

/* Alone d'accento dietro il numerale - terzo livello di parallasse (il
   piu' lento), muove insieme allo scroll via --mm-track-card-parallax
   impostata da mm-animations.js. */
.mm-track::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: -8%;
  top: -45%;
  width: 55%;
  height: 190%;
  background: radial-gradient(closest-side, var(--accent-dim), transparent 72%);
  transform: translateY(var(--mm-track-card-parallax, 0px));
  will-change: transform;
  pointer-events: none;
}

.mm-track.mm-track-revealed {
  opacity: 1;
  transform: none;
}

/* Il sollevamento in hover e' condizionato allo stato rivelato: prima del
   reveal la card ha ancora la sua transform d'ingresso, e un hover li'
   sopra la farebbe saltare a meta' animazione. */
.mm-track.mm-track-revealed:hover {
  transform: translateY(-3px);
  border-color: rgba(139, 92, 246, 0.45);
  background-image: linear-gradient(160deg, var(--glass-bg-hover), var(--glass-bg-end-hover));
  box-shadow: inset 0 1px 0 var(--glass-inset-highlight),
    0 26px 60px -28px var(--accent-glow);
}

.mm-track:hover::before {
  opacity: 0.9;
}

/* Numerale "01/02/03" ingrandito di circa 4x (da ~2.25rem a ~10rem) e
   spostato dalla colonna di sinistra della griglia a un livello assoluto
   DIETRO il contenuto - richiesta esplicita di Marco (2026-09-04):
   "increase the numbers (01, 02..) and let them sit partly below the text
   block". Il blocco testo parte piu' a destra (margin-left qui sotto),
   quindi solo la parte sinistra del numerale resta scoperta: il resto
   scorre sotto al testo. La maschera lo sfuma proprio verso destra/basso,
   dove il testo lo attraversa, cosi' l'incrocio dei due non toglie mai
   leggibilita' al paragrafo. */
.mm-track-index {
  position: absolute;
  z-index: 0;
  top: clamp(0.4rem, 1.4vw, 1.1rem);
  left: clamp(0.75rem, 1.6vw, 1.75rem);
  font-family: var(--font-mono);
  font-size: clamp(5rem, 13vw, 12rem);
  font-weight: 300;
  line-height: 0.78;
  letter-spacing: -0.04em;
  background-image: linear-gradient(155deg, var(--accent-light) 0%, var(--accent) 45%, transparent 92%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  opacity: 0.5;
  /* La maschera non arriva mai a trasparente pieno: la seconda cifra
     ("2"/"3"), che e' quella che finisce sotto al testo, deve restare
     leggibile come parte del numero - solo attenuata dove il paragrafo la
     attraversa, non cancellata (primo tentativo: sfumava a 0 e i numeri
     leggevano tutti come "0"). */
  -webkit-mask-image: linear-gradient(100deg, #000 0%, rgba(0, 0, 0, 0.55) 62%, rgba(0, 0, 0, 0.18) 100%);
  mask-image: linear-gradient(100deg, #000 0%, rgba(0, 0, 0, 0.55) 62%, rgba(0, 0, 0, 0.18) 100%);
  transform: translateY(var(--mm-track-num-parallax, 0px));
  will-change: transform;
  transition: opacity var(--transition-base);
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.mm-track:hover .mm-track-index {
  opacity: 0.58;
}

/* Nel tema chiaro l'accento e' un viola scuro (#7c3aed/#6d28d9) su vetro
   chiaro: alla stessa opacita' del tema scuro il numerale diventerebbe una
   massa scura sotto a un testo anch'esso scuro (--text-secondary e' quasi
   nero al 60%), togliendo contrasto proprio dove i due si sovrappongono.
   Stessa logica gia' applicata altrove nel file quando l'accento cambia
   ruolo tra i due temi: non un'inversione 1:1, opacita' ritarata a mano. */
:root[data-theme="light"] .mm-track-index {
  opacity: 0.3;
}

:root[data-theme="light"] .mm-track:hover .mm-track-index {
  opacity: 0.4;
}

.mm-track-body {
  position: relative;
  z-index: 1;
  /* Rientro che determina quanta parte del numerale resta scoperta a
     sinistra e quanta finisce sotto al testo: tarato in locale perche' la
     prima cifra resti tutta nel margine e la seconda vada per circa meta'
     sotto al blocco di testo (~40% del numerale coperto a 1280px, misurato
     - col valore precedente la sovrapposizione era del 16%, si leggeva
     come un numero affiancato al testo invece che sotto). */
  margin-left: clamp(3rem, 8.5vw, 8.5rem);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-width: 0;
  /* Secondo livello di parallasse: verso opposto e ampiezza minore di
     quella del numerale - vedi mm-animations.js, initIntroTracks. */
  transform: translateY(var(--mm-track-body-parallax, 0px));
  will-change: transform;
}

.mm-track-headrow {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
}

.mm-track-title {
  /* !important: .mm-track-title e' un <h3> e la sezione 6 di questo file
     ha "h1, h2, h3 { font-family: var(--font-display) !important }" - a
     parita' di regole con !important vincerebbe quella (la nostra classe ha
     specificita' maggiore ma nessun !important, quindi perde comunque).
     Non serviva prima perche' il valore precedente era --font-body, che
     punta anch'esso a Inter: il conflitto c'era gia' ma era invisibile
     (bug trovato in locale, 2026-09-04: il titolo restava Inter dopo il
     passaggio a DM Mono). */
  font-family: var(--card-title-font) !important;
  font-weight: var(--card-title-weight);
  /* Una tacca sopra --card-title-size (24 -> 27px): richiesta di Marco
     (2026-09-04, "increase a notch the headings of the cards"). Vale solo
     per le card della home, dove il testo del corpo e' stato al contempo
     ridotto di una tacca (vedi .mm-track-intro / .mm-track-steps li) - il
     token condiviso resta a 24px, cosi' le card di /projects continuano ad
     allinearsi ai titoli Experience/Education della pagina About. Scritto
     in calc() sul token e non come valore assoluto: se un giorno il token
     cambia, questo lo segue restando "una tacca sopra". */
  font-size: calc(var(--card-title-size) + 0.1667rem);
  letter-spacing: var(--card-title-tracking);
  line-height: var(--card-title-line);
  text-transform: none;
  color: var(--text-primary);
  margin: 0;
}

/* Meta come pastiglia in vetro invece che come testo nudo: allo stesso
   peso tipografico di prima, ma con un contenitore che la separa dal
   titolo su cui ora e' in linea. */
.mm-track-meta {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  white-space: nowrap;
  /* Spinta all'estremo destro della riga di testa: la card occupa tutta la
     larghezza del container (vedi il fix flex sul titolo di sezione) mentre
     il corpo del testo resta a 62ch - senza questo la riga di testa
     resterebbe ammassata a sinistra con meta' card vuota accanto. */
  margin-left: auto;
}

.mm-track-intro {
  font-family: var(--font-body);
  /* Una tacca sotto (18.4 -> 17.1px), in coppia con il titolo ingrandito:
     insieme aprono la gerarchia dentro la card, che con 24px di titolo su
     18px di corpo era piuttosto piatta. */
  font-size: 0.95rem;
  color: var(--text-secondary);
  line-height: 1.65;
  max-width: 62ch;
  margin: 0;
}

/* Riga "dettaglio": elenco puntato a colonna singola + illustrazione
   isometrica nella colonna accanto (richiesta di Marco, 2026-09-04). E' la
   riga che riempie la meta' destra della card, rimasta vuota da quando le
   card occupano tutta la larghezza del container: prima ci finiva la
   seconda colonna di puntini, ora l'illustrazione. */
.mm-track-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
}

/* Due colonne solo quando c'e' spazio vero per entrambe: sotto i 1000px
   l'illustrazione scende sotto l'elenco invece di stringerlo. */
@media (min-width: 1000px) {
  .mm-track-detail {
    grid-template-columns: minmax(0, 1fr) clamp(190px, 20vw, 280px);
  }
}

.mm-track-steps {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  max-width: 62ch;
}

.mm-track-steps li {
  position: relative;
  /* Prima ereditavano i 18px del corpo pagina: scesi di una tacca insieme
     al paragrafo introduttivo, appena sotto di questo come gia' erano. */
  font-size: 0.92rem;
  padding-left: 1.4rem;
  color: var(--text-secondary);
  font-family: var(--font-body);
  line-height: 1.55;
}

.mm-track-steps li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.52em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  /* Alone attorno al punto: lo stesso segno di prima, ma acceso come il
     resto della card invece che piatto. */
  box-shadow: 0 0 0 3px var(--accent-dim);
}

/* --------------------------------------------------------------------------
   Illustrazione isometrica (mm-animations.js: buildTrackArt). Le facce SVG
   prendono il colore da queste classi e non da attributi fill/stroke sul
   nodo: le variabili CSS non funzionano dentro gli attributi di
   presentazione SVG, e questi colori devono cambiare col tema.
   -------------------------------------------------------------------------- */
.mm-track-art {
  justify-self: center;
  width: 100%;
  /* 200px quando l'illustrazione e' impilata sotto l'elenco (sotto i
     1000px, vedi .mm-track-detail): alla misura piena diventerebbe
     l'elemento dominante della card proprio dove la card e' gia' la piu'
     alta. In colonna torna a 280px. */
  max-width: 200px;
  /* Quarto livello di parallasse, sommato a quello del blocco testo che la
     contiene - vedi MM_TRACK_ART_PARALLAX_RANGE in mm-animations.js. */
  transform: translateY(var(--mm-track-art-parallax, 0px));
  will-change: transform;
  pointer-events: none;
}

/* Sopra i 1000px l'illustrazione ha una colonna sua e puo' riempirla. La
   media query sta QUI e non accanto a .mm-track-detail apposta: a parita'
   di specificita' vince l'ultima regola nel file, e li' sopra sarebbe
   arrivata prima del max-width di base (bug trovato in locale, 2026-09-04:
   l'illustrazione restava a 200px anche a due colonne). */
@media (min-width: 1000px) {
  .mm-track-art {
    max-width: 280px;
  }
}

.mm-track-art-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.mm-track-art .mm-iso-face {
  stroke: var(--iso-stroke);
  /* non-scaling-stroke: il tratto resta di 1px reale a qualunque
     dimensione l'SVG venga scalato dalla colonna, invece di ingrossarsi
     sui viewport larghi. */
  vector-effect: non-scaling-stroke;
  stroke-width: 1;
  stroke-linejoin: round;
  transition: fill var(--transition-base), stroke var(--transition-base);
}

.mm-track-art .mm-iso-top { fill: var(--iso-top); }
.mm-track-art .mm-iso-right { fill: var(--iso-right); }
.mm-track-art .mm-iso-left { fill: var(--iso-left); }

.mm-track-art .mm-iso-top.mm-iso-accent { fill: var(--iso-accent-top); }
.mm-track-art .mm-iso-right.mm-iso-accent { fill: var(--iso-accent-right); }
.mm-track-art .mm-iso-left.mm-iso-accent { fill: var(--iso-accent-left); }
.mm-track-art .mm-iso-face.mm-iso-accent { stroke: var(--iso-accent-stroke); }

.mm-track-art .mm-iso-line {
  fill: none;
  stroke: var(--iso-accent-stroke);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 3 4;
}

/* --------------------------------------------------------------------------
   Animazione in loop delle illustrazioni (richiesta di Marco, 2026-09-04:
   "softly animate the illustrations in the cards with a loop animation").
   Due soli movimenti, entrambi continui e senza inizio/fine percepibili:
   - i volumi galleggiano su e giu' di poche unita', sfasati uno rispetto
     all'altro cosi' l'onda percorre la scena dal fondo verso l'osservatore
     (--i, assegnata in mm-animations.js nell'ordine di disegno);
   - le tracce tratteggiate della card "AI Workflow" scorrono lungo il
     percorso, come dati che passano dagli agenti al prodotto.
   Tutto in CSS e su transform/stroke-dashoffset: nessun timer JS, nessun
   layout ricalcolato a ogni frame.
   Le animazioni partono FERME e si avviano col reveal della card
   (.mm-track-revealed): quelle sotto la piega non consumano cicli finche'
   non vengono raggiunte, e la card entra in scena con l'illustrazione
   ancora immobile invece che a meta' oscillazione.
   -------------------------------------------------------------------------- */
@keyframes mm-iso-float {
  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    /* Unita' del viewBox, non pixel di schermo: l'SVG e' scalato circa 2x
       nella sua colonna, quindi in pagina sono circa 5px. */
    transform: translateY(-2.5px);
  }
}

@keyframes mm-iso-flow {
  to {
    /* Due periodi interi del tratteggio (dasharray 3 4 = passo 7): il ciclo
       si richiude esattamente su se stesso, senza scatto al rientro. */
    stroke-dashoffset: -14;
  }
}

.mm-track-art .mm-iso-solid {
  animation: mm-iso-float 6s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -0.5s);
  animation-play-state: paused;
}

.mm-track-art .mm-iso-line {
  animation: mm-iso-flow 2.4s linear infinite;
  animation-play-state: paused;
}

/* Il piano d'appoggio non galleggia: e' il riferimento fermo della scena. */
.mm-track-art .mm-iso-ground {
  animation: none;
}

.mm-track-revealed .mm-track-art .mm-iso-solid,
.mm-track-revealed .mm-track-art .mm-iso-line {
  animation-play-state: running;
}

/* Riga di tag separata dal corpo da una hairline: da' un piede alla card
   invece di lasciare i tag appesi sotto l'ultimo punto elenco. */
.mm-track-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding-top: clamp(1rem, 2vw, 1.4rem);
  border-top: 1px solid var(--glass-border);
}

.mm-track-tags span {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 0.35rem 0.8rem;
  transition: color var(--transition-base), border-color var(--transition-base);
}

.mm-track:hover .mm-track-tags span {
  color: var(--text-primary);
  border-color: rgba(139, 92, 246, 0.35);
}

@media (max-width: 900px) {
  /* La meta torna accanto al titolo quando la card non e' piu' abbastanza
     larga perche' spingerla a destra si legga come allineamento invece che
     come distacco. */
  .mm-track-meta {
    margin-left: 0;
  }
}

@media (max-width: 640px) {
  /* Sotto i 640px il numerale resterebbe piu' largo dello spazio libero a
     sinistra del testo: si rimpicciolisce e il rientro del corpo si
     riduce, mantenendo comunque la sovrapposizione (il numerale resta
     dietro, non sopra al testo). */
  .mm-track {
    padding: 1.75rem 1.25rem 1.5rem;
  }

  .mm-track-index {
    font-size: 4.5rem;
    opacity: 0.34;
  }

  .mm-track-body {
    margin-left: 1.75rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mm-track {
    transition: none;
  }

  /* Con "riduci movimento" mm-animations.js non aggancia nemmeno i
     listener di scroll, quindi le variabili di parallasse restano al loro
     default 0px - questo azzeramento e' la rete di sicurezza per il caso
     in cui la preferenza cambi a pagina gia' aperta (le variabili
     restano scritte sugli elementi). */
  .mm-track-index,
  .mm-track-body,
  .mm-track-art,
  .mm-track::after {
    transform: none !important;
  }

  /* Il loop delle illustrazioni e' movimento puramente decorativo: con
     "riduci movimento" resta la scena, ferma. */
  .mm-track-art .mm-iso-solid,
  .mm-track-art .mm-iso-line {
    animation: none !important;
  }
}

/* Titolo "SELECTED PROJECTS" di riserva (mm-animations.js:
   initIntroTracks, ramo di fallback) - stesso trattamento del titolo nativo
   ".mm-page-heading-label" ma con margini/colore propri, dato che non vive
   dentro la struttura .column-content di Semplice da cui quella regola
   eredita font-family/colore. */
.mm-page-heading-fallback {
  display: block;
  font-family: var(--font-mono);
  color: var(--text-primary);
  text-transform: uppercase;
  margin: 0 0 1rem;
}

/* ==========================================================================
   5c. Elenco progetti (mm-animations.js: initProjectList) - card impilate
   verticalmente, niente trascinamento/rotazione 3D.
   Effetto di scorrimento rifatto il 2026-09-04: l'immagine NON si muove
   piu' (la card art e' un frame 16:10 in uno slot 16:10 e va vista intera),
   niente piu' sfocatura/attenuazione/rimpicciolimento delle card fuori
   centro. Restano due movimenti piccoli e continui, calcolati in JS dalla
   posizione della card rispetto al centro del viewport: la card intera
   (--mm-plist-drift, ±14px) e il blocco testo (--mm-plist-drift-text,
   ±6px, verso opposto). La comparsa e' una dissolvenza per singola card
   (.mm-project-card-in). Motivazioni per esteso nel commento sopra
   MM_PLIST_DRIFT_RANGE in mm-animations.js. */
.mm-project-list-block {
  padding-top: clamp(1.5rem, 4vw, 3rem) !important;
  padding-bottom: clamp(2rem, 5vw, 4rem) !important;
}

.mm-project-list {
  display: flex;
  flex-direction: column;
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

.mm-project-card {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 3rem);
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--glass-bg), var(--glass-bg-end));
  /* "Premium": ombra ambiente sempre presente (prima solo in hover), non
     solo sfondo/bordo in vetro - da' alle card un distacco/peso reale sullo
     sfondo invece di restare "piatte" fino al passaggio del mouse. */
  box-shadow: 0 20px 60px -28px rgba(0, 0, 0, 0.55);
  padding: clamp(1.25rem, 2.4vw, 1.85rem);
  /* La comparsa e' una sola dissolvenza; il MOVIMENTO viene dalla deriva
     continua qui sotto, aggiornata a ogni frame dal rAF. Deliberatamente
     nessuna transizione su transform: se ci fosse, ogni aggiornamento della
     deriva partirebbe una transizione nuova e il movimento resterebbe
     indietro rispetto allo scroll. */
  opacity: 0;
  transform: translateY(var(--mm-plist-drift, 0px));
  will-change: transform;
  transition: opacity 0.7s ease,
    border-color var(--transition-base), background var(--transition-base),
    box-shadow var(--transition-base);
}

.mm-project-card.mm-project-card-in {
  opacity: 1;
}

.mm-project-card:hover {
  border-color: rgba(139, 92, 246, 0.45);
  background: linear-gradient(160deg, var(--glass-bg-hover), var(--glass-bg-end-hover));
  box-shadow: 0 24px 70px -24px var(--accent-glow);
}

/* alternanza immagine sinistra/destra, solo da desktop in su - stesso
   linguaggio "case study" gia' in uso in altre parti del sito */
@media (min-width: 761px) {
  .mm-project-list .mm-project-card:nth-child(even) {
    flex-direction: row-reverse;
  }
}

.mm-project-card-media {
  flex: 0 0 min(52%, 600px);
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-md);
  overflow: hidden;
  position: relative;
  display: block;
}

.mm-project-card-media img {
  /* Nessun overscan e nessuna traslazione: la card art e' un frame 16:10
     dentro uno slot 16:10, quindi combacia esattamente e si vede intera.
     Il 136% + parallasse di prima esisteva solo per poter muovere
     l'immagine, e ritagliava composizioni fatte per riempire il frame. */
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.mm-project-card-info {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  flex: 1;
  /* Secondo livello: contro-movimento piu' piccolo e di verso opposto
     rispetto alla deriva della card - vedi il commento in mm-animations.js. */
  transform: translateY(var(--mm-plist-drift-text, 0px));
  will-change: transform;
}

.mm-project-card-brand {
  color: var(--accent-light);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.mm-project-card-title {
  color: var(--text-primary);
  font-family: var(--card-title-font);
  font-weight: var(--card-title-weight);
  font-size: var(--card-title-size);
  letter-spacing: var(--card-title-tracking);
  line-height: var(--card-title-line);
  text-transform: none;
}

.mm-project-card-desc {
  color: var(--text-secondary);
  font-family: var(--font-body);
  line-height: 1.55;
}

.mm-project-card-cta {
  display: inline-block;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin-top: 0.3rem;
  transition: transform var(--transition-base);
}

.mm-project-card:hover .mm-project-card-cta {
  transform: translateX(4px);
}

@media (max-width: 760px) {
  .mm-project-card {
    flex-direction: column;
    align-items: stretch;
  }

  .mm-project-card-media {
    flex-basis: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mm-project-card {
    transition: none;
  }

  .mm-project-card-media img,
  .mm-project-card-info,
  .mm-project-card {
    transform: none !important;
  }

  .mm-project-card {
    opacity: 1 !important;
    filter: none !important;
  }
}

/* Link inline dentro paragrafi (es. "@Swydo" nella pagina About) - senza
   questa regola restano nel blu di default del tema padre Semplice
   (frontend.min.css ha una sua regola "a { color: ... }" con la nostra
   stessa specificita' - vince per ordine di caricamento, dopo il nostro
   CSS - bug trovato in locale, 2026-09-01). Specificita' piu' alta invece
   di !important per non toccare i link di nav/bottoni, che hanno gia' i
   loro colori espliciti. */
.content-block .column-content[data-module="text"] .is-content a {
  color: var(--accent-light);
  text-decoration: underline;
  text-decoration-color: rgba(167, 139, 250, 0.35);
  text-underline-offset: 0.15em;
  transition: color var(--transition-fast), text-decoration-color var(--transition-fast);
}

.content-block .column-content[data-module="text"] .is-content a:hover {
  color: var(--text-primary);
  text-decoration-color: var(--accent-light);
}

/* ==========================================================================
   6. Titoli generici (pagine interne: About, case study, ecc.)
   ========================================================================== */
h1, h2, h3,
.column-content[data-module="text"] .is-content h1,
.column-content[data-module="text"] .is-content h2,
.column-content[data-module="text"] .is-content h3 {
  font-family: var(--font-display) !important;
  color: var(--text-primary) !important;
}

/* Intestazione di pagina coerente sulle 3 pagine principali (Projects/Home,
   About, Logos) - classe assegnata da mm-animations.js (initPageHeadings),
   oggi solo a "SELECTED PROJECTS" (ABOUT/MARCO e LOGOFOLIO sono usciti da
   questo elenco, vedi sezione 4 - ricevono il trattamento hero grande).
   Dimensione allineata a .mm-timeline-heading (EXPERIENCE/EDUCATION nella
   pagina About, qui sotto) su richiesta esplicita di Marco, 2026-09-02 -
   32px non aveva piu' un riferimento coerente col resto del sito una volta
   che ABOUT/MARCO e LOGOFOLIO sono passati al trattamento hero. !important
   necessario per battere il font-size inline che il builder Semplice
   scrive su ogni paragrafo. */
.mm-page-heading-label {
  font-size: 1.15rem !important;
  font-weight: 400 !important;
  letter-spacing: 1.6px !important;
  line-height: 1.25 !important;
}

/* ==========================================================================
   7. Bottoni ("View project", "Email", "LinkedIn", ecc.) - vetro + gradiente in hover
   ========================================================================== */
/* BUG REALE trovato in locale (2026-09-04, pagina Contact): i bottoni
   "LinkedIn"/"Instagram" (mm_dark_child_contact_page_markup(), markup
   nostro non creato nel builder Semplice - vedi nota li' sul perche')
   apparivano con uno sfondo GIALLO acceso invece del vetro viola atteso.
   Causa reale, isolata via elementsFromPoint() sull'esatto pixel del
   bottone: non e' l'<a> (il suo background risultava gia' corretto, viola
   trasparente al 6%) ma il suo GENITORE ".is-content" - il tema padre
   (frontend.min.css) ha una regola generica ".is-content{background-color:
   #ffd300;cursor:pointer}" con NESSUNO scoping, quasi certamente pensata
   per lo stato "modulo cliccabile per modificarlo" dentro l'editor visuale
   di Semplice, mai per il frontend reale. Su ogni bottone creato DAVVERO
   nel builder questo sfondo giallo di base viene sempre sovrascritto da un
   <style> generato per-pagina (stesso meccanismo, con la stessa causa alla
   radice, gia' documentato sopra per bordo/raggio) - i nostri bottoni,
   costruiti a mano, non hanno mai quel <style> e ricadono quindi sul giallo
   grezzo del tema padre. Il 6% di opacita' del nostro sfondo viola lo
   lasciava trasparire quasi interamente. Fix: transparent esplicito sul
   div ".is-content" stesso (non solo sull'<a> dentro), scoped a ".ce-button"
   per non toccare le altre ".is-content" (i moduli di testo, es. il titolo
   "CONTACT", che non hanno questo problema). */
.ce-button .is-content {
  background: transparent !important;
}

/* !important su border/border-radius/background: Semplice genera CSS per-
   pagina con selettori per ID (es. "#content-holder .ce-button .is-content a"
   e persino uno specifico per elemento "#content-470 #content_d29682440
   .is-content a { border-radius: 0rem }") che batte la nostra specificita'
   a sole classi e azzerava bordo/raggio dei bottoni "Email"/"Download my CV"
   ecc. nella pagina About - bug trovato in locale, 2026-09-01. */
.ce-button .is-content a,
.mm-footer-cta {
  display: inline-block;
  padding: 0.6em 1.75em !important;
  font-family: var(--font-mono) !important;
  font-size: 0.8rem !important;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--glass-border) !important;
  border-radius: var(--radius-lg) !important;
  background: var(--glass-bg) !important;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--text-primary) !important;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}

.ce-button .is-content a:hover,
.mm-footer-cta:hover {
  border-color: var(--accent) !important;
  background: linear-gradient(120deg, var(--accent-dim), rgba(167, 139, 250, 0.12)) !important;
  color: var(--accent-light) !important;
  box-shadow: 0 0 24px -8px var(--accent-glow);
}

/* 7b. Tag di categoria nelle pagine progetto (mm-animations.js,
   initTagChips - riconosciuti dalla struttura: 2+ moduli bottone
   consecutivi senza testo in mezzo, es. "UI project"/"UX project" sotto
   "SLIGRO"). Stesso componente bottone ma trattamento piu' leggero: niente
   blur/bordo/sfondo pieno, solo testo mono discreto con un bordo sottile -
   una vera etichetta, non un secondo CTA (segnalato da Marco: "troppo
   effetto vetro"). */
.ce-button .is-content a.mm-tag-chip {
  padding: 0.35em 0.9em !important;
  font-size: 0.7rem !important;
  border-color: var(--border-subtle) !important;
  background: transparent !important;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--text-secondary) !important;
}

.ce-button .is-content a.mm-tag-chip:hover {
  border-color: rgba(139, 92, 246, 0.35) !important;
  background: rgba(139, 92, 246, 0.06) !important;
  color: var(--accent-light) !important;
  box-shadow: none;
}

/* ==========================================================================
   8. Footer ("GET IN TOUCH"). In homepage e' anche l'ultimo .content-block,
   ma nella pagina About "GET IN TOUCH" NON e' l'ultimo blocco (Experience/
   Education vengono dopo). Selettore basato SOLO sulla classe assegnata da
   initSectionMarkers() (mm-animations.js), che riconosce la sezione dal
   testo reale invece che dalla posizione - :last-of-type c'era anche qui in
   OR fino al 2026-09-03 (funzionava su Home, dove "GET IN TOUCH" e' anche
   l'ultimo blocco) ma su About colpiva silenziosamente EDUCATION (il vero
   ultimo blocco li'), forzando testo/colore del footer anche sul titolo
   delle card Education - bug reale trovato allineando il font delle card
   Education a quelle Experience (il titolo restava Inter invece di DM Mono
   nonostante la regola dedicata, proprio per questa fuoriuscita). Rimosso:
   .mm-section-get-in-touch da solo basta gia' su ENTRAMBE le pagine (la
   classe si assegna per testo, non per posizione), quindi :last-of-type
   non serviva comunque a niente che l'altra regola non coprisse gia'.
   ========================================================================== */
.content-block.mm-section-get-in-touch {
  border-top: 1px solid var(--border-subtle);
}

/* Logo del footer ingrandito (richiesta esplicita di Marco, 2026-09-04):
   prima 85x18.7px, la dimensione "originale" del file SVG stesso (nessuna
   regola dedicata lo controllava - data-width="original" nel builder,
   quindi width/height del file vincevano) - troppo piccolo per leggersi
   come il primo livello della gerarchia del footer (logo -> GET IN TOUCH
   -> copyright). clamp() invece di un valore fisso: resta proporzionato
   anche su schermi stretti, dove il container si restringe parecchio. */
.content-block.mm-section-get-in-touch .column-content[data-module="image"] img {
  width: clamp(140px, 15vw, 190px);
  height: auto;
}

/* Il file e' bianco pieno (New_logo_white.svg, pensato per lo sfondo
   scuro) - invisibile/a bassissimo contrasto sullo sfondo quasi bianco
   del tema chiaro (--bg-primary: #faf9fc). Stesso trattamento gia' usato
   altrove nel progetto per lo stesso problema (logo della navbar, loghi
   "_black.svg" nella pagina Logos): invertito solo quando il tema chiaro
   e' attivo. */
:root[data-theme="light"] .content-block.mm-section-get-in-touch .column-content[data-module="image"] img {
  filter: invert(1);
}

.content-block.mm-section-get-in-touch .column-content[data-module="text"] .is-content span {
  color: var(--text-secondary) !important;
  /* font body standard (Inter), non mono - richiesta esplicita di Marco,
     2026-09-02: questa regola ormai colpisce solo il paragrafo body del
     footer ("If you'd like to discuss..."), non piu' anche l'intestazione
     "GET IN TOUCH"/"CONTACTS" (estratta a parte da initFooterHeadings(),
     vedi .mm-footer-heading qui sotto, che resta invece in mono). */
  font-family: var(--font-body) !important;
}

/* 8-heading. Etichette "GET IN TOUCH"/"CONTACTS" (mm-animations.js,
   initFooterHeadings - div pulito iniettato al posto del modulo originale,
   stessa tecnica di .mm-timeline-heading qui sotto). Senza questa regola
   ricadevano nella dimensione ~32px generata da Semplice per il vecchio
   design chiaro (classe "style_xxxxx" imprevedibile) invece dei 20.7px del
   mockup, e nel colore text-secondary della regola qui sopra (pensata per
   il paragrafo, non per l'intestazione) invece del bianco pieno. */
.mm-footer-heading {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  letter-spacing: 0.06em;
  color: var(--text-primary);
  /* "GET IN TOUCH" e' gia' in maiuscolo nel contenuto originale, "Contacts"
     no (solo iniziale) - forzato qui per coerenza visiva con le altre 3
     etichette di sezione (EXPERIENCE/EDUCATION/GET IN TOUCH), tutte in
     caps nel mockup. */
  text-transform: uppercase;
}

/* Gerarchia verticale del footer (richiesta esplicita di Marco,
   2026-09-04: logo, "GET IN TOUCH" e le righe di copyright devono leggersi
   come 3 livelli chiaramente separati, non un blocco unico appiccicato).
   BUG TROVATO sistemando questo: la vecchia regola qui (margin-left:2.5rem
   sulla colonna GET IN TOUCH, pensata per staccarla da una colonna
   PORTFOLIO/copyright ACCANTO) sommata alla larghezza delle due colonne
   (data-xl-width="6" ciascuna, meta' del container) superava lo spazio
   disponibile nella riga - "row" di Semplice ha flex-wrap:wrap, quindi le
   due colonne finivano comunque impilate verticalmente invece che
   affiancate, rendendo quel margin-left un semplice disallineamento
   orizzontale senza scopo (verificato in locale su Home a 1440px).
   Sostituito con margine VERTICALE, coerente con l'impilamento reale:
   spazio sotto il logo (separazione dal blocco CTA) e sopra la colonna
   PORTFOLIO/copyright (separazione dal blocco CTA sopra), scoping
   invariato su :has(), marcatori creati da initFooterActions(). */
.content-block.mm-section-get-in-touch .column:has(.column-content[data-module="image"]) {
  margin-bottom: 2rem;
  /* La colonna del logo ha "data-xl-width=1" (1/12 della riga nel builder
     originale, pensato per un logo piccolo) - Semplice fissa
     width/max-width/flex-basis tutti a quell'8.33% via
     "[data-xl-width='1']{width:...;max-width:...;flex-basis:...}"
     (frontend.min.css), che continuava a schiacciare l'immagine a ~85px
     anche dopo aver alzato il suo width in CSS (max-width:100% ereditato
     lungo la catena .ce-image/.column-content si appoggia alla larghezza
     REALE della colonna, non a quella che vorremmo dare all'immagine) -
     bug trovato in locale, 2026-09-04, aumentando la dimensione del logo.
     Libera la colonna dalla griglia a 12 invece di continuare a inseguire
     il max-width lungo la catena di elementi discendenti. */
  width: auto !important;
  max-width: none !important;
  flex-basis: auto !important;
}

.content-block.mm-section-get-in-touch .column:has(.mm-footer-actions) {
  margin-bottom: 2.5rem;
}


/* 8a. Bottoni Email/LinkedIn: due .column-content[data-module="button"]
   fratelli, block di default con width:100% (il tema padre lo fissa con
   "#content-holder .content-block .column .content-wrapper .column-content
   {width:100%}", un selettore con un ID che batte qualsiasi nostra regola a
   sole classi senza !important) -> ognuno occupa tutta la riga, impilati
   verticalmente. Risolto in JS (mm-animations.js, initFooterActions)
   spostando i due bottoni dentro un wrapper dedicato (.mm-footer-actions)
   con un vero flex in riga; il width:100% ereditato viene neutralizzato con
   !important cosi' ciascun bottone si restringe al contenuto invece di
   riempire la riga - altrimenti anche dentro un flex container ciascuno
   reclama comunque il 100% della riga e va a capo da solo. */
.mm-footer-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
}

.mm-footer-actions > .column-content[data-module="button"] {
  width: auto !important;
}

/* ==========================================================================
   8b. Footer globale (mm-animations.js: initGlobalFooter). Le pagine senza
   un blocco "GET IN TOUCH"/"CONTACTS" costruito a mano nel builder (Logos,
   ogni pagina progetto) restavano senza alcun footer - richiesta esplicita
   di Marco (2026-09-04) che lo stesso footer compaia in fondo a OGNI
   pagina, "come una stringa sottile di elementi". Costruito in JS con
   markup proprio (non un clone del blocco Semplice, che varia pagina per
   pagina - About ha anche CV/Instagram) - stessa identita' visiva del
   footer nativo (stessa classe .mm-footer-heading per il titolo, stessa
   .mm-footer-cta/.mm-footer-actions per i bottoni, condivise con le
   regole della sezione 7/8 sopra).

   Prima versione: singola colonna centrata (logo, GET IN TOUCH, bottoni,
   portfolio, copyright tutti impilati). Rivista su richiesta di Marco
   (2026-09-04, dopo aver visto uno screenshot reale) per ridurre
   l'altezza: 2 colonne affiancate, logo+portfolio+copyright a sinistra
   (un'unica "voce" identitaria/legale), GET IN TOUCH+bottoni a destra (il
   CTA) - stesso contenuto, meta' dell'altezza. flex-wrap:wrap per tornare
   a impilate su schermi stretti (mobile), dove 2 colonne affiancate non
   avrebbero spazio per respirare.

   Struttura esterno/interno (richiesta esplicita di Marco, 2026-09-04:
   "make sure the footer and the header have width 100% but respect the
   given padding"): PRIMA il max-width:1440px viveva sullo stesso elemento
   del border-top, quindi su schermi piu' larghi di 1440px+padding il
   bordo/sfondo si fermava al centro invece di arrivare bordo a bordo.
   Struttura ora replicata dalla navbar: ".mm-global-footer" (fuori) a
   piena larghezza con bordo/sfondo, ".mm-global-footer-inner" (dentro)
   col solo padding, dove vive tutto il resto.

   NESSUN max-width sull'interno (aggiornamento dello stesso giorno, dopo
   aver confrontato header e footer sul sito LIVE): la navbar li' usa
   ".container-fluid" (width:100% senza alcun cap - un dettaglio della
   navbar reale non visibile testando solo in locale, dove il tipo di
   navbar puo' differire) - un max-width:1440px qui avrebbe reso il
   footer piu' STRETTO della navbar invece che della stessa larghezza.
   Tolto: resta fluido come la navbar, stesso padding di base. */
.mm-global-footer {
  width: 100%;
  border-top: 1px solid var(--border-subtle);
}

.mm-global-footer-inner {
  padding: 3rem 1.66667rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.mm-global-footer-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85rem;
}

.mm-global-footer-logo {
  width: clamp(120px, 12vw, 160px);
  height: auto;
}

:root[data-theme="light"] .mm-global-footer-logo {
  filter: invert(1);
}

.mm-global-footer .mm-footer-actions {
  width: auto;
}

.mm-global-footer-meta p {
  margin: 0;
  color: var(--text-secondary);
  font-family: var(--font-body);
}

.mm-global-footer-portfolio {
  font-family: var(--font-mono) !important;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.85rem;
  margin-bottom: 0.35rem !important;
}

.mm-global-footer-copyright {
  font-size: 0.78rem;
}

/* ==========================================================================
   8c. Pagina About: voci "EXPERIENCE"/"EDUCATION" allineate allo stile a
   card delle "SELECTED PROJECTS" (mm-animations.js, initTimelineSections) -
   stessa identita' visiva (bordo glass, linea sfumata in cima, hover) ma
   senza il fold/apri-chiudi, dato che qui il testo e' gia' breve.
   ========================================================================== */
.mm-timeline-heading {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  letter-spacing: 0.06em;
  color: var(--text-primary);
  margin-bottom: 1.5rem;
  width: 100%;
  flex: 1 1 100%;
}

.mm-timeline-block .row {
  display: flex;
  flex-direction: column;
}

/* Gap tra le card Education (24px nel mockup, gap-[24px] sul contenitore,
   nodo 11664:5167) messo sulla ROW (margin-top, non sulla card via
   margin-bottom): il contenitore Semplice qui sopra e' un flex row con
   wrap, una card per riga - il margin-bottom su .mm-timeline-col (dentro
   una .row a sua volta flex-column) non arrivava a produrre spazio reale
   tra le righe wrappate (verificato in locale, 2026-09-02: con
   margin-bottom la riga successiva restava comunque attaccata, un
   margin-top sulla riga stessa invece sposta correttamente). Escluso
   .mm-timeline-experience, che usa gia' .mm-timeline-track con margin
   zero apposta (le card alternate sinistra/destra dell'Experience si
   toccano nel mockup, vedi sezione 8d).
   !important necessario: il tema padre ha "#content [data-gutter="no"]
   .row, ... { margin: 0 }" - selettore con ID, batte qualsiasi nostra
   regola a sole classi indipendentemente dall'ordine nel file (bug trovato
   in locale, 2026-09-02: senza !important la card restava comunque
   attaccata alla precedente). */
.mm-timeline-block:not(.mm-timeline-experience) .row + .row {
  margin-top: 24px !important;
}

.mm-timeline-col {
  flex: 0 0 100% !important;
  max-width: 100% !important;
  width: 100% !important;
  position: relative;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background-color: var(--bg-primary) !important;
  background-image: linear-gradient(160deg, var(--glass-bg), var(--glass-bg-end));
  padding: 1.5rem;
  overflow: hidden;
  transition: border-color var(--transition-base), background-color var(--transition-base), box-shadow var(--transition-base);
}

/* Il padding qui sopra (1.5rem) viene battuto silenziosamente da Semplice:
   ogni card ha il proprio ID univoco (es. "#column_puwc0m6zb") e il tema
   genera per ognuna una regola CSS per-pagina con quell'ID (es.
   "#content-470 #column_puwc0m6zb { padding-top: 1.77778rem;
   padding-bottom: 0.888889rem }", residuo dei valori impostati a mano da
   Marco card per card nel vecchio design chiaro) - un selettore per ID
   batte le nostre classi indipendentemente da dove viene caricato nel
   documento (bug trovato in locale, 2026-09-02, card per card leggermente
   diverse l'una dall'altra). !important forza lo stesso padding ovunque,
   coerente col mockup: 24px uniformi per Education, 32/15/16 per
   Experience (vedi override dedicato piu' sotto). */
.mm-timeline-block:not(.mm-timeline-experience) .mm-timeline-col {
  padding: 24px !important;
}

.mm-timeline-experience .mm-timeline-col {
  padding: 24px !important;
}

.mm-timeline-col::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent) 30%, var(--accent-light) 70%, transparent);
  opacity: 0.7;
}

.mm-timeline-col:hover {
  border-color: rgba(139, 92, 246, 0.45);
  background: linear-gradient(160deg, var(--glass-bg-hover), var(--glass-bg-end-hover));
  box-shadow: 0 8px 40px -12px var(--accent-glow);
}

/* 8c-text. Testo delle card Education: titolo/data/descrizione ereditavano
   il font Inter e il colore text-secondary (55%) dal contenuto WordPress
   originale (autore Marco, mai differenziato per riga li' - a differenza
   di Experience, dove il testo originale aveva gia' colori/font diversi
   per titolo/data/descrizione).
   Il font-family "stesso di Experience" (richiesta esplicita di Marco,
   2026-09-03) NON e' un font unico: dentro le card Experience il titolo e'
   DM Mono (via la classe generata da Semplice sullo <span> del titolo,
   es. "style_cfi8ovt39" sul modulo "Senior Product Designer @Swydo") ma
   data/descrizione sono Inter - verificato sui leaf <span> (non sul <p>
   genitore, il cui font-family calcolato puo' differire da quello di un
   figlio con una regola piu' specifica) su tutte e 8 le voci Experience,
   stesso schema ovunque. Replicato qui identico: base Inter per
   tutto, poi il titolo (1o modulo) riportato a DM Mono - non un font
   unico uniforme (tentativo precedente, sbagliato: rendeva TUTTO Inter
   invece di rispecchiare lo split reale di Experience). Colore forzato
   esplicitamente via posizione (titolo poi data poi descrizione sono
   sempre, nell'ordine, i primi 3 moduli testo della card, verificato su
   tutte e 5 le voci Education in locale, 2026-09-02). */
.mm-timeline-block:not(.mm-timeline-experience) .mm-timeline-col p {
  font-family: var(--font-body) !important;
}

.mm-timeline-block:not(.mm-timeline-experience) .mm-timeline-col .column-content:nth-of-type(1) p {
  color: var(--text-primary) !important;
  font-family: var(--font-mono) !important;
}

.mm-timeline-block:not(.mm-timeline-experience) .mm-timeline-col .column-content:nth-of-type(2) p {
  color: var(--accent-light) !important;
}

.mm-timeline-block:not(.mm-timeline-experience) .mm-timeline-col .column-content:nth-of-type(3) p {
  color: var(--text-secondary) !important;
}

/* 8c-image. Card Education con certificato (Figma Academy, UX Design
   Institute, International English Test): nel markup Semplice originale
   titolo/data/descrizione/immagine sono 4 .column-content fratelli dentro
   lo STESSO .content-wrapper in flusso normale (display:block) - finivano
   quindi impilati uno sotto l'altro, immagine compresa a piena larghezza
   sotto il testo, invece che testo a sinistra/immagine a destra come nel
   mockup (segnalato da Marco con screenshot di confronto, 2026-09-02).
   I primi 3 moduli (titolo/data/descrizione) vengono raggruppati in un
   wrapper dedicato via JS (mm-animations.js, initEducationImageCards ->
   .mm-timeline-text-group) invece di restare fratelli piatti dell'immagine:
   un CSS Grid con l'immagine su grid-row:1/span 3 (primo tentativo) distribuiva
   l'altezza intrinseca dell'immagine (~400px) sulle 3 righe implicite anche
   con grid-auto-rows:min-content, gonfiandole ben oltre l'altezza reale del
   testo - risultato, righe separate da un salto di ~100px invece di stare
   vicine come nel mockup (gap-[2px] sul contenitore "Text", segnalato da
   Marco con screenshot, 2026-09-02). Un flex a 2 soli figli (wrapper testo +
   immagine) non ha questo problema: ciascuno si dimensiona sul proprio
   contenuto, indipendente dall'altro. */
.mm-timeline-block:not(.mm-timeline-experience) .content-wrapper:has(> .mm-timeline-text-group) {
  display: flex;
  column-gap: 8px;
  align-items: start;
}

.mm-timeline-text-group {
  display: flex;
  flex-direction: column;
  row-gap: 2px;
  flex: 1 1 0%;
  min-width: 0;
}

.mm-timeline-block:not(.mm-timeline-experience) .content-wrapper:has(> .mm-timeline-text-group) > .column-content[data-module="image"] {
  flex: 1 1 0%;
  min-width: 0;
}

.mm-timeline-block:not(.mm-timeline-experience) .content-wrapper:has(> .mm-timeline-text-group) > .column-content[data-module="image"] img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius-md);
}

/* Sotto i 700px lo split 50/50 testo/certificato qui sopra (flex:1 1 0% su
   entrambi) lascia al testo solo ~135-140px reali (verificato in locale,
   sanity check mobile 2026-09-03) - abbastanza stretto da spezzare a meta'
   parola titoli lunghi come "International English Test" (diventava
   "Internation" / "al English" / "Test", card EDUCATION su About). Il
   certificato scende a una miniatura di larghezza fissa (stesso approccio
   gia' usato per i thumbnail delle card progetto in 5. qui sopra) cosi' il
   testo riprende la maggior parte della larghezza della card. */
@media (max-width: 700px) {
  .mm-timeline-block:not(.mm-timeline-experience) .content-wrapper:has(> .mm-timeline-text-group) > .column-content[data-module="image"] {
    flex: 0 0 96px;
    min-width: 0;
  }

  .mm-timeline-text-group {
    flex: 1 1 auto;
  }
}

/* ==========================================================================
   8d. Pagina About: "EXPERIENCE" come albero a timeline con le voci
   alternate a sinistra/destra di una linea centrale (richiesta esplicita di
   Marco - diverso dalla lista verticale di card usata per "EDUCATION", che
   resta invariata). Le card mantengono la stessa identita' vetro/gradiente
   di .mm-timeline-col qui sopra: cambia solo la disposizione, non lo stile.
   mm-animations.js (initTimelineSections) sposta ogni .row voce dentro
   .mm-timeline-track e alterna le classi mm-timeline-side-left/-right.
   ========================================================================== */
.mm-timeline-track {
  position: relative;
  padding: 0.5rem 0;
  /* ".container" di Semplice e' esso stesso un flex container - senza un
     width esplicito ".mm-timeline-track" (a differenza di ".row", che ha
     "width:100%" nel CSS del tema padre) si dimensiona sul CONTENUTO invece
     che sullo spazio disponibile, e con testo lungo che non va a capo
     dentro i flex item straripava oltre il viewport su mobile - bug trovato
     in locale, 2026-09-01. */
  width: 100%;
  flex: 1 1 100%;
}

.mm-timeline-track::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, transparent, var(--accent) 6%, var(--accent-light) 50%, var(--accent) 94%, transparent);
  opacity: 0.5;
  transform: translateX(-50%);
}

/* Nessun gap tra una voce e la successiva (margin-bottom: 0, non 2rem come
   prima) - confrontando i valori esatti del mockup Figma (nodo 11664:5167,
   2026-09-02) i "Container" di ogni voce si impilano uno sull'altro senza
   spazio (es. il primo alto 202.48px finisce a y=211.48, il secondo inizia
   esattamente li'): le card restano comunque separate visivamente perche'
   alternano lato sinistro/destro, non serve margine aggiuntivo - il 2rem
   precedente allungava la sezione EXPERIENCE ben oltre l'altezza del
   mockup (Marco: "spacing tra le card non corrisponde al design"). */
.mm-timeline-experience .mm-timeline-track .row {
  display: flex !important;
  flex-direction: row !important;
  position: relative;
  margin-bottom: 0;
}

/* pallino sulla linea centrale, allineato verticalmente al centro della
   card (indipendente dalla sua altezza, che varia voce per voce) */
.mm-timeline-track .row::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--bg-primary);
  border: 2px solid var(--accent-light);
  box-shadow: 0 0 14px -2px var(--accent-glow);
  transform: translate(-50%, -50%);
  z-index: 1;
}

.mm-timeline-experience .mm-timeline-col {
  flex: 0 0 calc(50% - 2.5rem) !important;
  max-width: calc(50% - 2.5rem) !important;
  width: calc(50% - 2.5rem) !important;
  margin-bottom: 0 !important;
}

.mm-timeline-experience .mm-timeline-side-left {
  margin-right: auto !important;
}

.mm-timeline-experience .mm-timeline-side-right {
  margin-left: auto !important;
}

/* sotto i ~700px l'alternanza sinistra/destra non ha piu' spazio per
   respirare: la timeline collassa su una sola colonna, linea e pallini
   spostati sul bordo sinistro invece che al centro. */
@media (max-width: 700px) {
  .mm-timeline-track::before {
    left: 10px;
  }

  .mm-timeline-track .row::before {
    left: 10px;
  }

  .mm-timeline-experience .mm-timeline-col,
  .mm-timeline-experience .mm-timeline-side-left,
  .mm-timeline-experience .mm-timeline-side-right {
    flex: 0 0 calc(100% - 2.5rem) !important;
    max-width: calc(100% - 2.5rem) !important;
    width: calc(100% - 2.5rem) !important;
    margin-left: 2.5rem !important;
    margin-right: 0 !important;
  }
}

/* ==========================================================================
   9. Pagina Logos: gli SVG sono neri (disegnati per sfondo chiaro) - via
   il pattern del filename (tutti "*_black.svg"), non tocca le altre
   immagini del sito (mockup progetti ecc.). L'invert va applicato SOLO nel
   tema scuro (2026-09-03, aggiunto col tema chiaro): sono gia' neri su
   sfondo chiaro - "disegnati per sfondo chiaro", come dice il commento
   originale sopra - quindi nel tema chiaro vanno mostrati cosi' come sono;
   nel tema scuro vanno invertiti a bianco per restare leggibili, come
   sempre. Senza questa guardia diventerebbero bianco su bianco (invisibili)
   appena introdotto il tema chiaro.
   ========================================================================== */
:root:not([data-theme="light"]) img[src*="_black.svg"] {
  filter: invert(1) brightness(1.3);
  transition: filter var(--transition-fast), opacity var(--transition-fast);
}

:root:not([data-theme="light"]) img[src*="_black.svg"]:hover {
  filter: invert(1) brightness(1.3) drop-shadow(0 0 12px var(--accent-glow));
}

img[src*="_black.svg"] {
  transition: filter var(--transition-fast), opacity var(--transition-fast);
}

:root[data-theme="light"] img[src*="_black.svg"]:hover {
  filter: drop-shadow(0 0 12px var(--accent-glow));
}

/* ==========================================================================
   10b. Back-to-top - elemento nativo del tema padre (freccia SVG fissa in
   basso a destra su ogni pagina), non nostro - fino ad ora solo restilizzato
   qui per il tema scuro (chip di vetro, fill chiaro sull'SVG). Rimosso
   GLOBALMENTE su richiesta esplicita di Marco, 2026-09-04 - piu' semplice e
   piu' sicuro nasconderlo via CSS che toccare il markup del tema padre
   (nessun file PHP suo da modificare, reversibile con una riga se dovesse
   servire di nuovo). display:none invece di visibility/opacity: il tema
   padre lo tiene comunque fixed sopra il contenuto, non deve restare nel
   flusso ne' intercettare click anche se invisibile. */
.back-to-top {
  display: none !important;
}

/* ==========================================================================
   11. Cookie banner - piccolo, in basso a sinistra, stesso linguaggio
   visivo delle card/bottoni (glass + bordo sottile + accento viola in
   hover), non un banner a tutta larghezza. Creato una sola volta via JS
   (mm-animations.js, initCookieConsent, chiamata da boot() non da
   runInit() - non deve ricomparire ad ogni navigazione AJAX), nascosto in
   automatico e per sempre (localStorage) dopo il primo click su "Accetta".
   ========================================================================== */
.mm-cookie-banner {
  position: fixed;
  left: 1.5rem;
  bottom: 1.5rem;
  z-index: 9500;
  max-width: 320px;
  padding: 1rem 1.125rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  background: var(--bg-elevated);
  background-image: linear-gradient(160deg, var(--glass-bg), transparent 70%);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 12px 32px -12px var(--shadow-soft);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--transition-slow), transform var(--transition-slow);
  pointer-events: none;
}

.mm-cookie-banner.mm-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.mm-cookie-banner p {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

.mm-cookie-banner-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.mm-cookie-banner-accept {
  display: inline-block;
  padding: 0.45em 1.25em;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-sm);
  background: var(--glass-bg);
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}

.mm-cookie-banner-accept:hover {
  border-color: var(--accent);
  background: var(--glass-bg-hover);
  color: var(--accent-light);
}

.mm-cookie-banner-dismiss {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--transition-fast);
}

.mm-cookie-banner-dismiss:hover {
  color: var(--text-primary);
}

@media (max-width: 500px) {
  .mm-cookie-banner {
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.75rem;
    max-width: none;
  }
}

/* ==========================================================================
   12. Selezione testo
   ========================================================================== */
::selection {
  background-color: var(--accent);
  color: var(--bg-primary);
}

/* ==========================================================================
   13. Fondo pagina progetto: barra Prev/Next (.semplice-next-prev) e griglia
   "Selected Works" (.project-panel, semplice_project_nav_html() in
   includes/helper/grid.php) - di default nel linguaggio chiaro originale del
   tema padre (sfondo bianco/grigio chiaro, testo nero), qui riportate al
   dark/glass/viola del resto del sito.

   mm-animations.js (initSelectedWorksSlider) trasforma .pp-thumbs in uno
   slider orizzontale a scorrimento quando i progetti pubblicati sono piu' di
   4, aggiungendo le frecce .mm-pp-prev/.mm-pp-next in un header accanto
   all'etichetta "Selected Works" - qui solo lo stile, la struttura la crea
   lo script (idempotente, marcatori .mm-pp-track/.mm-pp-slide/.mm-pp-header).
   Con 4 progetti o meno lo script marca comunque le stesse classi (stile
   card identico) ma non crea le frecce: non serve scorrere nulla.
   ========================================================================== */

/* 13a. Barra Prev/Next */
.semplice-next-prev {
  background: var(--bg-elevated) !important;
  border-top: 1px solid var(--border-subtle);
}

.semplice-next-prev .np-link {
  transition: background var(--transition-base);
}

.semplice-next-prev .np-link:hover {
  background: var(--glass-bg);
}

.semplice-next-prev .np-inner .np-link .np-label-above {
  color: var(--accent-light) !important;
  font-family: var(--font-mono) !important;
  letter-spacing: 0.08em !important;
}

.semplice-next-prev .np-inner .np-link .np-label {
  color: var(--text-primary) !important;
  font-family: var(--font-body) !important;
  transition: color var(--transition-fast);
}

.semplice-next-prev .np-inner .np-link:hover .np-label {
  color: var(--accent-light) !important;
}

.semplice-next-prev .nextprev-seperator {
  background: var(--border-subtle) !important;
}

/* 13b. "Selected Works" - etichetta + header con frecce */
.project-panel {
  background: var(--bg-primary) !important;
  border-top: 1px solid var(--border-subtle);
}

#content-holder .project-panel .panel-label {
  color: var(--text-secondary) !important;
  font-family: var(--font-mono) !important;
  text-transform: uppercase !important;
  letter-spacing: 0.08em !important;
  font-size: 0.8rem !important;
  margin: 0;
}

.mm-pp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.mm-pp-header .panel-label {
  padding-bottom: 0 !important;
}

.mm-pp-nav {
  display: flex;
  gap: 0.6rem;
  flex: 0 0 auto;
}

.mm-pp-arrow {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast), opacity var(--transition-fast);
}

.mm-pp-arrow svg {
  width: 1rem;
  height: 1rem;
  display: block;
}

.mm-pp-arrow:hover:not(:disabled) {
  border-color: var(--accent);
  background: linear-gradient(120deg, var(--accent-dim), rgba(167, 139, 250, 0.12));
  color: var(--accent-light);
}

.mm-pp-arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

/* 13c. Griglia/slider delle card - il tema padre genera .pp-thumbs come riga
   che va a capo (float/grid a larghezza fissa via attributi data-*-width);
   qui diventa una track flex a scorrimento orizzontale con scroll-snap,
   cosi' funziona anche via swipe touch senza JS aggiuntivo per il drag. */
.project-panel .pp-thumbs.mm-pp-track {
  display: flex;
  flex-wrap: nowrap;
  gap: 1.25rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  margin: 0 !important;
}

.project-panel .pp-thumbs.mm-pp-track::-webkit-scrollbar {
  display: none;
}

/* 4 card per vista su desktop (richiesta esplicita di Marco) */
.project-panel .pp-thumb.mm-pp-slide {
  scroll-snap-align: start;
  flex: 0 0 calc(25% - 0.9375rem) !important;
  max-width: calc(25% - 0.9375rem) !important;
  width: calc(25% - 0.9375rem) !important;
  padding: 0 !important;
}

@media (max-width: 1169px) {
  .project-panel .pp-thumb.mm-pp-slide {
    flex-basis: calc(33.333% - 0.834rem) !important;
    max-width: calc(33.333% - 0.834rem) !important;
  }
}

@media (max-width: 860px) {
  .project-panel .pp-thumb.mm-pp-slide {
    flex-basis: calc(50% - 0.625rem) !important;
    max-width: calc(50% - 0.625rem) !important;
  }
}

@media (max-width: 560px) {
  .project-panel .pp-thumb.mm-pp-slide {
    flex-basis: 82% !important;
    max-width: 82% !important;
  }
}

.project-panel .pp-thumb.mm-pp-slide > a {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.project-panel .pp-thumb.mm-pp-slide > a img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--transition-slow);
}

.project-panel .pp-thumb.mm-pp-slide:hover > a {
  border-color: rgba(139, 92, 246, 0.45);
  box-shadow: 0 8px 32px -10px var(--accent-glow);
}

.project-panel .pp-thumb.mm-pp-slide:hover > a img {
  transform: scale(1.06);
}

.project-panel .pp-title {
  padding: 0.9rem 0 0 0 !important;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.project-panel .pp-title a {
  font-family: var(--font-body) !important;
  font-size: 0.95rem !important;
  color: var(--text-primary) !important;
  text-transform: none !important;
  transition: color var(--transition-fast);
}

.project-panel .pp-thumb.mm-pp-slide:hover .pp-title a {
  color: var(--accent-light) !important;
}

.project-panel .pp-title span {
  font-family: var(--font-mono) !important;
  font-size: 0.7rem !important;
  color: var(--text-secondary) !important;
  text-transform: uppercase !important;
  letter-spacing: 0.05em !important;
}

/* ==========================================================================
   14. Pagina Contact (page-contact.php + mm_dark_child_contact_page_markup()
   in functions.php). Markup nostro, non del builder Semplice - vedi commento
   li' sul perche' - quindi il layout a due colonne (lista info + form) usa
   classi CSS proprie invece degli attributi data-xl-width del builder, che
   da soli non producono nessuna larghezza (nessun <style> per-pagina
   generato server-side per contenuto non creato nel builder).
   ========================================================================== */
/* BUG REALE trovato in locale (2026-09-03, segnalato da Marco: "should have
   the same container dimension of the other pages"): il ".container" (il
   box a 1440px, sezione 2b) risultava gia' identico su Contact e sulle
   altre pagine (verificato via getBoundingClientRect - stessi 1440px,
   stesso left/right) - il problema era piu' sotto, sulla ".column" dentro.
   Ipotesi iniziale sbagliata (vedi commento sopra, mai verificata davvero):
   che senza data-xl-width la ".column" ricadesse comunque su una larghezza
   100% di default. Verificato invece che NON esiste una regola generica
   ".column{width:100%}" nel tema padre applicabile qui - le uniche regole
   simili trovate sono scoped a contesti specifici (".featured-img-full
   .column", "...semplice-cover .column-pin-inner .column") che non
   riguardano questa pagina. Senza width/flex-basis espliciti, una ".column"
   e' un flex item con le proprieta' flex INIZIALI del browser
   (flex:0 1 auto) - si restringe al contenuto invece di riempire la riga.
   Su ogni altra pagina questo non si nota perche' Semplice genera un
   <style> per-pagina con la vera percentuale (dedotta da data-xl-width) per
   ogni ID di colonna - contenuto che qui non esiste, essendo nostro. Fix:
   larghezza esplicita, scoped a questa pagina per non toccare altrove. */
.mm-contact-page .column {
  width: 100%;
  max-width: 100%;
  flex: 1 1 100%;
}

/* Titolo "CONTACT": stessa classe (.mm-hero-name-solid) usata per "LOGOFOLIO"
   in Logos e per il nome progetto in ogni pagina progetto (sezione 4a) -
   font-family/peso/dimensione/letter-spacing/gradiente identici su tutte e
   3, invece di una classe/dimensione dedicata solo a questa pagina (bug
   segnalato da Marco: usava prima .mm-page-heading-label, la stessa
   dell'etichetta piccola "SELECTED PROJECTS" - un'altra classe di
   intestazione, non il titolo di pagina). Margine sotto per lo spazio prima
   della griglia info/form: la' dove About/Logos hanno un modulo
   .mm-hero-role/.mm-hero-bio successivo con gap naturale tra .column-content
   (vedi nota sezione 4a), qui il prossimo elemento e' .mm-contact-grid
   (nostro, non un modulo Semplice) - nessun gap naturale da cui ereditare,
   va aggiunto esplicitamente. */
.mm-contact-page .mm-hero-name-solid {
  margin-bottom: 3rem;
}

.mm-contact-page .column {
  /* Contesto di posizionamento per .mm-contact-whatsapp-badge qui sotto -
     non .mm-contact-grid (primo tentativo): top:0/right:0 li' cadeva
     sull'angolo del campo NAME del form, sovrapposto e illeggibile. Ancorato
     invece a .column (l'intera colonna di contenuto, eyebrow+titolo+griglia)
     il badge si posiziona nello spazio vuoto in alto a destra accanto al
     titolo "CONTACT", senza sovrapporsi a nulla - stessa idea del badge
     About, che occupa lo spazio libero accanto al nome invece di stare
     sopra un elemento interattivo. Scoped a .mm-contact-page: non deve
     toccare ".column" nelle altre pagine. */
  position: relative;
}

.mm-contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: 4rem;
  align-items: start;
}

@media (max-width: 900px) {
  .mm-contact-grid {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
}

.mm-contact-info-list {
  list-style: none;
  margin: 0 0 2rem 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.mm-contact-info-item {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--border-subtle);
}

.mm-contact-info-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.mm-contact-info-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.mm-contact-info-item a,
.mm-contact-info-item span:not(.mm-contact-info-label) {
  font-family: var(--font-body);
  font-size: 1.1rem;
  color: var(--text-primary);
  transition: color var(--transition-fast);
}

.mm-contact-info-item a:hover {
  color: var(--accent-light);
}

.mm-contact-info-links {
  display: flex;
  gap: 1.25rem;
}

/* Bottone WhatsApp -> stesso anello di testo 3D rotante del badge About
   (richiesta esplicita di Marco, 2026-09-03: "should become a circular 3D
   gif like the one in about with the chat on whatsapp text"), popolato in
   JS da buildTextRingMarkup() (mm-contact-form.js) dentro il link vuoto
   costruito qui in PHP (#mm-whatsapp-badge). Sostituisce il precedente
   bottone "pillola" in vetro con icona.

   Dimensione 150px (contro i 337px del badge About, un elemento decorativo
   grande accanto alla foto) - qui e' un elemento funzionale nel flusso
   della lista informazioni, va tenuto piu' contenuto. --mm-badge-radius e
   --mm-badge-perspective scalati in proporzione (337:105 circa come
   337:600, stesso rapporto qui sotto) cosi' la "profondita'" 3D percepita
   resta la stessa, non piu' piatta solo perche' il box e' piu' piccolo.

   position:absolute in alto a destra di .mm-contact-grid (richiesta
   esplicita di Marco, 2026-09-03: "move it to top right and tilt it of 30
   degrees anticlockwise") - .mm-contact-grid ha position:relative apposta
   per questo. rotate(-30deg): in CSS gli angoli positivi di rotate() sono
   orari, quindi antiorario e' un valore NEGATIVO. */
/* +50% su richiesta di Marco (2026-09-04): 150 * 1.5 = 225px. Raggio/
   prospettiva/font-size scalati dello stesso 1.5x (non solo il box) - vedi
   nota sopra sul perche' vanno tenuti proporzionali, altrimenti l'anello
   ingrandito leggerebbe piu' piatto (raggio invariato in un box piu'
   grande) invece che semplicemente piu' grande. */
.mm-contact-whatsapp-badge {
  --mm-badge-radius: 72px;
  --mm-badge-perspective: 405px;
  position: absolute;
  top: 0;
  right: 0;
  display: block;
  width: 225px;
  height: 225px;
  transform: rotate(-30deg);
  transition: transform var(--transition-fast);
}

.mm-contact-whatsapp-badge .mm-badge-word {
  font-size: 13.5px;
}

.mm-contact-whatsapp-badge:hover {
  transform: rotate(-30deg) scale(1.05);
}

/* Sotto i 900px (stesso breakpoint dove .mm-contact-grid collassa a una
   colonna sola) lo spazio vuoto accanto al titolo "CONTACT" da cui questo
   badge ha bisogno per stare in alto a destra senza sovrapporsi non c'e'
   piu' - verificato dal vivo: a 375px il badge finiva DIRETTAMENTE sopra il
   testo "CONTACT", illeggibile. Sotto quella soglia torna un elemento
   normale nel flusso (non ruotato, ne' assoluto), sotto la lista info come
   nel primissimo layout - stesso approccio del badge About
   (.mm-about-glass-badge, sezione 4a-badge), che sotto una certa larghezza
   smette di provare a stare "a fianco" e semplicemente non c'e' piu' spazio
   per l'effetto decorativo. */
@media (max-width: 900px) {
  .mm-contact-whatsapp-badge {
    position: static;
    transform: none;
    margin: 2rem 0 0;
  }

  .mm-contact-whatsapp-badge:hover {
    transform: scale(1.05);
  }
}

.mm-contact-form {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.mm-form-field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.mm-form-field label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.mm-form-field input,
.mm-form-field textarea {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--text-primary);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: 0.75em 1em;
  resize: vertical;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.mm-form-field input:focus,
.mm-form-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--glass-bg-hover);
}

/* Honeypot: campo nascosto visivamente ma presente nel DOM (nascosto con
   position:absolute fuori schermo, non display:none - alcuni bot ignorano i
   campi display:none quando decidono cosa compilare, vanificando la trappola). */
.mm-form-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.mm-form-submit {
  align-self: flex-start;
  padding: 0.7em 2em;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--text-primary);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}

.mm-form-submit:hover:not(:disabled) {
  border-color: var(--accent);
  background: linear-gradient(120deg, var(--accent-dim), rgba(167, 139, 250, 0.12));
  color: var(--accent-light);
  box-shadow: 0 0 24px -8px var(--accent-glow);
}

.mm-form-submit:disabled {
  opacity: 0.6;
  cursor: default;
}

.mm-form-status {
  font-family: var(--font-body);
  font-size: 0.9rem;
  min-height: 1.3em;
  margin: 0;
}

.mm-form-status-success {
  color: var(--accent-light);
}

.mm-form-status-error {
  color: #f87171;
}
