/*
 * Il tema del sito: quello dell'orologio, tradotto sul web.
 *
 * La palette viene da `shared/theme.js` dell'app Zepp, dove sono numeri per il canvas.
 * Qui servono stringhe CSS e ripeterli e' l'unico modo -- ma **in un posto solo**: il sito
 * e l'orologio devono leggersi come la stessa cosa, e due tabelle di colori divergono al
 * primo ritocco.
 *
 * Le squadre hanno TRE registri, e non e' un dettaglio da appiattire:
 *   --blue / --gold              set in corso, tinte piene      (CUR_A / CUR_B)
 *   --blue-past / --gold-past    set chiusi, smorzate           (PAST_A / PAST_B)
 *   --blue-panel / --gold-panel  i pannelli del tabellone       (BLUE / GOLD)
 * Sull'orologio un punteggio passato non pesa come quello in gioco, e un sito che usa la
 * tinta piena per tutto perde quella gerarchia.
 *
 * I separatori sull'orologio sono DERIVATI -- `blend(INK, BG, alpha)` -- proprio per non
 * essere valori fissi calcolati su un fondo che poi cambia. Qui sono pre-calcolati sulle
 * stesse alpha (0.16, 0.12, 0.08) contro il nero pieno.
 */
:root {
    --bg: #000000;
    --ink: #f3f2f2;

    --divider: #272727;   /* blend(INK, BG, 0.16) */
    --set-fill: #1d1d1d;  /* blend(INK, BG, 0.12) */
    --row-rule: #131313;  /* blend(INK, BG, 0.08) */

    --muted-500: #9b9797; /* etichette */
    --muted-600: #7d7979; /* testate */
    --muted-700: #605d5d; /* pie di pagina */
    --tb-small: #6f6b6b;  /* TB_SMALL: apice del tie-break dei set chiusi */

    --blue: #4a7dff;
    --gold: #e8a72c;
    --blue-past: #5f7fc9;
    --gold-past: #a9832f;
    --blue-panel: #1c4fd6;
    --gold-panel: #c07f16;

    --accent: #ec3013;
    --accent-200: #ffe0d9;

    /*
     * Il font di sistema, come sull'orologio -- che non ha risorse di carattere e disegna
     * col font di sistema. Nessun carattere scaricato: il sito deve stare in piedi su un
     * host lento e con partenze a freddo, e un webfont e' una dipendenza di rete per
     * qualcosa che il sistema operativo ha gia.
     */
    --font: system-ui, -apple-system, "Segoe UI Variable Display", "Segoe UI", Roboto, sans-serif;

    /*
     * I due valori di spaziatura del sistema Modernist, misurati sull'orologio:
     * 1.5px sulle etichette e 2-2.5px sui maiuscoletti. Qui in em, cosi seguono il corpo.
     */
    --track-label: 0.05em;
    --track-caps: 0.22em;
}

/*
 * Bootstrap 5.3 porta un tema scuro proprio; si accende con data-bs-theme sull'html e poi
 * gli si riscrivono sopra i colori nostri. E la strada corta e giusta: le pagine di
 * Identity sono venticinque, tutte scritte con le classi di Bootstrap, e ridipingerle a
 * mano vorrebbe dire riscriverle. Cosi bastano le variabili.
 */
[data-bs-theme="dark"] {
    --bs-body-bg: var(--bg);
    --bs-body-color: var(--ink);
    --bs-body-font-family: var(--font);
    --bs-emphasis-color: #ffffff;
    --bs-secondary-color: var(--muted-500);
    --bs-tertiary-color: var(--muted-700);
    --bs-border-color: var(--divider);
    --bs-border-color-translucent: var(--divider);

    --bs-primary: var(--accent);
    --bs-primary-rgb: 236, 48, 19;
    --bs-link-color: var(--ink);
    --bs-link-hover-color: var(--accent);
    --bs-link-color-rgb: 243, 242, 242;

    --bs-secondary-bg: var(--set-fill);
    --bs-tertiary-bg: var(--row-rule);

    --bs-heading-color: var(--ink);
}

html {
    color-scheme: dark;
}

body {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font);
    -webkit-font-smoothing: antialiased;
}

/* ── Tipografia ──────────────────────────────────────────────────────────────
 *
 * La firma visiva dell'app e' questa: **numerali enormi e serrati su fondo nero**, con
 * micro-etichette maiuscole spaziate attorno. Sull'orologio il punteggio e' 136px su un
 * canvas alto 450 -- occupa un terzo dello schermo. Qui i corpi grandi si stringono
 * (letter-spacing negativo) perche' a quelle dimensioni la spaziatura normale sfarina la
 * parola, e i numeri sono tabulari perche' un punteggio che cambia non deve ballare.
 */
h1, h2, h3, h4, .display-1, .display-2, .display-3, .display-4 {
    letter-spacing: -0.03em;
    font-weight: 650;
}

h1 {
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    margin-bottom: 1.25rem;
}

h1:focus {
    outline: none;
}

.font-monospace,
td.font-monospace,
.tabular {
    font-family: var(--font);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    letter-spacing: -0.01em;
}

/** L'occhiello: maiuscolo, spaziato, smorzato. Nomina una zona senza pesare come un titolo. */
.eyebrow {
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

/** La riga piena del sistema Modernist: 2px, non un filetto. */
.rule {
    border: 0;
    border-top: 2px solid var(--ink);
    opacity: 1;
    margin: 0 0 1.5rem 0;
}

/* ── Superfici ───────────────────────────────────────────────────────────────
 *
 * Il raggio e il bordo vengono dalla pagina impostazioni dell'app Zepp (`setting/index.js`),
 * dove il riquadro del nome del foglio e' 12px di raggio e 1px di divider: e' la stessa
 * scheda, sullo stesso fondo.
 */
.card,
.panel {
    background: transparent;
    border: 1px solid var(--divider);
    border-radius: 12px;
}

.card-body {
    padding: 1.25rem;
}

/** Il solco del sistema Modernist fra due pannelli accostati: 4px, non una linea. */
.groove {
    display: grid;
    gap: 4px;
}

/* ── Controlli ───────────────────────────────────────────────────────────────
 *
 * Pillole, come sull'orologio e nella pagina impostazioni. Il primario e' l'accento, e
 * l'accento **si usa con parsimonia**: e' rosso, e su un fondo nero ogni cosa rossa in
 * piu' toglie peso a quella che conta.
 */
.btn {
    border-radius: 999px;
    padding: 0.6rem 1.4rem;
    font-weight: 600;
    letter-spacing: var(--track-label);
}

.btn-primary {
    --bs-btn-bg: var(--accent);
    --bs-btn-border-color: var(--accent);
    --bs-btn-color: #ffffff;
    --bs-btn-hover-bg: #ff3d1c;
    --bs-btn-hover-border-color: #ff3d1c;
    --bs-btn-hover-color: #ffffff;
    --bs-btn-active-bg: #c9280f;
    --bs-btn-active-border-color: #c9280f;
}

.btn-outline-secondary {
    --bs-btn-color: var(--ink);
    --bs-btn-border-color: var(--divider);
    --bs-btn-hover-bg: var(--set-fill);
    --bs-btn-hover-border-color: var(--muted-700);
    --bs-btn-hover-color: var(--ink);
}

/* Il pulsante di un accesso esterno: il logo accanto al testo, centrati insieme. */
.btn-external {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.65rem;
}

.google-mark {
    width: 1.1rem;
    height: 1.1rem;
    flex: none;
}

.btn-lg {
    padding: 0.85rem 1.6rem;
    font-size: 1rem;
}

.form-control,
.form-select {
    background: var(--set-fill);
    border: 1px solid var(--divider);
    border-radius: 10px;
    color: var(--ink);
    padding: 0.7rem 0.9rem;
}

.form-control:focus,
.form-select:focus {
    background: var(--set-fill);
    border-color: var(--muted-700);
    box-shadow: none;
    color: var(--ink);
}

.form-control::placeholder {
    color: var(--muted-700);
}

.form-label,
legend {
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
    margin-bottom: 0.4rem;
}

/*
 * Le etichette flottanti di Bootstrap, vestite invece che nascoste.
 *
 * Nasconderle era un errore: le pagine dell'account di Identity le usano al posto di una
 * label sopra il campo, e senza di loro un modulo resta con delle caselle anonime. Qui
 * restano dove Bootstrap le mette -- dentro il campo, in alto -- coi colori nostri.
 *
 * Le pagine scritte da noi (accesso, registrazione) usano invece una label esplicita sopra
 * il campo: e' piu' leggibile, e con l'etichetta in maiuscoletto spaziato del sistema
 * Modernist dentro la casella non ci sarebbe stata.
 */
.form-floating > label {
    color: var(--muted-600);
    padding: 0.75rem 0.9rem;
    opacity: 1;
    text-transform: none;
    letter-spacing: 0;
    font-size: 1rem;
    font-weight: 400;
    margin: 0;
    border: 0;
}

.form-floating > .form-control {
    padding-top: 1.6rem;
    padding-bottom: 0.45rem;
    min-height: 3.6rem;
}

.form-floating > .form-control:focus ~ label,
.form-floating > .form-control:not(:placeholder-shown) ~ label,
.form-floating > .form-select ~ label {
    color: var(--muted-700);
    opacity: 1;
    transform: scale(0.78) translateY(-0.5rem) translateX(0.18rem);
}

/** Il fondo che Bootstrap dipinge dietro l'etichetta ridotta: il nostro, non quello del corpo. */
.form-floating > label::after {
    background: transparent !important;
}

.form-check-input {
    background-color: var(--set-fill);
    border-color: var(--divider);
}

.form-check-input:checked {
    background-color: var(--accent);
    border-color: var(--accent);
}

/* ── Tabelle ─────────────────────────────────────────────────────────────────
 *
 * Le testate sono occhielli, non celle in grassetto: e' cosi che l'app nomina le colonne
 * delle statistiche. I separatori di riga usano l'alpha piu bassa (0.08), quella che
 * sull'orologio divide le righe senza disegnare una griglia.
 */
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--ink);
    --bs-table-border-color: var(--row-rule);
    --bs-table-hover-bg: var(--row-rule);
    --bs-table-hover-color: var(--ink);
    margin-bottom: 0;
}

.table > thead th {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
    border-bottom: 2px solid var(--divider);
    padding-bottom: 0.6rem;
}

.table > tbody td,
.table > tbody th {
    padding-top: 0.85rem;
    padding-bottom: 0.85rem;
    border-color: var(--row-rule);
}

