/* =========================================================
   Parrucchiere Digitale — layout tokens
   Color tokens live in tokens.css (loaded first). Editorial,
   warm-neutral base: white/osso/greige surfaces, two full navy
   sections, copper reserved for eyebrows/result numbers/primary
   CTA only. No shadows, no gradients — hairline borders throughout.
   ========================================================= */
:root{
  --font-display: "Inter", sans-serif;
  --font-label: "Inter", sans-serif;
  --font-body: "Inter", sans-serif;
  --font-mono: "IBM Plex Mono", monospace;

  --container: 1170px;
  --radius: 12px;
  --section-y: clamp(44px, 4.5vw, 68px);
  /* Measured on the reference (getComputedStyle on its --ease custom
     property): a sharp, fast-decelerating curve used for every
     entrance animation, not a stock GSAP power-ease. */
  --ease: cubic-bezier(0.55, 0.085, 0, 0.99);
}

*, *::before, *::after{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }
@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;
    scroll-behavior: auto !important;
  }
}

/* =========================================================
   Scroll reveal (site-wide)
   JS marks observed elements with [data-reveal] and toggles
   .is-visible once, the first time each one enters the viewport.
   Gated behind html.has-js so content never gets stuck hidden
   if JavaScript fails to load.
   .reveal adds the default fade + rise; elements that need a
   bespoke transform (e.g. the hero notify cards) can use
   [data-reveal] alone and define their own is-visible state.
   ========================================================= */
[data-reveal]{ transition: opacity .7s cubic-bezier(.4,0,.2,1); }
.reveal{ transition: opacity .7s cubic-bezier(.4,0,.2,1), transform .7s cubic-bezier(.4,0,.2,1); }
html.has-js [data-reveal]{ opacity: 0; }
html.has-js [data-reveal].is-visible{ opacity: 1; }
html.has-js .reveal{ transform: translateY(28px); }
html.has-js .reveal.is-visible{ transform: none; }

.reveal-delay-1{ transition-delay: .08s; }
.reveal-delay-2{ transition-delay: .16s; }
.reveal-delay-3{ transition-delay: .24s; }
.reveal-delay-4{ transition-delay: .32s; }
.reveal-delay-5{ transition-delay: .4s; }

@media (prefers-reduced-motion: reduce){
  html.has-js [data-reveal]{ opacity: 1 !important; transform: none !important; }
}

/* overflow-x:hidden lives on html only, not body: setting it on body too
   forces body's overflow-y to compute to "auto" (the UA pairing rule for
   overflow), which makes body a second scroll container that position:sticky
   elements can resolve against instead of the real viewport — since body
   never actually scrolls itself, every sticky section (feature-pin,
   method-pin) silently stopped sticking and just scrolled away with the
   page. html carries the clip alone so it's the viewport's own scroll
   container that governs, which is what sticky actually needs. */
html{ overflow-x: hidden; }
body{
  margin: 0;
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

.container{
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
}

@media (max-width: 560px){
  .container{ padding: 0 20px; }
}

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

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

::selection{ background: var(--blue); color: var(--on-dark); }

:focus-visible{
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}

.skip-link{
  position: absolute;
  left: -999px;
  top: auto;
  background: var(--blue);
  color: var(--on-dark);
  padding: 12px 20px;
  z-index: 200;
  border-radius: var(--radius);
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
}
.skip-link:focus{
  left: 24px;
  top: 24px;
}

h1, h2, h3{
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--text-primary);
  margin: 0;
  letter-spacing: -0.025em;
}

/* Sizes measured directly from the reference (getComputedStyle):
   h1 72px/700/lh1.04, section h2 34–55px/700/lh~1.0-1.12. */
h1{ font-size: clamp(2.4rem, 4.6vw + 1rem, 4.5rem); line-height: 1.04; font-weight: 700; }
h2{ font-size: clamp(1.85rem, 3vw + 1rem, 3.2rem); line-height: 1.08; font-weight: 700; }
h3{ font-size: clamp(1.25rem, 2vw, 1.55rem); line-height: 1.25; font-weight: 700; }

p{ margin: 0; }

.eyebrow{
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blue);
  margin: 0 0 14px;
}

.text-link{
  display: inline-block;
  margin-top: 20px;
  font-weight: 600;
  color: var(--blue);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease, color .2s ease;
}
.text-link:hover{ color: var(--blue-hover); border-color: var(--blue-hover); }

/* =========================================================
   Buttons
   ========================================================= */
.btn{
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 0 26px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.96rem;
  cursor: pointer;
  transition: transform .18s ease, background .2s ease, border-color .2s ease, color .2s ease, box-shadow .2s ease;
  white-space: nowrap;
}
.btn:hover{ transform: translateY(-2px); box-shadow: 0 10px 22px -10px rgba(4,19,52,.45); }
.btn:active{ transform: translateY(0) scale(0.96); box-shadow: none; transition-duration: .1s; }

/* Primary buttons carry a circular icon badge flush to the pill's
   edge (measured on the reference: padding 5px 18px 5px 5px) instead
   of a plain trailing arrow in the text. */
.btn--primary{
  background: var(--blue);
  color: var(--bg-base);
  padding: 5px 22px 5px 5px;
  gap: 12px;
}
.btn__icon{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.2em;
  height: 2.2em;
  border-radius: 50%;
  background: var(--bg-base);
  transition: transform .2s ease;
}
.btn__icon svg{ width: 40%; height: 40%; stroke: var(--blue); fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.btn--primary:hover .btn__icon{ transform: translateX(3px); }
.btn--primary:active .btn__icon{ transform: translateX(1px); }

/* CTA secondaria: trasparente, hairline border, testo primario. */
.btn--ghost{
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text-primary);
}
.btn--ghost:hover{ border-color: var(--blue); color: var(--blue); }

.btn--outline{
  background: transparent;
  border-color: var(--blue);
  color: var(--blue);
}
.btn--outline:hover{ background: var(--blue); color: var(--on-dark); }

.btn--small{ min-height: 42px; padding: 0 18px; font-size: 0.86rem; }
.btn--small.btn--primary{ padding: 4px 18px 4px 4px; }
.btn--large{ min-height: 58px; padding: 0 34px; font-size: 1.02rem; }
.btn--large.btn--primary{ padding: 6px 30px 6px 6px; }

@media (prefers-reduced-motion: reduce){
  .btn:hover, .btn:active{ transform: none; box-shadow: none; }
  .btn--primary:hover .btn__icon, .btn--primary:active .btn__icon{ transform: none; }
}

/* =========================================================
   Header
   ========================================================= */
.site-header{
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--blue-deep);
  border-bottom: 0.5px solid var(--on-dark-border);
}
.site-header__inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 80px;
  gap: 24px;
}

.wordmark{
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.brand-mark{
  width: 42px;
  height: 42px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: #000;
  border: 0.5px solid var(--border-strong);
}
.brand-mark img{
  width: 100%;
  height: 150%;
  object-fit: cover;
  object-position: 50% 32%;
}
.brand-name{
  display: flex;
  flex-direction: column;
  line-height: 1.05;
}
.brand-name__primary{
  font-family: var(--font-display);
  font-size: 1.08rem;
  font-weight: 600;
  color: var(--on-dark);
}
.brand-name__accent{
  font-family: var(--font-label);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--blue-on-dark);
  margin-top: 2px;
}
.wordmark--footer .brand-mark{ width: 52px; height: 52px; }
.wordmark--footer .brand-name__primary{ font-size: 1.3rem; }

.main-nav ul{
  display: flex;
  gap: 32px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.main-nav a{
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--on-dark-soft);
  transition: color .2s ease;
}
.main-nav a:hover{ color: var(--on-dark); }

.site-header__actions{ display: flex; align-items: center; gap: 16px; }

/* Bottone header su sfondo ora blu pieno: stesso trucco di
   .mid-cta__card .btn--primary (blu -> bianco/blu invertiti), altrimenti
   il bottone blu di default sparirebbe contro l'header dello stesso
   colore. */
.site-header .btn--primary{ background: var(--bg-base); color: var(--blue); }
.site-header .btn__icon{ background: var(--blue); }
.site-header .btn__icon svg{ stroke: var(--bg-base); }

.nav-toggle{
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  background: transparent;
  border: 0.5px solid var(--on-dark-border);
  border-radius: var(--radius);
  cursor: pointer;
}
.nav-toggle span{
  display: block;
  height: 1.5px;
  margin: 0 8px;
  background: var(--on-dark);
  transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1){ transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2){ opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3){ transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 860px){
  .main-nav{
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--surface-card);
    border-bottom: 0.5px solid var(--border);
    max-height: 0;
    overflow: hidden;
    transition: max-height .25s ease;
  }
  .main-nav.is-open{ max-height: 340px; }
  .main-nav ul{
    flex-direction: column;
    gap: 0;
    padding: 8px 24px 20px;
  }
  .main-nav li{ border-top: 0.5px solid var(--border); }
  /* Il pannello a tendina qui sopra resta bianco (non blu come la barra
     dell'header): i link dentro devono tornare scuri, altrimenti col
     colore chiaro ereditato dalla barra sparirebbero su questo sfondo. */
  .main-nav a{ display: block; padding: 14px 0; color: var(--text-secondary); }
  .main-nav a:hover{ color: var(--blue); }
  .site-header__actions .btn--primary{ display: none; }
  .nav-toggle{ display: flex; }
}

