/* ==========================================================================
   FONDAMENTA MOBILE (Fase C) — piano docs/superpowers/plans/2026-07-28-mobile-fondamenta.md
   ==========================================================================
   INVARIANTE: ogni regola di questo file vive dentro
   `@media screen and (max-width:768px)`.
   Il `screen and` NON è decorativo: una media query di sola larghezza
   matcha anche in stampa, dove la page box A4 vale 741 CSS px (misurato).
   Senza `screen and`, questo file riscriverebbe ogni PDF generato dalla app.
   Non rimuoverlo.
   ========================================================================== */

@media screen and (max-width:768px){
  :root{
    --fc-safe-bottom:env(safe-area-inset-bottom,0px);
    --fc-safe-top:env(safe-area-inset-top,0px);
  }

  header{padding-top:calc(.4rem + var(--fc-safe-top,0px))}
}

/* --------------------------------------------------------------------------
   1. CAMPI DI FORM A 16px — contro lo zoom automatico di iOS al focus.
   `!important` è STRUTTURALE, non una scorciatoia. Va difeso in review:
   - 41 regole di classe in style.css battono `input,select,textarea` per
     specificità (es. style.css:42 `.task-form .fg input` = (0,2,1));
   - 169 campi generati in JS portano `font-size` inline (es.
     opmodal-steps.js:159, opmodal-gestione.js:400, tasks.js:395);
   - css/lender.css e css/lender-admin.css sono iniettati a runtime
     (lender.js:40-45, lender-admin.js:131-135) e finiscono DOPO mobile.css.
   Un `!important` d'autore batte sia la specificità sia lo stile inline.
   Esclusi checkbox/radio/range: iOS non zooma su quelli e lì il font-size
   inciderebbe sul rendering del widget.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  input:not([type=checkbox]):not([type=radio]):not([type=range]),
  select,
  textarea,
  [contenteditable="true"]{font-size:16px!important}
}

/* --------------------------------------------------------------------------
   2. SCALA TIPOGRAFICA DALLA RADICE.
   Le 388 dichiarazioni font-size in rem di style.css, più quelle inline
   generate in JS, si riscalano tutte da qui: +18,75%.
   .45rem 7,2 -> 8,55px | .5rem 8 -> 9,5px | .55rem 8,8 -> 10,45px
   .6rem 9,6 -> 11,4px | .72rem 11,5 -> 13,7px | .8rem 12,8 -> 15,2px
   Sicuro perché nel foglio non esiste alcuna regola html{}, nessuna media
   query in em/rem, e una sola larghezza in rem (style.css:1678 .dp-sw).
   `body` resta a 14px per scelta (style.css:47): vedi "Decisioni prese"
   nel piano. Il riscalo è deliberatamente parziale.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  html{font-size:19px}
}

/* Pavimento a 11px sui componenti dei tre flussi che restano sotto soglia
   anche dopo il riscalo. Elenco chiuso, ricavato dalla misurazione. */
@media screen and (max-width:768px){
  .kpi-lbl,
  .op-card-city,.op-card-city-txt,.op-card-code,
  .pipe-col-title,.pipe-col-count,
  .op-tag,.op-tag-tipo,.op-tag-agenzia,
  .op-metric{font-size:11px}
}