.table > tbody th {
    font-weight: 400;
    color: var(--muted-500);
}

/* ── Le squadre ──────────────────────────────────────────────────────────────
 * Tre registri, tre classi. Vedi il commento in testa al file.
 */
.team-blue { color: var(--blue); }
.team-gold { color: var(--gold); }
.team-blue-past { color: var(--blue-past); }
.team-gold-past { color: var(--gold-past); }

/* ── Barra superiore ─────────────────────────────────────────────────────────
 *
 * Al posto della barra laterale del modello. Una barra laterale ruba larghezza a una
 * tabella di punteggi -- che e' il contenuto -- per tenere in vista quattro voci; in alto
 * costa 56px e li restituisce tutti.
 */
.topbar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    height: 56px;
    padding: 0 1.5rem;
    border-bottom: 1px solid var(--divider);
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 10;
}

/*
 * Il nome col marchio davanti, l'icona dell'app sull'orologio (BrandMark, nel disegno per le
 * misure piccole). Prima c'era un punto rosso: il marchio lo sostituisce, e la barra resta
 * senza accento -- il rosso nelle pagine e' dei pulsanti.
 */
.topbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}

.topbar-brand .brand-mark {
    width: 1.6rem;
    height: 1.6rem;
    flex: none;
}

.topbar-nav {
    display: flex;
    gap: 1.25rem;
    margin-left: auto;
    align-items: center;

    /*
     * Le voci scorrono ma la barra di scorrimento non si vede.
     *
     * E' l'ultima risorsa, sugli schermi piu' stretti, e quando scorre lo dice una sfumatura
     * (vedi --topbar-fade in fondo al foglio). Sopra, le misure delle media query fanno stare
     * tutto (revisione, voce 24 -- a 430px lo scorrimento nascondeva «Esci» e la lingua
     * senza che si capisse). Le alternative restano peggio: mandare le
     * voci a capo raddoppia l'altezza della barra su ogni pagina, e un menu a tendina mette
     * due tocchi fra l'utente e lo storico. La barra di sistema, che su una riga alta 56px si
     * mangiava il testo, non si vede.
     */
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    /* Un filo di respiro a destra, cosi' l'ultima voce non tocca il bordo quando e' scorsa. */
    padding-right: 0.25rem;
}

.topbar-nav::-webkit-scrollbar {
    display: none;
}

.topbar-nav a,
.topbar-nav button {
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-label);
    color: var(--muted-500);
    text-decoration: none;
    background: none;
    border: 0;
    padding: 0;
    white-space: nowrap;
}

/*
 * «Esci» e' un pulsante dentro un form, e non un collegamento come le altre voci: il form era un
 * blocco con l'interlinea della pagina (24px), il pulsante si appoggiava alla linea di base di
 * quella riga e stava quasi un pixel sotto le altre voci, che la barra centra. In flex il form e'
 * alto quanto il pulsante, e la barra centra anche lui.
 */
.topbar-nav form {
    display: flex;
}

.topbar-nav a:hover,
.topbar-nav button:hover {
    color: var(--ink);
}

.topbar-nav a.active {
    color: var(--ink);
}

/*
 * Il selettore di lingua, ultima voce della barra.
 *
 * Staccato dalle voci da un filetto e un tono piu' basso: non e' un posto dove andare, e
 * non deve leggersi come la sesta sezione del sito. Niente accento: la barra non ne ha.
 */
.topbar-nav a.topbar-language {
    color: var(--muted-600);
    padding-left: 1.25rem;
    border-left: 1px solid var(--divider);
}

.topbar-nav a.topbar-language:hover {
    color: var(--ink);
}

.page-body {
    max-width: 68rem;
    margin: 0 auto;
    padding: 2.5rem 1.5rem 4rem;
}

/* ── L'ingresso ──────────────────────────────────────────────────────────────
 *
 * La schermata di accesso non ha cornice: niente barra, niente navigazione. Chi non e
 * entrato non ha nessun posto dove andare, e mostrargli delle voci di menu che lo
 * rimandano al login e' un giro a vuoto.
 */
.auth-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 2rem 1.5rem;
}

.auth-card {
    width: 100%;
    max-width: 23rem;
}

/*
 * Il marchio e il nome sulla stessa riga, sopra il titolo.
 *
 * Scelto fra tre varianti nella revisione del 13 settembre 2026. Fa il lavoro che faceva la
 * riga rossa corta di prima: la scheda di accesso sta sospesa in mezzo a molto nero, e un
 * segno in alto le da' un appoggio e un verso di lettura. In piu' dice subito di che app si
 * tratta, con l'icona che si vede sull'orologio -- e il rosso resta solo al pulsante.
 */
.auth-brand {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.35rem;
}

.auth-brand .brand-mark {
    width: 2.25rem;
    height: 2.25rem;
    flex: none;
}

.auth-mark {
    font-size: clamp(2.4rem, 8vw, 3.25rem);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1;
    margin: 0.75rem 0 0;
}

.auth-sub {
    color: var(--muted-500);
    font-size: 0.95rem;
    line-height: 1.5;
    margin: 1rem 0 2.25rem;
}

.auth-alt {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--divider);
    font-size: 0.9rem;
    color: var(--muted-500);
}

.auth-alt a {
    color: var(--ink);
    font-weight: 600;
}

.auth-minor {
    margin-top: 0.85rem;
    font-size: 0.82rem;
}

.auth-minor a {
    color: var(--muted-600);
    text-decoration: none;
}

.auth-minor a:hover {
    color: var(--ink);
}

/*
 * La lingua, in fondo alla scheda d'ingresso.
 *
 * Sotto tutto il resto e con piu' aria sopra: e' l'ultima cosa che serve a chi entra, e la
 * cerca solo chi non legge bene la prima.
 */
.auth-language {
    margin-top: 2.5rem;
}

/** La casella «ricordati di me»: il testo non e' un'etichetta di campo, quindi non maiuscolo. */
.auth-card .form-check-label {
    text-transform: none;
    letter-spacing: 0;
    color: var(--muted-500);
    font-size: 0.9rem;
    margin: 0;
}

.auth-card .form-check {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-bottom: 1.75rem;
}

.auth-card .form-check-input {
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    float: none;
    flex: none;
}

/*
 * Condizioni e informativa, in fondo a ogni scheda d'ingresso (voce 84). Prendono loro l'aria che
 * prima stava sopra la lingua, e la lingua le segue da vicino: sono le due cose che non servono per
 * entrare.
 */
.auth-legal {
    margin-top: 2.5rem;
}

.auth-legal + .auth-language {
    margin-top: 0.85rem;
}

/*
 * La pagina del primo accesso (voce 84): due caselle una sotto l'altra e «Continua». Le caselle
 * hanno testi di due righe, quindi la spunta si allinea alla prima riga e non al centro; la riga
 * d'aiuto e l'errore rientrano come il testo delle caselle (spunta 1.05rem + spazio 0.55rem).
 */
.welcome-title {
    margin-bottom: 2.25rem;
}

.welcome .form-check {
    align-items: flex-start;
    padding-left: 0;
    margin-bottom: 0;
}

.welcome .form-check + .form-check,
.welcome .validation-message + .form-check {
    margin-top: 1.25rem;
}

.welcome .form-check-input {
    margin-top: 0.2rem;
}

.welcome .form-check-label a {
    color: var(--ink);
    font-weight: 600;
}

.welcome .validation-message {
    margin: 0.5rem 0 0 1.6rem;
}

.welcome-help {
    margin: 0.35rem 0 0 1.6rem;
    color: var(--muted-600);
    font-size: 0.82rem;
    line-height: 1.45;
}

/* La nota sull'import dal foglio (SheetImport/): non appesa a una casella, quindi senza il
   rientro di welcome-help, ma la stessa voce smorzata -- non e' una scelta da fare qui. */
.welcome-note {
    margin: 1.5rem 0 0;
    color: var(--muted-600);
    font-size: 0.82rem;
    line-height: 1.45;
}

.welcome-note strong {
    color: var(--muted-500);
}

.welcome .btn-lg {
    margin-top: 2rem;
}

/* ── Resti del modello ───────────────────────────────────────────────────────*/

.validation-message,
.text-danger,
.status-message-error,
.field-message-error {
    color: #ff6b52 !important;
}

.validation-message,
.text-danger {
    font-size: 0.85rem;
}

/*
 * I messaggi sono righe di testo, mai riquadri.
 *
 * Fino alla revisione del 13 settembre 2026 erano gli alert di Bootstrap, con lo sfondo e il
 * bordo dei campi: «Conferma la nuova email...» sopra il campo email sembrava un campo da
 * modificare. Un errore e' nel rosso della convalida, cosi' uno in cima alla pagina e uno sotto
 * un campo si leggono uguali.
 */
.status-message {
    margin: 0 0 1rem;
    font-size: 0.92rem;
    color: var(--ink);
}

/* Sotto il titolo di una pagina dell'account, attaccato al titolo e non al form. */
.manage-body h1 + .status-message {
    margin-top: -0.35rem;
}

/*
 * Sotto il titolo grande delle pagine d'ingresso, che non ha margine sotto: senza, la riga
 * toccava il titolo. Stessa distanza del sottotitolo (.auth-sub).
 */
.auth-mark + .status-message {
    margin-top: 1rem;
}

/* Il messaggio che riguarda un campo, scritto sotto di lui: il cambio di email nel profilo. */
.field-message {
    margin-top: 0.4rem;
    font-size: 0.85rem;
    color: var(--ink);
}

.pagination {
    --bs-pagination-bg: transparent;
    --bs-pagination-color: var(--muted-500);
    --bs-pagination-border-color: var(--divider);
    --bs-pagination-hover-bg: var(--set-fill);
    --bs-pagination-hover-color: var(--ink);
    --bs-pagination-active-bg: var(--ink);
    --bs-pagination-active-border-color: var(--ink);
    --bs-pagination-active-color: var(--bg);
}

#blazor-error-ui {
    background: var(--accent);
    color: #fff;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

#blazor-error-ui .reload {
    color: #fff;
    text-decoration: underline;
}

/* ── Il tabellone di una partita ─────────────────────────────────────────────
 *
 * Una riga per squadra, una colonna per set: la forma del tabellone dell'orologio.
 *
 * Le colonne dei set sono a larghezza fissa e i due numeri di uno stesso set cadono
 * incolonnati, perche' e' cosi' che si legge un punteggio -- 6 sopra 4, non "6-4" in mezzo
 * a una frase. Il numero di colonne arriva dal componente come `--sets`, cosi' una partita
 * a tre set e una a uno non si disegnano con la stessa griglia mezza vuota.
 *
 * Il solco fra le schede e' 4px, il `PANEL_GAP` del sistema Modernist: le partite sono
 * accostate, non separate da spazio bianco.
 */
