/* ==========================================================================
   BUGLIONE YACHT BUILDER — MOVIMENTO (strato comune a tutte le pagine)

   Le sequenze grandi (hero, tre parole, anatomia, film, andature) hanno i
   loro file. Qui sta il resto: il linguaggio di movimento di tutto il sito,
   scritto una volta sola, cosi' che catalogo, contatti, ISTANTE 58', footer,
   bottoni e menu parlino come la home.

   Tre regole, le stesse del manuale:
     - un solo angolo: ogni taglio che si apre o si chiude e' a 30 gradi;
     - un solo tempo: le cose escono da sotto una linea, non appaiono dal nulla;
     - nessuna ginnastica: niente rimbalzi, niente elementi che inseguono il
       cursore per tutta la pagina. Chi compra una barca di quattordici metri
       non va intrattenuto, va accompagnato.

   Tutte le classi .mv-* le mette movimento.js. Senza JS non c'e' niente da
   nascondere, quindi niente resta invisibile. Si appoggia ai token di
   style.css e va caricato per ultimo.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. LA TENDINA FRA LE PAGINE

   Un pannello navy con i bordi rossi attraversa lo schermo inclinato a 30
   gradi: entra da destra quando si lascia una pagina, esce a sinistra quando
   si arriva nella successiva. Sta su body::before perche' deve coprire la
   pagina GIA' al primo disegno: la classe d'arrivo la mette uno script di una
   riga nell'head, prima che esista qualunque altra cosa.

   Il pannello e' piu' largo dello schermo di tan(30)·altezza, altrimenti
   l'inclinazione lascerebbe scoperti gli angoli.
   -------------------------------------------------------------------------- */
body::before {
  content: "";
  position: fixed; z-index: 10000; top: 0; bottom: 0;
  left: calc(-0.3 * 100vh);
  width: calc(100vw + 0.6 * 100vh);
  background: var(--navy);
  border-inline: 6px solid var(--rosso);
  transform: translateX(calc(100vw + 0.7 * 100vh)) skewX(var(--shear));
  pointer-events: none;
  visibility: hidden;
}
html.mv-leaving body::before {
  visibility: visible;
  transform: translateX(0) skewX(var(--shear));
  transition: transform .56s cubic-bezier(.7, 0, .3, 1), visibility 0s;
}
html.mv-arrive body::before {
  visibility: visible;
  animation: mv-curtain-out .85s cubic-bezier(.7, 0, .2, 1) .08s both;
}
@keyframes mv-curtain-out {
  from { transform: translateX(0) skewX(var(--shear)); }
  to   { transform: translateX(calc(-100vw - 0.7 * 100vh)) skewX(var(--shear)); }
}

/* --------------------------------------------------------------------------
   1. IL MENU
   Si ritira quando si scende e torna appena si risale: la pagina guadagna
   l'altezza di una riga proprio mentre la si sta leggendo. Sotto, un filetto
   rosso dice quanto della pagina e' gia' passato.
   -------------------------------------------------------------------------- */
.nav {
  transition: background var(--t-mid) var(--ease), backdrop-filter var(--t-mid),
              translate .55s var(--ease-out);
}
.nav.mv-hide { translate: 0 -100%; }

.mv-progress {
  position: absolute; left: 0; bottom: -1px; z-index: 2;
  width: 100%; height: 2px;
  background: var(--rosso);
  transform-origin: 0 50%;
  transform: scaleX(var(--mv-p, 0));
  pointer-events: none;
}

/* All'arrivo le voci del menu scendono in sequenza. Solo una volta. */
.mv-nav-in .nav__brand,
.mv-nav-in .nav__links > * {
  /* backwards e non both: finita l'entrata la voce deve tornare libera di
     spostarsi al passaggio del mouse, come prima */
  animation: mv-drop .8s var(--ease-out) backwards;
}
.mv-nav-in .nav__links > *:nth-child(1) { animation-delay: .12s; }
.mv-nav-in .nav__links > *:nth-child(2) { animation-delay: .18s; }
.mv-nav-in .nav__links > *:nth-child(3) { animation-delay: .24s; }
.mv-nav-in .nav__links > *:nth-child(4) { animation-delay: .30s; }
.mv-nav-in .nav__links > *:nth-child(5) { animation-delay: .38s; }
@keyframes mv-drop {
  from { opacity: 0; translate: 0 -14px; }
  to   { opacity: 1; translate: 0 0; }
}