/* --------------------------------------------------------------------------
   PAVIMENTO 11px, seconda tornata: chrome della sidebar più i bottoni
   piccoli. Residui misurati nel browser a 390x844 (radice 19px), non
   dedotti:
   .sidebar-section-label 9,5px (presente su ogni pannello) |
   #googleAccLabel 9,5px | #googleDisconnectBtn 8,55px (il più piccolo
   di tutti) | #gmailBadge 9,12px | #pushStatusLabel 9,5px |
   .btn-sm 10,45px (bottoni piccoli nei modali sopralluogo e gestione).
   `!important` necessario su 5 dei 6: googleAccLabel, googleDisconnectBtn,
   gmailBadge e pushStatusLabel hanno font-size inline in index.html
   (style="font-size:.5rem" ecc.); .btn-sm lo riceve da markup generato
   in JS (es. opmodal-steps.js:273 .55rem, opmodal-finance.js:692 .55rem,
   opmodal.js:976 .58rem, gmail.js:636 .55rem). Un font-size inline non
   `!important` batte sempre una regola d'autore non `!important`,
   qualunque sia la specificità del selettore (anche un id) — stesso
   motivo del blocco 1 di questo file.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  .sidebar-section-label,
  #googleAccLabel,
  #googleDisconnectBtn,
  #gmailBadge,
  #pushStatusLabel{font-size:11px!important}
}

/* --------------------------------------------------------------------------
   PAVIMENTO 11px, terza tornata: chrome della pipeline, presente su ogni
   schermata. Misurato nel browser a 390x844 (radice 19px), non dedotto:
   SPAN#pushToggleBtn "⚙" 8,55px | SPAN anonimo "In attesa" dentro
   #rtStatusBadge 10,45px | DIV.sidebar-user-role "Ops Manager" 10,45px |
   BUTTON.hdr-btn.hdr-btn-primary "+ Nuova Op." 9,5px.

   `!important` necessario sui primi due: #pushToggleBtn ha font-size inline
   in index.html:123 (style="font-size:.45rem..."); lo SPAN dentro
   #rtStatusBadge lo riceve da markup generato in JS (realtime-status.js:63,
   dentro il template di _renderBadge: style="...font-size:.55rem..."). Un
   font-size inline non `!important` batte sempre una regola d'autore —
   stesso motivo del blocco 1 di questo file.

   NON serve su .sidebar-user-role né su .hdr-btn: entrambi prendono il
   font-size da una regola d'autore, non da inline. .sidebar-user-role è
   style.css:69 (classe, nessun inline). .hdr-btn è style.css:433, dentro
   una media query max-width 768px propria di style.css, ripreso da
   .hdr-btn-primary a style.css:501 dentro una media query max-width 480px —
   stessa specificità di classe della nostra regola. mobile.css è collegato
   dopo style.css in index.html (riga 65 dopo riga 64): a parità di
   specificità vince l'ultimo foglio in ordine di sorgente, senza bisogno
   di `!important`.

   ATTENZIONE: alzare .hdr-btn da 9,5 a 11px allarga "+ Nuova Op." nella
   barra header, che deve restare su 2 righe. Il controller ha misurato
   margine (riga 2 a 265px sui 323 disponibili) ma il valore resta
   vincolato: se cambia il testo del bottone o il layout dell'header,
   riverificare le 2 righe.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  #pushToggleBtn,
  #rtStatusBadge span{font-size:11px!important}

  .sidebar-user-role,
  .hdr-btn{font-size:11px}
}

/* --------------------------------------------------------------------------
   PAVIMENTO 11px, quarta tornata: nei modali sopralluogo e gestione, dentro
   #opModal, 3 SPAN anonimi e 1 BUTTON senza classe, tutti a 10,45px misurati
   a 390x844 (.55rem alla radice di 19px). Markup generato in JS con solo
   stile inline: non esiste un selettore di classe, quindi selettore per
   valore dell'attributo di stile — colpisce SOLO gli inline sotto il
   pavimento, non tocca chi è già a norma. Occorrenze verificate con grep in
   js/modules/opmodal*.js: font-size:.55rem × 66, font-size:.5rem × 34,
   font-size:.45rem × 2 — tutte e tre le forme compaiono, nessuna rimossa.
   `!important` obbligatorio: un font-size inline batte sempre una regola
   d'autore, qualunque sia la specificità del selettore (anche un id).

   ESCLUSIONE `:not(input):not(select):not(textarea)` (fix regressione,
   misurata su INPUT#bpAptQty a 11px invece dei 16px richiesti): l'attributo
   `[style*="font-size:..."]` sommato all'id `#opModal` vale (1,1,0,0), che
   batte la specificità (0,3,0,1) della regola dei campi di form a 16px
   (blocco 1 di questo file). Essendo entrambe `!important`, decide la
   specificità e vince questo pavimento — un campo di form scende sotto i
   16px e iOS torna a zoomare al focus. Senza l'esclusione il pavimento
   riapre lo zoom iOS su ogni input/select/textarea con font-size inline
   sotto i 16px dentro #opModal. L'esclusione lascia il pavimento attivo su
   span, div e button, che non sono soggetti allo zoom iOS. */
@media screen and (max-width:768px){
  #opModal [style*="font-size:.55rem"]:not(input):not(select):not(textarea):not([contenteditable]),
  #opModal [style*="font-size:.5rem"]:not(input):not(select):not(textarea):not([contenteditable]),
  #opModal [style*="font-size:.45rem"]:not(input):not(select):not(textarea):not([contenteditable]){font-size:11px!important}
}