/* minmax(0, 1fr) e non la colonna automatica: il luogo e la data, che non vanno a capo dentro di
 * se' (voci 38 e 39), allargherebbero la colonna fino alla loro riga intera, e a 375px la pagina
 * scorrerebbe di lato. */
.match-list {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 4px;
    margin-top: 1.75rem;
}

.match {
    display: block;
    padding: 1rem 1.15rem 1.1rem;
    border: 1px solid var(--divider);
    border-radius: 12px;
    text-decoration: none;
    color: var(--ink);
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

/* Senza href (l'anteprima dell'import) la scheda non si preme, e non deve sembrarlo. */
.match[href]:hover {
    background: var(--row-rule);
    border-color: var(--muted-700);
}

/*
 * La testa della scheda: data e luogo (voce 39). Il luogo sta accanto alla data se ci sta, e se
 * non ci sta va tutto intero alla riga sotto, dove si tronca coi puntini. Durata e modalita' non
 * ci sono piu': si leggono nella pagina della partita.
 *
 * E' un flex che va a capo, e il luogo ha la sua larghezza intera come base: se non entra accanto
 * alla data e' lui a scendere, non a troncarsi. Il puntino separatore e' il ::before del luogo,
 * nello spazio fra i due, e sparisce quando il luogo apre la riga: la riga interna e' spostata a
 * sinistra di quello spazio (margin-left negativo) e la testa taglia cio' che esce, quindi il
 * puntino di un luogo a inizio riga cade fuori e non si vede. Senza, la seconda riga
 * comincerebbe con «· Padel Ostia».
 */
.match-head {
    overflow: hidden;
    line-height: 1.2rem;
    margin-bottom: 0.7rem;
    color: var(--muted-700);
}

.match-head-line {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    margin-left: -1.5rem;
}

.match-when,
.match-place {
    margin-left: 1.5rem;
}

.match-when {
    flex: none;
    white-space: nowrap;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-500);
}

/*
 * Il troncamento sta nel testo interno e non qui: overflow nascosto su questo elemento taglierebbe
 * anche il suo puntino, che sta fuori dal bordo. min-width: 0 lo lascia stringere sotto la sua
 * larghezza intera quando e' da solo sulla riga.
 */
.match-place {
    position: relative;
    flex: 0 1 auto;
    min-width: 0;
    font-size: 0.78rem;
}

.match-place::before {
    content: "·" / "";
    position: absolute;
    left: -0.95rem;
}

.match-place-text {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.match-board {
    display: grid;
    grid-template-columns: minmax(0, 1fr) repeat(var(--sets, 3), 1.6rem);
    gap: 0.2rem 0.5rem;
    align-items: baseline;
}

/*
 * I nomi sono la voce che puo' eccedere, e vanno troncati invece di mandare a capo: due
 * righe di nome scardinerebbero l'incolonnamento dei set, che e' la ragione della griglia.
 */
.match-name {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    min-width: 0;
}

/*
 * Il nome del proprietario dell'account, fra i quattro della partita: una pillola grigia
 * (revisione del 13 settembre 2026). Il testo resta nel colore del team -- la pillola dice
 * «sei tu», il colore continua a dire in che squadra. Inline e non inline-block, perche' dentro
 * un nome troncato con i puntini un blocco verrebbe tagliato di netto invece che puntinato.
 */
.match-player-me {
    background: var(--divider);
    border-radius: 0.45em;
    padding: 0.08em 0.4em;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}

.match-name-sep {
    white-space: pre;
}

/*
 * Le note della partita in fondo alla scheda (voce 43): corpo piccolo e smorzato come il luogo, e
 * al massimo due righe coi puntini, cosi' una nota lunga non allunga la scheda. Gli a capo scritti
 * nella nota restano; una parola senza spazi va a capo dove serve invece di allargare la pagina.
 */
.match-notes {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    margin: 0.7rem 0 0;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--muted-500);
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* Si tronca il testo e non la riga: la coppa accanto al vincitore resta sempre visibile. */
.match-name-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * La coppa accanto a chi ha vinto (Trophy.razor), nel colore del nome: currentColor. Un
 * po' piu' piccola del corpo del nome, perche' non gridi piu' forte del nome stesso.
 */
.trophy {
    width: 0.95em;
    height: 0.95em;
    flex: none;
}

.match-set {
    font-size: 1.15rem;
    font-weight: 650;
    text-align: center;
    letter-spacing: -0.02em;
}

@media (max-width: 30rem) {
    .match-name {
        font-size: 0.98rem;
    }

    .match-board {
        grid-template-columns: minmax(0, 1fr) repeat(var(--sets, 3), 1.35rem);
    }
}

/* ── La pagina di una partita ────────────────────────────────────────────────
 *
 * In testa il tabellone con i nomi da scrivere, poi dove e note, poi le statistiche. Una
 * colonna sola e non due: la tabella dei numeri accanto alla scheda dei nomi separava due
 * cose che si leggono insieme -- chi ha giocato e come e' finita.
 */
.match-detail {
    max-width: 44rem;
}

/*
 * Lo stesso tabellone delle schede dello storico (.match-board), piu' grande: una riga per
 * squadra coi nomi «sinistro / destro», la coppa, i game dei set a destra. In sola lettura dal
 * 24 settembre 2026: fino ad allora i nomi erano due campi affiancati, e si scrivevano qui.
 */
.detail-board {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 1.25rem repeat(var(--sets, 3), 1.9rem);
    gap: 0.45rem 0.5rem;
    align-items: center;
    margin-top: 1.5rem;
}

.detail-col {
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-700);
}

.detail-col-set {
    text-align: center;
    letter-spacing: 0;
}

/*
 * Il nome si scrive nel colore della squadra, e il campo ne porta il filetto a sinistra: la
 * riga si riconosce anche vuota, quando il segnaposto dice solo «Team Blue».
 */
.detail-name {
    font-weight: 600;
    min-width: 0;
    padding: 0.55rem 0.7rem;
}

.detail-name-blue {
    border-left: 3px solid var(--blue-panel);
}

.detail-name-gold {
    border-left: 3px solid var(--gold-panel);
}

.form-control.detail-name.team-blue,
.form-control.detail-name.team-blue:focus { color: var(--blue); }
.form-control.detail-name.team-gold,
.form-control.detail-name.team-gold:focus { color: var(--gold); }

.detail-board .match-set {
    font-size: 1.3rem;
}

/* I nomi di una squadra, col filetto del campo che erano (.detail-name-blue/gold): una riga, troncata. */
.detail-team {
    min-width: 0;
    padding: 0.35rem 0 0.35rem 0.7rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 1.1rem;
    font-weight: 600;
}

/* Le note vanno a capo dove le ha mandate a capo chi le ha scritte. */
.detail-notes {
    white-space: pre-line;
    overflow-wrap: anywhere;
}

/* La colonna della coppa: vuota sulla riga di chi ha perso, e sempre larga uguale. */
.detail-trophy {
    display: flex;
    justify-content: center;
    font-size: 1.15rem;
}

.detail-fields {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: 1rem;
    margin-top: 1.5rem;
}

/*
 * Le note alte una riga, come «Dove» accanto (revisione del 13 settembre 2026): lo fa
 * rows="1", col padding comune ai due campi. Resta un'area di testo -- cinquecento caratteri,
 * si va a capo -- e la maniglia la allunga a mano, solo in verticale per non uscire dalla
 * colonna.
 */
.detail-fields textarea.form-control {
    resize: vertical;
}

/* Il trattino fra il valore del Blue e quello del Gold: grigio, staccato dai numeri. */
.pair-sep {
    color: var(--muted-600);
}

.detail-stats th {
    width: 11rem;
    font-weight: 500;
    color: var(--muted-500);
}

@media (max-width: 30rem) {
    .detail-board {
        grid-template-columns: minmax(0, 1fr) 1rem repeat(var(--sets, 3), 1.4rem);
        gap: 0.4rem 0.35rem;
    }

    .detail-team {
        font-size: 1rem;
    }

    .detail-name {
        font-size: 0.9rem;
        padding: 0.5rem 0.5rem;
    }

    .detail-board .match-set {
        font-size: 1.1rem;
    }

    .detail-fields {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Undici rem di etichetta su 327px mandavano a capo il nome del vincitore. */
    .detail-stats th {
        width: 8rem;
    }
}

/* ── La schermata della partita intera (MatchEdit.razor, 23 settembre 2026) ───
 *
 * Gli stessi pezzi della pagina della partita: i nomi con il filetto della squadra, le colonne
 * dei set numerate, dove e note. Al posto dei game scritti, un campo per game, nel colore della
 * squadra e col peso dei numeri del tabellone.
 */
.hand-score {
    max-width: 44rem;
}

.hand-hint {
    max-width: 38rem;
    margin-bottom: 0;
    color: var(--muted-500);
}

.hand-names {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0.45rem 0.5rem;
    margin-top: 1.5rem;
}

.hand-sets {
    display: grid;
    grid-template-columns: minmax(0, 1fr) repeat(var(--sets, 3), 3.4rem);
    gap: 0.45rem 0.5rem;
    align-items: center;
    margin-top: 1.5rem;
}

/* I nomi della squadra sulla sua riga: una riga sola, troncata, perché i campi restino allineati. */
.hand-team {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}

.hand-games {
    padding: 0.45rem 0.2rem;
    text-align: center;
    font-size: 1.15rem;
    font-weight: 650;
    -moz-appearance: textfield;
    appearance: textfield;
}

/* Le frecce del campo numerico non stanno in tre rem e mezzo, e i game si scrivono. */
.hand-games::-webkit-inner-spin-button,
.hand-games::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.form-control.hand-games.team-blue,
.form-control.hand-games.team-blue:focus { color: var(--blue); }
.form-control.hand-games.team-gold,
.form-control.hand-games.team-gold:focus { color: var(--gold); }

/*
 * Allineati in basso (24 settembre 2026): un'etichetta che va a capo sale, e i tre campi restano sulla
 * stessa linea. Prima «Durata (minuti)», nella colonna piu' stretta, andava a capo e ne abbassava il campo.
 */
.hand-when {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: end;
    gap: 1rem;
    margin-top: 1.5rem;
}

.hand-score .validation-message {
    margin-top: 0.4rem;
}

.hand-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 1.5rem;
}

