/* ==========================================================================
   Quadra 2.0 — Design System (quadra.css)
   Standard UI ufficiale. Vedi analisi/05-decisioni/03-ui-design-system.md
   Da caricare DOPO bootstrap.min.css. Nessun SCSS: personalizzazione via
   variabili CSS. Nel progetto reale va servito self-hosted da static/quadra/css/.

   Derivato da imav.css di iMav 2.0 con analisi/strumenti/deriva_mockup_da_imav.py
   (prefisso quadra-, palette verde, blocco «Tema Bootstrap»): non modificarlo a mano,
   aggiornare lo script. Componenti nuovi si aggiungono quando le schermate di
   Quadra entrano nell'analisi.
   ========================================================================== */

/* Alpine.js: nasconde gli elementi con x-cloak finche' Alpine non inizializza. */
[x-cloak] { display: none !important; }

:root {
  /* Palette */
  --quadra-primary: #14614A;
  --quadra-primary-dark: #0E4836;
  --quadra-accent: #1E7A5C;
  --quadra-accent-hover: #17664C;
  --quadra-bg: #F1F4F3;
  --quadra-surface: #ffffff;
  --quadra-text: #16212A;
  --quadra-muted: #55666F;
  --quadra-muted-2: #62737B;
  --quadra-border: #DCE3E1;

  /* Stati (badge soft) */
  --quadra-success-bg: #E2F4F0; --quadra-success-fg: #0F7B6C;
  --quadra-warning-bg: #F8EFE1; --quadra-warning-fg: #8A5410;
  --quadra-danger-bg:  #fbe6e6; --quadra-danger-fg:  #b02a2a;
  --quadra-info-bg:    #e5f0fb; --quadra-info-fg:    #1c5fb0;
  --quadra-neutral-bg: #ECEFEE; --quadra-neutral-fg: #55666F;

  /* Forme */
  --quadra-radius: .75rem;
  --quadra-radius-sm: .5rem;
  --quadra-shadow: 0 1px 3px rgba(16,40,32,.08);
  --quadra-sidebar-width: 15.25rem;
  --quadra-topbar-height: 3.5rem;

  /* Icone (scala dimensionale; vedi 03-ui-design-system.md §6).
     Regola di base: senza token l'icona eredita il font-size del contesto.
     I token servono solo quando l'icona deve staccarsi dal testo che la circonda. */
  --quadra-icon-sm: .78rem;   /* icona di servizio accanto a testo ridotto */
  --quadra-icon-md: 1rem;     /* icona-dato o icona di comando */
  --quadra-icon-lg: 1.25rem;  /* icona di identita' o di messaggio: brand, toast */
  --quadra-icon-xl: 1.75rem;  /* icona illustrativa: dropzone, stati vuoti */

  /* Tabelle (tinte derivate dalla palette della soluzione) */
  --quadra-table-head-bg: #EAF0EE;   /* banda intestazione (come sfondo <code>) */
  --quadra-table-stripe:  #F5F8F7;   /* riga alternata: neutro chiarissimo */
  --quadra-table-hover:   #E7F0EC;   /* hover: tinta accent chiara */
  --quadra-table-selected: #D5E7DF;  /* record selezionato: tinta accent un grado sopra l'hover */
  --quadra-table-max-height: 22rem;  /* tetto in modalita' "auto" (tabelle annidate) */
  --quadra-table-search-width: 17.5rem; /* ricerca globale della toolbar (280px) */
  --quadra-badge-status-width: 6.5rem; /* badge di stato: larghezza comune, cosi' incolonnati restano allineati */
  --quadra-col-code-width: 8rem;     /* riserva minima di una colonna-codice (128px) */
  --quadra-col-num-width: 7.5rem;    /* colonna di importi o numeri: regge «999.999,99 €» (120px) */
  --quadra-col-date-width: 8.25rem;  /* colonna-data senza ora: misura identica per tutte (132px) */
  --quadra-col-datetime-width: 9.5rem; /* colonna data e ora: misura identica per tutte (152px) */
  --quadra-col-w-sm: 8rem;           /* colonna a misura fissa, piccola (128px): icona-dato, sigla */
  --quadra-col-w-md: 9.5rem;         /* colonna a misura fissa, media (152px): autore, stato breve */
  --quadra-col-w-lg: 13.5rem;        /* colonna a misura fissa, grande (216px): badge di evento/stato */
  --quadra-col-actions-count: 2;     /* comandi ospitabili dalla colonna azioni (default: modifica + elimina) */
  --quadra-col-actions-slot: 1.875rem; /* passo di un comando di riga: bottone 26px + gap 4px */

  /* Tipografia (font di sistema, self-hosted per definizione) */
  --quadra-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
               Arial, "Noto Sans", sans-serif;
  /* Monospace di sistema moderno per i tracciati a larghezza fissa (design system §5) */
  --quadra-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, "Cascadia Mono", "Cascadia Code",
                    Consolas, "Liberation Mono", monospace;
}

/* Bootstrap theme override (accent = colore componenti primary) */
:root {
  --bs-primary: #1E7A5C;
  --bs-primary-rgb: 30,122,92;
  --bs-body-color: #16212A;
  --bs-body-bg: #F1F4F3;
  --bs-border-color: #DCE3E1;
  --bs-link-color: #17664C;
  --bs-link-hover-color: #14614A;
}

/* ------------------------------------------- Tema Bootstrap: verde Quadra ---- */
/* Bootstrap 5.3 compilato fissa il blu #0d6efd nelle variabili dei componenti e in alcuni
   selettori, invece di derivarlo da --bs-primary: qui si riallineano all'accent di Quadra. */
:root {
  --bs-primary-text-emphasis: #0C3127;
  --bs-primary-bg-subtle: #D5E7DF;
  --bs-primary-border-subtle: #A9D1C2;
  --bs-link-color-rgb: 23,102,76;
  --bs-link-hover-color-rgb: 20,97,74;
  --bs-focus-ring-color: rgba(30,122,92,.25);
}
.nav-pills { --bs-nav-pills-link-active-bg: var(--quadra-accent); }
.dropdown-menu { --bs-dropdown-link-active-bg: var(--quadra-accent); }
.list-group { --bs-list-group-active-bg: var(--quadra-accent); --bs-list-group-active-border-color: var(--quadra-accent); }
.pagination { --bs-pagination-active-bg: var(--quadra-accent); --bs-pagination-active-border-color: var(--quadra-accent);
  --bs-pagination-color: var(--quadra-accent-hover); --bs-pagination-hover-color: var(--quadra-primary);
  --bs-pagination-focus-color: var(--quadra-primary); --bs-pagination-focus-box-shadow: 0 0 0 .25rem rgba(30,122,92,.25); }
.progress, .progress-stacked { --bs-progress-bar-bg: var(--quadra-accent); }
.btn-primary { --bs-btn-bg: var(--quadra-accent); --bs-btn-border-color: var(--quadra-accent);
  --bs-btn-hover-bg: var(--quadra-accent-hover); --bs-btn-hover-border-color: var(--quadra-accent-hover);
  --bs-btn-active-bg: var(--quadra-primary); --bs-btn-active-border-color: var(--quadra-primary);
  --bs-btn-disabled-bg: var(--quadra-accent); --bs-btn-disabled-border-color: var(--quadra-accent); --bs-btn-focus-shadow-rgb: 30,122,92; }
.btn-outline-primary { --bs-btn-color: var(--quadra-accent); --bs-btn-border-color: var(--quadra-accent);
  --bs-btn-hover-bg: var(--quadra-accent); --bs-btn-hover-border-color: var(--quadra-accent);
  --bs-btn-active-bg: var(--quadra-accent); --bs-btn-active-border-color: var(--quadra-accent);
  --bs-btn-disabled-color: var(--quadra-accent); --bs-btn-disabled-border-color: var(--quadra-accent); --bs-btn-focus-shadow-rgb: 30,122,92; }
