﻿/* ===================================== */
/* BASE STYLES                           */
/* ===================================== */

html, body {
    height: 100%;
    margin: 0;
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    /* Niente rimbalzo elastico del documento e niente propagazione dello scorrimento.
       Il browser fa rimbalzare la pagina anche quando NON c'e' nulla da scorrere: nella chat, dove
       l'altezza e' esattamente quella del viewport, trascinando il dito dal titolo si vedeva muovere
       tutto - titolo, messaggi e barra di scrittura - per poi tornare al suo posto. Non impedisce lo
       scorrimento vero delle altre pagine, che restano piu' alte del viewport e scorrono come prima;
       toglie solo il movimento oltre i limiti. Il gesto "tira per aggiornare" non ne soffre: e'
       costruito sugli eventi touch in pull-to-refresh.js, non sul rimbalzo nativo. */
    overscroll-behavior: none;
}

a, .btn-link {
    color: #006bb7;
}

h1:focus {
    outline: none;
}

.content {
    padding-top: 1.1rem;
}

/* ===================================== */
/* BUTTONS & FOCUS STATES                */
/* ===================================== */

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus,
.btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

/* ===================================== */
/* VALIDATION                           */
/* ===================================== */

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

/* ===================================== */
/* BLAZOR ERROR UI                       */
/* ===================================== */

/* La schermata dell'errore irrecuperabile - quella che Blazor mostra da solo quando non riesce
   piu' a proseguire - riusa il riquadro degli avvisi dell'app (.popup-velo/.popup), definito piu'
   in basso in questo foglio. Di serie era una striscia gialla in fondo allo schermo con un link
   "Reload", l'unico pezzo di interfaccia che non assomigliava a niente altro nell'app.

   Qui resta il solo interruttore, e le regole del velo stanno sul figlio: Blazor accende il
   riquadro scrivendo display:block inline sul contenitore, e quel block sostituirebbe il flex
   che tiene la nuvoletta al centro dello schermo. */
#blazor-error-ui {
    display: none;
}

/* Sopra a tutto, loader compreso (9999): quando si arriva qui l'app non prosegue, e un velo di
   attesa rimasto acceso coprirebbe l'unica via d'uscita. */
#blazor-error-ui .popup-velo {
    z-index: 10000;
}

/* La traccia dell'errore non serve al donatore ma serve a chi riceve la segnalazione: sta chiusa,
   e chi vuole la apre. */
#blazor-error-ui .errore-dettagli {
    margin-top: 0.75rem;
    text-align: left;
}

#blazor-error-ui .errore-dettagli summary {
    cursor: pointer;
    font-size: 0.9em;
}

#blazor-error-ui .errore-dettagli pre {
    max-height: 9rem;
    margin: 0.5rem 0 0;
    padding: 0.5rem;
    overflow: auto;
    border-radius: 0.5rem;
    background-color: #f5f6f7;
    font-size: 0.75em;
    /* Le tracce hanno righe lunghissime e senza spazi: senza questi due il riquadro si allarga
       oltre lo schermo invece di far scorrere il testo. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.blazor-error-boundary {
    padding: 1rem 1rem 1rem 3.7rem;
    background: url(data:image/...) no-repeat 1rem/1.8rem, #b32121;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred.";
    }

/* ===================================== */
/* SAFE AREA (iOS notch support)         */
/* ===================================== */

.status-bar-safe-area {
    display: none;
}

@supports (-webkit-touch-callout: none) {
    .status-bar-safe-area {
        display: flex;
        position: sticky;
        top: 0;
        height: env(safe-area-inset-top);
        width: 100%;
        background-color: #f7f7f7;
        z-index: 1;
    }

    .flex-column,
    .navbar-brand {
        padding-left: env(safe-area-inset-left);
    }

    html, body, #app, .language-selector {
        padding-bottom: calc(env(safe-area-inset-bottom) + 1rem);
    }
}

/* ===================================== */
/* LOGIN e REGISTRATION CENTER           */
/* ===================================== */

main.login-center,
main.registration-center {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: white;
}

/* ===================================== */
/* ERROR MODAL                           */
/* ===================================== */

.error-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgba(0,0,0,0.5);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s, visibility 0.3s;
    z-index: 1100;
}

    .error-container.visible {
        opacity: 1;
        visibility: visible;
    }

/* Forma, misure e colori del riquadro arrivano da .popup, in fondo a questo foglio: l'avviso di
   errore e' un popup come gli altri e deve somigliargli. Qui resta solo cio' che riguarda questo
   contenitore, che a differenza degli altri sta sempre nel DOM e appare in dissolvenza. */
.error-container {
    padding: 1.25rem;
}

.error-content {
    max-height: 85%;
    overflow: auto;
}

/* I dettagli tecnici, quando ci sono, non devono sfondare il riquadro: la traccia di
   un'eccezione e' fatta di righe lunghissime e senza spazi dove andare a capo. */
.popup .error-dettagli {
    text-align: left;
}

