/* Gravity — composizione della pagina.
   Fondo nero pieno dall'inizio alla fine. Le sezioni si distinguono per scala
   tipografica e per vuoto, mai per colore. */

/* ============================================================== controlli */

/* Rettangolo pieno, angoli vivi. È l'unico elemento chiaro della pagina e compare
   tre volte: navbar, hero e chiusura. */
.gv-btn-solid {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  background: var(--gv-text);
  color: var(--gv-black);
  border: 0;
  border-radius: 0;
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--gv-dur-hover) var(--gv-ease);
}

.gv-btn-solid:hover {
  background: #ffffff;
}

.gv-btn-solid[aria-disabled="true"] {
  background: var(--gv-line-strong);
  color: var(--gv-text-dim);
  cursor: default;
  pointer-events: none;
}

/* Grande: il bottone primario, in Instrument Sans a 500 al corpo del titolo di una voce. */
.gv-btn-solid--lg {
  font-weight: 500;
  font-size: var(--gv-type-button);
  letter-spacing: var(--gv-type-button-tracking);
  min-height: clamp(58px, 6vw, 96px);
  padding-inline: clamp(28px, 4vw, 64px);
}

/* Piccolo: un'etichetta su fondo pieno, al corpo delle voci della navbar accanto. */
.gv-btn-solid--sm {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  min-height: 44px;
  padding-inline: 22px;
}

/* Bottone di servizio: bordo sottile, nessun riempimento, etichetta maiuscola. */
.gv-btn-line {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: var(--gv-touch);
  padding-inline: 20px;
  border: var(--gv-border) solid var(--gv-line-strong);
  color: var(--gv-text);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  transition: var(--gv-transition-hover);
}

.gv-btn-line:hover {
  border-color: var(--gv-text-dim);
}

.gv-icon {
  width: 16px;
  height: 16px;
  flex: none;
  fill: currentColor;
}

.gv-icon--20 {
  width: 20px;
  height: 20px;
}

/* ============================================================== 00 navbar */

.gv-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--gv-bg);
  border-bottom: var(--gv-border) solid var(--gv-line);
}

.gv-nav__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gv-space-5);
  height: var(--gv-nav-height);
}

.gv-nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}

/* Lockup ufficiale in maschera: simbolo e scritta già composti nello SVG allegato,
   presi come sono e colorati dal testo corrente. Rapporto 676:218. */
.gv-logo-lockup {
  display: block;
  height: 34px;
  width: calc(34px * 676 / 218);
  background-color: var(--gv-text);
  -webkit-mask: url("../assets/brand/Gravity_logo_wordmark_black.svg") no-repeat center / contain;
  mask: url("../assets/brand/Gravity_logo_wordmark_black.svg") no-repeat center / contain;
}

/* Solo simbolo, senza scritta. */
.gv-logo-mark {
  display: block;
  width: 30px;
  height: 30px;
  background-color: var(--gv-text);
  -webkit-mask: url("../assets/brand/gravity_hypercube_black.svg") no-repeat center / contain;
  mask: url("../assets/brand/gravity_hypercube_black.svg") no-repeat center / contain;
}

.gv-nav__right {
  display: flex;
  align-items: center;
  gap: var(--gv-space-6);
}

.gv-nav__links {
  display: none;
  align-items: center;
  gap: var(--gv-space-6);
}

/* Voci della navbar: etichette maiuscole strette, al corpo delle etichette. */
.gv-nav__link {
  font-size: var(--gv-type-small);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-dim);
}

.gv-nav__link[href]:hover,
.gv-nav__link[aria-current="true"] {
  color: var(--gv-text);
}

/* Area clienti: stessa voce del menu, a destra, fuori dall'elenco delle sezioni.
   Senza indirizzo resta scritta ma non reagisce. */
.gv-nav__client {
  display: none;
}

.gv-nav__link[aria-disabled="true"],
.gv-nav__panel a[aria-disabled="true"] {
  cursor: default;
}

.gv-nav__menu-btn {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  color: var(--gv-text);
}

.gv-nav__panel {
  display: none;
  border-top: var(--gv-border) solid var(--gv-line);
  background: var(--gv-bg);
  padding-block: var(--gv-space-2) var(--gv-space-4);
}

.gv-nav__panel[data-open="true"] {
  display: block;
}

.gv-nav__panel a:not(.gv-btn-solid) {
  display: flex;
  align-items: center;
  min-height: var(--gv-touch);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-dim);
}

.gv-nav__panel a[href]:not(.gv-btn-solid):hover {
  color: var(--gv-text);
}

/* Sotto i 640px "Prenota 30 minuti" non entra nella barra accanto al marchio e
   al bottone del menu: lo spingerebbe fuori dallo schermo. Lì il bottone passa
   dentro il menu, e nell'hero resta quello grande. */
.gv-nav__panel-cta {
  display: none;
}

@media (max-width: 639px) {
  .gv-nav__row .gv-btn-solid {
    display: none;
  }

  .gv-nav__panel-cta {
    display: flex;
    margin-top: var(--gv-space-3);
  }
}

