/* ============================================================
   COMPASS — one-pager
   Palette e tipografia da Compass Brand Directions.pdf
   ============================================================ */

:root {
  --blu: #1D36DA;
  --blu-scuro: #172CC8;
  --blu-tint: #E4E7FB;
  --porpora: #7C2D8A;
  --porpora-tint: #F4E9F6;

  /* Le tinte CARICHE (13 ago 2026). I due tint qui sopra sono così chiari che
     su una superficie grande il colore si legge come un'ombra, non come una
     scelta. Questi stanno più in basso di luminosità ma con più croma: sono
     scuriti verso il blu e il porpora di marca, MAI verso il grigio — è il
     grigio che li renderebbe opachi. Restano lucidi perché chi li usa ci
     appoggia sopra un riflesso bianco (vedi .method-card). */
  --blu-tint-forte: #B7BFF2;
  --porpora-tint-forte: #E3C9E9;
  /* Le VELATURE di sezione sono un gradino sotto le tinte piene: stanno sotto
     il testo corrente di intere sezioni, non dentro una card, quindi non
     possono prendere la stessa densità senza mangiarsi la leggibilità.
     Misurato: croma di fondo della pagina prima di questi valori — chi siamo
     28, per chi 13,6, hero 8,2, education 7,5, casi 5, metodo 3. Una sezione
     gridava e le altre sussurravano: è quello il "delicato". */
  --velo-blu: #C9D0F4;
  --velo-porpora: #E5CFEB;
  /* Il corpo del testo sulle tinte cariche: il --grigio non ci arriva più
     (2.74:1 su --blu-tint-forte, sotto la soglia di leggibilità). */
  --ink-su-tinta: #454C5E;
  /* Scurito il 13 ago 2026 da #6A7180. Il vecchio grigio passava a stento sul
     bianco (4,77:1) e FALLIVA su ogni velatura del sito (3,99 sul blu, 4,16 sul
     porpora): era sotto la soglia da prima che i colori si caricassero, e
     caricandoli sarebbe precipitato. Questo tiene 4,5 anche sulle velature
     nuove e resta 2,6 volte più leggero del titolo, quindi il testo corrente
     non diventa un secondo titolo. */
  --grigio: #525968;
  --surface: #F6F8FB;
  --ink: #13161C;
  --bg: #FBFCFE;
  --line: rgba(19, 22, 28, 0.08);

  --font-sans: "Instrument Sans", system-ui, -apple-system, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --radius-s: 12px;
  --radius-m: 18px;
  --radius-l: 28px;

  --container: 1180px;
  --nav-h: 72px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

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

body {
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

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

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

:focus-visible {
  outline: 2.5px solid var(--blu);
  outline-offset: 3px;
  border-radius: 4px;
}

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

section { scroll-margin-top: calc(var(--nav-h) + 12px); }

/* ---------- Primitives ---------- */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 40px);
}

/* Etichetta di sezione: un filetto e un maiuscoletto spaziato, niente pillola.
   Il testo nell'HTML va scritto in minuscolo — a maiuscolarlo ci pensa il CSS,
   così gli screen reader leggono una parola e non una sigla lettera per lettera. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blu);
  display: inline-flex;
  align-items: center;
  gap: 12px;
  width: fit-content;
  margin-bottom: 20px;
}

.eyebrow::before {
  content: "";
  flex: none;
  width: 26px;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

.eyebrow-light { color: #8A96EC; }

/* Solo per screen reader (la vetrina la usa per annunciare il caso corrente) */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.section { padding-block: clamp(84px, 11vw, 148px); }

.section-title {
  font-size: clamp(30px, 4.4vw, 52px);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.08;
  max-width: 16ch;
}

.section-lead {
  font-size: clamp(17px, 1.6vw, 20px);
  color: var(--grigio);
  margin-top: 16px;
  max-width: 52ch;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 600;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}

.btn-primary {
  background: var(--blu);
  color: #fff;
  box-shadow: 0 6px 18px rgba(29, 54, 218, 0.28);
}

.btn-primary:hover {
  background: var(--blu-scuro);
  transform: translateY(-1px);
  box-shadow: 0 10px 24px rgba(29, 54, 218, 0.32);
}

.btn-primary:active { transform: translateY(0); }

.btn-nav { font-size: 15px; padding: 10px 22px; }

.btn-lg { font-size: 17px; padding: 16px 34px; }

.btn-block { width: 100%; }

/* ============================================================
   NAVBAR
   ============================================================ */
.navbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: rgba(251, 252, 254, 0.78);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}

.navbar.is-scrolled {
  border-bottom-color: var(--line);
  box-shadow: 0 4px 24px rgba(19, 22, 28, 0.05);
}

.navbar-inner {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 40px);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: 32px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-right: auto;
}

.brand-mark { height: 30px; width: auto; }

.brand-word {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.nav-links {
  display: flex;
  gap: 30px;
  font-size: 15.5px;
  font-weight: 500;
  color: var(--grigio);
}

.nav-links a { transition: color 0.2s ease; }
.nav-links a:hover { color: var(--ink); }

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative;
  overflow: hidden;
  padding-top: var(--nav-h);
  min-height: 100svh;
  display: flex;
  align-items: center;
  /* UN SOLO BLOB, in alto a destra, dalla parte del titolo. Il 55% è la sosta
     che porta il blu a zero prima di metà pagina: è geometria tarata, non si
     cambia senza rimisurare.

     IL ROSA IN BASSO A SINISTRA È STATO TOLTO (13 ago 2026, scelta di Daniele).
     Era `radial-gradient(55% 45% at 0% 78%, var(--velo-porpora) 0%, transparent
     48%)`. Due motivi, e il secondo è quello che conta: (1) misurato, dava 28
     livelli concentrati sotto x=450 e tra y=550 e y=880 — così compatto non si
     leggeva come una velatura ma come una chiazza; (2) non serve più, perché da
     quando "Chi siamo" ha la sua fascia il basso dell'hero confina già con una
     campitura vera, e ripeterla qui era dire due volte la stessa cosa.

     NON RIMETTERLO "aggiustandogli la posizione": era già stato spostato da
     `at 0% 100%` a `at 0% 78%` per curargli un gradino di 14,8 livelli sul
     bordo inferiore. Adesso quel bordo vale 0 su tutta la larghezza perché lì
     non è dipinto niente — è il modo più solido di non avere il problema.
     Il token --velo-porpora resta vivo: lo usa .section-education. */
  background:
    radial-gradient(85% 75% at 100% 0%, var(--velo-blu) 0%, transparent 55%),
    var(--bg);
}

/* Hero centrato a colonna singola (richiesta 17 lug 2026):
   titolo grande su due righe — "Automatizziamo processi" sopra,
   parola che ruota sotto — poi sottotitolo e CTA.

   SFONDO — storia e regola.
   Il 17 lug 2026 uno sfondo animato è stato provato DUE volte (prima 72 <path>
   SVG animati, poi un porting su <canvas>) e bocciato da Daniele: rumoroso.
   Il difetto non era il numero di path — era che si muoveva DA SOLO.
   Le due varianti qui sotto rispettano cinque regole che nascono da lì:
     1. a puntatore fermo NON viene schedulato un solo frame (zero, non "poco");
     2. una sola proprietà scritta per frame;
     3. niente si muove entro 120px dal titolo — la parola che ruota resta
        l'unica protagonista, e lo è per costruzione, non per accordo;
     4. ogni pixel di movimento deve risalire alla mano di chi guarda;
     5. zero dipendenze, zero file nuovi.
   Collaudo: 5s di cattura col mouse fermo, diff primo/ultimo frame = 0 px
   fuori da .hero-rotate. Se fallisce, abbiamo rifatto la versione bocciata. */
.hero-inner {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(20px, 4vw, 40px);
  padding-block: clamp(40px, 6vh, 80px);
  width: 100%;
}

.hero-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* alza il blocco rispetto al centro verticale (richiesta 17 lug 2026) */
  margin-top: calc(-1 * clamp(20px, 5vh, 56px));
}

