/*
Theme Name:   Replatforming
Description:  Child theme North (Ensoul) di Twenty Twenty-Five per il nuovo sito Ensoul (replatforming). Design tokens del brand dal pannello Aspetto > Design Tokens del plugin North.
Author:       Ensoul
Template:     twentytwentyfive
Version:      0.2.0
Text Domain:  replatforming
*/

/* I bleed orizzontali (breakout North) non devono allargare il documento. */
html,
body {
  overflow-x: clip;
}

body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Regole che il vecchio ensoul-blocks-variables.css aggiungeva ai token e che
   il frontend.css di North 1.4 non ha. I contenitori restano !important e fuori
   dai layer: le regole :where() del layout constrained di core altrimenti
   vincono sulle utility di Tailwind, che stanno in un layer. */
/* North 1.4.0 usa --btn-padding-x nelle varianti dei bottoni ma non la
   dichiara (la 1.4.1 si'): senza, il padding orizzontale va a zero. Con la
   1.4.1 questa riga si toglie e il valore torna al pannello. */
:root {
  --btn-padding-x: 16px;
}
.max-w-container-columns {
  max-width: var(--spacing-container-columns) !important;
}
.max-w-container-content {
  max-width: var(--spacing-container-content) !important;
}
@media (width <= 64rem) {
  .content-slider.has-mobile-controls {
    padding-bottom: var(--spacing-4xl);
  }
  .content-slider-next,
  .content-slider-prev {
    top: auto;
    bottom: 0;
  }
}

/* North 1.4 passa h1-h3 alla misura desktop da 768px; il sito le ha sempre
   avute da 1024, con la misura mobile in mezzo. */
@media (768px <= width < 1024px) {
  h1,
  .h1 {
    font-size: var(--text-heading-base);
    line-height: var(--text-heading-base--line-height);
  }
  h2,
  .h2 {
    font-size: var(--text-heading-sm);
    line-height: var(--text-heading-sm--line-height);
  }
  h3,
  .h3 {
    font-size: var(--text-heading-xs);
    line-height: var(--text-heading-xs--line-height);
  }
}

/* ==========================================================================
   Sfondo "liquido" (Figma: foto acqua + velatura; HTML di riferimento
   replatforming-ensoul.html): canvas WebGL fisso dietro a tutto, immagine
   statica di ripiego, grana fissa sopra. Il contenuto sta su z-index 2.
   ========================================================================== */
/* Lo spazio della barra di scorrimento resta riservato: durante il cambio pagina
   la pagina vecchia esce prima che quella nuova occupi il suo posto, e sui
   browser con la barra visibile tutto il contenuto scattava di lato. */
html {
  background: #16121d;
  scrollbar-gutter: stable;
  overflow-y: scroll;
}
/* Durante il cambio pagina Lenis ferma lo scroll con `overflow: clip` sull'html:
   la barra sparisce e tutto scatta di lato, poi torna. scrollbar-gutter non
   basta (con clip non vale, e Safari non lo conosce), quindi la barra resta
   sempre, anche a scroll fermo: la rotella la blocca comunque Lenis, e nel
   cambio pagina la pagina vecchia esce prima che arrivi la nuova, quando il
   documento per un attimo e' piu' corto dello schermo. */
html.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow-x: visible;
  overflow-y: scroll;
}
#liquid {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  pointer-events: none;
}
#liquid-fallback {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: #2d1f3d url(assets/img/bg-water.jpg) center / cover no-repeat;
}
/* liquid-wait: il liquido non ha ancora disegnato (vedi functions.php). Al
   posto della foto di ripiego il suo colore medio, poi il canvas entra piano. */
html.liquid-wait #liquid-fallback,
html.liquid-wait .grain {
  visibility: hidden;
}
html.liquid-wait body {
  background: #1d1926;
}
#liquid {
  transition: opacity 0.6s ease-out;
}
html.liquid-wait #liquid {
  opacity: 0;
}
.grain {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.2;
  background: url(assets/img/grain.png) repeat;
  background-size: 256px 256px;
  mix-blend-mode: overlay;
}
/* Niente z-index: il contenuto non deve fare un livello a se', o il testo in
   difference (text-diff.js) non vedrebbe la scia del cursore sul canvas. Sta
   sopra fondo e grana per ordine nel documento (tutti a z 0 / auto). */
.wp-site-blocks {
  position: relative;
}

/* Tutto il sito e' a tutta larghezza (contentSize 1840 in theme.json), quindi
   l'aria ai lati non arriva piu' dal centraggio a 1360 ma da questo padding.
   North lo usa per il gutter della pagina (--north-gutter) e per le sezioni a
   tutta larghezza; il pannello lo darebbe a scalini (20 mobile, 40 da 768),
   qui segue la stessa misura del padding di root, 20 su mobile e 40 da 1440.
   L'hero della home ha il padding nei suoi attributi (xl): da tablet in su gli
   si ridefinisce la variabile, cosi' resta a filo con le altre sezioni.
   --edge e' il bordo del contenitore visto da un blocco a tutta larghezza: la
   stessa formula del padding di .wp-site-blocks, quindi oltre 1920 i testi
   delle sezioni piene si fermano dove si fermano quelli delle altre. Il 100%
   si risolve dove la variabile viene usata: va messa solo in un padding il cui
   blocco contenitore e' largo quanto la pagina. */
:root {
  --spacing-content-padding: clamp(20px, 2.78vw, 40px);
  --edge: max(
    var(--spacing-content-padding),
    calc((100% - var(--spacing-container-content)) / 2)
  );
}
@media (min-width: 768px) {
  .hero > .ensoul-columns-block,
  .hero.ensoul-columns-block {
    --spacing-xl: var(--edge);
  }
  .hero > .ensoul-columns-block > *,
  .hero.ensoul-columns-block > * {
    --spacing-xl: var(--spacing-content-padding);
  }
}

/* ==========================================================================
   Utility tipografiche (Figma usa Display e Text mischiati nello stesso titolo)
   ========================================================================== */
.ft {
  font-family: var(--wp--preset--font-family--parabole-text);
}
.fd {
  font-family: var(--wp--preset--font-family--parabole-display);
}
.fw-300 {
  font-weight: 300;
}
.fw-500 {
  font-weight: 500;
}
.fw-700 {
  font-weight: 700;
}
.c-cream {
  color: var(--color-primary-500);
}
.c-white {
  color: var(--color-white);
}
.amp {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 200;
}

a:hover {
  color: var(--color-white);
}

/* La navigazione sta tutta in assets/css/header.css (markup in
   inc/site-nav.php). */

/* ==========================================================================
   Home — hero (Figma 2528:294)
   ========================================================================== */
/* La riga verticale a sinistra della colonna destra si accende con la classe
   hero-right, ed e' l'unica cosa che quella classe fa: misure dell'icona e
   della pila WebGL valgono per la seconda colonna dell'hero, con o senza riga. */
.hero-right {
  position: relative;
}
@media (min-width: 768px) {
  /* niente riga dentro l'hero su mobile: nel frame 2613:6 l'unica riga e'
     quella che chiude la sezione (il divider che sta gia' dopo le colonne). */
  .hero-right::before {
    content: "";
  }
}
@media (max-width: 767px) {
  /* la copia mobile dell'icona e' centrata nel frame. Il blocco icona ha gia'
     `justify-center` dentro, ma e' figlio flex di una colonna items-start:
     resta largo quanto l'svg. Basta dargli la larghezza piena. */
  .hero .icon-block.ico-ellipses {
    width: 100%;
  }
}

/* Box "glass" delle sezioni Corporate / Ecommerce (Figma: backdrop-blur 32, radius 16) */
.glass {
  -webkit-backdrop-filter: blur(32px);
  backdrop-filter: blur(32px);
  border-radius: 16px;
}

/* ==========================================================================
   "Quando scegliere il replatforming" — righe impilate a linguetta
   (Figma 2528:130/141/148/156: bg #0A0E1F, bordo bianco 1px, angoli alti 16)
   ========================================================================== */
.stack-row {
  border-top: 1px solid #fff;
}
@media (min-width: 1024px) {
  .stack-row-1 .stack-circles {
    margin-left: 32px;
  }
  .stack-row-2 .stack-circles {
    margin-left: 470px;
  }
  .stack-row-3 .stack-circles {
    margin-left: 210px;
  }
  .stack-row-4 .stack-circles {
    margin-left: 280px;
  }
}
/* --------------------------------------------------------------------------
   Animazioni delle icone.

   REGOLA che vale per tutte: un <svg> ha `overflow:hidden` di default, e i
   tracciati di queste icone toccano gia' i bordi del viewBox. Qualunque
   traslazione li fa uscire e li TAGLIA.
   -------------------------------------------------------------------------- */

/* 1. Stack-row: le molle le muove assets/js/shape-motion.js, una per parola.
   I cerchi si spostano lungo la riga e possono sporgere dal box dell'svg
   (l'assestamento di ENTERPRISE lo supera di poco), ma non dalla riga:
   quella e' full-bleed, quindi fa da guardia alla pagina. */
.stack-row {
  overflow: hidden;
}
.stack-row .stack-circles svg {
  overflow: visible;
}

/* 2. Rombi piccoli e cerchi del tech stack: onda di opacita' lungo la pila,
   zero movimento, cosi' non escono dalla propria scatola. */
@keyframes layer-glow {
  0%,
  100% {
    opacity: 0.38;
  }
  50% {
    opacity: 1;
  }
}
.ico-diamond-sm path,
.tech-circles circle {
  animation: layer-glow 3.4s ease-in-out infinite;
}
.ico-diamond-sm path:nth-child(1),
.tech-circles circle:nth-child(1) {
  animation-delay: 0s;
}
.ico-diamond-sm path:nth-child(2),
.tech-circles circle:nth-child(2) {
  animation-delay: 0.22s;
}
.ico-diamond-sm path:nth-child(3),
.tech-circles circle:nth-child(3) {
  animation-delay: 0.44s;
}
.ico-diamond-sm path:nth-child(4) {
  animation-delay: 0.66s;
}
.ico-diamond-sm path:nth-child(5) {
  animation-delay: 0.88s;
}

@media (prefers-reduced-motion: reduce) {
  .tech-circles circle,
  .ico-diamond-sm path,
  .ico-arches path {
    animation: none;
    opacity: 1;
  }
}

/* ==========================================================================
   Card progetti (Figma 2528:237: radius 13.5, anello 7.6px rosa al 20%)
   ========================================================================== */
/* Lo slider e' `dimension:"full"` (edge-to-edge) e non ha padding strutturale.
   La gutter va di PADDING, mai di margine: l'overflow si taglia sul border box, quindi le slide
   restano visibili fino al bordo del viewport (escono a filo schermo invece di sparire in una
   fascia morta), ma inizio e fine corsa si fermano dentro la gutter — spazio prima della prima
   card e dopo l'ultima: 20 mobile, 40 da tablet, fissi (non segue il padding fluido
   delle sezioni, --spacing-content-padding). */
.projects-slider .swiper {
  padding: 8px 20px;
}
@media (min-width: 768px) {
  .projects-slider .swiper {
    padding-inline: 40px;
  }
}

/* Le PNG dei progetti SONO gia' la card del Figma (2528:237): angoli trasparenti, anello rosa
   e screenshot arrotondato dentro. Niente radius/anello/sfondo dal CSS, o si sommano due
   cornici con due raggi diversi e quella dell'immagine viene tagliata. */
.card-shot img {
  border-radius: 0;
  box-shadow: none;
  background: none;
}

/* ==========================================================================
   "A chi ci rivolgiamo" — due colonne separate da una riga verticale; elenco a righe
   ========================================================================== */
@media (min-width: 768px) {
  .split-cols
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper,
  .split-cols-3
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper {
    position: relative;
  }
  .split-cols
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper::before,
  .split-cols-3
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper::before {
    content: "";
  }
}
.rule-list li {
  position: relative;
  padding: 12px 0;
}
.rule-list li + li::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.5);
  pointer-events: none;
}

/* "Dicono di noi" — slider in modalita' sticky pinnata (content-slider autoScroll).
   Due correzioni al JS del blocco, necessarie in questo tema:
   1. il blocco imposta `body{overflow-x:hidden}` inline: cosi' il body diventa uno
      scroll-container e il suo stesso position:sticky non aggancia piu'. `clip` ritaglia
      uguale ma NON crea un contesto di scroll.
   2. imposta `top:17%`, che in sticky si risolve sull'altezza del contenitore (qui 1636px,
      fuori dal viewport): serve una misura relativa alla finestra. */
body {
  overflow-x: clip !important;
}
.quotes-slider .content-slider {
  top: 30vh;
}
/* le righe verticali del design fra una voce e l'altra */
.quotes-slider .swiper-slide {
  padding-right: 32px;
}
@media (min-width: 1024px) {
  .quotes-slider .swiper-slide + .swiper-slide {
    padding-left: 32px;
  }
  .quotes-slider .swiper-slide + .swiper-slide::before {
    content: "";
  }
}
/* ruolo sotto il nome (32px light, rosa) */
.quote-role {
  display: block;
  font-size: var(--text-paragraph-2xl);
  line-height: var(--text-paragraph-2xl--line-height);
}

/* ==========================================================================
   Footer (Figma 2528:306 = screenshot del footer ensoul.it; testi dall'HTML di riferimento)
   ========================================================================== */
.site-footer {
  border-radius: 20px;
  font-size: 14px;
  line-height: 17px;
  margin-bottom: var(--footer-bottom, 24px);
}
/* Stessa veste della card del form: scura come lo sfondo, vetro e cornice.
   Il colore pieno arriva dagli attributi del gruppo nel template part, e
   l'utility di North e' `!important`: serve anche qui. */
.site-footer.ensoul-group {
  background: rgba(45, 31, 61, 0.55) !important;
  -webkit-backdrop-filter: blur(32px);
  backdrop-filter: blur(32px);
  border: 1px solid rgba(255, 255, 255, 0.35);
}
/* Apertura (footer-morph.js): la card parte stretta al centro e si allarga.
   Si ritaglia, non si ridimensiona: il contenuto non rifluisce e l'altezza
   resta quella finale dall'inizio. */
