/* **Prima di sapere chi guarda non si mostra niente.**

   L'avvio disegnava il guscio — la barra laterale con tutte le voci, la
   testata, lo scheletro della pagina — e *poi* chiedeva al server se ci
   fosse una sessione. In locale quella risposta arriva in dieci
   millisecondi e non si vede mai; dietro a un dominio vero sono due o
   tre decimi di secondo, e chi arriva sulla porta vede l'applicazione
   aperta per un attimo prima della schermata di accesso. Non usciva
   nessun dato — i riquadri sono grigi e ogni chiamata senza cookie si
   prende un 401 — ma dice «sei dentro» a chi non lo e', ed e' la prima
   cosa che vede.

   `visibility` e non `display`: lo spazio resta preso, quindi quando il
   guscio compare non spinge niente e la testata e' gia' dov'era. E' la
   stessa promessa che tiene in piedi lo scheletro d'avvio. */
body.jt-avvio .app{visibility:hidden;}

/* ============================================================
   L'ATTESA, L'ACCESSO E IL SALVATAGGIO
   I tre momenti in cui l'app non sta mostrando dati: il primo fotogramma
   (lo scheletro di `boot-skeleton.js`), la schermata di accesso, e la
   barra che dice che si sta salvando.

   Stanno insieme perche' sono la stessa domanda — cosa vede chi aspetta
   — e perche' li tocca sempre la stessa persona nello stesso momento.
   ============================================================ */

/* ============================================================
   ACCESSO, AVVIO E STATO DI SALVATAGGIO
   ============================================================ */

/* Attesa iniziale: i dati arrivano dalla rete, e disegnare l'app con le
   collezioni ancora vuote mostrerebbe "nessun dato" quando non e' vero. */
.boot-wait{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  min-height:60vh;color:var(--muted);font-size:14px;}
.boot-spin{width:22px;height:22px;border:2.5px solid var(--track);border-top-color:var(--primary);
  border-radius:50%;animation:boot-turn .7s linear infinite;}
.boot-error{color:var(--text);font-weight:600;}
@keyframes boot-turn{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion:reduce){.boot-spin{animation-duration:2.4s;}}

/* ---- L'attesa a elementi: la forma della pagina prima dei dati ----
   Chi sceglie «A elementi» nel profilo vede la struttura in grigio invece
   del cerchietto: quando i dati arrivano niente salta di posizione, perche'
   le righe erano gia' li'. Le misure sono finte ma verosimili, e nessuno
   deve poterle leggere come dati: `aria-hidden` sul contenitore. */
/* La barretta grigia col riflesso che scorre e' un pezzo a se': la usa
   l'attesa vera (`.ld-skel`) e la usa l'anteprima nelle Impostazioni, che
   deve far vedere esattamente la stessa cosa in piccolo. Legata al
   contenitore, l'anteprima restava un riquadro vuoto. */
.ld-bar{background:var(--track);border-radius:4px;height:8px;position:relative;overflow:hidden;}
.ld-bar.block{height:26px;border-radius:9px;}
.ld-bar::after{content:'';position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,var(--hover),transparent);animation:ld-shimmer 1.4s infinite;}
@keyframes ld-shimmer{100%{transform:translateX(100%);}}
@media (prefers-reduced-motion:reduce){.ld-bar::after{animation:none;}}

/* ---- lo scheletro dell'avvio ----
   Ha la forma della pagina che sta per aprirsi, non una forma qualsiasi:
   quando i dati arrivano, quello che c'era gia' resta dov'era. Le misure
   grandi (altezze dei blocchi, larghezze delle barre) le scrive
   `bootSkeletonSizes` leggendo i `data-`, cosi' nel markup non entra un
   attributo `style`. */
.ld-page{display:flex;flex-direction:column;gap:14px;}
/* Una barra al posto di una parola: alta quanto la riga di testo che
   sostituira', cosi' la scatola di riga e' gia' quella definitiva e
   niente si sposta quando le parole arrivano. */
