/* ============================================================
   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);}}

.login-screen{min-height:100vh;display:flex;align-items:center;justify-content:center;
  background:var(--bg);padding:24px;}
.login-card{width:100%;max-width:380px;background:var(--card);border:1px solid var(--border);
  border-radius:16px;padding:30px 28px;box-shadow:var(--shadow);}
.login-brand{display:flex;align-items:center;gap:10px;margin-bottom:22px;}
.login-card h1{font-size:21px;font-weight:800;letter-spacing:-.02em;margin:0 0 6px;}
.login-note{font-size:13px;color:var(--muted);margin:0 0 20px;line-height:1.5;}
.login-card form{display:flex;flex-direction:column;gap:7px;}
.login-card label{font-size:11.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);}
.login-card input{border:1px solid var(--border);border-radius:10px;padding:10px 12px;font-size:14px;
  font-family:inherit;background:var(--card);color:var(--text);width:100%;box-sizing:border-box;}
.login-card input:focus{outline:2px solid var(--primary-mid);outline-offset:1px;border-color:var(--primary);}
.login-card .btn{justify-content:center;margin-top:6px;padding:11px 14px;}
/* I pulsanti dentro al modulo si allargano da soli (la colonna flessibile
   li stira); quelli fuori — Google, «usa un altro indirizzo», «riprova» —
   sarebbero larghi quanto la loro parola. Stessa azione, stessa forma. */
.login-card > .btn{width:100%;box-sizing:border-box;}
.login-card a.btn{text-decoration:none;}
.login-sep{display:flex;align-items:center;gap:10px;margin:18px 0 14px;color:var(--muted);font-size:11.5px;}
.login-sep::before,.login-sep::after{content:'';flex:1;height:1px;background:var(--border);}
.login-foot{font-size:12.5px;color:var(--muted);margin:14px 0 0;min-height:1.2em;line-height:1.5;}
/* La riga del codice a sei cifre nasce nascosta e compare quando il
   server lo chiede. **Una classe, non un `#id`**: `.u-hidden` e' una
   classe, e un selettore di id la batte in specificita' — con
   `#loginTotpRow{display:flex}` il campo restava a schermo sempre, e lo
   vedeva anche chi la verifica in due passaggi non ce l'ha. Si vede solo
   guardando la pagina: il markup era giusto. */
.login-totp{display:flex;flex-direction:column;gap:7px;}
.login-hint{font-size:12px;color:var(--muted);margin:2px 0 0;line-height:1.45;}
/* Google: stessa altezza del pulsante primario, con il suo marchio a
   sinistra. Il marchio non si ritinge — e' di qualcun altro — quindi qui
   non c'e' nessun `color` che lo tocchi. */
.login-google{display:flex;align-items:center;justify-content:center;gap:9px;}
.login-google svg{flex-shrink:0;}
/* ---- i due canali dei messaggi ----
   Sotto al campo va quello che non torna in **quello che hai scritto**;
   nel riquadro in cima al modulo va quello che e' **successo quando
   abbiamo provato**. Non si sovrappongono mai, perche' non rispondono
   alla stessa domanda.

   Il riquadro sta **sopra al pulsante**, che e' dove l'occhio torna dopo
   averlo premuto. Prima era una riga grigia in fondo alla scheda, sotto
   ai link: la stessa informazione, nel posto dove non la legge nessuno.

   I toni sono le coppie di §2 — fondo tenue piu' inchiostro forte — che
   si rovesciano da sole di notte. Un pieno con del testo chiaro sopra,
   qui, di notte sparirebbe. */
.login-alert{display:flex;gap:9px;align-items:flex-start;margin:0 0 16px;padding:11px 13px;
  border-radius:11px;font-size:12.5px;line-height:1.45;}
.login-alert svg{width:15px;height:15px;flex-shrink:0;margin-top:1px;}
.login-alert.errore{background:var(--red-soft);color:var(--red-dark);}
.login-alert.avviso{background:var(--amber-soft);color:var(--amber-dark);}
.login-alert.info{background:var(--primary-soft);color:var(--primary-dark);}
/* Il posto c'e' sempre, anche vuoto: si riempie senza ridisegnare. Vuoto
   non deve occupare spazio, se no il modulo respira a scatti. */
.login-fielderr:empty{display:none;}

/* L'etichetta e la sua scorciatoia sulla stessa riga: «entra con un
   link» e' un'alternativa alla password, e sta dove si decide se
   scriverla. */
.login-labelrow{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}
.login-labelrow .login-link{width:auto;margin:0;font-size:11.5px;text-align:right;}

/* Una riga sola in fondo, e non un pulsante: chiedere l'accesso lo fa
   una persona sola una volta sola. Sottolineata solo l'azione. */
.login-ask{margin:18px 0 0;text-align:center;font-size:12.5px;color:var(--muted);}
.login-ask .login-link{display:inline;width:auto;margin:0;font-size:inherit;}

/* L'errore sta attaccato al campo che lo riguarda, non in fondo alla
   scheda: una nota a pie' di pagina sotto al pulsante non la lega
   nessuno al campo che ha sbagliato. */
.login-err{font-size:12.5px;color:var(--red-dark);margin:2px 0 0;line-height:1.45;}
.login-card input[aria-invalid="true"]{border-color:var(--red);}
/* «Il link e' partito»: non e' piu' un modulo, e non deve sembrarlo. */
.login-done{text-align:center;padding:4px 0 2px;}
.login-done .ic{display:inline-flex;align-items:center;justify-content:center;
  width:46px;height:46px;border-radius:50%;background:var(--primary-soft);color:var(--primary-dark);
  margin-bottom:12px;}
.login-done .ic svg{width:22px;height:22px;}
.login-done h1{margin-bottom:6px;}
.login-done .login-note{margin-bottom:6px;}

/* Le due righe su di se': lo stesso vestito dei campi, con l'altezza
   che serve a due frasi e niente maniglia per tirarlo — a una domanda
   piccola non si risponde con un tema. */
.login-card textarea{border:1px solid var(--border);border-radius:10px;padding:10px 12px;font-size:14px;
  font-family:inherit;background:var(--card);color:var(--text);width:100%;box-sizing:border-box;resize:none;}
.login-card textarea:focus{outline:2px solid var(--primary-mid);outline-offset:1px;border-color:var(--primary);}
/* Il segnaposto di Google spento: e' li' per dire che esiste, non per
   invitare a premerlo. */
.login-card .btn:disabled{opacity:.55;cursor:default;}

/* La terza strada: un pulsante che sembra un link, perche' e' quello che
   e'. Non porta da nessuna parte, cambia il modo della scheda. */
.login-link{display:block;width:100%;margin:16px 0 0;padding:0;border:0;background:none;
  font-family:inherit;font-size:12.5px;color:var(--primary-dark);text-align:center;cursor:pointer;
  text-decoration:underline;text-underline-offset:2px;}
.login-link:hover{color:var(--primary-deep);}
.login-link:disabled{color:var(--muted);cursor:default;text-decoration:none;}
.login-link:focus-visible{outline:2px solid var(--primary-mid);outline-offset:3px;border-radius:6px;}

/* 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;}