@media (max-width: 30rem) {
    /* 2.7rem: con cinque colonne a 2.9 «Team Blue» si troncava su 343px. */
    .hand-sets {
        grid-template-columns: minmax(0, 1fr) repeat(var(--sets, 3), 2.7rem);
        gap: 0.4rem 0.35rem;
    }

    /* Data e ora affiancate, la durata sotto: tre campi in 343px schiacciavano la data. */
    .hand-when {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

/* ── Il sommario in testa allo storico ───────────────────────────────────────
 *
 * Tre numeri grandi, com'e' grande il punteggio sull'orologio: e' la firma visiva
 * dell'app, e questi sono i numeri che si vogliono sapere entrando. L'etichetta sta sotto,
 * piccola e maiuscola -- lo stesso rapporto fra valore ed etichetta della schermata delle
 * statistiche al polso.
 */
.summary {
    display: flex;
    flex-wrap: wrap;
    gap: 2.25rem;
    margin-top: 1.5rem;
    padding-bottom: 1.5rem;
    border-bottom: 2px solid var(--divider);
}

/*
 * La Dashboard dell'Admin ha etichette piu' lunghe dello storico («users/passes»), e a 375px
 * col font di sistema del telefono, piu' largo del Segoe UI, l'inglese andava a capo (voce 67).
 * Si stringe solo lo spazio fra i numeri, e solo qui: lo storico resta com'e'.
 */
.summary-admin {
    gap: clamp(1.25rem, 5vw, 2.25rem);
}

.summary-num {
    display: block;
    font-size: clamp(2.25rem, 6vw, 3rem);
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1;
}

/** Il segno di percentuale non e' un numero: piu' piccolo e smorzato, non ruba la cifra. */
.summary-pct {
    font-size: 0.45em;
    font-weight: 600;
    color: var(--muted-600);
    margin-left: 0.1em;
    letter-spacing: 0;
}

/*
 * La barra di «utenti/pass» nella Dashboard: smorzata, e un filo di spazio ai lati, cosi' i due
 * numeri restano due cifre e non una frazione.
 */
.summary-sep {
    font-weight: 400;
    color: var(--muted-700);
    margin: 0 0.08em;
}

.summary-lab {
    display: block;
    margin-top: 0.45rem;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

/* L'invito a impostare il nome giocatore, al posto di «vinte» e «resa»: a filo coi numeri. */
.summary-hint {
    align-self: flex-end;
    max-width: 20rem;
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--muted-500);
}

.summary-hint a {
    color: var(--ink);
    font-weight: 600;
}

.empty-state {
    margin-top: 1.5rem;
    color: var(--muted-500);
    line-height: 1.7;
}

.empty-state a {
    color: var(--ink);
    font-weight: 600;
}

/* ── Il filtro dello storico (voce 45) ───────────────────────────────────────
 *
 * Sotto il sommario e sopra le schede: il testo prende la riga, le date gli stanno accanto se
 * c'e' posto e vanno a capo insieme se non c'e'. Nessun colore: e' uno strumento, e l'accento
 * resta a cio' che va premuto. «Dal» e «Al» sono occhielli come le etichette del sommario.
 */
/*
 * Dalla voce 46 il form sta dietro «Filtra»: un occhiello come quelli del sommario, con una
 * freccia che si gira aprendo. Il triangolo del browser va via, perche' ognuno lo disegna a modo suo.
 */
.matches-filter-box {
    margin-top: 1.25rem;
}

.matches-filter-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    list-style: none;
    cursor: pointer;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-500);
}

.matches-filter-toggle::-webkit-details-marker {
    display: none;
}

.matches-filter-toggle::after {
    content: "";
    width: 0.4rem;
    height: 0.4rem;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translateY(-0.12rem) rotate(45deg);
    transition: transform 0.15s;
}

.matches-filter-box[open] > .matches-filter-toggle::after {
    transform: translateY(0.1rem) rotate(-135deg);
}

.matches-filter-toggle:hover,
.matches-filter-box[open] > .matches-filter-toggle {
    color: var(--ink);
}

.matches-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.75rem;
}

.matches-filter-text {
    flex: 1 1 14rem;
    min-width: 0;
}

.matches-filter-dates {
    display: flex;
    flex: 0 1 auto;
    gap: 0.6rem;
    min-width: 0;
}

.matches-filter-date {
    display: flex;
    flex: 1 1 0;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
    margin: 0;
}

.matches-filter-date span {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

/* Meno margine interno del solito: a 375px, con l'etichetta accanto, «01/09/2026» e l'icona del
 * calendario col margine di Bootstrap non ci stavano, e la data si troncava. */
.matches-filter-date .form-control {
    min-width: 0;
    padding-left: 0.55rem;
    padding-right: 0.45rem;
}

.matches-filter-actions {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.matches-filter-clear {
    font-size: 0.85rem;
    color: var(--muted-500);
}

.matches-filter-clear:hover {
    color: var(--ink);
}

/* «Mostra altre» sotto l'ultima scheda, al centro: e' la fine della lista finche' non lo si preme. */
.matches-more {
    display: flex;
    justify-content: center;
    margin-top: 1.25rem;
}

/*
 * Sul telefono le date non stanno accanto al testo: vanno sotto, e si dividono la riga. «Azzera»
 * resta accanto al testo invece di scendere dopo le date, dove prenderebbe una riga da sola.
 *
 * E l'etichetta va sopra il campo, come «Email» e «Password» nella schermata d'accesso: accanto,
 * in inglese «From» lasciava alla data 112px, e «01/09/2026» ne vuole circa 125 (misurato a 375px).
 */
@media (max-width: 36rem) {
    .matches-filter-dates {
        flex: 1 1 100%;
        order: 1;
    }

    .matches-filter-date {
        flex-direction: column;
        align-items: stretch;
        gap: 0.3rem;
    }
}

/*
 * La barra sugli schermi stretti: prima le voci si stringono, poi il nome dell'app lascia il
 * posto al suo marchio. Soglie diverse per lingua, e misurate, non stimate.
 *
 * Le voci si stringono -- margini, spazi fra le voci, stacco della lingua -- prima del corpo
 * del testo, che resta quello del desktop. Il nome se ne va solo dopo: il marchio resta, ed e'
 * il collegamento alla radice, ma le quattordici lettere di «Padel Companion» valgono meno di
 * una voce visibile senza trascinare. Il gap va a zero: il testo a corpo zero resta un
 * elemento del flex, e lo spazio fra i due rimarrebbe vuoto.
 *
 * Larghezza minima perche' le voci non scorrano, per chi e' entrato. Misurate la prima volta nella
 * revisione del 13 settembre 2026 (voci 24 e 25), **rifatte il 16 settembre 2026 (voce 66)**,
 * quando la sigla della lingua e' uscita dalla barra per chi e' entrato: in inglese, con lei, la
 * barra non stava a 375px e la sigla era proprio il pezzo che restava fuori. Misurate forzando le
 * tre disposizioni e sommando i pezzi, coi testi delle due lingue:
 *
 *                                      italiano   inglese
 *   nome e spazi normali                 507px     550px
 *   nome e spazi stretti                 451px     494px
 *   solo marchio e spazi stretti         314px     357px
 *
 * Chi non e' entrato ha «Accedi» e la sigla, piu' corti: le stesse soglie gli vanno larghe.
 *
 * Le soglie sono queste misure piu' una decina di pixel. Per lingua, e non una sola: le voci
 * inglesi sono 43px piu' lunghe, e con una soglia comune l'italiano perdeva il nome dove ci
 * stava. Si leggono da <html lang>; una lingua che non sia l'italiano prende quelle
 * inglesi, le piu' prudenti. **Se cambia il testo di una voce della barra nei .resx, queste
 * misure vanno rifatte.** Sotto l'ultima soglia la barra scorre, con la sfumatura qui sotto.
 *
 * Misurate su Windows, col Segoe UI di --font. Il font e' quello di sistema, e su iPhone e
 * Android le stesse parole possono essere qualche pixel piu' larghe: se il margine non basta
 * la barra scorre e la sfumatura lo dice, niente si taglia di nascosto.
 */
@media (max-width: 32.5rem) {
    .topbar:lang(it) {
        padding: 0 1rem;
        gap: 0.75rem;
    }

    .topbar-nav:lang(it) {
        gap: 0.75rem;
        padding-right: 0;
    }

    .topbar-nav a.topbar-language:lang(it) {
        padding-left: 0.75rem;
    }
}

@media (max-width: 35rem) {
    .topbar:not(:lang(it)) {
        padding: 0 1rem;
        gap: 0.75rem;
    }

    .topbar-nav:not(:lang(it)) {
        gap: 0.75rem;
        padding-right: 0;
    }

    .topbar-nav a.topbar-language:not(:lang(it)) {
        padding-left: 0.75rem;
    }
}

@media (max-width: 29rem) {
    .topbar-brand:lang(it) {
        font-size: 0;
        gap: 0;
    }
}

@media (max-width: 32rem) {
    .topbar-brand:not(:lang(it)) {
        font-size: 0;
        gap: 0;
    }
}

/*
 * Quando la barra scorre, una sfumatura sul bordo destro dice che c'e' altro.
 *
 * Solo quando scorre davvero, e non sotto una larghezza fissa: le voci inglesi sono piu'
 * lunghe di quasi 40px, e una soglia giusta per una lingua sbaglia l'altra. Lo fa una
 * animazione legata allo scorrimento della barra stessa: se la barra non scorre la sua
 * timeline e' inattiva e l'animazione non si applica, --topbar-fade resta 0 e la maschera
 * non vela niente. A fine corsa la sfumatura si chiude, e l'ultima voce si legge piena.
 * Dove animation-timeline non c'e' (Firefox, oggi) resta lo scorrimento senza sfumatura,
 * cioe' com'era prima.
 */
@property --topbar-fade {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@keyframes topbar-fade {
    from, 90% { --topbar-fade: 1.5rem; }
    to { --topbar-fade: 0px; }
}

@supports (animation-timeline: scroll()) {
    .topbar-nav {
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--topbar-fade)), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - var(--topbar-fade)), transparent);
        animation: topbar-fade linear both;
        animation-timeline: scroll(self inline);
    }
}

/* ── Il codice di accoppiamento ──────────────────────────────────────────────
 *
 * La cifra ha il peso che ha il punteggio sull'orologio: e' l'unica cosa che si deve fare
 * in questa schermata, e va letta da un metro di distanza mentre si tiene il telefono in
 * mano. I numeri sono tabulari e spaziati, perche' un codice si ribatte un carattere per
 * volta e l'occhio deve poter tenere il segno.
 */
