/* Floating Tags — sezione a tutto schermo con headline e tag fluttuanti. */

.ft {
  --ft-runway: 120vh;
  --ft-crop: 1.5px;
  --ft-accent: #7c5ce6;
  --ft-bg: #fff;
  --ft-ink: #000;
  --ft-size: clamp(2.5rem, 8vw, 7rem);
  --ft-pad: clamp(1rem, 4vw, 3.5rem);

  /* Il riquadro del tag e' il colore di accento schiarito. color-mix evita di
     dover gestire una seconda variabile: cambi l'accento e il chip lo segue. */
  --ft-chip-bg: color-mix(in srgb, var(--ft-accent) 16%, #fff);
  --ft-chip-ink: color-mix(in srgb, var(--ft-accent) 78%, #000);

  position: relative;
  width: 100%;
  background: var(--ft-bg);
  color: var(--ft-ink);
  /* niente overflow qui: renderebbe .ft un contenitore di scorrimento e
     position: sticky smetterebbe di funzionare */
}

/* Il pannello che resta incollato in alto mentre la pagina scorre sotto. */
.ft__sticky {
  position: sticky;
  top: var(--ft-top, 0px);
  /* fallback senza JavaScript: l'altezza e' quella della finestra meno lo
     scostamento, mai meno l'altezza dell'header */
  height: calc(100svh - var(--ft-top, 0px));
  display: flex;
  align-items: stretch;
  width: 100%;
  height: var(--ft-height, calc(100svh - var(--ft-top, 0px)));
  padding: var(--ft-pad);
  box-sizing: border-box;
  background: var(--ft-bg);
  overflow: clip;
}

/* La corsa di scorrimento: e' l'altezza in piu' della sezione a decidere per
   quanto il pannello resta fermo prima di lasciare andare la pagina. */
.ft--scroll {
  height: calc(
    var(--ft-height, calc(100svh - var(--ft-top, 0px))) + var(--ft-runway, 120vh)
  );
}

/* Senza l'effetto, il pannello torna un normale blocco a tutto schermo. */
.ft:not(.ft--scroll) {
  min-height: var(--ft-height, 100svh);
}
.ft:not(.ft--scroll) .ft__sticky {
  position: static;
  min-height: var(--ft-height, 100svh);
  height: auto;
}

@supports not (height: 100svh) {
  .ft { min-height: var(--ft-height, 100vh); }
}

/* Su fondo scuro il chip non puo' essere l'accento schiarito: sparirebbe il
   contrasto. Si mescola verso il nero per il riquadro e verso il bianco per
   il testo, mantenendo l'accento come tinta di entrambi. */
.ft--dark {
  --ft-chip-bg: color-mix(in srgb, var(--ft-accent) 32%, #000);
  --ft-chip-ink: color-mix(in srgb, var(--ft-accent) 40%, #fff);
}

/* Se color-mix non e' supportato, un lilla chiaro fisso. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
  .ft { --ft-chip-bg: #ece5ff; --ft-chip-ink: #5b43ad; }
  .ft--dark { --ft-chip-bg: #2a2140; --ft-chip-ink: #cbbcff; }
  .ft__img { background: transparent; }
}

.ft__stage {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
}

.ft__headline {
  margin: 0;
  position: relative;
  z-index: 2;
  max-width: var(--ft-measure, 13ch);
  font-family: inherit;          /* il font del sito */
  font-size: var(--ft-size);
  font-weight: 800;
  line-height: 0.95;
  letter-spacing: -0.02em;
  text-align: center;
  text-wrap: balance;
  color: var(--ft-ink);
  /* Resta ferma al centro per tutta la corsa: sono i tag a raccontare
     l'avanzamento, l'headline e' il punto fisso attorno a cui orbitano.

     Unica eccezione lo spostamento verticale del mobile, qui sotto. Usa la
     proprieta' translate e non transform: la keyframe di entrata anima
     transform, e un'animazione batte sempre una dichiarazione normale.
     Essendo due proprieta' distinte, convivono senza sovrascriversi. */
  translate: 0 calc(var(--p, 0) * var(--ft-headshift, 0px));
  will-change: auto;
}

/* --- i tag ------------------------------------------------------------- */

.ft__tags {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  z-index: 4;
}

/* Il tag con il media aperto deve stare sopra gli altri e sopra l'headline,
   altrimenti un tag vicino gli passa davanti. */
.ft__tag:hover,
.ft__tag:focus-within,
.ft__tag.is-open {
  z-index: 20;
}

/* Alcuni temi ridichiarano list-style sui li o disegnano il marcatore:
   va spento su entrambi i livelli. */
.ft__tags,
.ft__tag {
  list-style: none !important;
}
.ft__tags::marker,
.ft__tag::marker,
.ft__tags li::before,
.ft__tag::before {
  content: none !important;
  display: none !important;
}

.ft__tag {
  position: absolute;
  left: var(--x);
  top: var(--y);
  /*
   * --p e' la progressione dello scroll sull'intera sezione, 0-1.
   * Ogni tag pero' si muove solo dentro la propria finestra [--s, --s + --w]:
   * --lp e' la progressione LOCALE. E' questo che trasforma il gruppo in una
   * barra di avanzamento: i tag escono uno dopo l'altro da sinistra a destra
   * invece di partire tutti insieme.
   */
  --lp: clamp(0, calc((var(--p, 0) - var(--s, 0)) / var(--w, 0.38)), 1);

  transform:
    translate(
      calc(-50% + var(--lp) * var(--exit, 900) * 1px),
      calc(-50% - var(--lp) * 30px)
    )
    scale(calc(1 - var(--lp) * 0.12));
  /* rotate e' una proprieta' a se: non entra in conflitto con la transform */
  rotate: calc(var(--lp) * var(--spin, 0) * 1deg);
  opacity: clamp(0, calc(1.2 - var(--lp) * 1.45), 1);
  will-change: transform, opacity;
}

/* Il galleggiamento sta sul link e non sul tag: cosi' non litiga con la
   transform di posizionamento, che ora e' pilotata dallo scroll. */
.ft__link {
  animation: ft-float var(--dur, 8s) ease-in-out var(--delay, 0s) infinite;
}

@keyframes ft-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

.ft__link {
  position: relative;
  display: inline-block;
  text-decoration: none;
  color: inherit;
  rotate: var(--tilt, 0deg);
  transition: rotate .35s ease, scale .35s ease;
}

.ft__chip {
  display: inline-block;
  white-space: nowrap;
  padding: 0.55em 1em;
  border-radius: 0.5em;
  background: var(--ft-chip-bg);
  color: var(--ft-chip-ink);
  font-size: var(--ft-tag, clamp(0.875rem, 1.3vw, 1.25rem));
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.1;
  /* il filtro di distorsione viene applicato qui da JavaScript, e solo
     mentre il cursore e' sopra: un elemento filtrato costa una
     rasterizzazione a parte anche quando il filtro non fa nulla */
  transform-origin: 50% 50%;
}

.ft__link:is(:hover, :focus-visible),
.ft__tag.is-open .ft__link {
  rotate: 0deg;
  scale: 1.06;
}

/* --- entrata -------------------------------------------------------------
   L'animazione sta sul chip e non sul tag ne' sul link: il primo ha la
   transform pilotata dallo scroll, il secondo il galleggiamento. Il chip e'
   l'unico elemento libero. */

.ft__chip { opacity: 0; }

.ft.is-in .ft__chip {
  animation: ft-pop .7s cubic-bezier(.16, 1.06, .3, 1.5) both;
  animation-delay: calc(var(--i, 0) * .085s + .15s);
}

/* Il rimbalzo e' nella curva, non nella keyframe: la cubic-bezier con il
   terzo valore oltre 1 fa superare il traguardo e rientrare. Piu' fluido di
   uno step intermedio, e una sola dichiarazione. */
@keyframes ft-pop {
  from { opacity: 0; transform: translateY(22px) scale(.72); }
  45%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}

/* Anche l'headline entra, appena prima dei tag. */
.ft__headline { opacity: 0; }
.ft.is-in .ft__headline {
  animation: ft-rise .8s cubic-bezier(.2, .8, .25, 1) both;
}
@keyframes ft-rise {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; }
}

/* --- il media rivelato --------------------------------------------------
   Immagine e video condividono la classe .ft__img, cosi' ogni regola di
   posizione, dimensione e transizione vale per entrambi. */

.ft__img {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 0.6em);
  /* I temi impostano img{max-width:100%}: il contenitore qui e' il tag,
     largo quanto il chip, quindi il media veniva ricondotto a ~150px
     qualunque width gli dessi. Va annullato esplicitamente. */
  /* Larghezza e altezza massima passano da variabili: il video ne ha
     bisogno per potersi ricavare il proprio limite senza duplicare i
     valori, e il mobile li ridichiara una volta sola. */
  --ft-imgw: var(--ft-img, clamp(200px, 19vw, 340px));
  --ft-maxh: 38vh;
  width: var(--ft-imgw);
  max-width: none !important;
  height: auto;
  max-height: var(--ft-maxh);
  object-fit: cover;
  border-radius: 0.6em;

  /*
   * Il contorno chiaro che si vedeva era il fondo di segnaposto: durante la
   * transizione l'elemento viene scalato, il ridimensionamento non copre
   * l'ultimo mezzo pixel e sotto affiorava. Ora il fondo e' ricavato
   * dall'inchiostro, quindi non stacca mai, e un ritaglio di un paio di
   * pixel mangia comunque il bordo dove l'antialiasing lascia residui.
   */
  background: color-mix(in srgb, var(--ft-ink) 8%, transparent);
  clip-path: inset(var(--ft-crop, 1.5px) round 0.6em);
  /* forza un livello di composizione proprio: senza, il bordo viene
     ricampionato a ogni frame della transizione e sfarfalla */
  backface-visibility: hidden;

  transform: translate(-50%, 8px) scale(0.92);
  transform-origin: 50% 100%;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .28s ease, transform .28s cubic-bezier(.2,.8,.3,1),
              visibility 0s linear .28s;
}

.ft__link:is(:hover, :focus-visible) .ft__img,
.ft__tag.is-open .ft__img {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0) scale(1);
  transition-delay: 0s;
}