@media (min-width: 1000px) {
  .gv-nav__links,
  .gv-nav__client {
    display: flex;
  }

  .gv-nav__menu-btn,
  .gv-nav__panel {
    display: none !important;
  }
}

/* =============================================================== 01 hero */

.gv-hero {
  position: relative;
  min-height: calc(100svh - var(--gv-nav-height));
  display: grid;
  grid-template-rows: 1fr auto;
}

.gv-hero__stage {
  position: relative;
  min-height: 280px;
}

.gv-hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Lo SVG statico è lo stato di partenza: senza JavaScript, senza canvas o con
   campionamento fallito resta questo. Le particelle lo sostituiscono solo
   quando partono davvero. */
.gv-hero__fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--gv-space-8);
}

.gv-hero__fallback img {
  width: min(62vh, 72vw, 720px);
  opacity: 0.7;
}

.gv-hero[data-particles="on"] .gv-hero__fallback {
  display: none;
}

.gv-hero__foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gv-space-6);
  padding-bottom: max(var(--gv-space-7), env(safe-area-inset-bottom));
  padding-top: var(--gv-space-5);
}

.gv-hero__claim {
  display: grid;
  gap: var(--gv-space-4);
}

/* Sotto i 1200px il titolo sta su tre righe e la seconda ruota. */
.hero-fixed {
  display: block;
}

/* Il riquadro della riga che ruota è alto quanto il termine più lungo, scritto
   invisibile nel ::before: occupa tutta la riga ma nessuno spazio orizzontale, e
   il termine vero ci si sovrappone. Così un termine che va a capo non spinge giù
   la terza riga. */
.hero-rotating {
  position: relative;
  display: flex;
  align-items: flex-start;
}

.hero-rotating::before {
  content: attr(data-rotate-longest);
  flex: none;
  width: 100%;
  margin-right: -100%;
  visibility: hidden;
}

/* A rotazione avviata il termine vive in un livello sopra il riquadro: qualunque
   cosa succeda a metà di un passaggio, non sposta niente. */
.hero-rotating__live {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

/* Senza rotazione il riquadro non ha niente da riservare. */
@media (prefers-reduced-motion: reduce) {
  .hero-rotating::before {
    content: none;
  }
}

.gv-hero__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px var(--gv-space-3);
  color: var(--gv-text-dim);
}

.gv-hero__stars {
  display: inline-flex;
  gap: 2px;
  color: var(--gv-text);
}

.gv-hero__stars svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

.gv-hero__score {
  color: var(--gv-text);
}

.gv-hero__action {
  display: grid;
  gap: var(--gv-space-3);
  justify-items: start;
  width: 100%;
}

.gv-hero__action .gv-btn-solid {
  width: 100%;
}

/* Da 1200px il titolo sta su una riga sola, a tutta larghezza, e sotto ci sono il
   voto a sinistra e il bottone a destra. Più stretto, su una riga scenderebbe sotto
   il corpo dei titoli di sezione. Il corpo lo decide la frase più lunga,
   "Costruiamo gestionali su misura per la tua azienda.": nel carattere pixel è
   larga 22,08 volte il corpo con un filo di margine, e lo script riscrive il
   valore solo se i termini cambiano. Il corpo non supera quello del display.
   Il riquadro del termine che ruota resta largo quanto il termine servito, scritto
   invisibile nel ::before, e la fine della frase segue il testo con transform: nel
   layout non si sposta niente. */
@media (min-width: 1200px) {
  .gv-hero__foot {
    container-type: inline-size;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--gv-space-5) var(--gv-space-6);
  }

  .gv-hero__claim {
    display: contents;
  }

  .gv-hero__claim h1 {
    --gv-hero-fit: 22.08;
    grid-column: 1 / -1;
    white-space: nowrap;
    font-size: min(var(--gv-type-display), 100cqi / var(--gv-hero-fit));
  }

  .hero-fixed,
  .hero-rotating {
    display: inline-block;
  }

  /* Il ::before dà al riquadro altezza e linea di base del testo: senza, con il
     termine nel livello sopra, il riquadro resterebbe alto zero e il termine
     scenderebbe sotto la riga. Prima dello script è un carattere a larghezza zero;
     a rotazione avviata contiene il termine servito, invisibile, e ne tiene la
     larghezza. È testo generato, quindi non entra nel testo del titolo. */
  .hero-rotating::before {
    content: "\200B";
    width: auto;
    margin-right: 0;
  }

  .hero-rotating[data-rotate-ghost]::before {
    content: attr(data-rotate-ghost);
  }

  /* Largo quanto il testo che si vede: la fine della frase lo segue. */
  .hero-rotating__live {
    width: auto;
  }

  .gv-hero__action {
    justify-items: end;
    width: auto;
  }

  .gv-hero__action .gv-btn-solid {
    width: auto;
  }
}

/* ======================================================= testata sezione */

/* Titolo e, sotto, il sottotitolo: a ogni larghezza, mai affiancati. */
.gv-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gv-space-5);
  margin-bottom: clamp(40px, 5.4vw, 80px);
}

.gv-head__title {
  color: var(--gv-text);
}

