/* ===========================================================================
   Ecosistema Jora — jorasolution.it
   Apertura scura come il sito istituzionale Pigreco, corpo su carta crema,
   arancione Jora come unica voce d'accento.
   Token in :root: un colore o una misura si cambia in un punto solo.
   =========================================================================== */

:root {
  /* Superfici */
  --bg:          #faf8f5;   /* carta crema */
  --surface:     #f1ede7;   /* bande alternate */
  --card:        #ffffff;
  --dark:        #14100d;   /* nero caldo, non neutro */
  --dark-2:      #1e1813;

  /* Testo */
  --ink:         #191512;
  --ink-soft:    #57514a;
  --ink-faint:   #8b847b;
  --border:      rgba(25, 21, 18, 0.12);
  --border-soft: rgba(25, 21, 18, 0.08);

  /* Brand Jora — l'arancio è il colore primario. La scala esiste perché lo
     stesso arancione non può fare tutti i lavori: su fondo scuro brilla
     (8,5:1), sulla carta crema è a 2,2:1 e come testo non si legge. */
  --jora-orange:        #fe531f;   /* primario: riempimenti, tutto su fondo scuro */
  --jora-orange-bright: #fd9319;   /* arancio del logo: primo stop dei gradienti */
  --jora-orange-deep:   #d3430f;   /* segni grafici su fondo chiaro (4,3:1) */
  --jora-orange-hover:  #d3430f;
  --jora-orange-text:   #c43e0b;   /* testo piccolo su fondo chiaro (4,9:1) */
  --pigreco-blue:       #1f6fb2;   /* accento del partner, dal sito istituzionale */

  /* Testo su fondo scuro */
  --on-dark:       #f7f4f0;
  --on-dark-muted: rgba(247, 244, 240, 0.68);
  --on-dark-faint: rgba(247, 244, 240, 0.40);

  /* Layout */
  --maxw:      1140px;
  --pad-x:     3rem;
  --radius:    18px;

  /* Tipografia — Poppins, unica famiglia, auto-ospitata (pesi 400/500/600/700) */
  --font:         'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-display: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --h1:  clamp(38px, 6vw, 64px);
  --h2:  clamp(26px, 3.5vw, 38px);
  --h3:  clamp(20px, 2.2vw, 26px);
  --body: 17px;
  --lead: 20px;

  /* Curva unica: uscita esponenziale, mai lineare */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--ink);
  font-size: var(--body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, .jo-display { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.03em; line-height: 1.14; }
h1 { font-size: var(--h1); }
h2 { font-size: var(--h2); }
h3 { font-size: var(--h3); }

p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }

a { color: inherit; }
img, svg { max-width: 100%; }

/* Superfici del browser: anche quello che non disegno appartiene al progetto */
::selection { background: var(--jora-orange); color: #14100d; }
:root { accent-color: var(--jora-orange); caret-color: var(--jora-orange); }
* { scrollbar-color: rgba(25, 21, 18, 0.28) transparent; scrollbar-width: thin; }
:focus-visible { outline: 2px solid var(--jora-orange-text); outline-offset: 3px; border-radius: 3px; }
a:not([class]) { text-underline-offset: 0.22em; text-decoration-thickness: 1px; }

[id] { scroll-margin-top: 92px; }

/* Grana di carta: una texture sola, generata, su tutta la pagina */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------- Primitive */

.jo-section { max-width: var(--maxw); margin: 0 auto; padding: 7.5rem var(--pad-x); }
/* Il target e' una striscia di servizio, non un capitolo: respira meno. */
.jo-section--tight { padding-top: 5.5rem; padding-bottom: 5.5rem; }
.jo-band--surface { background: var(--surface); }
.jo-band--dark { background: var(--dark); color: var(--on-dark); }

.jo-lead { font-size: var(--lead); line-height: 1.65; color: var(--ink-soft); max-width: 34ch; }
.jo-body { color: var(--ink-soft); max-width: 68ch; }
.jo-accent { color: var(--jora-orange); }

/* Intestazione di sezione: titolo a sinistra, testo affiancato a destra.
   Nessuna etichetta sopra il titolo: il titolo si porta da solo. */
.jo-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 3rem;
  align-items: end;
}
.jo-head h2 { max-width: 22ch; }
.jo-head p { font-size: var(--lead); line-height: 1.6; color: var(--ink-soft); max-width: 42ch; }

/* Bottoni */
.jo-btn {
  display: inline-block;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  padding: 14px 28px;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.4s var(--ease), background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.jo-btn:hover { transform: translateY(-2px); }
.jo-btn--orange { background: var(--jora-orange); color: var(--on-dark) }
.jo-btn--orange:hover { background: var(--jora-orange-hover); }
.jo-btn--light { background: var(--on-dark); color: var(--dark); }
.jo-btn--light:hover { background: #fff; }
.jo-btn--outline-dark { background: transparent; color: var(--on-dark); border-color: rgba(247, 244, 240, 0.28); }
.jo-btn--outline-dark:hover { border-color: var(--on-dark); }
.jo-btn--outline { background: transparent; color: var(--ink); border-color: var(--border); }
.jo-btn--outline:hover { border-color: var(--ink); }

.jo-skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: #fff; padding: 10px 18px;
  border-radius: 0 0 8px 0; font-size: 13px; text-decoration: none;
}
.jo-skip-link:focus { left: 0; }

/* ---------------------------------------------------------------- Navbar */
/* Nera sempre: trasparente sopra l'hero, e allo scroll diventa la stessa
   superficie scura invece di passare alla carta crema. La barra resta un
   elemento del marchio su tutta la pagina, non un pezzo di sfondo che cambia
   colore a metà; e sopra le bande chiare il contrasto è massimo comunque. */

.jo-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  padding: 1.05rem var(--pad-x);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background 0.35s var(--ease), border-color 0.35s var(--ease), padding 0.35s var(--ease);
}
.jo-nav.is-scrolled {
  background: rgba(20, 16, 13, 0.92);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom-color: rgba(247, 244, 240, 0.10);
  padding-top: 0.8rem;
  padding-bottom: 0.8rem;
}

.jo-nav-logo { display: flex; align-items: center; gap: 11px; text-decoration: none; }
.jo-nav-logo img { display: block; height: 28px; width: auto; }
.jo-nav-wordmark {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 700; letter-spacing: 0.16em;
  color: var(--on-dark);
}

.jo-nav-menu { display: flex; align-items: center; gap: 2.5rem; }
.jo-nav-links { display: flex; gap: 2rem; }
/* Una pillola non va a capo: senza questo, fra 1000 e 1140px la CTA si spezzava
   su due righe e la barra cresceva di 38px. */
.jo-nav-cta { white-space: nowrap; }
.jo-nav-links a {
  position: relative;
  font-size: 15px;
  color: var(--on-dark-muted);
  text-decoration: none;
  transition: color 0.25s var(--ease);
}
.jo-nav-links a::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -6px;
  height: 1.5px;
  background: var(--jora-orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.45s var(--ease);
}
.jo-nav-links a:hover::after,
.jo-nav-links a.is-active::after { transform: scaleX(1); }
.jo-nav-links a:hover,
.jo-nav-links a.is-active { color: var(--jora-orange); }

.jo-nav-cta { font-size: 14px; padding: 10px 22px; }

