/*
 * Indicatore di focus globale da tastiera.
 *
 * PERCHE' STA IN Common/Styles E NON ACCANTO ALLE DIRETTIVE DI ACCESSIBILITA'.
 * Deve valere su TUTTE le pagine, non solo dentro l'applicazione. Le pagine servite
 * dal layout frontend (home prima del login, login, registrazione tenant, pagine di
 * errore -- Views/Layout/_Layout.cshtml) non caricano `app.min.css`: caricano
 * `frontend.min.css`, `metronic.min.css` e `common.min.css`. Con il file sotto
 * `App/` l'anello non arrivava li', e proprio quel tema fa `a, a:focus { outline: 0 }`
 * (metronic/assets/frontend/layout/css/style.css), quindi erano le pagine messe
 * peggio. `Common/Styles` e' l'unica cartella pescata da entrambi i lati:
 * `common.min.css` per il frontend e, via GetCssInFolder("~/Common/Styles"),
 * anche dentro `app.min.css` per l'applicazione e per menuless.
 * Se un giorno il file torna sotto `App/`, torna anche il buco.
 *
 * L'audit di accessibilita' TxDOT (DGWGEOWORK-9108, §2.1) rileva che navigando con
 * Tab non si vede dove si e' arrivati: WCAG 2.4.7 Focus Visible (A) e 1.4.11
 * Non-text Contrast (AA), che chiede almeno 3:1 per l'indicatore.
 *
 * La causa e' il tema Metronic, che azzera l'outline nativo del browser senza mai
 * rimpiazzarlo. Nel repo esistevano solo cinque stili di focus isolati, sui singoli
 * componenti.
 *
 * SPECIFICITA' -- la parte controintuitiva di questo file.
 * Nei CSS Metronic ci sono 57 regole che azzerano l'outline e 27 di queste sono gia'
 * `!important`. Fra due dichiarazioni entrambe `!important` non vince chi arriva dopo:
 * vince la specificita' piu' alta, e solo a parita' conta l'ordine. Un semplice
 * `:focus-visible { outline: ... !important }` vale (0,1,0) e perderebbe contro
 * `.btn:focus` (0,2,0) e soprattutto contro il selettore peggiore misurato,
 * `.page-quick-sidebar-wrapper .page-quick-sidebar .nav-tabs > li > a` (0,3,2).
 * Per questo la pseudo-classe e' ripetuta: e' la tecnica standard per alzare la
 * specificita' senza inventare selettori finti. `html:root` + tre ripetizioni + l'esclusione
 * `:not([tabindex="-1"])` valgono (0,5,1), che supera (0,3,2). L'eccezione sulle celle, in
 * fondo, ne usa cinque -- (0,6,1) -- per poter battere a sua volta la regola generale.
 *
 * L'INVARIANTE DA NON ROMPERE: questo foglio non scrive mai `box-shadow` su un elemento il
 * cui `box-shadow` non e' l'anello, e dove l'anello non si vuole lo si ESCLUDE, non si
 * sopprime a valle.
 * `box-shadow` e' una proprieta' condivisa: nell'applicazione disegna l'ombra delle modali,
 * le elevazioni Metronic, il glow dei pulsanti azione, l'inset dei campi e il contorno rosso
 * degli invalidi. E `box-shadow: none` non ripristina il valore sottostante, lo cancella --
 * quindi "applico l'anello a tutto e poi lo ritiro dove non serve" cancella anche ombre che
 * non c'entrano nulla con il focus.
 * E' il difetto di DGWGEOWORK-9316: `#modal-content` (che ha `tabindex="-1"` e porta l'ombra
 * della modale) la perdeva appena il focus finiva su di lui, cioe' a ogni click nello spazio
 * vuoto fra i campi; e il glow dei pulsanti azione spariva a ogni click, per 280 ms di
 * transizione. Da qui la forma attuale: la regola 1 e' guardata da `@supports` -- non c'e'
 * piu' niente da ritirare -- e le regole dell'anello escludono i contenitori.
 * L'unica sovrascrittura voluta e' quella dichiarata qui sotto sugli input, e vale soltanto
 * finche' il campo e' a fuoco.
 *
 * CONTRASTO -- l'anello e' a due strati proprio per non dipendere dal colore di cio'
 * che sta sotto: un singolo colore fallisce sempre da qualche parte (un anello verde
 * su un bottone verde non si distingue). Il tratto scuro stacca sui fondi chiari,
 * l'alone chiaro stacca sui fondi scuri e sui bottoni saturi.
 * Rapporti calcolati secondo WCAG 2.1 (da riverificare con Colour Contrast Analyser,
 * lo strumento con cui TxDOT validera'):
 *   #101820 su bianco #ffffff ............ 18,1:1
 *   #101820 su grigio pagina #f5f5f5 ..... 16,6:1
 *   #101820 su verde CONTINUE #5cb85c ..... 5,1:1
 *   #101820 su blu SAVE #337ab7 ........... 5,4:1
 *
 * Effetto collaterale voluto: sugli input il nostro box-shadow sostituisce il bagliore
 * azzurro di Bootstrap. E' un cambiamento visibile in tutta l'applicazione, non solo
 * nelle schermate segnalate dall'audit.
 *
 * Questo foglio va caricato per ultimo (vedi bundles.json, app.min.css e app-rtl.min.css).
 */