.table-primary { --bs-table-bg: #D5E7DF; --bs-table-border-color: #BFD3CC; }
.nav-link:focus-visible { box-shadow: 0 0 0 .25rem rgba(30,122,92,.25); }
.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: #8FC5B1; box-shadow: 0 0 0 .25rem rgba(30,122,92,.25);
}
.form-check-input:checked, .form-check-input[type=checkbox]:indeterminate {
  background-color: var(--quadra-accent); border-color: var(--quadra-accent);
}
.form-switch .form-check-input:focus {
  --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%238FC5B1'/%3e%3c/svg%3e");
}
.form-range::-webkit-slider-thumb { background-color: var(--quadra-accent); }
.form-range::-webkit-slider-thumb:active { background-color: #BFE0D3; }
.form-range::-moz-range-thumb { background-color: var(--quadra-accent); }
.form-range::-moz-range-thumb:active { background-color: #BFE0D3; }
.form-range:focus::-webkit-slider-thumb, .form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(30,122,92,.25); }
.accordion {
  --bs-accordion-btn-focus-box-shadow: 0 0 0 .25rem rgba(30,122,92,.25);
  --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%230C3127' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e");
}

/* --------------------------------------------------------------- Base ---- */
body {
  background: var(--quadra-bg);
  color: var(--quadra-text);
  font-family: var(--quadra-font);
}
a { text-decoration: none; }
code {
  background: #EAF0EE; padding: .1rem .4rem; border-radius: .35rem;
  color: var(--quadra-primary);
}

/* Contenitore pagina (come .app-shell del mockup 2.0) */
.app-shell { max-width: 1400px; margin: 1.5rem auto; padding: 0 1rem; }

/* Banner informativo del mockup (solo anteprima statica) */
.mockup-banner {
  background: linear-gradient(90deg, var(--quadra-primary), var(--quadra-accent));
  color: #fff; padding: .4rem 1rem; font-size: .8rem;
}

/* ------------------------------------------------ Application shell ---- */
/* Layout flex secondo l'esempio ufficiale Bootstrap "Sidebars". */
.quadra-shell { display: flex; height: 100vh; overflow: hidden; }
.quadra-shell-preview { height: auto; min-height: 22rem; overflow: visible; }
.quadra-shell-preview .quadra-sidebar,
.quadra-shell-preview .quadra-main { height: auto; overflow: visible; }
.quadra-shell-preview .quadra-content.quadra-fill { display: block; overflow: visible; }

/* Sidebar: contenitore Bootstrap (in markup: d-flex flex-column flex-shrink-0 p-3),
   voci come .nav.nav-pills.flex-column native. Qui solo il tema navy + larghezza. */
.quadra-sidebar {
  width: var(--quadra-sidebar-width);
  height: 100vh; overflow-y: auto;
  background: var(--quadra-primary); color: #D3E0DB;
}
/* Sidebar senza animazioni (v. 26.10.12.B): compressione, apertura dei gruppi, chevron e passaggio del
   mouse sono istantanei; .collapsing e' la tendina del Collapse di Bootstrap (durata 0 = apertura subito). */
.quadra-sidebar .nav-link,
.quadra-sidebar .collapsing { transition: none; }
.quadra-sidebar .quadra-brand { color: #fff; }
.quadra-sidebar .quadra-brand .bi { color: #9FD8C1; }
.quadra-sidebar .nav-link { color: #D3E0DB; }
.quadra-sidebar .nav-link:hover { background: rgba(255,255,255,.08); color: #fff; }
.quadra-sidebar .nav-link.active { color: #fff; } /* sfondo = --bs-primary (accent) via .nav-pills */
/* Divisore della sidebar: linea sottile sfumata, trasparente ai bordi e piu' luminosa al centro. */
.quadra-sidebar hr {
  height: 1px; border: 0; opacity: 1;
  background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.35) 50%, rgba(255,255,255,0));
}
.quadra-sidebar-section {
  color: #BFD3CC; font-size: .68rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
}

/* Contenuto principale accanto alla sidebar (flex). */
/* Contenitore di scroll: la sidebar resta fissa, il contenuto scorre sotto la topbar e le tab sticky. */
.quadra-main { flex: 1 1 auto; min-width: 0; height: 100vh; overflow-y: auto; }

/* Wrapper del contenuto di pagina (in markup: p-4). Cresce per occupare lo spazio
   residuo sotto la topbar; con `min-height: 0` non impedisce lo shrink dei figli. */
.quadra-content { flex: 1 1 auto; min-height: 0; }
/* Pagine che SCORRONO (tutte tranne le pagine-lista .quadra-fill): il wrapper non si
   restringe all'altezza della finestra ma segue il contenuto. Altrimenti il contenuto
   ne esce e gli elementi sticky (.quadra-sticky-tabs, .quadra-sticky-entity), che non
   possono uscire dal loro contenitore, dopo una pagina di scroll vengono trascinati via. */
.quadra-content:not(.quadra-fill) { flex-shrink: 0; }

/* Modificatore "fill": pagine il cui contenuto principale e' una tabella dati.
   La pagina non scorre, scorre solo il corpo righe (vedi .quadra-table-fill).
   L'overflow auto e' la rete di sicurezza per viewport troppo basse. */
.quadra-content.quadra-fill { display: flex; flex-direction: column; overflow: auto; }
.quadra-content.quadra-fill > * { flex: 0 0 auto; }
.quadra-fill > .card.quadra-card {
  flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0;
}

/* Topbar: .navbar Bootstrap tematizzata (superficie, bordo, altezza). */
.quadra-topbar {
  position: sticky; top: 0; z-index: 1030;
  min-height: var(--quadra-topbar-height);
  background: var(--quadra-surface);
  border-bottom: 1px solid var(--quadra-border);
}
.quadra-topbar-title { color: var(--quadra-primary); font-size: .9rem; font-weight: 600; }

/* Tab-bar appiccicata sotto la topbar: il contenuto scorre verticalmente sotto le tab. */
.quadra-sticky-tabs {
  position: sticky; top: var(--quadra-topbar-height); z-index: 1020;
  background: var(--quadra-bg);
}
/* Nelle pagine-lista .quadra-fill il contenitore di scroll e' .quadra-content (non
   .quadra-main, gia' sotto la topbar): l'offset della topbar spingerebbe la tab-bar
   sopra la ricerca e l'intestazione della tabella. */
.quadra-content.quadra-fill .quadra-sticky-tabs { top: 0; }

/* Header dell'entita' e tab-bar FISSI insieme sotto la topbar (.quadra-sticky-entity):
   nelle schede di un record (es. l'avviso emesso) l'operatore non perde mai di vista
   CHE COSA sta guardando mentre il contenuto scorre sotto. Il blocco avvolge
   .quadra-entity-header e la tab-bar; margine negativo e padding pari al padding del
   contenuto (p-4) tengono la stessa posizione a riposo e coprono, quando e' fermo,
   la fascia fra topbar e header. Le note persistenti vanno DOPO il blocco. */
.quadra-sticky-entity {
  position: sticky; top: var(--quadra-topbar-height); z-index: 1020;
  background: var(--quadra-bg);
  margin-top: -1.5rem; padding-top: 1.5rem; padding-bottom: 1rem;
}
/* Il margine dell'ultimo elemento (header o tab-bar) non deve uscire dal blocco: la
   fascia sotto resta coperta dallo sfondo anche quando il blocco e' fermo. */
.quadra-sticky-entity > :last-child { margin-bottom: 0 !important; }

/* Azioni primarie del form nella topbar (Salva/Annulla): icona + testo, rettangolari e di egual misura. */
.quadra-form-action.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .3rem; min-width: 5.25rem;
}

/* Sidebar comprimibile a "rail" di sole icone (toggle .quadra-collapsed sulla shell).
   In stato compresso azzera i padding laterali (come .nav-flush dell'esempio Bootstrap)
   cosi' le icone si centrano nell'intera larghezza del rail. */
.quadra-shell.quadra-collapsed { --quadra-sidebar-width: 4rem; }
.quadra-collapsed .quadra-sidebar { padding-left: 0 !important; padding-right: 0 !important; }
.quadra-collapsed .quadra-sidebar .nav-link,
.quadra-collapsed .quadra-sidebar > a {
  display: flex; align-items: center; justify-content: center;
  padding-left: 0; padding-right: 0;
}
.quadra-collapsed .quadra-sidebar .bi { margin-right: 0 !important; }
.quadra-collapsed .quadra-link-text,
.quadra-collapsed .quadra-brand-text { display: none; }
/* Titoli di sezione nel rail (v. 26.10.11.B): restano come spazio vuoto della stessa altezza, cosi' ogni
   icona del rail sta alla stessa quota della voce espansa e comprimendo nulla si sposta in verticale. */
.quadra-collapsed .quadra-sidebar-section { visibility: hidden; white-space: nowrap; overflow: hidden; }
/* Menu utente nel rail: icona centrata come le voci, senza il triangolino del dropdown. Il menu
   usa Popper "fixed" (data-bs-popper-config) e si apre a destra (.dropend), fuori dal rail. */
.quadra-collapsed .quadra-user-menu > a { justify-content: center; }
.quadra-collapsed .quadra-user-menu > .dropdown-toggle::after { display: none; }
.quadra-collapsed .quadra-user-menu .dropdown-menu .bi { margin-right: .25rem !important; }

/* Contatore di una voce della sidebar (.quadra-nav-count, v. 26.10.03.B): .badge.rounded-pill a destra
   del testo, la voce diventa d-flex. Base accent (informativo), .warn per le scadenze; a zero non si
   mostra (lo omette il server). Nel rail compresso diventa un bollino sull'angolo dell'icona. */
.quadra-nav-count {
  background: var(--quadra-accent); color: #fff;
  font-weight: 600; font-variant-numeric: tabular-nums;
}
.quadra-nav-count.warn { background: var(--quadra-warning-bg); color: var(--quadra-warning-fg); }
.quadra-sidebar .nav-link.active .quadra-nav-count:not(.warn) { background: rgba(255, 255, 255, .25); }
.quadra-collapsed .quadra-sidebar .nav-link { position: relative; }
.quadra-collapsed .quadra-nav-count {
  position: absolute; top: .1rem; right: .6rem;
  font-size: .6rem; padding: .2em .4em;
}

/* Riga versione in fondo alla sidebar: release a sinistra, geotag del percorso a destra.
   Nel rail compresso le due icone restano affiancate su una riga (v. 26.10.11.B), per l'allineamento. */
.quadra-geotag {
  background: transparent; border: 0; padding: 0 .15rem; line-height: 1;
  color: inherit; border-radius: var(--bs-border-radius-sm);
}
.quadra-geotag:hover { color: #fff; }
.quadra-geotag:focus-visible { outline: 2px solid #9FD8C1; outline-offset: 2px; }
.quadra-collapsed .quadra-version { justify-content: center; gap: .6rem; }
.quadra-collapsed .quadra-version .quadra-geotag { margin-left: 0 !important; }

/* Voce con sottovoci della sidebar (.quadra-nav-group, v. 26.10.11.B, UI-09). Il gruppo e' un <button
   class="nav-link quadra-nav-toggle"> con il Collapse di Bootstrap (data-bs-toggle="collapse",
   aria-controls, aria-expanded) sul <ul class="nav nav-pills flex-column quadra-subnav collapse">; il
   tooltip sta sull'<i> dell'icona perche' il pulsante porta gia' il collapse. Il <li> porta .open
   (dal server per il gruppo della pagina corrente, poi da quadra.js) e .has-active.
   Righe ad altezza fissa ed etichette su una riga: ogni icona del rail sta alla stessa quota della voce
   espansa. */
.quadra-sidebar .quadra-brand { height: 1.5rem; }
.quadra-sidebar .nav-link { height: 2.5rem; }
.quadra-sidebar .quadra-link-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.quadra-nav-toggle { width: 100%; text-align: start; }
.quadra-nav-chevron { font-size: var(--quadra-icon-sm); opacity: .7; }
.quadra-nav-group.open > .quadra-nav-toggle .quadra-nav-chevron { transform: rotate(90deg); }
/* Gruppo che contiene la pagina corrente: testo pieno, senza riempimento (il pieno resta alla voce). */
.quadra-sidebar .quadra-nav-group.has-active > .quadra-nav-toggle { color: #fff; font-weight: 600; }
/* Contatore del gruppo (.quadra-nav-sum, somma delle sottovoci): solo a gruppo chiuso. */
.quadra-nav-group.open > .quadra-nav-toggle .quadra-nav-sum { display: none; }
.quadra-nav-group.open > .quadra-nav-toggle .quadra-nav-sum + .quadra-nav-chevron { margin-left: auto !important; }
.quadra-subnav {
  margin: .15rem 0 .3rem 1.05rem; padding-left: .45rem;
  border-left: 1px solid rgba(255,255,255,.16);
}
.quadra-sidebar .quadra-subnav .nav-link { height: 1.9rem; padding: .3rem .6rem; font-size: .875rem; }
/* Rail: chevron a destra e centrato come nell'espansa; il gruppo aperto diventa una «capsula» con le
   icone delle sottovoci in linea, separate dall'icona del gruppo da una linea sovrapposta (non occupa
   altezza). */
.quadra-collapsed .quadra-nav-toggle { position: relative; }
.quadra-collapsed .quadra-nav-chevron {
  position: absolute; right: .3rem; top: 50%;
  transform: translateY(-50%); margin: 0 !important;
}
.quadra-collapsed .quadra-nav-group.open > .quadra-nav-toggle .quadra-nav-chevron { right: .2rem; transform: translateY(-50%) rotate(90deg); }
.quadra-collapsed .quadra-nav-group.open {
  background: rgba(255,255,255,.07); border-radius: .75rem; margin: 0 .4rem;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
}
.quadra-collapsed .quadra-nav-group.has-active:not(.open) > .quadra-nav-toggle { background: rgba(255,255,255,.14); }
.quadra-collapsed .quadra-subnav { position: relative; margin: .15rem .35rem .3rem; padding: 0; border: 0; }
.quadra-collapsed .quadra-subnav::before {
  content: ''; position: absolute; left: 0; right: 0; top: -.1rem; height: 1px;
  background: rgba(255,255,255,.12);
}
.quadra-collapsed .quadra-subnav .quadra-nav-count { right: .05rem; top: 0; }

/* Comandi contestuali: sono normali .btn di Bootstrap.
   - solo icona:        .btn .btn-sm .btn-outline-secondary .quadra-btn-icon
   - icona + testo:     .btn .btn-sm .btn-outline-secondary
   Nessuna classe custom oltre al modificatore di forma quadrata qui sotto. */

/* Modificatore: bottone-icona "ghost" quadrato, senza outline a riposo.
   Si appoggia a .btn (per stati/focus/disabled) e personalizza solo le variabili
   native --bs-btn-* di Bootstrap 5.3. Pensato per toolbar di comandi contestuali. */
.quadra-btn-icon {
  --bs-btn-padding-x: .4rem;
  --bs-btn-padding-y: .4rem;
  --bs-btn-color: var(--quadra-muted);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--quadra-primary);
  --bs-btn-hover-bg: #F3F8F6;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--quadra-primary);
  --bs-btn-active-bg: #EAF0EE;
  --bs-btn-active-border-color: transparent;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
}
.quadra-btn-icon.danger {
  --bs-btn-hover-color: var(--quadra-danger-fg);
  --bs-btn-hover-bg: var(--quadra-danger-bg);
  --bs-btn-active-color: var(--quadra-danger-fg);
  --bs-btn-active-bg: var(--quadra-danger-bg);
}

/* ECCEZIONE documentata: comando etichettato 40x40 (icona sopra, testo minuscolo sotto).
   Non esiste un equivalente nativo in Bootstrap; si appoggia comunque a .btn per
   ereditare stati (hover/focus/disabled) e accessibilita'. */
.quadra-command-labeled.btn {
  --bs-btn-padding-x: .2rem;
  --bs-btn-padding-y: .2rem;
  width: 2.5rem; height: 2.5rem;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .1rem; font-size: .5rem; font-weight: 600; line-height: 1;
}
.quadra-command-labeled.btn .bi { font-size: var(--quadra-icon-md); line-height: 1; }

/* ------------------------------------------------------ Entity header --- */
/* Componente su base Bootstrap .card (tematizzato via --bs-card-* + flex header). */
.card.quadra-entity-header {
  --bs-card-bg: var(--quadra-surface);
  --bs-card-border-width: 0;
  --bs-card-border-radius: var(--quadra-radius);
  box-shadow: var(--quadra-shadow); margin-bottom: 1rem;
  flex-direction: row; justify-content: space-between; align-items: flex-start;
  gap: 1rem; flex-wrap: wrap; padding: 1.1rem 1.4rem;
}
.entity-title { font-size: 1.25rem; font-weight: 700; color: var(--quadra-primary); margin: 0; }
.entity-sub { font-size: .8rem; color: #6E807A; }
.entity-codes { font-size: .78rem; color: var(--quadra-muted); margin-top: .35rem; }
.entity-codes code { background: #EAF0EE; padding: .1rem .4rem; border-radius: .35rem; color: var(--quadra-primary); }

/* -------------------------------------------------------- Content card -- */
/* Componente su base Bootstrap .card (tematizzato via --bs-card-*). */
.card.quadra-card {
  --bs-card-bg: var(--quadra-surface);
  --bs-card-border-width: 0;
  --bs-card-border-radius: var(--quadra-radius);
  box-shadow: var(--quadra-shadow); overflow: hidden;
}

/* --------------------------------------------------------- Nav pills ---- */
.nav-pills-modern { padding: 1rem 1.25rem 0; gap: .35rem; border-bottom: 1px solid var(--quadra-border); }
.nav-pills-modern .nav-link {
  color: var(--quadra-muted); font-size: .85rem; font-weight: 500;
  border-radius: .5rem .5rem 0 0; padding: .5rem .9rem;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.nav-pills-modern .nav-link .bi { margin-right: .35rem; }
.nav-pills-modern .nav-link:hover { color: var(--quadra-primary); }
.nav-pills-modern .nav-link.active {
  color: var(--quadra-accent); background: transparent;
  border-bottom: 2px solid var(--quadra-accent);
}
/* Gruppi di schede (v. 26.10.15.G): etichetta non cliccabile che apre un gruppo nella stessa tab-bar;
   dal secondo gruppo in poi un separatore verticale la stacca dal gruppo precedente. */
.nav-pills-modern .quadra-tab-group {
  display: flex; align-items: center; padding: .5rem .25rem .5rem 0;
  font-size: .7rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--quadra-muted); white-space: nowrap;
}
.nav-pills-modern .nav-item + .quadra-tab-group {
  margin-left: .5rem; padding-left: .75rem; border-left: 1px solid var(--quadra-border);
}
.tab-body { padding: 1.5rem; }

/* ------------------------------------------------------ Forms / labels -- */
fieldset legend {
  font-size: .9rem; font-weight: 600; color: var(--quadra-primary);
  text-transform: uppercase; letter-spacing: .03em;
  border-bottom: 1px solid var(--quadra-border);
  padding-bottom: .35rem; margin-bottom: 1rem; float: none;
}
.form-label {
  font-size: .76rem; font-weight: 500; color: var(--quadra-muted-2);
  margin-bottom: .2rem; text-transform: uppercase; letter-spacing: .02em;
}
.form-control, .form-select { font-size: .88rem; border-color: #D6DFDC; }
.form-control:focus, .form-select:focus {
  border-color: var(--quadra-accent);
  box-shadow: 0 0 0 .2rem rgba(30,122,92,.15);
}
.form-control:disabled, .form-select:disabled { background: #F6F8F7; }
/* CAP (5 cifre): stato invalido e messaggio di aiuto, coerenti col design
   system. La validita' e' gestita in quadra.js (.quadra-cap): qui solo la resa.
   Il feedback compare quando il campo e' :invalid (1-4 cifre) senza dover
   attivare .was-validated a livello di form. */
.form-control.quadra-cap { letter-spacing: .12em; }
.form-control.quadra-cap:invalid {
  border-color: var(--quadra-danger-fg);
}
.form-control.quadra-cap:invalid:focus {
  box-shadow: 0 0 0 .2rem rgba(176,42,42,.15);
}
.form-control.quadra-cap:invalid ~ .invalid-feedback { display: block; }
/* Numeri con evidenza delle migliaia: cifre a larghezza fissa (tabular) per
   allineare colonne e separatori delle migliaia. Utility condivisa del design
   system: applicabile a celle, input e testo che mostrano numeri/importi. */
.quadra-num, .quadra-num input,
td[data-number], td[data-amount],
.form-control[data-amount], .form-control[data-number] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* Checkbox/radio: bordo piu' marcato (il --bs-border-color globale e' troppo tenue per
   un quadratino) e stato selezionato/focus allineati all'accent del design system. */
.form-check-input { border-color: #A9B8B3; }
.form-check-input:checked { background-color: var(--quadra-accent); border-color: var(--quadra-accent); }
.form-check-input:focus {
  border-color: var(--quadra-accent);
  box-shadow: 0 0 0 .2rem rgba(30,122,92,.15);
}

/* ------------------------------------------------------------- Badges --- */
/* Larghezza comune (non "minima per stare stretti"): badge incolonnati devono avere
   la STESSA misura, altrimenti il bordo destro balla da una riga all'altra e la
   colonna si legge male. Il valore e' un parametro di contesto, non una costante:
   si sovrascrive la variabile sul contenitore quando i badge portano piu' testo. */
.badge-status {
  font-weight: 600; font-size: .72rem; padding: .4em .7em; border-radius: 2rem;
  min-width: var(--quadra-badge-status-width); display: inline-flex; align-items: center; justify-content: center;
  gap: .3rem;
}
.badge-soft-success { background: var(--quadra-success-bg); color: var(--quadra-success-fg); }
.badge-soft-warning { background: var(--quadra-warning-bg); color: var(--quadra-warning-fg); }
.badge-soft-danger  { background: var(--quadra-danger-bg);  color: var(--quadra-danger-fg); }
.badge-soft-info    { background: var(--quadra-info-bg);    color: var(--quadra-info-fg); }
.badge-soft-neutral { background: var(--quadra-neutral-bg); color: var(--quadra-neutral-fg); }
/* Badge a contorno: e' la forma delle CLASSIFICAZIONI (che cos'e'), contrapposta al
   badge pieno degli STATI (come sta). Distinguere i due per **forma** invece che per
   tinta libera la palette da un compito che non sa svolgere: le varianti sono cinque e
   se una serve a dire "categoria" non e' piu' disponibile per dire "esito". Cosi' il
   colore resta un segnale scarso e leggibile, e la categoria conserva comunque la sua
   presenza visiva. */
.badge-status.badge-outline {
  background: transparent; color: var(--quadra-muted-2);
  box-shadow: inset 0 0 0 1px var(--quadra-border);
}

/* ------------------------------------------------------------ Buttons --- */
.btn-quadra { background: var(--quadra-accent); border-color: var(--quadra-accent); color: #fff; }
.btn-quadra:hover, .btn-quadra:focus { background: var(--quadra-accent-hover); border-color: var(--quadra-accent-hover); color: #fff; }
.btn-outline-quadra { color: var(--quadra-accent); border-color: var(--quadra-accent); }
.btn-outline-quadra:hover { background: var(--quadra-accent); color: #fff; }

/* --------------------------------------------------------- Agent card --- */
/* Componente su base Bootstrap .card (tematizzato via --bs-card-*). */
.card.quadra-agent-card {
  --bs-card-bg: var(--quadra-surface);
  --bs-card-border-color: var(--quadra-border);
  --bs-card-border-radius: .6rem;
  padding: 1rem;
}
.quadra-agent-card h6 {
  font-size: .8rem; color: var(--quadra-primary); font-weight: 700;
  text-transform: uppercase; margin-bottom: .75rem;
}

/* --------------------------------------------------------------- Notes --- */
/* Componente su base Bootstrap .alert (tematizzato via --bs-alert-* + bordo sx). */
.alert.quadra-note {
  --bs-alert-bg: #EAF3EF;
  --bs-alert-border-color: transparent;
  --bs-alert-color: #3A4A53;
  border-left: 3px solid var(--quadra-accent);
  border-radius: .35rem; padding: .5rem .75rem; font-size: .8rem; margin-bottom: 0;
}
.alert.quadra-note.warn { --bs-alert-bg: #FBF4EA; border-left-color: var(--quadra-warning-fg); }
.alert.quadra-note.danger { --bs-alert-bg: #fdeeee; border-left-color: var(--quadra-danger-fg); }
.doc-status { display: inline-flex; align-items: center; gap: .3rem; font-size: .8rem; }

/* ------------------------------------------------------------- Modali ---- */
/* La superficie della modale usa lo sfondo "surface" (bianco), non il grigio del
   body: garantisce contrasto ai controlli interni (campi, checkbox, ecc.). */
.modal {
  --bs-modal-bg: var(--quadra-surface);
  --bs-modal-border-color: var(--quadra-border);
  --bs-modal-border-radius: var(--quadra-radius);
}
/* L'elenco di Tom Select e' agganciato a <body> (dropdownParent): sopra la modale
   (1055) e sotto tooltip (1080) e toast, altrimenti in una modale resta nascosto. */
.ts-dropdown { z-index: 1060; }

/* -------------------------------------------------------------- Toast ---- */
.toast-container { z-index: 1200; }

/* ------------------------------------------------------------- Tabelle --- */
/* .table Bootstrap tematizzata sulla palette (tinte via --bs-table-*).
   Ordinamento/filtri/paginazione: HTMX server-side in produzione; Alpine per
   piccole tabelle gia' caricate / anteprime. Contenuti e intestazioni con lo
   stesso font-size; allineamento per colonna (text-start/center/end) applicato
   sia all'header sia alle celle. */
.quadra-table {
  --bs-table-bg: var(--quadra-surface);
  --bs-table-color: var(--quadra-text);
  --bs-table-border-color: var(--quadra-border);
  --bs-table-striped-bg: var(--quadra-table-stripe);
  --bs-table-striped-color: var(--quadra-text);
  --bs-table-hover-bg: var(--quadra-table-hover);
  --bs-table-hover-color: var(--quadra-text);
  --bs-table-cell-padding-y: .35rem;   /* righe compatte: header e celle stessa altezza */
}
.quadra-table .badge-status { padding-top: .12em; padding-bottom: .12em; }
.quadra-table .row-actions .btn { --bs-btn-padding-y: .05rem; --bs-btn-padding-x: .3rem; }
.quadra-table thead th,
.quadra-table tbody td { font-size: .78rem; }
.quadra-table thead th {
  background: var(--quadra-table-head-bg);
  text-transform: uppercase; letter-spacing: .03em;
  color: var(--quadra-muted-2); font-weight: 600; white-space: nowrap;
  border-bottom-color: var(--quadra-border);
}
/* Etichetta intestazione = zona di ordinamento; imbutino = zona di filtro.
   Contenuto in inline-flex: etichetta + gruppo icone; le due icone vicine tra loro. */
.quadra-table thead th .quadra-th-inner { display: inline-flex; align-items: center; gap: .4rem; }
.quadra-table thead th .quadra-th-icons { display: inline-flex; align-items: center; gap: .15rem; }
.quadra-table thead th .quadra-th-label { cursor: pointer; user-select: none; }
.quadra-table thead th .quadra-th-label:hover { color: var(--quadra-primary); }
.quadra-table thead th .quadra-th-hastip { text-decoration: underline dotted; text-underline-offset: 3px; text-decoration-color: var(--quadra-muted-2); }
.quadra-table thead th .quadra-th-sort {
  font-size: .7rem; opacity: .55; cursor: pointer;
  width: 1em; display: inline-flex; justify-content: center; flex: 0 0 1em;
}
.quadra-table thead th .quadra-th-sort.quadra-active { opacity: 1; color: var(--quadra-accent); }
.quadra-table thead th .quadra-th-label:hover + .quadra-th-icons .quadra-th-sort { opacity: .9; color: var(--quadra-accent); }
.quadra-th-filter {
  border: 0; background: transparent; padding: 0; color: var(--quadra-muted);
  line-height: 1; cursor: pointer; display: inline-flex; align-items: center;
}
.quadra-th-filter:hover { color: var(--quadra-accent); }
.quadra-th-filter .bi { font-size: var(--quadra-icon-sm); width: 1em; display: inline-flex; justify-content: center; }
.quadra-table tbody td { vertical-align: middle; }

/* Colonna-codice (§7.1, parametro `cls`): ospita un identificativo strutturato —
   il protocollo della pratica, una matricola — che non deve andare a capo ne'
   essere compresso quando la tabella si stringe. Cifre a larghezza fissa perche'
   i codici incolonnati restino confrontabili a occhio, e una larghezza minima con
   margine per la crescita del numero (invio a tre cifre). La misura sta qui, non
   in attributi style del markup. */
.quadra-table th.quadra-col-code,
.quadra-table td.quadra-col-code {
  min-width: var(--quadra-col-code-width); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* In tabella il codice NON e' un chip. Il fondo di `code` serve a staccare un
   identificativo dentro un testo corrente; in una colonna, dove ogni riga ne porta uno
   (e spesso due), diventa una colonna di pasticche grigie che pesa quanto un dato
   importante senza esserlo. Resta il monospace con le cifre a larghezza fissa, che e'
   cio' che serve davvero: confrontare i codici a occhio. Il chip continua a valere
   altrove — nelle intestazioni entita', dove i codici sono pochi e vanno copiati. */
.quadra-table code {
  background: transparent; padding: 0; border-radius: 0;
  color: inherit; font-variant-numeric: tabular-nums;
}

/* Colonne temporali (§7.1) — REGOLA: dentro lo stesso prospetto tutte le colonne
   "data" hanno la STESSA larghezza, e tutte le colonne "data e ora" hanno la stessa
   larghezza fra loro. Non e' estetica: quando in una tabella convivono piu' date
   l'occhio le confronta in verticale, e colonne di misura diversa fanno sembrare
   diversi dei dati che diversi non sono (e spostano le cifre, che con tabular-nums
   stanno invece incolonnate). Le due famiglie restano distinte perche' l'ora e'
   contenuto in piu': accomunarle sprecherebbe spazio sulle date secche.
   La misura e' FISSA (width + min + max) e pari alla piu' piccola che regge
   l'intestazione piu' lunga insieme alle sue icone di ordinamento e filtro:
   niente spazio in eccesso, in tabelle che di colonne ne hanno molte. */
.quadra-table th.quadra-col-date,
.quadra-table td.quadra-col-date {
  width: var(--quadra-col-date-width);
  min-width: var(--quadra-col-date-width);
  max-width: var(--quadra-col-date-width);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.quadra-table th.quadra-col-datetime,
.quadra-table td.quadra-col-datetime {
  width: var(--quadra-col-datetime-width);
  min-width: var(--quadra-col-datetime-width);
  max-width: var(--quadra-col-datetime-width);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Colonne di importi e numeri (§9): misura minima comune, cifre incolonnate e mai a capo. L'allineamento resta
   all'intestazione e alle celle (text-end per gli importi, text-center per i conteggi). Un importo piu' lungo
   allarga la colonna invece di andare a capo. */
.quadra-table th.quadra-col-num,
.quadra-table td.quadra-col-num {
  width: var(--quadra-col-num-width);
  min-width: var(--quadra-col-num-width);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Colonne a misura fissa (§7.1) — .quadra-col-w-sm / -md / -lg: in una tabella
   PAGINATA la larghezza di una colonna non deve dipendere dal contenuto della pagina
   visualizzata, altrimenti cambiando pagina (o filtro, o ordinamento) le colonne
   "ballano". Si usano sulle colonne di testo o badge a lunghezza variabile che non
   sono la colonna elastica: la misura e' fissa (width + min + max) e scelta sul valore
   piu' lungo del vocabolario della colonna; un testo che non ci sta va a capo e non
   allarga mai la colonna. */
.quadra-table th.quadra-col-w-sm,
.quadra-table td.quadra-col-w-sm { width: var(--quadra-col-w-sm); min-width: var(--quadra-col-w-sm); max-width: var(--quadra-col-w-sm); }
.quadra-table th.quadra-col-w-md,
.quadra-table td.quadra-col-w-md { width: var(--quadra-col-w-md); min-width: var(--quadra-col-w-md); max-width: var(--quadra-col-w-md); }
.quadra-table th.quadra-col-w-lg,
.quadra-table td.quadra-col-w-lg { width: var(--quadra-col-w-lg); min-width: var(--quadra-col-w-lg); max-width: var(--quadra-col-w-lg); }
.quadra-table tbody tr .row-actions { visibility: hidden; }
.quadra-table tbody tr:hover .row-actions { visibility: visible; }

/* Colonna elastica (§7.1) — .quadra-col-grow: la colonna che ASSORBE lo spazio in
   eccesso, al massimo una per tabella. Senza, lo spazio si distribuisce fra tutte e
   ogni cella galleggia in mezzo al vuoto: effetto che si nota appena si nascondono
   colonne, quando il residuo da ripartire diventa grande. Va messa su una colonna di
   TESTO a lunghezza variabile (un nome, una denominazione): e' l'unica che con piu'
   spazio guadagna davvero qualcosa. Metterla su codici, importi, date o comandi
   sposterebbe solo il vuoto altrove. */
.quadra-table th.quadra-col-grow,
.quadra-table td.quadra-col-grow { width: 100%; }

/* Record su due righe (§7.1) — .quadra-table-grouped.
   Serve quando una colonna porta un testo lungo (una descrizione, un riferimento
   discorsivo) che in colonna andrebbe comunque a capo: invece di pagare la seconda
   riga DENTRO una cella stretta, dove il testo si spezza e si legge peggio, la si
   paga una volta sola a piena larghezza, liberando la colonna e la sua larghezza
   per i dati che restano.

   Un record = un <tbody> con due <tr>: la riga dati e la riga di nota. E' l'unico
   modo corretto di tenerli insieme, perche' zebratura, hover e comandi di riga in
   Bootstrap ragionano per <tr>: con due <tr> sciolti il record si colorerebbe a
   meta' e l'hover ne illuminerebbe solo una parte. Per lo stesso motivo su queste
   tabelle NON si usano .table-striped / .table-hover: alternanza e hover sono qui
   per RECORD, cioe' per <tbody>, e passano dalle stesse variabili di Bootstrap. */
.quadra-table-grouped > tbody:nth-of-type(even) > tr > * { --bs-table-bg-type: var(--quadra-table-stripe); }
.quadra-table-grouped > tbody:hover > tr > * { --bs-table-bg-state: var(--quadra-table-hover); }
.quadra-table-grouped > tbody:hover .row-actions { visibility: visible; }
/* Record selezionato (§7.1, selezione riga per riga): tinta un grado sopra l'hover, che
   vince anche in hover, e filetto accent sul bordo sinistro delle due righe del record.
   Il filetto si AGGIUNGE all'ombra con cui Bootstrap dipinge il fondo della cella: da
   solo la sostituirebbe e la prima cella resterebbe bianca. */
.quadra-table-grouped > tbody.quadra-record-selected > tr > * { --bs-table-bg-state: var(--quadra-table-selected); }
.quadra-table-grouped > tbody.quadra-record-selected > tr > :first-child { box-shadow: inset 3px 0 0 var(--quadra-accent), inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); }
/* La riga dati non chiude il record: il filetto sta sotto la nota, cosi' le due
   righe si leggono come un blocco solo e la separazione cade fra un record e l'altro. */
.quadra-table-grouped > tbody > tr:first-child > * { border-bottom-width: 0; }
/* La nota e' subordinata al dato: attaccata sopra (padding-top 0), interlinea stretta
   e tinta attenuata. Le due righe insieme devono costare quanto costava la riga sola
   con il testo che andava a capo: la seconda riga si paga in leggibilita', non in
   record visibili. */
.quadra-table-grouped .quadra-record-note > td { padding-top: 0; padding-bottom: .25rem; line-height: 1.2; color: var(--quadra-muted); }
/* L'icona della nota segue il testo attenuato, ma NON quella dentro un badge, che deve
   restare della tinta del badge: altrimenti l'indicatore ha il glifo grigio e la parola
   colorata, e si legge come un errore di resa. */
.quadra-table-grouped .quadra-record-note > td > .bi { color: var(--quadra-muted-2); }

/* Colonna azioni (§7.1): non ospita dati ma i soli comandi di riga, quindi non
   partecipa alla distribuzione dello spazio in eccesso — `width: 1%` la tiene
   sempre alla misura del suo contenuto e lascia tutto il resto alle colonne-dato,
   che sono quelle da leggere. Ha pero' un **minimo garantito** calcolato sul
   numero massimo di comandi della tabella (--quadra-col-actions-count): senza, la
   larghezza dipenderebbe dai soli comandi visibili nella pagina corrente e la
   colonna "ballerebbe" a ogni cambio pagina, filtro o ordinamento. Quando la
   somma dei minimi di tutte le colonne supera il riquadro, la tabella non si
   comprime oltre e subentra lo scroll orizzontale di .quadra-table-scroll, con le
   intestazioni che scorrono insieme al corpo. Una tabella con un numero diverso
   di comandi lo dichiara con .quadra-actions-N sul **contenitore host** della
   tabella (lo stesso elemento che porta la modalita' di altezza), cosi' il
   parametro sopravvive agli swap HTMX che sostituiscono il frammento; sulla
   <table> stessa per le tabelle statiche senza frammento. */
.quadra-table th.quadra-col-actions,
.quadra-table td.quadra-col-actions {
  width: 1%; white-space: nowrap;
  min-width: calc(var(--quadra-col-actions-count) * var(--quadra-col-actions-slot) + .75rem);
}
.quadra-actions-1 { --quadra-col-actions-count: 1; }
/* Il default e' gia' in :root, ma la classe serve per tornarci: la variabile si eredita,
   e una tabella annidata in un host con N diverso altrimenti non potrebbe reimpostarlo. */
.quadra-actions-2 { --quadra-col-actions-count: 2; }
.quadra-actions-3 { --quadra-col-actions-count: 3; }
.quadra-actions-4 { --quadra-col-actions-count: 4; }
.quadra-actions-5 { --quadra-col-actions-count: 5; }

/* Colonna Status (§7.1) — .quadra-col-status: fino a quattro badge di stato in solo testo, due affiancati
   sulla riga dati e due sulla riga di nota del record, a scalare da sinistra. La colonna
   e' larga esattamente due badge di larghezza comune (piu' lo spazio fra i due e il
   padding della cella): non dipende dai badge della pagina, quindi non balla. */
.quadra-table th.quadra-col-status,
.quadra-table td.quadra-col-status {
  --quadra-badge-status-width: 5.6rem; /* il minimo per la voce piu' lunga, «Da verificare», in solo testo: badge uguali e piu' stretti possibile */
  width: 1%; white-space: nowrap;
  min-width: calc(2 * var(--quadra-badge-status-width) + .25rem + 1rem);
}
.quadra-status-badges { display: inline-flex; gap: .25rem; vertical-align: middle; }

/* Toolbar e footer del componente tabella (§7.1). Le misure stanno qui, non in
   attributi style del markup: toolbar e footer fanno parte del componente e
   devono essere identici fra frammento HTMX e mockup. */
.quadra-table-search { max-width: var(--quadra-table-search-width); }
.quadra-table-perpage { width: auto; }

/* Filtri rapidi (§7.1) — .quadra-quick-filters. E' un normale .btn-group di Bootstrap con
   un .btn per opzione e .active + aria-pressed sull'opzione scelta: qui si tematizzano solo
   le variabili native --bs-btn-* con i token della palette (riposo neutro, scelta = accent,
   come le voci attive della navigazione). Il contatore e' un .badge con .quadra-quick-count:
   grigio neutro a riposo, bianco trasparente sull'opzione scelta. */
.quadra-quick-filters > .btn {
  --bs-btn-color: var(--quadra-muted);
  --bs-btn-bg: var(--quadra-surface);
  --bs-btn-border-color: var(--quadra-border);
  --bs-btn-hover-color: var(--quadra-primary);
  --bs-btn-hover-bg: #F3F8F6;
  --bs-btn-hover-border-color: var(--quadra-border);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--quadra-accent);
  --bs-btn-active-border-color: var(--quadra-accent);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
  display: inline-flex; align-items: center; gap: .35rem;
}
.quadra-quick-filters .quadra-quick-count {
  background: var(--quadra-neutral-bg); color: var(--quadra-neutral-fg);
  font-weight: 600; font-variant-numeric: tabular-nums;
}
.quadra-quick-filters > .btn.active .quadra-quick-count { background: rgba(255, 255, 255, .25); color: #fff; }

/* Scroll verticale con intestazioni bloccate (sticky).
   Modalita' "auto" (default, tabelle annidate): la tabella cresce con le righe fino
   al tetto --quadra-table-max-height, poi scorre internamente. */
.quadra-table-scroll { max-height: var(--quadra-table-max-height); overflow: auto; }
.quadra-table-scroll .quadra-table thead th {
  position: sticky; top: 0; z-index: 2;
}

/* Modalita' "fill" (pagine-lista): il riquadro occupa lo spazio residuo fino al fondo
   finestra; toolbar e footer (paginazione) restano fissi, scorre solo il corpo righe.
   La classe sta sul contenitore host del target HTMX, cosi' sopravvive agli swap. */
.quadra-table-fill { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.quadra-table-fill > * { flex: 0 0 auto; }
.quadra-table-fill > .quadra-table-scroll { flex: 1 1 auto; min-height: 10rem; max-height: none; }

/* Modalita' "full" (griglie di un editor, poche righe sempre tutte visibili): nessun tetto
   di altezza, la pagina resta il contenitore di scroll verticale; resta lo scroll
   orizzontale quando le colonne non entrano. */
.quadra-table-scroll.quadra-table-full { max-height: none; }

/* -------------------------------------------- Campo immagine (§7.8) ---- */
/* Campo "Targa" reso come colonna a sinistra del fieldset Anagrafica, affiancata
   alle due righe di campi (denominazione/tipo soggetto e P.IVA/codice fiscale).
   L'etichetta "Targa" e' un'etichetta di campo (.form-label) sopra il riquadro;
   il riquadro sottostante e' un quadrato che si allinea con l'area delle righe.
   La colonna si stira in altezza; larghezza del riquadro imposta da quadra.js
   (sincronizza larghezza = altezza -> quadrato). */
.quadra-foto-col { flex: 0 0 auto; }
/* Riquadro cliccabile (e' un <label> che avvolge l'input file nascosto): un
   click in qualsiasi punto apre la selezione del file. Dimensione fissa: il
   riquadro NON si adatta alla foto, e' l'immagine a essere ridotta al suo
   interno (object-fit-contain). `width` e' un fallback prima del JS. */
.quadra-foto-thumb {
  width: 8rem; min-height: 0; flex: 1 1 auto; cursor: pointer;
}
/* L'immagine/segnaposto riempie il riquadro senza alterarne le dimensioni. */
.quadra-foto-thumb .quadra-foto-img { position: absolute; inset: 0; }
.quadra-foto-thumb img { display: block; }
/* Cestino accanto all'etichetta "Targa": rimuove/ripristina la foto o annulla
   la selezione non ancora salvata. Bottone "ghost" minimale, senza riquadro. */
.quadra-foto-trash {
  padding: 0; border: 0; background: transparent; line-height: 1;
  color: var(--quadra-muted); font-size: .8rem;
  display: inline-flex; align-items: center;
}
.quadra-foto-trash:hover { color: var(--quadra-danger-fg); }

/* ------------------------------------------------- Trasmissione file ---- */
/* Dropzone multifile (design system §7.6). Unico componente ammesso per far
   entrare file dal browser: drag & drop oppure picking multiplo, lista di
   preparazione, avanzamento ed esito per file. Nessun selettore di tipo ne'
   di contesto: il tipo lo determina il server, il contesto e' quello attivo. */
.quadra-dropzone { display: flex; flex-direction: column; gap: .75rem; }
/* .quadra-dropzone-input e' solo un aggancio per il JS (come .quadra-select per Tom
   Select): non ha stile proprio, l'input resta nascosto con .visually-hidden di
   Bootstrap per restare raggiungibile da tastiera e screen reader. */

.quadra-dropzone-area {
  border: 2px dashed var(--quadra-border);
  border-radius: var(--quadra-radius);
  background: var(--quadra-table-stripe);
  padding: 1.5rem 1rem; text-align: center; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.quadra-dropzone-area:hover { border-color: var(--quadra-accent); background: var(--quadra-table-hover); }
.quadra-dropzone-area:focus-visible {
  outline: 2px solid var(--quadra-accent); outline-offset: 2px; border-color: var(--quadra-accent);
}
.quadra-dropzone-area.is-dragover {
  border-color: var(--quadra-accent); background: var(--quadra-table-hover);
  border-style: solid;
}
.quadra-dropzone-area.is-disabled { opacity: .6; pointer-events: none; }

.quadra-dropzone-icon { font-size: var(--quadra-icon-xl); color: var(--quadra-accent); display: block; margin-bottom: .4rem; }
.quadra-dropzone-title { margin: 0; font-weight: 600; color: var(--quadra-text); }
.quadra-dropzone-link { color: var(--quadra-accent); text-decoration: underline; }
.quadra-dropzone-hint { margin: .15rem 0 0; font-size: .82rem; color: var(--quadra-muted); }
.quadra-dropzone-context {
  margin: .5rem 0 0; font-size: .82rem; color: var(--quadra-muted);
}
.quadra-dropzone-context strong { color: var(--quadra-primary); }

/* Lista dei file: in preparazione, in invio, con esito. */
.quadra-dropzone-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.quadra-dropzone-list:empty { display: none; }
.quadra-dropzone-item {
  display: flex; align-items: center; gap: .6rem;
  border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
  background: var(--quadra-surface); padding: .45rem .6rem;
}
.quadra-dropzone-item .bi { color: var(--quadra-muted); }
.quadra-dropzone-name { font-size: .88rem; color: var(--quadra-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.quadra-dropzone-size { font-size: .78rem; color: var(--quadra-muted-2); white-space: nowrap; }
.quadra-dropzone-outcome { margin-left: auto; display: inline-flex; align-items: center; gap: .4rem; }
.quadra-dropzone-reason { font-size: .78rem; color: var(--quadra-danger-fg); }
.quadra-dropzone-ref { font-size: .78rem; color: var(--quadra-muted); }

/* Avanzamento: visibile solo durante l'invio della voce. */
.quadra-dropzone-bar { flex: 1 1 6rem; height: .35rem; border-radius: 1rem; background: var(--quadra-neutral-bg); overflow: hidden; display: none; }
.quadra-dropzone-item.is-uploading .quadra-dropzone-bar { display: block; }
.quadra-dropzone-bar > span { display: block; height: 100%; width: 0; background: var(--quadra-accent); transition: width .2s linear; }
.quadra-dropzone-item.is-uploading .quadra-dropzone-remove { visibility: hidden; }
.quadra-dropzone-item.is-ok { border-color: var(--quadra-success-bg); }
.quadra-dropzone-item.is-error { border-color: var(--quadra-danger-bg); background: #fffafa; }

.quadra-dropzone-actions { display: flex; align-items: center; gap: .5rem; }
.quadra-dropzone-count { font-size: .82rem; color: var(--quadra-muted); margin-right: auto; }

/* Menu filtrabile (design system §7.7): tetto di altezza per i dropdown che
   possono elencare molte voci; il campo di ricerca resta fermo in cima (sticky)
   e scorre solo l'elenco. */
.quadra-menu-scroll { max-height: 18rem; overflow-y: auto; }
.quadra-menu-scroll > li:first-child { position: sticky; top: 0; z-index: 1; background: var(--quadra-surface); }

/* Voce di menu con codice identificativo (§7.7): il codice e' il **primo dato**,
   tra parentesi, in tinta attenuata e a larghezza fissa, cosi' le denominazioni
   restano incolonnate anche con codici di lunghezza diversa. */
.quadra-menu-code { color: var(--quadra-muted-2); font-variant-numeric: tabular-nums; }
/* Sulla voce ATTIVA la tinta attenuata non vale: il fondo e' pieno e un grigio
   chiaro sopra diventa illeggibile proprio sulla voce che l'utente sta cercando
   — quella corrente. Il codice eredita quindi il colore della voce, restando
   comunque un gradino sotto la denominazione. */
.dropdown-item.active .quadra-menu-code,
.dropdown-item:active .quadra-menu-code { color: inherit; opacity: .75; }

/* La voce attiva dei menu usa l'ACCENT del design system: senza, Bootstrap
   applica il proprio blu compilato (#1E7A5C), che non e' in palette e si nota
   subito accanto ai comandi Quadra. L'override passa dalla variabile nativa, cosi'
   valgono ancora hover, focus e contrasto del componente. */
.dropdown-menu { --bs-dropdown-link-active-bg: var(--quadra-accent); }

/* Icona informativa in cella (§7.1): l'icona che **sostituisce** il testo della
   colonna — non lo accompagna — e deve quindi reggere da sola. Sta a
   --quadra-icon-md come .quadra-command-labeled, che risolve lo stesso problema: il
   testo della cella (.78rem) e' misura da leggere in parole, non da leggere in
   un solo glifo. Resta a --quadra-icon-sm, invece, l'imbutino di colonna
   (.quadra-th-filter): e' un invito all'azione accanto all'etichetta, non un dato. */
.quadra-table .quadra-cell-icon { font-size: var(--quadra-icon-md); line-height: 1; vertical-align: -.1em; }

/* Icona-dato cliccabile in cella (§7.1): l'icona resta il DATO — glifo, tinta di
   palette e tooltip invariati — ma porta alla scheda dell'oggetto che descrive
   (es. il lucchetto EMI -> scheda dell'avviso emesso). E' un LINK reale
   (<a href>), perche' e' navigazione e non un'azione di riga: niente .btn, niente
   riserva nella colonna azioni. L'affordance e' un riquadro bianco con filetto che
   compare all'hover e un anello accent al focus da tastiera; si stacca anche dal
   fondo della riga in hover (--quadra-table-hover), che e' gia' una tinta chiara. */
.quadra-table .quadra-cell-link {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .25rem; border-radius: .35rem; line-height: 1;
  text-decoration: none; cursor: pointer;
  transition: background-color .15s ease, box-shadow .15s ease;
}
.quadra-table .quadra-cell-link:hover { background: var(--quadra-surface); box-shadow: 0 0 0 1px var(--quadra-border); }
.quadra-table .quadra-cell-link:focus-visible { outline: 2px solid var(--quadra-accent); outline-offset: 1px; }

/* Codice cliccabile in cella (§7.1): il codice apre l'oggetto che identifica. Un
   DOCUMENTO (es. il codice avviso -> PDF su Google Drive) in una nuova scheda, con
   l'anteprima; una PAGINA di Quadra (es. il codice richiesta -> dettaglio) nella stessa
   scheda. E' un link di testo: tinta accent come ogni link, sottolineatura all'hover,
   anello accent al focus; il codice resta monospace a cifre fisse. Senza destinazione
   il codice resta testo. */
.quadra-table a.quadra-code-link { text-decoration: none; border-radius: .2rem; }
.quadra-table a.quadra-code-link code { color: var(--quadra-accent); }
.quadra-table a.quadra-code-link:hover code { text-decoration: underline; text-underline-offset: 2px; }
.quadra-table a.quadra-code-link:focus-visible { outline: 2px solid var(--quadra-accent); outline-offset: 2px; }

/* Anteprima del documento (§7.1): popover con la miniatura della prima pagina, aperto
   dalla sosta sul codice cliccabile. Cornice a misura fissa in formato A4 (niente salti
   mentre l'immagine arriva), fondo neutro come segnaposto, didascalia attenuata. */
.quadra-preview-popover { --bs-popover-max-width: 32rem; --bs-popover-body-padding-x: .5rem; --bs-popover-body-padding-y: .5rem; }
.quadra-preview { margin: 0; }
.quadra-preview-frame {
  width: 30rem; max-width: calc(100vw - 2rem); max-height: calc(100vh - 5rem);
  aspect-ratio: 210 / 297; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--quadra-table-stripe); border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
}
.quadra-preview-img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Variante foto (es. targa del soggetto CRM): cornice 4:3 orizzontale, piu' stretta. */
.quadra-preview-frame-foto { width: 24rem; aspect-ratio: 4 / 3; }
.quadra-preview-empty { font-size: .78rem; color: var(--quadra-muted-2); }
.quadra-preview-caption { margin-top: .4rem; font-size: .78rem; color: var(--quadra-muted-2); text-align: center; }

/* Griglia campi (.quadra-grid) e sezioni del form (.quadra-form): la spaziatura
   verticale tra le righe deriva dal solo gutter g-3, quindi si azzera il margine
   inferiore che crispy-forms impone (.mb-3) su ogni campo per non raddoppiare lo
   spazio; azzerandolo si perde pero' la separazione fra un fieldset e il
   successivo, ripristinata con un margine superiore su ogni sezione tranne la
   prima. Componente nato nel codice e riportato qui: la styleguide e' il
   riferimento vincolante e deve conoscere tutto cio' che l'app usa. */
.quadra-grid > [class*="col-"] > .mb-3 { margin-bottom: 0 !important; }
.quadra-form fieldset + fieldset { margin-top: 1.5rem; }

/* ----------------------------------------------------------- Utilities --- */
/* Scala delle icone: usare queste utility (mai fs-* di Bootstrap, che e' una
   scala tipografica) quando l'icona non deve ereditare il testo del contesto. */
.quadra-icon-sm { font-size: var(--quadra-icon-sm) !important; line-height: 1; }
.quadra-icon-md { font-size: var(--quadra-icon-md) !important; line-height: 1; }
.quadra-icon-lg { font-size: var(--quadra-icon-lg) !important; line-height: 1; }
.quadra-icon-xl { font-size: var(--quadra-icon-xl) !important; line-height: 1; }

.text-quadra-primary { color: var(--quadra-primary) !important; }
.text-quadra-accent { color: var(--quadra-accent) !important; }
/* Colori semantici della palette (non i verdi/rossi nativi di Bootstrap, che
   sono fuori palette): per icone-dato e testi di stato. */
.text-quadra-success { color: var(--quadra-success-fg) !important; }
.text-quadra-warning { color: var(--quadra-warning-fg) !important; }
.text-quadra-danger { color: var(--quadra-danger-fg) !important; }
.text-quadra-muted { color: var(--quadra-muted-2) !important; }

/* Riga che apre il dettaglio (§7.1): tr[data-quadra-open], clic sullo spazio libero. */
.quadra-table tr[data-quadra-open] { cursor: pointer; }

/* Selezione di righe (§7.1): il gesto e' il CLIC SULLA RIGA (niente spunte). Il record
   selezionabile ha il cursore a mano; il pulsante nascosto .quadra-row-toggle e' l'accesso da
   tastiera e, al focus, evidenzia il record come in hover. Dalla prima selezione la toolbar
   lascia il posto alla barra delle azioni (.quadra-selection-bar), alta quanto la toolbar e
   tinta come il record selezionato. */
.quadra-table-grouped > tbody.quadra-record-selectable { cursor: pointer; }
.quadra-table-grouped > tbody:has(.quadra-row-toggle:focus-visible) > tr > * { --bs-table-bg-state: var(--quadra-table-hover); }
.quadra-table-grouped > tbody:has(.quadra-row-toggle:focus-visible) > tr > :first-child { box-shadow: inset 3px 0 0 var(--quadra-accent-hover), inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); }
.quadra-selection-bar {
  min-height: calc(1.5em + .5rem + 2px); padding: .25rem .5rem;
  background: var(--quadra-table-selected); border-radius: var(--quadra-radius-sm);
}
.quadra-selection-count { font-size: .875rem; color: var(--quadra-primary); }
.quadra-selection-count > .bi { color: var(--quadra-accent); margin-right: .15rem; }

/* Tracciato a larghezza fissa (design system §5): record grezzi di un flusso, come il
   ricevuto dalla banca. Nessun a capo: la riga scorre in orizzontale. */
.quadra-tracciato {
  font-family: var(--quadra-font-mono); font-size: .8rem; line-height: 1.5;
  white-space: pre; overflow-x: auto; margin: 0; padding: .5rem .75rem;
  color: var(--quadra-text); background: var(--bs-tertiary-bg);
  border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
}
/* Il `code` globale e' un chip (fondo e padding): nel tracciato il padding sposterebbe la sola prima riga. */
.quadra-tracciato code {
  font-family: inherit; font-size: inherit; color: inherit;
  background: none; padding: 0; border-radius: 0;
}

/* ------------------------------------------------ Misure e ritocchi (§7.14) --- */
/* Al posto degli stili in linea: una scala breve di misure e pochi ritocchi con nome. Una misura
   nuova si aggiunge qui e nella styleguide, mai come style="" nella pagina. */
.quadra-w-sm { width: 12rem; }
.quadra-w-md { width: 24rem; }
.quadra-w-lg { width: 34rem; }
.quadra-minw-xs { min-width: 3.5rem; }
.quadra-minw-sm { min-width: 8rem; }
.quadra-minw-md { min-width: 11rem; }
.quadra-minw-lg { min-width: 16rem; }
.quadra-maxw-sm { max-width: 20rem; }
.quadra-maxw-md { max-width: 26rem; }
.quadra-maxw-lg { max-width: 60rem; }
/* Larghezza massima dei campi nelle barre dei filtri e nei moduli compatti (select, ricerca, importi). */
.quadra-campo-xs { max-width: 5rem; }
.quadra-campo-sm { max-width: 7rem; }
.quadra-campo-md { max-width: 9.5rem; }
.quadra-campo-lg { max-width: 12rem; }
.quadra-campo-xl { max-width: 18rem; }
/* Contenitori flex che devono potersi restringere (liste a tutta altezza, testo troncato). */
.quadra-min-h-0 { min-height: 0; }
.quadra-min-w-0 { min-width: 0; }
.quadra-basis-0 { flex-basis: 0; }
/* Altezza minima delle aree di testo (corpo dell'email, testo del modello, schermo del portale). */
.quadra-min-h-sm { min-height: 6rem; }
.quadra-min-h-md { min-height: 8rem; }
.quadra-min-h-lg { min-height: 14rem; }
.quadra-min-h-xl { min-height: 15rem; }
/* Barre di avanzamento sottili (indicatori del cruscotto e dei report). */
.progress.quadra-progress-xs { height: .25rem; }
.progress.quadra-progress-sm { height: .5rem; }
/* Testo minimo (ruolo sotto il nome dell'utente) e fondo della pagina dentro un riquadro (passi di una procedura). */
.quadra-text-xs { font-size: .7rem; }
.quadra-bg-page { background: var(--quadra-bg); }
/* Riquadro che scorre oltre un'altezza massima (elenchi lunghi in una finestra o in una scheda). */
.quadra-scroll-box { max-height: 50vh; overflow-y: auto; }
.quadra-scroll-box-sm { max-height: 14rem; overflow-y: auto; }
.quadra-scroll-box-md { max-height: 21rem; overflow-y: auto; }
/* Testo che conserva gli a capo e gli spazi (note, trascrizioni, testi letti dall'IA). */
.quadra-pre-wrap { white-space: pre-wrap; }
/* Colonna di spunta (§9): misura fissa, come le altre colonne di tipo. */
.quadra-table th.quadra-col-check,
.quadra-table td.quadra-col-check { width: 2.5rem; min-width: 2.5rem; max-width: 2.5rem; }
/* Badge di stato alla misura del testo (codici brevi delle aree) e badge tratteggiato (area senza responsabile). */
.quadra-badge-auto { --quadra-badge-status-width: auto; }
.badge-status.quadra-badge-dashed { border-style: dashed; }
/* Chiusura minima dentro un badge (togli la voce). */
.btn-close.quadra-btn-close-xs { font-size: .55rem; }
/* Messaggi sopra le finestre aperte (popup della telefonia). */
.toast-container.quadra-toast-top { z-index: 1090; }
/* Pallino di stato accanto a un'icona o a un testo (collegamento, modifiche non salvate). */
.bi.quadra-dot { font-size: .5rem; }
/* Testo giustificato come nel documento stampato (editor dei modelli). */
.quadra-justify { text-align: justify; }

/* --------------------------------------------- Componenti adottati (§7.15) --- */
/* Attesa senza percentuale: barra piena a strisce in movimento (lettura del contratto con l'IA). */
.quadra-progress-attesa .progress-bar {
  width: 100%;
  background-image: linear-gradient(45deg, rgba(255,255,255,.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.15) 50%, rgba(255,255,255,.15) 75%, transparent 75%, transparent);
  background-size: var(--bs-progress-height) var(--bs-progress-height);
  animation: progress-bar-stripes 1s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .quadra-progress-attesa .progress-bar { animation: none; } }
/* Riga di sezione dentro una tabella (raggruppa le righe che seguono). */
.quadra-table tr.quadra-row-section > td { --bs-table-bg-type: var(--quadra-table-head-bg); background: var(--quadra-table-head-bg); font-weight: 600; }
/* Bordo di evidenza con i colori della palette (non quelli nativi di Bootstrap): da completare / elemento corrente. */
.quadra-border-warning { border-color: var(--quadra-warning-fg) !important; }
.quadra-border-accent { border-color: var(--quadra-accent) !important; }
/* Intensita' graduata di una cella (tabelle a matrice: quante chiamate in quell'ora). Neutra: dice quanto, non come va. */
.quadra-table td.quadra-heat-1 { background: rgba(85,102,111,.10); }
.quadra-table td.quadra-heat-2 { background: rgba(85,102,111,.22); }
.quadra-table td.quadra-heat-3 { background: rgba(85,102,111,.38); }
/* Ombra dei riquadri sovrapposti alla pagina (suggerimenti, menu aperti a mano). */
.quadra-shadow { box-shadow: var(--quadra-shadow) !important; }

/* ------------------------------------------------------- Editor email --- */
/* Editor delle email (design system §7.9, styleguide §13, mockup 07-editor-email.html):
   un unico componente per modelli (eredi di TabellaEmailBody) ed email estemporanee.
   contenteditable in-house senza dipendenze; segnaposto a catalogo chiuso resi come
   pillole non spezzabili; modalita' Scrivi | HTML | Anteprima. */
/* Oggetto: campo a riga singola che ospita le pillole (niente a-capo, niente HTML incollato). */
.quadra-mail-subject { white-space: nowrap; overflow-x: auto; overflow-y: hidden; min-height: calc(1.5em + .75rem + 2px); }
.quadra-mail-subject[contenteditable="false"] { background: #F6F8F7; }
.quadra-mail-subject:empty::before,
.quadra-mail-body:empty::before { content: attr(data-ph); color: var(--quadra-muted-2); }

/* Cornice unica: toolbar + area (Scrivi | HTML | Anteprima). */
.quadra-mail-frame { border: 1px solid #D6DFDC; border-radius: var(--quadra-radius-sm); background: var(--quadra-surface); overflow: hidden; }
.quadra-mail-frame:focus-within { border-color: var(--quadra-accent); box-shadow: 0 0 0 .2rem rgba(30,122,92,.15); }
.quadra-mail-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .15rem; padding: .3rem .4rem;
  border-bottom: 1px solid var(--quadra-border); background: var(--quadra-table-head-bg); }
.quadra-mail-toolbar .btn:disabled { opacity: .35; }
.quadra-mail-inline { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; padding: .5rem .6rem;
  border-bottom: 1px solid var(--quadra-border); background: var(--quadra-table-stripe); }
.quadra-mail-body { min-height: 20rem; max-height: 34rem; overflow: auto; padding: .85rem 1rem; font-size: .9rem; outline: 0; }
.quadra-mail-body p { margin: 0 0 .6rem; }
.quadra-mail-body img { max-width: 100%; }
.quadra-mail-source { display: block; width: 100%; min-height: 20rem; max-height: 34rem; border: 0; outline: 0; resize: vertical;
  padding: .85rem 1rem; font-family: var(--quadra-font-mono); font-size: .78rem; color: var(--quadra-text); background: #FBFCFC; }

/* Segnaposto di campo: pillola inline non spezzabile. */
.quadra-mail-token { display: inline-flex; align-items: center; gap: .25rem; padding: 0 .5rem; margin: 0 .1rem;
  border-radius: 2rem; border: 1px solid rgba(28,95,176,.25); background: var(--quadra-info-bg); color: var(--quadra-info-fg);
  font-size: .8em; font-weight: 600; line-height: 1.65; white-space: nowrap; user-select: all; vertical-align: baseline; }
.quadra-mail-token .bi { font-size: .9em; opacity: .75; }
/* Blocco dinamico (tabella avvisi, paragrafi condizionali): riga intera tratteggiata. */
.quadra-mail-block { display: flex; align-items: center; gap: .5rem; margin: .45rem 0; padding: .35rem .65rem;
  border: 1px dashed rgba(28,95,176,.45); border-radius: var(--quadra-radius-sm); background: #F2F7F5;
  color: var(--quadra-info-fg); font-size: .8rem; font-weight: 600; user-select: all; }
.quadra-mail-block small { margin-left: auto; font-weight: 400; color: var(--quadra-muted-2); }
/* Stati della pillola: non riconosciuta (errore) / non disponibile nel tipo del modello (avviso). */
.quadra-mail-token.is-unknown, .quadra-mail-block.is-unknown { background: var(--quadra-danger-bg); color: var(--quadra-danger-fg); border-color: rgba(176,42,42,.35); }
.quadra-mail-token.is-off, .quadra-mail-block.is-off { background: var(--quadra-warning-bg); color: var(--quadra-warning-fg); border-color: rgba(138,84,16,.35); }

/* Pannello dei segnaposto (a destra dell'editor). */
.quadra-mail-palette { border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm); padding: .6rem; max-height: 40rem; overflow: auto; background: var(--quadra-surface); }
.quadra-mail-group-title { display: flex; align-items: center; gap: .35rem; font-size: .7rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--quadra-muted-2); margin: .75rem 0 .35rem; }
.quadra-mail-group-title:first-child { margin-top: .25rem; }
.quadra-mail-group-title .badge-status { min-width: 0; margin-left: auto; text-transform: none; letter-spacing: 0; }
.quadra-mail-chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.quadra-mail-chip { border: 1px solid var(--quadra-border); background: var(--quadra-surface); color: var(--quadra-primary);
  border-radius: 2rem; padding: .1rem .6rem; font-size: .75rem; line-height: 1.5; cursor: pointer; }
.quadra-mail-chip:hover:not(:disabled) { background: var(--quadra-table-hover); border-color: var(--quadra-accent); }
.quadra-mail-chip.is-block { border-style: dashed; border-radius: var(--quadra-radius-sm); }
.quadra-mail-chip:disabled { opacity: .45; cursor: not-allowed; }

/* Anteprima risolta. */
.quadra-mail-envelope { margin: 0; padding: .6rem 1rem; border-bottom: 1px solid var(--quadra-border); font-size: .82rem; }
.quadra-mail-envelope dt { color: var(--quadra-muted-2); font-weight: 600; }
.quadra-mail-envelope dd { margin-bottom: .15rem; }
.quadra-mail-rendered { padding: 1rem; font-size: .9rem; max-height: 34rem; overflow: auto; }
.quadra-mail-rendered p { margin: 0 0 .6rem; }
.quadra-mail-rendered img { max-width: 100%; }
.quadra-mail-missing { background: var(--quadra-danger-bg); color: var(--quadra-danger-fg); border-radius: .3rem; padding: 0 .3rem; font-family: var(--quadra-font-mono); font-size: .8em; }


/* --------------------------------------------------- Procedura guidata --- */
/* Procedura guidata a passi (design system §7.10, styleguide §14). La barra dei passi
   sta dove starebbe una tab-bar e ne riusa il comportamento sticky (.quadra-sticky-tabs);
   il passo corrente e' una .card.quadra-card senza padding proprio: il contenuto sta in un
   .tab-body e i comandi di navigazione in un piede sticky in basso, fratello del corpo,
   cosi' Avanti/Indietro restano a portata anche sui passi lunghi. */
.quadra-steps {
  display: flex; align-items: center; gap: .35rem; list-style: none; margin: 0;
  padding: 1rem 1.25rem; border-bottom: 1px solid var(--quadra-border);
}
.quadra-step { display: flex; align-items: center; flex: 1 1 0; min-width: 0; gap: .35rem; }
.quadra-step:last-child { flex: 0 0 auto; }
/* Linea di raccordo verso il passo successivo: verde quando il passo e' completato. */
.quadra-step:not(:last-child)::after { content: ""; flex: 1 1 auto; min-width: 1rem; height: 2px; background: var(--quadra-border); }
.quadra-step.is-done:not(:last-child)::after { background: var(--quadra-success-fg); opacity: .45; }
.quadra-step-link {
  display: inline-flex; align-items: center; gap: .5rem; min-width: 0;
  padding: .3rem .5rem; border: 0; border-radius: var(--quadra-radius-sm); background: transparent;
  color: var(--quadra-muted); font-size: .85rem; font-weight: 500; text-align: left; white-space: nowrap;
}
.quadra-step-link:not(:disabled):hover { color: var(--quadra-primary); background: var(--quadra-table-hover); }
.quadra-step-link:disabled { cursor: default; opacity: .7; }
.quadra-step-label { overflow: hidden; text-overflow: ellipsis; }
.quadra-step-num {
  flex: 0 0 auto; width: 1.75rem; height: 1.75rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid #D6DFDC; background: var(--quadra-surface); color: var(--quadra-muted);
  font-size: .8rem; font-weight: 600;
}
.quadra-step.is-current .quadra-step-link { color: var(--quadra-accent); font-weight: 600; }
.quadra-step.is-current .quadra-step-num { border-color: var(--quadra-accent); background: var(--quadra-accent); color: #fff; }
.quadra-step.is-done .quadra-step-link { color: var(--quadra-text); }
.quadra-step.is-done .quadra-step-num { border-color: var(--quadra-success-fg); background: var(--quadra-success-bg); color: var(--quadra-success-fg); }
/* Avviso di un passo gia' visitato (non blocca): icona ambra accanto all'etichetta. */
.quadra-step-warn { color: var(--quadra-warning-fg); font-size: var(--quadra-icon-sm); }
/* Su schermi stretti restano i soli numeri: l'etichetta del passo corrente e' nel titolo del passo. */
@media (max-width: 991.98px) { .quadra-step-label { display: none; } }

/* Titolo del passo dentro la card: numero e nome del passo, come una legend di primo livello. */
.quadra-step-title { font-size: 1rem; font-weight: 600; color: var(--quadra-primary); margin-bottom: 1rem; }
.quadra-step-title .text-muted { font-weight: 500; font-size: .85rem; }

/* La card del passo non ritaglia il contenuto (.quadra-card ha overflow hidden): altrimenti
   il piede sticky si aggancerebbe alla card invece che al contenitore di scroll. */
.card.quadra-steps-card { overflow: visible; }

/* Piede dei comandi del passo: Annulla a sinistra, Indietro / Avanti (o il comando finale) a destra. */
.quadra-steps-footer {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: .5rem;
  padding: .75rem 1.5rem;
  background: var(--quadra-surface); border-top: 1px solid var(--quadra-border);
  border-radius: 0 0 var(--quadra-radius) var(--quadra-radius);
}

/* I toast (in basso a destra) non devono coprire Avanti: con una procedura guidata in
   pagina il contenitore si alza sopra il piede. */
body:has(.quadra-steps-footer) .toast-container { padding-bottom: 4.5rem !important; }

/* Elenco di scelta multipla del passo (profili, Studi…): ogni voce e' un <label> con
   l'interruttore, il titolo, una riga di dettaglio e, se non selezionabile, il motivo. */
.quadra-pick-list { display: flex; flex-direction: column; gap: .4rem; max-height: 26rem; overflow-y: auto; padding-right: .25rem; }
.quadra-pick {
  display: flex; align-items: flex-start; gap: .75rem; margin: 0;
  padding: .55rem .75rem; border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
  background: var(--quadra-surface); cursor: pointer;
}
.quadra-pick:hover { background: var(--quadra-table-hover); }
.quadra-pick.is-selected { border-color: var(--quadra-accent); background: var(--quadra-table-selected); }
.quadra-pick.is-disabled { cursor: not-allowed; background: var(--quadra-table-stripe); }
.quadra-pick .form-check { margin: .1rem 0 0; min-height: 0; }
.quadra-pick-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.quadra-pick-title { font-size: .88rem; font-weight: 600; color: var(--quadra-primary); }
.quadra-pick.is-disabled .quadra-pick-title { color: var(--quadra-muted); }
.quadra-pick-sub { font-size: .78rem; color: var(--quadra-muted-2); }
.quadra-pick-reason { font-size: .78rem; color: var(--quadra-warning-fg); }
.quadra-pick-side { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem; }

/* ------------------------------------------------ Indicatori KPI (§7.11) ---- */
/* Griglia di indicatori sintetici in cima a un report (v. 26.10.03.E, primo uso: Report del CRM).
   Ogni indicatore e' un riquadro con etichetta (icona + testo), valore grande e una riga di dettaglio
   facoltativa (formula o confronto). Nessun grafico: i grafici attendono il componente UI-06. */
.quadra-kpi-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: .75rem; }
.quadra-kpi {
  display: flex; flex-direction: column; gap: .15rem; min-width: 0;
  padding: .75rem 1rem; background: var(--quadra-surface);
  border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
}
.quadra-kpi-label {
  display: flex; align-items: center; gap: .4rem;
  font-size: .72rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--quadra-muted);
}
.quadra-kpi-label .bi { color: var(--quadra-accent); }
.quadra-kpi-value {
  font-size: 1.5rem; font-weight: 600; line-height: 1.2; color: var(--quadra-primary);
  font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.quadra-kpi-sub { font-size: .75rem; color: var(--quadra-muted-2); }
/* Riga di totale di una tabella di riepilogo (.quadra-table statica): in grassetto, banda dell'intestazione. */
.quadra-table tr.quadra-row-total > * {
  font-weight: 600; --bs-table-bg-type: var(--quadra-table-head-bg); background-color: var(--quadra-table-head-bg);
  border-top: 2px solid var(--quadra-border);
}

/* ------------------------------------------------- Conversazione (§7.12) ---- */
/* Conversazione di un ticket (v. 26.10.04.B, styleguide §16, primo uso: Assistenza). Elenco
   cronologico (dal piu' vecchio al piu' recente) di messaggi ed eventi, con il composer in fondo.
   Tre tipi di messaggio: del cliente (fondo neutro), risposta dell'operatore (filo accent a sinistra),
   NOTA INTERNA (fondo ambra tenue, bordo tratteggiato, lucchetto: non arriva mai al cliente).
   Gli eventi (cambi di stato, assegnazioni) sono righe sottili centrate fra i messaggi. */
.quadra-thread { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .75rem; }
.quadra-msg {
  background: var(--quadra-surface); border: 1px solid var(--quadra-border);
  border-radius: var(--quadra-radius-sm); padding: .7rem .9rem; min-width: 0;
}
.quadra-msg-in { background: var(--quadra-table-stripe); }
.quadra-msg-out { border-left: 3px solid var(--quadra-accent); }
.quadra-msg-note {
  background: var(--quadra-warning-bg); border: 1px dashed rgba(138,84,16,.45);
  border-left: 3px solid var(--quadra-warning-fg);
}
.quadra-msg-head { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem; margin-bottom: .45rem; }
.quadra-msg-avatar {
  flex: 0 0 auto; width: 1.9rem; height: 1.9rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .72rem; font-weight: 700; color: var(--quadra-primary); background: var(--quadra-neutral-bg);
}
.quadra-msg-out .quadra-msg-avatar { color: #fff; background: var(--quadra-primary); }
.quadra-msg-note .quadra-msg-avatar { color: var(--quadra-warning-fg); background: #fff; }
.quadra-msg-author { font-size: .86rem; font-weight: 600; color: var(--quadra-primary); }
.quadra-msg-meta { font-size: .76rem; color: var(--quadra-muted-2); }
.quadra-msg-time { margin-left: auto; font-size: .76rem; color: var(--quadra-muted-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.quadra-msg-notelabel { display: inline-flex; align-items: center; gap: .3rem; font-size: .74rem; font-weight: 600; color: var(--quadra-warning-fg); }
.quadra-msg-body { font-size: .88rem; color: var(--quadra-text); overflow-wrap: anywhere; }
.quadra-msg-body p { margin: 0 0 .5rem; }
.quadra-msg-body p:last-child { margin-bottom: 0; }
/* Testo citato (storico della risposta e-mail): chiuso per default, <details> nativo. */
.quadra-msg-quote { margin-top: .5rem; font-size: .8rem; }
.quadra-msg-quote > summary { cursor: pointer; color: var(--quadra-muted); list-style: none; display: inline-flex; align-items: center; gap: .3rem; }
.quadra-msg-quote > summary::-webkit-details-marker { display: none; }
.quadra-msg-quote > div { margin-top: .35rem; padding-left: .7rem; border-left: 2px solid var(--quadra-border); color: var(--quadra-muted); }
/* Allegati del messaggio: chip con icona, nome e dimensione; stato della verifica come badge. */
.quadra-msg-files { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; }
.quadra-msg-file {
  display: inline-flex; align-items: center; gap: .4rem; max-width: 100%;
  padding: .2rem .55rem; font-size: .78rem; border: 1px solid var(--quadra-border);
  border-radius: var(--quadra-radius-sm); background: var(--quadra-surface); color: var(--quadra-text); text-decoration: none;
}
.quadra-msg-file:hover { border-color: var(--quadra-accent); color: var(--quadra-accent-hover); }
.quadra-msg-file small { color: var(--quadra-muted-2); }
.quadra-msg-file.is-blocked { color: var(--quadra-muted); pointer-events: none; }
/* Evento di sistema fra i messaggi. */
.quadra-thread-event {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  font-size: .76rem; color: var(--quadra-muted-2); text-align: center;
}
.quadra-thread-event::before, .quadra-thread-event::after { content: ""; flex: 1 1 1.5rem; max-width: 6rem; border-top: 1px solid var(--quadra-border); }
/* Composer in fondo alla conversazione; in modalita' nota prende la tinta della nota interna. */
.quadra-composer { border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm); background: var(--quadra-surface); padding: .75rem .9rem; }
.quadra-composer.is-note { background: var(--quadra-warning-bg); border: 1px dashed rgba(138,84,16,.45); }
.quadra-composer-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .6rem; }
/* Minuti dedicati nel piede del composer (cronometro, v. 26.10.04.L): campo numerico stretto. */
.quadra-composer-foot .input-group > .form-control { flex: 0 0 auto; width: 4.5rem; }

/* -------------------------------------------- eMail Navigator (§7.13) ---- */
/* Navigator delle caselle in ingresso dell'Assistenza (v. 26.10.04.O, styleguide §17, mockup
   10-email-navigator.html). A sinistra le CASELLE (riquadri selezionabili) e, sotto la casella
   scelta, l'ALBERO DELLE CARTELLE letto dal server, con il ruolo della cartella (lettura,
   convertiti, scartati, cartella di una regola) e il conteggio; al centro l'elenco dei
   messaggi (.quadra-table, riga corrente evidenziata); sotto, il dettaglio del messaggio. */
.quadra-mailbox-list { display: flex; flex-direction: column; gap: .5rem; }
.quadra-mailbox {
  display: flex; flex-direction: column; gap: .15rem; width: 100%; text-align: left;
  padding: .6rem .75rem; border: 1px solid var(--quadra-border); border-radius: var(--quadra-radius-sm);
  background: var(--quadra-surface); color: var(--quadra-text);
}
.quadra-mailbox:hover { border-color: var(--quadra-accent); }
.quadra-mailbox.active { border-color: var(--quadra-accent); background: var(--quadra-table-selected); }
.quadra-mailbox-name { display: flex; align-items: center; gap: .4rem; font-size: .88rem; font-weight: 600; color: var(--quadra-primary); }
.quadra-mailbox-sub { font-size: .76rem; color: var(--quadra-muted-2); overflow-wrap: anywhere; }
.quadra-folder-tree { list-style: none; margin: 0; padding: 0; }
.quadra-folder-tree .quadra-folder-tree { padding-left: 1.1rem; }
.quadra-folder {
  display: flex; align-items: center; gap: .45rem; width: 100%; text-align: left;
  padding: .3rem .5rem; border: 0; border-radius: .4rem; background: transparent;
  font-size: .84rem; color: var(--quadra-text);
}
.quadra-folder:hover { background: var(--quadra-table-hover); }
.quadra-folder.active { background: var(--quadra-table-selected); color: var(--quadra-primary); font-weight: 600; }
.quadra-folder > .bi { color: var(--quadra-muted-2); }
.quadra-folder.active > .bi { color: var(--quadra-accent); }
.quadra-folder-role { font-size: .7rem; color: var(--quadra-muted-2); font-weight: 400; }
.quadra-folder-count {
  margin-left: auto; min-width: 1.5rem; padding: .05rem .4rem; border-radius: 1rem; text-align: center;
  font-size: .72rem; font-weight: 600; font-variant-numeric: tabular-nums;
  background: var(--quadra-neutral-bg); color: var(--quadra-neutral-fg);
}
.quadra-folder-count.warn { background: var(--quadra-warning-bg); color: var(--quadra-warning-fg); }
/* Riga corrente di un elenco master-detail (il record mostrato nel dettaglio sotto). */
.quadra-table tr.quadra-row-current > * { --bs-table-bg-state: var(--quadra-table-selected); }
.quadra-table tr.quadra-row-current > :first-child { box-shadow: inset 3px 0 0 var(--quadra-accent), inset 0 0 0 9999px var(--bs-table-bg-state); }
.quadra-folder { min-width: 0; }
.quadra-folder-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.quadra-folder-role, .quadra-folder-count { flex-shrink: 0; }