.pairing {
    margin: 1.75rem 0;
    padding: 2rem 1.5rem;
    border: 1px solid var(--divider);
    border-radius: 12px;
    text-align: center;
}

.pairing-code {
    font-size: clamp(2.25rem, 9vw, 3.25rem);
    font-weight: 700;
    letter-spacing: 0.12em;
    line-height: 1.1;
    margin: 0.9rem 0 1.4rem;
}

.pairing-how {
    margin: 0 auto;
    max-width: 30rem;
    line-height: 1.6;
}

.pairing-note {
    margin: 0.85rem auto 0;
    max-width: 30rem;
    font-size: 0.88rem;
    color: var(--muted-600);
    line-height: 1.6;
}

/* ── La scheda di un orologio ────────────────────────────────────────────────
 *
 * Schede e non righe di tabella: i dati non sono omogenei -- un campo di testo, tre valori
 * e un'azione -- e in una cella di tabella il campo per rinominare veniva schiacciato a
 * larghezza zero dal flex.
 */
/*
 * `min-width: 0` perche' la scheda sta nella griglia di .match-list, dove un elemento non si
 * stringe sotto il suo contenuto: un nome lungo, che non va a capo, allargava la pagina a
 * 575px su un telefono da 375 invece di troncarsi.
 */
.device {
    min-width: 0;
    padding: 1.15rem 1.15rem 1.25rem;
    border: 1px solid var(--divider);
    border-radius: 12px;
}

.device-off {
    color: var(--muted-600);
}

/*
 * Campo, «Salva» e «Annulla» su una riga; se il campo resterebbe sotto i 12rem i pulsanti vanno
 * a capo. A 375px, con due pulsanti accanto, il campo si riduceva a 55px e non si leggeva il
 * nome che si stava correggendo.
 *
 * I pulsanti stanno in un gruppo che non va a capo al suo interno: quando erano due elementi
 * del flex, a certe larghezze «Salva» restava accanto al campo e «Annulla» scendeva da solo.
 */
.device-rename {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

/** `min-width: 0` e' quello che impedisce al flex di schiacciare il campo. */
.device-rename .form-control {
    flex: 1 1 12rem;
    min-width: 0;
    max-width: 20rem;
}

.device-rename-actions {
    display: flex;
    flex: none;
    gap: 0.5rem;
}

/*
 * Il nome a riposo, con accanto la matita.
 *
 * Il nome si tronca e quello che gli sta accanto no: la matita deve restare premibile anche
 * con un nome da sessanta caratteri a 375px. `min-width: 0` sul nome, come per il campo.
 * Alta quanto il campo (48px), cosi' premendo la matita la scheda non si allunga di colpo.
 */
.device-title {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
    min-height: 3rem;
}

.device-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 1.05rem;
    font-weight: 600;
}

/*
 * La matita nel grigio delle testate, e nel colore del testo al passaggio: e' un comando raro,
 * non deve pesare quanto il nome. Il bersaglio e' piu' grande del disegno, per il dito.
 */
.device-edit {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 8px;
    color: var(--muted-600);
}

.device-edit:hover,
.device-edit:focus-visible {
    color: var(--ink);
    background: var(--set-fill);
}

.pencil {
    width: 1.1rem;
    height: 1.1rem;
}

/*
 * L'occhio dei campi password (PasswordReveal), a destra dentro il campo.
 *
 * Grigio e piu' chiaro al passaggio, come la matita: e' un comando secondario, e il rosso resta
 * ai pulsanti principali. Due contenitori: .password-field quando l'etichetta sta sopra (accesso,
 * registrazione) e .form-floating nelle pagine dell'account, dove l'etichetta sta dentro il campo
 * e sotto c'e' la convalida -- per questo li' l'altezza e' quella del campo e non del contenitore.
 */
.password-field {
    position: relative;
}

.password-field > .form-control,
.form-floating:has(> .password-reveal) > .form-control {
    padding-right: 2.9rem;
}

.password-reveal {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.9rem;
    height: 100%;
    padding: 0;
    background: none;
    border: 0;
    color: var(--muted-600);
}

.form-floating > .password-reveal {
    height: 3.6rem;
}

.password-reveal:hover,
.password-reveal[aria-pressed="true"] {
    color: var(--ink);
}

.password-reveal:focus-visible {
    outline: 2px solid var(--muted-600);
    outline-offset: -6px;
    border-radius: 10px;
}

.eye {
    width: 1.2rem;
    height: 1.2rem;
}

/* Barrato mentre la password si vede: il clic la nasconde. */
.eye .eye-slash {
    display: none;
}

.password-reveal[aria-pressed="true"] .eye-slash {
    display: inline;
}

/*
 * Il titolo «Orologi» col pulsante di accoppiamento a destra, sulla stessa riga. Se non ci
 * stanno tutti e due, il pulsante va a capo sotto il titolo e resta intero: un pulsante
 * schiacciato su due righe accanto a un titolo grande si legge come un errore. Il titolo
 * perde il suo margine, che passa alla riga: centrati in verticale, un margine sotto il
 * solo titolo lo alzerebbe rispetto al pulsante.
 */
.devices-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 1.25rem;
}

.devices-head h1 {
    margin: 0;
}

.devices-head .btn {
    white-space: nowrap;
}

/*
 * «Scollegati», sopra le schede degli orologi scollegati: un occhiello e non un titolo pieno,
 * perche' nomina un gruppo di schede come «Dispositivi» nomina la pagina. Lo stacco sopra e'
 * quello fra due sezioni, piu' largo di quello fra due schede.
 */
.devices-section {
    margin: 2.5rem 0 0;
}

.devices-section + .match-list {
    margin-top: 0.75rem;
}

.device-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin: 1.15rem 0 0;
}

.device-meta dt {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

.device-meta dd {
    margin: 0.3rem 0 0;
    font-size: 0.95rem;
}

/*
 * L'azione distruttiva sta smorzata e diventa rossa solo al passaggio.
 *
 * Un «Scollega» rosso pieno accanto al pulsante di accoppiamento metteva due rossi sulla
 * stessa pagina a contendersi l'attenzione -- e l'app usa quell'accento per una cosa sola
 * alla volta. Il colore arriva quando la mano e' gia' li'.
 */
.btn-quiet-danger {
    margin-top: 1.15rem;
    padding: 0;
    background: none;
    border: 0;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: var(--track-label);
    color: var(--muted-600);
    text-decoration: underline;
    text-underline-offset: 0.25em;
}

.btn-quiet-danger:hover {
    color: var(--accent);
}

/*
 * La conferma dentro la pagina (ConfirmForm): la domanda al posto del pulsante, e sotto le
 * due scelte. «Si'» e' il primario rosso -- in quel momento e' l'unica azione della pagina --
 * e «Annulla» il secondario accanto, cosi' non si preme il rosso per abitudine.
 */
.confirm-question {
    margin: 0 0 0.65rem;
    font-size: 0.92rem;
    color: var(--ink);
}

.confirm-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Nella scheda dell'orologio il pulsante discreto ha il suo stacco: la domanda prende lo stesso. */
.device .confirm-inline {
    margin-top: 1.15rem;
}

/*
 * I comandi discreti in fondo alla scheda dell'orologio, «Importa dal foglio» e «Scollega», su una
 * riga: lo stacco ce l'ha la riga, e ai due pulsanti si toglie. Se non ci stanno, vanno a capo.
 */
.device-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.75rem 1.5rem;
    margin-top: 1.15rem;
}

.device-actions .btn-quiet-danger,
.device .device-actions .confirm-inline {
    margin-top: 0;
}

/* Come «Scollega», ma al passaggio prende l'inchiostro e non il rosso: non distrugge niente. */
.device-import {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: var(--track-label);
    color: var(--muted-600);
    text-decoration: underline;
    text-underline-offset: 0.25em;
}

.device-import:hover,
.device-import:focus-visible {
    color: var(--ink);
}

/* La riga sotto «Importa CSV»: piu' piccola e piu' smorzata, dice solo da dove viene il file. */
.device-import-note {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.75rem;
    color: var(--muted-700);
}

/* ── L'import dal foglio (SheetImport) ───────────────────────────────────────
 *
 * Legge anche il file di «Esporta partite» (voce 88). Il nome dell'orologio sotto il titolo,
 * smorzato, dice a chi andranno le partite. Il campo del file e «Anteprima» su una riga, e il campo
 * con `min-width: 0`, o il flex lo schiaccia a niente accanto al pulsante (come nella scheda
 * dell'orologio). I conti riprendono le etichette della scheda (.device-meta).
 */
.import-title {
    margin-bottom: 0.25rem;
}

.import-device {
    margin: 0 0 1rem;
    font-weight: 600;
    color: var(--muted-600);
}

.import-how {
    max-width: 38rem;
    color: var(--muted-500);
    line-height: 1.6;
}

.import-file-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

.import-file-row .form-control {
    flex: 1 1 14rem;
    min-width: 0;
    max-width: 26rem;
}

.import-file-row .btn {
    flex: none;
}

.import-file .validation-message {
    margin-top: 0.4rem;
}

.import-done {
    margin-top: 1.25rem;
}

.import-done a {
    color: var(--ink);
    font-weight: 600;
}

.import-counts {
    margin-top: 1.75rem;
}

.import-problems {
    margin: 1rem 0 0;
    padding-left: 1.1rem;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--muted-500);
}

.import-confirm .btn {
    margin-top: 1.5rem;
}

/* ── Le pagine dell'account ──────────────────────────────────────────────────
 *
 * Due colonne su schermo largo, una sopra l'altra su telefono. Le voci sono un elenco
 * verticale di collegamenti smorzati, non delle "pillole" di Bootstrap: quelle portano un
 * fondo pieno che su nero diventa un blocco grigio in mezzo alla pagina.
 */
.manage {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
    margin-top: 1.25rem;
}

@media (min-width: 52rem) {
    .manage {
        grid-template-columns: 13rem minmax(0, 1fr);
        gap: 3rem;
    }
}