/* Sottotitolo della sezione: testo corrente, largo quanto la misura e con le righe
   bilanciate, così non resta una parola sola in fondo. */
.gv-head__intro {
  max-width: var(--gv-measure);
  color: var(--gv-text-muted);
  text-wrap: balance;
}

/* Sui telefoni i paragrafi superano spesso le sei righe, oltre le quali Chrome non
   bilancia più e lascia l'a capo normale: pretty sistema almeno le ultime righe. */
@media (max-width: 639px) {
  .gv-head__intro,
  .gv-method__text,
  .gv-cta__text,
  .gv-faq__a,
  .gv-case__summary,
  .gv-case__text,
  .gv-projects__item .gv-projects__body {
    text-wrap: pretty;
  }
}

/* Occhiello sopra il titolo e nelle schede. Resta scritto come nel testo, in
   minuscolo e a larghezza normale: non il maiuscolo delle etichette. */
.gv-eyebrow {
  display: block;
  margin-bottom: var(--gv-space-4);
  font-weight: 400;
  font-stretch: 100%;
  text-transform: none;
  letter-spacing: 0;
  color: var(--gv-text-dim);
}

.gv-head__aside {
  flex: none;
  color: var(--gv-text-dim);
}

@media (min-width: 900px) {
  .gv-head__aside.gv-label {
    white-space: nowrap;
  }
}

/* =========================================================== 02 progetti */

/* Desktop: un solo riquadro bordato, lista a sinistra con righe separate da
   una linea, riquadro immagine a destra allineato alla lista. */
.gv-projects__frame {
  display: none;
}

.gv-projects__list {
  flex: 1 1 auto;
  min-width: 0;
  /* Stesso materiale della scheda proof: il velo sta dietro alla lista, l'anteprima
     resta piena perché ci va un'immagine. */
  background: var(--gv-frost-bg);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .gv-projects__list {
    -webkit-backdrop-filter: var(--gv-frost-filter);
    backdrop-filter: var(--gv-frost-filter);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .gv-projects__list {
    background: var(--gv-surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

.gv-projects__item {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gv-space-3);
  padding-block: var(--gv-space-5);
  padding-inline: clamp(20px, 2.4vw, 40px);
  text-align: left;
  border-top: var(--gv-border) solid var(--gv-line-mid);
  transition: background-color var(--gv-dur-hover) var(--gv-ease);
}

.gv-projects__item:first-child {
  border-top: 0;
}

.gv-projects__item:hover {
  background: rgba(255, 255, 255, 0.035);
}

/* Testata della riga: cliente e tag a sinistra, il numero a destra alla stessa
   altezza. */
.gv-projects__item-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gv-space-4);
}

.gv-projects__item-id {
  display: grid;
  gap: 10px;
  min-width: 0;
}

.gv-projects__item-name {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-label);
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-faint);
  transition: color var(--gv-dur-hover) var(--gv-ease);
}

.gv-projects__item-tag {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  line-height: var(--gv-leading-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-ghost);
  transition: color var(--gv-dur-hover) var(--gv-ease);
}

.gv-projects__item[data-active="true"] .gv-projects__item-name {
  color: var(--gv-text);
}

.gv-projects__item[data-active="true"] .gv-projects__item-tag {
  color: var(--gv-text-muted);
}

/* Il numero è il dato che conta: il valore al corpo dei titoli delle voci, l'unità in
   etichetta sotto, tutti e due allineati a destra. Nella riga accesa il valore prende
   l'ultravioletto. Senza numero il campo si chiude e il nome prende la riga. */
.gv-projects__number {
  display: grid;
  justify-items: end;
  gap: var(--gv-space-2);
  flex: none;
  max-width: 50%;
  text-align: right;
}

.gv-projects__number:empty {
  display: none;
}

.gv-projects__number-value {
  font-weight: 500;
  font-size: var(--gv-type-stat);
  line-height: var(--gv-leading-none);
  letter-spacing: var(--gv-type-stat-tracking);
  white-space: nowrap;
  color: var(--gv-text);
}

.gv-projects__number-unit {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  line-height: var(--gv-leading-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-muted);
}

.gv-projects__body {
  display: block;
  font-size: var(--gv-type-body);
  line-height: var(--gv-leading-body);
  color: var(--gv-text-muted);
  text-wrap: pretty;
}

/* Nella lista desktop la riga non selezionata si spegne tutta insieme, come il
   nome; quella selezionata si riaccende. */
.gv-projects__item .gv-projects__number-value,
.gv-projects__item .gv-projects__number-unit,
.gv-projects__item .gv-projects__body {
  color: var(--gv-text-faint);
  transition: color var(--gv-dur-hover) var(--gv-ease);
}

.gv-projects__item .gv-projects__number-unit {
  color: var(--gv-text-ghost);
}

.gv-projects__item .gv-projects__body {
  max-width: var(--gv-measure);
  text-wrap: balance;
}

.gv-projects__item[data-active="true"] .gv-projects__number-value {
  color: var(--gv-accent);
}

.gv-projects__item[data-active="true"] .gv-projects__number-unit,
.gv-projects__item[data-active="true"] .gv-projects__body {
  color: var(--gv-text-muted);
}