/* I tag nella meta' inferiore aprono l'immagine verso il basso, altrimenti
   uscirebbe dallo schermo. La classe la assegna lo script. */
.ft__tag.is-down .ft__img {
  bottom: auto;
  top: calc(100% + 0.6em);
  transform-origin: 50% 0;
  transform: translate(-50%, -8px) scale(0.92);
}
.ft__tag.is-down .ft__link:is(:hover, :focus-visible) .ft__img,
.ft__tag.is-down.is-open .ft__img {
  transform: translate(-50%, 0) scale(1);
}

/* --- full width --------------------------------------------------------- */

.ft--full {
  width: auto;
  margin-inline: calc(50% - 50vw);
  max-width: none !important;
  box-sizing: border-box !important;
}

/* Larghezza e margini definitivi li calcola lo script misurando la posizione
   reale della sezione: e' l'unico modo affidabile quando il tema applica
   "margin-left: auto !important" ai figli del contenitore. Quanto sopra e' il
   fallback se il JavaScript non parte.

   Se pero' un antenato ritaglia, nessuna tecnica di full width funziona: qui
   si sbloccano i contenitori piu' comuni. Si usa clip e non hidden, che
   romperebbe position: sticky negli header. */
.wp-site-blocks,
.entry-content,
.wp-block-post-content,
.nectar-blocks-column__inner {
  overflow-x: clip;
}

