/* ==========================================================================
   PROGETTI: ACCESO / SPENTO
   --------------------------------------------------------------------------
   Da qui si nascondono i progetti da tutto il sito senza cancellarli.

   COME SI FA
   Ogni progetto ha gia la sua riga qui sotto, scritta ma disattivata.
   Le righe disattivate sono racchiuse fra i due simboli di commento e nel
   programma si vedono in grigio.

     - per NASCONDERE un progetto: cancella i due simboli di commento che
       racchiudono la sua riga, quello all'inizio e quello alla fine
     - per FARLO TORNARE: riscrivili

   Una riga vale per tutte le pagine insieme: home e pagina Progetti.
   Non serve toccare l'HTML.

   ATTENZIONE: nascondere non e cancellare. Il progetto resta scritto nel
   codice della pagina e la sua case study resta raggiungibile da chi ha il
   link diretto. Se un lavoro va tolto per davvero (accordo di riservatezza,
   richiesta del cliente) va cancellato, immagini comprese.
   ========================================================================== */

/* .project-card[data-progetto="la-veneranda"] { display: none; } */
/* .project-card[data-progetto="skillsprout"]  { display: none; } */
/* .project-card[data-progetto="fatturatoo"]   { display: none; } */
/* .project-card[data-progetto="buddy-growth"] { display: none; } */
/* .project-card[data-progetto="mindmatch"]    { display: none; } */

/* ==========================================================================
   Design tokens — vedi docs/design-system.md
   ========================================================================== */
:root {
  --color-primary: #F7F5F0;
  --color-secondary: #313130;
  --color-accent: #15DAC6;
  --color-accent-hover: #0FC4B1;
  --color-text-faint: #B7B7B7;
  --color-text-muted: #8B8B84;
  --color-border: #EAE7E0;
  --color-error: #E24B4A;
  --color-fill-empty: #D8D6D0;        /* grigio di partenza della CTA su fondo chiaro */
  --color-fill-empty-dark: #4A4A48;   /* la stessa cosa, su fondo scuro */

  /* Verde e rosso delle etichette "Pro:" e "Contro:" nelle schede competitor
     delle case study. Presi dal mockup, si usano solo su fondo scuro. */
  --color-pro: #19D31F;
  --color-contro: #FF6D6F;

  --font-heading: 'Oswald', sans-serif;
  --font-body: 'Manrope', sans-serif;

  --container-max: 1636px;
  --container-padding: 134px;

  /* Spigoli vivi: regola generale del sito. I bottoni restano pill. */
  --radius-card: 0;
  --radius-pill: 69px;

  /* Altezza dell'header (padding 32+32 + bottone 64). Serve al pattern a
     puntini per risalire fin sotto l'header. */
  --header-height: 128px;

  /* Immagine a cavallo fra sezione scura e chiara:
     - overlap = di quanto risale dentro la sezione scura
     - gap     = spazio bianco fra la foto di "Chi sono" e questa immagine
     Cambiando questi due valori si sposta tutto, senza toccare altro. */
  --showcase-overlap: 232px;
  --showcase-gap: 120px;

  --transition-base: 0.2s ease;
}

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

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

body {
  margin: 0;
  background: var(--color-primary);
  color: var(--color-secondary);
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.6;
}

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

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

button, input, textarea { font-family: inherit; }

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

/* ==========================================================================
   Typografia
   ========================================================================== */
h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.03em;
}

h1, h2 { text-transform: uppercase; }

h1 { font-size: 150px; line-height: 1.2; }
h2 { font-size: 46px; line-height: 1.2; }
h3 { font-size: 30px; line-height: 1.2; }

p { font-size: 18px; line-height: 30px; margin: 0; }

.text-muted { color: var(--color-text-muted); }

/* Breakpoint responsive per i titoli — dimensioni "da verificare" (vedi
   docs/design-system.md §6); soglie px scelte come convenzione standard
   in attesa di conferma visiva. */
@media (max-width: 1200px) {
  h1 { font-size: 42px; }
  h2 { font-size: 34px; }
  h3 { font-size: 28px; }
}
@media (max-width: 1024px) {
  h1 { font-size: 38px; }
  h2 { font-size: 30px; }
  h3 { font-size: 26px; }
}
@media (max-width: 768px) {
  h1 { font-size: 34px; }
  h2 { font-size: 28px; }
  h3 { font-size: 24px; }
}
@media (max-width: 480px) {
  h1 { font-size: 32px; }
  h2 { font-size: 26px; }
  h3 { font-size: 22px; }
}

/* ==========================================================================
   Layout
   ========================================================================== */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

@media (max-width: 1440px) { .container { --container-padding: 80px; } }
@media (max-width: 1200px) { .container { --container-padding: 60px; } }
@media (max-width: 1024px) { .container { --container-padding: 40px; } }
@media (max-width: 768px)  { .container { --container-padding: 24px; } }
@media (max-width: 480px)  { .container { --container-padding: 20px; } }

section { padding-block: 120px; }
@media (max-width: 1024px) { section { padding-block: 80px; } }
@media (max-width: 768px)  { section { padding-block: 56px; } }

/* ==========================================================================
   Bottoni
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  padding: 16px 32px;
  font-family: var(--font-body);
  font-size: 18px;
  line-height: 30px;
  cursor: pointer;
  border: 1px solid transparent;
  transition: var(--transition-base);
}

.btn-outline {
  border-color: var(--color-secondary);
  background: transparent;
  color: var(--color-secondary);
}
.btn-outline:hover {
  background: var(--color-accent);
  color: var(--color-secondary);
  transform: scale(1.03);
}

.btn-filled {
  background: var(--color-accent);
  color: var(--color-secondary);
}
.btn-filled:hover {
  background: var(--color-accent-hover);
  transform: scale(1.03);
}

/* Outline su sfondo scuro (es. CTA dentro sezione scura, banda del case study) */
.section-dark .btn-outline,
.cs-banda-sito .btn-outline {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.section-dark .btn-outline:hover,
.cs-banda-sito .btn-outline:hover {
  background: var(--color-accent);
  color: var(--color-secondary);
  /* Senza questo il bordo resterebbe chiaro e si vedrebbe un contorno
     bianco attorno al turchese. Il bordo prende lo stesso colore del fondo. */
  border-color: var(--color-accent);
}

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 32px;
  /* Trasparente: sotto ci deve passare il pattern a puntini dell'hero.
     z-index tiene i link cliccabili sopra il pattern. */
  position: relative;
  z-index: 2;
  background: transparent;
}

/* --- Logo -----------------------------------------------------------------
   Il logo resta una normale <img>: cosi si vede sempre, anche se il CSS non
   arriva o e vecchio in cache. Il colore al passaggio del mouse e un
   SECONDO strato appoggiato sopra, non una modifica all'immagine.

   Perche due strati e non uno: un <img> e un documento a parte, e il CSS
   della pagina non ci puo entrare a cambiargli i colori. Lo strato sopra e
   invece un rettangolo pieno di verde acqua a cui la stessa forma del logo
   viene applicata come stampino ("mask"), e che compare in dissolvenza solo
   quando serve.

   Se un browser non conoscesse "mask", lo strato sopra semplicemente non
   comparirebbe: resterebbe il logo normale che si ingrandisce. Niente si
   rompe. */
.logo {
  position: relative;
  display: inline-block;
  line-height: 0;          /* toglie lo spazio che una riga di testo lascia sotto */
}
.logo img {
  height: 56px;
  width: auto;
  display: block;
  transition: transform var(--transition-base);
}

.logo::after {
  content: '';
  position: absolute;
  inset: 0;                /* stessa identica area dell'immagine sotto */
  background-color: var(--color-accent);
  -webkit-mask: url(../images/logo-f.svg) no-repeat center / contain;
          mask: url(../images/logo-f.svg) no-repeat center / contain;
  opacity: 0;
  transition: opacity var(--transition-base), transform var(--transition-base);
  pointer-events: none;
}

/* :focus-visible = quando ci si arriva col tasto Tab invece che col mouse */
.logo:hover img,
.logo:focus-visible img,
.logo:hover::after,
.logo:focus-visible::after { transform: scale(1.08); }

.logo:hover::after,
.logo:focus-visible::after { opacity: 1; }

.main-nav { display: flex; }

.nav-list {
  display: flex;
  align-items: center;
  gap: 40px;
}

.nav-link {
  position: relative;
  font-size: 18px;
  line-height: 30px;
  padding-bottom: 6px;
  transition: color var(--transition-base);
}

/* Un unico indicatore per entrambi gli stati: un pallino turchese sotto la
   voce. Esiste sempre nel DOM ma parte invisibile (opacity 0), cosi puo
   comparire in dissolvenza senza far muovere il testo. */
.nav-link::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-accent);
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity var(--transition-base);
}

/* Hover: testo turchese + pallino */
.nav-link:hover { color: var(--color-accent); }
.nav-link:hover::after { opacity: 1; }

/* Pagina corrente: grassetto + lo stesso pallino turchese, sempre visibile */
.nav-link.is-active { font-weight: 700; }
.nav-link.is-active::after { opacity: 1; }

.header-actions { display: flex; align-items: center; gap: 24px; }

.nav-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  flex-direction: column;
  gap: 5px;
}
.nav-toggle span {
  width: 26px;
  height: 2px;
  background: var(--color-secondary);
  display: block;
}

@media (max-width: 768px) {
  .nav-toggle { display: flex; }
  .main-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--color-primary);
    border-bottom: 1px solid var(--color-border);
    display: none;
    padding: 24px;
  }
  .main-nav.is-open { display: block; }
  .nav-list { flex-direction: column; align-items: flex-start; gap: 20px; }
  .site-header { position: relative; }
}