/* =========================================================
   Hero
   ========================================================= */
.hero{
  position: relative;
  padding: clamp(56px, 9vw, 108px) 0 clamp(48px, 7vw, 88px);
  overflow: hidden;
  background: var(--bg-base);
}
.eyebrow--dot{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 16px 7px 14px;
  border-radius: 999px;
  background: var(--blue-soft);
}
.eyebrow--dot::before{
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--blue);
}

/* =========================================================
   Hero entrance — measured from the reference: per-letter
   stagger on the H1 (30ms/letter, 180ms base delay), then the
   lede/actions/note fade+rise on the same keyframe at 0.55s/
   0.8s/0.95s. Gated behind html.has-js so text is always
   readable if the split-into-letters script never runs.
   ========================================================= */
@keyframes heroUp{
  0%   { opacity: 0; transform: translateY(22px); }
  100% { opacity: 1; transform: translateY(0); }
}
html.has-js #heroTitle .word{ display: inline-block; white-space: nowrap; }
html.has-js #heroTitle .ltr{
  display: inline-block;
  opacity: 0;
  animation: heroUp .6s var(--ease) both;
  animation-delay: calc(.18s + var(--i, 0) * .03s);
}
html.has-js .hero__anim{
  opacity: 0;
  animation: heroUp .8s var(--ease) both;
}
@media (prefers-reduced-motion: reduce){
  html.has-js #heroTitle .ltr,
  html.has-js .hero__anim{ opacity: 1; animation: none; }
}

/* =========================================================
   Reveal-title — the reference's scroll-scrubbed text "wipe":
   a linear-gradient text-clip whose hard edge sits at --reveal
   (0%=hidden, 100%=fully lit), updated continuously on scroll
   by main.js. Gated behind html.has-js so headings render as
   normal solid text if the script never runs.
   ========================================================= */