.jo-nav-toggle {
  display: none;
  background: none; border: none; cursor: pointer;
  color: var(--on-dark); font-size: 26px; line-height: 1;
}

/* ------------------------------------------------------------------ Hero */

.jo-hero {
  position: relative;
  background: var(--dark);
  color: var(--on-dark);
  overflow: hidden;
  padding: 9.5rem 0 6.5rem;
}
/* Alone caldo: la luce viene dal motore dati */
.jo-hero::before {
  content: '';
  position: absolute;
  top: 8%; right: -6%;
  width: 780px; height: 780px;
  background: radial-gradient(circle, rgba(254, 83, 31, 0.26) 0%, rgba(254, 83, 31, 0.08) 42%, transparent 68%);
  pointer-events: none;
}
.jo-hero-inner {
  position: relative;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.98fr);
  gap: 2.5rem;
  align-items: center;
}
.jo-hero h1 { font-size: clamp(32px, 4.2vw, 52px); }
.jo-hero h1 em { font-style: normal; color: var(--jora-orange); }
.jo-hero-sub {
  margin-top: 1.75rem;
  font-size: var(--lead);
  line-height: 1.6;
  color: var(--on-dark-muted);
  max-width: 52ch;
}
.jo-hero-btns { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 2.5rem; }

.jo-hero-figure { margin-right: -2.5rem; }
.jo-hero-figure svg { width: 100%; height: auto; }

/* Il momento autoriale: le tracce si disegnano una volta, poi un impulso
   viaggia dal motore verso ciascun servizio. */
.jo-flow-line {
  stroke-dasharray: 300;
  stroke-dashoffset: 300;
  animation: jo-draw 1.5s var(--ease) forwards;
}
.jo-flow-line--2 { animation-delay: 0.12s; }
.jo-flow-line--3 { animation-delay: 0.24s; }
.jo-flow-line--4 { animation-delay: 0.36s; }
.jo-flow-line--5 { animation-delay: 0.48s; }
@keyframes jo-draw { to { stroke-dashoffset: 0; } }

.jo-pulse {
  offset-distance: 0%;
  animation: jo-pulse 4.6s linear infinite;
  opacity: 0;
}
.jo-pulse--1 { offset-path: path('M212 190 C 276 190, 288 44, 344 44'); animation-delay: 1.5s; }
.jo-pulse--2 { offset-path: path('M212 190 C 276 190, 288 117, 344 117'); animation-delay: 1.75s; }
.jo-pulse--3 { offset-path: path('M212 190 C 268 190, 288 190, 344 190'); animation-delay: 2s; }
.jo-pulse--4 { offset-path: path('M212 190 C 276 190, 288 263, 344 263'); animation-delay: 2.25s; }
.jo-pulse--5 { offset-path: path('M212 190 C 276 190, 288 336, 344 336'); animation-delay: 2.5s; }

/* In ingresso: ERP, Excel e cataloghi verso il motore. Stesso ciclo di 4,6s
   degli impulsi in uscita, ma occupa la prima metà: il dato arriva, il nodo
   lo assorbe, poi riparte normalizzato. */
.jo-pulse-in {
  offset-distance: 0%;
  opacity: 0;
  animation: jo-pulse-in 4.6s linear infinite;
}
.jo-pulse-in--2 { animation-delay: 0.22s; }
.jo-pulse-in--3 { animation-delay: 0.44s; }
.jo-pulse-in--1 { offset-path: path('M96 80 C 134 80, 142 190, 172 190'); }
.jo-pulse-in--2 { offset-path: path('M96 190 C 134 190, 142 190, 172 190'); }
.jo-pulse-in--3 { offset-path: path('M96 300 C 134 300, 142 190, 172 190'); }
@keyframes jo-pulse-in {
  0%   { offset-distance: 0%;   opacity: 0; }
  4%   { opacity: 0.85; }
  28%  { offset-distance: 100%; opacity: 0.85; }
  33%  { offset-distance: 100%; opacity: 0; }
  100% { offset-distance: 100%; opacity: 0; }
}
@keyframes jo-pulse {
  0%   { offset-distance: 0%;   opacity: 0; }
  4%   { opacity: 1; }
  34%  { offset-distance: 100%; opacity: 1; }
  40%  { offset-distance: 100%; opacity: 0; }
  100% { offset-distance: 100%; opacity: 0; }
}

.jo-node-core { animation: jo-breathe 4.6s ease-in-out infinite; transform-origin: 190px 190px; }
@keyframes jo-breathe {
  0%, 22%   { transform: scale(1); }
  32%       { transform: scale(1.13); }
  48%, 100% { transform: scale(1); }
}

/* --------------------------------------------------------- Il mercato */
/* Due fasce invece di due colonne piene: la prima porta titolo e premessa,
   la seconda tira fuori dal paragrafo la frase che decide tutto. Così la
   sezione occupa metà dell'altezza e nessuna colonna resta vuota. */

.jo-market { max-width: var(--maxw); margin: 0 auto; padding: 6rem var(--pad-x); }

.jo-market-top {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: 3.5rem;
  align-items: start;
}
.jo-market h2 { font-size: clamp(28px, 3.8vw, 42px); }
.jo-market-top p { font-size: 17px; line-height: 1.7; color: var(--ink-soft); max-width: 56ch; }

.jo-market-bottom {
  margin-top: 3.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--border);
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 3.5rem;
  align-items: start;
}
/* La frase che decide tutto non e' un paragrafo in mezzo agli altri: sta
   dietro un segno arancione che si disegna dall'alto quando la fascia entra in
   campo. E' l'unico movimento della sezione, e cade sulla riga giusta. */
.jo-market-pull { position: relative; padding-left: 1.6rem; }
.jo-market-pull::before {
  content: '';
  position: absolute;
  left: 0; top: 0.2em; bottom: 0.25em;
  width: 2px;
  border-radius: 1px;
  background: var(--jora-orange);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.9s var(--ease) 0.2s;
}
.jo-market-bottom.is-visible .jo-market-pull::before { transform: scaleY(1); }

.jo-market-kicker {
  font-size: 15px;
  color: var(--ink-faint);
  max-width: 40ch;
  margin-bottom: 1rem;
}
.jo-market-claim {
  font-family: var(--font-display);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.2;
  color: var(--ink);
  max-width: 26ch;
}
/* La seconda meta' della frase e' la conseguenza: la porta il colore, non un
   altro corpo tipografico. */
.jo-market-claim em { font-style: normal; color: var(--jora-orange-text); }
.jo-market-kicker strong { color: var(--ink); font-weight: 600; }
.jo-market-rest { font-size: 16px; line-height: 1.7; color: var(--ink-soft); max-width: 48ch; }

/* ---------------------------------------------------------------- Moduli */
/* Il mozzo. JORA PIM sta al centro geometrico e i cinque servizi gli stanno
   attorno su un'ellisse: la forma stessa dice che c'è un modulo che alimenta
   tutto il resto. I raggi vivono in un SVG con viewBox 1044x760 e le card sono
   posizionate in percentuale sullo stesso rapporto, quindi disegno e contenuto
   scalano insieme e i raggi cadono sempre sul bordo giusto.
   L'hero mostra il movimento in ingresso, questa sezione quello in uscita.
   Il collegamento non si vede tutto insieme: quando la sezione entra in campo
   c'e' solo il disco, poi ogni 1,8s si aggancia un servizio, una volta sola.
   Il tempo lo tiene hub.js, che scrive data-hub-step sul campo e mette is-on
   su chi porta data-hub-item: lo portano insieme la card, il suo raggio e il
   suo impulso. Curve, ritardi e direzioni di ingresso stanno qui.
   Il ritmo: 1,1s fra un servizio e l'altro, raggio in 0,5s e card in 0,45s
   con 0,12s di ritardo — la card arriva mentre il raggio finisce, e il
   collegamento successivo parte quando questo si e' appena assestato. */