/* ==========================================================================
   Freccia "torna su" (pagine case study)
   --------------------------------------------------------------------------
   Sta ferma in basso a destra mentre la pagina scorre: "fixed" vuol dire
   posizionata rispetto alla finestra, non rispetto alla pagina, quindi non
   scorre via col resto.

   E' un semplice link a un'ancora (#inizio, che e l'header): funziona anche
   senza JavaScript, e con lo scorrimento morbido qui sotto risale in modo
   fluido senza una riga di codice.

   Colore: e il verde acqua d'accento, lo stesso dei bottoni pieni del sito.
   Serve perche la freccia galleggia sopra sezioni chiare e scure che si
   alternano: un colore neutro sparirebbe sull'una o sull'altra.
   ========================================================================== */
.torna-su {
  position: fixed;
  right: 32px;
  bottom: 32px;
  z-index: 900;          /* sopra la pagina, sotto ai popup (che stanno a 1000) */

  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-secondary);

  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--transition-base), transform var(--transition-base);
}
.torna-su svg {
  width: 22px;
  height: 22px;
  display: block;
}
.torna-su:hover,
.torna-su:focus-visible {
  background: var(--color-accent-hover);
  transform: translateY(-3px);
}

/* Lo scorrimento morbido serve solo a questo link. Chi ha chiesto al sistema
   operativo di ridurre le animazioni non lo vuole: per quelli il salto resta
   istantaneo. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

@media (max-width: 768px) {
  .torna-su { right: 16px; bottom: 16px; width: 48px; height: 48px; }
  .torna-su svg { width: 18px; height: 18px; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  border-top: 1px solid var(--color-border);
  padding-block: 48px 32px;
}

/* Griglia a 3 colonne invece di space-between: le due colonne laterali sono
   entrambe 1fr, quindi la nav centrale cade sull'asse esatto della pagina,
   lo stesso della riga "Realizzato da...". Con space-between la nav veniva
   spinta fuori centro perche logo e social hanno larghezze diverse. */
.footer-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.footer-nav { justify-self: center; }
.footer-social { justify-self: end; }

.footer-nav .nav-list { gap: 32px; }

.footer-social {
  display: flex;
  align-items: center;
  gap: 28px;
}
.footer-social a {
  display: inline-flex;
  color: var(--color-secondary);
  transition: color var(--transition-base);
}
/* height fissa + width auto: i due loghi hanno proporzioni diverse
   (Behance e piu largo) ma restano alti uguali. currentColor fa
   ereditare all'icona il colore del link, hover compreso. */
.footer-social svg {
  height: 32px;
  width: auto;
  display: block;
}
.footer-social a:hover { color: var(--color-accent); }

.footer-bottom {
  text-align: center;
  margin-top: 32px;
  font-size: 16px;
  color: var(--color-text-muted);
}

@media (max-width: 768px) {
  .footer-top {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
  }
  .footer-social { justify-self: center; }
  /* .nav-list su mobile e allineata a sinistra perche serve cosi nel menu
     a tendina dell'header. Nel footer la si ricentra. */
  .footer-nav .nav-list { align-items: center; }
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  /* I 48px in basso fanno finire il pattern a puntini poco sotto
     la scritta "EXPERIENCE.", come nel mockup. */
  padding-block: 152px 48px;
}

/* Pattern a puntini: un solo pallino ripetuto da CSS, senza immagini.
   Il top negativo lo fa risalire fin sopra l'header, che è trasparente. */
.hero-dotgrid {
  position: absolute;
  top: calc(-1 * var(--header-height));
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  opacity: 0.08;            /* 8% */
  background-image: radial-gradient(var(--color-secondary) 1.5px, transparent 1.5px);
  background-size: 24px 24px;
  pointer-events: none;
}

/* Puntini interattivi: il JavaScript infila un <canvas> dentro .hero-dotgrid e
   aggiunge questa classe. Solo a quel punto lo sfondo CSS si spegne. Se il
   canvas non viene creato (JavaScript assente, browser vecchio, schermo touch,
   "riduci animazioni") la classe non arriva e restano i puntini di sempre.

   opacity torna a 1 perche col canvas la trasparenza la decide il disegno,
   puntino per puntino: quelli vicino al mouse devono poter diventare piu
   scuri degli altri, e con un'opacita unica sul contenitore non si potrebbe. */
.hero-dotgrid.ha-canvas {
  background-image: none;
  opacity: 1;
}
.hero-dotgrid canvas { display: block; width: 100%; height: 100%; }

/* position: relative serve per ancorare il paragrafo posizionato in alto a destra */
.hero-inner { position: relative; z-index: 1; }

/* Stessa scala del titolo dell'hero: 250px sul mockup a 1920 (13vw). */
.hero-title,
.page-title {
  font-size: clamp(48px, 13vw, 250px);
  line-height: 0.92;
  margin: 0;
}
.hero-line { display: block; }
.hero-line-1 { color: var(--color-text-faint); }
.hero-line-2 { color: var(--color-text-muted); }
.hero-line-3 { color: var(--color-secondary); }

.hero-intro {
  position: absolute;
  top: 30px;
  right: 0;
  max-width: 470px;
  display: flex;
  align-items: flex-start;
  gap: 46px;
}
.hero-asterisk { flex-shrink: 0; width: 60px; height: auto; }

/* Sotto i 1200px il paragrafo non ci sta più accanto al titolo:
   torna nel flusso normale, sotto. */
@media (max-width: 1200px) {
  .hero-intro {
    position: static;
    max-width: none;
    margin-top: 40px;
    gap: 24px;
  }
  .hero-asterisk { width: 40px; }
}

@media (max-width: 768px) {
  .hero { padding-block: 80px 40px; }
  /* Su mobile il titolo e corto rispetto alla riga e resterebbe troppo
     piccolo: si alza il fattore da 13vw a 16vw. A 375px fa 60px, contro
     i 65px massimi che entrano senza andare a capo. */
  .hero-title,
  .page-title { font-size: clamp(48px, 16vw, 250px); }
}

/* ==========================================================================
   Striscia strumenti (marquee)
   ========================================================================== */
.tools {
  padding-block: 100px 60px;   /* ~150px di stacco dall'hero, come nel mockup */
  overflow: hidden;   /* nasconde la parte di striscia fuori dallo schermo */
}

.tools-track {
  display: flex;
  width: max-content;
  animation: tools-scroll 40s linear infinite;
}

.tools-row {
  display: flex;
  align-items: center;
  gap: 185px;
  padding-right: 185px;
}

.tools-row img {
  width: 98px;
  height: 98px;
  object-fit: contain;
}

/* Scorre di metà larghezza: a quel punto la seconda copia è esattamente
   dove stava la prima, quindi il salto a inizio animazione è invisibile. */
@keyframes tools-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Rispetta chi ha disattivato le animazioni nelle impostazioni di sistema */
@media (prefers-reduced-motion: reduce) {
  .tools-track { animation: none; }
}

@media (max-width: 768px) {
  .tools { padding-block: 64px 40px; }
  .tools-row { gap: 80px; padding-right: 80px; }
  .tools-row img { width: 64px; height: 64px; }
}

/* ==========================================================================
   Intestazione di sezione centrata
   ========================================================================== */
.section-head {
  text-align: center;
  max-width: 900px;
  margin: 0 auto 72px;
}
.section-head h2 { margin-bottom: 24px; }

@media (max-width: 768px) {
  .section-head { margin-bottom: 48px; }
}

/* ==========================================================================
   Griglia progetti / Card
   ========================================================================== */
.project-grid {
  display: grid;
  /* minmax(0, 1fr) e non 1fr: senza il minimo a 0 una colonna si allarga
     per far stare la larghezza nativa dell'immagine e le due si sbilanciano. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 42px;
}

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

.project-card { display: block; }

/* aspect-ratio tiene le proporzioni del Figma (797x464) a qualsiasi larghezza */
.project-card-image {
  position: relative;      /* ancora l'overlay qui sotto */
  overflow: hidden;
  border-radius: var(--radius-card);
  aspect-ratio: 797 / 464;
  background: var(--color-border);
}

/* Velo chiarissimo che compare sull'immagine al passaggio del mouse.
   pointer-events: none serve perche il velo sta sopra l'immagine e
   altrimenti "mangerebbe" il click sul link della card. */
.project-card-image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--color-primary);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-base);
}
.project-card:hover .project-card-image::after { opacity: 0.1; }
.project-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}
.project-card:hover .project-card-image img {
  transform: scale(1.05);
}

.project-card-body { padding-top: 24px; }

.project-card-title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 24px;
  line-height: 30px;
  letter-spacing: 0;
  margin: 0 0 6px;
}

.project-card-meta { font-size: 18px; }

/* Card "Coming soon": stesso ingombro dell'immagine, nessun link */
/* Card "Coming soon": rettangolo scuro con la scritta grande dentro.
   container-type lo rende un "contenitore misurabile": da qui in giu
   l'unita cqw vale l'1% della larghezza DI QUESTA CARD (non della finestra),
   quindi la scritta resta sempre in proporzione al rettangolo, a qualsiasi
   larghezza di schermo e anche quando la griglia passa a una colonna sola. */
.project-card-soon {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  aspect-ratio: 797 / 464;
  background: var(--color-secondary);
  padding: 6cqw;           /* 48px su una card da 797, in proporzione ovunque */
  container-type: inline-size;
}
.project-card-soon h3 {
  font-family: var(--font-heading);
  font-size: 14cqw;        /* 14% della larghezza della card, come nel mockup */
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--color-primary);
}

/* Variante testuale della card (usata in progetti.html) */
.project-card-text {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  aspect-ratio: 797 / 464;
  background: var(--color-secondary);
  color: var(--color-primary);
  border-radius: var(--radius-card);
  padding: 48px;
}

/* Riquadro grigio delle immagini non ancora esportate, fuori dalle case
   study: la foto di "Chi sono" in home, le due fasce a cavallo e la foto
   grande della pagina Chi sono. Come nelle case study, la classe e il nome
   del file li mette il JavaScript quando il caricamento fallisce; il nome
   vero e proprio lo scrive la regola piu sotto, insieme a quelle delle case
   study. */
