/* ============================================================================
   Polymerization · Fusion Tracker — reserved area skin
   White-label: nessun marchio. Superficie neutra, un solo accento, niente
   effetti decorativi: il colore resta un segnale (verdetto, stato, esito).
   ========================================================================== */

/* i token e i componenti comuni (06-C-SISTEMA): @import deve stare prima di ogni altra regola */
@import url("poly.6a564c8db0c4.css");

/* ---- fonts (self-hosted, no CDN) ---- */
@font-face {
  font-family: "Inter";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/inter-400.73aaa95eab31.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/inter-600.0bf7eadca131.woff2") format("woff2");
}
@font-face {
  font-family: "Cascadia Mono";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/cascadia-mono-400.b60944e41b46.woff2") format("woff2");
}
@font-face {
  font-family: "Cascadia Mono";
  font-style: normal; font-weight: 600; font-display: swap;
  src: url("../fonts/cascadia-mono-600.627923f67433.woff2") format("woff2");
}
/* Bandierine di paese. Una bandiera emoji e' la sigla ISO scritta con due
   "regional indicator" (IT = 🇮🇹), e disegnarla richiede al font una legatura
   che Segoe UI Emoji NON ha: su Windows, Chrome ed Edge mostrerebbero le due
   lettere. Questo woff2 e' un ritaglio di Twemoji con le sole bandiere (78 KB),
   e lo `unicode-range` lo confina all'intervallo dei regional indicator — il
   resto della pagina continua a usare Inter e Cascadia senza saperne nulla.
   Auto-ospitato come gli altri font: nessuna CDN. */
@font-face {
  font-family: "Bandiere";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/twemoji-bandiere.a19faae092f7.woff2") format("woff2");
  unicode-range: U+1F1E6-1F1FF;
}

.bandiera {
  font-family: "Bandiere", sans-serif;
  /* Le bandiere Twemoji sono piu' alte delle cifre: rimpicciolite e allineate
     a mano, restano dentro l'interlinea della riga di tabella. */
  font-size: 0.95em;
  line-height: 1;
  margin-right: 0.35em;
  vertical-align: -0.05em;
  cursor: default;
}

/* ---- design tokens ----
   I token stanno in poly.css (run «vetrina-fronte», 06-C-SISTEMA): caricato da
   _base.html prima di questo foglio, e importato qui in testa per login.html e
   _accesso_base.html. Qui restano solo i nomi che poly.css non porta. */
:root {
  --notrun: #A78BFA;   /* NOT RUN: controllo non eseguito, ne' passato ne' fallito (= --v-unscanned) */
  --secret-bg: rgba(217, 130, 92, .10);   /* = --fuoco-rgb; i valori dei token restano leggibili a occhio e dai test */
  --secret-line: rgba(217, 130, 92, .34); /* = --fuoco-rgb */
  --t-slow: .4s;
}

/* prefers-reduced-motion NON viene rispettato, ed e' una scelta consapevole.
   Windows con "Effetti di animazione" spento lo fa dichiarare al browser, e
   quella e' un'impostazione che parecchia gente mette per prestazioni, non per
   sensibilita' al movimento: obbedendo, l'unica cosa che si otteneva era che
   chi ha quel flag non vedeva ne' il vortice del login, ne' il lampeggio che
   dice quale card si e' aperta, ne' che il caricamento sta andando avanti.
   Qui dentro non c'e' niente che scatti o lampeggi in fretta: sono dissolvenze
   e rotazioni lente. Se un domani servisse tornare a obbedire, le regole da
   rimettere sono quattro: le durate qui sotto, `.richiamata`, `.reveal`,
   `.stage .spin` e `.scan-beam::after`.

   UNA ECCEZIONE, ED E' UNA SOLA: l'alone della barra di Zen. Quello respira
   da solo, in loop, senza che nessuno abbia chiesto niente — e un movimento
   perpetuo in mezzo allo schermo e' l'unica cosa qui dentro che si puo'
   guardare per un minuto intero. Il suo ramo `prefers-reduced-motion` sta in
   fondo al foglio, nella sezione "la scena di Zen", e ferma il respiro
   lasciando l'alone acceso e fermo. */

/* ---- reset ---- */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: var(--cyan); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: rgba(var(--ice-rgb), .40); color: var(--text); }

/* universal visible focus */
:focus-visible {
  outline: none;
  box-shadow: var(--focus);
  border-radius: var(--r-sm);
}

/* monospazio = dati (hash, indirizzi, importi). Mai maiuscolo forzato:
   un indirizzo checksummed deve restare leggibile com'e'. */
.mono {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0;
  text-transform: none;
}
/* micro-etichetta: sans, non spaziata, solo piu' piccola e smorzata */
.label {
  font-family: var(--sans); font-size: 12px; font-weight: 400;
  letter-spacing: 0; text-transform: none; color: var(--text-dim);
}
.hidden { display: none !important; }
.banda { max-width: 1200px; margin: 0 auto; padding: 0 clamp(20px, 4vw, 48px); }

/* ============================================================================
   Sfondo
   Login: il vortice che si chiude (canvas + velo). Guscio applicativo:
   superficie piatta, nessun canvas caricato.
   `--cielo` va da 0 (pomeriggio bianco) a 1 (fronte arrivato): lo scrive il
   controller in login.html a ogni tick, e da lui dipendono sia il velo sia il
   colore del chrome, che deve restare leggibile su entrambi i cieli.
   ========================================================================== */
/* Il valore di partenza sta anche qui, non solo in JS: fra il primo frame
   dipinto dal browser e il primo tick del controller passa qualche
   millisecondo, e con --cielo a 0 quel buco si vedeva come un lampo chiaro. */
body.login { --cielo: 1; }

#bagliore {
  position: fixed; inset: 0; width: 100%; height: 100%; display: block; z-index: 0;
  background: radial-gradient(60% 45% at 46% 48%, #6E4A66 0%, #2A1E33 45%, #07070C 100%);
}
/* senza WebGL resta un bagliore dipinto in CSS, non un buco nero */
#bagliore.senza-webgl {
  background: radial-gradient(60% 45% at 46% 48%, #6E4A66 0%, #2A1E33 45%, #07070C 100%);
}

/* Il velo protegge la scheda quando il cielo e' ancora bianco e si ritira via
   via che il cielo si scurisce da solo. */
#velo {
  position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: calc(1 - .4 * var(--cielo));
  background:
    radial-gradient(130% 100% at 50% 34%,
      rgba(8, 9, 10, 0) 52%, rgba(8, 9, 10, .16) 100%),
    linear-gradient(to bottom,
      rgba(8, 9, 10, 0) 58%, rgba(8, 9, 10, .30) 100%);
}

/* ============================================================================
   Topbar (login topline + shell topbar condividono i pezzi)
   ========================================================================== */
.spia {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--text-mute);
  display: inline-block;
}
.spia.ok { background: var(--ok); }

.topline {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 20px clamp(20px, 4vw, 40px);
}
.topline .stato {
  display: flex; align-items: center; gap: 8px;
  color: var(--text-mute); font-family: var(--sans); font-size: 12px;
}

/* `--chrome` lo scrive il controller: e' il colore del testo interpolato fra
   inchiostro (cielo bianco) e bianco (cielo di piombo). Interpolato in JS e non
   con color-mix() perche' una percentuale calcolata da var() non e' affidabile
   ovunque, e un chrome illeggibile e' peggio di un chrome fermo. */
