/* Tema e struttura della dashboard — foglio condiviso da ogni pagina.
 *
 * ⚠️ Era inline in base.html, quindi **20 KB riscaricati a ogni pagina**:
 *    l'HTML ha `Cache-Control: no-store` (v4.38.5, per non servire versioni
 *    vecchie dopo un deploy), e finche' il CSS stava dentro l'HTML quella
 *    regola valeva anche per lui. Da /static invece il browser lo scarica
 *    una volta sola.
 *
 * ⚠️ Definisce le 15 variabili di tema (--accent, --bg, --text…) usate da
 *    **45 template**: il <link> deve restare **prima** del `block head`,
 *    altrimenti le pagine che le usano nel proprio CSS le troverebbero
 *    ancora indefinite. C'e' un test sull'ordine.
 */

/* ── Reset & base ─────────────────────────────────── */
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /* ── Tema "Carattere proprio" (v4.39.0) ───────────────
     *
     * Viola-notte caldo con accento ambra. I 15 nomi di variabile sono
     * **invariati**: 45 template li usano nel proprio CSS, quindi
     * cambiando qui i valori l'intera dashboard segue insieme.
     *
     * ⚠️⚠️ Ogni colore qui sotto e' verificato contro WCAG AA (4.5:1 sul
     *    testo normale): il tema precedente aveva **10 combinazioni su 24
     *    sotto la norma**, la peggiore a 2.71:1 — il blurple come testo su
     *    una card. Prima di cambiare un valore, rimisurare: e' il difetto
     *    che questo tema esiste per non riavere.
     *
     * ⚠️ `--accent` fa **sia da sfondo sia da testo**, ed e' per questo che
     *    l'ambra e' schiarita: su #1d1927 da' 7.4:1 come testo, e sotto il
     *    testo scuro di un pulsante regge lo stesso. Un accento che
     *    funziona solo da sfondo e' cio' che rendeva il blurple inusabile.
     */
    :root {
      --bg:        #14121a;   /* viola-notte, il fondo della pagina        */
      --sidebar:   #191622;   /* un gradino piu' chiaro del fondo          */
      --card:      #1d1927;   /* le schede si staccano dal fondo           */
      --card-alt:  #221e2c;   /* righe alterne, campi, stati premuti       */
      --accent:    #f0a868;   /* ambra: 7.4:1 su --card                    */
      --accent-h:  #f6c79b;   /* ambra schiarita per hover e focus         */
      --success:   #7ee0a0;
      --danger:    #f08b8d;
      --warn:      #f0c268;
      --text:      #e6e2ee;
      --text-muted:#9b93a8;   /* 4.9:1 su --card: leggibile davvero        */
      --border:    rgba(255,255,255,0.09);
      --sidebar-w: 220px;
      --header-h:  60px;
      --radius:    8px;
      /* ⚠️ usata da 8 template ma mai definita: lo sfondo dei loro campi
         cadeva su trasparente. Stesso valore dei campi generici. */
      --input-bg:  rgba(0,0,0,.25);

      /* ⚠️ Grigio piu' tenue delle etichette: **non** scendere sotto
       *    questo valore. Verificato sul fondo piu' chiaro (--card-alt),
       *    non solo su --card: a #888095 passava su --card (4.56) ma
       *    cadeva a 4.32 su --card-alt — il controllo va fatto su tutte
       *    e tre le superfici, o se ne salva una e se ne perde un'altra. */
      --text-faint:#8c8499;   /* 4.55 su --card-alt, 4.81 --card, 5.19 --bg */

      /* superficie di un pulsante ambra: il testo sopra e' scuro */
      --on-accent: #14121a;

      /* ── Spaziature ──────────────────────────────────────
       * ⚠️ Misurate prima di introdurle: le pagine usavano **5 valori di
       *    gap** (10/12/14/20/24) e **6 di padding**, scelti a occhio uno
       *    per volta — non una progressione, quindi due blocchi vicini
       *    respiravano in modo diverso senza una ragione.
       * ⚠️ La scala e' geometrica (×1,5 circa): i passi si distinguono a
       *    occhio. Una scala lineare (4/8/12/16/20) da' passi che a
       *    grandezze alte non si vedono, e si finisce per aggiungerne
       *    altri in mezzo — cioe' il disordine di prima. */
      --sp-1: 4px;    /* fra un'icona e la sua etichetta                 */
      --sp-2: 8px;    /* dentro un elemento                              */
      --sp-3: 12px;   /* fra elementi affini                             */
      --sp-4: 20px;   /* fra blocchi                                     */
      --sp-5: 32px;   /* fra sezioni                                     */

      /* ⚠️ Due raggi, con un criterio: il piccolo per i controlli
       *    (pulsanti, campi), il grande per le superfici (schede,
       *    riquadri). Prima 8px e 12px si alternavano sullo stesso tipo
       *    di contenitore senza una regola. */
      --radius-sm: 8px;
      --radius-lg: 12px;

      /* ── Movimento ───────────────────────────────────────
       * Durate e curve in un posto solo, cosi' tutta la dashboard si
       * muove allo stesso modo invece che una pagina per volta.
       * ⚠️ Azzerate in blocco sotto `prefers-reduced-motion`: chi ha
       *    chiesto meno movimento non deve inseguire le eccezioni. */
      --dur-1: .14s;   /* stati immediati: hover, colore                  */
      --dur-2: .22s;   /* movimento breve: sollevamenti, aperture         */
      --dur-3: .42s;   /* entrate in scena                                */
      --ease:  cubic-bezier(.2, .7, .3, 1);
      --ease-out: cubic-bezier(.16, 1, .3, 1);
    }

    html, body {
      height: 100%;
      font-family: 'Inter', sans-serif;
      background: var(--bg);
      color: var(--text);
      font-size: 14px;
      line-height: 1.5;
    }

    a { color: var(--accent); text-decoration: none; }
    a:hover { text-decoration: underline; }

    /* ── Layout ───────────────────────────────────────── */
    .layout {
      display: flex;
      min-height: 100vh;
    }

    /* ── Sidebar ──────────────────────────────────────── */
    .sidebar {
      width: var(--sidebar-w);
      background: var(--sidebar);
      display: flex;
      flex-direction: column;
      position: fixed;
      top: 0;
      left: 0;
      height: 100vh;
      z-index: 100;
      border-right: 1px solid var(--border);
      overflow-y: auto;
    }

    .sidebar-logo {
      padding: 20px 16px 16px;
      font-size: 18px;
      font-weight: 700;
      color: #fff;
      border-bottom: 1px solid var(--border);
      letter-spacing: -0.3px;
      user-select: none;
    }

    .sidebar-section {
      padding: 12px 8px 4px;
      font-size: 11px;
      font-weight: 600;
      letter-spacing: 0.8px;
      color: var(--text-muted);
      text-transform: uppercase;
    }

    .sidebar nav {
      padding: 8px;
      flex: 1;
    }

    /* ── Gruppi apribili ──────────────────────────────────────────
       <details>/<summary>: la sidebar resta navigabile anche senza JS
       (i gruppi sono aperti di default nell'HTML). Lo script aggiunge
       solo la memoria delle aperture. */
    /* Separatore fra gruppi: da aperti, senza uno stacco le voci di due
       gruppi diversi sembrano un elenco unico */
    .nav-group { margin-bottom: 4px; }
    .nav-group + .nav-group { border-top: 1px solid var(--border); padding-top: 4px; }

    .nav-group > summary {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 10px 12px 6px;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 1px;
      /* ⚠️ Più chiaro delle voci sotto (--text-muted): con lo stesso colore
         l'intestazione si confondeva con i link e i gruppi non si
         distinguevano l'uno dall'altro da aperti */
      color: #a8b0bd;
      text-transform: uppercase;
      cursor: pointer;
      user-select: none;
      list-style: none;
      border-radius: var(--radius);
      transition: color 0.15s, background 0.15s;
    }
    .nav-group > summary::-webkit-details-marker { display: none; }
    .nav-group > summary:hover { color: #fff; background: rgba(255,255,255,0.04); }

    /* ── Animazione apri/chiudi ────────────────────────────────────
       <details> non è animabile nativamente e `height: auto` non è
       interpolabile: la griglia da 0fr a 1fr è il modo di animare
       un'altezza sconosciuta senza misurarla in JavaScript.
       ⚠️ Serve `min-height: 0` sul figlio, altrimenti il contenuto
       impedisce alla riga di scendere sotto la propria altezza. */
    .nav-group-body {
      display: grid;
      grid-template-rows: 0fr;
      transition: grid-template-rows 0.24s ease;
    }
    .nav-group[open] > .nav-group-body { grid-template-rows: 1fr; }
    /* Durante la chiusura `open` è ancora presente (lo toglie il JS a fine
       animazione): questa regola vince e fa collassare la riga */
    .nav-group.is-closing[open] > .nav-group-body { grid-template-rows: 0fr; }
    .nav-group.is-closing[open] > .nav-group-body > .nav-group-inner {
      opacity: 0;
      transition: opacity 0.14s ease;
    }
    /* Anche la freccia deve tornare indietro insieme al resto */
    .nav-group.is-closing[open] > summary .chev { transform: rotate(0deg); }

    .nav-group-inner {
      overflow: hidden;
      min-height: 0;
      /* Le voci sfumano leggermente in ritardo rispetto all'altezza:
         chiudendo, sparisce prima il contenuto e poi lo spazio */
      opacity: 0;
      transition: opacity 0.18s ease;
    }
    .nav-group[open] > .nav-group-body > .nav-group-inner {
      opacity: 1;
      transition: opacity 0.24s ease 0.06s;
    }

    /* ⚠️ Chi ha chiesto meno animazioni al sistema non deve subirle */
    @media (prefers-reduced-motion: reduce) {
      .nav-group-body,
      .nav-group-inner,
      .nav-group[open] > .nav-group-body > .nav-group-inner,
      .nav-group > summary .chev { transition: none; }
    }

    /* Le voci di un gruppo rientrano rispetto al titolo, con una linea che
       le lega alla categoria: cosi' il rientro si legge come appartenenza
       invece che come disallineamento */
    .nav-group .nav-group-inner > .nav-link {
      padding-left: 22px;
      margin-left: 12px;
      border-left: 2px solid var(--border);
      border-radius: 0 var(--radius) var(--radius) 0;
    }
    .nav-group .nav-group-inner > .nav-link:hover  { border-left-color: rgba(255,255,255,0.18); }
    .nav-group .nav-group-inner > .nav-link.active { border-left-color: var(--accent); }

    .nav-group > summary .chev {
      margin-left: auto;
      font-size: 9px;
      transition: transform 0.18s ease;
      opacity: 0.7;
    }
    .nav-group[open] > summary .chev { transform: rotate(90deg); }

    /* Pallino sul gruppo chiuso che contiene la pagina corrente: senza,
       chiudendolo si perderebbe ogni traccia di dove ci si trova */
    .nav-group > summary .dot {
      width: 6px; height: 6px; border-radius: 50%;
      background: var(--accent);
      flex-shrink: 0;
      display: none;
    }
    .nav-group.has-active:not([open]) > summary .dot { display: block; }
    /* Il gruppo chiuso che contiene la pagina corrente deve risaltare *più*
       degli altri, non meno: con var(--text) risultava più scuro del titolo
       normale, che ora è #a8b0bd */
    .nav-group.has-active:not([open]) > summary { color: #fff; }

    .nav-link {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 9px 12px;
      border-radius: var(--radius);
      color: var(--text-muted);
      font-weight: 500;
      font-size: 14px;
      transition: background 0.15s, color 0.15s;
      text-decoration: none;
    }

    .nav-link:hover {
      background: rgba(255,255,255,0.06);
      color: var(--text);
      text-decoration: none;
    }

    .nav-link.active {
      background: var(--accent);
      color: var(--on-accent);
    }

    .nav-link .icon {
      font-size: 16px;
      width: 20px;
      text-align: center;
      flex-shrink: 0;
    }

    /* ── Sezioni da configurare ────────────────────────────────────
       ⚠️ Le voci NON cambiano posto: spostarle in un gruppo "da
       configurare" le renderebbe difficili da ritrovare, e su 6 dei 10
       server reali sarebbero 8-9 su 15 — le altre categorie
       resterebbero vuote. Qui si marca soltanto. */
    .nav-link[data-todo]::after {
      content: "";
      width: 6px; height: 6px;
      border-radius: 50%;
      background: var(--warn);
      margin-left: auto;
      flex-shrink: 0;
      opacity: 0.85;
    }
    /* Sulla voce attiva il pallino sparisce: sei già lì, e sul fondo
       blurple il giallo stona */
    .nav-link.active[data-todo]::after { display: none; }

    /* Contatore sul titolo del gruppo: dice quante voci lì dentro sono
       da configurare, utile soprattutto a gruppo chiuso */
    .nav-group > summary .todo-n {
      font-size: 10px;
      font-weight: 700;
      color: var(--warn);
      background: color-mix(in srgb, var(--warn) 12%, transparent);
      border-radius: 10px;
      padding: 1px 6px;
      flex-shrink: 0;
      letter-spacing: 0;
    }

    .sidebar-footer {
      padding: 12px;
      border-top: 1px solid var(--border);
    }

    .sidebar-footer a {
      display: flex;
      align-items: center;
      gap: 8px;
      color: var(--text-muted);
      font-size: 13px;
      padding: 8px 12px;
      border-radius: var(--radius);
      transition: background 0.15s, color 0.15s;
      text-decoration: none;
    }

    .sidebar-footer a:hover {
      background: color-mix(in srgb, var(--danger) 15%, transparent);
      color: var(--danger);
      text-decoration: none;
    }

    .sidebar-footer-links {
      display: flex;
      gap: 8px;
      padding: 8px 12px 4px;
      flex-wrap: wrap;
    }
    .sidebar-footer-links a {
      font-size: 11px;
      color: var(--text-muted);
      text-decoration: none;
      padding: 0;
      background: none;
      border-radius: 0;
      transition: color .15s;
    }
    .sidebar-footer-links a:hover {
      color: var(--text);
      background: none;
    }
    .sidebar-footer-links span {
      color: var(--border);
      font-size: 11px;
    }

    /* ── Main ─────────────────────────────────────────── */
    .main {
      margin-left: var(--sidebar-w);
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 100vh;
      /* ⚠️⚠️ `.main` e' un figlio flex, e un figlio flex ha
         min-width:auto: si allarga fino al contenuto piu' rigido che ha
         dentro (una tabella), spingendo in fuori l'intera colonna. Senza
         questa riga si scorre di lato tutta la pagina, testo compreso,
         invece del solo elemento largo — ed e' anche cio' che rende
         efficace `overflow-x` piu' in basso: finche' lo spazio arriva in
         eccesso da qui, nessun contenitore sottostante puo' contenere
         niente. Misurato su /privacy a 390px: .main andava a 554px. */
      min-width: 0;
    }

    /* ── Header ───────────────────────────────────────── */
    .header {
      height: var(--header-h);
      background: var(--sidebar);
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 24px;
      position: sticky;
      top: 0;
      z-index: 50;
    }

    .header-title {
      font-size: 16px;
      font-weight: 600;
      color: #fff;
    }

    .header-user {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .header-user img {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      border: 2px solid var(--accent);
      object-fit: cover;
    }

    .header-user span {
      font-size: 13px;
      font-weight: 500;
      color: var(--text);
    }

    /* ── Header right area ───────────────────────────── */
    .header-right {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    /* ── Server badge ─────────────────────────────────── */
    .server-badge {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      background: rgba(255,255,255,0.06);
      border: 1px solid var(--border);
      color: var(--text-muted);
      border-radius: 8px;
      padding: 5px 11px;
      font-size: 12px;
      font-weight: 500;
      text-decoration: none;
      transition: background .15s, border-color .15s, color .15s;
      white-space: nowrap;
      max-width: 180px;
      overflow: hidden;
    }
    .server-badge .server-icon {
      width: 20px;
      height: 20px;
      border-radius: 50%;
      object-fit: cover;
      flex-shrink: 0;
    }
    .server-badge .server-name {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .server-badge:hover {
      background: rgba(255,255,255,0.12);
      border-color: rgba(255,255,255,0.18);
      color: var(--text);
      text-decoration: none;
    }

    .btn-invite {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      background: color-mix(in srgb, var(--accent) 18%, transparent);
      border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
      color: #7289da;
      border-radius: 8px;
      padding: 6px 12px;
      font-size: 12px;
      font-weight: 600;
      text-decoration: none;
      transition: background .15s, border-color .15s;
      white-space: nowrap;
    }
    .btn-invite:hover {
      background: color-mix(in srgb, var(--accent) 30%, transparent);
      border-color: color-mix(in srgb, var(--accent) 60%, transparent);
      color: #fff;
    }

    /* Dropdown utente */
    .user-dropdown {
      position: relative;
    }
    .user-dropdown-trigger {
      display: flex;
      align-items: center;
      gap: 10px;
      cursor: pointer;
      padding: 4px 8px;
      border-radius: 8px;
      transition: background .15s;
      user-select: none;
    }
    .user-dropdown-trigger:hover {
      background: rgba(255,255,255,.07);
    }
    .user-dropdown-trigger .caret {
      font-size: 10px;
      color: var(--text-muted);
      transition: transform .15s;
    }
    .user-dropdown-trigger.open .caret {
      transform: rotate(180deg);
    }
    .user-dropdown-menu {
      display: none;
      position: absolute;
      top: calc(100% + 8px);
      right: 0;
      background: var(--sidebar);
      border: 1px solid var(--border);
      border-radius: 10px;
      min-width: 160px;
      box-shadow: 0 8px 24px rgba(0,0,0,.4);
      overflow: hidden;
      z-index: 100;
    }
    .user-dropdown-menu.open { display: block; }
    .user-dropdown-menu a {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 10px 14px;
      font-size: 13px;
      color: var(--text-muted);
      text-decoration: none;
      transition: background .12s, color .12s;
    }
    .user-dropdown-menu a:hover {
      background: color-mix(in srgb, var(--danger) 15%, transparent);
      color: var(--danger);
    }

    /* ── Content ──────────────────────────────────────── */
    .content {
      padding: 28px 32px;
      flex: 1;
      /* ⚠️ Stessa ragione di `.main`: e' il secondo figlio flex della
         catena, e basta che uno dei due conservi min-width:auto perche'
         il contenuto rigido continui ad allargare la colonna. */
      min-width: 0;

      /* ⚠️⚠️ Tetto unico alla larghezza delle pagine (v4.39.1).
       *
       * Prima ogni pagina aveva il suo: **13 valori diversi** fra 720 e
       * 1150px, e **18 pagine senza alcun limite** che si allargavano
       * quanto lo schermo. Passando da una all'altra il contenuto
       * "saltava" da un bordo all'altro.
       *
       * ⚠️ Il tetto sta su `.content`, non sui contenitori di pagina: una
       *    regola sola invece di 31, e le pagine che non ne avevano uno
       *    lo ereditano senza toccarle.
       * ⚠️ 1180px e' scelto sul contenuto **piu' largo che esiste**: la
       *    tabella a 6 colonne di /admin/stats e i 1150 di /raidstats.
       *    Sotto quel valore si comprimerebbero; sopra, non servirebbe a
       *    nessuno. Il testo NON si legge a questa larghezza — per quello
       *    c'e' `.leggibile` qui sotto, che e' l'altra meta' della
       *    correzione. */
      max-width: 1180px;
    }

    /* ⚠️⚠️ La misura di lettura, che e' una cosa diversa dalla larghezza
     * della pagina.
     *
     * Misurato sul carattere reale della dashboard: **6,64px per
     * carattere**, quindi 75 caratteri stanno in ~500px. Su uno schermo
     * 1920 le righe arrivavano a **157 caratteri** (moderazione) e 141
     * (comandi): oltre i ~90 l'occhio perde la riga tornando a capo.
     *
     * ⚠️ `ch` e non `px`: l'unita' segue il carattere, quindi la misura
     *    resta giusta se un domani cambia il font o la sua dimensione.
     * ⚠️⚠️ La regola e' **generale sui paragrafi**, non un elenco di
     *    classi. Elencarle non funziona: ci ho provato due volte e ogni
     *    giro ne saltavano fuori altre (`.form-hint` da sola conta 74
     *    usi, poi `.warn-box`, `.gb-note`, le voci di lista…). Una
     *    dimenticata resta a 180 caratteri, ed e' invisibile finche'
     *    qualcuno non apre quella pagina su un monitor largo.
     *
     * ⚠️ Si applica al **testo che scorre** (`p`, `li`, e i contenitori
     *    di sola descrizione), mai ai contenitori di struttura: una
     *    tabella o una griglia dentro un blocco da 66ch sarebbe
     *    strozzata. Per questo l'eccezione qui sotto e' altrettanto
     *    importante della regola.
     */
    .content p,
    .content li,
    .content .card > div:not([class]),
    .content .empty > span,
    .content .section-card-body > div:not([class]),
    .end-opt em, .end-opt span,
    .leggibile, .intro, .hint, .form-hint, .note,
    .sc-desc, .filter-desc, .rule-desc, .cmd-long, .cmd-brief,
    .page-sub, .empty-state, .warn-box, .gb-note, .legend, .err {
      /* ⚠️ `ch` si misura sul font dell'**elemento**: questi testi vanno
       *    da 11 a 14px, quindi lo stesso valore in `ch` da' larghezze
       *    diverse. 62ch e' quello che li tiene tutti sotto i ~90
       *    caratteri reali, misurato sul render. */
      max-width: 62ch;
    }

    /* ⚠️ Le eccezioni: qui il testo NON e' prosa da leggere riga dopo
     *    riga, e limitarlo spezzerebbe l'allineamento della struttura.
     * ⚠️ Fra queste i **log** e gli **esempi di comando**: una riga di
     *    log va letta intera e un comando spezzato a meta' non si puo'
     *    piu' copiare. Li' la riga lunga e' corretta, e la soluzione e'
     *    lo scorrimento orizzontale che hanno gia'. */
    .logbox, .logbox *,
    code, pre, .ex code,
    .content table p,
    .content table li,
    .content td, .content th,
    .h-strip p, .h-strip li,
    .kpi p, .kpi li,
    .ms-dropdown p, .ms-dropdown li,
    .cmp-list p, .cmp-list li,
    .mz-list p, .mz-list li {
      max-width: none;
    }

    /* ⚠️ Le pagine legali sono **documenti da leggere**, non pannelli: il
     * loro 760px non era una divergenza ma una scelta tipografica giusta,
     * e toglierlo le avrebbe portate a 1180 — 170 caratteri per riga su
     * un testo che si legge davvero dall'inizio alla fine. */
    .leggibile-doc { max-width: 80ch; margin: 0 auto; }

    .page-title {
      font-size: 22px;
      font-weight: 700;
      color: #fff;
      margin-bottom: 24px;
    }

    /* ⚠️⚠️ Il titolo di pagina era **ripetuto** (v4.39.1): compare gia'
     * nell'header in cima, e 17 pagine su 34 lo ristampavano nel corpo —
     * 13 identico, e **4 diverso**, che e' peggio: /tickets diceva
     * "Ticket" sopra e "Sistema Ticket" sotto, /raids/view "Partecipanti"
     * sopra e "Raid" sotto. Le altre 17 non lo avevano: non era una
     * scelta, era una divergenza.
     *
     * ⚠️ Si **nasconde**, non si rimuove dai template: molte pagine hanno
     *    il titolo dentro una riga flex insieme al pulsante "Crea…", e
     *    togliere l'elemento cambierebbe l'allineamento di quel pulsante
     *    in 13 file. Nascosto, la riga resta e il pulsante non si sposta.
     * ⚠️ `.page-title-solo` lo rimette visibile dove il titolo del corpo
     *    dice qualcosa che l'header non dice (il nome di un evento, di un
     *    raid): li' non e' una ripetizione. */
    .content .page-title:not(.page-title-solo) { display: none; }

    /* ── Cards ────────────────────────────────────────── */
    .card {
      background: var(--card);
      border-radius: var(--radius);
      border: 1px solid var(--border);
      padding: 20px 24px;
    }

    .card-title {
      font-size: 13px;
      font-weight: 600;
      color: var(--text-muted);
      text-transform: uppercase;
      letter-spacing: 0.6px;
      margin-bottom: 8px;
    }

    .card-value {
      font-size: 32px;
      font-weight: 700;
      color: #fff;
    }

    .stats-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
      gap: 16px;
      margin-bottom: 32px;
    }

    /* ── Alert banners ────────────────────────────────── */
    .alert {
      padding: 12px 16px;
      border-radius: var(--radius);
      font-size: 14px;
      margin-bottom: 20px;
      font-weight: 500;
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .alert-success {
      background: color-mix(in srgb, var(--success) 12%, transparent);
      border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
      color: var(--success);
    }

    .alert-error {
      background: color-mix(in srgb, var(--danger) 12%, transparent);
      border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
      color: var(--danger);
    }

    /* ── Movimento ─────────────────────────────────────
     *
     * Le animazioni della dashboard stanno **qui**, non copiate pagina
     * per pagina: sono l'ennesimo candidato a divergere in 8 versioni,
     * come il multi-select (v4.38.13).
     *
     * ⚠️⚠️ La regola che conta e' quella in fondo, sotto
     *    `prefers-reduced-motion`: e' **generale** (`*`), non un elenco
     *    di selettori. Un elenco va aggiornato ogni volta che si aggiunge
     *    un'animazione, e la prima dimenticata e' movimento addosso a chi
     *    aveva chiesto di non averne.
     *
     * ⚠️ Si anima solo `opacity` e `transform`: sono le due proprieta'
     *    che il browser compone senza rifare il layout. Animare `height`,
     *    `top` o `margin` fa ricalcolare la pagina a ogni fotogramma e
     *    sui telefoni si vede.
     */

    @keyframes dodo-entra {
      from { opacity: 0; transform: translateY(10px); }
      to   { opacity: 1; transform: none; }
    }
    @keyframes dodo-sfuma {
      from { opacity: 0; }
      to   { opacity: 1; }
    }
    @keyframes dodo-cresce {
      from { transform: scaleX(0); }
      to   { transform: scaleX(1); }
    }
    @keyframes dodo-pulsa {
      0%, 100% { opacity: 1; }
      50%      { opacity: .4; }
    }

    /* L'entrata in scena dei blocchi di una pagina. */
    .anima-entra { animation: dodo-entra var(--dur-3) var(--ease) both; }
    .anima-sfuma { animation: dodo-sfuma var(--dur-3) var(--ease) both; }

    /* Una barra che si riempie da sinistra (percentuali, capienza raid).
       ⚠️ Vuole `transform-origin: left`, o cresce dal centro. */
    .anima-barra {
      animation: dodo-cresce .7s var(--ease-out) both;
      transform-origin: left;
    }

    /* Il pallino di uno stato "in diretta" (bot online, live Twitch). */
    .anima-pulsa { animation: dodo-pulsa 2.2s ease-in-out infinite; }

    /* Scala i ritardi di una lista, cosi' le voci entrano una dopo
       l'altra invece che tutte insieme.
       ⚠️⚠️ I figli devono avere **anche loro** un'animazione, o il ritardo
          non ritarda niente: `animation-delay` da solo non anima. Per
          questo la classe la assegna ai figli qui sotto invece di
          affidarsi a quella del contenitore — errore commesso davvero
          mettendo `anima-entra anima-scala` sullo stesso elemento.
       ⚠️ Si ferma a 8: oltre, l'ultima voce aspetterebbe piu' di mezzo
          secondo e l'effetto diventa attesa invece che movimento. */
    .anima-scala > * { animation: dodo-entra var(--dur-3) var(--ease) both; }
    .anima-scala > *:nth-child(1) { animation-delay: .00s; }
    .anima-scala > *:nth-child(2) { animation-delay: .04s; }
    .anima-scala > *:nth-child(3) { animation-delay: .08s; }
    .anima-scala > *:nth-child(4) { animation-delay: .12s; }
    .anima-scala > *:nth-child(5) { animation-delay: .16s; }
    .anima-scala > *:nth-child(6) { animation-delay: .20s; }
    .anima-scala > *:nth-child(7) { animation-delay: .24s; }
    .anima-scala > *:nth-child(n+8) { animation-delay: .28s; }

    /* Una scheda che risponde al passaggio del mouse.
       ⚠️ Solo sui puntatori fini: su un touch screen `:hover` resta
          attaccato dopo il tocco e la scheda rimane sollevata. */
    @media (hover: hover) and (pointer: fine) {
      .alza {
        transition: transform var(--dur-2) var(--ease),
                    box-shadow var(--dur-2) var(--ease),
                    border-color var(--dur-2) var(--ease);
      }
      .alza:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 26px rgba(0,0,0,.34);
        border-color: rgba(240,168,104,.28);
      }
    }

    /* ⚠️⚠️ L'indicatore di focus da tastiera: prima di questo blocco la
     *    dashboard non ne aveva **nessuno** (0 `:focus-visible` in tutto
     *    il foglio, e un `outline: none`), quindi navigandola da tastiera
     *    non si sapeva dove si fosse.
     * ⚠️ `:focus-visible` e non `:focus`: col secondo l'anello comparirebbe
     *    anche a ogni clic del mouse, ed e' il motivo per cui in giro viene
     *    spento con `outline: none` — che e' come e' sparito qui. */
    :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
      border-radius: 4px;
    }

    /* ── Tables ───────────────────────────────────────── */
    .table-wrap {
      overflow-x: auto;
      border-radius: var(--radius);
      border: 1px solid var(--border);
    }

    /* Solo lo scorrimento, senza bordo ne' raggio: per le tabelle che
       stanno gia' dentro una .card o un .panel, dove .table-wrap
       disegnerebbe un secondo bordo dentro il primo.
       ⚠️ min-width:0 e' necessario quanto overflow-x: un figlio flex o
       grid ha min-width:auto e si allarga fino al contenuto, quindi
       senza questa riga la tabella spinge il contenitore invece di
       scorrere — che e' il difetto osservato su /privacy. */
    .table-scroll {
      overflow-x: auto;
      min-width: 0;
    }

    table {
      width: 100%;
      border-collapse: collapse;
    }

    thead th {
      background: var(--card);
      color: var(--text-muted);
      font-size: 11px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.6px;
      padding: 10px 16px;
      text-align: left;
      border-bottom: 1px solid var(--border);
    }

    tbody tr {
      border-bottom: 1px solid var(--border);
      transition: background 0.1s;
    }

    tbody tr:last-child { border-bottom: none; }

    tbody tr:hover { background: rgba(255,255,255,0.03); }

    tbody td {
      padding: 11px 16px;
      color: var(--text);
      font-size: 14px;
    }

    /* ── Badges ───────────────────────────────────────── */
    .badge {
      display: inline-block;
      padding: 3px 10px;
      border-radius: 20px;
      font-size: 12px;
      font-weight: 600;
      text-transform: capitalize;
    }

    .badge-raid {
      background: rgba(155,89,182,0.2);
      color: #b19cd9;
      border: 1px solid rgba(155,89,182,0.35);
    }

    .badge-evento {
      background: color-mix(in srgb, var(--success) 15%, transparent);
      color: #57f287;
      border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
    }

    .badge-on {
      background: color-mix(in srgb, var(--success) 15%, transparent);
      color: #57f287;
      border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
    }

    .badge-off {
      background: color-mix(in srgb, var(--danger) 12%, transparent);
      color: var(--danger);
      border: 1px solid color-mix(in srgb, var(--danger) 25%, transparent);
    }

    /* ── Forms ────────────────────────────────────────── */
    .form-group {
      margin-bottom: 18px;
    }

    label {
      display: block;
      font-size: 13px;
      font-weight: 600;
      color: var(--text);
      margin-bottom: 6px;
    }

    .form-hint {
      font-size: 12px;
      color: var(--text-muted);
      margin-top: 4px;
    }

    input[type="text"],
    input[type="number"],
    input[type="url"],
    input[type="color"],
    textarea,
    select {
      width: 100%;
      padding: 10px 12px;
      background: rgba(0,0,0,0.25);
      border: 1px solid rgba(255,255,255,0.12);
      border-radius: var(--radius);
      color: var(--text);
      font-family: inherit;
      font-size: 14px;
      outline: none;
      transition: border-color 0.15s;
    }

    input[type="text"]:focus,
    input[type="number"]:focus,
    input[type="url"]:focus,
    textarea:focus,
    select:focus {
      border-color: var(--accent);
      background: rgba(0,0,0,0.35);
    }

    textarea { resize: vertical; min-height: 90px; }

    /* ── Riquadri di sezione e menu dei canali (v4.54.1) ─────────────────
       ⚠️ Erano copiati in 10 template in 2-3 versioni diverse, e 4 pagine
       (storico, moderazione, statistiche raid, ticket) usavano .section-card
       SENZA alcuna regola: riquadri senza sfondo ne' bordo, con .alza che
       sollevava un riquadro invisibile. Una copia sola, qui.
       Le pagine che differiscono (Impostazioni) lo fanno con regole
       limitate al proprio contenitore, non ridefinendo queste. */
    .section-card {
      background: var(--card); border: 1px solid var(--border);
      border-radius: 12px; overflow: hidden; margin-bottom: 20px;
    }
    .section-card:last-child { margin-bottom: 0; }
    /* font-weight/size servono alle intestazioni di solo testo; quelle con
       h3 e p non ne risentono, perche' hanno dimensioni proprie */
    .section-card-header {
      padding: 16px 22px; border-bottom: 1px solid var(--border);
      display: flex; align-items: center; gap: 12px;
      font-weight: 600; font-size: 15px;
    }
    .section-card-header h3 { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
    .section-card-header p  { font-size: 12px; font-weight: 400; color: var(--text-muted); line-height: 1.5; }
    .section-card-body { padding: 20px 22px; }

    /* ⚠️ padding-right lascia spazio alla freccia: con 12px un nome di
       canale lungo le finiva sopra */
    .channel-select {
      -webkit-appearance: none; appearance: none;
      background-color: var(--input-bg);
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23aaa' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
      background-repeat: no-repeat; background-position: right 12px center;
      border: 1px solid var(--border); border-radius: var(--radius);
      padding: 10px 36px 10px 12px;
      font-family: inherit; cursor: pointer;
      transition: border-color var(--dur-1, .15s);
    }
    .channel-select:focus { border-color: var(--accent); outline: none; }
    .channel-select option { background: var(--bg); color: var(--text); }
    .channel-select optgroup {
      color: var(--text-muted); font-size: 12px; font-weight: 600; text-transform: uppercase;
    }

    /* ── Color input row ──────────────────────────────── */
    .color-row {
      display: flex;
      gap: 10px;
      align-items: center;
    }

    .color-row input[type="color"] {
      width: 46px;
      height: 40px;
      padding: 2px 4px;
      cursor: pointer;
      flex-shrink: 0;
    }

    .color-row input[type="text"] {
      flex: 1;
    }

    /* ── Toggle switch ────────────────────────────────── */
    .toggle-row {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 18px;
    }

    .toggle-label {
      font-size: 14px;
      font-weight: 500;
      color: var(--text);
      cursor: pointer;
      user-select: none;
    }

    .toggle {
      position: relative;
      display: inline-block;
      width: 44px;
      height: 24px;
      flex-shrink: 0;
    }

    .toggle input { opacity: 0; width: 0; height: 0; }

    .slider {
      position: absolute;
      cursor: pointer;
      top: 0; left: 0; right: 0; bottom: 0;
      background: rgba(255,255,255,0.15);
      border-radius: 24px;
      transition: background 0.2s;
    }

    .slider::before {
      position: absolute;
      content: "";
      height: 18px;
      width: 18px;
      left: 3px;
      bottom: 3px;
      background: #fff;
      border-radius: 50%;
      transition: transform 0.2s;
    }

    .toggle input:checked + .slider {
      background: var(--accent);
    }

    .toggle input:checked + .slider::before {
      transform: translateX(20px);
    }

    /* ── Buttons ──────────────────────────────────────── */
    .btn {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 10px 20px;
      border-radius: var(--radius);
      font-family: inherit;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
      border: none;
      transition: background 0.15s, opacity 0.15s;
    }

    .btn:hover { opacity: 0.88; }

    .btn-primary {
      background: var(--accent);
      color: var(--on-accent);
    }

    .btn-danger {
      background: var(--danger);
      color: var(--on-accent);
      padding: 7px 14px;
      font-size: 13px;
    }

    .btn-sm { padding: 6px 12px; font-size: 13px; }

    .btn-secondary {
      background: rgba(255,255,255,0.08);
      color: var(--text);
      border: 1px solid var(--border);
    }
    .btn-secondary:hover { background: rgba(255,255,255,0.13); }

    /* ── Responsive ───────────────────────────────────── */
    @media (max-width: 768px) {
      /* ⚠️⚠️ La sidebar qui sotto diventa `width: 100%` e
         `position: relative`, ma `.layout` restava `display:flex` **in
         riga**: sidebar e contenuto finivano affiancati, con la sidebar
         che occupa gia' tutta la larghezza e `.main` spinto oltre il
         bordo destro. Da li' in giu' ogni contenuto rigido (una tabella)
         allargava il documento. Misurato su /privacy a 390px: si scorreva
         fino a 554px, con `.main` che partiva da left:375. */
      .layout { flex-direction: column; }

      .sidebar {
        width: 100%;
        height: auto;
        position: relative;
        flex-direction: row;
        flex-wrap: wrap;
        border-right: none;
        border-bottom: 1px solid var(--border);
      }

      .sidebar-logo { padding: 12px 16px; border-bottom: none; }

      .sidebar nav {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 4px;
        padding: 8px;
        flex: 1;
      }

      .sidebar-footer { display: none; }

      /* ⚠️ L'header e' un flex in riga con altezza fissa: i tre blocchi a
         destra (nome server, "Aggiungi bot", menu utente) non hanno dove
         andare e sommati facevano 437px su 390 di schermo, sbordando su
         5 pagine su 7. Qui li si lascia comprimere e andare a capo invece
         di spingere. ⚠️ `min-width: 0` sui figli e' indispensabile: un
         figlio flex non scende sotto la propria larghezza di contenuto,
         quindi senza, `flex-wrap` da solo non basta. */
      .header {
        height: auto;
        min-height: var(--header-h);
        flex-wrap: wrap;
        gap: 8px;
        padding: 8px 16px;
      }

      .header-title,
      .header-right { min-width: 0; }

      /* il nome del server si tronca invece di allargare la riga */
      .server-badge { max-width: 40vw; }

      .main { margin-left: 0; }

      .content { padding: 16px; }

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

    /* ── Meno movimento, su richiesta ──────────────────
     *
     * ⚠️⚠️ Deliberatamente **generale** (`*`) e in fondo al foglio, cosi'
     *    vince su tutto: un elenco di selettori va aggiornato a ogni
     *    animazione nuova, e la prima che ci si dimentica e' movimento
     *    addosso a chi ha chiesto di non averne. Vale anche per le
     *    animazioni scritte nel CSS delle singole pagine.
     *
     * ⚠️ `animation: none` e non `animation-duration: 0s`: con la seconda
     *    un'animazione `both` resterebbe bloccata sul primo fotogramma —
     *    cioe' `opacity: 0`, contenuto invisibile. Qui invece gli elementi
     *    compaiono e basta.
     *
     * ⚠️ `scroll-behavior: auto` incluso: uno scorrimento animato e'
     *    movimento quanto una transizione.
     */
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        animation: none !important;
        transition: none !important;
        scroll-behavior: auto !important;
      }
      /* la scheda non si solleva piu', ma resta il segnale del passaggio */
      .alza:hover { transform: none; }
    }