.jo-solutions { max-width: var(--maxw); margin: 0 auto; padding: 8rem var(--pad-x); }
.jo-solutions-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 3rem;
  align-items: end;
  margin-bottom: 3.5rem;
}
.jo-solutions-head h2 { font-size: clamp(28px, 4vw, 44px); color: var(--on-dark); }
.jo-solutions-head p { font-size: var(--lead); line-height: 1.6; color: var(--on-dark-muted); max-width: 44ch; }

/* Il campo del diagramma: stesso rapporto del viewBox, così le percentuali
   delle card e le coordinate dei raggi restano allineate a ogni larghezza. */
.jo-hub {
  position: relative;
  /* L'altezza del campo e' il 73% della sua larghezza, quindi la larghezza e'
     anche il budget verticale: il tetto in vh tiene tutto il diagramma dentro
     lo schermo mentre la sequenza va, altrimenti le due card in basso si
     collegano fuori campo e non le vede nessuno. */
  max-width: min(100%, 96vh);
  margin: 0 auto;
  aspect-ratio: 1044 / 760;
}
.jo-hub-rays {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Il raggio si disegna dal centro verso fuori nel momento in cui il servizio
   si collega, poi resta vivo: una seconda animazione lo fa pulsare, sullo
   stesso ciclo di 4,6s degli impulsi. Due animazioni per raggio, quindi i
   ritardi sono coppie: il primo vale per il tracciato, il secondo per la
   pulsazione. Le pulsazioni restano sfalsate fra raggio e raggio, cosi' i
   cinque non respirano all'unisono. */
/* Il tratteggio che tiene il raggio invisibile vale solo a sequenza avviata:
   data-hub-step lo scrive hub.js al primo render. Senza JavaScript nessuna
   regola nasconde niente e il mozzo si legge completo. */
.jo-hub[data-hub-step] .jo-ray {
  stroke-dasharray: 160;
  stroke-dashoffset: 160;
}
.jo-ray.is-on {
  animation:
    jo-draw 0.5s var(--ease) forwards,
    jo-hub-ray 4.6s ease-in-out 1.6s infinite;
}
.jo-ray--2.is-on { animation-delay: 0s, 1.75s; }
.jo-ray--3.is-on { animation-delay: 0s, 1.9s; }
.jo-ray--4.is-on { animation-delay: 0s, 2.05s; }
.jo-ray--5.is-on { animation-delay: 0s, 2.2s; }

@keyframes jo-hub-ray {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

/* Gli impulsi: il dato che parte dal motore e arriva al servizio. Partono col
   collegamento, un attimo dopo il raggio: prima la linea, poi il dato che la
   percorre. Stesso ciclo di 4,6s dell'hero, così le due animazioni della
   pagina respirano insieme. */
.jo-ray-pulse { offset-distance: 0%; opacity: 0; }
.jo-ray-pulse.is-on { animation: jo-pulse 4.6s linear infinite; }
.jo-ray-pulse--1 { offset-path: path('M522 290 L522 205');        animation-delay: 1.2s; }
.jo-ray-pulse--2 { offset-path: path('M629 374.3 L770.8 340.2');  animation-delay: 1.45s; }
.jo-ray-pulse--3 { offset-path: path('M599.1 478.5 L659.1 539.6'); animation-delay: 1.7s; }
.jo-ray-pulse--4 { offset-path: path('M444.9 478.5 L384.9 539.6'); animation-delay: 1.95s; }
.jo-ray-pulse--5 { offset-path: path('M415 374.3 L273.2 340.2');  animation-delay: 2.2s; }

/* Il mozzo: disco arancione, unica superficie piena della pagina.
   220px sul viewBox da 1044 = 21,07%. */
.jo-hub-core {
  position: absolute;
  left: 50%;
  top: 52.63%;
  width: 21.07%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: linear-gradient(150deg, var(--jora-orange-bright) 0%, var(--jora-orange) 72%);
  color: #14100d;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1rem;
}
/* Il disco respira dall'inizio: allo scatto 0 e' l'unica cosa in campo e deve
   sembrare accesa, non in attesa. */
.jo-hub-core { animation: jo-hub-breathe 4.6s ease-in-out infinite; }

@keyframes jo-hub-breathe {
  0%, 100% { box-shadow: 0 0 40px 0 rgba(254, 83, 31, 0.18); }
  50%      { box-shadow: 0 0 72px 8px rgba(254, 83, 31, 0.32); }
}

/* E da' un colpo a ogni servizio che si aggancia. I keyframe sono due, -a e -b,
   alternati per parita' dello scatto: e' il cambio di nome che fa ripartire
   l'animazione: con un nome solo il browser la considera la stessa e non la
   riavvia al passaggio successivo. Il colpo e' una scala sulla proprieta'
   singola, che si compone col transform che centra il disco invece di
   sostituirlo. */
.jo-hub:is([data-hub-step="1"], [data-hub-step="3"], [data-hub-step="5"]) .jo-hub-core {
  animation:
    jo-hub-breathe 4.6s ease-in-out infinite,
    jo-hub-kick-a 0.6s var(--ease);
}
.jo-hub:is([data-hub-step="2"], [data-hub-step="4"]) .jo-hub-core {
  animation:
    jo-hub-breathe 4.6s ease-in-out infinite,
    jo-hub-kick-b 0.6s var(--ease);
}

@keyframes jo-hub-kick-a {
  0%, 100% { scale: 1; }
  45%      { scale: 1.04; }
}
@keyframes jo-hub-kick-b {
  0%, 100% { scale: 1; }
  45%      { scale: 1.04; }
}
.jo-hub-kicker {
  font-family: var(--font-display);
  font-size: clamp(9px, 0.85vw, 11px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(20, 16, 13, 0.62);
}
.jo-hub-name {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  font-size: clamp(19px, 2.2vw, 28px);
  margin: 0.3rem 0 0.15rem;
}
.jo-hub-sub { font-size: clamp(11px, 1vw, 13px); line-height: 1.3; color: rgba(20, 16, 13, 0.72); }

/* Le card in orbita. Fondo pieno, non trasparente: coprono la coda dei raggi
   e non leggono come riquadri vuoti accanto al disco.
   Prima del proprio turno la card non c'e'. Quando arriva, parte da addosso al
   disco e si porta al suo posto: ogni card ha il suo scostamento iniziale, che
   punta verso il centro, quindi le cinque non entrano tutte dalla stessa parte
   ma ognuna esce dal motore lungo il proprio raggio. Il ritardo di 0,22s la
   lascia arrivare dopo il raggio: prima la linea, poi quello che ci sta in
   fondo. Resta nel DOM e leggibile a uno screen reader, che non guarda
   l'opacita' e legge la sezione tutta insieme, in ordine. */
.jo-node {
  position: absolute;
  transform: translate(-50%, -50%);
  width: clamp(180px, 24.9%, 260px);
  padding: 1.15rem 1.25rem 1.25rem;
  border-radius: var(--radius);
  background: #1c1613;
  border: 1px solid rgba(247, 244, 240, 0.12);
  transition:
    opacity 0.45s var(--ease) 0.12s,
    scale 0.45s var(--ease) 0.12s,
    translate 0.45s var(--ease) 0.12s,
    border-color 0.4s var(--ease),
    background 0.4s var(--ease),
    transform 0.5s var(--ease);
}
/* Come per i raggi: la card sparisce solo a sequenza avviata */
.jo-hub[data-hub-step] .jo-node { opacity: 0; scale: 0.94; }
.jo-hub[data-hub-step] .jo-node--1 { translate: 0 30px; }
.jo-hub[data-hub-step] .jo-node--2 { translate: -28px 10px; }
.jo-hub[data-hub-step] .jo-node--3 { translate: -19px -26px; }
.jo-hub[data-hub-step] .jo-node--4 { translate: 19px -26px; }
.jo-hub[data-hub-step] .jo-node--5 { translate: 28px 10px; }
.jo-hub[data-hub-step] .jo-node.is-on { opacity: 1; scale: 1; translate: 0 0; }
.jo-node:hover {
  background: #221a15;
  border-color: rgba(254, 83, 31, 0.7);
  transform: translate(-50%, -50%) scale(1.03);
}
.jo-node h3 { font-size: clamp(17px, 1.5vw, 20px); color: var(--on-dark); }
.jo-node p { margin-top: 0.5rem; font-size: clamp(13px, 1.05vw, 14px); line-height: 1.55; color: var(--on-dark-muted); }
.jo-node .jo-node-who {
  margin-top: 0.85rem;
  padding-top: 0.7rem;
  border-top: 1px solid rgba(247, 244, 240, 0.10);
  font-size: 12px;
  color: var(--on-dark-faint);
}

/* Le cinque posizioni sull'ellisse (rx 392, ry 290 attorno a 522,400),
   in percentuale del campo: 72° di distanza l'una dall'altra. */
.jo-node--1 { left: 50%;    top: 14.474%; }
.jo-node--2 { left: 85.71%; top: 40.842%; }
.jo-node--3 { left: 72.07%; top: 83.500%; }
.jo-node--4 { left: 27.93%; top: 83.500%; }
.jo-node--5 { left: 14.29%; top: 40.842%; }

/* La didascalia sotto il diagramma: la frase che il disegno non può dire */
.jo-hub-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1.5rem 2.5rem;
  margin-top: 3rem;
  padding-top: 2.25rem;
  border-top: 1px solid rgba(247, 244, 240, 0.12);
}
.jo-hub-foot p { font-size: 16px; line-height: 1.6; color: var(--on-dark-muted); max-width: 62ch; }
.jo-hub-foot strong { color: var(--on-dark); font-weight: 600; }
.jo-hub-foot .jo-btn { flex: none; }

/* ---------------------------------------------------------------- Target */
/* Filtro, non capitolo. Header standard come le altre sezioni (titolo a
   sinistra, frase del cliente a destra) e sei casi in tre colonne: sei
   etichette corte non giustificano una sezione a due colonne alta 700px.
   La pillola tonda della prima versione (`.jo-tags`, rimossa) diceva
   "metadato" e prometteva un click che non esiste; la riga rigata dice
   "requisito". */

/* Il filtro vero della pagina: era la subordinata centrale di una frase lunga
   e nessuno la vedeva. */
.jo-req { color: var(--ink); font-weight: 600; }

.jo-cases {
  margin-top: 3.5rem;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 3rem;
  /* Regola di chiusura sull'elenco, non sull'ultima riga di celle: cosi' resta
     una riga sola qualunque sia il numero di colonne. */
  border-bottom: 1px solid var(--border);
}
.jo-cases li {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 1.1rem 0;
  border-top: 1px solid var(--border);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
}
.jo-cases li::before {
  content: '';
  width: 7px;
  height: 7px;
  margin-top: 0.55em;
  border-radius: 50%;
  background: var(--jora-orange-deep);
  flex-shrink: 0;
}

/* La lista non compare in blocco: si costruisce riga per riga, da sinistra,
   e il pallino arriva dopo la riga che sta segnando. Il ritardo sta in --d,
   letto sia dalla riga sia dal suo pallino: un valore per riga invece di due
   serie di regole. Non c'e' hover: le voci non sono cliccabili e un hover
   prometterebbe un click che non esiste. La scala del pallino non muove il
   layout, la cella e' larga comunque. */
.jo-cases li { --d: 0s; }
.jo-cases li:nth-child(2) { --d: 0.08s; }
.jo-cases li:nth-child(3) { --d: 0.16s; }
.jo-cases li:nth-child(4) { --d: 0.24s; }
.jo-cases li:nth-child(5) { --d: 0.32s; }
.jo-cases li:nth-child(6) { --d: 0.40s; }
.jo-cases > li {
  opacity: 0;
  transform: translateX(-16px);
  transition:
    opacity 0.6s var(--ease) var(--d),
    transform 0.6s var(--ease) var(--d);
}
.jo-cases.is-visible > li { opacity: 1; transform: none; }
.jo-cases li::before { scale: 0; transition: scale 0.5s var(--ease) calc(var(--d) + 0.14s); }
.jo-cases.is-visible li::before { scale: 1; }

/* -------------------------------------------------------- Valore aggiunto */
/* Elenco tipografico su due colonne: nessun contenitore, il titolo porta il
   peso e il trattino arancione fa da segno. */

/* L'intro non e' una didascalia: e' la frase piu' forte della pagina, quindi
   sale di peso e di colore senza arrivare alla scala del titolo, che le sta
   accanto e la schiaccerebbe. */
.jo-head .jo-why-lead {
  font-size: clamp(19px, 2vw, 23px);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.45;
  color: var(--ink);
  max-width: 34ch;
}

.jo-why { margin-top: 4rem; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 4rem; }
.jo-why-item { padding: 2rem 0; border-top: 1px solid var(--border); }
.jo-why-item h3 { font-size: 19px; letter-spacing: -0.01em; }
/* 34px = trattino 22px + 12px di margine: titolo, testo ed esito stanno sulla
   stessa colonna e il segno arancione resta fuori, nel margine. */
.jo-why-item p { margin-top: 0.6rem; padding-left: 34px; color: var(--ink-soft); font-size: 16px; }
.jo-why-item h3::before {
  content: '';
  display: inline-block;
  width: 22px; height: 2px;
  margin-right: 12px;
  vertical-align: 0.32em;
  background: var(--jora-orange-deep);
}
/* L'esito era la coda grigia del paragrafo: e' la parte che vende. Selettore a
   due classi perche' `.jo-why-item p` e' piu' specifico di `.jo-why-out` e
   altrimenti vince lui su misura, colore e margine.
   Sta attaccato al proprio corpo, non ancorato al fondo della cella: allineare
   i quattro esiti fra loro apriva buchi di 80px fra paragrafo ed esito, e la
   prossimita' conta piu' dell'allineamento. */
.jo-why-item .jo-why-out {
  margin-top: 0.9rem;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1.45;
  color: var(--jora-orange-text);
}

/* --------------------------------------------------------------- Percorso */
/* Qui i numeri restano: la sequenza e' l'informazione. E se e' quella
   l'informazione, e' anche il pezzo che deve pesare: 01-05 grandi e cavi come
   l'anno 2027 della visione, che passano ad arancione pieno quando la fase si
   accende. Il progresso si legge dalla riga dei numeri, senza dover guardare i
   pallini.
   La sezione sta fra due bande scure (moduli, visione) e non puo' diventare
   scura a sua volta: l'impatto lo fanno tipografia e movimento. */

.jo-path {
  margin-top: 4.5rem;
  position: relative;
  /* Timeline di scorrimento a disposizione dei discendenti: vedi il blocco
     @supports piu' sotto. Dichiararla qui non costa niente ai browser che non
     la sanno leggere. */
  view-timeline-name: --path;
  view-timeline-axis: block;
}

.jo-path-rail { position: absolute; top: 10px; left: 0; right: 0; height: 1px; background: var(--border); }
/* La barra cresce da sinistra con uno scaleX: animare la larghezza per 1,8s
   fa ricalcolare il layout a ogni frame, la scala no. */
.jo-path-rail::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--jora-orange-deep);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.8s var(--ease);
}
.jo-path.is-visible .jo-path-rail::after { transform: scaleX(1); }

