/* =====================================================================
   Elettromaster — style.css
   Conforme a DESIGN_SYSTEM.md: scuro di default, flat, denso,
   glass SOLO sui livelli flottanti (dialog / popover / drawer / topbar).
   Nessun !important in tutto il file: se serve, la specificita' e' sbagliata.
   ===================================================================== */

:root{
  /* BRAND — unica variabile da cambiare per progetto (DS §14) */
  --accent:#0ea5e9;
  --accent-contrast:#ffffff;
  /* Calcolata, non fissata: con un rgba() non seguirebbe l'accento
     personalizzato che head.php inietta da settings.accent. */
  --accent-soft:color-mix(in srgb, var(--accent) 8%, transparent);

  /* superfici (tema scuro) */
  --app-bg:#0a0a0f;
  --sidebar-bg:#0a0a14;
  --card-bg:#0f0f1a;
  --input-bg:#0a0a0f;
  --row-hover:rgba(127,127,127,.05);
  --header-bg:#0d0d16;

  /* bordi */
  --border:#1f1f2e;
  --border-2:#2a2a3d;

  /* testo */
  --text:#e4e4ef;
  --text-dim:#8b8ba3;
  --text-muted:#6b6b83;

  /* semantici — mai un letterale nel resto del file */
  --success:#22c55e;
  --warning:#f59e0b;
  --danger:#ef4444;
  --info:#3b82f6;

  /* raggi — scala, non un valore unico */
  --radius-sm:6px;
  --radius:8px;
  --radius-lg:12px;
  --radius-xl:16px;
  --space-card:16px;   /* spazio standard TRA le card, in ogni direzione (gap/margine) */
  --radius-pill:999px;

  /* tipografia */
  --font:'Inter', system-ui, -apple-system, sans-serif;
  --mono:ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;

  /* livelli — scala unica, mai numeri a caso */
  --z-popover:60;
  --z-menu:200;
  --z-drawer:900;
  --z-dialog:1000;
  --z-lightbox:1100;
  --z-tooltip:1200;
}

[data-theme="light"]{
  --accent:#0284c7;              /* ricalibrato: contrasto su fondo chiaro */
  --app-bg:#f0f4f8;
  --sidebar-bg:#ffffff;
  --card-bg:#ffffff;
  --input-bg:#f8fafc;
  --row-hover:#f1f5f9;
  --header-bg:#f1f5f9;
  --border:#e2e8f0;
  --border-2:#cbd5e1;
  --text:#1a1a2e;
  --text-dim:#64748b;
  --text-muted:#94a3b8;
  --danger:#dc2626;
  --success:#16a34a;
}

/* ---------------- Base ---------------- */
*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; }
body{
  font-family:var(--font);
  font-size:13px;
  background:var(--app-bg);
  color:var(--text);
  -webkit-font-smoothing:antialiased;
}
a{ color:inherit; text-decoration:none; }
h1,h2,h3{ margin:0; font-weight:700; }
h1{ font-size:20px; }
h2{ font-size:17px; }
.text-dim{ color:var(--text-dim); }
.text-muted{ color:var(--text-muted); }
.mono{ font-variant-numeric:tabular-nums; }
.nowrap{ white-space:nowrap; }
.ico{ display:block; }

/* Focus visibile ovunque: mai togliere l'outline senza rimpiazzarlo. */
:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius:var(--radius-sm);
}
/* Su touch il focus torna al pulsante che ha aperto un dialog (Cambia, edit…)
   alla chiusura, e il ring di :focus-visible resta appiccicato: sommato al
   bordo del pulsante sembra un DOPPIO bordo. Su coarse pointer i pulsanti non
   mostrano il ring — non c'e' una tastiera da seguire — mentre gli input, che
   il ring lo usano davvero, lo tengono. */
@media (pointer: coarse){
  .btn:focus-visible, .icon-btn:focus-visible{ box-shadow:none; }
}

/* ---------------- Layout ---------------- */
.app{ display:flex; min-height:100vh; }
.content{ flex:1; min-width:0; display:flex; flex-direction:column; }
.page{ padding:20px 24px; max-width:1280px; width:100%; margin:0 auto; }

/* ---------------- Sidebar ---------------- */
.sidebar{
  width:240px; flex:0 0 240px;
  background:var(--sidebar-bg);
  border-right:1px solid var(--border);
  display:flex; flex-direction:column;
  position:sticky; top:0; height:100vh;
  transition:width .18s ease;
}
.sb-collapsed .sidebar{ width:64px; flex-basis:64px; }
.sb-brand{
  display:flex; align-items:center; gap:10px;
  /* Stessa altezza della .topbar (60px): i due bordi in cima devono
     allinearsi in una linea sola. Padding verticale 0, l'altezza la fa
     min-height e il contenuto e' centrato. */
  min-height:60px; padding:0 16px; border-bottom:1px solid var(--border);
}
/* Logo rotondo e cliccabile: apre/chiude il menu. E' un <button>, quindi
   si azzerano gli stili nativi. Da compresso resta lui (l'hamburger sparisce)
   ed e' il solo modo per riespandere: un controllo che si nasconde nello
   stato che crea sarebbe un vicolo cieco (MIGLIORIE 3.6). */
.sb-logo{
  width:32px; height:32px; border-radius:50%;
  /* background-color/size longhand, non lo shorthand: se il sito ha un logo
     caricato lo mostriamo come background-image, e lo shorthand azzererebbe
     il cover (stessa trappola degli avatar, MIGLIORIE 3.4). */
  background-color:var(--accent); color:var(--accent-contrast);
  background-size:cover; background-position:center;
  display:grid; place-items:center; flex:0 0 32px; overflow:hidden;
  border:0; padding:0; cursor:pointer;
}
.sb-name{ font-weight:700; font-size:15px; white-space:nowrap; }
.sb-collapse{ margin-left:auto; }
.sb-collapsed .sb-name,
.sb-collapsed .sb-collapse,
.sb-collapsed .sb-label,
.sb-collapsed .sb-user-info{ display:none; }
.sb-collapsed .sb-brand{ justify-content:center; padding:0; }

.sb-nav{ padding:10px 8px; display:flex; flex-direction:column; gap:2px; overflow-y:auto; flex:1; }
.sb-item{
  display:flex; align-items:center; gap:11px;
  padding:9px 11px; border-radius:7px;
  color:var(--text-dim); font-weight:500;
  /* bordo trasparente di base: l'attivazione non deve spostare il testo */
  border-left:3px solid transparent; white-space:nowrap;
}
.sb-item:hover{ background:var(--accent-soft); color:var(--text); }
.sb-item.active{
  color:var(--text); background:var(--accent-soft);
  border-left-color:var(--accent);
}
.sb-ico{ flex:0 0 18px; display:grid; place-items:center; color:inherit; }
.sb-collapsed .sb-item{ justify-content:center; padding:10px 0; border-left-color:transparent; }

/* Divisore di sezione: una pillola col solo bordo, testo maiuscolo tenue e
   spaziato, che stacca i gruppi di voci. Non è cliccabile e non si evidenzia.
   La sidebar segue il tema (scura o bianca): i colori vengono dai token, non
   da un bianco-trasparente fisso, o sul tema chiaro sparirebbero. L'etichetta
   è libera: il divisore si ripete con testi diversi (DS §11). */
.sb-divider{
  display:flex; align-items:center; gap:0;
  /* -8px annulla il padding orizzontale del .sb-nav: così la riga arriva ai
     bordi veri della sidebar, non si ferma prima. */
  margin:16px -8px 7px; pointer-events:none; user-select:none;
}
.sb-divider-pill{
  flex:0 0 auto;
  border:1px solid color-mix(in srgb, var(--text-muted) 42%, transparent);
  border-radius:999px; padding:2px 8px;
  font-size:7px; font-weight:600; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-muted); white-space:nowrap;
}
/* Riga hairline continua: tocca i bordi della sidebar e i due lati della
   pillola (gap:0), centrata in verticale (align-items:center). La pillola è a
   SINISTRA: il tratto sinistro è fisso a 20px (col margine negativo il
   divisore parte dal bordo, quindi la pillola resta 20px dal bordo), quello
   destro riempie tutto il resto. */
.sb-divider::before{ content:''; flex:0 0 15px; height:1px; background:color-mix(in srgb, var(--text-muted) 25%, transparent); }
.sb-divider::after{ content:''; flex:1 1 auto; height:1px; background:color-mix(in srgb, var(--text-muted) 25%, transparent); }
/* Da compressa (solo desktop, 64px) la pillola sparisce: i due tratti formano
   una linea continua a tutta larghezza. */
.sb-collapsed .sb-divider{ margin:12px -8px 7px; }
.sb-collapsed .sb-divider-pill{ display:none; }

.sb-foot{ border-top:1px solid var(--border); padding:10px 8px; display:flex; flex-direction:column; gap:8px; }
/* Il blocco utente e' un link al proprio profilo: cursore, hover e stato
   attivo come le voci di menu. L'ingranaggio a destra dice che ci si clicca. */
.sb-user{ display:flex; align-items:center; gap:9px; padding:6px; border-radius:var(--radius);
  color:inherit; text-decoration:none; cursor:pointer; transition:background .12s; }
.sb-user:hover{ background:var(--accent-soft); }
.sb-user.active{ background:var(--accent-soft); }
.sb-user-info{ display:flex; flex-direction:column; min-width:0; line-height:1.2; flex:1; }
.sb-user-name{ font-weight:600; font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sb-user-role{ font-size:11px; color:var(--text-dim); }
.sb-user-gear{ display:flex; color:var(--text-dim); flex:0 0 auto; }
.sb-user:hover .sb-user-gear{ color:var(--text); }
.sb-collapsed .sb-user-gear{ display:none; }
.avatar{
  width:30px; height:30px; border-radius:50%; flex:0 0 30px;
  display:grid; place-items:center; color:#fff; font-weight:700; font-size:12px;
  background-size:cover; background-position:center;
}
.sb-theme .th-light{ display:none; }
[data-theme="light"] .sb-theme .th-dark{ display:none; }
[data-theme="light"] .sb-theme .th-light{ display:block; }

.sb-overlay{ display:none; }

/* ---------------- Topbar ---------------- */
/* Unica superficie non flottante con backdrop-filter, ed e' deliberato:
   il contenuto le scorre sotto, quindi si comporta come un livello. */
.topbar{
  display:flex; align-items:center; gap:12px;
  /* Altezza uguale a .sb-brand (60px, padding verticale via min-height +
     align-items) cosi' i due bordi inferiori formano UNA linea continua in
     cima, invece di due segmenti sfalsati. Se cambi qui, cambia anche la'. */
  min-height:60px; padding:0 24px; border-bottom:1px solid var(--border);
  position:sticky; top:0;
  background:color-mix(in srgb, var(--app-bg) 88%, transparent);
  backdrop-filter:blur(8px); z-index:20;
}
.page-title-wrap{ display:flex; align-items:center; gap:10px; min-width:0; }
/* Badge dell'icona di sezione accanto al titolo: pieno d'accento, icona
   bianca (come il logo). La forma segue il raggio standard. */
.page-title-ico{
  width:30px; height:30px; flex:0 0 30px; border-radius:6px;
  background:var(--accent); color:var(--accent-contrast);
  display:grid; place-items:center;
}
/* Anteprima del logo nelle impostazioni: stesso componente del menu, più
   grande per vederlo bene. Il logo caricato copre il fondo d'accento. */
.logo-set{ display:flex; align-items:center; gap:16px; margin-bottom:4px; }
.logo-anteprima{ width:56px; height:56px; flex:0 0 56px; }
.logo-anteprima svg{ width:26px; height:26px; }
.page-title{ font-size:18px; }
.topbar-spacer{ flex:1; }
.topbar-user{ display:flex; align-items:center; gap:8px; }
.topbar-user a.saluto{ text-decoration:none; }
.topbar-user a.saluto:hover strong{ color:var(--accent); }
.topbar-user .saluto{ font-size:13px; color:var(--text-dim); white-space:nowrap; }
.topbar-user .saluto strong{ color:var(--text); font-weight:600; }

/* ---------------- Buttons ---------------- */
.btn{
  display:inline-flex; align-items:center; gap:7px;
  background:var(--accent); color:var(--accent-contrast); border:none;
  border-radius:var(--radius); padding:8px 14px;
  font-size:13px; font-weight:600; cursor:pointer; font-family:inherit;
  transition:filter .12s ease;
}
.btn:hover{ filter:brightness(1.12); }
.btn:active{ transform:scale(.97); }
.btn:disabled{ background:var(--border-2); color:var(--text-muted); cursor:not-allowed; filter:none; }
.btn.secondary{ background:transparent; color:var(--text); border:1px solid var(--border-2); }
.btn.secondary:hover{ background:var(--accent-soft); filter:none; }
.btn.danger{ background:var(--danger); color:#fff; }
.btn.sm{ padding:6px 12px; font-size:12px; }

.icon-btn{
  display:inline-grid; place-items:center;
  width:34px; height:34px; border-radius:var(--radius);
  background:transparent; border:1px solid transparent; color:var(--text-dim);
  cursor:pointer; font-family:inherit;
}
.icon-btn:hover{ background:var(--accent-soft); color:var(--text); }
/* Mappa azione -> colore (DS §4): elimina e' l'unica distruttiva, quindi
   e' rossa gia' a riposo. Le altre si colorano solo al hover, altrimenti
   ogni riga della tabella diventa un arcobaleno. */
.icon-btn.act-delete{ color:var(--danger); }
.icon-btn.act-delete:hover{ background:color-mix(in srgb, var(--danger) 12%, transparent); color:var(--danger); }
.icon-btn.act-edit:hover{ color:var(--accent); }
.icon-btn.act-warn:hover{ color:var(--warning); }

/* ---------------- Cards & KPI ---------------- */
.card{
  background:var(--card-bg); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:18px;
}
/* Margine generoso prima del primo campo: preferenza esplicita (DS §8). */
.card-title{ font-size:17px; margin-bottom:20px; }
.grid{ display:grid; gap:14px; }
.kpis{ grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); }
.kpi{
  background:var(--card-bg); border:1px solid var(--border);
  border-radius:var(--radius-lg); padding:16px 18px;
  display:flex; flex-direction:column; gap:6px;
}
.kpi-top{ display:flex; align-items:center; gap:8px; color:var(--text-muted); }
.kpi-ico{
  width:30px; height:30px; border-radius:var(--radius);
  display:grid; place-items:center;
  background:var(--accent-soft); color:var(--accent);
}
.kpi-label{ font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; }
.kpi-value{ font-size:24px; font-weight:800; line-height:1; font-variant-numeric:tabular-nums; white-space:nowrap; }
.kpi-sub{ font-size:11px; color:var(--text-dim); }

/* ---------------- Tables ---------------- */
.table-wrap{ background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden; }
.toolbar{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:12px 14px; border-bottom:1px solid var(--border);
}
.toolbar .spacer{ flex:1; }
/* Gruppo di filtri nella toolbar (picker affiancati che ricaricano). */
.toolbar-filtri{ display:flex; align-items:center; gap:8px; margin:0; }

/* Icona allegato: accesa in accento quando il file c'e', spenta e non
   cliccabile quando manca. Si legge a colpo d'occhio chi ha la ricevuta. */
.icon-btn.has-file{ color:var(--accent); }
.icon-btn.no-file{ color:var(--text-muted); cursor:default; }
.icon-btn.no-file:hover{ background:transparent; color:var(--text-muted); }
.search{
  display:flex; align-items:center; gap:7px;
  background:var(--input-bg); border:1px solid var(--border-2);
  border-radius:var(--radius); padding:6px 10px; color:var(--text-muted);
  min-width:200px;
}
/* Il selettore aggiunge [type] di proposito: le regole globali input[type=…]
   (piu' in basso nel foglio) hanno la STESSA specificita' di ".search input" e,
   venendo dopo, le ri-applicavano bordo e sfondo dentro il wrapper → doppio
   bordo. `.search input[type]` (0,2,1) batte qualunque input[type=…] (0,1,1)
   indipendentemente dall'ordine, per OGNI tipo (text, search…): prima era
   coperto solo il type=search e le ricerche con type=text (es. Cantieri)
   avevano ancora il doppio bordo. -webkit-appearance:none toglie anche la
   cornice nativa del type=search. */
.search input,
.search input[type]{
  -webkit-appearance:none; appearance:none;
  border:none; background:transparent; color:var(--text);
  outline:none; box-shadow:none; font-size:13px; width:100%; font-family:inherit; padding:0;
}
.table-scroll{ overflow-x:auto; }

/* Tag d'ingresso al cantiere (colonna Ubicazione): è un PULSANTE per entrare
   nella scheda, quindi ha padding più generoso e feedback all'hover, non un
   semplice testo colorato. */
.loc-link{ display:inline-block; border-radius:var(--radius); text-decoration:none; transition:background .12s; }
.loc-link .chip{ padding:5px 10px; font-size:12.5px; cursor:pointer; }
.loc-link:hover{ background:var(--accent-soft); }
.loc-link:hover .chip{ border-color:var(--border-2); }

/* Pannello «Impostazioni» del cantiere: si apre dal pulsante in testa e fa
   scendere la pagina (blocco in flusso, non overlay). */
.cant-impost{
  /* Sfondo del PANNELLO più scuro (app-bg): così le card interne (card-bg)
     staccano, invece di confondersi con lo stesso colore. */
  background:var(--app-bg); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:16px; margin-bottom:var(--space-card);
}
.cant-impost-form{ display:flex; flex-direction:column; gap:var(--space-card); }
.cant-impost .field{ margin-bottom:0; }
.cant-impost-grid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
/* Impostazioni in CARD su due colonne 50/50: Cantiere, Cliente, Direttore
   lavori, Ditta edile, Fatturazione. Ogni card impila i suoi campi con gap. */
/* Due colonne a MASONRY (multi-column): le card si impaccano una sotto l'altra
   senza allinearsi per riga → niente buchi dove una card è più corta. */
.cant-impost-cards{ columns:2; column-gap:var(--space-card); }
.cant-impost-card{ display:flex; flex-direction:column; gap:10px; margin:0 0 var(--space-card); break-inside:avoid; }
.cant-impost-tit{ font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; margin:0 0 4px; }
@media (max-width:760px){ .cant-impost-cards{ columns:1; } }
.cant-impost-sep{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-muted); margin-top:6px; }
.cant-impost-az{ display:flex; justify-content:flex-end; gap:8px; margin-top:8px; }
@media (max-width:680px){ .cant-impost-grid{ grid-template-columns:1fr; } }

