/* Foglio del kit: fondamenta di Parte 6, componenti di Parte 8, estensioni di §1B.5,
   responsivita' di Parte 10, stampa. Identico per tutte le piattaforme del pacchetto:
   i soli valori che cambiano sono i token, che ogni piattaforma dichiara in tokens.css.
   Nessun esadecimale che non sia un bianco o un nero: ogni colore viene da un token.

   Vive nella radice del repository, che NON sta sotto la radice web di nessuna
   piattaforma. Non si collega direttamente: ogni piattaforma ha un ponte di poche
   righe nella propria radice web (kit.css.php) che lo serve come text/css. Cosi' e'
   un foglio di stile vero &mdash; cache separata, nessun 'unsafe-inline' nella CSP &mdash; e il
   contenuto sta in un posto solo. Vedi DESIGN-LOG DL-044. */

/* ---------- Parte 6.1 - tipografia ---------- */
html, body { height: 100%; font-family: var(--rg-font-body); line-height: normal; }
body { background: var(--rg-app-bg); color: var(--rg-text); }
/* Parte 10: un'immagine non esce dal proprio contenitore. Bootstrap non lo garantisce
   (ha .img-fluid, che va messo a mano) e senza questa riga una immagine alla sua
   larghezza naturale allarga la pagina: misurato a 360 px sui riquadri dei marchi di
   prodotti.php, scrollWidth 609 contro 360. `height: auto` per non deformarla quando
   solo la larghezza viene limitata. */
img { max-width: 100%; height: auto; }
/* Le icone Flaticon (`fi`) e Font Awesome disegnano il glifo nella parte ALTA della
   scatola em, e la scatola prende il line-height del testo intorno - 24px per un
   carattere da 16. Risultato: la scatola e' centrata ma il segno si vede alto.
   Misurato su un pulsante: scatola dell'icona centrata a 155, testo centrato a 155, e
   il cestino comunque visibilmente sopra. Con line-height 1 la scatola coincide con
   l'em e il glifo si centra con la riga.
   `inline-flex` perche' su un elemento vuoto e' l'unico modo di farlo collassare
   sull'altezza del proprio contenuto senza dipendere dalla baseline. */
.fi, .fa-solid, .fa-regular, .fa-brands { line-height: 1; display: inline-flex;
  align-items: center; justify-content: center; }
.wordmark   { font-family: var(--brand-font-display); }
.subtitle   { font-size: 13px; color: var(--rg-caption); }
.bg-card .subtitle, .table-responsive .subtitle { color: var(--rg-label); }
.text-label { color: var(--rg-label); font-weight: 500; }
.text-strong{ color: var(--rg-text-strong); }
.fs-7       { font-size: 14px; }
.font-17    { font-size: 17px; }
.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6 { font-weight: 600 !important; }

/* L'attributo `hidden` deve nascondere DAVVERO. Il foglio del browser lo rende con
   `display: none`, che e' una regola di elemento: qualunque classe che dichiari un
   display - .btn (inline-flex), .d-flex, .col-* - la batte per specificita', e
   l'elemento resta visibile con l'attributo addosso. Sorpreso su un pulsante "Indietro"
   che restava in pagina al primo passo di un modulo (DL-116). Una riga qui, e ogni
   `prop('hidden', ...)` del sito fa quello che dice. */
[hidden] { display: none !important; }