.jo-path-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 2rem; }

.jo-step {
  position: relative;
  padding-top: 2.75rem;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.jo-path.is-visible .jo-step { opacity: 1; transform: none; }

/* Pallino cavo sul fondo della banda (--surface, non --bg: la banda e' grigia)
   finche' il binario non lo raggiunge. */
.jo-step::before {
  content: '';
  position: absolute; top: 6px; left: 0;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px solid var(--border);
  transition: background 0.5s var(--ease), border-color 0.5s var(--ease);
}
.jo-path.is-visible .jo-step::before { background: var(--jora-orange-deep); border-color: var(--jora-orange-deep); }

/* Due classi: il numero e' un <p>, quindi `.jo-step p` (0,1,1) batterebbe
   `.jo-step-num` (0,1,0) e la misura resterebbe quella del corpo. */
.jo-step .jo-step-num {
  font-family: var(--font-display);
  font-size: clamp(34px, 3.6vw, 52px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.045em;
  color: transparent;
  -webkit-text-stroke: 1.3px rgba(25, 21, 18, 0.24);
  transition: color 0.5s var(--ease), -webkit-text-stroke-color 0.5s var(--ease);
}
.jo-path.is-visible .jo-step-num { color: var(--jora-orange-text); -webkit-text-stroke-color: transparent; }

.jo-step h3 { font-size: 19px; letter-spacing: -0.01em; margin: 1rem 0 0.5rem; }
.jo-step p { font-size: 15px; line-height: 1.6; color: var(--ink-soft); }

/* Ritardi in scia: il binario attraversa la fase n a (n-1)/5 del suo percorso,
   1,8s in tutto. Prima tutti e cinque i pallini si accendevano insieme a 0,6s e
   l'animazione non raccontava nessun ordine. */
/* Il corpo della fase entra prima, il numero si riempie dopo: se partono
   insieme lo stato cavo non lo vede nessuno. */
.jo-step:nth-child(1) { transition-delay: 0s; }
.jo-step:nth-child(2) { transition-delay: 0.36s; }
.jo-step:nth-child(3) { transition-delay: 0.72s; }
.jo-step:nth-child(4) { transition-delay: 1.08s; }
.jo-step:nth-child(5) { transition-delay: 1.44s; }
.jo-step:nth-child(1)::before, .jo-step:nth-child(1)::after, .jo-step:nth-child(1) .jo-step-num { transition-delay: 0.30s; }
.jo-step:nth-child(2)::before, .jo-step:nth-child(2)::after, .jo-step:nth-child(2) .jo-step-num { transition-delay: 0.66s; }
.jo-step:nth-child(3)::before, .jo-step:nth-child(3)::after, .jo-step:nth-child(3) .jo-step-num { transition-delay: 1.02s; }
.jo-step:nth-child(4)::before, .jo-step:nth-child(4)::after, .jo-step:nth-child(4) .jo-step-num { transition-delay: 1.38s; }
.jo-step:nth-child(5)::before, .jo-step:nth-child(5)::after, .jo-step:nth-child(5) .jo-step-num { transition-delay: 1.74s; }

@keyframes jo-rail-x  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes jo-seg-fill { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes jo-step-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes jo-dot-on {
  from { background: var(--surface); border-color: var(--border); }
  to   { background: var(--jora-orange-deep); border-color: var(--jora-orange-deep); }
}
@keyframes jo-num-on {
  from { color: transparent; -webkit-text-stroke-color: rgba(25, 21, 18, 0.24); }
  to   { color: var(--jora-orange-text); -webkit-text-stroke-color: transparent; }
}

/* Movimento legato allo scorrimento, dove il browser lo sa fare. Il percorso
   non parte al primo pixel visibile per poi finire da solo su un cronometro:
   avanza col dito e si completa mentre la sezione arriva in posizione.
   Chi non ha `animation-timeline` (Firefox) resta sulle transizioni con i
   ritardi in scia definiti sopra: stessa scena, cronometro diverso.
   `animation-range` in percentuale di `cover`: 15% + 8% per fase, perche' il
   binario tocca la fase n a (n-1)/5 della sua corsa (15% -> 55%). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* La forma abbreviata `animation` azzera `animation-timeline`: la timeline
       va dichiarata dopo, mai prima. */
    .jo-path-rail::after {
      transition: none;
      animation: jo-rail-x linear both;
      animation-timeline: --path;
      animation-range: cover 15% cover 55%;
    }
    .jo-step        { transition: none; animation: jo-step-in linear both; animation-timeline: --path; }
    .jo-step::before { transition: none; animation: jo-dot-on  linear both; animation-timeline: --path; }
    .jo-step::after  { transition: none; animation: jo-seg-fill linear both; animation-timeline: --path; }
    .jo-step .jo-step-num { transition: none; animation: jo-num-on linear both; animation-timeline: --path; }

    /* Corpo della fase: sei punti percentuali prima del suo pallino, cosi' il
       numero cavo si vede prima di riempirsi. */
    .jo-step:nth-child(1) { animation-range: cover  9% cover 15%; }
    .jo-step:nth-child(2) { animation-range: cover 17% cover 23%; }
    .jo-step:nth-child(3) { animation-range: cover 25% cover 31%; }
    .jo-step:nth-child(4) { animation-range: cover 33% cover 39%; }
    .jo-step:nth-child(5) { animation-range: cover 41% cover 47%; }
    /* Pallino, segmento e numero: quando il binario tocca la fase. */
    .jo-step:nth-child(1)::before, .jo-step:nth-child(1)::after, .jo-step:nth-child(1) .jo-step-num { animation-range: cover 15% cover 21%; }
    .jo-step:nth-child(2)::before, .jo-step:nth-child(2)::after, .jo-step:nth-child(2) .jo-step-num { animation-range: cover 23% cover 29%; }
    .jo-step:nth-child(3)::before, .jo-step:nth-child(3)::after, .jo-step:nth-child(3) .jo-step-num { animation-range: cover 31% cover 37%; }
    .jo-step:nth-child(4)::before, .jo-step:nth-child(4)::after, .jo-step:nth-child(4) .jo-step-num { animation-range: cover 39% cover 45%; }
    .jo-step:nth-child(5)::before, .jo-step:nth-child(5)::after, .jo-step:nth-child(5) .jo-step-num { animation-range: cover 47% cover 53%; }
  }
}

/* ---------------------------------------------------------------- Visione */

.jo-vision-inner { max-width: var(--maxw); margin: 0 auto; padding: 7rem var(--pad-x); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4rem; align-items: end; }
.jo-vision h2 { font-size: clamp(30px, 4.4vw, 50px); max-width: 18ch; }
.jo-vision p { margin-top: 2rem; color: var(--on-dark-muted); font-size: var(--lead); line-height: 1.6; }
.jo-vision-year {
  font-family: var(--font-display);
  font-size: clamp(56px, 12vw, 132px);
  font-weight: 700;
  letter-spacing: -0.05em;
  line-height: 0.85;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(247, 244, 240, 0.30);
}

/* ------------------------------------------------------------- Chi siamo */
/* È la sezione della credibilità, quindi ha due ancoraggi: un collegamento
   disegnato tra le due schede partner — la partnership mostrata, non solo
   dichiarata, con lo stesso stilema della mappa dei moduli — e la
   certificazione TecDoc su card scura, l'unico blocco pieno della fascia. */

/* Coda più lunga: sotto c'è la banda scura dei moduli, e due blocchi scuri
   separati da una striscia sottile di crema sembrano un errore. */
#chi-siamo { padding-bottom: 9rem; }

.jo-partners {
  --partner-gap: 2.5rem;
  position: relative;
  margin-top: 3.5rem;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--partner-gap);
}
/* Il collegamento tra i due partner: traccia nel gap + nodo al centro */
.jo-partners::before,
.jo-partners::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.jo-partners::before {
  width: var(--partner-gap);
  height: 1px;
  background: var(--jora-orange-deep);
}
.jo-partners::after {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--jora-orange-deep);
}