.ld-txt{display:inline-block;height:1em;vertical-align:-0.12em;border-radius:5px;}
/* Il posto dei pulsanti della pagina, largo quanto erano l'ultima volta. */
.ld-topfill{display:inline-block;height:36px;border-radius:10px;}
.ld-toolbar{display:flex;gap:10px;align-items:center;}
.ld-toolbar .ld-bar{height:30px;border-radius:9px;}
.ld-kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;}
.ld-kpis .ld-card{height:92px;}
.ld-cols{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:14px;align-items:start;}
.ld-grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;}
.ld-band{display:block;height:64px;border-radius:var(--radius);background:var(--card);border:1px solid var(--border);}
.ld-tabs{display:flex;gap:16px;align-items:center;}
.ld-board{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px;align-items:start;}
.ld-col{background:var(--hover);border-radius:14px;padding:10px;display:flex;flex-direction:column;gap:10px;}
.ld-deal{display:block;height:116px;border-radius:14px;background:var(--card);border:1px solid var(--border);}
.ld-tabs .ld-bar{height:11px;}
.ld-set{display:grid;grid-template-columns:minmax(0,220px) minmax(0,1fr);gap:14px;align-items:start;}
.ld-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:16px;display:flex;flex-direction:column;gap:12px;}
.ld-block{display:block;border-radius:10px;background:var(--track);}
.ld-row{display:flex;align-items:center;gap:12px;}
/* il fondo della barra, al primo fotogramma */
.ld-dock{display:block;height:44px;border-radius:12px;background:var(--track);}
.ld-urow{display:flex;align-items:center;gap:10px;padding:6px 8px;}
.ld-av{width:32px;height:32px;border-radius:50%;background:var(--track);flex-shrink:0;}
.ld-dot{width:28px;height:28px;border-radius:9px;background:var(--track);flex-shrink:0;}
.ld-rowtxt{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;}
.ld-rowtxt .w1{width:46%;}
.ld-rowtxt .w2{width:26%;height:7px;}
@media(max-width:900px){
  .ld-kpis{grid-template-columns:repeat(2,minmax(0,1fr));}
  .ld-cols,.ld-set,.ld-grid2{grid-template-columns:minmax(0,1fr);}
  .ld-board{grid-template-columns:repeat(2,minmax(0,1fr));}
}

.ld-skel{display:flex;flex-direction:column;gap:11px;padding:6px 0;}
.ld-skel .ld-bar:nth-child(3n+1){width:42%;}
.ld-skel .ld-bar:nth-child(3n+2){width:100%;}
.ld-skel .ld-bar:nth-child(3n){width:78%;}

/* Una scrittura in corso verso il server: sottile, in alto, non blocca nulla. */
.app.is-syncing::before{content:'';position:fixed;top:0;left:0;right:0;height:2px;z-index:60;
  background:linear-gradient(90deg,var(--primary-soft),var(--primary),var(--primary-soft));
  background-size:200% 100%;animation:sync-slide 1.1s linear infinite;}
@keyframes sync-slide{to{background-position:-200% 0;}}
@media (prefers-reduced-motion:reduce){.app.is-syncing::before{animation:none;background:var(--primary);}}

/* La schermata d'accesso ha il suo foglio: `login.css`. */

/* Il pulsante di uscita sta accanto al profilo, discreto finché non serve. */
.profile-exit svg{width:15px;height:15px;}

/* Il selettore dell'app: l'icona o il pallino di una voce prendono la
   tinta dal dato (il colore di un cliente, di una categoria). Arriva in
   `--tint`, controllata, e se manca resta il grigio di sempre. */
.aselect-tinted{color:var(--tint,var(--muted));}
.aselect-dot{background:var(--tint,var(--muted));}
.aselect-lead{width:14px;height:14px;flex-shrink:0;color:var(--tint,var(--muted));}
.aselect-label.aselect-none{color:var(--muted);}
.dlg-sub{font-size:13.5px;color:var(--muted);margin:-8px 0 18px 0;}

/* Le sei tinte con cui si distinguono le persone dello studio. Sono le
   stesse coppie dei toni, prese in giro da una funzione di dispersione:
   qui hanno un numero perche' e' quello che la funzione sa produrre. */
.crm-p0{background:var(--primary-soft);color:var(--primary-dark);}
.crm-p1{background:var(--blue-soft);color:var(--blue);}
.crm-p2{background:var(--violet-soft);color:var(--violet);}
.crm-p3{background:var(--green-soft);color:var(--green-dark);}
.crm-p4{background:var(--pink-soft);color:var(--pink);}
.crm-p5{background:var(--amber-soft);color:var(--amber-dark);}

.adp-month{text-transform:capitalize;font-size:12.5px;}
.type-icon{background:color-mix(in srgb, var(--tint,var(--primary)) 13%, transparent);color:var(--tint,var(--primary));}
.type-icon.lg{background:color-mix(in srgb, var(--tint,var(--primary)) 15%, transparent);}
.kpi-sw-nonbill{background:var(--nonbill);}
.kpi-sw-bill{background:var(--primary);}
.modal.confirm{max-width:380px;}