.about-home-image.is-mancante,
.showcase-image.is-mancante,
.about-foto.is-mancante {
  position: relative;
  background: #D9D9D9;
  border-radius: var(--radius-card);
}

/* ==========================================================================
   Sezione scura
   ========================================================================== */
.section-dark {
  background: var(--color-secondary);
  color: var(--color-primary);
}

/* Sezione su fondo beige, un gradino piu scuro dello sfondo di pagina.
   La usa SkillSprout per il blocco "Logo + Motion design": nel mockup quella
   parte e staccata dal resto proprio con questo colore (#EAE7E0, lo stesso
   gia in uso per i bordi). */
.section-beige { background: var(--color-border); }

/* Il riquadro grigio di un'immagine mancante usa lo stesso colore del bordo,
   che qui e anche lo sfondo della sezione: sparirebbe. Dentro alla sezione
   beige lo scuriamo di un gradino, cosi si vede. */
.section-beige .cs-figura { background: var(--color-fill-empty); }
.section-dark .text-muted { color: #C7C7C2; }

/* ==========================================================================
   CTA finale
   ========================================================================== */
.cta-final {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  flex-wrap: wrap;
}
.cta-final h2 { max-width: 900px; }

@media (max-width: 768px) {
  .cta-final { flex-direction: column; align-items: flex-start; }
}

/* ==========================================================================
   Processo di design (cerchio con le 4 tappe)
   ========================================================================== */
/* La fascia illustrata sotto questa sezione e stata tolta per ora. Finche
   non torna, il padding in basso e normale. Quando l'immagine tornera,
   rimettere: calc(var(--showcase-overlap) + var(--showcase-gap)) — serve a
   lasciare il buco in cui l'immagine sale. */
.dark-block {
  padding-block: 120px;
}

.process {
  position: relative;
  width: 100%;
  max-width: 805px;
  margin: 0 auto;
  aspect-ratio: 1;          /* quadrato: dentro ci sta il cerchio */
  display: flex;
  align-items: center;
  justify-content: center;
}

.process-ring {
  position: absolute;
  inset: 0;
  border: 1px solid rgba(247, 245, 240, 0.35);
  border-radius: 50%;
}

.process-title {
  position: relative;
  text-align: center;
  font-size: clamp(48px, 6.25vw, 120px);   /* 120px sul mockup a 1920 */
  line-height: 1.05;
  color: var(--color-primary);
}

.process-steps { position: absolute; inset: 0; }

/* Ogni tappa è una pillola chiara appoggiata sul bordo del cerchio.
   translate(-50%, -50%) la centra sul punto indicato da top/left. */
.process-step {
  position: absolute;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  background: var(--color-primary);
  color: var(--color-secondary);
  border-radius: var(--radius-pill);
  padding: 0.5em 1em;
  font-size: clamp(18px, 1.67vw, 32px);    /* 32px sul mockup a 1920 */
  font-weight: 700;
  line-height: 1.375;
}
.process-step-1 { top: 10%; left: 15%; }   /* Ricerca */
.process-step-2 { top: 10%; left: 85%; }   /* Architettura */
.process-step-3 { top: 82%; left: 15%; }   /* Interfaccia */
.process-step-4 { top: 82%; left: 85%; }   /* Prototipo */

/* Sotto i 768px il cerchio diventa illeggibile: le tappe passano
   a una lista impilata sotto il titolo. */
@media (max-width: 768px) {
  .dark-block {
    padding-block: 64px;
  }
  .process {
    aspect-ratio: auto;
    flex-direction: column;
    gap: 32px;
  }
  .process-ring { display: none; }
  .process-steps {
    position: static;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
  }
  .process-step { position: static; transform: none; }
}

/* ==========================================================================
   Blocco "Chi sono" in home
   ========================================================================== */
.about-home {
  display: grid;
  grid-template-columns: 1fr 535px;
  gap: 80px;
  align-items: start;
  margin-top: 200px;
}

.about-home-text h2 { margin-bottom: 24px; }
.about-home-text p { max-width: 650px; margin-bottom: 32px; }

.about-home-image { aspect-ratio: 535 / 581; }
.about-home-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-card);
}

@media (max-width: 1024px) {
  .about-home {
    grid-template-columns: 1fr;
    gap: 48px;
    margin-top: 120px;
  }
  .about-home-image { aspect-ratio: 16 / 10; }
}

/* ==========================================================================
   Immagine a cavallo fra sezione scura e chiara
   ========================================================================== */
.showcase { padding-block: 0 120px; }

/* Il margine negativo la fa risalire dentro la sezione scura sopra:
   nel Figma l'immagine sta esattamente a metà tra le due. */
.showcase-image {
  aspect-ratio: 1310 / 464;
  margin-top: calc(-1 * var(--showcase-overlap));
}
.showcase-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-card);
}

@media (max-width: 768px) {
  .showcase { padding-block: 0 64px; }
  /* Su mobile il formato 1310x464 diventa una striscia troppo bassa:
     si passa a un 3:2, proporzione fotografica standard. */
  .showcase-image { aspect-ratio: 3 / 2; }
}

/* Su schermi piu stretti overlap e stacco si riducono in proporzione */
@media (max-width: 1024px) {
  :root { --showcase-overlap: 180px; --showcase-gap: 90px; }
}
@media (max-width: 768px) {
  :root { --showcase-overlap: 120px; --showcase-gap: 60px; }
}

/* ==========================================================================
   CTA finale della home
   ========================================================================== */
.cta-home { padding-block: 40px 120px; }

.cta-home-inner {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
  flex-wrap: wrap;
}

.cta-home-title {
  max-width: 900px;
}

/* Una riga per <span>. Questi sono i colori finali: restano gli stessi di
   prima, e sono anche quelli che si vedono se le animazioni sono spente. */
.cta-home-title .fill-line {
  display: block;
  color: var(--color-text-muted);
}
.cta-home-title .fill-line-strong { color: var(--color-secondary); }

@media (max-width: 768px) {
  .cta-home { padding-block: 24px 64px; }
  .cta-home-inner { flex-direction: column; align-items: flex-start; }

  /* Su desktop ogni riga e un blocco a se, come nel mockup. Su mobile quei
     quattro blocchi andavano a capo ognuno per conto suo e lasciavano righe
     con una parola sola ("PARLARE", "L'INIZIO"). Rendendoli "inline" le tre
     righe della domanda tornano a essere un testo unico che riempie la
     larghezza; la frase finale resta un blocco a se, cosi va comunque a capo.
     Corpo e interlinea non cambiano: cambia solo dove il testo va a capo. */
  .cta-home-title .fill-line { display: inline; }
  .cta-home-title .fill-line-strong { display: block; }

  /* box-decoration-break: clone -> quando un testo inline occupa piu righe,
     ogni riga riceve la sua copia dello sfondo. Senza questo il riempimento
     colorato si spalmerebbe male sulle righe successive. */
  .cta-home-title .fill-line {
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
  }

  /* Miglioria dove supportata: evita che l'ultima riga resti con una parola
     sola. Dove non c'e supporto viene semplicemente ignorata. */
  .cta-home-title { text-wrap: pretty; }
}

/* ==========================================================================
   Intestazione delle pagine interne (es. Progetti)
   ========================================================================== */
.page-head {
  position: relative;
  padding-block: 152px 0;
  text-align: center;
}

.page-head .container { position: relative; z-index: 1; }

/* Il pattern a puntini sale sopra l'header (che e trasparente) e scende
   oltre il fondo di questa sezione, fino a coprire la prima riga di card,
   come nel mockup. --dotgrid-oltre e di quanto sborda in basso. */
.page-head {
  --dotgrid-oltre: 520px;
}
.page-head .hero-dotgrid {
  bottom: calc(-1 * var(--dotgrid-oltre));
}

.page-head .page-title { margin-bottom: 0; }

@media (max-width: 1200px) { .page-head { --dotgrid-oltre: 380px; } }
@media (max-width: 1024px) { .page-head { --dotgrid-oltre: 300px; } }
@media (max-width: 768px)  {
  .page-head { padding-block: 80px 0; --dotgrid-oltre: 200px; }
}

/* Spazio fra l'intestazione e la griglia dei progetti */
.projects-page { padding-block: 140px 120px; }
@media (max-width: 1024px) { .projects-page { padding-block: 100px 80px; } }
@media (max-width: 768px)  { .projects-page { padding-block: 72px 56px; } }

/* ==========================================================================
   CTA finale dentro una sezione scura (pagina Progetti)
   --------------------------------------------------------------------------
   Sulla home la CTA sta su fondo chiaro. Qui il fondo e scuro, quindi i
   colori vanno ribaltati: l'ultima riga diventa chiara invece che scura, e
   il grigio da cui parte il riempimento deve essere piu scuro del fondo,
   non piu chiaro.
   ========================================================================== */
/* Come .dark-block: la fascia sotto e sospesa, quindi padding normale. */
.cta-dark {
  padding-block: 120px;
}

.section-dark .cta-home-title .fill-line-strong { color: var(--color-primary); }

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .anim-on .section-dark .cta-home-title .fill-line {
    background-image: linear-gradient(
      to right,
      var(--fill) 50%,
      var(--color-fill-empty-dark) 50%
    );
  }
  .anim-on .section-dark .cta-home-title .fill-line-strong {
    --fill: var(--color-primary);
  }
}

/* L'immagine sotto la CTA scura sborda verso il basso, uscendo dalla
   sezione: e lo stesso meccanismo della home, a specchio. */
.showcase-sotto { padding-block: 0 120px; }
.showcase-sotto .showcase-image {
  margin-top: calc(-1 * var(--showcase-overlap));
}

@media (max-width: 768px) {
  .cta-dark { padding-block: 64px; }
  .showcase-sotto { padding-block: 0 64px; }
}