.hero-title {
  font-size: clamp(40px, 6.6vw, 86px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.06;
}

.hero-title-line { display: block; }

.adj {
  font-weight: 700;
  color: var(--blu);
  letter-spacing: -0.01em;
}

/* Slot della parola che ruota (una sola visibile alla volta), su riga propria.
   Il sizer invisibile riserva l'altezza e la larghezza di RIPETITIVI: niente salti. */
.hero-rotate {
  position: relative;
  display: block;
  margin-top: 0.04em;
}

.adj-sizer { visibility: hidden; }

.adj-rotate {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
  opacity: 0;
  will-change: opacity, transform;
  animation: word-cycle 9s cubic-bezier(0.22, 1, 0.36, 1) infinite both;
}

/* il sizer è il primo span dello slot: le parole rotanti sono la 2ª, 3ª e 4ª */
.adj-rotate:nth-of-type(2) { animation-delay: 0s; }
.adj-rotate:nth-of-type(3) { animation-delay: 3s; }
.adj-rotate:nth-of-type(4) { animation-delay: 6s; }

.hero-sub {
  font-size: clamp(17px, 1.7vw, 20px);
  color: var(--grigio);
  max-width: 54ch;
  margin-top: 26px;
}

.hero-actions { margin-top: 36px; }

/* ---------- Sfondo hero: "il reticolo" ----------
   Griglia immobile per sempre + una lente che scatta di cella in cella.
   Passo (40px) e lato lente (320px) sono multipli l'uno dell'altro: il pattern
   della lente resta registrato su quello di base senza mai ricalcolare
   background-position, quindi muoverla costa solo compositing. */
.hero-grid {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(90deg, rgba(29, 54, 218, 0.045) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(0deg,  rgba(29, 54, 218, 0.045) 0 1px, transparent 1px 40px);
}

.hero-lens {
  position: absolute;
  top: 0;
  left: 0;
  width: 320px;
  height: 320px;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background-image:
    repeating-linear-gradient(90deg, rgba(29, 54, 218, 0.19) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(0deg,  rgba(29, 54, 218, 0.19) 0 1px, transparent 1px 40px),
    radial-gradient(closest-side, rgba(29, 54, 218, 0.035), transparent 72%);
  -webkit-mask-image: radial-gradient(closest-side, #000 0 32%, transparent 74%);
  mask-image: radial-gradient(closest-side, #000 0 32%, transparent 74%);
  transform: translate3d(calc(var(--lx, 0px) - 160px), calc(var(--ly, 0px) - 160px), 0);
  transition:
    transform 160ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.hero-lens.is-lit { opacity: 1; }

/* ============================================================
   CHI SIAMO
   ============================================================ */
.manifesto {
  font-size: clamp(19px, 2.1vw, 25px);
  line-height: 1.45;
  letter-spacing: -0.012em;
  max-width: 46ch;
  margin-top: 22px;
  font-weight: 500;
}

/* ---------- Chi siamo: la nuvola ----------
   La sezione non è delimitata da un bordo ma dal COLORE: una campitura che
   tiene tutta la zona di foto + nome + bio e si spegne in ogni direzione
   prima di incontrare un margine. Nessuna riga netta da nessuna parte — il
   confine con l'hero sopra e con i casi di studio sotto resta indecidibile,
   ed è esattamente il punto: la pagina continua, ma questa zona è un'altra.

   PERCHÉ NON SCONFINA (13 ago 2026). Prima la fascia era estesa di 180px
   sopra e sotto per darsi una rampa lunga, e il prezzo era che il colore
   cominciava a salire 180px DENTRO l'hero e moriva 328px dentro ai casi di
   studio: la zona non era più leggibile come zona. Ora la fascia è alta
   esattamente quanto la sezione e la rampa è il suo padding — 148px al
   desktop, 84px sotto i 760px. Il timore di allora (una rampa corta si legge
   come un bordo) era mal tarato: 39 livelli su 148px fanno 3,8px per livello,
   cioè quattro volte la distanza a cui comincia il banding. Non c'è nessun
   bordo, e il colore vale zero esattamente sui due bordi della sezione, dove
   di là c'è --bg in entrambi i casi: la giunzione è continua per costruzione.

   PERCHÉ POSIZIONATA. `position: relative` porta la sezione tra i
   positioned descendants, che si dipingono dopo i fondi delle sezioni in
   flusso. `isolation: isolate` chiude lo z-index:-1 dentro la sezione, così
   la nuvola sta sotto al contenuto ma sopra al fondo pagina.

   PERCHÉ UNA @property. I gradienti non si interpolano in una transizione.
   Registrando la variabile come <color> diventa animabile lei e il gradiente
   si ridisegna a ogni frame: senza, il cambio di persona scatterebbe. */
@property --nuvola {
  syntax: "<color>";
  inherits: true;
  initial-value: transparent;
}

/* 20%, ed è un tetto misurato, non una preferenza. La campitura piena sta
   ~39 livelli sotto al bianco pagina (il 15% di prima ne dava 29): più densa,
   come chiesto, e se lo può permettere perché adesso occupa molto meno spazio.
   Sopra il 20 non si va: a 22% la tinta magenta di .tm-role scende a 4,39:1
   sul proprio fondo, sotto la soglia AA — e il ruolo è testo da 13px. */
.section-team {
  position: relative;
  isolation: isolate;
  --nuvola: color-mix(in oklab, #1D36DA 20%, transparent);
  transition: --nuvola 620ms ease;
}

/* FASCIA, NON ALONE. La sfumatura corre solo in VERTICALE: in orizzontale il
   colore è pieno da bordo a bordo, perché la sezione deve appoggiarsi tutta
   quanta su un altro colore — è quello a delimitare la regione.
   La variante radiale provata prima (`radial-gradient(68% 62% at 50% 50%,
   var(--nuvola) 0%, transparent 72%)`) sfumava anche ai lati: misurata, dava
   51 livelli di colore al centro ma 3 ai bordi della finestra, cioè angoli
   bianchi. Si leggeva come un faretto acceso dietro al contenuto, non come
   una zona. È a una riga di distanza se la si preferisce.

   LA RAMPA È IL PADDING DELLA SEZIONE, e non è una coincidenza estetica: è la
   definizione. Il contenuto comincia esattamente a padding-top (il titolo è il
   primo figlio del .container, che non ha padding verticale) e finisce
   esattamente a padding-bottom — misurato: 148 e 1153,7 su una sezione alta
   1301,7. Facendo coincidere le soste con quella stessa clamp, il colore è
   PIENO dal titolo fino all'ultima riga della bio e sale/scende solo nel vuoto
   sopra e sotto, senza mai uscire dalla sezione.

   Le soste vanno scritte in px e non in %, perché una % qui si misura
   sull'altezza della fascia, che cambia con la lunghezza delle bio: le rampe
   scivolerebbero dentro o fuori dal contenuto a ogni modifica del testo. In px
   restano incollate al padding qualunque cosa succeda in mezzo. */
.section-team::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  --rampa: clamp(84px, 11vw, 148px); /* = padding-block di .section */
  background: linear-gradient(180deg,
    transparent 0,
    var(--nuvola) var(--rampa),
    var(--nuvola) calc(100% - var(--rampa)),
    transparent 100%);
}

/* La tinta la sceglie il CSS leggendo chi è aperto: il JS continua a scrivere
   solo data-pos, come già fa, e il colore lo segue da sé.

   SOLO NEL LAYOUT LARGO, e non è un dettaglio. Sotto 760px lo stack non è più
   una fisarmonica: le schede sono tutte aperte davvero, e infatti sync() in
   script.js:748 scrive data-pos="active" su TUTTE E TRE. Lì non esiste "la
   persona attiva" — e senza questo media query le tre regole matcherebbero
   insieme, vincerebbe l'ultima per ordine, e la fascia resterebbe magenta
   qualunque scheda si tocchi. Sul telefono resta la tinta di partenza.
   (Stessa soglia del blocco mobile a styles.css:1894.) */
@media (min-width: 761px) {
  .section-team:has(.team-card[data-who="andrea"][data-pos="active"]) {
    --nuvola: color-mix(in oklab, #6B2BC9 20%, transparent);
  }
  .section-team:has(.team-card[data-who="daniele"][data-pos="active"]) {
    --nuvola: color-mix(in oklab, #A62D77 20%, transparent);
  }
}

/* ---------- Rastrelliera orizzontale ----------
   Tre pannelli verticali in fila: quello attivo si allarga, gli altri restano
   dorsi da 88px col nome scritto in verticale, come coste di libri.

   Regola strutturale, invariata dalla versione a fisarmonica: UNA scheda è
   SEMPRE aperta. Da lì discende tutto — l'altezza della fila è costante
   (quindi il layout non può saltare), la sezione è compiuta al primo sguardo,
   e i casi touch / reduced-motion / "il JS non è partito" sono già risolti
   perché l'HTML servito ha già la prima aperta.

   Il JS non scrive MAI geometria: scrive solo data-pos su ogni scheda.
   Tutto il resto è qui.

   PERCHÉ flex-grow E NON grid-template-columns. `1fr` e `88px` non sono
   interpolabili: con la griglia l'apertura scatterebbe invece di scorrere.
   Con flex la base resta fissa a 88px e si anima solo il numero `flex-grow`,
   che interpola davvero.

   NIENTE 3D. La fisarmonica ruotava le schede su un asse e si portava dietro
   la trappola di `preserve-3d` (hit-testing rotto: elementFromPoint sul
   centro di una scheda restituiva il contenitore e il click non arrivava).
   Qui non c'è nessuna rotazione, quindi il problema non esiste più. */
.team-panel { margin-top: clamp(40px, 5vw, 64px); }

.team-stack {
  --tm-h: clamp(360px, 40vw, 500px);   /* altezza della fila */
  --tm-dorso: 88px;                    /* larghezza di una scheda chiusa */
  --tm-gap: 14px;
  /* Stondatura appena accennata: 12px su un dorso da 88px è il 14% del lato
     corto — si vede che l'angolo non è tagliato di netto e non si legge come
     una "pillola". È il --radius-s del sito, quindi la scheda si stonda come
     tutto il resto invece di inventarsi una misura sua. */
  --tm-raggio: var(--radius-s);

  list-style: none;
  display: flex;
  gap: var(--tm-gap);
  height: var(--tm-h);
}

.team-card {
  position: relative;
  flex: 0 1 var(--tm-dorso);
  min-width: 0;
  transition: flex-grow 460ms cubic-bezier(0.22, 1, 0.36, 1);
}

.team-card[data-pos="active"] { flex-grow: 1; }

/* IL COLORE DELLA PERSONA STA DOVE LA FOTO FINISCE, non dietro alla foto.
   Sta sotto a .tm-photo e si vede solo attraverso i due tratti in cui la
   maschera la dissolve: così il ritratto non viene tinto (le facce vere
   diventerebbero blu, viola e magenta) ma nello sfumare attraversa il colore
   di chi è. È anche il motivo per cui il campo della foto qui sotto è il
   neutro chiaro della specifica e non una tinta: sulla fascia colorata della
   sezione un pannello della stessa tinta sparirebbe — misurato, il blu su blu
   non si distingueva. */
.team-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* L'ANGOLO VISIBILE DELLA SCHEDA È QUESTO, non quello della foto: in cima e
     in fondo la maschera di .tm-photo ha già dissolto il campo chiaro, quindi
     lì l'unica cosa che si vede è questa banda di tinta — ed era lei ad avere
     lo spigolo secco. Il raggio va quindi ripetuto su tutte e due (qui e su
     .tm-photo): tolto da uno dei due, lo spigolo torna. */
  border-radius: var(--tm-raggio);
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--tinta) 34%, transparent) 0%,
    transparent 24%,
    transparent 76%,
    color-mix(in oklab, var(--tinta) 34%, transparent) 100%);
}

/* Il bottone È la scheda: copre tutta la colonna e tiene dentro foto e dorso.
   Così l'area cliccabile coincide esattamente con quello che si vede, e non
   serve nessun bersaglio invisibile sovrapposto. */
.tm-trigger {
  position: absolute;
  inset: 0;
  display: block;
  padding: 0;
  background: none;
  border: none;
  font-family: var(--font-sans);
  color: inherit;
  cursor: pointer;
}

.tm-trigger:focus-visible {
  outline: 2.5px solid var(--tinta, var(--blu));
  outline-offset: 4px;
  /* raggio della scheda + l'offset, così l'anello resta concentrico alla
     stondatura invece di stringersi negli angoli */
  border-radius: calc(var(--tm-raggio) + 4px);
}

/* LA FOTO SI DISSOLVE, non sta in una cornice. Nessun bordo, nessun raggio
   visibile: la maschera la fa svanire in alto e in basso, e nello svanire
   attraversa il colore della persona — il fondo della sezione continua a
   vedersi attraverso. È il motivo per cui la specifica dei ritratti
   (index.html) impone sfondo chiaro piatto e occhi al 33%: con foto a fondo
   pieno o inquadrate strette, lo sfumato in alto mangerebbe la testa. */
.tm-photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: grid;
  place-items: center;
  /* esattamente il fondo che la specifica chiede alle foto vere (index.html):
     così il segnaposto prova già la cosa giusta, e quando le foto arrivano
     non cambia niente attorno */
  background: #EEF1F7;
  /* Stesso raggio della banda di tinta. Oggi lo si nota poco — la maschera qui
     sotto sfuma via proprio le quattro zone d'angolo — ma quando arriveranno i
     ritratti veri sarà l'`overflow: hidden` di questa regola a stondare l'<img>,
     e senza il raggio la foto tornerebbe a spigolo dentro una banda stondata. */
  border-radius: var(--tm-raggio);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 10%, #000 87%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 10%, #000 87%, transparent 100%);
}

.tm-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.04);
  transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* la foto continua a scendere per ~200ms dopo che la colonna si è fermata:
   dà la sensazione che la persona stia ancora arrivando */
.team-card[data-pos="active"] .tm-photo img { transform: scale(1); }

/* Ritratto che non c'è ancora. NON un avatar circolare: un cerchio differisce
   per categoria da una fotografia, e la fila si leggerebbe "due foto + uno che
   manca". Qui la colonna resta identica ed è lei a dire "qui c'è un ritratto";
   dentro vive lo stesso numerale mono fantasma che il sito usa già in
   .case-ph-num e .method-ghost. Sul dorso da 88px non ci sta, quindi si
   accende solo sulla scheda aperta. */
.tm-photo-mono {
  font-family: var(--font-mono);
  font-size: clamp(72px, 8vw, 132px);
  font-weight: 500;
  line-height: 1;
  color: color-mix(in oklab, var(--tinta) 24%, transparent);
  user-select: none;
  opacity: 0;
  transition: opacity 240ms ease;
}

.team-card[data-pos="active"] .tm-photo-mono { opacity: 1; }

/* l'unica modifica futura è aggiungere <img> dentro .tm-photo */
.tm-photo:has(img) .tm-photo-mono { display: none; }

/* IL DORSO. Il nome ruotato come sulla costa di un libro, e come sulle coste
   si legge dal basso verso l'alto: `vertical-rl` + `rotate(180deg)`.
   Sta FUORI da .tm-photo, non dentro: la maschera della foto se lo
   mangerebbe insieme al ritratto. */
.tm-spine {
  position: absolute;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%) rotate(180deg);
  writing-mode: vertical-rl;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  color: var(--ink);
  transition: opacity 240ms ease;
}

/* aperta, il nome grande sta già sotto la fila: sul pannello sarebbe un doppione */
.team-card[data-pos="active"] .tm-spine { opacity: 0; }

/* I TRE TESTI, impilati nella stessa cella di griglia. L'altezza la detta la
   bio più lunga: è costante per costruzione, quindi cambiare persona non muove
   niente di quello che sta sotto — e non c'è nessun min-height da indovinare.

   IL RICAMBIO È UNA STAFFETTA, NON UNA DISSOLVENZA INCROCIATA: chi esce ha
   finito (190ms) prima che chi entra cominci (ritardo 210ms). Sovrapposti si
   leggerebbe testo sopra testo. */
.team-texts {
  display: grid;
  margin-top: clamp(26px, 3vw, 40px);
}

.tm-text {
  grid-area: 1 / 1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 190ms ease;
}

.team-panel:has(.team-card[data-who="rolando"][data-pos="active"]) .tm-text[data-for="rolando"],
.team-panel:has(.team-card[data-who="andrea"][data-pos="active"]) .tm-text[data-for="andrea"],
.team-panel:has(.team-card[data-who="daniele"][data-pos="active"]) .tm-text[data-for="daniele"] {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 260ms cubic-bezier(0.22, 1, 0.36, 1) 210ms;
}

.tm-name {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 640;
  letter-spacing: -0.022em;
  line-height: 1.1;
}

.tm-role {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--tinta);
  margin-top: 7px;
}