/* --- responsive ---------------------------------------------------------
   Sotto i 900px lo scatter assoluto non funziona: i tag si sovrappongono
   all'headline. Diventano un flusso flex sopra e sotto. */

@media (max-width: 900px) {
  /* Lo scivolamento verticale dell'headline lo misura lo script: dipende da
     quanti tag ci sono e da quante righe occupano a questa larghezza. Il
     valore qui e' solo un ripiego se il JavaScript non gira. */
  .ft { --ft-headshift: 40px; }

  .ft__stage {
    flex-direction: column;
    justify-content: center;
    gap: clamp(1.25rem, 4vh, 2.5rem);
  }

  .ft__headline { max-width: 100%; }

  .ft__tags {
    position: static;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.5rem 0.6rem;
    max-width: 34rem;
  }

  .ft__tag {
    position: static;
    transform:
      translateX(calc(var(--lp) * var(--exit, 700) * 1px))
      scale(calc(1 - var(--lp) * 0.12));
  }

  .ft__link { animation-name: ft-float-soft; }

  @keyframes ft-float-soft {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
  }

  .ft__img {
    --ft-imgw: var(--ft-img-mobile, clamp(170px, 52vw, 290px));
    --ft-maxh: 30vh;
  }
}

@media (max-width: 480px) {
  .ft__chip { font-size: 0.75rem; padding: 0.45em 0.8em; }
}

@media (prefers-reduced-motion: reduce) {
  .ft__link { animation: none; }
  .ft__chip, .ft__headline { opacity: 1; animation: none; }
  .ft__img { transition-duration: .01ms; }
  /* niente corsa di scorrimento: la sezione torna un blocco normale */
  .ft--scroll { height: var(--ft-height, 100svh); }
  .ft__tag, .ft__headline { transform: none; rotate: none; opacity: 1; }
  .ft__headline { translate: none; }
}

/* Le proporzioni reali arrivano dai metadati dell'allegato, scritte inline
   sull'elemento come aspect-ratio e come --ft-ar. Il 16/10 qui e' solo il
   ripiego per quando non si conoscono: serve a non far collassare l'elemento
   prima che il file si carichi.

   Il rapporto si rompeva su max-height. Con larghezza fissa e aspect-ratio,
   quando l'altezza calcolata superava il limite era l'altezza a cedere: la
   scatola smetteva di rispettare il rapporto e object-fit: contain riempiva
   la differenza con due bande.

   Qui il limite lo prende la larghezza, non l'altezza: --ft-ar e' il rapporto
   come numero, quindi --ft-maxh * --ft-ar e' la larghezza massima compatibile
   con quell'altezza. Il min() sceglie la piu' stretta fra questa e la
   larghezza nominale, e la scatola resta sempre in proporzione.

   Il fallback 99 di --ft-ar serve a neutralizzare il calcolo quando il
   rapporto non e' noto: min() sceglie la larghezza nominale e il video ricade
   sul 16/10 qui sopra, ritagliato con cover invece che imbandierato. */
.ft__video {
  aspect-ratio: 16 / 10;
  object-fit: cover;
  width: min(var(--ft-imgw), calc(var(--ft-maxh) * var(--ft-ar, 99)));
}