/* ==========================================================================
   Pagina "Chi sono"
   --------------------------------------------------------------------------
   Impianto: un'intestazione col nome grande e la foto, poi una serie di
   sezioni a due colonne — etichetta a sinistra, contenuto a destra.
   ========================================================================== */

/* --- Testa: nome grande con la foto dietro ------------------------------- */
.about-head {
  position: relative;
  padding-block: 152px 0;
  text-align: center;
  --dotgrid-oltre: 420px;
}
.about-head .container { position: relative; z-index: 1; }
.about-head .hero-dotgrid { bottom: calc(-1 * var(--dotgrid-oltre)); }

/* z-index 1: il nome deve passare SOPRA la foto, come nel mockup */
.about-name {
  position: relative;
  z-index: 1;
}
.about-name .hero-line { display: block; }

.about-foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-card);
}

/* La foto PARTE tutta sotto al nome: appena aperta la pagina si vede intera,
   senza il titolo che le passa sopra. E poi lo scroll a farla salire fino a
   scorrere dietro all'ultima riga (vedi piu sotto, "--su" scritto dal
   JavaScript). Prima invece partiva gia sovrapposta, con un margine negativo,
   e l'effetto di risalita non si capiva. */
.about-foto {
  position: relative;
  z-index: 0;
  width: min(510px, 60vw);
  aspect-ratio: 510 / 515;
  margin: 24px auto 0;
}
.about-foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 768px) {
  .about-head { padding-block: 80px 0; --dotgrid-oltre: 180px; }
  .about-foto { margin-top: 16px; }
}

/* --- Sezioni a due colonne ----------------------------------------------- */
.about-sezioni { padding-block: 140px 120px; }

.about-riga {
  display: grid;
  grid-template-columns: 420px 1fr;
  gap: 158px;
  align-items: start;
  margin-bottom: 120px;
}
.about-riga:last-child { margin-bottom: 0; }

/* L'etichetta di sinistra: Oswald, maiuscolo, piu piccola dei titoli */
.about-etichetta {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 30px;
  line-height: 1.2;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  margin: 0;
}

@media (max-width: 1200px) {
  .about-riga { grid-template-columns: 320px 1fr; gap: 80px; }
}
@media (max-width: 1024px) {
  .about-sezioni { padding-block: 100px 80px; }
  /* Sotto i 1024px le due colonne diventano una: l'etichetta va sopra */
  .about-riga { grid-template-columns: 1fr; gap: 24px; margin-bottom: 80px; }
}
@media (max-width: 768px) {
  .about-sezioni { padding-block: 72px 56px; }
  .about-riga { margin-bottom: 56px; }
  .about-etichetta { font-size: 24px; }
}

/* --- Voci: esperienza, educazione, corsi --------------------------------- */
.about-voce { margin-bottom: 56px; }
.about-voce:last-child { margin-bottom: 0; }

.about-voce-titolo {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 24px;
  line-height: 32px;
  letter-spacing: 0;
  text-transform: none;
  margin: 0 0 4px;
}

/* Riga "azienda • periodo": il separatore e un <span> vero e non un
   carattere dentro al testo, cosi un lettore di schermo non lo legge. */
.about-voce-meta {
  font-size: 18px;
  color: var(--color-text-muted);
  margin-bottom: 20px;
}
.about-voce-meta .sep {
  display: inline-block;
  margin: 0 10px;
}

.about-voce-testo { margin-bottom: 16px; }

.about-elenco {
  list-style: disc;
  padding-left: 20px;
  margin: 0;
}
.about-elenco li {
  font-size: 18px;
  line-height: 30px;
  margin-bottom: 10px;
}
.about-elenco li::marker { color: var(--color-text-muted); }

/* --- Link "Certificato" con la freccina ---------------------------------- */
.about-link {
  font-size: 18px;
  color: var(--color-secondary);
  border-bottom: 1px solid transparent;
  transition: var(--transition-base);
}
.about-link:hover {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}
.about-link .freccia { display: inline-block; margin-left: 4px; }

.about-link-riga { display: flex; flex-wrap: wrap; align-items: center; gap: 0; }
.about-link-riga .sep { margin: 0 12px; color: var(--color-text-muted); }

/* --- Etichette di skillset e programmi ------------------------------------
   Sono etichette, non bottoni: bordo sottile e angoli appena smussati, come
   nel mockup. Non seguono la regola degli spigoli vivi, che riguarda le
   immagini e i riquadri. */
.about-tag-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.about-tag {
  border: 1px solid var(--color-secondary);
  border-radius: 16px;
  padding: 16px 24px;
  font-size: 18px;
  line-height: 1;
}

@media (max-width: 768px) {
  .about-tag { padding: 12px 18px; font-size: 16px; }
  .about-tag-lista { gap: 12px; }
}

/* ==========================================================================
   Popup di contatto
   ========================================================================== */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(49, 49, 48, 0.6);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 1000;
  opacity: 0;
  transition: opacity var(--transition-base);
}
.modal-overlay.is-open {
  display: flex;
  opacity: 1;
}

.modal {
  position: relative;
  width: 100%;
  max-width: 720px;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--color-secondary);
  color: var(--color-primary);
  border-radius: var(--radius-card);
  padding: 48px;
  transform: scale(0.96);
  transition: transform var(--transition-base);
}
.modal-overlay.is-open .modal { transform: scale(1); }

/* Popup del design system: quasi a tutto schermo, perche dentro c'e una
   tavola nata per il desktop. Niente padding: il riquadro col design system
   arriva fino ai bordi, e il fondo e chiaro perche quella tavola ha uno
   sfondo chiaro suo e uno stacco scuro attorno sembrerebbe una cornice. */
.modal-ds {
  max-width: 1440px;
  height: 92vh;
  max-height: 92vh;
  padding: 0;
  overflow: hidden;          /* a scorrere ci pensa l'iframe dentro */
  background: var(--color-primary);
  color: var(--color-secondary);
  display: flex;
  flex-direction: column;
}

.modal-ds-testa {
  display: flex;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
  padding: 24px 72px 20px 32px;   /* 72px a destra: lo spazio della X */
  border-bottom: 1px solid var(--color-border);
}
.modal-ds-testa h2 { margin: 0; padding: 0; }

.modal-ds-link {
  font-size: 16px;
  color: var(--color-text-muted);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}
.modal-ds-link:hover { color: var(--color-secondary); }

/* flex: 1 = "prenditi tutta l'altezza che avanza". Senza, un iframe si
   fermerebbe alla sua altezza di default (150px) e il design system si
   vedrebbe da uno spiraglio. */
.modal-ds-telaio {
  flex: 1;
  width: 100%;
  border: 0;
  display: block;
}

/* La X del popup del design system sta su fondo chiaro, non scuro */
.modal-ds .modal-close { color: var(--color-secondary); }


.modal-close {
  position: absolute;
  top: 24px;
  right: 24px;
  background: none;
  border: none;
  color: var(--color-primary);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  padding: 8px;
}
.modal-close:hover { color: var(--color-accent); }

.modal h2 { margin-bottom: 32px; padding-right: 40px; }

/* ==========================================================================
   Popup "Contattami" — impaginato come il mockup "Desktop - Form v2"
   --------------------------------------------------------------------------
   Al posto del titolo c'e l'asterisco del sito, poi due righe di
   presentazione, l'indirizzo email e infine il form. Il titolo vero e
   ancora nel codice ma nascosto (.visually-hidden), cosi chi naviga con un
   lettore di schermo sente comunque "Contattami" all'apertura.
   ========================================================================== */
.modal-contatti {
  max-width: 1018px;
  padding: clamp(32px, 5.5vw, 82px);
  text-align: center;
}

.modal-contatti-asterisco {
  display: block;
  width: 60px;
  height: auto;
  margin: 0 auto 40px;
}

.modal-contatti-intro {
  font-size: 18px;
  line-height: 1.6;
  margin: 0 0 18px;
  text-wrap: pretty;
}

/* L'indirizzo email: icona busta + testo, su una riga sola. */
.modal-contatti-mail {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  margin: 34px 0 62px;
  font-size: 20px;
  color: var(--color-primary);
  text-decoration: none;
  transition: color var(--transition-base);
}
.modal-contatti-mail svg {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}
.modal-contatti-mail:hover,
.modal-contatti-mail:focus-visible { color: var(--color-accent); }

/* Il form torna allineato a sinistra: solo l'intestazione e centrata. */
.modal-contatti #contact-form { text-align: left; }
.modal-contatti .form-row { gap: 38px; margin-bottom: 24px; }
.modal-contatti .form-field input,
.modal-contatti .form-field textarea { padding: 20px 16px; }
.modal-contatti .form-field textarea { min-height: 183px; }

.modal-contatti-azioni {
  text-align: center;
  margin-top: 40px;
}
.btn-invia { min-width: 220px; }

/* Il fondo del popup e scuro, quindi il bordo e il testo del pulsante
   devono essere chiari — come gia succede nelle sezioni scure del sito. */
.modal-contatti .btn-outline {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.modal-contatti .btn-outline:hover,
.modal-contatti .btn-outline:focus-visible {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-secondary);
}

.modal-contatti .form-status { text-align: center; margin-top: 24px; }

/* La X di chiusura qui e un po' piu grande: il popup e largo 1018px e con
   la misura standard (24px) si perdeva nell'angolo. */
.modal-contatti .modal-close {
  font-size: 34px;
  top: 28px;
  right: 28px;
}

@media (max-width: 768px) {
  .modal-contatti-asterisco { width: 44px; margin-bottom: 28px; }
  .modal-contatti-intro { font-size: 16px; }
  .modal-contatti-mail { margin: 26px 0 40px; font-size: 17px; gap: 12px; }
  .modal-contatti-mail svg { width: 22px; height: 22px; }
  .modal-contatti .form-row { gap: 0; }
  .modal-contatti .form-field textarea { min-height: 140px; }
  .btn-invia { width: 100%; }
}