.jo-partner-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  display: flex;
  flex-direction: column;
  transition: transform 0.5s var(--ease), border-color 0.4s var(--ease);
}
.jo-partner-card:hover { transform: translateY(-3px); border-color: rgba(25, 21, 18, 0.24); }
.jo-partner-brand {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--border-soft);
  line-height: 1;
}
/* Il marchio accanto al lettering: il lockup completo, rimpicciolito a
   questa altezza, renderebbe "SOLUTIONS" illeggibile. */
.jo-partner-mark { height: 26px; width: auto; vertical-align: -0.42em; margin-right: 10px; }
/* Il marchio Pigreco è più basso e larghissimo di quello Jora: pareggio
   l'ingombro ottico invece dell'altezza nominale. */
.jo-partner-mark--pigreco { height: 22px; vertical-align: -0.32em; }
.jo-brand-jora { color: var(--jora-orange-text); }
/* Il dato è testo grande (38px): può portare il primario pieno (3,25:1 su
   bianco); l'etichetta piccola resta sulla variante leggibile. */
.jo-partner-stats dt.jo-brand-jora { color: var(--jora-orange); }
.jo-brand-pigreco { color: var(--pigreco-blue); }
.jo-partner-card h3 { margin-top: 1.5rem; font-size: 21px; }
.jo-partner-text { margin-top: 0.85rem; color: var(--ink-soft); font-size: 16px; line-height: 1.7; }
.jo-partner-text strong { color: var(--ink); font-weight: 600; }