:root {
    /* Sovrascrivibili per installazione se il brand lo richiede: l'importante e'
       mantenere >= 3:1 fra tratto e alone e fra tratto e sfondi su cui compare. */
    --gw-focus-ring-color: #101820;
    --gw-focus-ring-halo: #ffffff;
    --gw-focus-ring-width: 3px;
    --gw-focus-ring-offset: 2px;
    --gw-focus-ring-halo-width: 7px; /* width + offset + 2 */
}

/*
 * 1. Fallback per i soli browser senza :focus-visible (Chrome <86, Safari <15.4): la' l'anello
 *    compare su ogni focus, anche da mouse -- meno elegante, ma conforme.
 *    La guardia `@supports` prende il posto della vecchia coppia "applica su ogni :focus" +
 *    "ritira con `box-shadow: none` dove :focus-visible esiste": quel ritiro era globale e
 *    cancellava anche le ombre che non erano l'anello (DGWGEOWORK-9316). Il ritiro non serve
 *    piu' perche' ora la regola non viene nemmeno applicata dove :focus-visible c'e'.
 *    NB: e' l'unico posto dove il difetto 9316 sopravvive, ed e' inevitabile -- su quei
 *    browser non c'e' modo di distinguere il focus da tastiera da quello da mouse.
 *
 *    E DOVE `@supports selector()` NON ESISTE (Chrome <83)? Una condizione con una funzione
 *    ignota vale `false`, quindi il blocco viene saltato: la' non c'e' anello per niente,
 *    mentre prima di 9316 c'era. Non e' una perdita reale, perche' quei browser non hanno
 *    nemmeno `:has()` -- che questo stesso file usa in 8 punti per l'anello delle `ui-select`
 *    e del breadcrumb del wizard, cioe' il pavimento effettivo e' gia' Chrome 105+ (2022).
 *    Se un giorno servisse davvero coprire un browser pre-2020, l'unica forma sicura e' un
 *    fallback col SOLO `outline` (che nessuno in questo repo usa per decorare, a differenza
 *    di `box-shadow`): NON reintrodurre il ritiro globale.
 */
@supports not selector(:focus-visible) {
    html:root :focus:focus:focus:not([tabindex="-1"]) {
        outline: var(--gw-focus-ring-width) solid var(--gw-focus-ring-color) !important;
        outline-offset: var(--gw-focus-ring-offset) !important;
        box-shadow: 0 0 0 var(--gw-focus-ring-halo-width) var(--gw-focus-ring-halo) !important;
    }
}