/* Avanzamento della rotazione: una linea sul bordo basso della riga accesa che si
   riempie nel tempo di permanenza. Con il puntatore o il focus sulla lista si
   ferma dove si trova; con il movimento ridotto la rotazione non c'è. */
.gv-projects__item::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--gv-text-dim);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
}

[data-autoplay="on"] .gv-projects__item[data-active="true"]::after {
  animation: gv-project-progress var(--gv-project-hold, 6000ms) linear forwards;
}

[data-autoplay="on"][data-autoplay-paused="true"] .gv-projects__item[data-active="true"]::after {
  animation-play-state: paused;
}

@keyframes gv-project-progress {
  to {
    transform: scaleX(1);
  }
}

.gv-projects__preview {
  flex: none;
  width: clamp(380px, 38vw, 580px);
  border-left: var(--gv-border) solid var(--gv-line-mid);
  position: relative;
  overflow: hidden;
  background: var(--gv-surface);
}

/* Uno spazio media per progetto, uno sopra l'altro: si accende quello della riga
   attiva, in dissolvenza. Immagini e video riempiono il riquadro. */
.gv-projects__media {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--gv-dur-ui) var(--gv-ease);
}

.gv-projects__media[data-active="true"] {
  opacity: 1;
}

.gv-projects__media img,
.gv-projects__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Loghi: interi, con aria intorno, invece che ritagliati. */
.gv-projects__media img[data-fit="contain"] {
  object-fit: contain;
  padding: 12%;
}

/* Mobile: griglia, immagine sopra e metadati sotto, stesso ordine della lista. */
.gv-projects__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gv-space-6) var(--gv-gutter);
}

/* Con numero e testo nelle schede due colonne sui telefoni sono troppo strette:
   una colonna fino a 640px. */
@media (max-width: 639px) {
  .gv-projects__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Su mobile l'intera scheda porta alla pagina del progetto. */
.gv-projects__card {
  display: block;
}

.gv-projects__card-media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--gv-surface);
  border: var(--gv-border) solid var(--gv-line);
}

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

.gv-projects__card-meta {
  display: grid;
  gap: 8px;
  padding-top: var(--gv-space-3);
}

/* Nelle schede il numero sta sotto il tag, allineato a sinistra, con valore e unità
   sulla stessa riga quando c'entrano. Le schede sono tutte accese. */
.gv-projects__card .gv-projects__number {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px var(--gv-space-2);
  max-width: none;
  margin-top: var(--gv-space-2);
  text-align: left;
}

.gv-projects__card .gv-projects__number-value {
  color: var(--gv-accent);
}

.gv-projects__card .gv-projects__number:empty {
  display: none;
}

@media (min-width: 1000px) {
  .gv-projects__frame {
    display: flex;
    align-items: stretch;
    border: var(--gv-border) solid var(--gv-line-mid);
  }

  .gv-projects__grid {
    display: none;
  }
}

/* Segnaposto: è un segnaposto e si vede che lo è. */
.gv-placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--gv-space-4);
  text-align: center;
  color: var(--gv-text-ghost);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  line-height: var(--gv-leading-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  background: repeating-linear-gradient(
    -45deg,
    transparent 0 12px,
    rgba(255, 255, 255, 0.025) 12px 13px
  );
  transition: opacity var(--gv-dur-ui) var(--gv-ease);
}

/* ============================================================= 03 metodo */

.gv-method {
  min-height: calc(100svh - var(--gv-nav-height));
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(28px, 3.6vw, 56px);
  padding-top: var(--gv-space-9);
  padding-bottom: var(--gv-space-9);
}

.gv-method__lower {
  display: flex;
  flex-direction: column;
  gap: var(--gv-space-8);
}

/* Un solo blocco raccolto: testo corrente alla misura, niente capoversi. */
.gv-method__text {
  max-width: var(--gv-measure);
  color: var(--gv-text-muted);
  text-wrap: balance;
}

/* Dove lavoriamo: riga singola al corpo delle etichette, scritta come nel testo, come
   la microcopy sotto la CTA. Nessun titolo. */
.gv-method__geo {
  font-weight: 400;
  font-stretch: 100%;
  text-transform: none;
  letter-spacing: 0;
  color: var(--gv-text-dim);
}

/* Testo e scheda partono dalla stessa altezza. */
@media (min-width: 900px) {
  .gv-method__lower {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--gv-space-10);
  }
}

/* Scheda risultati: quadrata, frost, a destra del testo. Scorre fra voci con i due
   controlli, senza rotazione automatica. */
.gv-proof {
  flex: none;
  width: 100%;
  max-width: 520px;
  aspect-ratio: 1;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--gv-space-4);
  padding: var(--gv-space-5);
}

.gv-proof__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gv-space-3);
  padding-bottom: var(--gv-space-3);
  border-bottom: var(--gv-border) solid var(--gv-line-mid);
  color: var(--gv-text-dim);
}

.gv-proof__head .gv-eyebrow {
  margin-bottom: 0;
}

.gv-proof__controls {
  display: flex;
  gap: var(--gv-space-2);
}

