/*
 * 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) */
    --appointment: #333131; /* blend(INK, BG, 0.21): il fondo degli appuntamenti, scelto dall'utente */

    --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);
}

/*
 * La freccia del menu a tendina. Le due regole qui sopra impostano lo sfondo con `background`,
 * che cancella anche l'immagine con cui Bootstrap disegna la freccia, e il menu sembrava un campo
 * di testo. Il primo menu del sito e' quello dell'orologio che riceve le partite (Orologi, dal 4
 * ottobre 2026). Il colore e' --muted-500 scritto per esteso: dentro un'immagine SVG le variabili
 * CSS non arrivano.
 */
.form-select,
.form-select:focus {
    padding-right: 2.4rem;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239b9797' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.9rem center;
    background-size: 0.8rem;
}

.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;
}

/* Sul telefono il margine ai lati e' quello della barra in alto e della striscia della prova, 1rem
   (voce 101): il contenuto parte allineato al marchio, e 24px per lato su 375 erano spazio tolto
   ai nomi delle schede. */
@media (max-width: 30rem) {
    .page-body {
        padding-right: 1rem;
        padding-left: 1rem;
    }
}

/* ── 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;
}

/*
 * Nell'ingresso il marchio porta alla home (voce 94): si legge come prima, senza sottolineatura, e
 * solo passandoci sopra il nome si schiarisce per dire che e' un collegamento. Largo quanto il suo
 * contenuto, o l'intera riga sopra il titolo sarebbe cliccabile.
 */
a.auth-brand {
    width: fit-content;
    text-decoration: none;
}

a.auth-brand:hover .eyebrow,
a.auth-brand:focus-visible .eyebrow {
    color: var(--ink);
}

.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;
}