.site-footer.footer-morph > .ensoul-group {
  clip-path: inset(0 calc(50% - clamp(125px, 12.5%, 250px)) round 20px);
  transition: clip-path 1.65s cubic-bezier(0.65, 0, 0.35, 1);
}
@media (max-width: 767px) {
  .site-footer.footer-morph > .ensoul-group {
    clip-path: inset(0 14% round 20px);
  }
}
.site-footer.footer-morph.is-opening > .ensoul-group {
  clip-path: inset(0 0 round 20px);
}
.site-footer.footer-morph.is-open > .ensoul-group {
  clip-path: none;
  transition: none;
}
/* ASCII: stessa impostazione di ensoul.it. La misura e' fluida sul contenitore
   (container query), non fissa: cosi' non serve mai scorrere e non c'e' barra.
   `overflow:hidden` su entrambi e' quello che toglieva la scrollbar. */
.site-footer .f-ascii {
  width: 100%;
  display: flex;
  justify-content: center;
  overflow: hidden;
  container-type: inline-size;
}
.site-footer .f-ascii__line {
  display: inline;
  opacity: 0;
  transition: opacity 0.08s ease;
}
.site-footer .f-ascii__line.is-visible {
  opacity: 1;
}
.site-footer .f-ascii__pre {
  margin: 0;
  font-family: var(
    --font-mono,
    ui-monospace,
    "Courier New",
    Courier,
    monospace
  );
  font-size: clamp(2.5px, 1.85cqw, 14px);
  line-height: 1.15;
  letter-spacing: 0;
  white-space: pre;
  text-align: center;
  color: var(--color-white, #fff);
  max-width: 100%;
  overflow: hidden;
}

/* ==========================================================================
   Icone non quadrate: il blocco icon impone box quadrato (--icon-size);
   qui le misure reali delle istanze Figma.
   ========================================================================== */
.icon-block.ico-arches .icon-svg-wrapper svg {
  width: 277px;
  height: 344px !important;
}
.icon-block.ico-diamond-sm .icon-svg-wrapper svg {
  width: 69px;
  height: 88px !important;
}
.icon-block.stack-circles .icon-svg-wrapper svg,
.icon-block.tech-circles .icon-svg-wrapper svg {
  height: 62px !important;
}
@media (max-width: 767px) {
  .icon-block.ico-arches .icon-svg-wrapper svg {
    width: 160px;
    height: 199px !important;
  }
  .icon-block.ico-diamond-sm .icon-svg-wrapper svg {
    width: 50px;
    height: 64px !important;
  }
  .icon-block.stack-circles .icon-svg-wrapper svg,
  .icon-block.tech-circles .icon-svg-wrapper svg {
    height: 36px !important;
  }
}

/* Bottoni: 35px di altezza come nel Figma (14px + padding 9) */
.ens-btn {
  line-height: 1.2;
}
/* L'icona di un bottone sta nascosta e si apre all'hover girando su se stessa,
   e si richiude al contrario. La guida la stessa molla del testo che scorre
   (--roll, assets/js/hover-roll.js): senza script resta com'e'. Da chiusa
   larghezza zero e il margine annulla lo spazio fra icona e testo; aperta,
   fra icona e testo c'e' lo stesso spazio che fra icona e bordo (il padding
   del bottone, dal pannello Design Tokens). La classe ens-btn--icon la mette
   functions.php: con :has(> svg) ogni span inserito nella pagina (le parole
   di reveal.js) faceva ricalcolare lo stile di tutto il documento. */
html.roll-js .ens-btn--icon > span:not(.sn-roll) {
  display: flex;
  justify-content: center;
  width: calc(var(--roll, 0) * var(--spacing-button-icon-width));
  opacity: var(--roll, 0);
}
html.roll-js .ens-btn--icon.icon-before > span:not(.sn-roll) {
  margin-right: calc(var(--roll, 0) * var(--btn-padding-x, 16px) - var(--spacing-button));
}
html.roll-js .ens-btn--icon:not(.icon-before) > span:not(.sn-roll) {
  margin-left: calc(var(--roll, 0) * var(--btn-padding-x, 16px) - var(--spacing-button));
}
/* Sui bottoni con icona il testo resta fermo: si muove solo l'icona. Due
   classi sul bottone: deve pesare piu' delle regole che lo fanno scorrere in
   header.css (html.roll-js .sn-roll .sn-roll__line e l'hover senza script). */
.ens-btn.ens-btn--icon .sn-roll .sn-roll__line {
  translate: none;
}
html.roll-js .ens-btn > span:not(.sn-roll) > svg {
  flex: none;
  /* North gli da' un margine verso il testo: nello spazio animato lo spostava di lato */
  margin: 0;
  rotate: calc((1 - var(--roll, 0)) * -360deg);
  transform: scale(var(--roll, 0));
}

/* Footer: aria attorno all'ASCII art */
.site-footer .f-ascii {
  margin: 48px auto 0;
}

/* Il wrapper dell'icona (span.icon-svg-wrapper) porta il box quadrato --icon-size: va
   ridimensionato lui, non solo l'svg, altrimenti la riga resta alta quanto il box. */
.icon-block.ico-arches .icon-svg-wrapper {
  width: 277px !important;
  height: 344px !important;
}
.icon-block.ico-diamond-sm .icon-svg-wrapper {
  width: 69px !important;
  height: 88px !important;
}
.icon-block.stack-circles .icon-svg-wrapper,
.icon-block.tech-circles .icon-svg-wrapper {
  height: 62px !important;
}
@media (max-width: 767px) {
  .icon-block.ico-arches .icon-svg-wrapper {
    width: 160px !important;
    height: 199px !important;
  }
  .icon-block.ico-diamond-sm .icon-svg-wrapper {
    width: 50px !important;
    height: 64px !important;
  }
  .icon-block.stack-circles .icon-svg-wrapper,
  .icon-block.tech-circles .icon-svg-wrapper {
    height: 36px !important;
  }
}

/* "A chi ci rivolgiamo": paragrafo stretto come nel Figma (w 343) */
.aud-head p {
  max-width: 350px;
}

/* "Stack tecnico": parole e cerchi distribuiti su tutta la riga (Figma justify-between) */
@media (min-width: 768px) {
  .tech-row > .ensoul-columns-block {
    justify-content: space-between;
  }
}

/* Mobile: aria fra label e cerchi nelle righe stack (su desktop gli offset Figma) */
@media (max-width: 1023px) {
  .stack-row .stack-circles {
    margin-left: 16px;
  }
}

/* ==========================================================================
   PAGINE INTERNE (Portfolio 2617:927 · Ecommerce 2618:1212)
   Componenti che non esistevano nella home. Le misure sono quelle misurate
   sulle istanze dei frame a 1440, non stimate a occhio.
   ========================================================================== */

/* Hero a due colonne separate dalla riga verticale (Figma: rule a x=720).
   Solo da tablet in su: su mobile le due colonne si impilano (icona sopra,
   titolo sotto — lo fa mobileReverseOrder sul blocco). */
@media (min-width: 768px) {
  .page-hero .hero-col-right {
    position: relative;
  }
  .page-hero .hero-col-right::before {
    content: "";
  }
}

/* Icona "pila di ellissi + rombo" (Figma 2617:1198). E' la stessa dell'hero
   della home nel design aggiornato; la variante -h e' ruotata di 90 gradi e
   fa da testata alla pagina ecommerce (2618:1385). */
.icon-block.ico-ellipses .icon-svg-wrapper,
.icon-block.ico-ellipses .icon-svg-wrapper svg {
  width: 270px !important;
  height: 275px !important;
}
.icon-block.ico-ellipses-h .icon-svg-wrapper,
.icon-block.ico-ellipses-h .icon-svg-wrapper svg {
  width: 671px !important;
  height: 350px !important;
}
@media (max-width: 767px) {
  /* 2613:6 -> 203x207 · 2630:2502 -> 325x171 (misurati sui frame a 376) */
  .icon-block.ico-ellipses .icon-svg-wrapper,
  .icon-block.ico-ellipses .icon-svg-wrapper svg {
    width: 200px !important;
    height: 204px !important;
  }
  .icon-block.ico-ellipses-h .icon-svg-wrapper,
  .icon-block.ico-ellipses-h .icon-svg-wrapper svg {
    width: 320px !important;
    height: 167px !important;
  }
}

/* --------------------------------------------------------------------------
   Riga progetto: video a sinistra, scheda subito accanto; larghezza e
   posizione della scheda le decidono i blocchi.
   -------------------------------------------------------------------------- */
@media (min-width: 768px) {
  /* Come su ensoul.it il video prende tutta la meta' sinistra della finestra,
     attaccato al bordo, a qualunque larghezza; la scheda resta a destra, a filo
     col contenitore. Il margine negativo e' la distanza fra contenitore e bordo
     della finestra; la larghezza del <style> di North (id) cede all'!important. */
  .project-row > .ensoul-columns-block > .ensoul-column-wrapper:first-of-type {
    width: 50vw !important;
    margin-left: calc((100% - 100vw) / 2);
  }
}
.project-row .video-content,
.project-row .block-video {
  width: 100%;
  height: auto;
}

/* pillola del tag (Figma: bordo 1px, raggio pieno, testo minuscolo) */
p.pill-tag {
  display: inline-block;
  width: -moz-fit-content;
  width: fit-content;
  border: 1px solid currentColor;
  border-radius: 200px;
  padding: 4px 14px;
  text-transform: lowercase;
}

/* riga meta: "cliente Ensoul dal 2020" + "data pubblicazione 2025".
   Le distanze fra le due colonne e fra i due bottoni le fa il PADDING dentro
   la colonna, non un gap: un gap si somma al 50%+50% e manda a capo. */
.project-meta strong {
  font-weight: 700;
}
/* nel Figma i bottoni della scheda sono alti 39 (il quinary di serie sta a 31) */
.project-actions .ens-btn {
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding-block: 11px;
}

/* --------------------------------------------------------------------------
   Step della pagina ecommerce: cerchio | numero + STEP | paragrafo
   -------------------------------------------------------------------------- */
.step-label .step-num {
  font-size: 0.3em;
  /* in alto a filo con le maiuscole del titolo: dalla linea di base si sale
     dell'altezza delle maiuscole del titolo (0.7em del titolo) meno quella
     del numero, in em del numero (0.3em del titolo) */
  vertical-align: 1.62em;
  padding-right: 0.35em;
  font-family: var(--wp--preset--font-family--parabole-text);
}

/* --------------------------------------------------------------------------
   Step: un cerchio solo a sinistra che si evolve, lista che scorre a destra.
   Il cerchio e' `sticky`, e sticky e' vincolato dal box del GENITORE: percio'
   la riga non si impila mai (26/74 a ogni breakpoint) e la colonna del
   quadrante deve arrivare in fondo alla sezione, non fermarsi al cerchio.
   Il motore e' initDial in assets/js/shape-motion.js.
   -------------------------------------------------------------------------- */
.steps-scroll > .ensoul-columns-block {
  align-items: stretch;
}
.steps-scroll .steps-dial > .column {
  height: 100%;
}

.dial {
  position: sticky;
  /* centrato sulla fascia di lettura: e' li' che sta lo step attivo, quindi la
     forma parte allineata alla sua label invece di galleggiare piu' in alto.
     Il transform non tocca lo sticky, sposta solo il disegno. */
  top: 50vh;
  transform: translateY(-50%);
  width: 164px;
  height: 150px;
}
.dial__shape {
  width: 100%;
  height: 100%;
  overflow: visible;
}
.dial__layer {
  fill: none;
  stroke: var(--color-secondary-500);
  stroke-width: 1;
  transition:
    opacity 0.5s ease,
    stroke 0.5s ease;
}
/* Senza JS restano tutti accesi: e' la pila completa, cioe' l'icona del sito.
   Col JS gli strati compaiono uno per step e solo l'ultimo e' in evidenza. */
.steps-scroll.is-enhanced .dial__layer {
  opacity: 0;
}
.steps-scroll.is-enhanced .dial__layer.is-on {
  opacity: 0.45;
}
.steps-scroll.is-enhanced .dial__layer.is-live {
  opacity: 1;
  stroke: var(--color-primary-500);
}

/* La lista: acceso solo lo step in lettura, gli altri smorzati e un filo piu'
   in basso. Lo stato smorzato lo abilita il JS (`is-enhanced`): senza JS
   restano tutti leggibili. */
.steps-scroll.is-enhanced .step-item {
  opacity: 0.3;
  transform: translateY(14px);
  transition:
    opacity 0.5s ease,
    transform 0.5s cubic-bezier(0.45, 0, 0.35, 1);
}
.steps-scroll.is-enhanced .step-item.is-past {
  opacity: 0.45;
  transform: none;
}
.steps-scroll.is-enhanced .step-item.is-active {
  opacity: 1;
  transform: none;
}

/* Col JS il quadrante non e' piu' sticky: occupa tutta la colonna e le forme
   si posano una per step lungo la sua altezza. Il viewBox lo tiene in pixel
   il JS, quindi il tratto resta da 1px a qualunque misura. */
.steps-scroll.is-enhanced .steps-dial {
  position: relative;
}
.steps-scroll.is-enhanced .dial {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  aspect-ratio: auto;
  transform: none;
}
/* la prima forma e' quella da cui nasce tutto: resta in evidenza */
.steps-scroll.is-enhanced .dial__layer--1.is-on {
  opacity: 1;
  stroke: var(--color-primary-500);
}

@media (max-width: 767px) {
  /* larghezza legata alla colonna, non fissa: a 342px la colonna e' 78px e un
     quadrante da 84 finiva sopra la label. I 12px sono l'aria verso il testo. */
  .dial {
    width: calc(100% - 12px);
    height: auto;
    aspect-ratio: 164 / 150;
  }
}
@media (prefers-reduced-motion: reduce) {
  .dial__layer,
  .steps-scroll.is-enhanced .step-item {
    transition: none;
  }
  .steps-scroll.is-enhanced .step-item,
  .steps-scroll.is-enhanced .dial__layer {
    opacity: 1;
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Righe "Da che piattaforma vuoi migrare?": stesso componente delle stack-row
   della home (bg #0A0E1F, bordo alto bianco, raggio 16 in alto), ma con la
   colonna del paragrafo a destra.
   -------------------------------------------------------------------------- */
.platform-row .ensoul-columns-block {
  align-items: center;
}


/* --------------------------------------------------------------------------
   Card del form. Nel Figma era una card rosa piena: ora e' scura come lo
   sfondo, col vetro dei box e la cornice del blocco in fondo alla pagina, e
   l'inchiostro crema. A sinistra il titolo, a destra i campi col bottone sotto.
   Gravity Forms tema "orbital": si pilota dalle sue variabili + poche regole.
   -------------------------------------------------------------------------- */
.form-card {
  --form-ink: var(--color-primary-500);
  --form-paper: var(--color-secondary-900);
}
.form-card > .ensoul-group {
  background: rgba(45, 31, 61, 0.55);
  -webkit-backdrop-filter: blur(32px);
  backdrop-filter: blur(32px);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 20px;
  padding: var(--spacing-2xl) var(--spacing-xl);
}
/* i figli del gruppo stanno in un div interno, ed e' quello a fare da griglia */
.form-card > .ensoul-group > div {
  gap: var(--spacing-l);
}
.form-card .form-title {
  color: var(--form-ink);
}
@media (min-width: 1024px) {
  .form-card > .ensoul-group > div {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--spacing-4xl);
    align-items: start;
  }
}
@media (max-width: 767px) {
  .form-card > .ensoul-group {
    padding: 24px;
    border-radius: 16px;
  }
}
.form-card .gform_wrapper {
  /* il wrapper del gruppo ensoul e' items-start: senza questo il form resta
     largo quanto il suo contenuto e la griglia sotto non ha spazio */
  width: 100%;
  --gf-color-primary: var(--form-ink);
  --gf-color-primary-contrast: var(--form-paper);
  --gf-color-primary-darker: var(--color-primary-600);
  --gf-color-in-ctrl: var(--form-ink);
  --gf-color-out-ctrl-primary: var(--form-ink);
  --gf-local-color: var(--form-ink);
  color: var(--form-ink);
}
.form-card .gform_wrapper .gfield_label,
.form-card .gform_wrapper legend {
  color: var(--form-ink);
  font-family: var(--wp--preset--font-family--parabole-text);
  font-weight: 700;
  font-size: 16px;
}
.form-card .gform_wrapper input[type="text"],
.form-card .gform_wrapper input[type="email"],
.form-card .gform_wrapper input[type="url"],
.form-card .gform_wrapper select,
.form-card .gform_wrapper textarea {
  background-color: transparent;
  border: 0;
  border-bottom: 1px solid var(--form-ink);
  border-radius: 0;
  padding: 6px 0;
  color: var(--form-ink);
  box-shadow: none;
}
/* Il messaggio e' una riga sola sottolineata che cresce col testo: a altezza
   fissa, alla seconda riga compariva la barra di scorrimento. Dove
   field-sizing non c'e' resta un campo da quattro righe. */
.form-card .gform_wrapper textarea {
  resize: none;
  overflow: hidden;
  height: 6.4em !important;
  min-height: 0 !important;
}
@supports (field-sizing: content) {
  .form-card .gform_wrapper textarea {
    field-sizing: content;
    height: auto !important;
    min-height: 2.4em !important;
  }
}
/* Un campo di testo e' sempre :focus-visible, anche col mouse, e l'anello
   giallo di North attorno a un campo fatto di una sola riga diventa un
   rettangolo acceso: qui il fuoco e' la riga che si fa bianca e piu' spessa.
   Su mobile 16px, o Safari ingrandisce la pagina a ogni tocco. */
.form-card .gform_wrapper input[type="text"]:focus-visible,
.form-card .gform_wrapper input[type="email"]:focus-visible,
.form-card .gform_wrapper input[type="url"]:focus-visible,
.form-card .gform_wrapper select:focus-visible,
.form-card .gform_wrapper textarea:focus-visible {
  outline: none;
  border-bottom-color: #fff;
  box-shadow: 0 1px 0 #fff;
}
@media (max-width: 767px) {
  .form-card .gform_wrapper input[type="text"],
  .form-card .gform_wrapper input[type="email"],
  .form-card .gform_wrapper input[type="url"],
  .form-card .gform_wrapper select,
  .form-card .gform_wrapper textarea {
    font-size: 16px;
  }
}
/* Modulo di Let's talk: menu a tendina e scelte multiple, nella stessa veste
   dei campi a riga. Il menu aperto e' quello del sistema: le voci restano
   scure su chiaro, o sarebbero illeggibili. */
.form-card .gform_wrapper select {
  height: auto;
  cursor: pointer;
}
.form-card .gform_wrapper select option {
  color: #16121d;
}
.form-card .gform_wrapper .gchoice label {
  color: var(--form-ink);
  font-size: 16px;
}
.form-card .gform_wrapper input[type="radio"] {
  background: transparent !important;
  border: 1px solid var(--form-ink) !important;
  box-shadow: none !important;
}
.form-card .gform_wrapper input[type="radio"]::before {
  background: var(--form-ink) !important;
}

/* Il marcatore "(Obbligatorio)" non c'e' nel design. Resta l'aria-required
   sull'input, quindi lo screen reader lo annuncia lo stesso. */
.form-card .gform_wrapper .gfield_required {
  display: none !important;
}
/* Gravity dichiara le sue variabili su #gform_wrapper_1.gform-theme, piu'
   specifico di qualunque selettore di classe: qui serve !important. */
.form-card .gform_wrapper .gform_footer input[type="submit"],
.form-card .gform_wrapper .gform_footer button {
  background: var(--form-ink) !important;
  color: var(--form-paper) !important;
  border: 0 !important;
  border-radius: 8px !important;
  padding: 14px 28px !important;
  font-family: var(--wp--preset--font-family--parabole-text);
  font-weight: 700;
  font-size: 14px;
}
.form-card .gform_wrapper .gform_footer input[type="submit"]:hover,
.form-card .gform_wrapper .gform_footer button:hover {
  background: var(--color-primary-600) !important;
}
.form-card .gform_wrapper .gform_footer {
  margin: 32px 0 0;
  padding: 0;
}

/* Righe verticali del design. Sono pseudo-elementi e non bordi perche' un
   bordo non si puo' disegnare: questi si scalano da zero all'ingresso.
   Ogni sezione li accende dove servono dichiarando solo `content`. */
.hero-right::before,
.page-hero .hero-col-right::before,
.split-cols
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper::before,
.split-cols-3
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper::before,
.quotes-slider .swiper-slide + .swiper-slide::before {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1px;
  background: #fff;
  pointer-events: none;
}

/* Entrate al primo ingresso nello schermo (assets/js/reveal.js).
   Tutto sta sotto `.reveal-on`, che arriva solo con JS attivo e movimento non
   ridotto: altrimenti la pagina resta ferma e leggibile. */
:root {
  /* Curve che rallentano dolcemente fino a fermarsi, senza scatti a meta':
     l'entrata deve dare calma e sicurezza, non energia. (Prima: 0.625, 0.05,
     0, 1, che accelerava di colpo e a scroll veloce dava cinetosi.) */
  --reveal-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --line-ease: cubic-bezier(0.33, 1, 0.68, 1);
  /* Quanto si sposta un contenuto entrando (1 = la distanza piena):
     regola in un punto solo tutte le entrate. */
  --rv-shift: 1;
}

/* I testi restano nascosti finche' non sono spezzati in parole, cosi' non si
   vedono interi per un istante prima di sparire nella maschera. Opacita', non
   visibility: con visibility:hidden screen reader e Lighthouse non vedevano i
   testi sotto la piega (e i titoli risultavano fuori ordine). */
.reveal-on
  :is(main, .site-footer)
  :is(
    .wp-block-ensoul-heading,
    .font-paragraph,
    .wp-block-ensoul-list-element > span
  ):not(.is-split):not(.pill-tag) {
  opacity: 0;
}
/* Nella testata (gli stessi contenitori di HERO in reveal.js) un'opacita'
   impercettibile invece di 0: Chrome conta per l'LCP solo cio' che disegna
   sopra lo zero, e cosi' i testi valgono dal primo disegno invece che da
   quando arriva reveal.js (su mobile in 4G lento: 8,6 s). */
.reveal-on
  main
  :is(.hero, .page-hero, .gl-band)
  :is(.wp-block-ensoul-heading, .font-paragraph):not(.is-split):not(.pill-tag) {
  opacity: 0.01;
}
/* La maschera e' la riga: un blocco che ritaglia (rettangolo, non clip-path:
   su un layer animato il clip-path costa alla GPU una superficie a parte).
   Padding e margine negativo si annullano nel layout ma allargano il ritaglio,
   cosi' ascendenti e discendenti non vengono tagliati con le interlinee strette. */
/* colonna flex: fra blocchi fratelli i margini negativi collasserebbero e
   le righe si allargherebbero di un quarto di em */
.rv-text {
  display: flex;
  flex-direction: column;
}
.rv-l {
  display: block;
  text-indent: 0;
  overflow: hidden;
  overflow: clip;
  white-space: nowrap;
  padding: 0.25em 0.08em;
  margin: -0.25em -0.08em;
}
/* text-indent si eredita: durante l'entrata vale solo per la prima riga,
   come sul testo intero, o le altre rientrerebbero e a fine entrata scatterebbero. */
.rv-l:first-child {
  text-indent: inherit;
}
/* 2D apposta: translate3d terrebbe un layer sulla GPU anche a riposo.
   La riga sale di poco e intanto emerge in dissolvenza: prima saliva di piu'
   di un'altezza intera (125%) e schizzava fuori dalla maschera. */
.rv-li {
  display: block;
  opacity: 0;
  transform: translate(0, calc(var(--rv-shift) * 45%));
  transition:
    transform 1.7s var(--reveal-ease),
    opacity 1.3s var(--line-ease);
}
/* gli elementi in linea riportati nella riga restano in linea (uno span che
   nell'originale va a capo da solo qui ha gia' la sua riga) */
.rv-li * {
  display: inline;
}
.rv-text.is-in .rv-li {
  opacity: 1;
  transform: none;
}
/* I titoli salgono di meta' (22,5%). Quelli che entrano con lo scroll
   (reveal.js, scrollTitle) hanno posizione e opacita' scritte dal JS a ogni
   fotogramma: nessuna transizione che le rincorra. */
.wp-block-ensoul-heading .rv-li {
  transform: translate(0, calc(var(--rv-shift) * 22.5%));
}
.wp-block-ensoul-heading.is-in .rv-li {
  transform: none;
}
.rv-scroll .rv-li {
  transition: none;
}
/* Testi della testata (LCP): stessa entrata degli altri, ma partono da un'opacita'
   impercettibile invece che da 0. Chrome scarta dall'LCP cio' che viene
   disegnato a opacita' 0 e, con la dissolvenza tutta sul compositor, lo
   ridisegnava solo a fine entrata (~2,5 s): cosi' lo conta subito. */
.rv-hero .rv-li {
  opacity: 0.01;
}

:is(main, .site-footer) .ensoul-divider hr,
:is(main, .site-footer) .rule-list li + li::before {
  transform-origin: 0 50%;
  transition: transform 2.2s var(--line-ease) var(--rv-delay, 0s);
}
main .hero-right::before,
main .hero-col-right::before,
main
  .split-cols
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper::before,
main
  .split-cols-3
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper::before,
main .quotes-slider .swiper-slide + .swiper-slide::before {
  transform-origin: 50% 0;
  transition: transform 2.2s var(--line-ease) var(--rv-delay, 0s);
}
/* la riga dell'hero sale dal basso */
main .hero-right::before {
  transform-origin: 50% 100%;
}

/* Lo stato di partenza sta su `:not(.ln-in)`: cosi' l'arrivo non deve battere
   in specificita' i selettori lunghi delle colonne. */
.reveal-on :is(main, .site-footer) .ensoul-divider:not(.ln-in) hr,
.reveal-on :is(main, .site-footer) .rule-list li + li:not(.ln-in)::before {
  transform: scaleX(0);
}
.reveal-on main .hero-right:not(.ln-in)::before,
.reveal-on main .hero-col-right:not(.ln-in)::before,
.reveal-on
  main
  .split-cols
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper:not(.ln-in)::before,
.reveal-on
  main
  .split-cols-3
  > .ensoul-columns-block
  > .ensoul-column-wrapper
  + .ensoul-column-wrapper:not(.ln-in)::before,
.reveal-on
  main
  .quotes-slider
  .swiper-slide
  + .swiper-slide:not(.ln-in)::before {
  transform: scaleY(0);
}

/* Il ritardo sta in una variabile e vale solo per l'opacita': sulla
   transizione intera rallenterebbe anche l'hover del bottone. */
.reveal-on main :is(.ens-btn, .pill-tag, .form-card > .ensoul-group) {
  transition:
    opacity 1.4s var(--line-ease) var(--rv-delay, 0s),
    color 0.3s ease-in-out,
    background-color 0.3s ease-in-out;
}
.reveal-on
  main
  :is(.ens-btn, .pill-tag, .form-card > .ensoul-group):not(.is-in) {
  opacity: 0;
}

.reveal-on main .projects-slider .swiper-slide {
  opacity: 0;
  transform: translate3d(calc(var(--rv-shift) * 32px), 0, 0);
  transition:
    transform 1.9s var(--reveal-ease) var(--rv-delay, 0s),
    opacity 1.4s var(--line-ease) var(--rv-delay, 0s);
}
.reveal-on main .projects-slider .swiper-slide.is-in {
  opacity: 1;
  transform: none;
}

/* Card degli slider progetti tagliate in fasce (assets/js/card-wave.js):
   l'immagine originale resta in pagina per misure e accessibilita', a
   disegnare sono le copie nelle fasce. */
.cw-live .card-shot figure.is-sliced > img {
  visibility: hidden;
}
.cw-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: none;
}
/* le fasce esistono solo mentre lo slider si muove: a riposo niente layer */
.cw-live .cw-layer {
  display: block;
}
.cw-strip {
  position: absolute;
  overflow: hidden;
}
.cw-live .cw-strip {
  will-change: transform;
}
.cw-strip img {
  position: absolute;
  max-width: none;
  display: block;
  object-fit: cover;
  -webkit-user-drag: none;
}

/* La barra di navigazione sta in basso, non in cima: lo spazio che il token
   `content-top` riserva all'header fisso qui non serve, basta un margine. */
@media (min-width: 768px) {
  main.pt-content-top {
    padding-top: 40px;
  }
  /* sulla home niente margine: la riga verticale dell'hero parte dal bordo della finestra.
   Le regole della home stanno sul main che contiene l'hero, non su body.home: nel
   cambio pagina la classe del body cambia mentre la home vecchia si sta ancora
   sciogliendo, e perdendo il padding scendeva di colpo. */
  main.pt-content-top:has(.hero) {
    padding-top: 0;
  }
}

/* Hero della home: il primo schermo finisce sulla riga che la chiude, con la
   pillola della nav sotto. L'altezza e' quindi quella della finestra meno la
   fascia della nav (100): in cima non c'e' ne' margine ne' riga. Icona e
   distanze della colonna destra si stringono con la finestra: alle misure
   del Figma (900 di altezza) valgono 275 / 140 / 64, sotto scalano, cosi'
   la riga resta nel primo schermo anche su finestre basse. */
@media (min-width: 768px) {
  .hero > .ensoul-columns-block {
    min-height: calc(100svh - 100px) !important;
  }
  .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .icon-block.ico-ellipses {
    --hero-ico-h: clamp(120px, calc(50svh - 175px), 275px);
    margin-top: clamp(16px, calc(28svh - 112px), 140px);
  }
  .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .icon-block.ico-ellipses
    .icon-svg-wrapper,
  .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .icon-block.ico-ellipses
    .icon-svg-wrapper
    svg {
    height: var(--hero-ico-h) !important;
    width: calc(var(--hero-ico-h) * 270 / 275) !important;
  }
  .hero .ensoul-column-wrapper ~ .ensoul-column-wrapper .font-paragraph {
    margin-top: clamp(16px, calc(14svh - 62px), 64px);
  }
  /* il titolo e' a 124px fissi da tablet in su: su finestre strette o basse
     andrebbe su quattro righe e da solo sarebbe piu' alto dello schermo.
     La misura segue la colonna del titolo, che e' il 62% dell'hero meno i
     40px ai lati e i 48 di padding: "Replatforming" e' largo 6,32em e ci sta
     a filo. I 124px del Figma (interlinea 110) arrivano da 1440 in su. */
  /* Si ridefiniscono le variabili e non font-size: l'utility di North e'
     `!important` dentro un @layer, e li' vince su qualunque regola esterna. */
  .hero h1.wp-block-ensoul-heading {
    --text-heading-3xl: min(calc(124 * var(--u)), calc(9.55vw - 13px), 18svh);
    --text-heading-3xl--line-height: 0.887em;
    --tw-leading: 0.887em;
  }
}
/* Il titolone della home sta col suo inchiostro sul bordo della colonna, come
   paragrafo e bottone. A questa misura le lettere hanno un margine interno
   (misurato in Parabole Display: R 0,089em, C 0,04em, & 0,032em): tutto il
   titolo si sposta di quello di C e &, la prima riga anche di quanto manca
   alla R. In em, cosi' segue la misura del titolo a ogni schermo. */
.hero h1.wp-block-ensoul-heading {
  margin-left: -0.036em;
  text-indent: -0.053em;
}

/* Hero della home: la pila WebGL prende il posto dell'icona (hero-webgl.js).
   L'svg si spegne (display, non visibility: shape-motion.js anima solo cio'
   che interseca, cosi' da spento non costa nulla) e torna se WebGL non parte:
   tutte le regole stanno sotto hero-gl-on, senza quella classe resta l'icona
   con le sue misure. Il blocco icona diventa il riquadro della pila e si
   prende tutta l'altezza della colonna sopra il paragrafo; il canvas ignora
   il padding sinistro della colonna e parte dalla riga verticale. Lo script
   misura quello scarto e sposta l'asse della pila: il fianco sinistro del
   cilindro cade a filo col paragrafo sotto. La camera lascia da sola un
   margine attorno alla pila, quindi il canvas puo' toccare i bordi. */
.hero-gl {
  display: none;
}
.hero-gl-on .hero .icon-block.ico-ellipses {
  position: relative;
}
.hero-gl-on .hero .icon-block.ico-ellipses svg {
  display: none;
}
.hero-gl-on .hero .hero-gl {
  display: block;
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.9s var(--line-ease) var(--rv-delay, 0s);
  touch-action: pan-y;
}
.hero-gl-on .hero .hero-gl.is-ready {
  opacity: 1;
}
.reveal-on main .hero .icon-block:not(.is-in) .hero-gl.is-ready {
  opacity: 0;
}
.hero-gl canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}
.hero-gl.dragging canvas {
  cursor: grabbing;
}
@media (min-width: 768px) {
  .hero-gl-on
    .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .icon-block.ico-ellipses {
    flex: 1 1 0;
    align-self: stretch;
    min-height: 160px;
    margin-top: 0;
  }
  .hero-gl-on
    .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .icon-block.ico-ellipses
    .icon-svg-wrapper {
    display: none;
  }
  .hero-gl-on .hero .ensoul-column-wrapper ~ .ensoul-column-wrapper .hero-gl {
    left: calc(var(--spacing-l) * -1);
  }
  .hero-gl-on
    .hero
    .ensoul-column-wrapper
    ~ .ensoul-column-wrapper
    .font-paragraph {
    margin-top: clamp(8px, 3svh, 32px);
  }
}
@media (max-width: 767px) {
  /* Su mobile la pila sta sotto il bottone: il riquadro sborda appena verso
     l'alto (il canvas e' alto 320), cosi' gli anelli in cima non toccano il
     bottone. */
  .hero-gl-on .hero .icon-block.ico-ellipses .icon-svg-wrapper {
    height: 300px !important;
  }
  .hero-gl-on .hero .hero-gl {
    top: -20px;
  }
  /* sulla home il primo schermo comincia col testo, appena sotto la barra in cima */
  main.pt-content-top:has(.hero) {
    padding-top: 40px;
  }
}

/* La stessa pila, coricata, come sfondo di una sezione con la classe gl-band
   (hero-webgl.js). Il riquadro esce dal contenitore fino ai bordi della
   finestra e sta sotto il contenuto, che resta cliccabile. In altezza lo
   script lo stringe fra il primo e l'ultimo titolo h1; qui la fascia centrale
   per le sezioni che non ne hanno due. */
.gl-band {
  position: relative;
  isolation: isolate;
}
.gl-band-stage {
  position: absolute;
  top: 20%;
  height: 60%;
  left: calc(50% - 50vw);
  width: 100vw;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s var(--line-ease);
}
.gl-band-stage.is-ready {
  opacity: 1;
}
/* Forme di vetro (assets/js/gl-glass.js) al posto di un'icona: classi
   gl-liquid, gl-split, gl-blinds, gl-slats, gl-solid, gl-monolith, gl-transfer, gl-pins sul blocco Icona. Il
   riquadro e' quadrato, centrato sull'icona e piu' grande di lei, cosi' ombre
   e curve di livello non vengono tagliate; non sposta niente. L'icona la nasconde html.gl-glass prima
   del primo paint e torna se l'effetto non parte (gl-off); il disegno entra in
   dissolvenza al primo fotogramma (is-live). --gl-size cambia la misura. */
:is(.gl-liquid, .gl-split, .gl-blinds, .gl-slats, .gl-solid, .gl-monolith, .gl-transfer, .gl-pins) {
  --gl-size: 260px;
  position: relative;
}
@media (min-width: 768px) {
  :is(.gl-liquid, .gl-split, .gl-blinds, .gl-slats, .gl-solid, .gl-monolith, .gl-transfer, .gl-pins) {
    --gl-size: calc(440 * var(--u));
  }
  /* Testata delle pagine interne: un gruppo alto quanto la finestra con
     l'icona in cima e il titolo (.page-hero) in fondo, space-between. L'icona
     prende tutto lo spazio fra i due e la forma ci sta centrata, grande quanto
     quello spazio (--gl-fill), mai piu' larga del contenuto. North fissa i figli
     del gruppo a flex 0 0 auto con !important: qui serve una specificita' piu'
     alta. */
  html.gl-glass :is(.gl-slats, .gl-blinds, .gl-split, .gl-transfer):not(.gl-off):has(~ .page-hero) {
    --gl-fill: 1.1;
    --gl-size: min(100cqw, var(--gl-fill) * 100cqh);
    flex: 1 1 0% !important;
    min-height: 240px;
    container-type: size;
  }
  /* le lamelle riempiono il loro riquadro, le sfere lasciano posto alle curve di livello */
  html.gl-glass :is(.gl-slats, .gl-blinds):not(.gl-off):has(~ .page-hero) {
    --gl-fill: 0.9;
  }
}
/* Liquido, solido e monolite sono larghi quanto la loro colonna (il suo
   contenuto, senza padding): per spostarli o ingrandirli si cambiano larghezza
   e padding della colonna dall'editor. */
.ensoul-column-wrapper:has(:is(.gl-liquid, .gl-solid, .gl-monolith, .gl-pins.icon-block)) {
  container-type: inline-size;
}
html.gl-glass :is(.gl-liquid, .gl-solid, .gl-monolith, .gl-pins.icon-block):not(.gl-off) {
  --gl-size: 100cqw;
}
/* su mobile la colonna sta sotto il testo: il blocco e' alto quanto la forma,
   che altrimenti salirebbe sul paragrafo sopra */
@media (max-width: 767px) {
  html.gl-glass :is(.gl-liquid, .gl-solid, .gl-monolith):not(.gl-off) {
    min-height: var(--gl-size);
  }
}
html.gl-glass :is(.gl-liquid, .gl-split, .gl-blinds, .gl-slats, .gl-solid, .gl-monolith, .gl-transfer, .gl-pins):not(.gl-off) .icon-svg-wrapper {
  visibility: hidden;
}
.gl-glass-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--gl-size);
  aspect-ratio: 1;
  translate: -50% -50%;
}
.gl-glass-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.6s var(--line-ease);
}
.is-live > .gl-glass-stage canvas {
  opacity: 1;
}
.reveal-on main .gl-glass-stage {
  transition: opacity 0.9s var(--line-ease) var(--rv-delay, 0s);
}
.reveal-on main :is(.gl-liquid, .gl-split, .gl-blinds, .gl-slats, .gl-solid, .gl-monolith, .gl-transfer, .gl-pins.icon-block):not(.is-in) .gl-glass-stage {
  opacity: 0;
}
/* Tessere (gl-pins) ed eco (gl-echo, solo sul blocco Immagine): occupano la
   larghezza della colonna, o del blocco
   Immagine che porta la classe; il riquadro del disegno e' piu' grande del 30%
   (STAGE in gl-glass.js), cosi' le tessere che escono non vengono tagliate.
   Nel blocco Immagine il disegno sta sulla figura visibile al caricamento.
   Sull'icona il blocco e' alto quanto il logo di Shopify, piu' alto che largo. */