/* --------------------------------------------------------------------------
   2. I TITOLI — riga per riga, da sotto la linea

   Ogni parola sta in una feritoia e sale; il ritardo lo decide la riga su cui
   la parola e' caduta (--l, lo misura il JS), non la sua posizione nella
   frase. Cosi' un titolo di due righe entra in due tempi, come si legge.
   Il margine negativo compensato lascia spazio agli accenti e al corsivo,
   che altrimenti la feritoia taglierebbe.
   -------------------------------------------------------------------------- */
.mv-w {
  display: inline-block; vertical-align: top;
  overflow: hidden;
  padding: .12em .08em .1em 0;
  margin: -.12em -.08em -.1em 0;
}
.mv-wi {
  display: inline-block;
  translate: 0 112%;
  transition: translate 1.05s var(--ease-out);
  transition-delay: calc(var(--l, 0) * 110ms + 60ms);
}
.mv-lines.is-in .mv-wi { translate: 0 0; }

/* --------------------------------------------------------------------------
   3. LE LETTERE — la stessa compressione delle tre parole in home

   Per i nomi dei modelli: la parola nasce sottile e larga e si stringe fino
   alla voce display del manuale. overflow-x: clip perche' a 125% di
   larghezza il nome esce dalla colonna, ed e' il punto di partenza.
   -------------------------------------------------------------------------- */
.mv-letters { overflow-x: clip; }
.mv-c {
  display: inline-block; vertical-align: top;
  overflow: hidden;
  padding-block: .2em .06em;
  margin-block: -.2em -.06em;
}
.mv-c > i {
  display: inline-block; font-style: inherit;
  font-variation-settings: "wght" 150, "wdth" 125;
  translate: 0 105%; opacity: 0;
  transition:
    font-variation-settings 1.15s var(--ease-out),
    translate .8s var(--ease-out),
    opacity .4s linear;
  transition-delay: calc(var(--i, 0) * 42ms);
}
.mv-letters.is-in .mv-c > i {
  font-variation-settings: "wght" var(--mv-wght, 800), "wdth" 62;
  translate: 0 0; opacity: 1;
}

/* --------------------------------------------------------------------------
   4. OCCHIELLI, FILETTI, MARCHIO
   Si aprono da sinistra. Un taglio e non uno spostamento: la riga accanto
   non si muove di un pixel.
   -------------------------------------------------------------------------- */
.mv-cut {
  clip-path: inset(0 100% 0 0);
  transition: clip-path .9s var(--ease-out);
}
.mv-cut.is-in { clip-path: inset(0 -1em 0 0); }

.mv-rule { transform-origin: 0 50%; scale: 0 1; transition: scale 1.3s var(--ease-out); }
.mv-rule.is-in { scale: 1 1; }

/* Il parallelogramma tricolore: le tre bande passano una dopo l'altra, e il
   taglio che le scopre e' inclinato come loro. */
.mv-mark {
  clip-path: polygon(0 0, 0 0, -60% 100%, -60% 100%);
  transition: clip-path 1.1s cubic-bezier(.7, 0, .2, 1) .1s;
}
.mv-mark.is-in { clip-path: polygon(0 0, 160% 0, 100% 100%, -60% 100%); }

/* --------------------------------------------------------------------------
   5. ELENCHI IN SEQUENZA
   Numeri, specifiche, sedi, colonne del footer, righe dei consumi: ogni voce
   un passo dopo la precedente. --i lo scrive il JS; il tetto a dodici passi
   evita che la sedicesima riga delle specifiche arrivi quando si e' gia'
   passati oltre.
   -------------------------------------------------------------------------- */
.mv-stagger > * {
  opacity: 0; translate: 0 18px;
  transition: opacity .7s var(--ease-out), translate .9s var(--ease-out);
  transition-delay: calc(min(var(--i, 0), 12) * 70ms);
}
.mv-stagger.is-in > * { opacity: 1; translate: 0 0; }