/* --------------------------------------------------------------------------
   3. PANNELLO HOME.
   Il blocco Home (style.css:1462-1595) è scritto in px assoluti, quindi
   la radice del blocco 2 non lo tocca. Qui si alza solo ciò che sta sotto
   il pavimento degli 11px. Non è una riprogettazione della Home.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  #pan-home .h-cf-ml,
  #pan-home .h-badge{font-size:11px}
}

/* --------------------------------------------------------------------------
   4. BERSAGLI TOCCABILI E FEEDBACK AL TOCCO.
   44×44 e' la soglia Apple HIG, ripresa da WCAG 2.5.5. Si misurano ENTRAMBE
   le dimensioni: un bersaglio alto ma stretto resta difficile da centrare.
   Molti bersagli dei tre flussi sono generati in JS senza classe: si
   raggiungono per struttura (.task-item button, .check-note input, ...).
   I link inline dentro il testo sono esclusi di proposito.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  /* Serve `display` esplicito, non solo min-height: `.btn` (style.css:219)
     non dichiara display, e su `<label class="btn">` (la label "Aggiungi
     Foto", opmodal-steps.js:235) min-height su un inline non ha effetto.
     `justify-content:center` è obbligatorio: un <button> centra il testo da
     solo, ma diventando flex il testo si allineerebbe a sinistra.
     `.wiz-step` può diventare flex senza perdere nulla: su mobile
     style.css:467 disattiva già `text-overflow:ellipsis`. */
  .btn,label.btn,
  .modal-close,.wiz-step,
  .task-item button,
  .task-modal-header button{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }

  /* Header: i 44px sui suoi controlli fanno CRESCERE la barra, non i bottoni.
     A <=768 header e' height:auto/min-height:48px e .hdr-actions ha
     flex-wrap:wrap (style.css:431-432), con .gsearch-wrap gia' su una riga
     tutta sua (style.css:442). Misurato a 390x844 da profilo admin:
     70px / 2 righe oggi -> 147px / 3 righe con i Task 3+4+6. Lo header e'
     position:sticky;top:0 (style.css:81), quindi quei 77px si pagano su
     OGNI pannello. Chi manda a capo la terza riga e' "Repair Drive"
     (index.html:191), che NON e' nell'elenco dei nascosti di
     style.css:435-439: e' manutenzione admin, non un comando da telefono.
     Nasconderlo riporta la barra a 98px su 2 righe.
     NON usare flex-wrap:nowrap + overflow-x:auto su .hdr-actions: la barra
     resta justify-content:flex-end (style.css:87), quindi .gsearch-wrap si
     comprime da 329px a 49px e sborda a left:-22px con maxScrollLeft = 0,
     cioe' la ricerca globale diventa irraggiungibile (misurato). */
  .hdr-btn[onclick*="repairAllDriveSubfolders"]{display:none}
  .hdr-btn,.hamburger,
  #taskNotifBell{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }

  /* Già flex e allineati a sinistra: non vanno centrati. */
  /* Larghi per costruzione: qui il min-width non serve. */
  .nav-item,.check-item{min-height:44px;display:flex;align-items:center;justify-content:flex-start}

  /* Controlli nativi: NON toccare `display`, il widget lo rende il browser.
     Basta l'altezza minima. */
  .task-item select,
  #pipeFilterCity,#pipeFilterReferente,#pipeFilterTecnico{min-height:44px;min-width:44px}

  /* Sopralluoghi Cantiere (flusso 3): opmodal-gestione.js:384-461 genera
     bottoni, label e input SENZA classe, con solo stile inline. Non esiste
     un selettore di classe: si raggiungono per struttura dal corpo del
     modale operazione. La label "Aggiungi foto" (:461) e' inline, quindi
     senza `display` il min-height non avrebbe effetto: stesso motivo di
     `label.btn` qui sopra. */
  #opModalBody button{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
  /* Regola separata da quella sopra: un selettore :has() non supportato
     invalida l'INTERA regola in CSS. Tenendola isolata, un browser senza
     :has() (Safari < 15.4, Chrome < 105) perde solo questa label, non
     anche #opModalBody button. */
  #opModalBody label:has(input[type=file]){
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
  #opModalBody input[type=date]{min-height:44px;min-width:44px}

  /* Via il ritardo di 300ms sul tap. */
  a,button,label,select,summary,[data-action],[onclick]{touch-action:manipulation}

  /* Highlight del tap in verde brand invece del blu di sistema. */
  *{-webkit-tap-highlight-color:rgba(27,94,32,.12)}

  /* I due badge portano testo lungo ("120 scadute + 11 in scadenza"): a 189px
     spingono "+ Nuova Op." su una terza riga, e l'header sticky passa da 98 a
     149px, cioe' 79px persi su ogni schermata. Su telefono conta il numero,
     non la frase: si tronca. Misurato: 44 + 63 + 63 + 83 + gap sta in 323px.
     Non condividono la regola inline-flex qui sopra apposta: su un flex
     container il testo diretto diventa un anonymous flex item con
     min-width:auto, quindi non si accorcia mai e text-overflow:ellipsis non
     scatta (verificato in browser). display:inline-block li tratta come
     scatole di testo normali, quindi l'ellissi taglia solo a DESTRA e il
     numero iniziale resta leggibile. min-height/min-width qui perché non
     sono più nel gruppo flex sopra; line-height:44px centra verticalmente
     l'unica riga di testo.
     padding-top/bottom azzerati (!important, batte l'inline di index.html):
     line-height:44px sommato al padding verticale inline .2rem (3,8px per
     lato a html{font-size:19px}) rendeva il badge a 52px, e l'header sticky
     (si paga su OGNI schermata) saliva da 101px/2 righe a 108px/3 righe,
     la stessa regressione che questa regola doveva evitare. Il padding
     orizzontale resta: serve a non appiccicare il testo ai bordi.
     max-width alzato a 6.5em (da 5.5em): con "🚨 120 scadute + 11 in
     arrivo" i 44px utili di 5.5em rendono "🚨 12…", i puntini di
     sospensione mangiano l'ultima cifra e si legge 12 invece di 120.
     Servono ~10px utili in più perché il numero intero ci stia prima
     dei puntini. Budget riga 2 verificato dopo l'aumento: campanella 44
     + badge 74 + badge 74 + "+ Nuova Op." 93 = 285px sui 323 disponibili
     (più i tre gap fra elementi), margine stretto ma sufficiente: per
     questo il padding va azzerato insieme, non da solo. */
  #deadlineBadge,#alertBadge{
    display:inline-block;
    vertical-align:middle;
    min-height:44px;
    min-width:44px;
    line-height:44px;
    padding-top:0!important;
    padding-bottom:0!important;
    max-width:6.5em;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap;
  }

  /* tasks.js:690 riscrive display inline a ogni aggiornamento del badge. */
  #taskNotifBell{display:inline-flex!important}

  /* Residui misurati a 390x844 dal controller sul Task 6 (pipeline 30->3,
     modale sopralluogo 41->5, modale gestione 39->9). Tutti dentro i tre
     flussi mobile. */

  /* A) I <select> dentro la scheda operazione (#opModalBody): la grande
     maggioranza dei residui (5 nel sopralluogo, 9 in gestione), generati
     in JS senza classe (es. SELECT#fotoCategoria 165x33, SELECT 237x38).
     Stessa nota dei controlli nativi qui sopra: NON toccare `display`,
     il widget lo rende il browser, basta l'altezza minima. */
  #opModalBody select{min-height:44px;min-width:44px}

  /* B) .sidebar-logout (style.css:70, .sidebar-footer) 21x29, nessuno
     stile inline.
     C) Il bottone "✕ Reset" dei filtri pipeline (#pipeFilters, index.html)
     68x27, senza classe, con stile inline solo su font-size/padding/
     border/colore: nessun conflitto con queste proprietà.
     Entrambi prendono le stesse proprietà degli altri bottoni del blocco. */
  .sidebar-logout,
  #pipeFilters button{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }

  /* D) #bugReportBtn (index.html:815) 40x40: width E height sono INLINE
     (style="...width:40px;height:40px...position:fixed...", che resta
     dov'e'). Senza !important su ENTRAMBE le proprietà la regola perde
     contro l'inline: stesso motivo del blocco 1 di questo file. */
  #bugReportBtn{
    width:44px!important;
    height:44px!important;
  }

  /* E) Modale attività (flusso 2): dentro .task-modal-body (contenitore
     creato e distrutto a runtime da openTaskModal/closeTaskModal in
     tasks.js — .task-modal-overlay/.task-modal, nessun id fisso), i due
     <select> filtro stato/assegnatario (tasks.js:373 e :376, 141x36 e
     199x36 misurati) e il bottone "+ Nuova Attività" (tasks.js:380,
     138x29 misurato). Sono fuori da .task-item e da .task-modal-header,
     quindi non coperti dalle regole sopra. Select: NON toccare `display`,
     stessa nota dei controlli nativi già vista sopra in questo blocco.
     Bottone: stessa ricetta degli altri bottoni del blocco. */
  .task-modal-body select{min-height:44px;min-width:44px}
  .task-modal-body button{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
}