html.gl-glass .gl-pins.icon-block:not(.gl-off) {
  min-height: calc(var(--gl-size) * 1.15);
}
html.gl-glass .gl-pins:not(.gl-off) > .gl-glass-stage {
  width: calc(var(--gl-size) * 1.3);
}
html.gl-glass :is(.gl-pins, .gl-echo).image-section:not(.gl-off) figure {
  position: relative;
}
html.gl-glass :is(.gl-pins, .gl-echo).image-section:not(.gl-off) .gl-glass-stage {
  left: -15%;
  top: -15%;
  width: 130%;
  height: 130%;
  aspect-ratio: auto;
  translate: none;
}
html.gl-glass :is(.gl-pins, .gl-echo).image-section:not(.gl-off) img {
  visibility: hidden;
}
:is(.gl-pins, .gl-echo).image-section.is-live .gl-glass-stage canvas {
  opacity: 1;
}
/* Passaggio (gl-transfer): due pile affiancate, il riquadro e' largo il doppio
   dell'altezza; nella testata delle pagine interne sta nello spazio sopra il titolo. */
html.gl-glass .gl-transfer:not(.gl-off) > .gl-glass-stage {
  width: 100%;
  aspect-ratio: 2;
}
@media (min-width: 768px) {
  html.gl-glass .gl-transfer:not(.gl-off):has(~ .page-hero) > .gl-glass-stage {
    width: min(100cqw, 200cqh);
  }
}