html.has-js .reveal-title{
  --reveal: 0%;
  color: transparent;
  -webkit-text-fill-color: transparent;
  background-image: linear-gradient(90deg,
    var(--text-primary) calc(var(--reveal) - 3%),
    rgba(19,26,43,.15) calc(var(--reveal) + 3%));
  -webkit-background-clip: text;
  background-clip: text;
}
@media (prefers-reduced-motion: reduce){
  html.has-js .reveal-title{ --reveal: 100%; color: var(--text-primary); -webkit-text-fill-color: var(--text-primary); }
}
.hero__grid{
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 56px;
  align-items: center;
}
.hero__actions{
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 34px;
}
.btn__icon-inline{
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.hero__note{
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 18px;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.hero__note-icon{
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 2px;
  stroke: var(--blue);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.hero__seal{ position: relative; display: flex; justify-content: center; align-items: center; gap: 20px; }

.hero__phone-frame{ display: flex; }

/* Il telefono attraversa lo schermo da sinistra a destra invece del
   solo fade generico di [data-reveal]: parte sovrapposto alla colonna
   di testo e scivola fino alla sua posizione a destra, "scoprendo" le
   scritte dietro di sé mentre se ne allontana. Essendo dopo il testo
   nel DOM, durante la sovrapposizione gli passa visivamente sopra
   senza bisogno di z-index. Distanza di partenza misurata sul centro
   colonna testo/telefono (~41vw a 1440px) — solo desktop: sotto gli
   860px le colonne sono impilate, uno scivolamento laterale non ha
   senso e resta lo spostamento breve di prima.
   Opacità e spostamento hanno durate DIVERSE apposta: se durano
   uguale, per gran parte del tragitto il telefono è troppo
   trasparente per notare che si muove e lo slide si "vede" solo
   nell'ultimo tratto, vicino alla posizione finale — sembra che non
   scorra affatto. Con l'opacità che arriva a piena vista in .35s e lo
   spostamento che continua fino a 1.1s, il telefono è già ben visibile
   mentre attraversa la maggior parte della distanza. */
html.has-js .hero__seal[data-reveal]{
  transition: opacity .35s ease-out, transform 1.1s cubic-bezier(.4,0,.2,1);
}
@media (min-width: 861px){
  html.has-js .hero__seal[data-reveal]{ transform: translateX(-41vw); }
}
@media (max-width: 860px){
  html.has-js .hero__seal[data-reveal]{ transform: translateX(-70px); }
}
html.has-js .hero__seal[data-reveal].is-visible{ transform: translateX(0); }

/* Foto del telefono (ritaglio a sfondo trasparente da un mockup
   fotorealistico fornito, non ricostruito in CSS): l'inclinazione e
   l'ombra sono già nell'immagine, qui si gestisce solo la dimensione
   responsive. */
.hero__phone-img{
  width: clamp(200px, 26vw, 300px);
  height: auto;
  display: block;
}

/* Il blocco valore (icona + titolo + paragrafo) affianca il telefono
   invece di stare sotto al titolo: allineato al centro, alla sua
   destra. */
.hero__phone-caption{
  flex-shrink: 0;
  width: 300px;
  text-align: left;
}
.hero__phone-caption-icon{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--blue-soft);
  margin-bottom: 14px;
}
.hero__phone-caption-icon svg{
  width: 22px;
  height: 22px;
  stroke: var(--blue);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.hero__phone-caption-title{
  margin: 0 0 6px;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-primary);
}
.hero__phone-caption-text{
  margin: 0;
  font-size: clamp(0.78rem, 0.3vw + 0.7rem, 0.9rem);
  line-height: 1.45;
  color: var(--text-primary);
}

@media (max-width: 860px){
  .hero__grid{ grid-template-columns: 1fr; gap: 0; }
  /* Titolo prima di tutto, poi il telefono, poi i pulsanti — non più il
     telefono come prima cosa. .hero__text diventa "contents" così i suoi
     figli (eyebrow, h1, pulsanti, nota) entrano direttamente nella grid
     di .hero__grid e possono essere riordinati insieme a .hero__seal
     (il telefono) con un ordine esplicito, invece di poter spostare solo
     il blocco testo intero prima/dopo il blocco telefono intero. Il gap
     di griglia passa a 0 (si applicherebbe a ogni elemento, non solo tra
     le due colonne di prima) e lo spazio tra i pezzi è ricreato a mano:
     l'eyebrow ha già il suo margin-bottom, i pulsanti/nota hanno già il
     loro margin-top di base — manca solo lo spazio sopra al telefono. */
  .hero__text{ display: contents; }
  .eyebrow--dot{ order: 1; }
  #heroTitle{ order: 2; }
  /* Telefono a sinistra, blocco valore (icona+titolo+testo) a destra,
     affiancati come su desktop — non più impilati. Il telefono ha un
     clamp con minimo 200px pensato per desktop: sotto 860px lo si
     restringe parecchio e il blocco testo passa da larghezza fissa
     (300px) a flessibile, altrimenti insieme sfondano la larghezza di
     un telefono normale. */
  .hero__seal{ order: 3; flex-direction: row; align-items: flex-start; justify-content: flex-start; gap: 16px; margin-top: 28px; }
  .hero__actions{ order: 4; }
  .hero__note{ order: 5; }
  .hero__phone-frame{ flex-shrink: 0; }
  .hero__phone-img{ width: clamp(110px, 32vw, 160px); }
  .hero__phone-caption{
    width: auto;
    max-width: none;
    flex: 1;
    min-width: 0;
    text-align: left;
  }
  .hero__phone-caption-icon{ margin-left: 0; margin-right: 0; }
}

/* =========================================================
   Apparsi su (press strip) — marquee a scorrimento continuo
   attivo a ogni larghezza (non più solo mobile): la riga statica
   .press-strip__inner resta nel markup ma nascosta, il blocco
   .press-strip__mobile (label + marquee) è quello sempre visibile.
   Nomi di classe invariati per non toccare l'HTML. Direzione
   invertita rispetto alla versione originale mobile-only: nuovi
   loghi entrano da sinistra ed escono a destra (translateX da
   -50% a 0%, non più 0 -> -50%), su richiesta esplicita ispirata
   a un sito di riferimento con lo stesso verso di scorrimento.
   ========================================================= */
.press-strip{
  position: relative;
  overflow: hidden;
  background-color: var(--bg-dark);
  border-bottom: 0.5px solid var(--on-dark-border);
  padding: 40px 0;
}
/* Curva e bagliore misurati a pixel sui due riferimenti (screenshot
   proof/press): non identici tra loro — quella di "Apparsi su" forma
   un unico arco che culmina intorno al 75% di larghezza, quella dei
   numeri parte più in alto a sinistra, scende, poi risale fino al
   bordo destro. Toni desaturati (blu-grigio, non blu acceso) per
   restare fedeli ai colori campionati. */
/* Ogni curva è disegnata due volte sullo stesso path: una passata
   larga e sfocata (il bagliore/alone, via feGaussianBlur) sotto una
   passata sottile e nitida (il nucleo luminoso) sopra — è questo
   doppio strato a dare l'effetto "fascio di luce" del riferimento,
   non ottenibile con un singolo stroke sottile. */
.press-strip{
  background-image:
    radial-gradient(ellipse 46% 130% at 76% 40%, rgba(79,106,162,.4), transparent 70%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 200' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='pg' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0%25' stop-color='%23BFD4FA' stop-opacity='0'/%3E%3Cstop offset='72%25' stop-color='%23FFFFFF' stop-opacity='1'/%3E%3Cstop offset='100%25' stop-color='%23BFD4FA' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='pb' x='-20%25' y='-100%25' width='140%25' height='300%25'%3E%3CfeGaussianBlur stdDeviation='9'/%3E%3C/filter%3E%3C/defs%3E%3Cpath d='M0,164 C300,20 550,10 870,78 C1000,120 1100,155 1200,182' fill='none' stroke='url(%23pg)' stroke-width='16' filter='url(%23pb)' opacity='.6'/%3E%3Cpath d='M0,164 C300,20 550,10 870,78 C1000,120 1100,155 1200,182' fill='none' stroke='url(%23pg)' stroke-width='2'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: cover, 100% 100%;
  background-position: center, center;
}
.proof{
  background-image:
    radial-gradient(ellipse 46% 130% at 82% 55%, rgba(79,106,162,.4), transparent 70%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 200' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='pf' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0%25' stop-color='%23BFD4FA' stop-opacity='0'/%3E%3Cstop offset='55%25' stop-color='%23FFFFFF' stop-opacity='1'/%3E%3Cstop offset='100%25' stop-color='%23BFD4FA' stop-opacity='0'/%3E%3C/linearGradient%3E%3Cfilter id='pc' x='-20%25' y='-100%25' width='140%25' height='300%25'%3E%3CfeGaussianBlur stdDeviation='9'/%3E%3C/filter%3E%3C/defs%3E%3Cpath d='M0,106 C120,157 220,157 340,110 C550,20 850,20 1050,60 C1120,80 1160,90 1200,98' fill='none' stroke='url(%23pf)' stroke-width='16' filter='url(%23pc)' opacity='.6'/%3E%3Cpath d='M0,106 C120,157 220,157 340,110 C550,20 850,20 1050,60 C1120,80 1160,90 1200,98' fill='none' stroke='url(%23pf)' stroke-width='2'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: cover, 100% 100%;
  background-position: center, center;
}
.press-strip::after, .proof::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 40px;
  background: radial-gradient(ellipse 45% 100% at 50% 100%, rgba(149,172,226,.5), transparent 75%);
  pointer-events: none;
}
.press-strip__inner{ display: none; }

.press-strip__label{
  font-family: var(--font-label);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--on-dark);
  white-space: nowrap;
}

.press-strip__mobile{
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 64px;
}
.press-strip__mobile .press-strip__label{ flex-shrink: 0; margin: 0; }
.press-strip__marquee{
  flex: 1;
  min-width: 0;
  overflow: hidden;
  /* Stop in pixel, non percentuale: con 3 loghi in loop, su schermi larghi
     una dissolvenza in percentuale lascia una zona "piena" troppo ampia e
     mostra lo stesso logo due volte contemporaneamente. La finestra piena
     (40→700px) è tarata per contenere tutti e 3 i loghi + i 2 gap tra
     loro (~660px con le dimensioni attuali) così restano visibili insieme;
     il margine residuo prima che il ciclo si ripeta è un solo gap (96px),
     il massimo possibile per costruzione quando la finestra copre "tutti
     gli elementi di un ciclo" — comunque sufficiente a evitare doppioni o
     salti, aiutato dalla dissolvenza morbida ai bordi invece di un taglio
     netto. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 40px, #000 700px, transparent 760px, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 40px, #000 700px, transparent 760px, transparent 100%);
}
.press-strip__track{
  display: flex;
  align-items: center;
  width: max-content;
  animation: pressMarquee 7s linear infinite;
  /* Promuove il track a un proprio layer compositato per un movimento più
     fluido. */
  will-change: transform;
  backface-visibility: hidden;
}
/* Spaziatura via margin-right su OGNI elemento (non "gap" sul container):
   con "gap" ci sono (n-1) spazi per n elementi, quindi raddoppiando il
   set per il loop (2n elementi) il 50% della larghezza totale non
   corrisponde mai esattamente a "un set completo" — resta sempre
   sfalsato di mezzo gap, che è esattamente lo scatto periodico notato a
   ogni giro. Con un margine uguale dopo OGNI elemento (compreso l'ultimo)
   uno "step" = larghezza+margine è identico ovunque, quindi metà della
   larghezza totale del track coincide sempre con un numero esatto di
   step: translateX(-50%) → translateX(0) diventa un loop perfettamente
   senza soluzione di continuità, qualunque sia la larghezza reale dei
   loghi. */
.press-strip__logo-mark{
  height: 68px;
  width: auto;
  flex-shrink: 0;
  margin-right: 96px;
  opacity: 0.95;
}
/* Placeholder testuale: stesso trattamento visivo dei loghi reali (chiaro
   su blu pieno, nessun riquadro), in attesa di un logo vero da inserire
   come immagine al posto di questo span. */
.press-strip__logo-mark--text{
  flex-shrink: 0;
  margin-right: 96px;
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 600;
  font-size: 2.1rem;
  letter-spacing: 0.01em;
  color: var(--on-dark);
  opacity: 0.95;
  white-space: nowrap;
}

@keyframes pressMarquee{
  0%   { transform: translateX(-50%); }
  100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce){
  .press-strip__track{ animation: none; }
}

@media (max-width: 640px){
  .press-strip__mobile{ flex-direction: column; align-items: stretch; gap: 16px; }
  .press-strip__mobile .press-strip__label{ text-align: center; font-size: 1.15rem; }
  .press-strip__marquee{
    margin-inline: -20px;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 30px, #000 560px, transparent 620px, transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 30px, #000 560px, transparent 620px, transparent 100%);
  }
  .press-strip__logo-mark{ height: 48px; }
  .press-strip__logo-mark--text{ font-size: 1.5rem; }
}

/* =========================================================
   Dicono di noi — video wall
   Reproduces the reference's .cases-track mechanism: the card
   rows and the center column occupy the same CSS Grid cell
   (grid-area overlap), the center column is native
   position:sticky (no GSAP/ScrollTrigger — verified absent on
   the reference for this section too). Card shape/border/bg
   measured identical to this project's own --card-grad/--line/
   --radius tokens. Play button: 58px circle, pure-CSS border
   triangle, cyan ring — no image, no JS.
   ========================================================= */
.case-wall{
  background: var(--bg-base);
  padding: var(--section-y) 0;
  overflow: hidden;
}
.case-wall__pin{
  position: relative;
  display: grid;
  max-width: min(1360px, 92vw);
  margin: 0 auto;
  padding: 0 24px;
}
.case-wall__rows{
  grid-area: 1 / 1;
  place-self: start center;
  width: 100%;
}
.case-wall__row{
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: clamp(220px, 26vw, 400px);
  row-gap: clamp(48px, 10vh, 140px);
  align-items: center;
}
.case-wall__center{
  grid-area: 1 / 1;
  place-self: start center;
  position: sticky;
  top: 96px;
  z-index: 5;
  width: min(300px, 85vw);
  text-align: center;
}
.case-wall__label{
  font-family: var(--font-label);
  font-weight: 500;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 14px;
}
.case-wall__title{
  font-size: clamp(1.05rem, 0.8vw + 0.75rem, 1.3rem);
  line-height: 1.2;
  margin: 0 0 28px;
}
.case-wall__center .btn{ margin: 0 auto; }

.case-card{
  border: 0.5px solid var(--border);
  background: var(--surface-card);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color .2s var(--ease);
}
.case-card:hover{ border-color: var(--border-strong); }

/* Le card testimonianza entrano con uno zoom-out — solo su mobile
   (≤860px). Niente più translateY combinato con lo scale: due assi di
   movimento insieme (su/giù + dimensione) è quello che dava la
   sensazione di "scatto"/non pulito segnalata — un puro zoom (solo
   scale, nessuno spostamento verticale) legge come un singolo
   movimento coerente. Scale di partenza più contenuto (1.08 invece di
   1.18) e transizione leggermente più lunga con un easing che decelera
   in modo più marcato in coda, cosi l'assestamento finale è morbido
   invece che arrivare di scatto. */
@media (max-width: 860px){
  html.has-js .case-card.reveal{
    transform: scale(1.9) !important;
    transition: opacity .7s cubic-bezier(.4,0,.2,1), transform 1.1s cubic-bezier(.16,1,.3,1) !important;
  }
  html.has-js .case-card.reveal.is-visible{ transform: none !important; }
}

.case-card__thumb{
  display: block;
  width: 100%;
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-alt-strong);
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
}
.case-card__video{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}
.case-card__overlay{
  position: absolute;
  inset: 0;
  background: rgba(19,26,43,.15);
  transition: opacity .2s var(--ease);
}
.case-card__play{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: rgba(19,26,43,.65);
  border: 0.5px solid rgba(255,255,255,.4);
  transition: transform .2s var(--ease);
}
.case-card__play::before{
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent var(--bg-base);
  transform: translate(-6px, -9px);
}
.case-card:hover .case-card__play{
  transform: translate(-50%, -50%) scale(1.08);
}
/* Una volta avviato il video, overlay e pulsante play spariscono per
   lasciare spazio ai controlli nativi invece di restare sovrapposti. */
.case-card__thumb.is-playing .case-card__overlay,
.case-card__thumb.is-playing .case-card__play{
  opacity: 0;
  pointer-events: none;
}

.case-card__meta{ padding: 16px 18px 18px; }
.case-card__name{ font-size: 1rem; font-weight: 700; color: var(--text-primary); margin: 0 0 5px; }
.case-card__loc{ font-size: 0.8rem; color: var(--text-secondary); margin: 0 0 12px; }
.case-card__result{
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
  border-top: 0.5px solid var(--border);
  padding-top: 11px;
  margin: 0;
}

@media (max-width: 860px){
  .case-wall__pin{ display: flex; flex-direction: column; gap: 32px; padding: 0 20px; }
  .case-wall__rows{ padding-bottom: 0; }
  .case-wall__row{ grid-template-columns: 1fr; gap: 20px; }
  .case-wall__center{ position: static; order: -1; width: 100%; }
}

/* =========================================================
   Mid CTA
   La card scura "galleggia" ora su una sezione chiara invece di
   fondersi con uno sfondo navy pieno (prima .mid-cta e .mid-cta__card
   erano quasi lo stesso colore): puntini decorativi ai lati (stessa
   tecnica di #metodo::before, ricolorata per sfondo chiaro) + ombra
   sotto la card per dargli rilievo.
   ========================================================= */
.mid-cta{
  position: relative;
  overflow: hidden;
  padding: 56px 0;
  background: linear-gradient(180deg, var(--blue-soft) 0%, var(--bg-base) 20%, var(--bg-base) 100%);
}
.mid-cta::before{
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: radial-gradient(circle, rgba(41,92,212,.28) 1px, transparent 1.5px);
  background-size: 24px 24px;
  -webkit-mask-image: linear-gradient(90deg,
    #000 0%, #000 14%, transparent 28%,
    transparent 72%, #000 86%, #000 100%);
  mask-image: linear-gradient(90deg,
    #000 0%, #000 14%, transparent 28%,
    transparent 72%, #000 86%, #000 100%);
}
.mid-cta__card{
  position: relative;
  z-index: 1;
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
  background-color: var(--blue-deep);
  background-image:
    radial-gradient(circle at 12% 22%, rgba(255,255,255,.2), transparent 13%),
    radial-gradient(circle at 88% 12%, rgba(255,255,255,.15), transparent 11%),
    radial-gradient(circle at 78% 82%, rgba(255,255,255,.13), transparent 15%),
    linear-gradient(rgba(4,19,52,.82), rgba(4,19,52,.82)),
    url("../images/services/service-01-ricerca-mercato.jpg");
  background-size: auto, auto, auto, cover, cover;
  background-position: 0 0, 0 0, 0 0, center, center;
  background-repeat: no-repeat;
  border-radius: var(--radius);
  padding: 64px 56px;
  overflow: hidden;
  box-shadow: 0 30px 60px -20px rgba(4,19,52,.35), 0 12px 28px -12px rgba(4,19,52,.28);
}
.mid-cta__card h2{ color: var(--bg-base); }
.mid-cta__card p{ margin-top: 14px; color: var(--on-dark); font-size: 1.05rem; }
.mid-cta__card .btn{ margin-top: 26px; }
.mid-cta__card .btn--primary{ background: var(--bg-base); color: var(--blue); }
.mid-cta__card .btn__icon{ background: var(--blue); }
.mid-cta__card .btn__icon svg{ stroke: var(--bg-base); }

/* =========================================================
   Proof strip
   ========================================================= */
/* Sezione "risultati/statistiche": una delle due sezioni piene navy. */
.proof{
  position: relative;
  overflow: hidden;
  background-color: var(--bg-dark);
  border-top: 0.5px solid var(--on-dark-border);
  border-bottom: 0.5px solid var(--on-dark-border);
}
.proof__grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
  padding: 44px 24px;
}
.proof__num{
  font-family: var(--font-mono);
  font-size: clamp(1.8rem, 3vw, 2.4rem);
  color: var(--blue-on-dark);
}
.proof__num-suffix{ font-size: 0.55em; color: currentColor; margin-left: 2px; }
.proof__label{
  margin-top: 6px;
  font-size: 0.85rem;
  color: var(--on-dark);
}

/* Entrance/exit reveal: each stat fades and rises in when the strip
   scrolls into view, and resets when it scrolls out, so it replays
   every time the section comes back on screen. */
.proof__item{
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .75s cubic-bezier(.4,0,.2,1), transform .75s cubic-bezier(.4,0,.2,1);
}
.proof__item:nth-child(2){ transition-delay: .1s; }
.proof__item:nth-child(3){ transition-delay: .2s; }
.proof__item:nth-child(4){ transition-delay: .3s; }
.proof.is-in .proof__item{
  opacity: 1;
  transform: translateY(0);
}

/* Star rating: a muted 5-star track with a solid blue row clipped on
   top of it. Width of the fill row is driven by --rating (out of 5)
   and animated in via JS alongside the count-up. */
.proof__stars{
  position: relative;
  width: 108px;
  height: 18px;
  margin-top: 10px;
}
.proof__stars-row{ position: absolute; inset: 0; display: flex; gap: 4px; }
.proof__stars-row svg{ width: 18px; height: 18px; flex: 0 0 18px; }
.proof__stars-row--track svg{ fill: none; stroke: var(--on-dark-border); stroke-width: 1.5; }
.proof__stars-row--fill{
  width: 0%;
  overflow: hidden;
  transition: width 1.6s cubic-bezier(.22,1,.36,1);
}
.proof__stars-row--fill svg{ fill: var(--blue-on-dark); }
.proof.is-in .proof__stars-row--fill{ width: calc(var(--rating, 0) / 5 * 100%); }

@media (max-width: 760px){
  .proof__grid{ grid-template-columns: repeat(4, 1fr); gap: 10px; padding: 32px 14px; }
  .proof__num{ font-size: clamp(1.1rem, 4.5vw, 1.5rem); }
  .proof__num-suffix{ font-size: 0.5em; }
  .proof__label{ font-size: 0.66rem; line-height: 1.25; margin-top: 4px; }
  .proof__stars{ width: 76px; height: 13px; margin-top: 6px; }
  .proof__stars-row svg{ width: 12px; height: 12px; flex: 0 0 12px; }
}

@media (prefers-reduced-motion: reduce){
  .proof__item{ opacity: 1; transform: none; transition: none; }
  .proof__stars-row--fill{ transition: none; width: calc(var(--rating, 0) / 5 * 100%); }
}

/* =========================================================
   Sections (generic)
   ========================================================= */
.section{ padding: var(--section-y) 0; }
.section--sunken{ background: var(--bg-alt); }
.section__head{ max-width: 62ch; margin-bottom: 40px; }
.section__intro{ margin-top: 18px; color: var(--text-secondary); font-size: 1.05rem; }
.section__cta-row{ margin-top: 36px; }

/* =========================================================
   Feature pin — icon+text list scrolls in normal flow on the
   left (each item fades/rises in via [data-reveal], the heading
   sweeps in via the shared reveal-title scroll-scrub wipe) while
   a sticky visual panel on the right stays fixed in place and
   crossfades which glyph is showing, based on which item is
   centered in view. Confirmed against the reference frames
   (Desktop/1/frame): the photo sits at an identical pixel
   position across every frame — it's the text that moves,
   scrolling normally underneath a pinned image, not the other
   way around.
   ========================================================= */
/* Come nel riferimento: lo sfondo della sezione cambia leggermente
   quando cambia la card attiva, invece di restare sempre bianco.
   Due toni soltanto (bianco / blu pieno, dal blu del sito), alternati
   in base all'indice della card — non i 5 colori diversi, solo un
   respiro cromatico ogni volta che cambia il pannello. */
#strumenti{ background: var(--bg-base); transition: background-color .6s ease; }
#strumenti.feature-pin--tinted{ background: var(--bg-alt); }
/* Blu pieno invece di azzurro tenue: il testo che sta direttamente
   sullo sfondo (non sulle card bianche/icona) passa ai toni chiari
   solo quando la tinta è attiva, altrimenti resta scuro sul bianco. */
#strumenti.feature-pin--tinted .eyebrow{ color: var(--blue-on-dark); }
#strumenti.feature-pin--tinted .section__intro,
#strumenti.feature-pin--tinted .feature-pin__item p:not(.eyebrow){ color: var(--on-dark); }
#strumenti.feature-pin--tinted .section__head h2{ color: var(--on-dark); }
#strumenti.feature-pin--tinted .text-link{ color: var(--blue-on-dark); }
#strumenti.feature-pin--tinted .text-link:hover{ color: var(--on-dark); }
html.has-js #strumenti.feature-pin--tinted .reveal-title{
  background-image: linear-gradient(90deg,
    var(--on-dark) calc(var(--reveal) - 3%),
    rgba(243,241,236,.2) calc(var(--reveal) + 3%));
}
@media (prefers-reduced-motion: reduce){
  html.has-js #strumenti.feature-pin--tinted .reveal-title{ color: var(--on-dark); -webkit-text-fill-color: var(--on-dark); }
}
.feature-pin{
  display: grid;
  grid-template-columns: 1fr 0.85fr;
  gap: 64px;
  /* stretch (grid default): .feature-pin__visual must span the full
     height of .feature-pin__list, not just the sticky panel's own
     ~450px, otherwise its containing block runs out before the list
     finishes scrolling and the sticky panel scrolls away early. */
}
.feature-pin__item{
  /* Taller than the panel/viewport on purpose: this is what paces the
     scroll-through — each item needs enough scroll distance for its
     own heading wipe (see updateRevealTitles in main.js) to fully
     resolve with room to spare before the next item starts entering,
     so items in normal flow never visually overlap. Bumped up from
     72vh: at 72 the reference felt "softer/more linear" by comparison
     because ours was rushing through each item slightly faster. */
  min-height: 88vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 32px 0;
}
.feature-pin__item:first-child{ min-height: 68vh; }
.feature-pin__icon{
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--surface-card);
  border: 0.5px solid var(--border-strong);
  margin-bottom: 20px;
}
.feature-pin__icon svg{ width: 24px; height: 24px; fill: none; stroke: var(--blue); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.feature-pin__item h3{ margin-bottom: 10px; }
.feature-pin__item p:not(.eyebrow){ color: var(--text-primary); font-size: 1rem; }
.feature-pin__item .eyebrow{ font-size: 1.4rem; letter-spacing: 0.02em; margin-bottom: 12px; }

.feature-pin__visual{ position: relative; }
.feature-pin__sticky{
  position: sticky;
  top: 110px;
  height: 64vh;
  min-height: 420px;
  max-height: 600px;
  background: var(--surface-card);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.feature-pin__panel{
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.feature-pin__panel.is-active{ opacity: 1; transform: scale(1); }
.feature-pin__photo{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Niente gradienti: al posto dello scrim sfumato sull'intera foto,
   un chip piatto solo dietro l'etichetta per restare leggibile. */
.plate-number{
  position: absolute;
  top: 20px;
  left: 24px;
  background: rgba(19,26,43,.75);
  padding: 4px 10px;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--bg-base);
  text-transform: uppercase;
}
.glyph{ width: 62%; height: auto; }
.glyph rect, .glyph line, .glyph path, .glyph circle{
  fill: none;
  stroke: var(--blue);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Foto per-item: nascosta su desktop (dove la stessa foto vive già nel
   pannello sticky .feature-pin__visual), mostrata solo sotto 860px al
   posto del pannello — così il mobile non perde le foto reali dei
   servizi, resta solo in normal flow invece che sticky/crossfade
   (lo scroll-jacking non ha senso su touch). display:none su desktop
   fa sì che i browser che rispettano lazy-loading su elementi non
   renderizzati non scarichino affatto queste immagini duplicate lì. */
.feature-pin__item-photo{
  display: none;
}
@media (max-width: 860px){
  .feature-pin{ grid-template-columns: 1fr; gap: 12px; }
  .feature-pin__visual{ display: none; }
  /* Foto in cima (più alta/"lunga" di prima, 3:4 invece di 4:3), poi
     tutto il testo raggruppato subito sotto senza spezzarlo — prima la
     foto stava in mezzo tra titolo e paragrafo. Padding aumentato +
     una linea sottile tra un item e il successivo (non prima del
     primo) per rendere lo stacco tra i servizi ben evidente. */
  .feature-pin__item{ min-height: 0; padding: 40px 0; }
  .feature-pin__item + .feature-pin__item{ border-top: 1px solid var(--border); }
  .feature-pin__item-photo{
    display: block;
    position: relative;
    aspect-ratio: 3 / 4;
    margin: 0 0 20px;
    border-radius: var(--radius);
    overflow: hidden;
    border: 0.5px solid var(--border);
  }
  .feature-pin__item-photo img{
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
}

/* =========================================================
   Final CTA / contact
   ========================================================= */
/* Sezione piena navy: CTA finale + form di contatto. */
.final-cta{ padding: var(--section-y) 0; background: var(--bg-dark); }
.final-cta__inner{ max-width: 900px; }
.final-cta .eyebrow{ color: var(--blue-on-dark); }
.final-cta h2{ color: var(--on-dark); }
.final-cta__lede{
  margin-top: 20px;
  color: var(--on-dark-soft);
  font-size: 1.1rem;
  max-width: 62ch;
}

.contact-form{ margin-top: 44px; max-width: 780px; }

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

.checkbox{
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.88rem;
  color: var(--on-dark-soft);
  margin-bottom: 28px;
  cursor: pointer;
}
.checkbox input{ margin-top: 3px; }
.checkbox a{ color: var(--blue-on-dark); text-decoration: underline; }

/* =========================================================
   Form finale a step ("wizard"), una domanda alla volta.
   Ogni .form-step occupa lo stesso spazio in normal flow (solo uno
   alla volta è display:block via .is-active) cosi il form non ha
   un'altezza fissa innaturale — cambia dolcemente da uno step
   all'altro invece di avere un buco vuoto sotto le domande brevi.
   ========================================================= */
.form-progress{
  height: 4px;
  border-radius: 999px;
  background: var(--on-dark-surface);
  overflow: hidden;
  margin-bottom: 40px;
}
.form-progress__bar{
  height: 100%;
  width: 0%;
  background: var(--blue-on-dark);
  border-radius: 999px;
  transition: width .4s var(--ease);
}

/* Bersaglio di tutti i CTA "Richiedi consulenza" del sito (non più la
   cima della sezione #contatti, che atterrava sopra eyebrow/titolo/lede
   lasciando il visitatore a dover scorrere ancora per vedere il form).
   #formSteps (non il singolo .form-step "nome") perché resta sempre
   visibile qualunque sia lo step attivo — i .form-step sono display:none
   a turno, quindi ancorarsi diretto a uno di loro smetterebbe di
   funzionare se il visitatore ha già superato lo step 0. scroll-margin-top
   compensa l'header sticky cosi la prima domanda resta visibile subito
   sotto l'header invece di finirci dietro. */
#formSteps{ scroll-margin-top: 120px; }

.form-step{ display: none; }
.form-step.is-active{
  display: block;
  animation: formStepIn .4s var(--ease) both;
}
@keyframes formStepIn{
  from{ opacity: 0; transform: translateY(10px); }
  to{ opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce){
  .form-step.is-active{ animation: none; }
}

.form-step__back{
  display: inline-block;
  background: none;
  border: 0;
  /* Padding invece di niente: ingrandisce l'area toccabile su mobile
     (font-size 0.86rem da solo resta sotto i 44px minimi consigliati)
     senza spostare la posizione visiva del testo — il margine negativo
     compensa esattamente il padding aggiunto. */
  padding: 10px 4px;
  margin: -10px 0 12px -4px;
  font-family: var(--font-body);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--on-dark-soft);
  cursor: pointer;
  transition: color .2s ease;
}
.form-step__back:hover{ color: var(--blue-on-dark); }

.form-step__question{
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.3rem, 1rem + 1.2vw, 1.8rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--on-dark);
  margin: 0 0 22px;
}

.form-step__input{
  width: 100%;
  min-height: 58px;
  padding: 14px 20px;
  background: var(--surface-card);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 1.05rem;
  transition: border-color .2s ease;
}
.form-step__input::placeholder{ color: var(--text-secondary); opacity: .7; }
.form-step__input:focus{ border-color: var(--blue); }
.form-step.has-error .form-step__input{ border-color: var(--red); }

.form-step__error{
  min-height: 1.2em;
  margin: 10px 0 0;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--red);
  opacity: 0;
  transition: opacity .15s ease;
}
.form-step.has-error .form-step__error{ opacity: 1; }

.form-step__nav{ margin-top: 28px; }

.form-step__choices{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
}
.form-choice{
  text-align: left;
  padding: 16px 20px;
  min-height: 56px;
  background: var(--surface-card);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.98rem;
  line-height: 1.3;
  cursor: pointer;
  transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.form-choice:hover{ border-color: var(--blue); }
.form-choice.is-selected{
  border-color: var(--blue);
  background: var(--blue-soft);
  transform: translateY(-1px);
}

/* =========================================================
   Schermata finale — stesso spazio del form, nessuna nuova sezione.
   ========================================================= */
.form-step--final .form-step__question--final{ margin-bottom: 14px; }
.form-final__text{
  margin: 0 0 28px;
  color: var(--on-dark-soft);
  font-size: 1.02rem;
  max-width: 56ch;
}
.form-final__consent{ margin-top: 20px; }
.form-final__cta[disabled]{
  opacity: .45;
  cursor: not-allowed;
  transform: none !important;
}
.form-step__back--final{ margin: 20px 0 0; }

@media (max-width: 640px){
  .form-step__question{ font-size: 1.35rem; }
  .form-step__input, .form-choice{ font-size: 1rem; }
  .form-step__choices{ grid-template-columns: 1fr; }
}

/* =========================================================
   Perché siamo diversi (problema + differenziazione accorpati)
   Sfondo a gradiente orizzontale (non obliquo) bianco → blu pieno,
   con una foto del salone che si intravede solo nella fascia scura
   a destra (stesso trucco overlay-colore+foto di .mid-cta__card, qui
   con l'overlay opaco fino al 64% cosi la foto non tocca mai la zona
   bianca). Gli stop sono tarati sulle posizioni REALI misurate a
   1440px (non sullo screen di riferimento, che ha proporzioni
   diverse): il titolo termina al 43% di larghezza sezione, le card
   iniziano al 46% — il bianco pieno deve coprire tutto il titolo con
   margine, quindi resta fino al 46%, poi scurisce in fretta (zona di
   transizione stretta apposta, 46%→64%) cosi le card partono già su
   sfondo scuro invece che a metà sfumatura. */
/* --diff-reveal pilota la posizione degli stop cosi il gradiente si
   può animare (i gradienti normali non si transizionano): a 0% la
   fascia bianca è collassata a zero (tutto già blu tranne un filo sul
   bordo sinistro), a 100% è alla sua posizione di riposo (bianco fino
   al 46%, blu pieno dal 64%) — stessa larghezza di transizione (18
   punti) mantenuta per tutto il tragitto, cosi il bordo sfumato
   sembra "spazzare" da sinistra verso destra invece di un fade
   generico. Fallback 100% fuori da html.has-js: senza JS la sezione
   deve comunque nascere già leggibile, non bloccata sullo stato
   collassato. */
@property --diff-reveal{
  syntax: '<percentage>';
  initial-value: 100%;
  inherits: true;
}
#differenza{
  --diff-reveal: 100%;
  background-image:
    linear-gradient(90deg,
      var(--bg-base) 0%,
      var(--bg-base) calc(var(--diff-reveal) * 0.46),
      var(--blue-deep) calc(18% + var(--diff-reveal) * 0.46),
      rgba(4,19,52,.85) 100%),
    url("../images/services/service-04-automazioni-crm.jpg");
  background-size: cover, cover;
  background-position: center, center right;
  background-repeat: no-repeat, no-repeat;
}
html.has-js #differenza{
  --diff-reveal: 0%;
  transition: --diff-reveal 1.2s cubic-bezier(.4,0,.2,1);
}
html.has-js #differenza.is-bg-visible{ --diff-reveal: 100%; }
@media (prefers-reduced-motion: reduce){
  html.has-js #differenza{ --diff-reveal: 100%; transition: none; }
}
.differenza__layout{
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 48px;
  align-items: start;
}
.differenza__compare{
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.differenza__row{
  display: grid;
  grid-template-columns: auto 1fr auto auto 1fr;
  align-items: center;
  gap: 16px;
  /* Opaco a sufficienza da restare leggibile indipendentemente da dove
     cade il gradiente bianco/blu della sezione dietro — un fondo
     troppo trasparente lasciava il testo a bassa leggibilità proprio
     nella fascia di transizione del gradiente. */
  background: rgba(4,19,52,.65);
  border: 0.5px solid rgba(255,255,255,.14);
  border-radius: var(--radius);
  padding: 22px 28px;
}
.differenza__mark{
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
  opacity: 0;
  transform: scale(0.4);
  transition: opacity .2s ease, transform .2s ease;
}
.differenza__mark--x{
  border: 1.5px solid var(--red);
  color: var(--red);
  box-shadow: 0 0 16px 1px rgba(200,30,30,.45);
}
.differenza__mark--check{
  border: 1.5px solid var(--green);
  color: var(--green);
  box-shadow: 0 0 16px 1px rgba(13,122,53,.45);
}
.differenza__arrow{
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  fill: none;
  stroke: var(--blue-on-dark);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transition: opacity .3s ease;
}

/* Ingresso sequenziale: ogni riga si "scrive" tutta insieme (icona X,
   testo, freccia, icona check, testo — stesso istante, non più
   colonna-per-colonna) via wipe a text-clip, stessa tecnica di
   .reveal-title ma a tempo invece che legata allo scroll. La logica
   direzionale (JS, non il generico [data-reveal] one-shot) sta in
   main.js, che aggiunge .is-visible solo entrando scendendo e la
   toglie solo uscendo salendo — quindi una volta completata la
   sequenza resta visibile anche scorrendo oltre verso il basso, e si
   rigenera solo uscendo dalla sezione verso l'alto e poi rientrando
   scendendo. */
@property --reveal-seq{
  syntax: '<percentage>';
  initial-value: 0%;
  inherits: true;
}
@keyframes differenzaWipe{ to{ --reveal-seq: 100%; } }
/* Stato di riposo: niente background-image, solo color:transparent →
   totalmente invisibile (non il "fantasma" al 12% qui sotto). Serve a
   restare davvero trasparente quando .is-visible non c'è ancora (prima
   voce) o non c'è più (arrivo risalendo dal basso). */
.differenza__wipe{
  --reveal-seq: 0%;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
/* Solo mentre la sequenza è attiva. Il bordo sfumato del gradiente sta
   tutto DIETRO a --reveal-seq (mai davanti): a riposo (--reveal-seq:0%)
   il secondo stop cade esattamente sullo 0, quindi tutta la riga è
   alpha 0, senza nessun residuo del colore sulla primissima lettera —
   con lo stop successivo spostato in avanti (+2%) restava visibile
   un filo di colore proprio lì, che si leggeva come testo già
   sbiadito/a metà all'arrivo sulla sezione. Colore chiaro (non più
   scuro) dato che le righe ora stanno sulla parte blu dello sfondo. */
.differenza__compare.is-visible .differenza__wipe{
  background-image: linear-gradient(90deg,
    var(--on-dark) calc(var(--reveal-seq) - 2%),
    rgba(243,241,236,0) var(--reveal-seq));
  -webkit-background-clip: text;
  background-clip: text;
  animation: differenzaWipe .2s linear forwards;
}
.differenza__compare.is-visible .differenza__mark{ opacity: 1; transform: scale(1); }
.differenza__compare.is-visible .differenza__arrow{ opacity: 1; }

.differenza__row:nth-child(1) .differenza__wipe,
.differenza__row:nth-child(1) .differenza__mark{ animation-delay: 0s; transition-delay: 0s; }
.differenza__row:nth-child(1) .differenza__arrow{ transition-delay: .15s; }
.differenza__row:nth-child(2) .differenza__wipe,
.differenza__row:nth-child(2) .differenza__mark{ animation-delay: .3s; transition-delay: .3s; }
.differenza__row:nth-child(2) .differenza__arrow{ transition-delay: .45s; }
.differenza__row:nth-child(3) .differenza__wipe,
.differenza__row:nth-child(3) .differenza__mark{ animation-delay: .6s; transition-delay: .6s; }
.differenza__row:nth-child(3) .differenza__arrow{ transition-delay: .75s; }

@media (prefers-reduced-motion: reduce){
  .differenza__wipe{
    background-image: none !important;
    color: var(--on-dark) !important;
    -webkit-text-fill-color: var(--on-dark) !important;
    animation: none !important;
  }
  .differenza__mark{ opacity: 1 !important; transform: none !important; }
  .differenza__arrow{ opacity: 1 !important; }
}

@media (max-width: 860px){
  #differenza{
    background: linear-gradient(180deg,
      var(--bg-base) 0%, var(--bg-base) 22%,
      var(--blue-deep) 42%, var(--blue-deep) 100%);
  }
  .differenza__layout{ grid-template-columns: 1fr; gap: 32px; }
}
/* Sotto i 1100px la riga a 5 colonne (icona X / testo / freccia / icona
   check / testo) resta schiacciata dentro la colonna destra di
   .differenza__layout non appena la finestra è affiancata a un'altra
   (768–1200px), quindi passa a icona+testo impilati su due righe — ma
   negativo a sinistra e positivo a destra restano affiancati come su
   desktop (non più negativo sopra/positivo sotto): 3 colonne (negativo |
   freccia | positivo) × 2 righe (icona | testo), posizionate per
   ordine reale dei figli nel markup, non per classe (le due .wipe
   condividono la stessa classe). */
@media (max-width: 1100px){
  .differenza__row{
    grid-template-columns: 1fr auto 1fr;
    grid-template-rows: auto auto;
    row-gap: 8px;
    column-gap: 14px;
    padding: 18px 16px;
  }
  .differenza__row > :nth-child(1){ grid-column: 1; grid-row: 1; }
  .differenza__row > :nth-child(2){ grid-column: 1; grid-row: 2; }
  .differenza__row > :nth-child(3){ grid-column: 2; grid-row: 1 / span 2; align-self: center; transform: none; width: 16px; height: 16px; }
  .differenza__row > :nth-child(4){ grid-column: 3; grid-row: 1; }
  .differenza__row > :nth-child(5){ grid-column: 3; grid-row: 2; }
}

/* =========================================================
   Metodo in 3 fasi
   ========================================================= */
.section__head--center{ max-width: 72ch; margin-left: auto; margin-right: auto; text-align: center; }
.section__cta-row--center{ text-align: center; }

/* Pinned scroll: tall track + sticky viewport. JS toggles .is-active
   on one .method-card at a time as the track scrolls past. Height is
   set inline (methodPin.style.height) so it matches step count exactly. */
.method-pin{ position: relative; }
.method-pin__sticky{
  position: sticky;
  top: 84px;
  height: calc(100vh - 84px);
  min-height: 520px;
  max-height: 760px;
  display: flex;
  align-items: center;
  overflow: hidden;
}
#metodo{
  position: relative;
  z-index: 0;
  background: var(--bg-alt);
}
/* Puntini solo nei margini sinistro/destro, non dietro a testo e
   card: un layer dedicato (non lo sfondo diretto della sezione)
   cosi si può sfumare via mask senza toccare il colore di fondo. */
#metodo::before{
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: radial-gradient(circle, rgba(149, 172, 226, .22) 1px, transparent 1.5px);
  background-size: 24px 24px;
  -webkit-mask-image: linear-gradient(90deg,
    #000 0%, #000 14%, transparent 28%,
    transparent 72%, #000 86%, #000 100%);
  mask-image: linear-gradient(90deg,
    #000 0%, #000 14%, transparent 28%,
    transparent 72%, #000 86%, #000 100%);
}
/* Sfondo blu pieno: eyebrow, titoli e note in questa sezione stanno
   direttamente sopra (le card del metodo restano bianche, non
   toccate), quindi passano ai toni chiari già usati sulle sezioni
   navy altrove nel sito — stesso trattamento di #differenza. */
#metodo .eyebrow{ color: var(--blue-on-dark); }
#metodo .section__intro{ color: var(--on-dark-soft); }
#metodo .method-scroll__side h3{ color: var(--on-dark); }
html.has-js #metodo .reveal-title{
  background-image: linear-gradient(90deg,
    var(--on-dark) calc(var(--reveal) - 3%),
    rgba(243,241,236,.2) calc(var(--reveal) + 3%));
}
@media (prefers-reduced-motion: reduce){
  html.has-js #metodo .reveal-title{ color: var(--on-dark); -webkit-text-fill-color: var(--on-dark); }
}
.method-scroll{
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 64px;
  align-items: center;
  width: 100%;
}
.method-scroll__note{ margin-top: 16px; color: var(--on-dark-soft); font-size: 1rem; }

/* Rail verticale sul bordo destro della sezione (fuori dal grid a due
   colonne, ancorato allo sticky wrapper cosi resta fisso mentre le
   card scorrono): stessi 5 pallini di prima, solo riletti in verticale
   con un bagliore sul passo attivo al posto del semplice scale(). */
.method-rail{
  position: absolute;
  top: 50%;
  right: clamp(20px, 4vw, 56px);
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  z-index: 1;
}
.method-rail__end{
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--on-dark-border);
  flex-shrink: 0;
}
.method-rail__arrow{
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  fill: none;
  stroke: var(--on-dark-soft);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.method-scroll__dots{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 4px 0;
  position: relative;
}
.method-scroll__dots::before{
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 0;
  border-left: 1px dashed var(--on-dark-border);
  transform: translateX(-50%);
  z-index: -1;
}
.method-dot{
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--on-dark-surface);
  border: 1.5px solid var(--on-dark-border);
  flex-shrink: 0;
  transition: background .3s ease, border-color .3s ease, box-shadow .3s ease, transform .3s ease;
}
.method-dot.is-active{
  background: var(--blue);
  border-color: var(--blue-on-dark);
  box-shadow: 0 0 0 4px rgba(41,92,212,.28), 0 0 16px 2px rgba(41,92,212,.7);
  transform: scale(1.4);
}
@media (max-width: 1100px){
  .method-rail{ display: none; }
}

.method-scroll__cta{
  margin-top: 28px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .4s ease, transform .4s ease;
  pointer-events: none;
}
.method-scroll__cta.is-visible{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Card stack: cards sit in their own natural flex slots (.method-cards__track,
   JS-translated so the active one is centered in the viewport — same
   real-DOM-measured math as a plain conveyor) so the opaque active card
   never fully covers its neighbours the way it did when every card
   shared one absolute inset:0 box. On top of that positioning, each
   card gets a discrete recede state: the exiting card blurs, dims and
   scales down roughly in place while the next rises into view and
   settles sharp — confirmed against 3 timestamped reference screenshots
   (Desktop/Screenshot ...2.32.27/32/36 PM.png) showing the outgoing
   card clearly visible-but-blurred, not reduced to a sliver. State is a
   function of position relative to the active card, never of scroll
   history, so the motion is identical and reversible forwards/backwards. */
.method-scroll__cards{ position: relative; min-height: 340px; height: 100%; padding: 44px; overflow: hidden; }
.method-cards__track{
  display: flex;
  flex-direction: column;
  gap: 64px;
}
.method-card{
  background: var(--surface-card);
  border: 0.5px solid var(--border);
  border-radius: var(--radius);
  padding: 40px 36px 36px;
  flex-shrink: 0;
  opacity: 0;
  transform: scale(0.96);
  transition: opacity .6s cubic-bezier(.4,0,.2,1), transform .6s cubic-bezier(.4,0,.2,1), filter .6s cubic-bezier(.4,0,.2,1), box-shadow .6s cubic-bezier(.4,0,.2,1);
  filter: blur(0);
  box-shadow: 0 0 0 rgba(41,92,212,0);
}
.method-card.is-waiting{ opacity: 0; }
.method-card.is-prev{ opacity: 0.6; transform: scale(0.94); filter: blur(6px); }
.method-card.is-past{ opacity: 0; transform: scale(0.92); filter: blur(6px); }
.method-card.is-active{
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  box-shadow: 0 0 30px 2px rgba(41,92,212,.35), 0 0 60px 10px rgba(41,92,212,.2), 0 20px 45px rgba(2,8,24,.4);
}
.method-card__icon{
  display: flex;
  width: 52px;
  height: 52px;
  margin-bottom: 22px;
}
.method-card__icon svg{
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--cyan-glow);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.method-card h3{ font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.1rem); margin-bottom: 14px; }
.method-card p{ color: var(--text-primary); font-size: 0.95rem; }
.method-card strong{ color: var(--text-primary); }

/* Reduced motion only: drop the pin/scrub effect entirely in favour of a
   plain static stacked layout, regardless of screen width. */
@media (prefers-reduced-motion: reduce){
  .method-pin{ height: auto !important; }
  .method-pin__sticky{
    position: static;
    height: auto;
    min-height: 0;
    max-height: none;
    overflow: visible;
  }
  .method-scroll{ grid-template-columns: 1fr; gap: 32px; }
  .method-scroll__dots{ display: none; }
  .method-scroll__cta{
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
  }
  .method-scroll__cards{ min-height: 0; height: auto; overflow: visible; }
  .method-cards__track{ transform: none !important; gap: 20px; }
  .method-card{
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
}

/* Below 860px the pin/scrub mechanic STAYS active (matches desktop: one
   card visible at a time, changing on scroll) — only the layout adapts.
   .method-pin__sticky keeps side-intro + cards + dots together as a
   single sticky unit (stacked in one column instead of two), sized to
   fit a phone viewport instead of a desktop one. */
@media (max-width: 860px){
  .method-scroll{ grid-template-columns: 1fr; gap: 20px; }
  /* height:auto invece di forzare quasi-100vh: .method-pin__sticky deve
     solo essere alta quanto il suo contenuto reale per restare "sticky"
     correttamente — non serve riempire lo schermo. Forzarla troppo alta
     con justify-content:center lasciava un vuoto enorme sopra/sotto un
     contenuto molto più corto del riquadro. top:84px (ereditato dalla
     regola base, non più sovrascritto a 8px) evita che il riquadro
     sticky si infili sotto l'header (anch'esso sticky, z-index sopra):
     con top:8px il riquadro partiva praticamente sotto l'header
     traslucido, che ne copriva la parte alta. */
  .method-pin__sticky{
    height: auto;
    min-height: 0;
    max-height: none;
    flex-direction: column;
    justify-content: flex-start;
    padding: 4px 0;
  }
  /* Il testo introduttivo (eyebrow + "Tre punti fermi, zero
     compromessi" + CTA) è ridondante col titolo della sezione appena
     sopra su mobile — via, per tenere le card il più vicino possibile
     al titolo invece di ripetere un secondo titolo prima di arrivarci. */
  .method-scroll__side{ display: none; }
  /* Alto quanto basta per la card più alta (~300px coi testi reali e le
     dimensioni compattate qui sotto) più un margine per intravedere la
     card vicina sfocata: su mobile main.js ancora la card attiva al suo
     stesso centro (niente più lo scrub continuo verso il centro della
     card successiva usato su desktop), quindi il riquadro non deve più
     assorbire lo spostamento di un'intera card+gap — solo prima lo
     faceva, ed essendo alto solo 420px con margine quasi nullo bastava
     lo scrub a metà transizione per spingere icona e titolo sopra il
     bordo (tagliati da overflow:hidden), lasciando un vuoto blu enorme
     sotto: la card "a mezzo schermo" segnalata. Va comunque tenuto
     entro l'altezza dello schermo (meno header e riga puntini): oltre
     quella soglia lo sticky esaurisce lo spazio del suo contenitore e
     si stacca (torna a scorrere normale) prima che lo scroll-scrub
     finisca, troncando l'animazione a metà invece di tagliare la
     card. */
  .method-scroll__cards{ padding: 0; min-height: 0; height: 480px; }
  .method-cards__track{ gap: 20px; transition: transform .45s cubic-bezier(.4,0,.2,1); }
  /* Card più compatta solo su mobile: meno padding/icona più piccola/
     titolo più contenuto tengono la card entro un'altezza che il
     riquadro qui sopra può contenere per intero con margine, invece di
     doverlo gonfiare oltre l'altezza dello schermo per rincorrere una
     card più alta. */
  .method-card{ padding: 28px 24px 24px; }
  .method-card__icon{ width: 40px; height: 40px; margin-bottom: 16px; }
  .method-card h3{ font-size: clamp(1.3rem, 1rem + 1.6vw, 1.7rem); margin-bottom: 10px; }
  .method-rail{
    display: flex;
    position: static;
    flex-direction: row;
    transform: none;
    top: auto;
    right: auto;
    margin-top: 8px;
    justify-content: center;
  }
  .method-rail__end, .method-rail__arrow{ display: none; }
  .method-scroll__dots{ flex-direction: row; }
  .method-scroll__dots::before{ display: none; }
}

/* =========================================================
   Processo / rassicurazione — timeline "onda": tre tappe alternate
   sopra/sotto una linea curva, invece delle due colonne precedenti
   (testo + lista verticale). Riferimento: screenshot di un altro
   sito (Atlantide Group) fornito come modello di stile.
   ========================================================= */
#processo{ background: var(--bg-base); }
.process-head{ max-width: 60ch; margin: 0 auto; text-align: center; }
.eyebrow--lines{ display: inline-flex; align-items: center; gap: 14px; }
.eyebrow--lines::before,
.eyebrow--lines::after{
  content: "";
  width: 28px;
  height: 1px;
  background: var(--border-strong);
}

.process-wave{
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-top: 72px;
  padding: 0 0 50px;
}
.process-wave__line{
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 260px;
  overflow: visible;
}
/* Linea blu (non più beige) e "disegnata" via stroke-dasharray: JS
   calcola la lunghezza reale del path e la transizione anima
   stroke-dashoffset da quella lunghezza a 0, dando l'effetto di una
   linea che si allunga da sinistra a destra invece di apparire già
   tracciata — vedi drawProcessWave in main.js. */
.process-wave__line path{
  fill: none;
  stroke: var(--blue);
  stroke-width: 2.5;
  transition: stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1);
}
.process-wave__line circle{ fill: var(--blue); }

.process-wave__step{
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 27%;
  text-align: center;
}
.process-wave__step--up{ margin-top: 0; }
.process-wave__step--down{ margin-top: 170px; }
.process-wave__step--up .process-wave__text{ margin-bottom: 44px; }
.process-wave__step--down .process-wave__text{ margin-top: 44px; }

/* Cerchi molto più ampi e più staccati dal testo (screen di
   riferimento): dimensione quasi raddoppiata rispetto alla prima
   versione, alone proporzionalmente più spesso. */
.process-wave__circle{
  flex-shrink: 0;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--text-primary);
  color: var(--bg-base);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1.5rem;
  box-shadow: 0 0 0 11px var(--blue-soft);
}
.process-wave__text h3{ font-size: 1.02rem; margin-bottom: 8px; }
.process-wave__text p{ margin: 0; color: var(--text-primary); font-size: 0.88rem; line-height: 1.45; }