body.login .topline {
  color: var(--chrome, var(--text));
  /* l'alone e' l'opposto del testo: senza, a meta' del fronte il chrome
     spariva contro un fondo della sua stessa chiarezza */
  text-shadow: 0 1px 3px var(--alone, transparent);
  transition: color .25s linear;
}
body.login .topline .brandtag .mark,
body.login .topline .brandtag .poly { color: inherit; }
body.login .topline .brandtag .app { color: inherit; opacity: .66; }

header.topbar {
  position: sticky; top: 0; z-index: 30;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
header.topbar .banda {
  display: flex; align-items: center; gap: 12px; height: 52px;
}

/* marchio: un piccolo glifo neutro + il nome del prodotto */
.brandtag { display: flex; align-items: center; gap: 9px; }
.brandtag .mark {
  width: 20px; height: 20px; flex: 0 0 auto; display: block; color: var(--ice);
}
.brandtag .poly {
  color: var(--text); font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: .04em;
}
.brandtag .app {
  color: var(--text-dim); font-family: var(--sans); font-size: 13px; font-weight: 400;
}
.brandtag .app::before { content: "· "; color: var(--text-mute); }
.sep { width: 1px; height: 18px; background: var(--line-strong); flex: 0 0 auto; }
header.topbar .spacer { flex: 1 1 auto; }
.op {
  display: flex; align-items: center; gap: 7px;
  color: var(--text-dim); font-family: var(--sans); font-size: 12.5px; letter-spacing: 0;
}
.op b { color: var(--text); font-weight: 500; }
/* Il badge dell'operatore E' UN LINK a «Il mio uso» (vedi `_menu.html`): gli
   serve quindi lo stesso ritorno al passaggio e allo stato di fuoco delle altre
   voci della barra, altrimenti resta una cosa cliccabile che non dichiara di
   esserlo. Non prende pero' il riquadro di `.topbar-link`: non e' una quarta
   voce di menu, e dargli il peso di una sarebbe proprio la cosa che il
   commento di `_menu.html` dichiara di non voler fare. Si accende il nome — la
   parte che dice «tu» — con la stessa sottolineatura `--ice` che marca la voce
   corrente fra gli attrezzi del superadmin. */
.op { text-decoration: none; }
.op b {
  border-bottom: 1px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.op:hover { color: var(--text-dim); text-decoration: none; }
.op:hover b { border-bottom-color: var(--line-strong); }
.op:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r-sm); }
.op[aria-current="page"] b { border-bottom-color: var(--ice); }
.topbar-link {
  font-family: var(--sans); font-size: 12.5px; font-weight: 500; letter-spacing: 0;
  text-transform: none;
  color: var(--text-dim); padding: 5px 10px; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: transparent; cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease);
}
.topbar-link:hover {
  color: var(--text); border-color: var(--line-strong);
  background: var(--bg-2); text-decoration: none;
}
.logout-form { display: inline; margin: 0; }

/* ------------------------------------------------------- il menu, fisso */
/* Le tre voci ci sono sempre e nello stesso ordine — Audit, APIs, Docs. La
   corrente non sparisce: si accende. Un menu che cambia forma a ogni passo
   non si impara. */
.topbar-nav { display: flex; align-items: center; gap: 6px; margin-left: 6px; }
.menu-voce { text-decoration: none; }
.menu-voce.attivo {
  color: var(--text); border-color: var(--line-strong); background: var(--bg-2);
}
/* Voce prevista ma non ancora raggiungibile (la rotta non c'e'): si vede che
   esiste, non si clicca. */

/* Gli attrezzi del superadmin stanno a destra, dopo il separatore, e non
   entrano nel terzetto: chi amministra vede le stesse tre voci di tutti piu'
   una cassetta, invece di un menu tutto suo. Peso da etichetta, non da voce. */