/* La sezione gl-band e' il primo schermo delle landing: titolo in cima,
   "to" in mezzo, titolo in fondo. Wrapper e colonne arrivano con
   `height: 100vh` inline, ma il main li porta giu' del suo padding: senza
   correzione la sezione sborda e l'ultimo titolo resta a meta' strada. Qui la
   sezione finisce col fondo della finestra (barra admin compresa) e l'ultimo
   titolo sta a --band-edge dal fondo. Il primo parte sotto la barra fissa in
   cima (logo e lingua, header.css .tb: 27 + 29 nella scala --u) con 24 di
   aria: a 40px dalla cima ci finiva sotto. */
@media (min-width: 768px) {
  .ensoul-group.gl-band {
    --band-edge: 40px;
    box-sizing: border-box;
    height: calc(100dvh - var(--wp-admin--admin-bar--height, 0px) - var(--band-edge)) !important;
    padding-top: max(0px, calc((27 + 29 + 24) * var(--u, 1px) - var(--band-edge)));
    padding-bottom: var(--band-edge);
  }
  .ensoul-group.gl-band > div > .ensoul-columns-section,
  .ensoul-group.gl-band > div > .ensoul-columns-section > .ensoul-columns-block {
    height: 100% !important;
  }
  .ensoul-group.gl-band > div > .ensoul-columns-section > .ensoul-columns-block {
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: space-between;
  }
  .ensoul-group.gl-band > div > .ensoul-columns-section > .ensoul-columns-block > .ensoul-column-wrapper {
    padding-bottom: 0;
  }
}
.gl-band-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Entrata delle icone: i tracciati si disegnano uno dopo l'altro mentre
   l'icona sale di opacita' (serve per le forme piene, che non hanno tratto).
   reveal.js mette `pathLength="1"` e la classe `rv-draw` sui tracciati e li
   toglie a disegno finito: il tratteggio vale solo finche' ci sono, cosi'
   non resta mai un'icona tratteggiata. */