/* Nomi, coppa, set: la colonna della coppa e' larga uguale sulle due righe (voce 91). */
.match-board {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 1.35rem 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. Dalla voce 99 e' un elemento della griglia
 * dei nomi, e si taglia coi suoi puntini dentro la pillola.
 */
.match-player-me {
    background: var(--divider);
    border-radius: 0.45em;
    padding: 0.08em 0.4em;
}

/* La barra fra due nomi: senza spazi nel testo, che ai lati di un elemento della griglia si
   perderebbero, ma col suo margine. Non si stringe. */
.match-name-sep {
    min-width: max-content;
    padding: 0 0.3em;
}

/*
 * 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;
}

/*
 * Ogni nome si taglia per conto suo (voce 99, 6 ottobre 2026): prima l'unico testo si tagliava in
 * fondo, e sul telefono il secondo nome spariva intero («Francesca Fant…»). Le colonne della griglia
 * partono dal minimo del loro elemento -- zero per un nome, la larghezza intera per la barra e per
 * la pillola del nome giocatore -- e crescono insieme, ciascuna fino alla larghezza del suo nome: il
 * nome corto si ferma e resta intero, il lungo prende lo spazio che resta e mette i suoi puntini. Con
 * due nomi lunghi si accorciano tutti e due, e di ciascuno si legge l'inizio. `minmax(0, …)`
 * ignorerebbe il minimo della pillola, e a 375px si leggeva «Ame…».
 */
.match-name-text,
.appointment-team,
.detail-team {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(auto, max-content);
    justify-content: start;
    align-items: baseline;
    min-width: 0;
    overflow: hidden;
}

.match-name-text > span:not(.match-name-sep),
.appointment-team > span:not(.match-name-sep),
.detail-team > span:not(.match-name-sep) {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Il nome giocatore, nella sua pillola, non si accorcia: lo spazio che manca lo cede il compagno.
   Diviso a meta', a 375px si leggeva «Ame…» accanto a «Rosari…». */
.match-name-text > span.match-player-me {
    min-width: max-content;
}

/*
 * Sul telefono il nome con la sola iniziale della seconda parola, «Francesca F.» (MatchNames.Short,
 * voce 99): le due forme sono tutte e due nella pagina, perche' il server non sa quanto e' largo lo
 * schermo. Se anche la forma breve non ci sta, si taglia coi puntini come le altre. Dalla voce 102 dove
 * l'intera ci sta torna lei, con name-fits: lo misura player-names.js.
 */
.name-short {
    display: none;
}

@media (max-width: 30rem) {
    .name-full {
        display: none;
    }

    .name-short {
        display: inline;
    }

    /* Il nome intero dove ci sta: lo misura player-names.js (voce 102). Senza script resta la forma
       breve, come prima. */
    .name-fits > .name-full {
        display: inline;
    }

    .name-fits > .name-short {
        display: none;
    }
}

/*
 * La coppa di chi ha vinto (Trophy.razor), nel colore della squadra: currentColor. La misura la
 * decide la sua colonna (.match-trophy, .detail-trophy), col corpo del testo.
 */
.trophy {
    width: 0.95em;
    height: 0.95em;
    flex: none;
}

/*
 * La colonna della coppa nelle schede, subito prima dei set (voce 91): vuota sulla riga di chi ha
 * perso. Centrata in altezza e non sulla linea di base della griglia, dove un'icona senza testo
 * starebbe appoggiata sotto le cifre. Alta quasi quanto le cifre dei set (27 settembre 2026, chiesto
 * dall'utente): piu' piccola si perdeva accanto alle celle velate della voce 92.
 */
.match-trophy {
    display: flex;
    justify-content: center;
    align-self: center;
    font-size: 1.35rem;
}

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

/*
 * Chi ha vinto ogni set (voce 92): la cella del suo game velata del colore della squadra, cioe'
 * currentColor, quindi pieno o smorzato come la riga. Il velo sta sul numero e non sulla cella della
 * griglia, che sotto i 30rem e' piu' stretta del numero con il suo margine. Scelta dall'utente fra
 * dieci proposte: il riquadro pieno dei pannelli gridava, il grigio sul perdente spegneva la riga, e
 * trattini, pallini e filetti si leggevano come separatori.
 */
.match-set > span {
    display: inline-block;
    min-width: 1.35em;
    border-radius: 5px;
    line-height: 1.35;
}

.match-set-won > span {
    background: color-mix(in srgb, currentColor 22%, transparent);
}

/*
 * Sul telefono (voce 101, 6 ottobre 2026) i nomi prendono lo spazio che i set possono cedere: margine
 * interno della scheda piu' stretto, colonne piu' accostate e cifre un po' piu' piccole. Col velo della
 * voce 92 (1.35em della cifra) le celle restano staccate di circa 4px: con le cifre a 1.15rem e lo
 * stacco a 0.3rem si toccherebbero. Con quattro set erano circa 140px di nomi a 375px, ora circa 180.
 */
@media (max-width: 30rem) {
    .match {
        padding-right: 0.9rem;
        padding-left: 0.9rem;
    }

    .match-name {
        font-size: 0.98rem;
    }

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

    .match-set {
        font-size: 1.05rem;
    }
}

/* ── Gli appuntamenti nello storico (2 ottobre 2026) ─────────────────────────
 *
 * Stile scelto dall'utente su un'anteprima, dopo alcune prove: non un tabellone ma una barra bassa a
 * fondo grigio pieno. La prima riga e' la testa delle partite (.match-head, stesse misure e stessi
 * separatori) con «Appuntamento» e il calendario in fondo a destra; poi i nomi nei colori delle
 * squadre, e la nota su una riga. Scartati il rosso (segna solo la partita in corso), il fondo
 * chiaro e quello blu, che sembrava il Team Blue.
 */
.appointment {
    padding: 0.7rem 1.15rem 0.75rem;
    background: var(--appointment);
    border-color: var(--appointment);
}

.appointment[href]:hover {
    background: color-mix(in srgb, var(--appointment) 88%, var(--ink));
    border-color: var(--muted-700);
}

.appointment .match-head {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 0.35rem;
}

.appointment .match-head-line {
    flex: 1 1 auto;
    min-width: 0;
}

.appointment .match-when {
    color: var(--ink);
}

.appointment .match-place {
    color: var(--muted-500);
}

.appointment-tag {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--ink);
}

.calendar-mark {
    width: 1.05rem;
    height: 1.05rem;
    flex: none;
}

/*
 * I nomi su due righe, Blue sopra e Gold sotto come nel tabellone delle partite (voce 100), con lo
 * stesso corpo e lo stesso stacco fra le righe (.match-board); ciascun nome tagliato per conto suo
 * (vedi .match-name-text).
 */
.appointment-names {
    display: grid;
    gap: 0.2rem;
    white-space: nowrap;
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.appointment-notes {
    margin: 0.3rem 0 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.82rem;
    color: var(--muted-500);
}

/* Scaduto: la stessa barra, con la prima riga barrata sottile; il calendario e' tagliato nell'SVG. */
.appointment-expired .match-head-line,
.appointment-expired .appointment-tag-text {
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

/* La pagina dell'appuntamento: la riga sotto il titolo, col calendario. */
.appointment-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0.4rem 0 0;
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--ink);
}

.appointment-label .calendar-mark {
    width: 1.15rem;
    height: 1.15rem;
}

@media (max-width: 30rem) {
    /* Lo stesso margine delle schede delle partite sul telefono (voce 101), o la data degli
       appuntamenti partirebbe piu' a destra di quella delle partite. */
    .appointment {
        padding-right: 0.9rem;
        padding-left: 0.9rem;
    }

    /* Sul telefono solo il calendario: la scritta accanto alla data tagliava l'ora. Resta per i
       lettori di schermo. */
    .appointment-tag-text {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .appointment-names {
        font-size: 0.98rem;
    }
}

/* ── 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.6rem 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);
}

/* Il filetto resta della squadra anche col fuoco (10 ottobre 2026, notato dall'utente): .form-control:focus
   colora tutto il bordo e, piu' specifica, lo faceva diventare grigio. */
.form-control.detail-name-blue:focus {
    border-left-color: var(--blue-panel);
}

.form-control.detail-name-gold:focus {
    border-left-color: 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, ogni nome
   tagliato per conto suo come nelle schede (voce 99, la griglia sta con .match-name-text). */
.detail-team {
    padding: 0.35rem 0 0.35rem 0.7rem;
    white-space: nowrap;
    font-size: 1.1rem;
    font-weight: 600;
}

/*
 * Il tabellone di un appuntamento (3 ottobre 2026): lo stesso, senza coppa e senza set, quindi una
 * colonna sola. Due classi, per vincere anche sulla griglia del telefono qui sotto.
 */
.detail-board.detail-board-names {
    grid-template-columns: minmax(0, 1fr);
}

/* 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.5rem;
}

.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) 1.3rem 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-trophy {
        font-size: 1.3rem;
    }

    .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);
}

/* Sotto i set, staccata dai campi come un errore di convalida. */
.hand-appointment-hint {
    margin-top: 0.6rem;
    font-size: 0.9rem;
}

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

/*
 * I suggerimenti dei nomi e di Dove (voce 103, name-suggestions.js): un riquadro sospeso sopra la pagina,
 * agganciato al campo con una punta, con l'etichetta e una riga sola di pillole che scorre di lato.
 * Sospeso e non nel flusso, scelto dall'utente: si legge come un suggerimento, e i campi sotto non
 * saltano quando compare. 6px piu' largo per lato, perche' la curva degli angoli cada fuori dai campi
 * sotto: col bordo colorato del campo Gold si vedeva spuntare. La sua altezza (--tray-top) e la punta
 * (--caret-x) le misura lo script.
 */
.suggest-host {
    position: relative;
}

.name-suggestions {
    position: absolute;
    z-index: 5;
    top: var(--tray-top, 100%);
    left: -6px;
    right: -6px;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.55rem;
    background: var(--row-rule);
    border: 1px solid var(--divider);
    border-radius: 0.7rem;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.75);
}

.name-suggestions[hidden] {
    display: none;
}

.name-suggestions::before {
    content: "";
    position: absolute;
    top: -4px;
    left: var(--caret-x, 1.5rem);
    width: 7px;
    height: 7px;
    transform: rotate(45deg);
    background: var(--row-rule);
    border-left: 1px solid var(--divider);
    border-top: 1px solid var(--divider);
}

.name-suggestions-label {
    flex: none;
    color: var(--muted-600);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: var(--track-caps);
    text-transform: uppercase;
}

/* Tutta la larghezza che resta: la sfumatura (.more) sta sul bordo del riquadro, non sull'ultima pillola. */
.name-suggestions-scroll {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
}

.name-suggestions-scroll::-webkit-scrollbar {
    display: none;
}

.name-suggestions-scroll.more {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
}

.name-suggestion {
    flex: none;
    white-space: nowrap;
    padding: 0.32rem 0.8rem;
    border: 1px solid var(--divider);
    border-radius: 999px;
    background: var(--set-fill);
    color: var(--ink);
    font-size: 0.9rem;
    line-height: 1.35;
}

.name-suggestion:hover {
    border-color: var(--muted-700);
}

/* Compare con una dissolvenza scivolando dall'alto, e se ne va allo stesso modo. */
.name-suggestions.entering {
    animation: suggestions-in 160ms ease-out;
}

.name-suggestions.leaving {
    animation: suggestions-out 120ms ease-in forwards;
}

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

@keyframes suggestions-out {
    to { opacity: 0; transform: translateY(-6px); }
}

@media (prefers-reduced-motion: reduce) {
    .name-suggestions.entering,
    .name-suggestions.leaving {
        animation: none;
    }
}

.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;
}

/*
 * L'icona delle statistiche in fondo al sommario (13 ottobre 2026): quattro barre in un cerchio col
 * bordo delle pillole, scelta dall'utente fra sette. Centrata in altezza sulla riga; l'icona nel
 * cerchio la centra il disegno (StatsMark.razor). Con lei a 375px i tre numeri e il cerchio stanno su
 * una riga solo stringendo lo spazio fra i numeri, come nella Dashboard dell'Admin.
 */
.summary:has(.stats-link) {
    gap: clamp(1.25rem, 5vw, 2.25rem);
}

.stats-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    align-self: center;
    margin-left: auto;
    width: 2.9rem;
    height: 2.9rem;
    border: 1px solid var(--divider);
    border-radius: 50%;
    color: var(--muted-500);
}

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