/* I numeri della fascia rossa: il filetto a 30 gradi cresce dal basso prima
   che il numero cominci a contare. */
.stats.mv-stagger > .stat::before {
  transform-origin: 50% 100%;
  scale: 1 0;
  transition: scale .9s var(--ease-out);
  transition-delay: inherit;
}
.stats.mv-stagger.is-in > .stat::before { scale: 1 1; }

/* Le specifiche: il filetto sotto ogni riga si traccia da sinistra. */
.specs.mv-stagger > div { position: relative; border-bottom-color: transparent; }
.specs.mv-stagger > div::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 1px; background: var(--rule);
  transform-origin: 0 50%; scale: 0 1;
  transition: scale 1.1s var(--ease-out);
  transition-delay: inherit;
}
.specs.mv-stagger.is-in > div::after { scale: 1 1; }

/* --------------------------------------------------------------------------
   6. FOTOGRAFIE — si aprono con un taglio a 30 gradi

   Il taglio attraversa l'immagine da sinistra; sotto, la foto parte piu'
   vicina e si allontana. Resta un filo ingrandita (1,08) per lasciare spazio
   alla parallasse senza scoprire i bordi.
   -------------------------------------------------------------------------- */
.mv-img {
  clip-path: polygon(0 0, 0 0, -43% 100%, -43% 100%);
  transition: clip-path 1.25s cubic-bezier(.7, 0, .2, 1);
}
.mv-img.is-in { clip-path: polygon(0 0, 143% 0, 100% 100%, -43% 100%); }
.mv-img img {
  scale: 1.2;
  transition: scale 1.9s var(--ease-out);
  will-change: translate;
}
.mv-img.is-in img { scale: 1.08; }
.card:hover .mv-img.is-in img { scale: 1.12; }

/* L'etichetta che segue il cursore sulla fotografia di una scheda. Vive solo
   dentro la fotografia e solo con un mouse: altrove sarebbe un gioco. */
.mv-link { cursor: pointer; }
.mv-tag {
  position: absolute; left: 0; top: 0; z-index: 3;
  pointer-events: none;
}
.mv-tag > span {
  display: block;
  translate: -50% -50%;
  transform: skewX(var(--shear)) scale(.6);
  padding: .85em 1.5em;
  background: var(--rosso); color: var(--navy);
  font-size: var(--fs-micro); font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
  opacity: 0;
  transition: opacity .3s var(--ease-out), transform .45s var(--ease-out);
}
.mv-tag > span > span { display: inline-block; transform: skewX(var(--shear-inv)); }
.mv-link:hover .mv-tag > span { opacity: 1; transform: skewX(var(--shear)) scale(1); }

/* --------------------------------------------------------------------------
   7. LO SCAFO CHE SI DISEGNA
   Il profilo tecnico sulle pagine del catalogo e di ISTANTE 58'. Prima era
   un <use>, e dentro un <use> Safari non applica pathLength: il tratteggio non
   copriva la linea e l'effetto era stato tolto. Ora il tracciato e' scritto
   direttamente nella pagina, dove pathLength funziona ovunque.
   -------------------------------------------------------------------------- */
.mv-hull path {
  /* in unita' del disegno, non in pixel: vector-effect avrebbe tenuto il
     tratto fisso a schermo, ma in alcuni browser cambia anche il conto del
     tratteggio e la linea non arriverebbe in fondo. Fra 560 e 1100 px di
     larghezza 1,6 unita' fanno fra 1 e 2 px. */
  stroke-width: 1.6;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  transition: stroke-dashoffset 2.8s cubic-bezier(.65, 0, .35, 1) .15s;
}
.mv-hull.is-in path { stroke-dashoffset: 0; }