/* --------------------------------------------------------------------------
   5. ALTEZZE DINAMICHE E SAFE-AREA.
   `dvh` conta soprattutto per la tastiera: in PWA installata le barre del
   browser non esistono. La riga in `vh` resta come fallback per i browser
   senza dvh e va tenuta PRIMA di quella in dvh.
   Gli offset magici (200px su .pipeline/.pipe-col, style.css:161-162)
   approssimano header+stats+filtri, tutti in rem: con la radice a 19px
   crescono del 18,75%, quindi l'offset va rialzato insieme a loro.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  .pipeline{min-height:calc(100vh - 240px);min-height:calc(100dvh - 240px)}
  .pipe-col{max-height:calc(100vh - 240px);max-height:calc(100dvh - 240px)}

  /* Senza questa riga tutta la conversione in dvh e' inerte su iPhone:
     style.css:511, dentro @media(max-width:480px) e quindi attivo a 390px,
     cappa .pipe-col-body a 250px. La colonna risolve a ~280px e non arriva
     mai al max-height calcolato sopra. Non serve !important: stessa
     specificita' (0,1,0) e mobile.css e' caricato dopo.
     Il 240px presuppone lo header a 2 righe (Task 6 Step 3-bis): se quello
     Step chiude a 3 righe, questo offset e' tarato male. */
  .pipe-col-body{max-height:none}

  /* Safe-area sul fondo dei pannelli ancorati in basso. */
  #scadenzePanel,#alertPanel{padding-bottom:var(--fc-safe-bottom,0px)}

  /* FIX REGRESSIONE (introdotta dal commit fe1d34b): #scadenzePanel ha
     max-height:60vh!important (style.css:478) mentre #scadenzePanelBody
     aveva inline max-height:calc(70vh - 40px), quindi il corpo era più alto
     del contenitore che lo ritaglia (overflow:hidden inline, index.html:165)
     e tagliava l'ultima scadenza. Il tentativo precedente (display:flex sul
     contenitore + flex:1 1 auto sul corpo) NON funziona: `display` di
     #scadenzePanel è scritto INLINE in index.html:165 ed è il meccanismo di
     apertura/chiusura del pannello (toggleScadenzePanel, tools.js:195 -
     flip none<->block); una regola d'autore non-`!important` non lo batte
     mai, quindi il contesto flex non nasce e flex:1 1 auto sul corpo non ha
     effetto. Non toccare `display`: si allinea invece il max-height del
     corpo al cap vero del pannello (60vh) meno l'intestazione.
     L'intestazione NON è ~40px: misurata nel browser a 390x844, è 66,8px
     (padding .6rem .8rem = 22,8px verticali a radice 19px + i due bottoni
     dell'header a 44px di altezza per `#scadenzePanel button{min-height:
     44px}`, mobile.css:465, il pavimento tocchi introdotto in ea9953d).
     Arrotondato a 68px per margine di sicurezza (arrotondare per eccesso
     tiene il corpo leggermente più corto del vero spazio residuo, mai più
     lungo: mai overflow oltre l'intestazione).
     `!important` su #scadenzePanelBody obbligatorio: il max-height è
     inline in index.html (index.html:173). Riga in vh prima come fallback,
     dvh dopo — stessa convenzione di .pipeline/.pipe-col qui sopra. */
  #scadenzePanelBody{max-height:calc(60vh - 68px)!important;max-height:calc(60dvh - 68px)!important}

  /* Safe-area in cima ai banner che si ancorano a top:0.
     `!important` obbligatorio: notifications.js:199 scrive
     `padding:.55rem 1rem` dentro style.cssText, e lo stile inline batte
     qualsiasi dichiarazione d'autore non-important. Senza, la regola e'
     morta e il banner resta sotto il notch in PWA. */
  #fcPushBanner{padding-top:calc(.55rem + var(--fc-safe-top,0px))!important}
}