.stats-mark {
    width: 1.35rem;
    height: 1.35rem;
}

/* ── La pagina delle statistiche (13 ottobre 2026, MatchStats.razor) ───────────
 *
 * Le cifre sono quelle del sommario dello storico (.summary-num, .summary-lab), raccolte in sezioni
 * con un titolo piccolo e il filetto del sommario. Niente colori delle squadre e niente rosso: sono
 * numeri tuoi, non di una squadra.
 */

/* Il filtro in sola lettura: ogni parte una pillola spenta, che non si tocca. */
.stats-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.stats-filter .eyebrow {
    margin-right: 0.25rem;
}

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

.stats-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.25rem 0.75rem;
    border: 1px solid var(--divider);
    border-radius: 999px;
    font-size: 0.85rem;
    color: var(--ink);
    overflow-wrap: anywhere;
}

.stats-chip small {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: var(--track-label);
    text-transform: uppercase;
    color: var(--muted-600);
}

.stats-section {
    padding: 1.5rem 0;
    border-bottom: 2px solid var(--divider);
}

.stats-section > .eyebrow {
    margin-bottom: 1rem;
}

/* Due sezioni brevi affiancate sul desktop, una sotto l'altra sul telefono. */
.stats-pair {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    column-gap: 3rem;
    border-bottom: 2px solid var(--divider);
}

.stats-pair > .stats-section {
    border-bottom: 0;
}

.stats-pair > .stats-section + .stats-section {
    border-top: 2px solid var(--divider);
}

@media (min-width: 48rem) {
    .stats-pair {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }

    .stats-pair > .stats-section + .stats-section {
        border-top: 0;
    }
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.75rem clamp(0.75rem, 4vw, 1.5rem);
}

.stats-grid.stats-two {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.stats-grid-row {
    grid-column-start: 1;
}

.stats-section .summary-num {
    font-size: clamp(2rem, 5.5vw, 2.6rem);
}

.stats-big .summary-num {
    font-size: clamp(2.25rem, 6vw, 3rem);
}

/* Senza nome giocatore: le partite e l'invito, come nel sommario dello storico. */
.stats-results {
    display: flex;
    flex-wrap: wrap;
    gap: 2.25rem;
}

/* Le unità del tempo in campo, come il segno di percentuale: non rubano la cifra. */
.stats-unit {
    font-size: 0.45em;
    font-weight: 600;
    color: var(--muted-600);
    letter-spacing: 0;
    margin: 0 0.3em 0 0.08em;
}

.stats-note {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.78rem;
    color: var(--muted-500);
}

/*
 * Quello che si tocca nelle statistiche (14 ottobre 2026, scelto dall'utente su due anteprime): i
 * numeri che portano allo storico filtrato (vinte, perse, pareggiate) e i nomi di compagni e avversari.
 * Lo stesso per «vinte» e «% vinte» nel sommario dello storico, chiesto lo stesso giorno.
 * **Una linea bianca leggerissima**, mezzo pixel al 55% anche sotto le cifre grandi, sempre visibile,
 * perché sul telefono il passaggio del mouse non c'è. Sui telefoni è un filo; sugli schermi che hanno
 * un pixel fisico per pixel il mezzo diventa uno, e la trasparenza la tiene leggera. Al passaggio si
 * illumina solo l'etichetta, il numero o il nome restano com'erano. Scartati: niente segno fino al
 * passaggio (sul telefono non si capiva), una freccina, l'etichetta sottolineata o bianca, linee
 * grigie, piene o più spesse sotto il numero. Il rosso
 * che i nomi prendevano al passaggio è tolto: l'accento segna solo la partita in corso.
 */
.stats-num-link {
    display: block;
    color: inherit;
    text-decoration: none;
}

.stats-num-link .summary-num,
a.stats-name {
    text-decoration: underline 0.5px color-mix(in srgb, var(--ink) 55%, transparent);
}

.stats-num-link .summary-num {
    text-underline-offset: 0.12em;
}

/* Solo la cifra, non il «%» accanto (chiesto dall'utente): una linea non scende in un inline-block. */
.stats-num-link .summary-pct {
    display: inline-block;
}

a.stats-name {
    text-underline-offset: 0.2em;
}

.stats-num-link .summary-lab,
.stats-row dt {
    transition: color 0.15s;
}

@media (hover: hover) {
    .stats-num-link:hover,
    a.stats-name:hover {
        color: var(--ink);
    }

    .stats-num-link:hover .summary-lab,
    .stats-row:has(a.stats-name:hover) dt {
        color: var(--ink);
    }
}

.stats-empty {
    margin: 0;
    font-size: 0.85rem;
    color: var(--muted-500);
}

/* Sinistra e destra: i due numeri ai due lati, e una barra divisa in proporzione. */
.stats-split-right {
    text-align: right;
}

.stats-split {
    display: flex;
    gap: 3px;
    height: 0.4rem;
    margin-top: 1.1rem;
    border-radius: 999px;
    overflow: hidden;
}

.stats-split span:first-child {
    background: var(--ink);
}

.stats-split span:last-child {
    background: var(--muted-700);
}

/* Compagni e avversari: etichetta, nome e numeri su una riga; sul telefono l'etichetta sta sopra. */
.stats-rows {
    margin: 0;
}

.stats-row {
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0.25rem 1rem;
    padding: 0.7rem 0;
    border-top: 1px solid var(--row-rule);
}

.stats-row:first-child {
    border-top: 0;
    padding-top: 0;
}

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

.stats-row dd {
    margin: 0;
}

@media (max-width: 30rem) {
    .stats-row {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .stats-row dt {
        grid-column: 1 / -1;
    }
}

.stats-name {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--ink);
    text-decoration: none;
    overflow-wrap: anywhere;
}

.stats-figures {
    text-align: right;
    white-space: nowrap;
    font-size: 0.85rem;
    color: var(--muted-500);
}

.stats-figures strong {
    margin-right: 0.35rem;
    font-size: 1.15rem;
    color: var(--ink);
}

/* Dove: nome e numeri, e sotto una barra lunga in proporzione al primo luogo. */
.stats-places {
    margin: 0;
    padding: 0;
    list-style: none;
}

.stats-places li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0.4rem 1rem;
    padding: 0.7rem 0;
    border-top: 1px solid var(--row-rule);
}