.topbar-riservato { display: flex; align-items: center; gap: 10px; }
.riservato-voce {
  font-family: var(--sans); font-size: 11.5px; font-weight: 500; letter-spacing: .02em;
  color: var(--text-mute); text-decoration: none;
  padding: 3px 0; border-bottom: 1px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.riservato-voce:hover { color: var(--text-dim); text-decoration: none; }
.riservato-voce.attivo { color: var(--text); border-bottom-color: var(--ice); }
.riservato-voce:focus-visible { outline: none; box-shadow: var(--focus); border-radius: var(--r-sm); }

/* ------------------------------------- l'altra pagina di Audit: zen/albero */
/* Erano due schede affiancate. Sotto lo switch delle quattro modalita' di Zen
   sembravano una quinta modalita', e Albero non lo e': e' un'altra pagina. Ora
   e' un link solo, discreto, all'altra — e nient'altro ha il peso di una
   scelta di modo. */
.modo-altro {
  display: flex; align-items: baseline; gap: 8px;
  margin: 0 0 18px; font-family: var(--sans); font-size: 12.5px;
}
.modo-vai {
  color: var(--text-dim); text-decoration: none;
  border-bottom: 1px dotted transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.modo-vai:hover { color: var(--text); text-decoration: none; border-bottom-color: var(--line-cyan); }
.modo-vai:focus-visible { outline: none; box-shadow: var(--focus); border-radius: 2px; }
.modo-nota {
  font-family: var(--sans); font-size: 11.5px; font-weight: 400; color: var(--text-mute);
}

/* Selettore di lingua: due sigle in un solo blocco, non due bottoni. Ha il
   peso di un'etichetta, non di un'azione — cambiare lingua si fa una volta. */
.lingua {
  display: inline-flex; align-items: center; gap: 2px; margin: 0;
  padding: 3px 6px; border: 1px solid var(--line); border-radius: var(--r-sm);
}
.lingua-voce {
  font-family: var(--sans); font-size: 11.5px; font-weight: 500;
  letter-spacing: .04em; color: var(--text-dim);
  padding: 2px 5px; border: 0; border-radius: 3px; background: transparent;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.lingua-voce:hover { color: var(--text); }
.lingua-voce.attiva { color: var(--text); background: var(--bg-2); cursor: default; }
.lingua-sep { color: var(--line-strong); font-size: 11px; }

/* Nel login la topline non ha ne' cornici ne' fondi: il selettore ci si posa
   sopra come il marchio, senza scatola. */
body.login .topline .lingua { border-color: transparent; padding: 3px 0; }
body.login .topline .lingua-voce { color: inherit; opacity: .5; }
body.login .topline .lingua-voce:hover { opacity: .8; }
body.login .topline .lingua-voce.attiva {
  color: inherit; opacity: 1; background: transparent;
  text-decoration: underline; text-underline-offset: 3px;
}
body.login .topline .lingua-sep { color: inherit; opacity: .35; }

/* ============================================================================
   LOGIN
   ========================================================================== */
body.login .wrap {
  position: relative; z-index: 4;
  min-height: 100svh; display: flex; flex-direction: column;
}
body.login .center {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  padding: 40px clamp(20px, 4vw, 40px);
}
.card {
  width: 100%; max-width: 400px; flex: 0 1 400px;
  background: rgba(11, 12, 14, .90);
  backdrop-filter: blur(24px) saturate(.9); -webkit-backdrop-filter: blur(24px) saturate(.9);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: var(--r-lg);
  padding: 30px 30px 28px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .5), 0 2px 0 rgba(255, 255, 255, .04) inset;
}
.card .eyebrow {
  font-family: var(--sans); font-size: 12px; font-weight: 400; letter-spacing: 0;
  text-transform: none; color: var(--text-mute); margin: 0 0 10px;
}
.card h1 { font-size: 24px; font-weight: 600; letter-spacing: -.02em; margin: 0 0 8px; }
.card .lead { color: var(--text-dim); font-size: 14px; line-height: 1.5; margin: 0 0 24px; }
.card form { display: block; }
.field-group { margin-bottom: 14px; }
.field-group label {
  display: block; font-family: var(--sans); font-size: 12.5px; font-weight: 500;
  letter-spacing: 0; text-transform: none; color: var(--text-dim); margin-bottom: 6px;
}
.field {
  width: 100%; padding: 9px 12px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 14px;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.field.mono { font-family: var(--mono); font-size: 13px; letter-spacing: 0; }
.field:focus { outline: none; border-color: var(--ice); box-shadow: var(--focus); }
.field::placeholder { color: var(--text-mute); }

.btn-primary {
  width: 100%; padding: 9px 16px; margin-top: 8px;
  background: var(--ice); color: var(--ice-ink);
  border: 1px solid var(--ice); border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 14px; font-weight: 500; letter-spacing: 0;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.btn-primary:hover { background: var(--accent-soft); border-color: var(--accent-soft); }
.btn-primary:active { background: var(--ice); }
.btn-primary:disabled { opacity: .55; cursor: default; }

.form-error {
  border: 1px solid var(--bad-line);
  background: var(--bad-bg);
  color: #F5B7B9;
  padding: 9px 12px; border-radius: var(--r-sm);
  font-size: 13px; margin: 0 0 16px;
}
.form-error ul { margin: 0; padding-left: 18px; }
/* L'esito buono, di ritorno dal link d'accesso: stessa forma dell'errore. */
.form-ok {
  border: 1px solid var(--ok-line);
  background: var(--ok-bg);
  color: #BFE6D1;
  padding: 9px 12px; border-radius: var(--r-sm);
  font-size: 13px; margin: 0 0 16px;
}
.shake { border-color: var(--bad-line); }


/* ----------------------------------------------------------------------------
   La carta sospesa
   Defusion scioglie una fusione: e' da li' che viene il nome dello strumento,
   quindi la carta sta nel primo schermo, accanto al login.
   Quattro strati sullo stesso piano prospettico: la carta, l'illustrazione
   staccata e girata un po' di piu', il security foil, il riflesso piu' avanti
   ancora. Gli angoli --rx/--ry e la posizione della luce --lx/--ly li scrive il
   controller in login.html.

   `carta-defusion.webp` e' la scansione RITAGLIATA sul bordo vero della carta:
   niente margine bianco dello scanner, angoli tondi gia' nell'alfa. Per questo
   qui sotto non c'e' border-radius — taglierebbe due volte — e `drop-shadow`,
   che segue l'alfa, da' all'ombra la forma della carta invece di un rettangolo.
   Misure prese sulla scansione (388x567): finestra dell'illustrazione
   x 46..341 / y 104..398, security foil x 354..372 / y 532..551.
   -------------------------------------------------------------------------- */
.ingresso {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(28px, 6vw, 76px);
  width: 100%; max-width: 940px;
}

.carta-scena {
  margin: 0; flex: 0 0 auto;
  /* la prospettiva vive qui: sui figli e' la carta a girare, non la scena */
  perspective: 1100px;
  perspective-origin: 50% 46%;
}

.carta {
  --rx: 0deg; --ry: 0deg; --lx: 50%; --ly: 45%;
  position: relative;
  width: clamp(212px, 22vw, 292px);
  aspect-ratio: 388 / 567;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  /* l'ombra non gira con la carta: resta a terra e la fa leggere sospesa */
  filter: drop-shadow(0 26px 34px rgba(0, 0, 0, .6));
  will-change: transform;
}

.carta-base {
  display: block; width: 100%; height: 100%;
  -webkit-user-drag: none; user-select: none;
}

/* L'illustrazione ricalca l'INTERNO della cornice stampata, non la cornice:
   e' quello il punto in cui si incastona, ed e' misurato (la deviazione
   standard per riga e per colonna salta da ~5 a ~35 dove il bordo finisce e il
   disegno comincia). Niente scale sopra 1: da ferma sta esattamente nel suo
   quadro. A sbordare ci pensa la prospettiva, che e' l'unico momento in cui ha
   senso: lo stacco (translateZ) e i fattori 0.20/0.24 le danno un po' PIU'
   angolo della carta, e inclinando il disegno fluttua e vuole uscire dal quadro. */
.carta-illo {
  position: absolute;
  left: 11.856%; top: 18.342%; width: 76.031%; height: 51.852%;
  object-fit: cover;
  transform:
    translateZ(18px)
    rotateX(calc(var(--rx) * 0.20))
    rotateY(calc(var(--ry) * 0.24));
  transform-origin: 50% 50%;
  filter: drop-shadow(0 4px 11px rgba(0, 0, 0, .45));
  -webkit-user-drag: none; user-select: none;
}

/* Il security foil, in basso a destra.
   Questo e' il RIPIEGO dipinto in CSS: due strati sovrapposti, le righe sottili
   (il reticolo) e un arcobaleno conico. Serve solo se foil.js non gira; quando
   gira, la regola .con-foil qui sotto lo spegne e lascia il canvas.
   --holo (tinta) e --brillo (quanto e' acceso) li scrive il rAF in login.html. */
.carta-holo {
  position: absolute;
  left: 91.24%; top: 93.83%; width: 4.64%; height: 3.35%;
  transform: translateZ(2px);
  pointer-events: none;
  mix-blend-mode: hard-light;
  opacity: calc(.20 + .62 * var(--brillo, .3));
  filter: hue-rotate(calc(var(--holo, .5) * 360deg)) saturate(1.7);
  background:
    repeating-linear-gradient(107deg,
      rgba(255, 90, 160, .85) 0%, rgba(120, 220, 255, .85) 1.6%,
      rgba(150, 255, 170, .85) 3.2%, rgba(255, 235, 120, .85) 4.8%,
      rgba(255, 90, 160, .85) 6.4%),
    conic-gradient(from calc(var(--holo, .5) * 360deg) at 40% 60%,
      #ff5aa0, #78dcff, #96ffaa, #ffeb78, #ff5aa0);
  background-size: 260% 260%, 100% 100%;
  background-position: calc(var(--holo, .5) * 200%) 50%, 0 0;
  border-radius: 1px;
}

/* Con foil.js il quadratino non e' piu' dipinto: dentro ci finisce un canvas
   che ridisegna il reticolo a ogni inclinazione. Via i gradienti, via il blend
   (il canvas e' gia' la cosa giusta, non un velo da fondere), resta solo il
   fatto che si accende quando la luce ci passa sopra. */
.carta-holo.con-foil {
  background: none;
  filter: none;
  mix-blend-mode: normal;
  opacity: calc(.74 + .26 * var(--brillo, .3));
}
.carta-holo.con-foil canvas {
  width: 100% !important; height: 100% !important; display: block;
  border-radius: 1px;
}

/* Il riflesso: una luce che scivola, non un lampo. Sta piu' avanti di tutto,
   cosi' inclinando passa sopra anche all'illustrazione sollevata. */
.carta-lucido {
  position: absolute; inset: -1.5%;
  transform: translateZ(46px) scale(.958);
  border-radius: 13px;
  pointer-events: none;
  mix-blend-mode: screen;
  /* leggero: deve far sembrare la carta imbustata, non annebbiarla */
  opacity: .34;
  background:
    radial-gradient(40% 32% at var(--lx) var(--ly),
      rgba(255, 255, 255, .5) 0%, rgba(255, 255, 255, .1) 44%, rgba(255, 255, 255, 0) 74%),
    linear-gradient(115deg,
      rgba(255, 255, 255, 0) 40%, rgba(190, 225, 255, .12) 50%, rgba(255, 255, 255, 0) 60%);
}

/* Il nome nel pannello e' gia' due pezzi. Il taglio fra «De» e «fusion» non e'
   piu' un trattino ma una FENDITURA VUOTA: il trattino non fa parte del nome, e
   cosi' quello che si legge e si copia e' «Defusion», senza segni in mezzo.
   La fenditura cade dove cade il senso della parola, fra il prefisso e cio' che
   il prefisso disfa. */
body.login .card h1 { display: flex; align-items: baseline; }
body.login .card h1 .taglio { flex: 0 0 .05em; }

@media (max-width: 860px) {
  /* in colonna la carta resta, ma piu' piccola: e' l'insegna, non il contenuto */
  .ingresso { flex-direction: column; gap: 26px; }
  .carta { width: clamp(150px, 42vw, 200px); }
}
@media (max-width: 520px) {
  /* sotto questa soglia il login vuole tutto lo schermo */
  .carta-scena { display: none; }
}

/* ============================================================================
   SHELL content
   ========================================================================== */
main.shell-main { position: relative; z-index: 2; padding: 28px 0 96px; }
/* testata di pagina: titolo e sua riga di contesto, incolonnati a sinistra */
.eyebrow-row { margin: 0 0 20px; }
.eyebrow-row .eyebrow {
  display: block; margin: 0 0 3px;
  font-family: var(--sans); font-size: 18px; font-weight: 600; letter-spacing: -.02em;
  text-transform: none; color: var(--text);
}
.eyebrow-row .sub {
  display: block; margin: 0;
  font-family: var(--sans); font-size: 13.5px; color: var(--text-dim);
}

/* Le tre `modecard` erano qui, grandi come carte. Ora sono i segmenti dello
   switch e stanno in fondo al foglio, nella sezione "la scena di Zen": la
   classe e' rimasta (app.js ci lavora sopra), il vestito no. */

/* ---- la carta del form: piena larghezza, il banco a due colonne non c'e' piu' ---- */
.carta-form {
  padding: 20px 20px 22px;
  background: var(--bg-1);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  margin-bottom: 22px;
}
.cf-testa { margin-bottom: 18px; }
.cf-titolo {
  margin: 0 0 4px; font-family: var(--sans); font-size: 14.5px; font-weight: 600;
  letter-spacing: -.01em; color: var(--text);
}
.cf-sub { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); max-width: 62ch; }

/* ---- forms ---- */
/* Le tre carte hanno la stessa anatomia, cosi' passando da una modalita'
   all'altra non si sposta niente: il campo che si incolla in cima a tutta
   larghezza, sotto la riga dei parametri incolonnati sempre allo stesso passo,
   in fondo il piede con la nota e l'azione. Il form riempie la carta: un
   max-width qui dentro lasciava un vuoto storto sulla destra. */
.trace-form { display: block; margin: 0; }
.trace-form > .fg-primo { margin-bottom: 18px; }
.trace-form .fg-primo input, .trace-form .fg-larga input { width: 100%; }
/* il campo principale e' anche piu' alto degli altri: si vede subito dove si incolla */
.trace-form .fg-primo input { padding: 12px 14px; font-size: 14px; }
.trace-form.trova input#hashlock { font-size: 13.5px; }
.lb-nota { color: var(--text-mute); font-weight: 400; }

/* La riga dei parametri: colonne uguali che riempiono la carta, quante sono i
   campi. Cosi' ogni riga chiude a filo con il campo grande sopra e con la riga
   del piede sotto: il margine vuoto e storto sulla destra non c'e' piu'. */
.param {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  gap: 16px 18px; align-items: end;
}

/* il piede: la riga di stacco a tutta larghezza, la nota a sinistra, il tasto a destra */
.cf-piede {
  display: flex; align-items: center; gap: 24px; justify-content: space-between;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line);
}
.cf-aiuto {
  margin: 0; max-width: 68ch;
  font-size: 12.5px; line-height: 1.55; color: var(--text-mute);
}
.cf-aiuto .mono { font-family: var(--mono); font-size: 11.5px; color: var(--text-dim); }

/* datetime-local porta con se' l'icona del calendario del browser: la si tinge,
   non la si nasconde — e' l'unico modo di aprire il picker con il mouse. */
.trace-form input[type="datetime-local"] { font-family: var(--mono); font-size: 12.5px; }
.trace-form input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(62%) sepia(6%) saturate(300%) hue-rotate(190deg);
  cursor: pointer;
}
.trace-form .fg { display: block; }
.trace-form label {
  display: block; font-family: var(--sans); font-size: 12.5px; font-weight: 500;
  letter-spacing: 0; text-transform: none; color: var(--text-dim); margin-bottom: 6px;
}
.trace-form select:not(.sr-only), .trace-form input {
  width: 100%; padding: 8px 11px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 13.5px;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.trace-form input.mono { font-family: var(--mono); font-size: 12.5px; letter-spacing: 0; }

/* Il <select> di sistema portava con se' la sua freccia e il suo incavo: qui
   accanto al picker della catena stonava. Stessa scatola, stesso caret. */
.trace-form select:not(.sr-only) {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%2362666D' stroke-width='1.4'%3E%3Cpath d='M3 4.5 6 7.5l3-3'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; background-size: 12px 12px;
}
.trace-form select:not(.sr-only):hover { border-color: rgba(255, 255, 255, .22); }
.trace-form select:not(.sr-only) option { background: var(--bg-3); color: var(--text); }

/* Le frecce dei campi numerici sono chrome del sistema operativo: fuori stile
   e inutili qui, dove il valore si scrive. */
.trace-form input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
.trace-form input[type="number"]::-webkit-outer-spin-button,
.trace-form input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- picker della catena sorgente -------------------------------------- */
/* Il <select> nativo resta nel DOM ed e' la fonte di verita' (i submit leggono
   il suo .value): sopra ci sta solo una superficie che sa disegnare i marchi. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.picker { position: relative; }
.picker-btn {
  width: 100%; display: flex; align-items: center; gap: 8px;
  padding: 8px 11px; cursor: pointer;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 13.5px; text-align: left;
  transition: border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.picker-btn:hover { border-color: rgba(255, 255, 255, .22); }
.picker-btn[aria-expanded="true"] { border-color: var(--ice); }
.picker-val { flex: 1 1 auto; display: flex; align-items: center; gap: 9px; min-width: 0; }
.picker-val .nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-ph { color: var(--text-mute); }
.picker-caret { width: 12px; height: 12px; flex: 0 0 auto; color: var(--text-mute); }

.marchio { width: 18px; height: 18px; flex: 0 0 auto; display: block; border-radius: 4px; }
.marchio text { font-family: var(--sans); font-size: 8.5px; font-weight: 600; }

.picker-pop {
  position: absolute; z-index: 60; top: calc(100% + 5px); left: 0; right: 0;
  max-height: 288px; overflow-y: auto; padding: 4px;
  background: var(--bg-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  box-shadow: 0 18px 44px rgba(0, 0, 0, .6);
}
.picker-opt {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 9px; border-radius: var(--r-sm); cursor: pointer;
  background: transparent; border: none; color: var(--text);
  font-family: var(--sans); font-size: 13.5px; text-align: left;
}
.picker-opt .nome { flex: 1 1 auto; }
.picker-opt .cid { color: var(--text-mute); font-family: var(--mono); font-size: 11px; }
.picker-opt:hover, .picker-opt.attiva { background: rgba(255, 255, 255, .06); }
.picker-opt[aria-selected="true"] .nome { font-weight: 600; }
.picker-opt[aria-selected="true"]::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ice); flex: 0 0 auto;
}
.trace-form select:not(.sr-only):focus, .trace-form input:focus {
  outline: none; border-color: var(--ice); box-shadow: var(--focus);
}
.trace-form input::placeholder { color: var(--text-mute); }
.btn-go {
  padding: 13px 34px; background: var(--fuoco); color: var(--fuoco-ink);
  border: 1px solid var(--fuoco); border-radius: var(--r-md);
  font-family: var(--sans); font-size: 15px; font-weight: 600; letter-spacing: -.01em;
  cursor: pointer; white-space: nowrap; min-width: 168px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .16) inset, 0 6px 18px rgba(var(--fuoco-rgb), .24);
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.btn-go:hover {
  background: var(--fuoco-soft); border-color: var(--fuoco-soft);
  transform: translateY(-1px); box-shadow: 0 8px 22px rgba(var(--fuoco-rgb), .32);
}
.btn-go:active { transform: translateY(0); }
.btn-go:focus-visible {
  outline: none;
  box-shadow: 0 0 0 1px var(--bg), 0 0 0 3px rgba(var(--fuoco-rgb), .60);
}
.btn-go:disabled,
.btn-go:disabled:hover {
  opacity: .55; cursor: default; background: var(--fuoco); border-color: var(--fuoco);
  transform: none; box-shadow: none;
}

/* ----------------------------------------------------------------------------
   Modalita' analisi
   Premuto Traccia, le carte del form restano indietro e questa riga prende il
   loro posto: da dove si torna, e su cosa si sta lavorando. La pagina diventa
   quella della transazione analizzata.
   -------------------------------------------------------------------------- */
.testata-analisi {
  display: flex; align-items: center; gap: 14px 20px; flex-wrap: wrap;
  padding-bottom: 16px; margin-bottom: 22px;
  border-bottom: 1px solid var(--line);
}
.btn-indietro {
  display: inline-flex; align-items: center; gap: 7px; flex: 0 0 auto;
  background: transparent; border: 1px solid var(--line-strong); color: var(--text-dim);
  font-family: var(--sans); font-size: 12.5px; font-weight: 500;
  padding: 7px 13px 7px 10px; border-radius: var(--r-sm); cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease);
}
.btn-indietro:hover {
  color: var(--text); border-color: rgba(255, 255, 255, .24); background: var(--bg-1);
}
.btn-indietro:focus-visible { outline: none; box-shadow: var(--focus); }
.btn-indietro svg { width: 12px; height: 12px; flex: 0 0 auto; }

.ta-cosa { display: flex; align-items: center; gap: 10px 20px; flex-wrap: wrap; min-width: 0; }
.ta-modo { font-size: 14px; font-weight: 600; letter-spacing: -.01em; color: var(--text); }
.ta-voce { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ta-k {
  font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-mute); flex: 0 0 auto;
}
.ta-v {
  font-size: 12.5px; color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ta-v.mono { font-family: var(--mono); letter-spacing: 0; }
.ta-v.copyable { cursor: pointer; transition: color var(--t-fast) var(--ease); }
.ta-v.copyable:hover { color: var(--text); }
.ta-v.ta-catena {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--text); align-self: center;
}

@media (max-width: 700px) {
  .testata-analisi { align-items: flex-start; flex-direction: column; gap: 12px; }
}

/* ============================================================================
   Result states
   ========================================================================== */
/* A riposo questa zona e' vuota e non tiene posto: l'altezza serve alla barra
   per stare al centro. Prima c'era #idle, con la sua lineart, e il vuoto lo
   riempiva senza dire niente. */
#result-region { min-height: 0; }

/* --- loader / trace console --- */
.trace-console {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 0; overflow: hidden;
}
.scan-beam {
  position: relative; height: 1px; background: var(--line); overflow: hidden;
}
.scan-beam::after {
  content: ""; position: absolute; top: 0; left: -35%; height: 1px; width: 35%;
  background: linear-gradient(90deg, transparent, var(--accent-soft), transparent);
  animation: beam 1.6s linear infinite;
}
.scan-beam.paused::after { animation-play-state: paused; }
@keyframes beam { from { left: -35%; } to { left: 100%; } }

.stage-list { list-style: none; margin: 0; padding: 18px 22px; }
.stage {
  display: flex; align-items: baseline; gap: 12px;
  font-family: var(--mono); font-size: 12.5px; letter-spacing: 0;
  color: var(--text-mute); padding: 4px 0;
  transition: color var(--t-med) var(--ease);
}
.stage .ts { color: var(--text-mute); font-size: 11.5px; min-width: 66px; }
.stage .ic { width: 16px; text-align: center; flex: 0 0 auto; }
.stage.active { color: var(--text); }
.stage.done { color: var(--text-dim); }
.stage .spin {
  display: inline-block; width: 11px; height: 11px;
  border: 1.5px solid var(--line-strong); border-top-color: var(--accent-soft);
  border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.stage .check { color: var(--ok); }
.stage.secret.done { color: var(--secret); }
.stage.secret.done .check { color: var(--secret); }

/* ============================================================================
   Result: verdict strip + panels
   ========================================================================== */
.reveal {
  opacity: 0; transform: translateY(4px);
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}
.reveal.in { opacity: 1; transform: none; }

/* Intestazione del risultato: verdetto, titolo, significato e — a destra — le
   azioni. Stavano in fondo alla pagina, dove nessuno le trovava. */
.verdict-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 24px;
  flex-wrap: wrap;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-left: 3px solid var(--text-mute);
  border-radius: var(--r-md);
  padding: 16px 18px; margin-bottom: 16px;
}
.verdict-head.v-ok { border-left-color: var(--ok); }
.verdict-head.v-warn { border-left-color: var(--warn); }
.verdict-head.v-bad { border-left-color: var(--bad); }
.vh-testo { flex: 1 1 420px; min-width: 0; }
.vh-riga { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.vh-titolo {
  margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.02em; color: var(--text);
}
.vh-verso { color: var(--text-mute); font-weight: 400; margin: 0 2px; }
.vh-sotto {
  margin: 5px 0 0; font-family: var(--mono); font-size: 12.5px; color: var(--text-dim);
}
.verdict-head .meaning {
  margin: 9px 0 0; color: var(--text-dim); font-size: 13px; line-height: 1.5; max-width: 74ch;
}
/* Pagina di un caso di ponte: la base di un PROVEN di Bridgers e l'allarme di una dichiarazione smentita, sotto
   il badge. Stessa misura di `.meaning`, ma a colori pieni e con il filetto a sinistra dello stato: la base
   non e' una nota a margine, e senza di lei quel PROVEN non si riferisce. */
.ponte-base, .ponte-allarme {
  margin: 9px 0 0; padding: 6px 10px; font-size: 13px; line-height: 1.5; max-width: 74ch;
  color: var(--text); border-radius: var(--r-sm);
}
.ponte-base { background: var(--ok-bg); border-left: 3px solid var(--ok); }
.ponte-allarme { background: var(--bad-bg); border-left: 3px solid var(--bad); }
.vh-azioni { display: flex; gap: 7px; flex-wrap: wrap; flex: 0 0 auto; padding-top: 2px; }
.vh-azioni button, .vh-azioni a.btn {
  background: transparent; border: 1px solid var(--line-strong); color: var(--text-dim);
  font-family: var(--sans); font-weight: 500; font-size: 12.5px;
  padding: 6px 12px; border-radius: var(--r-sm); cursor: pointer;
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease);
}
.vh-azioni button:hover, .vh-azioni a.btn:hover {
  color: var(--text); background: var(--bg-2); text-decoration: none;
}
.vh-azioni .btn-pdf { color: var(--text); border-color: var(--line-cyan); }

.badge {
  display: inline-block; padding: 3px 10px; border-radius: var(--r-sm);
  font-family: var(--sans); font-size: 12px; font-weight: 600; letter-spacing: .02em;
}
.PROVEN, .DETERMINISTIC { background: var(--ok-bg); color: var(--ok); box-shadow: 0 0 0 1px var(--ok-line) inset; }
.PARTIAL, .UNSCANNED { background: var(--warn-bg); color: var(--warn); box-shadow: 0 0 0 1px var(--warn-line) inset; }
.UNRESOLVED { background: var(--bad-bg); color: var(--bad); box-shadow: 0 0 0 1px var(--bad-line) inset; }

/* ============================================================================
   Sintesi: la lettura corta. Ogni tessera si apre sui valori interi
   ========================================================================== */
.sintesi {
  display: grid; grid-template-columns: 1fr 44px 1fr; gap: 0 0;
  /* Ogni tappa alta quanto il suo contenuto: con le card stirate, aprirne una
     lasciava all'altra un buco vuoto della stessa altezza. */
  align-items: start; margin-bottom: 14px;
}
.tappa {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 16px 18px 14px;
  transition: border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.tappa:hover { border-color: var(--line-cyan); background: var(--bg-2); }
.tappa:focus-visible { box-shadow: var(--focus); outline: none; }
.tp-ruolo { margin: 0 0 4px; font-size: 12px; color: var(--text-mute); }
.tp-chain { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.015em; }
/* L'importo e' il valore: caldo, come l'approdo dove finisce. */
.tp-amount { margin: 1px 0 12px; font-size: 13.5px; font-weight: 500; color: var(--fuoco-soft); }
.tp-righe { display: flex; flex-direction: column; gap: 5px; }
.tp-riga { display: flex; align-items: baseline; gap: 10px; font-size: 12.5px; }
.tp-k { color: var(--text-mute); min-width: 74px; }
.tp-v { color: var(--text); }
/* Allineata alle intestazioni delle due tappe: centrata verticalmente finiva a
   meta' di una card aperta, lontana da cio' che collega. */
.tp-freccia {
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 40px; color: var(--text-mute); font-size: 17px;
}

.approdo {
  grid-column: 1 / -1; margin-top: 12px;
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; border-radius: var(--r-md);
  background: var(--fuoco-bg); border: 1px solid var(--fuoco-line);
  transition: border-color var(--t-fast) var(--ease);
}
.approdo:hover { border-color: var(--fuoco); }
.approdo:focus-visible { box-shadow: var(--focus); outline: none; }
.ap-k { color: var(--fuoco); font-size: 12.5px; font-weight: 500; }
.ap-v { font-size: 13.5px; color: var(--text); }
.ap-base { color: var(--text-mute); font-size: 12px; flex-basis: 100%; }

.giunzione {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  flex-wrap: wrap;
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 15px 18px; margin-bottom: 14px;
  transition: border-color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease);
}
.giunzione:hover { border-color: var(--fuoco-line); background: var(--bg-2); }
.giunzione:focus-visible { box-shadow: var(--focus); outline: none; }
.gi-frase { margin: 0; font-size: 13.5px; color: var(--text); }
.gi-hash { margin: 4px 0 0; font-size: 12.5px; color: var(--fuoco); }
.giunzione .dett, .approdo .dett { flex-basis: 100%; }

/* ============================================================================
   Dettaglio tecnico: dentro la card, non in un pannello a parte
   Sono cinque o sei righe: un drawer a tutta altezza per cosi' poco era un
   contenitore piu' grande del contenuto. La card corta si apre e le mostra.
   ========================================================================== */
.dett {
  margin-top: 14px; padding-top: 13px;
  border-top: 1px solid var(--line);
}
.dett[hidden] { display: none; }
.dett-gruppo + .dett-gruppo { margin-top: 14px; }
.dett-tit {
  margin: 0 0 8px; font-size: 11.5px; font-weight: 500; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-mute);
}
.dett-nota { margin: 0 0 9px; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }
.dett .row { margin-bottom: 10px; }
.dett .row:last-child { margin-bottom: 0; }
.dett .row .v { font-size: 12.5px; line-height: 1.5; word-break: break-all; }

/* Il bottone che apre: dice sempre cosa fara', non cosa e'. */
.tp-piu, .gi-piu, .ap-piu {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 0; margin: 0;
  font-family: var(--sans); font-size: 12.5px; color: var(--text-mute);
  cursor: pointer; transition: color var(--t-fast) var(--ease);
}
.tp-piu { margin-top: 12px; }
.tp-piu::after, .gi-piu::after, .ap-piu::after {
  content: "\203A"; display: inline-block; font-size: 15px; line-height: 1;
  transform: rotate(90deg); transition: transform var(--t-fast) var(--ease);
}
.aperta > .tp-piu::after, .aperta > .gi-testo .gi-piu::after,
.aperta .gi-piu::after, .aperta .ap-piu::after { transform: rotate(-90deg); }
.tappa:hover .tp-piu, .giunzione:hover .gi-piu,
.tp-piu:hover, .gi-piu:hover, .ap-piu:hover { color: var(--accent-soft); }
.tp-piu:focus-visible, .gi-piu:focus-visible, .ap-piu:focus-visible {
  outline: none; box-shadow: var(--focus); border-radius: var(--r-sm);
}

/* Quando si clicca un nodo del grafo, la card corrispondente si apre laggiu':
   un lampo breve dice quale, altrimenti non si capisce cosa e' cambiato. */
@keyframes richiamo {
  0%   { box-shadow: 0 0 0 1px var(--ice), 0 0 0 6px rgba(var(--ice-rgb), .22); }
  100% { box-shadow: 0 0 0 1px transparent, 0 0 0 6px rgba(var(--ice-rgb), 0); }
}
.richiamata { animation: richiamo 1.1s var(--ease) 1; }

/* ── LA SCENA DEL GRAFO ───────────────────────────────────────────────────
   Lo stesso telaio della pagina dell'albero: barra dei comandi in flusso
   sopra, disegno sotto, reticolo sotto il disegno. I comandi non stanno piu'
   sopra la tela — un bottone in `position:absolute` copre un nodo ogni volta
   che il layout arriva in quell'angolo, e nel PNG del fascicolo non c'era
   modo di saperlo.
   `dvh` e non `vh`: su tablet la barra dell'indirizzo che si ritrae
   taglierebbe la tela sotto la piega per tutta la sessione. */
:root {
  /* Il reticolo sotto il grafo. Leggerissimo di proposito: deve dare la
     sensazione di un piano su cui si posano le caselle e sparire appena si
     guarda un nodo. Lo legge graph.js, che ne scrive passo e origine a ogni
     pan e a ogni zoom perche' scorra insieme al disegno. */
  --graph-reticolo: rgba(255, 255, 255, .045);
}

#graph-hero {
  position: relative;
  display: flex; flex-direction: column; min-width: 0;
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  height: clamp(300px, calc(100dvh - 320px), 640px);
  margin-bottom: 16px; overflow: hidden;
}
#graph-hero.v-ok { border-color: var(--ok-line); }
#graph-hero.v-warn { border-color: var(--warn-line); }
#graph-hero.v-bad { border-color: var(--bad-line); }