/*
 * 2. Il caso che conta: focus da tastiera.
 *
 *    PERCHE' `:not([tabindex="-1"])` E NON UNA REGOLA CHE AZZERA I CONTENITORI.
 *    Chi apre una modale o un wizard riceve il focus sul contenitore per far annunciare il
 *    titolo allo screen reader: e' un focus programmatico, non una tappa di Tab, e disegnarci
 *    l'anello attorno confonde. `tabindex="-1"` identifica esattamente questo caso, e fino a
 *    9316 lo si gestiva con una regola in fondo al file che azzerava outline E box-shadow.
 *    Ma quei contenitori hanno spesso un'ombra propria: NON applicargli l'anello e' corretto,
 *    azzerargli il `box-shadow` no -- e' il difetto. L'esclusione ottiene la stessa cosa senza
 *    scrivere niente sull'elemento.
 *    Vale anche per `input.ui-select-search`, che la libreria dichiara `tabindex="-1"`: resta
 *    senza anello proprio, e glielo disegna il contenitore (vedi in fondo al file).
 */
html:root :focus-visible:focus-visible:focus-visible:not([tabindex="-1"]) {
    outline: var(--gw-focus-ring-width) solid var(--gw-focus-ring-color) !important;
    outline-offset: var(--gw-focus-ring-offset) !important;
    box-shadow: 0 0 0 var(--gw-focus-ring-halo-width) var(--gw-focus-ring-halo) !important;
}

/*
 * ECCEZIONI -- (0,6,1), una ripetizione in piu' per battere la regola qui sopra.
 */

/*
 * L'alone e' un box-shadow, quindi un antenato con overflow:hidden puo' tagliarlo.
 * Il tratto (outline) non viene mai tagliato, percio' l'indicatore resta comunque
 * visibile: l'alone e' un rinforzo, non la condizione di conformita'.
 * Nelle celle di tabella si rinuncia anche all'offset, altrimenti l'anello finisce
 * sotto la cella adiacente.
 *
 * E' l'unica soppressione di `box-shadow` che resta nel file, e non contraddice l'invariante
 * dichiarato in testa: qui non si sta cancellando l'ombra di qualcun altro, si sta togliendo
 * SOLO l'alone che la regola 2 ha appena messo, su quattro selettori dove il `box-shadow`
 * non e' mai nient'altro (una cella di tabella non ha ombra propria). Non generalizzarla:
 * appena il selettore si allarga a elementi che hanno un'ombra loro, torna il difetto 9316.
 */
html:root td:focus:focus:focus:focus:focus,
html:root th:focus:focus:focus:focus:focus,
html:root tr:focus:focus:focus:focus:focus,
html:root .ui-grid-cell:focus:focus:focus:focus:focus {
    outline-offset: -1px !important;
    box-shadow: none !important;
}

/*
 * ELEMENTI CON clip-path: l'anello va disegnato da un antenato.
 *
 * clip-path ritaglia TUTTO cio' che l'elemento dipinge, `outline` e `box-shadow` compresi.
 * Su un elemento ritagliato l'anello viene quindi applicato e subito buttato via: non esiste
 * modo di renderlo visibile sull'elemento stesso.
 *
 * Caso misurato (DGWGEOWORK-9109) sui passi del wizard (App/common/modalComponents/
 * wizardBreadcrumb.html): le frecce del breadcrumb sono sagomate con
 * `clip-path: polygon(...)` in Scripts/BIG/css/bootstrap-arrow-buttons/. Con un Tab reale
 * l'elemento risultava `:focus-visible` con `outline: 3px solid rgb(16,24,32)` e l'alone
 * regolarmente calcolati -- e invisibili. Il pulsante di scorrimento accanto, che non e'
 * ritagliato, mostrava l'anello: stesso CSS, geometria diversa.
 * Il solo riscontro visibile era il cambio di fondo di `.btn-progress-*:focus` in big.css, che
 * sopravvive perche' il fondo sta DENTRO la regione ritagliata; e sul passo corrente sparisce
 * anche quello, perche' `.progress-focus` ha la stessa specificita' e viene dopo nel file.
 * Risultato: il passo corrente non aveva alcun indicatore di focus -> WCAG 2.4.7, livello A.
 *
 * La soluzione e' spostare il disegno sul <li>, che non e' ritagliato. L'anello diventa un
 * rettangolo attorno alla freccia invece di seguirne il profilo: e' il compromesso normale per
 * i breadcrumb sagomati, e in cambio l'indicatore e' IDENTICO a quello di tutto il resto
 * dell'applicazione, perche' usa le stesse variabili qui sopra invece di ricopiarne i valori.
 *
 * `:has(:focus-visible)` e non `:focus-within`: mantiene la distinzione tastiera/mouse che fa
 * il resto di questo foglio. `:has` e' gia' usato altrove nell'app (modalHeader.html).
 */