.gv-proof__btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: var(--gv-border) solid var(--gv-line-strong);
  border-radius: 0;
  color: var(--gv-text-muted);
  transition: var(--gv-transition-hover);
}

.gv-proof__btn:hover:not(:disabled) {
  color: var(--gv-text);
  border-color: var(--gv-text-dim);
}

.gv-proof__btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.gv-proof__track {
  display: flex;
  overflow: hidden;
}

.gv-proof__item {
  flex: 0 0 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--gv-space-3);
  transition: opacity var(--gv-dur-ui) var(--gv-ease);
}

/* La voce: come il titolo di una scheda. */
.gv-proof__caption {
  font-size: var(--gv-type-title);
  font-weight: 500;
  line-height: var(--gv-leading-title);
  letter-spacing: var(--gv-type-title-tracking);
  color: var(--gv-text);
}

.gv-proof__count {
  color: var(--gv-text-ghost);
}

@media (min-width: 640px) {
  .gv-proof {
    width: clamp(320px, 36vw, 520px);
  }
}

/* Come funziona, sezione a sé dopo il metodo. Stesse colonne delle schede servizi e
   recensioni: una sotto l'altra sui telefoni, due per due da 640px, in fila da
   1200px. Sono passaggi in sequenza, si leggono tutti insieme: nessun carosello,
   nessun raggio, nessuna animazione. */
.gv-steps__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gv-gutter);
}

.gv-steps__item {
  display: flex;
  flex-direction: column;
  gap: var(--gv-space-3);
  padding: var(--gv-space-5);
}

@media (min-width: 640px) {
  .gv-steps__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1200px) {
  .gv-steps__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ============================================================ 04 servizi */

/* Card alla Leviathan: media arrotondato dentro una scheda arrotondata, titolo
   e descrizione sotto, nessuna freccia. La fila esce dallo schermo a destra. */
.gv-cards {
  display: flex;
  gap: var(--gv-gutter);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--gv-pad);
  padding-inline: var(--gv-pad);
  margin-inline: calc(var(--gv-pad) * -1);
  padding-bottom: var(--gv-space-2);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.gv-cards::-webkit-scrollbar {
  display: none;
}

.gv-card {
  flex: 0 0 clamp(272px, 30vw, 460px);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  padding: 14px;
  transition: border-color var(--gv-dur-hover) var(--gv-ease);
}

.gv-card:hover {
  border-color: var(--gv-line-strong);
}

.gv-card__media {
  background: rgba(255, 255, 255, 0.02);
}

.gv-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

.gv-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* MVP: immagini statiche in bianco e nero. */
  filter: grayscale(1);
}

/* Il corpo riempie la scheda: con testi di lunghezza diversa i collegamenti
   restano allineati in fondo, come vuole il margin-top: auto dell'azione. */
.gv-card__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: var(--gv-space-5) 10px var(--gv-space-3);
}

/* Titolo della voce: schede servizio, passaggi, domande. */
.gv-card__title {
  font-size: var(--gv-type-title);
  font-weight: 500;
  line-height: var(--gv-leading-title);
  letter-spacing: var(--gv-type-title-tracking);
  color: var(--gv-text);
}

.gv-card__desc {
  font-size: var(--gv-type-body);
  line-height: var(--gv-leading-body);
  color: var(--gv-text-muted);
  text-wrap: pretty;
}

.gv-card__action {
  margin-top: auto;
  padding-top: var(--gv-space-4);
  align-self: start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-muted);
  border-bottom: var(--gv-border) solid var(--gv-line-strong);
  padding-bottom: 6px;
}

.gv-card__action:hover {
  color: var(--gv-text);
  border-color: var(--gv-text-dim);
}

/* Recensioni: stessa scheda, contenuto diverso. */
.gv-card--quote {
  justify-content: flex-start;
  padding: var(--gv-space-5);
  gap: var(--gv-space-4);
  min-height: clamp(340px, 32vw, 440px);
}

.gv-card__rating {
  color: var(--gv-text-dim);
}

/* La citazione è testo corrente, pieno: in quattro colonne un titolo non ci starebbe. */
.gv-card__quote {
  margin: 0;
  font-size: var(--gv-type-body);
  line-height: var(--gv-leading-body);
  color: var(--gv-text);
}

.gv-card__meta {
  margin-top: auto;
  display: grid;
  gap: 6px;
  color: var(--gv-text-dim);
}

/* Nella recensione il fondo lo tengono i metadati; il collegamento li segue. */
.gv-card--quote .gv-card__action {
  margin-top: 0;
}

.gv-card__action[aria-disabled="true"] {
  cursor: default;
  pointer-events: none;
}

.gv-carousel__controls {
  display: flex;
  align-items: center;
  gap: var(--gv-space-3);
  margin-top: var(--gv-space-6);
}

.gv-carousel__count {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-ghost);
  margin-right: auto;
}

.gv-carousel__btn {
  display: grid;
  place-items: center;
  width: var(--gv-touch);
  height: var(--gv-touch);
  border: var(--gv-border) solid var(--gv-line-strong);
  color: var(--gv-text-muted);
  transition: var(--gv-transition-hover);
}