/* la barra: a sinistra che cosa si puo' fare con la mano, a destra i comandi */
.graph-barra {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px 8px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-1);
}
.graph-vista { font-size: 12px; color: var(--text-mute); min-width: 0; }
.graph-controls { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.graph-controls .cmd {
  height: 28px; min-width: 28px; padding: 0;
  display: grid; place-items: center;
  background: var(--bg-2); color: var(--text-dim);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  font: inherit; font-size: 12.5px; cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease);
}
.graph-controls .cmd svg { width: 14px; height: 14px; }
.graph-controls .cmd:hover { color: var(--text); background: var(--bg-3); }
.graph-controls .cmd:focus-visible { outline: none; box-shadow: var(--focus); }

.graph-host { flex: 1 1 auto; min-height: 0; position: relative; }
#cy { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Il reticolo. Sta SOTTO la tela di Cytoscape (che e' trasparente) e si muove
   col pan/zoom perche' passo e origine glieli riscrive graph.js. Una griglia
   che non segue il grafo non dice "piano di lavoro", dice "carta da parati". */
.graph-griglia {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, var(--graph-reticolo) 1px, transparent 1px),
    linear-gradient(to bottom, var(--graph-reticolo) 1px, transparent 1px);
  transition: opacity 160ms var(--ease);
}