/* Grigio LOCALE, più scuro del token di marca. Sul fondo colorato della
   sezione `--grigio` (#6A7180) scende sotto il minimo AA di 4,5:1.
   Sceso da #5C6372 a #525967 quando la campitura è passata da 15% a 20%: sul
   fondo nuovo il vecchio grigio dava 4,13:1 (blu) / 4,19 (porpora) / 4,25
   (magenta), cioè bocciato su tutte e tre le persone. Questo dà 4,82 / 4,89 /
   4,96 — misurato sul colore composito vero, non sul valore dichiarato.
   Vale solo dentro Chi siamo: il token globale è usato ovunque nel sito e non
   si tocca da qui. */
.tm-bio {
  font-size: 16.5px;
  line-height: 1.65;
  color: #525967;
  margin-top: 14px;
  max-width: 52ch;
}

/* ============================================================
   CASI DI STUDIO — vetrina a prisma
   Non è un carosello di slide: è un solido che gira. Le facce laterali si
   voltano verso l'ESTERNO di 45° (bordo interno vicino, bordo esterno che si
   allontana), così se ne vedono tre come sui lati di un esagono. La scala non
   si calcola: la fa la prospettiva. I transform li scrive script.js.
   ============================================================ */
.section-cases {
  /* Finisce sulla stessa velatura da cui riparte "Per chi": le due sezioni si
     saldano invece di accostarsi, e sparisce la riga di stacco tra loro.
     Prima andava da --bg a --surface, cioè da un bianco a un altro bianco:
     croma di fondo 5, la sezione più smorta del sito dopo il Metodo. */
  background: linear-gradient(180deg, var(--bg) 0%, #E8ECFA 55%, var(--velo-blu) 100%);
  overflow: hidden; /* le facce laterali sbordano senza creare scroll orizzontale */
}

.cases-stage {
  --cases-h: clamp(430px, 44vw, 540px);
  --case-w: min(480px, 82vw); /* la larghezza della card: la legge anche il JS */
  position: relative;
  margin-top: clamp(44px, 5vw, 72px);
}

/* Ombra a terra. Sta FUORI dal contesto 3D: dentro la track verrebbe ruotata
   insieme alle facce invece di restare per terra. */
.cases-stage::after {
  content: "";
  position: absolute;
  top: calc(var(--cases-h) - 4px);
  left: 50%;
  width: calc(var(--case-w) * 0.66);
  height: 30px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(19, 22, 28, 0.3) 0%, transparent 72%);
  filter: blur(8px);
  pointer-events: none;
  z-index: 0;
}