@media (max-width: 860px){
  .process-wave{ flex-direction: column; gap: 40px; padding: 0; margin-top: 40px; }
  .process-wave__line{ display: none; }
  .process-wave__step{
    width: 100%;
    max-width: 320px;
    margin: 0 auto !important;
  }
  .process-wave__step--up .process-wave__circle,
  .process-wave__step--down .process-wave__circle{ order: -1; margin-bottom: 32px; }
  .process-wave__step--up .process-wave__text,
  .process-wave__step--down .process-wave__text{ margin: 0; }
}

/* =========================================================
   Footer
   ========================================================= */
/* Prosegue la sezione piena navy iniziata dal final-cta. */
.site-footer{
  background: var(--bg-dark);
  border-top: 0.5px solid var(--on-dark-border);
  padding-top: 72px;
}
.footer-grid{
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 40px;
  padding-bottom: 56px;
}
.footer-col--about p{ margin-top: 16px; color: var(--on-dark-soft); font-size: 0.92rem; max-width: 34ch; }
.wordmark--footer{ margin-bottom: 4px; }
.wordmark--footer .brand-name__primary{ color: var(--on-dark); }
.wordmark--footer .brand-name__accent{ color: var(--blue-on-dark); }
.footer-col h4{
  font-family: var(--font-label);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-on-dark);
  margin: 0 0 18px;
}
.footer-col ul{ list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.footer-col a{ color: var(--on-dark-soft); font-size: 0.92rem; transition: color .2s ease; }
.footer-col a:hover{ color: var(--blue-on-dark); }
.footer-col li{ color: var(--on-dark-soft); font-size: 0.92rem; }

.legal-bar{
  border-top: 0.5px solid var(--on-dark-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px 24px;
  font-size: 0.82rem;
  color: var(--on-dark-soft);
  flex-wrap: wrap;
  gap: 12px;
}
.back-to-top{ color: var(--blue-on-dark); font-weight: 600; }

@media (max-width: 860px){
  .footer-grid{ grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px){
  .footer-grid{ grid-template-columns: 1fr; }
}

/* =========================================================
   Cookie banner
   ========================================================= */
.cookie-banner{
  position: fixed;
  left: 20px;
  right: 20px;
  bottom: 20px;
  z-index: 300;
  background: var(--surface-card);
  border: 0.5px solid var(--border-strong);
  border-radius: var(--radius);
}
.cookie-banner__inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px 24px;
  flex-wrap: wrap;
}
.cookie-banner__inner p{ font-size: 0.88rem; color: var(--text-secondary); max-width: 56ch; }
.cookie-banner__actions{ display: flex; gap: 10px; flex-shrink: 0; }

/* =========================================================
   Pagine legali (Privacy Policy / Cookie Policy)
   Testo lungo in colonna leggibile, stessi token tipografici/colore
   del resto del sito ma senza le animazioni scroll-driven (pagine
   statiche, contenuto normativo).
   ========================================================= */
.legal-page{ padding: var(--section-y) 0 calc(var(--section-y) * 1.4); }
.legal-page__header{ max-width: 68ch; margin: 0 auto 48px; }
.legal-page__updated{
  margin-top: 14px;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.legal-page__body{
  max-width: 68ch;
  margin: 0 auto;
  color: var(--text-secondary);
  font-size: 1.02rem;
  line-height: 1.7;
}
.legal-page__body h2{
  font-size: clamp(1.25rem, 1rem + 1vw, 1.6rem);
  color: var(--text-primary);
  margin: 44px 0 16px;
}
.legal-page__body h2:first-child{ margin-top: 0; }
.legal-page__body p{ margin: 0 0 16px; }
.legal-page__body ul{ margin: 0 0 16px; padding-left: 22px; }
.legal-page__body li{ margin-bottom: 8px; }
.legal-page__body a{ color: var(--blue); text-decoration: underline; }
.legal-page__body strong{ color: var(--text-primary); }
.legal-page__back{
  display: inline-block;
  margin-bottom: 32px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-secondary);
}
.legal-page__back:hover{ color: var(--blue); }

/* =========================================================
   Split-screen / "mezzo schermo" desktop (768–1200px)
   L'unico breakpoint largo del sito è 860px: tra 861 e 1180px (tipico
   quando la finestra è affiancata a un'altra su un monitor
   1440–2560px, es. 960px = metà di un 1920) le griglie desktop restano
   piene con gap pensati per viewport intere, e finiscono per rubare
   spazio utile al contenuto. Scoperto con range (min+max) invece di
   un secondo max-width, così non entra mai in conflitto di cascata
   con i blocchi @media (max-width:860px) già presenti sopra — nessun
   riordinamento delle regole esistenti necessario. */
@media (min-width: 861px) and (max-width: 1180px){
  .hero__grid{ gap: 36px; }
  .feature-pin{ gap: 36px; }
  .differenza__layout{ gap: 32px; }
  .method-scroll{ gap: 36px; }
  .case-wall__row{ column-gap: clamp(48px, 6vw, 220px); }
  .footer-grid{ grid-template-columns: 1fr 1fr; }
}