/* --------------------------------------------------------------------------
   6. MODALI A SCHERMO PIENO.
   Due sistemi indipendenti: .modal-overlay/.modal (style.css:340) e
   .task-modal-overlay/.task-modal (style.css:27).
   VINCOLI DA RISPETTARE:
   - non toccare `display` su .modal-overlay/.modal: js/modules/opmodal.js:81
     e :86 lo scrivono inline e l'apertura passa da .open (style.css:341);
   - style.css:460 porta già tre !important su .modal (max-width, width,
     border-radius): qui si aggiungono solo proprietà diverse;
   - index.html:776 mette max-height:90vh inline sul .modal di #ddModal:
     serve !important per batterlo.
   -------------------------------------------------------------------------- */
@media screen and (max-width:768px){
  .modal-overlay{
    align-items:stretch;
    overflow:hidden;
    overscroll-behavior:contain;
  }
  .modal{
    height:100vh;
    height:100dvh;
    max-height:none!important;
    display:flex;
    flex-direction:column;
  }
  .modal-top{
    flex:0 0 auto;
    padding-top:calc(1rem + var(--fc-safe-top,0px));
  }
  .modal-body{
    flex:1 1 auto;
    max-height:none;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    padding-bottom:calc(.5rem + var(--fc-safe-bottom,0px));
  }
  .wizard-nav{position:sticky;top:0;z-index:1;background:var(--fc-cream)}

  /* Barra azioni fissa in fondo, sopra la safe-area. Richiede il Task 8. */
  .modal-body .fc-modal-actions{
    position:sticky;
    bottom:0;
    margin-top:1rem;
    padding:.6rem 0 calc(.6rem + var(--fc-safe-bottom,0px));
    background:#F8F8F6;
    box-shadow:0 -4px 12px rgba(0,0,0,.06);
    z-index:2;
  }

  /* Sistema modali delle attività. */
  .task-modal-overlay{align-items:stretch;overscroll-behavior:contain}
  .task-modal{
    height:100vh;
    height:100dvh;
    max-height:none;
    max-width:none;
    width:100%;
    border-radius:0;
    overflow:hidden;
    display:flex;
    flex-direction:column;
  }
  .task-modal-header{
    flex:0 0 auto;
    padding-top:calc(.8rem + var(--fc-safe-top,0px));
  }
  .task-modal-body{
    flex:1 1 auto;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    padding-bottom:calc(1.2rem + var(--fc-safe-bottom,0px));
  }
}