.gv-carousel__btn:hover:not(:disabled) {
  color: var(--gv-text);
  border-color: var(--gv-text-dim);
}

.gv-carousel__btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Da 640px le quattro schede stanno tutte nello schermo, centrate: due per due, e
   da 1200px in fila. Colonne uguali dentro il padding della pagina, quindi il
   margine a sinistra e a destra è sempre lo stesso. Il carosello, con i suoi
   controlli, resta solo sui telefoni. */
@media (min-width: 640px) {
  .gv-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    overflow: visible;
    scroll-snap-type: none;
    margin-inline: 0;
    padding-inline: 0;
    padding-bottom: 0;
  }

  [data-carousel] .gv-carousel__controls {
    display: none;
  }
}

@media (min-width: 1200px) {
  .gv-cards {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* =========================================================== 05 confronto */

/* La tabella sta dentro una scheda dello stesso materiale delle altre. Il colore di
   Gravity è uno solo, ricavato dall'accento e steso sopra il frost: un velo uniforme
   per la superficie e una linea più piena per il divisorio. */
.gv-compare__panel {
  --gv-compare-tint: color-mix(in srgb, var(--gv-accent) 11%, transparent);
  --gv-compare-divider: color-mix(in srgb, var(--gv-accent) 55%, var(--gv-line-mid));
  padding: var(--gv-space-5) var(--gv-space-5) var(--gv-space-3);
}

.gv-compare__table {
  display: none;
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.gv-compare__table th,
.gv-compare__table td {
  text-align: left;
  vertical-align: top;
  padding: var(--gv-space-5) var(--gv-space-4);
  border-top: var(--gv-border) solid var(--gv-line-mid);
  font-size: var(--gv-type-body);
  font-weight: 400;
  line-height: var(--gv-leading-body);
  color: var(--gv-text-muted);
}

/* Intestazioni chiare come il testo, tutte sulla stessa riga di base. */
.gv-compare__table thead th {
  padding-block: 0 var(--gv-space-4);
  border-top: 0;
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text);
}

.gv-compare__table tbody th {
  color: var(--gv-text);
  font-weight: 500;
}

/* La colonna Gravity: testo pieno, lo stesso velo su tutta la superficie e un
   divisorio verticale che la separa dalle altre. */
.gv-compare__col--gravity {
  color: var(--gv-text) !important;
}

/* Da 1000px la tabella occupa il pannello fino ai bordi e il margine interno passa
   alle celle, con il testo dove stava prima. Così la colonna Gravity arriva al bordo
   alto, basso e destro della scheda e il divisorio la attraversa tutta. */
@media (min-width: 1000px) {
  .gv-compare__panel {
    padding: 0;
  }

  .gv-compare__table thead th {
    padding-top: var(--gv-space-5);
  }

  .gv-compare__table th:first-child,
  .gv-compare__table td:first-child {
    padding-left: calc(var(--gv-space-5) + var(--gv-space-4));
  }

  .gv-compare__table th:last-child,
  .gv-compare__table td:last-child {
    padding-right: calc(var(--gv-space-5) + var(--gv-space-4));
  }

  .gv-compare__table tbody tr:last-child > * {
    padding-bottom: calc(var(--gv-space-5) + var(--gv-space-3));
  }

  .gv-compare__table .gv-compare__col--gravity {
    background: var(--gv-compare-tint);
    border-left: var(--gv-border) solid var(--gv-compare-divider);
  }
}

.gv-compare__cards {
  display: grid;
  gap: var(--gv-space-8);
}

@media (max-width: 999px) {
  .gv-compare__panel {
    padding: var(--gv-space-4);
  }
}

.gv-compare__criterion {
  display: grid;
  gap: var(--gv-space-3);
  padding-top: var(--gv-space-6);
  border-top: var(--gv-border) solid var(--gv-line-mid);
}

.gv-compare__criterion-name {
  font-size: var(--gv-type-title);
  font-weight: 500;
  line-height: var(--gv-leading-title);
  letter-spacing: var(--gv-type-title-tracking);
}

.gv-compare__option {
  display: grid;
  gap: 8px;
}

.gv-compare__option-label {
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text);
}

.gv-compare__option-value {
  padding: var(--gv-space-3);
  border: var(--gv-border) solid var(--gv-line);
  background: rgba(255, 255, 255, 0.02);
  color: var(--gv-text-muted);
}

/* Sui telefoni lo stesso velo e lo stesso divisorio, dentro la risposta di Gravity. */
.gv-compare__option--gravity .gv-compare__option-value {
  border-left: 2px solid var(--gv-compare-divider);
  background: var(--gv-compare-tint);
  color: var(--gv-text);
}

@media (min-width: 1000px) {
  .gv-compare__table {
    display: table;
  }

  .gv-compare__cards {
    display: none;
  }
}

/* ============================================================ domande
   Stesso materiale e stessi angoli di "Come funziona". Accordion nativo con
   <details>: le risposte restano nell'HTML servito anche a domanda chiusa.
   Il titolo sta sopra e le domande occupano tutta la larghezza del contenuto,
   con lo stesso margine ai due lati. */

.gv-faq__list {
  display: grid;
  gap: var(--gv-gutter);
}

/* La domanda resta un blocco normale: niente flex sul <summary>, che alcuni motori
   ignorano, e nessun marcatore nativo in nessun browser. Il segno sta a destra, in
   un posto riservato dal padding. */
.gv-faq__q {
  position: relative;
  display: block;
  padding: var(--gv-space-5);
  padding-right: calc(var(--gv-space-5) + var(--gv-space-4) + var(--gv-type-title));
  cursor: pointer;
  list-style: none;
}

.gv-faq__q::-webkit-details-marker {
  display: none;
}

.gv-faq__q::marker {
  content: "";
}

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

/* + allineato alla prima riga della domanda, al corpo della domanda. Aprendo ruota di
   un quarto di giro e diventa =, nello stesso tempo in cui si apre la risposta. */
.gv-faq__toggle {
  position: absolute;
  top: var(--gv-space-5);
  right: var(--gv-space-5);
  display: grid;
  place-items: center;
  width: var(--gv-type-title);
  height: calc(var(--gv-type-title) * var(--gv-leading-title));
  font-size: var(--gv-type-title);
  font-weight: 400;
  line-height: var(--gv-leading-none);
  color: var(--gv-text);
}

.gv-faq__toggle::before,
.gv-faq__toggle::after {
  grid-area: 1 / 1;
  transition: transform var(--gv-dur-ui) var(--gv-ease), opacity var(--gv-dur-ui) var(--gv-ease);
}

.gv-faq__toggle::before {
  content: "+";
}

.gv-faq__toggle::after {
  content: "=";
  opacity: 0;
  transform: rotate(-90deg);
}

/* Senza script vale [open]. Con lo script vale data-expanded, che cambia subito al
   clic mentre l'altezza si muove ancora. */
.gv-faq__item[open]:not([data-expanded]) .gv-faq__toggle::before,
.gv-faq__item[data-expanded="true"] .gv-faq__toggle::before {
  opacity: 0;
  transform: rotate(90deg);
}

.gv-faq__item[open]:not([data-expanded]) .gv-faq__toggle::after,
.gv-faq__item[data-expanded="true"] .gv-faq__toggle::after {
  opacity: 1;
  transform: rotate(0deg);
}

/* La risposta arriva alla stessa linea della griglia dei sottotitoli: alla misura si
   aggiunge il margine interno sinistro della scheda. */
.gv-faq__a {
  max-width: calc(var(--gv-measure) + var(--gv-space-5));
  padding: 0 var(--gv-space-5) var(--gv-space-5);
  text-wrap: balance;
}

/* Sui telefoni la scheda stringe il suo margine interno: alla domanda resta più riga. */
@media (max-width: 639px) {
  .gv-faq__q {
    padding: var(--gv-space-4);
    padding-right: calc(var(--gv-space-4) + var(--gv-space-3) + var(--gv-type-title));
  }

  .gv-faq__toggle {
    top: var(--gv-space-4);
    right: var(--gv-space-4);
  }

  .gv-faq__a {
    padding: 0 var(--gv-space-4) var(--gv-space-4);
  }
}

/* ================================================================ 06 CTA */

.gv-cta {
  min-height: calc(100svh - var(--gv-nav-height));
  padding-bottom: var(--gv-space-9);
  padding-inline: var(--gv-pad);
  display: grid;
  align-content: start;
  justify-items: center;
  gap: clamp(40px, 5vw, 72px);
  text-align: center;
}

.gv-cta__text {
  max-width: var(--gv-measure);
  color: var(--gv-text-muted);
  text-wrap: balance;
}

/* Stesso bottone dell'hero e stesso peso: sotto i 900px, dove quello dell'hero
   prende tutta la larghezza, la prende anche questo. */
@media (max-width: 899px) {
  .gv-cta__contact,
  .gv-cta__contact .gv-btn-solid {
    width: 100%;
  }
}

/* Microcopy sotto il bottone: scritta come nel testo, in minuscolo, con indirizzo
   e telefono chiari e sottolineati. Stesso trattamento della nota che stava sotto
   la CTA dell'hero. */
.gv-cta__note {
  display: grid;
  gap: 6px;
  font-weight: 400;
  font-stretch: 100%;
  text-transform: none;
  letter-spacing: 0;
  color: var(--gv-text-dim);
}

.gv-cta__note a {
  color: var(--gv-text);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
}

/* ======================================================== pagina progetto
   Stessi token e componenti della home. La sintesi sta in cima, in un riquadro
   frost: è il pezzo che un assistente estrae per primo. Da 1000px ogni blocco
   tiene il titolo a sinistra e il contenuto a destra, sempre sulla stessa colonna. */

.gv-case {
  display: grid;
  gap: var(--gv-space-8);
  padding-top: var(--gv-section-top);
  padding-bottom: var(--gv-section-bottom);
}

.gv-case__intro {
  display: grid;
  justify-items: start;
  gap: var(--gv-space-5);
}

.gv-case__summary {
  max-width: var(--gv-measure);
  padding: var(--gv-space-5);
  color: var(--gv-text);
  text-wrap: balance;
}

.gv-case__meta {
  color: var(--gv-text-dim);
}

.gv-case__row {
  display: grid;
  gap: var(--gv-space-4);
}

.gv-case__label {
  font-size: var(--gv-type-title);
  font-weight: 500;
  line-height: var(--gv-leading-title);
  letter-spacing: var(--gv-type-title-tracking);
  color: var(--gv-text);
}

.gv-case__text {
  max-width: var(--gv-measure);
  color: var(--gv-text-muted);
  text-wrap: balance;
}

/* Il risultato: numero grande al corpo dei titoli di sezione. Senza numero si chiude. */
.gv-case__number {
  margin-bottom: var(--gv-space-4);
  color: var(--gv-text);
}

.gv-case__number:empty {
  display: none;
}

.gv-case__quote {
  margin: 0;
  padding: var(--gv-space-5);
}

.gv-case__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--gv-surface);
  border: var(--gv-border) solid var(--gv-line);
}