html:root .wizard-navbar-nav > li {
    /* Bootstrap lo dichiara gia' su .nav > li; ribadito perche' il riquadro qui sotto e'
       posizionato rispetto a questo box. */
    position: relative;
}

html:root .wizard-navbar-nav > li:has(:focus-visible)::after {
    /* PERCHE' UN PSEUDO-ELEMENTO E NON UN outline.
       Due tentativi precedenti, entrambi scartati su misura:
       1) outline con l'offset positivo del resto dell'applicazione: la <ul
          class="wizard-navbar-nav"> ha `overflow: hidden` e altezza IDENTICA al <li> (33px,
          stesso top), quindi i 2px che sporgono sopra e sotto venivano tagliati e restavano
          visibili solo i due lati verticali - due barre nere invece di un anello. Liberare
          l'asse verticale non e' praticabile: la striscia scorre in orizzontale, e in CSS un
          `overflow-y: visible` accanto a `overflow-x: auto` viene forzato ad `auto`.
       2) outline con offset NEGATIVO, disegnato dentro il box: invisibile, perche' il
          <button> figlio dipinge il proprio fondo sopra la decorazione del genitore.
       Un pseudo-elemento posizionato risolve entrambe le cose: sta dentro il box (niente
       ritaglio) ed e' dipinto sopra il pulsante (niente copertura).
       Il colore e lo spessore restano quelli globali qui sopra, quindi l'indicatore e' lo
       stesso di tutta l'applicazione anche se il meccanismo e' diverso. */
    content: '';
    position: absolute;
    inset: 0;
    border: var(--gw-focus-ring-width) solid var(--gw-focus-ring-color);
    /* Sopra il pulsante, e sopra la freccia successiva che si sovrappone di 10px
       (margin-left negativo). */
    z-index: 2;
    /* Il riquadro copre il pulsante: senza questo intercetterebbe i click. */
    pointer-events: none;
}