.manage-nav .nav {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.manage-nav .nav-link {
    --bs-nav-link-color: var(--muted-500);
    --bs-nav-link-hover-color: var(--ink);
    --bs-nav-pills-link-active-bg: transparent;
    --bs-nav-pills-link-active-color: var(--ink);
    padding: 0.45rem 0;
    border-radius: 0;
    font-size: 0.92rem;
    font-weight: 600;
    text-align: left;
}

/** L'attivo si marca con un segno a sinistra, non con un fondo pieno. */
.manage-nav .nav-link.active {
    background: transparent;
    color: var(--ink);
    box-shadow: inset 2px 0 0 var(--accent);
    padding-left: 0.75rem;
}

.manage-body h1,
.manage-body h2,
.manage-body h3 {
    font-size: 1.35rem;
    margin-bottom: 1rem;
}

.manage-body hr {
    border-color: var(--divider);
    opacity: 1;
    margin: 1.25rem 0;
}

/* La data di registrazione in testa al profilo: senza lo stacco sopra, che qui c'e' gia' il titolo. */
.profile-meta {
    margin: 0 0 1.5rem;
}

/** I moduli dell'account non prendono tutta la larghezza: un campo lungo 60rem si legge male. */
.manage-form {
    max-width: 26rem;
}

.manage-form .btn {
    width: auto !important;
}

/*
 * Il consenso a battito e calorie, sotto il «Salva» del profilo: e' una scelta a se', non un
 * campo del modulo, quindi si stacca con un filetto come fa la voce dell'Admin nel menu. Il
 * titolo scende di un gradino perche' «Profilo» resta il titolo della pagina: due titoli della
 * stessa taglia direbbero che sono due pagine appaiate.
 */
.health-consent {
    margin-top: 2.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--divider);
}

.health-consent h2 {
    font-size: 1.05rem;
    margin-bottom: 0.35rem;
}

/*
 * La voce della pagina dell'Admin, staccata dalle tre dell'account da un filetto: non
 * riguarda il proprio account, e la vede uno solo.
 */
.manage-nav-admin {
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--divider);
}

/* ── La pagina dell'Admin ────────────────────────────────────────────────────
 *
 * Il sommario dello storico per i totali, poi la ricerca e la tabella degli utenti. Nessun
 * colore nuovo: e' una pagina di lavoro, e l'accento resta al pulsante che non c'e'.
 */
/*
 * La versione del sito accanto all'occhiello, «Ver. 1.0.1 Staging». Piu' smorzata della testata
 * (muted-700, il grigio del pie' di pagina) perche' e' un dato di servizio, non un titolo; e senza
 * il maiuscolo dell'occhiello, o «Ver.» diventerebbe «VER.» e il numero perderebbe la sua forma.
 * Il punto mediano sta qui e non nel markup: e' un segno, non un testo da tradurre.
 */
.admin-version {
    text-transform: none;
    letter-spacing: 0;
    color: var(--muted-700);
}

.admin-version::before {
    content: "·";
    margin: 0 0.4em;
}

.admin-search {
    display: flex;
    gap: 0.6rem;
    max-width: 32rem;
    margin: 1.5rem 0;
}

.admin-search .form-control {
    flex: 1 1 auto;
    min-width: 0;
}

/* Cinque colonne non stanno in un telefono: scorre la tabella, non la pagina. */
.admin-table {
    overflow-x: auto;
}

.admin-table td {
    white-space: nowrap;
}

/* Le intestazioni sono collegamenti che ordinano: restano occhielli, non testo sottolineato. */
.admin-table thead th a {
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}

.admin-table thead th a:hover,
.admin-table thead th[aria-sort] a {
    color: var(--ink);
}

.admin-num {
    text-align: right;
}

/*
 * L'email del titolo sta su una riga rimpicciolendosi (voce 69). Il CSS non sa misurare il testo,
 * quindi la larghezza si stima: --chars caratteri da 0,6em ciascuno, un po' piu' della media di un
 * indirizzo, cosi' la stima sbaglia verso il piccolo e non verso l'a capo. Il massimo e' il corpo di
 * .h3 di Bootstrap, il minimo 0,95rem: sotto si va a capo sui <wbr>, e solo in ultimo a meta'
 * parola, perche' la pagina di un telefono non si allarghi.
 */
.admin-user-head {
    container-type: inline-size;
}

.admin-user-email {
    font-size: clamp(0.95rem, calc(100cqi / (var(--chars, 20) * 0.6)), min(calc(1.3rem + 0.6vw), 1.75rem));
    overflow-wrap: anywhere;
}

/* La licenza dell'utente, staccata dai suoi dati come il sommario dallo storico. */
.admin-user-license {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 2px solid var(--divider);
}

.admin-user-license p {
    margin-bottom: 0.75rem;
}

.admin-user-note {
    font-size: 0.85rem;
    color: var(--muted-600);
}

/*
 * La cancellazione dell'account (voce 83): stessa spaziatura della licenza, un riquadro in piu'
 * separato da lei. Il campo resta stretto (max-width): una riga larga quanto la pagina non serve
 * a una frase di poche parole.
 */
.admin-user-danger {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 2px solid var(--divider);
}

.admin-user-danger .form-control {
    max-width: 22rem;
}

/* ── La licenza del sito ─────────────────────────────────────────────────────
 *
 * Vedi LICENZA.md. Nessuna tinta nuova, e niente accento nella striscia: il rosso resta ai
 * pulsanti, e l'acquisto con Paddle ne avra' uno.
 */

/*
 * La striscia della prova, sotto la barra in alto (TrialNotice): una riga smorzata col
 * collegamento pieno, come l'invito a impostare il nome giocatore nello storico. Si legge
 * senza gridare su ogni pagina, per tre settimane. Su un telefono il collegamento va a capo.
 */
.trial-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.75rem;
    padding: 0.55rem 1.5rem;
    border-bottom: 1px solid var(--divider);
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--muted-500);
}

.trial-notice a {
    color: var(--ink);
    font-weight: 600;
}

@media (max-width: 30rem) {
    .trial-notice {
        padding: 0.55rem 1rem;
    }
}

/* La prova detta sotto il sottotitolo della registrazione, piu' chiara di lui. */
.auth-trial {
    color: var(--ink);
    font-weight: 600;
}

.license-lead {
    margin: 0.5rem 0 0;
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--muted-500);
}

.license-offer {
    max-width: 34rem;
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 2px solid var(--divider);
}