@media (min-width: 900px) {
  .gv-case {
    gap: var(--gv-space-10);
  }
}

@media (min-width: 1000px) {
  .gv-case__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    gap: var(--gv-space-8);
    align-items: start;
  }

  /* Blocchi senza titolo: il contenuto resta nella colonna di destra. */
  .gv-case__row > :only-child {
    grid-column: 2;
  }
}

/* ============================================================= 07 footer */

.gv-footer {
  position: relative;
  z-index: 1;
  border-top: var(--gv-border) solid var(--gv-line);
  padding-block: var(--gv-space-10) var(--gv-space-7);
}

/* Il marchio sta al centro. Le due parti del lockup ufficiale sono ritagliate dallo
   stesso file, alla stessa scala e nella stessa posizione: non viene ricomposto,
   viene solo deciso quale metà si vede. Il simbolo occupa 221 dei 676 del lockup. */
.gv-footer__brand {
  display: flex;
  justify-content: center;
  margin-bottom: var(--gv-space-10);
}

.gv-footer__logo {
  position: relative;
  display: block;
  width: 260px;
  max-width: 70vw;
  aspect-ratio: 676 / 218;
}

.gv-footer__word {
  position: absolute;
  inset: 0;
  background-color: var(--gv-text);
  -webkit-mask: url("../assets/brand/Gravity_logo_wordmark_black.svg") no-repeat center / contain;
  mask: url("../assets/brand/Gravity_logo_wordmark_black.svg") no-repeat center / contain;
  clip-path: inset(0 0 0 32.7%);
}