/* --------------------------------------------------------------------------
   8. BOTTONI E LINK

   Il riempimento attraversa il bottone da sinistra con il suo bordo a 30
   gradi — il bottone e' gia' inclinato, quindi il bordo lo e' da se'. La
   freccia esce a destra e rientra da sinistra: un solo gesto, non un tremolio.
   -------------------------------------------------------------------------- */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn::before {
  content: ""; position: absolute; inset: -2px; z-index: -1;
  background: var(--mv-sweep, var(--lime));
  transform: translateX(-102%);
  transition: transform .55s var(--ease-out);
}
.btn:hover::before, .btn:focus-visible::before { transform: translateX(0); }
.btn--primary:hover { background: var(--rosso); }
.btn--ghost { --mv-sweep: color-mix(in srgb, currentColor 12%, transparent); }
.su-rosso .btn--ghost { --mv-sweep: rgba(0, 0, 102, .1); }

.btn:hover .btn__arrow { animation: mv-arrow .55s var(--ease-out); }
.link-arrow:hover svg { animation: mv-arrow .55s var(--ease-out); }
@keyframes mv-arrow {
  0%   { transform: translateX(0); opacity: 1; }
  45%  { transform: translateX(130%); opacity: 0; }
  46%  { transform: translateX(-130%); opacity: 0; }
  100% { transform: translateX(3px); opacity: 1; }
}

/* Il filetto dei link con freccia si ritira e si ridisegna. */
.link-arrow::after { transform-origin: 100% 50%; transition: scale .5s var(--ease-out), opacity var(--t-fast) var(--ease); }
.link-arrow:hover::after { opacity: 1; animation: mv-underline .7s var(--ease-out); }
@keyframes mv-underline {
  0%   { scale: 1 1; transform-origin: 100% 50%; }
  45%  { scale: 0 1; transform-origin: 100% 50%; }
  46%  { scale: 0 1; transform-origin: 0 50%; }
  100% { scale: 1 1; transform-origin: 0 50%; }
}

/* Link del footer e contatti diretti: il filetto a 30 gradi entra sotto. */
.footer nav a, .footer__bottom a, .contact-direct a { position: relative; }
.footer nav a::after, .footer__bottom a::after, .contact-direct a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: .55em;
  height: 1px; background: currentColor;
  transform: skewX(var(--shear)); transform-origin: 0 50%;
  scale: 0 1; transition: scale .45s var(--ease-out);
}
.contact-direct a::after { bottom: -.1em; height: 2px; }
.footer nav a:hover::after, .footer__bottom a:hover::after, .contact-direct a:hover::after { scale: 1 1; }

/* --------------------------------------------------------------------------
   9. IL MODULO
   Il campo attivo si sottolinea da sinistra in rosso, e la sua etichetta si
   accende: si vede dove si sta scrivendo senza cambiare la forma del campo.
   -------------------------------------------------------------------------- */
.field input, .field textarea, .field select {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 2px;
  transition: border-color var(--t-fast), background-color var(--t-fast), background-size .6s var(--ease-out);
}
.field input:focus, .field textarea:focus, .field select:focus { background-size: 100% 2px; }
.field > label { transition: color .35s var(--ease-out), translate .45s var(--ease-out); }
.field:focus-within > label { color: var(--accent); translate: .35em 0; }

/* --------------------------------------------------------------------------
   10. MOTO RIDOTTO
   Tutto al suo stato d'arrivo, senza transizioni. La tendina non c'e'.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  body::before { display: none; }
  .nav.mv-hide { translate: none; }
  .mv-nav-in .nav__brand, .mv-nav-in .nav__links > * { animation: none; }
  .mv-wi, .mv-c > i, .mv-stagger > *, .mv-img img {
    translate: none !important; opacity: 1 !important; transition: none !important;
  }
  .mv-c > i { font-variation-settings: "wght" var(--mv-wght, 800), "wdth" 62 !important; }
  .mv-cut, .mv-img, .mv-mark { clip-path: none !important; transition: none !important; }
  .mv-rule, .stats.mv-stagger > .stat::before, .specs.mv-stagger > div::after { scale: 1 1 !important; transition: none !important; }
  .mv-hull path { stroke-dashoffset: 0 !important; transition: none !important; }
  .btn::before { transition: none; }
  .btn:hover .btn__arrow, .link-arrow:hover svg, .link-arrow:hover::after { animation: none; }
}