/* ==========================================================================
   Form
   ========================================================================== */
.form-row {
  display: flex;
  gap: 24px;
  margin-bottom: 20px;
}
.form-row .form-field { flex: 1; }

.form-field { margin-bottom: 20px; }
.form-field.form-field-wide { width: 100%; }

.form-field label {
  display: block;
  font-size: 16px;
  margin-bottom: 8px;
}

.form-field input,
.form-field textarea {
  width: 100%;
  background: var(--color-primary);
  color: var(--color-secondary);
  border: 2px solid transparent;
  border-radius: var(--radius-card);
  padding: 14px 16px;
  font-size: 16px;
  outline: none;
  transition: border-color var(--transition-base);
}
.form-field textarea { resize: vertical; min-height: 140px; }

.form-field input::placeholder,
.form-field textarea::placeholder { color: var(--color-text-muted); }

.form-field input:focus,
.form-field textarea:focus {
  border-color: var(--color-accent);
}

.form-field.has-error input,
.form-field.has-error textarea {
  border-color: var(--color-error);
}
.form-error {
  display: block;
  color: var(--color-error);
  font-size: 16px;
  margin-top: 8px;
}

.form-field input:disabled,
.form-field textarea:disabled,
.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.form-status {
  font-size: 18px;
}
.form-status.form-status-success { color: var(--color-primary); }
.form-status.form-status-success strong { color: var(--color-accent); }
.form-status.form-status-error { color: var(--color-error); }

@media (max-width: 600px) {
  .form-row { flex-direction: column; gap: 0; }
}


/* ==========================================================================
   Animazioni

   Regola di sicurezza: tutto quello che parte NASCOSTO sta sotto ".anim-on".
   Quella classe la mette lo script nel <head> di index.html, e solo se il
   JavaScript funziona e l'utente non ha chiesto di ridurre le animazioni.
   Senza quella classe niente qui dentro si applica: la pagina resta visibile.
   ========================================================================== */

/* --- Hero: le tre righe entrano in dissolvenza, una dopo l'altra --------- */
.anim-on .hero-line {
  opacity: 0;
  /* forwards = alla fine dell'animazione l'elemento RESTA come e arrivato
     (visibile), invece di tornare al punto di partenza. */
  animation: fade-in 0.8s ease forwards;
}
.anim-on .hero-line-1 { animation-delay: 0.1s; }
.anim-on .hero-line-2 { animation-delay: 0.8s; }
.anim-on .hero-line-3 { animation-delay: 1.5s; }

@keyframes fade-in {
  to { opacity: 1; }
}

/* --- Hero: le singole lettere si alzano al passaggio del mouse ----------- */
/* Le <span> le crea il JavaScript. inline-block serve perche una <span>
   normale non accetta lo spostamento verticale. */
.hero-char {
  display: inline-block;
  transition: transform 0.25s ease;
}
.anim-on .hero-char:hover { transform: translateY(-0.07em); }