.stats-places li:first-child {
    border-top: 0;
    padding-top: 0;
}

.stats-bar {
    grid-column: 1 / -1;
    height: 0.3rem;
    border-radius: 999px;
    background: var(--set-fill);
    overflow: hidden;
}

.stats-bar span {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--muted-600);
}

/*
 * L'andamento (13 ottobre 2026, Shared/TrendChart.razor): la % vinte, una curva bianca sola. L'SVG si
 * stira sul riquadro, quindi i tratti non scalano e il pallino e il cursore del tocco sono HTML sopra di
 * lui. `pan-y`: col dito si scorre lungo il grafico e la pagina scorre ancora in verticale.
 */
/* Alta due righe: tante ne ha il riquadro del tocco, e la legenda di una non deve far saltare il grafico. */
.trend-legend {
    min-height: 2.6rem;
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    color: var(--muted-500);
}

.trend-swatch {
    display: inline-block;
    width: 1.1rem;
    height: 3px;
    margin-right: 0.45rem;
    vertical-align: middle;
    background: var(--ink);
}

.trend-readout strong {
    display: block;
    font-weight: 600;
    color: var(--ink);
}

.trend-plot {
    position: relative;
    height: 11rem;
    margin-right: 2.6rem;
    touch-action: pan-y;
    cursor: crosshair;
}

@media (min-width: 48rem) {
    .trend-plot {
        height: 15rem;
    }
}

.trend-plot svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.trend-grid,
.trend-mid {
    stroke: var(--divider);
    stroke-width: 1;
}

.trend-mid {
    stroke-dasharray: 4 4;
}

.trend-rate {
    fill: none;
    stroke: var(--ink);
    stroke-width: 2.5;
    stroke-linejoin: round;
}

/* La scala fuori dal riquadro, a destra: dentro starebbe sopra la curva, che all'inizio parte spesso
   proprio da 0 o da 100. */
.trend-scale {
    position: absolute;
    left: calc(100% + 0.5rem);
    font-size: 0.68rem;
    line-height: 1;
    color: var(--muted-700);
    transform: translateY(-50%);
    pointer-events: none;
}

.trend-scale-top {
    top: 0;
}

.trend-scale-mid {
    top: 50%;
}

.trend-scale-bottom {
    top: 100%;
}

.trend-cursor {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    margin-left: -0.5px;
    background: var(--ink);
    pointer-events: none;
}