/* l'indicazione dello zoom: minuscola, in un angolo, mai sopra un nodo */
.graph-nota-zoom {
  position: absolute; right: 8px; bottom: 6px; z-index: 4; pointer-events: none;
  font-size: 10.5px; letter-spacing: .01em; line-height: 1; padding: 3px 6px;
  border-radius: var(--r-sm); color: var(--text-mute);
  background: rgba(13, 14, 16, .72);
  background: color-mix(in srgb, var(--bg-1) 78%, transparent);
  opacity: .85; user-select: none;
}

/* Su schermo stretto la frase della barra e i comandi non ci stanno insieme:
   sparisce la frase, che e' un suggerimento, non un comando. */
@media (max-width: 560px) {
  .graph-vista { display: none; }
  #graph-hero { height: clamp(280px, 62dvh, 520px); }
}

.graph-tooltip {
  position: fixed; z-index: 100; pointer-events: none;
  background: var(--bg-3); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 8px 11px; max-width: 340px;
  font-family: var(--mono); font-size: 11.5px; color: var(--text);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .6);
  opacity: 0; transition: opacity var(--t-fast) var(--ease);
}
.graph-tooltip.show { opacity: 1; pointer-events: auto; }
.graph-tooltip .lbl {
  color: var(--text-mute); letter-spacing: 0; text-transform: none;
  font-family: var(--sans); font-size: 11px;
}
.graph-tooltip .val { word-break: break-all; }
.graph-tooltip a { color: var(--cyan); }