/* --------------------------------------------------------------------------
   7. PANNELLO SCADENZE (residuo Task 6, flusso 2 "task e scadenze").
   Controller a 390x844 dentro #scadenzePanel: 134 bersagli sotto 44x44 e 132
   testi sotto gli 11px. Tutti gli altri contesti dei tre flussi già a zero.

   I 134 bersagli sono TUTTI <button> senza classe, generati in JS
   (js/modules/tools.js, funzione updateDeadlineBadge) o inline in
   index.html (header del pannello). Esempi misurati: BUTTON#scadenzeFilterBtn
   77x21 (index.html:169), il bottone "✕" di chiusura pannello 18x14
   (index.html:170), il bottone "✕" che archivia una scadenza 13x20
   (tools.js:186), i bottoni azione bulk 141x21 (tools.js:170-172, "Nascondi
   tutte le scadute" / "Mostra N nascoste" / "Ripristina tutte"). Nessuno ha
   classe: si raggiungono per struttura, come gli altri bersagli senza classe
   di questo file (blocco 4).

   Markup reale verificato: il brief stimava "righe 170-190" per le card
   scadenza; la card per-scadenza vera è alle righe 181-190 dentro il forEach
   175-191, la action bar bulk è alle righe 169-173. Scarto di poche righe,
   non i 28 visti in altri checkout di questo piano. */
@media screen and (max-width:768px){
  #scadenzePanel button{
    min-height:44px;
    min-width:44px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
  }
}