.jo-partner-stats {
  margin-top: auto;
  padding-top: 1.75rem;
  border-top: 1px solid var(--border-soft);
  display: flex;
  gap: 3rem;
}
.jo-partner-stats dt {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
}
.jo-partner-stats dd { margin-top: 0.5rem; font-size: 13px; color: var(--ink-faint); }

/* La certificazione: card scura con dentro il certificato bianco.
   Il badge TecDoc ha fondo bianco e non si può ricolorare (è un brand kit):
   invece di appiccicarlo su una targhetta, la superficie bianca diventa un
   oggetto — il certificato, che porta il badge e il nome della persona. */
.jo-cert {
  margin-top: 2.5rem;
  padding: 2.5rem;
  background: var(--dark);
  color: var(--on-dark);
  border-radius: var(--radius);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 2.75rem;
  align-items: center;
}

.jo-cert-doc {
  background: #fff;
  border-radius: 12px;
  padding: 1.5rem 1.75rem;
  text-align: center;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
}
.jo-cert-doc img { height: 70px; width: auto; display: block; margin: 0 auto; }
.jo-cert-doc figcaption {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(25, 21, 18, 0.12);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.jo-cert-doc figcaption strong {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.15rem;
}

.jo-cert-claim {
  font-family: var(--font-display);
  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.2;
  max-width: 26ch;
}
.jo-cert-text {
  margin-top: 1.25rem;
  font-size: 16px;
  line-height: 1.7;
  color: var(--on-dark-muted);
  max-width: 52ch;
}
.jo-cert-note {
  grid-column: 1 / -1;
  margin-top: 0.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(247, 244, 240, 0.12);
  font-size: 12px;
  line-height: 1.6;
  color: var(--on-dark-faint);
  padding-right: 22%;
}

/* ---------------------------------------------------------------- Contatti */

.jo-contact { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: 4rem; align-items: start; }
.jo-contact h2 { font-size: clamp(34px, 5vw, 58px); }
.jo-contact-lead { margin-top: 1.5rem; font-size: var(--lead); line-height: 1.6; color: var(--ink-soft); max-width: 34ch; }
.jo-contact-actions { margin-top: 2.25rem; display: flex; flex-wrap: wrap; gap: 12px; }
.jo-contact-card { padding-top: 1.75rem; border-top: 2px solid var(--ink); }
.jo-contact-card h3 { font-size: 22px; }
.jo-contact-mail { display: inline-block; margin-top: 0.4rem; font-size: 17px; color: var(--jora-orange-text); text-decoration: none; text-underline-offset: 0.22em; }
.jo-contact-mail:hover { text-decoration: underline; }
.jo-contact-block { margin-top: 1.75rem; padding-top: 1.5rem; border-top: 1px solid var(--border-soft); color: var(--ink-soft); }
.jo-contact-block a { color: var(--ink); text-decoration: none; text-underline-offset: 0.22em; }
.jo-contact-block a:hover { color: var(--jora-orange-text); text-decoration: underline; }

/* ------------------------------------------------------------------ Footer */

.jo-footer { background: var(--dark); color: var(--on-dark-faint); padding: 2.25rem var(--pad-x); }
.jo-footer-inner { max-width: var(--maxw); margin: 0 auto; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.75rem; font-size: 13px; }
.jo-footer-inner a { color: var(--on-dark-muted); text-decoration: none; text-underline-offset: 0.22em; }
.jo-footer-inner a:hover { color: var(--jora-orange); text-decoration: underline; }
/* Riapertura del pannello CookieYes: è un button (apre un pannello, non
   naviga) ma nel footer deve leggersi come gli altri link. */
.jo-footer-inner button.cky-banner-element { background: none; border: none; padding: 0; font: inherit; color: var(--on-dark-muted); text-decoration: none; cursor: pointer; }
.jo-footer-inner button.cky-banner-element:hover { color: var(--jora-orange); text-decoration: underline; }

/* -------------------------------------------------------------- Animazioni */
/* Ingressi differenziati: le sezioni non entrano tutte allo stesso modo. */

.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }

.reveal-stagger > * { opacity: 0; transform: translateY(20px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal-stagger.is-visible > * { opacity: 1; transform: none; }
.reveal-stagger.is-visible > *:nth-child(2) { transition-delay: 0.07s; }
.reveal-stagger.is-visible > *:nth-child(3) { transition-delay: 0.14s; }
.reveal-stagger.is-visible > *:nth-child(4) { transition-delay: 0.21s; }
.reveal-stagger.is-visible > *:nth-child(5) { transition-delay: 0.28s; }
.reveal-stagger.is-visible > *:nth-child(6) { transition-delay: 0.35s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal, .reveal-stagger > * { opacity: 1; transform: none; transition: none; }
  .jo-cases > li { opacity: 1; transform: none; transition: none; }
  .jo-cases li::before { scale: 1; transition: none; }
  .jo-market-pull::before { transform: none; transition: none; }
  .jo-flow-line { animation: none; stroke-dashoffset: 0; }
  .jo-pulse, .jo-pulse-in, .jo-node-core { animation: none; }
  .jo-pulse, .jo-pulse-in { opacity: 0; }
  .jo-path-rail::after { transition: none; }
  .jo-step, .jo-step::before, .jo-step::after, .jo-step .jo-step-num { transition: none; animation: none; }
  .jo-step { opacity: 1; transform: none; }
  .jo-step::after { transform: scaleY(1); }
  /* Il raggio va riaperto con la stessa forma di selettore che lo chiude,
     altrimenti resta il tratteggio della scena a scatti e non si vede piu'. */
  .jo-ray,
  .jo-hub[data-hub-step] .jo-ray { animation: none; stroke-dashoffset: 0; }
  .jo-ray-pulse { animation: none; opacity: 0; }
  .jo-hub-core,
  .jo-hub[data-hub-step] .jo-hub-core { animation: none; }
  .jo-node { transition: none; }
  .jo-node:hover { transform: translate(-50%, -50%); }
  .jo-btn:hover { transform: none; }
}

/* -------------------------------------------------------------- Responsive */

/* Da 1280px in su i moduli stanno in uno schermo. Prima testo e diagramma
   erano incolonnati e la sezione era alta ~1350px: su 1920x1080 il mozzo si
   guardava scorrendo, cioe' la sequenza di collegamento partiva fuori campo e
   finiva dentro. Qui il testo passa in colonna a sinistra e il diagramma
   prende tutta l'altezza che resta: intestazione, mozzo e chiusa si vedono
   insieme. Il diagramma non e' dimensionato in larghezza ma in altezza — il
   budget e' lo schermo meno il padding della sezione — e l'aspect-ratio
   ricava il resto, quindi il campo si adatta a qualunque altezza di finestra
   invece di sforare a una certa soglia. Sotto i 720px di altezza si torna
   incolonnati: a quel punto il campo sarebbe cosi' basso che le card
   sporgerebbero sopra la barra fissa. */
@media (min-width: 1280px) and (min-height: 720px) {
  .jo-solutions {
    max-width: min(1700px, 100%);
    min-height: 100svh;
    /* Sopra c'e' la barra fissa: il padding non e' simmetrico perche' la card
       piu' alta dell'orbita finirebbe sotto la nav invece che sotto la piega. */
    padding: 7rem var(--pad-x) 4rem;
    display: grid;
    /* Il mozzo occupa entrambe le righe: intestazione e chiusa si incontrano a
       meta' della colonna di sinistra, separate dal filo della chiusa. */
    grid-template-columns: minmax(300px, 0.38fr) minmax(0, 1fr);
    grid-template-areas:
      "head hub"
      "foot hub";
    column-gap: 4rem;
    align-content: center;
  }
  .jo-solutions-head {
    grid-area: head;
    align-self: end;
    grid-template-columns: 1fr;
    gap: 1.25rem;
    margin-bottom: 0;
  }
  /* In colonna il titolo ha meno larghezza di riga: scende di scala per non
     spezzarsi su quattro righe. */
  .jo-solutions-head h2 { font-size: clamp(30px, 2.5vw, 42px); }
  .jo-solutions-head p { font-size: 17px; max-width: 38ch; }

  .jo-hub {
    grid-area: hub;
    align-self: center;
    /* 14rem = il padding della sezione piu' lo sporgere delle card sopra e
       sotto il campo, che sta fuori dal box del diagramma. */
    width: min(100%, calc((100svh - 14rem) * 1044 / 760));
    max-width: none;
  }

  .jo-hub-foot {
    grid-area: foot;
    align-self: start;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 1.5rem;
    margin-top: 2.25rem;
    padding-top: 2rem;
  }
  .jo-hub-foot p { font-size: 15px; max-width: 42ch; }
}

/* Fra 1140 e 1000px le sei voci ci stanno solo stringendo il passo. */
@media (max-width: 1140px) {
  .jo-nav-links { gap: 1.4rem; }
}

@media (max-width: 1000px) {
  /* La nav passa a menu a tendina qui, non a 860px: con sei voci piu' la CTA la
     riga non sta sotto i ~1000px e andava a capo. */
  .jo-nav-toggle { display: block; }
  .jo-nav-menu {
    display: none;
    position: absolute;
    top: 100%; left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 1.1rem;
    padding: 1.25rem var(--pad-x) 1.75rem;
    background: rgba(20, 16, 13, 0.98);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border-bottom: 1px solid rgba(247, 244, 240, 0.10);
  }
  .jo-nav-menu.is-open { display: flex; }
  .jo-nav-links { flex-direction: column; gap: 1.1rem; }
  .jo-nav-cta { text-align: center; }

  .jo-market-top { gap: 1.5rem; }
  .jo-market-bottom { gap: 2rem; margin-top: 2.5rem; padding-top: 2rem; }
  .jo-hero-inner,
  .jo-market-top,
  .jo-market-bottom,
  .jo-solutions-head,
  .jo-vision-inner,
  .jo-head,
  .jo-contact { grid-template-columns: 1fr; }
  .jo-head { gap: 1.5rem; align-items: start; }
  .jo-cases { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 2.5rem; margin-top: 2.5rem; }
  .jo-hero-inner { gap: 3rem; }
  .jo-hero-figure { margin-right: 0; }
  /* Sotto questa larghezza l'orbita non ha piu' spazio: il diagramma sparisce,
     il motore va in testa e i servizi diventano una colonna di card. */
  .jo-hub {
    max-width: none;
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
  }
  .jo-hub-rays { display: none; }
  /* In colonna il disco continua a respirare, ma il colpo non ha piu' senso:
     qui i servizi non si agganciano uno per uno, ci sono tutti. */
  .jo-hub[data-hub-step] .jo-hub-core { animation: jo-hub-breathe 4.6s ease-in-out infinite; }
  .jo-hub[data-hub-step] .jo-node { translate: 0 0; }
  .jo-hub-core,
  .jo-node {
    position: static;
    transform: none;
    width: 100%;
  }
  .jo-hub-core {
    aspect-ratio: auto;
    border-radius: var(--radius);
    align-items: flex-start;
    text-align: left;
    padding: 1.75rem;
  }
  .jo-hub-name { font-size: clamp(28px, 5vw, 36px); }
  .jo-hub-kicker { font-size: 12px; }
  .jo-hub-sub { font-size: 15px; }
  .jo-node:hover { transform: none; }
  .jo-hub-foot { justify-content: flex-start; margin-top: 2.5rem; }
  /* Verticale, non "senza binario": la sequenza e' l'informazione, e prima
     sotto i 1000px sparivano sia la linea sia i pallini. Il binario diventa un
     segmento per fase (bordo sinistro + riempimento in ::after), cosi' la linea
     si accende un pezzo alla volta invece che tutta insieme. */
  .jo-path-steps { grid-template-columns: 1fr; gap: 0; }
  .jo-path-rail { display: none; }
  .jo-step { padding: 0 0 2.5rem 2.25rem; border-left: 1px solid var(--border); }
  .jo-step:last-child { border-left-color: transparent; padding-bottom: 0; }
  /* In colonna la fase e' larga quanto la pagina: senza un limite la riga
     arriva a ~100 caratteri. */
  .jo-step p { max-width: 52ch; }
  .jo-step::before { top: 12px; left: -5px; }
  .jo-step::after {
    content: '';
    position: absolute;
    left: -1px; top: 0; bottom: 0;
    width: 1px;
    background: var(--jora-orange-deep);
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 0.5s var(--ease);
  }
  .jo-step:last-child::after { display: none; }
  .jo-path.is-visible .jo-step::after { transform: scaleY(1); }
}

@media (max-width: 860px) {
  :root { --pad-x: 1.5rem; }

  .jo-section { padding: 4.5rem var(--pad-x); }
  .jo-hero { padding: 7rem 0 4rem; }
  .jo-market { padding: 4.5rem var(--pad-x); }
  .jo-vision-inner { padding: 4.5rem var(--pad-x); gap: 2rem; }
  .jo-solutions { padding: 4.5rem var(--pad-x); }
  .jo-solutions-head { margin-bottom: 2.5rem; gap: 1.25rem; align-items: start; }
  .jo-hub-core { padding: 1.5rem; }
  .jo-node { padding: 1.25rem; }
  .jo-node h3 { font-size: 19px; }
  .jo-node p { font-size: 14px; }
  .jo-why { grid-template-columns: 1fr; gap: 0; }
  .jo-partners { grid-template-columns: 1fr; }
  .jo-partners::before, .jo-partners::after { display: none; }
  .jo-cert { grid-template-columns: 1fr; gap: 1.75rem; padding: 1.75rem; }
  .jo-cert-doc { justify-self: start; }
  .jo-cert-note { padding-right: 0; }
  .jo-partner-stats { gap: 2rem; }
}

@media (max-width: 640px) {
  .jo-cases { grid-template-columns: 1fr; }
  /* Su schermo stretto l'indentazione a 34px mangia larghezza di riga: il
     segno arancione resta nel titolo, testo ed esito tornano a filo. */
  .jo-why-item p { padding-left: 0; }
}

@media (max-width: 560px) {
  .jo-step h3 { font-size: 18px; }
}

/* ===========================================================================
   CookieYes — riallineamento al design del sito
   CookieYes scrive i colori scelti nella sua dashboard come attributi `style`
   inline su barra, pannello e bottoni (`style="background-color:#1863dc"`), e
   inietta la propria <style id="cky-style"> dopo questo foglio: senza
   `!important` qualunque override perde. Da qui il blocco: blu di default
   (#1863dc) -> arancio Jora, grigio (#d0d0d0) -> testo su fondo scuro, nero
   neutro (#121212) -> nero caldo del sito, verde "sempre attivo" -> arancio.
   Classi della v3, verificate sul DOM in produzione.
   =========================================================================== */

/* Superfici. Il `color` sta qui e non sui figli: CookieYes lo mette inline
   solo su questi due contenitori, tutto il resto lo eredita. */
.cky-consent-bar,
.cky-preference-center,
.cky-preference-center .cky-footer-wrapper {
  background-color: var(--dark) !important;
  border-color: rgba(247, 244, 240, 0.14) !important;
  color: var(--on-dark-muted) !important;
}

/* Titoli e voci di categoria: hanno un `color` inline proprio, vanno ripresi */
.cky-title,
.cky-preference-title,
.cky-accordion-btn {
  color: var(--on-dark) !important;
}
.cky-notice-des,
.cky-notice-des *,
.cky-preference-content-wrapper,
.cky-accordion-header-des {
  color: var(--on-dark-muted) !important;
}

/* Tabella dei cookie dentro le categorie: grigio neutro -> nero caldo */
.cky-audit-table {
  background-color: var(--dark-2) !important;
  color: var(--on-dark-muted) !important;
}

/* "Sempre attivo": il verde di CookieYes non appartiene alla palette e su
   fondo scuro non si legge. */
.cky-always-active {
  color: var(--jora-orange) !important;
}

/* Link dell'informativa e "Mostra di piu": arancio pieno, 8,5:1 sul nero */
.cky-notice-des a.cky-policy,
.cky-notice-des button.cky-policy,
.cky-notice-des a.cky-link-default,
.cky-preference-content-wrapper button.cky-show-desc-btn,
.cky-preference-content-wrapper button.cky-show-desc-btn:not(:hover):not(:active) {
  color: var(--jora-orange) !important;
}

/* Bottoni: stessa forma dei .jo-btn (pillola, Poppins 500) */
.cky-btn {
  font-family: var(--font) !important;
  font-size: 14px !important;
  font-weight: 500 !important;
  border-radius: 999px !important;
  border-width: 1px !important;
  border-style: solid !important;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease) !important;
}

/* "Accetta tutto" = .jo-btn--orange */
.cky-btn-accept {
  background-color: var(--jora-orange) !important;
  border-color: var(--jora-orange) !important;
  color: var(--on-dark) !important;
}
.cky-btn-accept:hover {
  background-color: var(--jora-orange-hover) !important;
  border-color: var(--jora-orange-hover) !important;
}

/* "Rifiuta tutto", "Personalizza", "Salva preferenze" = .jo-btn--outline-dark */
.cky-btn-reject,
.cky-btn-customize,
.cky-btn-preferences {
  background-color: transparent !important;
  border-color: rgba(247, 244, 240, 0.28) !important;
  color: var(--on-dark) !important;
}
.cky-btn-reject:hover,
.cky-btn-customize:hover,
.cky-btn-preferences:hover {
  border-color: var(--on-dark) !important;
  background-color: rgba(247, 244, 240, 0.06) !important;
}

/* Interruttori delle categorie: oggi il banner non ne mostra (configurazione
   senza toggle), la regola c'e' per quando verranno accesi. */
.cky-switch input[type="checkbox"]:checked {
  background: var(--jora-orange) !important;
}

/* Pastiglia flottante che riapre il pannello */
.cky-btn-revisit-wrapper {
  background-color: var(--jora-orange) !important;
}
.cky-btn-revisit-wrapper:hover {
  background-color: var(--jora-orange-hover) !important;
}

/* Anello di focus: quello del sito, non quello di CookieYes */
.cky-btn:focus-visible,
.cky-accordion-btn:focus-visible,
.cky-show-desc-btn:focus-visible,
.cky-btn-revisit:focus-visible,
.cky-btn-close:focus-visible {
  outline: 2px solid var(--jora-orange) !important;
  outline-offset: 3px !important;
}