.trend-dot {
    position: absolute;
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    background: var(--ink);
    /* Un anello del fondo, o sulla curva bianca il pallino non si distingue. */
    box-shadow: 0 0 0 2px var(--bg);
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.trend-dates {
    display: flex;
    justify-content: space-between;
    margin: 0.5rem 2.6rem 0 0;
    font-size: 0.75rem;
    color: var(--muted-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,
.matches-roles-opponents::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-box[open] > .matches-filter-toggle {
    color: var(--ink);
}

/* Il bianco al passaggio del mouse solo dove c'e' un mouse (12 ottobre 2026, visto dall'utente): sul
 * telefono :hover resta attaccato all'ultimo elemento toccato, e «Filtra» richiuso restava bianco. */
@media (hover: hover) {
    .matches-filter-toggle:hover {
        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);
}

/*
 * «Compagno e avversari» (12 ottobre 2026, matches-roles.js): l'ultima riga del form, sotto testo e
 * date anche sul telefono, chiusa dietro un occhiello con la freccia di «Filtra». Tre campi uguali; sul
 * desktop non si allargano oltre quanto serve a un nome, o tre campi da un terzo di pagina
 * sembrerebbero un modulo da compilare.
 *
 * Fra il compagno e gli avversari una colonna larga zero, scelto dall'utente lo stesso giorno: lo
 * spazio fra le due parti diventa doppio di quello fra i due avversari, e i campi restano larghi uguali.
 * La stessa griglia la prende la riga che apre e chiude, quando e' aperta (sotto).
 */
.matches-roles {
    --roles-columns: minmax(0, 1fr) 0 minmax(0, 1fr) minmax(0, 1fr);
    flex: 1 1 100%;
    order: 2;
}

/*
 * La riga che apre e chiude fa anche da intestazione, chiesto dall'utente lo stesso giorno al posto di
 * una riga «Con» / «Contro» sopra i campi. Chiusa: «Compagno e avversari» e la freccia. Aperta: la
 * griglia dei campi, «Compagno» sopra il primo, «Avversari» sopra gli altri due, e la «e» sparisce. Per
 * questo la freccia sta dopo «Avversari» e non in fondo alla riga, dove la griglia la sposterebbe.
 */
.matches-roles-toggle::after {
    content: none;
}

/* Bianca anche da chiusa, come «Filtra» aperto, chiesto dall'utente: la riga si vede solo dentro il
 * filtro aperto, e il grigio di un occhiello chiuso la faceva sembrare spenta. Il bianco che compariva
 * dopo averla aperta e richiusa era solo il :hover del mouse rimasto sopra. */
.matches-roles-toggle {
    color: var(--ink);
}

.matches-roles-opponents {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.matches-roles[open] > .matches-roles-toggle {
    display: grid;
    grid-template-columns: var(--roles-columns);
    column-gap: 0.5rem;
    max-width: 36rem;
    color: var(--ink);
}

.matches-roles[open] .matches-roles-and {
    display: none;
}

.matches-roles[open] .matches-roles-partner {
    grid-column: 1;
}

.matches-roles[open] .matches-roles-opponents {
    grid-column: 3 / span 2;
}

.matches-roles[open] .matches-roles-opponents::after {
    transform: translateY(0.1rem) rotate(-135deg);
}

.matches-roles-fields {
    display: grid;
    grid-template-columns: var(--roles-columns);
    gap: 0.5rem;
    max-width: 36rem;
    margin-top: 0.4rem;
}

.matches-roles-fields > [data-role="partner"] + [data-role="opponent"] {
    grid-column: 3;
}

/* «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. **Rifatte di nuovo il
 * 6 ottobre 2026 (voce 97)**, quando gli Orologi sono passati nel menu dell'account: con le soglie
 * di prima il nome spariva su telefoni dove ormai ci stava. Misurate sommando i pezzi delle tre
 * disposizioni, coi testi delle due lingue (fra parentesi le misure del 16 settembre):
 *
 *                                      italiano        inglese
 *   nome e spazi normali               426px (507)     467px (550)
 *   nome e spazi stretti               378px (451)     419px (494)
 *   solo marchio e spazi stretti       241px (314)     282px (357)
 *
 * 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 41px 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: 27.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: 30rem) {
    .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: 24.5rem) {
    .topbar-brand:lang(it) {
        font-size: 0;
        gap: 0;
    }
}

@media (max-width: 27rem) {
    .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;
}

/* Righe di lunghezza simile: senza, «accoppiamento» restava da solo sulla seconda riga del
   gesto, a larghezza di desktop (voce 96). */
.pairing-how {
    margin: 0 auto;
    max-width: 30rem;
    line-height: 1.6;
    text-wrap: balance;
}

/* Il gesto viene dopo una riga vuota: e' un secondo passo, non il seguito del percorso. */
.pairing-tap {
    margin-top: 1.6em;
}

/* La scheda di Padel Companion nell'app Zepp, con l'ingranaggio gia' cerchiato nel file: 520px
   veri mostrati a 260, per gli schermi densi. Sui telefoni stretti si restringe col riquadro. */
.pairing-shot {
    display: block;
    width: min(100%, 260px);
    height: auto;
    margin: 1.1rem auto 0;
    border: 1px solid var(--divider);
    border-radius: 12px;
}

.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;
}

/* Con .manage-body davanti: la pagina sta nella cornice dell'account (voce 97), e il margine
   sotto dei suoi titoli, piu' in fondo al foglio, staccherebbe il titolo dal pulsante accanto. */
.manage-body .devices-head h1 {
    margin: 0;
}

/*
 * «Scollegati», sopra le schede degli orologi scollegati: un occhiello e non un titolo pieno,
 * perche' nomina un gruppo di schede, non una 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);
}

/* I campi della domanda, come il menu dell'orologio che riceve le partite: largo quanto il testo. */
.confirm-details {
    margin: 0 0 0.75rem;
    max-width: 24rem;
}

.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).
 */
/* Con .manage-body davanti, come il titolo degli Orologi: nella cornice dell'account vincerebbe il
   margine dei suoi titoli. */
.manage-body .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.
 */
/*
 * Lo spazio della barra di scorrimento sempre riservato nelle pagine dell'account: passando da una
 * pagina lunga (Generale dell'Admin) a una corta (Indicatori) la barra spariva, la finestra si
 * allargava di 15px e la pagina centrata si spostava di mezza barra. Solo qui e non su tutto il
 * sito: la Partita Live prende tutta la finestra e avrebbe una striscia vuota a destra.
 */
html:has(.manage) {
    scrollbar-gutter: stable;
}

.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;
}

/*
 * Il gruppo delle pagine dell'Admin, staccato dalle voci dell'account da un filetto: non
 * riguarda il proprio account, e lo vede uno solo. Il titolo del gruppo e' un occhiello, come
 * «Account» sopra il menu, con la versione del sito accanto (.admin-version).
 */
.manage-nav-heading {
    margin-top: 0.6rem;
    padding: 0.9rem 0 0.2rem;
    border-top: 1px solid var(--divider);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--muted-600);
}

.manage-nav-heading .admin-version {
    font-size: 0.72rem;
}

/* ── 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;
}

/*
 * Tranne la licenza, che va a capo dopo la virgola (Admin.razor, LicenseText): accanto al menu
 * dell'account «Acquistato, 27 set 2026» su una riga faceva scorrere la tabella anche su un
 * desktop. Allargare la sola pagina con la tabella spostava il menu cambiando voce.
 */
.admin-table td.admin-license {
    white-space: normal;
}

/*
 * Le intestazioni sono collegamenti che ordinano: restano occhielli, non testo sottolineato. Vanno
 * a capo («Nome / giocatore», «Ultima / partita»): accanto al menu dell'account, su una riga,
 * facevano scorrere la tabella anche su un desktop. La freccia dell'ordinamento resta attaccata
 * alla parola (Admin.razor, Arrow).
 */
.admin-table thead th a {
    color: inherit;
    text-decoration: none;
}

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

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

/*
 * Gli Indicatori: i numeri del sommario in una griglia di tre colonne, anche sul telefono, cosi'
 * ogni riga e' un periodo (sopra i totali, sotto gli ultimi 30 giorni, che ricomincia dalla prima
 * colonna con .summary-grid-row). A 375px le etichette lunghe vanno su due righe: e' voluto, un
 * numero per riga allungherebbe la pagina e perderebbe i periodi.
 */
.summary-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 2rem clamp(0.75rem, 4vw, 1.5rem);
    margin-top: 1.5rem;
    padding-bottom: 1.5rem;
    border-bottom: 2px solid var(--divider);
}

.summary-grid-row {
    grid-column-start: 1;
}

/*
 * 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;
}

/* Le ultime partite dell'utente, staccate come la licenza: le schede sono quelle dello storico. */
.admin-user-matches {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 2px solid var(--divider);
}

/* Gli orologi collegati, staccati come la licenza: il nome a sinistra, l'ultimo contatto a destra,
   con la sua etichetta sopra la colonna delle date. Un nome lungo si taglia, la data no. */
.admin-user-watches {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 2px solid var(--divider);
}

.admin-user-watches-head,
.admin-user-watch-list li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
}

.admin-user-watch-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.admin-user-watch-list li {
    padding: 0.5rem 0;
    border-top: 1px solid var(--divider);
}