/* Titoletti della pagina: occhielli, come le etichette delle statistiche al polso. */
.license-includes-title {
    margin: 0 0 0.75rem;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

.license-includes {
    margin: 0;
    padding: 0;
    list-style: none;
}

.license-includes li {
    padding: 0.6rem 0;
    border-bottom: 1px solid var(--row-rule);
}

.license-once {
    margin: 1.25rem 0 0.35rem;
    font-weight: 600;
}

.license-unavailable {
    margin: 0;
    font-size: 0.85rem;
    color: var(--muted-600);
}

/*
 * L'acquisto (fase 2, Paddle). Il prezzo lo scrive Paddle.js, e finche' non arriva resta nascosto:
 * grande come i numeri del sommario dello storico, perche' e' la cosa che si guarda. Il pulsante e'
 * l'accento della pagina, l'unico: la regola dell'accento rosso usato per una cosa sola.
 */
.license-price {
    margin: 1.5rem 0 0;
    font-size: 2.4rem;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.license-price + .license-once {
    margin-top: 0.6rem;
}

.license-buy-button {
    margin-top: 1rem;
}

/* A 375px il pulsante prende la riga intera, come i pulsanti delle schermate d'ingresso. */
@media (max-width: 30rem) {
    .license-buy-button {
        width: 100%;
    }
}

.license-checkout-error {
    margin: 0.75rem 0 0;
    font-size: 0.85rem;
    color: #ff6b52;
}

.license-refund {
    margin: 0.75rem 0 0;
    font-size: 0.85rem;
    color: var(--muted-600);
}

/*
 * La presentazione sulla radice per chi non e' entrato (26 settembre 2026, chiesta da Paddle per
 * approvare il dominio): la scheda dell'accesso con le righe di /license. Il prezzo e' una frase e non
 * un numero grande, perche' sono due valute; il pulsante e' l'unico accento, come nell'accesso.
 */
.home-pricing {
    margin: 1.75rem 0 0;
    line-height: 1.5;
}

.home-pricing + .license-once {
    margin-top: 0.35rem;
}

.home-start {
    margin-top: 1.5rem;
}

/* ── Il tabellone dal vivo (/live, 15 settembre 2026) ────────────────────────
 *
 * La schermata del punteggio dell'orologio, con le quote di shared/theme.js sul canvas da
 * 388x450: testata 60, filetto 3, striscia dei set 138, filetto 3, pannelli 246. Le misure sono
 * frazioni del tabellone e non pixel, in unita' del contenitore: --ux e' un 388esimo della
 * larghezza, --uy un 450esimo dell'altezza, e i testi usano la minore delle due, cosi' non
 * escono dal loro riquadro ne' in una colonna stretta ne' su una TV orizzontale.
 *
 * Il tabellone prende tutta la finestra, in larghezza e in altezza (voce 56): e' il contenuto
 * della pagina, e in una colonna da 28rem su un monitor ne restava vuoto tre quarti. Le
 * proporzioni dell'orologio si perdono di proposito -- come gia' succedeva a schermo intero -- e i
 * pannelli si allargano invece di lasciare due bande nere ai lati; i corpi dei testi seguono --u,
 * cioe' il lato corto, e non escono dai loro riquadri nemmeno su una TV orizzontale.
 *
 * L'altezza che avanza non si puo' scrivere a mano: sopra al tabellone ci sono la barra, la
 * striscia della prova quando c'e', e la riga del titolo, che a 375px puo' andare a capo. La
 * misura una catena flex dal body, accesa con :has() solo dove c'e' il tabellone, cosi' le altre
 * pagine non cambiano. E' 100dvh e non 100vh: sul telefono le barre del browser entrano ed escono,
 * e con vh il fondo del tabellone finirebbe sotto il bordo dello schermo.
 */
body:has(.live) {
    display: flex;
    flex-direction: column;
    height: 100dvh;
}

/* Da un bordo all'altro: qui la colonna del sito e i suoi margini toglierebbero spazio al gioco. */
body:has(.live) .page-body {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
    max-width: none;
    /* Il margin: 0 auto che centra la colonna va tolto: in una colonna flex un margine automatico
       ferma l'allargamento, e il tabellone restava largo quanto il suo contenuto. */
    margin: 0;
    padding: 0;
}

.live {
    position: relative;
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

/*
 * Il ritorno e la riga del titolo tengono i margini laterali delle altre pagine, perche' sono
 * testo del sito e non tabellone; sopra pero' meno dei 2.5rem di .page-body: ogni riga in piu' la
 * perde il punteggio.
 */
.live-back,
.live-bar {
    padding-right: 1.5rem;
    padding-left: 1.5rem;
}

.live-back {
    padding-top: 1.25rem;
}

.live-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.75rem;
}

.live-bar .eyebrow {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * La pillola: «Schermo intero» in /live e «Tabellone dal vivo» nello storico (voce 50, 16 settembre
 * 2026, quando il collegamento dello storico non si notava). Una classe sola, perché sono la stessa
 * cosa: maiuscolo spaziato, bordo sottile, fondo trasparente. Vale per un <button>, un <a> e uno
 * <span> spento, quindi azzera sottolineatura e allineamento dei tre.
 */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    flex: none;
    white-space: nowrap;
    padding: 0.35rem 0.9rem;
    border: 1px solid var(--divider);
    border-radius: 999px;
    background: transparent;
    color: var(--muted-500);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.5;
    text-transform: uppercase;
    text-decoration: none;
    letter-spacing: var(--track-caps);
}

.pill:hover {
    color: var(--ink);
    border-color: var(--muted-700);
}

/* Spenta: non cliccabile, e più scura della pillola a riposo perché non si confonda con lei. */
.pill[aria-disabled="true"],
.pill[aria-disabled="true"]:hover {
    color: var(--muted-700);
    border-color: var(--row-rule);
    cursor: default;
}

/* Sul telefono titolo e pulsante stanno su una riga solo con la spaziatura delle etichette. */
@media (max-width: 30rem) {
    .live-bar .eyebrow,
    .pill {
        letter-spacing: var(--track-label);
    }
}

/*
 * La parte che lo script sostituisce e il tabellone dentro prendono l'altezza che avanza. Prima
 * il tabellone aveva aspect-ratio: 388 / 450, le proporzioni dell'orologio, e queste tre regole
 * valevano solo a schermo intero (.live:fullscreen): ora valgono sempre, e a schermo intero non
 * resta niente di diverso se non la testata che sparisce.
 */
.live-part {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}

.live-board {
    container: live-board / size;
    flex: 1;
    width: 100%;
    min-height: 0;
}

/*
 * Senza una partita in corso la frase sta in mezzo allo spazio del tabellone: la pagina e' alta
 * quanto la finestra, e lasciarla in alto a sinistra sembrava un pezzo che non ha finito di
 * caricare.
 */
.live-part > .empty-state {
    margin: auto;
    padding: 0 1.5rem;
    text-align: center;
}

.live-screen {
    --ux: calc(100cqw / 388);
    --uy: calc(100cqh / 450);
    --u: min(var(--ux), var(--uy));
    /*
     * Il corpo dei set e della pallina (voce 73): il lato corto da solo li faceva minuscoli su un
     * tabellone basso e largo, come un telefono coricato, dove l'altezza e' meta' della larghezza.
     * Qui la larghezza conta per intero e l'altezza un po' di piu' del solito, e vince la piu'
     * stretta: sul telefono in piedi resta --ux, coricato cresce di quasi due volte.
     */
    --uz: min(var(--ux), calc(1.75 * var(--uy)));

    display: grid;
    grid-template-rows: 63fr 387fr;
    height: 100%;
    background: var(--bg);
    line-height: 1;
}

/*
 * Il filetto come bordo e non come fondo che traspare da un intervallo: con un fondo grigio sotto,
 * a larghezze frazionarie ne restava un filo ai lati della testata (visto a 375px).
 */
.live-header {
    border-bottom: calc(3 * var(--uy)) solid var(--divider);
}

/*
 * Ora a sinistra, cronometro a destra, **centrati in altezza nella loro riga** (voce 73, 16
 * settembre 2026): prima stavano sul fondo, sulla linea di base come in buildScore() nell'app, e sul
 * sito sembravano scivolati in basso.
 */
.live-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 calc(44 * var(--ux));
    background: var(--bg);
    font-size: calc(36 * var(--u));
}

.live-clock {
    color: var(--ink);
}

.live-elapsed {
    color: var(--muted-600);
}

/*
 * I due pannelli fino in fondo, e in mezzo la colonna dei set (voce 73): prima i set stavano in una
 * striscia sopra i pannelli, che toglieva loro un terzo dell'altezza. Fra le tre colonne il solco da 4
 * del sistema Modernist, come fra i due pannelli di prima.
 */
.live-panels {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    /*
     * Una riga sola, alta quanto lo spazio e non quanto il contenuto: con cinque set la colonna era
     * piu' alta del tabellone, la riga si allungava oltre il bordo e i numeri dei pannelli scendevano.
     */
    grid-template-rows: minmax(0, 1fr);
    /* Sul lato corto: su una TV coricata --ux faceva due fasce grigie larghe quanto un dito. */
    column-gap: calc(4 * var(--u));
    min-height: 0;
    background: var(--divider);
}

/*
 * I set uno sotto l'altro, «Blue – Gold», al centro della colonna. Il corpo segue --uz (vedi
 * .live-screen): la colonna resta stretta, e la larghezza che avanza va ai pannelli. Niente minuti
 * dei set (voce 73).
 */
.live-sets {
    display: flex;
    flex-direction: column;
    gap: calc(6 * var(--uz));
    min-height: 0;
    padding: 0 calc(8 * var(--uz));
    background: var(--bg);
    overflow: hidden;
    /*
     * **Quando i set non ci stanno, resta il set in corso** (chiesto dall'utente il 16 settembre
     * 2026, dopo un quinto set che non si vedeva): la fila si allinea in fondo, e a traboccare, cioe'
     * a uscire dall'alto, sono i primi. Quando ci stanno, i due margini automatici qui sotto si
     * dividono lo spazio e la fila resta al centro; quando non ci stanno valgono zero, e l'allineamento
     * in fondo decide. Niente sfumatura sul set tagliato: provata e tolta su richiesta dell'utente,
     * basta che si veda il set in corso.
     */
    justify-content: flex-end;
}

.live-set:first-child {
    margin-top: auto;
}

.live-set:last-child {
    margin-bottom: auto;
}

.live-set {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: calc(5 * var(--uz));
    padding: calc(5 * var(--uz)) calc(8 * var(--uz));
}

/* Il set in corso: sul fondo del set, in tinte piene. */
.live-set-current {
    background: var(--set-fill);
}

.live-games {
    font-size: calc(40 * var(--uz));
    font-weight: 600;
    letter-spacing: -0.03em;
    white-space: nowrap;
}

/* Il numero di Blue verso il trattino, quello di Gold dall'altra parte: i trattini restano in fila. */
.live-set .live-games:first-child {
    text-align: right;
}

.live-set-dash {
    font-size: calc(40 * var(--uz));
    color: var(--muted-700);
}

.live-games sup {
    top: -0.6em;
    margin-left: 0.08em;
    font-size: 0.4em;
    font-weight: 600;
    color: var(--tb-small);
}

/*
 * **Le cifre al centro della cella** (16 settembre 2026, notato dall'utente sul set in corso): con
 * l'interlinea a 1 la riga tiene lo spazio degli accenti sopra e delle discendenti sotto, che le cifre
 * non usano, e in Segoe UI il primo e' molto piu' grande del secondo: le cifre stavano 15 px sotto il
 * centro su un monitor da 1912. Uno spostamento fisso non va, perche' cambia con il carattere di
 * sistema (Segoe, Roboto, San Francisco); `text-box` taglia la riga all'altezza delle maiuscole e alla
 * linea di base, cioe' alle cifre, qualunque sia il carattere. L'imbottitura cresce di quanto si
 * taglia (circa un quarto del corpo, cinque unita' e mezza su quaranta) e la cella resta alta uguale. Dove
 * `text-box` non c'e' (Firefox) resta com'era. In piedi decide la regola del contenitore, piu' sotto.
 */
@supports (text-box: trim-both cap alphabetic) {
    .live-games,
    .live-set-dash {
        text-box: trim-both cap alphabetic;
    }

    .live-set {
        padding-block: calc(10.5 * var(--uz));
    }
}

/*
 * Ogni pannello e' un contenitore, e il numero si misura su di lui: da quando i set stanno in mezzo
 * la larghezza del pannello non e' piu' una frazione fissa del tabellone.
 */
.live-panel {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    overflow: hidden;
    container-type: size;
}

.live-panel-blue {
    background: var(--blue-panel);
    color: var(--blue-panel);
}

.live-panel-gold {
    background: var(--gold-panel);
    color: var(--gold-panel);
}

/*
 * Il bianco al 75% di SCORE_ALPHA: sull'orologio e' pre-fuso sul pannello, qui trasparente.
 *
 * Il corpo ha **due limiti, uno per lato del pannello, e vince il piu' stretto** (voce 58):
 *   - **in larghezza** il 62% del pannello, la proporzione dell'orologio (136 su 192) ridotta
 *     perche' il font di sistema di un PC e' piu' largo di quello del polso: di piu', «AD», il
 *     punteggio piu' largo che esista, tocca i bordi. Non si alza;
 *   - **in altezza** il 75% del pannello. Il glifo ne occupa circa i tre quarti, quindi resta
 *     staccato dal filetto sopra e non arriva sulla pallina di chi serve, in basso.
 * Prima della voce 73 erano 120 * --ux e 200 * --uy, cioe' le stesse proporzioni su un pannello largo
 * mezzo tabellone e alto 246 su 450.
 */
.live-points {
    font-size: min(62cqw, 75cqh);
    font-weight: 700;
    letter-spacing: -0.05em;
    color: rgba(255, 255, 255, 0.75);
}

/*
 * **Il tabellone in piedi tiene la disposizione di prima** (voce 73, scelto dall'utente il 16
 * settembre 2026): la striscia dei set sopra i due pannelli, ogni set una colonna con Blue sopra e
 * Gold sotto. In piedi comanda la larghezza, e la colonna in mezzo la toglieva ai pannelli: il numero
 * del game calava da 98 a 83 px su un telefono da 375. I minuti dei set non tornano.
 *
 * Lo decide la forma del tabellone (una query sul contenitore .live-board), non la finestra: conta
 * lo spazio che il tabellone ha davvero, dopo barra e titolo, anche a schermo intero. Il markup e'
 * uno solo; qui cambiano solo le aree della griglia, e il trattino si nasconde.
 */
@container live-board (aspect-ratio < 1) {
    .live-panels {
        grid-template-columns: 1fr 1fr;
        grid-template-rows: minmax(0, 127fr) minmax(0, 260fr);
        grid-template-areas:
            "sets sets"
            "blue gold";
        column-gap: calc(4 * var(--ux));
    }

    .live-panel-blue { grid-area: blue; }
    .live-panel-gold { grid-area: gold; }

    /* Le colonne dei set seguono il corpo dei numeri (--u): si allargano i pannelli, non i set. */
    /*
     * Anche qui resta il set in corso: la fila si allinea a destra e trabocca a sinistra, e il
     * margine automatico dell'ultimo la tiene a sinistra finche' ci sta.
     */
    .live-sets {
        grid-area: sets;
        flex-direction: row;
        justify-content: flex-end;
        gap: calc(3 * var(--u));
        padding: 0 0 0 calc(13 * var(--u));
        border-bottom: calc(3 * var(--uy)) solid var(--divider);
    }

    .live-set:first-child {
        margin-top: 0;
    }

    .live-set:last-child {
        margin-bottom: 0;
        margin-right: auto;
    }

    .live-set {
        display: grid;
        flex: none;
        grid-template-columns: none;
        grid-template-rows: calc(56 * var(--uy)) calc(56 * var(--uy));
        row-gap: calc(2 * var(--uy));
        align-content: start;
        width: calc(57 * var(--u));
        padding: calc(4 * var(--uy)) 0 0;
    }

    /* Il set in corso: piu' largo, sul fondo della cella. */
    .live-set-current {
        width: calc(65 * var(--u));
    }

    .live-set-dash {
        display: none;
    }

    .live-games {
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: calc(52 * var(--u));
    }

    .live-set .live-games:first-child {
        text-align: center;
    }

    .live-games sup {
        top: 0;
        align-self: flex-start;
        margin-top: calc(8 * var(--uy));
        margin-left: calc(2 * var(--u));
        font-size: calc(16 * var(--u));
    }
}

/* La pallina sul bordo interno del pannello, in basso: vicino al solco, come sull'orologio. */
.live-ball {
    position: absolute;
    bottom: calc(12 * var(--uy));
    width: calc(26 * var(--uz));
    height: calc(26 * var(--uz));
}

.live-panel-blue .live-ball {
    right: calc(12 * var(--ux));
}

.live-panel-gold .live-ball {
    left: calc(12 * var(--ux));
}

/*
 * A schermo intero: il tabellone prende tutto lo schermo, e la barra col pulsante sparisce (voce
 * 47: la riga «Esci dallo schermo intero» rubava troppo spazio). Si esce con un tocco sul
 * tabellone, dal telefono, o con Esc; lo gestisce live-board.js.
 */
.live:fullscreen {
    background: var(--bg);
}

.live::backdrop {
    background: var(--bg);
}

.live:fullscreen .live-bar,
.live:fullscreen .live-back {
    display: none;
}

/*
 * Dallo storico (voci 49, 50 e 52): la pillola sulla riga del titolo, a destra. Se titolo e
 * pillola non ci stanno insieme, la pillola va a capo sotto invece di schiacciare il titolo.
 * Il margine che il titolo aveva sotto passa alla riga.
 */
.matches-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 1.25rem;
}