.reveal-on main .icon-block svg,
.reveal-on main .dial__shape {
  transition: opacity 0.9s var(--line-ease) var(--rv-delay, 0s);
}
.reveal-on main .icon-block:not(.is-in) svg,
.reveal-on main .steps-dial:not(.is-in) .dial__shape {
  opacity: 0;
}
.reveal-on main .icon-block svg .rv-draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
/* la transizione vale solo in entrata: dichiarata sempre, partirebbe anche
   quando reveal.js mette la classe, e l'entrata troverebbe il tratto a meta' */
.reveal-on main .icon-block.is-in svg .rv-draw {
  transition: stroke-dashoffset 1.5s var(--line-ease)
    calc(var(--rv-delay, 0s) + var(--rv-i, 0) * 0.07s);
}
.reveal-on main .icon-block:not(.is-in) svg .rv-draw {
  stroke-dashoffset: 1;
}

/* Testi ancora da validare (bozze del copy, traduzioni provvisorie): gialli
   finche' qualcuno non li conferma. La classe si toglie dal blocco. Il doppio
   selettore serve a battere `has-*-color`, che e' `!important`. */
.is-draft.is-draft,
.is-draft.is-draft * {
  color: #ffe14d !important;
}

/* "Quando serve": il testo e' una colonna da un terzo, in fondo a destra
   della riga. Entra quando la riga arriva a meta' schermo (reveal.js, MID). */
@media (min-width: 768px) {
  .stack-row .stack-text {
    margin-left: auto;
    padding-top: 0;
  }
  .stack-row > .ensoul-columns-block {
    row-gap: 24px;
  }
}
/* Su mobile il titolo della riga ha `w-full` ma una base di 0% (regola per
   id che North stampa per la colonna), che vince sulla larghezza: accanto al
   testo largo 100% finiva largo zero e le parole cadevano sopra il paragrafo.
   Con la base dalla larghezza va a capo. */
@media (max-width: 767px) {
  .stack-row > .ensoul-columns-block > .ensoul-column-wrapper {
    flex-basis: auto !important;
  }
}
/* PERFORMANCE ha i cerchi piu' a destra di tutte (470px nel Figma): con la
   colonna di testo accanto finirebbero sotto il paragrafo, e la riga andrebbe
   a capo da sola. Da 1440 in su si accorcia quanto basta per stare su una riga. */
@media (min-width: 1440px) {
  .stack-row-2 .stack-circles {
    margin-left: 285px;
  }
}

/* Schede progetto senza video: la card e' uno screenshot verticale, in
   colonna piena sarebbe alto il doppio del video delle altre righe. */
.project-row .card-shot img {
  width: auto;
  max-width: 100%;
  max-height: 520px;
  margin-inline: auto;
}

/* FAQ: accordion di North nella veste delle altre liste, filetti bianchi e
   domanda in Parabole Text leggero. Il corpo e' heading-xs negli attributi del
   blocco: qui la variabile scende a 24/30, 22 su mobile. */
.faq-list,
.faq-list > li {
  border-color: #fff;
}
.faq-list .title_header,
.faq-list [data-accordion-trigger] {
  font-family: var(--wp--preset--font-family--parabole-text);
  font-weight: 300;
  color: var(--color-primary-500);
}
.faq-list {
  --text-heading-xs: max(20px, calc(24 * var(--u, 1px)));
  --text-heading-xs--line-height: calc(var(--text-heading-xs) * 1.25);
  --tw-leading: var(--text-heading-xs--line-height);
}
@media (max-width: 767px) {
  .faq-list {
    --text-heading-xs: 22px;
    --text-heading-xs--line-height: 28px;
    --tw-leading: 28px;
  }
}
/* L'anello di fuoco resta alla sola tastiera. Dopo un click il bottone tiene
   il `:focus`, e Chrome gli riaccende anche `:focus-visible` se la tastiera e'
   stata usata prima: si guarda la modalita' di input che nav-tweaks.js scrive
   su <html>, come per la nav. */
.faq-list [data-accordion-trigger]:focus:not(:focus-visible),
:root[data-nav-input="pointer"] .faq-list [data-accordion-trigger]:focus {
  outline: none;
  box-shadow: none;
}
.faq-list [data-accordion-trigger] {
  padding-block: 22px;
}
/* Da tablet in su domanda, risposta e icona stanno sulla stessa riga. Si
   allinea la cima delle MAIUSCOLE, non quella dei riquadri: la domanda e' a
   24/30 e la sua maiuscola parte 6px sotto il riquadro, la risposta e' a 18/23
   e parte 4,5px sotto. Quindi 22 + 6 - 4,5. L'icona (20px) sta centrata sulla
   prima riga della domanda, a 37px dalla cima. La sua cella ruota di 180 gradi
   quando la voce si apre: il padding dev'essere uguale sopra e sotto, o
   l'icona ruotando cambierebbe quota. */
@media (min-width: 768px) {
  .faq-list [class*="col-start-2"][class*="py-accordion-y"] {
    padding-top: 23.5px;
  }
  .faq-list span[class*="col-start-3"] {
    padding-block: 27px;
    line-height: 0;
  }
  .faq-list span[class*="col-start-3"] svg {
    display: block;
  }
}
.faq-list .accordion-text {
  padding-block: 0 32px;
}
@media (min-width: 768px) {
  .faq-list .accordion-text {
    padding-block: 0 40px;
  }
}

/* "Quando serve": le quattro righe arrivano gia' tutte visibili, accostate
   sotto il loro contenuto, e quando la pila aperta ci sta nella finestra si
   aprono tutte insieme, una volta sola. In pagina le righe stanno gia' ai
   loro posti: stack-pile.js le tiene sollevate (--pile-shift) e ne ritaglia il
   fondo coperto (--pile-cover), e la classe pile-open scioglie entrambi con
   una transizione. Le regole valgono solo con la classe pile-on, che mette lo
   script: senza JS, o con movimento ridotto, restano le quattro righe
   distese. */
/* North avvolge ogni riga a tutta larghezza in una sua <section>. Il gruppo e'
   gia' a tutta larghezza: il margine negativo con cui la riga esce dal
   contenitore qui la sposterebbe fuori schermo. */
.stack-pile section:has(> .stack-row) {
  width: 100%;
  margin-inline: 0;
}
/* Il titolo della sezione sta nel gruppo, sopra le righe, e si ferma con loro.
   Il gruppo e' a tutta larghezza: l'aria ai lati, che fuori arriva dalla
   pagina, qui se la porta il titolo. */
.stack-pile .pile-title {
  width: 100%;
  padding-inline: var(--edge);
}
/* Le righe restano a tutta larghezza, i testi dentro si fermano al bordo del
   contenitore come nel resto della pagina. Il padding arriva dalle utility di
   North (xl ai lati, !important in un layer): si cambia la variabile sul
   blocco e si rimette quella originale ai figli. Il 5xl non si tocca: nelle
   righe e' il padding in basso, e legato al margine laterale cresceva con la
   finestra (402px a 2560px: schede alte 549px). */
@media (min-width: 768px) {
  .stack-pile .stack-row {
    --pile-xl: var(--spacing-xl);
  }
  .stack-pile .stack-row > .ensoul-columns-block {
    --spacing-xl: var(--edge);
  }
  .stack-pile .stack-row > .ensoul-columns-block > * {
    --spacing-xl: var(--pile-xl);
  }
}
/* Il margine sopra il titolo (3xl, 9xl da tablet) passa alla sezione: dentro
   il blocco che si ferma terrebbe le righe 160px piu' in basso, e l'ultima
   finirebbe fuori schermo. */
.stack-pile {
  margin-top: var(--spacing-3xl);
}
.stack-pile .pile-title {
  margin-top: 0;
}
@media (min-width: 768px) {
  .stack-pile {
    margin-top: var(--spacing-9xl);
  }
}
.stack-pile .stack-row > .ensoul-columns-block > .ensoul-column-wrapper {
  align-self: flex-start;
}
.stack-pile {
  /* apertura della pila: piu' lenta e che si posa (19/10, "piu' aggraziate") */
  --pile-ease: cubic-bezier(0.45, 0.05, 0.15, 1);
}
.stack-pile.pile-on .stack-row {
  min-height: var(--pile-row, 0px);
}
.stack-pile.pile-on section:has(> .stack-row) {
  position: relative;
  transform: translateY(var(--pile-shift, 0px));
}
/* La transizione sta solo sullo stato aperto: al caricamento le righe si
   chiudono senza muoversi. */
.stack-pile.pile-open section:has(> .stack-row) {
  transform: none;
  transition: transform 2.4s var(--pile-ease);
}
/* Le righe non hanno fondo: resta il filetto in cima. La classe preset del
   colore di sfondo e' `!important`, quindi serve anche qui. */
.stack-pile .stack-row.has-background {
  background: transparent !important;
}
/* Senza fondo il contenuto di una riga si vedrebbe attraverso quella che le
   sta sopra: stack-pile.js scrive in --pile-cover quanto del suo fondo e'
   coperto dalla riga dopo, e quella parte non si disegna. */
.stack-pile.pile-on .stack-row {
  clip-path: inset(0 0 var(--pile-cover, 0px) 0);
}
.stack-pile.pile-open .stack-row {
  clip-path: inset(0);
  transition: clip-path 2.4s var(--pile-ease);
}

/* La freccia che segue il cursore negli slider dei progetti riposa
   nell'angolo in alto a sinistra, mezza fuori schermo: ora li' ci sono i nomi.
   Si vede solo col cursore sullo slider. */
.projects-slider .content-slider-prev-next {
  transition: opacity 0.2s;
}
.projects-slider:not(:hover) .content-slider-prev-next {
  opacity: 0;
}

/* Tech stack: una riga sola che scorre da bordo a bordo (marquee.js). Senza
   JS, o con movimento ridotto, resta la riga ferma di prima. Lo script clona
   la serie quanto basta e scrive --marquee-shift, la larghezza di una serie:
   la pista trasla di quel tanto e ricomincia senza salto. */
.marquee-on.tech-row {
  overflow: hidden;
}
.marquee-on.tech-row > .ensoul-columns-block {
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  max-width: none;
  column-gap: 0;
  animation: marquee var(--marquee-time, 30s) linear infinite;
}
.marquee-on.tech-row > .ensoul-columns-block > .ensoul-column-wrapper {
  flex: 0 0 auto;
  width: auto;
  max-width: none;
  padding-right: clamp(32px, 5vw, 88px);
}
.marquee-on.tech-row h3 {
  white-space: nowrap;
}
@keyframes marquee {
  to {
    transform: translateX(calc(var(--marquee-shift) * -1));
  }
}

/* "Con chi lavoriamo" su mobile: le due colonne vanno una sotto l'altra e
   la riga che le separa diventa orizzontale. */
@media (max-width: 767px) {
  /* solo padding: la colonna e' alta quanto il contenitore (h-full), un
     margine la farebbe sbordare sulla riga che chiude la sezione */
  .split-cols
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper {
    border-top: 1px solid #fff;
    padding-top: 40px;
    height: auto;
  }
}

/* Blocco "ciao ai": testo per i motori, visibile e in fondo alla pagina.
   Stessa cornice delle righe a linguetta, corpo piccolo su tre colonne. */
.hi-ai > .ensoul-group {
  border-radius: 16px;
  padding: 32px 40px;
  padding-bottom: 0px;
}
.hi-ai .font-paragraph {
  opacity: 0.8;
}
@media (min-width: 1024px) {
  .hi-ai .font-paragraph {
    column-count: 3;
    column-gap: 48px;
  }
}
@media (max-width: 767px) {
  .hi-ai > .ensoul-group {
    padding: 24px;
  }
}

/* Titolo d'apertura con una parola lunga ("replatforming"): a 124px non entra
   nella mezza colonna dell'hero e il browser la spezza a meta'. Si ridefinisce
   la variabile, l'utility di North non si batte da fuori. */
@media (min-width: 768px) {
  .hero-title-long {
    --text-heading-3xl: min(calc(96 * var(--u)), 6.6vw);
    --text-heading-3xl--line-height: 1em;
    --tw-leading: 1em;
  }
}

/* Pagina "Come lavoriamo". Le cinque fasi stanno nello slider pinnato di
   "Dicono di noi" (stessa classe, stessi filetti fra le voci). In cima a ogni
   fase c'e' la pila di forme arrivata fin li': dal cerchio dell'analisi al
   rombo del lancio, che e' l'icona del sito. Un filo le infila tutte e si
   accende con l'avanzare dello slider (assets/js/phase-rail.js). */
.phases-slider {
  --phase-ico: 240px;
}
.icon-block.ico-phase .icon-svg-wrapper,
.icon-block.ico-phase .icon-svg-wrapper svg {
  width: calc(var(--phase-ico) * 240 / 334);
  height: var(--phase-ico);
}
.ico-phase svg {
  overflow: visible;
}
/* Il blocco e' alto circa 490px: centrato nella finestra. La misura vera la
   scrive phase-rail.js in --phase-top. */
.phases-slider.quotes-slider .content-slider {
  top: var(--phase-top, max(24px, calc((100svh - 490px) / 2))) !important;
}
.phases-slider .slide-index-display {
  display: none;
}
/* Lo slider e' a tutta larghezza, ma la prima fase parte dal bordo del
   contenuto e ogni fase e' larga un terzo del contenuto: all'inizio si vede
   come prima, poi la striscia scorre fino ai bordi della finestra. Swiper
   scrive la larghezza delle slide in linea, North sposta la striscia da solo
   sulla sua scrollWidth: padding e larghezze si leggono da li'. */
/* lo spazio in fondo e' un elemento della riga: il padding destro non entra
   nella scrollWidth e l'ultima fase finiva contro il bordo della finestra */