.admin-user-watch-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* L'etichetta della colonna e le date non vanno a capo: a 375px in inglese «Last seen» finiva su due
   righe accanto al titolo. Va a capo il titolo. */
.admin-user-watches-head > span,
.admin-user-watch-seen {
    flex-shrink: 0;
    white-space: nowrap;
}

.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;
}

@media (max-width: 30rem) {
    .live-back,
    .live-bar {
        padding-right: 1rem;
        padding-left: 1rem;
    }
}

.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;
}

/* ── La home per chi non è entrato (27 settembre 2026) ─────────────────────────
 *
 * Disegnata con l'utente su un'anteprima statica e portata qui com'era. Le classi sono tutte
 * `landing-`, perche' la pagina ha pulsanti, schede e barre sue e Bootstrap ha gia' `.btn`, `.nav`
 * e compagnia: un nome generico qui cambierebbe altre pagine. I pezzi del sito vero (tabellone,
 * schede, sommario) tengono invece le loro classi, e la home li disegna come le pagine vere.
 *
 * Il prezzo sta in fondo, smorzato: il fuoco della pagina e' che cos'e' Padel Companion e che cosa
 * offre, scelto dall'utente.
 */
.landing {
    overflow-x: hidden;
    line-height: 1.5;
}

.landing-wrap {
    width: 100%;
    max-width: 1320px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 4vw, 3rem);
}

/* La barra: marchio, «Accedi», «Registrati». «Accedi» resta anche sui telefoni stretti. */
.landing-nav {
    position: sticky;
    top: 0;
    z-index: 20;
    background: rgba(0, 0, 0, 0.82);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--row-rule);
}

.landing-nav .landing-wrap {
    display: flex;
    align-items: center;
    gap: 1rem;
    height: 60px;
}

.landing-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--ink);
    font-weight: 650;
    letter-spacing: -0.01em;
    text-decoration: none;
}

.landing-brand:hover {
    color: var(--ink);
}

.landing-brand .brand-mark {
    width: 28px;
    height: 28px;
}

.landing-nav-links {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-left: auto;
    font-size: 0.92rem;
}

.landing-login {
    color: var(--muted-500);
    text-decoration: none;
}

.landing-login:hover {
    color: var(--ink);
}

@media (max-width: 400px) {
    .landing-nav .landing-wrap { gap: 0.6rem; }
    .landing-nav-links { gap: 0.9rem; font-size: 0.88rem; }
    .landing-brand { gap: 0.5rem; font-size: 0.95rem; }
    .landing-brand .brand-mark { width: 24px; height: 24px; }
    .landing-btn.landing-btn-small { padding: 0.45rem 0.85rem; }
}

/* I pulsanti: il rosso per iscriversi, il contorno per il resto. */
.landing-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: transform 0.12s ease, background-color 0.12s ease, border-color 0.12s ease;
}

.landing-btn:hover {
    transform: translateY(-1px);
}

.landing-btn-primary,
.landing-btn-small {
    background: var(--accent);
    color: #fff;
}

.landing-btn-primary:hover,
.landing-btn-small:hover {
    background: #ff4426;
    color: #fff;
}

.landing-btn-primary {
    padding: 0.95rem 1.7rem;
    font-size: 1.05rem;
}

.landing-btn-small {
    padding: 0.45rem 1rem;
    font-size: 0.88rem;
}

.landing-btn-ghost {
    padding: 0.95rem 1.5rem;
    border: 1px solid var(--divider);
    color: var(--ink);
    font-size: 1.05rem;
}

.landing-btn-ghost:hover {
    border-color: var(--muted-700);
    color: var(--ink);
}

.landing-btn-quiet {
    justify-self: start;
    padding: 0.7rem 1.3rem;
    font-size: 0.95rem;
}

/* ── L'apertura: titolo, scena, testo ──────────────────────────────────────── */
.landing-hero {
    position: relative;
    padding: clamp(2rem, 6vw, 5rem) 0 clamp(3rem, 7vw, 6rem);
}

.landing-hero::before {
    content: "";
    position: absolute;
    inset: -60px 0 0;
    background:
        radial-gradient(40rem 26rem at 78% 30%, rgba(28, 79, 214, 0.22), transparent 70%),
        radial-gradient(30rem 22rem at 96% 75%, rgba(192, 127, 22, 0.16), transparent 70%);
    pointer-events: none;
}

.landing-hero .landing-wrap {
    position: relative;
    display: grid;
    gap: 1.75rem clamp(2rem, 5vw, 4.5rem);
    align-items: center;
}

/* Sul telefono la scena sta fra titolo e testo, e si vede al primo colpo; sul desktop a destra. */
@media (min-width: 960px) {
    .landing-hero {
        display: flex;
        align-items: center;
        min-height: calc(100vh - 60px);
    }

    .landing-hero .landing-wrap {
        grid-template-columns: minmax(0, 11fr) minmax(0, 13fr);
        grid-template-areas: "head scene" "body scene";
        align-content: center;
        row-gap: 0;
    }

    .landing-hero-head { grid-area: head; align-self: end; }
    .landing-hero-body { grid-area: body; align-self: start; padding-top: 1.5rem; }
    .landing-scene { grid-area: scene; }
}

.landing-hero h1 {
    margin: 0.9rem 0 0;
    font-size: clamp(2.5rem, 4.4vw, 4.4rem);
    font-weight: 700;
    line-height: 0.98;
    letter-spacing: -0.045em;
}

.landing-hero-second {
    color: var(--muted-600);
}

.landing-lead {
    max-width: 34rem;
    margin: 0 0 0.9rem;
    font-size: clamp(1.05rem, 1.4vw, 1.2rem);
    color: #c9c6c6;
}

.landing-lead-strong {
    color: var(--ink);
    font-weight: 600;
}

.landing-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 2rem;
}

.landing-fine {
    margin: 1rem 0 0;
    font-size: 0.86rem;
    color: var(--muted-600);
}

/* La scena: tutto in percentuali (6:5) e in cqw, lo stesso disegno a 375px e a 1400px. */
.landing-scene {
    position: relative;
    aspect-ratio: 6 / 5;
    container-type: inline-size;
    overflow: hidden;
    border-radius: clamp(16px, 2.4vw, 28px);
    background: #05070c;
    box-shadow: 0 40px 120px -40px rgba(28, 79, 214, 0.45), 0 0 0 1px #15181f;
}