/* Documento di vendita cumulativo del cantiere. */
.cant-doc{ background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-lg); padding:16px; margin-top:var(--space-card); }
.tbl-doc{ width:100%; }
.tbl-doc tfoot td{ font-variant-numeric:tabular-nums; padding-top:6px; }
.tbl-doc-tot td{ font-weight:700; font-size:15px; border-top:1px solid var(--border); }

/* ---- Cantieri: layout master-detail (seconda sidebar + dettaglio) ---- */
.page.page-cantieri{ max-width:none; padding:0; flex:1 1 auto; min-height:0; display:flex; flex-direction:column; overflow:hidden; }
.cant-layout{ flex:1 1 auto; min-height:0; display:flex; }
.cant-side{ flex:0 0 264px; display:flex; flex-direction:column; min-height:0; border-right:1px solid var(--border); background:var(--card-bg); }
.cant-side-head{ display:flex; gap:8px; align-items:center; padding:12px 12px 8px; }
.cant-side-head .search{ flex:1; min-width:0; }
.cant-side-nuovo{ flex:0 0 auto; padding:8px 10px; }
.cant-side-chiusi{ padding:0 12px 10px; font-size:12px; }
.cant-side-list{ flex:1 1 auto; overflow-y:auto; padding:0 8px 10px; display:flex; flex-direction:column; gap:6px; }
.cant-card{ display:flex; align-items:center; gap:10px; padding:8px; border:1px solid var(--border); border-radius:var(--radius); background:var(--app-bg); text-decoration:none; color:var(--text); }
.cant-card:hover{ border-color:var(--border-2); background:var(--accent-soft); }
.cant-card.is-active{ border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.cant-card-ico{ flex:0 0 40px; width:40px; height:40px; border-radius:var(--radius-sm); overflow:hidden; display:grid; place-items:center; background:var(--card-bg); color:var(--text-dim); border:1px solid var(--border); }
.cant-card-ico img{ width:100%; height:100%; object-fit:cover; }
/* Icona «cantieri» colorata col colore scelto del cantiere (al posto del pallino).
   La colora `color:` inline perché l'SVG usa stroke=currentColor. */
.cant-ico-col{ display:inline-flex; align-items:center; }
.cant-card-body{ min-width:0; display:flex; flex-direction:column; gap:4px; }
.cant-card-nome{ font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; display:flex; align-items:center; gap:6px; }
.cant-card-nome .dot{ flex:0 0 auto; width:8px; height:8px; }
/* Tag stato cantiere: verde (aperto) / rosso (chiuso) — bordo + fondo tenue,
   niente puntino. Deriva da is_closed, non dal colore libero dello stato. */
/* Nel dettaglio (section-head, flex a righe) niente align-self: si allinea in
   verticale al nome grazie all'align-items:center del contenitore. */
.stato-tag{ display:inline-flex; align-items:center; padding:2px 9px; border-radius:var(--radius-pill); font-size:11.5px; font-weight:600; border:1px solid; white-space:nowrap; }
.stato-tag.is-aperto{ color:var(--success); border-color:color-mix(in srgb, var(--success) 55%, transparent); background:color-mix(in srgb, var(--success) 14%, transparent); }
.stato-tag.is-chiuso{ color:var(--danger); border-color:color-mix(in srgb, var(--danger) 55%, transparent); background:color-mix(in srgb, var(--danger) 14%, transparent); }
/* Nella card della sidebar: più piccolo e allineato a sinistra sotto il nome. */
.cant-card .stato-tag{ align-self:flex-start; font-size:10px; padding:1px 7px; }
/* Pill dell'azione nel Log: stessa forma dello stato, colore inline per azione
   (verde=creazione, ambra=modifica, rosso=eliminazione, azzurro=accesso…). */
.log-pill{ display:inline-flex; align-items:center; padding:2px 9px; border-radius:var(--radius-pill); font-size:11.5px; font-weight:700; border:1px solid; white-space:nowrap; }

/* Mfiltro: filtro multi-scelta a interruttori (EM.initMfiltro). Il bottone è
   un picker; quando è filtrato (non tutti attivi) si accende col bordo accento. */
.mfiltro{ position:relative; }
.mfiltro .picker.is-attivo{ border-color:var(--accent); color:var(--accent); }
.mf-menu{ min-width:200px; }
.mf-head{ display:flex; align-items:center; gap:8px; padding:2px 8px 8px; border-bottom:1px solid color-mix(in srgb, var(--text) 10%, transparent); margin-bottom:4px; }
.mf-azione{ background:none; border:0; padding:2px 2px; font:inherit; font-size:12px; color:var(--accent); cursor:pointer; }
.mf-azione:hover{ text-decoration:underline; }
.mf-sep{ color:var(--text-muted); }
.mf-lista{ display:flex; flex-direction:column; gap:1px; max-height:320px; overflow-y:auto; }
/* Riga = toggle a piena larghezza: pallino, etichetta che spinge, interruttore
   a destra. È un .toggle (input nascosto + .track), quindi tutta la riga clicca. */
.mf-riga{ display:flex; align-items:center; gap:8px; width:100%; padding:6px 8px; border-radius:var(--radius-sm); }
.mf-riga:hover{ background:var(--accent-soft); }
.mf-riga .mf-lab{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px; }
/* Interruttore più piccolo del default (38×22): qui è accanto a una scritta di
   13px e a piena grandezza sovrastava la voce. 30×16 col pomello da 12.
   Selettore con DUE classi (.mf-riga.toggle) per battere `.toggle .track`, che
   sta più in basso nel file: a parità di specificità vincerebbe lui. */
.mf-riga.toggle .track{ flex:0 0 30px; width:30px; height:16px; }
.mf-riga.toggle .track::after{ width:12px; height:12px; }
.mf-riga.toggle input:checked + .track::after{ transform:translateX(14px); }

/* Scorciatoie di periodo del Log: control segmentato di bottoncini; l'attivo
   in accento. Sta nella toolbar accanto alle date (per l'intervallo su misura). */
.log-periodo{ display:inline-flex; border:1px solid var(--border-2); border-radius:var(--radius-sm); overflow:hidden; }
.log-per{ background:var(--input-bg); border:0; border-left:1px solid var(--border-2); padding:7px 11px; font:inherit; font-size:12.5px; color:var(--text-dim); cursor:pointer; white-space:nowrap; }
.log-per:first-child{ border-left:0; }
.log-per:hover{ background:var(--accent-soft); color:var(--text); }
.log-per.is-on{ background:var(--accent); color:#fff; }
/* Selettore magazzino nella toolbar (quando ce n'è più d'uno). */
.mag-sel{ font-size:14px; font-weight:600; padding:7px 10px; border:1px solid var(--border-2); border-radius:var(--radius); background:var(--input-bg); color:var(--text); cursor:pointer; }
/* Nome cliente cliccabile in tabella (→ scheda cliente). */
.cli-nome{ color:var(--text); font-weight:600; text-decoration:none; }
.cli-nome:hover{ color:var(--accent); text-decoration:underline; }
/* Select nativo dentro il pannello impostazioni (es. cliente dall'anagrafica). */
.cant-select{ width:100%; font-size:14px; padding:9px 11px; border:1px solid var(--border-2); border-radius:var(--radius); background:var(--input-bg); color:var(--text); cursor:pointer; }
.cant-select:focus{ outline:none; border-color:var(--accent); }
.cant-detail{ flex:1 1 auto; min-width:0; overflow-y:auto; padding:20px 24px; }
.cant-detail.is-caricando{ opacity:.45; pointer-events:none; transition:opacity .1s; }
/* Toggle-pill in testata: mostrano/nascondono Info, Documento, Movimenti. */
.cant-toggles{ display:flex; gap:6px; flex-wrap:wrap; }
.cant-tg{
  font-size:11.5px; font-weight:600; padding:4px 11px; border-radius:var(--radius-pill);
  border:1px solid var(--border-2); background:var(--app-bg); color:var(--text-muted); cursor:pointer;
}
.cant-tg:hover{ color:var(--text); border-color:var(--text-muted); }
.cant-tg.is-on{ background:var(--accent); border-color:var(--accent); color:#fff; }
/* Card info principale del cantiere (cliente, direttore lavori, IVA…). */
.cant-info{ margin-bottom:var(--space-card); }
.cant-info-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(190px, 1fr)); gap:12px 22px; }
.cant-info-lbl{ display:block; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-muted); margin-bottom:2px; }
.cant-info-val{ font-size:13.5px; color:var(--text); }
@media (max-width:760px){
  .cant-layout{ flex-direction:column; }
  .cant-side{ flex:0 0 auto; max-height:40vh; border-right:0; border-bottom:1px solid var(--border); }
}

/* Entrata rapida di materiale nella scheda cantiere (movimenti in blocco):
   righe prodotto+quantità (aggiunta) o articolo+residuo+usati (consumo). */
.dlg-bulk{ width:min(560px, 94vw); }
.bulk-riga{ display:flex; align-items:center; gap:8px; margin-bottom:8px; }
.bulk-prod{ flex:1; min-width:0; }
.bulk-prod, .bulk-qta{
  font-size:13px; padding:7px 9px; border:1px solid var(--border-2); border-radius:var(--radius-sm);
  background:var(--input-bg); color:var(--text); font-family:inherit;
}
.bulk-qta{ width:92px; flex:0 0 92px; text-align:right; }
/* Consumato inline nella tabella articoli (salvataggio live al change). */
.qta-consumo{
  width:74px; text-align:right; font-size:13px; padding:4px 6px; font-family:inherit;
  border:1px solid var(--border-2); border-radius:var(--radius-sm);
  background:var(--input-bg); color:var(--warning); font-variant-numeric:tabular-nums;
}
.qta-consumo:focus{ outline:none; border-color:var(--accent); }
.qta-consumo:disabled{ opacity:.5; }