.phases-slider .swiper-wrapper {
  padding-left: var(--edge);
}
.phases-slider .swiper-wrapper::after {
  content: "";
  flex: 0 0 var(--edge);
}
@media (min-width: 768px) {
  .phases-slider .swiper-slide {
    width: calc((100% - 2 * var(--edge) - 96px) / 3) !important;
  }
  /* anche l'ultima slide porta i 48px di spaceBetween di Swiper */
  .phases-slider .swiper-wrapper::after {
    flex-basis: max(0px, calc(var(--edge) - 48px));
  }
}
/* niente filetti verticali fra le fasi: il filo basta a legarle */
main .phases-slider.quotes-slider .swiper-slide + .swiper-slide {
  padding-left: 0;
}
main .phases-slider.quotes-slider .swiper-slide + .swiper-slide::before {
  display: none;
}

.phases-slider.has-rail .phase-slide::after {
  content: "";
  position: absolute;
  top: calc(var(--phase-ico) / 2 - 4px);
  left: var(--rail-start, 0px);
  width: var(--rail-length, 100%);
  height: 9px;
  /* due strati: il punto in testa al filo (solo nella slide dove il filo si
     ferma) e il filo, acceso fino a `--rail-lit` */
  background:
    radial-gradient(
      circle at var(--rail-lit, 0px) 50%,
      var(--rail-dot, transparent) 0 3.5px,
      transparent 4.5px
    ),
    linear-gradient(
        90deg,
        #e5d3ce 0,
        #e5d3ce var(--rail-lit, 0px),
        rgba(255, 255, 255, 0.2) var(--rail-lit, 0px)
      )
      0 50% / 100% 1px no-repeat;
  pointer-events: none;
}
/* l'ultimo tratto finisce sul centro del rombo: mezzo punto in piu' di spazio,
   o il punto in testa al filo verrebbe tagliato a meta' */
.phases-slider.has-rail .phase-slide:last-child::after {
  width: calc(var(--rail-length, 100%) + 5px);
}
/* Il pieno della forma e' una copia senza contorno sotto la forma
   (phase-rail.js): nasce nel centro, dove arriva il punto del filo, e si
   allarga gia' piena fino all'outline in 0,2 s. */
.phases-slider .pile-fill {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  transform: scale(0);
  opacity: 0;
}
.phases-slider .phase-label,
.phases-slider .phase-slide .font-paragraph {
  transition: opacity 0.9s var(--reveal-ease);
}
/* finche' il filo non arriva alla fase, titolo e testo sotto restano spenti */
.phases-slider.has-rail .phase-slide:not(.is-on) .phase-label,
.phases-slider.has-rail .phase-slide:not(.is-on) .font-paragraph {
  opacity: 0.4;
}