.matches-head h1 {
    margin-bottom: 0;
}

/*
 * La riga di «Filtra» con «+ Partita manuale» a destra (24 settembre 2026). La pillola e' fuori dal
 * <details>, che resta largo quanto la riga: aprendolo il form usa tutta la larghezza. Sta sulla riga
 * del <summary>, centrata sulla sua altezza, e il form aperto comincia sotto di lei.
 */
.matches-tools {
    position: relative;
    margin-top: 1.25rem;
}

.matches-tools > .matches-filter-box {
    margin-top: 0;
    min-height: 1.9rem;
    display: block;
}

.matches-tools > .matches-filter-box > .matches-filter-toggle {
    min-height: 1.9rem;
}

.matches-manual {
    position: absolute;
    top: 0;
    right: 0;
}

/* Accesa: testo pieno e pallino rosso. */
.matches-live[href] {
    color: var(--ink);
    border-color: var(--muted-700);
}

/*
 * Il pallino della partita in corso: l'accento rosso, l'unico della pagina come vuole la regola del
 * sito. Lampeggia piano, voce 52: si accende e si spegne senza scatti, come la spia «in onda».
 * Fermo per chi nel sistema ha chiesto meno animazioni.
 */
.live-dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--accent);
    animation: live-dot 1.4s ease-in-out infinite;
}

@keyframes live-dot {
    50% { opacity: 0.2; }
}

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

/*
 * Senza collegamento col server (voce 71, 16 settembre 2026): il tabellone in grigio, perché il
 * punteggio può essere vecchio, e sopra l'indicatore di riconnessione. Il grigio non copre niente:
 * l'ultimo punteggio arrivato resta leggibile. L'indicatore sta in mezzo a tutto il tabellone,
 * anche a schermo intero, e non usa l'accento rosso, che nella pagina è di nessuno. Lo accende
 * live-board.js.
 */
.live-part {
    transition: filter 0.4s ease, opacity 0.4s ease;
}

.live-offline .live-part {
    filter: grayscale(1);
    opacity: 0.45;
}

.live-reconnecting {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1;
    transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    max-width: calc(100% - 2rem);
    padding: 0.6rem 1.25rem;
    border: 1px solid var(--muted-700);
    border-radius: 999px;
    background: var(--bg);
    color: var(--ink);
    font-size: clamp(0.8rem, 2.5vmin, 1.25rem);
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    white-space: nowrap;
}

.live-reconnecting[hidden] {
    display: none;
}

.live-spinner {
    flex: none;
    width: 1.1em;
    height: 1.1em;
    border: 2px solid var(--muted-700);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: live-spinner 0.9s linear infinite;
}

@keyframes live-spinner {
    to { transform: rotate(360deg); }
}

/* Chi ha chiesto meno animazioni vede un anello fermo: la parola dice già che si sta riprovando. */
@media (prefers-reduced-motion: reduce) {
    .live-spinner {
        animation: none;
    }
}

/*
 * La lingua nel Profilo (voce 66, 16 settembre 2026): le due lingue una accanto all'altra, quella
 * attiva piena e l'altra smorzata come i collegamenti minori dell'ingresso. Niente accento: il rosso
 * della pagina e' del «Salva».
 */
.language-choice {
    display: inline-flex;
    gap: 1rem;
}

.language-current {
    color: var(--ink);
    font-weight: 600;
}

.language-choice a {
    color: var(--muted-500);
    text-decoration: none;
}

.language-choice a:hover {
    color: var(--ink);
    text-decoration: underline;
}

/*
 * Il punto che cambia (voce 72, 16 settembre 2026): il pannello si accende due volte di fila, come
 * un battito, e il numero pulsa con lui. Scelto dall'utente fra sei proposte in un'anteprima. La
 * classe la mette live-board.js al solo pannello il cui punteggio è cambiato; il pannello è nuovo a
 * ogni aggiornamento, quindi l'animazione riparte da sé. Niente accento rosso, e niente per chi nel
 * sistema ha chiesto meno movimento: il numero nuovo si legge lo stesso.
 */
.live-panel.live-changed {
    animation: live-beat-panel 0.9s ease-out;
}

.live-points.live-changed {
    animation: live-beat-points 0.9s ease-out both;
}

@keyframes live-beat-panel {
    0%, 100% { filter: brightness(1); }
    15% { filter: brightness(1.45); }
    35% { filter: brightness(1.05); }
    50% { filter: brightness(1.3); }
}

@keyframes live-beat-points {
    0% { transform: scale(0.9); opacity: 0; }
    15% { transform: scale(1.22); opacity: 1; }
    35% { transform: scale(0.97); }
    50% { transform: scale(1.12); }
    100% { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .live-panel.live-changed,
    .live-points.live-changed {
        animation: none;
    }
}

/*
 * Il game vinto (voce 75, 16 settembre 2026): la cella del set si riempie della tinta piena di chi ha
 * vinto il game, coi numeri in bianco, e sfuma; il numero nuovo salta fuori. Scelta dall'utente fra
 * sei proposte in un'anteprima. Le classi le mette live-board.js alla cella del set in corso, o a
 * quella appena chiusa quando il game chiude il set. Le animazioni non hanno una fine scritta: si
 * torna al colore proprio della cella, il grigio del set in corso o il nero di quello chiuso, e ai
 * colori smorzati dei suoi numeri. Niente accento rosso, e niente per chi ha chiesto meno movimento.
 */
.live-won-blue { --live-won: var(--blue); }
.live-won-gold { --live-won: var(--gold); }

.live-set.live-game-won {
    animation: live-game-cell 1.5s ease-out;
}

.live-set.live-game-won > *,
.live-set.live-game-won sup {
    animation: live-game-text 1.5s ease-out;
}

.live-set.live-game-won > .live-games.live-game-won {
    animation: live-game-text 1.5s ease-out, live-game-pop 0.6s ease-out;
}

@keyframes live-game-cell {
    0%, 35% { background: var(--live-won); }
}

@keyframes live-game-text {
    0%, 35% { color: #fff; }
}

@keyframes live-game-pop {
    0% { transform: scale(0.4); opacity: 0; }
    45% { transform: scale(1.35); opacity: 1; }
    70% { transform: scale(0.95); }
    100% { transform: none; }
}

/* La cella del set nuovo, quando il game ha chiuso quello prima. */
.live-set.live-set-new {
    animation: live-set-in 0.6s ease-out both;
}

@keyframes live-set-in {
    from { opacity: 0; transform: scale(0.5); }
}

@media (prefers-reduced-motion: reduce) {
    .live-set.live-game-won,
    .live-set.live-game-won > *,
    .live-set.live-game-won sup,
    .live-set.live-set-new {
        animation: none;
    }
}

/* ── Condizioni e informativa (/terms, /privacy) ─────────────────────────────
 *
 * Testo da leggere, non da guardare: una colonna stretta (una riga lunga 60rem non si legge), titoli
 * di sezione piccoli perche' le sezioni sono tante e brevi, e nessun colore nuovo. Le basi legali in
 * corsivo smorzato: servono a chi le cerca, e chi legge per capire le salta.
 */
.legal {
    max-width: 40rem;
}

.legal h1 {
    margin-bottom: 0.35rem;
}

.legal-version {
    color: var(--muted-600);
    font-size: 0.85rem;
    margin-bottom: 2rem;
}

.legal h2 {
    font-size: 1.05rem;
    margin: 1.75rem 0 0.4rem;
}

.legal p,
.legal li {
    line-height: 1.6;
}

.legal ul {
    padding-left: 1.1rem;
}

.legal li + li {
    margin-top: 0.5rem;
}

.legal em {
    color: var(--muted-500);
}

.legal a {
    color: var(--ink);
}

/* I due collegamenti in fondo alle pagine dell'account (ManageLayout). */
.manage-legal {
    margin-top: 3rem;
}