/* ---- panels ---- */
.panel {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 16px 20px; margin-bottom: 14px;
  transition: border-color var(--t-fast) var(--ease);
}
.panel h3, .panel > header h3 {
  margin: 0 0 12px; font-family: var(--sans); font-size: 13px; font-weight: 600;
  letter-spacing: -.01em; text-transform: none; color: var(--text); cursor: default;
}

.row { margin-bottom: 9px; }
.row .k {
  font-family: var(--sans); font-size: 11.5px; letter-spacing: 0; text-transform: none;
  color: var(--text-mute); margin-bottom: 2px;
}
.row .v { font-family: var(--mono); font-size: 12.5px; word-break: break-all; color: var(--text); }
.row .v a { color: var(--cyan); }
.small { font-size: 12.5px; color: var(--text-dim); }

/* cryptographic join */
.proof code { font-family: var(--mono); font-size: 12.5px; color: var(--cyan); word-break: break-all; }
.proof .secret-row .v code { color: var(--secret); }
.proof .secret-row .k { color: var(--secret); }

/* checks table */
table.checks-t { width: 100%; border-collapse: collapse; }
table.checks-t td {
  padding: 11px 14px 11px 0; border-top: 1px solid var(--line);
  vertical-align: top; font-size: 13px;
}
table.checks-t tr:first-child td { border-top: none; }
table.checks-t td.n { color: var(--text-mute); width: 26px; font-family: var(--mono); font-size: 12px; }
table.checks-t td.name { width: 260px; font-weight: 500; }
table.checks-t td.res {
  width: 96px; font-family: var(--sans); font-size: 12px; font-weight: 600; white-space: nowrap;
}
table.checks-t td.res svg { vertical-align: middle; margin-right: 5px; }
table.checks-t td.basis { color: var(--text-dim); font-size: 12.5px; word-break: break-word; }
.sw-stato { color: var(--text-mute); font-style: italic; }
.sw-escrow { display: block; color: var(--text-mute); font-size: 12px; margin-top: 2px; }
.res.PASS { color: var(--ok); }
.res.FAIL { color: var(--bad); }
.res.NA { color: var(--warn); }
/* NOT RUN non e' n/a e non e' FAIL: il controllo non e' stato eseguito. Colore
   proprio, corsivo e sottolineatura punteggiata, perche' la differenza deve
   reggere anche a monitor scadente o stampato in bianco e nero. */