/* Pavimento 11px sul pannello scadenze. Stesso motivo del blocco 2: markup
   generato con solo stile inline, quindi selettore per valore dell'attributo
   con `!important` (un font-size inline batte sempre una regola d'autore).

   Verificato con grep su js/modules/tools.js righe 169-192 (action bar +
   loop delle card): compaiono 7 forme, non le 6 indicate come esempio nel
   brief. Conteggio per forma: font-size:.52rem x3 (righe 170-172, bottoni
   azione bulk), font-size:.5rem x1 (riga 183, badge severità),
   font-size:.65rem x1 (riga 184), font-size:.6rem x1 (riga 185),
   font-size:.75rem x1 (riga 186), font-size:.62rem x1 (riga 188),
   font-size:.58rem x1 (riga 189).

   Alla radice di 19px (blocco 2, +18,75%) solo le prime due scendono sotto
   gli 11px: .52rem = 9,88px (misura del controller sul BUTTON) e .5rem =
   9,5px (misura del controller sullo SPAN). Le altre cinque sono già a
   norma: .58rem 11,02px | .6rem 11,4px | .62rem 11,78px | .65rem 12,35px |
   .75rem 14,25px. Includerle nel pavimento le farebbe scendere a 11px
   invece di lasciarle dove sono: una regressione non richiesta. Il
   pavimento resta quindi solo sulle due forme che il controller ha
   davvero misurato sotto soglia.

   Esclusione :not(input):not(select):not(textarea): stesso motivo del
   blocco 2 (regressione già presa e corretta una volta in questo file,
   INPUT#bpAptQty dentro #opModal). #scadenzePanel oggi non contiene campi
   di form, l'esclusione resta comunque per coerenza con la tecnica e per
   blindare il pavimento se in futuro un campo finisse nel pannello. */
@media screen and (max-width:768px){
  #scadenzePanel [style*="font-size:.52rem"]:not(input):not(select):not(textarea):not([contenteditable]),
  #scadenzePanel [style*="font-size:.5rem"]:not(input):not(select):not(textarea):not([contenteditable]){font-size:11px!important}
}

/* --------------------------------------------------------------------------
   8. TAB "BP & CRONO" (opmodal-finance.js) — segnalazione utente su iPhone,
   geometria riprodotta e misurata dal controller a 390x844 (radice 19px).

   Le tre schede scenario (Persona Fisica / Società IVA / Imposta Registro,
   opmodal-finance.js:1006) vivono in una griglia inline dentro #bpKPI:
   `grid-template-columns:repeat(3,1fr)`. Misurato: tre colonne da 140,96px
   chiedono 446px dentro un contenitore da 371 disponibili — la terza scheda
   sborda. Dentro ogni scheda una seconda griglia 1fr 1fr (colonne 48-58px)
   con valori a font-size 1.1rem (20,9px) e .85rem (16,15px) manda 15 valori
   a capo in mezzo alla cifra (simbolo euro su una riga, cifre sotto).
   Varianti misurate dal controller: due colonne = 6 valori ancora a capo,
   altezza 474px; una colonna = 0 valori a capo, altezza 571px. Una colonna
   sola e' l'unica che azzera il wrap.
   `!important` obbligatorio: grid-template-columns e' inline sul figlio
   diretto di #bpKPI (unico div scritto da _bpKPIEl.innerHTML). */
@media screen and (max-width:768px){
  #bpKPI>div{grid-template-columns:1fr!important}
}

/* --------------------------------------------------------------------------
   9. BARRA AZIONI MODALE — stessa segnalazione del blocco 8, stessa
   geometria misurata a 390x844 (radice 19px). `.fc-modal-actions` (usata in
   opmodal-finance.js:798 fra gli altri: il bottone tagliato era proprio
   "Avanti → Decisione") chiede 396px dentro i 371 disponibili e taglia
   l'ultimo bottone. Variante flex-wrap:wrap misurata dal controller: non
   sborda, altezza 122px, tutte le etichette intere; l'alternativa
   (comprimere i bottoni con flex:1 1 0;min-width:0) arriva a 100px ma
   tronca le etichette — scartata.
   Nessun `!important`: lo stile inline di .fc-modal-actions è
   `display:flex;gap:.5rem;margin-top:1rem`, senza flex-wrap, quindi una
   regola d'autore basta a vincere. */
@media screen and (max-width:768px){
  .fc-modal-actions{flex-wrap:wrap}
}

/* --------------------------------------------------------------------------
   10. GRIGLIE A NUMERO FISSO DI COLONNE CHE SBORDANO A 390px — segnalazione
   ricerca "8 griglie CSS sbordano su telefono", stesso meccanismo del blocco
   8: le celle di una griglia hanno `min-width:auto` di default, quindi non
   scendono sotto la larghezza del proprio contenuto — a `repeat(N,1fr)` con
   N troppo alto per 390px, la griglia chiede più spazio di quanto ne abbia e
   il contenuto va tagliato o a capo in mezzo alle cifre.

   Banco di prova (stesso metodo del blocco 8): pagina isolata che carica
   css/style.css + css/mobile.css veri, markup verbatim dentro
   .modal-overlay>.modal>.modal-body (griglie del modale operazione,
   larghezza utile misurata 371px) o .main>.panel.active (pannello a tutta
   pagina, 371px anch'esso in questo banco), viewport 390x844 (radice 19px
   dal blocco 2). Per ognuna delle 5 griglie sotto: misurate la variante a 2
   colonne e quella a 1, scelto il numero più alto che dia zero sbordamenti
   (`g.scrollWidth>g.clientWidth`) e zero valori a capo (nodo foglia con
   altezza > 1,6x la propria line-height). Nessuna delle 5 sborda in nessuna
   variante testata: cambia solo il conteggio dei valori a capo.
   -------------------------------------------------------------------------- */