.cases-viewport {
  position: relative;
  z-index: 1; /* esplicito: senza, l'ombra a terra finirebbe sopra le card */
  height: var(--cases-h);
  perspective: 1600px;
  outline-offset: -2.5px;
  cursor: grab;
  touch-action: pan-y; /* lo swipe orizzontale è nostro, lo scroll verticale resta al browser */
}

.cases-viewport.is-dragging { cursor: grabbing; }

.cases-track {
  list-style: none;
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* Il contenitore sta sul piano z=0 e copre tutta l'area: se resta
     cliccabile, intercetta lui il click destinato alle facce laterali, che
     stanno DIETRO quel piano. Diventa trasparente ai puntatori e sono le card
     a raccoglierli (il JS gli mette pointer-events: auto); gli eventi bubbling
     dei figli continuano a passare di qui come prima. */
  pointer-events: none;
}

.case-slide {
  --veil: 0;          /* quanto è velata: la scrive il JS insieme al transform */
  --veil-angle: 90deg; /* da che parte cade l'ombra: 90deg a destra, 270deg a sinistra */
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--case-w);
  height: 100%;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-l);
  background: var(--bg);
  border: 1px solid var(--line);
  box-shadow: 0 34px 80px -34px rgba(19, 22, 28, 0.3);
  overflow: hidden;
  cursor: pointer;
  will-change: transform, opacity;
  transition:
    transform 0.65s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.65s ease;
}

/* Velatura direzionale: il bordo che si allontana si scurisce. È luce che cade
   su un solido — per questo il gradiente cambia verso di lato, invece di
   sbiadire in blocco le "card di dietro". */
.case-slide::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  background: linear-gradient(var(--veil-angle), transparent 40%, rgba(19, 22, 28, 0.30));
  opacity: var(--veil);
  pointer-events: none;
  transition: opacity 0.65s ease;
}

/* Durante il trascinamento il layout si riscrive a ogni frame: le transition
   litigherebbero col dito. */
.cases-track.is-dragging .case-slide,
.cases-track.is-dragging .case-slide::after { transition: none; }

.case-slide.is-active { box-shadow: 0 44px 100px -36px rgba(29, 54, 218, 0.35); }

/* --- Slide pubblicata --- */
.case-media {
  height: 52%;
  background:
    radial-gradient(120% 100% at 15% 0%, rgba(143, 176, 255, 0.22) 0%, transparent 60%),
    linear-gradient(160deg, #1A1E27 0%, var(--ink) 70%);
  position: relative;
  overflow: hidden;
  flex: none;
}

.case-media img,
.case-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.case-body {
  padding: clamp(20px, 2.4vw, 30px) clamp(22px, 2.6vw, 34px);
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
  min-height: 0;
}

.case-sector {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grigio);
}

.case-title {
  font-size: clamp(19px, 2vw, 24px);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

.case-metric {
  font-family: var(--font-mono);
  font-size: clamp(21px, 2.3vw, 28px);
  font-weight: 500;
  color: var(--blu);
  margin-top: auto;
}

.case-open {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--blu);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.case-open span { transition: transform 0.3s ease; }
.case-slide.is-active:hover .case-open span { transform: translateX(4px); }

/* --- Faccia ancora vuota: "in arrivo" ---
   Bordo pieno come le altre: il tratteggio la faceva sembrare un wireframe
   accanto ai casi veri. */
.case-slide.is-placeholder {
  cursor: default;
  border: 1px solid var(--line);
  background:
    radial-gradient(115% 95% at 12% 8%, var(--blu-tint) 0%, transparent 60%),
    radial-gradient(110% 90% at 90% 92%, var(--porpora-tint) 0%, transparent 55%),
    var(--surface);
  align-items: center;
  justify-content: center;
  text-align: center;
}

.case-ph {
  position: relative;
  z-index: 1;
  padding: 24px;
  display: grid;
  gap: 14px;
  justify-items: center;
}

.case-ph-num {
  font-family: var(--font-mono);
  font-size: clamp(64px, 8vw, 104px);
  font-weight: 500;
  line-height: 1;
  color: rgba(29, 54, 218, 0.14);
  user-select: none;
}

.case-ph-label {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blu);
}

.case-ph-text {
  font-size: 15px;
  color: var(--grigio);
  max-width: 26ch;
}

/* --- Indicatori, non comandi ---
   La vetrina si trascina: qui sotto non c'è niente da cliccare. Il contatore
   dice a che punto sei, la barra è il timer dell'autoplay (continua, non a
   segmenti: deve leggersi come un tempo che scorre, non come dei puntini). */
.cases-meta {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 22px);
  margin-top: clamp(30px, 3.6vw, 46px);
}

.cases-counter {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  display: flex;
  gap: 8px;
  flex: none;
}

.cases-counter-now { color: var(--ink); }
.cases-counter-sep,
.cases-counter-tot { color: var(--grigio); }

.cases-progress {
  width: clamp(84px, 12vw, 140px);
  height: 2px;
  border-radius: 999px;
  background: rgba(19, 22, 28, 0.1);
  overflow: hidden;
  flex: none;
}

.cases-progress span {
  display: block;
  height: 100%;
  background: var(--blu);
  transform: scaleX(0);
  transform-origin: left center;
}

.cases-progress.is-running span {
  animation: cases-fill var(--autoplay, 5000ms) linear forwards;
}