.res.NOTRUN { color: var(--notrun); font-style: italic; text-decoration: underline dotted; }
.checks-legenda {
  margin: 10px 0 0; color: var(--notrun); font-size: 12.5px; font-style: italic; line-height: 1.45;
}

/* Timelocks: lista verticale. Sull'asse orizzontale sette etichette finivano
   una sull'altra e il pannello era illeggibile. */
.tl-lista { list-style: none; margin: 0 0 12px; padding: 0; }
.tl-riga {
  position: relative;
  display: grid; grid-template-columns: 18px 96px 1fr auto; align-items: baseline;
  gap: 10px; padding: 7px 0;
}
.tl-riga + .tl-riga { border-top: 1px solid var(--line); }
.tl-punto {
  width: 7px; height: 7px; border-radius: 50%; background: var(--text-mute);
  justify-self: center; align-self: center;
}
.tl-origine .tl-punto { background: var(--ok); }
.tl-origine .tl-nome { color: var(--text); font-weight: 600; }
.tl-ora { font-size: 12px; color: var(--text-dim); }
.tl-nome { font-size: 13px; color: var(--text); }
.tl-delta { font-size: 12px; color: var(--text-mute); }

/* evidence */
.evidence .kv { display: grid; grid-template-columns: 150px 1fr; gap: 6px 14px; font-size: 13px; }
.evidence .kv .k {
  font-family: var(--sans); font-size: 11.5px; letter-spacing: 0; text-transform: none;
  color: var(--text-mute);
}
.evidence .kv .v { font-family: var(--mono); font-size: 12px; word-break: break-all; }
.evidence code { font-family: var(--mono); color: var(--cyan); }