.landing-scene > svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.landing-flow {
    fill: none;
    stroke: #fff;
    stroke-opacity: 0.45;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-dasharray: 2 9;
}

.landing-pulse {
    fill: none;
    stroke: #fff;
    stroke-width: 5;
    stroke-linecap: round;
    opacity: 0;
}

/* Il tablet sta sospeso davanti ai vetri, senza supporto: un'ombra e un alone al posto del morsetto. */
.landing-tablet {
    position: absolute;
    left: 7%;
    top: 6%;
    width: 55%;
    aspect-ratio: 16 / 10;
    padding: 1.5cqw;
    border-radius: 2.8cqw;
    background: linear-gradient(145deg, #2a2b2f, #0c0c0e 40%, #17181b);
    box-shadow: 0 0 0 0.25cqw #34363b, 0 4cqw 8cqw -1cqw rgba(0, 0, 0, 0.85), 0 0 9cqw -2cqw rgba(74, 125, 255, 0.35);
    transform: rotate(-1.2deg);
}

.landing-glass {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #000;
}

.landing-tablet .landing-glass {
    border-radius: 1.3cqw;
}

.landing-tablet .landing-glass::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(115deg, rgba(255, 255, 255, 0.07), transparent 38%);
    pointer-events: none;
}

/* Il tabellone vero dentro gli schermi finti: .live-board prende l'altezza dello schermo. */
.landing .live-board {
    height: 100%;
}

/* Lo schermo dell'orologio sul polso, sulla cassa disegnata nell'SVG. */
.landing-wrist-screen {
    position: absolute;
    left: 73%;
    top: 66.5%;
    width: 13.33%;
    height: 19%;
    overflow: hidden;
    border-radius: 24.4% / 20.5%;
    background: #000;
    transform: rotate(-8deg);
}

/* Sull'orologio i set stanno sopra i pannelli coi loro minuti, come nelle schermate dello store. */
.landing-set-minutes {
    display: none;
}

/* La testata piu' alta e piu' in dentro del tabellone: sull'orologio gli angoli arrotondati sono larghi,
   e ora e minuti li toccavano. Le misure sono quelle della schermata dello store (432x514, raggio 106). */
.landing-watch-face .live-screen { grid-template-rows: 78fr 372fr; }
.landing-watch-face .live-header { padding: calc(10 * var(--uy)) calc(66 * var(--ux)) 0; font-size: calc(34 * var(--u)); }
.landing-watch-face .live-panels { grid-template-rows: minmax(0, 150fr) minmax(0, 244fr); }
.landing-watch-face .live-set { grid-template-rows: calc(52 * var(--uy)) calc(52 * var(--uy)) calc(22 * var(--uy)); }

.landing-watch-face .landing-set-minutes {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: calc(15 * var(--u));
    color: var(--muted-500);
}

.landing-tag {
    position: absolute;
    display: inline-flex;
    align-items: center;
    gap: 0.9cqw;
    padding: 0.9cqw 1.8cqw;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 99px;
    background: rgba(10, 10, 12, 0.78);
    backdrop-filter: blur(6px);
    font-size: max(10px, 2.1cqw);
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.landing-tag-live { left: 66%; top: 9%; }
.landing-tag-wrist { left: 4%; bottom: 4%; }

.landing-tag-dot {
    width: max(6px, 1.3cqw);
    height: max(6px, 1.3cqw);
    border-radius: 50%;
    background: var(--accent);
    animation: landing-dot 1.6s ease-in-out infinite;
}

@keyframes landing-dot {
    50% { opacity: 0.25; }
}

/* Il dito sull'orologio: un cerchio che si allarga sulla meta' toccata (landing.js). */
.landing-tap {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 70%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.55);
    transform: translate(-50%, -50%) scale(0);
    animation: landing-tap 0.6s ease-out forwards;
    pointer-events: none;
}

@keyframes landing-tap {
    0% { transform: translate(-50%, -50%) scale(0.2); opacity: 0.9; }
    100% { transform: translate(-50%, -50%) scale(1.6); opacity: 0; }
}

[data-landing-screen],
[data-landing-watch] {
    transition: opacity 0.35s ease;
}

.landing-fading {
    opacity: 0;
}

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

/* ── Le sezioni ────────────────────────────────────────────────────────────── */
.landing-section {
    padding: clamp(3.5rem, 8vw, 7rem) 0;
    border-top: 1px solid var(--row-rule);
    scroll-margin-top: 60px;
}

.landing-section h2 {
    margin: 0.8rem 0 1rem;
    font-size: clamp(1.9rem, 3.6vw, 3.1rem);
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -0.04em;
}

.landing-section p {
    max-width: 36rem;
    font-size: 1.05rem;
    color: #c9c6c6;
}

.landing-steps {
    display: grid;
    gap: 1px;
    margin-top: 2.5rem;
    overflow: hidden;
    border: 1px solid var(--divider);
    border-radius: 18px;
    background: var(--divider);
}

@media (min-width: 820px) {
    .landing-steps { grid-template-columns: repeat(3, 1fr); }
}

.landing-step {
    padding: clamp(1.5rem, 3vw, 2.25rem);
    background: var(--bg);
}