.cases-progress.is-paused span { animation-play-state: paused; }

@keyframes cases-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* L'unico invito a trascinare. Sparisce al primo gesto e non torna più. */
.cases-hint {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grigio);
  margin-left: auto;
  text-align: right;
  transition: opacity 0.5s ease;
}

.cases-hint.is-gone { opacity: 0; }

/* ============================================================
   MODAL CASO DI STUDIO
   ============================================================ */
body.modal-open { overflow: hidden; }

.case-modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: clamp(12px, 3vw, 44px);
}

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

.case-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(19, 22, 28, 0.66);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  animation: modal-fade 0.3s ease both;
}

.case-modal-dialog {
  position: relative;
  width: min(780px, 100%);
  max-height: min(88vh, 920px);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
  border-radius: var(--radius-l);
  box-shadow: 0 50px 120px rgba(0, 0, 0, 0.45);
  animation: modal-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.case-modal-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  border: 1px solid rgba(251, 252, 254, 0.25);
  background: rgba(19, 22, 28, 0.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #F4F6FA;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background-color 0.25s ease, transform 0.25s ease;
}

.case-modal-close:hover {
  background: rgba(19, 22, 28, 0.8);
  transform: scale(1.06);
}

.case-modal-close svg { width: 20px; height: 20px; }

/* media in alto: contiene sia GIF orizzontali che video verticali 9:16 */
.case-modal-media:empty { display: none; } /* caso senza demo: niente box vuoto */

.case-modal-media {
  aspect-ratio: 16 / 9;
  max-height: 46vh;
  width: 100%;
  background: linear-gradient(160deg, #1A1E27 0%, var(--ink) 70%);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.case-modal-media img,
.case-modal-media video {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.case-modal-content {
  padding: clamp(26px, 3.4vw, 44px);
  display: grid;
  gap: 18px;
}

.case-modal-sector {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grigio);
}

.case-modal-title {
  font-size: clamp(24px, 3vw, 34px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.case-modal-metric {
  font-family: var(--font-mono);
  font-size: clamp(26px, 3.2vw, 38px);
  font-weight: 500;
  color: var(--blu);
}

.case-modal-blocks {
  display: grid;
  gap: 20px;
  margin-top: 8px;
}

.case-block h4 {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blu);
  margin-bottom: 6px;
}

.case-block p {
  font-size: 16.5px;
  color: var(--ink);
  line-height: 1.65;
}

.case-modal-tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.case-modal-tags li {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--blu);
  background: var(--blu-tint-forte);
  padding: 6px 13px;
  border-radius: 999px;
}

.case-modal-cta {
  justify-self: start;
  margin-top: 10px;
}

@keyframes modal-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes modal-in {
  from { opacity: 0; transform: translateY(26px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ============================================================
   PER CHI / COSA FACCIAMO
   ============================================================ */
.section-processes {
  /* Parte dalla velatura su cui finisce "Casi di studio": giunzione invisibile */
  background: linear-gradient(175deg, var(--velo-blu) 0%, #EDF1FC 55%, var(--surface) 100%);
}

.process-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(14px, 1.6vw, 22px);
  margin-top: clamp(44px, 5vw, 64px);
}

.process-card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  padding: clamp(24px, 2.4vw, 32px);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.process-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(19, 22, 28, 0.07);
}

.process-card h3 {
  font-size: 18.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: 18px;
}

.process-card p {
  font-size: 15.5px;
  color: var(--grigio);
  margin-top: 8px;
  line-height: 1.55;
}

.process-icon {
  width: 46px;
  height: 46px;
  border-radius: 13px;
  /* tinta piena: è un oggetto piccolo su una card chiara, non una velatura */
  background: var(--blu-tint-forte);
  color: var(--blu);
  display: grid;
  place-items: center;
}

.process-icon svg {
  width: 23px;
  height: 23px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* card CTA — unico accento porpora della sezione */
.process-card-cta {
  /* stessa costruzione della card del Metodo: riflesso sopra, tinta sotto,
     filo di luce sul bordo alto. È l'unica card colorata della sezione, quindi
     è quella che deve reggere lo sguardo. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0) 42%),
    linear-gradient(150deg, var(--porpora-tint-forte) 0%, #F3E6F5 100%);
  border-color: rgba(124, 45, 138, 0.16);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

.process-card-cta .process-icon {
  background: rgba(124, 45, 138, 0.16);
  color: var(--porpora);
}

.process-card-cta h3 { color: var(--porpora); }

/* il filo di luce va ripetuto: box-shadow si sostituisce, non si somma */
.process-card-cta:hover {
  box-shadow:
    0 14px 34px rgba(124, 45, 138, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

.positioning {
  font-size: clamp(24px, 3.2vw, 38px);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.22;
  max-width: 26ch;
  margin-top: clamp(56px, 7vw, 96px);
}

.positioning em {
  font-style: normal;
  color: var(--blu);
}

/* ============================================================
   IL METODO
   ============================================================ */
.method-flow {
  margin-top: clamp(48px, 6vw, 80px);
  max-width: 940px;
}

/* Velatura di fondo: resta MOLTO sotto la densità delle schede, perché qui il
   colore deve stare addosso agli oggetti, non al terreno — durante il pin le
   card girano e devono staccare. Serve solo a non lasciare un buco bianco tra
   "Per chi" e Education, che dopo il 13 ago sono entrambe colorate: misurata,
   la sezione stava a croma 3 tra due vicine a 20 e 15.
   Parte dal --surface su cui finisce "Per chi" e torna al --bg da cui riparte
   Education: nessuna delle due giunzioni ha un gradino. */
.section-method {
  background: linear-gradient(180deg, var(--surface) 0%, #EAEEF9 45%, var(--bg) 100%);
}

/* contenitore prospettico: il reveal resta qui, il tilt sta sulla card interna */
.method-step {
  position: relative;
  perspective: 1200px;
}

.method-card {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr minmax(0, 300px);
  align-items: start;
  gap: clamp(20px, 4vw, 48px);
  padding: clamp(32px, 4.5vw, 60px) clamp(24px, 4vw, 56px);
  border-radius: var(--radius-l);
  /* Due strati, e l'ordine conta. Sopra il RIFLESSO: bianco sul bordo alto che
     si spegne al 42%. È lui a tenere la superficie lucida mentre la tinta sotto
     si fa densa — toglilo e la card diventa subito opaca, che è il difetto che
     questo blocco esiste per evitare.
     Sotto la TINTA, che non si dissolve più nel bianco della pagina: prima
     finiva su rgba(...,0.35) e a metà card il colore era già sparito. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0) 42%),
    linear-gradient(150deg, var(--blu-tint-forte) 0%, #DCE0FA 100%);
  overflow: hidden;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  will-change: transform;
  /* il filo di luce interno è il bordo lucido: va tenuto in TUTTI gli stati,
     hover compreso, o al passaggio del mouse la card si spegne di un gradino */
  box-shadow:
    0 18px 44px -28px rgba(29, 54, 218, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
  transition:
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.5s ease;
}

/* glow indaco discreto quando la card è viva */
.method-card:hover {
  box-shadow:
    0 30px 70px -30px rgba(29, 54, 218, 0.32),
    0 0 0 1px rgba(29, 54, 218, 0.07),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

.method-num {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 500;
  color: var(--blu);
  background: rgba(251, 252, 254, 0.85);
  padding: 8px 14px;
  border-radius: 9px;
  margin-top: 6px;
}

.method-body {
  position: relative;
  z-index: 1;
}

/* strati in parallasse: contenuto e numero fluttuano col mouse */
.method-num,
.method-body {
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.method-body h3 {
  font-size: clamp(26px, 3.4vw, 44px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.method-body p {
  font-size: clamp(16.5px, 1.7vw, 19px);
  /* non --grigio: su questa tinta darebbe 2.74:1. Così sono 4.80:1, e il
     titolo resta 2.1 volte più forte — il paragrafo non diventa un secondo
     titolo, resta secondario. */
  color: var(--ink-su-tinta);
  margin-top: 12px;
  line-height: 1.65;
  max-width: 52ch;
}

/* Riquadro della micro-clip. Finché il video non c'è, dentro vive il numero
   fantasma: lo stesso device che il sito usa già per "contenuto in arrivo".
   Così la sezione è composta anche a clip mancanti — ed è lo stato in cui
   verrà spedita la prima volta. */
.method-media {
  position: relative;
  align-self: center;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  background: rgba(251, 252, 254, 0.55);
  border: 1px solid rgba(29, 54, 218, 0.1);
  display: grid;
  place-items: center;
}

.method-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* numero fantasma: presenza grafica dello step, in controfase col mouse */
.method-ghost {
  transform: translate3d(var(--gx, 0px), var(--gy, 0px), 0);
  font-family: var(--font-mono);
  font-size: clamp(64px, 7vw, 96px);
  font-weight: 500;
  line-height: 1;
  /* 0.20 e non 0.14: su una tinta più densa il fantasma a 0.14 spariva */
  color: rgba(29, 54, 218, 0.2);
  pointer-events: none;
  user-select: none;
  transition: transform 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}

.method-media:has(video) .method-ghost { display: none; }

/* connettore verticale tra gli step */
.method-link {
  width: 2px;
  height: clamp(28px, 4vw, 52px);
  margin-inline: auto;
  background: repeating-linear-gradient(180deg, var(--blu) 0 6px, transparent 6px 12px);
  opacity: 0.45;
}

.method-link:last-of-type {
  background: repeating-linear-gradient(180deg, var(--porpora) 0 6px, transparent 6px 12px);
}

/* il Development è il climax: accento porpora */
.method-step-final .method-card {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0) 42%),
    linear-gradient(150deg, var(--porpora-tint-forte) 0%, #F3E6F5 100%);
  box-shadow:
    0 18px 44px -28px rgba(124, 45, 138, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

.method-step-final .method-card:hover {
  box-shadow:
    0 30px 70px -30px rgba(124, 45, 138, 0.32),
    0 0 0 1px rgba(124, 45, 138, 0.07),
    inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

.method-step-final .method-num { color: var(--porpora); }

.method-step-final .method-ghost { color: rgba(124, 45, 138, 0.16); }

/* Fuori dal prisma il rail non serve: le tre card si vedono già tutte
   insieme, non c'è nessun "a che punto sono" da risolvere.
   NB: questa regola deve stare PRIMA della media query del prisma — stessa
   specificità, vince l'ultima scritta. */
.method-rail { display: none; }

/* ------------------------------------------------------------
   IL PRISMA
   Le tre card diventano le facce di un solido che gira sull'asse
   orizzontale mentre si scrolla: scendendo, salgono da sotto una alla volta.

   Vive TUTTO dentro la media query qui sotto E sotto la classe .is-prism,
   quindi è additivo: se cade una sola delle condizioni, la sezione resta
   esattamente la colonna di card scritta qui sopra, connettori compresi.
     min-width 761px  → su telefono lo scroll bloccato si legge come una pagina
                        che si è impuntata (stessa soglia del team-stack)
     min-height 700px → filtro grezzo: sotto, non ci sta mai
     no-preference    → chi ha chiesto meno movimento non si merita un pin
     .is-prism        → la mette script.js, e solo dopo aver MISURATO che lo
                        stage ci sta davvero nel pin

   Perché serve anche la misura, e la media query non basta: l'altezza della
   faccia dipende dalla larghezza. Sotto i 1080px la card perde la terza
   colonna, il testo si stringe e la card passa da 368px a ~536px — lo stage
   con lei, da 523px a 761px. A 1000×760 servivano 819px e ce n'erano 688:
   sbordava di 131px fuori dal pin. Nessuna soglia fissa in vh può prevederlo,
   perché la grandezza da confrontare la sa solo il layout a runtime.

   Effetto collaterale voluto: senza JS non parte nemmeno, e senza JS la
   colonna di card è esattamente la risposta giusta. Prima, con le sole media
   query, un JS morto lasciava un prisma bloccato sulla faccia 01 dentro una
   pista vuota alta 300vh.

   GEOMETRIA (H = --face-h, l'altezza della card più alta):
     faccia i → rotateX(-i·step) translateZ(radius·H)  ⇒ finisce SOTTO il centro
     prisma   → rotateX(+angolo) crescente con lo scroll ⇒ le facce SALGONO
   step 45°, radius 1.25. Il radius minimo perché due facce non si compenetrino
   è 0.5/tan(step/2) = 1.207: 1.25 lascia una fessura di luce. È la stessa
   costante della vetrina casi di studio, qui girata sull'asse X.
     bordo alto della faccia adiacente → 0.530H sotto il centro
     stage alto 1.42H                  → se ne intravede 0.18H: "la punta"
   ------------------------------------------------------------ */
@media (min-width: 761px) and (min-height: 700px) and (prefers-reduced-motion: no-preference) {
  /* La pista è lo spazio di scroll che il pin consuma: 300vh meno la
     schermata occupata dallo stage = ~200vh di rotazione utile. */
  .method-track.is-prism {
    position: relative;
    height: 300vh;
  }

  .is-prism .method-stage {
    position: sticky;
    top: var(--nav-h);
    height: calc(100vh - var(--nav-h));
    display: grid;
    align-content: center;
  }

  /* La perspective sta QUI e non sul prisma: deve proiettare le facce da
     fuori il contesto 3D, o girerebbe insieme a loro.
     place-items: center (non stretch) è obbligatorio — con stretch l'altezza
     dello stage tornerebbe a vincolare quella del prisma, e --face-h, che da
     quell'altezza è derivata, si morderebbe la coda. */
  .is-prism .method-viewport {
    --face-h: 360px;            /* valore di partenza: lo riscrive script.js */
    perspective: 1600px;
    height: calc(var(--face-h) * 1.42);
    display: grid;
    place-items: center;
    /* È questo che trasforma la faccia adiacente in una PUNTA: senza, la card
       che sta girando via si vede tutta intera, angolata e leggibile, e il
       solido non si legge più come un solido. L'altezza 1.42·H lascia passare
       ~0.18H di faccia successiva sopra e sotto. Stesso mestiere dell'overflow
       sulla vetrina casi di studio.
       Non spegne il 3D: il preserve-3d sta sul prisma, un livello più sotto. */
    overflow: hidden;
    /* La maschera ammorbidisce il taglio: senza, la punta finisce contro una
       lama e si legge come una card tagliata a metà, non come una faccia che
       sta girando via. Il 13% è calibrato sulla fascia della punta — dove
       comincia la faccia in fuoco la maschera è già piena, quindi la card
       davanti non sbiadisce mai. */
    mask-image: linear-gradient(180deg, transparent 0, #000 13%, #000 87%, transparent 100%);
  }

  /* Le facce stanno tutte nella stessa cella di griglia: così il prisma prende
     da solo l'altezza della card più alta, e a script.js resta solo da
     leggerla (translateZ non accetta le percentuali, serve un px). */
  .is-prism .method-flow {
    --step: 45deg;
    --radius: 1.25;
    width: 100%;
    max-width: 940px;
    margin-top: 0;              /* qui a centrare ci pensa lo stage */
    display: grid;
    transform-style: preserve-3d;
    /* Il translateZ negativo va PRIMA della rotazione, cioè si applica nello
       spazio della vista: riporta l'asse del cilindro indietro di un raggio,
       così la faccia in fuoco torna sul piano z=0 e si vede a grandezza
       naturale. Senza, tutto il solido galleggia un raggio più vicino
       all'occhio e la prospettiva ingrandisce la faccia davanti del 40%:
       sborda dalla colonna e riempie lo stage, cancellando le punte. */
    transform:
      translateZ(calc(var(--radius) * var(--face-h) * -1))
      rotateX(var(--angle, 0deg));
    will-change: transform;
  }

  .is-prism .method-step {
    grid-area: 1 / 1;
    display: grid;              /* la card riempie la faccia: il solido non ha buchi */
    transform:
      rotateX(calc(var(--i) * var(--step) * -1))
      translateZ(calc(var(--radius) * var(--face-h)));
    backface-visibility: hidden;
  }

  .is-prism .method-step:nth-of-type(1) { --i: 0; }
  .is-prism .method-step:nth-of-type(2) { --i: 1; }
  .is-prism .method-step:nth-of-type(3) { --i: 2; }

  .is-prism .method-card {
    height: 100%;
    align-content: center;
  }

  /* I connettori raccontano una colonna: dentro il solido non esiste un "sotto". */
  .is-prism .method-link { display: none; }

  /* Il tilt al mouse resta vivo, ma solo sulla faccia in fuoco: sulle altre
     inseguirebbe il cursore su una superficie vista di taglio. */
  .is-prism .method-step:not(.is-current) { pointer-events: none; }

  /* Il reveal delle card scrive `transform`, che sovrascriverebbe la posizione
     della faccia sul cilindro. Nel prisma le card non entrano una a una: entra
     il solido, girando. La classe .reveal resta comunque nell'HTML, perché
     sotto le soglie di questa media query è ancora lei a farle entrare. */
  .is-prism .method-step.reveal,
  .is-prism .method-step.reveal.is-visible {
    opacity: 1;
    animation: none;
  }

  .is-prism .method-rail {
    display: flex;
    justify-content: center;
    gap: 14px;
    list-style: none;
    margin-top: clamp(20px, 2.5vw, 32px);
  }

  .is-prism .method-rail li {
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--grigio);
    opacity: 0.35;
    padding-bottom: 7px;
    border-bottom: 2px solid currentColor;
    transition: opacity 0.45s ease, color 0.45s ease;
  }

  .is-prism .method-rail li.is-on { opacity: 1; color: var(--blu); }

  .is-prism .method-rail li:last-child.is-on { color: var(--porpora); }
}

/* ============================================================
   EDUCATION
   Seconda offerta, non secondo protagonista: pesa di proposito MENO del
   metodo — colonna stretta, niente card, un solo accento porpora.
   ============================================================ */
.section-education {
  background: linear-gradient(180deg, var(--bg) 0%, var(--velo-porpora) 100%);
}

/* NB: niente max-width sul contenitore — restringerlo lo centrerebbe e il suo
   bordo sinistro non starebbe più in colonna con le altre sezioni, rompendo
   il ritmo verticale della pagina. La misura la danno i cap in ch sul testo. */

.section-education .eyebrow { color: var(--porpora); }

.education-body {
  font-size: clamp(16.5px, 1.6vw, 19px);
  line-height: 1.65;
  color: var(--grigio);
  margin-top: 18px;
  max-width: 58ch;
}

.education-facts {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 32px;
}

.education-facts li {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--porpora);
  background: rgba(124, 45, 138, 0.07);
  border: 1px solid rgba(124, 45, 138, 0.14);
  padding: 8px 15px;
  border-radius: 999px;
}

.education-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 34px;
  font-size: 17px;
  font-weight: 600;
  color: var(--porpora);
  border-bottom: 1.5px solid rgba(124, 45, 138, 0.3);
  padding-bottom: 3px;
  transition: gap 0.25s ease, border-color 0.25s ease;
}

.education-cta:hover {
  gap: 14px;
  border-bottom-color: var(--porpora);
}

/* ============================================================
   PRENOTAZIONE
   Unico blocco scuro della pagina: chiude con peso. Il background_color
   passato a Calendly è ESATTAMENTE questo #13161C, così il rettangolo
   dell'iframe sparisce dentro la sezione invece di galleggiarci sopra.
   ============================================================ */
.section-book {
  background: var(--ink);
  color: #F4F6FA;
}

.book-inner {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}

.section-book .section-title { color: #F9FAFD; }

.book-lead {
  font-size: clamp(17px, 1.7vw, 20px);
  color: #A9B1C0;
  margin-top: 18px;
  max-width: 34ch;
}

/* I dettagli dell'evento li scriviamo noi, nel nostro font: dentro l'iframe
   sono nascosti con hide_event_type_details=1. È qui che si vince la
   coerenza, non nei tre colori che Calendly ci lascia cambiare. */
.book-facts {
  margin-top: 34px;
  display: grid;
  gap: 14px;
  border-top: 1px solid rgba(244, 246, 250, 0.1);
  padding-top: 24px;
  max-width: 320px;
}

.book-facts > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.book-facts dt {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: #6E7788;
}

.book-facts dd {
  font-size: 15.5px;
  font-weight: 500;
  color: #F4F6FA;
}

.book-slot {
  position: relative;
  min-height: 440px;                    /* prima del consenso il box non deve essere
                                           una voragine vuota; il pavimento che conta
                                           è quello su #calendly-slot qui sotto, e la
                                           crescita al click è voluta dall'utente */
  border-radius: var(--radius-l);
  overflow: hidden;                     /* arrotonda l'iframe, che è rettangolare */
  border: 1px solid rgba(244, 246, 250, 0.1);
  /* ESATTAMENTE il colore che passiamo a Calendly come background_color:
     se il contenitore fosse di un grigio diverso, sotto l'iframe comparirebbe
     una banda più chiara e l'illusione del componente nativo cadrebbe */
  background: var(--ink);
  display: grid;
}

/* PAVIMENTO ANTI-COLLASSO — non toglierlo. Durante il caricamento Calendly
   emette page_height:2px e il contenitore collassa DAVVERO: senza questo la
   pagina fa un salto brutale. height inline non batte un min-height da foglio. */
#calendly-slot {
  min-width: 320px;
  min-height: 700px;
}

@media (max-width: 640px) {
  #calendly-slot { min-height: 1000px; }   /* il layout "small" di Calendly è più alto */
}

#calendly-slot[hidden] { display: none; }

/* --- Gate del consenso --- */
.book-consent {
  place-self: center;
  max-width: 42ch;
  padding: clamp(28px, 4vw, 44px);
  text-align: center;
  display: grid;
  justify-items: center;
  gap: 22px;
}

.book-consent-text {
  font-size: 16px;
  line-height: 1.6;
  color: #A9B1C0;
}

.book-consent[hidden] { display: none; }

.book-consent-text strong { color: #F4F6FA; font-weight: 600; }

.book-consent-alt {
  font-size: 14px;
  color: #6E7788;
}

.book-consent-alt a { color: #8A96EC; text-decoration: underline; }

/* lo spinner di Calendly vive nel NOSTRO dom: si ricolora col blu di brand */
.calendly-spinner > div { background-color: #8A96EC !important; }

/* --- Grazie --- */
.book-thanks {
  grid-column: 1 / -1;
  justify-self: center;
  max-width: 46ch;
  text-align: center;
  padding: clamp(40px, 4vw, 56px);
}

.book-thanks[hidden] { display: none; }

.book-thanks svg {
  width: 52px;
  height: 52px;
  margin-inline: auto;
  color: #8A96EC;
}

.book-thanks h3 {
  font-size: 24px;
  font-weight: 600;
  margin-top: 18px;
  letter-spacing: -0.015em;
  color: #F9FAFD;
}

.book-thanks p {
  color: #A9B1C0;
  margin-top: 8px;
}

/* ============================================================
   FOOTER
   ============================================================ */
.footer {
  background: var(--ink);
  border-top: 1px solid rgba(244, 246, 250, 0.08);
  padding-block: 36px;
}

.footer-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}

.brand-light { color: #F4F6FA; }

/* il PNG del mark è nero: sul footer scuro si inverte via filtro */
.brand-light .brand-mark { filter: invert(0.94); }

.footer-tag {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #6E7788;
  margin-right: auto;
}

.footer-legal {
  font-size: 13.5px;
  color: #6E7788;
}

/* ============================================================
   MOTION
   Regole: sottile, max 24px di traslazione, 0.6–0.8s, una volta sola.
   Eccezioni vive (in loop): il ciclo parola della hero (word-cycle,
   richiesto il 14 lug 2026), l'autoplay del carosello casi di studio
   (gestito in script.js) e il tilt 3D delle card del metodo
   (solo su hover, mitigato).
   Eccezione a parte, la più grossa: il PRISMA DEL METODO (12 ago 2026).
   È l'unico movimento del sito legato allo scroll invece che al tempo o al
   cursore, e l'unico che blocca la pagina — la sezione sta appiccicata per
   ~200vh mentre il solido gira. Regge perché ha tre valvole: sotto 761px di
   larghezza, sotto 700px d'altezza e con "riduci movimento" non si accende
   proprio, e la sezione torna a essere una colonna di card. Geometria e
   soglie stanno nel blocco IL PRISMA, il driver in script.js.
   ============================================================ */

/* --- Reveal allo scroll (via IntersectionObserver in script.js) --- */
.reveal,
.reveal-scale { opacity: 0; }

.reveal.is-visible {
  opacity: 1;
  animation: reveal-up 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: var(--d, 0s);
}

.reveal-scale.is-visible {
  opacity: 1;
  animation: reveal-scale 0.8s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* --- Metodo: le card entrano flottando con lieve inclinazione 3D --- */
.method-step.reveal.is-visible {
  animation-name: reveal-tilt;
  animation-duration: 0.85s;
}

@keyframes reveal-tilt {
  from { opacity: 0; transform: perspective(1200px) translateY(36px) rotateX(6deg); }
  to   { opacity: 1; transform: perspective(1200px) translateY(0) rotateX(0deg); }
}

@keyframes reveal-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes reveal-scale {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* Ciclo parola hero: entra dal basso, resta ~3s, esce verso l'alto
   (ritmo 3s a parola: ciclo 9s / 3 parole). L'uscita (33,3→38,3%) è
   speculare all'entrata della successiva (delay 3s + fade 0→5%): stesso
   istante, stessa easing — dissolvenza incrociata perfetta, la parola
   uscente "spinge su" quella che entra e la riga non resta mai vuota
   (prima c'era quasi 1s di buio tra una parola e l'altra). */
@keyframes word-cycle {
  0%      { opacity: 0; transform: translateY(0.4em); }
  5%      { opacity: 1; transform: translateY(0); }
  33.333% { opacity: 1; transform: translateY(0); }
  38.333% { opacity: 0; transform: translateY(-0.4em); }
  100%    { opacity: 0; transform: translateY(-0.4em); }
}

/* --- Hero: sequenza al caricamento --- */
.hero-title,
.hero-sub,
.hero-actions {
  opacity: 0;
  animation: reveal-up 0.65s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.hero-title { animation-delay: 0.1s; }
.hero-sub { animation-delay: 0.35s; }
.hero-actions { animation-delay: 0.5s; }

/* --- Reduced motion: tutto fermo, tutto visibile --- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .reveal,
  .reveal-scale,
  .hero-title,
  .hero-sub,
  .hero-actions {
    opacity: 1;
    animation: none !important;
  }

  /* Niente ciclo: mostra ferma solo la prima parola (dopo il sizer) */
  .adj-rotate { animation: none !important; opacity: 0; }
  .adj-rotate:nth-of-type(2) { opacity: 1; }

  /* Sfondo hero: le due varianti non vengono nemmeno montate da script.js
     (i listener non si attaccano proprio, non "si attaccano e non fanno nulla").
     Qui si spegne comunque la lente, per non dipendere solo dal JS. */
  .hero-lens { display: none !important; }

  /* La rastrelliera resta un accordion perfettamente funzionante: scatta
     invece di scorrere. Uno scatto istantaneo non è movimento, quindi è la
     risposta giusta — l'interazione non va disabilitata, va solo tolta
     l'animazione. */
  .team-card,
  .tm-photo,
  .tm-photo-mono,
  .tm-spine,
  .tm-text,
  .team-panel:has(.team-card[data-who="rolando"][data-pos="active"]) .tm-text[data-for="rolando"],
  .team-panel:has(.team-card[data-who="andrea"][data-pos="active"]) .tm-text[data-for="andrea"],
  .team-panel:has(.team-card[data-who="daniele"][data-pos="active"]) .tm-text[data-for="daniele"],
  .tm-photo img { transition: none !important; }

  /* Anche la nuvola scatta: il colore cambia lo stesso, non ci scivola. */
  .section-team { transition: none !important; }

  /* Senza autoplay la barra è un timer che non parte mai: resta il contatore.
     La vetrina si trascina e si naviga da tastiera esattamente come prima. */
  .cases-progress { display: none; }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1080px) {
  /* la clip scende sotto il testo invece di stringerlo */
  .method-card { grid-template-columns: auto 1fr; }
  .method-media { grid-column: 2 / -1; width: 100%; max-width: 420px; margin-top: 8px; }
}

@media (max-width: 960px) {
  .process-grid { grid-template-columns: repeat(2, 1fr); }
  .book-inner { grid-template-columns: 1fr; }

  .cases-stage { --cases-h: clamp(430px, 62vw, 520px); }

  /* la fila si accorcia: meno altezza morta accanto al ritratto */
  .team-stack { --tm-h: clamp(320px, 40vw, 420px); }
}

@media (max-width: 760px) {
  .nav-links { display: none; }

  .hero { min-height: auto; }

  .hero-inner { padding-block: clamp(64px, 10vh, 96px); }

  /* Sotto i 760 la rastrelliera non degrada: SPARISCE.
     Sono tre persone, non c'è un problema di densità da risolvere a 375px —
     e obbligare a tre tap per vedere tre facce è peggio che mostrarle. Tutte
     e tre aperte, ritratto e testo alternati.

     `display: contents` su ENTRAMBI i contenitori rende schede e testi
     fratelli nella stessa griglia. Senza, le tre foto finirebbero tutte in
     cima e i tre testi tutti in fondo: sono in due contenitori diversi, ed è
     esattamente il prezzo di aver tirato fuori il testo dalle schede per il
     desktop. L'ordine lo rimette --i, che ogni elemento porta inline.
     Il `role="list"` sul <ul> è scritto nell'HTML apposta: `display: contents`
     gli toglierebbe la semantica di lista.

     Il JS qui non serve e non viene chiamato: sotto 760px sync() scrive
     data-pos="active" su tutte e tre le schede e si ferma lì. */
  .team-panel {
    display: grid;
    gap: clamp(26px, 6vw, 40px);
  }

  .team-stack,
  .team-texts { display: contents; }

  /* NB: la selezione include [data-pos] perché il JS scrive quell'attributo e
     `.team-card[data-pos="active"]` è più specifico di `.team-card` — senza
     questo, il flex-grow della scheda aperta vincerebbe anche su mobile. */
  .team-card,
  .team-card[data-pos] {
    order: calc(var(--i) * 2);
    flex: none;
    height: clamp(300px, 74vw, 420px);
    transition: none;
  }

  /* La stessa forma di selettore del desktop, ripetuta: qui vale l'ordine nel
     file, non la specificità, e questo blocco viene dopo. `grid-area: auto` è
     obbligatorio — senza, i tre testi resterebbero impilati nella cella 1/1
     anche da fratelli, e si leggerebbero uno sopra l'altro. */
  .tm-text,
  .team-panel:has(.team-card[data-who="rolando"][data-pos="active"]) .tm-text[data-for="rolando"],
  .team-panel:has(.team-card[data-who="andrea"][data-pos="active"]) .tm-text[data-for="andrea"],
  .team-panel:has(.team-card[data-who="daniele"][data-pos="active"]) .tm-text[data-for="daniele"] {
    grid-area: auto;
    order: calc(var(--i) * 2 + 1);
    opacity: 1;
    pointer-events: auto;
    transition: none;
  }

  /* il nome grande sta già nel testo qui sotto: sul telefono il dorso non
     serve, e ruotato di 90° sarebbe solo un ostacolo */
  .tm-spine { display: none; }

  .tm-photo-mono { opacity: 1; }

  .tm-photo img { transform: none; transition: none; }

  .tm-trigger { cursor: default; }
}

@media (max-width: 560px) {
  .process-grid { grid-template-columns: 1fr; }

  .method-card { grid-template-columns: 1fr; gap: 16px; }
  .method-num { margin-top: 0; width: fit-content; }
  .method-media { grid-column: 1 / -1; max-width: none; }
  .method-ghost { font-size: 64px; transform: none; }

  .cases-stage {
    --cases-h: clamp(440px, 128vw, 500px);
    --case-w: min(340px, 84vw);
  }

  /* Il suggerimento va a capo sotto contatore e barra invece di stringerli */
  .cases-meta { flex-wrap: wrap; }
  .cases-hint { margin-left: 0; flex-basis: 100%; text-align: left; }

  .case-modal { padding: 10px; }
  .case-modal-media { max-height: 40vh; }
  .case-modal-cta { justify-self: stretch; }
}