/*
 * ui-select: il focus arriva su un elemento RITAGLIATO. Stesso problema del caso qui sopra,
 * con `clip` invece di `clip-path`.
 *
 * Caso misurato (DGWGEOWORK-9109) su #!/websiteLogs, e vale per tutte le 366 <ui-select>
 * dell'applicazione. Il tab stop di una ui-select NON e' il rettangolo che si vede (quello ha
 * `tabindex="-1"`): e' `input.ui-select-focusser.ui-select-offscreen`, 1x1 px in posizione
 * assoluta con `clip: rect(0 0 0 0)`. Con un Tab reale quell'input risulta regolarmente
 * `:focus-visible` e riceve `outline: 3px solid rgb(16,24,32)` con il suo alone -- e li butta
 * via, perche' `clip` ritaglia tutto cio' che l'elemento dipinge, `outline` e `box-shadow`
 * compresi. L'anello globale di questo foglio era quindi invisibile su OGNI tendina.
 *
 * Quello che si vedeva al suo posto non era il nostro anello: era l'indicatore storico di
 * ui-select, e arrivava rotto per due ragioni indipendenti fra loro.
 *   - Sta su `.ui-select-match`, che ha altezza ZERO. Il suo unico figlio `.ui-select-toggle`
 *     e' `float: left` e non c'e' nessun clearfix, quindi il genitore collassa (misurato:
 *     383x0 con il figlio a 383x34). Outline e bagliore si schiacciano su una riga alta 0 in
 *     cima al controllo e ne restano visibili soltanto gli spigoli: e' "l'outline mangiato".
 *   - Ed e' il bagliore azzurro di Bootstrap, `rgba(102,175,233,.6)`, circa 1,6:1 su bianco:
 *     sotto il 3:1 richiesto da 1.4.11 Non-text Contrast anche se fosse intero.
 *
 * L'anello si disegna quindi sul contenitore, che non e' ritagliato (misurato:
 * `overflow: visible`, 383x34) e circonda tutto il controllo.
 *
 * PERCHE' DUE SELETTORI E NON `:has(:focus-visible)`.
 * Dentro il contenitore ci sono TRE possibili destinazioni del focus, e solo due hanno bisogno
 * che l'anello lo disegni qualcun altro:
 *   - il focusser, a tendina chiusa: ritagliato da `clip`, non puo' mostrarlo (sopra);
 *   - `input.ui-select-search`, a tendina aperta: e' visibile e a tutta larghezza, ma la
 *     libreria lo dichiara `tabindex="-1"` (lo mette a fuoco lei via codice, non il Tab).
 *     E' quindi escluso dalla regola 2 dall'`:not([tabindex="-1"])`: misurato
 *     `:focus-visible = true` e `outline-style: none`. Quell'esclusione esiste per i
 *     contenitori di modali e wizard che ricevono focus programmatico, e qui prende un campo
 *     di testo vero. Anche lui, quindi, resta senza indicatore se non glielo disegna il
 *     contenitore. (Fino a DGWGEOWORK-9316 al posto dell'esclusione c'era una regola che
 *     azzerava outline e box-shadow: per questo campo l'effetto e' identico, per i contenitori
 *     con un'ombra propria no -- vedi l'invariante in testa al file.);
 *   - la "x" di cancellazione, quando c'e' un valore selezionato: e' `tabindex="0"` e riceve
 *     regolarmente il proprio anello. Su di lei il contenitore NON deve accendersi, altrimenti
 *     si ottengono due anelli concentrici. E' esattamente il caso che `:has(:focus-visible)`
 *     avrebbe preso per sbaglio.
 * Da qui i due selettori espliciti invece di uno generico.
 *
 * La selezione multipla non e' toccata: non ha focusser, e il suo campo di ricerca non e'
 * `tabindex="-1"`, quindi mostra il proprio anello da se'.
 */
html:root .ui-select-container:has(.ui-select-offscreen:focus-visible),
html:root .ui-select-container:has(input.ui-select-search:focus-visible) {
    outline: var(--gw-focus-ring-width) solid var(--gw-focus-ring-color) !important;
    outline-offset: var(--gw-focus-ring-offset) !important;
    box-shadow: 0 0 0 var(--gw-focus-ring-halo-width) var(--gw-focus-ring-halo) !important;
}

/*
 * Spento lo spigolo azzurro, per non avere due indicatori sovrapposti. Solo in questo ramo:
 * col mouse `btn-default-focus` arriva senza `:focus-visible`, quindi resta il comportamento
 * di prima. Non e' un `outline: none` orfano -- l'alternativa e' la regola qui sopra.
 */
html:root .ui-select-container:has(.ui-select-offscreen:focus-visible) .ui-select-match.btn-default-focus,
html:root .ui-select-container:has(input.ui-select-search:focus-visible) .ui-select-match.btn-default-focus {
    outline: none !important;
    box-shadow: none !important;
}

/*
 * Chi preferisce piu' contrasto a livello di sistema operativo riceve un anello piu' marcato.
 */
@media (prefers-contrast: more) {
    :root {
        --gw-focus-ring-width: 4px;
        --gw-focus-ring-halo-width: 8px;
    }
}