/* --- Asterisco che gira lentamente --------------------------------------- */
.anim-on .hero-asterisk,
.anim-on .modal-contatti-asterisco {
  animation: spin 14s linear infinite;   /* un giro ogni 14 secondi */
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* --- Card progetti: entrano dal basso ------------------------------------ */
/* Ogni card viene osservata da sola. Sul desktop le due card della stessa
   riga hanno lo stesso bordo superiore, quindi entrano nello schermo nello
   stesso istante e si animano insieme, a coppie. Su mobile la griglia e a
   una colonna, quindi ogni card e una riga a se e arrivano una alla volta.
   Non serve nessun calcolo: e la griglia stessa a dettare il ritmo. */
.anim-on .project-card {
  opacity: 0;
  transform: translateY(48px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.anim-on .project-card.is-visible {
  opacity: 1;
  transform: none;
}

/* --- Sezione "Chi sono": gli elementi entrano scaglionati ---------------- */
.anim-on .about-home-text h2,
.anim-on .about-home-text p,
.anim-on .about-home-text .btn,
.anim-on .about-home-image {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.anim-on .about-home.is-visible h2,
.anim-on .about-home.is-visible p,
.anim-on .about-home.is-visible .btn,
.anim-on .about-home.is-visible .about-home-image {
  opacity: 1;
  transform: none;
}
/* I ritardi danno l'ordine di entrata: titolo, testo, bottone, foto. */
.anim-on .about-home.is-visible h2                 { transition-delay: 0s; }
.anim-on .about-home.is-visible p                  { transition-delay: 0.15s; }
.anim-on .about-home.is-visible .btn               { transition-delay: 0.3s; }
.anim-on .about-home.is-visible .about-home-image  { transition-delay: 0.45s; }


/* --- Nome che entra lettera per lettera, dal basso ----------------------- */
/* Ogni lettera parte 0.4em piu in basso e trasparente, e sale al suo posto.
   --i e l'indice della lettera, scritto dal JavaScript: moltiplicato per il
   passo, sfalsa le partenze e crea l'onda.

   backwards (e non forwards): durante l'attesa la lettera resta nello stato
   di partenza, ma a fine animazione il controllo del transform torna al CSS
   normale. Serve perche subito dopo deve funzionare l'hover, che usa una
   transition sullo stesso transform: con forwards l'animazione lo terrebbe
   bloccato e l'hover non si vedrebbe piu. */
/* Vale per il titolo di qualunque pagina interna: "Progetti" e il nome in
   "Chi sono" (che ha entrambe le classi, page-title e about-name). */
.anim-on .page-title .hero-char,
.anim-on .cs-titolo .hero-char {
  animation: lettera-dal-basso 0.9s cubic-bezier(0.22, 1, 0.36, 1) backwards;
  /* --passo lo calcola il JavaScript in base a quante lettere ha il titolo,
     cosi l'onda dura sempre lo stesso tempo: un titolo corto non sembra piu
     veloce di uno lungo. Il valore di riserva serve se il JS non arriva. */
  animation-delay: calc(var(--i, 0) * var(--passo, 0.05s));
}

@keyframes lettera-dal-basso {
  from { opacity: 0; transform: translateY(0.45em); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --- Blocchi che salgono allo scroll ------------------------------------- */
/* Classe generica: si mette .rivela nel markup a qualunque elemento debba
   entrare dal basso. Il JavaScript aggiunge .is-visible quando arriva a
   schermo. La curva e la stessa delle lettere, cosi il movimento del sito
   ha un'unica personalita. */
.anim-on .rivela {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.7s ease,
              transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.anim-on .rivela.is-visible {
  opacity: 1;
  transform: none;
}

/* --- Foto della pagina "Chi sono": sale e sfuma allo scroll --------------- */
/* Sale piu in fretta della pagina, quindi scorre dietro al nome (che sta a
   z-index piu alto), e sul finale sfuma. Il valore lo scrive il JavaScript
   in --su e --sfuma. will-change avvisa il browser che questi due cambiano
   di continuo, cosi li gestisce sulla scheda video invece che ridisegnare. */
.anim-on .about-foto {
  transform: translateY(var(--su, 0px));
  opacity: var(--sfuma, 1);
  will-change: transform, opacity;
}

/* --- CTA finale: il colore si riempie da sinistra a destra, riga per riga -- */
/* Come funziona: al posto di un colore pieno, il testo viene "riempito" con
   un'immagine di sfondo larga il doppio della riga, meta colore finale e
   meta grigio chiaro. background-clip: text ritaglia lo sfondo sulla forma
   delle lettere. Spostando lo sfondo da destra a sinistra, il colore finale
   entra progressivamente. Nessun testo duplicato, quindi nessun problema per
   i lettori di schermo.

   Il blocco @supports e la rete di sicurezza: se un browser non sapesse fare
   background-clip: text, "color: transparent" renderebbe il testo invisibile.
   Dentro @supports quelle righe vengono applicate solo dove funziona. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .anim-on .cta-home-title .fill-line {
    --fill: var(--color-text-muted);
    background-image: linear-gradient(
      to right,
      var(--fill) 50%,
      var(--color-fill-empty) 50%
    );
    background-size: 200% 100%;
    background-position: 100% 0;      /* si vede la meta grigia */
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    transition: background-position 1s ease;
    transition-delay: var(--fill-delay, 0s);
  }
  .anim-on .cta-home-title .fill-line-strong { --fill: var(--color-secondary); }

  /* si vede la meta colorata */
  .anim-on .cta-home-title.is-filled .fill-line { background-position: 0 0; }

  .anim-on .cta-home-title .fill-line:nth-child(1) { --fill-delay: 0s; }
  .anim-on .cta-home-title .fill-line:nth-child(2) { --fill-delay: 0.2s; }
  .anim-on .cta-home-title .fill-line:nth-child(3) { --fill-delay: 0.4s; }
  .anim-on .cta-home-title .fill-line:nth-child(4) { --fill-delay: 0.6s; }
}


/* ==========================================================================
   Processo di design — sezione guidata dallo scroll

   Le regole SENZA ".anim-on" descrivono la sezione normale, quella che si
   vede se il JavaScript non parte. Le regole CON ".anim-on" accendono
   l'effetto. E lo stesso principio delle altre animazioni.
   ========================================================================== */

/* --- Stato base: una normale sezione scura ------------------------------- */
.process-mask {
  display: flex;
  align-items: center;
  justify-content: center;
  padding-block: 120px;
}
/* Senza width:100% il container, essendo dentro un flex, si stringe sul
   contenuto e il cerchio verrebbe piu piccolo del dovuto. */
.process-mask > .container { width: 100%; }

/* --- Effetto acceso ------------------------------------------------------ */

/* Il contenitore alto 3 schermate. Le prime 2 servono all'effetto (mentre il
   pannello e incollato), la terza e il pannello stesso. */
.anim-on .process-scroll { height: 300vh; }

/* sticky = "resta incollato a 0px dal bordo alto finche c'e contenitore".
   Lo scroll della pagina non viene bloccato: e il pannello a non muoversi. */
.anim-on .process-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
}

/* Il fondo scuro ritagliato a cerchio. --mask-r (il raggio) lo scrive il
   JavaScript a ogni frame di scroll. Parte da 0 e cresce fino a coprire
   tutto lo schermo. Il ritaglio vale anche per il contenuto dentro, quindi
   titolo e pills vengono scoperti dal cerchio mentre si allarga. */
.anim-on .process-mask {
  height: 100%;
  padding-block: 0;
  clip-path: circle(var(--mask-r, 0px) at 50% 50%);
}

/* Su schermi bassi il quadrato da 805px non ci starebbe in altezza:
   78vh lascia un margine sopra e sotto. */
.anim-on .process-sticky .process { max-width: min(805px, 78vh); }

/* Le pills partono invisibili e le accende il JavaScript, una alla volta */
.anim-on .process-scroll .process-step {
  opacity: 0;
  transition: opacity 0.5s ease;
}
.anim-on .process-scroll .process-step.is-on { opacity: 1; }

/* Nella pagina di prova "Chi sono" apre la sezione scura, quindi non serve
   lo stacco che nella home lo separa dal cerchio. */
.dark-block-about .about-home { margin-top: 0; }

/* Su mobile l'effetto dura meta: 3 schermate col pollice sono troppe. */
@media (max-width: 768px) {
  .anim-on .process-scroll { height: 200vh; }
}

/* ==========================================================================
   Utility
   ========================================================================== */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   CASE STUDY — i blocchi della pagina di dettaglio di un progetto
   --------------------------------------------------------------------------
   Tutte le classi qui sotto iniziano con "cs-" (case study) e servono solo
   alle pagine case-study-*.html. La pagina di riferimento e
   case-study-la-veneranda.html: le prossime nascono da una sua copia.

   Nell'HTML ogni blocco e racchiuso fra due commenti col suo nome: quelli
   segnati OPZIONALE si possono cancellare per intero se un progetto non ha
   quella parte (per esempio i competitor o le personas).
   ========================================================================== */

/* --- La colonna di testo, piu stretta del container ----------------------
   Nel mockup i testi non arrivano ai bordi della pagina: stanno in una
   colonna centrata piu stretta. Questa classe va messa DENTRO al .container,
   sui blocchi di testo (le immagini a fascia restano larghe quanto il
   container). */
.cs-stretto { max-width: 1160px; margin-inline: auto; }

/* --- Testa della pagina: immagine, titolo, riga della categoria ----------
   Stesso impianto di .page-head (Progetti, Chi sono): il pattern a puntini
   sale dietro l'header trasparente e sborda un po' sotto la sezione. */
/* Lo spazio sopra l'immagine di apertura e proporzionale alla larghezza
   della finestra, non fisso: cosi il blocco di apertura (immagine, titolo e
   riga della categoria) resta leggibile senza scorrere anche sui portatili,
   e mantiene le proporzioni del mockup sugli schermi grandi.

   I 61px del massimo sono la misura presa dal mockup, dove fra il fondo del
   logo e l'inizio dell'immagine ci sono 61px su una pagina larga 1920. */
.cs-head {
  position: relative;
  padding-block: clamp(32px, 3.2vw, 61px) 0;
  --dotgrid-oltre: 180px;
}
.cs-head .container { position: relative; z-index: 1; }
.cs-head .hero-dotgrid { bottom: calc(-1 * var(--dotgrid-oltre)); }

/* Il titolo della case study: nel mockup e 150px su un viewport da 1920.
   150 diviso 1920 fa il 7,8125% della larghezza della finestra, ed e quello
   il valore in mezzo al clamp.

   clamp = "mai sotto 48px, mai sopra 150px, in mezzo il 7,8125% della
   larghezza". Cosi il titolo si rimpicciolisce da solo su ogni schermo senza
   bisogno di una misura diversa per ogni breakpoint, e sopra i 1920px non
   cresce oltre la misura del mockup.

   I 48px minimi sono gli stessi dell'hero della home: sotto i 614px il
   7,8125% darebbe misure da testo normale, non da titolo di pagina.

   Quanto viene, ai vari schermi:
   1920 -> 150px | 1440 -> 112px | 1280 -> 100px | 1024 -> 80px
    768 ->  60px |  614 ->  48px |  375 ->  48px */
.cs-titolo {
  text-align: center;
  font-size: clamp(48px, 7.8125vw, 150px);
  line-height: 1.05;
  /* Stessa logica del padding sopra: le due distanze (dall'immagine e dalla
     riga della categoria) sono quelle del mockup a 1920px, e si stringono
     insieme alla finestra. */
  margin-block: clamp(16px, 1.8vw, 35px) clamp(20px, 2.6vw, 50px);
}

/* Riga sotto il titolo: categoria a sinistra, proprieta a destra */
.cs-meta {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 40px;
  font-size: 16px;
}

/* --- Immagini ------------------------------------------------------------
   .cs-figura e la cornice: tiene le proporzioni giuste e mostra un
   rettangolo grigio finche l'immagine non e stata esportata da Figma.
   Le classi -hero, -banda, -alta, -persona cambiano solo le proporzioni. */
.cs-figura {
  position: relative;
  background: var(--color-border);
  overflow: hidden;
}

/* La cornice non impone proporzioni: l'altezza la detta l'immagine stessa,
   cosi non viene mai tagliata. Le proporzioni scritte piu sotto servono solo
   a dare un'altezza al riquadro grigio quando l'immagine ancora non c'e.

   Il ">" vuol dire "solo figlio diretto". Serve: dentro la cornice c'e anche
   il logo e21, dentro la scritta in alto, e senza il ">" questa regola lo
   allargherebbe a tutta la fascia.

   Nell'HTML ogni <img> ha anche gli attributi width e height con le misure
   vere del file: il browser li usa per sapere in anticipo quanto spazio
   riservare, cosi la pagina non "salta" mentre le immagini arrivano. Con
   height:auto quelle misure non impongono nulla, servono solo alla
   proporzione.

   Vale anche per i video (es. la clip di Fatturatoo al posto di una foto
   ferma): stessa cornice, stessa regola, un video si comporta come
   un'immagine larga quanto il contenitore. */
.cs-figura > img, .cs-figura > video { width: 100%; height: auto; display: block; }

/* Immagini con lo sfondo trasparente (loghi, illustrazioni ritagliate).
   Il grigio qui sopra e un fondo di cortesia: copre il riquadro finche
   l'immagine non e arrivata. Ma se l'immagine e trasparente quel grigio non
   viene mai coperto e si vede come un quadrato dietro al disegno. Con questa
   classe il fondo sparisce e si vede il colore della sezione.
   Torna solo se il file manca davvero: li il grigio serve, e sopra ci va
   scritto il nome del file da esportare. */
.cs-figura-trasparente { background: transparent; }
.section-beige .cs-figura-trasparente { background: transparent; }
.cs-figura-trasparente.is-mancante,
.section-beige .cs-figura-trasparente.is-mancante { background: var(--color-fill-empty); }

/* Riquadro di un'immagine non ancora esportata: al centro compare il nome
   del file da salvare in images/. La classe e l'attributo data-file li mette
   il JavaScript quando il caricamento fallisce (vedi in fondo a js/main.js).
   attr(data-file) = "scrivi qui il valore di quell'attributo". */
.cs-figura.is-mancante::after,
.cs-mockup-lista figure.is-mancante::after,
.about-home-image.is-mancante::after,
.showcase-image.is-mancante::after,
.about-foto.is-mancante::after {
  content: attr(data-file);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: var(--color-text-muted);
}
.cs-mockup-lista figure.is-mancante {
  position: relative;
  aspect-ratio: 3 / 2;
  background: var(--color-border);
}

.cs-figura-hero.is-mancante    { aspect-ratio: 29 / 10; }
.cs-figura-banda.is-mancante   { aspect-ratio: 21 / 9; }
.cs-figura-alta.is-mancante    { aspect-ratio: 4 / 5; }
.cs-figura-persona.is-mancante { aspect-ratio: 9 / 10; }

/* Proporzioni che servono a SkillSprout: la fascia video sotto l'Overview,
   il video largo del motion design, i due quadrati, il simbolo verticale del
   logo e le foto piccole accanto. */
.cs-figura-video.is-mancante    { aspect-ratio: 11 / 2; }
.cs-figura-motion.is-mancante   { aspect-ratio: 11 / 3; }
.cs-figura-quadrata.is-mancante { aspect-ratio: 1 / 1; }
.cs-figura-simbolo.is-mancante  { aspect-ratio: 5 / 8; }
.cs-figura-mini.is-mancante     { aspect-ratio: 5 / 3; }
.cs-figura-larga.is-mancante    { aspect-ratio: 5 / 4; }

/* L'immagine che esce dai bordi del container e occupa tutta la larghezza
   della finestra. Va messa fuori dal .container. */
.cs-figura-fullbleed { width: 100%; }
.cs-figura-fullbleed.is-mancante { aspect-ratio: 21 / 9; }

/* La scritta bianca appoggiata in alto a sinistra sull'immagine di apertura.
   L'ombra la tiene leggibile anche sulle parti chiare della foto. */
/* Il logo e21 dentro la scritta. Il reset del sito mette le immagini a
   display:block: qui serve inline-block, altrimenti andrebbe a capo da solo.
   vertical-align lo allinea alla riga del testo. */
.cs-nota-logo {
  display: inline-block;
  height: 1.7em;
  width: auto;
  vertical-align: -0.5em;
  margin-left: 6px;
}

/* Finche la foto manca, la scritta bianca sarebbe invisibile sul grigio */
.cs-figura.is-mancante .cs-hero-nota {
  color: var(--color-text-muted);
  text-shadow: none;
}

.cs-hero-nota {
  position: absolute;
  top: 24px;
  left: 32px;
  z-index: 1;
  font-size: 16px;
  color: var(--color-primary);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.45);
}

/* Variante: scritta in basso a sinistra e scura invece che bianca in alto.
   Serve quando in quel punto la foto e chiara, come nell'immagine di
   apertura di Fatturatoo. */
.cs-hero-nota-basso {
  top: auto;
  bottom: 24px;
  color: var(--color-secondary);
  text-shadow: none;
}


/* --- Overview + Problema e Soluzione ------------------------------------- */
.cs-intro {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 48px 96px;
}

/* Elenco "Ruolo / Team / Tool / Link": etichetta a sinistra, valori a destra.
   In HTML e una <dl>, la lista fatta di coppie termine-descrizione. */
.cs-dati { margin: 0; }
.cs-dato {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: 6px 16px;
  margin-bottom: 28px;
}
.cs-dato:last-child { margin-bottom: 0; }
.cs-dato dt { font-weight: 700; }
.cs-dato dd { margin: 0; grid-column: 2; }

/* --- Titoli dei blocchi --------------------------------------------------
   Gli h2 del sito sono tutti maiuscoli. Qui "Overview", "Problema" e
   "Soluzione" nel mockup sono scritti normale: questa classe spegne il
   maiuscolo solo per loro. */
.cs-h2-normale { text-transform: none; }
.cs-h2 { margin-bottom: 20px; }

/* Sopratitolo: la riga piccola sopra il titolo ("Contesto e cliente",
   "Ricerca & Insight"). E in Oswald come i titoli ma di peso normale: per
   questo la pagina carica anche il peso 400 del font. */
.cs-sopratitolo {
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 20px;
  line-height: 1.3;
  margin-bottom: 8px;
}

/* Nel mockup un sopratitolo e scritto tutto maiuscolo: questa variante lo
   ottiene dal CSS, cosi nell'HTML il testo resta leggibile. */
.cs-sopratitolo-maiuscolo { text-transform: uppercase; }

/* Distanza fra un paragrafo e l'altro dentro lo stesso blocco */
.cs-testo p + p { margin-top: 20px; }

/* Elenco puntato dei blocchi (obiettivi, personas) */
.cs-elenco { list-style: disc; padding-left: 20px; }
.cs-elenco li { font-size: 18px; line-height: 30px; margin-bottom: 12px; }
.cs-elenco li:last-child { margin-bottom: 0; }
.cs-elenco li::marker { color: var(--color-text-muted); }

/* --- Due colonne affiancate (immagine + testo, testo + immagine) --------- */
.cs-due {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
}
.cs-due-alto { align-items: start; }

/* --- Riferimenti e competitor (OPZIONALE) -------------------------------- */
.cs-competitor {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 32px;
}

/* Il bordo e chiaro perche queste schede stanno dentro la sezione scura */
.cs-scheda {
  border: 1px solid rgba(247, 245, 240, 0.45);
  padding: 32px;
}
.cs-scheda h3 { margin-bottom: 20px; }

/* Riga "Pro: ..." / "Contro: ...": etichetta colorata a sinistra,
   testo a destra, allineati in colonna fra una riga e l'altra. */
.cs-riga {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 12px;
  margin-bottom: 16px;
}
.cs-riga:last-child { margin-bottom: 0; }
.cs-riga span { font-size: 18px; line-height: 30px; }
.cs-etichetta-pro    { color: var(--color-pro); }
.cs-etichetta-contro { color: var(--color-contro); }
.cs-etichetta-nota   { color: var(--color-text-muted); }

/* Scheda competitor larga quanto tutta la griglia, con Pro e Contro
   affiancati invece che uno sotto l'altro. Nel mockup di BuddyGrowth l'ultimo
   competitor e da solo sulla sua riga e occupa tutto lo spazio: cosi non
   resta mezza riga vuota. */
.cs-scheda-larga { grid-column: 1 / -1; }
.cs-scheda-larga .cs-scheda-corpo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
}
.cs-scheda-larga .cs-riga { margin-bottom: 0; }

/* Quando dentro a "Pro:" / "Contro:" c'e un elenco invece di una frase sola
   (BuddyGrowth), l'elenco non deve rientrare oltre il suo puntino. */
.cs-riga .cs-elenco { padding-left: 18px; }
.cs-riga .cs-elenco li { margin-bottom: 8px; }

/* --- User personas (OPZIONALE) ------------------------------------------ */
/* Foto a sinistra, contenuto a destra. La variante "invertita" mette la
   foto a destra: nel mockup le due personas sono a specchio. */
.cs-persona {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 56px;
  align-items: start;
}
.cs-persona-invertita { grid-template-columns: 1fr 300px; }

.cs-persona h3 { margin-bottom: 24px; }

/* Obiettivi e Frustrazioni affiancati dentro la scheda della persona */
.cs-persona-colonne {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  margin-bottom: 32px;
}

/* Il titoletto "Obiettivi principali" / "Come risponde al progetto" */
.cs-persona-etichetta {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 20px;
  margin-bottom: 12px;
}

/* --- Wireframe ----------------------------------------------------------- */
/* Testo a sinistra, titolo grande a destra, come nel mockup */
.cs-wireframe-testa {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 48px;
  align-items: start;
  margin-bottom: 48px;
}

/* --- Statistiche di ricerca (OPZIONALE) ----------------------------------
   Il blocco di SkillSprout: numero grande a sinistra, spiegazione a destra.
   I numeri sono allineati a destra fra loro, cosi "85%" e "29 anni" finiscono
   sulla stessa linea verticale anche se sono larghi in modo diverso. */
.cs-statistiche { display: grid; gap: 48px; }

.cs-stat {
  display: grid;
  grid-template-columns: minmax(0, 200px) 1fr;
  gap: 32px;
  align-items: start;
}
.cs-stat-numero {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 64px;
  line-height: 1;
  text-align: right;
  white-space: nowrap;   /* "29 anni" non deve andare a capo */
}
.cs-stat p { margin: 0; }

/* La riga piccola sotto il testo della ricerca, con le fonti dei dati */
.cs-fonte {
  font-size: 15px;
  color: var(--color-text-muted);
  margin-top: 32px;
}

/* --- Logo: due gruppi affiancati (OPZIONALE) -----------------------------
   Ogni gruppo e il simbolo del logo a sinistra (verticale) e due foto
   impilate a destra. Nel mockup i gruppi sono due, affiancati. */
.cs-logo-griglia {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 72px;
  margin-top: 48px;
}
.cs-logo-gruppo {
  display: grid;
  grid-template-columns: 3fr 4fr;
  gap: 16px;
  align-items: start;
}
.cs-logo-colonna { display: grid; gap: 16px; }

/* Fila dei passaggi di costruzione del logo (BuddyGrowth): quattro riquadri
   affiancati, ognuno con dentro un'immagine centrata. */
.cs-logo-passi {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 40px;
  align-items: center;
  margin-top: 48px;
}

/* --- Motion design (OPZIONALE) -------------------------------------------
   Un video largo sopra, due quadrati sotto. I quadrati non arrivano ai bordi
   del video largo: nel mockup stanno un po' piu stretti e centrati. */
.cs-motion-coppia {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  max-width: 84%;
  margin: 48px auto 0;
}

/* --- Design system (OPZIONALE) -------------------------------------------
   Sezione scura di MindMatch: il titolo sta a destra, sotto c'e l'immagine
   del design system e sopra ci si appoggia un bollino tondo che porta al
   file vero. */
.cs-ds-titolo { text-align: right; margin-bottom: 40px; }

/* "relative" sul contenitore e la chiave: il bottone qui sotto e "absolute",
   e un elemento absolute si posiziona rispetto al primo antenato relative.
   Senza questa riga schizzerebbe in cima alla pagina. */
.cs-ds-cornice { position: relative; }

/* Il bottone che apre il design system. E' un .btn normale (stessa forma a
   pillola, stesso padding degli altri bottoni del sito) con colori suoi:
   grigio da fermo, verde acqua al passaggio del mouse, verde piu scuro
   mentre lo si tiene premuto.

   I due colori stanno in due variabili invece che scritti dentro alle
   regole: cosi per cambiare tinta si tocca un punto solo per stato. */
/* Il posizionamento sta su un contenitore a parte, non sul bottone: il
   bottone e magnetico, e il JavaScript gli riscrive il transform 60 volte al
   secondo per farlo inseguire il mouse. Se il centraggio fosse un transform
   sul bottone stesso, verrebbe cancellato al primo movimento. Cosi invece
   centra il contenitore, e il bottone resta libero di muoversi. */
.cs-ds-posizione {
  position: absolute;
  /* top/left sono la posizione dell'ANGOLO; il translate del -50% tira
     indietro il contenitore di meta della sua misura, cosi il 50%/50% vale
     per il suo CENTRO. */
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.cs-btn-ds {
  --ds-fondo: #292929;
  --ds-bordo: #EDEDED;
  --ds-testo: #979797;
  background: var(--ds-fondo);
  border-color: var(--ds-bordo);
  color: var(--ds-testo);

  /* Nel Figma il bottone a riposo sta al 50%: la tavola del design system si
     intravede dietro. Al passaggio del mouse torna pieno, cosi la scritta
     diventa leggibile proprio nel momento in cui serve leggerla. */
  opacity: 0.5;

  text-decoration: none;
  white-space: nowrap;
}
.cs-btn-ds:hover,
.cs-btn-ds:focus-visible {
  opacity: 1;
  --ds-fondo: #5FD9C8;
  --ds-bordo: #5FD9C8;
  --ds-testo: var(--color-secondary);
}
/* :active = mentre il tasto del mouse e premuto. Stessa logica del design
   system di MindMatch, dove lo stato "pressed" e sempre una versione piu
   scura del colore base. */
.cs-btn-ds:active { --ds-fondo: #3BBFAC; --ds-bordo: #3BBFAC; }



/* --- Tipografia e colori ------------------------------------------------- */
.cs-centrato { text-align: center; }
.cs-centrato p { margin-inline: auto; max-width: 980px; }

.cs-palette {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
  margin-top: 48px;
}

/* Il colore del campione arriva dall'HTML con --campione: cosi il codice
   esadecimale sta scritto una volta sola, accanto al nome del colore. */
.cs-campione-colore {
  aspect-ratio: 1 / 1.1;
  background: var(--campione, var(--color-border));
  border: 1px solid var(--color-border);
}
.cs-campione-riga {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  font-size: 16px;
}

/* --- Galleria dei mockup -------------------------------------------------
   Immagini alte e strette (pagine intere): niente proporzione forzata,
   ognuna tiene la sua altezza naturale. */
.cs-mockup-lista { display: grid; gap: 68px; }
.cs-mockup-lista img { width: 100%; height: auto; }

/* --- Banda scura col bottone al sito -------------------------------------
   Nel mockup questa banda ha un fondo leggermente piu chiaro delle altre
   sezioni scure (#363636 invece di #313130) e sopra il logo "F" ripetuto,
   appena piu scuro del fondo.

   Il motivo lo disegna ::before, un livello che sta dietro al contenuto.
   Ci sono DUE copie della stessa piastrella, la seconda spostata di mezza
   piastrella in orizzontale e in verticale: e quello sfalsamento a dare la
   disposizione a mattoncini del mockup, con le file che non si allineano.
   Le distanze fra un simbolo e l'altro sono gia dentro il file
   images/logo-f-pattern.svg, che contiene la F con il vuoto attorno. */
.cs-banda-sito {
  position: relative;
  background: #363636;
  color: var(--color-primary);
  padding-block: 104px;
  text-align: center;
  overflow: hidden;
}
.cs-banda-sito::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    url('../images/logo-f-pattern.svg'),
    url('../images/logo-f-pattern.svg');
  background-size: 120px 194px;
  background-position: 0 0, 60px 97px;
  pointer-events: none;
}
.cs-banda-sito .container { position: relative; z-index: 1; }

/* --- Bottone magnetico ---------------------------------------------------
   Lo spostamento e l'ingrandimento li scrive il JavaScript fotogramma per
   fotogramma (vedi in fondo a js/main.js): qui NON va messa una transition
   su transform, altrimenti il browser proverebbe ad ammorbidire un valore
   che sta gia cambiando 60 volte al secondo, e il movimento risulterebbe
   in ritardo e impastato.

   will-change avvisa il browser che questo elemento si muovera: lo mette su
   un livello a se e lo sposta senza ridisegnare il resto della pagina. */
.btn-magnetico {
  will-change: transform;
  /* "opacity" serve al bottone del design system, che a riposo sta al 50%:
     questa regola viene DOPO .cs-btn-ds nel foglio, quindi e qui che va
     elencata, altrimenti la dissolvenza scatterebbe di colpo. */
  transition: background-color var(--transition-base),
              color var(--transition-base),
              border-color var(--transition-base),
              opacity var(--transition-base);
}

/* Nota: l'ingrandimento all'hover degli altri bottoni (transform: scale)
   qui non serve toglierlo. Il JavaScript scrive il transform direttamente
   sull'elemento e quello ha sempre la precedenza sul foglio di stile; se il
   JavaScript non parte, l'hover normale torna a funzionare come sempre. */

/* --- CTA finale ----------------------------------------------------------
   Stessa CTA scura della pagina Progetti, ma senza lo spazio extra in basso:
   li sotto c'e un'immagine a cavallo, qui subito il footer. */
.cs-cta { padding-block: 120px; }

/* --- Stacchi fra i blocchi ------------------------------------------------
   Invece di scrivere i margini dentro l'HTML, ogni distanza ha qui il suo
   nome: cosi si cambia in un punto solo e si riduce da sola su mobile. */
.cs-blocco { margin-top: 120px; }          /* fra due blocchi diversi */
.cs-blocco-grande { margin-top: 200px; }   /* fra due sezioni molto dense */
.cs-blocco-piccolo { margin-top: 64px; }   /* fra un testo e la sua immagine */
.cs-h2-dopo { margin-top: 48px; }          /* secondo titolo nella stessa colonna */
.cs-titolo-blocco { margin-bottom: 48px; } /* titolo centrato sopra una griglia */

/* Sezione che parte attaccata a quella sopra, senza lo stacco iniziale */
.cs-sezione-attaccata { padding-top: 0; }

/* Nella scheda della persona, il titoletto che segue un paragrafo */
.cs-persona p + .cs-persona-etichetta { margin-top: 32px; }

/* Le <figure> della galleria non hanno il margine di default del browser */
.cs-mockup-lista figure { margin: 0; }

/* --- Responsive ----------------------------------------------------------
   Sotto i 1024px le griglie a due colonne diventano una colonna sola:
   affiancare testo e immagine su uno schermo stretto li renderebbe entrambi
   troppo compressi. */
@media (max-width: 1200px) {
  .cs-intro { grid-template-columns: 280px 1fr; gap: 40px 64px; }
  .cs-due { gap: 48px; }
}

@media (max-width: 1024px) {
  .cs-head { --dotgrid-oltre: 120px; }
  .cs-intro,
  .cs-due,
  .cs-competitor,
  .cs-persona,
  .cs-persona-invertita,
  .cs-wireframe-testa { grid-template-columns: 1fr; gap: 40px; }

  /* Con una colonna sola la foto della persona sta sopra il testo in
     entrambe le versioni: l'ordine del codice torna a essere quello giusto. */
  .cs-persona-invertita .cs-figura { order: -1; }

  /* Stesso problema col wireframe: nell'HTML il titolo e scritto DOPO il
     paragrafo, perche sul desktop sta nella colonna di destra. In colonna
     singola finirebbe sotto. order: -1 lo rimanda in cima, cosi l'ordine
     letto e quello giusto: titolo, paragrafo, immagine. */
  .cs-wireframe-testa h2 { order: -1; }

  /* Blocchi fatti da "titolo a sinistra, testo a destra" (Logo, User
     personas, Wireframe): in colonna singola il titolo si ritrova a 40px di
     gap PIU i 20px del proprio margine dal paragrafo che lo segue, quindi
     sembra staccato. Qui la distanza torna quella normale fra un titolo e il
     suo testo, la stessa del resto del sito. */
  .cs-due-titolo,
  .cs-wireframe-testa { gap: 20px; }
  .cs-due-titolo .cs-h2 { margin-bottom: 0; }

  .cs-palette { grid-template-columns: repeat(2, 1fr); }
  .cs-mockup-lista { gap: 32px; }

  /* I due gruppi del logo e i due video quadrati vanno uno sotto l'altro */
  .cs-logo-griglia { grid-template-columns: 1fr; gap: 40px; }
  .cs-motion-coppia { grid-template-columns: 1fr; gap: 32px; max-width: 100%; }

  /* Dentro la scheda competitor larga, Pro e Contro tornano incolonnati */
  .cs-scheda-larga .cs-scheda-corpo { grid-template-columns: 1fr; gap: 16px; }
  .cs-scheda-larga .cs-riga:first-child { margin-bottom: 16px; }

  /* I quattro passaggi del logo passano a due per riga */
  .cs-logo-passi { grid-template-columns: repeat(2, 1fr); gap: 32px; }
}

@media (max-width: 768px) {
  .cs-blocco { margin-top: 64px; }
  .cs-blocco-grande { margin-top: 96px; }
  .cs-blocco-piccolo { margin-top: 40px; }
  .cs-titolo-blocco { margin-bottom: 32px; }
  .cs-titolo { margin-block: 20px 20px; }
  .cs-hero-nota { top: 12px; left: 16px; font-size: 14px; }
  .cs-hero-nota-basso { top: auto; bottom: 12px; }
  .cs-figura-hero.is-mancante { aspect-ratio: 3 / 2; }
  .cs-figura-fullbleed.is-mancante { aspect-ratio: 3 / 2; }
  .cs-persona-colonne { grid-template-columns: 1fr; gap: 24px; }
  .cs-scheda { padding: 24px; }
  .cs-riga { grid-template-columns: 68px 1fr; }
  .cs-banda-sito { padding-block: 72px; }
  .cs-cta { padding-block: 64px; }

  /* Il numero della statistica si rimpicciolisce e passa sopra al testo,
     invece di rubargli meta della larghezza. */
  .cs-statistiche { gap: 32px; }
  .cs-stat { grid-template-columns: 1fr; gap: 8px; }
  .cs-stat-numero { font-size: 48px; text-align: left; }

  /* Le proporzioni delle fasce video: su schermo stretto un 11:2 sarebbe
     una striscia altissima due dita. */
  .cs-figura-video.is-mancante { aspect-ratio: 16 / 9; }
  .cs-figura-motion.is-mancante { aspect-ratio: 16 / 9; }

  /* Il design system su schermo stretto: il titolo torna al centro e il
     bottone scende SOTTO l'immagine invece di starci sopra. Sovrapposto non
     funzionerebbe: l'immagine e una fascia larga e bassa, a 375px sarebbe
     alta un dito e il bottone ci starebbe sopra a fatica.
     position:static rimette il contenitore nel flusso normale, e
     "transform:none" annulla il centraggio che serviva solo da sovrapposto. */
  /* Il popup del design system a tutto schermo: su un telefono i margini
     rubano spazio a una tavola che ne ha gia poco. */
  .modal-overlay { padding: 0; }
  .modal-ds { height: 100vh; max-height: 100vh; }
  .modal-ds-testa { padding: 16px 64px 14px 20px; }
  .modal-ds-testa h2 { font-size: 28px; }

  .cs-ds-titolo { text-align: center; margin-bottom: 32px; }
  .cs-ds-posizione {
    position: static;
    transform: none;
    margin-top: 32px;
    text-align: center;
  }
}

@media (max-width: 480px) {
  .cs-palette { grid-template-columns: 1fr; }
}