/* dec-scenarios (opmodal-steps.js:1922, tab Decisione, 3 schede scenario
   fiscale PF/IVA/Registro) — stesso identico caso delle schede del Business
   Plan risolte nel blocco 8: dentro ogni scheda una griglia 2x2 con gli
   importi (es. "€ 245.000", font-size 1rem/800). Misurato: 2 colonne = 0
   sbordi ma 3 valori a capo (i tre "Profitto", spezzati fra il simbolo € e
   le cifre), altezza 332px; 1 colonna = 0 sbordi, 0 a capo, altezza 418px.
   Una colonna sola azzera il wrap, come nel BP.
   `!important` obbligatorio: grid-template-columns è inline sul div con
   questa classe. */
@media screen and (max-width:768px){
  .dec-scenarios{grid-template-columns:1fr!important}
}

/* dec-rlv-grid (opmodal-steps.js:2018, tab Decisione, 3 card RLV). Misurato:
   2 colonne = 0 sbordi, 0 a capo (anche il titolo più lungo, "RLV Imposta
   Registro" a .5rem uppercase, ci sta in colonna), altezza 167px; 1 colonna
   = 0 sbordi, 0 a capo, altezza 256px. A parità di zero-zero vince il
   numero più alto: 2 colonne.
   `!important` obbligatorio: grid-template-columns è inline sul div con
   questa classe. */
@media screen and (max-width:768px){
  .dec-rlv-grid{grid-template-columns:repeat(2,1fr)!important}
}

/* Citofoni/Cassette/Ripartitori (opmodal-gestione.js:200, tab Gestione),
   markup senza classe: raggiunta per struttura con un selettore d'attributo
   sullo stile inline scopato a #opModalBody, stessa tecnica del pavimento
   font-size di questo file (blocco "PAVIMENTO 11px, quarta tornata").
   Misurato: 2 colonne = 0 sbordi, 0 a capo (select e textarea sono
   width:100% e si comprimono; l'etichetta più lunga, "CASSETTE POSTA" a
   .65rem uppercase, ci sta), altezza 498px; 1 colonna = 0 sbordi, 0 a capo,
   altezza 755px. Vince il numero più alto: 2 colonne.
   `!important` obbligatorio: grid-template-columns è inline. */
@media screen and (max-width:768px){
  #opModalBody [style*="grid-template-columns:repeat(3,1fr);gap:.8rem"]{grid-template-columns:repeat(2,1fr)!important}
}

/* 4 stat card (stato-operazioni.js:162, pannello Stato Operazioni), markup
   senza classe: raggiunta per struttura, scopata a #statoOpContent (un
   pannello a tutta pagina, non il modale operazione). Misurato: 2 colonne =
   0 sbordi, 0 a capo, altezza 193px; 1 colonna = 0 sbordi, 0 a capo, altezza
   398px. Vince il numero più alto: 2 colonne.
   `!important` obbligatorio: grid-template-columns è inline. */
@media screen and (max-width:768px){
  #statoOpContent [style*="grid-template-columns:repeat(4,1fr);gap:.6rem"]{grid-template-columns:repeat(2,1fr)!important}
}

/* Stima Prezzi Casafari, 3 card (opmodal-steps.js:705, dentro
   #casafariResults), markup senza classe: raggiunta per struttura. Misurato:
   2 colonne = 0 sbordi, 0 a capo, altezza 173px; 1 colonna = 0 sbordi, 0 a
   capo, altezza 264px. Vince il numero più alto: 2 colonne.
   `!important` obbligatorio: grid-template-columns è inline. */
@media screen and (max-width:768px){
  #casafariResults [style*="grid-template-columns:repeat(3,1fr);gap:.4rem"]{grid-template-columns:repeat(2,1fr)!important}
}