table{ width:100%; border-collapse:collapse; }
thead th{
  text-align:left; padding:10px 12px;
  font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-muted); background:var(--header-bg);
  border-bottom:1px solid var(--border); white-space:nowrap;
}
tbody td{ padding:10px 12px; font-size:13px; border-bottom:1px solid var(--border); }
tbody tr:last-child td{ border-bottom:none; }
/* Riga di totale: staccata dal corpo e su fondo intestazione. */
tfoot td{ padding:10px 12px; font-size:13px; border-top:2px solid var(--border-2); background:var(--header-bg); }
tbody tr:hover{ background:var(--row-hover); }
/* Allineamento per tipo di dato, non per colonna (DS §7). */
.num{ text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.ctr{ text-align:center; }
.row-actions{ display:flex; gap:4px; justify-content:flex-end; }
.sku{ font-family:var(--mono); font-size:12px; color:var(--text-dim); }

/* Header ordinabili: il click cicla asc -> desc -> naturale. */
th.sortable{ cursor:pointer; user-select:none; }
th.sortable:hover{ color:var(--text); }
th.sortable::after{ content:''; margin-left:5px; font-size:10px; }
th.sortable[data-dir="asc"]::after{ content:'▴'; }
th.sortable[data-dir="desc"]::after{ content:'▾'; }

/* Righe speciali */
tr.row-alert td{ background:color-mix(in srgb, var(--danger) 5%, transparent); }
tr.is-hidden{ display:none; }

/* ---------------- Pills / chips ---------------- */
.pill{
  display:inline-flex; align-items:center; gap:5px;
  padding:2px 8px; border-radius:var(--radius-pill);
  font-size:12px; font-weight:700; border:1px solid transparent;
  white-space:nowrap;
}
.dot{ width:7px; height:7px; border-radius:50%; display:inline-block; flex:0 0 7px; }
.chip{
  display:inline-flex; align-items:center; gap:6px;
  padding:2px 8px; border-radius:var(--radius-sm); font-size:11.5px;
  background:var(--app-bg); border:1px solid var(--border); white-space:nowrap;
}

/* Chips-search: input di ricerca + token multipli (multi-select con
   autocompletamento — vedi initChips in app.js). La casella replica un input
   di testo; i token scelti sono .chip, il campo interno filtra, il menu a
   comparsa (glass, come il popover) mostra i risultati non ancora scelti. */
.chips-field{ position:relative; }
.chips-box{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px;
  background:var(--input-bg); border:1px solid var(--border-2);
  border-radius:var(--radius-sm); padding:6px 8px; min-height:38px; cursor:text;
}
.chips-box:focus-within{
  border-color:var(--accent);
  box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}
/* display:contents: il wrapper sparisce dal layout e i .chip diventano item
   flex della casella, così vanno a capo insieme al campo di ricerca. */
.chips-list{ display:contents; }
.chips-chip{ padding-right:3px; }
.chip-x{
  display:inline-flex; align-items:center; justify-content:center;
  border:0; background:none; padding:0; margin-left:1px;
  color:var(--text-dim); cursor:pointer; border-radius:50%;
}
.chip-x:hover{ color:var(--danger); }
/* Il campo interno non è un input a sé stante: azzera larghezza/bordo/fondo/
   focus della regola base input[type=text] e vive DENTRO la casella. */
.chips-box .chips-input{
  flex:1 1 130px; width:auto; min-width:110px;
  border:0; background:none; padding:2px; box-shadow:none;
}
.chips-box .chips-input:focus{ border:0; box-shadow:none; }
.chips-menu{
  position:absolute; left:0; right:0; top:calc(100% + 4px); z-index:var(--z-popover);
  max-height:240px; overflow-y:auto; padding:6px; color:var(--text);
  background:color-mix(in srgb, var(--card-bg) 92%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  border:1px solid color-mix(in srgb, var(--text) 12%, transparent);
  border-radius:var(--radius-lg); box-shadow:0 20px 50px rgba(0,0,0,.4);
}
.chips-menu[hidden]{ display:none; }
.chips-opt{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left;
  padding:8px 10px; border:0; background:transparent; border-radius:var(--radius-sm);
  font-size:13px; color:var(--text); cursor:pointer; font-family:inherit;
}
.chips-opt:hover,.chips-opt.is-active{ background:var(--accent-soft); }
.chips-opt-meta{ margin-left:auto; font-size:11px; color:var(--text-dim); }
.chips-empty{ padding:14px 10px; text-align:center; color:var(--text-muted); font-size:12px; }

/* ---------------- Forms ---------------- */
.field{ display:flex; flex-direction:column; gap:5px; margin-bottom:14px; }
.field label,
label.lbl{
  font-size:11px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--text-muted);
}
/* Stesso stile dentro e fuori i dialog: nessuna variante per contenitore. */
input[type=text],input[type=email],input[type=password],input[type=number],
input[type=date],input[type=datetime-local],input[type=search],input[type=tel],textarea{
  width:100%; background:var(--input-bg); border:1px solid var(--border-2);
  border-radius:var(--radius-sm); padding:8px 12px; font-size:13px; color:var(--text);
  font-family:inherit; outline:none;
}
/* Textarea: crescono da sole col testo (altezza gestita da EM.autogrow) e
   restano ridimensionabili a mano solo in verticale — orizzontale romperebbe
   il layout. min-height: non collassano sotto una riga. */
textarea{ resize:vertical; min-height:38px; line-height:1.5; }
/* iOS/Safari fa auto-zoom quando si mette a fuoco un input con font-size < 16px,
   e poi tocca all'utente ristringere a due dita. Su touch (coarse pointer) tutti
   i campi di testo vanno a 16px: niente zoom automatico. Su desktop restano
   densi a 13px. 16px e' la soglia esatta, non un valore a caso. */
@media (pointer: coarse){
  input[type=text],input[type=email],input[type=password],input[type=number],
  input[type=date],input[type=datetime-local],input[type=search],input[type=tel],
  textarea, select{ font-size:16px; }
}
input:focus,textarea:focus{
  border-color:var(--accent);
  box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}
/* Selettore colore nativo: alto come un input, lo swatch a tutta larghezza. */
.input-colore{
  width:100%; height:38px; padding:4px;
  background:var(--input-bg); border:1px solid var(--border-2);
  border-radius:var(--radius-sm); cursor:pointer;
}
textarea{ resize:vertical; }
.form-row{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.hint{ font-size:11px; color:var(--text-dim); }
.err{ font-size:12px; color:var(--danger); }

/* Checkbox custom. Niente backdrop-filter qui: causa flickering reale
   durante lo scroll (bug osservato, non teorico). */
input[type=checkbox]{
  appearance:none; -webkit-appearance:none;
  width:16px; height:16px; flex:0 0 16px; margin:0;
  border:1px solid var(--border-2); border-radius:4px;
  background:var(--input-bg); cursor:pointer; position:relative;
}
input[type=checkbox]:checked{ background:var(--accent); border-color:var(--accent); }
input[type=checkbox]:checked::after{
  content:''; position:absolute; left:5px; top:1.5px;
  width:4px; height:8px; border:solid #fff; border-width:0 2px 2px 0;
  transform:rotate(45deg);
}

/* Toggle switch: l'input resta nel DOM e nel tab order, spostato fuori
   schermo — display:none lo toglierebbe dalla navigazione da tastiera. */
.toggle{ display:inline-flex; align-items:center; gap:9px; cursor:pointer; }
.toggle input{ position:absolute; left:-9999px; }
.toggle .track{
  width:38px; height:22px; border-radius:var(--radius-pill);
  background:var(--border-2); position:relative; transition:background .15s ease; flex:0 0 38px;
}
.toggle .track::after{
  content:''; position:absolute; top:2px; left:2px;
  width:18px; height:18px; border-radius:50%; background:#fff;
  box-shadow:0 1px 3px rgba(0,0,0,.3); transition:transform .15s ease;
}
.toggle input:checked + .track{ background:var(--accent); }
.toggle input:checked + .track::after{ transform:translateX(16px); }
.toggle input:focus-visible + .track{ box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }

/* Campo password con occhiello */
.pw-wrap{ position:relative; }
.pw-wrap input{ padding-right:40px; }
.pw-wrap .icon-btn{ position:absolute; right:3px; top:50%; transform:translateY(-50%); width:30px; height:30px; }

/* Campo importo: simbolo in overlay, non dentro il valore */
.eur-wrap{ position:relative; }
.eur-wrap::before{
  content:'€'; position:absolute; left:11px; top:50%; transform:translateY(-50%);
  color:var(--text-muted); font-size:13px; pointer-events:none;
}
.eur-wrap input{ padding-left:26px; }

/* Picker: sostituisce il <select> nativo (DS §11). Il valore vero sta
   nell'input hidden accanto; questo bottone e' solo la faccia visibile. */
.picker{
  width:100%; display:flex; align-items:center; gap:8px;
  background:var(--input-bg); border:1px solid var(--border-2);
  border-radius:var(--radius-sm); padding:8px 12px;
  font-size:13px; font-family:inherit; color:var(--text);
  cursor:pointer; text-align:left; min-height:35px;
}
.picker:hover{ border-color:var(--accent); }
.picker .picker-val{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.picker.is-empty .picker-val{ color:var(--text-muted); }
.picker .picker-caret{ color:var(--text-muted); flex:0 0 auto; display:grid; }

/* ---------------- Livelli flottanti (glass) ---------------- */
dialog{
  border:1px solid color-mix(in srgb, var(--text) 12%, transparent);
  border-radius:var(--radius-xl); padding:22px;
  background:color-mix(in srgb, var(--card-bg) 78%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  box-shadow:0 24px 70px rgba(0,0,0,.35), 0 0 0 1px rgba(255,255,255,.03) inset;
  color:var(--text); width:420px; max-width:calc(100vw - 32px); max-height:85vh;
  overflow:auto;
}
dialog[open]{ animation:dlg-pop .14s ease-out; }
dialog::backdrop{ background:rgba(10,10,15,.45); backdrop-filter:blur(3px); }
@keyframes dlg-pop{ from{ opacity:0; transform:translateY(-6px) scale(.97); } }

/* Larghezze per tipo (DS §6) */
dialog.dlg-confirm{ width:360px; }
dialog.dlg-prompt{ width:400px; }
dialog.dlg-img{ width:460px; }
dialog.dlg-wide{ width:640px; }

.dialog-head{ font-size:16px; font-weight:600; margin-bottom:16px; }
.dialog-body{ font-size:13px; line-height:1.5; }
.dialog-actions{ display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
/* Nel dialog di conferma le azioni sono centrate e i pulsanti larghi
   uguali: la scelta e' binaria, nessuna delle due va sminuita. */
dialog.dlg-confirm .dialog-actions{ justify-content:center; }
dialog.dlg-confirm .dialog-actions .btn{ min-width:112px; justify-content:center; }
.confirm-ico{
  width:44px; height:44px; border-radius:50%; display:grid; place-items:center;
  margin:0 auto 14px; background:color-mix(in srgb, var(--danger) 12%, transparent); color:var(--danger);
}
.confirm-ico.neutral{ background:var(--accent-soft); color:var(--accent); }
.dlg-confirm .dialog-body{ text-align:center; }
.dlg-error{ margin-top:12px; }

/* Crop circolare */
dialog.dlg-crop{ width:340px; }
.crop-viewport{
  width:280px; height:280px; margin:0 auto;
  position:relative; overflow:hidden; border-radius:50%;
  background:var(--app-bg);
  /* Bordo legato a --text (scuro su tema chiaro, chiaro su tema scuro) + alone
     soft: sul tema scuro un `--border-2` sottile spariva e non si vedeva dove
     cadrà il ritaglio. */
  border:1px solid color-mix(in srgb, var(--text) 32%, transparent);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--text) 8%, transparent);
  cursor:grab; touch-action:none;    /* il drag non deve far scrollare la pagina */
}
.crop-viewport.quadrato{ border-radius:var(--radius-lg); }
/* Ritaglio dei componenti (rettangolo): angoli quasi squadrati, un componente
   è un rettangolo tecnico, non una foto stondata. */
.crop-viewport.rett{ border-radius:3px; }
.crop-viewport:active{ cursor:grabbing; }
.crop-viewport img{ position:absolute; max-width:none; user-select:none; }
/* Linee-guida verticali dell'ingombro (un tratto per confine di modulo) nel
   ritaglio delle immagini dei componenti. Colore accento: le foto prodotto
   sono quasi sempre su fondo bianco, dove un tratto chiaro sparirebbe. */
.crop-guida{
  position:absolute; top:0; bottom:0; width:0; z-index:2; pointer-events:none;
  border-left:1.5px dashed color-mix(in srgb, var(--accent) 75%, transparent);
}
.crop-hint{ text-align:center; margin:12px 0 8px; }
.crop-ingombro{ text-align:center; margin:12px 0 0; }
.crop-zoom-row{ display:flex; align-items:center; gap:8px; }
.crop-zoom-row input[type=range]{ flex:1; accent-color:var(--accent); }
.crop-zoom-val{ font-size:12px; color:var(--text-dim); min-width:34px; text-align:right; font-variant-numeric:tabular-nums; }
.link-btn{
  display:block; margin:10px auto 0; background:none; border:none;
  color:var(--text-dim); font-size:12px; font-family:inherit;
  text-decoration:underline; cursor:pointer; padding:0;
}
.link-btn:hover{ color:var(--accent); }

/* Popover / menu */
.popover{
  position:fixed; z-index:var(--z-popover);
  /* Il popover viene promosso nel top layer con la Popover API (vedi
     app.js). La UA stylesheet dei [popover] impone inset:0 e margin:auto
     per centrarli: qui il posizionamento e' calcolato, quindi vanno
     annullati o left/top verrebbero ignorati. */
  right:auto; bottom:auto; margin:0;
  min-width:200px; max-width:340px;
  max-height:min(560px, calc(100vh - 190px));
  display:flex; flex-direction:column;
  /* color esplicito: lo UA stylesheet dei [popover] impone color:CanvasText
     (nero), che rompe l'ereditarieta' dal body. Senza questo, il testo che
     non fissa un proprio colore (es. .popover-riga) esce nero e su tema
     scuro non si legge. Vale come per i <dialog>. */
  color:var(--text);
  background:color-mix(in srgb, var(--card-bg) 88%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  border:1px solid color-mix(in srgb, var(--text) 12%, transparent);
  border-radius:var(--radius-lg);
  box-shadow:0 20px 50px rgba(0,0,0,.4);
  padding:6px;
}
.pop-search{ padding:4px 4px 8px; }
.pop-search input{ padding:6px 10px; }
.pop-list{ overflow-y:auto; display:flex; flex-direction:column; gap:1px; }
.pop-item{
  display:flex; align-items:center; gap:8px;
  padding:8px 10px; border-radius:var(--radius-sm);
  font-size:13px; color:var(--text); cursor:pointer;
  border:none; background:transparent; font-family:inherit; text-align:left; width:100%;
}
.pop-item:hover{ background:var(--accent-soft); }
.pop-item.is-sel{ box-shadow:inset 0 0 0 1px var(--accent); color:var(--accent); }
.pop-group{
  padding:9px 10px 4px; font-size:10.5px; font-weight:800;
  text-transform:uppercase; letter-spacing:.06em; color:var(--text-muted);
}
.pop-empty{ padding:14px 10px; text-align:center; color:var(--text-muted); font-size:12px; }

/* Drawer destro: un solo guscio, riusato per contenuti diversi. */
.drawer-overlay{
  position:fixed; inset:0; z-index:var(--z-drawer);
  background:rgba(10,10,15,.45); backdrop-filter:blur(2px);
  /* Da chiuso l'overlay resta nel DOM (per la transizione di opacita') ma NON
     deve catturare i clic: opacity:0 lo rende invisibile, non innocuo. Senza
     pointer-events:none un <div> fixed inset:0 a opacita' 0 copre l'intera
     pagina e ne intercetta OGNI clic, restando invisibile. */
  opacity:0; pointer-events:none; transition:opacity .25s ease;
}
.drawer-overlay.is-open{ opacity:1; pointer-events:auto; }
.drawer{
  /* Sopra il proprio overlay: senza z-index il drawer (auto) restava DIETRO
     l'overlay (z-index --z-drawer) e non era cliccabile. */
  position:fixed; top:0; right:0; height:100vh; width:620px; max-width:94vw;
  z-index:calc(var(--z-drawer) + 1);
  background:color-mix(in srgb, var(--card-bg) 92%, transparent);
  backdrop-filter:blur(20px) saturate(160%);
  border-left:1px solid color-mix(in srgb, var(--text) 12%, transparent);
  display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform .25s ease;
}
.drawer.is-open{ transform:translateX(0); }
.drawer-head{
  display:flex; align-items:center; gap:10px;
  padding:16px 18px; border-bottom:1px solid var(--border); font-size:16px; font-weight:600;
}
.drawer-body{ flex:1; overflow-y:auto; padding:18px; }
/* Su touch la tastiera virtuale copre la meta' bassa dello schermo. L'ultimo
   campo del drawer (di solito l'editor Note) non riesce a salire sopra la
   tastiera perche' sotto di lui non c'e' niente da scrollare: la sua testata
   resta tagliata. Un fondo ampio da' lo spazio di scorrimento per portarlo in
   vista. scroll-padding-top lascia invece lo spazio della testata del drawer
   quando un campo va a fuoco, cosi' l'etichetta non finisce sotto l'header. */
@media (pointer: coarse){
  .drawer-body{ scroll-padding-top:80px; padding-bottom:40vh; }
}

/* Lightbox */
/* Il lightbox e' un <dialog> (top layer): azzero gli stili nativi del dialog
   (bordo, padding, margin auto, max-width) e lo faccio a tutto schermo. */
.lightbox{
  position:fixed; inset:0; z-index:var(--z-lightbox);
  width:100vw; height:100vh; max-width:100vw; max-height:100vh; margin:0; border:0;
  background:rgba(8,12,22,.92); display:grid; place-items:center;
  cursor:zoom-out; padding:20px;
}
.lightbox::backdrop{ background:transparent; }   /* il fondo scuro lo fa il dialog stesso */
.lightbox img{ max-width:92vw; max-height:80vh; border-radius:var(--radius); }

/* ---------------- Upload & dropzone ---------------- */
.dropzone{
  border:2px dashed var(--border-2); border-radius:var(--radius-lg);
  padding:22px 18px; text-align:center; color:var(--text-dim);
  cursor:pointer; transition:border-color .12s ease, background .12s ease;
}
.dropzone:hover{ border-color:var(--text-muted); }
/* Tre stati distinti: hover, "il file sta arrivando davvero", occupata. */
.dropzone.is-dragover{ border-color:var(--accent); background:var(--accent-soft); color:var(--text); }
.dropzone.is-busy{ opacity:.6; pointer-events:none; }
.up-list{ display:flex; flex-direction:column; gap:8px; margin-top:12px; }

/* Filedrop: allegato di un form (trascina-o-clicca, senza upload subito).
   Piu' compatto della dropzone, ma stessi tre stati. E' una <label>. */
.filedrop{
  display:flex; align-items:center; gap:10px;
  border:2px dashed var(--border-2); border-radius:var(--radius);
  padding:12px 14px; color:var(--text-dim); cursor:pointer;
  transition:border-color .12s ease, background .12s ease, color .12s ease;
}
.filedrop:hover{ border-color:var(--text-muted); }
.filedrop.is-dragover{ border-color:var(--accent); background:var(--accent-soft); color:var(--text); }
.filedrop.has-file{ border-style:solid; border-color:var(--border-2); color:var(--text); }
/* Dropzone grande dentro il dialog "Carica foto": verticale, con piu' aria. */
.filedrop-grande{ flex-direction:column; text-align:center; gap:8px; padding:34px 18px; }
.filedrop-ico{ display:grid; place-items:center; color:var(--text-dim); flex:0 0 auto; }
.filedrop.has-file .filedrop-ico{ color:var(--accent); }
.filedrop-testo{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.up-item{ display:flex; align-items:center; gap:10px; font-size:12px; }
.up-nome{ flex:0 0 auto; max-width:180px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.up-thumb{
  width:36px; height:36px; flex:0 0 36px; border-radius:var(--radius-sm);
  background-size:cover; background-position:center; border:1px solid var(--border-2);
}
.up-item.is-done .up-thumb{ border-color:var(--success); }
.up-item.is-error .up-thumb{ border-color:var(--danger); }
.up-peso{ flex:0 0 auto; font-size:11px; white-space:nowrap; }
.up-bar{ flex:1; height:4px; border-radius:var(--radius-pill); background:var(--border); overflow:hidden; }
.up-bar span{ display:block; height:100%; width:0; background:var(--accent); transition:width .15s ease; }

/* Maniglia di trascinamento dedicata: il grab non e' mai su tutta la riga. */
.drag-handle{ cursor:grab; color:var(--text-muted); display:grid; place-items:center; }
.drag-handle:active{ cursor:grabbing; }
.is-dragging{ opacity:.4; }

/* ---------------- Toast di pagina & stati ---------------- */
.toast{
  padding:11px 14px; border-radius:var(--radius); margin-bottom:16px;
  font-size:13px; border:1px solid var(--border);
}
.toast-success{
  background:color-mix(in srgb, var(--success) 10%, transparent);
  border-color:color-mix(in srgb, var(--success) 35%, transparent);
}
.toast-error{
  background:color-mix(in srgb, var(--danger) 10%, transparent);
  border-color:color-mix(in srgb, var(--danger) 35%, transparent);
}
.toast-info{
  background:var(--accent-soft);
  border-color:color-mix(in srgb, var(--accent) 35%, transparent);
}

/* Toast flottante e transitorio (EM.toast): conferme al volo — "copiato",
   "salvato" — che non devono restare in pagina. Diverso dal .toast in flusso
   dei messaggi flash del server: questo galleggia in basso al centro e
   sparisce da solo. Riusa i colori .toast-*. aria-live lo annuncia. */
.toast-float{
  position:fixed; left:50%; bottom:22px; transform:translateX(-50%) translateY(8px);
  z-index:var(--z-tooltip); margin:0; max-width:calc(100vw - 32px);
  box-shadow:0 8px 24px rgba(0,0,0,.28); backdrop-filter:blur(8px);
  display:flex; align-items:center; gap:8px; white-space:nowrap;
  opacity:0; transition:opacity .18s ease, transform .18s ease; pointer-events:none;
}
.toast-float.is-in{ opacity:1; transform:translateX(-50%) translateY(0); }
.toast-float svg{ flex:0 0 auto; }

/* Colonna barcode: in cella solo l'icona. Il codice si legge col title
   (hover) e si copia al click; l'icona diventa una spunta verde per un attimo. */
.col-barcode, .col-barcode-h{ text-align:center; }
.barcode-copy{ cursor:pointer; }
.barcode-copy:hover{ color:var(--accent); }
.barcode-copy.copiato{ color:var(--success); }

/* ---------------- Editor quadri ----------------
   L'editor sfrutta TUTTA l'altezza (.page.page-editor): topbar compatta in
   alto, sotto la palette a sinistra e la tela a destra che riempie lo spazio.
   Le file crescono in altezza per usare lo spazio (con un tetto), i moduli
   sono a larghezza fissa: su pannelli larghi la tela scorre in orizzontale. */
.page.page-editor{
  max-width:none; padding:0; flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column; overflow:hidden;
}
.qc-topbar{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap; flex:0 0 auto;
  padding:10px 18px; border-bottom:1px solid var(--border);
}
.qc-meta{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }

.qc-wrap{ flex:1 1 auto; min-height:0; padding:16px; display:flex; }
.qc-layout{ display:flex; gap:16px; align-items:stretch; width:100%; min-height:0; }
/* La palette componenti a lista è stata rimossa (i componenti si aggiungono dal
   «+» della cella): resta solo il ritocco al campo ricerca del pannello quadri. */
.qc-pal-cerca{ margin-bottom:8px; }

.qc-canvas{ flex:1 1 auto; min-width:0; overflow:auto; }

/* Pannello dei quadri (al posto della palette): la lista dei progetti; un
   click cambia la tela LIVE, senza ricaricare. */
.qc-panel{ flex:0 0 240px; display:flex; flex-direction:column; min-height:0; }
.qc-panel-head{ display:flex; align-items:center; gap:6px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-muted); margin-bottom:8px; }
.qc-panel-head svg{ flex:0 0 auto; }
.qc-panel-nuovo{ margin-left:auto; font-size:11px; font-weight:600; color:var(--accent); text-decoration:none; text-transform:none; letter-spacing:0; }
.qc-panel-lista{ display:flex; flex-direction:column; gap:5px; overflow-y:auto; flex:1 1 auto; min-height:0; padding-right:2px; }
.qc-panel-item{
  display:flex; flex-direction:column; gap:2px; padding:8px 10px; width:100%; text-align:left;
  border:1px solid var(--border); border-radius:8px; background:var(--card-bg); cursor:pointer;
}
.qc-panel-item:hover{ border-color:var(--border-2); }
.qc-panel-item.attivo{ border-color:var(--accent); background:var(--accent-soft); }
.qc-panel-nome{ font-size:13px; font-weight:600; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.qc-panel-sub{ font-size:10.5px; color:var(--text-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
@media (max-width:700px){
  .qc-panel{ flex-basis:auto; width:100%; max-height:180px; }
}
/* Le file hanno un'altezza PROPORZIONALE alla larghezza del modulo (≈3×): un
   dispositivo DIN è stretto e alto, e la cella deve rispettarne le proporzioni.
   La tela cresce col contenuto e scorre dentro .qc-canvas (niente più
   riempimento forzato dell'altezza, che schiacciava le celle larghe). */
.qc-tela{ display:flex; flex-direction:column; gap:16px; width:max-content; }
.qc-riga{ display:flex; align-items:flex-start; gap:10px; }
.qc-riga-num{ flex:0 0 22px; align-self:center; text-align:center; font-size:15px; font-weight:700; color:var(--text-muted); }
.qc-riga-corpo{ min-width:0; display:flex; flex-direction:column; }
/* Numeri dei moduli SOPRA le celle, fuori dal rettangolo, centrati e sempre
   visibili (un componente piazzato non li copre). */
.qc-moduli{
  display:flex;
  background:var(--card-bg); border:1px solid var(--border-2); border-radius:0; overflow:hidden;
}
.qc-cella{
  flex:0 0 var(--qc-cell, 48px); width:var(--qc-cell, 48px);
  height:185px;   /* un modulo è 68×185: larghezza dal --qc-cell, altezza fissa */
  border-right:1px solid color-mix(in srgb, var(--text) 8%, transparent); position:relative;
}
.qc-cella:last-child{ border-right:0; }
/* Cella vuota: un «+» compare in hover (le celle occupate sono coperte dal
   blocco, così il + appare solo dove si può aggiungere). Click = scelta. */
.qc-cella{ cursor:pointer; }
.qc-cella::before{
  content:'+'; position:absolute; inset:0; display:grid; place-items:center;
  font-size:26px; color:var(--accent); opacity:0; transition:opacity .12s; pointer-events:none;
}
.qc-cella:hover::before{ opacity:.6; }

/* Popover di scelta del componente (dal «+» o da «Cambia componente»). */
.qc-scelta{ display:flex; flex-direction:column; gap:8px; padding:10px; width:250px; }
.qc-scelta-lista{ display:flex; flex-direction:column; gap:4px; max-height:280px; overflow-y:auto; }
.qc-scelta-item{
  display:flex; align-items:center; gap:9px; padding:6px 7px; width:100%;
  border:1px solid transparent; border-radius:7px; background:transparent; cursor:pointer; text-align:left;
}
.qc-scelta-item:hover{ background:var(--accent-soft); border-color:var(--border-2); }
/* Anteprima RETTANGOLARE: larghezza ∝ moduli (inline dal JS, 16px/modulo),
   altezza fissa, SQUADRATA e `cover` come sul quadro. Così si distingue a
   colpo d'occhio un 1 modulo da un 2/3/4. */
.qc-scelta-foto{
  flex:0 0 auto; height:44px; min-width:14px; border:1px solid var(--border-2); border-radius:0;
  background-color:var(--app-bg); background-size:cover; background-repeat:no-repeat; background-position:center;
}
.qc-scelta-info{ min-width:0; flex:1; display:flex; flex-direction:column; }
.qc-scelta-nome{ font-size:12.5px; font-weight:600; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.qc-scelta-sub{ font-size:10.5px; color:var(--text-muted); }
/* Filtri combinabili (fabbricante / tipo / moduli) in cima al chooser */
.qc-scelta-filtri{ display:flex; flex-wrap:wrap; gap:5px; }
.qc-filtro{
  flex:1 1 46%; min-width:0; font-size:11.5px; padding:5px 6px;
  border:1px solid var(--border-2); border-radius:7px;
  background:var(--input-bg); color:var(--text); cursor:pointer;
}
.qc-filtro:focus{ outline:none; border-color:var(--accent); }
.qc-scelta-vuoto{ font-size:12px; color:var(--text-muted); text-align:center; padding:14px 6px; }

/* Blocco senza immagine: il nome al centro (fallback, l'etichetta sta sotto). */
.qc-blocco-nome{ flex:1; display:grid; place-items:center; text-align:center; font-size:10px; font-weight:600; color:var(--text); padding:3px; overflow:hidden; }

/* ---- Strip delle etichette (sotto i moduli) ---- */
/* Strip etichette. In alto una riga FISSA di numeri di modulo (per posizione),
   sotto le celle per il «+», e le etichette colorate (spostabili) sopra. Il
   numero sta al vertice della fascia colorata ma è un livello a sé: quando
   sposti un'etichetta cambia colore/testo, i numeri restano al loro posto. */
:root{ --qc-etnum: 15px; }   /* altezza della riga numeri in cima alla strip */
.qc-etichette{ position:relative; display:flex; height:64px; margin-top:5px; flex:0 0 auto; }
.qc-et-numeri{ position:absolute; top:0; left:0; right:0; height:var(--qc-etnum); display:flex; z-index:4; pointer-events:none; }
.qc-etn{ flex:0 0 var(--qc-cell, 48px); width:var(--qc-cell, 48px); text-align:center; font-size:11px; font-weight:600; color:var(--text-muted); font-variant-numeric:tabular-nums; }
.qc-et-cella{ flex:0 0 var(--qc-cell, 48px); width:var(--qc-cell, 48px); height:100%; position:relative; cursor:pointer; }
.qc-et-cella::before{
  content:'+'; position:absolute; left:0; right:0; top:var(--qc-etnum); bottom:0; display:grid; place-items:center;
  font-size:18px; color:var(--accent); opacity:0; transition:opacity .12s; pointer-events:none;
}
.qc-et-cella:hover::before{ opacity:.5; }
/* Etichetta: fascia con la testa colorata (dove appoggiano i numeri fissi) e
   sotto icona + testo. Spostabile (drag). */
.qc-etic{
  position:absolute; top:0; height:100%; box-sizing:border-box; overflow:hidden; cursor:grab; touch-action:none;
  background:var(--card-bg); box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--text) 14%, transparent);
  padding-top:var(--qc-etnum);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
}
.qc-etic:active{ cursor:grabbing; }
.qc-etic.qc-trascino{ opacity:.35; }
.qc-etic::before{ content:''; position:absolute; top:0; left:0; right:0; height:var(--qc-etnum); background:var(--et-col); }
.qc-etic-ico{ color:var(--et-col); display:flex; }
.qc-etic-ico svg{ width:16px; height:16px; }
.qc-etic-txt{
  font-size:10px; font-weight:600; line-height:1.05; color:var(--text); text-align:center; padding:0 2px;
  overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}

/* ---- Popover proprietà (nome del componente / etichetta) ---- */
.qc-props-nome{ font-size:13px; font-weight:600; color:var(--text); margin-bottom:2px; }
.qc-etic-props{ display:flex; flex-direction:column; gap:5px; padding:10px; width:236px; }
.qc-etic-props .lbl{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-muted); }
.qc-etic-riga{ display:flex; gap:8px; }
.qc-etic-riga > div{ flex:1; min-width:0; display:flex; flex-direction:column; gap:4px; }
.qc-etic-span{ display:flex; align-items:center; gap:8px; }
.qc-etic-span span{ font-size:12px; min-width:48px; text-align:center; }
.qc-etic-span .btn{ min-width:34px; justify-content:center; }
.qc-etic-icone{ display:grid; grid-template-columns:repeat(6, 1fr); gap:4px; }
.qc-ic-scelta{
  display:grid; place-items:center; height:30px; font-size:12px; cursor:pointer;
  border:1px solid var(--border); border-radius:6px; background:var(--card-bg); color:var(--text-dim);
}
.qc-ic-scelta:hover{ border-color:var(--border-2); color:var(--text); }
.qc-ic-scelta.sel{ border-color:var(--accent); color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.qc-ic-scelta svg{ width:16px; height:16px; }

/* Blocco piazzato: immagine sopra, fascia colorata dell'etichetta sotto.
   Bordi SQUADRATI (i componenti sono rettangolari, non stondati). */
/* Blocco = solo il dispositivo, che RIEMPIE la cella (niente margine): come in
   un quadro vero, i moduli sono attaccati e li separa solo un filo grigio (il
   box-shadow a destra). Fondo bianco perché le foto dei dispositivi lo sono. */
.qc-blocco{
  position:absolute; top:0; height:100%; display:flex; flex-direction:column;
  overflow:hidden; border-radius:0; background:#fff;
  box-shadow:inset -1px 0 0 color-mix(in srgb, #000 18%, transparent);
  cursor:grab; touch-action:none;
}
.qc-blocco:active{ cursor:grabbing; }
.qc-blocco.qc-trascino{ opacity:.35; }
/* L'immagine salvata è il dispositivo INTERO (viti sopra e sotto comprese), ma
   sul quadro — come nella realtà, dove il coperchio lascia scoperto solo il
   centro — si mostra solo la fascia centrale: `cover` riempie la cella e taglia
   simmetricamente sopra e sotto, senza deformare né alterare l'originale. */
.qc-blocco-img{ flex:1; min-height:0; margin:0; background-size:cover; background-repeat:no-repeat; background-position:center; }
.qc-blocco-lab{
  font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.02em;
  color:#fff; padding:3px; text-align:center;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

/* Ghost sotto il puntatore + anteprima del punto di rilascio (squadrati). */
.qc-ghost{
  position:fixed; z-index:var(--z-tooltip); height:150px; pointer-events:none; opacity:.9;
  border-radius:0; overflow:hidden; background:var(--card-bg);
  box-shadow:0 8px 24px rgba(0,0,0,.35); display:flex; flex-direction:column;
}
.qc-preview{ position:absolute; top:0; height:100%; border-radius:0; pointer-events:none; z-index:2; }
.qc-preview.ok{ background:color-mix(in srgb, var(--success) 22%, transparent); box-shadow:inset 0 0 0 1px var(--success); }
.qc-preview.no{ background:color-mix(in srgb, var(--danger) 20%, transparent); box-shadow:inset 0 0 0 1px var(--danger); }
/* Durante il trascinamento i blocchi non catturano il puntatore, o
   elementFromPoint restituirebbe un blocco invece della cella sotto. */
.qc-tela.qc-dragging .qc-blocco,
.qc-tela.qc-dragging .qc-etic{ pointer-events:none; }

/* Proprietà del blocco (popover). */
.qc-props{ display:flex; flex-direction:column; gap:6px; padding:10px; min-width:184px; }
.qc-props .lbl{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--text-muted); }
/* Riga azioni dei popover del quadro: ELIMINA a sinistra come cestino rosso
   piccolo (.icon-btn, non .btn — così non prende il flex:1 e non diventa una
   barra rossa larga quanto il popover), azione principale a DESTRA. Il peso
   visivo segue la frequenza d'uso: si salva spesso, si elimina di rado. */
.qc-props-az{ display:flex; align-items:center; gap:6px; margin-top:8px; }
.qc-props-az .btn{ flex:1; justify-content:center; }
.qc-props-az .spacer{ flex:1; }
.qc-props-az .icon-btn{ flex:0 0 auto; width:30px; height:30px; }
/* L'azione principale non si stira: sta a destra, della sua misura. */
.qc-props-az .btn.qc-az-ok{ flex:0 0 auto; padding-left:20px; padding-right:20px; }

/* Stato del salvataggio in topbar. */
.qc-stato{ font-size:12px; color:var(--text-muted); }
.qc-stato.ok{ color:var(--success); }
.qc-stato.no{ color:var(--danger); }
.qc-stato.attesa{ color:var(--warning); }

@media (max-width:700px){
  .page.page-editor{ overflow:auto; }
  .qc-wrap{ display:block; }
  .qc-layout{ flex-direction:column; }
  .qc-riga{ min-height:150px; }
}
.empty{ text-align:center; padding:56px 20px; display:flex; flex-direction:column; align-items:center; gap:10px; }
.empty-ico{ color:var(--text-dim); opacity:.6; }
.empty h2{ font-size:17px; }
.is-loading{ opacity:.5; pointer-events:none; }

/* ---------------- Tab a pillola ---------------- */
.tabs{
  display:inline-flex; gap:2px; padding:3px; flex-wrap:wrap;
  background:var(--card-bg); border:1px solid var(--border);
  border-radius:var(--radius-pill);
}
.tab{
  display:inline-flex; align-items:center; gap:7px;
  padding:7px 15px; border-radius:var(--radius-pill);
  font-size:13px; font-weight:600; color:var(--text-dim); white-space:nowrap;
}
.tab:hover{ color:var(--text); }
.tab.is-active{
  background:color-mix(in srgb, var(--accent) 15%, transparent);
  color:var(--accent);
}
@media (max-width:900px){ .tab{ padding:10px 16px; } }

/* ---------------- Passi di una procedura (stepper) ----------------
   Stessa scocca a pillola delle .tabs, ma NON e' un menu: i passi
   hanno un ordine e uno stato. Da qui le tre differenze:
   il numero davanti all'etichetta, i tre stati (fatto / corrente /
   futuro), e il fatto che solo i passi gia' fatti sono cliccabili —
   saltare avanti significherebbe arrivare a un passo senza i dati che
   quello prima doveva produrre. */
.steps{
  display:inline-flex; gap:2px; padding:3px; flex-wrap:wrap;
  background:var(--card-bg); border:1px solid var(--border);
  border-radius:var(--radius-pill);
}
.step{
  display:inline-flex; align-items:center; gap:8px;
  padding:7px 15px; border-radius:var(--radius-pill);
  font-size:13px; font-weight:600; color:var(--text-dim); white-space:nowrap;
}
.step-n{
  display:inline-flex; align-items:center; justify-content:center;
  width:20px; height:20px; border-radius:var(--radius-pill);
  background:color-mix(in srgb, var(--text-dim) 18%, transparent);
  font-size:11.5px; font-variant-numeric:tabular-nums;
}
/* Passo gia' completato: si puo' tornarci. */
.step.is-done{ color:var(--text-muted); }
.step.is-done:hover{ color:var(--text); }
.step.is-done .step-n{
  background:color-mix(in srgb, var(--ok) 22%, transparent); color:var(--ok);
}
/* Passo corrente. */
.step.is-current{
  background:color-mix(in srgb, var(--accent) 15%, transparent);
  color:var(--accent);
}
.step.is-current .step-n{
  background:var(--accent); color:var(--accent-ink);
}
/* Passo futuro: visibile per dare il senso della lunghezza, ma spento
   e non raggiungibile. Non e' un <a>, quindi non e' focalizzabile da
   tastiera: un passo che non si puo' aprire non deve entrare nel giro
   del Tab. */
.step.is-todo{ opacity:.55; cursor:default; }

/* Sotto i 700px le etichette dei passi non correnti spariscono: sette
   parole in fila su un telefono manderebbero la barra a capo due volte
   e ruberebbero lo schermo al lavoro vero. Restano i numeri, che danno
   comunque "sei al 3 di 5". */
@media (max-width:700px){
  .step{ padding:8px 10px; }
  .step:not(.is-current) .step-lbl{ display:none; }
}

/* ---------------- Registrazione rapida (telefono in cantiere) ----------------
   Bersagli grandi: chi la usa ha spesso i guanti e una mano sola. Le
   dimensioni qui NON seguono la scala densa del resto dell'app, ed e'
   voluto — questa pagina si usa in piedi, non alla scrivania. */
.rapido{ max-width:520px; }
.rapido .field{ margin-bottom:18px; }
.rapido label{ font-size:14px; }
.rapido input[type="text"]{ font-size:17px; padding:14px 14px; }

/* Il pulsante che apre la fotocamera e' l'azione principale: sta in
   cima, occupa tutta la larghezza e non somiglia agli altri. */
.rapido-scan{
  width:100%; justify-content:center; gap:10px;
  font-size:16px; padding:18px; margin-bottom:14px;
}
.rapido-esito{ margin:-6px 0 16px; }
.rapido-esito.ok{ color:var(--success-bright); }
.rapido-esito.ko{ color:var(--danger); }

/* + campo − : il campo al centro, i pulsanti quadrati ai lati. */
.rapido-qta{ display:flex; gap:10px; align-items:stretch; }
.rapido-qta input{
  flex:1; min-width:0; text-align:center;
  font-size:22px; font-weight:700; font-variant-numeric:tabular-nums;
}
.rapido-qta .btn{
  width:56px; justify-content:center;
  font-size:22px; line-height:1; padding:0;
}
.rapido-invia{
  width:100%; justify-content:center;
  font-size:16px; padding:18px; margin-top:4px;
}

/* Scorciatoia in cima alla dashboard, solo da telefono.
   NON si usa .only-mobile: quella diventa display:inline-grid, e su un
   pulsante manderebbe icona e testo su due righe della griglia. Qui
   serve restare flex. */
.rapido-scorciatoia{ display:none; }
@media (max-width:900px){
  .rapido-scorciatoia{ display:inline-flex; }
}

/* ---------------- Selezione multipla ---------------- */
.col-sel{ width:36px; padding-right:0; text-align:center; }
.col-sel input{ cursor:pointer; accent-color:var(--accent); }

/* La riga scelta si tinge appena: deve restare leggibile e distinguersi
   da .row-alert, che significa un'altra cosa (sotto scorta). */
tr.riga-scelta > td{ background:var(--accent-soft); }

/* Accento pieno e testo bianco (DS §7): la barra deve leggersi come uno
   stato attivo — "stai per agire su delle righe" — non come un altro
   pezzo di pagina sempre presente. */
.barra-azioni{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:12px; padding:10px 14px;
  background:var(--accent); color:#fff;
  border-radius:var(--radius-lg);
  box-shadow:0 6px 20px color-mix(in srgb, var(--accent) 40%, transparent);
  /* Sticky e non fixed: resta dentro il riquadro della tabella e non
     copre il contenuto delle altre pagine. */
  position:sticky; bottom:12px; z-index:5;
}
.barra-azioni[hidden]{ display:none; }
.barra-azioni form{ display:flex; align-items:center; gap:8px; margin:0; }
.barra-conta{ font-size:13px; font-weight:700; margin-right:4px; }

/* Semitrasparenti sul fondo accento: i colori pieni dei pulsanti (incluso
   il rosso di .danger) su accento diventano illeggibili. */
.barra-azioni .btn,
.barra-azioni .picker{
  background:rgba(255,255,255,.16); color:#fff;
  border:1px solid rgba(255,255,255,.28);
}
.barra-azioni .btn:hover,
.barra-azioni .picker:hover{ background:rgba(255,255,255,.26); filter:none; }
.barra-azioni .picker-val{ color:#fff; }
.barra-gruppo .picker{ min-width:190px; }

/* ---------------- Colonne nascoste ----------------
   display:none e non visibility: la colonna deve smettere di occupare
   spazio, altrimenti nasconderla non serve a niente su una tabella
   larga — che e' l'unico motivo per cui la si nasconde. */
.col-nascosta{ display:none; }
.popover-titolo{
  font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  color:var(--text-dim); padding:2px 4px 8px;
}
.popover-riga{ display:flex; padding:5px 4px; font-size:13px; }

/* ---------------- Lettore di codici a barre ----------------
   L'anteprima riempie la larghezza del dialog e resta 4:3, cosi' il
   riquadro non salta quando la fotocamera parte. Il mirino non serve al
   riconoscimento — BarcodeDetector guarda tutto il fotogramma — ma dice
   alla persona dove mettere il codice, che e' la differenza fra
   inquadrare al primo colpo e girare il telefono. */
.scanner-wrap{
  position:relative; width:100%; aspect-ratio:4/3;
  background:#000; border-radius:var(--radius-lg); overflow:hidden;
  margin-bottom:14px;
}
.scanner-wrap video{ width:100%; height:100%; object-fit:cover; display:block; }
.scanner-mirino{
  position:absolute; inset:22% 12%;
  border:2px solid color-mix(in srgb, var(--accent) 85%, transparent);
  border-radius:var(--radius);
  box-shadow:0 0 0 100vmax color-mix(in srgb, #000 45%, transparent);
  pointer-events:none;
}
/* .dlg-scanner e NON #dlg-scanner: buildDialog() in app.js assegna una
   CLASSE, non un id. Con il selettore per id la regola non si applicava
   e su schermo largo l'anteprima della fotocamera si allargava a tutta
   la pagina. Trovato provando sul sito, non leggendo il codice. */
.dlg-scanner{ max-width:460px; }

/* Riepilogo di cosa sta per succedere, ultimo passo di una procedura.
   Righe con il numero in evidenza: e' quello che si legge, la frase
   intorno serve solo a dirgli cosa conta. */
.riepilogo{ list-style:none; display:flex; flex-direction:column; gap:8px; }
.riepilogo li{
  display:flex; align-items:baseline; gap:8px;
  padding:8px 12px; border-radius:var(--radius);
  background:color-mix(in srgb, var(--text-dim) 7%, transparent);
}
.riepilogo strong{ font-size:16px; font-variant-numeric:tabular-nums; }

/* Le card di Impostazioni sono impilate dentro .page (block, senza gap): senza
   questo si toccano. Lo spazio è il token standard --space-card, in ogni
   direzione (qui verticale fra card impilate; nelle griglie di card è il gap). */
.impostazioni-card{ max-width:680px; margin-bottom:var(--space-card); }

/* Pagina Backup: righe compatte per retention e caricamento da file. */
.bk-retention{ display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-top:14px; font-size:13px; color:var(--text-dim); }
.bk-retention input[type=number]{ width:64px; text-align:center; }
.bk-upload{ display:flex; align-items:center; flex-wrap:wrap; gap:10px; }
.bk-upload input[type=file]{ flex:1; min-width:180px; font-size:13px; color:var(--text-dim); }

/* Tab Quadri: Componenti e Modelli affiancati 50/50, poi le Marche sotto.
   Un'unica colonna con gap = --space-card, e la riga è una griglia 1fr 1fr
   con lo stesso gap → spazio uguale in orizzontale e verticale. */
.imp-quadri{ display:flex; flex-direction:column; gap:var(--space-card); max-width:1000px; }
.imp-quadri > .card{ margin-bottom:0; }   /* lo spazio lo dà il gap, non il margine */
.imp-quadri-row{ display:grid; grid-template-columns:1fr 1fr; gap:var(--space-card); align-items:start; }
.imp-quadri-row > .card{ margin-bottom:0; }
/* Card a metà larghezza, allineata alla colonna sinistra: (100% - gap)/2. */
.imp-quadri-mezza{ width:calc(50% - var(--space-card) / 2); align-self:flex-start; }
@media (max-width:760px){
  .imp-quadri-row{ grid-template-columns:1fr; }
  .imp-quadri-mezza{ width:100%; }
}
/* Carico da fattura */
.riepilogo-carico{ display:flex; gap:28px; flex-wrap:wrap; }
.riepilogo-carico .kpi-value{ font-size:20px; }
/* Il simbolo di valuta va rimpicciolito quando l'input e' stretto,
   altrimenti si sovrappone alle cifre. */
.eur-piccolo{ display:inline-block; }
.eur-piccolo::before{ left:8px; font-size:12px; }
.eur-piccolo input{ width:96px; padding-left:22px; text-align:right; }

/* Rettifica inventario */
.inp-conta{ width:90px; text-align:right; padding:5px 8px; font-variant-numeric:tabular-nums; }
.diff{ font-variant-numeric:tabular-nums; color:var(--text-muted); }
.diff-su{ color:var(--success); font-weight:600; }
.diff-giu{ color:var(--danger); font-weight:600; }

/* Foto prodotto: quadrata con angoli, non tonda come gli avatar. */
.foto-anteprima{
  width:64px; height:64px; flex:0 0 64px;
  border-radius:var(--radius-lg); border:1px solid var(--border-2);
  background:var(--input-bg) center/cover no-repeat;
  display:grid; place-items:center; color:var(--text-muted);
}
.foto-anteprima.con-foto > svg{ display:none; }
.foto-anteprima.con-foto{ cursor:zoom-in; }   /* clic = lightbox */
.mini-foto{
  width:26px; height:26px; border-radius:var(--radius-sm);
  object-fit:cover; vertical-align:middle; margin-right:7px;
  border:1px solid var(--border); cursor:zoom-in;
}
/* Colonna Foto della tabella prodotti: miniatura (o segnaposto) centrata,
   la colonna si stringe al contenuto. */
.col-foto, .col-foto-h{ width:1%; white-space:nowrap; text-align:center; }
.col-foto .mini-foto{ margin:0; width:36px; height:36px; }
.mini-foto-vuota{
  display:inline-grid; place-items:center; width:36px; height:36px;
  border-radius:var(--radius-sm); border:1px solid var(--border);
  background:var(--input-bg); color:var(--text-muted);
}
/* Anteprima componente in tabella: RETTANGOLARE, larghezza ∝ moduli (inline
   dal PHP, 17px/modulo), altezza fissa e squadrata — si vede a colpo d'occhio
   se è da 1, 2, 3… moduli invece di miniature tutte uguali. */
.col-foto .mini-foto-mod{ height:46px; border-radius:0; }
.mini-foto-vuota.mini-foto-mod{ height:46px; border-radius:0; }

.cat-riga{
  display:flex; align-items:center; gap:10px;
  padding:10px 4px; border-bottom:1px solid var(--border);
}
.cat-riga:last-child{ border-bottom:none; }
.cat-nome{ font-weight:600; }
.cat-riga .spacer{ flex:1; }
/* Conteggio d'uso in una colonna a sé: margin-left:auto lo spinge a destra
   (assorbe lo spazio libero al posto dello spacer) e min-width + testo a
   destra allineano i numeri in colonna riga per riga. */
.riga-conteggio{ margin-left:auto; min-width:82px; text-align:right; white-space:nowrap; }

.evento-blocco{ padding:16px 0; border-bottom:1px solid var(--border); }
.evento-blocco:last-of-type{ border-bottom:none; }
.evento-testa{ margin-bottom:4px; }
.evento-nome{ font-weight:600; color:var(--text); }
.evento-testo{ font-family:var(--mono); font-size:12.5px; line-height:1.6; margin-top:10px; }
.var-riga{ display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; align-items:center; }
.var-chip{
  display:inline-block; font-family:var(--mono); font-size:11px;
  padding:2px 7px; border-radius:var(--radius-sm);
  background:var(--app-bg); border:1px solid var(--border); color:var(--text-dim);
}
/* Le variabili inseribili sono <button>: devono sembrare cliccabili,
   altrimenti restano indistinguibili dalle etichette decorative. */
button.var-chip{ cursor:pointer; font-family:var(--mono); }
button.var-chip:hover{ border-color:var(--accent); color:var(--accent); background:var(--accent-soft); }
.mt-8{ margin-top:8px; }
.mb-8{ margin-bottom:8px; }
.sep{ border:none; border-top:1px solid var(--border); margin:20px 0; }
.anteprima-accento{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:16px; border:1px dashed var(--border-2); border-radius:var(--radius-lg);
}

/* ---------------- Profilo e utenti ---------------- */
/* Profilo su una colonna centrale (DS 11): avatar in testa, poi le card
   impilate. Prima erano affiancate e venivano tagliate sui portatili. */
.profilo-wrap{ max-width:560px; margin:0 auto; }
.profilo-avatar-block{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:12px; }
.profilo-avatar-block .flex{ justify-content:center; flex-wrap:wrap; }
/* Foto profilo: l'avatar con foto si clicca per ingrandirlo (lightbox).
   Il drag-and-drop vive nel dialog aperto da "Cambia" (openFotoDialog). */
.pf-avatar-foto{ cursor:zoom-in; }
/* Bordino del colore utente attorno all'avatar. Ring semplice ovunque;
   sull'avatar grande del profilo un anello piu' spesso con stacco dal fondo.
   Il colore arriva da --ring, impostato inline. */
.avatar-ring{ box-shadow:0 0 0 2px var(--ring, var(--accent)); }
.avatar-xl.avatar-ring{ box-shadow:0 0 0 3px var(--app-bg), 0 0 0 6px var(--ring, var(--accent)); }
.avatar-xl{ width:110px; height:110px; flex:0 0 110px; font-size:38px; }
.avatar-lg{ width:64px; height:64px; flex:0 0 64px; font-size:22px; }
.avatar-xl{ width:92px; height:92px; flex:0 0 92px; font-size:30px; }
.avatar-upload-row{ display:flex; align-items:center; gap:14px; margin-bottom:18px; }
/* Testa del dialog utente (e fornitore): titolo a sinistra, avatar (grande) AL
   CENTRO, i tasti a destra accanto. Grid 1fr auto 1fr → l'avatar resta centrato
   a prescindere da quanti tasti ci sono (1 «Carica» senza foto, 3 con foto). */
.uhead{ display:grid; grid-template-columns:1fr auto 1fr; align-items:center; gap:14px; margin-bottom:18px; }
.uhead .dialog-head{ margin:0; font-size:22px; justify-self:start; }
.uhead .avatar-xl{ justify-self:center; }
.uhead .foto-azioni{ justify-self:start; flex-wrap:wrap; align-items:center; }
@media (max-width:560px){
  .uhead{ grid-template-columns:1fr; justify-items:center; text-align:center; gap:12px; }
  .uhead .dialog-head, .uhead .foto-azioni{ justify-self:center; }
  .avatar-xl{ width:84px; height:84px; flex:0 0 84px; }
}
/* Divisore e intestazione di sezione dentro un form (es. «Referente»). */
.form-hr{ border:0; border-top:1px solid var(--border); margin:18px 0 14px; }
.form-sez{ font-size:12px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); margin-bottom:12px; }
/* Logo del fornitore: miniatura accanto al nome. Non tondo come un avatar ma
   QUADRATO con bordi poco smussati (18% scala con la dimensione) — è un logo. */
.forn-nome{ display:flex; align-items:center; gap:9px; }
.forn-logo{ width:30px; height:30px; flex:0 0 30px; font-size:11px; }
.avatar.logo-quadro{ border-radius:18%; }

/* Chip «filtro attivo» in una toolbar (es. prodotti filtrati per fornitore):
   dice qual è il filtro e lo si toglie con la ×. */
.filtro-attivo{ display:inline-flex; align-items:center; gap:6px; padding:5px 6px 5px 10px; font-size:12.5px;
  background:var(--accent-soft); color:var(--accent); border:1px solid color-mix(in srgb, var(--accent) 35%, transparent); border-radius:var(--radius-pill); }
.filtro-attivo a{ display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px;
  border-radius:50%; color:inherit; text-decoration:none; font-size:15px; line-height:1; opacity:.8; }
.filtro-attivo a:hover{ background:color-mix(in srgb, var(--accent) 20%, transparent); opacity:1; }

/* Barra dei filtri sotto la toolbar (es. prodotti): interruttori + slider. */
.filtri-bar{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--border); }
.filtri-bar-lbl{ font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); }

/* Range2: slider a due maniglie (forbice di prezzo). */
.range2{ display:flex; flex-direction:column; gap:3px; }
.range2-head{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; }
.range2-head [data-r2-label]{ font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); }
.range2-vals{ font-size:12px; font-weight:600; color:var(--text-dim); font-variant-numeric:tabular-nums; white-space:nowrap; }
.range2-slider{ position:relative; height:18px; }
.range2-rail{ position:absolute; left:0; right:0; top:50%; transform:translateY(-50%); height:4px; border-radius:3px; background:var(--border-2); }
.range2-fill{ position:absolute; top:0; bottom:0; background:var(--accent); border-radius:3px; }
.range2-input{ position:absolute; left:0; top:0; width:100%; height:18px; margin:0; background:none; pointer-events:none; -webkit-appearance:none; appearance:none; }
/* Niente outline sull'input intero (compariva come un bordo rosso attorno a
   tutto lo slider quando prendeva il fuoco); l'anello di focus va sul thumb. */
.range2-input:focus{ outline:none; }
/* La traccia è alta quanto l'input, così il thumb si centra col margin. */
.range2-input::-webkit-slider-runnable-track{ height:18px; background:none; border:none; }
.range2-input::-moz-range-track{ height:18px; background:none; border:none; }
/* margin-top = (traccia 18 − thumb 16) / 2 = 1px → centrato sulla linea. */
.range2-input::-webkit-slider-thumb{ -webkit-appearance:none; pointer-events:auto; width:16px; height:16px; margin-top:1px; border-radius:50%; background:#fff; border:2px solid var(--accent); box-shadow:0 1px 3px rgba(0,0,0,.35); cursor:pointer; }
.range2-input::-moz-range-thumb{ pointer-events:auto; width:16px; height:16px; border-radius:50%; background:#fff; border:2px solid var(--accent); box-shadow:0 1px 3px rgba(0,0,0,.35); cursor:pointer; }
.range2-input:focus-visible::-webkit-slider-thumb{ box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent); }
.range2-input:focus-visible::-moz-range-thumb{ box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent); }

/* ---------------- Foto cantiere: albero piani/stanze + galleria ---------- */
.onedrive-avviso{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:12px; }
.onedrive-avviso span{ display:flex; align-items:center; gap:8px; }
.onedrive-ok{ display:flex; align-items:center; gap:6px; font-size:12px; color:var(--text-dim); margin-bottom:12px; }
.foto-wrap{ display:flex; gap:16px; align-items:flex-start; }
.foto-albero{ flex:0 0 260px; background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-lg); padding:10px; }
.foto-albero-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:8px; }
.albero, .alb-stanze{ list-style:none; margin:0; padding:0; }
.alb-stanze{ padding-left:14px; }
.alb-riga{ display:flex; align-items:center; gap:6px; padding:5px 6px; border-radius:var(--radius-sm); }
.alb-riga:hover{ background:var(--accent-soft); }
.alb-riga-piano{ font-weight:600; }
.alb-nome{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-flex; align-items:center; gap:5px; }
.alb-nome svg{ flex:0 0 auto; color:var(--text-dim); }
.alb-stanza .alb-nome[data-vai]{ cursor:pointer; }
.alb-az{ display:inline-flex; gap:1px; opacity:0; transition:opacity .1s ease; }
.alb-riga:hover .alb-az{ opacity:1; }
.alb-stanza.is-sel > .alb-riga{ background:var(--accent-soft); box-shadow:inset 2px 0 0 var(--accent); }
.icon-btn.sm{ width:26px; height:26px; }
.foto-galleria{ flex:1; min-width:0; }
.galleria-vuota{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; padding:60px 20px; text-align:center; color:var(--text-dim); opacity:.75; }
.foto-dz{ display:flex; flex-direction:column; align-items:center; gap:8px; margin-bottom:12px; }
.foto-dz .dz-ico{ color:var(--text-dim); display:grid; place-items:center; }
.cfoto-griglia{ display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:10px; }
.cfoto{ position:relative; border:1px solid var(--border); border-radius:var(--radius-sm); overflow:hidden; background:var(--input-bg); }
.cfoto img{ width:100%; aspect-ratio:1; object-fit:cover; display:block; cursor:zoom-in; }
.cfoto-meta{ display:flex; align-items:center; justify-content:space-between; gap:6px; padding:4px 7px; font-size:11px; color:var(--text-dim); }
.cfoto-del{ border:0; background:none; color:var(--text-dim); cursor:pointer; padding:2px; border-radius:4px; display:inline-flex; }
.cfoto-del:hover{ color:var(--danger); background:color-mix(in srgb, var(--danger) 12%, transparent); }
@media (max-width:720px){
  .foto-wrap{ flex-direction:column; }
  .foto-albero{ flex-basis:auto; width:100%; }
}
/* Testa dei dialog foto (prodotto/utente): foto a sinistra, a destra il titolo
   su una riga e sotto i tre tasti (Cambia, Ritaglia, cestino). */
.dialog-head-foto{ display:flex; align-items:center; gap:14px; margin-bottom:18px; }
.dialog-head-foto-col{ display:flex; flex-direction:column; gap:8px; min-width:0; }
.dialog-head-foto-col .dialog-head{ margin:0; }
.foto-azioni{ flex-wrap:wrap; align-items:center; }
/* Cestino della foto: e' un <button class="btn secondary sm"> con la sola
   icona, ma in ROSSO (testo + bordo). Stessa forma e altezza di Cambia e
   Ritaglia — quindi la riga e' allineata — con il colore che lo distingue
   come azione distruttiva. Padding orizzontale ridotto: e' solo un'icona. */
.btn.foto-elimina{ color:var(--danger); border-color:color-mix(in srgb, var(--danger) 45%, transparent); padding-left:9px; padding-right:9px; }
.btn.foto-elimina:hover{ color:var(--danger); background:color-mix(in srgb, var(--danger) 12%, transparent); border-color:var(--danger); }
/* Mobile: foto piu' grande, la riga resta orizzontale (foto a sinistra), e
   i tre tasti si stringono per stare tutti su una riga. */
@media (max-width:680px){
  .dialog-head-foto{ align-items:flex-start; }
  /* Foto piu' grande del default (64) ma non tanto da spingere il cestino a
     capo: a 76px i tre tasti stretti entrano tutti su una riga a 375px. */
  .dialog-head-foto .foto-anteprima,
  .dialog-head-foto .avatar-lg{ width:76px; height:76px; flex:0 0 76px; font-size:24px; }
  /* .dialog-head-foto davanti per battere .flex{gap:10px} (stessa
     specificita', ma .flex viene dopo nel file). */
  .dialog-head-foto .foto-azioni{ gap:5px; }
  .foto-azioni .btn{ padding-left:8px; padding-right:8px; gap:5px; }
  .foto-azioni .foto-elimina{ padding-left:7px; padding-right:7px; }
}
.cella-utente{ display:flex; align-items:center; gap:9px; flex-wrap:nowrap; }
/* Le funzioni accessibili sono molte: due colonne le tengono leggibili
   senza far diventare il dialog una colonna infinita. */
.access-grid{ display:grid; grid-template-columns:1fr 1fr; gap:8px 16px; }
@media (max-width:680px){ .access-grid{ grid-template-columns:1fr; } }
/* Un picker disabilitato deve sembrarlo: e' un <button>, non un input,
   quindi non eredita nessuno stile di disabilitazione. */
.picker:disabled{ opacity:.55; cursor:not-allowed; }
.picker:disabled:hover{ border-color:var(--border-2); }
.profilo-nome{ font-size:20px; font-weight:700; margin-bottom:8px; }
.profilo-meta{ margin:2px 0 0; font-size:12px; line-height:1.6; }
.profilo-cards{ grid-template-columns:1fr; gap:18px; align-items:start; }

/* Swatch dei colori avatar: tondi 28px, il selezionato con anello accento */
.swatch-row{ display:flex; flex-wrap:wrap; gap:8px; }
.swatch{
  width:28px; height:28px; flex:0 0 28px; border-radius:50%;
  border:none; cursor:pointer; padding:0;
}
.swatch.is-sel{ box-shadow:0 0 0 2px var(--app-bg), 0 0 0 4px var(--accent); }
.swatch-custom{
  display:grid; place-items:center; position:relative;
  background:var(--input-bg); border:1px dashed var(--border-2); color:var(--text-muted);
}
/* L'input color resta sopra lo swatch ma invisibile: cliccando si apre il
   selettore di sistema, e il "+" disegnato sotto resta la faccia visibile. */
.swatch-custom input[type=color]{
  position:absolute; inset:0; opacity:0; cursor:pointer; border:none; padding:0;
}

/* ---------------- Login ---------------- */
.login-wrap{ min-height:100vh; display:grid; place-items:center; padding:20px; }
.login-card{
  width:380px; max-width:100%; background:var(--card-bg);
  border:1px solid var(--border); border-radius:var(--radius-xl); padding:30px;
}
.login-logo{
  width:46px; height:46px; border-radius:var(--radius-lg);
  background:var(--accent); color:var(--accent-contrast);
  display:grid; place-items:center; margin:0 auto 14px;
}
.login-card h1{ text-align:center; font-size:20px; margin-bottom:4px; }
.login-card .sub{ text-align:center; color:var(--text-dim); margin-bottom:22px; font-size:13px; }
.login-card .btn{ width:100%; justify-content:center; margin-top:6px; }

/* ---------------- Utility ---------------- */
/* wrap di default: senza, ogni gruppo di pulsanti sfora a destra su
   telefono invece di andare a capo. */
.flex{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.mt-16{ margin-top:16px; }
.mb-16{ margin-bottom:16px; }
.section-head{ display:flex; align-items:center; gap:12px; margin-bottom:16px; flex-wrap:wrap; }
.section-head .spacer{ flex:1; }

/* ---------------- Responsive ---------------- */
@media (max-width:1100px){
  .form-row{ grid-template-columns:1fr; }
}

/* Sotto 900px: sidebar -> drawer, target touch >= 40px (DS §13). */
@media (max-width:900px){
  .sidebar{
    position:fixed; left:0; top:0; z-index:var(--z-drawer);
    transform:translateX(-100%); transition:transform .2s ease;
    width:240px; flex-basis:240px;
  }
  /* Nel drawer la sidebar resta sempre a 240px: icone sole senza
     tooltip sono inutilizzabili al tocco. */
  .sb-collapsed .sidebar{ width:240px; flex-basis:240px; }
  .sb-collapsed .sb-name,
  .sb-collapsed .sb-label,
  .sb-collapsed .sb-user-info{ display:revert; }
  .sb-collapsed .sb-item{ justify-content:flex-start; padding:11px; }
  /* Nel drawer la sidebar è piena: torna la pillola con le righe unite. */
  .sb-collapsed .sb-divider{ margin:16px -8px 7px; }
  .sb-collapsed .sb-divider-pill{ display:revert; }
  .sb-open .sidebar{ transform:translateX(0); }
  .sb-collapse{ display:none; }
  .sb-overlay{
    display:block; position:fixed; inset:0; background:rgba(0,0,0,.5);
    z-index:calc(var(--z-drawer) - 1); opacity:0; pointer-events:none; transition:opacity .2s;
  }
  .sb-open .sb-overlay{ opacity:1; pointer-events:auto; }

  .icon-btn{ width:40px; height:40px; }
  .btn{ padding:10px 16px; }
  .sb-item{ padding:11px; }
  .pop-item{ padding:11px 10px; }
  .picker{ padding:10px 12px; min-height:40px; }
  .page{ padding:16px; }
  .topbar{ padding:0 16px; }   /* verticale via min-height, come da desktop */
}

@media (max-width:680px){
  /* Il saluto sparisce, il tasto Esci resta: su telefono il nome occupa
     mezza barra e l'utente sa gia' chi e'. */
  .topbar-user .saluto{ display:none; }
  .kpis{ grid-template-columns:1fr 1fr; }
  .toolbar{ padding:10px; }
  .search{ min-width:0; flex:1; }
  tbody td,thead th{ padding:9px 10px; }
}

@media (max-width:440px){
  /* Sotto i 440px due KPI affiancate spezzano l'etichetta su tre righe
     e il numero grande non ci sta piu': meglio una per riga. */
  .kpis{ grid-template-columns:1fr; }
}

/* =====================================================================
   Regole di visibilita' — IN FONDO DI PROPOSITO.
   `[hidden]` e `.only-mobile` hanno la stessa specificita' delle classi
   dei componenti (.empty, .icon-btn), quindi a parita' di peso vince
   l'ultima dichiarata. Spostarle piu' in alto le farebbe perdere: e' il
   motivo per cui lo stato vuoto restava visibile e l'hamburger compariva
   anche su desktop. Niente !important, solo ordine.
   ===================================================================== */
[hidden]{ display:none; }

.only-mobile{ display:none; }
@media (max-width:900px){
  .only-mobile{ display:inline-grid; }
  .only-mobile[hidden]{ display:none; }
}

/* --- Voce di menu dentro un popover (bottone a riga intera) --------- */
.menu-voce{
  display:block; width:100%; text-align:left; padding:8px 10px;
  background:transparent; border:none; border-radius:var(--radius-sm);
  color:var(--text); font-size:13px; cursor:pointer;
}
.menu-voce:hover{ background:var(--accent-soft); }

/* --- Stampa (→ PDF): resta solo la tabella, senza la cornice dell'app.
   Le colonne nascoste sono gia' display:none (.col-nascosta), quindi non
   compaiono nemmeno qui: la stampa rispetta filtri e colonne come lo
   schermo. Elemento .solo-stampa: nascosto a video, visibile in stampa.
   Niente !important: queste regole stanno in fondo al file e hanno pari
   specificita' di quelle a schermo, quindi vincono per ordine (DS: se
   servisse !important, la specificita' sarebbe sbagliata). */
/* ===================================================================
 *  PIANTINE — mappa dell'impianto (una piantina per piano).
 *  I 4 tipi di punto hanno un colore ciascuno, condiviso da marker e
 *  legenda tramite --c: cambiare qui cambia ovunque.
 * ================================================================ */
/* I colori dei punti NON stanno qui: li genera pt_css_colori() da
   app/piantine.php, cosi' marker, legenda e foglio di stampa non possono
   divergere. Qui restano solo le regole strutturali. */

/* Bottone "ghost": azione discreta senza bordo (usato in mappa e dialog). */
.btn.ghost{ background:transparent; color:var(--text-dim); border:1px solid transparent; }
.btn.ghost:hover{ background:var(--accent-soft); color:var(--text); filter:none; }

/* Selettore dei piani (tab a pillola) */
.pt-piani{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; margin-bottom:14px; }
/* Le linguette si riordinano trascinandole di lato (l'ordine si salva da sé).
   touch-action:pan-y — il pan ORIZZONTALE lo prendiamo noi per il riordino,
   quello verticale resta al browser: la pagina si scorre anche partendo da qui. */
.pt-piano-tab{ display:inline-flex; align-items:center; gap:6px; padding:7px 13px; font-size:13px; font-weight:500;
  background:var(--card-bg); color:var(--text); border:1px solid var(--border-2); border-radius:var(--radius-pill); cursor:pointer;
  touch-action:pan-y; user-select:none; }
.pt-piano-tab:hover{ border-color:var(--text-muted); }
/* Cursore a manina aperta dove il riordino è permesso: è il segnale che
   l'elemento si trascina (la classe la mette il JS, che conosce i permessi). */
.pt-piani-ord .pt-piano-tab{ cursor:grab; }
.pt-piano-tab.is-drag{ opacity:.4; cursor:grabbing; }
.pt-piano-tab.is-active{ background:var(--accent); color:var(--accent-contrast); border-color:var(--accent); }
.pt-piano-ok{ color:var(--success); font-size:9px; line-height:1; }
.pt-piano-tab.is-active .pt-piano-ok{ color:var(--accent-contrast); }

/* Barra strumenti */
.pt-toolbar{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; padding:10px 12px; margin-bottom:12px;
  background:var(--card-bg); border:1px solid var(--border-2); border-radius:var(--radius); }
.pt-tool-lbl{ font-size:12px; color:var(--text-dim); font-weight:600; }
.pt-tipo{ display:inline-flex; align-items:center; gap:6px; padding:6px 11px; font-size:12px; font-weight:700;
  background:var(--input-bg); color:var(--text); border:1px solid var(--border-2); border-radius:var(--radius-sm); cursor:pointer; }
.pt-tipo .pt-dot{ width:11px; height:11px; border-radius:50%; background:var(--c); box-shadow:0 0 0 2px color-mix(in srgb, var(--c) 30%, transparent); }
.pt-tipo:hover{ border-color:var(--c); }
.pt-tipo.is-on{ background:color-mix(in srgb, var(--c) 16%, transparent); border-color:var(--c); }
.pt-sep{ width:1px; height:22px; background:var(--border-2); margin:0 2px; }
/* Iconcine dei tubi: l'icona «collega» nei 6 colori. Premuta = modo collega
   armato con quel colore. --tc arriva inline dal PHP (stessa palette del DB). */
.pt-coll{ position:relative; display:inline-flex; align-items:center; justify-content:center; width:30px; height:30px;
  color:var(--tc); background:var(--input-bg); border:1px solid var(--border-2); border-radius:var(--radius-sm); cursor:pointer; }
.pt-coll:hover{ border-color:var(--tc); }
/* Selezione con UN anello esterno in accent (il colore proprio non basta: il
   tubo nero su tema scuro sparirebbe). Il bordo resta quello neutro di base:
   colorarlo aggiungeva un secondo anello concentrico. */
.pt-coll.is-on{ background:color-mix(in srgb, var(--tc) 18%, transparent);
  outline:2px solid var(--accent); outline-offset:2px; }
/* Badge della misura (Ø20/25/32) sopra le iconcine dei tubi neri. */
.pt-coll-mis{ position:absolute; top:-8px; left:50%; transform:translateX(-50%);
  font-size:9px; font-weight:700; line-height:1; padding:2px 5px; color:var(--text);
  background:var(--card-bg); border:1px solid var(--border-2); border-radius:var(--radius-pill); }
.pt-hint{ font-size:12px; color:var(--accent); font-weight:500; }

/* Palco + mappa */
.pt-stage{ min-height:120px; }
/* Schermo intero: ci entra il wrapper INTERO — barra degli strumenti compresa,
   perché a schermo intero si deve poter lavorare, non solo guardare.
   Dove il browser concede la Fullscreen API spariscono anche le sue barre;
   su iPhone/iPad no (l'API vale solo per i video) e resta la tutta-pagina. */
#ptFull.is-full{ position:fixed; inset:0; z-index:70; margin:0; padding:0;
  background:var(--bg); display:flex; flex-direction:column;
  padding-top:env(safe-area-inset-top); padding-bottom:env(safe-area-inset-bottom); }
#ptFull.is-full .pt-toolbar{ margin:0; border-radius:0; border-left:0; border-right:0; }
#ptFull.is-full .pt-stage{ flex:1; min-height:0; overflow:hidden; touch-action:none;
  padding:8px; display:flex; align-items:flex-start; justify-content:center; }
#ptFull.is-full .pt-map{ max-width:none; }
#ptFull.is-full .pt-legenda{ margin:0 8px 8px; }
body.pt-no-scroll{ overflow:hidden; }
.pt-fs-bar{ display:flex; align-items:center; gap:8px; padding:9px 12px;
  background:var(--card-bg); border-bottom:1px solid var(--border-2); flex:0 0 auto; }
.pt-fs-perc{ font-size:12px; color:var(--text-dim); min-width:44px; text-align:center;
  font-variant-numeric:tabular-nums; }
.pt-dz{ min-height:180px; }
.pt-map{ position:relative; display:inline-block; max-width:100%; border:1px solid var(--border-2);
  border-radius:var(--radius); overflow:hidden; background:var(--input-bg); line-height:0; user-select:none; touch-action:none; }
.pt-map-img{ display:block; max-width:100%; height:auto; }
.pt-lines{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; }
/* Tubi: fondo scuro sotto + tratteggio nel colore del tubo sopra (stesso
   dasharray: il fondo fa da contorno a ogni tratto, e anche il tubo bianco
   sporco resta leggibile su una piantina chiara). Il viewBox è in pixel veri
   (lo imposta il JS), quindi larghezze e tratteggi sono misure di schermo. */
.pt-lines line{ stroke-linecap:round; stroke-dasharray:7 5; }
.pt-lines .tubo-fondo{ stroke:rgba(15,15,26,.4); stroke-width:2.4; }
.pt-lines .tubo{ stroke-width:1.1; }
/* La cancellazione dei tubi non usa linee-bersaglio CSS: il tocco sulla mappa
   cerca il tubo più vicino via geometria (tuboVicino, soglia 14px). */
/* Bottone di cancellazione che appare cliccando un tubo */
.tubo-x{ position:absolute; transform:translate(-50%,-50%); z-index:6; width:26px; height:26px;
  display:flex; align-items:center; justify-content:center; border:1px solid var(--border-2); border-radius:50%;
  background:var(--card-bg); color:var(--danger); cursor:pointer; box-shadow:0 2px 8px rgba(0,0,0,.35); line-height:normal; }
.tubo-x:hover{ background:color-mix(in srgb, var(--danger) 12%, transparent); border-color:var(--danger); }
.pt-map-bar{ margin-top:8px; line-height:normal; }

/* Marker: pillola colorata con la sola etichetta (DA1, P3…), ancorata al
   centro sul punto. Ruota a scatti di 90° (rot0..rot3): la rotazione si
   COMPONE col translate di ancoraggio, mai da sola. */
.pt-marker{ position:absolute; transform:translate(-50%,-50%); display:inline-flex; align-items:center; justify-content:center;
  padding:3px 9px; font-size:11px; font-weight:700; color:#fff; cursor:pointer; white-space:nowrap;
  background:var(--c); border:2px solid #fff; border-radius:var(--radius-pill);
  box-shadow:0 1px 4px rgba(0,0,0,.35); touch-action:none; }
/* Rotazione: TRE stati utili — orizzontale, verticale con la scritta verso
   destra (90°) e verticale con la scritta verso sinistra (270°). Il 180° si
   salta: la pillola è simmetrica e la scritta uscirebbe capovolta. */
.pt-marker.rot1{ transform:translate(-50%,-50%) rotate(90deg); }
.pt-marker.rot2{ transform:translate(-50%,-50%) rotate(270deg); }
/* Il quadro è fisicamente più grande e ci arrivano più tubi: la sua pillola
   ha più respiro ai lati. Il verde acido è chiaro, quindi lì la scritta è
   scura (il bianco non si leggerebbe) — vale anche per il badge nel dialog. */
.pt-marker.pt-Q{ padding-left:15px; padding-right:15px; }
.pt-marker.pt-Q, .dp-etic.pt-Q{ color:#1a2e05; }
.pt-marker.has-foto::after{ content:""; position:absolute; top:-3px; right:-3px; width:9px; height:9px;
  background:var(--accent); border:1.5px solid #fff; border-radius:50%; }
.pt-marker:hover{ filter:brightness(1.08); }
.pt-marker.is-pick{ outline:3px solid color-mix(in srgb, var(--accent) 60%, transparent); outline-offset:1px; }
:root[data-theme="light"] .pt-marker{ border-color:#fff; }

/* Legenda */
.pt-legenda{ display:flex; flex-wrap:wrap; gap:16px; margin-top:14px; padding:10px 12px; font-size:12px;
  background:var(--card-bg); border:1px solid var(--border-2); border-radius:var(--radius); }
.pt-leg-voce{ display:inline-flex; align-items:center; gap:6px; }
/* La voce di legenda porta la PILLOLA vera del marker (come sulla mappa e sul
   foglio stampato), non un pallino: si riconosce l'oggetto, non un codice. */
.pt-leg-pill{ display:inline-flex; align-items:center; padding:2px 8px; border-radius:var(--radius-pill);
  background:var(--c); color:#fff; font-size:11px; font-weight:700; border:1.5px solid var(--card-bg);
  flex:0 0 auto; line-height:normal; }
.pt-leg-pill.pt-Q{ color:#1a2e05; }
.pt-leg-btn.is-on{ background:var(--accent-soft); color:var(--accent); }

.pt-marker-lbl{ display:inline-block; }

/* Azioni rapide sul marker (ruota / elimina): iconcine tonde appoggiate al
   bordo alto. Su desktop appaiono al passaggio del mouse; su touch (niente
   hover) restano sempre visibili. Non trascinano e non aprono la scheda. */
.pt-az-mini{ position:absolute; top:calc(100% + 6px); left:50%; transform:translateX(-50%);
  display:flex; gap:4px; line-height:normal; }
.pt-mini{ width:18px; height:18px; display:flex; align-items:center; justify-content:center;
  background:var(--card-bg); color:var(--text); border:1px solid var(--border-2); border-radius:50%;
  cursor:pointer; box-shadow:0 1px 3px rgba(0,0,0,.3); }
.pt-mini:hover{ background:var(--accent-soft); }
.pt-mini-del{ color:var(--danger); }
@media (hover:hover){
  .pt-az-mini{ opacity:0; transition:opacity .12s; }
  .pt-marker:hover .pt-az-mini, .pt-marker:focus-visible .pt-az-mini{ opacity:1; }
  /* Nella STESSA media query: col tasto acceso restano visibili anche col
     mouse, senza dover indovinare chi vince nella cascata. */
  .pt-controlli .pt-az-mini{ opacity:1; }
}
/* Senza mouse non c'è un «passaggio sopra» che le riveli: su touch resterebbero
   sempre a schermo, a coprire la piantina proprio dove si lavora. Quindi lì
   sono NASCOSTE finché non si accende il tasto dei controlli. */
@media (hover:none){
  .pt-az-mini{ display:none; }
  .pt-controlli .pt-az-mini{ display:flex; }
}
/* Il pallino «ha una foto» si sposta a sinistra: a destra ora ci sono le azioni. */
.pt-marker.has-foto::after{ right:auto; left:-3px; }

/* ---- Dialog del punto ---- */
/* Più alto degli altri dialog (85vh): qui dentro c'è una foto, e la barra di
   scorrimento deve comparire solo quando serve davvero. */
dialog.dlg-punto{ width:720px; max-width:calc(100vw - 32px); max-height:94vh; }
.dp-head{ display:flex; align-items:center; gap:10px; }
.dp-etic{ display:inline-block; padding:2px 12px; border-radius:var(--radius-pill); background:var(--c,var(--accent));
  color:#fff; font-weight:800; font-size:15px; }
/* Foto propria del punto: a SINISTRA la foto (o la dropzone), a DESTRA la
   sidebar dei collegamenti — si sfrutta la larghezza invece di andare in
   verticale. Le pillole Ø sono i segnaposti dei tubi (colore inline). */
/* Foto a sinistra (con sotto la riga di aggiunta), lista dei tubi a destra. */
.dpf-cols{ display:flex; gap:12px; align-items:flex-start; }
.dpf-main{ flex:1; min-width:0; }
.dpf-side{ flex:0 0 230px; min-width:0; }
.dpf-side-tit{ display:flex; align-items:center; justify-content:space-between; gap:8px;
  font-size:12px; font-weight:600; margin-bottom:7px; flex-wrap:wrap; }
.dpf-side-tit > span{ display:inline-flex; align-items:center; gap:5px; }
/* Toggle piccolo «Nascondi usati» (due classi per battere `.toggle .track`). */
.dpf-toggle{ font-size:11px; font-weight:500; color:var(--text-dim); gap:6px; }
.dpf-toggle.toggle .track{ flex:0 0 28px; width:28px; height:15px; }
.dpf-toggle.toggle .track::after{ width:11px; height:11px; }
.dpf-toggle.toggle input:checked + .track::after{ transform:translateX(13px); }
/* Azioni della foto: sopra l'immagine, al suo bordo destro. */
.dpf-az{ display:flex; justify-content:flex-end; gap:4px; margin-bottom:6px; min-height:26px; }
/* Con molti tubi scorre SOLO la lista, non tutto il dialog. */
.dpf-side .dp-coll{ max-height:min(46vh, 420px); overflow-y:auto; padding-right:2px; }
.dpf-dz{ min-height:96px; padding:14px; }
.dpf-wrap{ position:relative; border:1px solid var(--border-2); border-radius:var(--radius); overflow:hidden;
  background:var(--input-bg); line-height:0; user-select:none; touch-action:none; }
.dpf-img{ display:block; width:100%; height:auto; }
.dpf-mark{ position:absolute; transform:translate(-50%,-50%); padding:2px 7px; font-size:10px; font-weight:700;
  color:#fff; border:1.5px solid #fff; border-radius:var(--radius-pill);
  box-shadow:0 1px 3px rgba(0,0,0,.4); cursor:pointer; white-space:nowrap; touch-action:none; line-height:normal; }
.dpf-mark-chiaro{ color:#333; }   /* pillola del tubo bianco sporco: testo scuro */
/* Su schermo stretto la lista dei tubi scende sotto la foto, a tutta larghezza. */
@media (max-width:600px){ .dpf-cols{ flex-direction:column; } .dpf-side{ flex:1 1 auto; width:100%; } }
/* Editor di ritaglio: immagine intera + riquadro trascinabile con 4 maniglie.
   Il fondo fuori riquadro si scurisce col box-shadow gigante del riquadro. */
.crop-wrap{ position:relative; border:1px solid var(--border-2); border-radius:var(--radius); overflow:hidden;
  line-height:0; user-select:none; touch-action:none; }
.crop-img{ display:block; width:100%; height:auto; }
.crop-rect{ position:absolute; border:2px solid var(--accent); cursor:move; touch-action:none;
  box-shadow:0 0 0 9999px rgba(10,10,15,.55); }
.crop-h{ position:absolute; width:16px; height:16px; background:var(--accent); border:2px solid #fff;
  border-radius:50%; touch-action:none; }
.crop-h[data-h="nw"]{ left:-9px; top:-9px; cursor:nwse-resize; }
.crop-h[data-h="ne"]{ right:-9px; top:-9px; cursor:nesw-resize; }
.crop-h[data-h="sw"]{ left:-9px; bottom:-9px; cursor:nesw-resize; }
.crop-h[data-h="se"]{ right:-9px; bottom:-9px; cursor:nwse-resize; }
.crop-az{ display:flex; gap:8px; align-items:center; margin-top:8px; line-height:normal; }
.dp-grid{ display:grid; grid-template-columns:120px 1fr; gap:12px; }
.dp-sez{ margin-top:16px; padding-top:14px; border-top:1px solid var(--border-2); }
.dp-sez-head{ display:flex; align-items:center; justify-content:space-between; gap:8px; font-size:13px; font-weight:600; margin-bottom:8px; }
.dp-sez-head > span{ display:inline-flex; align-items:center; gap:6px; }
.dp-coll{ list-style:none; margin:0 0 8px; padding:0; display:flex; flex-direction:column; gap:4px; }
.dp-coll li{ display:flex; align-items:center; gap:6px; font-size:12px; }
/* Riga-tubo nella sidebar della foto: toccabile (arma il segnaposto).
   TUTTO su una riga (nowrap): il piano si tronca coi puntini, il pallino
   verde sta ACCANTO alla × — mai a capo. */
.dp-coll-riga{ padding:5px 7px; border:1px solid var(--border-2); border-radius:var(--radius-sm);
  cursor:pointer; flex-wrap:nowrap; min-width:0; }
.dp-coll-riga:hover{ border-color:var(--text-muted); }
/* Un solo anello anche qui: bordo accent + sfondo tenue, niente outline sopra. */
.dp-coll-riga.sel{ border-color:var(--accent); background:var(--accent-soft); }
.dp-coll-dot{ width:12px; height:12px; border-radius:50%; border:1px solid var(--border-2); flex:0 0 auto; }
.dp-coll-mis{ font-size:11px; font-weight:700; color:var(--text-dim); flex:0 0 auto; }
.dp-coll-piano{ font-size:11px; flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dp-coll-et{ font-weight:700; flex:0 0 auto; }
.dp-coll-n{ font-size:11px; color:var(--text-dim); background:var(--input-bg); border-radius:var(--radius-sm); padding:1px 6px;
  max-width:64px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dp-coll-x{ margin-left:auto; display:inline-flex; padding:3px; color:var(--danger); background:none; border:none; cursor:pointer; border-radius:var(--radius-sm); }
.dp-coll-x:hover{ background:color-mix(in srgb, var(--danger) 12%, transparent); }
/* Scelta del punto da collegare: tendine (piano → punto), palette dei tubi e
   «Aggiungi» tutti su una riga SOTTO la foto. Le tendine sono strette: sono
   liste corte, non devono rubare spazio alla palette. */
.dpf-add{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin:10px 0 2px; }
.dp-sel{ flex:0 1 auto; max-width:130px; padding:5px 8px; background:var(--input-bg); color:var(--text);
  border:1px solid var(--border-2); border-radius:var(--radius-sm); font-size:12px; }
.dp-coll-colori{ display:flex; gap:6px; align-items:center; flex-wrap:wrap; padding-top:9px; }  /* aria per i badge Ø */
.dp-cc{ position:relative; width:20px; height:20px; border-radius:50%; background:var(--tc); border:2px solid var(--border-2); cursor:pointer; padding:0; flex:0 0 auto; }
/* Un solo anello di selezione: border colorato E outline insieme facevano due
   cerchi concentrici. Qui vince l'outline, staccato dal pallino. */
.dp-cc.sel{ outline:2px solid var(--accent); outline-offset:2px; }
.dp-cc-mis{ position:absolute; top:-9px; left:50%; transform:translateX(-50%);
  font-size:8px; font-weight:700; line-height:1; padding:1px 4px; color:var(--text);
  background:var(--card-bg); border:1px solid var(--border-2); border-radius:var(--radius-pill); }

/* Pallino verde a DESTRA della ×: questo tubo è già segnato sulla foto.
   Occupa il suo posto anche quando non c'è (.off, invisibile): le × restano
   incolonnate ferme in ogni riga. */
.dp-coll-fatto{ width:6px; height:6px; border-radius:50%; background:var(--success); flex:0 0 auto; }
.dp-coll-fatto.off{ visibility:hidden; }
.dp-foto-scelte{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:8px; }
.dp-fchip{ position:relative; width:64px; height:64px; border-radius:var(--radius-sm); overflow:hidden; border:2px solid var(--border-2); }
.dp-fchip img{ width:100%; height:100%; object-fit:cover; cursor:zoom-in; }
.dp-fx{ position:absolute; right:2px; top:2px; width:18px; height:18px; display:flex; align-items:center; justify-content:center;
  border:none; border-radius:50%; cursor:pointer; color:#fff; background:rgba(0,0,0,.55); }
.dp-galleria{ margin-top:6px; max-height:260px; overflow:auto; border:1px solid var(--border-2); border-radius:var(--radius); padding:8px; }
.dp-gall-grp{ font-size:11px; font-weight:700; color:var(--text-dim); text-transform:uppercase; letter-spacing:.04em; margin:6px 0 4px; }
.dp-gall-row{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:6px; }
.dp-gall-foto{ width:60px; height:60px; padding:0; border:2px solid transparent; border-radius:var(--radius-sm); overflow:hidden; cursor:pointer; background:none; }
.dp-gall-foto img{ width:100%; height:100%; object-fit:cover; display:block; }
.dp-gall-foto.is-sel{ border-color:var(--accent); }

@media (max-width:640px){
  .dp-grid{ grid-template-columns:1fr; }
  dialog.dlg-punto{ width:100%; }
}

.solo-stampa{ display:none; }
@media print{
  .sidebar, .sb-overlay, .topbar, .toolbar, .sb-foot,
  .empty[data-empty-for], .row-actions{ display:none; }
  .solo-stampa{ display:block; }
  .stampa-testata{ margin:0 0 10px; font-size:14px; color:#000; }
  body{ margin:0; padding:0; background:#fff; color:#000; }
  .content{ margin:0; padding:0; }
  .table-wrap{ border:none; box-shadow:none; background:#fff; }
  a[href]{ color:#000; }
  table{ font-size:11px; }
  thead th{ background:#eee; color:#000; }
  tfoot td{ background:#eee; }
}

/* Carico da fattura: righe precompilate dalla fattura elettronica — si
   riconoscono a colpo d'occhio e stanno in cima alla tabella. */
#tblCarico tr.riga-fe td{ background:color-mix(in srgb, var(--accent) 7%, transparent); }
#tblCarico tr.riga-fe td:first-child{ box-shadow:inset 3px 0 0 var(--accent); }