.gv-footer__glyph {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 32.7%;
}

.gv-footer__symbol {
  position: absolute;
  inset: 0;
  background-color: var(--gv-text);
  -webkit-mask: url("../assets/brand/gravity_hypercube_black.svg") no-repeat center / contain;
  mask: url("../assets/brand/gravity_hypercube_black.svg") no-repeat center / contain;
  transition: opacity 280ms var(--gv-ease);
}

.gv-footer__loader {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity 280ms var(--gv-ease);
  pointer-events: none;
}

.gv-footer__loader svg {
  width: 100%;
  height: 100%;
}

[data-footer-logo][data-loading="true"] .gv-footer__symbol {
  opacity: 0;
}

[data-footer-logo][data-loading="true"] .gv-footer__loader {
  opacity: 1;
}

/* Una sola fascia sotto il marchio: sito, contatto, social e dati dell'azienda, ognuno
   una volta sola, tutto in mono piccolo maiuscolo. Una colonna sui telefoni; dal
   tablet tre colonne con l'azienda sotto, a tutta larghezza; da 1200px tutto su una
   riga, con l'azienda larga il doppio perché le sue righe restino intere. */
.gv-footer__band {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gv-space-6) var(--gv-gutter);
  padding-top: var(--gv-space-6);
  border-top: var(--gv-border) solid var(--gv-line);
}

.gv-footer__col h2 {
  margin-bottom: var(--gv-space-3);
  font-size: var(--gv-type-small);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-dim);
}

/* Tutte le righe allo stesso passo, con o senza collegamento: le colonne restano
   allineate riga per riga. */
.gv-footer__col li {
  padding-block: calc(var(--gv-space-1) / 2);
  font-weight: 500;
  font-stretch: var(--gv-type-label-stretch);
  font-size: var(--gv-type-small);
  line-height: var(--gv-leading-label);
  text-transform: uppercase;
  letter-spacing: var(--gv-type-label-tracking);
  color: var(--gv-text-muted);
}

/* L'area del collegamento sborda sopra e sotto senza spostare il testo: si tocca anche
   col dito. */
.gv-footer__col a {
  display: inline-block;
  padding-block: var(--gv-space-1);
  margin-block: calc(var(--gv-space-1) * -1);
}

.gv-footer__col a:hover {
  color: var(--gv-text);
}

@media (min-width: 640px) {
  .gv-footer__band {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .gv-footer__col--azienda {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1200px) {
  .gv-footer__band {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .gv-footer__col--azienda {
    grid-column: span 2;
  }
}

@media (min-width: 900px) {
  .gv-footer__logo {
    width: 300px;
  }
}
