/* app.css — CSS proprio di YoReorder, caricato dopo il tema Ynex.
   Il blocco qui sotto (fino a "fine override mockup") è copiato dal mockup
   "YoReorder vestito Ynex.dc.html" (§2.4 dell'handoff): punto di partenza,
   non toccare senza confrontare col mockup. Classi proprie con prefisso yr-. */

:root { --text-muted:#66696f; }
:root[data-theme-mode="dark"] { --text-muted:#9aa0ad; }
.app-sidebar, .main-sidebar-header { font-family:'Montserrat',sans-serif; }
.fe { font-family:'boxicons'!important; font-weight:400!important; font-style:normal; }
.fe-chevron-right:before { content:"\ea50"; }
.card-title, .no-text-transform { text-transform:none!important; }
/* semantici leggibili come testo */
.text-danger { color:#b23021!important; }
.text-success { color:#0d7a63!important; }
.text-warning { color:#8a5a08!important; }
.bg-warning-transparent { color:#8a5a08!important; }
.bg-danger-transparent { color:#b23021!important; }
.bg-success-transparent { color:#0d7a63!important; }
.bg-secondary-transparent, .bg-info-transparent { color:#1f5aa8!important; }
.badge.bg-danger, .btn-danger { background-color:#b23021!important; border-color:#b23021!important; }
.badge.bg-success, .btn-success { background-color:#0d7a63!important; border-color:#0d7a63!important; }
.badge.bg-warning, .btn-warning { color:#332107!important; }
.badge.bg-secondary, .badge.bg-info { background-color:#1f5aa8!important; border-color:#1f5aa8!important; }
.badge.bg-danger, .badge.bg-success, .badge.bg-primary, .badge.bg-secondary, .badge.bg-info { color:#fff!important; }
/* varianti "-light" del tema: fondo al 10% con testo alla tinta piena → 2.15:1. Testo scurito. */
.btn-success-light { background-color:rgba(13,122,99,.12)!important; color:#0a5f4d!important; border-color:transparent!important; }
.btn-danger-light { background-color:rgba(178,48,33,.12)!important; color:#8e2318!important; border-color:transparent!important; }
.btn-warning-light { background-color:rgba(138,90,8,.14)!important; color:#6b4606!important; border-color:transparent!important; }
.btn-primary-light { background-color:rgba(var(--primary-rgb),.12)!important; color:#5c3aab!important; border-color:transparent!important; }
/* le option di un select ereditano il colore primario dal tema: 3.59:1 */
select option, .form-select option, .form-control option { color:#23252e!important; background-color:#fff!important; }
:root[data-theme-mode="dark"] select option { color:#e5e8ef!important; background-color:#232323!important; }
/* Ynex dipinge di bianco il testo SVG dei grafici e il centro del radiale, battendo i fill
   inline di ApexCharts: la cascata va riportata per superficie, non per singola etichetta. */
.apexcharts-pie text, .apexcharts-datalabel-value { fill:#23252e!important; }
.apexcharts-datalabel-label { fill:#4d5160!important; }
#obiettivo .apexcharts-radialbar-hollow { fill:transparent!important; }
#obiettivo .apexcharts-radialbar-track path { stroke:rgba(0,0,0,.28)!important; }
#obiettivo .apexcharts-radial-series path { stroke:#ffffff!important; }
#obiettivo .apexcharts-datalabel-value, #obiettivo .apexcharts-datalabel-label { fill:#fff!important; }
:root[data-theme-mode="dark"] .apexcharts-pie text,
:root[data-theme-mode="dark"] .apexcharts-datalabel-value { fill:#e9eaee!important; }
:root[data-theme-mode="dark"] .apexcharts-datalabel-label { fill:#a7abb8!important; }
/* iniziali dell'avatar a 10.4px: la tinta piena su fondo al 10% dà 4.1:1 */
.main-content .avatar.bg-primary-transparent, .app-sidebar .avatar.bg-primary-transparent { color:#5c3aab!important; }
.app-header .avatar.bg-primary-transparent { color:#d5c6f8!important; }
.main-content .badge.bg-primary-transparent, .modal .badge.bg-primary-transparent, .dropdown-menu .badge.bg-primary-transparent, .offcanvas .badge.bg-primary-transparent { color:#5c3aab!important; }
.app-sidebar .badge.bg-primary-transparent { color:#d5c6f8!important; }
/* Scuriti per il contrasto sul fondo quasi bianco degli alert in tema chiaro. In tema scuro il
   fondo è quasi nero: lì il colore "crudo" del tema (rgb(var(--warning-rgb)) ecc.) ha già
   abbastanza contrasto da solo — scurirlo ulteriormente come qui sotto lo rende illeggiabile
   nell'altro verso (bug segnalato). Per questo l'override vale solo fuori dal tema scuro. */
html:not([data-theme-mode="dark"]) .alert-primary, html:not([data-theme-mode="dark"]) .alert-primary .fw-semibold { color:#5c3aab!important; }
html:not([data-theme-mode="dark"]) .alert-success, html:not([data-theme-mode="dark"]) .alert-success .fw-semibold { color:#0b6d5a!important; }
html:not([data-theme-mode="dark"]) .alert-danger, html:not([data-theme-mode="dark"]) .alert-danger .fw-semibold { color:#a02b1d!important; }
html:not([data-theme-mode="dark"]) .alert-warning, html:not([data-theme-mode="dark"]) .alert-warning .fw-semibold { color:#7c4f07!important; }
html:not([data-theme-mode="dark"]) .alert-info, html:not([data-theme-mode="dark"]) .alert-info .fw-semibold { color:#1b5296!important; }
.modal .avatar.bg-primary-transparent, .dropdown-menu .avatar.bg-primary-transparent, .offcanvas .avatar.bg-primary-transparent { color:rgb(var(--primary-text-rgb))!important; }
.modal .text-primary, .dropdown-menu .text-primary { color:rgb(var(--primary-text-rgb))!important; }

/* Il colore del tenant è arbitrario: dove il tema lo usa come TESTO su fondo chiaro (non come
   sfondo con testo bianco) va sostituito con la variante scurita per il contrasto (§5.4,
   lib/format.php colore_testo_leggibile()). Altrimenti certi arancioni/gialli diventano
   illeggibili sulle schede bianche — bug segnalato sulle schede di Impostazioni. */
.tab-style-6 .nav-item .nav-link:not(.active),
.text-primary,
.link-primary { color:rgb(var(--primary-text-rgb))!important; }
.link-primary:hover, .link-primary:focus { color:rgb(var(--primary-text-rgb))!important; }
.avatar.bg-danger-transparent { color:#8e2318!important; }
.avatar.bg-warning-transparent { color:#6b4606!important; }
.avatar.bg-success-transparent { color:#0a5f4d!important; }
.avatar.bg-secondary-transparent, .avatar.bg-info-transparent { color:#1a4c8c!important; }
/* il tema azzera il content degli indicatori (li forniva il plugin jQuery):
   qui sono elementi reali, indipendenti dalla cascata. */
.yr-sortico { display:inline-flex; flex-direction:column; line-height:.55; margin-inline-start:.35rem; vertical-align:middle; }
.yr-sortico i { font-size:.62rem; font-style:normal; opacity:.3; }
th.sorting_asc .yr-sortico i:first-child,
th.sorting_desc .yr-sortico i:last-child { opacity:1; color:rgb(var(--primary-rgb)); }
.yr-sub-open { display:block!important; }
.yr-sub-closed { display:none!important; }
/* Impostazioni: configurazione, non lavoro — piede separato come in Struttura definitiva */
/* il tema riserva 80px di padding-bottom per un widget che qui non c'è: è quello il vuoto sotto il piede */
/* Colonna flessibile alta almeno quanto la barra: senza, la firma in fondo non ha un
   contenitore su cui spingersi e `mt-auto` non sposta niente — restava appiccicata
   all'ultima voce di menu. */
.app-sidebar .main-sidebar {
  display:flex!important; flex-direction:column!important;
  /* 3.75rem è l'altezza dell'intestazione della barra nel tema, non un numero a caso:
     sta in .main-sidebar-header di styles.min.css. */
  height:auto!important; min-height:calc(100vh - 3.75rem)!important;
  padding-block-end:1rem!important;
  /* NIENTE `overflow-y: auto` qui.
     Il tema monta SimpleBar su questo elemento, e SimpleBar si porta dentro un involucro
     alto il doppio (mascheratura + contenuto sfalsato). Aggiungendo uno scorrevole nostro
     sopra il suo, il contenitore diventava scorrevole per 1072px in una finestra da 1180:
     con il mouse non si nota, su un tablet basta trascinare la barra laterale e il menu
     scorre via. La barra e` fissa — era il suo contenuto a scivolare dentro di lei. */
}
.app-sidebar .main-menu-container { flex:1 1 auto!important; overflow:visible!important; }
.app-sidebar { position:fixed!important; }
html:not([data-toggled]) body .main-content { max-width:calc(100% - 15rem); overflow-x:hidden; }
html[data-toggled] body .main-content { overflow-x:hidden; }
html[data-toggled="icon-overlay-close"] body .main-content { max-width:calc(100% - 5rem); }

/* ── Il tablet: fra 768px e 992px il contenuto finiva sotto la barra ────────────
   Il tema, sotto i 992px, dichiara la barra «chiusa» (`data-toggled="close"`) e toglie il
   margine al contenuto: si aspetta che la barra sia scorsa via. Ma noi la teniamo
   `position: fixed !important` — serve perche' la firma in fondo e il menu si comportino —
   e cosi` la barra resta visibile a 0→240 mentre il contenuto parte da 0. Su un iPad in
   verticale il risultato e` che la prima colonna di ogni scheda sparisce dietro il menu, e
   il panino non cambia niente: `close` e `open` lasciano la barra dov'e`.
   Misurato a 820px: barra [0→240], contenuto a 0.

   Qui il margine si rimette. Non e` un ripiego per far entrare tutto: a 820px ci sono 580px
   per il contenuto, che e` piu` di un telefono — la barra laterale su un tablet e` la cosa
   giusta, va solo lasciato lo spazio a chi le sta accanto. */
@media (min-width: 768px) and (max-width: 991.98px) {
  html[data-toggled="close"] body .main-content,
  html[data-toggled="open"] body .main-content {
    margin-inline-start: 15rem;
    max-width: calc(100% - 15rem);
    overflow-x: hidden;
  }
  /* Anche l'intestazione, per lo stesso motivo e con la stessa misura: il suo contenitore
     parte da 0 e il titolo della pagina finiva dietro il menu — si vedeva spuntare l'ultima
     lettera. Sopra i 992px questo margine glielo mette gia` il tema. */
  html[data-toggled="close"] .app-header .main-header-container,
  html[data-toggled="open"] .app-header .main-header-container {
    /* Il margine da solo non basta: il contenitore e` largo il 100% del suo genitore, e
       spostandolo sborderebbe di 240px a destra. La larghezza va tolta quanto il margine. */
    margin-inline-start: 15rem;
    max-width: calc(100% - 15rem);
  }
  /* Ridotta a striscia di icone non serve niente: quel margine il tema lo mette gia`, e
     aggiungerne un secondo lo raddoppiava — l'intestazione partiva da 160 invece che da 80.
     La regola qui sopra vale solo per «close» e «open», che sono gli stati che il tema
     lascia scoperti. */

  /* Il logo torna. Il tema nasconde l'intestazione della barra sotto i 992px perche' li` la
     barra dovrebbe essere sparita: ma da noi c'e`, e restava senza testa — sopra la prima
     voce c'era un vuoto. */
  .app-sidebar .main-sidebar-header { display: flex !important; }
  /* E il menu scende sotto di essa. Il tema questo margine lo mette solo sopra i 992px:
     senza, il menu parte da zero e le prime due voci — «Oggi» e «Vendi ora» — finiscono
     coperte dall'intestazione. Non sparivano: erano sotto. 3.75rem e` l'altezza vera
     dell'intestazione nel tema, la stessa gia` usata piu` in alto in questo file. */
  .app-sidebar .main-sidebar { margin-block-start: 3.75rem !important; }

  /* Nome e ruolo lasciano il posto. A 820px la barra laterale si prende 240px e
     all'intestazione ne restano 580: il panino, il titolo, i due pulsanti di pagina, la
     campanella e il blocco utente non ci stanno, e i pulsanti andavano a capo finendo uno
     sopra il bordo (misurato: «Crea ordine» a y=-10). Il nome e` la cosa che si puo`
     togliere senza perdere niente — l'iniziale nel tondo resta, e il menu sotto lo ripete
     per esteso. */
  .app-header .header-link .d-sm-block { display: none !important; }

  /* I pulsanti di pagina non si stringono, il titolo si`.
     -------------------------------------------------------------------------
     Al gruppo dei due pulsanti restavano 229px e glienе servivano 235: sei. Con
     `flex-wrap: nowrap` sul contenitore non poteva andare a capo li`, e allora andava a
     capo **dentro**, dentro una riga alta 59 — «Crea ordine» finiva a y=-10, cioe` sopra
     il bordo dell'intestazione, e «Esporta vendite» sotto.
     Chi deve cedere quei sei pixel e` il titolo, che ha i puntini e non perde una funzione;
     un pulsante tagliato a meta` invece non si preme. `min-width: 0` perche' senza, un
     elemento flex non scende sotto la larghezza del suo contenuto e non cede niente. */
  .app-header .header-content-right > .header-element:first-child { flex-shrink: 0; }
  .app-header .header-content-left { min-width: 0; }

  /* Niente patina. Il velo scuro serve a una barra che si apre **sopra** il contenuto: si
     preme fuori e si chiude. Qui la barra sta di fianco e non si chiude mai, quindi il velo
     scuriva la pagina senza avere niente da chiudere. */
  #responsive-overlay, .responsive-overlay { display: none !important; }
}
/* Lo stato "close-menu-close" (barra laterale sparita del tutto) non lo produce più
   nessuno: data-vertical-style è "overlay", e il panino riduce la barra alla striscia di
   icone invece di toglierla. Le regole restano perché chi tornasse a "closed" — dal
   selettore del tema o a mano — troverebbe altrimenti il contenuto con un margine
   sinistro per una barra che non c'è. */
html[data-toggled="close-menu-close"] body .main-content { margin-inline-start:0!important; max-width:100%!important; }
html[data-toggled="close-menu-close"] body .app-header { padding-inline-start:0!important; }
.app-sidebar .yr-menu-sep { list-style:none; height:1px; margin:.85rem .9rem .55rem; background:rgba(255,255,255,.12); }
.yr-authwrap { position:fixed; inset:0; z-index:9999; display:flex; flex-direction:column;
  box-sizing:border-box; background:#fff; overflow:hidden; }
.yr-auth { flex:1; min-height:0; width:100%; display:flex; background:#fff; }
.yr-auth-side { width:42%; flex:0 0 42%; background:#2A2449; color:#fff; padding:56px 56px 104px; display:flex; flex-direction:column; }
.yr-auth-side * { color:inherit; }
.yr-auth-main { flex:1; padding:48px 64px 104px; display:flex; flex-direction:column; justify-content:center; overflow-y:auto; }
.yr-auth-main > div { width:100%; max-width:400px; margin:0 auto; }
.yr-auth-main .form-label { display:block; width:100%; margin-bottom:7px; }
.yr-auth-main .form-control { display:block; width:100%; box-sizing:border-box; height:46px; }
.yr-auth-main .btn-primary { height:48px; font-size:15px; font-weight:600; }
.yr-auth-main .w-100 { width:100%!important; }
.yr-auth-main .yr-lab { font:600 10.5px/1.4 'Public Sans',sans-serif; letter-spacing:.06em; text-transform:uppercase; color:#666b7d; }
.yr-auth-main h3 { font-size:24px; letter-spacing:-0.018em; }
.yr-authnav { position:fixed; bottom:0; left:0; right:0; background:#fff; border-top:1px solid #dfe3ec;
  display:flex; align-items:center; gap:8px; padding:12px 20px; z-index:10000; }
.yr-authnav-l { font:600 10.5px/1 'Public Sans',sans-serif; letter-spacing:.08em; text-transform:uppercase; color:#666b7d; margin-right:4px; }
.yr-authnav-b { font:500 12.5px/1 'Public Sans',sans-serif; padding:8px 12px; border-radius:8px; border:1px solid #c9cedd; background:#fff; color:#23252e; cursor:pointer; }
.yr-authnav-b.on { background:rgb(var(--primary-rgb)); border-color:rgb(var(--primary-rgb)); color:#fff; font-weight:600; }
.app-sidebar .yr-menu-piede { border-top:0!important; box-shadow:none!important; }
.app-sidebar .yr-piede-wrap { border-top:0!important; background:transparent!important; padding:0!important; }
.app-sidebar .yr-menu-piede { margin:0!important; padding:0!important; background:transparent!important; }
.app-sidebar .yr-menu-piede .side-menu__item { margin:0!important; border-radius:.5rem; }
.app-sidebar .yr-piede-nota { display:none; }
html[data-toggled="icon-overlay-close"] .app-sidebar .yr-piede-nota { display:none; }
html[data-toggled="icon-overlay-close"] .app-sidebar .yr-piede-wrap { padding:0; }
.yr-menu-lavoro { flex:1 1 auto; }
.yr-menu-piede { flex:none; margin-block:0; padding:.5rem 0 .25rem; background:rgba(0,0,0,.22); border-top:1px solid rgba(255,255,255,.14); }
.yr-menu-piede .side-menu__item { padding-block:.5rem!important; }

.yr-kb-wrap { display:flex; gap:12px; overflow-x:auto; padding-bottom:6px; align-items:flex-start; }
.yr-kl { flex:0 0 244px; max-width:244px; background:#f0f1f7; border-radius:10px; display:flex; flex-direction:column; max-height:600px; }
.yr-kl-h { display:flex; align-items:center; gap:7px; padding:10px 10px 8px; }
.yr-kl-dot { width:8px; height:8px; border-radius:50%; flex:0 0 8px; }
.yr-kl-add { border:0; background:transparent; color:#6b7791; width:22px; height:22px; border-radius:6px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; font-size:15px; }
.yr-kl-add:hover { background:rgba(0,0,0,.07); color:#333335; }
.yr-kl-b { overflow-y:auto; padding:0 8px 8px; display:flex; flex-direction:column; gap:8px; }
.yr-kl-empty { border:1px dashed #d3d7e3; border-radius:8px; padding:14px 10px; text-align:center; font-size:11.5px; color:#66696f; }
/* Senza user-select:none, iniziare il trascinamento cliccando sul testo della card (titolo,
   badge...) fa partire una selezione di testo invece del drag nativo — su Chrome è la causa più
   comune di "il drag&drop non parte proprio" quando la card è piena di testo come questa. */
.yr-kc { background:#fff; border-radius:8px; box-shadow:0 1px 2px rgba(10,10,10,.09); padding:9px 10px; cursor:grab; transition:box-shadow .12s, transform .12s; user-select:none; -webkit-user-drag:element; }
.yr-kc:active { cursor:grabbing; }
.yr-kc:hover { box-shadow:0 4px 10px rgba(10,10,10,.14); transform:translateY(-1px); }
.yr-kc-mv { border:0; background:transparent; color:#8b90a0; width:20px; height:20px; border-radius:5px; display:inline-flex; align-items:center; justify-content:center; cursor:pointer; font-size:14px; }
.yr-kc-mv:hover { background:rgba(0,0,0,.07); color:#333335; }
.yr-kc-mv:disabled { opacity:.28; cursor:default; }
.yr-avl .avatar { margin-inline-end:2px!important; }
/* BUG GRAVE (risolto): questo z-index a 4 cifre bastava a battere le card successive (z-index
   auto) ma sfondava anche la scala del tema per le modali (backdrop 104, modale 105) — su una
   pagina come Ticket, dove il filtro con la select personalizzata sta DENTRO la card della
   lista, quella card finiva sopra ogni modale aperto sulla stessa pagina, "cancellandola" alla
   vista (il corpo della modale c'era nel DOM, misure e testo corretti, ma dipinto sotto la
   card). Basta un valore appena sopra lo zero implicito delle card vicine, molto sotto 104. */
.card:has(.yr-selmenu) { position:relative; z-index:2; }
.yr-sel-open { position:relative; z-index:3; }
.app-header .btn-outline-light.text-fixed-white:hover,
.app-header .btn-outline-light.text-fixed-white:focus,
.app-header .btn-outline-light.text-fixed-white:active {
  background-color:#f3f6f8!important; border-color:#f3f6f8!important; color:#23252e!important; }
.yr-selmenu { max-height:260px; overflow-y:auto; box-shadow:0 8px 24px rgba(10,10,10,.18); }
/* Il tema forza lo sfondo pieno con !important su .dropdown-item.active: senza !important qui
   sotto, il nostro sfondo chiaro perdeva sempre e il testo (fisso, pensato per fondo chiaro)
   restava scuro su sfondo scuro — illeggibile con certi colori del tenant. */
.yr-selmenu .dropdown-item.active { background:rgba(var(--primary-rgb),.12) !important; color:rgb(var(--primary-text-rgb)) !important; }
/* Stesso bug, generale: il tema usa il colore pieno del tenant come testo al passaggio del
   mouse su QUALSIASI voce di un menu a tendina (non solo il nostro), su fondo quasi bianco
   (tinta al 10%) — stessa illeggibilità per certi colori, corretta con la stessa variante. */
.dropdown-item:hover, .dropdown-item:focus { color:rgb(var(--primary-text-rgb)) !important; }
.yr-modal-back { position:fixed; inset:0; background:rgba(20,22,30,.52); z-index:1060; display:flex; align-items:flex-start; justify-content:center; padding:56px 16px 24px; overflow-y:auto; }
.yr-modal { width:100%; max-width:640px; box-shadow:0 18px 48px rgba(10,10,10,.28); }
.yr-toast-stack { position:fixed; bottom:22px; left:50%; transform:translateX(-50%); z-index:1090; display:flex; flex-direction:column; gap:8px; align-items:center; }
/* Stesso z-index della pila: sono la stessa cosa a vedersi, e a 1070 il messaggio
   singolo finiva SOTTO la barra di impersonificazione (1080) — si leggeva in
   trasparenza, tagliato a metà. */
.yr-toast { position:fixed; bottom:22px; left:50%; transform:translateX(-50%); z-index:1090; }
/* Con la barra di impersonificazione in fondo, il messaggio sale sopra di lei invece di
   coprirla: sono due informazioni diverse — «stai vedendo l'app come un altro» e «ho
   appena fatto questo» — e sovrapporle rende illeggibili tutte e due. */
body:has(.yr-impersona-barra) .yr-toast-stack,
body:has(.yr-impersona-barra) .yr-toast { bottom:4.25rem; }
.app-header .header-element { position:relative; }
.app-header .header-content-right { position:relative; }
.app-header .main-header-dropdown { position:absolute; inset:auto 0 auto auto; margin-top:.25rem; transform:translateY(3.75rem); z-index:1055; }
.app-header .main-header-dropdown.header-profile-dropdown { min-width:13rem; }
html body .main-content { transition:margin-inline-start .2s ease; }
html:not([data-toggled]) body .main-content { margin-inline-start:15rem!important; }
html body .app-header { transition:padding-inline-start .2s ease; }
html:not([data-toggled]) body .app-header { padding-inline-start:15rem!important; }
@media (min-width: 0px) {
  html[data-toggled="icon-overlay-close"] body .app-header,
  html[data-toggled="icon-overlay-close"] body .app-header.app-header { padding-inline-start:5rem!important; }
}
html[data-toggled="icon-overlay-close"] body .app-sidebar,
html[data-toggled="icon-overlay-close"] body .app-sidebar .main-sidebar-header { width:5rem!important; inline-size:5rem!important; min-width:5rem!important; max-width:5rem!important; }
html[data-toggled="icon-overlay-close"] body .main-content { margin-inline-start:5rem!important; }
html[data-toggled="icon-overlay-close"] body .app-sidebar .side-menu__label,
html[data-toggled="icon-overlay-close"] body .app-sidebar .side-menu__angle,
html[data-toggled="icon-overlay-close"] body .app-sidebar .badge,
html[data-toggled="icon-overlay-close"] body .app-sidebar .main-sidebar-header > div,
html[data-toggled="icon-overlay-close"] body .app-sidebar button span:not(.badge) { display:none!important; }
html[data-toggled="icon-overlay-close"] body .app-sidebar .side-menu__item { justify-content:center!important; padding-inline:0!important; }
html[data-toggled="icon-overlay-close"] body .app-sidebar .side-menu__icon { margin-inline-end:0!important; }
html[data-toggled="icon-overlay-close"] body .app-sidebar .main-sidebar-header { justify-content:center!important; }
.min-w-0 { min-width:0!important; }
/* Provato e tolto: `white-space: nowrap` qui sopra.
   Un numero spezzato su piu` righe si legge come piu` numeri, ed era la tentazione giusta.
   Ma nella tabella dello scadenzario ripiegata la cella e` larga 70px: vietando il ritorno
   a capo, «101.187,25 €» non va piu` su tre righe — esce dalla cella per 63px e si disegna
   sopra la colonna accanto. Fra un importo su tre righe e un importo stampato addosso a un
   altro, il primo si legge ancora. Il rimedio vero e` dare piu` spazio a quella colonna,
   non impedire al testo di adattarsi. */
.tnum { font-variant-numeric:tabular-nums; }
.yr-clip { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* Una tabella che si adatta al contenitore invece di imporre la propria misura.
   Serve dove le colonne **non si possono nascondere** — per esempio quando sono caselle da
   spuntare: li` il ripiegamento toglierebbe la funzione della pagina, e lo scorrimento di
   lato dentro una card stretta non si vede nemmeno che c'e`. Le colonne con una larghezza
   dichiarata la tengono, il resto se lo divide la prima, e il testo lungo va a capo. */
.yr-tab-fissa { table-layout: fixed; width: 100%; }
/* Solo nelle celle, non nelle intestazioni: `anywhere` spezza a meta` parola, e
   «Può ordinare» diventava tre righe tagliate dove capita. Un'intestazione va a capo fra
   le parole come qualunque testo. */
.yr-tab-fissa td { overflow-wrap: anywhere; }
/* `.yr-clip` porta una larghezza massima scritta nell'attributo `style`, pensata per la
   scrivania: dentro una tabella che si adatta al contenitore quella misura e` piu` grande
   della cella, e il testo esce invece di finire con i puntini. `!important` perche' e` un
   attributo `style` che si sta scavalcando. */
.yr-tab-fissa .yr-clip { max-width: 100% !important; }

.yr-riga:hover { background:rgba(0,0,0,.015); }
/* Bootstrap mette il bordo su ogni cella (td), non sulla riga: azzerarlo sulla <tr>
   non basta, serve sulle celle. Senza var(--default-border) qui, il browser cade
   sul nero di default (currentColor) — è la riga nera "sotto ogni pagina". */
.table > tbody > tr.yr-riga > * { border-bottom-color: var(--default-border); }
.yr-riga:last-child > * { border-bottom: 0 !important; }
.fs-13-5 { font-size:.845rem; }
.flex-none { flex:none; }
.yr-kb-scroll { display:flex; gap:16px; overflow-x:auto; padding-bottom:8px; align-items:flex-start; }
.yr-kb-col { flex:0 0 300px; min-width:300px; background:rgba(0,0,0,.02); border:1px solid var(--default-border); border-radius:8px; padding:12px; min-height:220px; }
.yr-kb-head { border-bottom:1px solid var(--default-border); }
.yr-kb-dot { width:8px; height:8px; border-radius:50%; display:inline-block; }
.yr-kb { cursor:grab; box-shadow:0 2px 0 rgba(10,10,10,.04); }
.yr-kb-drop.yr-kb-drop-over { background:rgba(var(--primary-rgb),.08)!important; outline:2px dashed rgba(var(--primary-rgb),.4); outline-offset:-2px; }
.yr-kb:hover { box-shadow:inset 0 0 0 1px rgba(51,51,53,.28), 0 2px 0 rgba(10,10,10,.04); }
.yr-kb-drag { opacity:.45; }
.yr-kb-vuota { border:1px dashed var(--default-border); border-radius:8px; min-height:110px; }
.yr-ev-dot { width:9px; height:9px; border-radius:50%; display:inline-block; flex:none; }
.yr-cal-head { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); border-bottom:1px solid var(--default-border); }
.yr-cal-head > div { padding:8px 10px; text-align:center; }
.yr-cal { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); }
.yr-cal-d { min-height:92px; padding:6px 7px; border-right:1px solid var(--default-border); border-bottom:1px solid var(--default-border); }
.yr-cal-d:nth-child(7n) { border-right:0; }
.yr-cal-off { background:rgba(0,0,0,.02); }
.yr-cal-oggi { background:rgba(var(--primary-rgb),.05); }
.yr-cal-num { width:19px; height:19px; border-radius:50%; background:rgb(var(--primary-rgb)); color:#fff; display:inline-flex; align-items:center; justify-content:center; }
.yr-cal-ev { border-radius:4px; padding:1px 5px 1px 4px; margin-bottom:2px; font-size:10.5px; color:#23252e; font-weight:500; overflow:hidden; display:flex; align-items:center; gap:4px; border-left:3px solid; }
.yr-cal-dot { width:5px; height:5px; border-radius:50%; flex:none; }
.yr-cal-ev > span:not(.yr-cal-dot) { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.yr-gt { min-width:1000px; }
.yr-gt-row { display:grid; grid-template-columns:260px repeat(14,minmax(0,1fr)); align-items:center; border-bottom:1px solid var(--default-border); }
.yr-gt-head { background:rgba(0,0,0,.02); }
.yr-gt-lab { padding:8px 12px; border-right:1px solid var(--default-border); min-width:0; }
.yr-gt-c { height:44px; border-right:1px solid rgba(0,0,0,.04); position:relative; display:flex; align-items:center; }
.yr-gt-head .yr-gt-c { height:34px; justify-content:center; }
.yr-gt-oggi { background:rgba(var(--primary-rgb),.06); }
.yr-gt-bar { height:22px; border-radius:6px; display:flex; align-items:center; padding:0 8px; position:absolute; left:3px; z-index:1; }
.yr-clip2 { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; min-height:2.5em; }
.yr-tkrow { padding:.7rem .25rem; border-bottom:1px solid #f1f3f8; }
.yr-tkrow:last-child { border-bottom:0; }
.yr-tkrow:hover { background:#f9fafc; }
.yr-tkrow.on { background:rgba(var(--primary-rgb),.06); }
.yr-vr { display:inline-block; width:1px; height:20px; background:#dfe3ec; }
.yr-tk { transition:box-shadow .16s, background-color .16s; cursor:default; }
.yr-tk:hover { box-shadow:inset 0 0 0 1px rgba(51,51,53,.28), 0 2px 0 rgba(10,10,10,.04); }
.card.yr-tk-on { box-shadow:inset 0 0 0 2px rgb(var(--primary-rgb)), 0 2px 0 rgba(10,10,10,.04); background-color:rgba(var(--primary-rgb),.04); }
.yr-dot { width:.5rem; height:.5rem; border-radius:50%; display:inline-block; }
.yr-chip-n { background:rgba(255,255,255,.92)!important; color:#5c3aab!important; }
.progress-xs { height:.3rem; }
@keyframes yrIn { from { opacity:0; transform:translateY(9px); } to { opacity:1; transform:none; } }
.yr-in { animation:yrIn .32s cubic-bezier(.22,.8,.36,1) both; }
@media (prefers-reduced-motion:reduce) { .yr-in { animation:none!important; } * { transition-duration:0ms!important; } }

/* fine override mockup */

/* --- YoReorder: aggiunte proprie (fuori dal blocco copiato) --- */

/* Il pannello di navigazione segue il colore del tenant (data-menu-styles="color" in
   head.php, §5.1): non più un navy fisso, quello era il bug "il colore non arriva alla
   sidebar". */

.yr-badge-stato { display:inline-flex; align-items:center; gap:.35rem; font-weight:600; }
.yr-badge-stato.yr-forma-pillola { border-radius:999px; }
.yr-badge-stato.yr-forma-angoli { border-radius:.25rem; }
.yr-badge-stato.yr-forma-arrotondato { border-radius:.5rem; }

.yr-empty { text-align:center; padding:3rem 1.5rem; color:var(--text-muted); }
.yr-empty i { font-size:2.5rem; opacity:.35; display:block; margin-bottom:.75rem; }

.yr-skeleton { background:linear-gradient(90deg, rgba(0,0,0,.06) 25%, rgba(0,0,0,.11) 37%, rgba(0,0,0,.06) 63%); background-size:400% 100%; animation:yrSkeleton 1.4s ease infinite; border-radius:.375rem; }
@keyframes yrSkeleton { 0% { background-position:100% 50%; } 100% { background-position:0 50%; } }

/* BUG GRAVE (risolto): qui c'era un override che forzava z-index:99999 sull'header per un
   presunto problema di "non resta fisso in scroll" — il tema ha GIÀ .app-header{position:fixed;
   z-index:100} come regola di base (verificato in styles.min.css), quindi non serviva affatto.
   Quello z-index:99999 sfondava la scala del tema (sidebar 102-103, modal-backdrop 104, modal
   105): l'header finiva SOPRA ogni modale del software, tagliandole tutte in cima o rendendole
   vuote (segnalato: "Crea ticket" senza campi, "Nuovo contatto" con la testata tagliata dietro
   l'header). In più l'inset-inline-start:15rem duplicava — sommandosi — il padding-inline-start
   già gestito responsivamente dal blocco esistente alle righe ~164-182, un secondo motivo
   plausibile dietro il vecchio bug "hamburger spostato a destra". Resta solo l'hint GPU per il
   lampo di contenuto durante uno scroll reale (§ non riproducibile in test automatico), che non
   tocca position/z-index/inset e quindi non interferisce più con le modali. */
.app-header { will-change:transform; transform:translateZ(0); backface-visibility:hidden; }
[data-menu-position="fixed"] .app-sidebar { will-change:transform; transform:translateZ(0); backface-visibility:hidden; }

/* Barra di impersonificazione (views/layout/impersonazione.php). Fissa in basso: header
   e sidebar Ynex sono già position:fixed, una barra in cima li sposterebbe entrambi. */
.yr-impersona-barra {
  position:fixed; inset-inline:0; bottom:0; z-index:1080;
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
  padding:.5rem 1rem; background:#b45309; color:#fff;
  box-shadow:0 -2px 12px rgba(0,0,0,.25); font-size:.8125rem;
}
.yr-impersona-testo { display:flex; align-items:center; gap:.5rem; min-width:0; }
.yr-impersona-barra strong { font-weight:600; }
.yr-impersona-ruolo, .yr-impersona-origine {
  padding:.1rem .45rem; border-radius:.35rem; background:rgba(255,255,255,.18); font-size:.6875rem;
}
.yr-impersona-origine { opacity:.85; }
/* Lo spazio in fondo alla pagina evita che la barra copra l'ultima riga di una tabella. */
body:has(.yr-impersona-barra) .main-content { padding-block-end:3.5rem; }

/* Menu dei filtri (views/components/chips.php: filtro_menu). Sostituisce la fila di
   chip sopra la tabella: stessi filtri, stessi conteggi, senza rubare una riga intera
   in cima alla pagina. */
.yr-filtro-menu { min-width: 232px; padding: .35rem; }
.yr-filtro-menu .dropdown-item { border-radius: .4rem; padding: .45rem .6rem; }
/* Serve !important, come per .yr-selmenu: il tema colora .dropdown-item.active di viola
   pieno, e senza vincere la cascata restava il testo scuro su fondo scuro — illeggibile.
   Stesso aspetto degli altri menu dell'app: fondo tenue e testo del colore primario. */
.yr-filtro-menu .dropdown-item.active,
.yr-filtro-menu .dropdown-item:active {
  background: rgba(var(--primary-rgb), .12) !important;
  color: rgb(var(--primary-text-rgb)) !important;
}
/* Il conteggio della voce attiva sta su fondo chiaro, non più sul viola pieno. */
.yr-filtro-menu .dropdown-item.active .badge {
  background: rgba(var(--primary-rgb), .18) !important;
  color: rgb(var(--primary-text-rgb)) !important;
}
.yr-filtro-menu .dropdown-item .badge { font-weight: 600; }

/* Nota di aiuto (views/components/nota.php): icona discreta accanto al titolo della card.
   Sostituisce i riquadri colorati che spiegavano una regola occupando una fascia intera. */
.yr-nota { border-color: transparent; }
.yr-nota:hover, .yr-nota:focus { border-color: rgba(var(--primary-rgb), .3); color: rgb(var(--primary-rgb)) !important; }
.popover { max-width: 320px; }
.popover .popover-header { font-size: .8125rem; font-weight: 600; }
.popover .popover-body { font-size: .75rem; line-height: 1.5; }

/* Select personalizzato (views/components/select_custom.php): l'etichetta scelta deve
   restare su una riga sola. Un nome prodotto lungo mandava il testo a capo, il controllo
   diventava alto il doppio e trascinava fuori asse tutto ciò che gli stava accanto —
   etichette, campi e pulsanti allineati in fondo. */
.yr-select [data-yr-select-btn] { min-width: 0; }
.yr-select [data-yr-select-testo] {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.yr-select [data-yr-select-btn] > i { flex-shrink: 0; margin-inline-start: .5rem; }

/* Zona di caricamento (views/components/upload.php + assets/js/upload.js).

   La struttura la disegna l'Uploader di Syncfusion, il vestito è tutto qui: del loro CSS
   non si carica niente, porterebbe un tema completo (bordi, altezze, il font e-icons) da
   ricondurre riga per riga a quello di Ynex. Le classi che iniziano per `e-` sono i loro
   agganci, quelle `yr-up-` sono nostre.

   Bassa di proposito: è un campo di un form, non una pagina. Un riquadro alto quanto tre
   campi sposta in fondo tutto quello che viene dopo, e chi compila il modulo si trova la
   foto — che è facoltativa — al centro dell'attenzione. */
.yr-up-zona {
  border: 1px dashed var(--default-border);
  border-radius: .5rem;
  padding: .75rem .9rem;
  background: var(--custom-white);
  transition: border-color .15s, background-color .15s;
}
.yr-up-zona.e-upload-drag-hover {
  border-color: rgb(var(--primary-rgb));
  background: rgba(var(--primary-rgb), .04);
}

/* L'invito su una riga sola: icona, testo, "sfoglia" e l'aiuto di seguito. */
.yr-up-invito {
  display: flex;
  align-items: center;
  gap: .6rem;
  pointer-events: none; /* il trascinamento deve cadere sulla zona, non sul testo */
}
.yr-up-invito-icona {
  width: 30px; height: 30px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  background: rgba(var(--primary-rgb), .1);
  color: rgb(var(--primary-rgb));
  font-size: 1rem;
}
.yr-up-invito-testo { font-size: .8125rem; color: var(--default-text-color); min-width: 0; }
.yr-up-invito-aiuto {
  display: block;
  font-size: .6875rem;
  color: var(--text-muted);
}
.yr-up-sfoglia {
  pointer-events: auto;
  border: 0; background: none; padding: 0;
  color: rgb(var(--primary-rgb));
  font-weight: 600;
  text-decoration: underline;
}

/* L'elenco dei file. `e-upload-files` è la lista di Syncfusion, spostata qui dentro dal JS. */
.yr-up-elenco:empty { display: none; }
.yr-up-zona.ha-file .yr-up-elenco {
  margin-top: .7rem;
  padding-top: .7rem;
  border-top: 1px solid var(--default-border);
}
.yr-up-elenco .e-upload-files { list-style: none; margin: 0; padding: 0; }
.yr-up-elenco .e-upload-file-list { padding: 0; border: 0; }
.yr-up-riga {
  display: flex; align-items: center; gap: .6rem;
  padding: .35rem 0;
}
.yr-up-elenco .e-upload-file-list + .e-upload-file-list .yr-up-riga {
  border-top: 1px solid var(--default-border);
}
.yr-up-icona {
  width: 32px; height: 32px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  background: rgba(var(--light-rgb), .6);
  color: var(--text-muted);
  overflow: hidden;
}
.yr-up-icona.ha-anteprima { background: none; }
.yr-up-icona img { width: 100%; height: 100%; object-fit: cover; }
.yr-up-testo { flex: 1 1 auto; min-width: 0; }
.yr-up-nome {
  font-size: .8125rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.yr-up-stato { font-size: .6875rem; color: var(--text-muted); }

/* La barra sparisce quando non serve più: a caricamento finito conta il testo di stato,
   e una barra piena al 100% che resta lì fa sembrare che ci sia ancora qualcosa in corso. */
.yr-up-barra {
  height: 3px; border-radius: 3px;
  background: rgba(var(--light-rgb), .8);
  margin-top: .25rem; overflow: hidden;
  max-width: 260px;
}
.yr-up-barra span {
  display: block; height: 100%; width: 0;
  border-radius: 3px;
  background: rgb(var(--primary-rgb));
  transition: width .2s linear;
}
.yr-up-riga.is-fatto .yr-up-barra,
.yr-up-riga.is-errore .yr-up-barra { display: none; }
.yr-up-riga.is-fatto .yr-up-stato { color: rgb(var(--success-rgb)); }
.yr-up-riga.is-errore .yr-up-stato { color: rgb(var(--danger-rgb)); }
.yr-up-riga.is-errore .yr-up-icona { background: rgba(var(--danger-rgb), .1); color: rgb(var(--danger-rgb)); }

.yr-up-togli {
  flex-shrink: 0;
  width: 26px; height: 26px;
  border: 0; border-radius: 6px;
  background: none; color: var(--text-muted);
  display: inline-flex; align-items: center; justify-content: center;
}
.yr-up-togli:hover { background: rgba(var(--danger-rgb), .1); color: rgb(var(--danger-rgb)); }

/* Syncfusion aggiunge una propria intestazione e i propri pulsanti alla lista: nel nostro
   modello di riga non servono, il "togli" è già dentro ogni riga. */
.yr-up .e-upload-actions,
.yr-up .e-file-select-wrap,
.yr-up .e-upload-file-list .e-icons { display: none !important; }
.yr-up.e-upload { border: 0; padding: 0; }

/* L'anteprima del file già presente. Senza JavaScript resta nel suo blocco sopra la
   zona; con il JavaScript prende il posto dell'icona dentro la riga dell'invito. */
.yr-upload-attuale img { width: 36px; height: 36px; object-fit: cover; }
.yr-up-attuale {
  width: 38px; height: 38px; flex-shrink: 0;
  border-radius: 8px; overflow: hidden;
  border: 1px solid var(--default-border);
}
.yr-up-attuale img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Chip selezionabili (attributi multi-valore, mesi di stagionalità) e riquadri di scelta
   (tracciabilità). Sono caselle e radio vere, nascoste: così la tastiera continua a
   funzionare e il form si invia da solo, senza JavaScript che tenga lo stato. */
.yr-chip {
  display: inline-flex; align-items: center;
  padding: .3rem .65rem;
  border: 1px solid var(--default-border);
  border-radius: 999px;
  font-size: .75rem;
  cursor: pointer;
  user-select: none;
  transition: border-color .12s, background-color .12s, color .12s;
}
.yr-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.yr-chip:hover { border-color: rgba(var(--primary-rgb), .5); }
.yr-chip.is-scelto {
  border-color: rgb(var(--primary-rgb));
  background: rgba(var(--primary-rgb), .1);
  color: rgb(var(--primary-rgb));
  font-weight: 600;
}
.yr-chip:focus-within { outline: 2px solid rgba(var(--primary-rgb), .35); outline-offset: 1px; }

.yr-scelta {
  display: block; height: 100%;
  padding: .6rem .75rem;
  border: 1px solid var(--default-border);
  border-radius: .5rem;
  cursor: pointer;
  color: var(--default-text-color);
  transition: border-color .12s, background-color .12s;
}
.yr-scelta input { position: absolute; opacity: 0; width: 0; height: 0; }
.yr-scelta span:last-child { color: var(--text-muted); }
.yr-scelta:hover { border-color: rgba(var(--primary-rgb), .5); }
.yr-scelta.is-scelto {
  border-color: rgb(var(--primary-rgb));
  background: rgb(var(--primary-rgb));
  /* Non --primary-text-rgb: quello è il primario scurito per il fondo bianco, e stampato
     sul primario sparisce. Qui serve il colore che ci sta SOPRA. */
  color: rgb(var(--su-primario-rgb));
}
.yr-scelta.is-scelto span:last-child { color: rgb(var(--su-primario-rgb)); opacity: .8; }
.yr-scelta:focus-within { outline: 2px solid rgba(var(--primary-rgb), .35); outline-offset: 1px; }
/* Il "+ Altro" degli attributi: tratteggiato perché non è un valore ma un'azione. */
.yr-chip-altro {
  border-style: dashed;
  background: none;
  color: rgb(var(--primary-rgb));
  font-weight: 600;
}

/* "+ Altro…" nella tendina non è un valore: si stacca dagli altri e prende il colore
   dell'azione, così non lo si sceglie per sbaglio credendo sia un'opzione. */
.yr-selmenu .dropdown-item[data-valore="__altro"] {
  border-top: 1px solid var(--default-border);
  margin-top: .25rem;
  padding-top: .5rem;
  color: rgb(var(--primary-rgb));
  font-weight: 600;
}
/* Il mese corrente nella striscia della stagionalità: serve a capire se «Di stagione»
   si accende adesso o fra sei mesi, e senza un segno bisogna contare le caselle. */
.yr-chip-ora:not(.is-scelto) { border-style: dashed; border-color: rgba(var(--primary-rgb), .55); }
.yr-chip-ora::after {
  content: '';
  width: 4px; height: 4px; border-radius: 50%;
  background: rgb(var(--primary-rgb));
  margin-inline-start: .35rem;
}
.yr-chip-ora.is-scelto::after { background: rgb(var(--su-primario-rgb)); }

/* Le tessere delle vetrine: la spiegazione sotto il nome va a capo su alcune e non su
   altre, e con l'altezza libera la fila risultava a scalini. L'altezza minima le pareggia
   senza schiacciare quelle con due righe di testo. */
.yr-vetrina {
  min-height: 78px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.yr-vetrina [data-yr-vetrina-perche] { line-height: 1.45; }

/* Il conteggio sulla scheda attiva: un badge arancione o grigio chiaro sul primario pieno
   non si legge. Sull'attiva prende il colore che sta sopra il primario, come il testo. */
.nav-pills .nav-link.active .badge,
.nav-tabs .nav-link.active .badge {
  background: rgba(var(--su-primario-rgb), .22) !important;
  color: rgb(var(--su-primario-rgb)) !important;
}
/* La tendina staccata dal suo contenitore per non farsi ritagliare: deve stare sopra il
   corpo della modale, che ha un suo piano di sovrapposizione. */
.yr-selmenu.yr-selmenu-fisso { z-index: 1080; }

/* La banda informativa (views/components/nota.php): fondo tenue del colore primario, non
   un giallo d'avviso. Non segnala un problema — spiega una regola della schermata. */
.yr-banda {
  background: rgba(var(--primary-rgb), .07);
  border-radius: .5rem;
  padding: .7rem .9rem;
  color: rgb(var(--primary-rgb));
}
.yr-banda .fs-12 { color: var(--default-text-color); opacity: .85; }

/* Interruttore che invia un form (views: Prezzi del catalogo, Tassonomia).
   Non è la casella di Bootstrap perché deve stare dentro un <form> e comportarsi da
   pulsante; ma deve avere lo stesso aspetto in entrambi gli stati — prima lo spento era
   un pallino grigio senza binario, e non si capiva che fosse la stessa cosa dell'acceso. */
.yr-switch {
  --yr-sw-h: 22px;
  width: 40px; height: var(--yr-sw-h);
  flex-shrink: 0;
  padding: 0; border: 0;
  border-radius: 999px;
  background: rgba(var(--light-rgb), 1);
  box-shadow: inset 0 0 0 1px var(--default-border);
  position: relative;
  transition: background-color .15s, box-shadow .15s;
  cursor: pointer;
}
.yr-switch::after {
  content: '';
  position: absolute;
  top: 3px; inset-inline-start: 3px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
  transition: inset-inline-start .15s;
}
.yr-switch.is-acceso {
  background: rgb(var(--primary-rgb));
  box-shadow: none;
}
.yr-switch.is-acceso::after { inset-inline-start: 21px; }
.yr-switch:disabled { opacity: .5; cursor: default; }
.yr-switch:focus-visible { outline: 2px solid rgba(var(--primary-rgb), .4); outline-offset: 2px; }
/* Mentre la richiesta viaggia: nessuno spinner, solo il segnale che è in corso. */
.yr-switch.is-inCorso { opacity: .6; }

/* Il marchio nella barra laterale: esteso quando c'è spazio, corto nella striscia di sole
   icone. Ridimensionare quello esteso non basterebbe — a 5rem di larghezza si leggerebbe
   "yoreord". Entrambi stanno nel documento e sceglie il CSS: il cambio è immediato. */
.yr-logo-esteso { height: 32px; display: block; }
.yr-logo-corto { height: 30px; display: none; }
.yr-logo-cliente { height: 32px; max-width: 180px; display: block; object-fit: contain; }

html[data-toggled="icon-overlay-close"] .yr-logo-esteso { display: none; }
html[data-toggled="icon-overlay-close"] .yr-logo-corto { display: block; margin-inline: auto; }
html[data-toggled="icon-overlay-close"] .yr-logo-cliente { max-width: 44px; margin-inline: auto; }

/* Col mouse sopra, la striscia **non si allarga**: resta 80px. Quelle regole rimettevano
   il marchio esteso (largo 86px) e il nome per esteso dentro una barra che non cresceva —
   il logo usciva dal suo bordo e finiva sopra il contenuto. Era il difetto che si vedeva
   passando il mouse sulla barra chiusa.
   Quindi non si cambia: chiusa e` chiusa, con o senza il mouse sopra. */
html[data-toggled="icon-overlay-close"][data-icon-overlay="open"] .yr-logo-esteso { display: none; }
html[data-toggled="icon-overlay-close"][data-icon-overlay="open"] .yr-logo-corto { display: block; }
html[data-toggled="icon-overlay-close"][data-icon-overlay="open"] .yr-logo-cliente { max-width: 44px; }
.yr-switch.is-errore { box-shadow: inset 0 0 0 2px rgba(var(--danger-rgb), .6); }

/* La firma in fondo alla barra laterale: chi ha fatto il software, in piccolo e staccato
   dalla navigazione. Discreta di proposito — si alza di opacità solo al passaggio del
   mouse, perché è un'informazione che si cerca, non una che deve trovarti. */
.yr-firma {
  padding: 1.25rem .9rem 1rem;
  text-align: center;
  opacity: .38;
  transition: opacity .18s;
}
.yr-firma:hover { opacity: .8; }
/* `display` NON sul selettore generico: `.yr-firma img` batte `.yr-firma-corto` per
   specificità (classe + elemento contro classe sola), e i due marchi comparivano
   entrambi, uno sotto l'altro. Ognuno dichiara il proprio. */
.yr-firma img { margin-inline: auto; }
.yr-firma .yr-firma-esteso { width: 86px; display: block; }
.yr-firma .yr-firma-corto { width: 30px; display: none; }
.yr-firma-versione {
  margin-top: .35rem;
  font-size: .625rem;
  color: rgba(255, 255, 255, .75);
  letter-spacing: .02em;
}
/* Nella striscia di sole icone resta il marchio corto: quello esteso, largo 5rem, si
   leggerebbe "MORETT". */
html[data-toggled="icon-overlay-close"] .yr-firma { padding: 1rem .35rem .75rem; }
html[data-toggled="icon-overlay-close"] .yr-firma .yr-firma-esteso { display: none; }
html[data-toggled="icon-overlay-close"] .yr-firma .yr-firma-corto { display: block; }
/* La versione resta anche nella striscia, come sul gestionale precedente: e` la prima
   cosa che si guarda quando qualcosa non torna, e nasconderla obbliga a riaprire la barra
   per leggerla. Piu` piccola, perche' in 80px «v. 1.0.0» a misura piena riempie la riga. */
html[data-toggled="icon-overlay-close"] .yr-firma-versione { display: block; font-size: .5625rem; margin-top: .25rem; }
html[data-toggled="icon-overlay-close"][data-icon-overlay="open"] .yr-firma .yr-firma-esteso { display: none; }
html[data-toggled="icon-overlay-close"][data-icon-overlay="open"] .yr-firma .yr-firma-corto { display: block; }

/* Il pannello del campanello. Largo abbastanza da leggere un titolo su una riga sola:
   più stretto, ogni notifica va a capo e l'elenco diventa un muro. */
.yr-notifiche-menu { width: 360px; max-width: calc(100vw - 1.5rem); padding: 0; }
.yr-notifiche-elenco { max-height: 360px; overflow-y: auto; }
/* Nessuna riga di separazione fra le notifiche e nessuna evidenza sulle non lette: il
   pannello dice quante ne sono arrivate col pallino sul campanello, e dentro conta solo
   leggerle. Righe divise da bordi e sfondi diversi fanno sembrare un elenco corto un
   modulo da compilare. */
.yr-notifica { transition: background .15s ease; }
.yr-notifica:hover { background: rgba(var(--primary-rgb), .05); }

/* Non letta: fondo appena tinto, filetto a sinistra e un pallino a destra. Erano tutte
   uguali, e l'unico modo di sapere quante ne restavano da guardare era il numero sul
   campanello — che dice quante, non quali. Tre segnali insieme e non solo il colore:
   chi non distingue le tinte vede comunque il filetto e il pallino. */
.yr-notifica-nuova {
  background: rgba(var(--primary-rgb), .06);
  box-shadow: inset 3px 0 0 rgb(var(--primary-rgb));
}
.yr-notifica-nuova:hover { background: rgba(var(--primary-rgb), .1); }
.yr-notifica-pallino {
  width: .5rem; height: .5rem; border-radius: 50%;
  background: rgb(var(--primary-rgb));
  margin-top: .35rem;
}
/* Il pallino è ancorato al centro del campanello, non all'angolo del bersaglio cliccabile:
   il bersaglio è largo quanto serve al dito, e un pallino appeso al suo angolo galleggia
   lontano dall'icona a cui si riferisce. Il doppio translate lo tiene centrato sull'angolo
   alto-destro del glifo anche quando il numero passa a due cifre. */
.yr-campanello-pallino {
  position: absolute; top: 50%; inset-inline-start: 50%;
  transform: translate(-50%, -50%) translate(.45rem, -.5rem);
  display: flex; align-items: center; justify-content: center;
  min-width: .9375rem; height: .9375rem; padding: 0 .2rem;
  font-size: .5rem; font-weight: 600; line-height: 1;
}
.header-element .header-link { position: relative; }
.yr-clip2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* La freccia di un blocco che si apre segue lo stato del blocco, non un ricaricamento:
   ruotarla via CSS evita di dover ricostruire la pagina per girare un'icona. */
[data-bs-toggle="collapse"][aria-expanded="true"] .yr-freccia { transform: rotate(180deg); }
.yr-freccia { transition: transform .15s ease; }

/* Un gruppo di pulsanti che sostituisce un menu a tendina: acceso è quello scelto, e lo
   decide lo stato del radio. Deciderlo in PHP significava che cliccandone un altro
   restavano accesi in due finché non si ricaricava — cioè proprio la ricarica che questi
   pulsanti servono a evitare.

   Gli `!important` non sono pigrizia: il tema marca `!important` su tutte e tre le
   proprietà di `.btn-check:checked + .btn-outline-light`. Senza, vinceva il nostro colore
   del testo (bianco) e restava il loro sfondo (grigio chiarissimo) — l'opzione scelta
   diventava bianco su bianco, cioè l'unica delle cinque che non si leggeva. */
.btn-check:checked + .btn.btn-outline-light {
  background-color: rgb(var(--primary-rgb)) !important;
  border-color: rgb(var(--primary-rgb)) !important;
  color: rgb(var(--su-primario-rgb)) !important;
}
/* Il focus da tastiera resta visibile anche quando il pulsante è già acceso: senza, chi
   naviga con il tab perde il segno di dove si trova appena sceglie. */
.btn-check:focus-visible + .btn.btn-outline-light {
  box-shadow: 0 0 0 .2rem rgba(var(--primary-rgb), .35);
}

/* Un elenco verticale di scelte: cinque righe di cui una sola è quella presa. Il colore
   da solo non basta a dirlo — c'è chi non lo distingue, e in una schermata stampata o
   ricondivisa si perde comunque. Il segno di spunta lo dice senza dipendere dal colore,
   e lo spazio è riservato anche sulle righe non scelte così il testo non si sposta al
   momento del clic. */
.yr-scelte .btn {
  position: relative;
  padding-inline-start: 2rem;
}
.yr-scelte .btn::before {
  content: "";
  position: absolute;
  inset-inline-start: .7rem;
  top: 50%;
  transform: translateY(-50%);
  width: .95rem;
  height: .95rem;
  border: 1px solid var(--default-border);
  border-radius: 50%;
}
.yr-scelte .btn-check:checked + .btn::before {
  border-color: rgb(var(--su-primario-rgb));
  background: rgb(var(--su-primario-rgb));
  box-shadow: inset 0 0 0 .22rem rgb(var(--primary-rgb));
}


/* ── Editor delle note ─────────────────────────────────────────────────────────
   La textarea resta il campo vero, ma sparisce dalla vista quando l'editor c'è: senza
   JavaScript non ha nessuna di queste classi e resta un normale campo di testo. */
.yr-editor-sorgente { display: none; }
.yr-editor-barra {
  display: flex; flex-wrap: wrap; gap: .25rem; margin-bottom: .375rem;
}
.yr-editor-barra .btn { padding: .2rem .45rem; line-height: 1; }
.yr-editor-corpo {
  min-height: 6.5rem; height: auto; overflow-y: auto; max-height: 22rem;
  font-size: .8125rem; line-height: 1.5;
}
.yr-editor-corpo:focus {
  outline: 0;
  border-color: rgb(var(--primary-rgb));
  box-shadow: 0 0 0 .15rem rgba(var(--primary-rgb), .15);
}
/* Il segnaposto di un contenteditable non esiste: si disegna, e solo quando è vuoto
   davvero — `:empty` non basta perché il browser ci lascia dentro un <br>. */
.yr-editor-corpo:empty::before,
.yr-editor-corpo > p:only-child:empty::before {
  content: attr(data-vuoto);
  color: var(--text-muted);
}
.yr-editor-corpo p { margin-bottom: .5rem; }
.yr-editor-corpo p:last-child { margin-bottom: 0; }
.yr-editor-corpo ul, .yr-editor-corpo ol { margin-bottom: .5rem; padding-inline-start: 1.25rem; }

/* Le note già scritte, quando si leggono e non si modificano: stessa resa dell'editor,
   così quello che si vede in modifica è quello che si vede dopo. */
.yr-nota-ricca p { margin-bottom: .5rem; }
.yr-nota-ricca p:last-child { margin-bottom: 0; }
.yr-nota-ricca ul, .yr-nota-ricca ol { margin-bottom: .5rem; padding-inline-start: 1.25rem; }
.yr-nota-ricca:last-child { margin-bottom: 0; }

/* ── La navigazione del telefono ────────────────────────────────────────────────
   Sotto i 768px la sidebar sparisce e comanda una barra fissa in basso: sta sotto il
   pollice, resta visibile mentre si legge e dice sempre dove si è, invece di costare due
   gesti (apri il menu, scegli) per ogni spostamento.

   `env(safe-area-inset-bottom)` non è decorazione: sull'iPhone senza tasto la striscia
   della barra di sistema si mangerebbe l'ultima riga di icone. Il `padding-bottom` sul
   contenuto serve allo stesso motivo dall'altra parte: senza, l'ultima riga di una
   tabella resta sempre coperta dalla barra. */
.yr-btm, .yr-alt, .yr-alt-vel { display: none; }

@media (max-width: 767.98px) {
  .yr-btm {
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 1030; display: flex;
    background: var(--custom-white, #fff);
    border-top: 1px solid var(--default-border, #dfe3ec);
    box-shadow: 0 -2px 12px rgba(30, 32, 50, .07);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .yr-btm-a {
    flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 3px; padding: 6px 2px; text-decoration: none;
    /* 52px è la misura minima di un bersaglio che si prende con il pollice senza
       sbagliare: sotto, si centra il vicino. */
    min-height: 52px; border: 0; background: none; color: var(--text-muted, #666b7d);
  }
  .yr-btm-a.on { color: rgb(var(--primary-rgb)); }
  .yr-btm-i { position: relative; display: block; font-size: 20px; line-height: 1; }
  .yr-btm-l {
    font-size: 10.5px; font-weight: 500; line-height: 1.2; text-align: center;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .yr-btm-a.on .yr-btm-l { font-weight: 600; }

  /* Il foglio con le voci che non entrano nella barra. */
  .yr-alt-vel:not(.d-none) { display: block; position: fixed; inset: 0; z-index: 1035; background: rgba(30, 32, 50, .42); }
  .yr-alt:not(.d-none) {
    display: block; position: fixed; left: 0; right: 0; z-index: 1040;
    bottom: calc(64px + env(safe-area-inset-bottom));
    background: var(--custom-white, #fff);
    border-top: 1px solid var(--default-border, #dfe3ec);
    border-radius: 14px 14px 0 0; box-shadow: 0 -8px 28px rgba(30, 32, 50, .18);
    max-height: 66vh; overflow-y: auto;
  }
  .yr-alt-h { display: flex; align-items: center; gap: 8px; padding: 14px 16px 8px; }
  .yr-alt-t { font-size: 13px; font-weight: 600; flex: 1; color: var(--default-text-color); }
  .yr-alt-x {
    width: 34px; height: 34px; border: 0; border-radius: 8px; font-size: 18px;
    background: var(--default-background, #f6f7fa); color: var(--text-muted, #5c6070);
  }
  .yr-alt-a {
    display: flex; align-items: center; gap: 12px; padding: 13px 16px; min-height: 52px;
    text-decoration: none; font-size: 14px; font-weight: 500;
    color: var(--default-text-color, #23252e);
    border-top: 1px solid var(--default-border, #f1f3f8);
  }
  .yr-alt-a i { font-size: 19px; color: var(--text-muted, #666b7d); flex: none; }
  .yr-alt-a.on { color: rgb(var(--primary-rgb)); background: rgba(var(--primary-rgb), .06); }
  .yr-alt-a.on i { color: rgb(var(--primary-rgb)); }
  .yr-alt-l { flex: 1; min-width: 0; }

  /* Con la barra in basso il menu a scomparsa non serve più: due navigazioni per la
     stessa cosa si contraddicono appena una delle due cambia. */
  .app-sidebar { display: none !important; }
  .app-header .sidemenu-toggle { display: none !important; }
  html body .main-content {
    max-width: 100% !important; margin-inline-start: 0 !important;
    padding-bottom: 76px !important;
  }
}

/* ── Tabelle ripiegate ──────────────────────────────────────────────────────────
   Le colonne che non entrano spariscono (`yr-col-via`) e ricompaiono nella riga che si
   apre sotto. Vale a ogni larghezza, non solo sul telefono: una tabella con dodici
   colonne su un portatile stretto ha lo stesso problema. */
.yr-col-via { display: none !important; }

.yr-piu {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-inline-end: 10px; padding: 0; flex: none;
  border: 1px solid var(--default-border); border-radius: 6px;
  background: var(--default-background); color: rgb(var(--primary-rgb));
  font-size: 15px; line-height: 1; vertical-align: middle;
}
.yr-piu:hover { background: rgba(var(--primary-rgb), .1); }
/* Il bersaglio vero e` piu` grande di quello che si vede: 26px disegnati stanno bene in
   una riga di tabella, ma un dito ne vuole almeno 40, e i pochi millimetri di scarto
   finivano sul collegamento accanto — cioe` sulla scheda invece che sul dettaglio. */
.yr-piu { position: relative; touch-action: manipulation; }
.yr-piu::after { content: ''; position: absolute; inset: -8px -7px; }
.yr-vai { touch-action: manipulation; }
/* Senza `manipulation` il browser aspetta di capire se e` un doppio tocco, e quel ritardo
   e` proprio quello che fa arrivare il clic quando la riga si e` gia` aperta. */
.yr-tab-resp a, .yr-tab-resp .yr-piu { touch-action: manipulation; }

/* La freccia che porta alla scheda. Larga sempre uguale, cosi` non viene tagliata come
   il pulsante «Apri», e staccata dal «piu`»: sono i due gesti che non devono confondersi. */
.yr-vai {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 8px;
  color: var(--text-muted); font-size: 22px; text-decoration: none;
}
.yr-vai:hover { background: var(--default-background); color: rgb(var(--primary-rgb)); }

/* Tutta la riga apre il dettaglio: si vede che si puo` toccare. */
.yr-riga-tocca { cursor: pointer; }
tr.yr-aperta > td { border-bottom-color: transparent; }
tr.yr-aperta { background: var(--default-background); }

.yr-figlia > td { background: var(--default-background); padding: .25rem 1rem 1rem; }
.yr-figlia-dati {
  display: grid; grid-template-columns: minmax(6rem, auto) 1fr;
  gap: .35rem .9rem; margin: 0; white-space: normal;
}
.yr-figlia-dati dt { font-size: 11px; font-weight: 500; color: var(--text-muted); }
.yr-figlia-dati dd { margin: 0; font-size: 13px; }
/* I pulsanti veri stanno qui, dove l'etichetta ci sta per intero. */
.yr-figlia-azioni {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
  margin-top: .75rem; padding-top: .75rem; border-top: 1px solid var(--default-border);
}
.yr-figlia-azioni form { margin: 0; }

@media (max-width: 991.98px) {
  /* Una tabella ripiegata non deve piu` scorrere di lato: se scorre vuol dire che il
     ripiegamento non e` bastato, e lo scorrimento resta l'ultima rete di sicurezza —
     ma le celle possono andare a capo invece di stare per forza su una riga. */
  /* Il testo va a capo **solo dopo** che il ripiegamento e` avvenuto. Se andasse a capo
     sempre, la tabella non straborderebbe mai: `adatta()` misura `scrollWidth` contro la
     larghezza del contenitore, non troverebbe nulla da nascondere, e resterebbero dodici
     colonne strizzate a una parola per riga. E` esattamente com'era. */
  .yr-tab-resp.yr-ripiegata { white-space: normal; }
  .yr-tab-resp td, .yr-tab-resp th { padding-inline: .5rem; }

  /* `.yr-clip` taglia con i puntini a una larghezza pensata per il desktop (`max-width`
     scritto sul posto). Ripiegata la tabella quella larghezza e` piu` grande dello
     schermo: i puntini finiscono fuori dalla vista e il nome sembra tagliato di netto
     contro il bordo — che e` peggio del troncamento, perche' non si vede nemmeno che
     manca qualcosa. Su una riga sola il nome del prodotto va a capo: e` l'unica cosa
     rimasta a dire di che prodotto si tratta, e leggerlo per intero conta piu` che
     tenere basse le righe. `!important` perche' la larghezza e` un attributo `style`. */
  .yr-tab-resp.yr-ripiegata .yr-clip {
    white-space: normal; overflow: visible; text-overflow: clip;
    max-width: 100% !important; min-width: 0;
  }
}

/* Il «piu`» e il contenuto della cella stanno affiancati, non impilati: dentro le celle
   ci sono blocchi (avatar + ragione sociale + partita IVA) e un bottone inserito davanti
   li spingerebbe a capo, raddoppiando l'altezza di ogni riga. */
td.yr-cella-piu { display: flex; align-items: center; }
td.yr-cella-piu > .yr-cella-corpo { flex: 1 1 auto; min-width: 0; }

/* ── Fasce di pillole che scorrono ──────────────────────────────────────────────
   Venti flussi mandati a capo su un telefono occupano lo schermo intero e la pagina
   comincia sotto il bordo. Qui lo scorrimento e` la scelta giusta — e non lo e` quasi
   mai — perche' le pillole sono tutte uguali fra loro: si scorre per cercarne una, non
   si legge in ordine, e quella scelta resta comunque visibile perche' e` la prima. */
.yr-pills { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; min-width: 0; }

@media (max-width: 991.98px) {
  .yr-pills {
    flex-wrap: nowrap; overflow-x: auto; width: 100%;
    /* La spinta al margine dice che c'e` dell'altro di lato: senza, la fascia sembra
       finire dove finisce lo schermo. */
    padding-bottom: 6px; scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
  }
  .yr-pills > * { flex: 0 0 auto; scroll-snap-align: start; }
  .yr-pills::-webkit-scrollbar { height: 3px; }
  .yr-pills::-webkit-scrollbar-thumb { background: var(--default-border); border-radius: 3px; }
}

/* La card appena arrivata in una colonna della bacheca: un lampo breve, quanto basta a
   ritrovarla con l'occhio dopo il rilascio. Senza ricaricare la pagina, e` l'unica cosa
   che dice «e` andata a buon fine». */
.yr-kb-arrivata { box-shadow: 0 0 0 2px rgba(var(--primary-rgb), .55); transition: box-shadow .3s; }
@media (prefers-reduced-motion: reduce) { .yr-kb-arrivata { transition: none; } }

/* ── Comandi a sola icona sul telefono ──────────────────────────────────────────
   Quattro pulsanti scritti per esteso vanno a capo su due righe e spingono giu` il
   contenuto: sulla scheda di un documento il documento cominciava sotto il bordo. Sotto
   i 768px le etichette dei comandi **secondari** spariscono e resta l'icona.

   L'azione principale la sua etichetta la tiene, e non e` un dettaglio: un'icona sola va
   bene per «torna indietro» o «scarica il PDF», che si indovinano; non per «Conferma ed
   evadi», che cambia lo stato di un ordine. Chi non e` sicuro di cosa fa un pulsante,
   quel pulsante non lo preme — o peggio, lo preme e scopre dopo.

   L'etichetta resta nel documento come `title`/`aria-label`, quindi il nome del comando
   non si perde per chi usa uno screen reader o tiene premuto. */
@media (max-width: 991.98px) {
  .yr-azioni-icone .yr-et { display: none; }
  .yr-azioni-icone .btn { padding-inline: .7rem; }
  .yr-azioni-icone .btn i { margin-inline-end: 0 !important; font-size: 1.05rem; }
}

/* La casella di ricerca: 210px fissi stanno bene su un monitor e mangiano meta` schermo
   su un telefono. Larghezza fissa dove c'e` spazio, elastica dove non ce n'e`. */
.yr-cerca { width: 210px; }
@media (max-width: 991.98px) {
  .yr-cerca { width: auto; min-width: 0; flex: 1 1 8rem; }
  .yr-azioni-icone .btn-group .btn { padding-inline: .7rem; }
}

/* ── Agenda sul telefono ────────────────────────────────────────────────────────
   La vista calendario resta: e` quella che si e` venuti a guardare. Cambia il contorno.
   La colonna dei filtri veniva **prima** e spingeva il calendario milleottocento pixel
   piu` giu`; adesso passa dietro, e i tipi di evento stanno dentro un'altezza massima
   invece di occupare mezzo schermo.

   Nella griglia il titolo di un evento non ci sta — una cella e` larga cinquanta pixel e
   diventava «14…», cioe` niente. Resta l'ora, che in un calendario e` l'informazione che
   si cerca davvero guardando un giorno; il titolo si legge toccando. */
@media (max-width: 767.98px) {
  .yr-agenda-cal { order: -1; }
  .yr-agenda-corpo { display: flex; flex-direction: column; }
  .yr-agenda-comandi { order: -2; border-top: 0 !important; }
  .yr-agenda-tipi { order: -1; max-height: 42vh; overflow-y: auto; }

  .yr-cal-d { min-height: 74px; padding: .3rem .2rem; }
  .yr-cal-ev { padding: 1px 3px; font-size: 10px; line-height: 1.35; }
  /* Il titolo esce, l'ora resta: `yr-cal-ora` la stampa la vista. */
  .yr-cal-ev .yr-cal-titolo { display: none; }
  .yr-cal-head > div { font-size: 9px; }
}

/* ── Agenda: gesti e attesa ─────────────────────────────────────────────────────
   La zona che si sostituisce sbiadisce mentre arriva la risposta. Non e` decorazione:
   senza il ricaricamento della pagina non c'e` piu` la barra del browser a dire che sta
   succedendo qualcosa, e due clic di fila sulla freccia del mese sembrerebbero persi. */
.yr-ag-attesa { opacity: .55; pointer-events: none; transition: opacity .12s; }

/* Il messaggio dopo un'azione: senza ricaricamento non c'e` piu` il flash della pagina. */
.yr-ag-avviso {
  position: fixed; left: 50%; transform: translateX(-50%); z-index: 1090;
  bottom: calc(1rem + env(safe-area-inset-bottom)); margin: 0; box-shadow: 0 6px 24px rgba(30, 32, 50, .18);
  max-width: min(92vw, 30rem);
}
@media (max-width: 767.98px) { .yr-ag-avviso { bottom: calc(76px + env(safe-area-inset-bottom)); } }

/* Un giorno vuoto si puo` cliccare per crearci un evento. */
.yr-cal-nuovo { cursor: pointer; }
.yr-cal-nuovo:hover { background: rgba(var(--primary-rgb), .04); }

/* Il trascinamento coi puntatori: funziona anche col dito, dove il `draggable` di HTML
   non esiste. Durante il trascinamento la pagina non deve scorrere sotto le dita. */
body.yr-trascino { touch-action: none; user-select: none; }
.yr-cal-fantasma {
  position: fixed; z-index: 1080; pointer-events: none; opacity: .9;
  box-shadow: 0 6px 18px rgba(30, 32, 50, .25); border-radius: 6px;
}
.yr-cal-drop-over { background: rgba(var(--primary-rgb), .12) !important; outline: 2px dashed rgba(var(--primary-rgb), .5); outline-offset: -2px; }
[data-evento-trascina] { touch-action: pan-y; }

/* Un evento che dura piu` giorni: la barra continua da una cella all'altra. Gli angoli
   dicono dove comincia e dove finisce — squadrati a destra vuol dire «segue domani»,
   squadrati a sinistra «veniva da ieri» — cosi` non serve leggere per capirlo. */
/* Una **fascia sola** che attraversa la settimana, come su yoFornitori: il nome all'inizio
   della riga, e poi la banda che corre fino a dove l'evento finisce.

   Tecnicamente restano barre per cella — la griglia e` una cella per giorno — ma i margini
   negativi mangiano il padding e il bordo della cella (7px + 1px), quindi si toccano e si
   leggono come una cosa sola. Gli angoli arrotondati stanno solo ai due capi veri.

   `min-height` non e` cosmesi: una barra di continuazione non ha ne` pallino ne` titolo, e
   senza altezza minima resta alta due pixel — cioe` invisibile. E` esattamente il difetto
   che aveva la prima versione: le barre c'erano nel documento e non si vedevano. */
.yr-cal-ev { min-height: 17px; }
.yr-cal-ev-cont {
  border-left-width: 0 !important;
  border-top-left-radius: 0; border-bottom-left-radius: 0;
  margin-left: -7px; padding-left: 7px;
}
.yr-cal-ev-segue {
  border-top-right-radius: 0; border-bottom-right-radius: 0;
  margin-right: -8px; padding-right: 8px;
}
/* La domenica la riga finisce: li` la fascia si chiude comunque, altrimenti sborda oltre
   il bordo della griglia. */
.yr-cal-d:nth-child(7n) .yr-cal-ev-segue { margin-right: -7px; }
.yr-cal-segue { opacity: .55; font-weight: 400; }

@media (max-width: 767.98px) {
  /* Le celle hanno meno padding: i margini che le ricuciono valgono meno. */
  .yr-cal-ev-cont { margin-left: -3.2px; padding-left: 3.2px; }
  .yr-cal-ev-segue { margin-right: -4.2px; padding-right: 4.2px; }
  .yr-cal-d:nth-child(7n) .yr-cal-ev-segue { margin-right: -3.2px; }
}

/* La banda di un evento lungo: piu` piena di un'etichetta di un giorno, perche' deve
   leggersi come una cosa sola che attraversa la settimana. */
.yr-cal-banda { font-weight: 600; }
.yr-cal-banda .yr-cal-titolo { color: #1f2330; }
:root[data-theme-mode="dark"] .yr-cal-banda .yr-cal-titolo { color: #f2f4f8; }

/* ── Scelta multipla a tendina (select_multiplo.php) ─────────────────────────
   Chiusa occupa una riga: con mille aziende un elenco sempre aperto farebbe una finestra
   infinita. L'elenco si apre sotto, nel flusso — dentro una finestra che scorre, un
   pannello che fluttua viene tagliato dal bordo, e lo si scopre solo quando il campo
   capita in fondo. */
.yr-selm { border: 1px solid var(--default-border); border-radius: 6px; }
.yr-selm-apri {
  display: flex; align-items: center; gap: .5rem; width: 100%; text-align: start;
  padding: .35rem .5rem; min-height: 2.35rem; border: 0; border-radius: 6px;
  background: transparent; color: inherit;
}
.yr-selm-aperta { border-color: rgba(var(--primary-rgb), .55); }
.yr-selm-scelte { display: flex; flex-wrap: wrap; gap: .25rem; align-items: center; flex: 1 1 auto; min-width: 0; }
.yr-selm-freccia { flex: none; color: var(--text-muted); transition: transform .15s; }
.yr-selm-aperta .yr-selm-freccia { transform: rotate(180deg); }
.yr-selm-chip {
  display: inline-flex; align-items: center; gap: .25rem; max-width: 14rem;
  padding: .05rem .3rem .05rem .45rem; border-radius: 4px;
  background: rgba(var(--primary-rgb), .12); color: rgb(var(--primary-text-rgb));
  font-size: 11.5px; font-weight: 500; line-height: 1.7;
}
.yr-selm-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.yr-selm-chip i { font-size: 13px; opacity: .7; cursor: pointer; }
.yr-selm-chip i:hover { opacity: 1; }
/* Staccato dal flusso: aperto non deve allungare la finestra che lo contiene. */
.yr-selm-pannello {
  z-index: 1080; background: var(--custom-white, #fff);
  border: 1px solid var(--default-border); border-radius: 6px;
  box-shadow: 0 8px 24px rgba(30, 32, 50, .18);
  display: flex; flex-direction: column; overflow: hidden;
}
.yr-selm-filtro { border: 0; border-bottom: 1px solid var(--default-border); border-radius: 0; flex: none; }
.yr-selm-filtro:focus { box-shadow: none; }
.yr-selm-lista { overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.yr-selm-riga { display: flex; align-items: center; gap: .5rem; padding: .35rem .6rem; margin: 0; cursor: pointer; }
.yr-selm-riga:hover { background: var(--default-background); }

/* La scheda di un evento: coppie etichetta/valore, non un modulo. L'etichetta stretta e in
   grigio, il valore che si legge — cosi` l'occhio scende sui valori e non sulle etichette. */
.yr-ev-dati { display: grid; grid-template-columns: minmax(5.5rem, auto) 1fr; gap: .5rem .9rem; margin: 0; }
.yr-ev-dati dt { font-size: 11px; font-weight: 500; color: var(--text-muted); padding-top: .1rem; }
.yr-ev-dati dd { margin: 0; font-size: 14px; }

/* ── Caselle di spunta: si devono vedere anche da spente ────────────────────────
   Il bordo predefinito e` cosi` chiaro che una casella vuota si confonde con lo sfondo
   della riga: si vede solo dopo averla spuntata, cioe` quando non serve piu`. Chi scorre
   un elenco deve capire che c'e` qualcosa da spuntare **prima** di provarci. */
.form-check-input:not(:checked):not(:indeterminate) {
  border-color: var(--text-muted);
  border-width: 1.5px;
  background-color: var(--custom-white, #fff);
}
.form-check-input:not(:checked):hover { border-color: rgb(var(--primary-rgb)); }

/* ── Il primario che si vede anche quando e` chiarissimo ────────────────────────
   Il testo sopra il primario si adatta gia`; la superficie no. Con un primario molto
   chiaro — il bianco e` il caso limite — un pulsante primario su pagina bianca ha il testo
   leggibile e **nessuna forma**: non si vede che c'e` un pulsante. Il contorno lo disegna.

   Per un colore normale `--primario-bordo-rgb` coincide col primario e questo bordo non si
   nota; per uno chiaro diventa una riga piu` scura. Cosi` il colore scelto resta quello
   scelto: non lo si corregge alle spalle di chi l'ha scelto, gli si da` un bordo. */
/* Il tema scrive `color:#fff!important` sul pulsante primario: con un primario chiaro
   diventa bianco su bianco. `--su-primario-rgb` esisteva gia` e nessuno lo usava qui — la
   macchina c'era, non era attaccata a niente. Serve `!important` per la stessa ragione per
   cui serviva a loro. */
.btn-primary,
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.badge.bg-primary {
  color: rgb(var(--su-primario-rgb)) !important;
  border-color: rgb(var(--primario-bordo-rgb, var(--primary-rgb))) !important;
}
.btn-primary { border-width: 1px; border-style: solid; }
.btn-primary i, .btn-primary .badge { color: inherit; }

/* ── La firma in fondo alla sidebar, davvero in fondo ───────────────────────────
   `mt-auto` sulla firma non bastava: spinge verso il basso solo dentro un contenitore che
   arriva fino in fondo, e qui la colonna del menu era alta quanto le sue voci (640px) in
   una sidebar da 1000. Il risultato: la firma appiccicata sotto «Impostazioni», a meta`
   schermo. Serve la catena intera in colonna — dalla sidebar al menu — perche' l'ultimo
   anello possa spingere. */
.app-sidebar { display: flex; flex-direction: column; }
.app-sidebar .main-sidebar { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* Fra la sidebar e il menu ci sono cinque contenitori messi da simplebar (la barra di
   scorrimento su misura del tema). Sono loro a interrompere la catena: alti quanto il
   contenuto, non quanto la sidebar. Vanno tirati fino in fondo, o l'ultimo anello non ha
   niente contro cui spingere. */
.app-sidebar .simplebar-wrapper,
.app-sidebar .simplebar-mask,
.app-sidebar .simplebar-offset,
.app-sidebar .simplebar-content-wrapper { height: 100% !important; }
.app-sidebar .simplebar-content { min-height: 100%; display: flex; flex-direction: column; }
.app-sidebar .main-menu-container { flex: 1 1 auto; min-height: 0; }
/* Dentro la colonna, **solo la firma** scende in fondo. L'elenco delle voci aveva
   `flex: 1 1 auto` dal tema e si allungava lui, portandosi dietro «Impostazioni» a meta`
   schermo: il separatore e la voce delle impostazioni appartengono al menu, e devono
   restare attaccati alle altre voci. Lo spazio vuoto sta **dopo** di loro. */
.app-sidebar .main-menu.yr-menu-lavoro { flex: 0 0 auto; }
.app-sidebar .yr-firma { margin-top: auto !important; }

/* La ricerca dentro una tendina resta in cima mentre si scorre l'elenco.
   Con centocinquanta aziende bastano due giri di rotella per non vederla piu`, e da li` in
   poi sembra che non ci sia: si scorre tutto a mano credendo che non ci sia altro modo. */
.yr-selmenu [data-yr-select-filtro] { margin: 0; }
.yr-selmenu > div:has([data-yr-select-filtro]) {
  position: sticky; top: 0; z-index: 2;
  background: var(--custom-white, #fff);
  border-bottom: 1px solid var(--default-border);
}
/* `:has()` non c'e` su tutti i browser: la stessa regola con una classe, messa dal
   componente, per quelli che non lo capiscono. */
.yr-selmenu .yr-select-cerca {
  position: sticky; top: 0; z-index: 2;
  background: var(--custom-white, #fff);
  border-bottom: 1px solid var(--default-border);
}

/* ── Niente ingrandimenti non chiesti sul telefono ──────────────────────────────
   iOS ingrandisce da solo quando si tocca un campo il cui testo sta sotto i 16px, e poi
   non torna indietro: si compila un filtro e si resta con la pagina a meta` schermo. I
   campi del tema sono a .875rem (14px), quindi succede su ogni form dell'applicazione —
   accesso compreso, che e` la prima cosa che si vede.

   16px non e` un numero scelto a caso: e` la soglia esatta di Safari. Vale solo sotto i
   768px, dove i campi sono comunque larghi e il testo piu` grande non stona.

   `touch-action: manipulation` toglie l'ingrandimento da doppio tocco (e con esso i 300ms
   di attesa che il browser si prende per capire se il tocco era doppio). */
@media (max-width: 991.98px) {
  /* `!important` a ragion veduta: senza, `.input-group-sm > .form-control` del tema
     (due classi contro una) rivince, e i campi dentro un gruppo tornano a 14px — cioe`
     proprio quelli delle barre di filtro, che sono i piu` toccati. Qui non si sta
     scegliendo un'estetica: si sta togliendo un comportamento del sistema operativo, e
     una regola che si puo` scavalcare per sbaglio non lo toglie. */
  .form-control, .form-select, .form-control-sm, .form-select-sm,
  input[type="text"], input[type="email"], input[type="password"], input[type="search"],
  input[type="number"], input[type="tel"], input[type="url"], input[type="date"],
  input[type="time"], input[type="datetime-local"], select, textarea {
    font-size: 16px !important;
  }
  body { touch-action: manipulation; }
}

/* ── La riga di un ticket sul telefono ──────────────────────────────────────────
   Non e` una tabella, e` una riga in `d-flex` con quattro colonne a larghezza fissa:
   tempo 76px, assegnatario 140, stato 104, freccia 34, piu` la casella e gli spazi. Fanno
   gia` da soli piu` di 390px, quindi la colonna elastica — quella con oggetto, numero,
   azienda e autore, cioe` **tutto** cio` che serve per riconoscere il ticket — veniva
   schiacciata a zero e mandata a capo una parola per riga, con i pulsanti sovrapposti.

   Sotto i 768px la riga va su due piani: sopra l'oggetto con la freccia che apre, sotto
   stato, tempo e assegnatario che si dispongono da soli. Le larghezze fisse cadono
   (`!important` perche' sono scritte inline sull'elemento) e la casella delle azioni di
   gruppo sparisce, come gia` fa nelle tabelle ripiegate: nessuno seleziona venti ticket
   dal telefono, ed e` un terzo bersaglio a un millimetro dagli altri due.

   Il `::before` con `flex-basis:100%` e` una riga vuota che manda a capo: senza, stato e
   tempo si accodano alla freccia e l'oggetto torna a essere strizzato. */
/* NOTA sulla soglia: 991.98 e non 767.98.
   La misura che conta non e` la finestra ma lo **spazio del contenuto**. Su un iPad in
   verticale la finestra e` 820px, ma la barra laterale se ne prende 240: al contenuto ne
   restano 580, cioe` meno di un telefono in orizzontale. Con la soglia a 768 queste righe
   tornavano a una riga sola su un tablet e si strizzavano esattamente come facevano sul
   telefono prima di questa regola — misurato: «1h 20m» sovrapposto a «registrate».
   Le regole che restano a 767.98 sono quelle che parlano del **telefono** e non della
   larghezza: la barra in basso, la pagina di accesso, la disposizione dell'agenda. */
@media (max-width: 991.98px) {
  .yr-tk { flex-wrap: wrap; row-gap: .5rem; column-gap: .5rem; }
  .yr-tk > .yr-bulk-voce-tk { display: none; }
  /* `!important` obbligato: `.flex-fill` di Bootstrap e` gia` `flex: 1 1 auto !important`,
     e con base `auto` questa colonna misura quanto il suo contenuto — cioe` tutta la riga,
     e la freccia finisce a capo. Con base 0 prende quello che avanza, non di piu`. */
  .yr-tk > .yr-tk-info  { order: 1; flex: 1 1 0 !important; min-width: 0; }
  .yr-tk > .yr-tk-vai   { order: 2; }
  .yr-tk::before        { content: ''; order: 3; flex-basis: 100%; height: 0; }
  .yr-tk > .yr-tk-stato { order: 4; width: auto !important; }
  .yr-tk > .yr-tk-tempo { order: 5; width: auto !important; text-align: left !important;
                          display: flex; align-items: baseline; gap: .3rem; }
  .yr-tk > .yr-tk-ass   { order: 6; width: auto !important; }
}

/* ── Le pagine di accesso (login, recupero, invito, sospeso) ────────────────────
   Erano due colonne affiancate a qualunque larghezza: su un telefono la fascia scura
   restava al 42% dello schermo, cioe` 164px, e il titolo ci finiva dentro una parola per
   riga («Questo / link / non / e` / piu` / valido.»), mentre il modulo viveva in quel poco
   che avanzava. Sono le prime schermate che si vedono e le uniche che vede chi non e`
   ancora entrato. */
.yr-auth-logo { display: flex; align-items: center; gap: 10px; }
.yr-auth-logo img { height: 26px; }
.yr-auth-claim { margin-top: auto; }
.yr-auth-claim-t { font: 700 26px/1.25 'Public Sans', sans-serif; letter-spacing: -.02em; }
.yr-auth-claim-s { font: 400 14px/1.65 'Public Sans', sans-serif; color: #cbc7de; margin-top: 12px; max-width: 340px; }
.yr-auth-tenant { margin-top: auto; padding-top: 28px; border-top: 1px solid #413a68;
                  font: 500 12px/1.5 'Public Sans', sans-serif; color: #a9a4c4; }

@media (max-width: 767.98px) {
  /* In colonna: la fascia scura diventa un'intestazione, il modulo prende tutto il resto.
     Lo scorrimento passa al contenitore, perche' con la tastiera aperta il modulo da solo
     non basta piu` e `position: fixed` non lascia scorrere la pagina sotto. */
  /* In colonna: la fascia scura resta scura e diventa l'intestazione della pagina, a
     tutta larghezza, con dentro il solo logo. Sotto, il modulo su bianco.

     Il claim sparisce. E` una promessa da vetrina: su uno schermo dove ci sta una cosa
     sola, quella cosa e` il modulo. E chi arriva qui sa gia` cosa sta aprendo — ci arriva
     da un link ricevuto o dall'icona che si e` messo in home — mentre quattro righe di
     presentazione spingono «Entra» sotto il bordo. */
  .yr-auth { flex-direction: column; overflow-y: auto; }
  .yr-auth-side {
    width: 100%; flex: 0 0 auto;
    align-items: center; justify-content: center;
    padding: calc(22px + env(safe-area-inset-top)) 20px 22px;
  }
  .yr-auth-logo img { height: 30px; }
  .yr-auth-claim, .yr-auth-tenant { display: none; }
  .yr-auth-main {
    flex: 1 0 auto; overflow: visible; justify-content: flex-start;
    padding: 28px 22px calc(34px + env(safe-area-inset-bottom));
  }
}

/* ── L'intestazione sul telefono ────────────────────────────────────────────────
   I pulsanti di pagina stanno in un `btn-list` che va a capo. L'intestazione pero` ha
   un'altezza fissa: andando a capo la seconda fila finisce fuori, tagliata a meta` — sulla
   dashboard il «+» sporgeva sopra il bordo dello schermo. Sotto i 768px l'etichetta e` gia`
   nascosta e restano le icone, che su una riga sola ci stanno: quello che deve cedere e` il
   titolo, e cede troncandosi invece di rubare spazio ai comandi. */
@media (max-width: 767.98px) {
  .app-header .btn-list { flex-wrap: nowrap !important; }
  .app-header .header-content-left { min-width: 0; }
  .app-header .header-content-left .header-element { min-width: 0; }
  .app-header .header-content-left p,
  .app-header .header-content-left span {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
}

/* ── Righe con i comandi in fondo, sul telefono ─────────────────────────────────
   Lo schema si ripete: una riga in `d-flex` con il nome elastico e in fondo un gruppo di
   pulsanti `flex-shrink-0`. Su un telefono i pulsanti tengono la loro larghezza e il nome
   viene schiacciato a due centimetri — «Cose da Fare» diventava tre righe da una parola.

   `yr-r2` = riga a due piani: sotto i 768px i comandi scendono su una riga tutta loro, e
   il nome si riprende la larghezza. Da mettere sulla riga e sul gruppo dei comandi; il
   nome non ha bisogno di niente, gli basta lo spazio. */
@media (max-width: 991.98px) {
  .yr-r2 { flex-wrap: wrap; row-gap: .5rem; }
  .yr-r2 > .yr-r2-azioni { flex: 1 0 100%; justify-content: flex-start; }
}

/* ── Il clip che stacca gli elementi fissi, tolto a ogni larghezza ──────────────
   Il tema mette `overflow-x: clip` su `body`. Su Safari un contesto di clip sopra un
   elemento `position: fixed` lo stacca dalla finestra: l'elemento si ancora al documento e
   **scorre con la pagina**. E` successo due volte, e la seconda perche' la correzione era
   applicata solo sotto i 768px: prima la barra in basso spariva sull'iPhone, poi sull'iPad
   scorreva via la barra laterale. Stessa causa, larghezza diversa.

   Il clip non si rimette dov'era: su `html` il browser lo **propaga alla finestra** e
   `html` stesso resta `visible`. Niente contesto di clip — quindi gli elementi fissi
   restano agganciati — e insieme niente scorrimento laterale, che era il motivo per cui il
   tema l'aveva messo. `overscroll-behavior-x: none` spegne il rimbalzo elastico: senza,
   Safari lascia comunque trascinare la pagina di lato per poi rimetterla a posto. */
/* NIENTE `overflow: hidden`, ne` su `html` ne` su `body`.
   -----------------------------------------------------------------------------
   Provato e ritirato: `html { overflow-x: hidden }` fermava lo scorrimento laterale, ma su
   iOS Safari e` **la** causa nota per cui un elemento `position: fixed` smette di essere
   fisso e scorre con la pagina. Prima e` sparita la barra in basso sull'iPhone, poi la
   barra laterale sull'iPad ha ripreso a scorrere: la stessa correzione applicata due volte
   che rompeva quello che doveva proteggere.
   Verificato: nessun antenato di `.yr-btm` e `.app-sidebar` ha `transform`, `filter`,
   `will-change` o `contain` — l'unico ostacolo era questa riga.

   Al posto del divieto, i due rimedi che non hanno effetti collaterali:
    - `body { overflow-x: visible }` toglie l'`overflow-x: clip` del tema, che e` la stessa
      trappola un gradino piu` in basso;
    - `overscroll-behavior-x: none` spegne il rimbalzo elastico, che e` il movimento che si
      vedeva come «lo schermo balla».
   Lo scorrimento laterale non torna perche' non c'e` niente da scorrere: la scansione delle
   77 rotte a 390, 768, 820, 991 e 1366px non trova una pagina piu` larga della finestra. Se
   un giorno ne comparisse una, il rimedio e` togliere quella larghezza, non nascondere il
   sintomo rompendo gli elementi fissi. */
html { overscroll-behavior-x: none; }
body { overflow-x: visible; overscroll-behavior-x: none; }

/* ── Perche' su iPhone la barra spariva ─────────────────────────────────────────
   Tre cause note, tolte tutte e tre invece di indovinare quale fosse:

   1. la barra stava dentro `.page` — spostata fuori (vedi `views/layout/footer.php`);
   2. il tema mette `overflow-x: clip` su `body`. Un contesto di clip sopra un elemento
      `position: fixed` su Safari lo stacca dalla finestra: la barra si ancora al
      documento, e su una pagina alta 3800px finisce fuori dallo schermo. Serviva a non
      far scorrere la pagina di lato — ma adesso nessuna delle 68 rotte straborda a
      390px, quindi il puntello si puo` togliere dove fa danno;
   3. `100vh` su iOS non e` l'altezza che si vede. `100dvh` si` — e dove non c'e` resta
      la riga di prima, che i browser vecchi leggono e i nuovi sovrascrivono.

   Il `padding-bottom` sul contenuto e` la contropartita: la barra copre 65px, e senza
   questo l'ultima riga di un elenco resta sotto di lei per sempre.

   SEGUITO: togliere il clip da `body` aveva pero` tolto anche l'unica cosa che impediva
   alla pagina di scorrere di lato, e su Safari lo schermo «ballava» a destra e sinistra
   con la barra che ballava insieme — sembrava fuori posto perche' era la pagina a
   spostarsi. Non era un secondo difetto: era lo stesso, visto dall'altra parte. */
@media (max-width: 767.98px) {
  /* La sbarratura orizzontale sta su `html`, non su `body`.
     -------------------------------------------------------------------------
     Togliere il clip da `body` aveva risolto la barra che spariva, ma aveva
     tolto anche l'unica cosa che impediva alla pagina di scorrere di lato: su
     Safari lo schermo «ballava» a destra e sinistra, e la barra fissa ballava
     con lui — sembrava fuori posto perche' era la pagina a essersi spostata.
     Il rimedio non e` rimettere il clip dov'era: su `html` il valore viene
     **propagato alla finestra** dal browser, e `html` stesso resta `visible`.
     Nessun contesto di clip, quindi niente barra staccata; e insieme niente
     scorrimento laterale. E` la sola forma che fa tutt'e due le cose.

     `overscroll-behavior-x: none` spegne il rimbalzo elastico: senza, Safari
     lascia comunque trascinare la pagina di lato per poi rimetterla a posto, ed
     e` proprio quel movimento che si vede come «balla». */
  body { min-height: 100vh; }
  body { min-height: 100dvh; }
  .main-content { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}

/* ── L'occhio sulle password ────────────────────────────────────────────────────
   Il guscio lo crea il JS intorno a ogni campo password (vedi app.js). `flex`/`min-width`
   servono perche' il campo puo` stare dentro un contenitore in `d-flex`: senza, il guscio
   non si allargherebbe e il campo diventerebbe largo quanto il suo testo. */
.yr-pwd { position: relative; display: block; flex: 1 1 auto; min-width: 0; }
.yr-pwd > .form-control { padding-inline-end: 2.6rem; }
.yr-pwd-occhio {
  position: absolute; inset-inline-end: 4px; top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; padding: 0;
  border: 0; background: none; border-radius: 6px; cursor: pointer;
  color: var(--text-muted, #666b7d); font-size: 1.05rem; line-height: 1;
}
.yr-pwd-occhio:hover { color: rgb(var(--primary-rgb)); background: var(--default-background, #f6f7fa); }
/* Il bersaglio vero e` piu` grande di quello disegnato: un dito ne vuole 40px, e i pochi
   millimetri di scarto finirebbero sul campo, riaprendo la tastiera. */
@media (max-width: 767.98px) {
  .yr-pwd-occhio { width: 2.6rem; height: 2.6rem; font-size: 1.15rem; }
  .yr-pwd > .form-control { padding-inline-end: 3rem; }
}

/* ── Le schede prodotto del portale ─────────────────────────────────────────────
   Il JS del carrello segna la riga scelta con `table-active`, che e` una classe di
   Bootstrap per le tabelle e su una scheda non fa niente. Invece di cambiare il JS — che
   non deve sapere se sotto c'e` una riga o una scheda — si aggancia la stessa classe alla
   scheda dentro. Chi ha una quantita` si riconosce a colpo d'occhio scorrendo. */
[data-yr-ord-riga].table-active > .yr-ord-scheda {
  border-color: rgb(var(--primary-rgb));
  box-shadow: 0 0 0 1px rgba(var(--primary-rgb), .25);
}
[data-yr-ord-riga].table-active { background: transparent !important; }

/* ── Le schede di sezione sul telefono: una riga che scorre ─────────────────────
   Sette voci (Azienda, Fisco e scontrini, Installazione, Integrazioni, Spedizioni,
   Sviluppatore, Impersonifica) andavano a capo su **quattro righe**: 154px di navigazione
   prima di arrivare al contenuto, su uno schermo alto 844.

   Qui lo scorrimento e` la scelta giusta — e non lo e` quasi mai — per lo stesso motivo
   delle pillole dei flussi: le voci sono tutte dello stesso tipo, si scorre per cercarne
   una e non si legge in ordine, e quella attiva resta comunque raggiungibile. La spinta al
   margine dice che c'e` dell'altro di lato. */
@media (max-width: 991.98px) {
  .nav-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
  }
  .nav-tabs > .nav-item { flex: 0 0 auto; scroll-snap-align: start; }
  .nav-tabs > .nav-item > .nav-link { white-space: nowrap; }
  .nav-tabs::-webkit-scrollbar { height: 3px; }
  .nav-tabs::-webkit-scrollbar-thumb { background: var(--default-border); border-radius: 3px; }
}

/* ── La tendina delle notifiche ─────────────────────────────────────────────────
   Il tema ha `.app-header .dropdown-menu { width: 100% }` — due classi contro la sola
   `.yr-notifiche-menu`, quindi vinceva lui. E quel 100% e` del contenitore, non dello
   schermo: la tendina veniva 160px e il testo si spezzava a due parole per riga.

   Sul telefono si prende quasi tutta la larghezza: una notifica e` una frase, e una frase
   spezzata in sei righe non si legge — si indovina. */
.app-header .yr-notifiche-menu { width: 360px; max-width: calc(100vw - 1.5rem); }
@media (max-width: 767.98px) {
  .app-header .yr-notifiche-menu {
    width: calc(100vw - 1rem);
    max-width: calc(100vw - 1rem);
  }
}

/* ── Lo scansionatore ───────────────────────────────────────────────────────────
   Il pulsante della fotocamera sta attaccato al campo, non sotto: e` la stessa azione, e
   separarli farebbe pensare a due cose diverse. */
.yr-scan { display: flex; align-items: stretch; gap: .4rem; }
.yr-scan > input { flex: 1 1 auto; min-width: 0; }
.yr-scan > .yr-scan-apri { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
                           width: 2.75rem; font-size: 1.1rem; }
/* Il video non deve mai coprire la pagina: sta nel flusso, sotto il campo, e si chiude da
   solo appena legge. Un rettangolo alto tutto lo schermo su un telefono nasconde proprio
   l'elenco in cui il codice deve comparire. */
/* Larghezza piena fino a 420px, e un'altezza sua: senza, il video parte a zero e cresce
   quando arriva il primo fotogramma, spingendo giu` la pagina sotto le dita di chi sta
   inquadrando. */
.yr-scan-video { width: 100%; max-width: 420px; }
.yr-scan-video video { min-height: 200px; object-fit: cover; }
.yr-scan-video video { display: block; background: #000; }