@media (max-width: 767px) {
  .phases-slider {
    --phase-ico: 150px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .phases-slider .phase-label,
  .phases-slider .phase-slide .font-paragraph {
    transition: none;
  }
}

/* Apertura delle sezioni corporate ed ecommerce (Figma 2728:8529): titolo su
   una riga e, sotto, due colonne larghe 961, centrate. La larghezza segue --u
   come il titolo, cosi' il rapporto fra i due resta quello del Figma anche
   dove la scala la decide l'altezza della finestra; sotto 1280 le colonne
   sarebbero troppo strette e occupano tutto. */
@media (min-width: 1280px) {
  .sec-lead-title {
    padding-inline: 4.49%;
  }
  .sec-lead-cols > .ensoul-columns-block {
    max-width: min(100%, calc(961 * var(--u))) !important;
    margin-inline: auto;
  }
}

/* Scala fluida. Il Figma e' una schermata 1440 x 900: --u e' "un pixel del
   Figma", vale 1px in una finestra 1440 x 900 e segue il lato che resta piu'
   corto in proporzione, cosi' la composizione di un primo schermo resta quella
   del Figma a qualunque larghezza, altezza o zoom (su un portatile basso, per
   esempio, le quattro righe "quando serve" stanno ancora in una schermata).
   Scende fino a 0,7px. Sopra 1440 x 900 cresce a meta' velocita' (con la
   finestra intera i testi venivano troppo grandi sugli schermi grandi) e si
   ferma a 1,167px, cioe' a 1920, dove il contenitore smette di allargarsi
   (1840 + 40 per lato); oltre, resta fermo come il contenitore. Da tablet in su seguono --u titoli, testi e
   spaziature; i testi piccoli hanno un minimo, per restare leggibili. I token
   del pannello North restano nel CSS generato dal plugin: qui si ridefiniscono,
   tranne quelli dei bottoni (corpo, padding, raggio, colori), che decide il
   pannello Design Tokens. */
@media (min-width: 768px) {
  :root {
    --u: clamp(
      0.7px,
      min(calc(100vw / 1440), calc(100svh / 900), calc((min(100vw / 1440, 100svh / 900) + 1px) / 2)),
      1.1667px
    );
    --text-heading-xs: calc(32 * var(--u));
    --text-heading-sm: calc(40 * var(--u));
    --text-heading-base: calc(48 * var(--u));
    --text-heading-lg: calc(56 * var(--u));
    --text-heading-xl: calc(64 * var(--u));
    --text-heading-2xl: calc(80 * var(--u));
    --text-heading-3xl: calc(124 * var(--u));
    --text-heading-xs--line-height: calc(var(--text-heading-xs) * 1.1250);
    --text-heading-sm--line-height: calc(var(--text-heading-sm) * 1.1000);
    --text-heading-base--line-height: calc(var(--text-heading-base) * 1.0833);
    --text-heading-lg--line-height: calc(var(--text-heading-lg) * 1.0714);
    --text-heading-xl--line-height: calc(var(--text-heading-xl) * 1.1250);
    --text-heading-2xl--line-height: calc(var(--text-heading-2xl) * 1.0000);
    --text-heading-3xl--line-height: calc(var(--text-heading-3xl) * 0.9194);
    --text-paragraph-xs: max(12px, calc(12 * var(--u)));
    --text-paragraph-sm: max(12px, calc(14 * var(--u)));
    --text-paragraph-base: max(14px, calc(16 * var(--u)));
    --text-paragraph-lg: max(15px, calc(18 * var(--u)));
    --text-paragraph-xl: max(19px, calc(24 * var(--u)));
    --text-paragraph-2xl: max(24px, calc(32 * var(--u)));
    --text-paragraph-3xl: max(34px, calc(48 * var(--u)));
    --text-paragraph-xs--line-height: calc(var(--text-paragraph-xs) * 1.3333);
    --text-paragraph-sm--line-height: calc(var(--text-paragraph-sm) * 1.2143);
    --text-paragraph-base--line-height: calc(var(--text-paragraph-base) * 1.2500);
    --text-paragraph-lg--line-height: calc(var(--text-paragraph-lg) * 1.2778);
    --text-paragraph-xl--line-height: calc(var(--text-paragraph-xl) * 1.3333);
    --text-paragraph-2xl--line-height: calc(var(--text-paragraph-2xl) * 1.1250);
    --text-paragraph-3xl--line-height: calc(var(--text-paragraph-3xl) * 1.0000);
    --spacing-xxs: calc(4 * var(--u));
    --spacing-xs: calc(8 * var(--u));
    --spacing-s: calc(16 * var(--u));
    --spacing-m: calc(24 * var(--u));
    --spacing-l: calc(32 * var(--u));
    --spacing-xl: calc(40 * var(--u));
    --spacing-2xl: calc(48 * var(--u));
    --spacing-3xl: calc(56 * var(--u));
    --spacing-4xl: calc(64 * var(--u));
    --spacing-5xl: calc(80 * var(--u));
    --spacing-6xl: calc(96 * var(--u));
    --spacing-7xl: calc(120 * var(--u));
    --spacing-8xl: calc(140 * var(--u));
    --spacing-9xl: calc(160 * var(--u));
    --spacing-columns-dk: calc(48 * var(--u));
    --spacing-columns-y-dk: calc(48 * var(--u));
  }
}

/* Le misure fisse in pixel del Figma seguono la stessa scala: icone, cerchi
   delle righe e i loro spostamenti, testi del footer e del form. Da 1024 le
   righe "quando serve" hanno la geometria del Figma a 1440, in proporzione;
   PERFORMANCE ha i cerchi a 340 invece di 470 a tutte le larghezze: il Figma
   non ha la colonna di testo, e con 470 (anche 400) la riga va a capo a 1024. */
@media (min-width: 768px) {
  .icon-block.ico-arches .icon-svg-wrapper,
  .icon-block.ico-arches .icon-svg-wrapper svg {
    width: calc(277 * var(--u)) !important;
    height: calc(344 * var(--u)) !important;
  }
  .icon-block.ico-diamond-sm .icon-svg-wrapper,
  .icon-block.ico-diamond-sm .icon-svg-wrapper svg {
    width: calc(69 * var(--u)) !important;
    height: calc(88 * var(--u)) !important;
  }
  .icon-block.stack-circles .icon-svg-wrapper,
  .icon-block.stack-circles .icon-svg-wrapper svg,
  .icon-block.tech-circles .icon-svg-wrapper,
  .icon-block.tech-circles .icon-svg-wrapper svg {
    height: calc(62 * var(--u)) !important;
  }
  .aud-head p {
    max-width: calc(350 * var(--u));
  }
  .site-footer {
    font-size: max(13px, calc(14 * var(--u)));
    line-height: 1.2143;
  }
  .form-card .gform_wrapper legend,
  .form-card .gform_wrapper .gfield_label,
  .form-card .gform_wrapper input[type="text"],
  .form-card .gform_wrapper input[type="email"],
  .form-card .gform_wrapper textarea {
    font-size: max(14px, calc(16 * var(--u)));
  }
  .form-card .gform_wrapper .gform_footer input[type="submit"],
  .form-card .gform_wrapper .gform_footer button {
    font-size: max(13px, calc(14 * var(--u))) !important;
  }
}
@media (min-width: 1024px) {
  .stack-row-1 .stack-circles {
    margin-left: calc(32 * var(--u));
  }
  .stack-row-2 .stack-circles {
    margin-left: calc(225 * var(--u));
  }
  .stack-row-3 .stack-circles {
    margin-left: calc(210 * var(--u));
  }
  .stack-row-4 .stack-circles {
    margin-left: calc(280 * var(--u));
  }
}

/* Cambio pagina (assets/js/page-tide.js).
   tide-hold: sott'acqua, fra l'uscita e l'arrivo. Barba aggiunge il main nuovo
   prima che head e script siano allineati e prima del ritorno in cima: resta
   nascosto finche' l'arrivo non lo prende in mano.
   tide-sinking: il blocco si sta dissolvendo o raccogliendo, i suoi stili li
   scrive il JS a ogni fotogramma e le sue transizioni non devono rincorrerli.
   tide-under: la pagina e' stata caricata sott'acqua e aspetta l'arrivo. */
html.tide-hold main[data-barba="container"]:not(.tide-leaving),
html.tide-under main[data-barba="container"],
html.tide-under footer.wp-block-template-part {
  opacity: 0;
}
/* Il main che esce resta in pagina, fermo, mentre l'onda scioglie cio' che si
   vedeva al clic. Fissato e con gli script spenti puo' accorciarsi sopra, e i
   blocchi che stavano sotto lo schermo risalivano nitidi (le righe delle
   tabelle "sopravvivevano" all'onda): visibile resta solo cio' che si scioglie. */
main.tide-leaving :is(.wp-block-ensoul-heading, .font-paragraph, .wp-block-ensoul-list-element, .ens-btn, .pill-tag, .icon-block, .steps-dial, figure, video, .ensoul-divider, .gform_wrapper, .swiper-slide):not(.tide-sinking, .tide-sinking *) {
  visibility: hidden;
}
/* finche' il liquido non parte, niente foto statica ne' grana: solo il colore
   del fondo visto sott'acqua */
html.tide-under body {
  background: #1e182a;
}
html.tide-under #liquid-fallback,
html.tide-under .grain {
  visibility: hidden;
}
.tide-sinking {
  transition: none !important;
}
html.tide-fade main[data-barba="container"] {
  opacity: 0;
  transition: opacity .2s linear;
}

/* reveal.js mostra il primo schermo di una pagina arrivata col cambio pagina
   senza le sue entrate: per un fotogramma nessuna transizione. */
.rv-instant,
.rv-instant::before,
.rv-instant::after,
.rv-instant *,
.rv-instant *::before,
.rv-instant *::after {
  transition: none !important;
}

/* "Quello che non facciamo": i simboli di divieto (.ico-no) sono il 50% piu'
   grandi di come li imposta il blocco (70/50px), centrati nella colonna da
   tablet in su (su mobile stanno a fianco del testo), e quando reveal.js ha
   finito di disegnarli (.is-drawn) fanno un leggero glow. Il filter va sull'svg
   esterno, l'unico a cui tutti i browser applicano drop-shadow. */
.icon-block.ico-no .icon-svg-wrapper {
  --icon-size: 75px !important;
  --icon-size-dk: 105px !important;
}
@media (min-width: 768px) {
  .icon-block.ico-no {
    justify-content: center;
  }
}
.icon-block.ico-no.is-drawn svg {
  animation: ico-no-glow 1.6s ease-out both;
}
@keyframes ico-no-glow {
  0%   { filter: drop-shadow(0 0 0 rgba(229, 211, 206, 0)); }
  30%  { filter: drop-shadow(0 0 7px rgba(229, 211, 206, 0.55)); }
  100% { filter: drop-shadow(0 0 2px rgba(229, 211, 206, 0.15)); }
}
@media (prefers-reduced-motion: reduce) {
  .icon-block.ico-no.is-drawn svg {
    animation: none;
  }
}

/* "Come lavoriamo" (IT e EN: l'unica pagina con lo slider delle fasi): le righe
   di North, cioe' i figli diretti del content, avevano spazi diversi fra loro
   (96, 160, 80, 96, 48px) perche' ogni blocco portava i suoi margini. Qui si
   azzerano e c'e' un passo unico fra una riga e l'altra, piu' ampio di prima, e
   uno fisso fra un titolo e il suo contenuto. Lo slider perde il suo padding
   verticale, che altrimenti si sommerebbe al passo. */
main.wp-block-ensoul-content:has(.phases-slider) {
  --row-gap: clamp(96px, 11vw, 192px);
}
/* il modulo di contatto no: il suo margine lo decide il blocco, dall'editor */
/* :where() non aggiunge peso: le regole sotto (titoli, stacco fra le righe)
   devono continuare a vincere su questa */
main.wp-block-ensoul-content:has(.phases-slider) > :where(:not(:has(.form-card))) {
  margin-top: 0 !important;
}
/* lo spazio sotto lo decidono i blocchi (dall'editor), tranne che per i titoli
   resta azzerato come prima per gli altri blocchi */
main.wp-block-ensoul-content:has(.phases-slider) > :where(:not(:has(.form-card)):not(h2)) {
  margin-bottom: 0 !important;
}
/* il precedente non deve essere un <style>: North ne mette uno in testa al
   main, e la testata della pagina prendeva lo stacco delle righe (158px in alto) */
main.wp-block-ensoul-content:has(.phases-slider) > :not(style) + :is(.slider-section, h2, [class*="cm-group"]) {
  margin-top: var(--row-gap) !important;
}

main.wp-block-ensoul-content:has(.phases-slider) > .slider-section {
  padding-top: 0;
  padding-bottom: 0;
}

/* Griglia del design (mu-plugin griglia-design, voce "Griglia" della barra):
   da 768px 12 colonne con gutter di 24px Figma (--u), larghe quanto il
   contenuto della pagina. Su un contenitore largo quanto il contenuto,
   N colonne = N * --grid-col + (N - 1) * --grid-gutter. */
@media (min-width: 768px) {
  :root {
    --grid-gutter: calc(24 * var(--u, 1px));
    /* larghezza del contenuto: quella del padding di .wp-site-blocks, fino a
       1840. --grid-vw la scrive functions.php (larghezza senza barra di
       scorrimento); 100vw resta come riserva. */
    --grid-content: min(var(--grid-vw, 100vw) - 2 * var(--spacing-content-padding), 1840px);
    --grid-col: calc((var(--grid-content) - 11 * var(--grid-gutter)) / 12);
    --grid-step: calc(var(--grid-col) + var(--grid-gutter));
  }
}

/* FAQ sulla griglia: domanda sulle colonne 1-6, risposta sulle 7-9 (tre
   colonne, la larghezza leggibile di prima), icona nella 12. Prima era una
   griglia propria 1fr 1fr auto, con la risposta fuori colonna. Su mobile la
   FAQ e' impilata e resta com'e'. */
@media (min-width: 768px) {
  .faq-list .accordion-item-side-by-side > .md\:grid {
    grid-template-columns: repeat(12, minmax(0, 1fr)) !important;
    column-gap: var(--grid-gutter) !important;
  }
  .faq-list .accordion-item-side-by-side > .md\:grid > .title_header {
    grid-column: 1 / 7;
  }
  .faq-list .accordion-item-side-by-side > .md\:grid > [data-accordion-content] {
    grid-column: 7 / 10;
  }
  .faq-list .accordion-item-side-by-side > .md\:grid > .col-start-3 {
    grid-column: 12 / 13;
    justify-self: end;
  }
}

/* Home, apertura: sopratitolo, titolo e paragrafo alla stessa distanza a occhio.
   Il sopratitolo ha 16px sotto, il paragrafo stava attaccato al titolo (0px):
   con lo stesso margine le due distanze fra le lettere vanno da 33/16 a 33/32. */
main:has(.hero) h1 + p {
  margin-top: 16px;
  /* riga piu' corta: arrivava a 800-1100px (quasi tutta la pagina sugli schermi
     larghi), ora circa 45 caratteri per riga */
  max-width: 32em;
}

/* Componenti di North agganciati alla griglia a 12 colonne (da 768px). Erano
   colonne in percentuale senza gutter, con padding fissi: bordi a pochi pixel
   dalle linee della griglia. N colonne = N * --grid-col + (N - 1) * gutter. */
@media (min-width: 768px) {
  /* Lo spazio standard fra le colonne di North diventa il gutter della
     griglia. Si ridefiniscono le variabili e non il column-gap: North le usa
     anche per calcolare le larghezze (P% - gap * (1 - P)), e cambiando solo
     il gap le righe flex uscivano di squadra. Cosi' colonne da 1/2, 1/3, 1/4
     coprono colonne intere; 67/33 restano a ~4px, perche' North arrotonda. */
  .ensoul-columns-section {
    --spacing-columns: var(--grid-gutter);
    --spacing-columns-dk: var(--grid-gutter);
  }

  /* Scheda progetto: la larghezza del testo e la sua posizione le decidono i
     blocchi (colonna del testo, dall'editor). */

  /* Due colonne "a chi serve": il separatore sta nel mezzo del gutter fra la
     colonna 6 e la 7; la meta' destra parte dalla colonna 8, una colonna di
     aria dopo il separatore (dalla 7 il testo stava a 12px dalla riga).
     L'icona occupa una colonna e il testo comincia da quella dopo. */
  .split-cols > .ensoul-columns-block > .ensoul-column-wrapper ~ .ensoul-column-wrapper {
    padding-left: calc(var(--grid-gutter) / 2 + var(--grid-step));
  }
  /* Le liste con i filetti larghe 5 colonne in entrambi i box: a sinistra
     colonne 1-5 (prima arrivavano al separatore), a destra 8-12 (prima i
     filetti uscivano fino al bordo della finestra). Stessa larghezza, cosi'
     le voci vanno a capo allo stesso modo e le righe restano allineate. */
  .split-cols .rule-list {
    max-width: calc(var(--grid-col) * 5 + var(--grid-gutter) * 4);
  }
  .aud-head > .ensoul-columns-block > .ensoul-column-wrapper:has(.icon-block) {
    flex: none !important;
    width: var(--grid-col) !important;
  }
  .aud-head > .ensoul-columns-block > .ensoul-column-wrapper:not(:has(.icon-block)) {
    flex: 1 1 0 !important;
    width: auto;
    padding-left: var(--grid-gutter);
  }

  /* Righe numerate: la forma a sinistra occupa 3 colonne, il numero e il
     titolo partono dalla 4; dove parte la descrizione lo decidono le larghezze
     delle colonne del blocco (editor). */
  .steps-scroll > .ensoul-columns-block > .ensoul-column-wrapper:not(.steps-list) {
    flex: none;
    width: calc(var(--grid-step) * 3) !important;
  }
  .steps-scroll > .ensoul-columns-block > .steps-list {
    flex: 1 1 0 !important;
    width: auto;
  }

  /* Pagine di migrazione, introduzione: la forma a sinistra copre 5 colonne,
     il testo le 5 successive (dalla 6 alla 10). Solo l'introduzione a due
     colonne: quella a quattro (home, Chi siamo) e' gia' in colonna. */
  .intro > .ensoul-columns-block:not(:has(> .ensoul-column-wrapper ~ .ensoul-column-wrapper ~ .ensoul-column-wrapper)) > .ensoul-column-wrapper:has(.icon-block) {
    flex: none;
    width: calc(var(--grid-step) * 5) !important;
  }
  .intro > .ensoul-columns-block:not(:has(> .ensoul-column-wrapper ~ .ensoul-column-wrapper ~ .ensoul-column-wrapper)) > .ensoul-column-wrapper:not(:has(.icon-block)) {
    flex: none;
    width: calc(var(--grid-col) * 5 + var(--grid-gutter) * 4) !important;
  }

  /* Home, le due colonne di testo sotto i titoli delle sezioni: dalla colonna
     3 alla 10, quattro colonne ciascuna (prima 240-1200px, fuori griglia). */
  .sec-lead-cols > .ensoul-columns-block {
    margin-left: calc(var(--grid-step) * 2) !important;
    width: calc(var(--grid-col) * 8 + var(--grid-gutter) * 7);
    max-width: none !important;
    column-gap: var(--grid-gutter);
    flex-wrap: nowrap;
  }
  .sec-lead-cols > .ensoul-columns-block > .ensoul-column-wrapper {
    flex: none;
    width: calc(var(--grid-col) * 4 + var(--grid-gutter) * 3) !important;
    padding-left: 0;
    padding-right: 0;
  }
}

/* "Dicono di noi" (home): video verticali dei clienti (Vimeo, 9:16, da
   ensoul.it). Il blocco video di North e' pensato per il 16:9: qui l'iframe
   prende la proporzione vera, e il video si ferma a 3 colonne della griglia
   (su mobile a 320px), altrimenti tre video verticali sarebbero alti come la
   finestra. */
.testimonial-video iframe {
  aspect-ratio: 9 / 16;
  height: auto;
  border-radius: 8px;
}
.testimonial-video {
  max-width: 320px;
}
@media (min-width: 768px) {
  .testimonial-video {
    max-width: calc(var(--grid-col) * 3 + var(--grid-gutter) * 2);
  }
}
.testimonials .column {
  row-gap: 0;
}

/* Chi siamo, "Le persone": nome e ruolo attaccati (il gap verticale della
   colonna di North li separava come due blocchi) e il link a Blueant
   Solutions riconoscibile come link. */
.team-grid .column {
  row-gap: 0;
}
.team-partner a {
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

/* Casi studio (video del sito nel telefono, a sinistra della scheda) e "Dicono
   di noi": il video compare in dissolvenza e intanto l'immagine si assesta da
   un ingrandimento del 4%, dentro la sua finestra (overflow: hidden), senza
   spostarsi. reveal.js mette `is-in` con il ritardo in --rv-delay, uno dopo
   l'altro. Niente clip-path: su Safari attorno a un <video> lo fa sparire. */
.reveal-on main :is(.testimonials, .project-row) .video-section {
  overflow: hidden;
  opacity: 0;
  transition: opacity 1.6s var(--line-ease) var(--rv-delay, 0s);
}
.reveal-on main .testimonials .video-section {
  border-radius: 8px;
}
.reveal-on main :is(.testimonials, .project-row) .video-section :is(video, iframe) {
  transform: scale(calc(1 + var(--rv-shift) * 0.04));
  transition: transform 2.4s var(--reveal-ease) var(--rv-delay, 0s);
}
.reveal-on main :is(.testimonials, .project-row) .video-section.is-in {
  opacity: 1;
}
.reveal-on main :is(.testimonials, .project-row) .video-section.is-in :is(video, iframe) {
  transform: none;
}

/* Outline trasparente su tutto il sito per chi usa mouse o touch; resta per chi
   naviga da tastiera, quindi anche per chi usa uno screen reader (il CSS non
   puo' sapere se c'e' uno screen reader: la tastiera e' il segnale che c'e').
   La modalita' la scrive nav-tweaks.js su <html>; senza attributo, cioe' prima
   di qualsiasi interazione, l'outline resta visibile. Solo il colore: lo
   spessore e la posizione non cambiano, quindi nulla si sposta passando da una
   modalita' all'altra. Basta la catena del fuoco (:focus-within comprende
   l'elemento col fuoco): nessun altro elemento ha un outline da nascondere. */
html[data-nav-input="pointer"] :focus-within,
html[data-nav-input="pointer"] :focus-within::before,
html[data-nav-input="pointer"] :focus-within::after {
  outline-color: transparent !important;
}

/* Righe orizzontali che dividono le parti: mezzo pixel invece di uno.
   Chrome arrotonda un bordo da 0,5px a 1px anche sugli schermi retina, quindi
   le righe fatte con border diventano un'ombra interna da mezzo pixel (segue
   anche gli angoli arrotondati delle righe impilate); quelle fatte come altezza
   (filetti dei divisori e delle liste) scendono a 0,5px direttamente.
   Su uno schermo a 1x il browser non disegna meno di un pixel: li' restano come
   prima. Fuori: le righe in SVG o WebGL, le verticali fra le colonne, le
   cornici del modulo e del footer, i campi del modulo. */
:root {
  --rule-w: 0.5px;
  /* sotto il mezzo pixel il browser non scende: piu' sottili a vista
     vuol dire piu' tenui (19/10) */
  --rule-c: rgba(229, 211, 206, 0.45);
}
:is(main, .site-footer) .ensoul-divider hr,
.rule-list li + li::before {
  height: var(--rule-w);
  background: var(--rule-c) !important;
}
.stack-row {
  border-top: 0;
  box-shadow: inset 0 var(--rule-w) 0 var(--rule-c);
}
.stack-pile.border-b {
  border-bottom: 0;
  box-shadow: inset 0 calc(var(--rule-w) * -1) 0 var(--rule-c);
}
/* fisarmonica delle FAQ: North legge lo spessore del bordo da questa variabile */
.faq-list {
  --spacing-dimension-border: 0px;
  box-shadow: inset 0 var(--rule-w) 0 var(--rule-c);
}
.faq-list > li {
  box-shadow: inset 0 calc(var(--rule-w) * -1) 0 var(--rule-c);
}
@media (max-width: 767px) {
  .split-cols
    > .ensoul-columns-block
    > .ensoul-column-wrapper
    + .ensoul-column-wrapper {
    border-top: 0;
    box-shadow: inset 0 var(--rule-w) 0 var(--rule-c);
  }
}

/* Numero di ogni domanda delle FAQ (01, 02, 03…), piccolo, in apice a
   sinistra della domanda. Un contatore CSS: si numerano da sole e restano
   giuste se si aggiunge o si sposta una domanda dall'editor. ::before e'
   libero sul bottone (::after e' l'area cliccabile del layout desktop). */
.faq-list {
  counter-reset: faq;
}
.faq-list > li {
  counter-increment: faq;
}
.faq-list > li .title_header button {
  display: flex;
  align-items: flex-start;
}
/* colonna fissa per il numero: le righe della domanda restano allineate
   fra loro e fra una domanda e l'altra */
.faq-list > li .title_header button::before {
  content: counter(faq, decimal-leading-zero);
  flex: 0 0 2.4em;
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.08em;
  margin-top: 0.15em;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* Menu a tendina del modulo Let's talk: freccia chiara a destra */
.form-card .gform_wrapper select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23E5D3CE' stroke-width='1.2'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 2px center !important;
  background-size: 12px 8px !important;
  padding-right: 24px;
  appearance: none;
}

/* Schede col bordo arrotondato (stack-row): stesso numero delle FAQ, in apice
   a sinistra del titolo. Ogni scheda sta nella sua <section>, una dopo
   l'altra: il contatore ricomincia alla prima di ogni gruppo. Il numero e'
   assoluto (con lo spazio tenuto dal padding del titolo) perche' durante
   l'entrata reveal.js mette il titolo in colonna flex, e un ::before in
   flusso finirebbe su una riga sua. */
section:has(> .stack-row) {
  counter-increment: card;
}
:not(section:has(> .stack-row)) + section:has(> .stack-row),
section:has(> .stack-row):first-child {
  counter-reset: card;
}
.stack-row .ensoul-column-wrapper:first-of-type h3 {
  position: relative;
  padding-left: 34px;
}
.stack-row .ensoul-column-wrapper:first-of-type h3::before {
  content: counter(card, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.35em;
  font-family: var(--wp--preset--font-family--parabole-text, inherit);
  font-size: 11px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: none;
  opacity: 0.6;
  font-variant-numeric: tabular-nums;
}

/* Menu a tendina personalizzabili (appearance: base-select, Chrome/Edge 135+):
   il <select> resta nativo (tastiera, lettori di schermo, invio del modulo),
   ma il campo e il menu che si apre (::picker(select)) si disegnano qui.
   Campo: la stessa riga sottolineata degli altri, con la freccina che gira
   all'apertura. Menu: un pannello di vetro scuro che scende e compare in
   dissolvenza, voci con l'evidenza al passaggio e un punto sulla scelta.
   Dove base-select non c'e' resta il menu del sistema, con la freccina
   disegnata come sfondo (regola sopra). */
@supports (appearance: base-select) {
  .form-card .gform_wrapper select,
  .form-card .gform_wrapper select::picker(select) {
    appearance: base-select;
  }
  .form-card .gform_wrapper select {
    display: flex;
    align-items: center;
    width: 100%;
    background-image: none !important;
    padding: 6px 0;
    font: inherit;
    font-size: 16px;
    color: var(--form-ink);
  }
  .form-card .gform_wrapper select::picker-icon {
    content: "";
    width: 12px;
    height: 8px;
    margin-left: auto;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23E5D3CE' stroke-width='1.2'/%3E%3C/svg%3E") no-repeat center / 12px 8px;
    transition: rotate 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .form-card .gform_wrapper select:open::picker-icon {
    rotate: 180deg;
  }
  .form-card .gform_wrapper select::picker(select) {
    margin-top: 10px;
    padding: 6px;
    border: 1px solid rgba(229, 211, 206, 0.22);
    border-radius: 10px;
    background: rgba(22, 18, 29, 0.9);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
    color: var(--form-ink);
    max-height: min(340px, 60vh);
    overflow-y: auto;
    scrollbar-width: thin;
    opacity: 0;
    translate: 0 -6px;
    transition:
      opacity 0.25s ease,
      translate 0.35s cubic-bezier(0.22, 1, 0.36, 1),
      display 0.35s allow-discrete,
      overlay 0.35s allow-discrete;
  }
  .form-card .gform_wrapper select:open::picker(select) {
    opacity: 1;
    translate: 0 0;
  }
  @starting-style {
    .form-card .gform_wrapper select:open::picker(select) {
      opacity: 0;
      translate: 0 -6px;
    }
  }
  .form-card .gform_wrapper select option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 6px;
    color: var(--form-ink);
    font-size: 15px;
    transition: background-color 0.2s ease;
  }
  .form-card .gform_wrapper select option:hover,
  .form-card .gform_wrapper select option:focus-visible {
    background: rgba(229, 211, 206, 0.1);
    outline: none;
  }
  /* la voce "Scegli" (segnaposto di Gravity Forms) non si sceglie: piu' tenue */
  .form-card .gform_wrapper select option[value=""] {
    opacity: 0.5;
  }
  .form-card .gform_wrapper select option::checkmark {
    content: "";
    order: 1;
    margin-left: auto;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
  }
}

/* Pollici di Incluso / Non incluso (Let's talk): ognuno pieno del colore del
   fondo, cosi' quello davanti copre quelli dietro e la cascata si legge
   come una pila di lastre vista dall'alto. La luce a cascata
   delle pile qui lavora sul solo tratto: sull'opacita' del tracciato intero
   il pieno diventerebbe trasparente e le linee dietro ricomparirebbero. */
.icon-block:is(.ico-pile-thumb-up, .ico-pile-thumb-down) svg path {
  fill: #100b13;
  animation-name: layer-glow-stroke;
}
@keyframes layer-glow-stroke {
  0%,
  100% {
    stroke-opacity: 0.38;
  }
  50% {
    stroke-opacity: 1;
  }
}

/* Righe verticali (fra le colonne, accanto all'hero, fra le testimonianze):
   stesso tratto delle orizzontali, mezzo pixel e crema tenue. */
main .hero-right::before,
main .hero-col-right::before,
.split-cols > .ensoul-columns-block > .ensoul-column-wrapper + .ensoul-column-wrapper::before,
.split-cols-3 > .ensoul-columns-block > .ensoul-column-wrapper + .ensoul-column-wrapper::before,
.quotes-slider .swiper-slide + .swiper-slide::before {
  width: var(--rule-w);
  background: var(--rule-c);
}

/* Testo sotto il cursore in difference con la scia del liquido
   (assets/js/text-diff.js): dove passa la scia chiara le lettere si invertono.
   Un elemento alla volta: ognuno chiede al browser una copia di quello che ha
   dietro, su tutto il testo insieme lo scroll rallenterebbe. */
.rp-diff {
  mix-blend-mode: difference;
}

/* Attorno al cursore il testo si schiarisce, solo dentro le lettere
   (text-diff.js): sfumatura radiale ritagliata sul testo, posizionata sulla
   finestra (background-attachment: fixed). Il centro e' il bianco pieno:
   in difference col fondo risulta il bianco piu' luminoso possibile, piu'
   leggibile del crema. Sul fondo non c'e' nessun alone. La porta solo il
   testo che il cerchio tocca (rp-lens), e le variabili non si ereditano:
   cambiarle a ogni fotogramma ricalcola quel testo, non la pagina. */
@property --rp-mx {
  syntax: "<length>";
  inherits: false;
  initial-value: -9999px;
}
@property --rp-my {
  syntax: "<length>";
  inherits: false;
  initial-value: -9999px;
}
@property --rp-r {
  syntax: "<length>";
  inherits: false;
  initial-value: 1px;
}
.rp-lens {
  --rp-dark: rgb(255, 255, 255);
  background-image: radial-gradient(
    circle var(--rp-r) at var(--rp-mx) var(--rp-my),
    var(--rp-dark) 0%,
    var(--rp-dark) 40%,
    var(--rp-c, currentColor) 100%
  );
  background-attachment: fixed;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.rp-lens * {
  -webkit-text-fill-color: transparent;
}

/* Numeri delle schede: sotto il cerchio (.rp-lens) il titolo ha il
   riempimento trasparente e il numero, che lo eredita, spariva. */
.stack-row .ensoul-column-wrapper:first-of-type h3::before {
  color: var(--color-primary-500, #e5d3ce);
  -webkit-text-fill-color: var(--color-primary-500, #e5d3ce);
}

/* Mentre il testo entra (reveal.js: .rv-text, righe che salgono e sfumano) niente
   sfumatura ritagliata sulle lettere: verrebbe disegnata sulle lettere gia' al
   loro posto e il testo comparirebbe di colpo, senza animazione. Riempimento
   normale finche' l'entrata non e' finita; la difference con la scia resta. */
.rp-lens.rv-text {
  background-image: none;
  -webkit-text-fill-color: currentColor;
}
.rp-lens.rv-text * {
  -webkit-text-fill-color: currentColor;
}

/* Classi di griglia da mettere sui blocchi dall'editor (Avanzate > Classi CSS
   aggiuntive), per allineare alle 12 colonne della griglia cio' che la scala
   di spaziature di North non centra. Senza !important: vincono sulle utility
   di North perche' quelle stanno in un @layer.
   grid-ml-1: comincia una colonna dopo un elemento che finisce a meta' gutter
   (come il video dei progetti, largo mezza finestra).
   grid-mr-1: si ferma una colonna prima del bordo destro (es. il testo delle
   righe numerate, spinto a destra).
   grid-w-4, grid-w-6: largo al massimo 4 o 6 colonne. */
@media (min-width: 768px) {
  .grid-ml-1 {
    margin-left: calc(var(--grid-gutter) / 2 + var(--grid-step));
  }
  .grid-mr-1 {
    margin-right: var(--grid-step);
  }
  /* larghezza massima in colonne (per paragrafi e titoli) */
  .grid-w-4 {
    max-width: calc(var(--grid-step) * 4 - var(--grid-gutter));
  }
  .grid-w-6 {
    max-width: calc(var(--grid-step) * 6 - var(--grid-gutter));
  }
}

/* Home, mobile (20/10).
   Hero: era alto 80vh (altezza mobile del blocco, ora "auto" dall'editor), ma
   testo, bottone e pila sono piu' alti e la pila usciva sotto, a cavallo del
   separatore. Il testo sta centrato nel primo schermo (sotto main e il margine
   della sezione, 64px, e la barra di amministrazione se c'e') e la pila (300px
   piu' il suo margine 3xl) viene dopo, prima del separatore. Il selettore e'
   lungo apposta: North azzera min-height delle colonne con uno di 8 classi. */
@media (max-width: 767px) {
  .hero > .ensoul-columns-block.flex.items-stretch > .ensoul-column-wrapper:has(.icon-block):not(.self-center):not(.self-start):not(.self-end) > .column {
    min-height: calc(100svh - var(--wp-admin--admin-bar--height, 0px) - 64px + 300px + var(--spacing-3xl));
  }
  .hero .ensoul-column-wrapper:has(.icon-block) > .column > :first-child {
    margin-top: auto;
  }
  .hero .ensoul-column-wrapper:has(.icon-block) > .column > .button-container {
    margin-bottom: auto;
  }
  /* Intro ("You spent months…"): era grande quanto il titolo dell'hero. La
     taglia arriva da text-heading-base! (!important in un layer di North): si
     cambia la variabile. */
  .intro .wp-block-ensoul-heading {
    --text-heading-base: var(--text-heading-xs);
    --text-heading-base--line-height: var(--text-heading-xs--line-height);
  }
  /* "Dicono di noi": i video sono un poco piu' stretti della colonna, centrati */
  .testimonials .video-section {
    margin-inline: auto;
  }
}

/* Titoli d'intestazione troppo larghi su mobile ("Ecommerce" a 64px usciva
   dalla colonna): classe title-fit dall'editor, 2px in meno. La taglia arriva
   da text-heading-xl! (utility di North in un layer): si cambia la variabile,
   64px su mobile nel tema. */
@media (max-width: 767px) {
  .title-fit {
    --text-heading-xl: 62px;
  }
}

/* Tabella "Cosa portiamo" (PrestaShop e Magento): righe con le classi
   map-head (intestazioni) e map-row (righe), messe dall'editor. Su mobile le
   tre colonne finivano una sotto l'altra con le intestazioni tutte in cima,
   e non si capiva quale fosse la piattaforma vecchia e quale la nuova. Qui
   ogni riga diventa "da | freccia | a" in grassetto, con sotto cosa facciamo
   (l'etichetta "What we do:" e' nel testo, dall'editor, nascosta da md:hidden
   su desktop). Le intestazioni restano come righetta in cima, "PrestaShop ->
   Shopify" in piccolo, senza la terza. La freccia e' un elemento della
   griglia (::before del blocco), nella colonna di mezzo: non sta nel testo,
   quindi l'entrata di reveal.js non la sposta. */
@media (max-width: 767px) {
  .map-head > .ensoul-columns-block > .ensoul-column-wrapper:nth-of-type(3) {
    display: none;
  }
  .map-head > .ensoul-columns-block {
    padding-block: var(--spacing-m);
    --text-heading-sm: var(--text-paragraph-sm);
    --text-heading-sm--line-height: var(--text-paragraph-sm--line-height);
  }
  .map-head h2 {
    margin-bottom: 0;
  }
  :is(.map-row, .map-head) > .ensoul-columns-block {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    column-gap: var(--spacing-xs);
    row-gap: var(--spacing-s);
    align-items: start;
  }
  :is(.map-row, .map-head) > .ensoul-columns-block::before {
    content: "\2192";
    grid-column: 2;
    grid-row: 1;
    font-size: var(--text-paragraph-base);
    line-height: var(--text-paragraph-base--line-height);
  }
  .map-head > .ensoul-columns-block::before {
    font-size: var(--text-paragraph-sm);
    line-height: var(--text-paragraph-sm--line-height);
  }
  :is(.map-row, .map-head) > .ensoul-columns-block > .ensoul-column-wrapper:nth-of-type(1) {
    grid-column: 1;
    grid-row: 1;
  }
  :is(.map-row, .map-head) > .ensoul-columns-block > .ensoul-column-wrapper:nth-of-type(2) {
    grid-column: 3;
    grid-row: 1;
  }
  .map-row > .ensoul-columns-block > .ensoul-column-wrapper:nth-of-type(-n + 2) p {
    font-weight: 500;
  }
  /* le due celle partono dalla prima riga, come la freccia: la colonna di
     North le centrava in verticale accanto a una cella su piu' righe */
  .map-row > .ensoul-columns-block > .ensoul-column-wrapper > .column {
    justify-content: flex-start;
  }
  /* cosa facciamo: sotto, su tutta la riga, un gradino sotto nella scala dei
     paragrafi (base -> sm) */
  .map-row > .ensoul-columns-block > .ensoul-column-wrapper:nth-of-type(3) {
    grid-column: 1 / -1;
    grid-row: 2;
    --text-paragraph-base: var(--text-paragraph-sm);
    --text-paragraph-base--line-height: var(--text-paragraph-sm--line-height);
  }
}