details.panel > summary {
  list-style: none; cursor: pointer;
  font-family: var(--sans); font-size: 13px; font-weight: 600; letter-spacing: -.01em;
  text-transform: none; color: var(--text); display: flex; align-items: center; gap: 8px;
}
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary::before {
  content: "›"; color: var(--text-mute); font-size: 15px; line-height: 1;
  display: inline-block; transition: transform var(--t-fast) var(--ease);
}
details.panel[open] > summary::before { transform: rotate(90deg); }
details.panel > summary:hover { color: var(--accent-soft); }
details.panel .details-body { margin-top: 14px; }

/* notes */
.notes { margin: 0; padding-left: 18px; color: var(--text-dim); font-size: 13px; }
.notes li { margin-bottom: 5px; }

/* sweep table */
table.sweep { width: 100%; border-collapse: collapse; margin-top: 8px; }
table.sweep th {
  text-align: left; font-family: var(--sans); font-size: 11.5px; letter-spacing: 0;
  text-transform: none; color: var(--text-mute); font-weight: 500;
  padding: 8px 12px; border-bottom: 1px solid var(--line);
}
table.sweep td { padding: 10px 12px; border-bottom: 1px solid var(--line); font-size: 13px; }
table.sweep tr.hit { background: var(--ok-bg); }
table.sweep tr.hit td:first-child { color: var(--ok); font-weight: 600; }
table.sweep td.mono { font-family: var(--mono); font-size: 12.5px; word-break: break-all; }
table.sweep td.mono a { color: var(--cyan); }
.miss { color: var(--text-mute); }
.failed { color: var(--warn); }

pre.report {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 16px; overflow-x: auto; font-family: var(--mono); font-size: 12px; margin-top: 14px;
  white-space: pre-wrap; word-break: break-word; color: var(--text-dim); line-height: 1.65;
}

/* status / errors */
.status { color: var(--text-dim); font-size: 13px; min-height: 20px; margin: 6px 0 12px; }
.status.err {
  color: var(--bad); border: 1px solid var(--bad-line); background: var(--bad-bg);
  border-radius: var(--r-sm); padding: 9px 12px;
}

/* toast */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(8px);
  background: var(--bg-3); border: 1px solid var(--line-strong); color: var(--text);
  font-family: var(--sans); font-size: 12.5px; letter-spacing: 0; text-transform: none;
  padding: 8px 16px; border-radius: var(--r-sm); z-index: 200;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* copyable items */
.copyable { cursor: pointer; }
.copyable:hover .v, .copyable:hover code { text-decoration: underline dotted; text-underline-offset: 3px; }

/* ============================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1100px) {
  .param { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 880px) {
  .sintesi { grid-template-columns: 1fr; gap: 10px; }
  .tp-freccia { padding: 2px 0; transform: rotate(90deg); }
  .verdict-head { gap: 14px; }
  .tl-riga { grid-template-columns: 18px 1fr auto; }
  .tl-riga .tl-ora { grid-column: 2; }
  .param { grid-template-columns: 1fr; }
  .cf-piede { flex-direction: column; align-items: stretch; gap: 14px; }
  .cf-piede .btn-go { width: 100%; }
  header.topbar .brandtag .app { display: none; }
  /* Il menu resta intero: e' l'orientamento, e non c'e' niente da guadagnare
     a nasconderlo. Cede spazio quel che gli sta attorno. */
  .topbar-nav { gap: 4px; margin-left: 2px; }
  .topbar-link { padding: 5px 8px; }
  .topbar-riservato { gap: 8px; }
}
@media (max-width: 560px) {
  table.checks-t td.name { width: auto; }
  table.checks-t, table.checks-t tbody, table.checks-t tr, table.checks-t td { display: block; width: auto; }
  table.checks-t tr { border-top: 1px solid var(--line); padding: 8px 0; }
  table.checks-t tr:first-child { border-top: none; }
  table.checks-t td { border-top: none; padding: 2px 0; }
  .evidence .kv { grid-template-columns: 1fr; }
  /* Il badge NON sparisce piu' a questa larghezza, ed e' cambiata la ragione,
     non il gusto: da quando e' un link a «Il mio uso» e' l'unico ingresso a
     quella sezione, e nasconderlo qui la renderebbe irraggiungibile da
     telefono. Sparisce invece l'etichetta «op:», che era la meta' ridondante —
     il nome accanto alla spia verde si legge da se'. */
  .op { gap: 5px; font-size: 0; }
  .op b { font-size: 12.5px; }
  /* Il marchio perde la parola e tiene il glifo. Non e' una rinuncia al brand:
     la riga era piena e qualcosa doveva uscire, e fra il nome del prodotto —
     che a questa larghezza il titolo della pagina ripete comunque — e il nome
     di chi sta lavorando, quello che serve mentre si lavora e' il secondo.
     Con la parola dentro, la banda andava a tre righe (125px di testata
     appiccicata in cima a un telefono); senza, ne bastano due. */
  header.topbar .brandtag .poly { display: none; }
  header.topbar .banda { height: auto; padding-top: 8px; padding-bottom: 8px; flex-wrap: wrap; }
  header.topbar .spacer { display: none; }
  .topbar-nav { order: 3; width: 100%; }
  .topbar-nav .menu-voce { flex: 1 1 0; text-align: center; }
  /* La nota accanto al link all'altra pagina e' un aiuto, non un dato: alla
     larghezza di un telefono il link sta meglio da solo. */
  .modo-nota { display: none; }
}

/* ============================================================================
   Stampa
   ========================================================================== */
/* Quel che si stampa di POLY e' un referto, non una schermata: il menu, il
   selettore di modalita' e il toast sono attrezzi per stare a schermo e su
   carta sono solo inchiostro sprecato. */
@media print {
  header.topbar,
  .modo-altro,
  .switch,
  .eyebrow-row,
  .lingua,
  .logout-form,
  .toast,
  .graph-tooltip { display: none !important; }
  body.shell { background: #fff; color: #000; }
  .shell-main { padding-top: 0; }
}

/* ---- la home e la barra: stanno in home.css (vetrina, 10-C-BARRA). Qui c'erano la barra di Zen,
   lo switch Trace / Solana / Hashlock e la scena che li centrava: tolti con zen.js e #manuale. ---- */

/* ---- l'anello: dall'analisi all'albero, e ritorno --------------------- */
.ap-albero, .sw-albero {
  display: inline-block; margin-top: 6px; font-size: 12.5px; color: var(--fuoco-soft);
  text-decoration: none; border-bottom: 1px dotted var(--fuoco-line);
}
.ap-albero:hover, .sw-albero:hover { color: var(--fuoco); border-bottom-style: solid; }
.sw-albero { margin: 0 0 0 8px; font-family: var(--sans); }
.ap-nota { display: block; margin-top: 4px; font-size: 11.5px; color: var(--text-mute); }