.popup .error-dettagli pre {
    max-height: 30vh;
    margin: 0.5rem 0 0;
    padding: 0.5rem;
    border-radius: 0.5rem;
    background-color: #f4f5f6;
    font-size: 0.75em;
    overflow: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ===================================== */
/* FULLSCREEN LOADER                     */
/* ===================================== */

.fullscreen-loader {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgba(255, 255, 255, 0.7);
    z-index: 9999;
}

.loader-content {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.spinner {
    width: 50px;
    height: 50px;
    border: 6px solid #ccc;
    border-top: 6px solid #007bff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ===================================== */
/* SIDEBAR                               */
/* ===================================== */

.sidebar {
    position: fixed;
    display: flex;
    flex-direction: column;
    height: 100vh;
    padding-top: 3rem;
    background-color: #f8f9fa;
    border-right: 1px solid #dee2e6;
    box-shadow: 1px 0 3px rgba(0, 0, 0, 0.05);
    transition: all 0.25s ease;
    overflow-x: hidden;
    overflow-y: auto;
    white-space: nowrap;
    z-index: 100;
}

    .sidebar.collapsed {
        width: 64px;
        min-width: 64px;
    }

    .sidebar.expanded {
        width: 233px;
        min-width: 233px;
    }

    .sidebar .toggle-button {
        position: absolute;
        top: 6px;
        right: 18px;
        width: 24px;
        height: 24px;
        padding: 0;
        border: none;
        font-size: 24px;
        cursor: pointer;
        background-color: transparent;
        color: #6c757d;
        z-index: 10;
    }

        .sidebar .toggle-button:hover {
            color: #000;
        }

    .sidebar .nav-link {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.65rem 1rem;
        font-size: 0.95rem;
        color: #495057;
        border-radius: 0;
        transition: background-color 0.2s ease, color 0.2s ease;
    }

        .sidebar .nav-link i {
            font-size: 1.1rem;
            min-width: 24px;
            text-align: center;
        }

        .sidebar .nav-link span {
            white-space: nowrap;
        }

        .sidebar .nav-link:hover {
            background-color: #e9ecef;
            color: #212529;
            text-decoration: none;
        }

        .sidebar .nav-link.active {
            font-weight: 600;
            background-color: #dee2e6;
            color: #000;
        }

/* Sotto agli strati della guida (1399 blocco, 1400 velo, 1401 fumetto) e sopra al selettore del
   carattere, che gli sta accanto in basso a sinistra. Era a 1500, cioe' sopra a tutti e tre:
   durante il tour la bandiera restava in chiaro e cliccabile mentre il resto era oscurato. */
/* Il "- var(--tastiera)" li tiene fermi rispetto allo schermo intero quando il viewport si
   accorcia per far posto alla tastiera: senza, salivano insieme alla chat. Finiscono fuori dal
   viewport accorciato, quindi spariscono dietro ai tasti invece di seguirli. La variabile la
   calcola js/tastiera.js; dove non c'e' tastiera vale 0 e questi due restano dov'erano. */
.language-selector-fixed {
    position: fixed !important;
    bottom: calc(0.1rem - var(--tastiera, 0px));
    left: 0.1rem;
    z-index: 1250;
}

.fontsize-selector-fixed {
    position: fixed !important;
    bottom: calc(2.2rem - var(--tastiera, 0px));
    left: 0.5rem;
    z-index: 1200;
}

    .fontsize-selector-fixed button {
        border-inline-style: solid;
        border-color: #212529;
        font-weight: bold;
        color: #212529;
        width: 2.9rem;
        padding: 0;
    }

/* ===================================== */
/* MAIN LAYOUT                           */
/* ===================================== */

.main {
    margin-left: 64px;
}

    .main.no-margin {
        margin-left: 0 !important;
    }

/* min-height: 100% e non 100vh, come nella copia MAUI: con 100vh, sommato al "padding-top: 20px"
   che .main riceve piu' sotto, ogni pagina risultava alta 20px piu' del viewport e si poteva
   trascinare anche quando il contenuto ci stava tutto. */
.sidebar.expanded ~ .main,
.sidebar:not(.expanded) ~ .main {
    transition: margin-left 0.25s ease;
    min-height: 100%;
}

.sidebar.invisible ~ .main {
    margin-left: 0;
}

.sidebar.invisible {
    display: none;
}

/* ===================================== */
/* PAGE FONT SIZES                        */
/* ===================================== */


.page.medium * {
    font-size: 1.1rem;
}

.page.medium .sidebar * {
    font-size: 1.3rem;
    margin-left: -1px;
}

.page.medium .sidebar.expanded {
    width: 295px;
    min-width: 295px;
}

.page.medium .sidebar .toggle-button i {
    font-size: 1.8rem;
}

.page.medium .sidebar .toggle-button {
    right: 22px;
}

.page.medium table * {
    font-size: 0.8rem;
    padding-left: 0.2rem;
    padding-right: 0.2rem;
}

.page.large * {
    font-size: 1.2rem;
}

.page.large .sidebar * {
    font-size: 1.5rem;
    margin-left: -2px;
}

.page.large .sidebar.expanded {
    width: 330px;
    min-width: 330px;
}

.page.large .sidebar .toggle-button i {
    font-size: 2rem;
}

.page.large .sidebar .toggle-button {
    right: 22px;
}

.page.large table * {
    font-size: 0.9rem;
    margin: 0;
    padding-left: 0.1rem;
    padding-right: 0.1rem;
}

.page * {
    font-size: inherit;
}

.sidebar, .sidebar * {
    font-size: inherit;
}

table, td, th {
    font-size: inherit;
}

.form-control, .btn {
    font-size: 0.875em;
}

/* ===================================== */
/* RESPONSIVE FONT SIZES                  */
/* ===================================== */

@media (max-width: 768px) {
    .page.small {
        font-size: 0.95rem;
    }

    .page.medium {
        font-size: 1.05rem;
    }

    .page.large {
        font-size: 1.2rem;
    }

    .page.medium .small-calendar * {
        font-size: 1.15rem;
    }

    .page.large .small-calendar * {
        font-size: 1.5rem;
    }


    .language-selector-fixed {
        left: -0.35rem;
    }

    .fontsize-selector-fixed {
        left: 0.25rem;
    }

        .fontsize-selector-fixed button {
            width: 2rem;
            font-size: 0.8rem;
        }

    .sidebar .toggle-button {
        top: 6px;
        right: 16px;
        width: 12px;
        height: 12px;
        font-size: 22px;
    }

    .sidebar.collapsed {
        width: 40px;
        min-width: 40px;
    }

    .sidebar.expanded {
        width: 100vw !important;
        min-width: 100vw !important;
    }

    .sidebar .nav-link i {
        font-size: 0.9rem;
        min-width: 0;
        width: 0;
        padding-right: 12px !important;
    }

    .sidebar .nav-link {
        font-size: 0.9rem;
        padding-left: 12px !important;
        margin-left: -2.5px !important;
    }

    .card {
        box-shadow: none !important;
        border: none !important;
        background-color: transparent !important;
        padding: 0 !important;
        margin: 0 !important;
    }

    .main {
        padding-top: 20px;
        margin-left: 40px;
    }

    .card td, .card tr {
        font-size: 0.9rem;
    }

    svg {
        width: 16px;
        height: 16px;
    }

    form {
        padding-bottom: 2rem;
    }

    .tracker {
        padding-bottom: 20px;
    }
}

@media (max-width: 600px) {
    .card td, .card tr {
        font-size: 0.8rem;
    }
}

@media (max-width: 575px) {
    td, tr {
        font-size: 0.60rem;
    }

    .form-control {
        font-size: 0.875rem;
        padding: 0.25rem 0.5rem;
    }

    .btn {
        font-size: 0.875rem;
        padding: 0.25rem 0.75rem;
    }
}

@media (max-width: 520px) {
    .card td, .card tr {
        font-size: 0.725rem;
    }
}


.bi-blood-bag {
    display: inline-block;
    width: 1em;
    height: 1em;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="red" viewBox="0 0 92.79 122.88"><path d="M65.35,19.13H11.88c-6.84,0-6.84,1.35-6.83,6.86l0,0.84h0.01v7.12h13.73c1.36,0,2.46,1.1,2.46,2.46 c0,1.36-1.1,2.46-2.46,2.46H5.06v5.74h13.73c1.36,0,2.46,1.1,2.46,2.46c0,1.36-1.1,2.46-2.46,2.46H4.99l-0.01,0.51 c-0.05,1.78-0.1,3.52-0.06,5.23h13.87c1.36,0,2.46,1.1,2.46,2.46c0,1.36-1.1,2.46-2.46,2.46H5.4c0.4,2.1,1.11,4.15,2.31,6.13 c2.87,4.72,7.6,9.18,11.95,13.29c1.31,1.24,2.59,2.44,3.81,3.65h27.71c19.02-20.57,18.87-23.44,17.88-40.9 c-0.26-4.58-0.57-10.12-0.64-17.3c-0.02-1.65-0.07-3.44-0.59-4.62C67.5,19.66,66.79,19.13,65.35,19.13L65.35,19.13z M36.52,93.08c0.1-0.01,0.21-0.02,0.31-0.02c0.11,0,0.21,0.01,0.31,0.02h12.59v-4.85H24.81v4.85H36.52L36.52,93.08z M39.29,97.99v2.41c0,1.82,0.08,3.72,0.33,5.52c0.24,1.76,0.64,3.49,1.27,5.05c1.09,2.68,3.22,4.54,5.69,5.49 c1.77,0.69,3.71,0.92,5.58,0.68c1.83-0.23,3.58-0.93,5.01-2.10c1.89-1.54,3.26-3.95,3.57-7.29c0.51-5.47,2.82-9.34,5.99-11.78 c2.29-1.77,5.02-2.76,7.82-3.04c2.75-0.28,5.58,0.13,8.17,1.16c4.07,1.62,7.53,4.77,9.10,9.19c1.16,3.27,1,9.33,0.88,13.92 c-0.03,1.04-0.05,1.98-0.05,3.21c0,1.36-1.10,2.46-2.46,2.46s-2.46-1.10-2.46-2.46c0-0.60,0.03-1.90,0.07-3.32 c0.11-4.19,0.25-9.72-0.61-12.17c-1.06-3.00-3.46-5.15-6.28-6.27c-1.86-0.74-3.90-1.03-5.88-0.84c-1.92,0.19-3.77,0.86-5.30,2.04 c-2.16,1.66-3.74,4.39-4.11,8.34c-0.45,4.80-2.50,8.33-5.36,10.65c-2.17,1.76-4.78,2.80-7.49,3.15c-2.67,0.34-5.44,0.01-7.96-0.97 c-3.67-1.42-6.84-4.19-8.47-8.22c-0.79-1.95-1.28-4.08-1.58-6.24c-0.29-2.12-0.38-4.22-0.38-6.18v-2.41H22.35 c-1.36,0-2.46-1.10-2.46-2.46v-8.95c-1.12-1.10-2.33-2.25-3.58-3.42c-4.58-4.31-9.55-9.00-12.78-14.33c-3.81-6.28-3.64-12.40-3.45-18.95 c0.03-1.22,0.07-2.45,0.07-4.15v-9.28l0-0.05l0-0.05v-9.52h0.01l0-0.84c-0.02-9.45-0.02-11.77,11.73-11.77h12.48v-1.90 c0-5.89,3.25-9.69,7.42-11.36C33.37,0.32,35.07,0,36.76,0c1.69,0,3.39,0.32,4.98,0.96c4.16,1.67,7.42,5.46,7.42,11.36v1.90h16.20 c3.83,0,5.86,1.74,6.96,4.21c0.91,2.05,0.99,4.43,1.01,6.58c0.07,6.90,0.38,12.46,0.64,17.07c1.09,19.29,1.26,22.41-19.32,44.65v8.81 c0,1.36-1.10,2.46-2.46,2.46H39.29L39.29,97.99z M44.23,14.18v-1.87c0-3.57-1.90-5.83-4.33-6.81c-0.98-0.39-2.06-0.59-3.15-0.59 s-2.17,0.20-3.15,0.59c-2.43,0.98-4.33,3.24-4.33,6.81v1.87H44.23L44.23,14.18z"/></svg>');
}

.font-btn .small-a {
    font-size: 0.6rem;
    font-weight: normal;
    vertical-align: baseline;
}

.font-btn .big-a {
    font-size: 1rem;
    font-weight: normal;
    vertical-align: baseline;
}

.text-uppercase {
    text-transform: uppercase;
}

.mobile-card {
    height: 90vh;
}

    .mobile-card.chat-card {
        height: calc(100dvh - 20px);
    }


.start-75 {
    left: 75% !important
}

.top-25 {
    top: 25% !important
}

.notification-icon {
    position: relative;
}

    .notification-icon::after {
        content: "";
        position: absolute;
        top: 0px;
        right: -6px;
        width: 8px;
        height: 8px;
        background-color: red;
        border-radius: 50%;
    }

.auto-textarea {
    line-height: 24px;
    font-size: 16px;
    resize: none;
    overflow-y: hidden;
}

.white-space-pre-line {
    white-space: pre-line;
}

.rotate-45 {
    transform: rotate(45deg);
    display: inline-block;
}

.rotate-90 {
    transform: rotate(90deg);
    display: inline-block;
}

.rotate-180 {
    transform: rotate(180deg);
    display: inline-block;
}

.rotate-270 {
    transform: rotate(270deg);
    display: inline-block;
}

.min-h-btn {
    min-height: 38px;
}

/* Nasconde il controllo nativo di rivelazione/pulizia password del browser (Edge: ::-ms-reveal, ::-ms-clear),
   così nel componente PasswordInput resta solo l'occhiolino custom ed evitiamo il doppio occhiolino. */
.password-input-group input::-ms-reveal,
.password-input-group input::-ms-clear {
    display: none;
}

/* Pallino di stato nella lista delle sedi trovate: dice a colpo d'occhio se il server della
   sede risponde, così l'utente non scopre solo dopo il click che è irraggiungibile. */
.pallino-stato {
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    /* Allinea il pallino alla prima riga del testo, non al centro della voce. */
    margin-top: 0.35rem;
    border-radius: 50%;
    background-color: #adb5bd;
}

.pallino-stato-verde {
    background-color: #198754;
}

.pallino-stato-rosso {
    background-color: #dc3545;
}

/* La pulsazione distingue "controllo ancora in corso" da un colore semplicemente acceso. */
.pallino-stato-arancio {
    background-color: #fd7e14;
    animation: pallino-stato-pulsazione 1.2s ease-in-out infinite;
}

@keyframes pallino-stato-pulsazione {
    0%, 100% {
        opacity: 1;
    }

    50% {
        opacity: 0.3;
    }
}

/* ===================================== */
/* GUIDA (coach mark)                    */
/* ===================================== */

/* Sta sotto allo spot e sopra alla pagina: durante la guida i comandi vanno spiegati, non
   usati. Senza questo strato un tocco sul velo finirebbe sul campo sottostante, aprendo la
   tastiera proprio mentre si spiega a cosa serve quel campo. */
.guida-blocco {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1399;
}

/* Velo e buco sono lo stesso elemento: l'ombra espansa scurisce tutto ciò che sta fuori dal
   riquadro. Evita di disegnare quattro rettangoli attorno al target e, soprattutto, evita
   l'SVG, che la regola globale più in alto in questo foglio ridurrebbe a 16px. */
.guida-spot {
    position: fixed;
    z-index: 1400;
    border-radius: 8px;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, .62);
    outline: 2px solid #fff;
    pointer-events: none;
    transition: top .18s ease, left .18s ease, width .18s ease, height .18s ease;
}

/* Passi che non evidenziano nulla: serve comunque lo scuro dietro al fumetto. */
.guida-velo-pieno {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1400;
    background-color: rgba(0, 0, 0, .62);
    pointer-events: none;
}

/* Largo quanto lo schermo invece che ancorato al target: così il fumetto non può uscire dal
   viewport e non serve calcolarne la posizione orizzontale. */
.guida-fumetto {
    position: fixed;
    left: 12px;
    right: 12px;
    z-index: 1401;
    max-width: 420px;
    margin: 0 auto;
    padding: 0.85rem 1rem 1rem;
    border-radius: 12px;
    background-color: #fff;
    box-shadow: 0 8px 28px rgba(0, 0, 0, .35);
    /* Stesso tempo del riquadro: fumetto ed evidenziazione si spostano insieme da un passo al
       successivo. La translate è animata perché è lei a ribaltare il fumetto sopra al bersaglio. */
    transition: top .18s ease, transform .18s ease;
}

.guida-fumetto-testa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.35rem;
}

.guida-contatore {
    color: #6c757d;
}

.guida-salta {
    padding: 0;
    color: #6c757d;
    text-decoration: underline;
}

.guida-titolo {
    margin: 0 0 0.35rem;
    font-weight: 700;
}

.guida-testo {
    margin: 0 0 0.9rem;
    line-height: 1.45;
}

.guida-fumetto-piede {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
}

/* ===================================== */
/* ONBOARDING (carosello primo avvio)    */
/* ===================================== */

/* Le regole che fissano una dimensione del carattere sono prefissate con .page perché più su in
   questo foglio .page.medium * e .page.large * assegnano un font-size a QUALSIASI discendente:
   senza il prefisso vincerebbero loro e l'icona grande diventerebbe alta come il testo. */

.onboarding {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    padding: calc(0.75rem + env(safe-area-inset-top)) 1.25rem calc(1rem + env(safe-area-inset-bottom));
}

.onboarding-testa {
    display: flex;
    justify-content: flex-end;
    min-height: 2rem;
}

.onboarding-salta {
    padding: 0;
    color: #6c757d;
    text-decoration: underline;
}

.onboarding-corpo {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    text-align: center;
}

.onboarding-illustrazione {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 8.5rem;
    height: 8.5rem;
    margin-bottom: 0.75rem;
    border-radius: 50%;
    background-color: #e7f6ff;
    color: #1d84df;
}

.page .onboarding-illustrazione i {
    font-size: 4rem;
    line-height: 1;
}

.onboarding-illustrazione img {
    width: 5.5rem;
    height: auto;
}

.page .onboarding-titolo {
    margin: 0;
    font-weight: 700;
    font-size: 1.35rem;
}

.onboarding-testo {
    max-width: 24rem;
    margin: 0;
    color: #55585e;
    line-height: 1.5;
}

.onboarding-lingue {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    width: 100%;
    max-width: 16rem;
    margin-top: 1rem;
}

.onboarding-lingua {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #dee2e6;
    border-radius: 0.6rem;
}

    .onboarding-lingua.attiva {
        border-color: #1b6ec2;
        background-color: #e7f1fb;
        font-weight: 700;
    }

.onboarding-funzioni {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
    width: 100%;
    max-width: 24rem;
    margin-top: 0.75rem;
}

.onboarding-funzione {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.65rem;
    border: 1px solid #e9e4e1;
    border-radius: 0.7rem;
    text-align: left;
    overflow-wrap: anywhere;
}

.page .onboarding-funzione i {
    font-size: 1.2rem;
    color: #1d84df;
}

.onboarding-piede {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.9rem;
}

.onboarding-puntini {
    display: flex;
    gap: 0.4rem;
}

.onboarding-puntino {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #ced4da;
    transition: background-color .2s ease, width .2s ease;
}

    .onboarding-puntino.attivo {
        width: 22px;
        border-radius: 4px;
        background-color: #1b6ec2;
    }

.onboarding-comandi {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    width: 100%;
    max-width: 24rem;
}

    .onboarding-comandi .btn {
        flex: 1;
    }

/* ===================================== */
/* ELENCHI A SCHEDA                      */
/* ===================================== */

/* Appuntamenti, sospensioni e benemerenze erano tabelle a tre colonne: su un telefono da 360px
   la colonna con il testo piu' lungo (il luogo dell'appuntamento) si riduceva a una parola per
   riga, e sotto i 575px ci finiva sopra anche il "td, tr { font-size: 0.60rem }" piu' su in
   questo foglio. Qui ogni voce e' una scheda che impila le informazioni una sotto l'altra, cosi'
   ognuna ha tutta la larghezza disponibile e niente va piu' a capo per forza.

   Le misure del carattere sono in em e non in rem perche' .page.medium * / .page.large * piu' su
   assegnano un font-size a QUALSIASI discendente: un em resta relativo a quel valore e continua
   quindi a crescere con il selettore della dimensione del testo. Per lo stesso motivo i selettori
   che fissano una misura sono prefissati con .page: serve ad arrivare alla stessa specificita' di
   quelle regole, e a pari specificita' vince questo blocco perche' viene dopo. */

.elenco-schede {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}

.scheda {
    border: 1px solid #e7e9ec;
    border-radius: 0.9rem;
    background-color: #fff;
    box-shadow: 0 2px 10px rgba(33, 37, 41, .05);
    overflow: hidden;
}

/* Voce conclusa (appuntamento effettuato, sospensione terminata): resta leggibile ma non si
   prende l'attenzione di quelle ancora aperte. */
.scheda.scheda-conclusa {
    border-color: #e2e5e8;
    background-color: #f7f8f9;
    box-shadow: none;
}

/* La testa e' un button e non un div con @onclick: tutta la riga diventa area di tocco e la si
   raggiunge anche da tastiera come un comando qualsiasi. Vanno azzerati sfondo, bordo e font di
   sistema che il browser mette ai button. */
.scheda-testa {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    width: 100%;
    padding: 0.7rem 0.8rem;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
}

/* min-width: 0 perche' altrimenti il testo lungo dentro un flex item ne allarga la base e la
   scheda sborda invece di mandare a capo. */
.scheda-corpo {
    flex: 1 1 auto;
    min-width: 0;
}

/* Riquadro con giorno/mese/anno: un appuntamento lo si cerca per data, quindi la data fa da
   ancora della scheda invece di essere una colonna schiacciata come le altre. */
.scheda-data {
    flex: 0 0 3.1rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.35rem 0;
    border-radius: 0.7rem;
    background-color: #eaf2fb;
    color: #1b6ec2;
    line-height: 1.15;
}

.scheda-data.scheda-data-conclusa {
    background-color: #eceef0;
    color: #6c757d;
}

/* Referto non ancora scaricato: pallino rosso sull'angolo della data, come quello delle voci di
   menu con una notifica. Il bordo bianco lo stacca dal riquadro azzurro su cui si appoggia. */
.scheda-data.scheda-data-nuovo-referto {
    position: relative;
}

    .scheda-data.scheda-data-nuovo-referto::after {
        content: "";
        position: absolute;
        top: -4px;
        right: -4px;
        width: 12px;
        height: 12px;
        background-color: red;
        border: 2px solid #fff;
        border-radius: 50%;
    }

.page .scheda-data-giorno {
    font-size: 1.3em;
    font-weight: 700;
}

.page .scheda-data-mese {
    font-size: 0.7em;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
}

.page .scheda-data-anno {
    font-size: 0.65em;
    opacity: .75;
}

/* Icona tonda al posto della data, per gli elenchi che non ruotano attorno a un giorno. */
.scheda-icona {
    flex: 0 0 2.6rem;
    height: 2.6rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.7rem;
    background-color: #eaf2fb;
    color: #1b6ec2;
}

.page .scheda-icona i {
    font-size: 1.35em;
}

.scheda-icona.scheda-icona-oro {
    background-color: #fdf3dc;
    color: #a8790b;
}

.scheda-icona.scheda-icona-allerta {
    background-color: #fdeaea;
    color: #c62828;
}

.scheda-icona.scheda-icona-spenta {
    background-color: #eceef0;
    color: #6c757d;
}

.scheda-titolo {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.page .scheda-titolo-testo {
    font-weight: 700;
    line-height: 1.25;
    overflow-wrap: anywhere;
}

/* Bootstrap darebbe alle etichette 0.75em, ma .page.medium * / .page.large * gliela riscrivono in
   rem e diventano grandi come il titolo. Il white-space va riportato a normal perche' Bootstrap
   mette nowrap: con la descrizione di un tipo di appuntamento per esteso, su uno schermo da 320px
   e il testo ingrandito, il badge sfondava la scheda e l'overflow: hidden ne tagliava la fine. */
.page .scheda-titolo .badge {
    font-size: 0.78em;
    white-space: normal;
    text-align: left;
}

/* La riga che nella tabella si spezzava parola per parola (il luogo): qui ha tutta la larghezza
   della scheda. */
.scheda-riga {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    margin-top: 0.25rem;
    color: #5c6169;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

    .scheda-riga i {
        flex: 0 0 auto;
        margin-top: 0.1rem;
    }

.page .scheda-riga {
    font-size: 0.9em;
}

.scheda-freccia {
    flex: 0 0 auto;
    color: #adb5bd;
    transition: transform .18s ease;
}

.scheda.scheda-aperta .scheda-freccia {
    transform: rotate(180deg);
}

.scheda-dettaglio {
    padding: 0.2rem 0.8rem 0.8rem;
    border-top: 1px solid #edeff1;
    background-color: #fbfcfd;
}

.scheda-dettaglio-riga {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.9rem;
    padding: 0.45rem 0;
}

    .scheda-dettaglio-riga + .scheda-dettaglio-riga {
        border-top: 1px dashed #e7eaed;
    }

.page .scheda-dettaglio-etichetta {
    flex: 0 0 auto;
    color: #70747c;
    font-size: 0.85em;
}

.scheda-dettaglio-valore {
    font-weight: 600;
    text-align: right;
    overflow-wrap: anywhere;
}

.scheda-comandi {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.7rem;
}

    .scheda-comandi .btn {
        flex: 1 1 0;
    }

/* Striscia di riepilogo in testa a un elenco: gli stessi riquadri col numero grande dei contatori
   delle donazioni nel tesserino. */
.riepilogo-contatori {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.9rem;
}

.riepilogo-contatore {
    flex: 1 1 0;
    padding: 0.5rem 0.25rem;
    border: 1px solid #e7e9ec;
    border-radius: 0.7rem;
    background-color: #fff;
    text-align: center;
}

.page .riepilogo-contatore-numero {
    font-size: 1.55em;
    font-weight: 700;
    line-height: 1;
}

.page .riepilogo-contatore-etichetta {
    margin-top: 0.15rem;
    color: #70747c;
    font-size: 0.68em;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* Valore di contatto toccabile (telefono, email, indirizzo della sede): stesso peso del testo dei
   dati nel tesserino, con colore e sottolineatura che dicono che ci si puo' toccare sopra. Non usa
   .btn perche' quella classe piu' su in questo foglio impone font-size 0.875em, e il valore
   finirebbe piu' piccolo delle etichette che gli stanno sopra. */
.contatto-azione {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 700;
    color: #1b6ec2;
    text-align: left;
    text-decoration: underline;
    overflow-wrap: anywhere;
}


/* ===================================== */
/* ===================================== */
/* SIDEBAR: ICONE E TESTO PIU' GRANDI    */
/* ===================================== */

/* A barra chiusa il binario e' largo 40px e l'icona ne usava una dozzina: font 0.9rem, spinta a
   sinistra dal "padding-left: 12px" del link e seguita da un "padding-right: 12px" sull'icona,
   cioe' meta' binario era spazio vuoto. Qui quello spazio passa al glifo: il padding orizzontale
   del link va a zero e l'icona si centra nel binario, quindi le icone diventano piu' grandi
   SENZA che la barra si allarghi di un pixel (.sidebar.collapsed resta 40px, .expanded 100vw).

   ATTENZIONE AI SELETTORI: la barra NON sta dentro a .page. In MainLayout.razor il componente
   Sidebar rende un involucro con la SOLA classe della dimensione del carattere (FontSizeClass,
   cioe' "small" / "medium" / "large") ed e' FRATELLO di div.page, non figlio. Per questo qui non
   si usa il prefisso .page e le varianti si scrivono ".medium .sidebar" e ".large .sidebar".
   Le regole piu' su in questo foglio scritte come ".page.medium .sidebar *" pretendono invece che
   .sidebar discenda da un elemento con entrambe le classi, cosa che non avviene mai: sono lettera
   morta, ed e' il motivo per cui fino a ora il selettore del carattere non toccava le voci del
   menu (restavano a 0.9rem in tutte e tre le misure). */

/* La centratura e' con justify-content e non con una colonna di larghezza fissa: quando le voci
   non ci stanno in altezza (tante voci, carattere grande) la barra scorre, e su Windows la barra
   di scorrimento si mangia qualche pixel dei 40 — una colonna fissa da 40px uscirebbe dal
   binario e il glifo verrebbe tagliato, mentre il centraggio flessibile si adatta. */
.sidebar.collapsed .nav-link {
    justify-content: center;
    padding-right: 0 !important;
    padding-left: 0 !important;
    margin-left: 0 !important;
}

.sidebar.collapsed .nav-link i {
    /* flex: 0 0 auto e non il solo min-width: 0: l'icona e' un flex item, e un min-width nullo
       la autorizza a restringersi fino a sparire se nella voce finisce altro contenuto. */
    flex: 0 0 auto;
    width: auto;
    min-width: 0;
    margin-left: 0;
    padding-right: 0 !important;
}

/* A barra aperta la larghezza e' tutto lo schermo e il vincolo dei 40px non c'e': qui l'icona
   torna a essere una colonna di larghezza fissa, cosi' le etichette partono tutte dallo stesso
   punto invece di scalare in avanti di un paio di pixel per volta al variare del glifo. */
.sidebar.expanded .nav-link {
    padding-right: 0.4rem !important;
    padding-left: 0.4rem !important;
    margin-left: 0 !important;
}

.sidebar.expanded .nav-link i {
    flex: 0 0 2rem;
    width: 2rem;
    min-width: 2rem;
    margin-left: 0;
    padding-right: 0 !important;
    text-align: center;
}

/* Misure in rem: qui il carattere ereditato non c'entra, perche' la barra vive fuori da .page e
   nessun selettore universale le ha gonfiato il font. Le tre misure sono scelte per stare dentro
   al binario da 40px anche nella piu' grande. */
.sidebar .nav-link i {
    font-size: 1.4rem;
    line-height: 1;
}

.medium .sidebar .nav-link i {
    font-size: 1.65rem;
}

.large .sidebar .nav-link i {
    font-size: 1.85rem;
}

/* Il pallino delle notifiche era tarato su un'icona piccola: con il glifo piu' grande va
   riportato all'angolo, altrimenti resta a mezz'aria dentro l'icona. */
.sidebar .nav-link .notification-icon::after {
    top: -1px;
    right: -3px;
    width: 9px;
    height: 9px;
}

/* L'etichetta si vede solo a barra aperta, dove lo spazio orizzontale e' tutto lo schermo. */
.sidebar .nav-link span {
    font-size: 1.05rem;
}

.medium .sidebar .nav-link span {
    font-size: 1.3rem;
}

.large .sidebar .nav-link span {
    font-size: 1.5rem;
}

/* Il chevron di apertura segue le voci, altrimenti col carattere grande resta l'unica cosa
   piccola della barra. Cresce poco: il suo contenitore e' di 12x12 px appoggiato a destra, e un
   glifo troppo largo sborderebbe dal binario. */
.medium .sidebar .toggle-button {
    font-size: 25px;
}

.large .sidebar .toggle-button {
    font-size: 28px;
}

/* Il "line-height: 1" sull'icona ha tolto il sovrappiu' che il glifo si portava dietro, quindi
   senza toccare nulla la voce si accorciava: 42px invece dei 44 di prima, cioe' un bersaglio da
   toccare piu' piccolo proprio dove l'icona e' diventata piu' grande. Con 0.7rem la voce torna a
   47px, due in piu' di prima: l'elenco non si allunga e il dito ha piu' spazio, non meno. */
.sidebar .nav-link {
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
}

/* ===================================== */
/* CHAT                                  */
/* ===================================== */

/* Stesse convenzioni del blocco delle schede: misure in em e selettori prefissati con .page per
   avere la meglio su ".page.medium *" / ".page.large *", che assegnano un font-size a qualunque
   discendente e quindi anche alle righe piccole (ora, mittente, separatori). */

/* Nella copia MAUI questa regola sottrae le fasce di sistema, var(--safe-*), che sul web non
   esistono: qui l'altezza e' semplicemente quella del viewport. Prima .chat-page non era definita
   affatto in questo foglio, quindi sul web l'elenco dei messaggi non era contenuto in altezza e a
   scorrere si trascinava tutta la pagina. */
.chat-page {
    /* I 20px sottratti sono il "padding-top: 20px" che il media query piu' su in questo foglio da'
       a .main, dentro cui questa pagina vive: senza sottrarlo l'altezza piena del viewport sfondava
       di esattamente quei 20px e la barra di scrittura finiva sotto il bordo dello schermo. Nella
       copia MAUI al loro posto ci sono le fasce di sistema, var(--safe-*), che li' sono il padding
       di .main. La prima dichiarazione e' il ripiego per i browser che non conoscono dvh. */
    height: calc(100vh - 20px);
    height: calc(100dvh - 20px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.chat-messages {
    flex: 1;
    /* min-height: 0 e' la correzione decisiva. In un contenitore flex in colonna la misura minima
       automatica di un elemento e' quella del suo contenuto: con abbastanza messaggi l'elenco NON
       si restringeva, sfondava .chat-page e spingeva fuori il titolo e la barra di scrittura. Da lì
       il fatto che a volte si trascinasse tutta la pagina invece dei soli messaggi, e solo "alcune
       volte" perche' con pochi messaggi il problema non si presenta. */
    min-height: 0;
    overflow-y: auto !important;
    /* Arrivati in cima o in fondo all'elenco il trascinamento si fermi lì, senza passare alla
       pagina sottostante. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.5rem;
    background-color: #f7f8f9;
}

/* Il titolo non scorre e non e' un comando: un trascinamento che parte da qui non deve muovere
   nulla. L'overscroll-behavior su html/body spegne gia' il rimbalzo del documento, ma e' arrivato
   solo con Safari 16 e il minimo dell'app e' iOS 15 (vedi SupportedOSPlatformVersion nel csproj):
   questa riga copre anche quelle versioni, dove la proprieta' viene ignorata. */
.chat-page .page-title {
    touch-action: none;
}

/* Separatore di giornata: la data al centro con un filo ai lati. Prima i messaggi di giorni
   diversi si susseguivano senza stacco e l'unico riferimento era la data ripetuta in ogni ora. */
.chat-separatore {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.9rem 0.25rem 0.6rem;
    color: #70747c;
}

    .chat-separatore::before,
    .chat-separatore::after {
        content: "";
        flex: 1 1 0;
        height: 1px;
        background-color: #e2e5e8;
    }

.page .chat-separatore span {
    font-size: 0.78em;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Divisore dei messaggi non letti: era una fascia grigia a tutta larghezza col testo bianco
   dentro, che sembrava un errore di stile piu' che un riferimento. */
.chat-separatore-nuovi {
    color: #c62828;
}

    .chat-separatore-nuovi::before,
    .chat-separatore-nuovi::after {
        background-color: #f1c9c9;
    }

/* Fumetto. L'angolo dal lato di chi scrive resta quadrato: e' quello che da' al fumetto un verso,
   senza dover disegnare la codina con uno pseudo-elemento ruotato. */
.chat-fumetto {
    max-width: 78%;
    padding: 0.5rem 0.7rem 0.35rem;
    border-radius: 1rem;
    box-shadow: 0 1px 2px rgba(33, 37, 41, .08);
    overflow-wrap: anywhere;
}

.chat-fumetto-mio {
    border-bottom-right-radius: 0.25rem;
    background-color: #1b6ec2;
    color: #fff;
}

.chat-fumetto-altrui {
    border: 1px solid #e7e9ec;
    border-bottom-left-radius: 0.25rem;
    background-color: #fff;
    color: #242326;
}

.page .chat-fumetto-mittente {
    margin-bottom: 0.1rem;
    color: #1b6ec2;
    font-size: 0.75em;
    font-weight: 700;
}

.page .chat-fumetto-ora {
    font-size: 0.7em;
    opacity: 0.75;
}

/* L'immagine riempie il fumetto invece di lasciare il bordo colorato attorno. */
.chat-fumetto img {
    display: block;
    max-width: 100%;
    border-radius: 0.7rem;
}

/* Avviso di sistema: non l'ha scritto nessuno, quindi non prende la forma del fumetto e non si
   schiera su un lato. Prima era testo giallo dentro un fumetto grigio, indistinguibile da un
   messaggio vero. */
.chat-avviso {
    max-width: 90%;
    margin: 0.35rem auto;
    padding: 0.5rem 0.8rem;
    border: 1px solid #ffe1a8;
    border-radius: 0.8rem;
    background-color: #fff8e6;
    color: #7a5b00;
    text-align: center;
}

/* Bacheca: la sede pubblica e il donatore legge, non c'e' una conversazione da alternare sui due
   lati. Fumetti e avvisi prendono tutta la larghezza, senza il verso dato dall'angolo quadrato. */
.chat-bacheca .chat-fumetto-bacheca {
    flex-grow: 1;
    max-width: 100%;
    border-radius: 0.8rem;
}

.chat-bacheca .chat-avviso-bacheca {
    max-width: 100%;
    text-align: left;
}

.chat-avviso-testo-notifica {
    font-size: 0.9em;
}

/* Barra di composizione: era "bg-secondary bg-opacity-25", cioe' una fascia grigia spenta. */
.chat-input {
    border-top: 1px solid #e2e5e8;
    background-color: #fff;
}

    .chat-input .form-control {
        border-radius: 1.1rem;
    }

/* Comandi tondi (allegati, invio): la stessa forma dei pulsanti del tesserino. */
.chat-tondo {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border-radius: 50%;
}

.page .chat-tondo i {
    font-size: 1.15em;
}

/* Avviso sugli orari della sede, in cima alla chat. Due gradi: ambra quando la sede sta per
   chiudere (o quando l'unico motivo e' la festivita'), rosso quando e' gia' chiusa. Colori e
   bordo sono impostati qui e non con le classi "alert" di Bootstrap perche' il riquadro deve
   avere gli stessi angoli tondi dei fumetti e dell'anteprima allegato. */
.chat-avviso-orari {
    border: 1px solid;
    border-radius: 0.9rem;
    padding: 0.7rem 0.9rem;
    text-align: center;
    /* Il riquadro e' figlio diretto di .chat-page, che non ha padding orizzontale: senza questi
       margini tocca i bordi della pagina. Sono leggermente piu' larghi del px-2 dell'area
       messaggi, cosi' l'avviso si stacca dai fumetti invece di allinearcisi. */
    margin-left: 0.75rem;
    margin-right: 0.75rem;
}

/* Prefissate con .page come gli altri blocchi: serve per avere la meglio su ".page.medium *" e
   ".page.large *" senza rinunciare al ridimensionamento del testo. */
.page .chat-avviso-orari .chat-avviso-titolo {
    font-weight: 600;
    margin-bottom: 0.15rem;
}

.page .chat-avviso-orari .chat-avviso-testo {
    font-size: 0.9em;
    line-height: 1.35;
}

/* Sta per chiudere */
.chat-avviso-attesa {
    border-color: #e8cf8b;
    background-color: #fdf7e6;
    color: #7a5a06;
}

/* Gia' chiusa */
.chat-avviso-chiusa {
    border-color: #eeb0ab;
    background-color: #fdeeed;
    color: #8f2e25;
}

/* Anteprima dell'allegato prima dell'invio. */
.chat-anteprima {
    padding: 0.6rem;
    border: 1px solid #e7e9ec;
    border-radius: 0.9rem;
    background-color: #f7f8f9;
}


/* ===================================== */
/* PRENOTAZIONI (wizard in quattro passi)*/
/* ===================================== */

/* Stesse convenzioni dei blocchi sopra: misure in em e selettori prefissati con .page, per avere
   la meglio su ".page.medium *" / ".page.large *" senza rinunciare al ridimensionamento del testo. */

/* Indicatore di avanzamento: prima nulla diceva quanti passi ci fossero ne' a che punto si era,
   e l'unico riferimento era il titolo della pagina, uguale in tutti e quattro gli step. */
.wizard-passi {
    display: flex;
    margin-bottom: 1.1rem;
}

.wizard-passo {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    text-align: center;
}

/* Il filo di collegamento: parte da metà della cella precedente e arriva a metà di questa, cosi'
   passa esattamente da pallino a pallino senza doverne conoscere la posizione. Sta sotto ai
   pallini (che hanno z-index 1) e non prima del primo passo, che non ha nulla a sinistra. */
.wizard-passo + .wizard-passo::before {
    content: "";
    position: absolute;
    top: 0.8rem;
    left: -50%;
    right: 50%;
    height: 2px;
    background-color: #e2e5e8;
}

.wizard-passo.wizard-fatto::before,
.wizard-passo.wizard-corrente::before {
    background-color: #1b6ec2;
}

.wizard-pallino {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    border: 2px solid #e2e5e8;
    border-radius: 50%;
    background-color: #fff;
    color: #adb5bd;
}

.page .wizard-pallino {
    font-size: 0.8em;
    font-weight: 700;
    line-height: 1;
}

.wizard-passo.wizard-fatto .wizard-pallino {
    border-color: #1b6ec2;
    background-color: #1b6ec2;
    color: #fff;
}

.wizard-passo.wizard-corrente .wizard-pallino {
    border-color: #1b6ec2;
    color: #1b6ec2;
    box-shadow: 0 0 0 3px rgba(27, 110, 194, .15);
}

.page .wizard-etichetta {
    color: #adb5bd;
    font-size: 0.68em;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.15;
    text-transform: uppercase;
}

.wizard-passo.wizard-fatto .wizard-etichetta,
.wizard-passo.wizard-corrente .wizard-etichetta {
    color: #1b6ec2;
}

/* Comandi in fondo a ogni passo: a tutta larghezza, cosi' il pollice li trova sempre nello stesso
   punto invece di inseguire due pulsanti di larghezza diversa agli angoli. */
.wizard-comandi {
    display: flex;
    gap: 0.5rem;
    margin-top: 1rem;
}

    .wizard-comandi .btn {
        flex: 1 1 0;
    }

/* ---- Calendario ---- */

.calendario-testa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
}

.page .calendario-mese {
    margin: 0;
    font-size: 1.05em;
    font-weight: 700;
    text-transform: capitalize;
}

/* Griglia e non tabella: la tabella aveva "w-auto" e si stringeva sul contenuto, quindi le celle
   restavano piccole e disallineate rispetto alla larghezza della pagina. Con le sette colonne in
   frazioni la griglia occupa tutta la larghezza disponibile qualunque essa sia. */
.calendario-griglia {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0.25rem;
}

.page .calendario-intestazione {
    padding-bottom: 0.2rem;
    color: #70747c;
    font-size: 0.7em;
    font-weight: 700;
    text-align: center;
    text-transform: uppercase;
}

.calendario-giorno {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    /* aspect-ratio tiene le celle quadrate al variare della larghezza; il min-height serve ai
       WebView che non lo conoscono, dove la cella resta comunque toccabile. */
    aspect-ratio: 1 / 1;
    min-height: 2.2rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 0.55rem;
    background: none;
    font: inherit;
    line-height: 1;
}

.calendario-giorno:disabled {
    cursor: default;
}

/* Le celle fuori dal mese occupano il posto ma non si vedono: servono a tenere l'allineamento
   delle colonne, non a essere lette. */
.calendario-vuoto {
    visibility: hidden;
}

.calendario-libero {
    border-color: #cfe9d7;
    background-color: #e8f6ec;
    color: #1b6e3c;
    font-weight: 700;
}

/* Tinta e non fondo pieno: prima ogni giorno senza posti era un rettangolo rosso a tutto campo, e
   un mese quasi chiuso sembrava una pagina di errori. */
.calendario-pieno {
    border-color: #f6d6d6;
    background-color: #fdeaea;
    color: #a33a3a;
}

.calendario-passato {
    background-color: #f4f5f6;
    color: #adb5bd;
}

.calendario-scelto {
    border-color: #1b6ec2 !important;
    background-color: #1b6ec2 !important;
    color: #fff !important;
    box-shadow: 0 0 0 3px rgba(27, 110, 194, .2);
}

/* Puntino sotto al numero: distingue "libero" da "scelto" anche per chi non separa il verde dal
   blu, e conferma che su quel giorno c'e' qualcosa da prenotare. */
.calendario-posti {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background-color: currentColor;
    opacity: 0.7;
}

.calendario-legenda {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
    margin-top: 0.7rem;
    color: #70747c;
}

.page .calendario-legenda {
    font-size: 0.75em;
}

    .calendario-legenda span {
        display: inline-flex;
        align-items: center;
        gap: 0.3rem;
    }

    .calendario-legenda i {
        display: inline-block;
        width: 0.7rem;
        height: 0.7rem;
        border-radius: 0.2rem;
    }

.legenda-libero {
    border: 1px solid #cfe9d7;
    background-color: #e8f6ec;
}

.legenda-pieno {
    border: 1px solid #f6d6d6;
    background-color: #fdeaea;
}

/* ---- Fasce orarie ---- */

/* Erano una tabella a una colonna: una riga per orario, tutta la larghezza sprecata e una lista
   lunghissima da scorrere. In griglia ci stanno tre o quattro orari per riga. */
.fasce-griglia {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
    gap: 0.5rem;
}

.fascia-pastiglia {
    padding: 0.55rem 0.3rem;
    border: 1px solid #d7dbe0;
    border-radius: 0.7rem;
    background-color: #fff;
    font: inherit;
    font-weight: 700;
    color: #242326;
}

.fascia-scelta {
    border-color: #1b6ec2;
    background-color: #1b6ec2;
    color: #fff;
}

/* ---- Informativa ---- */

/* La pagina resta grande quanto tutte le altre: il pannello sta nel flusso, dentro .main, quindi
   non finisce sotto alla sidebar e non c'e' niente da trascinare di lato. A scorrere e' il solo
   documento, dentro il suo riquadro.

   Due tentativi precedenti sono stati sbagliati e vale la pena ricordarli: con position: fixed il
   pannello nel WebView nasceva piu' largo dello schermo e con il pulsante fuori portata; lasciando
   scorrere la pagina intera il documento passava sotto alla sidebar, che e' fissa. */

.pannello-accesso.informativa-pannello {
    display: flex;
    flex-direction: column;
    max-width: 42rem;
    margin: 0 auto;
    /* Altezza definita: senza, il riquadro del documento non ha un limite entro cui scorrere e si
       torna a trascinare la pagina. Lo stacco sottratto e' quello sopra e sotto il pannello (il
       padding-top di .main, che qui vale 20px, e il margine del contenitore). Come in .chat-page la
       prima dichiarazione e' il ripiego per i browser che non conoscono dvh; le fasce di sistema,
       che nella copia MAUI entrano nel conto, sul web non esistono. */
    height: calc(100vh - 20px - 4.5rem);
    height: calc(100dvh - 20px - 4.5rem);
    /* La spaziatura la mettono le tre fasce interne. */
    padding: 0;
    overflow: hidden;
}

/* Riga con il ritorno alla registrazione e i comandi dello zoom. Il pulsante di conferma sta in
   fondo al documento, che e' lungo: senza una via d'uscita in cima si resta dentro l'informativa
   senza poterne uscire. */
.informativa-testa {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.45rem 0.55rem;
    border-bottom: 1px solid #e7e9ec;
}

.informativa-zoom {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

.informativa-testa button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 2.4rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background-color: transparent;
    color: #1b6ec2;
}

.informativa-testa button:active {
    background-color: #eef4fb;
}

.informativa-testa button:disabled {
    color: #b9bec5;
    background-color: transparent;
}

.page .informativa-testa button i {
    font-size: 1.25em;
}

/* Il visore del documento: e' qui che si scorre, in tutte e due le direzioni, e mai fuori dai
   propri bordi. */
.documento-visore {
    flex: 1;
    /* Stessa correzione di .chat-messages: senza, il riquadro non si restringe, sfonda il pannello
       e porta il pulsante fuori schermo. */
    min-height: 0;
    /* Lo stesso, ma di lato. Il pannello sta in un elemento flessibile largo quanto il suo
       contenuto: senza questo azzeramento un documento con dentro qualcosa di indivisibile - un
       indirizzo PEC lunghissimo, una tabella - alza la larghezza minima di tutta la catena, il
       pannello non riesce piu' a restringersi e va oltre lo schermo. Con min-width a zero la
       larghezza in eccesso resta dentro il visore, che la fa scorrere. */
    min-width: 0;
    overflow: auto;
    /* Arrivati a un bordo il trascinamento si ferma li', senza passare alla pagina sottostante. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 1rem 1.15rem 1.25rem;
    /* Serve alle unita' cqw qui sotto: e' questo il riquadro rispetto a cui si misura il documento. */
    container-type: inline-size;
}

.documento-informativa {
    zoom: var(--zoom-informativa, 1);
}

/* Niente larghezza imposta: il documento e' un blocco normale e si adatta al visore.
   Prima era 100cqw, per far diventare il contenuto davvero piu' largo del riquadro sotto
   ingrandimento invece di limitarsi a riandare a capo. Ma i comandi dello zoom non sono mai stati
   collegati, e le cqw si contano sul riquadro SENZA togliere la barra di scorrimento verticale:
   il documento nasceva quindi una quindicina di pixel piu' largo dello spazio disponibile e il
   visore si ritrovava una barra orizzontale buona a nulla. Un contenuto davvero piu' largo - una
   tabella, un facsimile di PDF - scorre lo stesso, perche' il visore e' in overflow auto. */

.informativa-comandi {
    padding: 0.75rem 1.15rem 0.9rem;
    border-top: 1px solid #e7e9ec;
}

/* Il contenuto arriva dal server come HTML e ogni sede scrive il suo: queste regole vestono i tag
   che ci si puo' aspettare di trovare. Nell'informativa di serie i capoversi sono <label>, che
   senza una regola restano in linea e si leggono come un unico blocco continuo. */

.page .documento-informativa h1 {
    margin: 0 0 0.9rem;
    font-size: 1.2em;
    font-weight: 700;
    line-height: 1.25;
    color: #212529;
}

.page .documento-informativa h2,
.page .documento-informativa h3 {
    margin: 1.3rem 0 0.5rem;
    font-size: 1.05em;
    font-weight: 700;
    color: #212529;
}

.page .documento-informativa label,
.page .documento-informativa p,
.page .documento-informativa li {
    display: block;
    margin: 0 0 0.85rem;
    font-size: 0.95em;
    line-height: 1.55;
    color: #3c4249;
}

/* Le voci di elenco no: "display: block" gli porta via il numero o il pallino, che nel display
   list-item e' un pezzo della voce stessa. Fino a quando gli unici documenti erano scritti a
   capoversi non si notava; con un'informativa che usa <ol> e <ul> veri gli elenchi arrivavano
   senza contrassegno e le voci numerate perdevano il numero. Il resto della riga sopra - margine,
   corpo, interlinea, colore - resta valido anche qui. */
.page .documento-informativa li {
    display: list-item;
}

/* Le tabelle dei documenti sono strette quanto serve, non stirate a tutta larghezza, e una che
   non ci sta scorre per conto suo dentro .table-responsive invece di allargare il visore. */
.page .documento-informativa table {
    width: auto;
    max-width: 100%;
    margin-bottom: 0.85rem;
}

/* Il capoverso di apertura dice di che documento si tratta: si stacca dagli altri. */
.page .documento-informativa label:first-of-type {
    font-weight: 600;
    color: #212529;
}

.page .documento-informativa ul,
.page .documento-informativa ol {
    margin: 0 0 0.85rem;
    padding-left: 1.2rem;
}

.page .documento-informativa a {
    color: #1b6ec2;
    text-decoration: underline;
}

/* Un indirizzo di posta o un link scritto per intero e' una parola sola: dove non ci sta il
   browser preferisce sfondare il riquadro piuttosto che spezzarlo. Fra i valori che lo spezzano
   "anywhere" e' l'unico che abbassa anche la larghezza minima del blocco, ed e' quella a contare
   perche' il pannello possa restringersi. Le parole normali non ne risentono: la rottura scatta
   solo quando la riga da sola non basta. */
.documento-informativa {
    overflow-wrap: anywhere;
}

/* Qualche sede mette il proprio logo nell'informativa, alla dimensione con cui e' stato caricato:
   quasi sempre piu' larga di un telefono. */
.documento-informativa img {
    max-width: 100%;
    height: auto;
}


/* ===================================== */
/* POPUP DI CONFERMA                     */
/* ===================================== */

/* Un solo aspetto per tutti gli avvisi dell'app. Prima ogni pagina si scriveva la sua modale
   Bootstrap a mano - nove copie in sei file - e si vedeva: intestazioni con e senza pulsante di
   chiusura, pulsanti in ordine invertito da una schermata all'altra, un "btn-default" che in
   Bootstrap 5 non esiste piu' e quindi restava senza colore.

   I selettori sono a due classi (".popup" piu' la classe interna) e non a una: piu' su in questo
   foglio ".page.medium *" e ".page.large *" assegnano un font-size a QUALSIASI discendente, e a
   una sola classe vincerebbero loro. Non si usa il prefisso .page perche' il popup della
   disconnessione vive dentro la Sidebar, che sta fuori da .page (vedi il blocco della sidebar).
   Le misure sono in em per continuare a seguire il selettore del carattere dove c'e'. */

.popup-velo {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
    background-color: rgba(33, 37, 41, .55);
    /* Lo stesso piano delle modali Bootstrap che sostituisce (1055), cosi' i rapporti con gli
       altri strati non cambiano: il riquadro di errore (1100) resta sopra, la guida (1399+) pure,
       l'overlay del PIN (2000) e il loader (9999) anche. */
    z-index: 1055;
}

.popup {
    width: 100%;
    max-width: 22rem;
    max-height: 90%;
    overflow-y: auto;
    padding: 1.25rem 1.1rem 1.1rem;
    border-radius: 1.1rem;
    background-color: #fff;
    box-shadow: 0 12px 40px rgba(33, 37, 41, .28);
    text-align: center;
}

/* Il tondo con l'icona da' il tono dell'avviso prima che si legga il testo: azzurro per
   un'informazione, verde per una cosa andata a buon fine, rosso per una da confermare che poi non
   si torna indietro. */
.popup .popup-icona {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    margin: 0 auto 0.75rem;
    border-radius: 50%;
    background-color: #eaf2fb;
    color: #1b6ec2;
}

.popup .popup-icona i {
    font-size: 1.6em;
    line-height: 1;
}

/* L'attesa prende il posto dell'icona dentro allo stesso tondo: l'avviso non si chiude e riapre,
   cambia solo quel pezzo. Il colore del tratto e' currentColor, cioe' quello che il tono ha gia'
   dato al tondo, cosi' non c'e' una variante per ognuno. Le misure sono in rem e non in em: qui
   dentro non c'e' testo da cui ereditare, e con il selettore del carattere in "grande" un cerchio
   piu' largo del tondo che lo contiene sborderebbe. */
.popup .popup-attesa {
    width: 1.9rem;
    height: 1.9rem;
    border: 3px solid rgba(33, 37, 41, .15);
    border-top-color: currentColor;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.popup .popup-icona-successo {
    background-color: #e8f6ec;
    color: #1b6e3c;
}

.popup .popup-icona-attenzione {
    background-color: #fff8e6;
    color: #9a6f00;
}

.popup .popup-icona-pericolo {
    background-color: #fdeaea;
    color: #c62828;
}

.popup .popup-titolo {
    margin: 0 0 0.4rem;
    color: #242326;
    font-size: 1.1em;
    font-weight: 700;
    line-height: 1.25;
}

.popup .popup-corpo {
    color: #55585e;
    line-height: 1.45;
    overflow-wrap: anywhere;
}

.popup .popup-corpo p:last-child {
    margin-bottom: 0;
}

/* I comandi in colonna e a tutta larghezza: su un telefono due pulsanti affiancati diventano
   stretti e si tocca quello sbagliato. L'azione principale sta in alto, dove arriva il pollice. */
.popup .popup-comandi {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 1.1rem;
}

.popup .popup-comandi .btn {
    width: 100%;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    font-size: 1em;
}


/* ===================================== */
/* RICERCA SEDE                          */
/* ===================================== */

/* La ricerca e' la prima schermata che si vede dell'app, prima ancora del login. */

.ricerca-testa {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
    text-align: center;
}

.ricerca-testa img {
    max-height: 4.5rem;
}

/* Schermata di apertura: e' la prima cosa che si vede avviando l'app (lettura dell'elenco sedi)
   e torna mentre si verifica il server della sede scelta. Logo al centro in un disco bianco
   con un alone che pulsa piano, titolo, e una barra indeterminata nei due colori del logo al
   posto della rotella generica. Leggermente sopra il centro, dove l'occhio si aspetta un
   logo di avvio. */
.caricamento-schermata {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 85vh;
    padding: 2rem 1.5rem 12vh;
    text-align: center;
    background: radial-gradient(circle at 50% 38%, #eaf3fd 0%, rgba(234, 243, 253, 0) 62%);
    animation: caricamento-comparsa 0.35s ease-out both;
}

/* L'alone e' la terza ombra, che si allarga dal bordo del disco e svanisce: un anello con uno
   pseudo-elemento finirebbe sotto lo sfondo sfumato del contenitore. */
.caricamento-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 7.5rem;
    height: 7.5rem;
    margin-bottom: 1.75rem;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 10px 30px rgba(0, 86, 179, 0.14), 0 2px 6px rgba(0, 86, 179, 0.08), 0 0 0 0 rgba(0, 123, 255, 0.28);
    animation: caricamento-alone 2s ease-out infinite;
}

    .caricamento-logo img {
        width: 4.6rem;
        height: auto;
    }

.page .caricamento-titolo,
.caricamento-titolo {
    margin: 0 0 1.75rem;
    color: #1d2b3a;
    font-weight: 600;
    font-size: 1.35rem;
    letter-spacing: 0.01em;
}

.caricamento-barra {
    position: relative;
    width: 9.5rem;
    height: 4px;
    overflow: hidden;
    border-radius: 2px;
    background: #e3ecf7;
}

    .caricamento-barra span {
        position: absolute;
        top: 0;
        bottom: 0;
        left: -40%;
        width: 40%;
        border-radius: 2px;
        background: linear-gradient(90deg, #007bff, #e30613);
        animation: caricamento-scorrimento 1.3s ease-in-out infinite;
    }

.page .caricamento-testo,
.caricamento-testo {
    margin: 0.9rem 0 0;
    color: #70747c;
    font-size: 0.9em;
}

/* Nome della sede che si sta ricontattando, sotto il titolo "Bentornato": riga sua, perche'
   inserito in una frase non si accorderebbe con nessuna preposizione. Il margine negativo lo
   avvicina al titolo, che da solo tiene piu' spazio verso la barra. */
.page .caricamento-sede,
.caricamento-sede {
    max-width: 18rem;
    margin: -1.25rem 0 1.75rem;
    color: #0056b3;
    font-weight: 600;
    font-size: 1rem;
    line-height: 1.35;
}

/* Avviso che compare se la sede tarda a rispondere: dice che l'attesa dipende dalla sede */
.page .caricamento-lento,
.caricamento-lento {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    max-width: 18rem;
    margin: 1.25rem 0 0;
    padding: 0.6rem 0.85rem;
    border-radius: 0.75rem;
    background: #fff6e5;
    color: #7a5200;
    font-size: 0.85em;
    line-height: 1.4;
    text-align: left;
    animation: caricamento-comparsa 0.35s ease-out both;
}

    .caricamento-lento i {
        flex: 0 0 auto;
        margin-top: 0.1em;
    }

@media (prefers-reduced-motion: reduce) {
    .caricamento-lento {
        animation: none;
    }
}

@keyframes caricamento-comparsa {
    from {
        opacity: 0;
        transform: translateY(6px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes caricamento-alone {
    0% {
        box-shadow: 0 10px 30px rgba(0, 86, 179, 0.14), 0 2px 6px rgba(0, 86, 179, 0.08), 0 0 0 0 rgba(0, 123, 255, 0.28);
    }

    100% {
        box-shadow: 0 10px 30px rgba(0, 86, 179, 0.14), 0 2px 6px rgba(0, 86, 179, 0.08), 0 0 0 1.6rem rgba(0, 123, 255, 0);
    }
}

@keyframes caricamento-scorrimento {
    0% {
        left: -40%;
    }

    100% {
        left: 100%;
    }
}

/* Chi ha chiesto meno movimento vede la barra ferma a meta' e nessun alone */
@media (prefers-reduced-motion: reduce) {
    .caricamento-schermata,
    .caricamento-logo,
    .caricamento-barra span {
        animation: none;
    }

    .caricamento-barra span {
        left: 30%;
    }
}

.page .ricerca-sottotitolo {
    max-width: 20rem;
    margin: 0;
    color: #70747c;
    font-size: 0.9em;
    line-height: 1.4;
}

/* Il campo e il pulsante della posizione sono un gruppo solo, con gli angoli tondi agli estremi:
   l'input-group di Bootstrap li squadrava e sembravano due controlli incollati. */
.ricerca-campo {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

    .ricerca-campo .form-control {
        border-radius: 1.4rem;
        padding-left: 1rem;
    }

/* Tondo per davvero: larghezza e altezza sono lo stesso valore, scritto due volte.
   Non basta "aspect-ratio: 1" con width auto, che era il tentativo precedente: il pulsante e' un
   flex item e la sua misura minima automatica e' quella del contenuto, quindi la larghezza restava
   quella dell'icona mentre l'altezza arrivava dallo stretch del contenitore — ovale.
   La misura e' in em e non in rem cosi' segue il campo di ricerca, che cresce col selettore del
   carattere; il contenitore non stira piu' (align-items: center), altrimenti l'altezza tornerebbe
   a essere imposta da fuori. */
.ricerca-posizione {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.6em;
    height: 2.6em;
    padding: 0;
    border-radius: 50%;
}

.page .ricerca-posizione i {
    font-size: 1.1em;
}

/* Il raggio: il valore va accanto all'etichetta come pastiglia, non annegato nel testo. */
.ricerca-raggio-testa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
}

.page .ricerca-raggio-valore {
    padding: 0.15rem 0.55rem;
    border-radius: 1rem;
    background-color: #eaf2fb;
    color: #1b6ec2;
    font-size: 0.8em;
    font-weight: 700;
}

/* Distanza della sede: pastiglia a destra del nome, cosi' si confrontano a colpo d'occhio invece
   di cercarle in fondo a tre righe di testo. */
.page .ricerca-distanza {
    flex: 0 0 auto;
    padding: 0.15rem 0.5rem;
    border-radius: 1rem;
    background-color: #f1f3f5;
    color: #55585e;
    font-size: 0.75em;
    font-weight: 700;
    white-space: nowrap;
}

/* Il pallino di stato del server dentro la scheda: allineato alla prima riga del nome. */
.scheda-testa .pallino-stato {
    margin-top: 0.3rem;
}

/* Selettore Elenco / Mappa: due metà di una pastiglia, quella attiva piena. */
.ricerca-vista {
    display: flex;
    padding: 0.2rem;
    border-radius: 1.4rem;
    background-color: #eaf2fb;
}

    .ricerca-vista button {
        flex: 1 1 0;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.4rem;
        padding: 0.4rem 0.75rem;
        border: 0;
        border-radius: 1.2rem;
        background: transparent;
        color: #1b6ec2;
        font-weight: 600;
        transition: background-color 0.15s ease, color 0.15s ease;
    }

        .ricerca-vista button.attiva {
            background-color: #007bff;
            color: #fff;
            box-shadow: 0 2px 6px rgba(0, 86, 179, 0.25);
        }

/* La mappa occupa quasi tutto lo schermo sotto il campo: e' lei il contenuto della pagina.
   L'altezza fissa serve a Leaflet, che con un contenitore alto zero non disegna nulla. */
.ricerca-mappa {
    height: 62vh;
    min-height: 18rem;
    border-radius: 1rem;
    overflow: hidden;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
    /* Sotto ai popup e alla guida dell'app: Leaflet usa z-index fino a 1000 nei suoi strati. */
    position: relative;
    z-index: 0;
}

/* Sede sulla mappa: spillo blu con la goccia rossa, i colori del logo (lo disegna mappa-sedi.js),
   uguale per tutte le sedi. L'elemento e' l'area di tocco (40 x 46, trasparente); lo spillo
   (30 x 39) sta in basso al centro, con la punta sulle coordinate della sede. */
.mappa-sede {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: transparent;
    cursor: pointer;
}

    /* Misure scritte qui e non solo nell'SVG: sotto i 768 px la regola "svg { 16px }" della
       sezione dei caratteri le schiacciava, e lo spillo cambiava misura con la larghezza della
       finestra. Devono restare uguali a LARGHEZZA_SPILLO / ALTEZZA_SPILLO di mappa-sedi.js. */
    .leaflet-container .mappa-sede .mappa-sede-spillo {
        display: block;
        width: 30px;
        height: 39px;
        flex: 0 0 auto;
        filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.35));
    }

/* Bolla con il numero di sedi della zona: si divide facendo zoom. */
.mappa-cluster {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 3px solid rgba(255, 255, 255, 0.85);
    border-radius: 50%;
    background-color: rgba(0, 86, 179, 0.88);
    box-shadow: 0 2px 8px rgba(0, 86, 179, 0.35);
    color: #fff;
    font-weight: 700;
    font-size: 0.85rem;
}

.mappa-fumetto {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.mappa-fumetto-nome {
    color: #1d2b3a;
    font-weight: 700;
    font-size: 0.95rem;
}

.mappa-fumetto-indirizzo {
    color: #70747c;
    font-size: 0.8rem;
    line-height: 1.35;
}

.mappa-fumetto-scegli {
    margin-top: 0.25rem;
    border-radius: 1rem;
}

/* Crediti della mappa raccolti in un pallino "i" nell'angolo: toccato si apre sul testo con i
   link (OpenStreetMap e' obbligatorio per licenza), toccato di nuovo si richiude. */
.leaflet-container .mappa-crediti {
    margin: 0 0.4rem 0.4rem 0;
    border-radius: 1rem;
    background-color: rgba(255, 255, 255, 0.85);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    cursor: pointer;
}

    .leaflet-container .mappa-crediti:not(.aperti) {
        width: 1.4rem;
        height: 1.4rem;
        padding: 0;
        overflow: hidden;
        font-size: 0;
        color: transparent;
    }

        .leaflet-container .mappa-crediti:not(.aperti) a {
            display: none;
        }

        .leaflet-container .mappa-crediti:not(.aperti)::before {
            content: "i";
            display: block;
            line-height: 1.4rem;
            text-align: center;
            color: #55585e;
            font: italic 700 0.8rem/1.4rem Georgia, serif;
        }

    .leaflet-container .mappa-crediti.aperti {
        padding: 0.15rem 0.6rem;
        font-size: 0.7rem;
    }


/* ===================================== */
/* PANNELLI DI ACCESSO                   */
/* ===================================== */

/* Login, registrazione e reimpostazione password usavano "card shadow", ma .card e' azzerata piu'
   su in questo foglio (bordo, sfondo, ombra e padding a zero dentro un @media sempre attivo):
   il riquadro non c'era, i campi galleggiavano sul bianco della pagina. Questa classe fa quello
   che .card avrebbe dovuto fare, senza toccare la regola che vale per tutta l'app. */
.pannello-accesso {
    padding: 1.25rem 1.1rem;
    border: 1px solid #e7e9ec;
    border-radius: 1.1rem;
    background-color: #fff;
    box-shadow: 0 6px 24px rgba(33, 37, 41, .07);
}

.accesso-testa {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 1.1rem;
    text-align: center;
}

.accesso-testa img {
    max-height: 5rem;
}

.page .accesso-titolo {
    margin: 0;
    font-size: 1.3em;
    font-weight: 700;
}

.page .accesso-sede {
    margin: 0;
    color: #1b6ec2;
    font-size: 0.95em;
    font-weight: 700;
}

.page .accesso-testo {
    max-width: 22rem;
    margin: 0;
    color: #70747c;
    font-size: 0.9em;
    line-height: 1.4;
}

/* Separatore fra l'accesso con la password e quello rapido (impronta, volto, PIN): dice che sotto
   c'e' un'alternativa, non un seguito. */
.accesso-separatore {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.25rem 0;
    color: #adb5bd;
}

    .accesso-separatore::before,
    .accesso-separatore::after {
        content: "";
        flex: 1 1 0;
        height: 1px;
        background-color: #e7e9ec;
    }

.page .accesso-separatore span {
    font-size: 0.75em;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}


/* ===================================== */
/* TITOLO DI PAGINA                      */
/* ===================================== */

/* Una sola classe per il titolo di tutte le pagine. Prima la chat usava .page-title e tutte le
   altre un "h3 text-center mb-4" dentro un contenitore con "mt-4": il titolo era piu' in basso e
   piu' smilzo che nella chat, e cambiava posizione passando da una pagina all'altra.
   Il margine superiore in vh riprende quello che aveva la chat, che e' l'altezza voluta. */
.page-title {
    margin: 2vh 0 1.1rem;
    font-weight: 800;
    line-height: 1.15;
    text-align: center;
}

/* Prefissato con .page per battere ".page.medium *" / ".page.large *", che assegnano un font-size
   a qualunque discendente; in em perche' continui a seguire il selettore del carattere. */
.page .page-title {
    font-size: 1.45em;
}

/* Trattino sotto al titolo: lo stacca dal contenuto senza bisogno di un margine grande, e da' alla
   pagina un punto d'inizio riconoscibile. */
.page-title::after {
    content: "";
    display: block;
    width: 2.5rem;
    height: 3px;
    margin: 0.5rem auto 0;
    border-radius: 2px;
    background-color: #1b6ec2;
}

/* Nel tesserino il titolo sta in una riga con il pulsante del barcode a sinistra: il trattino
   centrato sotto a un titolo che occupa solo parte della riga risulterebbe fuori asse. */
.page-title-in-riga::after {
    display: none;
}


/* ===================================== */
/* PIN A SEI CIFRE                       */
/* ===================================== */

/* La schermata sta in alto e non piu' in mezzo. Al centro del viewport ci finiva sotto la tastiera:
   si apriva il tastierino e di celle e comandi restava visibile una striscia, giusto il tempo di
   vederli sparire. Ancorata in alto resta tutto sopra la tastiera su qualunque telefono, e se
   proprio non ci sta (schermo basso, carattere grande) la schermata scorre invece di tagliare.
   Il fallback 0px sugli inset serve a chi non ha env(): senza, l'intera calc() sarebbe invalida. */
.pin-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: calc(var(--safe-top, 0px) + 1.75rem) 1.25rem calc(var(--safe-bottom, 0px) + 1.25rem);
    overflow-y: auto;
    background-color: #fff;
}

/* Le celle non hanno una larghezza fissa in pixel (50, poi 40, poi 32 a seconda del media query):
   si dividono la riga in parti uguali e restano quadrate, quindi il PIN e' grande quanto lo schermo
   lo permette invece di essere tarato su tre soglie. */
.pin-pannello {
    width: 100%;
    max-width: 22rem;
    text-align: center;
}

/* Il tondo con la chiave. Prima l'icona era un <i> nudo: senza il tondo che le da' la misura
   restava grande quanto il testo intorno, un dettaglio da 16px in cima a una schermata che non ha
   altro. Le misure sono in rem e non in em perche' il selettore del carattere in "grande" gonfierebbe
   il tondo fino a rubare l'altezza che serve alle celle. */
.pin-pannello .pin-icona {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 4.5rem;
    height: 4.5rem;
    margin: 0 auto 1.1rem;
    border-radius: 50%;
    background-color: #eaf2fb;
    color: #1b6ec2;
    transition: background-color .2s ease, color .2s ease;
}

.pin-pannello .pin-icona i {
    font-size: 2.3rem;
    line-height: 1;
}

.pin-pannello .pin-titolo {
    margin: 0 0 1.3rem;
    color: #242326;
    font-size: 1.15em;
    font-weight: 700;
    line-height: 1.3;
}

.pin-input-container {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin-bottom: 1.6rem;
}

/* Il PIN si digita in coda, sul tram, davanti a chiunque: le cifre non si devono vedere mai.
   Mascherare il testo del campo (-webkit-text-security: disc) sembrava la strada breve, ma il
   WebView tratta quel campo come una password e lascia in chiaro l'ultima cifra battuta per un
   istante prima di coprirla. Qui le celle sono solo disegno - il riquadro e sopra il pallino,
   acceso dal modello - e le cifre le prende un campo unico e invisibile steso sopra la riga
   (.pin-campo). */
.pin-cella {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    aspect-ratio: 3 / 4;
}

.pin-cell {
    position: absolute;
    inset: 0;
    border: 2px solid #dee2e6;
    border-radius: 0.7rem;
    background-color: #f5f7f9;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}

/* Il campo vero, sopra le celle: prende tocchi e tasti e non mostra niente. Su iOS "color:
   transparent" da solo non basta, WebKit disegna il testo con -webkit-text-fill-color e la cifra
   si vedeva in chiaro per un istante. Il cursore lampeggiante sembrerebbe una settima cifra a
   meta': a dire dove si sta scrivendo basta il bordo blu della cella attiva. Il corpo a 16px
   evita che iOS ingrandisca la pagina quando il campo prende il fuoco. */
.pin-campo {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    outline: none;
    opacity: 0;
    background: transparent;
    font-size: 16px;
    color: transparent;
    -webkit-text-fill-color: transparent;
    caret-color: transparent;
    -webkit-tap-highlight-color: transparent;
}

    /* Il testo selezionato torna visibile anche quando e' trasparente, perche' la selezione
       ridipinge il colore: qui resta trasparente pure quello. */
    .pin-campo::selection {
        background-color: transparent;
        color: transparent;
        -webkit-text-fill-color: transparent;
    }

.pin-pallino {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0.8rem;
    height: 0.8rem;
    margin: -0.4rem 0 0 -0.4rem;
    border-radius: 50%;
    background-color: #242326;
    /* Il tocco e' del campo steso sopra la riga, non del pallino. */
    pointer-events: none;
}

/* Le celle gia' battute si distinguono da quelle ancora da riempire: a pallini tutti uguali, e' il
   solo modo di vedere a colpo d'occhio a che punto si e' arrivati. */
.pin-cella-piena .pin-cell {
    border-color: #bcd4ec;
    background-color: #fff;
}

    .pin-cell.pin-cell-attiva {
        border-color: #1b6ec2;
        background-color: #fff;
        box-shadow: 0 0 0 0.25rem rgba(27, 110, 194, .2);
    }

/* L'esito della verifica. Il pulsante "Conferma" non c'e' piu' - la sesta cifra fa partire il
   controllo da sola - quindi la risposta la danno le celle: verdi per meno di mezzo secondo e la
   schermata si chiude, rosse e scosse se il PIN e' sbagliato, e si svuotano da sole per riprovare.
   E' il riscontro che si vede senza leggere, che e' quello che serve a chi sta digitando. */
.pin-stato-ok .pin-cell {
    border-color: #198754;
    background-color: #e8f6ec;
    box-shadow: none;
    animation: pin-conferma .3s ease;
}

.pin-stato-ok .pin-pallino {
    background-color: #0f5132;
}

.pin-stato-errore .pin-cell {
    border-color: #dc3545;
    background-color: #fdeaea;
    box-shadow: none;
}

.pin-stato-errore .pin-pallino {
    background-color: #a33a3a;
}

/* Solo le celle si scuotono, non il tondo dell'icona che pure porta la stessa classe: e' la riga
   del PIN ad essere sbagliata, ed e' li' che si deve guardare. */
.pin-input-container.pin-stato-errore {
    animation: pin-scuoti .5s cubic-bezier(.36, .07, .19, .97);
}

.pin-pannello .pin-icona.pin-stato-ok {
    background-color: #e8f6ec;
    color: #198754;
}

.pin-pannello .pin-icona.pin-stato-errore {
    background-color: #fdeaea;
    color: #dc3545;
}

@keyframes pin-scuoti {
    10%, 90% {
        transform: translateX(-4px);
    }

    20%, 80% {
        transform: translateX(6px);
    }

    30%, 50%, 70% {
        transform: translateX(-8px);
    }

    40%, 60% {
        transform: translateX(8px);
    }
}

@keyframes pin-conferma {
    50% {
        transform: scale(1.06);
    }
}

/* Riga degli avvisi (PIN sbagliato, account bloccato, tentativi rimasti): erano tre <h5> incolonnati,
   cioe' tre titoli grandi come quello della schermata, che coprivano il messaggio principale. */
.pin-avviso {
    margin-bottom: 0.9rem;
    padding: 0.6rem 0.8rem;
    border-radius: 0.7rem;
    background-color: #fdeaea;
    color: #a33a3a;
}

.pin-pannello .pin-avviso {
    font-size: 0.9em;
}

.pin-avviso-attenzione {
    background-color: #fff8e6;
    color: #7a5b00;
}

/* I comandi in fondo. Erano tre pulsanti pieni a tutta larghezza incolonnati - Conferma, l'altro
   metodo, Annulla - cioe' tre azioni di pari peso a chiudere la schermata. Il Conferma e' sparito e
   quel che resta e' una via d'uscita: un contorno leggero, la forma tonda e la freccia che dice
   dove si torna, senza tirare l'occhio via dalle celle. */
.pin-comandi {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
}

.pin-pannello .pin-comandi button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    padding: 0.55rem 1.5rem;
    border-radius: 2rem;
    background-color: transparent;
    font-family: inherit;
    font-size: 0.95em;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.pin-pannello .pin-comandi button:disabled {
    opacity: .45;
    cursor: default;
}

.pin-btn-alternativo {
    border: 0;
    color: #1b6ec2;
}

    .pin-btn-alternativo:hover,
    .pin-btn-alternativo:active {
        background-color: #eaf2fb;
    }

.pin-btn-annulla {
    border: 1px solid #d8dbe0;
    color: #55585e;
}

    .pin-btn-annulla:hover,
    .pin-btn-annulla:active {
        border-color: #b9bdc4;
        background-color: #f2f4f6;
        color: #242326;
    }


/* ===================================== */
/* SEGNAPOSTO DI CARICAMENTO (SKELETON)  */
/* ===================================== */

/* Al posto del velo bianco con la rotella che copriva tutta la pagina: la struttura di quello che
   sta arrivando si vede subito, e quando i dati arrivano non c'e' un salto perche' i segnaposto
   occupano lo stesso spazio del contenuto vero. Sull'espansione di una scheda e' la differenza fra
   "l'app si e' bloccata" e "quel dato sta arrivando".

   Il gradiente e' largo il quadruplo del segnaposto e viene spostato: e' l'onda di chiarore che
   attraversa la barra. Si anima background-position e non left/width, cosi' il lavoro resta al
   compositore e non costringe il browser a rifare il layout a ogni fotogramma. */
.scheletro {
    display: block;
    border-radius: 0.5rem;
    background-color: #eef0f2;
    background-image: linear-gradient(90deg, #eef0f2 25%, #f7f8f9 37%, #eef0f2 63%);
    background-size: 400% 100%;
    /* Due animazioni: l'onda, e una comparsa ritardata di 400ms con riempimento "both", che tiene il
       segnaposto invisibile per i primi 400ms.
       Serve all'avvio dell'app con l'accesso rapido gia' configurato: si attraversano di fila la
       ricerca sede e il login, ognuna per una frazione di secondo, e i rispettivi segnaposto
       comparivano e sparivano come un lampeggio. Sotto i 400ms non si vede nulla; oltre, il
       segnaposto appare ed e' la' che serve, perche' l'attesa e' vera. Il ritardo e' in CSS e non in
       un timer C# per non aggiungere uno stato e un rendering in piu' a ogni pagina. */
    animation: scheletro-onda 1.4s ease-in-out infinite,
               scheletro-comparsa 1ms linear 400ms both;
}

@keyframes scheletro-comparsa {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes scheletro-onda {
    0% {
        background-position: 100% 50%;
    }

    100% {
        background-position: 0 50%;
    }
}

/* Chi ha chiesto al sistema di ridurre le animazioni vede un segnaposto fermo: qui il movimento
   e' decorativo, l'informazione la da' la forma grigia. */
@media (prefers-reduced-motion: reduce) {
    /* Via l'onda, ma il ritardo di comparsa resta: non e' decorazione, e' quello che evita il
       lampeggio quando l'attesa e' di poche decine di millisecondi. */
    .scheletro {
        animation: scheletro-comparsa 1ms linear 400ms both;
    }
}

.scheletro-tondo {
    border-radius: 50%;
}

/* Un blocco data segnaposto della stessa forma di .scheda-data, cosi' la riga non si sposta
   quando il contenuto vero prende il suo posto. */
.scheletro-data {
    flex: 0 0 3.1rem;
    height: 3.1rem;
    border-radius: 0.7rem;
}

.scheletro-icona {
    flex: 0 0 2.6rem;
    height: 2.6rem;
    border-radius: 0.7rem;
}


/* Codice fiscale sotto al codice a barre: monospazio e lettere distanziate, come lo stampano i
   lettori, cosi' l'operatore puo' leggerlo a voce o digitarlo se la scansione non riesce. Era uno
   style inline con font-size in rem, che il selettore del carattere non toccava. */
.barcode-codice {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: 0.15em;
}

.page .barcode-codice {
    font-size: 0.8em;
}


/* ===================================== */
/* SCHERMATA DI STATO                    */
/* ===================================== */

/* Usata quando una pagina non ha il suo contenuto ma una situazione da spiegare: per esempio la
   prenotazione quando un appuntamento c'e' gia'. Prima era un alert rosso con dentro un <h5> del
   codice errore: il codice tecnico era la cosa piu' grande a video e il rosso diceva "qualcosa e'
   andato storto", mentre avere gia' un appuntamento e' del tutto normale. */
.stato-pagina {
    padding: 1.5rem 1.1rem;
    border: 1px solid #e7e9ec;
    border-radius: 1.1rem;
    background-color: #fff;
    box-shadow: 0 6px 24px rgba(33, 37, 41, .06);
    text-align: center;
}

.stato-pagina .popup-corpo {
    margin-bottom: 0;
}

/* Il codice resta a video perche' serve a chi assiste l'utente al telefono, ma in fondo e in
   piccolo: non e' l'informazione, e' il riferimento. */
.page .stato-pagina-codice {
    margin-top: 0.75rem;
    color: #adb5bd;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75em;
}