/* ---------- Parte 6.2 - troncamento ---------- */
.ellipsis    { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.min-width-0 { min-width: 0; }
.subtitle.ellipsis, .username.ellipsis {
  display: -webkit-box; -webkit-line-clamp: 1; line-clamp: 1;
  -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;
}
.subtitle.two-rows.ellipsis { -webkit-line-clamp: 2; line-clamp: 2; height: 40px; }

/* ---------- Parte 6.3 - spaziature ---------- */
.p-2-5      { padding: 12px; }
.px-2-5     { padding-left: 12px; padding-right: 12px; }
.mt-2-5     { margin-top: 10px !important; }
.py-12px    { padding-top: 12px; padding-bottom: 12px; }
.min-w-130  { min-width: 130px; }
.padding-footer { padding-bottom: 80px !important; }

/* ---------- Parte 6.4 - raggi e ombre ---------- */
.rounded-3-5, .btn-outline-secondary, .nav-link.rounded-3-5 { border-radius: 12px; }
.rounded-start-3-5 { border-top-left-radius: 12px !important; border-bottom-left-radius: 12px !important; }
.rounded-end-3-5   { border-top-right-radius: 12px !important; border-bottom-right-radius: 12px !important; }
@media (min-width: 768px) { .w-md-auto { width: auto !important; } }
.table-head-sticky thead th { position: sticky; top: 0; z-index: 2; }
.rounded-card-top    { border-top-left-radius: 45px; border-top-right-radius: 45px; }
.rounded-card-bottom { border-bottom-left-radius: 45px; border-bottom-right-radius: 45px; }
.rounded-top-accordion    { border-radius: 16px 16px 0 0 !important; }
.rounded-bottom-accordion { border-radius: 0 0 16px 16px !important; }
.select2-container--bootstrap-5 .select2-selection { border-radius: 16px; }
.shadow-md        { box-shadow: var(--rg-shadow-md) !important; }
.shadow-dashboard { box-shadow: var(--rg-shadow-dashboard) !important; }

/* ---------- Parte 6.5 - i due soli gradienti ammessi ---------- */
.dashboard-card       { background-image: linear-gradient(120deg, #eef0f2 0%, #fdfbfb 100%); }
.dashboard-header     { background-image: linear-gradient(to top,  var(--brand-accent) 0%, var(--brand-primary) 100%); color: #fff; }
.dashboard-header-det { background-image: linear-gradient(to left, var(--brand-accent) 0%, var(--brand-primary) 100%); color: #fff; }
.login-gradient       { background-image: linear-gradient(to top, #F2F5F9 25%, var(--brand-primary-subtle) 100%); }

/* ---------- Parte 6.6 - utility di stato ---------- */
.clickable, .editable { cursor: pointer; }
.cursor-default       { cursor: default !important; }
.disabled-content     { pointer-events: none; opacity: .4; }
.disabled-pointer     { pointer-events: none; }
tr.disabled td        { color: var(--rg-caption) !important; }

/* ---------- Parte 6.7 / 10.4 - regioni a piena altezza ---------- */
@media (min-width: 992px) {
  .card-main      { min-height: calc(100vh - 20px); min-height: calc(100dvh - 20px); }
  .container-list { height: calc(100vh - 185px); height: calc(100dvh - 185px); overflow: auto; }
  #stats          { height: calc(100vh - 155px); height: calc(100dvh - 155px); overflow-x: hidden; overflow-y: auto; }
  [id^="data_"]   { height: calc(100vh - 170px); height: calc(100dvh - 170px); overflow-x: hidden; overflow-y: auto; }
}
@media (max-width: 991.98px) {
  .card-main      { min-height: 0; }
  .container-list,
  #stats,
  [id^="data_"]   { height: auto !important; overflow: visible !important; }
}

/* ---------- Parte 8.1 - intestazione di pagina ---------- */
.btn-clear { background: #fff; }
.btn-clear.btn-icon { width: 38px; padding: 7px; }
.btn-clear:hover { color: var(--rg-text) !important; }
.btn-clear.btn-arrow { padding: 3px; }
.btn-lg { min-width: 115px !important; }
.back-page:hover { color: #000; }

/* ---------- Parte 3.3 - pulsanti il cui colore codifica l'operazione ---------- */
.btn-add, .btn-send, .btn-accept { background: var(--rg-add);      color: #fff; }
.btn-del, .btn-refuse            { background: var(--rg-del);      color: #fff; }
.btn-save, .btn-edit             { background: var(--rg-save);     color: #fff; }
.btn-download                    { background: var(--rg-download); color: #fff; }
.btn-back                        { background: var(--rg-back);     color: #fff; width: 40px; height: 40px; border-radius: 50%; }
.btn-search                      { background: var(--rg-search);   color: #fff; }
.btn-chat                        { background: var(--rg-chat);     color: #fff; }
.btn-whatsapp                    { background: var(--rg-whatsapp); color: #fff; }
.btn-info                        { background: var(--rg-info);     color: #fff; }
/* Gate di DL-031: SOLO le regole di passaggio. Il colore base del pulsante non e'
   gated &mdash; su un touch il pulsante deve avere il proprio colore. */
@media (hover: hover) {
  .btn-add:hover, .btn-send:hover, .btn-accept:hover { background: var(--rg-add-hover); color: #fff; }
  .btn-del:hover, .btn-refuse:hover{ background: var(--rg-del-hover); color: #fff; }
  .btn-save:hover, .btn-edit:hover { background: var(--rg-save-hover); color: #fff; }
  .btn-download:hover              { background: var(--rg-download-hover); color: #fff; }
  .btn-back:hover                  { background: var(--rg-back-hover); color: #fff; }
  .btn-search:hover                { background: var(--rg-search-hover); color: #fff; }
  .btn-chat:hover                  { background: var(--rg-chat-hover); color: #fff; }
  .btn-whatsapp:hover              { background: var(--rg-whatsapp-hover); color: #fff; }
  .btn-info:hover                  { background: var(--rg-info-hover); color: #fff; }
}
.btn-secondary                   { background: var(--rg-secondary); border-color: var(--rg-secondary); color: var(--rg-text-black); }

/* ---------- Parte 8.2 - card dentro card ---------- */
.table-responsive, .bg-card { background: var(--rg-surface-sunken); }
/* Il vassoio infossato di §8.2 serve a far leggere le schede BIANCHE che gli stanno
   sopra quando sta sul fondo dell'applicazione. Dentro una scheda bianca e' un livello
   di troppo: si vede una lastra grigia dentro il bianco, con dentro altro bianco. Tre
   superfici per due informazioni. Dentro una scheda il vassoio e' trasparente, e le
   schede impilate si distinguono con un BORDO invece che per contrasto di fondo
   (la riga sotto, nel blocco di Parte 10.5). Misurato a 360 px: 6 vassoi grigi su
   quattro schermate, alti fino a 2894 px. */
.card > .table-responsive, .card .table-responsive,
.app-card .table-responsive { background: transparent; }
.card-footer { background: var(--rg-surface-sunken); }
/* Lo stato di passaggio esiste solo dove il puntatore puo' passare. Su un touch il
   browser emula :hover al tocco e ce lo LASCIA finche' non si tocca altrove: la
   scheda resta tinta e si legge come selezionata quando non lo e'. Da qui il gate. */
@media (hover: hover) {
  .card.bg-card.clickable:hover { background: var(--rg-surface-hover) !important; }
  .card.clickable:hover, .filter-button:hover {
    box-shadow: 0 0 6px 0 rgba(0,0,0,.2) !important;
    box-shadow: 0 0 6px 0 color-mix(in srgb, var(--brand-primary) 70%, transparent) !important;
  }
  .card.clickable.btn-list:hover { box-shadow: none !important; background: #fff; color: var(--rg-text); }
}

/* ---------- Parte 7 - shell, famiglia BARRA SUPERIORE ----------
   Parte 7 e' l'implementazione di riferimento di UNA shell a barra laterale: da qui
   si prendono le primitive, non la forma (§7 nota d'apertura, §1B.11). Per una barra
   superiore le primitive sono: la pila delle superfici (fondo app -> scheda bianca),
   gli stati di .nav-link di §8.7, il dropdown di §8.5, il ritmo .p-2-5, e §10.3a per
   il comportamento sotto lg. La composizione viene dal brief della shell, non da qui.
   Il valore dell'altezza e' il token --header-height, non un numero scritto a mano. */
/* Due fasce. La prima porta l'identita' e le destinazioni frequenti su fondo di
   marchio; la seconda le altre destinazioni su fondo bianco.
   Il blu e' --brand-primary e NON --brand-primary-bright: bianco sul valore legacy
   esatto misura 4,17:1, sotto il minimo di 4,5. E' la stessa riconciliazione di
   §2.1.4 che A1 ha gia' prodotto &mdash; il valore legacy vale per i riempimenti
   decorativi, non per le superfici che portano testo. --brand-primary da' 5,21:1. */
.app-bar {
  height: var(--header-height); background: var(--brand-primary);
  color: var(--brand-on-primary);
  position: sticky; top: 0; z-index: 1030;
}
/* I controlli della fascia di marchio NON sono .btn-clear: quella classe ha fondo
   bianco, e su una fascia colorata con testo bianco dava un riquadro bianco vuoto.
   Non si combatte la classe, si smette di usarla (DL-012): la fascia ha i propri. */
.app-bar .nav-link { color: var(--brand-on-primary) !important; }
.app-bar .btn-bar {
  /* inline-FLEX e non inline-block: .btn di Bootstrap e' inline-block, e con una
     min-height il contenuto resta in alto invece di centrarsi. Era il disallineamento
     della riga su mobile &mdash; il solo pulsante centrato era quello che portava
     d-flex align-items-center a mano. Lo porta il componente, non il markup.
     LA FORMA: pillola con il filo bianco (committente, 2026-09-11). Su una fascia
     tinta un pulsante senza contorno non si distingue dal testo che gli sta accanto:
     il filo dice dove finisce la cosa che si preme. Il fondo resta trasparente -
     riempirlo lo farebbe competere con l'azione primaria della pagina. */
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  background: transparent; border: 1px solid rgba(255,255,255,.45);
  color: var(--brand-on-primary);
  border-radius: 999px; padding: .45rem 1rem; font-weight: 500;
}
/* Il controllo dell'utente: stessa pillola, ma con il fondo appena acceso e l'avatar a
   sinistra. E' l'unico controllo della fascia che rappresenta una PERSONA, e le
   iniziali lo dicono prima del nome. */
.app-bar .btn-user {
  background: rgba(255,255,255,.18); border-color: transparent;
  padding-left: .3rem; padding-right: .75rem; gap: .55rem; max-width: 320px;
}
/* Il NOME e' in grassetto e l'avatar e' piu' chiaro della pillola che lo contiene
   (committente, 2026-09-11, con i due schermi a riferimento): in una fascia tinta due
   toni di bianco al 18% e al 28% sono lo stesso tono, e il tondo spariva dentro la
   pillola. Ora sono separati - .18 la pillola, .40 il tondo - e il nome pesa quanto la
   cosa che nomina. */
.app-bar .btn-user .shell-user-name { font-weight: 700; }
.shell-avatar {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 50%;
  background: rgba(255,255,255,.4); color: var(--brand-on-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; letter-spacing: .02em;
}
/* SOTTO md I COMANDI DELLA FASCIA SONO SOLO ICONA, e allora hanno la forma di un
   comando solo icona: un tondo. Con il riempimento della pillola diventavano lozenghe
   di tre misure diverse (54x44, 50x44, 54x50 misurati): tre forme per tre comandi che
   stanno sulla stessa riga e valgono lo stesso.
   L'apertura del menu e' l'eccezione: e' un quadrato arrotondato, perche' non e' una
   destinazione ne' una persona - apre il pannello - e la differenza di forma e' il modo
   piu' rapido di dirlo. Il controllo dell'utente resta una PILLOLA anche qui, perche'
   contiene due cose: l'avatar e il segno che si apre.
   LA SOGLIA E' 768 E NON 992 (committente, 2026-09-17): sul TABLET i tre comandi - menu
   utente, carrello e KStore - portano la propria parola, e l'icona sola resta al
   telefono. Un'icona senza etichetta si impara, non si legge: la si tiene dove lo spazio
   non lascia scelta. */
@media (max-width: 767.98px) {
  .app-bar .btn-bar {
    width: 44px; height: 44px; padding: 0; border-radius: 50%;
  }
  .app-bar .btn-menu { border-radius: 14px; }
  .app-bar .btn-user {
    width: auto; height: 44px; border-radius: 999px;
    padding: .25rem .5rem .25rem .25rem; gap: .25rem;
  }
}
/* Il menu utente: una scheda, non un elenco di link. Il blocco di testa porta chi sei e
   per chi stai operando - l'ambito, che il legacy mostrava solo sulla home (S-09) - e
   le voci hanno la propria icona, perche' un elenco di sole parole si scandisce, uno
   con le icone si riconosce. */
.shell-menu { min-width: 300px; padding: 0; overflow: hidden; }
.shell-menu-head { background: var(--rg-surface-sunken); padding: .85rem 1rem; }
.shell-menu .dropdown-item {
  display: flex; align-items: center; gap: .75rem; padding: .6rem 1rem;
}
.shell-menu .dropdown-item .fi { font-size: 18px; line-height: 1; color: var(--rg-label); }
.shell-menu .dropdown-item.text-danger .fi { color: inherit; }
.shell-menu .switch-row { padding: .35rem .6rem .6rem; }
/* Il pulsante tondo del blocco di testa: azzera il cliente in corso. Era un'immagine da
   12 px senza etichetta (rilievo S-12). */
.btn-circle {
  width: 36px; height: 36px; flex: 0 0 36px; border-radius: 50%; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
@media (hover: hover) {
  .app-bar .btn-bar:hover { background: rgba(255,255,255,.12); color: var(--brand-on-primary); }
}
.app-bar .nav-link.active {
  background-color: rgba(255,255,255,.18) !important;
  color: var(--brand-on-primary) !important;
}
/* Il passaggio del puntatore delle voci sta TUTTO in Parte 8.7, in un blocco solo:
   averlo qui e la' significava due regole per una cosa, e quella che arriva dopo nel
   foglio spegneva l'altra in silenzio. E' il difetto che questa passata ha corretto. */
/* Seconda fascia: le altre destinazioni, su bianco. Qui valgono gli stati di §8.7
   cosi' come sono nel foglio, senza sovrascritture. */
.app-bar-2 {
  /* La banda centra il proprio contenuto: con la sola min-height il contenuto resta in
     alto, e la voce attiva toccava la fascia blu sopra (0px sopra, 7px sotto, misurati).
     L'utility d-lg-flex nel markup fa il resto, perche' e' !important. */
  min-height: 44px; align-items: center; background: var(--rg-surface);
  border-bottom: 1px solid var(--rg-border);
  position: sticky; top: var(--header-height); z-index: 1029;
}
.app-bar-2 .nav-link { padding: .5rem .75rem; border-radius: var(--rg-radius-input); }
/* L'interruttore dentro un menu e' uno SWITCH, non un checkbox: un checkbox dice
   «questo verra' incluso quando invio», uno switch dice «questo e' acceso ADESSO».
   La visibilita' degli importi e' un interruttore di stato, non una scelta da
   inviare. Componente Bootstrap .form-switch (§5B.3: prima il componente Bootstrap). */
/* Riga interruttore: etichetta a sinistra, switch a destra. Bootstrap mette l'input
   a sinistra con un margine negativo e un padding compensativo sul contenitore; qui
   serve l'ordine opposto, quindi si azzerano entrambi invece di combatterli con un
   allineamento che li contraddice (era l'etichetta che andava a capo). */
/* Il menu utente ha una larghezza minima: le sue voci piu' lunghe sono
   «Caricamento da File» e la riga dell'interruttore, e senza minimo la riga
   dell'interruttore va a capo. Misurata: serve 172px, il menu ne dava 138. */
.app-bar .dropdown-menu { min-width: 16rem; }
.switch-row { display: flex; align-items: center; gap: .5rem; }
.switch-row label { white-space: nowrap; }
.switch-row .form-switch { padding-left: 0; margin: 0; min-height: 0; }
.switch-row .form-switch .form-check-input { margin: 0; width: 2.25em; height: 1.25em; }
.form-switch .form-check-input:checked {
  background-color: var(--brand-primary); border-color: var(--brand-primary); }
/* Lo slot di marchio di §1.4.4: l'altezza e' del sistema, l'asset e' della
   piattaforma. 36px e non 32: il logo di cer98 e' un lock-up 260x110 con testo
   piccolo, e a 32px il testo non si legge piu'. Chi ha un marchio piu' compatto
   puo' scendere dal proprio shell-config. */
.app-bar .app-brand img { height: 36px; width: auto; display: block; }
/* Il piede sta in fondo anche su una pagina corta: senza questo una schermata breve
   lascia il piede a mezz'aria e la pagina finisce in grigio. Sta su una classe che
   la shell aggiunge al body, non sul body nudo: le pagine senza shell (la galleria
   di verifica, i frammenti) non devono diventare contenitori flex. */
body.has-shell { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
/* Ogni fascia della shell e' flex: 0 0 auto, e SOLO la regione del contenuto flette.
   Senza questo le fasce si comprimono: Parte 6.1 tiene `html, body { height: 100% }`,
   quindi il body e' un contenitore flex di altezza FISSA, e quando il contenuto lo
   eccede i figli si restringono. La barra dichiarata 56px ne misurava 46. */
body.has-shell > .app-bar,
body.has-shell > .app-bar-2,
body.has-shell > .app-foot { flex: 0 0 auto; }
body.has-shell .app-main { flex: 1 0 auto; min-height: 0; }
.app-bar .nav-link { border-radius: var(--rg-radius-input); padding: .5rem .75rem; }
/* Il carosello marchi: ultima fascia della pagina, a piena larghezza. */
.app-foot { padding-bottom: 1rem; }
.app-foot .foot-carousel { border-top: 1px solid var(--rg-border); }
  /* La striscia dei marchi. NON e' un carosello a slide: Slick ne mostrava n-1 alla
     volta, quindi un carosello Bootstrap &mdash; che mostra una slide per volta &mdash; toglierebbe
     la capacita' di vederli tutti insieme (§1.1). E' una striscia scorrevole nativa: si
     scorre col dito, con la rotella e con la tastiera, con scroll-snap.
     Nessun autoplay, che e' anche un guadagno di accessibilita': un contenuto che si
     muove da solo senza comando di pausa non soddisfa WCAG 2.2.2, e Slick lo faceva
     ogni secondo. */
  /* Il comportamento e' una primitiva: la usa la striscia dei marchi nel piede e la
     usa la fila delle novita' nella ricerca, che nel legacy era il SECONDO carosello
     della piattaforma (unslider, rilievo L-05). Due librerie di carosello diventano una
     regola di scorrimento. Chi la usa decide quanto sono grandi le proprie immagini. */
  .scroll-strip, .brand-strip {
    display: flex; align-items: center; gap: 2.5rem;
    overflow-x: auto; scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch; padding-bottom: .5rem;
    scrollbar-width: thin;
  }
  .scroll-strip > *, .brand-strip > * { flex: 0 0 auto; scroll-snap-align: start; }
  .brand-strip img { max-width: 120px; max-height: 30px; width: auto; height: auto; }
  .scroll-strip::-webkit-scrollbar, .brand-strip::-webkit-scrollbar { height: 6px; }
  .scroll-strip::-webkit-scrollbar-thumb, .brand-strip::-webkit-scrollbar-thumb {
    background: var(--rg-track); border-radius: var(--rg-radius-pill); }

/* ---------- la striscia che scorre DA SOLA (committente, 2026-09-11) ----------
   Il committente ha chiesto il ritorno dello scorrimento automatico, con la pausa al
   passaggio del mouse. Supera la scelta di DL-049, e si costruisce con tre vincoli che
   non sono negoziabili (WCAG 2.2.2 chiede che un movimento automatico si possa
   fermare):
   1. si ferma col PUNTATORE sopra - e' la richiesta - e anche col FUOCO dentro, perche'
      chi naviga da tastiera deve poter leggere un logo senza inseguirlo;
   2. sotto `prefers-reduced-motion` non parte affatto, e la striscia torna quella
      scorrevole a mano: chi ha dichiarato che il movimento gli da' fastidio non lo
      riceve;
   3. il movimento e' una traslazione della pista, non uno `scrollLeft` a colpi di
      timer: resta fluido e non litiga con il dito di chi scorre.
   La pista contiene i contenuti DUE volte e trasla del 50%: cosi' il giro si chiude
   senza salto. Il tempo e' proporzionale a quanti sono, dichiarato dal PHP che li conta,
   perche' venti marchi a velocita' di tre sarebbero una corsa.
   IL COMPORTAMENTO E' DI TUTTE E DUE LE STRISCE (committente, 2026-09-16): lo chiede
   anche la fascia delle promozioni, che e' una `.scroll-strip`. Non si duplica la regola
   per l'altra classe: la regola ne prende due. */
  .brand-strip.is-auto, .scroll-strip.is-auto { overflow: hidden; scroll-snap-type: none; }
/* La pista e' SEMPRE una fila: la dichiarazione sta fuori da `.is-auto`, perche' quando
   l'animazione non serve - pochi elementi, movimento ridotto - la classe se ne va e la
   pista resta. Senza, il contenitore tornava un blocco e i contenuti andavano a capo. */
  .brand-track {
    display: flex; align-items: center; gap: 2.5rem; flex: 0 0 auto;
    will-change: transform;
  }
  .brand-track > * { flex: 0 0 auto; }
  .brand-strip.is-auto .brand-track, .scroll-strip.is-auto .brand-track {
    animation: brandScroll var(--brand-scroll-time, 40s) linear infinite;
  }
/* Solo la fascia promozioni scorre un po' piu' lenta della fascia marchi: stesso
   calcolo del PHP (proporzionale al numero di elementi), semplicemente scalato
   del 15%. Longhand dopo lo shorthand, stessa specificita': vince solo per la
   durata, il resto della regola sopra resta invariato. */
  .scroll-strip.is-auto .brand-track {
    animation-duration: calc(var(--brand-scroll-time, 40s) * 1.25);
  }
@media (hover: hover) {
  .brand-strip.is-auto:hover .brand-track,
  .scroll-strip.is-auto:hover .brand-track { animation-play-state: paused; }
}
  .brand-strip.is-auto:focus-within .brand-track,
  .scroll-strip.is-auto:focus-within .brand-track { animation-play-state: paused; }
@keyframes brandScroll {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-50% - 1.25rem)); }
}
/* Il carosello marchi/promozioni deve scorrere sempre, con movimento lineare,
   anche con prefers-reduced-motion attivo: la regola che qui disattivava
   overflow e animazione e' stata rimossa a richiesta (committente, 2026-09-18).
   L'override in fondo al file (Parte 11.1) resta valido anche contro il reset
   globale delle durate e ridichiara `linear` esplicitamente. */
/* Cromatura di schermata: due slot che la shell dichiara e ogni schermata riempie.
   Una schermata che non li riempie e' un difetto del suo brief, non della shell. */
/* Solo l'asse verticale: con `padding: 1rem 0 .5rem` si azzera anche l'orizzontale, e
   se .page-head sta su una colonna di griglia le si toglie il gutter &mdash; il titolo
   finiva 12px a sinistra del contenuto. */
/* Padding dichiarato dal committente: zero sopra, 16 px sotto. Lo spazio fra la
   navigazione e il primo elemento della pagina NON e' della cromatura di schermata - se
   stesse qui, una schermata senza titolo non l'avrebbe - ed e' passato alla regione di
   pagina, sotto. Misurato senza: su una schermata senza scheda di pagina il titolo
   restava a 4 px dalla barra. */
.page-head { padding-block: 0 1rem; }
/* La regione di pagina stacca dalla navigazione, e vale nei due casi: con la scheda di
   pagina - che comincia da li' - e senza, dove il primo elemento e' il titolo. */
.app-main { padding-block-start: .75rem; }
.page-head .page-title { font-size: 24px; font-weight: 600; color: var(--rg-text-strong); }
/* Il piede: fluido, senza larghezza minima. Accoglie cio' che la banda da 61 px
   portava in cima (E5, S-17). */
.app-foot { background: var(--rg-surface); border-top: 1px solid var(--rg-border);
  color: var(--rg-caption); font-size: 13px; }
.app-foot .foot-logos img { height: 26px; width: auto; }
.app-foot a { color: var(--rg-label); }

@media (max-width: 991.98px) {
  /* §10.3a: una riga di cromatura, i bersagli al pavimento del tocco, la
     navigazione dietro UNA affordance. */
  /* Sotto lg le due fasce collassano in una: la seconda non si rende, le sue
     destinazioni vivono nel cassetto (§10.3a punto 1). */
  .app-bar { height: 56px; }
  .app-bar-2 { display: none; }
  /* Anche in LARGHEZZA: la soglia di §10.1.3 e' 44x44, e i due comandi di destra della
     fascia - carrello e utente - misuravano 44 di altezza e 40 di larghezza. Il padding
     di .btn-bar non basta per un'icona sola. */
  .app-bar .btn, .app-bar .nav-link { min-height: 44px; min-width: 44px; }
  /* Sotto lg nella riga sta il MARCHIO, non il titolo di schermata (direttiva del
     committente). I due non ci stanno insieme: logo.png e' 879x156 e a 26px di altezza
     occupa 147px su 360. La posizione corrente resta visibile senza aprire niente
     grazie a briciola e titolo subito sotto la barra; quello che si perde e' la
     posizione mentre si scorre, perche' la barra e' sticky e il titolo no. */
  .app-bar .app-brand { display: flex; align-items: center; min-height: 44px; }
  .app-bar .app-brand img { height: 26px; }
  /* Il cassetto non copre TUTTO lo schermo: `.offcanvas-start` di Bootstrap vale 400 px
     e a 360 diventa la pagina intera, senza piu' niente della schermata dietro - non si
     vede dove si stava e non c'e' un fuori da toccare per chiudere. §10.3 da' la misura:
     min(85vw, 320px), che a 360 px lascia 54 px di pagina e di velo. */
  .app-drawer { width: min(85vw, 320px) !important; }
  .app-drawer .nav-link { min-height: 44px; display: flex; align-items: center; }
  .app-drawer .drawer-group { color: var(--rg-label); font-weight: 500; font-size: 13px;
    padding: .75rem .75rem .25rem; }
}

/* ---------- Parte 8.1b - i pulsanti che il foglio legacy dichiara ----------
   `.buttons` e' la classe con cui il legacy dipinge i propri pulsanti di invio
   (`style.css:457`): fondo #ff452f, corpo 12 px, nessun raggio. Due difetti in uno.
   Il primo e' di significato: quel rosso e' il colore del PERICOLO nella tavolozza, e
   dipingerlo sull'azione primaria di una ricerca dice all'utente «questo distrugge
   qualcosa» - due significati per un colore, che e' DL-070. Il secondo e' di misura:
   12 px di corpo e 38 px di altezza, sotto la soglia del tocco.
   Il pulsante diventa quello di marchio del kit. La classe resta dov'e': non si tocca
   il markup legacy, si smette di lasciargli decidere la cromatura. */
.buttons {
  background: var(--brand-primary); color: var(--brand-on-primary);
  border: 1px solid var(--brand-primary); border-radius: var(--rg-radius-input);
  font-size: 14px; font-weight: 500; padding: .5rem 1rem;
}
@media (hover: hover) {
  .buttons:hover { background: var(--brand-primary-hover); border-color: var(--brand-primary-hover); }
}
@media (max-width: 991.98px) { .buttons { min-height: 44px; font-size: 16px; } }

/* ---------- §8.11b - il pulsante che si conferma da SE' ----------
   Lo stato transitorio di un'azione ripetitiva: al posto del popup, il pulsante che si e'
   premuto diventa per un momento la conferma di cio' che ha fatto (verde, con la spunta).
   E' verde e non di marchio perche' non e' piu' un comando: e' l'esito. Il verde
   dell'esito e quello della disponibilita' non si confondono - DL-070 - perche' questo
   dura un secondo e mezzo e sta sul pulsante che l'utente sta guardando, non in una
   colonna di dati. Il tempo lo decide `btnDone`. */
.btn.is-done {
  background: var(--rg-success) !important;
  border-color: var(--rg-success) !important;
  color: #fff !important;
  pointer-events: none;
}

/* Due utility legate ai token di marchio. Bootstrap 5.3 ha `.bg-primary-subtle` e
   `.text-primary`, ma sono il SUO blu (#0d6efd): usarle porterebbe in pagina un colore
   che non e' nel palette di Parte 3. Queste due dicono la stessa cosa col nostro token.
   Servono alla testata del blocco dei prezzi netti, dove il committente vuole la fascia
   tenue di marchio (brief della ricerca 11.2). */
.bg-brand-subtle { background-color: var(--brand-primary-subtle); }
.text-brand      { color: var(--brand-primary); }

/* ---------- Parte 8.2b - la scheda che si SCEGLIE ---------- */
/* Una scelta singola resa come schede grandi. Il radio resta nel documento e nella
   tastiera - `visually-hidden`, non `display:none` - ma non si vede: lo stato lo porta
   il BORDO della scheda, dichiarato dal committente il 2026-09-10 (DL-118).
   Il bordo e' quello che la scheda ha gia', quindi fra scelto e non scelto cambia
   soltanto il colore e nessuna misura: niente salto di layout, e nessun secondo bordo.
   Il fuoco non puo' restare invisibile perche' il controllo e' nascosto: l'anello passa
   alla scheda, ed e' lo stesso alone dei campi di Parte 8.8. */
.card-choice { cursor: pointer; }
.card-choice:has(input:checked) { border-color: var(--brand-primary) !important; }
/* `:focus` e non `:focus-visible`: il controllo e' nascosto, quindi non esiste un caso
   in cui il fuoco possa restare senza segno - e i campi del kit (Parte 8.8) usano lo
   stesso alone su `:focus` semplice. */
.card-choice:has(input:focus) { box-shadow: 0 0 0 .25rem rgba(26,104,217,.25); }
@media (hover: hover) {
  .card-choice:not(:has(input:checked)):hover { border-color: var(--rg-border-strong) !important; }
}

/* ---------- Parte 8.4c - la scala dei prezzi netti, e la tabella ANNIDATA ----------
   Nasce sulla ricerca articolo, dove i netti si vedono in prima battuta per richiesta
   del cliente del B2B (DEV-021). Sta nel kit e non nella schermata perche' due cose qui
   sono generali: la scatola compatta allineata sotto i numeri che spiega, e soprattutto
   l'OPT-OUT di una tabella annidata dentro una scheda (DL-120).
   Le regole della vista a schede (Parte 10.5) sono scritte come DISCENDENTI
   - `.table-stack td`, `.table-head-sticky thead th` - quindi colpiscono anche le celle
   di una tabella dentro una cella. Una tabella annidata deve dichiararsi tabella. */
.netti-box   { width: 100%; max-width: 420px; }
.netti-table { table-layout: fixed; }
.netti-table th, .netti-table td { padding: .35rem .75rem; }
/* L'ultima colonna e' la piu' larga perche' la sua INTESTAZIONE e' la piu' lunga:
   «NETTO SCONTATO» sta su una riga sola (committente). Misurato a 14 px: la parola vuole
   130 px piu' il padding, quindi il 40% di 420 la contiene con margine. */
.netti-table th { white-space: nowrap; }
/* E NEMMENO UN NUMERO VA A CAPO. La colonna «A» portava l'8% - 33 px - e un limite di
   999,00 si spezzava in verticale, una cifra per riga: il `overflow-wrap: break-word`
   che la tabella eredita spezza dove non c'e' spazio, e in una colonna di numeri non
   c'e' mai. Le larghezze ora tengono il valore piu' lungo che la scala puo' portare
   (999,00, perche' oltre il limite diventa una freccia), e `nowrap` lo garantisce.
   L'ultima colonna resta la piu' larga perche' la sua intestazione lo chiede. */
.netti-table td { white-space: nowrap; }
.netti-table th:nth-child(1), .netti-table td:nth-child(1) { width: 15%; }
.netti-table th:nth-child(2), .netti-table td:nth-child(2) { width: 18%; }
.netti-table th:nth-child(3), .netti-table td:nth-child(3) { width: 15%; }
.netti-table th:nth-child(4), .netti-table td:nth-child(4) { width: 14%; }
.netti-table th:nth-child(5), .netti-table td:nth-child(5) { width: 38%; }
/* L'intestazione di una tabella annidata NON e' sticky: un `th` sticky esce dal flusso,
   e la riga dei valori finisce SOTTO la fascia dell'intestazione - il DOM la da'
   presente e lo schermo non la mostra. */
.netti-table thead th { position: static !important; top: auto !important; }
/* La riga di dettaglio SEMPRE aperta non prende il fondo infossato: appartiene alla riga
   e il bordo lo porta la scatola dei netti. E fra la riga e la sua scala non c'e' filo. */
tr.detail-row.detail-plain > td { background: transparent; }
tr.flt-data:has(+ tr.detail-row.detail-plain) > td { border-bottom: 0; }
/* La cella del codice: nella tabella il pre-codice sta accanto al codice. */
.pre-codice { margin-right: .35rem; }

/* ---------- Parte 8.3 - pillola di ricerca ---------- */
/* IL CAMPO CON L'ICONA DENTRO. Stessa meccanica della pillola di §8.3 - una scatola
   sola e l'icona posizionata dentro - con l'icona all'INIZIO e l'aspetto del campo di
   §8.8, cioe' `.form-control`. Sostituisce l'`input-group` con la scatola dell'icona
   accanto, che era due scatole per un controllo solo: due bordi da far combaciare, e
   l'anello di fuoco che si disegnava attorno alla META' destra invece che attorno al
   campo. Con una scatola sola non c'e' niente da far combaciare.
   Il campo tiene TUTTO quello che il kit gli da' - bordo, raggio, anello di fuoco, i
   44 px e i 16 px di corpo sotto lg, lo stato di non valido - perche' resta un
   `.form-control`: il contenitore aggiunge solo la posizione dell'icona e lo spazio.
   `pointer-events: none` sull'icona: un tocco sull'icona porta il fuoco nel campo
   invece di cadere nel vuoto. L'icona e' decorativa e non e' un comando - la ricerca la
   fa il typeahead mentre si scrive - quindi non e' nemmeno un bersaglio da 44 px.
   Le 44 px di spazio a sinistra sono le stesse dell'`.input-group-text` che c'era prima,
   cosi' il testo comincia dove cominciava. */
.search-field { position: relative; }
.search-field > .search-field-icon {
  position: absolute; left: 0; top: 0; bottom: 0; width: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--rg-caption); pointer-events: none;
}
.search-field > .form-control { padding-left: 44px; min-height: 42px; }
.search-field > .form-control#resiCerca { min-height: auto; }

.search_mini { height: 48px; background: var(--rg-app-bg); padding: 7px 10px; }
.search_input { border: 0; outline: 0; background: none; width: 0; line-height: 50px; }
.search_mini .search_input { padding: 0 10px; }
.search_icon_mini { height: 35px; width: 35px; float: right; display: flex;
  justify-content: center; align-items: center; border-radius: 50%; }
.clear-input-btn { position: absolute; width: 30px; font-weight: 550; border: none;
  background: transparent; z-index: 9; }
.search_mini .clear-input-btn { line-height: 35px; left: calc(100% - 75px); }
.clear-input-btn:hover { color: var(--brand-primary); }
.textarea_search { height: auto; }
.textarea_search .search_input { resize: none; overflow: hidden; line-height: 30px; max-height: 125px; }

/* ---------- Parte 8.4 - tabelle ---------- */
/* L'intestazione di QUALUNQUE tabella, comprese quelle legacy che non hanno una classe.
   Era `--rg-secondary` (#D2D2D2) con testo nero: una lastra grigia scura, e su mobile
   il difetto piu' visibile della piattaforma - 254 celle contate, di cui 231 nella sola
   Area Personale, dove i `th` sono la colonna delle etichette e formano una colonna
   grigia alta quanto la pagina. Ora e' l'intestazione di Parte 8.4: fondo infossato
   chiaro, testo strutturale in --rg-label (§3.2, che sostituisce proprio i grigi
   scuri dell'app di riferimento per il testo strutturale), peso 500 e un filo sotto.
   Resta `!important` perche' deve battere gli attributi di presentazione del markup
   legacy, che a volte porta un bgcolor sul `th`. */
th {
  background-color: var(--rg-surface-sunken) !important;
  color: var(--rg-label) !important;
  font-weight: 500 !important;
  border-bottom: 1px solid var(--rg-border-strong);
}
.table-dashboard { padding: 0 12px; }
.table-dashboard th {
  background: var(--rg-surface-sunken) !important;
  color: var(--rg-label) !important;
  font-size: 14px; font-weight: 500 !important;
  text-transform: none; letter-spacing: 0;
  vertical-align: middle; padding: 10px !important;
  position: sticky; top: 0; z-index: 1;
  border-color: var(--rg-border-strong) !important; border-bottom: 0 !important;
}
.table-dashboard td { font-size: 14px; vertical-align: middle; }

/* ---------- Parte 8.4c - LA RIGA E' IL BERSAGLIO ----------
   Rilievi C5 e M-43: sullo Storico Ordini l'unico elemento cliccabile della riga e' il
   numero d'ordine, sei caratteri su una riga larga ~1.680 px - il 3%. Il collegamento
   resta UNO e resta dov'e', sul numero: si stende sopra tutta la riga con uno
   pseudo-elemento, che e' la tecnica di `.stretched-link` di Bootstrap portata sulla
   riga invece che sulla scheda.
   Perche' non `.stretched-link` e basta: quello copre il primo antenato POSIZIONATO, e
   dentro una tabella l'antenato posizionato piu' vicino sarebbe il contenitore dello
   scorrimento, non la riga - il velo coprirebbe tutta la tabella. Qui e' la `tr` a
   dichiararsi posizionata, e il velo si ferma su di essa.
   I COMANDI RESTANO COMANDI: tutto cio' che si preme dentro la riga sale sopra il velo.
   Vale anche nella vista a schede, dove la `tr` e' gia' un blocco. */
tr.row-link { position: relative; }
tr.row-link .riga-stretch::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1;
}
tr.row-link .btn,
tr.row-link button,
tr.row-link input,
tr.row-link select,
tr.row-link a:not(.riga-stretch) { position: relative; z-index: 2; }
/* Il puntatore lo dice prima del clic; su un touch non c'e' puntatore da cambiare. */
@media (hover: hover) { tr.row-link { cursor: pointer; } }
/* ---------- Parte 8.4b - le tabelle che il PHP legacy emette NUDE ----------
   Non hanno una classe: `table:not([class])` le prende tutte e non prende nessuna
   tabella del kit. Restano tabelle - il loro brief le ridisegnera' - ma la cromatura
   e' quella del kit, perche' una schermata non puo' avere due look di tabella.
   LA ZEBRATURA. `ECommerce.php:3386` e `:3770` alternano riga per riga due tinte
   scritte nello `style` della `<tr>`: #DFF1FF azzurro e #EBEAE9 beige. E' zebratura
   PURA - il colore si scambia a ogni giro, non dice niente della riga - e su mobile,
   dentro una scheda bianca, e' il residuo piu' visibile del foglio vecchio. Si
   neutralizza e l'alternanza la ridisegna il kit col proprio grigio infossato.
   Il selettore nomina le DUE tinte e nient'altro, di proposito: il colore di riga che
   invece PORTA un significato - i tre flag delle pratiche di reso compressi in un
   fondo (`Stats.php:2633` e `:2756`, rilievo M-39) - non passa da qui e non si tocca,
   perche' togliergli il colore prima che il suo brief ne abbia relocato il significato
   cancellerebbe un'informazione (§1.1). */
.app-main table:not([class]) > tbody > tr > td,
.app-main table:not([class]) > tr > td { padding: .5rem; vertical-align: middle; }
.app-main tr[style*="DFF1FF"], .app-main tr[style*="EBEAE9"] { background-color: transparent !important; }
.app-main tr[style*="DFF1FF"]:nth-of-type(even),
.app-main tr[style*="EBEAE9"]:nth-of-type(even) { background-color: var(--rg-surface-sunken) !important; }
.table-dashboard-white th { background: #fff !important; font-size: 16px !important; padding: 8px !important; }
tr.clickable > *        { background-color: #fff !important; }
@media (hover: hover) {
  tr.clickable:hover > *  { background-color: var(--rg-row-hover) !important; }
  .table-hover > tbody > tr:hover > * { background: var(--brand-primary-subtle) !important; }
}
/* Al tocco nessun colore: ne' l'emulazione di :hover, ne' il lampo che il browser
   dipinge di suo sugli elementi interattivi. La riga si sceglie con il proprio
   controllo di selezione, e quello ha il suo stato. */
tr.clickable, .table-hover > tbody > tr, .card.clickable {
  -webkit-tap-highlight-color: transparent; }
/* Spegnere le PROPRIE regole di hover non basta: al tocco restano accese quelle di
   Bootstrap e di DataTables, che dipingono per conto loro e con due meccanismi
   diversi &mdash; Bootstrap con la variabile di stato della tabella, DataTables con
   un'ombra interna. Si neutralizzano entrambe alla fonte, ripetendo i loro selettori
   esatti: il foglio del kit viene dopo i loro, quindi a pari specificita' vince.
   La SELEZIONE resta: e' uno stato che l'utente ha scelto, non un riflesso del
   puntatore, e la sua regola porta !important. */
@media (hover: none) {
  .table-hover > tbody > tr:hover > * {
    --bs-table-color-state: initial; --bs-table-bg-state: initial; }
  table.table.dataTable.table-hover > tbody > tr:hover > * { box-shadow: none; }
  table.dataTable thead > tr > th.dt-orderable-asc:hover,
  table.dataTable thead > tr > th.dt-orderable-desc:hover,
  table.dataTable thead > tr > td.dt-orderable-asc:hover,
  table.dataTable thead > tr > td.dt-orderable-desc:hover { outline: 0; }
}
.tbl-pvt thead.text-bg-dark th { background: var(--brand-dark) !important; color: #fff !important; }
.table-spacing { border-collapse: separate; }
div.dt-layout-cell.dt-layout-end { margin: 0 auto !important; }
div.dt-layout-cell.dt-layout-end .dt-search, .dt-search { display: none !important; }
div.dt-layout-start { width: 0 !important; margin: 0 !important; padding: 0 !important; }
div.dt-layout-end:has(> div.dt-paging) { margin: 0 auto !important; }
div.dt-container .dt-paging .dt-paging-button {
  margin: 0 !important; padding: 0 !important; border: 0 !important;
  background: #fff !important; box-shadow: none !important;
}
div.dt-container .dt-paging .dt-paging-button .page-link:focus { box-shadow: none !important; }
div.dt-container .dt-paging .page-link { height: 100%; }
div.dt-length { display: none; }
div.dtcc-dropdown button.dtcc-button span.dtcc-button-text { padding: 8px 0 !important; font-size: 14px !important; }
div.dtcc-dropdown div.dtcc-list div.dtcc-list-buttons { background: #fff !important; }
div.dtcc-list-controls { border-bottom: 1px solid var(--rg-border); margin: 0 5px; }
/* La selezione di riga e' un affordance di selezione, non un campo di modulo:
   prende forma circolare, cosi' si distingue dai checkbox dei moduli, e misura
   piu' del 15px legacy. */
.table.dataTable input.dt-select-checkbox,
.form-check-input.bulk-select {
  width: 20px; height: 20px; margin-top: 0; border-radius: 50%;
  border: 2px solid var(--rg-border-strong); background-color: var(--rg-surface);
  transition: background-color .15s ease-in-out, border-color .15s ease-in-out;
}
@media (hover: hover) {
  .table.dataTable input.dt-select-checkbox:hover,
  .form-check-input.bulk-select:hover { border-color: var(--brand-primary); }
}
.table.dataTable input.dt-select-checkbox:checked,
.form-check-input.bulk-select:checked,
.table.dataTable input.dt-select-checkbox:indeterminate,
.form-check-input.bulk-select:indeterminate {
  background-color: var(--brand-primary); border-color: var(--brand-primary);
}
@media (max-width: 991.98px) {
  .table.dataTable input.dt-select-checkbox,
  .form-check-input.bulk-select { width: 24px; height: 24px; }
}
.table.dataTable .dt-column-header input.dt-select-checkbox { display: none; }
.select .dt-column-header { display: block !important; }
table.table.dataTable > tbody > tr.selected > * {
  box-shadow: inset 0 0 0 9999px var(--brand-primary) !important;
}
.dt-select-checkbox { cursor: pointer; }

/* ---------- Parte 8.5 - dropdown ---------- */
/* Sotto lg ogni voce di dropdown e' un bersaglio di tocco: §10.1.3 chiede 44px e
   Bootstrap ne da' 41. Vale per OGNI dropdown della piattaforma, non solo per quello
   della shell, quindi sta qui e non fra i componenti di shell.
   Il difetto e' stato trovato aprendo il menu prima di misurare: a menu chiuso il
   conto dei bersagli sotto i 44px tornava zero, e non dimostrava niente. */
@media (max-width: 991.98px) {
  /* Non solo .dropdown-item: QUALUNQUE cosa cliccabile dentro un menu. La prima
     stesura copriva solo la classe di Bootstrap e lasciava fuori un link normale
     dentro il menu, che misurava 41px. */
  .dropdown-menu a, .dropdown-menu button { min-height: 44px; display: flex;
    align-items: center; }
  /* La chiusura di un offcanvas e di un modale e' anch'essa un bersaglio: Bootstrap
     le da' 32px. */
  .btn-close { min-width: 44px; min-height: 44px; }
}
.dropdown-toggle::after { display: none; }
.dropdown-toggle.no-arrow::after,
.dropstart .dropdown-toggle.no-arrow::before { display: none; }
.dropdown-menu { padding: 0 !important; }
.dropdown-menu li a { padding: 10px !important; }

/* ---------- Parte 8.6 - avatar ---------- */
.badge-icon      { width: 35px; height: 35px; background: var(--brand-dark); color: #fff; }
.badge-icon.warning { background: var(--rg-alert); }
.badge-icon-list { width: 45px; height: 45px; background: var(--brand-dark); color: #fff; }
.badge-icon-card { width: 35px; height: 35px; background: #9BFBF9; font-size: 13px; }
.card_usr_logo   { width: 45px; height: 45px; object-fit: cover; }
.img-area        { max-width: 32px; }
.thumb-tsk       { width: 40px; height: 40px; }
.img-card-list   { width: 18px; height: 18px; }

/* ---------- Parte 8.7 - pillole di filtro ---------- */
.nav-link { color: var(--rg-caption) !important; }
/* Lo stato ATTIVO non e' gated: e' posizione, non passaggio del puntatore. Il
   passaggio si', per DL-031 &mdash; su un touch una voce toccata resterebbe tinta e si
   leggerebbe come la voce attiva, che e' esattamente il segnale che la shell deve
   dare senza ambiguita'. */
/* SCOPATO alle barre della shell, e non a `.nav-link` nudo. Con la regola non scopata
   e `!important`, lo stato attivo delle pillole di filtro era MORTO: `!important` batte
   qualunque specificita', quindi la pillola attiva prendeva il grigio incassato invece
   del bianco. Misurato sul mockup del carrello: fondo della pillola attiva
   rgb(242,242,242), fondo della striscia rgb(242,242,242) - lo stesso colore, cioe'
   nessuno stato attivo visibile. Colpiva anche le schede di Area Personale, gia'
   costruite. E' DL-012 applicato a una regola mia contro un'altra regola mia. */
.app-bar .nav-link.active,
.app-bar-2 .nav-link.active,
.app-drawer .nav-link.active { background-color: var(--rg-surface-sunken) !important; color: var(--rg-text) !important; }
/* La pillola attiva e' BIANCA sulla striscia incassata: e' il contrasto che dice quale
   voce e' scelta. `!important` perche' deve battere le utility di Bootstrap. */
.nav-filter .nav-link.active { background: #fff !important; color: var(--rg-text) !important; box-shadow: var(--rg-shadow-sm); }
@media (hover: hover) {
  /* Sulle DUE superfici bianche della navigazione - la seconda fascia e il cassetto -
     il passaggio del puntatore prende la tinta di marchio PIENA con il testo bianco
     (schermata di riferimento del committente). Il blu e' --brand-primary, che con il
     bianco misura 5,21:1; --brand-primary-bright ne darebbe 4,17 ed e' riservato ai
     riempimenti decorativi (§2.1.4), quindi qui non entra.
     `:not(.active)` non e' un dettaglio di stile: senza, passare sopra la voce CORRENTE
     la ridipinge e il segnale di posizione sparisce proprio mentre lo si cerca. Lo stato
     attivo resta la pillola chiara di adesso, per decisione del committente. */
  .app-bar-2 .nav-link:not(.active):hover,
  .app-drawer .nav-link:not(.active):hover {
    background-color: var(--brand-primary) !important; color: var(--brand-on-primary) !important; }
  /* La fascia di marchio NON prende il blu: blu su blu non si vede. Li' il passaggio e'
     il velo di bianco al 12%, che si distingue anche dalla pillola chiara dello stato
     attivo. Prima questa riga dava --rg-surface-sunken a tutte e tre le barre e,
     arrivando dopo quella della Parte 7, spegneva il velo: sulla fascia blu passaggio e
     stato attivo erano lo STESSO grigio chiaro, cioe' due significati e un solo aspetto.
     E' DL-068 di nuovo - una mia regola contro un'altra mia regola - e stavolta non per
     specificita' ma per ordine nel foglio. */
  .app-bar .nav-link:not(.active):hover {
    background-color: rgba(255,255,255,.12) !important; color: var(--brand-on-primary) !important; }
  /* Le pillole di filtro non sono la navigazione: restano con il grigio di passaggio
     di §8.7. Il blu pieno le farebbe leggere tutte come la pillola scelta. */
  .nav-filter .nav-link:not(.active):hover { background: var(--rg-surface-hover) !important; color: var(--rg-text) !important; }
}

/* ---------- Parte 8.8 - form ---------- */
/* Solo il COLORE, non la scorciatoia `border`. Bootstrap da' gia' larghezza e stile
   (`border: var(--bs-border-width) solid var(--bs-border-color)`), e al kit serve solo
   la propria tinta; la scorciatoia con `!important`, invece, riscriveva tutti e quattro
   i lati e spegneva le utility `border-start-0` / `border-end-0`, che hanno la stessa
   specificita' e arrivano PRIMA nel foglio. Si vedeva sul campo di ricerca: l'icona e il
   campo mostravano due bordi a contatto invece di uno, perche' il lato che il markup
   chiedeva di togliere tornava. Misurato: `border-left-width` 1px dove il markup
   dichiarava 0. E' DL-077 su una proprieta' invece che su un colore - una scorciatoia
   con `!important` non batte una regola, batte OTTO proprieta'. */
.form-select, .form-control, .input-group-text { border-color: var(--rg-border) !important; }
.form-select.is-invalid, .form-control.is-invalid { border-color: var(--rg-invalid-border) !important; }
.input-group-text { width: 44px; }
.input-group-text.clickable { background: var(--brand-primary); color: #fff; }
@media (hover: hover) { .input-group-text.clickable:hover { background: var(--brand-primary-hover); } }
.form-check-input:checked { background-color: var(--brand-primary); border-color: var(--brand-primary); }
.form-check-input:focus { border-color: var(--brand-primary); box-shadow: 0 0 0 .25rem rgba(26,104,217,.25); }
.form-control:focus, .form-select:focus { border-color: var(--brand-primary) !important; box-shadow: 0 0 0 .25rem rgba(26,104,217,.25); }
/* L'ANELLO DEL FUOCO ABBRACCIA TUTTO IL GRUPPO (committente, 2026-09-17).
   Un `.input-group` e' UN controllo: il campo della password e il pulsante che la mostra,
   il campo di ricerca e la sua lente, il campo della quantita' e i suoi due scatti.
   Con l'anello sul solo `.form-control` il contorno blu si fermava a meta' del controllo e
   il pulsante accanto restava fuori, come se non ne facesse parte.
   L'anello passa al gruppo e il campo dentro lo spegne, altrimenti se ne vedono due, uno
   dentro l'altro. Il raggio e' quello del gruppo, cosi' l'anello segue la pillola invece
   di tagliarne gli angoli. */
.input-group:focus-within { box-shadow: 0 0 0 .25rem rgba(26,104,217,.25); border-radius: var(--rg-radius-input); }
.input-group:focus-within .form-control:focus,
.input-group:focus-within .form-select:focus { box-shadow: none; }
.input-group:focus-within .form-control,
.input-group:focus-within .form-select,
.input-group:focus-within .input-group-text,
.input-group:focus-within .btn { border-color: var(--brand-primary) !important; }
.form-switch-big { width: 40px !important; height: 20px !important; }
textarea { resize: none; }
hr.title_separator { border: 1px solid var(--rg-rule); }
.accordion-button { background: var(--rg-surface-sunken) !important; color: #000 !important; }
.accordion-button:not(.collapsed) { box-shadow: none; }
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--selected,
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option[aria-selected=true]:not(.select2-results__option--highlighted) {
  color: var(--rg-text-strong); background-color: #fff;
}

/* ---------- Parte 8.10 - modali ---------- */
/* La scheda di conferma e' larga 325 px e CENTRATA (§8.10). Il centro non era: sotto sm
   `.modal-dialog` di Bootstrap ha `margin: .5rem` senza `auto`, e un max-width senza
   margini automatici resta incollato a sinistra. Misurato a 360 px: la scheda a 8 px dal
   bordo sinistro e 27 dal destro. Sopra sm Bootstrap mette `margin: 1.75rem auto` da se',
   quindi la riga serve solo sotto - ma vale a ogni larghezza, che e' piu' semplice da
   leggere di una media query per un margine. */
.modal-dialog:not(.modal-lg):not(.modal-xl):not(.modal-normal) {
  max-width: 325px; margin-inline: auto;
}
.modal-90 { --bs-modal-width: 90%; }
.modal-header .btn-close-white { filter: brightness(0) invert(1) !important; }

/* ---------- Parte 8.11 - toast ----------
   Bootstrap non da' uno z-index al toast fuori dal .toast-container: senza questo il
   toast finisce sotto la barra di riepilogo, che e' sticky a 1020 e fissa sul telefono.
   La posizione verticale la da' questa regola e non la utility .bottom-0: quella porta
   !important e non si vince per specificita'. La classe .mb-summary la mette showToast
   quando nella pagina c'e' una barra di riepilogo, che sul telefono e' fissa in basso. */
.toast { border-radius: var(--rg-radius-pill); }
/* Con un raggio da pillola il testo va rientrato, altrimenti tocca la curva. */
.toast .toast-body { padding-inline: 1.25rem; }
.toast.position-fixed { z-index: 1090; bottom: 0; }
.toast.position-fixed.mb-summary { bottom: 7rem; }
@media (max-width: 991.98px) { .toast.position-fixed.mb-summary { bottom: 10rem; } }

/* ---------- Parte 8.12 - accordion come riga di gruppo ---------- */
.accordion-tpp .accordion-button::after { content: none !important; }
.accordion-tpp .accordion-button { box-shadow: none !important; }

/* ---------- Parte 8.12b - l'albero a SCHEDE ANNIDATE ----------
   Un prospetto ad albero a nove colonne e tre livelli non entra in 360 px, e impilarlo
   con la vista a schede di Parte 10.5 lo distrugge: una scheda per CELLA invece che per
   nodo. La forma giusta e' una scheda per NODO, con il valore e lo scarto in testa e il
   confronto dentro, e i figli dentro il genitore (committente, 2026-09-11).
   Il FILO VERTICALE dice il livello: e' l'unico segno che resta quando le colonne non ci
   sono piu'. I primi due colori sono marchio e accento; dal terzo in giu' vale la rampa
   estesa dei grafici (§3.6), nell'ordine che la rampa dichiara.
   `!important` e le tre dichiarazioni separate: `.border-0` di Bootstrap e'
   `border: 0 !important`, e senza questo il filo non si disegna affatto. */
.liv-brand, .liv-accent, .liv-terzo, .liv-quarto, .liv-quinto {
  border-left-style: solid !important; border-left-width: 4px !important;
}
.liv-brand  { border-left-color: var(--brand-primary) !important; }
.liv-accent { border-left-color: #E68B52 !important; }
.liv-terzo  { border-left-color: #9B7EBD !important; }
.liv-quarto { border-left-color: #4978D8 !important; }
.liv-quinto { border-left-color: #978D71 !important; }
.liv-lbl-brand  { color: var(--brand-primary); }
.liv-lbl-accent { color: #E68B52; }
.liv-lbl-terzo  { color: #9B7EBD; }
.liv-lbl-quarto { color: #4978D8; }
.liv-lbl-quinto { color: #978D71; }
/* La testa della scheda e' premibile e si riconosce: fondo di marchio appena acceso. */
.nodo-testa { background: var(--brand-primary-subtle); }
/* La tabellina del confronto dentro la scheda. Ogni livello di annidamento mangia ~24 px:
   al terzo la tabella veniva TAGLIATA dal bordo della scheda, che ha `overflow-hidden` e
   quindi non la lasciava nemmeno scorrere. Sotto lg le celle si stringono e la tabella
   sta in un contenitore che scorre - un numero da raggiungere e' meglio di un numero
   tagliato, la stessa regola della scala dei netti. */
.tab-conf th, .tab-conf td { padding: .5rem .75rem; }
@media (max-width: 991.98px) {
  .tab-conf th, .tab-conf td { padding: .35rem .5rem; font-size: 13px; }
  .tab-conf th:first-child, .tab-conf td:first-child { white-space: nowrap; }
}

/* ---------- Parte 8.14 - selettore di periodo ---------- */
.drp-selected { display: none !important; }
.drp-calendar th { background: #fff !important; }
@media (min-width: 992px) { #date-range { width: 260px; } }

/* ---------- Parte 3.4 - le rampe di stato sono blocchi in linea ----------
   Il markup di §3.4 mette padding e raggio su uno <span>, che di suo e' `inline`:
   quando l'etichetta va a capo il fondo si spezza fra le due righe e il testo esce
   dalla tinta. Con inline-block il fondo avvolge l'etichetta su quante righe serve.
   Sta qui e non nel markup: se servisse una classe in piu' su ogni badge, la regola
   sarebbe nel posto sbagliato (§1B.10). */
[class*="text-bg-flg-"] { display: inline-block; text-align: center; }

/* ---------- Parte 8.15 - skeleton ---------- */
@media (prefers-reduced-motion: reduce) {
  .placeholder-wave, .placeholder-glow { animation: none !important; mask-image: none !important; }
  .placeholder-wave .placeholder, .placeholder-glow .placeholder { opacity: .35; }
}
/* Il grigio dello skeleton viene da --rg-skeleton, non da currentColor. Non si
   tocca l'opacita': .placeholder di Bootstrap rende al 50% e la regola di
   prefers-reduced-motion qui sopra al 35%, e restano entrambe valide sul token. */
.skel            { display: block; border-radius: var(--rg-radius-input);
                   color: var(--rg-skeleton); }
.skel-line       { height: 12px; margin-bottom: .5rem; }
.skel-line.sm    { height: 10px; }
.skel-line.lg    { height: 16px; }
.skel-badge      { height: 24px; width: 88px; border-radius: var(--rg-radius-pill); }
.skel-avatar     { width: 35px;  height: 35px; border-radius: 50%; }
.skel-avatar.lg  { width: 45px;  height: 45px; }
.skel-btn        { height: 38px; width: 130px; border-radius: var(--rg-radius-input); }
.skel-kpi        { height: 34px; width: 96px; }
[aria-busy="true"] { cursor: progress; }

/* ---------- Parte 8.17 - tracker ---------- */
.tracker-container { max-width: 800px; margin: 0 auto; }
.tracker-step { position: relative; z-index: 1; text-align: center; flex: 1;
  display: flex; flex-direction: column; align-items: center; }
.tracker-step:not(:last-child)::after {
  content: ''; position: absolute; top: 9px; left: calc(50% + 10px);
  width: calc(100% - 20px); height: 3px; background-color: var(--rg-track); z-index: 0;
}
.tracker-step:not(.inactive):not(:last-child)::after { background-color: var(--brand-dark); }
.tracker-step.is-last-active::after { background: linear-gradient(to right, var(--brand-dark) 50%, var(--rg-track) 50%); }
.tracker-step:not(.inactive):has(+ .tracker-step.inactive)::after {
  background: linear-gradient(to right, var(--brand-dark) 50%, var(--rg-track) 50%);
}
.tracker-dot { width: 20px; height: 20px; background-color: var(--brand-dark); border-radius: 50%;
  margin: 0 auto 10px; box-shadow: 0 0 0 4px #fff; position: relative; z-index: 1; }
.tracker-label { color: var(--brand-dark); font-weight: 600; font-size: 14px; white-space: nowrap; }
.tracker-step.inactive .tracker-dot { background-color: var(--rg-track); }
.tracker-step.inactive .tracker-label { color: var(--rg-track-text); }
@media (max-width: 768px) {
  .tracker-label { font-size: 11px; }
  .tracker-dot { width: 16px; height: 16px; }
  .tracker-step:not(:last-child)::after { top: 7px; left: calc(50% + 8px); width: calc(100% - 16px); }
}

/* ---------- Parte 8.18 - accesso ---------- */
/* La schermata di accesso non ha shell: il centraggio verticale se lo fa da se'.
   Grid con place-items e non il solo align-items: .form-signin ha m-auto, ma
   html, body { height: 100% } di Parte 6.1 rende il body di altezza FISSA, e senza
   grid il modulo resta incollato in cima (DL-050: dare un'altezza non centra). */
body.login-page { display: grid; place-items: center; min-height: 100vh; min-height: 100dvh; padding-block: 1.5rem; }
.form-signin { max-width: 1000px; padding: 15px; }
.form-signin .form-floating:focus-within { z-index: 2; }

/* ---------- Parte 8.19 - tooltip ---------- */
.custom-tooltip { --bs-tooltip-bg: var(--brand-primary); z-index: 1200 !important; }

/* ---------- §1B.5.1 - briciola di pane ----------
   Il separatore e' un pseudo-elemento, non un tag: cosi' sotto md basta nascondere gli
   antenati e resta "genitore / corrente", senza che spariscano anche i separatori.
   La prima stesura usava :nth-last-child e a 360 px lasciava solo il nodo corrente,
   cioe' toglieva proprio la via di ritorno che questo componente esiste per dare. */
.breadcrumb-bar { font-size: 14px; }
.breadcrumb-bar .crumb { color: var(--rg-caption); }
.breadcrumb-bar .crumb:hover { color: var(--brand-primary); }
.breadcrumb-bar .crumb + .crumb::before,
.breadcrumb-bar .current::before { content: "/"; color: var(--rg-label); margin: 0 .5rem; }
.breadcrumb-bar .current { color: var(--rg-text-strong); font-weight: 500; }
@media (max-width: 767.98px) {
  .breadcrumb-bar .crumb:not(:last-of-type) { display: none; }
  .breadcrumb-bar .crumb:last-of-type::before { content: none; }
}

/* ---------- §1B.5.2 - typeahead ---------- */
.typeahead { position: relative; }
.typeahead-results {
  position: absolute; z-index: 1050; width: 100%; margin-top: .25rem;
  max-height: 340px; overflow-y: auto;
  background: var(--rg-surface); border-radius: var(--rg-radius-card);
  box-shadow: var(--rg-shadow-md);
}
.typeahead-results .list-group-item { border: 0; border-bottom: 1px solid var(--rg-border); padding: 10px 12px; }
.typeahead-results .list-group-item:last-child { border-bottom: 0; }
.typeahead-results .list-group-item.active,
@media (hover: hover) {
  .typeahead-results .list-group-item:hover { background: var(--brand-primary-subtle); color: var(--rg-text); }
  .typeahead-results .list-group-item.active .subtitle,
  .typeahead-results .list-group-item:hover .subtitle { color: var(--rg-label); }
}
.typeahead-results .ta-state { padding: 12px; color: var(--rg-label); font-size: 14px; }
@media (max-width: 767.98px) {
  .typeahead.ta-open .typeahead-results {
    position: fixed; inset: 0; width: 100%; max-height: none; margin: 0;
    border-radius: 0; overflow-y: auto; z-index: 1060;
    padding-top: env(safe-area-inset-top);
  }
  .typeahead.ta-open .typeahead-sheet-head { display: flex !important; }
}
.typeahead-sheet-head { display: none; position: sticky; top: 0; z-index: 1;
  background: var(--rg-surface); border-bottom: 1px solid var(--rg-border); padding: .5rem; gap: .5rem; }

/* ---------- §1B.5.3 - stepper di quantita' ---------- */
/* Non va a capo: meno, valore e piu' sono un comando unico, e spezzarlo su due
   righe lo rende illeggibile. Sotto lg i pulsanti crescono a 44px per §10.1.3 e in
   una colonna di tabella non ci stanno piu': allora e' la tabella che scorre dentro
   .table-responsive (§8.4), che e' il ripiego previsto. Trovato a 800 px, la banda
   fra md e lg dove la tabella e' ancora tabella (§10.5) ma i bersagli sono gia'
   quelli del tocco (§10.1.3). */
/* nowrap da solo non basta: senza flex-shrink 0 sono i figli a cedere, e il valore
   si schiaccia a larghezza zero fra i due pulsanti. */
/* LA MISURA: sotto lg lo stepper occupa almeno 128 px - 44 + 40 + 44 - e i suoi figli
   non cedono. Una colonna piu' stretta non lo stringe: lo fa DEBORDARE sul vicino, in
   silenzio, perche' i figli escono dalla scatola del gruppo. Misurato a 360 px sul
   carrello: colonna da 107 px, e il pulsante «+» copriva 19 px del pulsante
   «Aggiungi». Chi compone una riga con uno stepper gli da' 128 px o lo mette da solo
   su una riga; il foglio non puo' rimediare a una colonna troppo stretta. */
.stepper { flex-wrap: nowrap; }
/* Compatto: la quantita' di riga e' una o due cifre, un campo da 64px la faceva
   sembrare un campo di testo. I pulsanti restano bersagli, non diventano francobolli. */
.stepper .form-control { max-width: 48px; min-width: 36px; flex-shrink: 0; }
.stepper .btn { min-width: 30px; flex-shrink: 0; }
@media (max-width: 991.98px) {
  /* 44px e' il pavimento del tocco di §10.1.3 e non si scende: si stringe il campo,
     che di bersaglio non ha bisogno. */
  .stepper .btn { min-width: 44px; min-height: 44px; }
  /* Il totale che apre la propria derivazione E' un bersaglio: sotto lg misura 44 px come
     tutti gli altri. Misurato sul mockup del carrello a 360 px: era alto 18.
     inline-flex e non il solo min-height, perche' dare un'altezza non centra (DL-050).
     NIENTE `justify-content: flex-end` qui: la scriveva questa riga per il totale del
     carrello, che sta in una cella allineata a destra, e la pagava ogni ALTRA disclosure
     della piattaforma. Su Storico Documenti le due intestazioni dell'albero - «Fatture» e
     «Documenti di trasporto» - sono figlie dirette della scheda, che e' un contenitore
     flex: si allargavano a 320 px e il loro contenuto finiva spinto al bordo destro,
     con il chevron staccato dal testo. L'allineamento a destra e' del CONTESTO, non del
     componente: lo dichiara la cella che lo contiene. */
  .disclosure { display: inline-flex; align-items: center; min-height: 44px; }
  td.text-end .disclosure, th.text-end .disclosure { justify-content: flex-end; }
  /* L'azione primaria della schermata: 44 px anche lei. Misurato: `py-2` su un .btn
     dava 42, cioe' due px sotto la soglia, sull'unico controllo che completa il task. */
  .summary-action .btn { min-height: 44px; }
  /* Parte 10.3a alla lettera: sotto lg OGNI comando misura 44 px, non solo quelli per
     cui mi sono ricordato di scrivere una riga. Misurato prima di questa regola:
     `Aggiungi` 42 px sul carrello e `Cerca` 38 px sulla home - due bersagli sotto
     soglia trovati contandoli, non guardandoli.
     I campi crescono insieme ai pulsanti: dentro un input-group un campo da 38 accanto
     a un pulsante da 44 si disallinea. E 16px di corpo perche' sotto quella misura
     iOS ingrandisce la pagina al fuoco. */
  /* Non piu' scopata a `.app-main` e ai modali: §10.1.3 dice «ogni bersaglio sotto lg»,
     senza eccezioni, e una schermata che non ha la regione `.app-main` - la pagina di
     accesso, la galleria dei componenti - restava fuori. Misurato sulla galleria: un
     campo a 38 px e due pulsanti a 42. Le barre della shell hanno gia' la propria
     regola, e questa non le peggiora: chiede lo stesso minimo. */
  .btn { min-height: 44px; }
  /* Anche le VOCI: una scheda di Area Personale e una pillola di filtro sono bersagli
     come un pulsante. Misurate a 360 px: le cinque schede di Area Personale a 37 px,
     cioe' sette sotto la soglia, su una schermata gia' consegnata. La soglia vale per
     i componenti del kit, non per i controlli legacy senza classe che vivono ancora
     dentro le viste: quelli li prende il brief della propria schermata. */
  .app-main .nav-link { min-height: 44px; display: inline-flex; align-items: center; }
  .form-control, .form-select { min-height: 44px; font-size: 16px; }
  .stepper .form-control { max-width: 44px; min-width: 40px; font-size: 16px; }
}

/* ---------- §1B.5.4 - riga di dettaglio espandibile ---------- */
.disclosure { text-decoration: none; color: var(--rg-text-strong); font-weight: 700; }
.disclosure .fi, .disclosure .fa-solid { transition: transform .15s ease; }
.disclosure[aria-expanded="true"] .fi,
.disclosure[aria-expanded="true"] .fa-solid { transform: rotate(180deg); }
tr.detail-row > td { background: var(--rg-surface-sunken); }
/* Una .row dentro un td non usa i margini negativi delle gutter: li compensa il
   padding del contenitore di griglia, e un td non ce l'ha. Senza questo il dettaglio
   sporge di 12px per lato dalla tabella e il contenitore prende una barra
   orizzontale che non gli serve. */
tr.detail-row > td > .row { margin-inline: 0; }
tr.flt-data + tr.detail-row.show > td { border-top: 0; }
@media (prefers-reduced-motion: reduce) {
  .disclosure .fi, .disclosure .fa-solid { transition: none; }
}

/* ---------- §1B.5.5 - intestazione di gruppo sticky ---------- */
tr.group-row th {
  position: sticky; /*top: 38px;*/ z-index: 1;
  background: var(--rg-surface-sunken) !important;
  color: var(--rg-label) !important; font-weight: 500 !important;
  border-bottom: 1px solid var(--rg-border-strong);
}
@media (max-width: 1024px) {
  /* Nella vista a schede l'intestazione di gruppo e' UNA PILLOLA a piena larghezza, con
     aria sopra. Tre cose insieme, ognuna per il proprio motivo.
     La PILLOLA: raggio e taglio stanno sul `tr`, non sui `th`. La fascia del pacchetto
     ha DUE celle - il nome e le sue due azioni - e con il raggio sui `th` diventavano
     due pillole impilate invece di una fascia sola; il `tr` diventa flex, i `th` la
     riempiono in fila.
     La LARGHEZZA: `.table-dashboard` porta 12px di padding orizzontale, e nella vista a
     schede quei 12px rientrano fascia e schede rispetto a tutto il resto del contenuto
     della scheda di pagina. Misurato a 360 px: il pannello di inserimento cominciava a
     44 px e la fascia a 56. La tabella impilata non e' piu' una tabella: quel padding
     serviva alle sue colonne, non alle schede.
     L'ARIA: prima la fascia aveva 12px sopra - il margine dell'ultima scheda del gruppo
     che chiude - e 8 sotto. Una fascia che separa due gruppi ha bisogno di piu' spazio
     sopra che sotto, altrimenti si legge come la coda del gruppo precedente invece che
     come la testa di quello nuovo. */
  .table-stack { padding-inline: 0; }
  .table-stack tr.group-row {
    display: flex; flex-wrap: nowrap; align-items: center;
    background: transparent; padding: 0; overflow: hidden;
    border-radius: var(--rg-radius-pill); margin: 1.25rem 0 .5rem;
  }
  /* La prima fascia apre la tabella: sopra ha gia' lo spazio della griglia di pagina. */
  .table-stack tbody > tr.group-row:first-child { margin-top: 0; }
  .table-stack tr.group-row th {
    display: block; width: auto; position: static; border-radius: 0; border-bottom: 0;
    /* `!important` perche' `.table-dashboard th` impone 10px con !important. */
    padding: .7rem 1rem !important;
  }
  .table-stack tr.group-row > th:first-child { flex: 1 1 auto; min-width: 0; }
  .table-stack tr.group-row > th + th { flex: 0 0 auto; }
  /* Etichetta di dominio sopra, nome della sede sotto. Su una riga sola le due vanno a
     capo insieme e la rottura cade DENTRO il nome: «CER / COSTAMAGNA», misurato a
     360 px. Su due righe la rottura cade dove c'e' un confine di significato. */
  .table-stack tr.group-row .group-label,
  .table-stack tr.group-row .group-name { display: block; margin-left: 0; }
}

.col-qty .btn{ min-height: 42px; }
@media (max-width: 575.98px) {
  /* Lo stepper e la propria azione stanno su UNA riga anche a 360 px: la colonna della
     quantita' vale 152 px (i 128 dello stepper piu' i 24 di gutter) e quella dell'azione
     prende il resto - 168, cioe' 144 di pulsante. Con il contenuto a 320 px lo spazio
     c'e'; a 272 non c'era, ed era il motivo per cui erano su due righe. */
  .col-qty { flex: 0 0 auto !important; width: 144px !important; }
  /* `min-width: 0` non e' cosmetico: la rottura di riga di un contenitore flex si
     calcola sulla misura MIN-CONTENT dell'elemento, non sulla sua flex-basis. Senza,
     il pulsante dell'azione dichiarava 163 px di min-content, 144 + 163 sforava i 304
     della fascia e la riga si spezzava - i due comandi tornavano su due righe pur
     avendo lo spazio. Con 0 la riga non si spezza mai e il pulsante si stringe. */
  .col-qty + .col-act { flex: 1 1 0 !important; width: auto !important; min-width: 0 !important; }
  /* Sotto sm la fascia del pacchetto va su DUE righe: nome e dettaglio a larghezza piena,
     le sue azioni sotto, a destra. Con le azioni accanto restavano 112 px di testo al nome
     e il dettaglio andava a capo quattro volte - misurato a 360 px: fascia alta 133 px per
     due righe di contenuto. Sopra sm lo spazio c'e' e le due celle restano in fila. */
  .table-stack tr.group-row { flex-wrap: wrap; }
  .table-stack tr.group-row > th:first-child { flex: 1 1 100%; }
  .table-stack tr.group-row > th + th { flex: 1 1 100%; padding-top: 0 !important; }
}
/* DUE VARIANTI di tinta, non due componenti: l'intestazione di gruppo resta quella, e
   cambia solo che cosa raggruppa. Serve perche' il carrello ha due tipi di gruppo che
   l'utente deve distinguere a colpo d'occhio - il magazzino da cui la merce parte, e il
   pacchetto promozionale, che e' un oggetto commerciale diverso da una spedizione.
   `!important` per stare al livello della regola sopra, che ce l'ha per battere
   .table-dashboard di Bootstrap. */
/* Il nome della sede accanto alla propria etichetta. Il margine sta qui e non su un
   `ms-2` nel markup, perche' nella vista a schede va azzerato: contro l'`!important`
   di un'utility di Bootstrap non si vince, e non e' quello il posto per litigare. */
tr.group-row .group-name { margin-left: .5rem; }
tr.group-row.group-prl th {
  background: var(--brand-primary-subtle) !important;
  color: var(--brand-primary) !important;
  border-bottom: 2px solid var(--brand-primary);
}

tr.group-row.group-prz {background: var(--rg-save) !important;}

tr.group-row.group-prz th {
  background: var(--rg-save) !important;
  border-bottom: 0;
  color: var(--bs-table-color-state) !important;
}
/* Il pulsante d'azione di riga: quadrato, bordato, con la sola icona. E' la forma di
   Parte 3.3 per un'azione di riga, con il bersaglio a 44 px sotto lg come tutto il
   resto (Parte 10.3a). Sulla fascia di marchio del pacchetto il bordo e l'icona
   diventano bianchi, altrimenti spariscono nel fondo.
   REGOLA GRAFICA DEL B2B (committente, 2026-09-11): questa e' la forma di OGNI azione
   di riga del sito - carrello, resi, ricerca, e quelle che verranno. Non ce n'e' una
   tonda in una schermata e una quadrata in un'altra, e non c'e' l'icona nuda senza
   scatola: una cosa che si puo' premere si vede che si puo' premere, e la si riconosce
   perche' ha sempre lo stesso aspetto (DL-121). */
.btn-icon-row { width: 34px; height: 34px; padding: 0; display: inline-flex;
  align-items: center; justify-content: center; }
tr.group-row.group-prz .btn-icon-row {
  border-color: #444444 !important; color: #444444 !important; background: transparent; }
@media (max-width: 991.98px) {
  .btn-icon-row { width: 44px; height: 44px; }
}

/* ---------- §1B.5.6 - barra di riepilogo sticky ---------- */
/* Nessun fondo sulla barra: la sfumatura serviva a far sfumare il contenuto che le
   scorre dietro, e il committente l'ha tolta. Quello che resta e' una scheda che
   GALLEGGIA sul contenuto, e l'ombra sotto e' cio' che lo dichiara. Conseguenza
   dichiarata: sotto lg, dove la barra e' fissa, le righe si vedono passare nei margini
   attorno alla scheda invece di sfumare. */
.summary-bar { position: sticky; bottom: 0; z-index: 1020; }
/* Ombra dichiarata dal committente, uguale su mobile e desktop: due strati bassi e
   morbidi al posto di --rg-shadow-md. E' l'unica ombra fuori dai token del progetto,
   e sta qui - non in tokens.css - perche' e' della forma di QUESTO componente, non
   della piattaforma. */
.summary-bar .card {
  box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
}
/* I totali: ogni cella e' una colonna spinta in basso, cosi' le etichette si
   allineano fra loro qualunque sia la dimensione del valore che sta sopra. La riga
   deve restare a altezze uguali: nessuna utility di allineamento verticale su di
   essa, ci pensa .summary-row. */
.summary-row     { align-items: stretch; }
/* Nessun height: 100% qui. L'altezza della riga la determinano i figli, quindi una
   percentuale non risolve, viene trattata come auto e ANNULLA lo stretch: le celle
   tornano alte quanto il proprio contenuto e le etichette si disallineano. Lo
   stretch dei flex item basta da solo. */
.summary-total   { display: flex; flex-direction: column; justify-content: flex-end; }
/* Un totale non va mai a capo: spezzato in «700,5» e «0» non e' piu' una cifra.
   Da qui il nowrap, e la dimensione del primario che scala con la larghezza invece
   di essere fissa &mdash; a 360 px in una colonna da un terzo, 32px non ci stavano. */
.summary-value   { font-size: 20px; font-weight: 500; line-height: 1.15;
                   white-space: nowrap; color: var(--rg-text-strong); }
.summary-total.primary .summary-value { font-size: clamp(24px, 6.5vw, 32px);
                   font-weight: 700; color: var(--rg-text-black); }
.summary-label   { font-size: 13px; color: var(--rg-caption); margin-top: .25rem;
                   line-height: 1.2; }
/* A 360 px «Totale Imponibile» e «Totale Documento» non stanno in un terzo di riga a
   13 px e vanno a capo in mezzo alla frase: due etichette su due righe e una su una,
   cioe' tre colonne che non si leggono insieme. A 11px stanno su una riga sola.
   `align-items: end` sulla riga tiene i tre valori allineati sotto, qualunque sia
   l'altezza di quello grande. */
@media (max-width: 575.98px) {
  .summary-label { font-size: 11px; }
  .summary-row   { align-items: flex-end; }
}
.summary-action  { display: flex; flex-direction: column; justify-content: flex-end; }
@media (min-width: 768px) {
  /*.summary-total.primary .summary-value { font-size: 40px; }*/
}
/* §1B.5.6: la barra non si sovrappone mai all'ultima riga.
   Su desktop non serve riservare nulla: sticky e ultima nel flusso, la barra occupa
   il proprio spazio e al fondo dello scorrimento il contenuto le sta sopra
   (verificato: 950 contro 982). Sotto lg diventa fixed, non occupa flusso, e lo
   spazio va riservato.
   Si riserva con ::after e non con padding-bottom: la regione che porta la barra
   porta quasi sempre anche una utility di spaziatura (py-3, p-4), le utility
   Bootstrap sono !important e vincono su qualunque padding dichiarato qui, senza
   errore e senza sintomo. Uno pseudo-elemento nessuna utility lo raggiunge, e alla
   schermata successiva basta la classe che esiste gia'. */
/* Lo spazio si riserva a OGNI larghezza, non solo sotto lg. `bottom: 0` su un elemento
   sticky lo fa salire fino al fondo del viewport finche' il suo contenitore e' in vista:
   su una pagina piu' corta del viewport la barra finisce SOPRA le ultime righe della
   tabella. Misurato sul mockup del carrello a 1440x900: la fascia del pacchetto
   promozionale e le sue due righe erano coperte. L'altezza sopra lg e' minore perche'
   sopra lg la barra sta su una riga sola. */
/* NIENTE spazio riservato sopra lg. La barra e' `sticky`: sta nel flusso dopo il
   contenuto, e al fondo dello scorrimento e' alla propria posizione, senza coprire
   nulla. Uno spazio in coda alla regione sarebbe spazio morto, e si vedeva.
   Sotto lg invece la barra e' `fissa`: copre 190px di viewport per sempre, quindi lo
   spazio va riservato - e va riservato in fondo al DOCUMENTO, non in fondo alla
   regione del contenuto, altrimenti chi finisce sotto la barra e' il PIEDE. Misurato:
   il piede della shell finiva dietro la barra dei totali.
   La classe sta sul `body`, cosi' il padding somma dopo l'ultima fascia. */
@media (max-width: 991.98px) {
  .summary-bar { position: fixed; left: 0; right: 0; bottom: 0;
    padding-bottom: calc(.75rem + env(safe-area-inset-bottom)); }
  /* Lo spazio si aggiunge all'ULTIMO FIGLIO, non al body. `html, body { height: 100% }`
     di Parte 6.1 da' al body un'altezza FISSA, e il contenuto la sfonda: un
     `padding-bottom` sul body resta dentro quella scatola e non compare in coda al
     documento. Misurato: il piede finiva ancora per 153 px sotto la barra.
     L'ultimo figlio e' il piede della shell; il ripiego sul body serve alle pagine che
     non hanno piede (modo `embedded`). */
  /* Il PADDING del piede, non un margine e non il padding del body. Le ragioni, tutte
     misurate:
      - sul `body` non funziona: `html, body { height: 100% }` di Parte 6.1 gli da'
        un'altezza FISSA e il contenuto la sfonda, quindi il padding resta dentro la
        scatola e non compare in coda al documento;
      - come `margin-bottom` sul piede non funziona: il margine dell'ultimo figlio NON
        entra nell'overflow scorribile del contenitore. Misurato: l'altezza scorribile
        restava 3821 con e senza;
      - il padding del piede si': cresce l'altezza di una scatola in flusso, e quella
        entra nell'overflow.
     Il `pb-3` di Bootstrap e' stato tolto dal markup della shell perche' con un
     `!important` addosso questa riga non avrebbe avuto effetto (DL-012). */
  body.has-summary-bar > .app-foot { padding-bottom: calc(190px + env(safe-area-inset-bottom)); }
  body.has-summary-bar:not(:has(> .app-foot)) .app-main { padding-bottom: 190px; }
}

/* ---------- §1B.5.7 - barra di selezione multipla ---------- */
.bulk-bar { display: none; }
.bulk-bar.show { display: block; }
.bulk-bar .card { background: var(--brand-primary-subtle); border: 1px solid var(--brand-primary) !important; }
.bulk-bar .bulk-count { font-weight: 600; color: var(--rg-text-strong); }

/* ---------- §1B.5.8 - stato salvato inline ---------- */
@keyframes saved-tint {
  0%   { box-shadow: inset 0 0 0 2px var(--rg-success); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}
.is-saved { animation: saved-tint 1.5s ease-out 1; }
.saved-mark { color: var(--rg-success); }
@media (prefers-reduced-motion: reduce) {
  .is-saved { animation: none; box-shadow: inset 0 0 0 2px var(--rg-success); }
}

/* ---------- Parte 8.20 - il PACCHETTO PROMOZIONALE ----------
   Cinque classi che il PHP e il JS del pacchetto assegnano da sempre - `checked`,
   `error`, `errorCnf`, `scoprz`, `important` - e che in tutto il repository non avevano
   NESSUNA regola: misurato il 2026-09-15 con una ricerca su tutti i fogli. Quindi
   l'evidenziazione delle righe scelte (censita come PROMO-006) non si vedeva, e un
   campo in errore era identico a uno corretto. Qui prendono la forma del kit. */
/* La LOCANDINA della promozione: prende TUTTA la testa della scheda (committente,
   2026-09-16). Aveva una proporzione fissa di 20/9 con `contain`, per tenere allineata
   la griglia: ma le locandine sono banner larghi e bassi, piu' larghi di 20/9, e dentro
   quella scatola restavano due bande vuote sopra e sotto. Ora l'immagine e' larga quanto
   la scheda e alta quanto le serve; le schede della riga restano pari perche' la riga di
   Bootstrap le stira, e cio' che cambia e' lo spazio sotto il testo, non l'immagine.
   Niente `cover`: una locandina porta del TESTO, e ritagliarla lo taglia. */
.promo-img { display: block; width: 100%; height: auto; background: #fff; }
/* La riga SCELTA. Il legacy la voleva verde; il verde del kit e' lo stato «completato»
   e qui non c'e' niente di completato: una riga scelta e' una riga SELEZIONATA, e la
   selezione nel kit e' la tinta tenue del marchio (come la riga di tabella scelta di
   Parte 8.2). */
tr.checked > td { background: var(--brand-primary-subtle) !important; }
/* La riga da cui si e' arrivati, quando si apre il pacchetto da un articolo: un filo
   sul bordo d'attacco, non un fondo - il fondo se lo gioca gia' la selezione. */
tr.fromsearch > td:first-child { box-shadow: inset 3px 0 0 var(--brand-primary); }
/* I due errori di quantita'. `error` e' «non disponibile» o «fuori intervallo»,
   `errorCnf` e' «non multipla della confezione»: la forma e' la stessa, perche' per chi
   guarda sono la stessa cosa - questo numero va cambiato. */
.qta.error, .qta.errorCnf {
  border-color: var(--rg-danger) !important;
  box-shadow: inset 0 0 0 1px var(--rg-danger);
}
/* Il RAGGRUPPAMENTO in errore: il vincolo non e' della riga, e' dell'insieme. Il segno
   sta sul gruppo, con la stessa grammatica del filo di livello di Parte 8.12b. */
tbody.rgrart.error > tr > td:first-child,
tbody.rgrtds.error > tr > td:first-child { box-shadow: inset 3px 0 0 var(--rg-danger); }
/* Il prezzo che la promozione ha CAMBIATO rispetto al listino del cliente. */
.scoprz { color: var(--rg-success); font-weight: 700; }
/* Dentro il messaggio di validazione, la parte che nomina l'articolo o il numero. */
#detCanvasMsg .important { font-weight: 700; }
/* LA CASELLA DI SCELTA e' quella che il B2B usa gia' per selezionare una riga
   (`.bulk-select`, §1B.5.4): tonda, 20 px, tinta di marchio quando e' scelta. Era la
   casella quadrata di serie di Bootstrap, 16 px, diversa da quella di ogni altra
   schermata (committente, 2026-09-16).
   Il selettore porta DUE classi e il nome dell'elemento perche' Bootstrap dichiara il
   raggio con `.form-check-input[type=checkbox]`, che pesa piu' di una classe sola: con
   `.cbPrz` e basta la larghezza passava e il raggio no - la casella restava quadrata a
   20 px. Misurato in pagina. */
input.form-check-input.cbPrz {
  width: 20px; height: 20px; margin-top: 0; border-radius: 50%;
  border: 2px solid var(--rg-border-strong); background-color: var(--rg-surface);
  transition: background-color .15s ease-in-out, border-color .15s ease-in-out;
}
@media (hover: hover) { input.form-check-input.cbPrz:not(:disabled):hover { border-color: var(--brand-primary); } }
input.form-check-input.cbPrz:checked { background-color: var(--brand-primary); border-color: var(--brand-primary); }
/* La CASELLA nella vista a schede. Una casella di 20 px in cima a una scheda e' sotto
   qualunque soglia praticabile su tocco (Parte 10.3a chiede 44): si ingrandisce a 24 e
   le si da' un'area premibile attorno. Il selettore ripete le due classi e il nome
   dell'elemento perche' altrimenti perde contro la regola qui sopra, che ne ha tre.
   Misurato a 360 px: la casella restava a 20. */
@media (max-width: 1024px) {
  .table-stack input.form-check-input.cbPrz { width: 24px; height: 24px; margin: 10px; }
}

/* LA RIGA CHE NON SI PUO' CAMBIARE. Erano identiche alle altre: una riga sempre inclusa
   nel pacchetto e una riga non disponibile avevano lo stesso aspetto di una che si puo'
   scegliere, e la casella spenta - 20 px - era l'unico segno (committente, 2026-09-16).
   Ora la riga e' infossata e la ragione la porta un gettone accanto al codice: il colore
   non e' l'unico portatore dell'informazione (§11). */
tr.bloccata > td { background: var(--rg-surface-sunken); }
tr.bloccata .cbPrz { opacity: .55; }
/* Una riga bloccata non e' un bersaglio: il puntatore non deve prometterlo. */
tr.bloccata { cursor: default !important; }
/* Le righe che si possono scegliere: la riga INTERA e' il bersaglio della casella
   (committente, 2026-09-16), quindi lo dice il puntatore. */
@media (hover: hover) {
  #detCanvas tbody tr:not(.bloccata):not(.group-row) { cursor: pointer; }
}
/* LE COLONNE DEL PACCHETTO. Senza larghezze dichiarate il browser dava 458 px alla
   quantita' - che contiene uno stepper largo 132 - e 363 all'articolo, che porta codice,
   codice EAN e descrizione. Misurato a 1440 px. */
@media (min-width: 1025px) {
  table.canvas th.col-scelta { width: 52px; }
  table.canvas th.col-imp    { width: 132px; }
  table.canvas th.col-qta    { width: 210px; }
  table.canvas th.col-dsp    { width: 150px; }
}

/* ---------- Parte 8.21 - la SCHEDA DI UNA NOVITA' ----------
   Data, marchio e testo, tutto a vista. Nessuna apertura: il contenuto di una novita'
   sono due righe, e nasconderle dietro un clic costava un gesto per leggerne due
   (committente, 2026-09-16).
   Tre forme prima di questa: la cella di tabella con l'onclick nell'attributo, le schede
   a due colonne che si aprivano - e aprirne una gonfiava la vicina, DL-170 - e l'elenco
   a una colonna a scomparsa.
   La scheda e' BORDATA e non ombreggiata perche' sta dentro la scheda bianca di
   schermata, dove bianco su bianco non si stacca: e' la stessa scelta di Parte 8.22. */
.nws-card { background: #fff; }
/* Il testo di una novita' e' prosa: interlinea di lettura, non quella di una tabella. */
.nws-testo { line-height: 1.6; }
/* Il collegamento «Clicca qui» che il PHP inserisce nel testo: non e' un pulsante, e'
   un collegamento dentro una frase, e si vede che lo e'. */
.nws-testo a { color: var(--brand-primary); text-decoration: none; }

/* ---------- Parte 8.29 - l'elenco I MIEI CLIENTI ----------
   Vive dentro un modale e puo' portare migliaia di righe: senza un tetto il dialogo cresce
   oltre lo schermo e i due campi di ricerca escono dalla vista proprio mentre si cerca.
   L'ALTEZZA E' FISSA, non massima (committente, 2026-09-17): con un tetto il dialogo nasce
   basso mentre l'elenco si carica e si allunga di colpo quando arriva - il pulsante di
   chiusura si sposta sotto il dito di chi stava per premerlo. Con un'altezza dichiarata la
   finestra e' la stessa prima e dopo, e cambia solo cio' che ci sta dentro.
   LA RIGA DEL CLIENTE NON ATTIVO. Il legacy la dipingeva di `background-color: red;
   color: white` nell'attributo: un rosso pieno di sistema operativo, su cui il bianco e'
   al limite del leggibile. Il committente la rivuole rossa (2026-09-17): rossa e', ma con
   la tinta tenue del kit e il testo scuro sopra - lo stesso rapporto della pastiglia di
   stato - e con la parola accanto, perche' il colore da solo non arriva a chi non lo
   distingue.
   E il puntatore non deve promettere un clic che non c'e': `style.css` lo mette su OGNI
   `.tr_age_cli`, comprese quelle che non si possono scegliere. Si spegne da qui - tre
   classi contro due - invece di toccare il foglio legacy (DL-088). */
.age-cli-lista { height: 55vh; overflow-y: auto; }
@media (min-width: 992px) { .age-cli-lista { height: 60vh; } }
tr.tr_age_cli.non-attivo > td { background: var(--rg-flg-3-bg); color: var(--rg-flg-3-fg); }
tr.tr_age_cli.non-attivo { cursor: default; }
@media (max-width: 1024px) {
  /* Nella vista a schede la riga E' la scheda, e il fondo lo porta lei: dipingendo le sole
     celle restava una cornice bianca attorno al rosso. */
  .table-stack tr.tr_age_cli.non-attivo { background: var(--rg-flg-3-bg); border-color: var(--rg-flg-3-fg); }
}
@media (min-width: 1025px) { .age-cli-lista th.col-cod { width: 120px; } }

/* ---------- Parte 8.28b - i DATI DI UNA SEDE ----------
   Etichetta a sinistra e valore a destra, incolonnati. Era un `<p>` con sei `<br>`, dove
   "Tel" e "Fax" stavano sulla stessa riga separati da due spazi insecabili: si leggeva
   come una frase, e i recapiti non sono una frase.
   Sotto sm l'etichetta va sopra il valore: a 360 px due colonne lasciano al valore meno
   di duecento pixel, e un indirizzo di posta ci va a capo in mezzo. */
.sede-dati { display: grid; grid-template-columns: auto 1fr; column-gap: 1.25rem; row-gap: .4rem; }
.sede-dati dt { color: var(--rg-label); font-weight: 500; font-size: 13px; }
.sede-dati dd { margin: 0; }
@media (max-width: 575.98px) {
  .sede-dati { grid-template-columns: 1fr; row-gap: 0; }
  .sede-dati dd { margin-bottom: .6rem; }
}

/* ---------- Parte 8.28 - la MAPPA DI UNA SEDE ----------
   Un riquadro che si adatta alla colonna invece dei 600x450 fissi dell'embed: due mappe
   affiancate dentro la scheda di schermata misurano ~660 px a 1440, e una sola a 360 ne
   misura 328. La proporzione tiene la forma; il minimo in altezza impedisce che a 360 la
   mappa si riduca a una striscia da 205 px, dove non si riconosce piu' una via.
   `border: 0` sta qui e non nell'attributo `style` dell'embed. */
.mappa-sede {
  display: block; width: 100%; border: 0;
  aspect-ratio: 16 / 10; min-height: 240px;
}
@supports not (aspect-ratio: 1) { .mappa-sede { height: 320px; } }

/* ---------- Parte 8.27 - l'ELENCO COMPARATIVO DENTRO KSTORE ----------
   La tabella vive in una finestra modale dell'applicativo di Solera: larga e BASSA, con
   la barra di scorrimento della finestra. Per questo la schermata non porta cromatura -
   niente briciola, niente titolo - e la tabella comincia subito.
   La riga il cui codice non e' a catalogo resta una riga, perche' il codice cercato va
   visto, ma e' attenuata: non porta dati e non porta comandi. */
.kst-tb tr.non-trovato > td { background: var(--rg-surface-sunken); }
@media (min-width: 1025px) {
  .kst-tb th.col-imp    { width: 130px; }
  .kst-tb th.col-sco    { width: 140px; }
  .kst-tb th.col-dsp    { width: 190px; }
  .kst-tb th.col-qta    { width: 140px; }
  .kst-tb th.col-azioni { width: 320px; }
}

/* ---------- Parte 8.26 - il DOCUMENTO D'ORDINE ----------
   Il logo si stampa e basta: sullo schermo il marchio sta gia' nella barra della shell,
   e un secondo logo dentro il contenuto e' la stessa cosa detta due volte; sul foglio la
   shell non c'e'. La regola sta QUI e non in una utility `d-print-*`: una classe che non
   esiste non applica nulla, e quella non e' garantita in ogni build di Bootstrap
   (DL-142, DL-155). */
.ord-logo { display: none; max-height: 56px; width: auto; }
/* Piu' documenti nella stessa richiesta - `showorder.php` esplode `doc` su `|` - e ognuno
   comincia su un foglio nuovo. */
.ord-doc + .ord-doc { margin-top: 2rem; }
@media (min-width: 1025px) {
  .ord-tb th.col-qta { width: 110px; }
  .ord-tb th.col-imp { width: 120px; }
  .ord-tb th.col-sco { width: 90px; }
  .ord-tb th.col-dsp { width: 150px; }
}
@media print {
  .ord-logo { display: block; }
  .ord-comandi { display: none !important; }
  .ord-doc + .ord-doc { page-break-before: always; }
  /* Una riga del documento non si spezza a meta' fra due fogli. */
  .ord-tb tr { page-break-inside: avoid; }
}

/* ---------- Parte 8.25 - l'ELENCO DEI DOCUMENTI ----------
   Quattro colonne: il tipo e' un gettone, il numero il dato che si cerca, la data lunga,
   e i formati di scarico in coda. Le tre colonne strette hanno una larghezza dichiarata,
   cosi' i comandi restano incolonnati e la descrizione del tipo - che e' la piu' lunga e
   la piu' variabile - prende quel che resta. */
@media (min-width: 1025px) {
  #tabDoc th.col-num  { width: 120px; }
  #tabDoc th.col-data { width: 200px; }
  #tabDoc th.col-dwl  { width: 420px; }
}

@media (max-width: 1025px) {
  #tabDoc th.col-num  { width: 120px; }
  #tabDoc th.col-data { width: 200px; }
  #tabDoc th.col-dwl  { width: 420px; }
}

/* ---------- Parte 8.24 - il PANNELLO DI UN MARCHIO (modale dei Prodotti) ----------
   Logo e nome in testa, una sezione per immagine, e i file in righe separate da un filo
   con i due comandi a destra. Era una `<table class="testo">` con il markup sbilanciato
   e i comandi come collegamenti nudi. */
.prd-logo { max-height: 56px; max-width: 220px; width: auto; height: auto; }
/* L'immagine di sezione: larga quanto il modale ma mai piu' alta di meta' schermo, o
   il comando che le sta sotto finisce fuori dalla finestra e nessuno lo trova. */
.prd-img { max-width: 100%; max-height: 50vh; width: auto; height: auto;
  border-radius: var(--rg-radius-input); }
/* Il filo sotto l'etichetta di categoria, e fra un file e l'altro. */
.prd-file { border-top: 1px solid var(--rg-border); }
.prd-riga + .prd-riga { border-top: 1px solid var(--rg-border); }

/* ---------- Parte 8.22 - la scheda di MARCHIO ----------
   Un logo di marchio e' un'immagine su fondo bianco, spesso con il bianco dentro
   l'immagine stessa: su un vassoio grigio i loghi con fondo pieno si stampano come
   francobolli. Scheda bianca, bordo tenue, e il logo al centro con aria attorno.
   L'altezza e' la stessa per tutte, cosi' la griglia resta una griglia: sono loghi di
   proporzioni diverse, e senza un'altezza comune ogni riga avrebbe la sua. */
.mrc-card { background: #fff; min-height: 104px; }
.mrc-card img { max-height: 56px; width: auto; object-fit: contain; }
@media (min-width: 992px) {
  .mrc-card { min-height: 120px; }
  .mrc-card img { max-height: 64px; }
}
/* L'intestazione di gruppo dei marchi: una fascia a piena larghezza sul grigio
   infossato, in maiuscoletto spaziato. E' un'etichetta di sezione, non un titolo di
   pagina: non compete con il titolo della schermata. */
.mrc-gruppo {
  background: var(--rg-surface-sunken); color: var(--rg-label);
  border-radius: var(--rg-radius-card); padding: .5rem 1rem;
  font-size: 13px; font-weight: 500; letter-spacing: .04em;
}

/* ---------- Parte 8.23b - la PIASTRELLA DELL'ICONA ----------
   Quadrato arrotondato, tinta tenue del marchio, icona satura: la stessa grammatica
   della pastiglia di stato - fondo tenue, contenuto saturo. Da' a una scheda un punto
   d'attacco per l'occhio che il testo nudo non ha.
   E' una primitiva, non un pezzo dei Servizi: la usano le cinque schede di servizio e
   le quattro scorciatoie della home. */
.tile-icona {
  width: 48px; height: 48px; border-radius: var(--rg-radius-input);
  background: var(--brand-primary-subtle); color: var(--brand-primary);
  display: inline-flex; align-items: center; justify-content: center; font-size: 22px;
  /* In una scheda `display: flex` in colonna il figlio si stira sulla larghezza: qui la
     larghezza e' dichiarata, ma l'allineamento esplicito rende la regola indipendente
     dal fatto che lo sia. */
  align-self: flex-start; flex: 0 0 auto;
}

/* ---------- Parte 8.23 - la scheda di SERVIZIO ----------
   Piastrella dell'icona in cima, titolo, punti. Cinque schede PARI.
   Erano un flusso: un filo univa una scheda alla successiva e ognuna portava il proprio
   numero, 01..05. Il committente (2026-09-16) ha chiarito che non e' una sequenza da
   percorrere ma cinque servizi offerti insieme, e filo e numeri dicevano il contrario.
   Cio' che resta e' la piastrella: e' la stessa grammatica della pastiglia di stato -
   fondo tenue del marchio, contenuto saturo - e da' alla scheda un punto d'attacco per
   l'occhio che il testo nudo non ha: e' la piastrella di Parte 8.23b. */
.srv-card ul { padding-left: 1.1rem; }
.srv-card li { margin-bottom: .15rem; }

/* ---------- Parte 10.5 - tabelle impilate sotto md ---------- */
/* 1024px e non 767.98: il tablet in verticale (768x1024, 810x1080, 834x1112, e
   1024x1366 per il 12,9") deve vedere le SCHEDE, non la tabella. Sopra 1024 resta la
   tabella. Il numero non e' un breakpoint di Bootstrap perche' il caso non e' un
   breakpoint di Bootstrap: e' la larghezza dei tablet in piedi. */
@media (max-width: 1024px) {
  .table-stack thead { display: none; }
  .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display: block; width: 100%; }
  /* La scheda di riga: bianca CON BORDO. Il bordo serve perche' il vassoio grigio non
     c'e' piu' quando la tabella sta dentro una scheda bianca - bianco su bianco non si
     stacca - e non fa danno dove il vassoio c'e'. E' anche la forma di §8.5 per una
     scheda di elenco dentro un contenitore chiaro. */
  .table-stack tr { background: #fff; border: 1px solid var(--rg-border);
    border-radius: var(--rg-radius-card); margin-bottom: .75rem; padding: .5rem .75rem; }
  /* Griglia e non flex: una cella puo' avere piu' di un figlio - codice piu'
     descrizione, per dire &mdash; e con display:flex i figli diventano item in FILA, uno
     accanto all'altro, e la descrizione si riduce a un troncone. Con la griglia
     l'etichetta occupa la prima colonna su tutte le righe e ogni figlio scende
     nella seconda, qualunque sia il loro numero. */
  /* 37% e non 40 per la colonna dell'etichetta: l'etichetta piu' lunga della tabella
     piu' larga misura 85 px («Imp. Scontato», 13 px), e il 37% a 360 px ne da' 92. Il
     resto va al VALORE, che e' il dato: con il 40% la pastiglia di stato aveva 137 px e
     ne chiedeva 139 - «Non Disponibile» andava a capo dentro la propria tinta per tre
     pixel, e una pastiglia di stato e' un gettone breve, non testo corrente (§3.2). */
  .table-stack td { border: 0; padding: .35rem 0;
    display: grid; grid-template-columns: 37% 1fr; gap: 0 .75rem; align-items: center; }
  /* Una parola che non ha spazi dentro - un indirizzo di posta, un codice articolo -
     non va a capo da se': allarga la cella, e con essa la tabella, e il valore finisce
     tagliato oltre il bordo dello schermo. Misurato a 360 px sui contatti:
     `capomagazziniere@cer98.it` usciva dalla scheda. `anywhere` e non `break-word`
     perche' break-word non spezza dentro una parola quando la cella ha una larghezza
     minima intrinseca, che e' esattamente questo caso. */
  .table-stack td, .table-stack td > * { overflow-wrap: anywhere; min-width: 0; }
  /* `text-align: left` sull'etichetta: le classi di allineamento della TABELLA
     (`text-center`, `text-end`) stanno sul `td` e nella vista a schede colpiscono anche
     lo pseudo-elemento. Misurato a 834 px: «Articolo» a 63 px, «Disp.» a 180, «Listino»
     a 280 - tre etichette su tre posizioni diverse nella stessa colonna. Il valore
     conserva il proprio allineamento, che gli serve per incolonnarsi. */
  /* L'etichetta resta a SINISTRA: e' una dichiarazione propria dello pseudo-elemento,
     quindi non eredita il `text-align: right !important` della cella - l'eredita' vale
     solo dove il figlio non dichiara nulla. */
  .table-stack td::before { content: attr(data-label); color: var(--rg-label);
    font-weight: 500; font-size: 13px; grid-column: 1; grid-row: 1 / -1;
    text-align: left !important; }
  /* IL VALORE STA A DESTRA, SEMPRE (richiesta del committente). Nella scheda l'etichetta
     e' a sinistra e il valore a destra: e' l'incolonnamento che rende leggibile la
     scheda, e le classi di allineamento della TABELLA - `text-center` su Sconti e
     Quantita', nessuna classe su Articolo - valgono per le colonne del desktop e nella
     scheda spezzavano quell'incolonnamento. Serve `text-align` e non solo
     `justify-self`: una cella che contiene TESTO NUDO, senza un elemento dentro, non ha
     nessun figlio da posizionare - era il caso di Articolo, che restava a sinistra.
     `!important` perche' deve battere le utility di allineamento, che ce l'hanno: la
     soglia di questa vista e' 1024 px e Bootstrap non ha una variante per breakpoint a
     quella misura, quindi la si batte dal foglio (DL-083, stesso ragionamento). */
  .table-stack td { text-align: right !important; }
  .table-stack td > * { grid-column: 2; justify-self: end; }
  /* E VALE ANCHE PER I CONTROLLI, non solo per il testo (committente, 2026-09-11).
     `.input-group` di Bootstrap dichiara `width: 100%`: riempie la colonna del valore,
     quindi `justify-self: end` non ha niente da spostare, e cio' che sta dentro si
     dispone secondo la propria classe - `justify-content-center` sullo stepper della
     ricerca, e lo stepper finiva CENTRATO in mezzo alla scheda mentre ogni altro valore
     era a destra. Misurato a 360: gruppo da 171 px in una colonna da 171.
     Un gruppo di controlli dentro una scheda si stringe su quello che contiene e si
     allinea come tutto il resto. Vale per lo stepper, per i gruppi di pulsanti e per
     qualunque altro `.input-group` che finisca in una cella. */
  .table-stack td > .input-group,
  .table-stack td > .btn-group { width: auto; justify-content: flex-end !important; }
  /* Una cella senza data-label non ha etichetta da mostrare, quindi non ha la prima
     colonna: il ::before vuoto le riserverebbe il 40% della scheda per niente. E' il
     caso della riga di dettaglio (colspan), che va a larghezza piena. */
  .table-stack td:not([data-label]) { display: block; }
  .table-stack td:not([data-label])::before { content: none; }
  /* Una cella SENZA valore non diventa una riga etichettata nella scheda. Nella tabella
     la colonna esiste comunque - la riga di spesa non ha disponibilita' ne' azioni - ma
     nella scheda «Disp.» seguito dal nulla si legge come un dato MANCANTE invece che
     come un dato che per quella riga non esiste. Lo dichiara chi rende la riga: il
     foglio non puo' saperlo, perche' `:empty` non vede lo spazio bianco che il PHP
     lascia dentro il `td`. */
  /* Sta DOPO `td:not([data-label])` di proposito: hanno la stessa specificita' e a
     parita' vince l'ultima, quindi una cella vuota deve sparire anche quando non porta
     etichetta - la cella delle azioni, per dire, che l'etichetta non l'ha piu'. */
  .table-stack td.cell-empty { display: none; }
  /* La cella d'IDENTITA' della scheda: il codice e la sua descrizione. Non ha etichetta
     da mostrare - il contenuto *e'* l'articolo - e va a larghezza piena, allineata a
     sinistra, che e' come si legge una scheda (Parte 8Z.6: codice e descrizione sulla
     prima riga). Serve anche la riga sui figli: senza, restano nella seconda colonna
     con justify-self: end e il codice finisce a destra. Misurato: scatola del codice a
     224 px in una cella che comincia a 52. */
  .table-stack td.cell-id { display: block; text-align: left !important; }
  .table-stack td.cell-id::before { content: none; }
  .table-stack td.cell-id > * { grid-column: auto; justify-self: start; }
  /* Una cella LARGA: etichetta sopra, valore sotto, tutto a sinistra e a larghezza
     piena. Serve per i valori di testo lunghi - una descrizione articolo - che nella
     seconda colonna al 60% andrebbero a capo tre volte allineati a destra, e un testo
     lungo allineato a destra si legge male: ogni riga comincia in un punto diverso.
     I numeri restano dove sono, a destra, dove si confrontano incolonnati. */
  /* La cella LARGA resta un'affordance del kit e continua a valere contro la regola
     sopra. Il carrello non la usa piu' - il committente vuole la descrizione a destra
     come gli altri valori - ma una descrizione lunga in una colonna stretta e' un caso
     che tornera'. */
  .table-stack td.cell-wide { display: block; text-align: left !important; }
  .table-stack td.cell-wide::before { display: block; grid-row: auto; margin-bottom: .1rem; }
  .table-stack td.cell-wide > * { grid-column: auto; justify-self: start; text-align: left; }
  /* Un troncamento e' una scelta di densita' ORIZZONTALE. Nella scheda impilata lo
     spazio che manca e' quello orizzontale e quello verticale e' libero: il testo
     va a capo, non si taglia. Va sciolto anche il line-clamp di Parte 6.2, non solo
     il nowrap: con -webkit-line-clamp la scatola resta alta una riga e le righe in
     piu' finiscono SOPRA la cella successiva. */
  .table-stack td .ellipsis,
  .table-stack td .subtitle.ellipsis {
    display: block; -webkit-line-clamp: none; line-clamp: none;
    white-space: normal; overflow: visible; text-overflow: clip; height: auto; }
  /* La riga di dettaglio appartiene alla scheda che la apre, non e' una scheda a
     parte: quando e' aperta, la riga sopra chiude senza raggio e senza margine e il
     dettaglio continua da li'. Con :has() non supportato il ripiego e' esattamente
     l'aspetto precedente &mdash; due schede &mdash; quindi non si rompe niente. */
  .table-stack tr.flt-data:has(+ tr.detail-row.show) {
    margin-bottom: 0; padding-bottom: 0;
    border-bottom-left-radius: 0; border-bottom-right-radius: 0;
    /* E il BORDO in mezzo cade. Senza questa riga la saldatura era a meta': le due
       schede si toccavano senza raggio, ma i loro due bordi da 1 px restavano uno
       sull'altro e disegnavano una linea - cioe' esattamente cio' che la saldatura
       doveva togliere. Trovato sulla ricerca, dove il dettaglio e' sempre aperto e la
       linea si vedeva su ogni articolo (committente, 2026-09-11). */
    border-bottom: 0; }
  .table-stack tr.detail-row.show {
    padding-top: 0; border-top: 0;
    border-top-left-radius: 0; border-top-right-radius: 0; }
  .table-stack tr.detail-row > td { border-radius: var(--rg-radius-input); padding: .5rem .75rem; }
  /* ---- la tabella ANNIDATA resta una tabella (DL-120) ----
     Le regole qui sopra sono discendenti e arrivano dentro una tabella dentro una
     cella: `overflow-wrap: anywhere` porta il min-content di una colonna a un carattere
     e le intestazioni si spezzano lettera per lettera; il display a griglia impila i
     numeri in una colonna sola. Una scala di prezzi e' fatta per il confronto PER
     COLONNA: impilarla la distrugge. */
  .netti-table                     { display: table !important; width: 100%; font-size: 12px;
                                     table-layout: auto !important; }
  .netti-table thead               { display: table-header-group !important; }
  .netti-table tbody               { display: table-row-group !important; }
  .netti-table tr {
    display: table-row !important; background: transparent !important; border: 0 !important;
    margin: 0 !important; padding: 0 !important; border-radius: 0 !important; }
  .netti-table th, .netti-table td {
    display: table-cell !important; grid-template-columns: none !important;
    width: auto !important; padding: .25rem .35rem !important; text-align: right !important;
    overflow-wrap: normal !important; word-break: normal !important; }
  .netti-table th                  { white-space: normal !important; }
  .netti-table th::before, .netti-table td::before { content: none !important; display: none !important; }
  .netti-table th:first-child, .netti-table td:first-child   { text-align: left !important; }
  .netti-table th:nth-child(2), .netti-table td:nth-child(2) { text-align: center !important; }
  /* La scatola non CLIPPA mai: cinque colonne di numeri in una scheda da 280 px
     possono non entrare, e allora si scorrono. Un numero tagliato dal bordo e' peggio
     di un numero da raggiungere. */
  .netti-box { max-width: none; overflow-x: auto; }
  /* Nella scheda non resta nessun filo fra l'articolo e la sua scala. */
  .table-stack tr.flt-data:has(+ tr.detail-row.detail-plain) > td { border-bottom: 0 !important; }
  /* La cella della foto: a sinistra e a larghezza piena, come la cella d'identita'. */
  .table-stack td.cell-foto { display: block; text-align: left !important; }
  .table-stack td.cell-foto::before { content: none; }
  .table-stack td.cell-foto > * { grid-column: auto; justify-self: start; }

  /* L'intestazione di gruppo nella vista a schede sta in §1B.5.5, dove sta il
     componente. Qui c'erano due righe che dicevano la stessa cosa in modo diverso e,
     stando PIU' AVANTI nel foglio, vincevano a parita' di specificita': il fondo
     trasparente della fascia era morto da allora. Una cosa, un posto. */
}

/* ---------- Parte 10.1a - fondamenta mobile: le misure di PAGINA ----------
   Stanno qui, una volta, e non in ogni vista: sono la base su cui poggiano tutte le
   schermate della piattaforma. */
@media (max-width: 575.98px) {
  /* IL GUTTER DI PAGINA. Prima: 12 px di `.container-fluid` + 16 di margine della
     scheda + 16 di padding della scheda = 44 px per lato, cioe' 88 px di cromatura su
     360 e 272 px di contenuto - il 75% dello schermo. Ora 8 + 0 + 12 = 20 per lato e il
     contenuto misura 320 px: 48 px in piu' proprio dove ogni pixel si vede. La scheda
     conserva il raggio e resta una scheda: non si incolla ai bordi dello schermo.
     I due valori che spariscono - il margine e i 4 px di padding - stanno nelle utility
     del markup, non qui: `mx-0 mx-sm-3` e `p-2-5 p-sm-3` sulla scheda della shell,
     `px-0 px-sm-3` sulle righe delle viste. Un'utility di Bootstrap e' `!important` e
     dal foglio non si batte: si cambia l'utility (DL-012), e Bootstrap ha la variante
     per breakpoint proprio per questo. */
  .app-main { padding-inline: .5rem; }
  /* I COMANDI DI SCHERMATA. Prima erano tre pulsanti impilati a larghezza intera: 44 px
     l'uno piu' i distacchi, 156 px di cromatura prima che il compito cominciasse, su un
     viewport alto 780. §10.3a chiede UNA riga sopra il primo contenuto e §10.2 lo dice
     esplicitamente per la barra dei comandi sotto sm: pulsanti con la sola icona. Cosi'
     i tre comandi restano tutti e tre visibili e a un tocco - nessun menu in piu' da
     aprire - e la riga costa 44 px invece di 156.
     L'etichetta NON si toglie con `display: none`: diventa nascosta solo alla VISTA, e
     resta nell'albero di accessibilita' come nome del pulsante. Un pulsante con la sola
     icona e senza nome accessibile e' un pulsante senza nome per chi usa uno screen
     reader, ed e' il difetto che §10.6 avverte di non introdurre. */
  .page-actions { width: auto; }
  .page-actions .btn { min-width: 44px; }
  .page-actions .btn > .btn-label,
  .page-toolbar .btn > .btn-label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
  /* I comandi stanno a DESTRA del titolo (richiesta del committente): la spinta la da'
     `me-auto` sul titolo nel markup della shell, non una regola di qui. */
}
@media (max-width: 991.98px) {
  /* I CONTROLLI LEGACY. La soglia di §10.1.3 e §10.1.5 vale per ogni controllo, non
     solo per quelli che portano una classe del kit: i campi che il PHP legacy emette
     nudi misuravano 27 px di altezza e 13 px di corpo. Contati a 360 px: 189 in Area
     Personale, 2 su E-Commerce, 2 su Storico Ordini. Sotto lg qualunque campo dentro
     `.app-main` misura almeno 44 px e ha 16 px di corpo, che e' anche cio' che evita
     l'ingrandimento automatico di iOS al fuoco. Caselle e radio restano quelle che
     sono: una casella alta 44 px non e' un bersaglio piu' grande, e' un quadrato
     sbagliato - il suo bersaglio e' la riga con l'etichetta, e lo prende il brief
     della schermata quando ne ridisegna il contenuto. */
  .app-main input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
  .app-main select, .app-main textarea {
    min-height: 44px; font-size: 16px;
  }
  /* Un'intestazione appiccicosa deve tenere conto della barra dell'applicazione, che
     sotto lg e' alta 56 px e sta anche lei appiccicata in cima (§10.7). Senza questo
     l'intestazione si ferma SOTTO la barra e non si vede. */
  .table-head-sticky thead th { top: 56px; }
}

/* ---------- Parte 10.6 - barre azioni, filtri, ricerca ---------- */
@media (max-width: 991.98px) {
  .page-toolbar { flex-wrap: wrap; gap: .5rem; }
  .page-toolbar .btn { min-width: 44px !important; min-height: 44px; }
  /* L'etichetta di un pulsante della barra non si CANCELLA: sotto sm la nasconde alla
     vista la regola di Parte 10.1a, che la lascia nell'albero di accessibilita'. Qui
     resta la sola misura del bersaglio. */
  .search_mini { width: 100%; margin-right: 0 !important; }
  .search_mini .clear-input-btn { left: auto; right: 48px; }
  .nav-filter { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .nav-filter::-webkit-scrollbar { display: none; }
  .nav-filter .nav-item { flex: 0 0 auto; }
  .nav-filter .nav-link { padding-left: .75rem !important; padding-right: .75rem !important; white-space: nowrap; }
  #date-range { width: 100% !important; }
}

/* ---------- Parte 10.7 - form, modali, selettori ---------- */
@media (max-width: 991.98px) {
  .col-md-4.pe-md-5 { padding-right: 0 !important; }
  .form-control, .form-select { font-size: 16px; }
  .form-switch-big { width: 48px !important; height: 26px !important; }
  .btn-add, .btn-del, .btn-edit, .btn-save, .btn-clear { min-width: 44px; min-height: 44px; }
  .btn-back, .btn-big { width: 44px; height: 44px; }
}

/* ---------- Parte 10.1 - nessuna larghezza minima ---------- */
/* Niente overflow-x: hidden sul body. Non rompe lo scorrimento (verificato), ma
   maschera l'overflow orizzontale, cioe' esattamente il sintomo che §10.1.1 chiede
   di misurare a 360 px: con la dichiarazione scrollWidth non puo' che uguagliare
   clientWidth, e la verifica non dimostra piu' nulla. Chi eccede si corregge dove
   eccede. */
body { min-width: 0; }

/* ---------- Parte 11.1 - movimento ridotto ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* Il carosello dei marchi/promozioni deve scorrere sempre, con movimento
   perfettamente lineare, anche con prefers-reduced-motion attivo (es. sessioni
   RDP che lo impongono per performance, non per scelta reale dell'utente).
   Shorthand completo, non solo animation-duration: la Parte 11.1 qui sopra
   azzera solo la durata, ma occorre ridichiarare anche il nome, altrimenti
   l'animazione resta senza keyframes assegnati. `linear` esplicito qui evita
   che un buon default venga silenziosamente perso in futuro. Specificita' di
   tre classi batte `*` a parita' di !important. */
@media (prefers-reduced-motion: reduce) {
  .brand-strip.is-auto .brand-track,
  .scroll-strip.is-auto .brand-track {
    animation: brandScroll var(--brand-scroll-time, 40s) linear infinite !important;
    animation-timing-function: linear !important;
  }
  /* Stesso 15% di rallentamento della regola normale, anche qui. */
  .scroll-strip.is-auto .brand-track {
    animation-duration: calc(var(--brand-scroll-time, 40s) * 1.25) !important;
  }
}

/* ---------- Parte 10.9 - stampa ---------- */
@media print {
  .sidebar, .mobile-topbar, .page-toolbar, .dt-paging, .nav-filter,
  .summary-bar, .bulk-bar, .breadcrumb-bar { display: none !important; }
  /* La shell non si stampa: navigazione, piede e carosello dei marchi non appartengono
     al foglio che esce dalla stampante. Serve da quando showorder.php adotta la shell
     (brief 8.6): quel documento si stampa, ed e' il suo scopo. */
  .app-bar, .app-bar-2, .app-drawer, .app-foot, .brand-strip { display: none !important; }
  .app-main { padding: 0 !important; }
  .main-content { margin: 0 !important; }
  .container-list, #stats, [id^="data_"] { height: auto !important; overflow: visible !important; }
  .card, .bg-card { background: #fff !important; box-shadow: none !important; }
}