.landing-step-n {
    display: block;
    margin-bottom: 1.25rem;
    font-size: clamp(3rem, 6vw, 4.5rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.05em;
}

.landing-step:nth-child(1) .landing-step-n { color: var(--blue-panel); }
.landing-step:nth-child(2) .landing-step-n { color: var(--gold-panel); }
.landing-step:nth-child(3) .landing-step-n { color: var(--ink); }

.landing-step h3 {
    margin: 0 0 0.5rem;
    font-size: 1.2rem;
    letter-spacing: -0.02em;
}

.landing-section .landing-step p {
    margin: 0;
    font-size: 0.97rem;
    color: var(--muted-500);
}

/* Evidenziato, ma meno del titolo del passo: scelto dall'utente. */
.landing-highlight {
    color: #cfcbcb;
    font-weight: 500;
}

.landing-feature .landing-wrap {
    display: grid;
    gap: clamp(2rem, 5vw, 5rem);
    align-items: center;
}

@media (min-width: 960px) {
    .landing-feature .landing-wrap { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
    .landing-flip .landing-wrap { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
    .landing-flip .landing-copy { order: 2; }
}

.landing-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 1.5rem 0 0;
    padding: 0;
    list-style: none;
}

.landing-chips li {
    padding: 0.4rem 0.85rem;
    border: 1px solid var(--divider);
    border-radius: 99px;
    font-size: 0.86rem;
    color: #d7d4d4;
}

/* Partita Live: una TV coricata e un telefono in piedi, col tabellone nelle sue due forme. */
.landing-screens {
    position: relative;
    aspect-ratio: 7 / 5;
    container-type: inline-size;
}

.landing-tv {
    position: absolute;
    top: 0;
    left: 0;
    width: 86%;
    aspect-ratio: 16 / 9;
    padding: 1cqw;
    border-radius: 1.4cqw;
    background: #0d0d0f;
    box-shadow: 0 0 0 0.2cqw #2c2d31, 0 4cqw 8cqw -3cqw rgba(28, 79, 214, 0.4);
}

.landing-tv .landing-glass {
    border-radius: 0.5cqw;
}

.landing-tv-foot {
    position: absolute;
    top: calc(86cqw * 9 / 16 + 0.5cqw);
    left: 38%;
    width: 10%;
    height: 2.2cqw;
    border-radius: 0 0 1cqw 1cqw;
    background: linear-gradient(#232428, #111214);
}

.landing-phone {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 29%;
    aspect-ratio: 9 / 19;
    padding: 1.1cqw;
    border-radius: 4.4cqw;
    background: #111214;
    box-shadow: 0 0 0 0.25cqw #34363b, 0 3cqw 6cqw -1cqw rgba(0, 0, 0, 0.9);
}

.landing-phone .landing-glass {
    display: flex;
    flex-direction: column;
    border-radius: 3.4cqw;
}

.landing-phone-bar {
    display: flex;
    flex: none;
    align-items: flex-end;
    height: 12%;
    padding: 0 8% 5%;
}

.landing-phone-bar span {
    font-size: 2.2cqw;
    font-weight: 650;
}

.landing-phone-board {
    flex: 1;
    min-height: 0;
}

/* Storico: il sommario e le schede del sito, e le statistiche di una partita. */
.landing-history {
    display: grid;
    gap: 1rem;
}

@media (min-width: 640px) {
    .landing-history {
        grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
        align-items: start;
    }
}

.landing-history .summary {
    grid-column: 1 / -1;
    margin-top: 0;
    padding-bottom: 0;
    border-bottom: 0;
}

.landing-history .match-list {
    margin-top: 0;
}

.landing-section .landing-history .match-notes {
    max-width: none;
    margin: 0.7rem 0 0;
    font-size: 0.82rem;
    color: var(--muted-500);
}

.landing-stats {
    padding: 1.1rem 1.15rem;
    border: 1px solid var(--divider);
    border-radius: 12px;
}

.landing-stats .eyebrow {
    margin-bottom: 0.6rem;
}

.landing-stats-row {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.55rem 0;
    border-top: 1px solid var(--row-rule);
    font-size: 0.95rem;
}

.landing-stats-row > span {
    align-self: center;
    font-size: 0.78rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-500);
}

.landing-stats-row b {
    font-weight: 650;
}

.landing-stats-sep {
    font-weight: 400;
    color: var(--muted-700);
}

/* Al polso: le due schermate vere dell'app, in una cassa col cinturino. */
.landing-watches {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: clamp(1rem, 4vw, 3rem);
    padding: 3.5rem 0 3rem;
}

.landing-watch {
    position: relative;
    width: min(40%, 230px);
}

.landing-watch:first-child { transform: rotate(-4deg); }
.landing-watch:last-child { transform: rotate(3deg) translateY(-6%); }

.landing-strap {
    position: absolute;
    left: 17%;
    right: 17%;
    height: 30%;
    background: linear-gradient(90deg, #121214, #1e1f22 50%, #121214);
}

.landing-strap-top { top: -22%; border-radius: 14px 14px 4px 4px; }
.landing-strap-bottom { bottom: -22%; border-radius: 4px 4px 14px 14px; }

.landing-case {
    position: relative;
    z-index: 1;
    padding: 5%;
    border-radius: 26% / 22%;
    background: linear-gradient(150deg, #3a3b40, #141417 45%, #26272b);
    box-shadow: 0 0 0 1px #45464c, 0 30px 60px -20px rgba(0, 0, 0, 0.9);
}

.landing-case::after {
    content: "";
    position: absolute;
    top: 30%;
    right: -2.4%;
    width: 2.6%;
    height: 14%;
    border-radius: 0 4px 4px 0;
    background: #3a3b40;
}

.landing-case img {
    display: block;
    width: 100%;
    height: auto;
}

/* ── Il prezzo, presente ma in secondo piano; e il fondo ───────────────────── */
.landing-price {
    padding: clamp(2.5rem, 6vw, 4rem) 0;
    border-top: 1px solid var(--row-rule);
}

.landing-price .landing-wrap {
    display: grid;
    gap: 1.5rem;
    align-items: center;
}

@media (min-width: 820px) {
    .landing-price .landing-wrap { grid-template-columns: minmax(0, 1fr) auto; }
}

.landing-price p {
    max-width: 46rem;
    margin: 0.5rem 0 0;
    font-size: 0.97rem;
    color: var(--muted-500);
}

.landing-footer {
    padding: 2rem 0 3rem;
    border-top: 1px solid var(--row-rule);
    font-size: 0.85rem;
    color: var(--muted-700);
}

.landing-footer .landing-wrap {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.5rem 1.25rem;
}

.landing-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.1rem;
}

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

.landing-footer a:hover {
    color: var(--ink);
}

/* ── La pagina che non esiste ────────────────────────────────────────────────
 *
 * Il 404 come un punteggio dell'orologio: numerali enormi e serrati, il primo quattro nel blu e il
 * secondo nell'oro pieni, e al posto dello zero il marchio, che e' una pallina. Il marchio sta alto
 * quanto le cifre (0.72em, l'altezza di una cifra del font di sistema), cosi' la riga si legge
 * «404». Tutto in em: cambiando il corpo, la pallina segue.
 */
.not-found {
    max-width: 32rem;
    margin: 2rem auto 0;
    text-align: center;
}

.not-found-code {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.06em;
    margin: 0 0 1.5rem;
    font-size: clamp(6rem, 28vw, 10rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.04em;
    font-variant-numeric: tabular-nums;
}

.not-found-blue { color: var(--blue); }
.not-found-gold { color: var(--gold); }

.not-found .brand-mark {
    width: 0.72em;
    height: 0.72em;
    flex: none;
}

.not-found .text-secondary {
    margin-bottom: 2rem;
}
