  :root{
    /* Sito sempre scuro (nessun tema chiaro): senza questa dichiarazione i
       controlli nativi del browser (menu a tendina dei <select> come "Profili
       di Configurazione", scrollbar, ecc.) restano bianchi di default anche se
       la casella chiusa è già stilizzata scura. */
    color-scheme: dark;
    --bg: #000000;
    --bg-panel: #100918;
    --bg-panel-2: #150C20;
    --blue: #A855F7;
    --red: #7C1FD4;
    --ink: #F1E7FF;
    --muted: #B6A0CF;
    --line: rgba(214,190,245,0.08);
    --radius: 14px;
    /* Rosso vero, per le azioni che distruggono qualcosa. Serve perché --red
       qui sopra, nonostante il nome, è il viola scuro del marchio (#7C1FD4):
       va benissimo per un accento, ma un pulsante "Elimina" di quel colore
       non si distingue da uno qualsiasi degli altri. Stesso rosso già usato
       dalla pagina di stato per i disservizi (--state-down). */
    --danger: #EF4444;
    --danger-soft: rgba(239,68,68,0.12);
  }
  *{ box-sizing: border-box; margin:0; padding:0; }

  /* Barra di scorrimento, ovunque. Prima era stilizzata solo dentro qualche
     componente (menu azioni, lista voci TTS, griglia regali...): tutto il
     resto — la pagina, la barra laterale della dashboard, ogni pannello che
     scorre — mostrava quella grigia di sistema, che su una pagina nera si
     legge come un pezzo di un'altra interfaccia incollato sopra la nostra.
     Le regole per componente restano dove sono: sono le stesse dichiarazioni,
     e sovrascriverle non cambierebbe niente.

     Servono due sintassi, e vanno tenute SEPARATE per browser — non messe una
     sotto l'altra sperando che ognuno prenda la sua. Chromium supporta ormai
     entrambe, e quando trova `scrollbar-color` disegna la scrollbar standard
     di sistema (su Windows: quella con le due frecce alle estremità)
     ignorando del tutto le regole `::-webkit-scrollbar`. Messe insieme, il
     risultato era una barra viola ma con le frecce grigie ancora lì, e nessun
     modo di toglierle.
     Quindi: `@supports not selector(::-webkit-scrollbar)` è vero SOLO dove le
     pseudo-classi WebKit non esistono, cioè Firefox — che riceve lo standard.
     Chrome/Edge/Safari saltano quel blocco e usano le regole WebKit qui
     sotto, dove le frecce si possono davvero nascondere.

     Il pollice ha un bordo trasparente con background-clip: padding-box, così
     il colore riempie solo la parte interna: sembra più sottile del canale in
     cui scorre, senza toccarne i bordi. */
  @supports not selector(::-webkit-scrollbar){
    *{ scrollbar-width: thin; scrollbar-color: rgba(185,107,250,0.45) transparent; }
  }
  ::-webkit-scrollbar{ width: 10px; height: 10px; }
  ::-webkit-scrollbar-track{ background: transparent; }
  /* Le due frecce alle estremità: restano grigie di sistema anche col resto
     stilizzato, e su una barra sottile e arrotondata stonano più della barra
     stessa. Tolte: si scorre con rotellina, trascinamento o tastiera, non
     cliccando una freccia da tre pixel. */
  ::-webkit-scrollbar-button{ display: none; width: 0; height: 0; }
  ::-webkit-scrollbar-thumb{
    background: rgba(185,107,250,0.45);
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: padding-box;
  }
  ::-webkit-scrollbar-thumb:hover{
    background: rgba(185,107,250,0.7);
    background-clip: padding-box;
  }
  /* Quadratino in basso a destra quando una zona scorre in entrambe le
     direzioni (es. una tabella larga dentro un pannello): senza questa riga
     resta grigio pieno, l'unico pezzo di scrollbar di sistema ancora visibile. */
  ::-webkit-scrollbar-corner{ background: transparent; }

  html{ scroll-behavior: smooth; }
  body{
    background: var(--bg);
    color: var(--ink);
    font-family: 'Nunito Sans', sans-serif;
    line-height: 1.5;
    overflow-x: hidden;
  }
  h1,h2,h3, .display{
    font-family: 'Baloo 2', sans-serif;
    font-weight: 700;
    letter-spacing: -0.01em;
  }
  .mono{ font-family: 'JetBrains Mono', monospace; }
  a{ color: inherit; text-decoration:none; }
  .wrap{ max-width: 1160px; margin: 0 auto; padding: 0 28px; }
  @media (max-width: 420px){ .wrap{ padding: 0 18px; } }
  ::selection{ background: var(--blue); color: #0E0518; }

  /* focus visibility */
  a:focus-visible, button:focus-visible{
    outline: 2px solid var(--blue);
    outline-offset: 3px;
  }

  @media (prefers-reduced-motion: reduce){
    *{ animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  }

  /* ---------- NAV ---------- */
  header{
    position: sticky; top:0; z-index: 50;
    background: rgba(14,6,23,0.82);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line);
  }
  header nav{
    display:flex; align-items:center; justify-content:space-between;
    padding: 18px 28px;
    max-width: 1160px; margin: 0 auto;
  }
  .logo{
    display:flex; align-items:center; gap:10px;
    font-family:'Baloo 2'; font-weight:700; font-size: 20px;
  }
  .logo-mark{
    width: auto; height:32px; border-radius:0;
    object-fit: contain;
    display:inline-block;
    transition: transform .2s ease;
  }
  .logo:hover .logo-mark{ transform: scale(1.06); }
  .nav-links{ display:flex; gap: 32px; align-items:center; }
  .nav-links a{ color: var(--muted); font-size: 14.5px; font-weight:500; transition: color .2s; }
  .nav-links a:hover{ color: var(--ink); }
  .nav-cta{
    background: var(--blue); color: #F1E7FF !important;
    padding: 10px 18px; border-radius: 999px; font-weight:600; font-size:14px;
    display:inline-block; transition: box-shadow .2s ease, transform .15s ease;
    box-shadow: 0 0 18px rgba(168,85,247,0.35);
  }
  .nav-cta:hover{
    box-shadow: 0 0 30px rgba(168,85,247,0.55);
    transform: translateY(-1px);
  }
  @media (max-width: 760px){ .nav-links{ display:none; } }

  /* ---------- MOBILE NAV TOGGLE (JS-driven) ---------- */
  .nav-toggle{
    display:none;
    background: transparent; border: 1px solid var(--line); color: var(--ink);
    width: 38px; height: 38px; border-radius: 8px; font-size: 16px; cursor: pointer;
    transition: border-color .2s ease, transform .2s ease;
  }
  .nav-toggle:hover{ border-color: var(--blue); transform: translateY(-2px); }
  @media (max-width: 760px){
    .nav-toggle{ display:inline-flex; align-items:center; justify-content:center; order: 2; }
    .nav-right{ order: 3; }
    .nav-links{
      display: none;
      position: absolute; top: 100%; left: 0; right: 0;
      background: var(--bg-panel);
      border-bottom: 1px solid var(--line);
      flex-direction: column; align-items: flex-start;
      padding: 18px 28px; gap: 18px;
    }
    .nav-links.open{ display: flex; }
    header nav{ position: relative; }
  }

  /* ---------- HERO ---------- */
  .hero{
    position: relative;
    padding: 96px 0 70px;
    border-bottom: 1px solid var(--line);
    overflow: hidden;
  }
  .hero-grid{
    display:grid; grid-template-columns: 1.05fr 0.95fr; gap: 56px; align-items:center;
  }
  @media (max-width: 900px){ .hero-grid{ grid-template-columns: 1fr; } }

  .eyebrow{
    display:inline-flex; align-items:center; gap:8px;
    font-family:'JetBrains Mono'; font-size: 12.5px; color: var(--blue);
    border: 1px solid rgba(185,107,250,0.35); background: rgba(185,107,250,0.06);
    padding: 6px 12px; border-radius: 999px; margin-bottom: 26px;
  }
  .eyebrow .dot{ width:6px; height:6px; border-radius:50%; background: var(--blue); animation: pulse 1.6s infinite; }
  @keyframes pulse{ 0%,100%{opacity:1;} 50%{opacity:.3;} }

  .hero h1{
    font-size: clamp(38px, 5.6vw, 62px);
    line-height: 1.04;
  }
  .hero h1 .hl-lime{ color: var(--blue); }
  .hero h1 .hl-mag{ color: var(--red); }

  .hero p.lead{
    margin-top: 22px; font-size: 17px; color: var(--muted); max-width: 480px;
  }
  .hero-ctas{ display:flex; gap:14px; margin-top: 34px; flex-wrap: wrap; }
  .btn{
    font-weight: 600; font-size: 14.5px; padding: 14px 24px; border-radius: 10px;
    border: none; cursor: pointer; display:inline-flex; align-items:center; gap:10px;
    transition: transform .15s ease, box-shadow .15s ease;
  }
  /* display:inline-flex sopra vince sempre sul display:none di default del
     browser per l'attributo hidden (una regola d'autore batte sempre quella
     dello user agent, a parità o meno di specificità): senza questa riga,
     un <button class="btn ..." hidden> impostato via JS (es. i pulsanti
     "Reset" overlay riservati agli admin) resterebbe visibile lo stesso.
     Stesso problema/stessa soluzione già applicata a .dash-nav-btn[hidden]. */
  .btn[hidden]{ display:none; }
  .btn:hover{ transform: translateY(-2px); }
  .btn-primary{ background: var(--blue); color: #F1E7FF; }
  .btn-primary:hover{ box-shadow: 0 8px 24px rgba(0,0,0,0.25), 0 0 24px rgba(168,85,247,0.4); }
  .btn-outline{ background: transparent; color: var(--ink); border: 1px solid var(--line); }
  .btn-outline:hover{ border-color: var(--red); box-shadow: 0 0 22px rgba(124,31,212,0.3); }

  .hero-meta{
    margin-top: 30px; display:flex; gap: 26px; color: var(--muted); font-size: 13px;
  }
  .hero-meta strong{ color: var(--ink); font-family:'Baloo 2'; }

  /* ---------- SIGNATURE: PARKOUR TRACK ---------- */
  .track-card{
    background: var(--bg-panel);
    border: 1px solid var(--line);
    border-radius: 20px;
    padding: 22px;
    position: relative;
  }
  .track-head{
    display:flex; justify-content:space-between; align-items:center;
    margin-bottom: 16px; padding: 0 6px;
  }
  .track-title{ font-size: 13px; color: var(--muted); font-family:'JetBrains Mono'; }
  .track-live{
    display:flex; align-items:center; gap:6px; font-family:'JetBrains Mono'; font-size: 12px; color: var(--red);
  }
  .live-dot{ width:7px; height:7px; border-radius:50%; background: var(--red); animation: pulse 1.2s infinite; }

  .track-body{
    position: relative;
    height: 420px;
    border-radius: 14px;
    background:
      repeating-linear-gradient(0deg, rgba(214,190,245,0.03) 0 1px, transparent 1px 42px),
      linear-gradient(180deg, #170B27 0%, #0E0518 100%);
    overflow: hidden;
    border: 1px solid var(--line);
  }
  .rail{
    position:absolute; left: 50%; top:0; bottom:0; width: 2px;
    background: repeating-linear-gradient(180deg, var(--line) 0 8px, transparent 8px 16px);
    transform: translateX(-50%);
  }
  .checkpoint{
    position:absolute; left: 50%; transform: translate(-50%,-50%);
    width: 34px; height:34px; border-radius: 8px;
    background: var(--bg-panel-2); border: 1px solid var(--line);
    display:flex; align-items:center; justify-content:center;
    font-family:'JetBrains Mono'; font-size: 11px; color: var(--muted);
    transition: transform .25s ease, border-color .25s ease, color .25s ease, box-shadow .25s ease;
    cursor: default;
  }
  .checkpoint:hover{
    transform: translate(-50%,-50%) scale(1.18) rotate(-4deg);
    border-color: var(--blue);
    color: var(--ink);
    box-shadow: 0 0 0 4px rgba(185,107,250,0.15);
  }
  .cp1{ top: 370px; } .cp2{ top: 260px; } .cp3{ top: 150px; } .cp4{ top: 40px; }

  .player{
    position:absolute; left: 50%; top: 370px;
    width: 22px; height: 22px; border-radius: 6px;
    background: var(--ink);
    transform: translate(-50%,-50%);
    box-shadow: 0 0 0 4px rgba(237,235,250,0.08);
    animation: climb 6s ease-in-out infinite;
  }
  @keyframes climb{
    0%{ top: 370px; }
    30%{ top: 300px; }
    45%{ top: 340px; }
    70%{ top: 190px; }
    85%{ top: 210px; }
    100%{ top: 60px; }
  }

  .bubble{
    position:absolute; font-family:'JetBrains Mono'; font-size: 11px; font-weight:600;
    padding: 4px 9px; border-radius: 999px; white-space: nowrap;
    opacity: 0; animation: rise 6s ease-in infinite;
  }
  .bubble.boost{ background: rgba(185,107,250,0.14); color: var(--blue); border: 1px solid rgba(185,107,250,0.4); left: 20%; }
  .bubble.penalty{ background: rgba(124,31,212,0.14); color: var(--red); border: 1px solid rgba(124,31,212,0.4); left: 62%; }
  .b1{ animation-delay: 0.3s; }
  .b2{ animation-delay: 2.1s; left: 68%; }
  .b3{ animation-delay: 3.6s; }
  .b4{ animation-delay: 4.8s; left: 24%; }
  @keyframes rise{
    0%{ bottom: -20px; opacity: 0; }
    10%{ opacity: 1; }
    75%{ opacity: 1; }
    100%{ bottom: 340px; opacity: 0; transform: translateY(-10px); }
  }

  .track-legend{
    display:flex; gap: 20px; margin-top: 14px; padding: 0 6px; font-size: 12.5px; color: var(--muted);
  }
  .legend-item{ display:flex; align-items:center; gap:7px; cursor: default; transition: color .2s ease; }
  .legend-item:hover{ color: var(--ink); }
  .legend-swatch{ width:10px; height:10px; border-radius:3px; transition: transform .25s ease, border-radius .25s ease; }
  .legend-item:hover .legend-swatch{ transform: scale(1.5); border-radius: 50%; }

  /* ---------- SECTION SHELL ---------- */
  section{ padding: 88px 0; border-bottom: 1px solid var(--line); }
  .section-tag{
    font-family:'JetBrains Mono'; font-size: 12.5px; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 14px;
  }
  .section-head{ max-width: 620px; margin-bottom: 56px; }
  .section-head h2{ font-size: clamp(28px, 3.4vw, 40px); }
  .section-head p{ margin-top: 14px; color: var(--muted); font-size: 16px; }

  /* ---------- COME FUNZIONA ---------- */
  .steps{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
  @media (max-width: 860px){ .steps{ grid-template-columns: 1fr; } }
  .step{
    background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 28px 24px;
    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  .step:hover{
    transform: translateY(-6px);
    border-color: var(--blue);
    box-shadow: 0 14px 30px rgba(185,107,250,0.14);
  }
  .step-num{ font-family:'JetBrains Mono'; color: var(--red); font-size: 13px; margin-bottom: 18px; transition: transform .25s ease; }
  .step:hover .step-num{ transform: translateX(4px); }
  .step h3{ font-size: 19px; margin-bottom: 10px; }
  .step p{ color: var(--muted); font-size: 14.5px; }
  .step-icons{ display:flex; gap:10px; margin-top:18px; }
  .pill{
    font-family:'JetBrains Mono'; font-size:11.5px; padding:5px 10px; border-radius:999px;
    border:1px solid var(--line); color: var(--muted);
    transition: transform .2s ease, border-color .2s ease, color .2s ease, background .2s ease;
    cursor: default;
  }
  .pill:hover{
    transform: translateY(-3px);
    border-color: var(--red);
    color: var(--ink);
    background: rgba(124,31,212,0.10);
  }

  /* ---------- GIOCHI ---------- */
  .games{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
  @media (max-width: 900px){ .games{ grid-template-columns: 1fr 1fr; } }
  @media (max-width: 600px){ .games{ grid-template-columns: 1fr; } }
  .game-card{
    border-radius: var(--radius); border: 1px solid var(--line); overflow:hidden;
    background: var(--bg-panel);
    transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  }
  .game-card:hover{
    border-color: rgba(185,107,250,0.45);
    transform: translateY(-6px);
    box-shadow: 0 16px 34px rgba(7,2,13,0.5);
  }
  .game-thumb{
    height: 140px; position:relative; overflow:hidden;
    background: linear-gradient(135deg, var(--g1), var(--g2));
  }
  .game-thumb::after{
    content:''; position:absolute; inset:0;
    background: repeating-linear-gradient(45deg, rgba(0,0,0,0.08) 0 10px, transparent 10px 20px);
    transition: transform .5s ease;
  }
  .game-card:hover .game-thumb::after{ transform: translate(10px,-10px); }
  .game-card:hover .game-thumb{ filter: saturate(1.3) brightness(1.08); }
  .game-body{ padding: 18px 20px 22px; }
  .game-diff{ font-family:'JetBrains Mono'; font-size:11px; color: var(--muted); margin-bottom:8px; }
  .game-body h3{ font-size: 17px; margin-bottom: 8px; }
  .game-body p{ font-size: 13.5px; color: var(--muted); }

  .games-platform-title{
    font-family:'JetBrains Mono'; font-size: 12.5px; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--muted); margin: 40px 0 18px; padding-top: 28px; border-top: 1px solid var(--line);
  }
  .games-platform-title:first-of-type{ margin-top: 0; padding-top: 0; border-top: none; }

  /* Tile piattaforma (Minecraft/Roblox) nel tab Giochi: solo titolo+immagine,
     apre l'elenco dei giochi di quella piattaforma. */
  /* Quattro per riga, non due: con due tile la pagina Giochi restava una
     colonnina stretta in alto a sinistra e mezzo schermo vuoto. Via anche il
     max-width, che era quello che teneva la griglia larga la metà del
     contenuto: senza, i riquadri riempiono la riga. */
  .game-platforms{ display:grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
  @media (max-width: 1080px){ .game-platforms{ grid-template-columns: repeat(2, 1fr); gap: 22px; } }
  @media (max-width: 600px){ .game-platforms{ grid-template-columns: 1fr; } }
  .game-platform-tile{
    display:block; width:100%; padding:0; border-radius: var(--radius); border: 1px solid var(--line);
    overflow:hidden; background: var(--bg-panel); cursor:pointer; text-align:left; font: inherit; color: inherit;
    transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  }
  .game-platform-tile:hover{
    border-color: rgba(185,107,250,0.45); transform: translateY(-6px); box-shadow: 0 16px 34px rgba(7,2,13,0.5);
  }
  .game-platform-tile .game-thumb{ height:160px; }
  .game-platform-tile h3{ margin:0; padding: 16px 20px 20px; font-size: 18px; }

  /* Immagini piattaforma (riusate sia in dashboard che in index.html). */
  .game-thumb-minecraft, .game-thumb-roblox, .game-thumb-gtav{ background-size: cover; background-position: center; }
  .game-thumb-minecraft{ background-image: url('../img/minecraft.png'); }
  .game-thumb-roblox{ background-image: url('../img/roblox.png'); }
  /* img/gtav.png: NON uno screenshot ufficiale del gioco (materiale protetto
     Rockstar/Take-Two) — solo una foto propria o un'immagine con licenza. Il
     gradiente resta come sfondo di riserva finché quel file non esiste. */
  .game-thumb-gtav{
    background-image:
      url('../img/gtav.png'),
      radial-gradient(120% 90% at 76% 14%, rgba(192,132,252,0.32), transparent 58%),
      linear-gradient(168deg, #3A1450 0%, #180B26 58%, #0B0512 100%);
  }

  /* Miniatura "Stack" (card "in arrivo" in home): stessa identica grafica
     disegnata in CSS del gioco su games.tikforge.net (vedi game/css/hub.css,
     .thumb-stack), non uno screenshot — così resta sempre allineata alla
     palette reale del gioco senza un file immagine da tenere sincronizzato. */
  .game-thumb-stack{ background: linear-gradient(168deg, #2A1140 0%, #150C20 58%, #0B0512 100%); }
  .thumb-stack{
    position:absolute; inset:0; display:flex; flex-direction:column;
    align-items:center; justify-content:flex-end; gap:3px; padding-bottom:24px;
  }
  .thumb-stack i{ display:block; height:13px; border-radius:3px; flex:none; box-shadow: 0 3px 0 rgba(0,0,0,0.28); }
  .thumb-stack i:nth-child(1){
    width:64px; background:#F0ABFC; margin-bottom:15px; transform:translateX(14px);
    box-shadow: 0 0 22px rgba(240,171,252,0.55), 0 3px 0 rgba(0,0,0,0.28);
  }
  .thumb-stack i:nth-child(2){ width:76px;  background:#C084FC; transform:translateX(-3px); }
  .thumb-stack i:nth-child(3){ width:92px;  background:#A855F7; transform:translateX(9px); }
  .thumb-stack i:nth-child(4){ width:104px; background:#9333EA; transform:translateX(-5px); }
  .thumb-stack i:nth-child(5){ width:118px; background:#7C3AED; transform:translateX(7px); }
  .thumb-stack i:nth-child(6){ width:128px; background:#6D28D9; }

  /* Miniatura "The Pull": stessa grafica CSS del hub giochi (game/css/hub.css,
     .thumb-pull) per la stessa ragione della torre di Stack qui sopra — la
     corda, il nodo al centro e le due teste colorate delle squadre. */
  .game-thumb-thepull{ background: linear-gradient(168deg, #2A1140 0%, #150C20 58%, #0B0512 100%); }
  .thumb-pull{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; }
  .thumb-pull::before{
    content:""; position:absolute; left:26px; right:26px; top:50%; height:6px;
    border-radius:99px; background:linear-gradient(180deg, #D9A860, #8A6430);
    box-shadow: 0 3px 0 rgba(0,0,0,0.28);
  }
  .thumb-pull i{ display:block; position:absolute; top:50%; border-radius:50%; }
  .thumb-pull i:nth-child(1){
    left:30px; width:34px; height:34px; transform:translateY(-50%);
    background:#38BDF8; box-shadow: 0 0 22px rgba(56,189,248,0.5);
  }
  .thumb-pull i:nth-child(2){
    left:50%; width:16px; height:16px; transform:translate(-50%,-50%);
    background:#F1E7FF; box-shadow: 0 0 14px rgba(241,231,255,0.7);
  }
  .thumb-pull i:nth-child(3){
    right:30px; width:34px; height:34px; transform:translateY(-50%);
    background:#F43F5E; box-shadow: 0 0 22px rgba(244,63,94,0.5);
  }

  /* Miniatura "Pop Shot": stessa grafica CSS del hub giochi (game/css/hub.css,
     .thumb-popshot) — tre palloncini in alto e la palla chiodata (stella a
     otto punte in clip-path) in basso. */
  .game-thumb-popshot{ background: linear-gradient(168deg, #2A1140 0%, #150C20 58%, #0B0512 100%); }
  .thumb-popshot{ position:absolute; inset:0; }
  .thumb-popshot i{ display:block; position:absolute; border-radius:50%; }
  .thumb-popshot i:nth-child(1){
    left:22%; top:22%; width:30px; height:33px;
    background:#A78BFA; box-shadow: 0 0 18px rgba(167,139,250,0.5);
  }
  .thumb-popshot i:nth-child(2){
    right:20%; top:30%; width:26px; height:29px;
    background:#38BDF8; box-shadow: 0 0 18px rgba(56,189,248,0.5);
  }
  .thumb-popshot i:nth-child(3){
    left:44%; top:14%; width:36px; height:39px;
    background:#FACC15; box-shadow: 0 0 24px rgba(250,204,21,0.55);
  }
  .thumb-popshot i:nth-child(4){
    left:50%; bottom:12%; width:26px; height:26px;
    transform:translateX(-50%);
    border-radius:0;
    background: radial-gradient(circle at 35% 30%, #F1F5F9, #94A3B8 55%, #475569);
    clip-path: polygon(50% 0%, 61% 33%, 93% 21%, 72% 50%, 93% 79%, 61% 67%, 50% 100%, 39% 67%, 7% 79%, 28% 50%, 7% 21%, 39% 33%);
  }

  /* Sezione "in arrivo": badge sopra la thumb + tile non cliccabile per chi non è admin. */
  .badge-coming-soon{
    position:absolute; top:10px; right:10px; z-index:1;
    background: rgba(7,2,13,0.75); color:#F1E7FF; border-color: rgba(214,190,245,0.25);
  }
  .game-platform-tile.is-locked{ cursor:not-allowed; }
  .game-platform-tile.is-locked:hover{ transform:none; box-shadow:none; border-color: var(--line); }
  .game-platform-tile.is-locked .game-thumb{ filter: grayscale(0.6) brightness(0.6); }


  /* ---------- PIATTAFORMA (pagine pubbliche minecraft.html / roblox.html: la
     libreria giochi di una singola piattaforma, aperta dai due blocchi
     "Scopri i minigiochi" / "Vertical Parkour" in home) ---------- */
  .platform-hero{ padding-bottom: 40px; }
  .platform-hero-back{
    display:inline-flex; align-items:center; gap:6px; color: var(--muted); font-size:13.5px;
    margin-bottom: 22px; transition: color .2s ease;
  }
  .platform-hero-back:hover{ color: var(--ink); }
  /* ---------- PAGINE PIATTAFORMA: una sezione per gioco ----------
     Prima ogni gioco era una riga di un accordion (<details>): per sapere
     cos'era bisognava aprirlo, uno alla volta. Su una pagina il cui lavoro è
     convincere che il gioco vale l'abbonamento, tenere il contenuto chiuso è
     il default sbagliato — e i giochi veri qui sono tre o quattro, non venti,
     quindi non c'è niente da riassumere.
     Ora ogni gioco è un blocco a piena larghezza con l'immagine grande da un
     lato e tutto il resto dall'altro. Si scorre e si legge, senza clic.
     I giochi "in arrivo" restano invece una griglia compatta in fondo: non
     hanno contenuto da mostrare, e affiancati si capisce a colpo d'occhio che
     sono un elenco di cose che verranno. */
  /* Card compatta della pagina piattaforma: immagine, nome, una riga di
     descrizione. Il resto — testo per esteso, cosa è incluso, collegamenti —
     sta sulla pagina dedicata al gioco, che è dove ha spazio per stare.
     Tutta la card è un link: a questa dimensione un pulsante dentro sarebbe
     un bersaglio piccolo dentro un bersaglio grande, e il bersaglio grande
     è quello che la gente prova a cliccare comunque. */
  .game-brief-grid{
    display:grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px;
  }
  .game-brief{
    display:flex; flex-direction:column;
    border: 1px solid var(--line); border-radius: var(--radius); overflow:hidden;
    background: var(--bg-panel); color: inherit; text-decoration: none;
    transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  }
  .game-brief:hover{
    border-color: rgba(185,107,250,0.45); transform: translateY(-4px);
    box-shadow: 0 16px 34px rgba(7,2,13,0.5);
  }
  /* position+overflow come .game-thumb qui sopra, e per la stessa ragione: le
     miniature disegnate col CSS (.thumb-pull, .thumb-popshot, .thumb-stack)
     sono figlie in position:absolute, e senza un antenato posizionato che le
     contenga si ancorano alla pagina — la corda di The Pull attraversava lo
     schermo e i palloncini di Pop Shot finivano sopra l'header. Le card con
     una copertina vera non se ne accorgono: l'immagine è uno sfondo. */
  .game-brief-media{
    height: 168px; background-size: cover; background-position: center;
    position: relative; overflow: hidden;
  }
  .game-brief-body{ padding: 18px 20px 20px; display:flex; flex-direction:column; flex:1; }
  .game-brief-body h3{ font-size: 18px; margin-bottom: 6px; }
  .game-brief-body p{ color: var(--muted); font-size: 13.5px; line-height: 1.6; }
  /* margin-top:auto: le descrizioni sono lunghe diverse, e senza questo la
     riga "Scopri di più" ballava da una card all'altra (stesso problema
     risolto per i pulsanti della dashboard). */
  .game-brief-more{
    margin-top: auto; padding-top: 16px;
    color: var(--blue); font-size: 13.5px; font-weight: 600;
  }
  /* Un gioco annunciato ma non ancora uscito sta nella stessa griglia degli
     altri, cosi' si vede che fa parte della libreria, ma la sua tessera e' un
     <div> e non un <a>: la pagina non esiste, il link darebbe 404. Senza
     is-locked erediterebbe il sollevamento all'hover, che promette un clic che
     non succede. */
  .game-brief.is-locked{ cursor: default; }
  .game-brief.is-locked:hover{
    border-color: var(--line); transform: none; box-shadow: none;
  }
  .game-brief-more.is-soon{ color: var(--dim); }
  /* Copertina segnaposto al posto della key art: stesso linguaggio dei thumb
     "In arrivo" del tab Giochi (gradiente viola scuro + righe diagonali), ma
     alta quanto un'immagine vera perche' sta in fila con quelle. */
  .game-brief-media-soon{
    position: relative; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(160deg, #241a38 0%, #150f24 55%, #0e0a18 100%);
    color: rgba(206,186,255,0.4);
  }
  .game-brief-media-soon::after{
    content:''; position:absolute; inset:0;
    background: repeating-linear-gradient(45deg, rgba(0,0,0,0.18) 0 10px, transparent 10px 20px);
  }
  /* position:relative tiene l'icona sopra le righe diagonali dell'::after. */
  .game-brief-media-soon svg{ width: 44px; height: 44px; position: relative; }

  /* ---------- PAGINA DEDICATA A UN GIOCO ---------- */
  .crumbs{
    display:flex; align-items:center; gap: 8px; flex-wrap: wrap;
    font-size: 13px; color: var(--muted); margin-bottom: 18px;
  }
  .crumbs a{ color: var(--muted); }
  .crumbs a:hover{ color: var(--ink); text-decoration: underline; }
  .crumbs span[aria-current]{ color: var(--ink); font-weight: 600; }
  .game-page-media{
    height: clamp(220px, 34vw, 380px); border-radius: var(--radius);
    background-size: cover; background-position: center;
    border: 1px solid var(--line); margin-bottom: 40px;
  }
  /* Scheda di un gioco la cui key art non c'è ancora. Senza questa classe
     .game-page-media resta un riquadro col solo bordo e niente dentro, perché
     tutto il suo aspetto arriva dal background-image del modificatore
     (.game-thumb-tntcube e simili). Righe diagonali come i thumb segnaposto del
     tab Giochi, ma su un gradiente di token che esistono davvero: quelli usano
     --g1/--g2, che nel foglio non sono mai stati definiti, quindi lì il
     gradiente non si applica per niente.

     Al momento nessuna pagina la usa — Survival, che l'aveva introdotta, ha
     ricevuto la sua copertina. Si tiene pronta per il prossimo gioco che nasce
     senza key art: si mette qui e si toglie il giorno che l'immagine arriva. */
  .game-page-media-placeholder{
    position: relative; overflow: hidden;
    background: linear-gradient(135deg, var(--bg-panel-2), var(--bg-panel));
  }
  .game-page-media-placeholder::after{
    content:''; position:absolute; inset:0;
    background: repeating-linear-gradient(45deg, rgba(0,0,0,0.18) 0 10px, transparent 10px 20px);
  }

  /* Il testo lungo a sinistra, la scheda con cosa è incluso e i pulsanti a
     destra: la seconda colonna è quella che si guarda per decidere, e messa
     in fila sotto ai paragrafi finirebbe fuori schermo. */
  .game-page-grid{
    display:grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 40px;
    align-items: start;
  }
  .game-page-main h2, .game-page-side h2, .game-page-more h2{
    font-size: 20px; margin-bottom: 14px;
  }
  .game-page-main p{ color: var(--muted); font-size: 15.5px; line-height: 1.75; }
  .game-page-main p + p{ margin-top: 14px; }
  .game-page-side{
    border: 1px solid var(--line); border-radius: 16px; padding: 24px;
    background: var(--bg-panel-2); position: sticky; top: 96px;
  }
  .game-page-side ul{
    list-style: none; padding: 0; margin: 0;
    display:flex; flex-direction:column; gap: 10px;
    color: var(--muted); font-size: 14px; line-height: 1.6;
  }
  .game-page-side ul li{ position:relative; padding-left: 24px; }
  .game-page-side ul li::before{
    content:''; position:absolute; left: 2px; top: 6px;
    width: 11px; height: 6px; border-left: 2px solid var(--blue); border-bottom: 2px solid var(--blue);
    transform: rotate(-45deg);
  }
  .game-page-actions{
    margin-top: 22px; padding-top: 22px; border-top: 1px solid var(--line);
    display:flex; flex-direction:column; align-items:flex-start; gap: 14px;
  }
  .game-page-actions .btn{ width:100%; justify-content:center; }
  .game-page-more{ margin-top: 56px; padding-top: 40px; border-top: 1px solid var(--line); }

  @media (max-width: 860px){
    /* Una colonna: la scheda laterale smette di essere "laterale" e va sotto,
       quindi sticky non ha più senso (resterebbe incollata a metà pagina). */
    .game-page-grid{ grid-template-columns: 1fr; gap: 30px; }
    .game-page-side{ position: static; }
  }

  .game-feature-list{ display:flex; flex-direction:column; gap: 26px; }
  .game-feature{
    display:grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 0; align-items: stretch;
    border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
    background: var(--bg-panel);
    transition: border-color .25s ease, box-shadow .25s ease;
  }
  .game-feature:hover{ border-color: rgba(185,107,250,0.4); box-shadow: 0 16px 34px rgba(7,2,13,0.45); }
  /* A blocchi alterni l'immagine passa a destra: dà un ritmo alla pagina
     invece di quattro sezioni identiche in fila. order funziona perché le due
     colonne della griglia sono figlie dirette. */
  .game-feature:nth-child(even) .game-feature-media{ order: 2; }
  .game-feature-media{
    position: relative; min-height: 300px;
    background-size: cover; background-position: center;
  }
  /* Sfumatura verso il pannello sul lato che tocca il testo: senza, il taglio
     netto fra foto e fondo scuro sembra un collage. */
  .game-feature-media::after{
    content:''; position:absolute; inset:0;
    background: linear-gradient(90deg, transparent 55%, rgba(11,4,16,0.55) 100%);
  }
  .game-feature:nth-child(even) .game-feature-media::after{
    background: linear-gradient(270deg, transparent 55%, rgba(11,4,16,0.55) 100%);
  }
  .game-feature-body{ padding: 32px 34px; display:flex; flex-direction:column; }
  .game-feature-body h3{ font-size: 24px; margin-bottom: 6px; }
  .game-feature-tag{ color: var(--blue); font-size: 14px; font-weight: 600; margin-bottom: 16px; }
  .game-feature-body p{ color: var(--muted); font-size: 14.5px; line-height: 1.7; }
  .game-feature-body p + p{ margin-top: 10px; }
  .game-feature-body ul{
    color: var(--muted); font-size: 14px; line-height: 1.6;
    margin: 16px 0 0; padding: 0; list-style: none;
    display:flex; flex-direction:column; gap: 8px;
  }
  /* Spunta al posto del pallino: sono cose incluse, non voci di un elenco
     qualsiasi. Disegnata col ::before invece che con un <svg> per ogni riga,
     così il markup generato resta leggibile. */
  .game-feature-body ul li{ position:relative; padding-left: 24px; }
  .game-feature-body ul li::before{
    content:''; position:absolute; left: 2px; top: 6px;
    width: 11px; height: 6px; border-left: 2px solid var(--blue); border-bottom: 2px solid var(--blue);
    transform: rotate(-45deg);
  }
  /* margin-top:auto tiene i pulsanti appoggiati al fondo del blocco: con
     descrizioni di lunghezza diversa, altrimenti ogni gioco li aveva a
     un'altezza sua. */
  .game-feature-actions{
    margin-top: auto; padding-top: 26px;
    display:flex; align-items:center; gap: 18px; flex-wrap: wrap;
  }

  /* Giochi in arrivo: griglia compatta, niente immagine né descrizione. */
  .game-soon-grid{
    display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px;
    margin-top: 26px;
  }
  .game-soon-card{
    display:flex; align-items:center; gap: 14px;
    border: 1px dashed var(--line); border-radius: 14px; padding: 16px 18px;
    background: var(--bg-panel-2);
  }
  .game-soon-card .game-thumb{ width: 54px; height: 54px; flex-shrink: 0; border-radius: 10px; }
  .game-soon-card h3{ font-size: 15px; margin-bottom: 3px; }
  .game-soon-card p{ color: var(--muted); font-size: 12.5px; line-height: 1.5; }

  @media (max-width: 860px){
    /* Sotto gli 860px le due colonne non stanno più: l'immagine va sopra e il
       testo sotto, e l'alternanza si spegne (con una colonna sola, order
       manderebbe la foto sotto al testo in metà dei blocchi). */
    .game-feature{ grid-template-columns: 1fr; }
    .game-feature:nth-child(even) .game-feature-media{ order: 0; }
    .game-feature-media{ min-height: 200px; }
    .game-feature-media::after,
    .game-feature:nth-child(even) .game-feature-media::after{
      background: linear-gradient(180deg, transparent 55%, rgba(11,4,16,0.55) 100%);
    }
    .game-feature-body{ padding: 26px 22px; }
    .game-feature-body h3{ font-size: 21px; }
  }


  .dash-back-btn{ margin-bottom: 18px; }

  /* Card TntCube dentro "Minecraft": l'intera card è cliccabile e porta alla
     pagina di configurazione (non solo il pulsante "Gioca ora"). */
  .game-card[data-open-config]:not(.locked){ cursor:pointer; }

  /* ---------- PREZZO ---------- */
  .price-wrap{ display:flex; justify-content:center; }
  .price-card{
    max-width: 460px; width:100%;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
    border: 1px solid rgba(185,107,250,0.3);
    border-radius: 20px; padding: 40px 36px;
    position: relative;
  }
  .price-card::before{
    content: 'UN SOLO PIANO'; position:absolute; top:-12px; left:36px;
    font-family:'JetBrains Mono'; font-size: 11px; letter-spacing:.08em;
    background: var(--blue); color: #0E0518; padding: 4px 10px; border-radius: 999px; font-weight:600;
  }
  .price-num{ display:flex; align-items:baseline; gap:8px; margin: 18px 0 6px; }
  .price-num .amount{ font-family:'Baloo 2'; font-size: 56px; font-weight:700; }
  .price-num .period{ color: var(--muted); font-size: 15px; }
  .price-card > p{ color: var(--muted); font-size: 14.5px; margin-bottom: 26px; }
  .price-feats{ list-style:none; display:flex; flex-direction:column; gap: 13px; margin-bottom: 30px; }
  .price-feats li{
    display:flex; gap: 10px; font-size: 14.5px; align-items:flex-start; cursor: default;
    transition: transform .18s ease; transform-origin: left center;
  }
  .price-feats li:hover{ transform: scale(1.035); }
  .check{ color: var(--blue); font-family:'JetBrains Mono'; flex-shrink:0; display:inline-block; transition: color .2s ease; }
  .price-feats li:hover .check{ color: var(--red); }
  .price-card .btn{ width: 100%; justify-content:center; background: var(--blue); color: #0E0518; }
  .price-card .btn:hover{ box-shadow: 0 0 26px rgba(185,107,250,0.4); }
  .price-fine{ margin-top: 16px; font-size: 12px; color: var(--muted); text-align:center; }

  /* Come .price-card ma senza il badge "UN SOLO PIANO" (::before): per liste di
     caratteristiche fuori dal contesto abbonamento, es. la pagina di un gioco. */
  .feature-card{
    max-width: 460px; width:100%;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
    border: 1px solid var(--line);
    border-radius: 20px; padding: 40px 36px;
  }
  .feature-card .btn{ width: 100%; justify-content:center; }

  /* ---------- FAQ ---------- */
  .faq-list{ max-width: 720px; }
  .faq-item{ border-bottom: 1px solid var(--line); padding: 22px 0; }
  .faq-q{
    display:flex; justify-content:space-between; align-items:center; cursor:pointer;
    font-family:'Baloo 2'; font-size: 16.5px; font-weight:600;
  }
  .faq-q .icon{ color: var(--muted); font-family:'JetBrains Mono'; transition: transform .2s; }
  .faq-item[open] .faq-q .icon{ transform: rotate(45deg); color: var(--red); }
  .faq-a{ margin-top: 12px; color: var(--muted); font-size: 14.5px; max-width: 600px; }
  summary::-webkit-details-marker{ display:none; }
  summary{ list-style:none; }

  /* ---------- FOOTER ---------- */
  footer{ padding: 48px 0 40px; }
  .footer-row{ display:flex; justify-content:space-between; align-items:center; flex-wrap: wrap; gap: 20px; }
  .footer-note{ color: var(--muted); font-size: 13px; max-width: 460px; }
  .footer-copy{ color: var(--muted); font-size: 12px; max-width: 460px; margin-top: 6px; opacity: .7; }
  .footer-links{ display:flex; gap: 24px; }
  .footer-links a{ color: var(--muted); font-size: 13.5px; }
  .footer-links a:hover{ color: var(--ink); }

  /* Footer a colonne (solo index.html): il footer-row semplice sopra resta
     invariato per le altre pagine (subscribe/login/ecc.). */
  .footer-cols{ display:grid; grid-template-columns: 1.3fr repeat(3, 1fr); gap: 32px; align-items:start; }
  @media (max-width: 760px){ .footer-cols{ grid-template-columns: 1fr 1fr; } }
  @media (max-width: 480px){ .footer-cols{ grid-template-columns: 1fr; } }
  .footer-col-title{
    font-family:'JetBrains Mono'; font-size: 11.5px; text-transform:uppercase;
    letter-spacing:.08em; color: var(--muted); margin-bottom: 16px;
  }
  .footer-col-links{ display:flex; flex-direction:column; gap: 12px; }
  .footer-col-links a{ color: var(--muted); font-size: 13.5px; }
  .footer-col-links a:hover{ color: var(--ink); }
  .footer-bottom{
    margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--line);
    display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap: 12px;
  }
  .footer-bottom .footer-copy{ margin-top:0; max-width:none; }
  .footer-social{ display:flex; gap: 16px; }
  .footer-social a{ color: var(--muted); font-size: 13px; }
  .footer-social a:hover{ color: var(--ink); }

  /* ---------- IN CIFRE ---------- */
  .stats-section{ padding: 56px 0; }
  .stats-row{ display:grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
  @media (max-width: 760px){ .stats-row{ grid-template-columns: repeat(2, 1fr); gap: 32px; } }
  .stat-block{ text-align:center; }
  .stat-block .stat-num{ font-family:'Baloo 2'; font-size: clamp(30px, 3.6vw, 44px); font-weight:700; }
  .stat-block .stat-label{
    margin-top:8px; color: var(--muted); font-size: 12.5px; font-family:'JetBrains Mono';
    text-transform:uppercase; letter-spacing:.05em;
  }

  /* ---------- FUNZIONALITÀ ---------- */
  .features-grid{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
  @media (max-width: 900px){ .features-grid{ grid-template-columns: 1fr 1fr; } }
  @media (max-width: 600px){ .features-grid{ grid-template-columns: 1fr; } }
  .feature-tile{
    background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 26px 24px; transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  .feature-tile:hover{
    transform: translateY(-6px); border-color: var(--blue);
    box-shadow: 0 14px 30px rgba(185,107,250,0.14);
  }
  .feature-icon{
    font-size:19px; margin-bottom:16px; display:inline-flex; width:44px; height:44px;
    align-items:center; justify-content:center; border-radius:12px; background: rgba(185,107,250,0.10);
  }
  .feature-tile h3{ font-size:17px; margin-bottom:8px; }
  .feature-tile p{ color: var(--muted); font-size:13.5px; }

  /* =================================================================
     SITO PUBBLICO — DESIGN 2026 (body.page-site)
     ------------------------------------------------------------------
     Rifacimento completo della parte pubblica: home, pagine piattaforma
     (minecraft/roblox), pagine auth, legali e di errore. Sostituisce il
     vecchio blocco "HOME: layout dedicato" + "REDESIGN CYBER GAMING",
     che era agganciato a body.page-home.

     Regola d'oro: tutto qui dentro è scoped a body.page-site. La
     dashboard (body.page-dashboard) e l'admin non vengono mai toccati,
     e nessuna classe usata dal JavaScript viene rimossa: i nomi che i
     vari script cercano (.nav-links, .js-auth-link, #nav-auth-link,
     #nav-subscribe-cta, .nav-btn-label, .nav-toggle, .faq-item, .hero,
     .hero-window, #page-loader, .lang-dropdown) restano tutti in piedi,
     solo ridisegnati.
     ================================================================= */

  body.page-site{
    /* Palette: viola unico su fondo quasi nero, niente più coppia
       rosso/blu. --blue e --red restano definite perché le regole
       globali condivise con la dashboard (.btn-primary, ::selection,
       .auth-link, ecc.) le leggono ancora. */
    --bg: #08060D;
    --bg-soft: #0B0812;
    --bg-panel: #100C18;
    --bg-panel-2: #15101F;
    --panel: #100C18;
    --panel-2: #15101F;
    --panel-3: #1B1526;
    --line: rgba(206,186,255,0.09);
    --line-2: rgba(206,186,255,0.17);
    --ink: #F4F0FB;
    --muted: #A69DBA;
    --dim: #7B7391;
    --violet: #8B5CF6;
    --violet-2: #A855F7;
    --violet-3: #C084FC;
    --blue: #8B5CF6;
    --red: #7C3AED;
    --radius: 16px;

    background:
      radial-gradient(900px 520px at 72% 2%, rgba(124,58,237,0.10), transparent 58%),
      var(--bg);
    background-attachment: fixed;
    color: var(--ink);
  }

  /* Contenitore unico del sito. Non ha bordo: nel mockup la cornice
     arrotondata visibile in alto è la sola barra di navigazione, che
     "galleggia". Tutto il resto della pagina (hero, striscia creator,
     card) si allinea al BORDO ESTERNO di quella barra, non al suo
     padding interno: per questo la larghezza utile la definisce lo
     shell e .wrap qui dentro non aggiunge padding proprio. */
  body.page-site .site-shell{
    position: relative;
    max-width: 1480px;
    margin: 0 auto;
    padding: 0 24px;
  }
  @media (max-width: 520px){ body.page-site .site-shell{ padding: 0 16px; } }

  /* ---------- HEADER ---------- */
  /* Barra arrotondata sospesa, bordata su tutti i lati. */
  body.page-site header{
    position: sticky; top: 14px; z-index: 60;
    margin-top: 16px;
    background: rgba(14,10,21,0.78);
    backdrop-filter: blur(18px) saturate(150%);
    border: 1px solid var(--line-2);
    border-radius: 22px;
  }

  body.page-site header nav{
    display: flex; align-items: center; gap: 22px;
    max-width: none; margin: 0; padding: 15px 28px;
  }

  body.page-site header .logo{ display: flex; align-items: center; gap: 11px; flex: none; }
  body.page-site header .logo-mark{
    display: block; width: auto; height: 34px; border-radius: 0; object-fit: contain;
    filter: drop-shadow(0 0 12px rgba(139,92,246,0.35));
    transition: transform .2s ease, filter .2s ease;
  }
  body.page-site header .logo:hover .logo-mark{
    transform: scale(1.05);
    filter: drop-shadow(0 0 18px rgba(168,85,247,0.55));
  }
  body.page-site header .logo-word{
    display: inline-block;
    font-family: 'Baloo 2', sans-serif; font-weight: 800; font-size: 19px;
    letter-spacing: .15em; text-transform: uppercase; color: var(--ink);
  }

  /* Voci centrali: il blocco si auto-centra fra logo e azioni. */
  body.page-site .nav-links{
    display: flex; align-items: center; gap: 10px;
    margin: 0 auto; position: static; padding: 0; background: none; border: none;
  }
  body.page-site .nav-links > a,
  body.page-site .nav-drop-btn{
    display: inline-flex; align-items: center; gap: 6px;
    padding: 9px 16px; border-radius: 10px;
    font-family: 'Nunito Sans', sans-serif; font-size: 15px; font-weight: 600;
    color: var(--muted); background: transparent; border: none; cursor: pointer;
    transition: color .18s ease, background .18s ease;
  }
  body.page-site .nav-links > a:hover,
  body.page-site .nav-drop-btn:hover{ color: var(--ink); background: rgba(206,186,255,0.06); }
  body.page-site .nav-links > a.nav-links-auth{ display: none; }

  /* ---------- MENU A TENDINA DELLA NAV ("Funzionalità", "Risorse") ----------
     Si aprono al passaggio del mouse e via tastiera (:focus-within); il
     click è gestito da js/nav-dropdown.js, che aggiunge .is-open. */
  body.page-site .nav-drop{ position: relative; }
  body.page-site .nav-chev{ width: 11px; height: 11px; opacity: .7; transition: transform .2s ease; }
  body.page-site .nav-drop:hover .nav-chev,
  body.page-site .nav-drop.is-open .nav-chev{ transform: rotate(180deg); }
  /* Ponte invisibile sui 12px fra il pulsante e il pannello (il "+ 12px" del
     top qui sotto). Quello stacco sta FUORI da .nav-drop, che è alto quanto
     il solo pulsante: scendendo col mouse verso una voce si attraversava una
     striscia in cui :hover non valeva più e il menu si chiudeva in faccia
     prima di poterlo raggiungere. Il ponte è largo come il pannello, non come
     il pulsante, altrimenti un movimento in diagonale verso una voce di bordo
     ne uscirebbe comunque di lato.
     Esiste SOLO a menu aperto: sempre presente, coprirebbe con una fascia
     invisibile di 320px quello che sta sotto la barra, rubando i click. */
  body.page-site .nav-drop::after{
    content: ""; position: absolute; z-index: 39;
    top: 100%; left: 50%; transform: translateX(-50%);
    width: 320px; height: 12px; display: none;
  }
  body.page-site .nav-drop:hover::after,
  body.page-site .nav-drop:focus-within::after,
  body.page-site .nav-drop.is-open::after{ display: block; }
  body.page-site .nav-drop-menu{
    position: absolute; z-index: 40; top: calc(100% + 12px); left: 50%;
    width: 320px; padding: 8px;
    transform: translateX(-50%) translateY(-8px);
    background: var(--panel); border: 1px solid var(--line-2); border-radius: 18px;
    box-shadow: 0 28px 64px rgba(0,0,0,0.62);
    opacity: 0; visibility: hidden;
    transition: opacity .18s ease, transform .18s ease, visibility .18s;
    /* Ritardo in CHIUSURA (in apertura è azzerato qui sotto): un'uscita di
       striscio dal pannello non lo fa sparire all'istante, c'è il tempo di
       rientrarci. Tenuto BASSO di proposito: a chiudere il buco fra pulsante
       e pannello ci pensa già il ponte qui sopra, questo serve solo contro lo
       scarto di un fotogramma, e più lungo si sente come menu che non se ne
       va. Niente "pointer-events: none" qui: bloccherebbe il mouse subito,
       rendendo il pannello vivo a vedersi ma morto al click proprio durante
       questo ritardo. A tenerlo non cliccabile da chiuso basta
       visibility: hidden, che è anche l'unica delle due proprietà che si può
       animare — quindi resta "visible" per tutta la tolleranza. */
    transition-delay: .12s;
  }
  body.page-site .nav-drop:hover .nav-drop-menu,
  body.page-site .nav-drop:focus-within .nav-drop-menu,
  body.page-site .nav-drop.is-open .nav-drop-menu{
    opacity: 1; visibility: visible;
    transform: translateX(-50%) translateY(0);
    transition-delay: 0s;
  }
  /* Passando da una tendina all'altra la precedente sparisce SUBITO, senza la
     tolleranza qui sopra: altrimenti per quei millisecondi restano aperte in
     due e i pannelli si sovrappongono. Il :has() sta sul contenitore perché
     serve guardare all'indietro: le tendine sono sorelle, e con "~" si
     raggiungono solo quelle che vengono dopo.
     Attenzione: vale solo quando il mouse è GIÀ su un'altra tendina. Nel
     tragitto fra le due non è sopra nessuna delle due, quindi la tolleranza
     torna valida ed è giusto così. */
  body.page-site .nav-links:has(.nav-drop:hover) .nav-drop:not(:hover) .nav-drop-menu{
    transition-delay: 0s;
  }
  /* Scelta una voce, il pannello se ne va anche se il mouse ci è ancora
     sopra. Senza questo restava aperto: js/nav-dropdown.js toglie .is-open,
     ma sulla home i link sono ancore interne, la pagina non cambia e il
     :hover continua a tenerlo visibile. La classe la mette e la toglie
     js/nav-dropdown.js. Deve stare DOPO le regole :hover: ha la loro stessa
     specificità, quindi vince solo per ordine. */
  body.page-site .nav-drop.is-dismissed .nav-drop-menu{
    opacity: 0; visibility: hidden; transition-delay: 0s;
    transform: translateX(-50%) translateY(-8px);
  }
  body.page-site .nav-drop-menu a{
    display: flex; align-items: flex-start; gap: 12px;
    padding: 11px 12px; border-radius: 12px;
    transition: background .16s ease;
  }
  body.page-site .nav-drop-menu a:hover{ background: rgba(139,92,246,0.13); }
  body.page-site .nav-drop-ico{
    width: 32px; height: 32px; border-radius: 10px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background-color: rgba(139,92,246,0.15); color: var(--violet-3);
    background-size: cover; background-position: center; overflow: hidden;
  }
  body.page-site .nav-drop-ico svg{ width: 16px; height: 16px; }
  body.page-site .nav-drop-menu strong{ display: block; font-size: 13.5px; font-weight: 700; color: var(--ink); }
  body.page-site .nav-drop-menu em{
    display: block; font-style: normal; font-size: 12px; line-height: 1.45;
    color: var(--dim); margin-top: 2px;
  }

  /* ---------- AZIONI A DESTRA ---------- */
  body.page-site .nav-right{ display: flex; align-items: center; gap: 10px; flex: none; }

  body.page-site .lang-dropdown-btn{
    border: none; background: transparent; padding: 8px 10px; border-radius: 10px;
    color: var(--muted); font-size: 14px; font-weight: 600; gap: 7px;
    transition: color .18s ease, background .18s ease;
  }
  body.page-site .lang-dropdown-btn svg{ width: 17px; height: 17px; }
  body.page-site .lang-dropdown-btn::after{ content: '▾'; font-size: 9px; opacity: .6; }
  body.page-site .lang-code{ font-size: 14px; font-weight: 700; letter-spacing: .02em; }
  body.page-site .lang-dropdown:hover .lang-dropdown-btn,
  body.page-site .lang-dropdown[open] .lang-dropdown-btn{
    color: var(--ink); background: rgba(206,186,255,0.07); border-color: transparent;
  }
  body.page-site .lang-dropdown-list{
    background: var(--panel); border: 1px solid var(--line-2); border-radius: 14px;
    padding: 7px; box-shadow: 0 26px 60px rgba(0,0,0,0.6);
  }
  body.page-site .lang-dropdown-list a{ border-radius: 9px; font-size: 14px; }

  body.page-site .nav-btn-ghost{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 11px 21px; border-radius: 11px;
    border: 1px solid var(--line-2); color: var(--ink);
    font-size: 14px; font-weight: 700;
    transition: border-color .2s ease, background .2s ease, transform .15s ease;
  }
  body.page-site .nav-btn-ghost svg{ width: 15px; height: 15px; flex: none; }
  body.page-site .nav-btn-ghost:hover{
    border-color: rgba(168,85,247,0.55); background: rgba(139,92,246,0.10);
    transform: translateY(-1px);
  }
  body.page-site .nav-cta{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 11px 23px; border-radius: 11px; font-size: 14px; font-weight: 700;
    color: #FFFFFF !important;
    background: linear-gradient(135deg, #9B6BFF 0%, #7C3AED 100%);
    box-shadow: 0 8px 26px rgba(124,58,237,0.42);
    transition: box-shadow .2s ease, transform .15s ease, filter .2s ease;
  }
  body.page-site .nav-cta svg{ width: 15px; height: 15px; flex: none; }
  body.page-site .nav-cta:hover{
    box-shadow: 0 12px 34px rgba(124,58,237,0.62);
    transform: translateY(-1px); filter: brightness(1.07);
  }

  body.page-site .nav-toggle{
    border: 1px solid var(--line-2); border-radius: 10px;
    width: 40px; height: 40px; color: var(--ink);
  }
  body.page-site .nav-toggle:hover{ border-color: rgba(168,85,247,0.55); transform: none; background: rgba(139,92,246,0.10); }

  /* Larghezze intermedie: si stringono i passi prima di passare al menu. */
  @media (max-width: 1180px){
    body.page-site header nav{ gap: 14px; padding: 14px 20px; }
    body.page-site .nav-links > a,
    body.page-site .nav-drop-btn{ padding: 9px 10px; font-size: 13.5px; }
    body.page-site .nav-btn-ghost, body.page-site .nav-cta{ padding: 10px 16px; }
  }

  /* Menu mobile: la barra si apre in verticale sotto l'header e le
     tendine si appiattiscono in elenchi sempre visibili. */
  @media (max-width: 1020px){
    body.page-site header nav{ flex-wrap: wrap; }
    body.page-site .nav-toggle{ display: inline-flex; align-items: center; justify-content: center; order: 2; margin-left: auto; }
    body.page-site .nav-right{ order: 3; }
    body.page-site .nav-links{
      order: 4; width: 100%; display: none;
      position: static; margin: 0; padding: 8px 0 12px;
      flex-direction: column; align-items: stretch; gap: 2px;
      background: transparent; border: none;
    }
    body.page-site .nav-links.open{ display: flex; }
    body.page-site .nav-drop{ width: 100%; }
    body.page-site .nav-drop-btn{ width: 100%; justify-content: space-between; }
    /* Il ponte anti-buco del desktop qui non serve e darebbe fastidio: sotto
       i 1020px la tendina non galleggia più staccata dal pulsante, è una
       fisarmonica in flusso, e quella fascia invisibile di 320px finirebbe
       sopra le voci sottostanti rubandosi i tocchi. Vanno ripetuti tutti e
       tre i selettori: un ".nav-drop::after" liscio non batterebbe
       ".nav-drop.is-open::after", che di specificità ha una classe in più. */
    body.page-site .nav-drop::after,
    body.page-site .nav-drop:hover::after,
    body.page-site .nav-drop:focus-within::after,
    body.page-site .nav-drop.is-open::after{ display: none; }
    body.page-site .nav-drop-menu{
      position: static; width: 100%; padding: 0 0 8px 10px;
      transform: none; opacity: 1; visibility: visible; pointer-events: auto;
      background: transparent; border: none; box-shadow: none;
    }
    body.page-site .nav-drop-menu em{ display: none; }
    body.page-site .nav-btn-ghost{ display: none; }
    body.page-site .nav-links > a.nav-links-auth{ display: flex; }
  }
  @media (max-width: 520px){
    body.page-site header nav{ padding: 12px 16px; gap: 10px; }
    body.page-site header .logo-word{ font-size: 17px; letter-spacing: .12em; }
    body.page-site .nav-cta{ padding: 10px 14px; font-size: 13.5px; }
  }

  /* ---------- BOTTONI ---------- */
  body.page-site .btn{
    font-family: 'Nunito Sans', sans-serif; font-weight: 700; font-size: 15px;
    padding: 16px 28px; border-radius: 14px; gap: 9px;
    transition: transform .16s ease, box-shadow .2s ease, background .2s ease, border-color .2s ease, filter .2s ease;
  }
  body.page-site .btn svg{ width: 16px; height: 16px; flex: none; }
  body.page-site .btn-primary{
    background: linear-gradient(135deg, #9B6BFF 0%, #7C3AED 100%); color: #FFFFFF;
    box-shadow: 0 12px 34px rgba(124,58,237,0.38);
  }
  body.page-site .btn-primary:hover{
    box-shadow: 0 18px 46px rgba(124,58,237,0.56); transform: translateY(-2px); filter: brightness(1.05);
  }
  body.page-site .btn-ghost{
    background: var(--panel); color: var(--ink); border: 1px solid var(--line-2);
  }
  body.page-site .btn-ghost:hover{
    border-color: rgba(168,85,247,0.5); background: var(--panel-2); transform: translateY(-2px);
  }
  body.page-site .btn-outline{ background: transparent; color: var(--ink); border: 1px solid var(--line-2); }
  body.page-site .btn-outline:hover{
    border-color: rgba(168,85,247,0.5); background: rgba(139,92,246,0.08); box-shadow: none;
  }

  /* ---------- IMPIANTO DELLE SEZIONI ---------- */
  /* La larghezza la impone .site-shell: qui niente max-width né padding,
     così hero, striscia creator e card finiscono esattamente sulla stessa
     verticale del bordo esterno della barra di navigazione. */
  body.page-site .wrap{ max-width: none; padding: 0; }

  /* .wrap sopra azzera il max-width: le varianti che DEVONO restare strette
     (colonna di lettura dei testi legali, card di login, blocco errore) se lo
     riprendono qui, altrimenti erediterebbero la larghezza piena dello shell. */
  body.page-site .legal-wrap{ max-width: 760px; }
  body.page-site .error-404-wrap, body.page-site .error-403-wrap{ max-width: none; }

  body.page-site section{ padding: 94px 0; border-bottom: none; }
  body.page-site .section-kicker{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 6px 14px; border-radius: 999px; margin-bottom: 20px;
    background: rgba(139,92,246,0.10); border: 1px solid rgba(168,85,247,0.24);
    font-size: 11.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
    color: var(--violet-3);
  }
  body.page-site .section-kicker svg{ width: 13px; height: 13px; }
  body.page-site .section-head{ max-width: 700px; margin-bottom: 52px; }
  /* h1 come h2: le pagine di sezione usano <h2> dentro .section-head, quelle
     dedicate a un singolo gioco usano <h1> (è il titolo della pagina, e vale
     per come i motori la leggono). Stesso aspetto, ruolo diverso. */
  body.page-site .section-head h1,
  body.page-site .section-head h2{
    font-size: clamp(28px, 3.6vw, 44px); line-height: 1.12; letter-spacing: -0.022em;
  }
  body.page-site .section-head p{ margin-top: 16px; font-size: 16.5px; line-height: 1.7; color: var(--muted); }
  body.page-site .section-head.is-center{ margin-left: auto; margin-right: auto; text-align: center; }

  /* ---------- HERO ---------- */
  body.page-site .hero{
    position: relative; overflow: visible; border-bottom: none;
    padding: 30px 0 0;
  }
  body.page-site .hero-glow{
    position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  }
  body.page-site .hero-glow::before{
    content: ''; position: absolute; top: -120px; right: 8%;
    width: 480px; height: 480px; border-radius: 50%;
    background: radial-gradient(circle, rgba(124,58,237,0.16), transparent 64%);
    filter: blur(80px);
  }
  body.page-site .hero .wrap{ position: relative; z-index: 1; }
  body.page-site .hero-split{
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
    gap: 34px; align-items: center; padding-bottom: 0;
  }
  @media (max-width: 1080px){
    body.page-site .hero-split{ grid-template-columns: 1fr; gap: 54px; }
  }

  /* min-width:0 evita che una riga lunga della lead sfondi la colonna del grid. */
  body.page-site .hero-copy{ min-width: 0; }

  body.page-site .hero-flag{
    display: inline-flex; align-items: center; gap: 12px;
    padding: 6px 16px 6px 6px; border-radius: 999px;
    background: rgba(206,186,255,0.035); border: 1px solid var(--line-2);
    transition: border-color .2s ease, background .2s ease, transform .18s ease;
  }
  body.page-site .hero-flag:hover{
    border-color: rgba(168,85,247,0.5); background: rgba(139,92,246,0.10); transform: translateY(-1px);
  }
  body.page-site .hero-flag-chip{
    background: linear-gradient(135deg, #9B6BFF, #7C3AED); color: #FFFFFF;
    font-size: 10.5px; font-weight: 800; letter-spacing: .09em;
    padding: 5px 11px; border-radius: 999px;
  }
  body.page-site .hero-flag-text{ font-size: 14px; color: #CFC7DF; }
  body.page-site .hero-flag svg{ width: 13px; height: 13px; color: var(--dim); flex: none; }

  body.page-site .hero h1{
    margin-top: 30px; text-transform: none;
    font-family: 'Baloo 2', sans-serif; font-weight: 800;
    font-size: clamp(38px, 4.5vw, 62px); line-height: 1.04; letter-spacing: -0.024em;
  }
  body.page-site .hero h1 .hl{
    background: linear-gradient(96deg, #B08CFF 0%, #8B5CF6 52%, #7C3AED 100%);
    -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  body.page-site .hero p.lead{
    margin-top: 24px; max-width: 520px;
    font-size: 17px; line-height: 1.7; color: var(--muted);
  }
  body.page-site .hero-ctas{ margin-top: 34px; gap: 16px; }
  body.page-site .hero-ctas .btn{ padding: 18px 34px; }
  body.page-site .hero-ctas .btn-primary{ padding-left: 48px; padding-right: 48px; }
  body.page-site .hero-assur{
    list-style: none; display: flex; flex-wrap: wrap; gap: 12px 26px; margin-top: 30px;
  }
  body.page-site .hero-assur li{
    display: flex; align-items: center; gap: 9px;
    font-size: 13.5px; font-weight: 600; color: #9E96B2;
  }
  body.page-site .hero-assur svg{ width: 17px; height: 17px; color: var(--violet-2); flex: none; }

  /* ---------- SCENA HERO: telefono + card evento ---------- */
  body.page-site .hero-stage{
    position: relative; display: flex; align-items: center; justify-content: center;
    gap: 46px; padding: 10px 0 16px;
  }
  @media (max-width: 1080px){ body.page-site .hero-stage{ gap: 34px; } }

  /* z-index più alto di .hero-events (2): i fili tratteggiati che partono
     dalle card devono passare DIETRO al telefono, non finirgli sopra allo
     schermo. Non basta abbassare il filo dentro la sua card: .event-card ha
     backdrop-filter, che crea un contesto di impilamento e ci imprigiona
     dentro qualsiasi z-index negativo. L'alone ::before qui sotto viene
     sollevato insieme al telefono, ma è già completamente trasparente prima
     di arrivare alle card (sfuma a 66% del raggio, le card iniziano oltre
     l'80%), quindi non le vela.
     La stessa cosa NON si può ottenere spostando l'animazione tf-float su
     .hero-window: quel transform lo riscrive js/hero-parallax.js a ogni
     movimento del mouse, e il galleggiamento sparirebbe. */
  body.page-site .hero-window-wrap{
    position: relative; z-index: 3; flex: none;
    animation: tf-float 7s ease-in-out infinite;
  }
  @keyframes tf-float{ 0%, 100%{ transform: translateY(0); } 50%{ transform: translateY(-12px); } }
  /* Bagliore dietro al telefono. La larghezza è limitata anche in vw e il
     centraggio usa translate invece di margini negativi fissi: con 440px
     secchi, su uno schermo da 390px questo alone (largo più del viewport,
     e invisibile perché sfocato) sporgeva di 25px oltre il bordo destro e
     faceva scorrere lateralmente TUTTA la home. Un elemento decorativo non
     deve poter allargare la pagina. */
  body.page-site .hero-window-wrap::before{
    content: ''; position: absolute; z-index: 0; left: 50%; top: 50%;
    width: min(440px, 78vw); aspect-ratio: 1; transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(circle, rgba(139,92,246,0.22), transparent 66%);
    filter: blur(60px); pointer-events: none;
  }

  /* .hero-window resta il nome della cornice: js/hero-parallax.js la usa
     per far seguire il telefono al mouse. */
  body.page-site .hero-window{
    position: relative; z-index: 1;
    width: 274px; padding: 8px; border-radius: 44px;
    background: linear-gradient(160deg, #2E2739 0%, #14101E 42%, #050308 100%);
    box-shadow:
      0 54px 96px -30px rgba(0,0,0,0.9),
      0 0 0 1px rgba(206,186,255,0.10),
      inset 0 0 0 1px rgba(0,0,0,0.65);
    transition: transform .2s ease-out;
    will-change: transform;
  }
  body.page-site .phone-screen{
    position: relative; overflow: hidden;
    aspect-ratio: 9 / 17.6; border-radius: 37px;
    background: #08060E; display: flex; flex-direction: column;
    /* Larghezza dell'isola, in un posto solo: la usa .phone-notch per
       disegnarsi e la barra di stato per calcolare le due "orecchie" ai suoi
       lati. Erano due numeri da tenere allineati a mano, e bastava cambiarne
       uno per scentrare l'altro. */
    --isola-larghezza: 82px;
  }
  /* Dynamic Island: pillola nera e basta, nessuna fotocamera disegnata.
     Le misure NON sono a occhio, sono quelle vere di un iPhone 15 Pro
     riportate in scala: schermo 393pt, isola 125x36.7pt, margine superiore
     11pt. Il nostro schermo è .hero-window (274px) meno la scocca (8px per
     lato) = 258px, quindi 125/393 x 258 = 82px, 36.7/393 x 258 = 24px,
     11/393 x 258 = 7px. È il rapporto a far sembrare vero un telefono
     disegnato: un'isola stretta o troppo in alto si riconosce subito come
     finta anche senza saper dire perché.
     border-radius 999px e non un valore fisso: la sagoma è uno stadio, i due
     capi sono semicerchi esatti qualunque sia l'altezza.
     z-index 6 e NON 3: .phone-status (l'ora e le icone) sta a z-index 5 e
     occupa la stessa fascia, quindi sotto il 5 l'isola finirebbe dietro
     all'orario. */
  body.page-site .phone-notch{
    position: absolute; z-index: 6; top: 7px; left: 50%; transform: translateX(-50%);
    width: var(--isola-larghezza); height: 24px; border-radius: 999px;
    background: #000;
  }
  body.page-site .phone-feed{
    position: absolute; inset: 0; z-index: 0;
    background: url('../img/minecraft/TntCube/tntcube.png') center/cover;
    filter: saturate(0.9) brightness(0.82);
  }
  body.page-site .phone-feed::after{
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(180deg,
      rgba(5,3,9,0.86) 0%, rgba(5,3,9,0.46) 20%,
      rgba(5,3,9,0.40) 44%, rgba(5,3,9,0.90) 70%, rgba(5,3,9,0.97) 100%);
  }

  /* padding-top allineato al centro verticale della Dynamic Island (top 11 +
     27/2 ≈ 24): sul telefono vero ora e icone stanno sulla stessa riga
     dell'isola, non un filo più in alto come prima. */
  /* Barra di stato: ora a sinistra dell'isola, le tre icone a destra.
     VERTICALE. Altezza 38px = (margine 7 + metà isola 12) x 2: con
     align-items:center il contenuto cade esattamente a 19px, cioè il centro
     dell'isola. Prima c'era un padding-top fisso che lo lasciava cadere più
     in basso, e i tre gruppi sembravano messi ad altezze diverse.
     ORIZZONTALE. Non basta justify-content:space-between con un padding: i
     due gruppi hanno larghezze molto diverse (l'ora ~26px, le icone ~64px),
     quindi spinti ai bordi arrivano a distanze diverse dall'isola — misurato,
     38px da un lato e 12px dall'altro. Su un iPhone vero ognuno è centrato
     nella propria "orecchia", lo spazio ai lati dell'isola. Qui ciascun
     gruppo occupa esattamente un'orecchia — (100% - isola) / 2 — e centra il
     proprio contenuto: i due vuoti tornano identici da soli, e restano tali
     anche se cambia la larghezza dell'isola. */
  body.page-site .phone-status{
    position: relative; z-index: 5;
    display: flex; align-items: center; justify-content: space-between;
    height: 38px; padding: 0;
    font-size: 11px; font-weight: 800; color: #FFFFFF;
  }
  body.page-site .phone-status > span{
    width: calc((100% - var(--isola-larghezza)) / 2);
    text-align: center;
  }
  body.page-site .phone-status-ico{ display: flex; align-items: center; justify-content: center; gap: 5px; }
  body.page-site .phone-status-ico svg{ width: 14px; height: 11px; }
  /* Il wifi è l'unica delle tre icone il cui tracciato non riempie il proprio
     viewBox: sta in basso, e misurato cadeva 1px sotto le altre due (che sono
     centrate). Il riquadro è allineato, è il DISEGNO dentro a non esserlo,
     quindi si corregge qui invece di ridisegnare il percorso. */
  body.page-site .phone-status-ico svg:nth-child(2){ transform: translateY(-1px); }

  body.page-site .live-head{
    position: relative; z-index: 5;
    display: flex; align-items: center; gap: 6px; padding: 16px 11px 0;
  }
  body.page-site .live-host{
    display: flex; align-items: center; gap: 7px;
    background: rgba(0,0,0,0.42); border-radius: 999px; padding: 3px 10px 3px 3px;
    backdrop-filter: blur(6px);
  }
  body.page-site .live-host-av{
    width: 22px; height: 22px; border-radius: 50%; flex: none;
    background: linear-gradient(135deg, #C084FC, #7C3AED);
  }
  body.page-site .live-host-txt strong{
    display: flex; align-items: center; gap: 3px;
    font-family: 'Nunito Sans', sans-serif; font-size: 10.5px; font-weight: 700; color: #FFFFFF;
  }
  body.page-site .live-host-txt strong svg{ width: 9px; height: 9px; color: #6BC5F8; }
  body.page-site .live-host-txt span{ display: block; font-size: 8.5px; color: rgba(255,255,255,0.6); }
  body.page-site .live-badge{
    background: #FE2C55; color: #FFFFFF; border-radius: 5px;
    font-size: 8.5px; font-weight: 800; letter-spacing: .07em; padding: 4px 7px;
  }
  body.page-site .live-count{
    display: flex; align-items: center; gap: 4px;
    background: rgba(0,0,0,0.45); border-radius: 999px; padding: 4px 8px;
    font-size: 9.5px; font-weight: 700; color: #FFFFFF; backdrop-filter: blur(6px);
  }
  body.page-site .live-count svg{ width: 10px; height: 10px; }
  body.page-site .live-close{ margin-left: auto; color: #FFFFFF; opacity: .82; display: flex; }
  body.page-site .live-close svg{ width: 14px; height: 14px; }

  body.page-site .live-spacer{ flex: 1; }

  body.page-site .live-events{
    position: relative; z-index: 5;
    display: flex; flex-direction: column; gap: 6px; padding: 0 11px;
  }
  /* Nel mockup il moltiplicatore ('x 12') sta FUORI dalla pillola scura,
     alla sua destra: la pillola avvolge solo avatar, nome e regalo. */
  body.page-site .live-event{
    display: flex; align-items: center; gap: 10px;
    animation: tf-slide-in .6s ease both;
  }
  body.page-site .live-event-pill{
    display: flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0;
    background: rgba(8,5,14,0.62); backdrop-filter: blur(6px);
    border: 1px solid rgba(206,186,255,0.07); border-radius: 999px; padding: 5px 10px 5px 5px;
  }
  body.page-site .live-event:nth-child(2){ animation-delay: .18s; }
  body.page-site .live-event:nth-child(3){ animation-delay: .36s; }
  @keyframes tf-slide-in{ from{ opacity: 0; transform: translateX(-14px); } to{ opacity: 1; transform: none; } }
  body.page-site .live-event-av{
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    background: linear-gradient(135deg, #A855F7, #6D28D9);
  }
  body.page-site .live-event:nth-child(2) .live-event-av{ background: linear-gradient(135deg, #60A5FA, #7C3AED); }
  body.page-site .live-event:nth-child(3) .live-event-av{ background: linear-gradient(135deg, #F0ABFC, #A855F7); }
  body.page-site .live-event-txt{ flex: 1; min-width: 0; line-height: 1.2; }
  body.page-site .live-event-txt strong{ display: block; font-size: 10.5px; font-weight: 700; color: #FFFFFF; }
  body.page-site .live-event-txt span{ display: block; font-size: 8.5px; color: rgba(255,255,255,0.58); }
  body.page-site .live-event-gift{ font-size: 15px; line-height: 1; flex: none; }
  body.page-site .live-event-mult{
    font-family: 'Baloo 2', sans-serif; font-size: 12.5px; font-weight: 800;
    color: #FFFFFF; flex: none;
  }

  body.page-site .live-chat{
    position: relative; z-index: 5;
    display: flex; align-items: center; gap: 8px; padding: 8px 11px 0;
  }
  body.page-site .live-chat-av{
    width: 22px; height: 22px; border-radius: 50%; flex: none;
    background: linear-gradient(135deg, #FBBF24, #F0ABFC);
  }
  body.page-site .live-chat p{ font-size: 9.5px; color: rgba(255,255,255,0.86); }

  body.page-site .live-composer{
    position: relative; z-index: 5;
    display: flex; align-items: center; gap: 8px; padding: 10px 11px 16px;
  }
  body.page-site .live-composer-input{
    flex: 1; background: rgba(255,255,255,0.10); border: 1px solid rgba(255,255,255,0.10);
    border-radius: 999px; padding: 8px 12px; font-size: 9.5px; color: rgba(255,255,255,0.58);
  }
  body.page-site .live-composer-btn{
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    font-size: 6.5px; color: rgba(255,255,255,0.72); flex: none;
  }
  body.page-site .live-composer-btn i{
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,0.12); font-style: normal; font-size: 12px;
  }

  /* ---- Le due card "evento attivato" collegate al telefono ---- */
  body.page-site .hero-events{
    position: relative; z-index: 2; flex: none;
    width: 252px; display: flex; flex-direction: column; gap: 14px;
  }
  body.page-site .event-card{
    position: relative; border-radius: 20px; padding: 13px;
    background: linear-gradient(165deg, rgba(32,22,52,0.94), rgba(13,9,20,0.96));
    border: 1px solid rgba(168,85,247,0.22);
    box-shadow: 0 26px 58px -20px rgba(0,0,0,0.85);
    backdrop-filter: blur(8px);
    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  body.page-site .event-card:hover{
    transform: translateY(-4px); border-color: rgba(168,85,247,0.5);
    box-shadow: 0 30px 66px -20px rgba(124,58,237,0.5);
  }
  /* Filo tratteggiato che collega la card al telefono: nel mockup è un
     arco, non un segmento dritto, quindi è un <path> SVG (.event-wire) e
     non un semplice border-top. Il pallino d'innesto resta un ::after. */
  body.page-site .event-wire{
    position: absolute; top: 50%; left: -54px;
    width: 54px; height: 40px; margin-top: -20px; pointer-events: none;
  }
  body.page-site .event-wire svg{ display: block; width: 100%; height: 100%; overflow: visible; }
  body.page-site .event-wire path{
    fill: none; stroke: rgba(168,85,247,0.55); stroke-width: 1.2;
    stroke-dasharray: 4 5; stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
  body.page-site .event-card::after{
    content: ''; position: absolute; top: 50%; left: -4px; width: 7px; height: 7px;
    margin-top: -3.5px; border-radius: 50%; background: var(--violet-2);
    box-shadow: 0 0 12px rgba(168,85,247,0.95);
  }
  @media (max-width: 1080px){
    body.page-site .event-wire, body.page-site .event-card::after{ display: none; }
  }
  body.page-site .event-card-head{ display: flex; align-items: center; gap: 10px; margin-bottom: 11px; }
  body.page-site .event-card-ico{
    width: 34px; height: 34px; border-radius: 9px; flex: none;
    background-size: cover; background-position: center;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
  }
  body.page-site .event-card-head h4{
    font-family: 'Baloo 2', sans-serif; font-size: 15px; font-weight: 700; color: var(--ink);
  }
  body.page-site .event-card-state{
    display: flex; align-items: center; gap: 5px; margin-top: 1px;
    font-size: 10.5px; color: #74D296;
  }
  body.page-site .event-card-state i{
    width: 5px; height: 5px; border-radius: 50%; background: #5BD37A;
    box-shadow: 0 0 8px rgba(91,211,122,0.85);
    animation: tf-blink 1.9s ease-in-out infinite;
  }
  @keyframes tf-blink{ 0%, 100%{ opacity: 1; } 50%{ opacity: .3; } }
  body.page-site .event-card-media{
    height: 112px; border-radius: 12px; background-size: cover; background-position: center;
  }
  body.page-site .event-card p{ margin-top: 11px; font-size: 12.5px; line-height: 1.45; color: #CDC5DE; }

  @media (max-width: 1080px){
    body.page-site .hero-stage{ flex-direction: column; }
    body.page-site .hero-events{ width: 100%; max-width: 560px; flex-direction: row; }
    body.page-site .event-card{ flex: 1; }
  }
  @media (max-width: 620px){
    body.page-site .hero-events{ flex-direction: column; }
    body.page-site .hero-window{ width: 260px; }
  }

  /* ---------- STRISCIA "SCELTO DA" ---------- */
  body.page-site .proof{ padding: 18px 0 0; }
  body.page-site .proof-label{
    text-align: center; font-size: 11.5px; font-weight: 800;
    letter-spacing: .17em; text-transform: uppercase; color: var(--dim);
  }
  body.page-site .proof-row{
    margin-top: 18px; display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: 18px 52px;
  }
  body.page-site .proof-item{
    display: flex; align-items: center; gap: 11px;
    font-family: 'Baloo 2', sans-serif; font-size: 20px; font-weight: 700;
    color: #C9C1D9; opacity: .88;
    transition: opacity .2s ease, color .2s ease, transform .2s ease;
  }
  body.page-site .proof-item:hover{ opacity: 1; color: var(--ink); transform: translateY(-2px); }
  body.page-site .proof-item svg{ width: 23px; height: 23px; color: #B9AECD; flex: none; }
  body.page-site .proof-more{ font-size: 14.5px; color: var(--dim); }
  @media (max-width: 700px){
    body.page-site .proof-row{ gap: 14px 26px; }
    body.page-site .proof-item{ font-size: 16px; }
    body.page-site .proof-item svg{ width: 19px; height: 19px; }
  }

  /* ---------- QUATTRO PILASTRI (subito sotto l'hero) ---------- */
  body.page-site .pillars-section{ padding: 32px 0 0; }
  body.page-site .pillars{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
  @media (max-width: 1020px){ body.page-site .pillars{ grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 560px){ body.page-site .pillars{ grid-template-columns: 1fr; } }
  body.page-site .pillar{
    background: linear-gradient(170deg, rgba(24,18,36,0.92), rgba(12,9,19,0.92));
    border: 1px solid var(--line); border-radius: 16px; padding: 28px 26px 30px;
    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  body.page-site .pillar:hover{
    transform: translateY(-5px); border-color: rgba(168,85,247,0.35);
    box-shadow: 0 24px 48px -20px rgba(0,0,0,0.85);
  }
  body.page-site .pillar-ico{
    width: 44px; height: 44px; border-radius: 12px; margin-bottom: 24px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.14); color: var(--violet-3);
  }
  body.page-site .pillar-ico svg{ width: 21px; height: 21px; }
  body.page-site .pillar h3{ font-size: 17px; font-weight: 700; margin-bottom: 9px; }
  body.page-site .pillar p{ font-size: 13.8px; line-height: 1.6; color: var(--muted); }

  /* ---------- COME FUNZIONA: tre passi ---------- */
  body.page-site .steps-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
  @media (max-width: 900px){ body.page-site .steps-grid{ grid-template-columns: 1fr; } }
  body.page-site .step-card{
    position: relative; background: var(--panel); border: 1px solid var(--line);
    border-radius: 22px; padding: 32px 28px 34px;
    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  body.page-site .step-card:hover{
    transform: translateY(-5px); border-color: rgba(168,85,247,0.35);
    box-shadow: 0 24px 50px -22px rgba(0,0,0,0.85);
  }
  body.page-site .step-badge{
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 13px; margin-bottom: 22px;
    background: linear-gradient(135deg, #9B6BFF, #7C3AED); color: #FFFFFF;
    font-family: 'Baloo 2', sans-serif; font-weight: 800; font-size: 16px;
    box-shadow: 0 10px 24px rgba(124,58,237,0.42);
  }
  body.page-site .step-card h3{ font-size: 19px; margin-bottom: 10px; }
  body.page-site .step-card p{ font-size: 14.5px; line-height: 1.65; color: var(--muted); }
  body.page-site .step-tags{ display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
  body.page-site .step-tag{
    font-size: 11.5px; font-weight: 600; color: var(--dim);
    border: 1px solid var(--line); border-radius: 999px; padding: 5px 11px;
    transition: color .2s ease, border-color .2s ease;
  }
  body.page-site .step-card:hover .step-tag{ color: var(--muted); border-color: var(--line-2); }

  /* ---------- LIBRERIA GIOCHI ---------- */
  /* Quattro piattaforme, quattro colonne: con tre la quarta card restava da
     sola su una riga tutta sua. Sotto i 1080px si passa a due per riga (che
     con quattro card resta pieno) e sotto i 620px a una. */
  body.page-site .lib-grid{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
  @media (max-width: 1080px){ body.page-site .lib-grid{ grid-template-columns: 1fr 1fr; gap: 22px; } }
  @media (max-width: 620px){ body.page-site .lib-grid{ grid-template-columns: 1fr; } }
  /* A quattro per riga la copertina va abbassata, altrimenti la card diventa
     una colonna stretta e altissima. */
  @media (min-width: 1081px){ body.page-site .lib-media{ height: 160px; } }
  body.page-site .lib-card{
    display: block; border-radius: 24px; overflow: hidden;
    border: 1px solid var(--line); background: var(--panel); color: inherit;
    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
  }
  body.page-site .lib-card:not(.is-locked):hover{
    transform: translateY(-6px); border-color: rgba(168,85,247,0.45);
    box-shadow: 0 28px 60px -24px rgba(0,0,0,0.9);
  }
  body.page-site .lib-media{
    position: relative; height: 194px; overflow: hidden;
    background-size: cover; background-position: center;
    transition: transform .45s ease;
  }
  body.page-site .lib-card:not(.is-locked):hover .lib-media{ transform: scale(1.06); }
  body.page-site .lib-card.is-locked .lib-media{ filter: grayscale(.5) brightness(.68); }
  body.page-site .lib-media::after{
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(6,4,10,0.35) 0%, transparent 42%, rgba(6,4,10,0.7) 100%);
  }
  body.page-site .lib-chip,
  body.page-site .lib-soon{
    position: absolute; top: 14px; z-index: 2;
    font-size: 11.5px; font-weight: 700; padding: 5px 12px; border-radius: 999px;
    background: rgba(6,4,10,0.72); border: 1px solid rgba(255,255,255,0.13);
    color: #FFFFFF; backdrop-filter: blur(6px);
  }
  body.page-site .lib-chip{ left: 14px; }
  body.page-site .lib-soon{ right: 14px; color: var(--violet-3); border-color: rgba(168,85,247,0.4); }
  body.page-site .lib-body{ padding: 22px 24px 26px; }
  body.page-site .lib-body h3{ font-size: 19px; margin-bottom: 8px; }
  body.page-site .lib-body p{ font-size: 14px; line-height: 1.6; color: var(--muted); }
  body.page-site .lib-foot{
    display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 20px;
  }
  body.page-site .lib-genre{
    font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
  }
  body.page-site .lib-go{
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 13.5px; font-weight: 700; color: var(--violet-3);
    transition: gap .2s ease;
  }
  body.page-site .lib-card:not(.is-locked):hover .lib-go{ gap: 11px; }
  body.page-site .lib-go svg{ width: 14px; height: 14px; }
  body.page-site .lib-note{ margin-top: 26px; text-align: center; font-size: 14px; color: var(--dim); }

  /* ---------- CAPACITÀ (griglia icona + testo) ---------- */
  body.page-site .cap-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
  @media (max-width: 960px){ body.page-site .cap-grid{ grid-template-columns: 1fr 1fr; } }
  @media (max-width: 600px){ body.page-site .cap-grid{ grid-template-columns: 1fr; } }
  body.page-site .cap{
    display: flex; gap: 16px; padding: 24px 24px 26px; border-radius: 18px;
    border: 1px solid var(--line); background: rgba(16,12,24,0.55);
    transition: border-color .25s ease, background .25s ease, transform .25s ease;
  }
  body.page-site .cap:hover{
    border-color: rgba(168,85,247,0.32); background: rgba(21,16,31,0.8); transform: translateY(-3px);
  }
  body.page-site .cap-ico{
    width: 42px; height: 42px; border-radius: 12px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.14); color: var(--violet-3);
  }
  body.page-site .cap-ico svg{ width: 19px; height: 19px; }
  body.page-site .cap h3{ font-size: 16.5px; margin-bottom: 8px; }
  body.page-site .cap p{ font-size: 14px; line-height: 1.6; color: var(--muted); }

  /* ---------- ABBONAMENTO ---------- */
  body.page-site .plan-wrap{
    display: grid; grid-template-columns: 1.02fr 0.98fr; gap: 24px;
    max-width: 1020px; margin: 0 auto; align-items: stretch;
  }
  @media (max-width: 900px){ body.page-site .plan-wrap{ grid-template-columns: 1fr; } }
  body.page-site .plan-card{
    position: relative; border-radius: 28px; padding: 38px 34px 34px;
    background: linear-gradient(165deg, rgba(41,26,66,0.9), rgba(13,10,20,0.96));
    border: 1px solid rgba(168,85,247,0.3);
    box-shadow: 0 44px 96px -38px rgba(124,58,237,0.6);
  }
  body.page-site .plan-tag{
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px 13px; border-radius: 999px;
    background: rgba(139,92,246,0.16); border: 1px solid rgba(168,85,247,0.34);
    font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
    color: var(--violet-3);
  }
  /* Serbatoio dei testi dei tre piani: non si vede mai, lo legge solo il JS.
     Regola esplicita e non solo l'attributo hidden, perché in questo blocco ci
     sono molte regole di display che potrebbero riaccenderlo per sbaglio. */
  body.page-site .plan-data{ display: none; }

  /* Selettore di piano a frecce (giornaliero / mensile / annuale). */
  body.page-site .plan-switch{
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    margin-top: 22px; padding: 6px; border-radius: 14px;
    background: rgba(8,5,14,0.5); border: 1px solid var(--line);
  }
  body.page-site .plan-switch-arrow{
    width: 38px; height: 38px; flex: none; border-radius: 10px; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.12); border: 1px solid transparent; color: var(--violet-3);
    transition: background .18s ease, border-color .18s ease, color .18s ease, transform .12s ease;
  }
  body.page-site .plan-switch-arrow svg{ width: 17px; height: 17px; }
  body.page-site .plan-switch-arrow:hover{
    background: rgba(139,92,246,0.22); border-color: rgba(168,85,247,0.45); color: var(--ink);
  }
  body.page-site .plan-switch-arrow:active{ transform: scale(0.94); }
  body.page-site .plan-switch-current{
    flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 7px;
  }
  body.page-site .plan-switch-name{
    font-family: 'Baloo 2', sans-serif; font-size: 16px; font-weight: 700; color: var(--ink);
  }
  body.page-site .plan-switch-dots{ display: flex; gap: 5px; }
  body.page-site .plan-switch-dots i{
    width: 5px; height: 5px; border-radius: 50%; background: rgba(206,186,255,0.22);
    transition: background .2s ease, transform .2s ease;
  }
  body.page-site .plan-switch-dots i.is-on{ background: var(--violet-2); transform: scale(1.35); }
  /* Micro-scatto sul prezzo al cambio piano: rende leggibile che è cambiato. */
  body.page-site .plan-price .amount.is-swapping{ animation: tf-price-swap .28s ease; }
  @keyframes tf-price-swap{ from{ opacity: 0; transform: translateY(-6px); } to{ opacity: 1; transform: none; } }
  @media (prefers-reduced-motion: reduce){
    body.page-site .plan-price .amount.is-swapping{ animation: none; }
  }
  body.page-site .plan-price{ display: flex; align-items: baseline; gap: 10px; margin: 20px 0 8px; }
  body.page-site .plan-price .amount{
    font-family: 'Baloo 2', sans-serif; font-size: 54px; font-weight: 800; letter-spacing: -0.03em;
  }
  body.page-site .plan-price .period{ font-size: 15px; color: var(--muted); }
  /* Etichetta dello sconto in home: la porta SOLO l'annuale (data-flag nel
     suo <span> di .plan-data, vedi js/plan-switcher.js) e sparisce scorrendo
     sugli altri piani. Stesso verde dell'etichetta nel checkout, così è
     riconoscibile come la stessa cosa nelle due pagine. */
  body.page-site .plan-flag{
    display: inline-block; margin-bottom: 10px; padding: 4px 11px; border-radius: 999px;
    background: rgba(74,222,128,0.12); border: 1px solid rgba(74,222,128,0.32);
    font-size: 11.5px; font-weight: 700; color: #4ADE80; white-space: nowrap;
  }
  body.page-site .plan-flag[hidden]{ display: none; }
  body.page-site .plan-card > p{ font-size: 14.5px; line-height: 1.65; color: var(--muted); }
  /* Consiglio "per chi è" del piano: sta SOPRA la nota di fatturazione e cambia
     con le frecce come prezzo e periodo (data-plan-hint, vedi
     js/plan-switcher.js). Più marcato della nota — che resta un dettaglio
     amministrativo in grigio — perché è quello che fa scegliere la durata.
     Stessa frase del piano corrispondente in subscribe.html e nella dashboard. */
  body.page-site .plan-card > p.plan-hint{
    margin-bottom: 6px; font-weight: 700; color: var(--ink);
  }
  body.page-site .plan-feats{
    list-style: none; display: flex; flex-direction: column; gap: 13px; margin: 26px 0 30px;
  }
  body.page-site .plan-feats li{ display: flex; gap: 11px; font-size: 14.5px; color: #D6CFE4; }
  body.page-site .plan-feats svg{ width: 18px; height: 18px; flex: none; margin-top: 2px; color: var(--violet-2); }
  body.page-site .plan-card .btn{ width: 100%; justify-content: center; }
  body.page-site .plan-note{ margin-top: 16px; text-align: center; font-size: 12.5px; color: var(--dim); }

  body.page-site .plan-side{ display: flex; flex-direction: column; gap: 16px; }
  body.page-site .plan-side-item{
    border: 1px solid var(--line); border-radius: 20px; padding: 24px 26px;
    background: rgba(16,12,24,0.55); flex: 1;
    transition: border-color .25s ease, background .25s ease;
  }
  body.page-site .plan-side-item:hover{ border-color: rgba(168,85,247,0.3); background: rgba(21,16,31,0.8); }
  /* L'icona in un suo riquadro viola invece che nuda accanto al titolo: dà
     un'ancora visiva alla riga e allinea fra loro le tre schede laterali, che
     prima partivano ognuna da un'icona di ingombro diverso.
     Il riquadro è l'SVG STESSO (sfondo + bordo + padding), non uno ::before
     su cui sovrapporlo: il primo tentativo faceva proprio così e centrava
     l'icona con margini negativi calcolati a mano, sbagliati di 11px perché
     non tenevano conto del gap del flex — l'icona risultava spostata dentro
     il riquadro. Con il padding la centratura è una conseguenza del box,
     non un numero da azzeccare. */
  body.page-site .plan-side-item h3{
    font-size: 16.5px; margin-bottom: 10px; display: flex; align-items: center; gap: 11px;
  }
  body.page-site .plan-side-item h3 svg{
    box-sizing: border-box; flex: none;
    width: 34px; height: 34px; padding: 8px; border-radius: 11px;
    color: var(--violet-3);
    background: rgba(139,92,246,0.13); border: 1px solid rgba(168,85,247,0.22);
  }
  body.page-site .plan-side-item p{ font-size: 14px; line-height: 1.6; color: var(--muted); }
  /* Metodi di pagamento: ogni logo in una sua piastrella invece che tutti in
     fila liberi. I quattro marchi hanno proporzioni molto diverse (il
     lettering PayPal è largo e basso, il cerchio Mastercard è quasi quadrato):
     allineati per altezza uguale sembravano messi a caso e di pesi diversi.
     Su una base identica il confronto è fra riquadri, non fra loghi, e la
     riga torna ordinata. */
  body.page-site .plan-pay{
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px; margin: 18px 0 0; padding: 0; list-style: none;
  }
  body.page-site .plan-pay-chip{
    display: flex; align-items: center; justify-content: center;
    height: 46px; padding: 0 8px; border-radius: 12px;
    border: 1px solid var(--line); background: rgba(255,255,255,0.035);
    transition: border-color .2s ease, background .2s ease;
  }
  body.page-site .plan-pay-chip:hover{
    border-color: rgba(168,85,247,0.32); background: rgba(255,255,255,0.06);
  }
  body.page-site .plan-pay-chip img{ width: auto; max-width: 100%; display: block; }
  /* Altezze calibrate una per una: a parità di altezza il marchio più "pieno"
     (Mastercard) sembrerebbe minuscolo accanto a un lettering lungo. */
  body.page-site .plan-pay img.pay-paypal{ height: 17px; }
  body.page-site .plan-pay img.pay-card{ height: 24px; }
  body.page-site .plan-pay img.pay-gpay{ height: 18px; }
  body.page-site .plan-pay img.pay-apple{ height: 17px; }
  @media (max-width: 420px){
    body.page-site .plan-pay{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* ---------- CHECKOUT (subscribe.html) ----------
     Due colonne: a sinistra i passaggi da compiere (durata → pagamento), a
     destra il riepilogo di cosa si sta comprando, che resta agganciato mentre
     si scorre. Gli id/classi che tocca js/subscribe.js (.plan-option,
     .plan-option-price, #price-amount, #price-period, .payment-method,
     #subscribe-form e gli altri stati) sono gli stessi di prima: qui cambia
     solo come sono disposti e vestiti. */
  body.page-site .checkout-section{ padding: 56px 0 96px; }
  body.page-site .checkout-grid{
    display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 26px;
    max-width: 1060px; margin: 0 auto; align-items: start;
  }
  @media (max-width: 940px){ body.page-site .checkout-grid{ grid-template-columns: 1fr; } }

  body.page-site .checkout-main{ display: flex; flex-direction: column; gap: 20px; }
  body.page-site .checkout-step{
    border: 1px solid var(--line); border-radius: 24px; padding: 28px 28px 26px;
    background: rgba(14,10,22,0.7);
  }
  @media (max-width: 560px){ body.page-site .checkout-step{ padding: 22px 18px; border-radius: 18px; } }
  body.page-site .checkout-step-head{
    display: flex; align-items: center; gap: 12px; margin-bottom: 6px;
  }
  body.page-site .checkout-step-num{
    width: 27px; height: 27px; flex: none; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.18); border: 1px solid rgba(168,85,247,0.34);
    font-family:'JetBrains Mono', monospace; font-size: 12px; font-weight: 600; color: var(--violet-3);
  }
  body.page-site .checkout-step-head h2{ font-size: 19px; }
  body.page-site .checkout-step-sub{ font-size: 14px; color: var(--muted); margin-bottom: 20px; }

  /* Scelta fra abbonamento ricorrente e pass una tantum: due schede larghe
     sopra le durate, perché è la decisione che cambia tutto il resto della
     pagina (durate disponibili, metodi di pagamento, cosa si sta comprando). */
  body.page-site .checkout-mode-options{
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0 0 22px;
  }
  @media (max-width: 620px){ body.page-site .checkout-mode-options{ grid-template-columns: 1fr; } }
  body.page-site .checkout-mode-option{
    display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
    text-align: left; padding: 16px 16px 14px; border-radius: 16px;
    border: 1px solid var(--line); background: rgba(8,5,14,0.45); cursor: pointer;
    transition: border-color .2s ease, background .2s ease, transform .2s ease;
  }
  body.page-site .checkout-mode-option:hover{ border-color: rgba(168,85,247,0.4); transform: translateY(-2px); }
  body.page-site .checkout-mode-option.selected{
    border-color: rgba(168,85,247,0.55); background: rgba(139,92,246,0.1);
    box-shadow: 0 18px 40px -22px rgba(124,58,237,0.75);
  }
  /* Percorso non percorribile (es. "pass" per chi ne ha già uno attivo): resta
     leggibile ma chiaramente inerte, il perché è nel title e nella nota sopra
     le due schede. */
  body.page-site .checkout-mode-option:disabled{
    opacity: .5; cursor: not-allowed;
  }
  body.page-site .checkout-mode-option:disabled:hover{
    border-color: var(--line); transform: none;
  }
  body.page-site .checkout-mode-name{
    font-family:'Baloo 2', sans-serif; font-size: 15.5px; font-weight: 700; color: var(--ink);
  }
  body.page-site .checkout-mode-hint{ font-size: 12.5px; line-height: 1.45; color: var(--muted); }

  /* Le quattro durate: schede vere e proprie, non pulsantini, disposte 2x2.
     In fila da quattro stavano in ~125px l'una (la colonna del checkout è
     larga ~536px): il nome più lungo, "Settimanale", non ci entrava e finiva
     sotto il segno di spunta in alto a destra, e le descrizioni si spezzavano
     su tre righe. Su due righe da due ogni scheda ha il doppio dello spazio e
     il problema non si ripresenta al primo nome un po' più lungo — in
     tedesco o spagnolo sarebbe tornato subito. */
  body.page-site .checkout-step .plan-options{
    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0;
  }
  @media (max-width: 460px){ body.page-site .checkout-step .plan-options{ grid-template-columns: 1fr; } }
  /* I due gruppi di durate (abbonamento / pass) si alternano con l'attributo
     hidden, ma "display:grid" qui sopra vince sul display:none di default del
     browser: senza questa riga si vedono TUTTI E DUE insieme. */
  body.page-site .checkout-step .plan-options[hidden]{ display: none; }
  body.page-site .checkout-step .plan-option{
    position: relative; align-items: flex-start; justify-content: flex-start; text-align: left;
    gap: 5px; padding: 18px 16px 16px; border-radius: 16px;
    background: rgba(8,5,14,0.45);
    transition: border-color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
  }
  body.page-site .checkout-step .plan-option:hover{ border-color: rgba(168,85,247,0.4); transform: translateY(-2px); }
  body.page-site .checkout-step .plan-option.selected{
    border-color: rgba(168,85,247,0.55); background: rgba(139,92,246,0.1);
    box-shadow: 0 18px 40px -22px rgba(124,58,237,0.75);
  }
  /* padding-right: il segno di spunta sta in alto a destra dentro la scheda
     (::after più sotto), e senza riservargli lo spazio il nome del piano ci
     finiva sotto — "Settimanale" arrivava a toccarlo. */
  body.page-site .plan-option-name{
    font-family:'Baloo 2', sans-serif; font-size: 15.5px; font-weight: 700; color: var(--ink);
    padding-right: 24px;
  }
  /* Importo e periodo su due righe (vedi setPrice in js/subscribe.js): in una
     colonna stretta l'unica riga andava a capo in mezzo, tipo "1,79€ /" +
     "giorno". */
  body.page-site .checkout-step .plan-option-price{
    display: flex; flex-direction: column; gap: 1px;
    font-family:'Baloo 2', sans-serif; text-transform: none;
  }
  body.page-site .plan-option-amount{
    font-size: 19px; font-weight: 800; letter-spacing: -0.01em; color: var(--violet-3);
    line-height: 1.15;
  }
  body.page-site .plan-option-period{
    font-family:'Nunito Sans', sans-serif; font-size: 12px; font-weight: 600;
    color: var(--muted); letter-spacing: 0;
  }
  body.page-site .plan-option-hint{ font-size: 12.5px; line-height: 1.45; color: var(--muted); }
  /* Il segno di spunta compare solo sulla scheda scelta: senza, "selezionato"
     si capiva soltanto dal bordo, poco leggibile su schermi poco contrastati. */
  body.page-site .checkout-step .plan-option::after{
    content: ""; position: absolute; top: 14px; right: 14px;
    width: 16px; height: 16px; border-radius: 50%;
    border: 1px solid rgba(206,186,255,0.22); transition: background .2s ease, border-color .2s ease;
  }
  body.page-site .checkout-step .plan-option.selected::after{
    background: var(--violet-2) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 10.5l3.8 3.8L16 6'/%3E%3C/svg%3E") center/11px no-repeat;
    border-color: var(--violet-2);
  }
  /* align-self flex-start + nowrap: la pillola "Risparmi 65,89€" si allargava
     a tutta la scheda e andava a capo in due righe strette, sembrando un
     errore invece di un'etichetta. margin-top:auto la incolla in fondo, così
     resta allineata anche se le schede accanto hanno testi più lunghi. */
  body.page-site .plan-option-flag{
    align-self: flex-start; margin-top: auto; padding: 3px 9px; border-radius: 999px;
    background: rgba(74,222,128,0.12); border: 1px solid rgba(74,222,128,0.32);
    font-size: 10.5px; font-weight: 700; color: #4ADE80; white-space: nowrap;
  }
  body.page-site .checkout-billing{
    margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
    font-size: 13.5px; line-height: 1.6; color: var(--muted);
  }

  /* auto-fit invece di 4 colonne fisse: i metodi disponibili non sono sempre
     quattro (Apple/Google Pay compaiono solo quando l'account PayPal li ha
     abilitati e solo sul pagamento unico). Con le colonne fisse i due bottoni
     rimasti si accucciavano nel quarto sinistro della riga lasciando metà
     spazio vuoto; così si distribuiscono sempre sulla larghezza intera. */
  body.page-site .checkout-step .payment-methods{
    grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 12px; margin: 0;
  }
  @media (max-width: 620px){ body.page-site .checkout-step .payment-methods{ grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  body.page-site .checkout-step .payment-method{
    flex-direction: column; gap: 9px; padding: 16px 10px; border-radius: 16px;
    background: rgba(8,5,14,0.45); font-size: 12.5px;
  }
  body.page-site .checkout-step .payment-method:hover:not(:disabled){ border-color: rgba(168,85,247,0.4); }
  body.page-site .checkout-step .payment-method.selected{
    border-color: rgba(168,85,247,0.55); background: rgba(139,92,246,0.1);
  }
  body.page-site .checkout-step .payment-method-icon img{ height: 22px; }
  /* Apple Pay e Google Pay esistono solo sul percorso "pass una tantum":
     PayPal non li offre sugli abbonamenti ricorrenti. Sul percorso
     abbonamento restano quindi visibili ma disattivati, con scritto perché —
     sparire del tutto sembrerebbe un bug della pagina. L'opacità di default
     (.4) rendeva il logo Apple Pay, già scuro di suo, praticamente invisibile
     sul fondo nero. */
  body.page-site .checkout-step .payment-method:disabled{ opacity: .62; cursor: not-allowed; }
  body.page-site .payment-method-soon{
    font-size: 10px; letter-spacing: .04em; text-transform: uppercase; color: var(--dim);
  }
  /* Nota "solo pass": visibile soltanto quando il metodo è bloccato, così sul
     percorso pass i due bottoni restano puliti come Carta e PayPal. */
  body.page-site .checkout-step .payment-method .payment-method-soon{ display: none; }
  body.page-site .checkout-step .payment-method:disabled .payment-method-soon{ display: block; }
  body.page-site .checkout-secure{
    display: flex; align-items: flex-start; gap: 9px; margin-top: 18px;
    font-size: 12.5px; line-height: 1.55; color: var(--dim);
  }
  body.page-site .checkout-secure svg{ width: 15px; height: 15px; flex: none; margin-top: 1px; color: var(--violet-3); }

  /* Stati alternativi al pagamento (non autenticato, admin, già abbonato). */
  body.page-site .checkout-state{
    border: 1px solid var(--line); border-radius: 24px; padding: 28px;
    background: rgba(14,10,22,0.7); text-align: center;
  }
  body.page-site .checkout-state .sub-note{
    margin: 0 0 18px; padding: 0; border: 0;
    font-size: 14.5px; line-height: 1.6; color: var(--muted);
  }
  body.page-site .checkout-state .btn{ width: 100%; justify-content: center; }

  /* "Ho un codice di attivazione": l'alternativa al pagamento. Un codice vale
     giorni di abbonamento veri (li genera il pannello admin) e NON passa da
     PayPal: per questo sta in un blocco suo, separato da un "oppure", invece
     di mettersi in fila agli altri metodi come se fosse un quinto modo di
     pagare. Resta visibile anche a chi ha già l'accesso attivo: i giorni del
     codice si sommano a quelli che restano. */
  body.page-site .checkout-code-or{
    display: flex; align-items: center; gap: 14px; margin: 0 0 20px;
    font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
  }
  body.page-site .checkout-code-or::before,
  body.page-site .checkout-code-or::after{ content: ""; flex: 1; height: 1px; background: var(--line); }
  body.page-site .checkout-code-row{ display: flex; gap: 10px; flex-wrap: wrap; }
  body.page-site .checkout-code-row input{
    flex: 1; min-width: 190px; padding: 13px 15px; border-radius: 14px;
    border: 1px solid var(--line); background: rgba(8,5,14,0.55); color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 15px; letter-spacing: .09em; text-transform: uppercase;
  }
  body.page-site .checkout-code-row input::placeholder{ color: var(--dim); letter-spacing: .09em; }
  body.page-site .checkout-code-row input:focus{ outline: none; border-color: var(--violet-3); }
  body.page-site .checkout-code-row .btn{ flex: none; }
  body.page-site .checkout-code-msg{ margin: 12px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--muted); }
  body.page-site .checkout-code-msg.is-error{ color: #FFB4B4; }
  body.page-site .checkout-code-msg.is-ok{ color: #A8F0C6; }

  /* Durate e modalità BLOCCATE da un codice sconto: il piano lo fissa il
     codice, e restare cliccabili all'apparenza (col prezzo pieno bello in
     vista accanto a un riepilogo che ne dice un altro) fa solo credere a un
     errore della pagina. Restano leggibili, spente. */
  body.page-site .checkout-step .plan-option:disabled,
  body.page-site .checkout-mode-option:disabled{
    opacity: .45; cursor: not-allowed; pointer-events: none;
  }
  body.page-site .checkout-step .plan-option:disabled:hover{ transform: none; border-color: var(--line); }

  /* Riepilogo: si aggancia in alto mentre si scorre la colonna dei passaggi. */
  body.page-site .checkout-side{
    display: flex; flex-direction: column; gap: 16px;
    position: sticky; top: 24px;
  }
  @media (max-width: 940px){ body.page-site .checkout-side{ position: static; } }
  body.page-site .checkout-summary{
    border-radius: 24px; padding: 28px;
    background: linear-gradient(165deg, rgba(41,26,66,0.9), rgba(13,10,20,0.96));
    border: 1px solid rgba(168,85,247,0.3);
    box-shadow: 0 44px 96px -38px rgba(124,58,237,0.6);
  }
  body.page-site .checkout-summary .plan-price{ margin: 18px 0 6px; }
  body.page-site .checkout-summary .plan-price .amount{ font-size: 44px; }
  body.page-site .checkout-summary .plan-feats{ margin: 22px 0 0; gap: 11px; }
  body.page-site .checkout-summary .plan-feats li{ font-size: 13.5px; }
  body.page-site .checkout-summary-name{
    margin-top: 14px; font-family:'Baloo 2', sans-serif; font-size: 15px; font-weight: 700; color: var(--ink);
  }

  /* ---------- CHI SIAMO ---------- */
  body.page-site .about-band{
    display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 46px; align-items: center;
    border: 1px solid var(--line); border-radius: 30px; padding: 48px 46px;
    background:
      radial-gradient(620px 320px at 12% 10%, rgba(139,92,246,0.16), transparent 62%),
      rgba(14,10,22,0.7);
  }
  @media (max-width: 900px){
    body.page-site .about-band{ grid-template-columns: 1fr; gap: 34px; padding: 36px 26px; }
  }
  body.page-site .about-band h2{ font-size: clamp(26px, 3.2vw, 38px); letter-spacing: -0.02em; }
  body.page-site .about-band p{ margin-top: 16px; font-size: 15.5px; line-height: 1.75; color: var(--muted); }
  body.page-site .about-band p + p{ margin-top: 12px; }
  /* I due nomi citati nel racconto (TikGameX, Righi Raimondo) sul colore pieno:
     in --muted come il resto del paragrafo il grassetto quasi non si vedeva. */
  body.page-site .about-band p strong{ color: var(--ink); font-weight: 700; }
  body.page-site .about-stats{ display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
  body.page-site .about-stat{
    border: 1px solid var(--line); border-radius: 18px; padding: 22px 24px;
    background: rgba(16,12,24,0.7);
  }
  body.page-site .about-stat strong{
    display: block; font-family: 'Baloo 2', sans-serif; font-size: 27px; font-weight: 800; color: var(--ink);
  }
  body.page-site .about-stat span{ display: block; margin-top: 5px; font-size: 12.5px; line-height: 1.45; color: var(--dim); }

  /* ---------- FAQ ---------- */
  body.page-site .faq-list{
    max-width: none; display: grid; grid-template-columns: 1fr 1fr;
    gap: 14px 20px; align-content: start;
  }
  @media (max-width: 820px){ body.page-site .faq-list{ grid-template-columns: 1fr; } }
  body.page-site .faq-item{
    border: 1px solid var(--line); border-radius: 18px; padding: 20px 24px;
    background: rgba(16,12,24,0.5); align-self: start;
    transition: border-color .2s ease, background .2s ease;
  }
  body.page-site .faq-item:hover{ border-color: rgba(168,85,247,0.32); }
  body.page-site .faq-item[open]{ background: var(--panel-2); border-color: rgba(168,85,247,0.34); }
  body.page-site .faq-q{
    font-family: 'Baloo 2', sans-serif; font-size: 16px; font-weight: 700; gap: 16px;
  }
  body.page-site .faq-q .icon{
    flex: none; width: 26px; height: 26px; border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.15); color: var(--violet-3);
    font-family: 'Nunito Sans', sans-serif; font-size: 15px;
    transition: transform .22s ease;
  }
  body.page-site .faq-item[open] .faq-q .icon{ transform: rotate(45deg); }
  body.page-site .faq-a{
    display: block; max-height: 0; opacity: 0; overflow: hidden; margin-top: 0;
    max-width: none; font-size: 14.5px; line-height: 1.7; color: var(--muted);
    transition: max-height .35s ease, opacity .3s ease, margin-top .35s ease;
  }
  body.page-site .faq-item[open] .faq-a{ max-height: 360px; opacity: 1; margin-top: 14px; }

  /* ---------- CTA FINALE ---------- */
  body.page-site .cta-band{ padding: 24px 0 96px; }
  body.page-site .cta-panel{
    position: relative; overflow: hidden;
    border-radius: 32px; padding: 72px 40px; text-align: center;
    border: 1px solid rgba(168,85,247,0.24);
    background:
      radial-gradient(720px 340px at 22% 10%, rgba(139,92,246,0.24), transparent 62%),
      radial-gradient(680px 320px at 80% 90%, rgba(124,58,237,0.22), transparent 60%),
      var(--panel);
  }
  body.page-site .cta-panel h2{
    font-size: clamp(28px, 4vw, 46px); max-width: 700px; margin: 0 auto; letter-spacing: -0.024em;
  }
  body.page-site .cta-panel p{
    margin: 18px auto 0; max-width: 560px; font-size: 16.5px; line-height: 1.7; color: var(--muted);
  }
  body.page-site .cta-panel .hero-ctas{ justify-content: center; margin-top: 32px; }
  @media (max-width: 620px){ body.page-site .cta-panel{ padding: 48px 24px; } }

  /* ---------- FOOTER ---------- */
  body.page-site footer{ position: relative; padding: 56px 0 44px; border-top: 1px solid var(--line); }
  body.page-site .footer-cols{ grid-template-columns: 1.6fr repeat(3, 1fr); gap: 36px; }
  /* Queste due media query DEVONO stare qui, non solo accanto alla regola base
     .footer-cols più in alto: "body.page-site .footer-cols" è più specifico e
     vinceva sulle media query generiche, tenendo il footer a 4 colonne anche a
     390px di larghezza. Risultato: 80px di scorrimento orizzontale su tutta la
     home, con l'ultima colonna fuori dallo schermo. */
  @media (max-width: 760px){ body.page-site .footer-cols{ grid-template-columns: 1fr 1fr; gap: 28px; } }
  @media (max-width: 480px){ body.page-site .footer-cols{ grid-template-columns: 1fr; gap: 24px; } }
  body.page-site footer .logo{ font-size: 18px; gap: 10px; }
  body.page-site footer .logo-mark{ height: 28px; }
  body.page-site footer .logo-word{
    font-family: 'Baloo 2', sans-serif; font-weight: 800; letter-spacing: .13em; text-transform: uppercase;
  }
  body.page-site .footer-note{
    margin-top: 14px; max-width: 330px; font-size: 13.5px; line-height: 1.65; color: var(--muted);
  }
  body.page-site .footer-col-title{
    font-family: 'Nunito Sans', sans-serif; font-size: 11.5px; font-weight: 800;
    letter-spacing: .13em; text-transform: uppercase; color: #8E85A6; margin-bottom: 16px;
  }
  body.page-site .footer-col-links{ gap: 12px; }
  body.page-site .footer-col-links a{ color: var(--muted); font-size: 14px; transition: color .2s ease; }
  body.page-site .footer-col-links a:hover{ color: var(--ink); }
  body.page-site .footer-bottom{ margin-top: 44px; padding-top: 24px; border-top: 1px solid var(--line); }
  body.page-site .footer-copy{ font-size: 12.5px; color: var(--dim); opacity: 1; }
  body.page-site .footer-social a{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 8px 15px; border: 1px solid var(--line); border-radius: 999px;
    font-size: 13px; color: var(--muted);
    transition: color .2s ease, border-color .2s ease, background .2s ease;
  }
  body.page-site .footer-social a:hover{
    color: var(--ink); border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-site .footer-social svg{ width: 15px; height: 15px; }

  /* ---------- PAGINE PIATTAFORMA (minecraft.html / roblox.html) ---------- */
  body.page-site .platform-hero{ padding: 44px 0 0; }
  /* display:flex + width:fit-content, non inline-flex: il pulsante deve stare
     su una riga sua, altrimenti finisce in linea col badge 'Libreria' che lo
     segue. E l'SVG senza misure esplicite verrebbe disegnato enorme. */
  body.page-site .platform-hero-back{
    display: flex; width: fit-content; align-items: center; gap: 8px;
    padding: 8px 15px; border-radius: 999px; border: 1px solid var(--line);
    font-size: 13.5px; color: var(--muted); margin-bottom: 24px;
    white-space: nowrap;
    transition: color .2s ease, border-color .2s ease, background .2s ease;
  }
  body.page-site .platform-hero-back svg{ width: 15px; height: 15px; flex: none; }
  body.page-site .platform-hero .section-head{ margin-bottom: 0; }
  /* La sezione con l'elenco dei giochi segue subito l'intro: senza questo si
     sommavano i 94px di padding standard e restava un buco enorme. */
  body.page-site .platform-hero + section{ padding-top: 44px; }
  body.page-site .platform-hero-back:hover{
    color: var(--ink); border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-site .game-thumb-soon{
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(160deg, #241a38 0%, #150f24 55%, #0e0a18 100%);
    color: rgba(206,186,255,0.4);
  }
  body.page-site .game-thumb-soon svg{ width: 26px; height: 26px; }
  body.page-site .soon-chip{
    display: inline-block; vertical-align: middle; margin-left: 9px;
    padding: 3px 10px; border-radius: 999px;
    background: rgba(139,92,246,0.14); border: 1px solid rgba(168,85,247,0.3);
    font-family: 'Nunito Sans', sans-serif; font-size: 10.5px; font-weight: 800;
    letter-spacing: .08em; text-transform: uppercase; color: var(--violet-3);
  }
  body.page-site .games-note{ margin-top: 26px; text-align: center; font-size: 14px; color: var(--dim); }

  /* ---------- PAGINE AUTH / LEGALI / ERRORE ---------- */
  body.page-site .auth-section{ padding: 72px 0; }
  body.page-site .auth-card{
    background: linear-gradient(168deg, rgba(30,21,48,0.9), rgba(13,10,20,0.96));
    border: 1px solid var(--line-2); border-radius: 26px; padding: 44px 40px;
    box-shadow: 0 44px 96px -40px rgba(124,58,237,0.55);
  }
  body.page-site .auth-card .btn{ font-size: 15px; }
  /* Login, registrazione e recupero password: il modulo da solo era una card
     stretta in mezzo a una pagina vuota. Stessa impostazione del checkout in
     subscribe.html — intestazione centrata sopra, modulo a sinistra e a destra
     due riquadri che dicono cosa c'è dall'altra parte del login. */
  body.page-site .auth-grid{
    display: grid; grid-template-columns: 1.04fr 0.96fr; gap: 24px;
    max-width: 940px; margin: 0 auto; align-items: start;
  }
  @media (max-width: 880px){ body.page-site .auth-grid{ grid-template-columns: 1fr; } }
  body.page-site .auth-side{ display: flex; flex-direction: column; gap: 16px; }
  /* Su schermo stretto il modulo viene prima: i riquadri sono contorno, non
     devono spingere in basso la cosa per cui si è arrivati qui. */
  @media (max-width: 880px){ body.page-site .auth-side{ order: 2; } }
  body.page-site .auth-section .section-head{ margin-bottom: 34px; }
  body.page-site .auth-section .section-head h1{
    font-size: clamp(30px, 4vw, 44px); line-height: 1.1; letter-spacing: -0.02em;
  }
  body.page-site .auth-link{ color: var(--violet-3); }
  body.page-site .field input:focus{ border-color: var(--violet); background: rgba(139,92,246,0.06); }
  body.page-site .legal{ padding: 64px 0 92px; }
  body.page-site .legal h2{ color: var(--ink); }
  body.page-site .error-404, body.page-site .error-403{ padding: 90px 0; }
  body.page-site .error-code{
    background: linear-gradient(135deg, #C084FC, #7C3AED);
    -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(0 0 40px rgba(139,92,246,0.35));
  }

  /* Footer semplice a una riga (auth, legali, errori): stesse regole
     cromatiche del footer a colonne della home. */
  body.page-site .footer-row{ align-items: flex-start; gap: 28px; }
  body.page-site .footer-row .footer-note{ margin-top: 12px; }
  body.page-site .footer-links{ gap: 22px; flex-wrap: wrap; }
  body.page-site .footer-links a{ color: var(--muted); font-size: 14px; transition: color .2s ease; }
  body.page-site .footer-links a:hover{ color: var(--ink); }

  /* Barra ridotta di queste pagine: nessuna tendina, quindi il CTA di
     destra è il solo pulsante pieno e le voci restano allineate a sinistra. */
  body.page-site .auth-section .wrap,
  body.page-site .legal .wrap{ position: relative; z-index: 1; }
  /* ---------- RIDUZIONE MOVIMENTO ---------- */
  @media (prefers-reduced-motion: reduce){
    body.page-site .hero-window-wrap,
    body.page-site .live-event,
    body.page-site .event-card-state i{ animation: none; }
  }


  /* ---------- AUTH / LOGIN ---------- */
  .auth-section{
    padding: 90px 0; min-height: calc(100vh - 148px);
    display:flex; align-items:center;
  }
  .auth-wrap{ display:flex; justify-content:center; }
  .auth-card{
    max-width: 440px; width:100%;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
    border: 1px solid var(--line); border-radius: 20px;
    padding: 44px 40px;
    box-shadow: 0 0 50px rgba(185,107,250,0.08), 0 0 50px rgba(124,31,212,0.06), 0 30px 80px -20px rgba(0,0,0,0.6);
  }
  .auth-card h1{ font-size: clamp(26px, 3vw, 32px); margin: 6px 0 10px; }
  .auth-sub{ color: var(--muted); font-size: 14.5px; margin-bottom: 30px; }

  .auth-error{
    background: rgba(124,31,212,0.10); border: 1px solid rgba(124,31,212,0.4); color: #E3C8FF;
    border-radius: 10px; padding: 12px 14px; font-size: 13.5px; margin-bottom: 22px;
  }

  .auth-form{ display:flex; flex-direction:column; gap: 20px; }
  .auth-form[hidden]{ display:none; }
  .field{ display:flex; flex-direction:column; gap: 8px; }
  .field-label{ font-size: 13px; color: var(--muted); font-weight:500; }
  /* Select nativi (es. tab "Manutenzione" del pannello admin): color-scheme
     su :root non basta ovunque, alcuni browser aprono comunque il menu a
     tendina con sfondo chiaro. Con solo "color: var(--ink)" ereditato dal
     <select> il testo delle opzioni risultava chiaro su sfondo chiaro,
     illeggibile — qui si forza sfondo e testo espliciti sulle <option>. */
  select{ color-scheme: dark; }
  select option{ background: #150C20; color: var(--ink); }
  .field-hint{ font-size: 12px; color: var(--muted); }
  .field-hint-error{ color: #C084FC; }
  .field input[type="email"],
  .field input[type="password"],
  .field input[type="text"],
  .field input[type="number"],
  .field textarea{
    background: rgba(214,190,245,0.03); border: 1px solid var(--line); border-radius: 10px;
    padding: 13px 14px; color: var(--ink); font-size: 16px; font-family: 'Nunito Sans', sans-serif;
    width: 100%; transition: border-color .2s ease, background .2s ease;
  }
  /* Le textarea dentro .field (oggi "Parole vietate" nel pannello TTS) senza
     questa riga uscivano con lo stile nativo del browser — bianche, bordo
     grigio, font di sistema — in mezzo a una dashboard scura. Le due textarea
     di admin.html non passano da qui: hanno il loro style inline e stanno
     fuori da .field.
     resize verticale e non libero: allargandola in orizzontale sfonderebbe la
     colonna della tile. line-height più arioso di un input perché qui le righe
     sono più di una e vanno lette come elenco. */
  .field textarea{
    resize: vertical;
    min-height: 92px;
    line-height: 1.5;
  }
  /* Frecce incremento/decremento native del browser: fuori stile col resto
     della dashboard (colori chiari su sfondo scuro), tolte per un input
     numerico che comunque si compila anche digitando (es. "Giorni di prova"). */
  .field input[type="number"]::-webkit-outer-spin-button,
  .field input[type="number"]::-webkit-inner-spin-button{
    -webkit-appearance: none; margin: 0;
  }
  .field input[type="number"]{ -moz-appearance: textfield; }
  .field input:focus,
  .field textarea:focus{ outline:none; border-color: var(--blue); background: rgba(185,107,250,0.05); }
  .field input[aria-invalid="true"]{ border-color: var(--red); }
  .field-input-wrap{ position:relative; display:flex; }
  .field-input-wrap input{ flex:1; padding-right: 44px; }
  .field-toggle{
    position:absolute; right:2px; top:50%; transform:translateY(-50%);
    background:transparent; border:none; color: var(--muted); cursor:pointer;
    font-size: 16px; padding: 10px; line-height:1;
    display:flex; align-items:center; justify-content:center;
  }
  .field-toggle:hover{ color: var(--ink); }
  .field-toggle svg{ width:18px; height:18px; display:block; }

  .auth-row{ display:flex; justify-content:space-between; align-items:center; font-size: 13.5px; flex-wrap: wrap; gap: 10px; }
  .checkbox{ display:flex; align-items:center; gap:8px; color: var(--muted); cursor:pointer; font-size: 13.5px; }
  .checkbox input{ accent-color: var(--blue); width:16px; height:16px; flex-shrink:0; }
  .auth-link{ color: var(--blue); font-weight:500; }
  .auth-link:hover{ text-decoration: underline; }

  .auth-submit{ width:100%; justify-content:center; margin-top: 6px; }
  .auth-submit:disabled{ opacity: 0.6; cursor: not-allowed; transform: none; }
  .auth-footer{ margin-top: 26px; text-align:center; font-size: 13.5px; color: var(--muted); }

  /* --- Accesso con Discord --- */
  /* Il blu è il "blurple" ufficiale di Discord (#5865F2), non una tinta della
     nostra palette: un pulsante di accesso con un servizio esterno si
     riconosce dal colore di QUEL servizio, ed è l'unico punto del sito dove
     ha senso uscire dai nostri viola. Per lo stesso motivo il testo è bianco
     pieno e non var(--ink), che su blurple non avrebbe contrasto sufficiente. */
  .btn-discord{ background: #5865F2; color: #FFFFFF; }
  .btn-discord:hover{ background: #4752C4; box-shadow: 0 8px 24px rgba(88,101,242,0.38); }
  .btn-discord:disabled{ opacity: 0.6; cursor: not-allowed; transform: none; }
  /* fill:currentColor fa seguire al logo il colore del testo del pulsante,
     compreso lo stato :disabled — un SVG con fill fisso resterebbe acceso
     mentre il resto del pulsante sbiadisce. */
  .btn-discord svg{ width: 18px; height: 18px; fill: currentColor; flex-shrink: 0; }

  /* Separatore "oppure" tra il modulo email/password e l'accesso con Discord:
     due righe che crescono ai lati del testo, così resta centrato qualunque
     sia la lunghezza della parola nelle quattro lingue. */
  .auth-divider{
    display:flex; align-items:center; gap:14px;
    margin: 22px 0 18px; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
  }
  .auth-divider::before, .auth-divider::after{
    content:''; flex:1; height:1px; background: var(--line);
  }
  .auth-alt-btn{ width:100%; justify-content:center; }
  /* Nota sotto il pulsante: spiega che l'accesso funziona solo per chi ha già
     collegato Discord dalla dashboard. Senza, un "Nessun account collegato"
     dopo il giro su Discord sembrerebbe un guasto invece di una regola. */
  .auth-alt-note{ margin-top: 10px; text-align:center; font-size: 12px; color: var(--muted); line-height: 1.5; }

  /* Riquadro in cima alla registrazione per chi ci arriva dal pulsante
     "Accedi con Discord" senza avere un account: Discord è già agganciato,
     gli resta solo da scegliere email e password. Bordo e sfondo in blurple
     per riconoscerlo come "roba di Discord" a colpo d'occhio, coerente col
     pulsante che l'ha portato qui. */
  .discord-pending{
    display:flex; align-items:flex-start; gap: 12px;
    padding: 14px 16px; margin-bottom: 22px;
    border: 1px solid rgba(88,101,242,0.45); border-radius: 12px;
    background: rgba(88,101,242,0.10);
    font-size: 13px; line-height: 1.55; color: var(--ink);
  }
  .discord-pending svg{ width: 20px; height: 20px; fill: #5865F2; flex-shrink: 0; margin-top: 1px; }
  .discord-pending strong{ color: #FFFFFF; }
  .discord-pending .discord-pending-note{ display:block; margin-top: 5px; color: var(--muted); font-size: 12px; }

  /* Fascia "arrivi dal link di un'agenzia", in cima alla registrazione: logo e
     nome dell'agenzia piu' il prezzo riservato ai suoi creator. Stessa cassa
     della .discord-pending qui sopra (l'altro avviso che puo' comparire nella
     stessa card) ma nel viola del marchio invece che nel blu di Discord.
     :not([hidden]) obbligatorio sul display: un display esplicito d'autore
     vince sul display:none dell'attributo, e la fascia vuota comparirebbe a
     chiunque apra la registrazione. */
  .agency-invite:not([hidden]){
    display:flex; align-items:center; gap: 12px;
    padding: 14px 16px; margin-bottom: 22px;
    border: 1px solid rgba(168,85,247,0.45); border-radius: 12px;
    background: rgba(168,85,247,0.10);
  }
  /* Riquadro con l'iniziale, e il logo vero ci va sopra: stesso meccanismo
     dell'agenzia in barra laterale (vedi .dash-agency-logo). */
  .agency-invite-logo{
    position:relative; overflow:hidden; flex:none;
    width: 38px; height: 38px; border-radius: 10px;
    display:flex; align-items:center; justify-content:center;
    background: rgba(214,190,245,0.06); border: 1px solid var(--line);
    color: var(--muted); font-family: 'Baloo 2', sans-serif; font-weight: 800; font-size: 15px;
  }
  .agency-invite-logo-img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  .agency-invite-text{ min-width:0; }
  .agency-invite-name{ margin:0; font-size: 13.5px; font-weight: 700; color: var(--ink); }
  .agency-invite-offer{ margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }

  .otp-group{ display:grid; grid-template-columns: repeat(6, 1fr); gap: 8px; }
  .otp-box{
    aspect-ratio: 3 / 4; width:100%; padding:0;
    text-align:center; background: rgba(214,190,245,0.03); border: 1px solid var(--line); border-radius: 10px;
    color: var(--ink); font-size: 22px; font-weight:700; font-family:'JetBrains Mono', monospace;
    transition: border-color .2s ease, background .2s ease;
  }
  .otp-box:focus{ outline:none; border-color: var(--blue); background: rgba(185,107,250,0.05); }
  .otp-box[aria-invalid="true"]{ border-color: var(--red); }
  .auth-actions-row{ display:flex; justify-content:space-between; align-items:center; font-size: 13px; margin-top: -8px; flex-wrap:wrap; gap: 8px; }
  .auth-actions-row .link-btn{ background:none; border:none; padding:0; cursor:pointer; font:inherit; color: var(--blue); font-weight:500; }
  .auth-actions-row .link-btn:hover{ text-decoration: underline; }
  .auth-actions-row .link-btn:disabled{ opacity:0.6; cursor:not-allowed; text-decoration:none; }

  @media (max-width: 380px){
    .otp-box{ font-size: 18px; }
  }

  @media (max-width: 520px){
    .auth-section{ padding: 48px 0; }
    .auth-card{ padding: 30px 22px; border-radius: 16px; }
  }

  /* ---------- ROOT REDIRECT PAGE ---------- */
  .redirect-page{
    display:flex; align-items:center; justify-content:center;
    min-height: 100vh; text-align:center; padding: 20px;
  }
  .redirect-page a{ color: var(--blue); text-decoration: underline; }

  /* ---------- LEGAL / COOKIE POLICY ---------- */
  .legal{ padding: 64px 0 88px; }
  .legal-wrap{ max-width: 760px; }
  .legal h1{ font-size: clamp(30px, 4vw, 42px); margin: 10px 0 6px; }
  .legal-updated{ color: var(--muted); font-size: 13px; font-family:'JetBrains Mono'; margin-bottom: 34px; }
  .legal h2{ font-family:'Baloo 2'; font-size: 20px; margin: 36px 0 12px; }
  .legal p{ color: var(--muted); font-size: 15px; line-height: 1.7; }
  .legal code{ font-family:'JetBrains Mono'; background: rgba(214,190,245,0.06); padding: 2px 6px; border-radius: 5px; color: var(--ink); font-size: 13px; }
  .legal p + p{ margin-top: 10px; }
  .legal ul{ color: var(--muted); font-size: 15px; line-height: 1.7; margin: 6px 0 12px; padding-left: 22px; list-style: disc; }
  .legal ul li{ margin: 4px 0; }
  .legal h3{ font-family:'Baloo 2'; font-size: 16px; margin: 20px 0 8px; color: var(--ink); }

  /* Guide passo-passo (es. tutorial-tntcube.html): stessa base tipografica di
     .legal, con un numero cerchiato invece del semplice elenco puntato. */
  .tutorial-steps{ display:flex; flex-direction:column; gap: 30px; margin: 30px 0 44px; }
  .tutorial-step{ display:flex; gap: 18px; align-items:flex-start; }
  .tutorial-step-num{
    flex-shrink:0; width: 34px; height: 34px; border-radius: 50%;
    background: var(--red); color:#F1E7FF; font-family:'Baloo 2'; font-weight:700; font-size: 15px;
    display:flex; align-items:center; justify-content:center; margin-top: 2px;
  }
  .tutorial-step-body{ flex:1; min-width:0; }
  .tutorial-step-body h3{ margin: 0 0 8px; }
  .tutorial-step-body p{ margin:0; }
  .tutorial-step-body p + p{ margin-top: 8px; }
  .tutorial-step-body .auth-error{ margin-top: 12px; }

  /* Codice profilo condivisibile (sezione "Profilo regali pronto" della pagina
     Survival): va letto da uno schermo e ricopiato a mano, quindi monospazio e
     piu' grande del testo intorno. user-select:all perche' un doppio clic ne
     prenda tutti e dieci i caratteri invece di fermarsi a meta'. */
  /* Il codice con il suo pulsante Copia accanto: in riga finche' ci stanno,
     a capo su schermo stretto invece di stringere il codice fino a spezzarlo. */
  .share-code-row{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin:0 0 18px; }

  .share-code{
    display:inline-block; font-family:'JetBrains Mono', monospace; font-size:15px;
    letter-spacing:.08em; padding:3px 9px; border-radius:6px;
    background: rgba(185,107,250,0.16); color: var(--ink); user-select:all;
  }

  .table-scroll{ overflow-x: auto; margin: 18px 0; border-radius: 12px; border: 1px solid var(--line); }
  .cookie-table{ width: 100%; border-collapse: collapse; min-width: 560px; background: var(--bg-panel); }
  .cookie-table th, .cookie-table td{ text-align:left; padding: 12px 16px; font-size: 13.5px; border-bottom: 1px solid var(--line); vertical-align: top; }
  .cookie-table th{ font-family:'JetBrains Mono'; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
  .cookie-table td{ color: var(--muted); }
  .cookie-table td code{ color: var(--ink); }
  .cookie-table tr:last-child td{ border-bottom: none; }

  /* ---------- COOKIE CONSENT BANNER ---------- */
  .cookie-banner{
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 100;
    background: rgba(23,10,40,0.97);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    padding: 18px 0;
    padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    animation: cookie-banner-in .3s ease;
  }
  @keyframes cookie-banner-in{ from{ transform: translateY(100%); } to{ transform: translateY(0); } }
  .cookie-banner-inner{
    display:flex; align-items:center; justify-content:space-between; gap: 24px; flex-wrap: wrap;
  }
  .cookie-banner-text{ color: var(--muted); font-size: 13.5px; max-width: 640px; flex: 1 1 320px; }
  .cookie-banner-actions{ display:flex; align-items:center; gap: 20px; flex-shrink: 0; }
  .cookie-banner-btn{ padding: 10px 20px; font-size: 13.5px; }

  @media (max-width: 600px){
    .cookie-banner-inner{ flex-direction: column; align-items: stretch; text-align: center; }
    .cookie-banner-actions{ justify-content: center; }
  }

  /* ---------- 404 ---------- */
  .error-404, .error-403{
    min-height: calc(100vh - 148px);
    display:flex; align-items:center;
    padding: 90px 0;
    text-align:center;
    border-bottom: none;
  }
  .error-404-wrap, .error-403-wrap{ display:flex; flex-direction:column; align-items:center; }
  .error-404 .eyebrow, .error-403 .eyebrow{ margin-bottom: 28px; }
  .error-code{
    font-family:'Baloo 2'; font-weight:700; line-height:1;
    font-size: clamp(90px, 18vw, 180px);
    background: linear-gradient(135deg, var(--blue), var(--red));
    -webkit-background-clip: text; background-clip: text; color: transparent;
    filter: drop-shadow(0 0 34px rgba(185,107,250,0.25)) drop-shadow(0 0 34px rgba(124,31,212,0.2));
  }
  .error-404 h1, .error-403 h1{ font-size: clamp(26px, 3.4vw, 36px); margin: 8px 0 16px; }
  .error-404 .lead, .error-403 .lead{ max-width: 460px; margin-left:auto; margin-right:auto; }
  .error-404 .hero-ctas, .error-403 .hero-ctas{ justify-content:center; margin-top: 34px; }

  /* ---------- LANGUAGE DROPDOWN ---------- */
  /* Raggruppa il selettore lingua e la CTA: stanno insieme a destra dell'header,
     fuori da .nav-links, così restano visibili anche col menu mobile chiuso. */
  .nav-right{ display:flex; align-items:center; gap:14px; }
  .lang-dropdown{ position:relative; }
  .lang-dropdown-btn{
    display:inline-flex; align-items:center; gap:6px; list-style:none; cursor:pointer;
    color: var(--muted); border: 1px solid var(--line); border-radius:999px; padding: 7px 11px;
    transition: color .2s ease, border-color .2s ease;
  }
  .lang-dropdown-btn::-webkit-details-marker{ display:none; }
  .lang-dropdown-btn::after{ content:'▾'; font-size:9px; opacity:.7; }

  /* Bandierine: SVG incorporate come data URI (nessuna richiesta esterna,
     compatibile con la CSP del sito senza doverla allentare). */
  .fi{
    display:inline-block; width:1.2em; height:0.9em; border-radius:2px;
    background-size: cover; background-position:50%; background-repeat:no-repeat;
    box-shadow: 0 0 0 1px rgba(214,190,245,0.15); flex-shrink:0;
  }
  .fi-it{
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Crect width='1' height='2' fill='%23009246'/%3E%3Crect x='1' width='1' height='2' fill='%23fff'/%3E%3Crect x='2' width='1' height='2' fill='%23ce2b37'/%3E%3C/svg%3E");
  }
  .fi-es{
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Crect width='3' height='2' fill='%23aa151b'/%3E%3Crect y='0.5' width='3' height='1' fill='%23f1bf00'/%3E%3C/svg%3E");
  }
  .fi-gb{
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 30'%3E%3Crect width='60' height='30' fill='%2300247d'/%3E%3Cpath d='M0,0 L60,30 M60,0 L0,30' stroke='%23fff' stroke-width='6'/%3E%3Cpath d='M0,0 L60,30 M60,0 L0,30' stroke='%23cf142b' stroke-width='2'/%3E%3Cpath d='M30,0 V30 M0,15 H60' stroke='%23fff' stroke-width='10'/%3E%3Cpath d='M30,0 V30 M0,15 H60' stroke='%23cf142b' stroke-width='6'/%3E%3C/svg%3E");
  }
  .fi-fr{
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Crect width='1' height='2' fill='%230055A4'/%3E%3Crect x='1' width='1' height='2' fill='%23fff'/%3E%3Crect x='2' width='1' height='2' fill='%23EF4135'/%3E%3C/svg%3E");
  }
  .lang-dropdown:hover .lang-dropdown-btn,
  .lang-dropdown[open] .lang-dropdown-btn{ color: var(--ink); border-color: rgba(185,107,250,0.4); }
  .lang-dropdown-list{
    position:absolute; top: calc(100% + 8px); right:0; z-index:20; min-width: 150px;
    display:flex; flex-direction:column; gap:2px; padding:6px;
    background: var(--bg-panel); border:1px solid var(--line); border-radius:10px;
    box-shadow: 0 16px 34px rgba(7,2,13,0.5);
  }
  .lang-dropdown-list a{
    display:flex; align-items:center; gap:9px;
    padding: 8px 10px; border-radius:6px; font-size: 14.5px; font-weight:500;
    color: var(--muted); transition: color .2s ease, background .2s ease;
  }
  .lang-dropdown-list a:hover{ color: var(--ink); background: rgba(214,190,245,0.06); }

  /* ---------- DASHBOARD / APP SHELL ---------- */
  /* Dashboard e admin sono un'app a sé, non pagine di marketing: niente header
     né footer del sito, solo una sidebar persistente a tutta altezza + il
     contenuto della pagina corrente. */
  .app-shell{ display:flex; min-height:100vh; align-items:stretch; }
  @media (max-width: 860px){ .app-shell{ flex-direction:column; } }

  .app-sidebar{
    width: 264px; flex-shrink:0; display:flex; flex-direction:column;
    background: var(--bg-panel); border-right: 1px solid var(--line);
    padding: 22px 18px; position:sticky; top:0; height:100vh; overflow-y:auto;
  }
  @media (max-width: 860px){ .app-sidebar{ position:static; width:auto; height:auto; border-right:none; border-bottom:1px solid var(--line); padding: 16px 16px 14px; } }

  /* justify-content:center centra il GRUPPO logo+testo nella colonna, non il
     testo dentro di sé: nome e sottotitolo restano allineati fra loro a
     sinistra del proprio blocco, accanto al logo, come è giusto che sia.
     Il padding orizzontale va a zero: serviva a far respirare il blocco
     appoggiato al bordo sinistro, ma su un elemento centrato sposterebbe solo
     il centro. */
  .app-sidebar-brand{
    display:flex; align-items:center; justify-content:center; gap:10px;
    text-decoration:none; color:inherit;
    padding: 4px 0 18px; margin-bottom: 14px; border-bottom: 1px solid var(--line);
  }
  .app-sidebar-logo{ width:auto; height:34px; border-radius:0; object-fit:contain; flex-shrink:0; }
  .app-sidebar-brand-name{ display:block; font-family:'Baloo 2'; font-weight:700; font-size:16px; }
  .app-sidebar-brand-sub{ display:block; font-size:11.5px; color: var(--muted); }

  .dash-nav{
    display:flex; flex-direction:column; justify-content:flex-start; align-items:stretch;
    gap:2px; flex:1; padding:0; margin:0; max-width:none;
  }
  .dash-nav-btn{
    display:flex; align-items:center; gap:10px;
    text-align:left; background:transparent; border:none; color: var(--muted);
    font-family:'Nunito Sans', sans-serif; font-size: 14px; font-weight:500; padding: 10px 12px;
    border-radius: 8px; cursor:pointer; transition: background .2s ease, color .2s ease;
    text-decoration:none;
  }
  .dash-nav-btn:hover{ color: var(--ink); background: rgba(214,190,245,0.04); }
  .dash-nav-btn.active{ color: var(--ink); background: rgba(185,107,250,0.12); }
  .dash-nav-btn .nav-icon{ width:18px; height:18px; flex-shrink:0; opacity:.85; }
  .dash-nav-btn[hidden]{ display:none; }
  /* Pallino "nuovi annunci" accanto ad Aggiornamenti: rosso vero (non
     var(--red), che nel tema di questo sito è in realtà un viola scuro usato
     per le azioni distruttive) — qui serve un colore che stacchi dalla
     palette viola per farsi notare come notifica. */
  .dash-nav-dot{
    width:8px; height:8px; border-radius:50%; background:#FF3B30;
    box-shadow: 0 0 6px 1px rgba(255,59,48,0.7);
    flex-shrink:0;
  }
  .dash-nav-dot[hidden]{ display:none; }

  .app-sidebar-footer{
    display:flex; flex-direction:column; gap:10px;
    margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line);
  }
  .app-discord-btn{
    display:flex; align-items:center; justify-content:center; gap:8px;
    background:#7C3AED; color:#F1E7FF !important; text-decoration:none;
    font-weight:600; font-size:13.5px; padding:10px 12px; border-radius:8px;
    transition: filter .2s ease;
  }
  .app-discord-btn:hover{ filter: brightness(1.12); }
  .app-discord-btn .nav-icon{ width:17px; height:17px; }

  /* Su mobile la sidebar verticale occuperebbe da sola tutto lo schermo prima
     di arrivare al contenuto: qui diventa una barra compatta con la nav a
     scorrimento orizzontale (stile tab bar), invece di restare impilata.
     ATTENZIONE ALLA POSIZIONE: questo blocco stava PRIMA delle regole base di
     .dash-nav/.app-sidebar-footer qui sopra. A parità di specificità vince
     l'ultima regola scritta, quindi la versione a colonna le sovrascriveva
     tutte e la barra compatta non è mai esistita: su telefono si scorrevano
     otto voci di menu prima di vedere il contenuto. Va tenuto DOPO. */
  @media (max-width: 860px){
    .app-sidebar-brand{ padding: 0 0 14px; margin-bottom: 12px; }
    .dash-nav{
      flex-direction: row; flex: none; overflow-x: auto; -webkit-overflow-scrolling: touch;
      gap: 6px; margin: 0 -16px 12px; padding: 0 16px 4px;
    }
    .dash-nav-btn{ flex-shrink: 0; white-space: nowrap; padding: 9px 14px; }
    .app-sidebar-footer{
      flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between;
      margin-top: 12px; padding-top: 12px; gap: 10px 14px;
    }
    .app-discord-btn{ flex: 1 1 auto; min-width: 120px; }
    .dash-user{ order: 1; flex: 1 1 auto; min-width: 160px; }
    /* Solo il pulsante Esci della barra laterale (admin.html): quello della
       barra superiore della dashboard non deve allargarsi a tutta riga. */
    .app-sidebar-footer .dash-logout{ order: 4; flex: 1 1 auto; min-width: 120px; }
  }

  /* Pulsante "Connetti" overlay (classifiche top regali/top like), sopra il
     pulsante Discord nel footer della sidebar: stessa forma a pillola, ma
     outline finché non è collegato e pieno (accento blu) quando lo è. */
  .app-overlay-btn{
    display:flex; align-items:center; justify-content:center; gap:8px;
    background: transparent; color: var(--ink); border: 1px solid var(--line);
    font-weight:600; font-size:13.5px; padding:10px 12px; border-radius:8px;
    cursor:pointer; font-family:inherit; transition: filter .2s ease, border-color .2s ease, background .2s ease;
  }
  .app-overlay-btn .nav-icon{ width:17px; height:17px; }
  .app-overlay-btn:hover{ border-color: rgba(214,190,245,0.28); }
  .app-overlay-btn[data-connected="1"]{ background: var(--blue); border-color: var(--blue); color:#F1E7FF; }
  .app-overlay-btn[data-connected="1"]:hover{ filter: brightness(1.12); }
  .app-overlay-btn:disabled{ opacity:.5; cursor:not-allowed; }
  .app-overlay-btn:disabled:hover{ border-color: var(--line); }


  .dash-user{ display:flex; align-items:center; gap:12px; padding: 4px 2px; }
  .dash-avatar{
    width: 38px; height:38px; border-radius:50%; flex-shrink:0;
    background: linear-gradient(135deg, var(--blue), var(--red));
    display:flex; align-items:center; justify-content:center;
    font-family:'Baloo 2'; font-weight:700; font-size: 15px; color:#0E0518;
  }
  .dash-user-email{ font-size: 12.5px; font-weight:600; word-break: break-all; }
  .dash-role-badge{ margin-top:4px; }

  .badge{
    display:inline-flex; align-items:center; gap:5px; font-family:'JetBrains Mono'; font-size: 10.5px;
    text-transform:uppercase; letter-spacing:0.05em; padding: 3px 9px; border-radius:999px;
    border: 1px solid var(--line); color: var(--muted);
  }
  .badge-admin{ color: var(--red); border-color: rgba(124,31,212,0.4); background: rgba(124,31,212,0.08); }
  .badge-active{ color: var(--blue); border-color: rgba(185,107,250,0.4); background: rgba(185,107,250,0.08); }
  .badge-inactive{ color: var(--muted); }
  .badge-trial{ color: #FFB020; border-color: rgba(255,176,32,0.4); background: rgba(255,176,32,0.08); }
  /* Abbonato: verde, per distinguerlo a colpo d'occhio sia dall'admin (viola)
     sia dalla prova (arancione). Chi paga e chi è in prova hanno gli stessi
     permessi, ma per lo staff sono due cose diverse. */
  .badge-subscriber{ color: #4ADE80; border-color: rgba(74,222,128,0.4); background: rgba(74,222,128,0.08); }

  .dash-logout{
    display:flex; align-items:center; justify-content:center; gap:8px;
    background:transparent; border: 1px solid var(--line); color: var(--muted);
    font-family:'Nunito Sans', sans-serif; font-size: 13.5px; font-weight:500;
    padding: 10px 12px; border-radius: 8px; cursor:pointer; transition: border-color .2s ease, color .2s ease;
  }
  .dash-logout:hover{ border-color: var(--red); color: var(--ink); }
  .dash-logout .nav-icon{ width:16px; height:16px; }

  .app-main{ flex:1; min-width:0; padding: 44px 48px; }
  @media (max-width: 600px){ .app-main{ padding: 28px 20px; } }
  .app-main-wrap{ max-width: 1120px; }

  .dash-panel h1{ font-size: clamp(22px, 2.6vw, 28px); margin-bottom: 8px; }
  .dash-panel > .dash-sub{ color: var(--muted); font-size: 14px; margin-bottom: 28px; }

  .dash-loading{ color: var(--muted); font-family:'JetBrains Mono'; font-size: 13px; }

  /* Info account: card a griglia (si adatta alla larghezza disponibile)
     invece della lista stretta impilata di prima, più scansionabile a colpo
     d'occhio. Riusata anche da #billing-plan-grid nel tab Pagamenti. */
  .profile-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; max-width: none; }
  .profile-item{
    display:flex; flex-direction:column; gap:6px;
    padding: 16px 18px; border-radius: 12px;
    background: var(--bg-panel-2); border: 1px solid var(--line);
    transition: border-color .2s ease, transform .2s ease;
  }
  .profile-item:hover{ border-color: rgba(168,85,247,0.35); transform: translateY(-2px); }
  .profile-label{ font-family:'JetBrains Mono'; font-size: 11px; color: var(--muted); text-transform:uppercase; letter-spacing:0.05em; }
  .profile-value{ font-size: 16px; font-weight:600; }

  .sub-card{
    border: 1px solid var(--line); border-radius: 14px; padding: 24px; max-width: 460px;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
  }
  .sub-status-row{ display:flex; align-items:center; justify-content:space-between; margin-bottom: 14px; }
  .sub-status-row h3{ font-size:16px; }
  .sub-note{ color: var(--muted); font-size: 12.5px; margin-top: 18px; padding-top:16px; border-top: 1px solid var(--line); }

  /* Piani disponibili nel pannello Abbonamento: li vede solo chi non ha un
     abbonamento attivo (li scopre renderSubscription in js/dashboard.js). */
  .sub-plans{ margin-top: 28px; }
  .sub-plans-title{ font-size: 16px; margin-bottom: 6px; }
  .sub-plans-sub{ color: var(--muted); font-size: 13px; margin-bottom: 18px; }
  .sub-plans-grid{
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px; max-width: 1000px;
  }
  @media (max-width: 1000px){ .sub-plans-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 520px){ .sub-plans-grid{ grid-template-columns: 1fr; } }
  .sub-plan{
    display: flex; flex-direction: column; gap: 8px; padding: 20px;
    border: 1px solid var(--line); border-radius: 16px;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
    transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  }
  .sub-plan:hover{
    border-color: rgba(214,190,245,0.18); transform: translateY(-2px);
    box-shadow: 0 18px 40px rgba(0,0,0,0.4);
  }
  .sub-plan.is-featured{ border-color: rgba(168,85,247,0.4); }
  .sub-plan-name{ font-size: 14px; }
  .sub-plan-price{ font-family:'Baloo 2', sans-serif; font-size: 24px; font-weight: 800; line-height: 1.1; }
  .sub-plan-price span{
    display: block; margin-top: 3px;
    font-family:'Nunito Sans', sans-serif; font-size: 12px; font-weight: 600; color: var(--muted);
  }
  /* flex:1 sulla nota tiene i tre pulsanti allineati anche quando le note
     occupano un numero di righe diverso. */
  .sub-plan-note{ flex: 1; font-size: 12.5px; color: var(--muted); }
  .sub-plan-cta{ width: 100%; justify-content: center; margin-top: 4px; }
  .sub-plans-foot{ max-width: 760px; margin-top: 16px; font-size: 12px; color: var(--muted); }

  .connections-card{
    border: 1px solid var(--line); border-radius: 14px; padding: 24px; max-width: 460px;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
    margin-top: 18px;
  }
  .connections-card h3{ font-size:16px; margin-bottom: 6px; }
  .connections-sub{ color: var(--muted); font-size: 12.5px; margin-bottom: 20px; }

  /* --- Card "Account Discord" (dashboard → Il mio profilo) --- */
  /* Elenco di cosa fa il collegamento, al posto di un paragrafo unico: sono
     tre effetti distinti e indipendenti (entri nel server, ricevi il ruolo,
     accedi col pulsante), e in fila si leggono a colpo d'occhio invece di
     doverli estrarre da una frase lunga. */
  .discord-perks{
    list-style: none; margin: 0 0 20px; padding: 0;
    display:flex; flex-direction:column; gap: 9px;
  }
  .discord-perks li{
    display:flex; align-items:flex-start; gap: 9px;
    font-size: 12.5px; color: var(--muted); line-height: 1.5;
  }
  /* Spunta in blurple: lega visivamente l'elenco al pulsante Discord sotto,
     senza ripetere il logo tre volte. flex-shrink:0 e il margin-top ottico la
     tengono allineata alla prima riga anche quando il testo va a capo. */
  .discord-perks svg{
    width: 15px; height: 15px; flex-shrink: 0; margin-top: 2px;
    stroke: #5865F2; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round;
  }
  /* Riga di stato ("Collegato come …" / "Nessun account collegato"): staccata
     dall'elenco e più marcata, è l'unica parte della card che cambia. */
  .discord-status{
    display:flex; align-items:center; gap: 9px;
    padding: 12px 14px; margin-bottom: 16px;
    border: 1px solid var(--line); border-radius: 10px;
    background: rgba(88,101,242,0.06);
    font-size: 13.5px; font-weight: 600; color: var(--ink);
  }
  /* Pallino di stato: verde collegato, grigio no. È ridondante col testo di
     proposito — chi scorre la pagina vede lo stato senza leggere. */
  .discord-dot{ width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
  .discord-status.is-linked{ border-color: rgba(88,101,242,0.45); }
  .discord-status.is-linked .discord-dot{ background: #3BA55D; box-shadow: 0 0 8px rgba(59,165,93,0.6); }
  .discord-role-line{ font-size: 12px; color: var(--muted); margin: -8px 0 16px; line-height: 1.5; }
  .discord-actions{ display:flex; gap: 10px; flex-wrap: wrap; }

  /* Tab "Aggiornamenti": elenco a piena larghezza (non una griglia di card
     come .connections-card, i messaggi variano troppo in lunghezza). */
  .announcement-list{ display:flex; flex-direction:column; gap:14px; }
  .announcement-item{
    border: 1px solid var(--line); border-radius: 14px; padding: 20px 24px;
    background: linear-gradient(180deg, var(--bg-panel-2), var(--bg-panel));
  }
  .announcement-head{ display:flex; align-items:baseline; justify-content:space-between; gap:14px; margin-bottom:10px; }
  .announcement-head h3{ font-size:15px; }
  .announcement-date{ color: var(--muted); font-size: 12px; font-family:'JetBrains Mono'; white-space:nowrap; }
  .announcement-badges{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
  .announcement-category{
    display:inline-block; padding:3px 10px; border-radius:999px;
    background: rgba(185,107,250,0.12); border:1px solid rgba(185,107,250,0.35);
    color:#E6D5FF; font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.02em;
  }
  .announcement-version{
    display:inline-block; padding:3px 10px; border-radius:999px;
    background: rgba(255,255,255,0.06); border:1px solid var(--line);
    color: var(--muted); font-size:11px; font-weight:600; font-family:'JetBrains Mono';
  }
  .announcement-body{ color: var(--muted); font-size: 13.5px; line-height:1.6; white-space:pre-wrap; }

  .connections-form{ display:flex; flex-direction:column; gap: 14px; }
  .connections-form .btn{ align-self:flex-start; }

  /* Collegamenti + Cambia password affiancate su schermi larghi, per non
     lasciare metà pagina vuota con card singole da 460px. */
  .profile-cards-grid{ display:grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 34px; max-width: none; }
  .profile-cards-grid .connections-card{ margin-top:0; max-width:none; }

  /* Riquadro "Il Mio Piano", in cima a Home. Le due righe riusano
     .profile-item per non inventare un'altra forma, ma dentro una card i loro
     bordo e sfondo farebbero una scatola dentro la scatola: qui si spengono e
     resta la sola coppia etichetta/valore, separata da una riga. */
  .home-plan-card .profile-item{
    padding: 10px 0; border: none; background: none; border-radius: 0;
  }
  .home-plan-card .profile-item:hover{ border-color: transparent; transform: none; }
  .home-plan-card .profile-item + .profile-item{ border-top: 1px solid var(--line); }
  .home-plan-card .btn{ width: 100%; margin-top: 16px; }
  @media (max-width: 760px){ .profile-cards-grid{ grid-template-columns: 1fr; } }

  .form-message{ border-radius: 10px; padding: 12px 14px; font-size: 13px; }
  .form-message.is-error{ background: rgba(124,31,212,0.10); border:1px solid rgba(124,31,212,0.4); color:#E3C8FF; }
  .form-message.is-success{ background: rgba(185,107,250,0.10); border:1px solid rgba(185,107,250,0.4); color:#E6D5FF; }

  /* ---------- TOAST (notifica in alto a destra, es. "Salvato automaticamente") ---------- */
  .toast-stack{
    position:fixed; top:20px; right:20px; z-index:100;
    display:flex; flex-direction:column; gap:10px; align-items:flex-end;
  }
  .toast{
    display:flex; align-items:center; gap:8px; max-width:320px;
    background: var(--bg-panel); border-radius:12px; padding:13px 18px;
    font-size:13.5px; font-weight:500; color: var(--ink);
    box-shadow: 0 16px 34px rgba(7,2,13,0.5);
    animation: toast-in .25s ease;
  }
  .toast.is-leaving{ animation: toast-out .2s ease forwards; }
  .toast-success{ border:1px solid rgba(34,197,94,0.45); background: rgba(34,197,94,0.14); color:#B7F3CD; }
  .toast-error{ border:1px solid rgba(124,31,212,0.45); background: rgba(124,31,212,0.12); color:#E3C8FF; }
  @keyframes toast-in{ from{ opacity:0; transform: translateX(24px); } to{ opacity:1; transform: translateX(0); } }
  @keyframes toast-out{ from{ opacity:1; transform: translateX(0); } to{ opacity:0; transform: translateX(24px); } }

  /* Quattro per riga come i riquadri delle piattaforme qui sopra: l'elenco
     giochi di Roblox ne ha esattamente quattro e riempie la riga. */
  .dash-games{ display:grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
  @media (max-width: 1080px){ .dash-games{ grid-template-columns: 1fr 1fr; } }
  @media (max-width: 600px){ .dash-games{ grid-template-columns: 1fr; } }
  .game-card{ position:relative; }
  .game-card .game-body{ display:flex; flex-direction:column; gap:12px; }

  /* Pulsante in fondo, alla stessa altezza in tutte le card della riga.
     Le card sono cella di una griglia, quindi sono GIÀ alte uguale: quello
     che cambiava era dove finiva il testo dentro, perché le descrizioni sono
     lunghe diverse (due righe per Vertical Parkour, quattro per Spiral
     Parkour). Il pulsante partiva subito dopo l'ultima riga di testo e
     scendeva a scalini da una card all'altra.
     La catena che serve è tutta e tre: la card diventa una colonna flex, il
     corpo si prende l'altezza avanzata (flex:1), e margin-top:auto spinge il
     pulsante contro il fondo. Ne manca una e il pulsante resta attaccato al
     testo.
     align-self:stretch al posto di flex-start: il pulsante occupa tutta la
     larghezza della card come chiesto, e justify-content:center rimette la
     scritta in mezzo (.btn è inline-flex, altrimenti allargandosi il testo
     resterebbe a sinistra).
     Il selettore prende .btn e non .game-play-btn perché le card "In arrivo"
     hanno un pulsante disabilitato SENZA quella classe: con il selettore
     stretto sarebbero rimaste indietro, ed è proprio una di quelle che si
     vede fuori linea. Ambito .dash-games: la libreria della home ha le sue
     card e non va toccata. */
  .dash-games .game-card{ display:flex; flex-direction:column; }
  .dash-games .game-card .game-body{ flex:1; }
  .dash-games .game-body > .btn{ margin-top:auto; align-self:stretch; justify-content:center; }
  .game-card.locked .game-thumb{ filter: grayscale(0.6) brightness(0.5); }
  .game-lock-note{ font-family:'JetBrains Mono'; font-size:11.5px; color: var(--muted); }
  /* Stesso stile di .game-lock-note ma classe SEPARATA apposta: dashboard.js
     sovrascrive il testo di OGNI .game-lock-note con un messaggio generico di
     abbonamento/manutenzione (vedi wireSettings lì) - le note "serve un
     profilo" di Azioni & Eventi (js/azioni-eventi-panel.js) userebbero quel
     testo sbagliato se condividessero la classe. */
  .ae-lock-note{ font-family:'JetBrains Mono'; font-size:11.5px; color: var(--muted); }

  /* ---------- ADMIN ---------- */
  .admin-stats{ display:grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px; margin-bottom: 32px; }
  .admin-stat{ border:1px solid var(--line); border-radius: 12px; padding: 18px 20px; background: var(--bg-panel-2); }
  .admin-stat-num{ font-family:'Baloo 2'; font-size: 28px; font-weight:700; }
  .admin-stat-label{ font-family:'JetBrains Mono'; font-size: 11px; color: var(--muted); text-transform:uppercase; letter-spacing:0.05em; margin-top:4px; }
  /* Un profitto in negativo si legge rosso, non come tutti gli altri numeri: è
     l'unica cifra del tab Business che può voler dire "stiamo rimettendoci", e
     un meno davanti a un numero grande si sorvola con lo sguardo. --danger e non
     --red, che nonostante il nome è il viola del brand. */
  .admin-stat-num.is-negative{ color: var(--danger); }

  .admin-table{ width:100%; border-collapse: collapse; min-width: 900px; }
  .admin-table th, .admin-table td{ text-align:left; padding: 11px 14px; font-size: 13px; border-bottom: 1px solid var(--line); vertical-align: middle; }
  .admin-table th{ font-family:'JetBrains Mono'; font-size: 10.5px; text-transform:uppercase; letter-spacing:0.05em; color: var(--muted); }
  .admin-table td{ color: var(--muted); }
  .admin-table td.admin-email{ color: var(--ink); }

  /* Tabella utenti: testo in Nunito Sans, come tutto il resto del sito.
     Ereditava il monospace di .admin-table th solo nell'intestazione, ma il
     corpo restava a 13px con interlinea stretta e leggeva male su nove
     colonne. Qui: intestazione più leggibile (niente maiuscoletto monospace),
     righe più alte e più aria, email in evidenza e resto in grigio.
     Scoped a .admin-users-table per non toccare le altre tabelle admin
     (Business, Abbonamenti, Live) che vanno bene come sono. */
  .admin-users-table th{
    font-family:'Nunito Sans', sans-serif; font-size: 12px; font-weight: 700;
    text-transform: none; letter-spacing: 0.01em; color: var(--muted);
    padding: 12px 14px;
  }
  .admin-users-table td{
    font-family:'Nunito Sans', sans-serif; font-size: 13.5px; line-height: 1.45;
    padding: 14px; white-space: nowrap;
  }
  .admin-users-table td.admin-email{ font-weight: 600; }
  .admin-table-empty{ text-align:center; color: var(--muted); font-size: 13.5px; padding: 28px 14px !important; }

  /* La riga è cliccabile (porta alla scheda) ma non lo dava a vedere: aveva
     solo il cursore a manina. Ora si illumina al passaggio. */
  .admin-users-row:hover td{ background: rgba(168,85,247,0.06); }

  /* Colonna "Gestisci" ancorata al bordo destro: con dieci colonne la tabella
     scorre in orizzontale su quasi ogni schermo, e l'azione principale
     finiva fuori vista - bisognava scorrere per scoprire che esisteva.
     Sticky la tiene ferma mentre il resto scorre sotto, quindi lo sfondo deve
     essere pieno (var(--bg), lo stesso della pagina) e non trasparente,
     altrimenti le celle in transito si vedrebbero passare dietro. Il valore
     :hover è lo stesso rgba qui sopra appiattito su nero: un rgba semi-
     trasparente qui lascerebbe di nuovo trasparire quello che scorre. */
  .admin-users-table th:last-child,
  .admin-users-table td:last-child{
    position: sticky; right: 0; z-index: 1;
    background: var(--bg); border-left: 1px solid var(--line);
    text-align: right;
  }
  .admin-users-row:hover td:last-child{ background: #0A0410; }

  /* Campo di ricerca in cima al tab Utenti (ha preso il posto del riquadro
     "Aggiungi un admin"): la lente sta dentro il campo a sinistra, la X per
     svuotare a destra e compare solo quando c'è del testo. */
  .admin-search{ position:relative; max-width: 560px; margin-bottom: 10px; }
  .admin-search-icon{
    position:absolute; left:14px; top:50%; transform: translateY(-50%);
    width:17px; height:17px; color: var(--muted); pointer-events:none;
  }
  .admin-search input{
    width:100%; padding: 12px 42px 12px 40px; border-radius: 10px;
    border: 1px solid var(--line); background: var(--bg-panel); color: var(--ink);
    font-family:'Nunito Sans', sans-serif; font-size: 14px;
    transition: border-color .2s ease, background .2s ease;
  }
  .admin-search input::placeholder{ color: var(--muted); opacity:.75; }
  .admin-search input:focus{ outline:none; border-color: var(--blue); background: rgba(168,85,247,0.05); }
  /* Via la X nativa di <input type="search"> in WebKit: ce n'è già una nostra,
     e due crocette nello stesso campo sono una di troppo. */
  .admin-search input::-webkit-search-cancel-button{ -webkit-appearance:none; appearance:none; }
  .admin-search-clear{
    position:absolute; right:10px; top:50%; transform: translateY(-50%);
    width:26px; height:26px; border-radius:50%; border:none; background:transparent;
    color: var(--muted); font-size:18px; line-height:1; cursor:pointer;
  }
  .admin-search-clear:hover{ color: var(--ink); background: rgba(168,85,247,0.12); }
  .admin-search-count{ color: var(--muted); font-size: 12.5px; margin-bottom: 18px; }

  /* "Gestisci": unico pulsante rimasto nella colonna azioni, al posto dei tre
     di prima. Più visibile di un .admin-action-btn (è l'invito a entrare nella
     scheda) ma sempre compatto, perché sta in una cella di tabella. */
  /* .admin-row-actions è un flex: i pulsanti si allineavano al suo bordo
     sinistro, e il text-align:right della cella non li toccava (non vale per i
     figli di un flex). Risultato: "Visualizza", più lungo di "Gestisci",
     sbordava a destra rispetto agli altri. Centrati, e con una larghezza
     minima uguale per tutti, la colonna resta in riga qualunque sia
     l'etichetta. */
  .admin-users-table .admin-row-actions{ justify-content: center; }
  .admin-manage-btn{
    font-family:'Nunito Sans', sans-serif; font-size: 12.5px; font-weight: 700;
    min-width: 108px; padding: 7px 16px; border-radius: 8px; cursor:pointer;
    white-space: nowrap; text-align: center;
    border: 1px solid rgba(168,85,247,0.45); background: rgba(168,85,247,0.10); color: var(--blue);
    transition: background .2s ease, border-color .2s ease, color .2s ease;
  }
  .admin-manage-btn:hover{ background: var(--blue); border-color: var(--blue); color:#fff; }
  /* Il proprio account: stesso pulsante ma neutro, perché lì si può solo
     guardare (le azioni le rifiuta il backend, vedi assertNotSelf).
     "Neutro" non vuol dire invisibile: il bordo era var(--line), cioè
     rgba(214,190,245,0.08) — su fondo nero non si vedeva, e il pulsante
     sembrava testo scritto lì. Ora ha un bordo e uno sfondo suoi, con lo
     stesso peso di quello viola: si legge come pulsante, solo senza il colore
     che invita all'azione. */
  .admin-manage-btn.is-self{
    border-color: rgba(182,160,207,0.45); background: rgba(214,190,245,0.06); color: var(--ink);
  }
  .admin-manage-btn.is-self:hover{ border-color: var(--blue); background: rgba(168,85,247,0.14); color: var(--ink); }
  /* Tab Live Analytics, colonna bridge: un badge per gioco (Minecraft/Roblox),
     impilati invece che affiancati — altrimenti due badge testuali nella stessa
     cella si affiancherebbero e andrebbero a capo in modo confuso. */
  .live-bridges-cell{ display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
  /* Tabella Azioni (tab Azioni & Eventi, admin): colonna checkbox/icona strette
     e pulsante di ordinamento per Nome dentro il suo <th>, stesso font della
     riga di intestazione .admin-table th ma esplicito perché un <button> non
     eredita il font di default. */
  .ae-col-check{ width: 40px; text-align:center; }
  /* text-align sul <th> va ripetuto con la specificità di .admin-table th
     (0,1,1), che allinea a sinistra tutte le intestazioni: senza, il "Tutto"
     della tabella Eventi resta a sinistra sopra una colonna di pulsanti
     centrati. */
  .admin-table th.ae-col-check, .admin-table th.ae-col-icon{ text-align:center; }
  /* Allargata da 52 a 130px: ora ci stanno i 4 pulsanti azione per riga
     (Play/Modifica/Duplica/Elimina), vedi actionRowToolsHtml in
     azioni-eventi-panel.js. */
  .ae-col-icon{ width: 150px; text-align:center; }
  /* Nome più largo (titolo azione, fino a 80 caratteri), Schermo/Durata più
     stretti (un solo numero corto ciascuno): Descrizione (ultima colonna,
     nessuna larghezza qui) recupera lo spazio lasciato libero da questi due. */
  #ae-actions-table th:nth-child(3), #ae-actions-table td:nth-child(3){ width: 320px; }
  #ae-actions-table th:nth-child(4), #ae-actions-table td:nth-child(4){ width: 84px; text-align:center; }
  #ae-actions-table th:nth-child(5), #ae-actions-table td:nth-child(5){ width: 84px; text-align:center; }
  /* Le due intestazioni corte non vanno a capo: "DURATA (S)" spezzato in due
     righe alzava tutta la riga di intestazione, e in spagnolo ("DURACIÓN
     (S)") succedeva a qualunque larghezza scelta a mano. Con nowrap la
     larghezza qui sopra fa da minimo e la colonna si prende quel che le
     serve. */
  #ae-actions-table th:nth-child(4), #ae-actions-table th:nth-child(5){ white-space: nowrap; }
  .ae-action-row-tools{ display:flex; gap:4px; justify-content:center; }
  .ae-action-tool-btn{
    width:22px; height:22px; border-radius:6px; border:1px solid var(--line); background:transparent;
    color: var(--muted); cursor:pointer; font-size:11px; display:flex; align-items:center; justify-content:center;
    transition: border-color .15s ease, color .15s ease;
  }
  .ae-action-tool-btn:hover{ border-color: rgba(185,107,250,0.45); color: var(--ink); }
  .ae-action-tool-btn:disabled{ opacity:0.35; cursor:not-allowed; }
  .ae-action-tool-btn.is-playing{ border-color: var(--blue); color: var(--blue); }
  .ae-action-delete-btn:hover{ border-color: var(--red); color: var(--red); }
  /* Intestazione ordinabile: Nome nelle Azioni, Utente e Trigger negli
     Eventi. La freccia resta ⇅ finche' la colonna non e' quella ordinata,
     poi diventa ▲/▼ — la scrive renderSortHeaders in azioni-eventi-panel.js.
     Il giro e' a tre: crescente, decrescente, nessun ordinamento. Serve la
     terza posizione perche' negli Eventi l'ordine dell'elenco E' l'ordine in
     cui il motore li valuta, e senza un modo di tornarci le frecce ▲▼ di
     riga resterebbero spente per sempre. */
  .ae-sort-btn{
    display:inline-flex; align-items:center; gap:5px; background:none; border:none; padding:0;
    color: var(--muted); font-family:'JetBrains Mono'; font-size: 10.5px; text-transform:uppercase;
    letter-spacing:0.05em; cursor:pointer; transition: color .15s ease;
  }
  .ae-sort-btn:hover{ color: var(--ink); }
  .ae-sort-btn.is-active{ color: var(--blue); }
  .ae-sort-arrow{ font-size: 10px; opacity:0.5; }
  .ae-sort-btn.is-active .ae-sort-arrow{ opacity:1; }

  /* Toolbar sopra le tabelle: "Nuova azione" e, solo con qualche riga
     spuntata, "Elimina azioni (N)". Entrambi a sinistra: lo space-between di
     prima teneva la casella di ricerca all'altro capo della riga, e quella
     casella non ha mai filtrato niente (nessun JS la ascoltava) — tolta. */
  .ae-actions-toolbar{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin: 14px 0; }
  .ae-actions-toolbar .btn{ font-size:13.5px; padding:10px 18px; }
  /* Spento: "Elimina azioni" finche' non c'e' niente di spuntato, "Nuova
     azione" finche' non c'e' un profilo. Nel foglio non esiste un
     .btn:disabled globale (e' una scelta: vedi .admin-contact-options), quindi
     senza questa regola i due restavano identici a quando si possono premere.
     Colori espliciti e non opacity: smorzato, il viola resta viola e il rosso
     resta rosso, e continuano a leggersi come comandi pronti. Il grigio dice
     "c'e', ma prima scegli qualcosa". */
  .ae-actions-toolbar .btn:disabled,
  .ae-actions-toolbar .btn:disabled:hover{
    background: rgba(214,190,245,0.04); border: 1px solid var(--line); color: var(--dim);
    cursor: not-allowed; box-shadow: none; transform: none; filter: none;
  }

  /* Tabelle Azioni/Eventi: bordo esterno e divisori tra colonne più marcati
     del filo appena accennato di .admin-table/.table-scroll usato altrove
     (lì il resto del layout basta già a farle riconoscere come tabelle;
     qui no). Scoped a queste due card per non toccare le altre .admin-table
     del sito (pannello Admin, sessioni Minecraft, ecc.). */
  #ae-actions-card .table-scroll, #ae-events-card .table-scroll{
    border-color: rgba(214,190,245,0.28);
  }
  #ae-actions-table th, #ae-actions-table td,
  #ae-events-table th, #ae-events-table td{
    border-right: 1px solid rgba(214,190,245,0.28);
    border-bottom-color: rgba(214,190,245,0.28);
  }
  #ae-actions-table th:last-child, #ae-actions-table td:last-child,
  #ae-events-table th:last-child, #ae-events-table td:last-child{
    border-right: none;
  }

  /* Scheda Azioni/Eventi ingrandita: titolo, tabella (intestazioni/celle,
     più respiro nel padding), ricerca e pulsante di ordinamento — stesso
     principio di scope di sopra (.table-scroll/i bordi), niente tocca
     .admin-table/.connections-card di base, condivise dal resto del
     pannello admin (utenti, sessioni Minecraft, ecc.). */
  /* Titolo di sezione (Azioni, Eventi, Schermi attivi, Simula eventi):
     piccolo, maiuscolo e spaziato invece del titolo da 19px di prima. Sono
     quattro nella stessa pagina e a corpo pieno competevano con il titolo
     del pannello; cosi' fanno da etichetta e il contenuto resta il primo a
     farsi leggere. Il maiuscolo lo mette il CSS, non l'HTML, perche' le
     stesse stringhe finiscono anche nei data-label della vista a schede. */
  .ae-section > h3{
    display:flex; align-items:center; gap:10px;
    font-family:'JetBrains Mono', monospace; font-size:12.5px; font-weight:600;
    text-transform:uppercase; letter-spacing:0.09em; color: var(--muted);
  }
  /* Contatore accanto a "Azioni"/"Eventi" (vedi renderActionsTable/
     renderEventsTable in azioni-eventi-panel.js): stesso linguaggio visivo
     di .badge-active, per riconoscerlo subito come "numero", non un'etichetta. */
  .ae-count-badge{
    display:inline-flex; align-items:center; justify-content:center;
    min-width:22px; height:22px; padding:0 7px; border-radius:999px;
    background: rgba(185,107,250,0.12); border:1px solid rgba(185,107,250,0.35);
    color: var(--blue); font-family:'JetBrains Mono'; font-size:12px; font-weight:600;
  }

  /* Freccette pagina sotto le tabelle Azioni/Eventi (vedi
     renderPaginationControls in azioni-eventi-panel.js), nascoste finché non
     servono (10 o meno righe) — stesso linguaggio visivo di
     .ae-action-tool-btn (bordo sottile, sfondo trasparente) per non
     introdurre un terzo stile di pulsante nella stessa scheda. */
  .ae-pagination{ display:flex; align-items:center; justify-content:center; gap:16px; margin-top:16px; }
  .ae-pagination-btn{
    width:30px; height:30px; border-radius:8px; border:1px solid var(--line); background:transparent;
    color: var(--muted); cursor:pointer; font-size:16px; line-height:1; display:flex; align-items:center; justify-content:center;
    transition: border-color .15s ease, color .15s ease;
  }
  .ae-pagination-btn:hover:not(:disabled){ border-color: rgba(185,107,250,0.45); color: var(--ink); }
  .ae-pagination-btn:disabled{ opacity:0.3; cursor:not-allowed; }
  .ae-pagination-label{ font-family:'JetBrains Mono'; font-size:12px; color: var(--muted); }
  #ae-actions-card .admin-table th, #ae-events-card .admin-table th,
  #ae-actions-card .admin-table td, #ae-events-card .admin-table td{
    padding: 13px 16px;
  }
  #ae-actions-card .admin-table th, #ae-events-card .admin-table th{ font-size:12px; }
  #ae-actions-card .admin-table td, #ae-events-card .admin-table td{ font-size:15px; }
  #ae-actions-card .ae-sort-btn, #ae-events-card .ae-sort-btn{ font-size:12px; }
  #ae-actions-card .ae-sort-arrow, #ae-events-card .ae-sort-arrow{ font-size:10px; }
  /* Pulsanti ▶✎⧉🗑️ per riga: 22px/11px era pensato per il testo piccolo di
     prima, ora sproporzionato per difetto rispetto al resto della scheda. */
  #ae-actions-card .ae-action-tool-btn, #ae-events-card .ae-action-tool-btn{
    width:26px; height:26px; font-size:13px;
  }
  /* Riquadro tratteggiato invece del solo testo centrato di .mc-empty-state
     di base: più chiaro come punto di partenza ("clicca Nuova azione/evento
     qui sopra") che come semplice messaggio di stato. */
  #ae-actions-card .mc-empty-state, #ae-events-card .mc-empty-state{
    font-size:14px; margin-top:4px; padding: 30px 16px;
    border: 1px dashed var(--line); border-radius:12px; background: rgba(214,190,245,0.02);
  }

  /* Interruttore "Attivo" della tabella Eventi (.ae-event-active-toggle,
     vedi renderEventsTable): un checkbox nativo qui sarebbe l'unico controllo
     "di sistema" della tabella, stona con .ae-action-tool-btn/.ae-count-badge
     tutti già ridisegnati — pillola con pallino che scorre invece del segno di
     spunta di .ae-action-option (quel linguaggio è per liste di scelte, qui è
     un solo on/off). */
  .ae-event-active-toggle{
    appearance:none; -webkit-appearance:none; width:36px; height:20px; border-radius:999px;
    background: rgba(214,190,245,0.08); border:1px solid var(--line); position:relative;
    cursor:pointer; flex-shrink:0; vertical-align:middle;
    transition: background .2s ease, border-color .2s ease;
  }
  .ae-event-active-toggle::after{
    content:''; position:absolute; top:2px; left:2px; width:14px; height:14px; border-radius:50%;
    background: var(--muted); transition: transform .2s ease, background .2s ease;
  }
  .ae-event-active-toggle:hover{ border-color: rgba(185,107,250,0.45); }
  /* Acceso in VERDE, non nel viola del tema: nella stessa riga ci sono già
     cinque comandi viola e il badge del conteggio: acceso e spento si
     distinguevano solo dalla posizione del pallino. Il verde è lo stesso
     --ok degli Schermi "Online" — nella pagina vuol dire sempre "sta
     funzionando adesso". */
  .ae-event-active-toggle:checked{ background: rgba(74,222,128,0.20); border-color:#4ADE80; }
  .ae-event-active-toggle:checked::after{ transform: translateX(16px); background:#4ADE80; }

  /* Finestrella "Nuova azione" (riquadro Azioni, admin): riusa .mc-prompt-
     overlay/.mc-prompt-modal come le altre modali del sito, ma di dimensione
     fissa (non si allarga/allunga col contenuto): width/height fissi invece
     di max-width/max-height da soli, così resta sempre della stessa
     grandezza. Se le sezioni aperte non ci stanno, scorre solo
     .ae-action-modal-scroll (titolo + le tre sezioni) — intestazione e
     pulsanti Annulla/Crea restano fissi in alto/basso, stesso schema già
     usato per "Personalizza overlay" (.overlay-style-modal più sotto).
     Selettore combinato (non solo .ae-action-modal) per battere in
     specificità .mc-prompt-modal{max-width:360px} più sotto nel foglio di
     stile, che altrimenti vincerebbe essendo dichiarato dopo. */
  .mc-prompt-modal.ae-action-modal{
    /* 700px, non più 960: su richiesta (2026-08) la finestrella è stretta e
       col testo grande — il contenuto è una pila verticale di sezioni, la
       larghezza in più era solo aria ai lati. */
    width: 700px; max-width: 92vw; height: 680px; max-height: 88vh;
    display:flex; flex-direction:column;
  }
  .ae-action-modal-scroll{
    flex:1 1 auto; min-height:0; overflow-y:auto; overflow-x:hidden;
    padding-right:4px; margin-right:-4px;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .ae-action-modal-scroll::-webkit-scrollbar{ width:8px; }
  .ae-action-modal-scroll::-webkit-scrollbar-track{ background: transparent; }
  .ae-action-modal-scroll::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  .ae-action-modal .mc-prompt-actions{ flex-shrink:0; padding-top:14px; }
  .ae-action-section{
    border:1px solid var(--line); border-radius:10px; margin-bottom:12px; overflow:hidden;
  }
  .ae-action-section-toggle{
    width:100%; display:flex; align-items:center; justify-content:space-between;
    background: rgba(214,190,245,0.03); border:none; padding:11px 14px; color:var(--ink);
    font-size:13.5px; font-weight:600; font-family:'Nunito Sans', sans-serif; cursor:pointer;
    transition: background .15s ease;
  }
  .ae-action-section-toggle:hover{ background: rgba(214,190,245,0.06); }
  .ae-action-section-caret{ color: var(--muted); font-size:11px; transition: transform .15s ease; }
  .ae-action-section.is-open .ae-action-section-caret{ transform: rotate(180deg); }
  .ae-action-section-body{ padding:8px; display:flex; flex-direction:column; gap:3px; }
  .ae-action-section-body[hidden]{ display:none; }
  .ae-action-option{
    display:flex; align-items:center; gap:8px; width:100%; text-align:left;
    border-radius:8px; padding:9px 10px; color:var(--ink);
    font-size:13px; font-family:'Nunito Sans', sans-serif; cursor:pointer; transition: background .15s ease;
  }
  .ae-action-option:hover{ background: rgba(214,190,245,0.06); }

  /* Checkbox/radio custom in stile TikForge, al posto del checkbox nativo
     del browser tinto solo con accent-color (unico controllo del tab ancora
     "di sistema" — colore/tendine/picker sono già tutti custom altrove nel
     sito). appearance:none toglie completamente il rendering nativo: da qui
     in poi bordo/sfondo/spunta sono nostri. Selettore unico condiviso da:
     - le caselle "Nuova azione" (.ae-action-option, incluse le radio
       "Aggiungi/Togli/Reimposta a zero" di Controllo overlay Win, che
       riusano la stessa classe);
     - "Ripetere in combo?" nel blocco Impostazioni aggiuntive;
     - i checkbox di riga/seleziona-tutto delle tabelle Azioni ed Eventi
       (entrambi dentro una cella .ae-col-check, stesso markup per le due
       tabelle: un solo selettore le copre entrambe senza toccare l'HTML). */
  .ae-action-option input[type="checkbox"],
  .ae-action-option input[type="radio"],
  #ae-combo-repeat-checkbox,
  .ae-col-check input[type="checkbox"]{
    appearance:none; -webkit-appearance:none;
    width:18px; height:18px; flex-shrink:0; cursor:pointer;
    border:1.5px solid var(--line); border-radius:5px;
    background: rgba(214,190,245,0.04); position:relative;
    transition: background .15s ease, border-color .15s ease;
  }
  .ae-action-option input[type="checkbox"]:hover,
  .ae-action-option input[type="radio"]:hover,
  #ae-combo-repeat-checkbox:hover,
  .ae-col-check input[type="checkbox"]:hover{ border-color: var(--blue); }
  .ae-action-option input[type="checkbox"]:checked,
  #ae-combo-repeat-checkbox:checked,
  .ae-col-check input[type="checkbox"]:checked{ background: var(--blue); border-color: var(--blue); }
  /* Spunta a "V" disegnata con un angolo di bordo ruotato (niente icona/SVG
     esterna): tecnica standard, si ridimensiona/ricolora con un CSS puro. */
  .ae-action-option input[type="checkbox"]:checked::after,
  #ae-combo-repeat-checkbox:checked::after,
  .ae-col-check input[type="checkbox"]:checked::after{
    content:""; position:absolute; left:6px; top:3px; width:4px; height:8px;
    border: solid var(--bg-panel); border-width:0 2px 2px 0; transform: rotate(45deg);
  }
  /* Stato "misto" della casella di intestazione: alcune righe della pagina
     spuntate, non tutte (lo mette syncSelectionUi in azioni-eventi-panel.js).
     Con appearance:none il trattino nativo non esiste più, e senza questa
     regola la casella resta identica a quella spenta — chi ha selezionato
     qualcosa vedeva l'intestazione vuota. Trattino invece della V, così i
     tre stati si distinguono a colpo d'occhio. */
  .ae-col-check input[type="checkbox"]:indeterminate{ background: var(--blue); border-color: var(--blue); }
  .ae-col-check input[type="checkbox"]:indeterminate::after{
    content:""; position:absolute; left:3px; right:3px; top:6.5px; height:2px;
    background: var(--bg-panel); border-radius:1px;
  }
  /* Radio (Controllo overlay Win): stesso box ma tondo, pallino pieno invece
     della spunta a V — la spunta ereditata sopra va annullata esplicitamente. */
  .ae-action-option input[type="radio"]{ border-radius:50%; }
  .ae-action-option input[type="radio"]:checked{ background: rgba(214,190,245,0.04); border-color: var(--blue); }
  .ae-action-option input[type="radio"]:checked::after{
    content:""; position:absolute; inset:4px; border-radius:50%; background: var(--blue);
    border:none; transform:none; width:auto; height:auto;
  }
  /* "Mostra alert": casella verde invece del viola di sistema delle altre
     opzioni, come nello screenshot di riferimento (invariato rispetto a
     prima, solo applicato allo sfondo pieno invece che al vecchio accent-color). */
  .ae-action-option-checkbox[data-action-type="alert"]:checked{ background:#22c55e; border-color:#22c55e; }
  .ae-action-section-empty{ color: var(--muted); font-size:12.5px; text-align:center; padding: 10px 4px; }
  .ae-action-option.is-selected{ background: rgba(185,107,250,0.16); color: var(--blue); }

  /* "Azioni Giochi" (vedi gameOptionHtml in azioni-eventi-panel.js): riquadri
     con l'immagine del gioco invece delle caselle testuali di
     .ae-action-option normali — stessa classe base (checkbox reale dentro
     la label, spostato in un angolo qui sotto) così is-selected/lettura al
     salvataggio restano quelli di .ae-action-option, non serve duplicarli. */
  .ae-game-tiles{ display:flex; flex-wrap:wrap; gap:10px; }
  .ae-action-option.ae-game-tile{
    position:relative; width:110px; flex:0 0 auto; flex-direction:column;
    align-items:center; justify-content:flex-start; gap:8px; text-align:center;
    padding:14px 10px 12px; border:1px solid var(--line); border-radius:12px;
    background: rgba(214,190,245,0.03);
  }
  .ae-action-option.ae-game-tile:hover{ background: rgba(214,190,245,0.06); }
  .ae-action-option.ae-game-tile.is-selected{ border-color: var(--blue); background: rgba(185,107,250,0.12); }
  .ae-game-tile input[type="checkbox"]{ position:absolute; top:8px; right:8px; }
  .ae-game-tile-thumb{
    width:64px; height:64px; border-radius:12px; flex-shrink:0;
    background-size:cover; background-position:center; background-color: rgba(214,190,245,0.06);
  }
  .ae-game-tile-name{ font-size:12.5px; line-height:1.3; }

  /* Pannello "Azioni nel gioco" (Azione/Quantità/Potenza per riga, vedi
     gameActionRowHtml in azioni-eventi-panel.js): una riga per azione
     configurata, stesso .ae-field-row di "Quantità"/"Schermo" altrove nel
     modal per i due campi numerici (già gestisce da solo lo stato hidden di
     Potenza, vedi .ae-field-row[hidden] più sopra). .ae-game-action-field
     è un .mc-action-field (width:100% di base): senza il limite qui
     allargherebbe la riga schiacciando Quantità/Potenza/✕, stesso motivo di
     #ae-tts-voice-field/#ae-event-gift-trigger. */
  .ae-game-action-row{
    display:flex; align-items:center; gap:10px; flex-wrap:wrap;
    padding:10px; margin-bottom:8px; border:1px solid var(--line); border-radius:10px;
    background: rgba(214,190,245,0.02);
  }
  .ae-game-action-field{ width:auto; min-width:150px; flex:1 1 150px; }
  .ae-game-action-quantity-row, .ae-game-action-power-row{ flex:0 0 auto; margin-bottom:0; }

  /* --- Argomenti del sottocomando Survival (vanillaArgsHtml) ---------------
     display:contents e non un contenitore vero: i campi devono stare nel flex
     della RIGA insieme alla tendina Azione e al cestino. Dentro un <div>
     normale si impilavano in colonna di fianco all'azione (e le regole flex
     qui sotto non avevano alcun effetto, perche' il genitore non era un flex
     container): "Give" veniva fuori come tre caselle incolonnate strette. */
  .ae-vanilla-args{ display:contents; }

  /* Le misure sono tarate sul modal (960px, meno 24+24 di padding e 10+10 della
     riga: ~890 utili). Il caso peggiore e' "Give", che ha tre argomenti:
     190 azione + 210 oggetto + 210 incantesimo + ~150 quantita' + 40 cestino +
     50 di gap = 850, quindi ci sta in riga. Sotto, va a capo da se'. */
  .ae-game-action-row > .ae-game-action-field{ flex:1 1 190px; min-width:165px; }
  .ae-vanilla-arg-row{ flex:0 0 auto; margin-bottom:0; }
  /* Le tendine (oggetto, mob, incantesimo, effetto, materiale) crescono; i campi
     numerici restano della loro larghezza, che gia' basta per un numero. */
  .ae-vanilla-arg-row.is-pick{ flex:1 1 210px; min-width:175px; }
  .ae-vanilla-arg-row.is-pick .ae-game-action-field{ flex:1 1 auto; min-width:0; width:auto; }
  /* Gli id del gioco in monospazio: sono identificatori, non parole, e cosi' si
     distinguono a colpo d'occhio dalle etichette tradotte intorno. */
  .ae-vanilla-arg-row.is-pick .mc-action-trigger-label,
  .ae-vanilla-arg-row.is-pick .mc-action-option{ font-family:'JetBrains Mono', monospace; font-size:12px; }
  .ae-game-action-remove-btn{ margin-left:auto; flex-shrink:0; }
  .ae-game-action-add-btn{ margin-top:6px; }
  /* Menu della tendina Azione: position:fixed invece di absolute (vedi
     positionGameActionMenu in azioni-eventi-panel.js) — una riga vicina al
     fondo di .ae-action-modal-scroll (overflow-y:auto) lo faceva tagliare
     dal bordo scorrevole. top/left/width impostati via JS all'apertura,
     qui servono solo ad azzerare i valori di .mc-action-menu di base
     (calc(100% + 4px)/0/0), che non hanno senso per un elemento fixed. */
  .ae-game-action-field .mc-action-menu{ position:fixed; top:0; left:0; right:auto; }
  /* Stesso fix per le tendine "Attiva azione"/"Azione Casuale" del modal
     Evento: dentro lo stesso .ae-action-modal-scroll, stavano in fondo al
     modal e il menu usciva sempre tagliato dal bordo scorrevole — vedi
     wireActionMultiSelectField in azioni-eventi-panel.js (riusa
     positionGameActionMenu per top/left/width via JS all'apertura). */
  #ae-event-actions-field .mc-action-menu,
  #ae-event-random-actions-field .mc-action-menu{ position:fixed; top:0; left:0; right:auto; }

  /* Blocco "Per quanto deve essere visibile?"/"Impostazioni aggiuntive" sotto
     le tre sezioni della finestrella Nuova azione (vedi visibilitySettingsHtml
     in azioni-eventi-panel.js): stesso per ogni azione, indipendente dai tipi
     scelti sopra. */
  .ae-visibility-block{ margin: 16px 0; }
  .ae-block-label{ font-size:13.5px; color: var(--ink); font-weight:600; margin-bottom:10px; }
  .ae-field-row{ display:flex; align-items:center; gap:10px; margin-bottom:8px; }
  /* Senza questa regola display:flex sopra vince sempre sullo stile di
     default del browser per [hidden] (le regole d'autore battono lo user
     agent stylesheet a prescindere dalla specificità): un .ae-field-row con
     l'attributo hidden (es. il campo utente di "Chi può attivare l'evento"
     in Azioni & Eventi, nascosto finché non si sceglie "Utente specifico")
     restava visibile lo stesso. Stesso schema già usato per .mc-action-menu[hidden]/
     .ae-audio-inline[hidden] più sotto. */
  .ae-field-row[hidden]{ display:none; }
  .ae-field-row-label{ font-size:13px; color: var(--muted); }
  .ae-field-row-checkbox{ cursor:pointer; }
  .ae-field-row-input{
    width:70px; flex-shrink:0; box-sizing:border-box; background: rgba(214,190,245,0.04);
    border:1px solid var(--line); border-radius:8px; padding:8px 10px; color:var(--ink);
    font-size:14px; font-family:'Nunito Sans', sans-serif;
  }
  .ae-field-row-input:focus{ outline:none; border-color: var(--blue); }
  .ae-field-row-suffix{ font-size:13px; color: var(--muted); }
  /* Link overlay OBS in fondo, centrato: solo un'anteprima testuale, vedi
     updateOverlayLinkPreview in azioni-eventi-panel.js. */
  .ae-overlay-link-block{ display:flex; justify-content:center; margin-top:12px; }
  .ae-overlay-link-block .mc-token-row{ margin:0; max-width:100%; }
  .ae-overlay-link-block .mc-token-value{ flex:1 1 auto; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

  /* Pannello "Riproduci Audio": non più una finestrella separata, uno spazio
     che si apre subito sotto la casella dentro "Azioni generali" (vedi
     audioInlinePanelHtml in azioni-eventi-panel.js). Rientro di 24px per
     allinearsi al testo della checkbox sopra (16px quadratino + 8px gap),
     non al bordo della riga. Tutto il pannello è zona di drop (non solo il
     pulsante Carica File), bordo tratteggiato che si accende trascinando sopra. */
  .ae-audio-inline{
    margin: 4px 0 10px 24px; padding: 12px; border-radius: 10px; border: 1px dashed var(--line);
    display:flex; flex-direction:column; gap:10px; transition: border-color .15s ease, background .15s ease;
  }
  .ae-audio-inline[hidden]{ display:none; }
  .ae-audio-inline.is-dragover{ border-color: var(--blue); background: rgba(185,107,250,0.08); }
  .ae-audio-volume-row{ display:flex; flex-direction:column; gap:6px; }
  .ae-audio-volume-label{ font-size:12.5px; color: var(--muted); }
  .ae-audio-volume-label strong{ color: var(--ink); }
  .ae-audio-volume-slider{ display:flex; align-items:center; gap:8px; font-size:14px; }
  .ae-audio-volume-slider input[type="range"]{ flex:1; accent-color: var(--blue); cursor:pointer; }
  .ae-audio-list-btn{ align-self:flex-start; }
  .ae-audio-upload-row{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .ae-audio-drop-hint{ font-size:12.5px; color: var(--muted); }
  .ae-audio-current{ font-size:12.5px; color: var(--ink); }

  /* Pannello "Mostra alert" (stesso spazio inline di "Riproduci Audio" sopra,
     vedi alertInlinePanelHtml in azioni-eventi-panel.js): campo testo su una
     riga, poi "Inserisci placeholder" (menu con {username}/{giftname}/ecc.,
     riusa lo stesso .mc-action-field/.mc-action-menu della tendina Font) e
     "Personalizza Overlay" (font/colore/opacità sfondo, target 'alert')
     sulla riga sottostante. */
  .ae-alert-text-input{
    width:100%; box-sizing:border-box; background: rgba(214,190,245,0.04);
    border:1px solid var(--line); border-radius:10px; padding:10px 12px; color:var(--ink);
    font-size:13px; font-family:'Nunito Sans', sans-serif;
  }
  .ae-alert-text-input:focus{ outline:none; border-color: var(--blue); }
  .ae-alert-actions-row{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .ae-alert-placeholder-field{ width:auto; flex:0 0 auto; }
  .ae-alert-personalize-btn{ flex-shrink:0; }
  /* Tendina voce di "Leggi testo (TTS)" dentro .ae-field-row (display:flex):
     senza un limite qui .mc-action-field{width:100%} la allargherebbe a
     schiacciare l'etichetta accanto. */
  #ae-tts-voice-field{ width:auto; min-width:200px; flex:1 1 auto; }
  /* Stesso motivo, ma per il pulsante "Regalo dal catalogo" del trigger
     "Regalo (specifico)" in Azioni & Eventi (.gift-combo-trigger{width:100%}
     schiaccerebbe l'etichetta "Regalo dal catalogo" accanto). */
  #ae-event-gift-trigger{ width:auto; min-width:200px; flex:1 1 auto; }

  /* Testo più grande nella finestrella "Nuova azione"/"Nuovo evento": la
     finestrella è STRETTA (700px, vedi .mc-prompt-modal.ae-action-modal
     sopra) e il testo grande — su richiesta 2026-08, che ha chiarito il giro
     precedente: il "troppo grande" era la finestra, non i caratteri. Tutti
     override scoped a .ae-action-modal (mai le classi base senza prefisso,
     es. .mc-prompt-label/.mc-prompt-input), perché quelle classi sono
     condivise da TUTTE le altre finestrelle del sito (Elenco Audio,
     Libreria Media, conferme, ecc.) — cambiarle senza scope le
     ingrandirebbe ovunque, non solo qui. */
  .ae-action-modal .mc-prompt-label{ font-size:16px; }
  .ae-action-modal .mc-prompt-input{ font-size:16px; }
  .ae-action-modal .ae-action-section-toggle{ font-size:15.5px; }
  .ae-action-modal .ae-action-section-caret{ font-size:12px; }
  .ae-action-modal .ae-action-option{ font-size:15px; }
  .ae-action-modal .ae-action-section-empty{ font-size:14px; }
  .ae-action-modal .ae-block-label{ font-size:15.5px; }
  .ae-action-modal .ae-field-row-label{ font-size:15px; }
  .ae-action-modal .ae-field-row-input{ font-size:16px; }
  .ae-action-modal .ae-field-row-suffix{ font-size:15px; }
  .ae-action-modal .ae-audio-volume-label{ font-size:14px; }
  .ae-action-modal .ae-audio-volume-slider{ font-size:15px; }
  .ae-action-modal .ae-audio-drop-hint{ font-size:14px; }
  .ae-action-modal .ae-audio-current{ font-size:14px; }
  .ae-action-modal .ae-alert-text-input{ font-size:15px; }

  /* Anteprima "Mostra alert" (pulsante ▶ Play, vedi showAlertPreview in
     azioni-eventi-panel.js): card fissa in alto a destra, sopra qualunque
     finestrella aperta (.mc-prompt-overlay è a z-index:90). Foto profilo
     centrata sopra, testo centrato sotto (come un vero alert box da
     diretta, non una riga orizzontale tipo notifica). Scompare da sola
     scorrendo verso destra, non un'azione dell'utente. */
  .ae-alert-preview{
    position:fixed; top:20px; right:20px; z-index:150; width:260px;
    display:flex; flex-direction:column; align-items:center; gap:10px; text-align:center;
    background: var(--bg-panel); border:1px solid var(--line); border-radius:14px;
    padding:20px 18px; box-shadow: 0 16px 40px rgba(7,2,13,0.5);
    opacity:0; transform: translateX(24px); pointer-events:none;
    transition: opacity .25s ease, transform .25s ease;
  }
  .ae-alert-preview.is-visible{ opacity:1; transform: translateX(0); }
  .ae-alert-preview-avatar{
    width:72px; height:72px; border-radius:50%; flex-shrink:0; font-size:32px;
    display:flex; align-items:center; justify-content:center;
    background: radial-gradient(circle at 30% 30%, #3A2B55, #1b2438);
  }
  .ae-alert-preview-text{ color: var(--ink); font-size:14.5px; font-weight:600; font-family:'Nunito Sans', sans-serif; word-break: break-word; }

  /* Anteprima "Mostra IMG/GIF/VIDEO" (pulsante ▶ Play, vedi showMediaPreview
     in azioni-eventi-panel.js): stesso pattern di .ae-alert-preview sopra
     ma in alto a SINISTRA (scompare scorrendo verso sinistra, transform
     opposto) invece che a destra, così un'azione con sia Alert che Media
     attivi mostra entrambe le anteprime in contemporanea senza sovrapporle.
     Niente padding/testo: il contenuto (<img> o <video>, iniettato da
     showMediaPreview) riempie tutta la card, angoli smussati dati
     dall'overflow:hidden sul contenitore invece che sul media stesso. */
  .ae-media-preview{
    position:fixed; top:20px; left:20px; z-index:150; width:320px;
    border-radius:14px; overflow:hidden; background: var(--bg-panel); border:1px solid var(--line);
    box-shadow: 0 16px 40px rgba(7,2,13,0.5);
    opacity:0; transform: translateX(-24px); pointer-events:none;
    transition: opacity .25s ease, transform .25s ease;
  }
  .ae-media-preview.is-visible{ opacity:1; transform: translateX(0); }
  .ae-media-preview img, .ae-media-preview video{
    display:block; width:100%; max-height:320px; object-fit:contain; background:#000;
  }

  /* La finestrella "Elenco Audio" è ora il componente condiviso
     .audio-picker-* (vedi js/audio-picker.js), stile più sotto vicino a
     .gift-modal-* — riusato anche dalle slot Minecraft/Roblox, non più
     specifico di questo tab. */

  /* Riquadro Profili (tab Azioni & Eventi, admin): selettore a tendina a
     sinistra, 3 righe di pulsanti a destra (crea/modifica/duplica/elimina —
     esporta/importa per codice — importa/esporta JSON). Niente .mc-wide-card
     qui: la card resta larga solo quanto il suo contenuto (si ferma al
     pulsante Elimina della prima riga), non si allarga come Azioni/Eventi. */
  /* Pannelli "SCHERMI ATTIVI" + "SIMULA EVENTI": una riga affiancata SOTTO
     Profili/Azioni/Eventi (non più dentro il layout a due colonne di prima —
     quello schiacciava la larghezza di .mc-wide-card, che deve restare piena
     pagina come prima). Qui invece i due pannelli sono simili per dimensione,
     niente da schiacciare. */
  .ae-side-row{ display:flex; gap:24px; flex-wrap:wrap; align-items:flex-start; margin-top:18px; }
  .ae-side-row > .ae-screens-panel{ flex:1 1 360px; min-width:280px; max-width:560px; margin-top:0; }
  .ae-screens-hint{ color: var(--muted); font-size:12px; margin: 4px 0 16px; line-height:1.6; }
  .ae-screens-list{ display:flex; flex-direction:column; gap:12px; }
  .ae-screen-row{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:16px 18px; border:1px solid var(--line); border-radius:10px;
    background: rgba(214,190,245,0.03);
  }
  .ae-screen-name{ font-size:14.5px; font-weight:600; }
  .ae-screen-row-right{ display:flex; align-items:center; gap:12px; }
  /* Copia il link overlay di quello specifico Schermo (vedi
     buildScreenOverlayUrl in azioni-eventi-panel.js) — stesso .btn.btn-outline
     del resto del sito ma più piccolo, per stare comodo dentro la riga
     accanto al badge Online/Offline. */
  .ae-screen-copy-btn{ padding:6px 14px; font-size:12.5px; }

  /* Puntino animato sul badge "Online" degli Schermi: .badge-active è già
     usato altrove nel sito (ruolo admin, ecc.) con un significato diverso da
     "sta ricevendo dati in questo momento" — scoped a #ae-screens-list per
     non far pulsare badge che non sono un vero stato "live". .badge è
     display:inline-flex con gap:5px: il ::before diventa il primo elemento
     flex, niente bisogno di margini manuali per staccarlo dal testo. */
  #ae-screens-list .badge-active::before{
    content:''; width:6px; height:6px; border-radius:50%; background: var(--blue); flex-shrink:0;
    animation: ae-screen-pulse 1.8s ease-out infinite;
  }
  @keyframes ae-screen-pulse{
    0%{ box-shadow: 0 0 0 0 rgba(185,107,250,0.5); }
    70%{ box-shadow: 0 0 0 6px rgba(185,107,250,0); }
    100%{ box-shadow: 0 0 0 0 rgba(185,107,250,0); }
  }

  /* ---------- Riga in alto del tab Eventi & Azioni (26/08/2026) ----------
     A sinistra il profilo su cui stai lavorando, a destra i comandi che lo
     riguardano. Prima era una card sola, larga quanto il suo contenuto, con
     la tendina e otto pulsanti su tre righe: il profilo corrente si leggeva
     dentro una casella invece di vedersi, e i quattro comandi che contano
     stavano in fila con importa/esporta, che si usano una volta ogni tanto. */
  .ae-top-row{
    display:grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
    gap: 20px; align-items:stretch; margin-top: 18px;
  }
  .ae-top-row > .connections-card{ max-width:none; margin-top:0; }
  /* La riga di esito sta SOTTO tutte e due le card, non dentro una: la usa
     sia il gruppo di comandi a destra sia Importa/Esporta a sinistra.
     Selettore per id perché showMessage riscrive className da capo. */
  #ae-profiles-message{ margin-top:14px; }

  .ae-profile-card{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:14px; }
  /* Il figlio diretto serve a battere .connections-card h3 (0,1,1), che
     aggiunge un margin-bottom di 6px: qui la spaziatura la dà il gap. */
  .ae-profile-card > .ae-profile-card-title{ font-size:16px; font-weight:600; margin:0; }

  /* Il nome del profilo E' la tendina: niente cassa attorno, il caret e'
     l'unico segno che si apre. Resta il widget condiviso .mc-action-field
     (renderProfilesDropdown ci scrive dentro e wireProfilesDropdown ne
     ascolta i click, tutti e due scoped a #ae-profiles-field), qui solo
     ridipinto. Il menu e' assoluto dentro il campo: siccome il campo adesso
     e' largo quanto il nome, va ricentrato a mano o resterebbe stretto e
     storto. */
  /* Figlio diretto: .mc-action-field{width:100%} sta più avanti nel foglio e
     a parità di specificità vincerebbe. */
  .ae-profile-card > .ae-profile-field{ width:auto; max-width:100%; }
  .ae-profile-field .mc-action-trigger{
    width:auto; max-width:100%; margin:0 auto; padding:4px 10px; gap:6px;
    background:transparent; border-color:transparent;
    font-family:'Baloo 2', sans-serif; font-size:17px; font-weight:700;
    letter-spacing:0.04em; text-transform:uppercase; color: var(--blue);
  }
  /* Il menu si apre SOPRA il disegno, e li' sotto ci sono le frecce: largo
     220px e centrato le copriva tutte e due, e un click sulla freccia
     finiva su una voce dell'elenco (elementFromPoint al centro della freccia
     tornava .mc-action-option) — cioe' saltavi a un altro profilo, di solito
     quello sopra. Con 200px e le frecce spostate ai bordi della card i due
     non si sovrappongono piu' a nessuna larghezza: lo spazio libero fra le
     frecce e' 224px anche nella colonna piu' stretta (340px meno i 24 di
     padding per lato, meno due frecce da 34). */
  .ae-profile-field .mc-action-menu{
    left:50%; right:auto; transform:translateX(-50%);
    min-width:0; width:200px; max-width: calc(100vw - 40px); text-align:left;
  }

  /* Il disegno con le frecce ai lati: si scorre un profilo alla volta
     (renderProfileCarousel), la tendina qui sopra serve quando sono tanti. */
  .ae-profile-stage{ display:flex; align-items:center; justify-content:center; gap:10px; width:100%; }
  /* Riquadro QUADRATO: le copertine dei giochi arrivano in formati diversi
     (16:9, verticali, quadrate) e in un riquadro libero ognuna cambierebbe
     l'altezza della card, e quindi anche di quella accanto. */
  .ae-profile-art{
    width:150px; max-width:100%; aspect-ratio:1 / 1;
    display:flex; align-items:center; justify-content:center;
  }
  /* object-fit:cover, non fill: l'immagine riempie il quadrato tagliando il
     lato lungo invece di schiacciarsi. Tagliata va bene, deformata no.
     :not([hidden]) obbligatorio sul display: senza, il display:block d'autore
     vince sul display:none dell'attributo hidden e l'immagine vuota resta a
     occupare mezzo riquadro accanto al disegno di ripiego (visto succedere).
     Stessa trappola già annotata sulle card di .overlay-subpanes. */
  .ae-profile-art-img:not([hidden]){ display:block; }
  .ae-profile-art-img{
    width:100%; height:100%; object-fit:cover;
    border-radius:14px; border:1px solid var(--line);
  }
  .ae-profile-art-fallback{ width:100%; height:auto; }
  .ae-profile-arrow{
    flex:none; width:34px; height:34px; border-radius:50%;
    border:1px solid var(--line); background:transparent; color: var(--muted);
    font-size:18px; line-height:1; cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    transition: border-color .15s ease, color .15s ease;
  }
  .ae-profile-arrow:hover:not(:disabled){ border-color: rgba(185,107,250,0.45); color: var(--ink); }
  /* Spente solo con un profilo solo (o nessuno): agli estremi il carosello
     gira in tondo, quindi c'e' sempre dove andare. */
  .ae-profile-arrow:disabled{ opacity:0.3; cursor:not-allowed; }

  /* Importa/Esporta: due <details>, l'apertura la fa il browser senza JS.
     Il triangolino di default va tolto in due modi perche' WebKit usa una
     pseudo-classe sua e il resto del mondo list-style. */
  .ae-profile-io{ display:flex; gap:10px; flex-wrap:wrap; justify-content:center; }
  .ae-io-menu{ position:relative; }
  .ae-io-menu > summary{ list-style:none; cursor:pointer; font-size:13px; padding:9px 16px; }
  .ae-io-menu > summary::-webkit-details-marker{ display:none; }
  .ae-io-menu > summary::marker{ content:''; }
  .ae-io-pop{
    position:absolute; z-index:30; top:calc(100% + 6px); left:50%; transform:translateX(-50%);
    display:flex; flex-direction:column; gap:8px; padding:12px; text-align:left;
    /* Non 250px secchi: su un telefono stretto il popup è centrato sul suo
       pulsante, che sta a metà card, e a larghezza fissa usciva dallo
       schermo dal lato corto. Il 100vw meno i margini della pagina è il
       tetto vero. */
    width: min(250px, calc(100vw - 48px));
    background: var(--bg-panel); border:1px solid var(--line); border-radius:12px;
    box-shadow: 0 16px 40px rgba(7,2,13,0.5);
  }
  .ae-io-pop .btn{ font-size:12.5px; padding:8px 12px; justify-content:center; }
  .ae-io-code-row{ display:flex; flex-direction:column; gap:8px; padding-top:10px; border-top:1px solid var(--line); }
  .ae-profile-code-input{
    width:100%; background: rgba(214,190,245,0.03); border:1px solid var(--line);
    border-radius:8px; padding:8px 10px; color: var(--ink); font-family:'Nunito Sans', sans-serif; font-size:13px;
  }
  .ae-profile-code-input:focus{ outline:none; border-color: var(--blue); }

  /* Un pallino per profilo: dice quanti sono e a che punto della fila sei,
     cosa che la tendina chiusa non diceva. margin-top:auto lo tiene in fondo
     alla card anche quando quella accanto e' piu' alta. */
  .ae-profile-dots{ display:flex; gap:7px; justify-content:center; flex-wrap:wrap; margin-top:auto; }
  .ae-profile-dot{ width:7px; height:7px; border-radius:50%; background: rgba(214,190,245,0.18); }
  .ae-profile-dot.is-current{ background: var(--blue); }

  /* La scelta gia' attiva nei popup a pulsanti dell'admin (oggi "Agenzia",
     vedi askAgency in js/admin.js): stesso segno di .mc-action-option
     .is-selected, che li' non si puo' riusare perche' le voci sono .btn. */
  .mc-prompt-options .btn.is-current{ border-color: var(--blue); color: var(--blue); }

  .ae-profile-manage{ display:flex; flex-direction:column; }
  .ae-profile-manage > h3{ font-size:17px; }
  .ae-profile-manage-row{ display:flex; gap:10px; flex-wrap:wrap; align-items:flex-start; }
  .ae-profile-manage-row .btn{ font-size:13.5px; padding:10px 18px; }
  .ae-profile-manage .form-message{ margin-top:16px; }

  /* Pulsanti che cancellano (Elimina profilo, Elimina azioni/eventi): stesso
     linguaggio del .btn-danger della danger-zone, ma con una classe propria
     perche' li' e' agganciato a un contenitore che qui non c'e'. Rosso vero
     (--danger), non il viola scuro che nel tema si chiama --red. */
  .ae-btn-danger{
    background: rgba(239,68,68,0.08); border-color: rgba(239,68,68,0.45); color:#F87171;
  }
  /* #DC2626 e non #EF4444: bianco su #EF4444 fa 3,76:1, sotto il minimo di
     leggibilità, ed è lo sfondo del pulsante che cancella per sempre. */
  .ae-btn-danger:hover{ background:#DC2626; border-color:#DC2626; color:#FFFFFF; box-shadow:none; }
  .ae-bulk-count{ font-family:'JetBrains Mono', monospace; font-size:0.92em; }

  /* Etichetta di categoria nella colonna Descrizione ("Azione:", "Azione
     extra:", "Gioco:"): un colore per categoria, cosi' si capisce di che
     tipo e' l'azione senza rileggere la frase intera. */
  .ae-desc-tag{ font-weight:700; }
  .ae-desc-general{ color:#4ADE80; }
  .ae-desc-extra{ color:#FBBF24; }
  .ae-desc-game{ color: var(--blue); }
  /* Riga cliccabile del tab Utenti (apre il popup di dettaglio): il cursore è
     l'unico segnale in più oltre all'hover già condiviso da tutte le
     .admin-table sopra, per non dover duplicare quello stile qui. */
  .admin-users-row{ cursor: pointer; }
  .admin-row-actions{ display:flex; gap:6px; flex-wrap:wrap; }
  .admin-action-btn{
    font-family:'JetBrains Mono'; font-size: 10.5px; padding: 5px 9px; border-radius: 6px;
    border: 1px solid var(--line); background:transparent; color: var(--muted); cursor:pointer;
    transition: border-color .2s ease, color .2s ease;
  }
  .admin-action-btn:hover{ color: var(--ink); border-color: var(--blue); }
  .admin-action-btn.danger:hover{ color: var(--red); border-color: var(--red); }
  .admin-action-btn:disabled{ opacity:0.4; cursor:not-allowed; }
  .admin-action-btn.is-playing{ color: var(--blue); border-color: var(--blue); }
  /* Nota "questo è il tuo account" in cima alla scheda. Era color: var(--line),
     cioè il colore dei bordi: rgba(214,190,245,0.08), praticamente invisibile
     su fondo nero — si leggeva solo selezionandola col mouse. Ora è testo a
     tutti gli effetti, nel colore normale. */
  .admin-self-note{ font-family:'Nunito Sans', sans-serif; font-size: 13.5px; color: var(--ink); }

  /* X compatta in fondo alla riga (es. tab Abbonamenti): un'icona invece di un
     pulsante di testo, per un'azione distruttiva separata da quelle normali
     della riga — sempre l'ultima a destra nel gruppo .admin-row-actions. */
  .admin-remove-btn{
    flex-shrink:0; width:26px; height:26px; border-radius:8px; border:1px solid var(--line);
    background:transparent; color: var(--muted); cursor:pointer; font-size:13px; line-height:1;
    transition: border-color .2s ease, color .2s ease;
  }
  .admin-remove-btn:hover{ border-color: var(--red); color: var(--red); }

  /* ---------- DANGER ZONE ---------- */
  /* Rosso vero, non var(--red): quella variabile si chiama "red" ma contiene
     un viola (#7C1FD4 sul sito, #7C3AED in dashboard), cioe' il colore del
     marchio. Su "elimina l'account" il viola non allarma nessuno: qui serve
     il colore che si distingue da tutto il resto dell'interfaccia. */
  .danger-zone{
    margin-top: 26px; padding-top: 20px; border-top: 1px solid rgba(239,68,68,0.32);
    max-width: 460px;
  }
  .danger-zone h3{ color: #F87171; font-size: 15px; margin-bottom: 8px; }
  .danger-zone p{ color: var(--muted); font-size: 13px; margin-bottom: 16px; }
  .danger-zone .btn-danger{
    background: rgba(239,68,68,0.08); border: 1px solid rgba(239,68,68,0.5); color: #F87171;
  }
  .danger-zone .btn-danger:hover{
    background: #EF4444; border-color: #EF4444; color: #FFFFFF;
  }

  .danger-confirm{
    margin-top: 16px; padding: 18px; border: 1px solid rgba(239,68,68,0.4); border-radius: 12px;
    background: rgba(239,68,68,0.07);
  }
  .danger-confirm p{ color: var(--muted); font-size: 12.5px; }
  .danger-confirm .field{ margin: 14px 0; }
  .danger-confirm-actions{ display:flex; gap:12px; }

  /* ---------- PAYMENT METHODS ---------- */
  .payment-methods{ display:grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 20px 0; }
  @media (max-width: 420px){ .payment-methods{ grid-template-columns: 1fr; } }
  .payment-method{
    display:flex; align-items:center; justify-content:center; gap:10px; padding: 12px 14px;
    border: 1px solid var(--line); border-radius: 10px; background: rgba(214,190,245,0.02);
    cursor:pointer; font-size: 13.5px; color: var(--muted); transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .payment-method:hover{ border-color: rgba(185,107,250,0.4); color: var(--ink); }
  .payment-method.selected{ border-color: var(--blue); color: var(--ink); background: rgba(185,107,250,0.08); }
  .payment-method:disabled{ cursor:not-allowed; opacity:.4; }
  .payment-method:disabled:hover{ border-color: var(--line); color: var(--muted); }
  .payment-method-icon{ font-size: 17px; line-height:1; display:flex; align-items:center; }
  .payment-method-icon img{ height: 20px; width:auto; display:block; }
  .payment-note{ font-family:'JetBrains Mono'; font-size: 11px; color: var(--muted); margin-top: -6px; margin-bottom: 18px; }

  /* ---------- PLAN OPTIONS (giornaliero/mensile/annuale) ---------- */
  .plan-options{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 20px 0; }
  @media (max-width: 420px){ .plan-options{ grid-template-columns: 1fr; } }
  .plan-option{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; padding: 12px 10px;
    border: 1px solid var(--line); border-radius: 10px; background: rgba(214,190,245,0.02);
    cursor:pointer; font-size: 13.5px; color: var(--muted); transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .plan-option:hover{ border-color: rgba(185,107,250,0.4); color: var(--ink); }
  .plan-option.selected{ border-color: var(--blue); color: var(--ink); background: rgba(185,107,250,0.08); }
  .plan-option .plan-option-price{ font-family:'JetBrains Mono'; font-size: 11px; color: var(--muted); }
  .plan-option.selected .plan-option-price{ color: var(--ink); }

  /* ---------- PAGE LOADER ---------- */
  /* Resta visibile finché la pagina non ha finito di caricare DAVVERO (evento
     "load": font, CSS e immagini inclusi), non per una durata fissa finta. */
  #page-loader{
    position: fixed; inset: 0; z-index: 9999;
    display:flex; align-items:center; justify-content:center;
    background: var(--bg);
    transition: opacity .35s ease;
  }
  #page-loader.is-hidden{ opacity: 0; pointer-events: none; }
  .page-loader-ring{
    width: 44px; height: 44px; border-radius:50%;
    border: 3px solid var(--line); border-top-color: var(--blue);
    animation: page-loader-spin 0.9s linear infinite;
  }
  @keyframes page-loader-spin{ to{ transform: rotate(360deg); } }

  /* Un indicatore "in corso" deve continuare a muoversi anche con le animazioni
     ridotte: la regola globale più sopra (transition/animation-duration:
     0.001ms su "*") altrimenti lo congela su un fotogramma fisso, facendolo
     sembrare bloccato invece che "sta ancora caricando". */
  @media (prefers-reduced-motion: reduce){
    .page-loader-ring{ animation-duration: 1.1s !important; }
  }

  /* ---------- PANNELLO MINECRAFT ---------- */
  /* .connections-card ha max-width:460px, troppo stretto per una tabella a 7
     colonne con 20 righe: questa variante la lascia occupare tutta la larghezza
     disponibile. */
  .connections-card.mc-wide-card{ max-width: 100%; }

  /* Collegamento + Carica Regali impilate a sinistra, tutorial/download a
     destra: margin-top azzerato su entrambi i rami (lo dà già .mc-config-top
     come blocco) così restano allineati in alto l'uno con l'altro. */
  .mc-config-top{ display:flex; gap:20px; flex-wrap:wrap; align-items:flex-start; }
  .mc-config-top > .mc-config-left, .mc-config-top > .connections-card{ flex:1; min-width: 320px; margin-top:0; }
  .mc-config-left{ display:flex; flex-direction:column; gap:18px; }
  .mc-config-left .connections-card{ margin-top:0; }
  .tutorial-download-links{ display:flex; flex-direction:column; gap:10px; margin-top:16px; }
  .tutorial-download-links .btn{ justify-content:flex-start; }
  .btn-youtube{ background: var(--red); color:#F1E7FF; }
  .btn-youtube:hover{ box-shadow: 0 8px 24px rgba(124,31,212,0.35); }
  .btn.is-disabled{ opacity:.45; cursor:not-allowed; pointer-events:none; }
  .btn.is-disabled:hover{ transform:none; box-shadow:none; }
  .tutorial-overlay-preview{ width:100%; height:auto; border-radius: 10px; border: 1px solid var(--line); display:block; }
  /* Separa visivamente il download principale (server .zip, sopra) dall'overlay
     OBS opzionale (sotto): una riga divisoria + etichetta piccola, cosi' non
     sembra un quarto pulsante dello stesso gruppo ma un extra a parte. */
  .tutorial-overlay-block{ margin-top:18px; padding-top:16px; border-top:1px solid var(--line); display:flex; flex-direction:column; gap:10px; }
  .tutorial-overlay-label{ font-size:11.5px; font-family:'JetBrains Mono'; text-transform:uppercase; letter-spacing:0.06em; color: var(--muted); margin:0; }
  /* Copertina della card TntCube nel tab Giochi (al posto del solo gradiente). */
  .game-thumb-tntcube{ background-image: url('../img/minecraft/TntCube/tntcube.png'); background-size: cover; background-position: center; }
  /* Niente righe diagonali sopra l'immagine reale della copertina (restano solo
     sui game-thumb a gradiente semplice, senza immagine, delle altre card). */
  .game-thumb-tntcube::after{ content:none; }
  /* Survival: key art vera (il logo TikForge "Vanilla-Interattiva" sul mondo
     sfocato). JPEG e non PNG come TntCube qui sopra, per lo stesso motivo di
     The Hum piu' sotto: e' un'immagine fotografica, in PNG pesava dieci volte
     tanto a parita' di resa. */
  .game-thumb-survival{ background-image: url('../img/minecraft/Survival/survival.jpg'); background-size: cover; background-position: center; }
  .game-thumb-survival::after{ content:none; }
  /* Stessa cosa per Vertical Parkour: copertina reale al posto del gradiente.
     Key art VERTICALE (pedane nel cielo): il cover la ritaglia al centro. */
  .game-thumb-verticalparkour{ background-image: url('../img/roblox/VerticalParkour/verticalparkour.jpg'); background-size: cover; background-position: center; }
  .game-thumb-verticalparkour::after{ content:none; }
  /* The Hum: key art vera (il runner inseguito dal Manutentore nel
     corridoio), al posto del vecchio gradiente CSS "corridoio nel buio".
     JPEG e non PNG come le altre thumb: è un render fotografico, in PNG
     pesava 1.6 MB contro i ~110 KB del JPEG a pari resa. */
  .game-thumb-thehum{ background-image: url('../img/roblox/TheHum/thehum.jpg'); background-size: cover; background-position: center; }
  .game-thumb-thehum::after{ content:none; }

  /* Spiral Parkour: key art vera (salti tra le pedane nel cielo), al posto
     della spirale ambra procedurale. JPEG come la thumb di The Hum:
     render fotografico, il PNG pesava un ordine di grandezza in più. */
  .game-thumb-spiralparkour{ background-image: url('../img/roblox/SpiralParkour/spiralparkour.jpg'); background-size: cover; background-position: center; }
  .game-thumb-spiralparkour::after{ content:none; }

  /* TNT Cube 2D: key art del muro 2D (la stessa della scheda azioni). */
  .game-thumb-tntcube2d{ background-image: url('../img/roblox/TntCube2D/tntcube2d.png'); background-size: cover; background-position: center; }
  .game-thumb-tntcube2d::after{ content:none; }

  /* StackBreak 2D: il gemello demolitore (immagine da caricare in
     img/roblox/StackBreak2D/, stessa key art della scheda azioni). */
  .game-thumb-stackbreak2d{ background-image: url('../img/roblox/StackBreak2D/stackbreak2d.png'); background-size: cover; background-position: center; }
  .game-thumb-stackbreak2d::after{ content:none; }

  /* Chip "BETA" accanto alla difficoltà di una game card: pallino arancione
     LUMINOSO che respira — segnala "giocabile ma in beta" a colpo d'occhio.
     Al momento NESSUNA card lo usa (tolto da The Hum e Spiral Parkour a
     fine beta): pronto da riappendere al prossimo gioco in beta. */
  .beta-chip{
    display:inline-flex; align-items:center; gap:5px;
    margin-left:8px; padding:2px 8px;
    font-size:10px; font-weight:800; letter-spacing:0.08em;
    color:#FFB65C; background:rgba(255,150,40,0.12);
    border:1px solid rgba(255,150,40,0.45); border-radius:999px;
    vertical-align:middle;
  }
  .beta-dot{
    width:7px; height:7px; border-radius:50%;
    background:#FF9628;
    box-shadow: 0 0 6px 1px rgba(255,150,40,0.9);
    animation: beta-dot-pulse 1.6s ease-in-out infinite;
  }
  @keyframes beta-dot-pulse{
    0%, 100%{ opacity:1; box-shadow: 0 0 6px 1px rgba(255,150,40,0.9); }
    50%{ opacity:0.55; box-shadow: 0 0 2px 0 rgba(255,150,40,0.4); }
  }
  .mc-token-row{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin: 16px 0; }
  .mc-token-value{
    font-family:'JetBrains Mono'; font-size: 13px; background: rgba(214,190,245,0.04);
    padding: 8px 12px; border-radius: 8px; border: 1px solid var(--line); word-break: break-all;
  }

  /* Card overlay TikTok live (tab Giochi): due link OBS lunghi, su una riga
     sola con etichetta fissa + valore troncato (a differenza di
     .mc-token-value, pensato per il token Minecraft più corto). */
  .overlay-link-label{ flex:0 0 96px; font-size:13px; color: var(--muted); font-weight:600; }

  /* Pulsante-interruttore "Auto reset" (una per card overlay, accanto a
     Reset): stato acceso evidenziato col colore accento + pallino ●, così
     ON/OFF si distingue a colpo d'occhio senza cambiare l'etichetta (il
     pulsante dice sempre "Auto reset", vedi wireAutoResetButtons in
     js/overlay-panel.js — aria-pressed tiene lo stato per gli screen reader). */
  .overlay-autoreset-btn[aria-pressed="true"]{
    border-color: var(--red);
    color: var(--red);
    box-shadow: 0 0 14px rgba(124,31,212,0.25);
  }
  .overlay-autoreset-btn[aria-pressed="true"]::before{ content:"● "; }
  .overlay-link-row .mc-token-value{ flex:1 1 auto; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; word-break:normal; }

  /* Anteprima live delle due pagine overlay (stessa pagina che gira in OBS,
     incorporata in un iframe): la pagina si auto-adatta già da sola alla
     dimensione del contenitore (vedi fitOverlay() in overlay/*.html), qui
     basta dargli un riquadro 16:9 con angoli arrotondati. */
  /* Obiettivi: UNA CARD PER OBIETTIVO nella griglia, come le altre card
     overlay (26/08/2026, sul modello di TikFinity). Le disegna
     js/overlay-panel.js dentro #overlay-goals-list, che sta nella griglia
     ma non occupa una cella: `display:contents` lascia che siano le card a
     prendere le tracce. Il `:not([hidden])` serve al filtro delle categorie,
     che nasconde il contenitore con l'attributo hidden — e un display
     esplicito vincerebbe sul display:none dell'attributo. */
  .overlay-goals-host:not([hidden]){ display:contents; }

  .goal-card h3{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
  /* L'etichetta "In diretta / Solo in live": il punto e il testo cambiano
     con lo stato. L'obiettivo funziona solo a diretta collegata, e la card
     lo dice sempre, non solo quando qualcosa non va. */
  .goal-card-live{
    display:inline-flex; align-items:center; gap:6px;
    padding:3px 10px; border-radius:999px;
    font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
    background: rgba(34,197,94,0.12); border:1px solid rgba(34,197,94,0.35); color:#4ADE80;
    white-space:nowrap;
  }
  .goal-card-live i{ width:7px; height:7px; border-radius:50%; background:currentColor; box-shadow:0 0 6px currentColor; }
  .goal-card-live-off{ display:none; }
  .goal-card.is-offline .goal-card-live{
    background: rgba(214,190,245,0.05); border-color: var(--line); color: var(--muted);
  }
  .goal-card.is-offline .goal-card-live i{ box-shadow:none; }
  .goal-card.is-offline .goal-card-live-on{ display:none; }
  .goal-card.is-offline .goal-card-live-off{ display:inline; }
  /* Traguardo raggiunto: si vede dalla card senza aprire OBS. */
  .goal-card.is-reached{ border-color: rgba(168,85,247,0.45); }

  /* I quattro campi in testa, come la riga "Goal / Title / When reached /
     Action" del modello: etichetta sopra, casella sotto, a griglia. */
  .goal-fields{
    display:grid; grid-template-columns: minmax(90px, 0.7fr) 1.3fr;
    gap:10px 12px; margin-top:14px;
  }
  .goal-field{ display:flex; flex-direction:column; gap:5px; min-width:0; }
  .goal-field > span{ font-size:12px; font-weight:700; color: var(--muted); }
  .goal-field input, .goal-select{
    width:100%; min-width:0;
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:8px;
    padding:8px 10px; color: var(--ink);
    font-family:'Nunito Sans', sans-serif; font-size:14px; font-weight:700;
  }
  .goal-field input:focus, .goal-select:focus{ border-color: var(--blue); outline:none; }
  .goal-select{
    appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:28px;
    background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
    background-position: calc(100% - 15px) 55%, calc(100% - 10px) 55%;
    background-size: 5px 5px, 5px 5px; background-repeat:no-repeat;
  }
  .goal-select option{ background:#161022; color: var(--ink); }
  .overlay-style-select{ width:auto; min-width:150px; padding:6px 28px 6px 10px; font-size:13px; }

  .goal-row-custom{ display:flex; gap:8px; margin-top:10px; }
  .goal-row-custom .btn{ font-size:13px; padding:6px 14px; }
  .goal-card .overlay-link-row{ margin-top:12px; }
  .goal-row-delete:hover{ border-color: rgba(255,77,77,0.55); color:#FF6B6B; }
  .goal-test-btn:disabled{ opacity:.45; cursor:not-allowed; }

  /* L'anteprima fra due freccette: sfogliano i modelli grafici pronti, e
     sotto sta scritto quale è acceso ("Stile: 2/6"). L'iframe è lo stesso
     overlay che va in OBS, aggiornato dal canale push: la scelta si vede
     lì dentro senza ricaricare niente. */
  .goal-preview{ display:flex; align-items:center; gap:8px; margin-top:2px; }
  .goal-preview .overlay-preview{ flex:1 1 auto; min-width:0; margin-top:0; }
  .goal-preview .overlay-preview-frame{ aspect-ratio:16/6; margin-top:10px; }
  .goal-preview-arrow{
    flex:none; width:34px; height:52px; margin-top:10px;
    border-radius:8px; border:1px solid var(--line);
    background: rgba(214,190,245,0.03); color: var(--ink);
    font-size:24px; line-height:1; cursor:pointer;
    transition: border-color .18s ease, background .18s ease;
  }
  .goal-preview-arrow:hover{ border-color: rgba(168,85,247,0.55); background: rgba(168,85,247,0.10); }
  .goal-preview-arrow:disabled{ opacity:.4; cursor:not-allowed; }
  .goal-preview-style{ margin:8px 0 0; text-align:center; font-size:12px; color: var(--muted); }
  .goal-preview-style b{ color: var(--ink); }

  /* Card Timer: i comandi sotto l'anteprima riusano .win-controls/.win-row
     (minuti e secondi come le caselle di Vittorie); qui la riga dei
     pulsanti Start / Pausa / Reset (il tempo che scorre lo mostra l'anteprima). */
  /* Tutto su UNA riga (caselle e pulsanti), così la card resta alta quanto
     Vittorie: caselle più strette (99 e 59 ci stanno) e spazi ridotti. */
  .timer-controls{ gap:10px 10px; }
  .timer-controls .win-target-input{ width:64px; }
  .timer-btns{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
  .timer-btns .btn{ padding:7px 12px; }
  .timer-btns .btn{ font-size:13px; padding:7px 16px; }

  /* La card "aggiungi personalizzato": tratteggiata come i segnaposto, si
     legge "questo lo puoi creare", non "questo è rotto". */
  .goal-card-add{ border-style:dashed; background:transparent; }
  .goal-card-add .btn{ margin-top:14px; }

  @media (max-width: 560px){
    .goal-fields{ grid-template-columns: 1fr; }
  }

  .overlay-preview-grid{ display:flex; gap:16px; flex-wrap:wrap; margin-top:20px; }
  .overlay-preview{ flex:1 1 280px; min-width:260px; }
  .overlay-preview .overlay-link-label{ flex:none; display:block; margin-bottom:8px; }
  .overlay-preview-frame{
    aspect-ratio:16/9; border-radius:12px; overflow:hidden;
    border:1px solid var(--line); background:#050308; margin-top:14px;
  }
  .overlay-preview-frame iframe{ width:100%; height:100%; border:none; display:block; }

  /* Tab Overlay: FILTRI a pillola sopra la griglia.
     Prima erano una seconda colonna a tutta altezza accanto alla sidebar
     principale (.app-subsidebar): 200px sempre occupati per quattro voci, e
     sotto gli 860px diventava comunque una striscia orizzontale — cioè quello
     che adesso è a ogni larghezza.
     Si accendono a PIÙ DI UNA: la griglia mostra l'unione delle categorie
     scelte (wireFilters in js/overlay-panel.js). Un overlay nuovo = una card
     nuova nell'HTML con il suo data-ovcat. */
  .ov-filters{
    display:flex; flex-wrap:wrap; gap:8px;
    margin: 2px 0 22px;
  }
  .ov-filter{
    display:inline-flex; align-items:center; justify-content:center;
    /* 40px di lato: sotto il dito ci sta, e la riga resta compatta anche con
       cinque pillole. */
    min-height:40px; padding: 0 18px; border-radius: 999px;
    background: transparent; border: 1px solid var(--line); color: var(--muted);
    font-family:'Nunito Sans', sans-serif; font-size:13.5px; font-weight:700;
    cursor:pointer; white-space:nowrap;
    transition: background .18s ease, border-color .18s ease, color .18s ease;
  }
  .ov-filter:hover{ color: var(--ink); border-color: rgba(168,85,247,0.45); }
  /* L'accesa si riconosce da tre cose insieme — testo, bordo e fondo — non
     dal solo colore: chi i viola non li distingue bene vede comunque
     l'anello. */
  .ov-filter.active{
    color: #F1E7FF; border-color: var(--blue);
    background: rgba(168,85,247,0.14);
    box-shadow: 0 0 0 1px rgba(168,85,247,0.38);
  }
  .ov-filter:focus-visible{ outline:2px solid var(--blue); outline-offset:2px; }

  /* Rigenera link: era una riga in coda al pannello, dal 26/08/2026 sta in
     alto a destra (titolo, descrizione, pulsante uno sotto l'altro). Testo
     nudo, senza la cassa delle card: si usa quando qualcosa non va, non a
     ogni visita, e con uno sfondo si prendeva l'occhio prima dei filtri.
     max-width: sotto i 1200px la colonna destra non c'e' e senza un tetto le
     righe andrebbero larghe quanto tutto il pannello. */
  .overlay-regen{ margin-top: 26px; max-width: 440px; }
  .overlay-regen h3{ font-size: 15px; margin-bottom: 6px; }
  .overlay-regen .connections-sub{ margin-bottom: 14px; }
  .overlay-regen .btn{ font-size:13px; padding: 9px 16px; }
  /* Il messaggio d'esito sotto al pulsante: in colonna stretta un errore
     lungo va a capo da se' senza spingere niente fuori. */
  .overlay-regen .form-message{ margin: 10px 0 0; font-size:12px; }

  /* Il pannello Overlay in due colonne: intestazione e filtri a sinistra, la
     scheda Rigenera in alto a destra, la griglia delle card sotto a tutto.
     @media a MIN-width, al contrario del resto del file: qui e' il desktop
     che cambia, sotto la soglia resta il blocco di prima e il testo torna
     in fondo da solo (nell'HTML e' l'ultimo figlio). 1400px perche' sotto,
     tolti sidebar (248), padding (2x48) e la colonna destra (440+28), alla
     sinistra resterebbero meno dei ~540px che i filtri chiedono in spagnolo,
     e andrebbero a capo. */
  @media (min-width: 1400px){
    /* :not([hidden]) obbligatorio: i pannelli si nascondono con l'attributo
       hidden e un display esplicito vincerebbe sul suo display:none —
       stessa trappola gia' annotata sulle card di .overlay-subpanes. */
    .dash-panel[data-panel="overlay"]:not([hidden]){
      display:grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
      column-gap: 28px;
    }
    .dash-panel[data-panel="overlay"] > h1{ grid-area: 1 / 1; align-self: baseline; }
    .dash-panel[data-panel="overlay"] > .dash-sub{ grid-area: 2 / 1; align-self: baseline; }
    .dash-panel[data-panel="overlay"] > .game-lock-note{ grid-area: 3 / 1; }
    .dash-panel[data-panel="overlay"] > .ov-filters{ grid-area: 4 / 1; }

    /* display:contents: il blocco sparisce come scatola e i suoi pezzi
       diventano celle della griglia del pannello, una per riga. Cosi' non
       si impilano per conto loro ma stanno sulle righe di sinistra: il
       titolo su quella di "Overlay", la descrizione su quella del
       sottotitolo, il pulsante su quella dei filtri.
       align-self:baseline sulle due righe di testo, non start: h3 e h1 sono
       di corpo diverso e allineati in alto le due scritte partirebbero a
       quote diverse. Vuole la baseline su TUTTE E DUE le celle della riga —
       da sola, quella di destra non ha con chi allinearsi e ricade su start.
       I margini qui vanno a zero: il ritmo delle righe lo detta la colonna
       di sinistra, sommarci anche i suoi farebbe due scale diverse.
       Il messaggio d'esito ha una riga sua sotto al pulsante (la 5): finche'
       e' nascosto quella riga e' alta zero, e quando compare spinge giu' solo
       la griglia delle card, non i filtri.
       Solo qui dentro: sotto la soglia il blocco torna in fondo, a sinistra
       e impilato come una volta. */
    .dash-panel[data-panel="overlay"] > .overlay-regen{
      display: contents; text-align: right;
    }
    .dash-panel[data-panel="overlay"] > .overlay-regen > h3{
      grid-area: 1 / 2; align-self: baseline; margin: 0;
    }
    .dash-panel[data-panel="overlay"] > .overlay-regen > .connections-sub{
      grid-area: 2 / 2; align-self: baseline; margin: 0;
    }
    .dash-panel[data-panel="overlay"] > .overlay-regen > .btn{
      grid-area: 4 / 2; justify-self: end; align-self: start;
    }
    .dash-panel[data-panel="overlay"] > .overlay-regen > .form-message{
      grid-area: 5 / 2; margin: 0;
    }
    /* Lo stacco sopra la griglia lo da' gia' il margine dei filtri: in una
       griglia i margini non si fondono, tenerli tutti e due farebbe 22+18. */
    .dash-panel[data-panel="overlay"] > .overlay-subpanes{
      grid-area: 6 / 1 / 7 / 3; margin-top:0;
    }
  }
  /* la griglia delle card della categoria: stesse tracce della vecchia
     .overlay-subpanel-grid — le card [hidden] semplicemente non ci sono.
     auto-FILL, non auto-fit: le tracce vuote restano, così una categoria
     con UNA card sola (Obiettivi, Giochi) la mostra della stessa taglia
     che ha in "Generali" invece di spalmarla su tutta la pagina. */
  .overlay-subpanes{
    display:grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
    gap: 22px 24px; align-items:start;
    margin-top: 18px;
  }
  .overlay-subpanes .connections-card{ max-width:none; margin-top:0; }

  /* ---------- Le card del tab Overlay, rimesse in ordine (26/08/2026) ----------
     Prima: titolo, riga con URL illeggibile + 3-4 pulsanti tutti uguali,
     anteprima in fondo, comandi sparsi. Ora, dall'alto:
       1. titolo e una riga di spiegazione;
       2. l'ANTEPRIMA, che è la cosa da guardare (è l'overlay vero);
       3. il LINK OBS su una riga sua, con l'etichetta "OBS" e il solo Copia;
       4. le azioni, in ordine: Personalizza prima, Reset/Auto reset dopo, più
          piccole e in tono smorzato — si usano una volta ogni tanto;
       5. i comandi (Win, Timer, Obiettivi) sotto una riga sottile.
     Tutto con `order` sui figli: lo stesso HTML nelle quattro lingue e le card
     disegnate da JS non cambiano di una virgola. */
  /* :not([hidden]) è obbligatorio: il filtro delle categorie nasconde le card
     con l'attributo hidden, e un display esplicito vincerebbe sul suo
     display:none — con "display:flex" secco le categorie hanno smesso di
     funzionare (26/08/2026). Stessa trappola già annotata su .overlay-goals-host. */
  .overlay-subpanes .connections-card:not([hidden]){ display:flex; flex-direction:column; }
  .overlay-subpanes .connections-card > h3{ order:0; }
  .overlay-subpanes .connections-card > .connections-sub{ order:0; margin-bottom:14px; }
  .overlay-subpanes .connections-card > .overlay-preview,
  .overlay-subpanes .connections-card > .goal-preview,
  .overlay-subpanes .connections-card > .goal-preview-style{ order:1; }
  .overlay-subpanes .connections-card > .overlay-link-row{ order:2; }
  .overlay-subpanes .connections-card > .win-controls,
  .overlay-subpanes .connections-card > .goal-fields,
  .overlay-subpanes .connections-card > .goal-row-custom,
  .overlay-subpanes .connections-card > .form-message{ order:3; }

  .overlay-subpanes .overlay-preview{ min-width:0; }
  .overlay-subpanes .overlay-preview-frame{ margin-top:0; border-radius:10px; }
  .overlay-subpanes .goal-preview .overlay-preview-frame{ margin-top:0; }
  .overlay-subpanes .goal-preview-arrow{ margin-top:0; }
  .overlay-subpanes .goal-preview-style{ margin:8px 0 0; }

  /* Il link: una riga sua. Il valore è troncato coi puntini (si copia, non
     si legge) e porta davanti la targhetta "OBS" così si capisce a che cosa
     serve senza spiegazioni. Il Copia gli sta accanto; tutto il resto va
     a capo nella riga delle azioni. */
  .overlay-subpanes .overlay-link-row{ margin:14px 0 0; gap:8px; align-items:center; }
  .overlay-subpanes .overlay-link-row .mc-token-value{
    flex:1 1 calc(100% - 96px); display:flex; align-items:center; gap:10px;
    font-size:12px; padding:7px 10px 7px 8px; color: var(--muted);
    background: rgba(0,0,0,0.25); border-color: rgba(214,190,245,0.10);
  }
  .overlay-subpanes .overlay-link-row .mc-token-value::before{
    content:"OBS"; flex:none;
    font-family:'Nunito Sans', sans-serif; font-size:10px; font-weight:800; letter-spacing:.08em;
    padding:2px 7px; border-radius:6px;
    background: rgba(168,85,247,0.16); color:#C99BFF;
  }
  .overlay-subpanes .overlay-link-row .btn{ font-size:12.5px; padding:7px 13px; }
  .overlay-subpanes .overlay-link-row .btn:nth-of-type(1){ flex:0 0 auto; min-width:80px; justify-content:center; }
  /* Le azioni dopo Copia: a capo, Personalizza per prima e in evidenza,
     Reset e Auto reset smorzati. L'ordine nell'HTML è Copia, Reset, Auto
     reset, Personalizza: si riordina con `order`, senza toccarlo. */
  .overlay-subpanes .overlay-link-row .btn:nth-of-type(n+2){ flex:0 0 auto; }
  .overlay-subpanes .overlay-link-row [id^="overlay-style-"],
  .overlay-subpanes .overlay-link-row [data-goal-action="style"]{
    order:5; margin-right:auto;
    border-color: rgba(168,85,247,0.45); color:#E2C6FF;
  }
  .overlay-subpanes .overlay-link-row [id^="overlay-style-"]::before,
  .overlay-subpanes .overlay-link-row [data-goal-action="style"]::before{ content:"⚙ "; }
  .overlay-subpanes .overlay-link-row [id^="overlay-reset-"],
  .overlay-subpanes .overlay-link-row .overlay-autoreset-btn,
  .overlay-subpanes .overlay-link-row [data-goal-action="delete"]{
    order:6; color: var(--muted); border-color: rgba(214,190,245,0.14);
  }
  .overlay-subpanes .overlay-link-row [data-goal-action="test"]{ order:5; }
  /* Chi ha almeno un pulsante dopo Copia: forza l'andata a capo delle azioni
     con un elemento-riga invisibile a larghezza piena. */
  .overlay-subpanes .overlay-link-row::after{ content:""; order:4; flex:1 1 100%; height:0; }
  .overlay-subpanes .overlay-link-row .overlay-autoreset-btn[aria-pressed="true"]{ color: var(--red); border-color: var(--red); }

  /* I comandi: staccati dal resto con una riga sottile, etichette allineate. */
  .overlay-subpanes .win-controls,
  .overlay-subpanes .goal-fields,
  .overlay-subpanes .goal-row-custom{
    margin-top:14px; padding-top:14px; border-top:1px solid rgba(214,190,245,0.10);
  }
  .overlay-subpanes .goal-row-custom{ margin-top:10px; padding-top:10px; border-top:none; }

  /* ---------- Overlay "Win: X/Y" (tab Overlay, contatore manuale) ---------- */
  /* Obiettivo e Vittorie attuali AFFIANCATI (non impilati, su richiesta):
     la card Vittorie resta della taglia delle altre */
  .win-controls{ display:flex; gap:14px 22px; margin-top:20px; flex-wrap:wrap; }
  .win-row{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
  .win-row label{ font-size:13px; color: var(--muted); flex:0 0 auto; }
  .win-target-input{
    width:90px; background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:8px;
    padding:8px 10px; color: var(--ink); font-family:'JetBrains Mono'; font-size:13px;
  }

  /* ---------- TTS Chat: ogni sezione è una "finestrella" a sé (.tts-tile,
     card con bordo rosso neon + titolo blu, stesso stile del riferimento
     mostrato dall'utente) dentro una griglia responsive, invece di un'unica
     card lunghissima con divisori interni. ---------- */
  .tts-cards-grid{
    display:grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap:20px; align-items:start; margin-top:22px;
  }
  .tts-tile{ border-color: rgba(124,31,212,0.35); margin-top:0; max-width:none; }
  .tts-tile > h4, .tts-tile .mc-slots-head h4{ font-size:14px; margin-bottom:12px; color: var(--blue); }

  /* Interruttore "Attiva/Disattiva TTS" in cima a "Impostazioni generali":
     stesso pulsante a pillola outline/pieno del "Connetti Live" in sidebar
     (.app-overlay-btn, vedi lì), ma qui è un secondo interruttore
     indipendente — accende/spegne solo la lettura dei commenti, non la
     connessione alla diretta (serve comunque "Connetti Live" attivo perché
     ci sia qualcosa da leggere). */
  .tts-enable-row{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-bottom:16px; }
  .tts-enable-row .app-overlay-btn{ flex-shrink:0; }
  .tts-enable-row .connections-sub{ margin:0; }

  .tts-row{ display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap; }
  .tts-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:14px; align-items:end; }
  .tts-grid .field{ margin:0; }

  .tts-checkbox{ display:flex; align-items:center; gap:8px; font-size:13px; color: var(--muted); cursor:pointer; }
  .tts-checkbox input{ accent-color: var(--blue); cursor:pointer; flex-shrink:0; }
  .tts-checks{ display:flex; flex-direction:column; gap:10px; margin-top:14px; }

  .tts-sliders{ display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:18px; margin-top:16px; }
  .tts-slider{ display:flex; flex-direction:column; gap:8px; font-size:13px; color: var(--muted); }
  .tts-slider strong{ color: var(--ink); font-family:'JetBrains Mono'; }
  .tts-slider input[type="range"]{ width:100%; accent-color: var(--blue); cursor:pointer; }

  /* Lingua/Voce/Leggi (tab TTS) usano lo stesso .mc-action-field a tendina
     custom di Azione/Profili di Configurazione (tab Giochi) invece del
     <select> nativo, non restilizzabile secondo il tema scuro: qui basta
     dargli la larghezza piena della griglia, il resto lo eredita già. */
  .tts-grid .mc-action-field{ width:100%; }

  .tts-special-list{ display:flex; flex-direction:column; gap:10px; margin-top:14px; }
  .tts-special-item{
    display:flex; align-items:center; gap:10px; flex-wrap:wrap;
    background: rgba(214,190,245,0.02); border:1px solid var(--line); border-radius:10px; padding:10px 12px;
  }
  .tts-special-item input[type="text"]{
    flex:1 1 140px; min-width:120px; background: rgba(214,190,245,0.03); border:1px solid var(--line);
    border-radius:8px; padding:8px 10px; color: var(--ink); font-family:'JetBrains Mono'; font-size:13px;
  }
  .tts-special-item .mc-action-field{ flex:1 1 140px; min-width:130px; width:auto; }
  .tts-special-item .mc-action-trigger{ font-size:12.5px; }
  .tts-special-item .tts-checkbox{ flex:0 0 auto; }
  .tts-special-remove-btn{
    flex-shrink:0; width:30px; height:30px; border-radius:8px; border:1px solid var(--line);
    background:transparent; color: var(--muted); cursor:pointer; font-size:14px; line-height:1;
    transition: border-color .2s ease, color .2s ease;
  }
  .tts-special-remove-btn:hover{ border-color: var(--red); color: var(--red); }

  /* ---------- Popup Voce (ricerca + filtro sesso/lingua + test per riga)
     al posto della tendina .mc-action-menu semplice: troppe voci di sistema
     per uno scroll piatto. Vedi renderVoiceList()/populateVoiceOptionsInto()
     in tts-panel.js. Larghezza fissa (non left/right:0 come .mc-action-menu)
     perché il trigger può essere stretto (voce dedicata per Utente Speciale)
     mentre il popup deve restare comodo da usare. ---------- */
  .tts-voice-popup{
    position:absolute; top: calc(100% + 4px); left:0; z-index:30; width:300px; max-width:80vw;
    background: var(--bg-panel); border:1px solid var(--line); border-radius:10px;
    box-shadow: 0 16px 40px rgba(7,2,13,0.5); padding:10px;
    display:flex; flex-direction:column; gap:8px;
  }
  .tts-voice-popup[hidden]{ display:none; }
  .tts-voice-search{
    width:100%; background: rgba(214,190,245,0.04); border:1px solid var(--line); border-radius:8px;
    padding:8px 10px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif;
  }
  .tts-voice-search:focus{ outline:none; border-color: var(--blue); }
  .tts-voice-filters{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
  .tts-voice-gender-filter{ display:flex; gap:4px; }
  .tts-voice-gender-btn{
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:6px;
    padding:5px 9px; color: var(--muted); font-size:11.5px; cursor:pointer; transition: all .15s ease;
  }
  .tts-voice-gender-btn:hover{ border-color: rgba(185,107,250,0.45); color: var(--ink); }
  .tts-voice-gender-btn.is-active{ background: rgba(185,107,250,0.16); border-color: rgba(185,107,250,0.5); color: var(--blue); }
  /* Filtro Lingua nel popup Voce: stesso trigger+menu .mc-action-field usato
     ovunque nella dashboard (non un <select> nativo, il cui menu a tendina è
     disegnato dal sistema operativo e resta bianco qualunque CSS gli si dia
     — stesso motivo già documentato sopra per il picker regalo). Qui viene
     solo compattato per stare nella riga di filtri stretta accanto ai
     pulsanti F/M. */
  .tts-voice-lang-field{ flex:1; min-width:90px; width:auto; }
  .tts-voice-lang-field .mc-action-trigger{ padding:5px 7px; font-size:11.5px; }
  .tts-voice-lang-field .mc-action-menu{ max-height:180px; }
  .tts-voice-list{
    max-height:220px; overflow-y:auto; display:flex; flex-direction:column; gap:2px;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .tts-voice-list::-webkit-scrollbar{ width:8px; }
  .tts-voice-list::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  /* Intestazione di gruppo mostrata solo quando il filtro lingua è su "Tutte
     le lingue" (renderVoiceList in tts-panel.js): separa visivamente le voci
     di lingue diverse mescolate nello stesso elenco. */
  .tts-voice-group-header{
    padding:8px 8px 3px; font-size:10px; font-weight:700; letter-spacing:.05em;
    text-transform:uppercase; color: var(--muted);
  }
  .tts-voice-group-header:not(:first-child){
    margin-top:4px; border-top:1px solid var(--line); padding-top:9px;
  }
  .tts-voice-option{
    display:flex; align-items:center; justify-content:space-between; gap:8px;
    border-radius:6px; padding:7px 8px; cursor:pointer; font-size:12.5px; color:var(--ink);
  }
  .tts-voice-option:hover{ background: rgba(214,190,245,0.06); }
  .tts-voice-option.is-selected{ background: rgba(185,107,250,0.16); color: var(--blue); }
  .tts-voice-option-label{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .tts-voice-option-lang{ color: var(--muted); font-size:11px; }
  /* Segnala le voci "Online (Natural)" (cloud, sintesi via internet): per
     leggere commenti in diretta hanno un ritardo evidente, meglio evitarle.
     Visibile sia nella lista sia nel pulsante della voce già scelta. */
  .tts-voice-cloud-badge{
    display:inline-block; flex-shrink:0; font-size:9.5px; font-weight:700; letter-spacing:.03em;
    text-transform:uppercase; color:#FF9B3E; background: rgba(255,155,62,0.14);
    border:1px solid rgba(255,155,62,0.4); border-radius:5px; padding:1px 5px; margin-left:4px;
    cursor:help;
  }
  .tts-voice-test-btn{
    flex-shrink:0; width:24px; height:24px; border-radius:6px; border:1px solid var(--line);
    background:transparent; color: var(--blue); cursor:pointer; font-size:10px; line-height:1;
    display:flex; align-items:center; justify-content:center; transition: border-color .15s ease, background .15s ease;
  }
  .tts-voice-test-btn:hover{ background: rgba(185,107,250,0.16); border-color: rgba(185,107,250,0.5); }
  .tts-voice-empty{ color: var(--muted); font-size:12px; text-align:center; padding:14px 4px; }

  /* Utenti Consentiti: categorie in OR fra loro ("Tutti gli utenti" scavalca
     le altre), vedi shouldRead()/isUserAllowedByCategory() in tts-panel.js. */
  .tts-allowed-list{ display:flex; flex-direction:column; gap:2px; margin-top:14px; }
  .tts-allowed-item{
    display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
    padding:10px 12px; border-radius:8px; transition: background .15s ease;
  }
  .tts-allowed-item:hover{ background: rgba(214,190,245,0.03); }
  .tts-allowed-item .tts-checkbox{ color: var(--ink); font-size:13.5px; }
  .tts-allowed-sub{ display:flex; align-items:center; gap:6px; font-size:12px; color: var(--blue); flex-shrink:0; }
  .tts-allowed-sub-input{
    width:48px; background: rgba(214,190,245,0.04); border:1px solid var(--line); border-radius:6px;
    padding:4px 6px; color: var(--ink); font-family:'JetBrains Mono'; font-size:12px; text-align:center;
  }
  .tts-allowed-sub-input:focus{ outline:none; border-color: var(--blue); }
  .tts-allowed-manage-btn{
    background:none; border:none; color: var(--blue); font-size:12px; cursor:pointer; padding:0;
    text-decoration:underline; text-underline-offset:2px;
  }
  .tts-allowed-manage-btn:hover{ color: var(--ink); }

  .mc-slots-head{ display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:12px; margin-bottom: 14px; }
  .mc-slots-actions{ display:flex; gap:10px; flex-wrap:wrap; }
  .mc-table-input{
    width:100%; min-width: 84px; background: rgba(214,190,245,0.03); border:1px solid var(--line);
    border-radius:6px; padding:7px 9px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif;
  }
  .mc-table-input:focus{ outline:none; border-color: var(--blue); }
  .mc-panel-save-btn{ margin-top: 18px; }

  /* ---------- GIFT COMBO (picker regalo icona+nome+diamanti) ---------- */
  .gift-combo-trigger{
    width:100%; display:flex; align-items:center; gap:8px; text-align:left;
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:6px;
    padding:6px 9px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif; cursor:pointer;
    transition: border-color .2s ease;
  }
  .gift-combo-trigger:hover, .gift-combo-trigger.is-open{ border-color: rgba(185,107,250,0.45); }
  .gift-combo-icon{ width:22px; height:22px; border-radius:4px; object-fit:cover; flex-shrink:0; background: rgba(214,190,245,0.06); }
  .gift-combo-icon-empty{ display:inline-block; }
  .gift-combo-name{ flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .gift-combo-cost{ font-family:'JetBrains Mono'; font-size:11px; color: var(--muted); flex-shrink:0; }
  .gift-combo-placeholder{ color: var(--muted); }

  /* Colonna "Trigger" della tabella Eventi per "Regalo (specifico)" (vedi
     triggerCellHtml in azioni-eventi-panel.js): riusa .gift-combo-icon/-name/
     -cost del picker sopra, ma qui il contenitore non è un .gift-combo-trigger
     (niente sfondo/bordo da pulsante, è solo testo di riga) — serve comunque
     lo stesso display:flex perché .gift-combo-name conta su un genitore flex. */
  .ae-trigger-gift-cell{ display:flex; align-items:center; gap:6px; max-width:220px; }
  .ae-trigger-gift-multiplier{ font-family:'JetBrains Mono'; font-size:11px; color: var(--muted); flex-shrink:0; }

  /* ---------- AZIONE (tendina custom, non <select> nativo) ----------
     Il <select> nativo su Windows/Chrome, dentro una grid di card, apriva un
     popup enorme quasi vuoto (bug di rendering del browser) e non poteva comunque
     essere restilizzato secondo il tema scuro del pannello: stesso motivo per cui
     il picker regalo qui sopra usa già un trigger+menu custom invece di un select. */
  .mc-action-field{ position:relative; width:100%; min-width: 84px; }
  .mc-action-trigger{
    width:100%; display:flex; align-items:center; justify-content:space-between; gap:8px;
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:6px;
    padding:7px 9px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif; cursor:pointer;
    transition: border-color .2s ease;
  }
  .mc-action-trigger:hover, .mc-action-trigger[aria-expanded="true"]{ border-color: rgba(185,107,250,0.45); }
  .mc-action-trigger-label{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .mc-action-trigger-caret{ color: var(--muted); font-size:10px; flex-shrink:0; }
  .mc-action-menu{
    position:absolute; top: calc(100% + 4px); left:0; right:0; z-index:30;
    background: var(--bg-panel); border:1px solid var(--line); border-radius:10px;
    box-shadow: 0 16px 40px rgba(7,2,13,0.5); padding:6px;
    max-height:240px; overflow-y:auto;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .mc-action-menu[hidden]{ display:none; }
  .mc-action-menu::-webkit-scrollbar{ width:8px; }
  .mc-action-menu::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  .mc-action-option{
    display:block; width:100%; text-align:left; background:none; border:none; border-radius:6px;
    padding:8px 10px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif; cursor:pointer;
  }
  .mc-action-option:hover{ background: rgba(214,190,245,0.06); }
  .mc-action-option.is-selected{ background: rgba(185,107,250,0.16); color: var(--blue); }

  /* Intestazione di gruppo dentro .mc-action-menu (es. "Minecraft", "Roblox"
     nella tendina "Cosa fermare" della tab Manutenzione): non cliccabile,
     solo per orientarsi in un elenco lungo diviso per categorie. */
  .mc-action-group-label{
    padding:8px 10px 4px; font-size:10.5px; font-weight:700; letter-spacing:.06em;
    text-transform:uppercase; color: var(--muted);
  }
  .mc-action-group-label:first-child{ padding-top:2px; }

  /* Campo di ricerca dentro .mc-action-menu (tendine lunghe: email conosciute,
     catalogo manutenzione) e messaggio "Nessun risultato" quando il filtro
     non trova nulla — vedi wireSearchCombo/wireGroupedDropdown in admin.js. */
  .search-combo-search{
    display:block; width:100%; margin-bottom:6px;
    background: rgba(214,190,245,0.05); border:1px solid var(--line); border-radius:6px;
    padding:7px 9px; color:var(--ink); font-size:12.5px; font-family:'Nunito Sans', sans-serif;
  }
  .search-combo-search:focus{ outline:none; border-color: rgba(185,107,250,0.45); }
  .search-combo-empty{ padding:8px 10px; font-size:12.5px; color: var(--muted); }

  /* Input di testo libero con suggerimenti sotto (es. Email in Trial/Codici
     Referral, Categoria in Avvisa): stesso sfondo/bordo di .mc-action-trigger
     ma senza i suoi flex/cursor:pointer, che non hanno senso su un <input>
     dove si scrive davvero — vedi wireSearchCombo in admin.js. */
  .search-combo-input{
    width:100%; background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:8px;
    padding:10px 12px; color:var(--ink); font-size:13.5px; font-family:'Nunito Sans', sans-serif;
  }
  .search-combo-input:focus{ outline:none; border-color: rgba(185,107,250,0.45); }

  /* Modale a griglia per la scelta del regalo (icona grande + nome + diamanti).
     z-index:95, sopra .mc-prompt-overlay (90): in Minecraft/Roblox si apre
     direttamente sulla pagina, ma in Azioni & Eventi (js/azioni-eventi-panel.js,
     picker del trigger "Regalo (specifico)") si apre DENTRO la finestrella
     "Nuovo evento" — senza questo starebbe visivamente dietro il suo stesso
     overlay. Stesso ragionamento di .ae-alert-preview/.mc-color-panel più sotto. */
  .gift-modal-overlay{
    position:fixed; inset:0; z-index:95; background: rgba(7,2,13,0.72);
    backdrop-filter: blur(10px) saturate(130%); -webkit-backdrop-filter: blur(10px) saturate(130%);
    display:flex; align-items:flex-start; justify-content:center; padding: 6vh 20px;
    overflow-y:auto; overflow-x:hidden;
  }
  .gift-modal-overlay[hidden]{ display:none; }
  /* Ingresso animato come le .mc-prompt-*: prima appariva di colpo — era
     l'unica famiglia di finestre senza transizione. La visibilità qui è su
     [hidden] (display none/flex), quindi niente transition: keyframes, che
     ripartono da soli a ogni riapertura. L'uscita resta immediata, come per
     tutte le finestre del sito. */
  .gift-modal-overlay:not([hidden]){ animation: modal-veil-in .2s ease both; }
  .gift-modal-overlay:not([hidden]) .gift-modal{ animation: modal-pop-in .3s cubic-bezier(.26,1.35,.45,1) both; }
  .gift-modal{
    position:relative; width:100%; max-width:640px; box-sizing:border-box;
    background: linear-gradient(180deg, rgba(214,190,245,0.05) 0%, rgba(214,190,245,0) 140px), var(--bg-panel);
    border:1px solid var(--line); border-radius:20px;
    box-shadow: 0 24px 60px rgba(7,2,13,0.65), 0 4px 16px rgba(7,2,13,0.5), 0 0 44px rgba(168,85,247,0.08);
    padding: 28px 28px 22px;
  }
  .gift-modal-close{
    position:absolute; top:18px; right:18px; background:transparent; border:none;
    color: var(--muted); font-size:16px; cursor:pointer; line-height:1; padding:6px;
    border-radius:10px; transition: color .15s ease, background .15s ease, transform .15s ease;
  }
  .gift-modal-close:hover{ color: var(--ink); background: rgba(214,190,245,0.08); transform: scale(1.08); }
  .gift-modal-close:focus-visible{ outline:2px solid var(--blue); outline-offset:2px; }
  .gift-modal-title{ font-family:'Baloo 2'; font-size:22px; margin-bottom:4px; padding-right:30px; }
  .gift-modal-subtitle{ color: var(--muted); font-size:13.5px; margin-bottom:18px; }
  .gift-modal-search{
    width:100%; background: rgba(214,190,245,0.04); border:1px solid var(--line); border-radius:10px;
    padding:11px 14px; color:var(--ink); font-size:14px; font-family:'Nunito Sans', sans-serif; margin-bottom:20px;
  }
  .gift-modal-search{ transition: border-color .15s ease, box-shadow .15s ease; }
  .gift-modal-search:focus{ outline:none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(168,85,247,0.18); }
  .gift-modal-grid{
    display:grid; grid-template-columns: repeat(4, 1fr); gap: 18px 12px;
    max-height:52vh; overflow-y:auto; overflow-x:hidden; padding: 4px 14px 4px 2px;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .gift-modal-grid::-webkit-scrollbar{ width:8px; }
  .gift-modal-grid::-webkit-scrollbar-track{ background: transparent; }
  .gift-modal-grid::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  .gift-modal-grid::-webkit-scrollbar-thumb:hover{ background: rgba(185,107,250,0.7); }
  @media (max-width: 560px){ .gift-modal-grid{ grid-template-columns: repeat(3, 1fr); } }
  .gift-modal-item{
    display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center;
    background:none; border:none; border-radius:12px; padding:10px 6px; color:var(--ink); cursor:pointer;
    transition: background .15s ease, transform .15s ease;
  }
  .gift-modal-item:hover{ background: rgba(214,190,245,0.06); transform: translateY(-2px); }
  .gift-modal-item-icon{ width:56px; height:56px; border-radius:12px; object-fit:cover; background: rgba(214,190,245,0.06); }
  .gift-modal-item-icon-empty{ display:inline-block; }
  .gift-modal-item-name{ font-size:12.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
  .gift-modal-item-cost{ font-family:'JetBrains Mono'; font-size:11px; color: var(--muted); }
  .gift-modal-empty{ grid-column: 1 / -1; padding:30px 8px; font-size:13px; color: var(--muted); text-align:center; }

  /* Finestrella "Elenco Audio" (Audio pubblici/Audio locali) condivisa —
     js/audio-picker.js, riusata da Azioni & Eventi e dalle slot
     Minecraft/Roblox. Dimensione fissa come le altre finestrelle grandi
     (.ae-action-modal sopra), riquadri quadrati come .gift-modal-item:
     stesso pattern visivo del picker regalo, adattato con due tab invece di
     due sezioni sempre visibili. */
  .mc-prompt-modal.audio-picker-modal{
    width: 640px; max-width: 92vw; height: 600px; max-height: 88vh;
    display:flex; flex-direction:column;
  }
  .audio-picker-modal .mc-prompt-actions{ flex-shrink:0; padding-top:14px; }
  .audio-picker-tabs{ display:flex; gap:8px; margin-bottom:16px; flex-shrink:0; }
  .audio-picker-tab{
    flex:1; background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:999px;
    padding:9px 16px; color: var(--muted); font-size:12.5px; font-weight:600; text-transform:uppercase; letter-spacing:.03em;
    cursor:pointer; transition: border-color .2s ease, color .2s ease;
  }
  .audio-picker-tab:hover{ color: var(--ink); }
  .audio-picker-tab.is-active{ border-color: var(--blue); color: var(--blue); }
  /* Campo della scheda "Cerca online". Riusa .gift-modal-search (stesso
     aspetto del campo di ricerca del picker regalo, un linguaggio solo per
     tutti i campi di ricerca dentro una finestrella): qui si aggiusta solo lo
     spazio sotto e si toglie la possibilità di restringersi, dato che vive
     dentro la colonna flex della modale insieme alla griglia che scorre. */
  .audio-picker-search{ margin-bottom:10px; flex-shrink:0; }
  /* Attribuzione alla fonte dei suoni. Piccola e in disparte, ma presente:
     l'elenco è roba loro, non nostra, e chi lo usa ha diritto di sapere da
     dove arriva. */
  .audio-picker-credit{
    margin:0 0 14px; flex-shrink:0; font-size:11.5px; color: var(--muted); text-align:right;
  }
  .audio-picker-credit a{ color: var(--blue); text-decoration:none; }
  .audio-picker-credit a:hover{ text-decoration:underline; }
  .audio-picker-grid{
    /* auto-fit invece di un numero fisso di colonne + breakpoint a mano:
       il modal si ridimensiona con max-width:92vw, un numero di colonne
       fisso poteva restare "incastrato" a 4 anche quando il modal era già
       più stretto di 640px (tra il breakpoint dei 560px e ~696px di
       viewport), spingendo l'ultima colonna oltre il bordo — segnalato
       come "il terzo audio viene tagliato dallo schermo". Con auto-fit il
       numero di colonne che stanno per davvero nello spazio disponibile si
       ricalcola da solo, non può più succedere. min-width:0 sul contenitore
       stesso (è anche un flex item della modal, non solo un grid container)
       evita che il contenuto minimo di una colonna forzi il modal stesso ad
       allargarsi oltre il bordo dello schermo. */
    flex:1 1 auto; min-width:0; min-height:0; display:grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 18px 12px;
    overflow-y:auto; overflow-x:hidden; padding: 4px 14px 4px 2px;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .audio-picker-grid::-webkit-scrollbar{ width:8px; }
  .audio-picker-grid::-webkit-scrollbar-track{ background: transparent; }
  .audio-picker-grid::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  .audio-picker-tile{
    display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center;
    background:none; border:none; border-radius:12px; padding:10px 6px; color:var(--ink); cursor:pointer;
    min-width:0; transition: background .15s ease, transform .15s ease;
  }
  .audio-picker-tile:hover{ background: rgba(214,190,245,0.06); transform: translateY(-2px); }
  .audio-picker-tile-icon{
    width:56px; height:56px; border-radius:12px; background: rgba(214,190,245,0.06);
    display:flex; align-items:center; justify-content:center; font-size:22px; flex-shrink:0;
  }
  .audio-picker-tile-icon.is-playing{ color: var(--blue); }
  .audio-picker-tile-name{ font-size:12.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
  .audio-picker-tile-duration{ font-family:'JetBrains Mono'; font-size:11px; color: var(--muted); }
  /* Terza riga della tile di un risultato online: al posto della durata (che
     si conosce solo dopo aver scaricato il file) c'è "Importa". Colorata come
     un'azione, non come un dato: quella tile fa una cosa, non descrive un file
     che c'è già. */
  .audio-picker-tile-source{ font-family:'JetBrains Mono'; font-size:11px; color: var(--blue); }
  /* Import in corso: la tile resta al suo posto ma smette di rispondere,
     così due clic di fila non fanno partire due import dello stesso suono. */
  .audio-picker-tile.is-importing{ opacity:.55; pointer-events:none; }
  /* Riquadro in fondo alla lista dei risultati online: non è un suono e non
     si clicca — è il segnale che, entrando nella vista, fa caricare la pagina
     successiva. Niente cursore a manina né sollevamento al passaggio, che
     prometterebbero un gesto che non esiste. */
  .audio-picker-more{ cursor:default; pointer-events:none; opacity:.6; }
  .audio-picker-more:hover{ background:none; transform:none; }
  .audio-picker-more .audio-picker-tile-name{ font-size:11.5px; color: var(--muted); white-space:normal; }
  .audio-picker-dropzone{ border:1px dashed var(--line) !important; transition: border-color .15s ease, background .15s ease; }
  .audio-picker-dropzone .audio-picker-tile-icon{ background: rgba(214,190,245,0.03); }
  .audio-picker-dropzone:hover, .audio-picker-dropzone.is-dragover{ border-color: var(--blue) !important; background: rgba(214,190,245,0.06); }

  /* Unica cosa nuova rispetto a .audio-picker-tile-icon riusata sopra (icona
     generica): la libreria Media mostra una miniatura vera per immagini/gif
     (i video restano un'icona placeholder, vedi js/media-picker.js) — stessa
     dimensione/angoli della tile-icon che sostituisce, object-fit:cover
     perché qualunque proporzione dell'immagine originale riempia comunque il
     quadrato senza deformarsi. */
  .media-picker-tile-thumb{
    width:56px; height:56px; border-radius:12px; object-fit:cover; flex-shrink:0;
  }

  /* Piccola modale nostra per chiedere un nome o confermare un'eliminazione,
     al posto di window.prompt()/window.confirm(). Resta nel DOM anche chiusa:
     la visibilità è su opacità/scala (classe is-open) per poterla animare. */
  .mc-prompt-overlay{
    position:fixed; inset:0; z-index:90; background: rgba(7,2,13,0.72);
    /* blur più deciso + saturate: il contenuto dietro si legge come "sfondo"
       e la finestrella stacca senza dover scurire di più il velo */
    backdrop-filter: blur(10px) saturate(130%); -webkit-backdrop-filter: blur(10px) saturate(130%);
    display:flex; align-items:center; justify-content:center; padding: 20px;
    opacity:0; pointer-events:none; transition: opacity .2s ease;
  }
  .mc-prompt-overlay.is-open{ opacity:1; pointer-events:auto; }
  /* Con una finestrella aperta la pagina di sotto NON scorre: rotella sul
     velo o swipe fuori dalla finestra non devono muovere il fondo. Fatto in
     CSS con :has() invece che con una classe da mettere/togliere via JS nei
     ~28 punti che aprono modali (fragilissimo: basta dimenticarne uno, o
     un early-return su una chiusura, e il blocco resta appiccicato).
     Regola SEPARATA dalle altre, apposta: un browser senza :has() scarta
     solo questa e resta al comportamento di oggi, niente si rompe. */
  html:has(.mc-prompt-overlay.is-open),
  html:has(.gift-modal-overlay:not([hidden])){ overflow: hidden; }
  /* E lo scroll INTERNO delle finestre non "trabocca" sulla pagina quando
     arriva a fine corsa (scroll chaining): vale per il velo scorrevole del
     picker regali e per tutte le aree scorrevoli dentro le finestrelle. */
  .mc-prompt-overlay,
  .gift-modal-overlay,
  .gift-modal-grid,
  .ae-action-modal-scroll,
  .overlay-style-fields-scroll,
  .mc-action-menu{ overscroll-behavior: contain; }
  .mc-prompt-modal{
    width:100%; max-width:360px; box-sizing:border-box;
    /* luce dall'alto sul pannello: un velo chiaro che sfuma nei primi 140px,
       come le superfici "glass" — dà profondità senza cambiare la palette */
    background: linear-gradient(180deg, rgba(214,190,245,0.05) 0%, rgba(214,190,245,0) 140px), var(--bg-panel);
    border:1px solid var(--line); border-radius:18px;
    /* ombra a strati + un alone viola appena percettibile del marchio */
    box-shadow: 0 24px 60px rgba(7,2,13,0.65), 0 4px 16px rgba(7,2,13,0.5), 0 0 44px rgba(168,85,247,0.08);
    padding: 24px;
    transform: scale(.92) translateY(14px); transition: transform .18s ease;
  }
  /* L'ingresso ha un molleggio leggero (cubic-bezier con overshoot), l'uscita
     resta secca col transition breve della regola base: una finestra che
     rimbalza anche mentre se ne va sembrerebbe lenta. */
  .mc-prompt-overlay.is-open .mc-prompt-modal{
    transform: scale(1) translateY(0);
    transition: transform .3s cubic-bezier(.26,1.35,.45,1);
  }
  .mc-prompt-label{ display:block; font-size:14px; line-height:1.55; color: var(--muted); margin-bottom:10px; }
  .mc-prompt-input{
    width:100%; box-sizing:border-box; background: rgba(214,190,245,0.04); border:1px solid var(--line); border-radius:10px;
    padding:11px 14px; color:var(--ink); font-size:14px; font-family:'Nunito Sans', sans-serif; margin-bottom:18px;
    transition: border-color .15s ease, box-shadow .15s ease;
  }
  .mc-prompt-input:hover{ border-color: rgba(214,190,245,0.18); }
  /* Anello di focus morbido, non solo il bordo che cambia colore: si vede
     anche con la finestrella piena di campi, ed è lo stesso trattamento di
     .gift-modal-search più sopra — un solo linguaggio per tutti i campi. */
  .mc-prompt-input:focus{ outline:none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(168,85,247,0.18); }
  .mc-prompt-actions{ display:flex; justify-content:flex-end; gap:10px; }
  /* Pulsanti a piè di finestrella più asciutti del .btn base (14px 24px,
     pensato per le call-to-action del sito): dentro una modale sono comandi,
     non promozioni. */
  .mc-prompt-actions .btn{ padding: 10px 18px; font-size: 13.5px; }
  .mc-prompt-actions .btn:active{ transform: translateY(1px) scale(.99); }
  .mc-prompt-actions .btn-danger{ background: var(--red); color:#F1E7FF; border-color: var(--red); }
  .mc-prompt-actions .btn-danger:hover{ box-shadow: 0 8px 24px rgba(124,31,212,0.35); }

  /* Ingresso condiviso delle finestre a [hidden] (oggi .gift-modal-*, vedi
     lì): stesso movimento della .mc-prompt-modal, scritto a keyframes perché
     display none→flex non può usare transition. */
  @keyframes modal-veil-in{ from{ opacity:0; } to{ opacity:1; } }
  @keyframes modal-pop-in{
    from{ opacity:0; transform: scale(.92) translateY(14px); }
    to{ opacity:1; transform: none; }
  }

  /* Le tre finestrelle grandi a piè fisso (Nuova azione, Elenco Audio/Media,
     Personalizza overlay) hanno i pulsanti sempre in vista sotto il contenuto
     che scorre: il filetto li separa dal contenuto e dice "questa è la barra
     dei comandi", specie a metà scroll. */
  .ae-action-modal .mc-prompt-actions,
  .audio-picker-modal .mc-prompt-actions,
  .overlay-style-modal .mc-prompt-actions{ border-top: 1px solid var(--line); }

  /* Chi naviga da tastiera deve vedere dove si trova anche nelle griglie dei
     picker (regali, audio): stesso anello di focus dei campi. */
  .gift-modal-item:focus-visible,
  .audio-picker-tile:focus-visible{ outline:2px solid var(--blue); outline-offset:2px; }

  /* Con "riduci animazioni" attivo nel sistema: le finestre appaiono e basta,
     niente molleggio né dissolvenze. */
  @media (prefers-reduced-motion: reduce){
    .mc-prompt-overlay, .mc-prompt-modal,
    .mc-prompt-overlay.is-open .mc-prompt-modal{ transition: none; }
    .gift-modal-overlay:not([hidden]),
    .gift-modal-overlay:not([hidden]) .gift-modal{ animation: none; }
  }

  /* Finestrella "Personalizza overlay" (tasto accanto a Copia/Reset, solo
     admin): riusa .mc-prompt-overlay/.mc-prompt-modal sopra, solo i campi
     font/scala sono specifici. Con 10+ campi (set "ricco"/win) il modulo non
     ci stava più in altezza sullo schermo: qui limitiamo l'altezza della
     modale e rendiamo scrollabile SOLO l'elenco campi, mentre titolo e
     pulsanti Annulla/Ripristina/Salva restano sempre visibili in alto/basso. */
  /* max-width sopra i 360 della .mc-prompt-modal base: con le sezioni a
     card (bordo + padding) le righe etichetta+controllo respirano; il
     selettore combinato serve a battere la regola base in specificità. */
  .mc-prompt-modal.overlay-style-modal{ max-width: 430px; max-height: 88vh; display:flex; flex-direction:column; }
  .overlay-style-fields-scroll{
    flex:1 1 auto; min-height:0; overflow-y:auto; overflow-x:hidden; padding-right:4px;
    /* margine negativo per non far toccare la scrollbar ai bordi del campo */
    margin-right:-4px;
    /* niente scrollbar-width/scrollbar-color qui: basterebbero a far tornare
       Chromium alla scrollbar di sistema per questo elemento, vanificando le
       regole WebKit globali. Firefox e` gia` coperto dal blocco @supports in cima. */
  }
  .overlay-style-fields-scroll::-webkit-scrollbar{ width:8px; }
  .overlay-style-fields-scroll::-webkit-scrollbar-track{ background: transparent; }
  .overlay-style-fields-scroll::-webkit-scrollbar-thumb{ background: rgba(185,107,250,0.45); border-radius:999px; }
  .overlay-style-fields-scroll::-webkit-scrollbar-thumb:hover{ background: rgba(185,107,250,0.7); }
  .overlay-style-modal .mc-prompt-actions{ flex-shrink:0; padding-top:14px; }
  .overlay-style-field{ margin-bottom:18px; }
  .overlay-style-field-label{ display:flex; align-items:center; justify-content:space-between; font-size:13px; color: var(--ink); margin-bottom:8px; }
  .overlay-style-field input[type="range"]{ width:100%; accent-color: var(--blue); }
  /* Tendina Font: .mc-action-field già ha width:100%, qui basta azzerare il
     margin-bottom di troppo verso il campo successivo (vive dentro
     .overlay-style-field, che ha già il suo). */
  .overlay-style-field .mc-action-field{ margin-bottom:0; }

  /* Set di campi "ricco" (solo Top Regali/Top Like, vedi isRichTarget in
     overlay-panel.js): etichetta a sinistra, controllo a destra su ogni riga,
     invece della pila etichetta-sopra/controllo-sotto di .overlay-style-field
     usata dal set semplice (Win/Top Gift/Top Streak) sopra. */
  /* Sezioni di "Personalizza overlay" (styleSection in overlay-panel.js):
     Testo / Sfondo / Elementi / Immagine ed effetti — la lista piatta di
     10-17 righe non si leggeva più, il raggruppamento a card con titoletto
     in maiuscoletto è lo stesso schema della finestra impostazioni dei
     giochi (Spiral/Vertical). Solo contenitori: le righe dentro sono le
     .overlay-style-row di sempre. */
  .overlay-style-section{
    border:1px solid var(--line); border-radius:12px;
    background: rgba(214,190,245,0.02);
    padding:12px 14px 2px; margin-bottom:12px;
  }
  .overlay-style-section-title{
    font-size:11px; font-weight:800; letter-spacing:0.09em; text-transform:uppercase;
    color: var(--muted); margin:0 0 10px;
  }
  .overlay-style-row{
    display:flex; align-items:center; justify-content:space-between; gap:14px;
    margin-bottom:12px;
  }
  .overlay-style-row-label{ font-size:13px; color: var(--ink); flex:1 1 auto; }
  .overlay-style-row-control{ display:flex; align-items:center; gap:10px; flex:0 0 auto; }
  .overlay-style-row-control input[type="range"]{ width:140px; accent-color: var(--blue); }
  .overlay-style-row-control strong{ font-family:'JetBrains Mono'; font-size:12.5px; color: var(--muted); min-width:28px; text-align:right; }
  .overlay-style-row .mc-action-field{ flex:0 0 auto; width:170px; }
  /* Color picker custom (colorFieldMarkup in overlay-panel.js) al posto
     dell'<input type="color"> nativo: quella finestrella è del sistema
     operativo/browser, fuori dal DOM, quindi impossibile da restilizzare.
     .mc-color-field è il wrapper posizionato (position:relative) da cui il
     pannello si apre in assoluto, .mc-color-trigger è lo swatch cliccabile.
     Non più scoped a .overlay-style-row: riusato anche nella riga rapida
     colore/opacità di "Mostra alert" (azioni-eventi-panel.js). */
  .mc-color-field{ position:relative; flex:0 0 auto; }
  .mc-color-trigger{
    -webkit-appearance:none; appearance:none;
    width:32px; height:32px; padding:0; border-radius:9px; border:2px solid var(--line);
    cursor:pointer; flex-shrink:0; display:block;
    transition: border-color .15s ease, box-shadow .15s ease, transform .1s ease;
  }
  .mc-color-trigger:hover{ border-color: var(--blue); transform: scale(1.06); }
  .mc-color-trigger[aria-expanded="true"]{
    border-color: var(--blue); box-shadow: 0 0 0 3px rgba(168,85,247,0.25);
  }
  /* Pannello: stesso linguaggio visivo di .mc-action-menu (tendina font) —
     stesso sfondo/bordo/ombra/border-radius, per sembrare un unico sistema di
     popover invece di due componenti diversi nella stessa finestrella. Si
     apre ancorato al bordo destro dello swatch (right:0), larghezza fissa
     abbastanza stretta da restare sempre dentro alla modale anche quando lo
     swatch è vicino al bordo destro. */
  /* position:fixed (non più absolute) con top/left calcolati via JS al click
     (vedi wireColorPickers in overlay-panel.js): un antenato con
     overflow:hidden/auto (.ae-action-modal-scroll/.overlay-style-fields-
     scroll, entrambe le finestrelle che usano questo picker) taglierebbe un
     popover absolute che esce dai propri bordi — fixed lo fa uscire dal
     flusso di clipping di qualunque contenitore scorrevole. */
  .mc-color-panel{
    position:fixed; z-index:120; width:200px;
    background: var(--bg-panel); border:1px solid var(--line); border-radius:10px;
    box-shadow: 0 16px 40px rgba(7,2,13,0.5); padding:12px;
    display:flex; flex-direction:column; gap:10px;
  }
  .mc-color-panel[hidden]{ display:none; }
  .mc-color-hex-input{
    width:100%; box-sizing:border-box; text-align:center; text-transform:uppercase;
    background: rgba(214,190,245,0.04); border:1px solid var(--line); border-radius:6px;
    padding:7px 9px; color:var(--ink); font-family:'JetBrains Mono'; font-size:12.5px; letter-spacing:0.5px;
  }
  .mc-color-hex-input:focus{ outline:none; border-color: var(--blue); }
  /* Quadrato saturazione (asse x) / valore (asse y): il colore di base
     (hsl(tinta,100%,50%)) è impostato via JS su background-color, i due
     gradienti qui sopra (bianco da sinistra, nero dal basso) sono fissi e
     restano identici qualunque sia la tinta corrente — stesso principio del
     "SV square" di un color picker completo (Photoshop/Finder/ecc). */
  .mc-color-sv{
    position:relative; width:100%; height:120px; border-radius:8px; overflow:hidden;
    cursor:crosshair; touch-action:none;
    background-image:
      linear-gradient(to top, #000, rgba(0,0,0,0)),
      linear-gradient(to right, #fff, rgba(255,255,255,0));
  }
  .mc-color-sv-pointer{
    position:absolute; width:14px; height:14px; margin:-7px; border-radius:50%;
    border:2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.4);
    pointer-events:none;
  }
  /* Barra tinta: arcobaleno fisso (le 6 tacche HSL a 60° l'una dall'altra),
     trascinabile in orizzontale per scegliere la tinta di base del quadrato. */
  .mc-color-hue-bar{
    position:relative; width:100%; height:14px; border-radius:7px; cursor:pointer; touch-action:none;
    background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
  }
  .mc-color-hue-pointer{
    position:absolute; top:50%; width:16px; height:16px; margin:-8px; border-radius:50%;
    border:2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.4);
    pointer-events:none;
  }
  .overlay-style-row input[type="checkbox"]{ width:18px; height:18px; accent-color: var(--blue); cursor:pointer; flex-shrink:0; }
  /* Casella di testo numerica (Dimensione testo, Opacità sfondo, Righe nel
     set "ricco"): al posto dello slider, il valore si scrive/legge
     direttamente nel campo, niente elemento separato da tenere sincronizzato. */
  .overlay-style-row .overlay-style-number-input{
    width:64px; flex-shrink:0; text-align:right;
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:6px;
    padding:7px 9px; color:var(--ink); font-family:'JetBrains Mono'; font-size:12.5px;
  }
  .overlay-style-row .overlay-style-number-input:focus{ outline:none; border-color: var(--blue); }
  /* Casella di testo (campo "Titolo" di Top Gift/Top Streak): stesso stile
     della casella numerica sopra, ma allineata a sinistra e più larga. */
  .overlay-style-row .overlay-style-text-input{
    width:200px; flex-shrink:0; text-align:left;
    background: rgba(214,190,245,0.03); border:1px solid var(--line); border-radius:6px;
    padding:7px 9px; color:var(--ink); font-family:'Nunito Sans', sans-serif; font-size:12.5px;
  }
  .overlay-style-row .overlay-style-text-input:focus{ outline:none; border-color: var(--blue); }

  /* Variante rossa della stessa modale, per conferme distruttive/irreversibili
     (es. eliminare una riga dalla tab Abbonamenti): bordo e titolo rossi invece
     del grigio neutro di default, per farla leggere subito come pericolosa
     prima ancora di leggere il testo. */
  .mc-prompt-modal.is-danger{
    border-color: var(--red);
    box-shadow: 0 24px 60px rgba(7,2,13,0.65), 0 0 44px rgba(124,31,212,0.28);
  }
  .mc-prompt-label.is-danger{ color: var(--red); font-weight:700; }

  /* Lista di opzioni verticale nella mc-prompt-modal (es. scelta del metodo di
     pagamento nel pannello admin): stessi .btn, ma a piena larghezza e allineati
     a sinistra invece che centrati come i pulsanti normali. */
  .mc-prompt-options{ display:flex; flex-direction:column; gap:8px; margin-bottom:18px; }
  .mc-prompt-options .btn{ width:100%; justify-content:flex-start; box-sizing:border-box; }
  .mc-prompt-options .btn-outline.is-trial{ border-style:dashed; color: var(--muted); }

  /* Scheda utente (tab Utenti del pannello admin, click su una riga): non più
     un popup ma un pannello a sé, con URL proprio su dashboard.tikforge.net
     (/dashboard/admin/utenti/<id>). Il popup non reggeva la quantità di dati
     da mostrare — un'intera anagrafica più cinque tabelle — e non era
     collegabile: le classi .user-detail-* qui sotto restano perché la scheda
     riusa gli stessi stili di testo (caricamento, vuoto, totale). */
  .admin-back-btn{
    display:inline-flex; align-items:center; gap:6px; margin-bottom: 18px;
    background:none; border:none; padding:0; cursor:pointer;
    font-family:'Nunito Sans', sans-serif; font-size: 13.5px; font-weight:700; color: var(--muted);
    transition: color .2s ease;
  }
  .admin-back-btn:hover{ color: var(--ink); }
  .admin-back-btn svg{ width:16px; height:16px; }

  /* Barra azioni in cima alla scheda utente. Non usa gli .admin-action-btn
     minuscoli della riga nell'elenco: lì stanno dentro una cella di tabella e
     devono restare compatti, qui sono l'unica cosa cliccabile della pagina e
     possono permettersi di farsi vedere. Font Baloo 2 (quello dei titoli)
     invece del monospace, corpo più grande, colori per gruppo.

     Due gruppi: a sinistra quello che si fa tutti i giorni (abbonamento,
     sblocco, contatto), a destra — spinto in fondo da margin-left:auto — le
     due azioni che cambiano o cancellano l'account. Separarli fisicamente è
     metà del lavoro: nessuno preme "Elimina" credendo di premere "Sblocca"
     se i due non sono mai adiacenti. */
  .admin-user-actions{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin: 20px 0 10px; }
  .admin-user-actions:empty{ margin:0; }
  .admin-user-actions-danger{ display:flex; flex-wrap:wrap; gap:10px; margin-left:auto; }
  /* Sotto i 620px i due gruppi finiscono uno sotto l'altro: margin-left:auto
     su una riga tutta sua spingerebbe i pulsanti pericolosi contro il bordo
     destro, staccati da tutto. Meglio allineati a sinistra come gli altri. */
  @media (max-width: 620px){
    .admin-user-actions-danger{ margin-left:0; width:100%; }
  }

  /* I due canali del popup "Contatta", ognuno col colore del suo mezzo invece
     di due pulsanti identici da leggere per capire quale è quale: Discord nel
     suo blurple (riusa .btn-discord, già definito più in alto per "Collega
     Discord"), l'email in ambra. L'ambra non è nella palette del sito ed è
     voluto: serviva un colore che non fosse né viola (tutto il resto) né
     rosso (le azioni distruttive), e la posta non ha un colore suo da
     rispettare come ce l'ha Discord. */
  /* Email: il viola normale dei pulsanti del sito (stessi valori di
     .btn-primary). Prima era ambra, per dare a ogni canale un colore proprio
     come Discord ha il suo — ma due tinte piene e sature una sopra l'altra su
     fondo nero stancano l'occhio, e l'ambra tirava a sé tutta l'attenzione
     senza meritarsela: Discord ha un colore da rispettare, l'email no. */
  .btn-mail{ background: var(--blue); color: #F1E7FF; }
  .btn-mail:hover{ box-shadow: 0 8px 24px rgba(0,0,0,0.25), 0 0 24px rgba(168,85,247,0.4); }
  .btn-mail svg{ width:19px; height:19px; flex:none; }
  .admin-contact-options .btn-discord svg{ width:19px; height:19px; flex:none; fill: currentColor; }
  /* Icona e testo centrati insieme nel pulsante. .mc-prompt-options impone
     justify-content:flex-start a tutte le sue opzioni (là serve: sono elenchi
     di voci da scorrere con l'occhio lungo il bordo sinistro), ma qui i
     pulsanti sono due soli e larghi quanto la modale — appoggiati a sinistra
     lasciavano un vuoto sproporzionato a destra. */
  .admin-contact-options .btn{ gap:10px; justify-content:center; }
  /* Un po' d'aria attorno ai due canali: la domanda in cima non deve stare
     appiccicata al primo pulsante, e i due pulsanti non devono sembrare un
     blocco unico diviso da una riga. Valori piccoli di proposito - la modale
     resta compatta, sono solo due scelte. */
  .admin-contact-options{ gap:12px; margin: 18px 0 20px; }

  /* Canale non disponibile (es. Discord non collegato): resta visibile ma
     spento. Regola scoped a questo popup e non un `.btn:disabled` globale:
     nel sito ci sono altri .btn che vengono disabilitati durante un invio, e
     non voglio cambiarli tutti da qui. */
  .admin-contact-options .btn:disabled{ opacity:.45; cursor:not-allowed; }
  .admin-contact-options .btn:disabled:hover{ transform:none; box-shadow:none; filter:none; }

  /* Pannello per scrivere un'email a un utente (Contatta → Email). Più largo e
     più alto della mc-prompt-modal normale: qui non si sceglie, si scrive.
     max-height + overflow perché su un portatile 13" la textarea da 12 righe
     più i modelli superano l'altezza dello schermo. */
  .admin-email-modal{ max-width: 640px; max-height: 88vh; overflow-y: auto; }
  .admin-email-head{
    display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
    margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid var(--line);
  }
  .admin-email-title{ font-family:'Baloo 2', sans-serif; font-size:18px; font-weight:700; color: var(--ink); }
  .admin-email-to{ margin-top:4px; font-size:13px; color: var(--muted); word-break: break-all; }
  .admin-email-to strong{ color: var(--ink); font-weight:600; }
  .admin-email-close{
    flex-shrink:0; width:32px; height:32px; border-radius:50%; border:1px solid var(--line);
    background: transparent; color: var(--muted); font-size:18px; line-height:1; cursor:pointer;
    transition: color .2s ease, border-color .2s ease, background .2s ease;
  }
  .admin-email-close:hover{ color: var(--ink); border-color: var(--blue); background: rgba(168,85,247,0.12); }

  /* Modelli: pastiglie in fila, vanno a capo da sole. Volutamente piccole e
     senza colore — sono un punto di partenza, non l'azione della finestra. */
  .admin-email-templates{ margin-bottom: 18px; }
  .admin-email-templates-label{
    display:block; margin-bottom:8px;
    font-family:'JetBrains Mono'; font-size:10.5px; text-transform:uppercase;
    letter-spacing:0.05em; color: var(--muted);
  }
  .admin-email-template-list{ display:flex; flex-wrap:wrap; gap:8px; }
  .admin-email-template{
    font-family:'Nunito Sans', sans-serif; font-size:12.5px; font-weight:600;
    padding:6px 13px; border-radius:999px; cursor:pointer;
    border:1px solid var(--line); background: rgba(214,190,245,0.04); color: var(--muted);
    transition: border-color .2s ease, color .2s ease, background .2s ease;
  }
  .admin-email-template:hover{ border-color: var(--blue); color: var(--ink); background: rgba(168,85,247,0.10); }

  .admin-email-body{
    resize: vertical; min-height: 220px; line-height:1.6;
    font-family:'Nunito Sans', sans-serif;
  }
  .admin-email-hint{
    margin: -8px 0 18px; color: var(--muted); font-size:12px; line-height:1.5;
  }
  .admin-email-feedback{
    margin-bottom:14px; padding:10px 12px; border-radius:8px; font-size:13px;
    background: rgba(168,85,247,0.10); border:1px solid rgba(168,85,247,0.4); color:#E6D5FF;
  }
  .admin-email-feedback.is-error{
    background: var(--danger-soft); border-color: rgba(239,68,68,0.45); color: var(--danger);
  }

  /* Anteprima dell'embed nel pannello "Messaggio diretto su Discord". Non è
     una decorazione: un embed non somiglia a niente di quello che si vede
     scrivendo in una textarea, e senza anteprima si manda alla cieca.
     I colori sono quelli veri di Discord (#2B2D31 lo sfondo del messaggio,
     #1E1F22 la barra del riquadro), non quelli del sito: deve somigliare a
     dove finirà, non alla pagina da cui si scrive. L'unico colore nostro è la
     barra laterale viola, che è esattamente ciò che l'embed avrà davvero
     (EMBED_COLOR in services/discordLink.js = --blue del sito). */
  .admin-dm-preview{ margin-bottom: 18px; }
  .dm-embed{
    position: relative; border-radius: 4px;
    background: #2B2D31; border-left: 4px solid var(--blue);
    padding: 12px 16px;
    font-family: 'Nunito Sans', 'gg sans', sans-serif;
  }
  .dm-embed-title{ color:#FFFFFF; font-size:15px; font-weight:700; margin-bottom:6px; word-break: break-word; }
  /* pre-wrap: gli a capo scritti nella textarea si vedono nell'anteprima
     esattamente come li vedrà l'utente, invece di collassare in un blocco. */
  .dm-embed-body{ color:#DBDEE1; font-size:14px; line-height:1.5; white-space: pre-wrap; word-break: break-word; }
  .dm-embed-footer{ margin-top:10px; color:#949BA4; font-size:11.5px; font-weight:600; }

  .admin-user-btn{
    font-family:'Baloo 2', sans-serif; font-weight:700; font-size:14.5px; letter-spacing:0.01em;
    padding: 11px 20px; border-radius: 10px; cursor:pointer;
    display:inline-flex; align-items:center; gap:8px;
    border:1px solid var(--line); background: transparent; color: var(--ink);
    transition: background .2s ease, border-color .2s ease, color .2s ease, transform .15s ease;
  }
  .admin-user-btn:hover{ transform: translateY(-1px); }
  .admin-user-btn:active{ transform: translateY(0); }
  .admin-user-btn svg{ width:17px; height:17px; flex:none; }

  /* Attiva abbonamento: l'azione positiva, l'unica piena di colore. */
  .admin-user-btn.is-primary{
    background: linear-gradient(135deg, var(--blue), var(--red));
    border-color: transparent; color:#fff;
  }
  .admin-user-btn.is-primary:hover{ box-shadow: 0 10px 26px -10px rgba(168,85,247,0.8); }

  /* Disattiva abbonamento e Sblocca: neutri, si accendono al passaggio. */
  .admin-user-btn.is-neutral:hover{ border-color: var(--blue); background: rgba(168,85,247,0.10); }

  /* Contatta: riconoscibile ma non invadente, è un'azione che si cerca. */
  .admin-user-btn.is-contact{ color: var(--blue); border-color: rgba(168,85,247,0.45); }
  .admin-user-btn.is-contact:hover{ background: rgba(168,85,247,0.14); border-color: var(--blue); }

  /* Rendi admin: rossa ma vuota. È pericolosa (dà pieni poteri) e sta nel
     gruppo di destra, ma si può disfare — non merita lo stesso peso visivo di
     un'eliminazione definitiva. */
  .admin-user-btn.is-danger-soft{ color: var(--danger); border-color: rgba(239,68,68,0.45); }
  .admin-user-btn.is-danger-soft:hover{ background: var(--danger-soft); border-color: var(--danger); }

  /* Elimina: l'unica piena di rosso in tutta la pagina. */
  .admin-user-btn.is-danger{ background: var(--danger); border-color: var(--danger); color:#fff; }
  .admin-user-btn.is-danger:hover{ background:#DC2626; box-shadow: 0 10px 26px -10px rgba(239,68,68,0.75); }

  /* Frecce e indicatore di pagina sotto le tabelle lunghe della scheda utente
     (sessioni di gioco, tentativi di accesso). Allineati a destra, sotto
     l'angolo della tabella: è dove si finisce a guardare dopo aver letto
     l'ultima riga. */
  .table-pager{
    display:flex; align-items:center; justify-content:flex-end; gap:10px;
    margin-top: 12px;
  }
  /* Il display:flex qui sopra è una regola d'autore e batte il display:none
     che il browser dà da sé a [hidden]: senza questa riga il pager dell'elenco
     utenti resterebbe a schermo anche quando c'è una pagina sola. Stesso
     inciampo già capitato con .btn[hidden] e .dash-nav-btn[hidden]. */
  .table-pager[hidden]{ display:none; }
  .table-pager-state{
    font-family:'Nunito Sans', sans-serif; font-size:12.5px; color: var(--muted);
  }
  .table-pager-btn{
    display:inline-flex; align-items:center; justify-content:center;
    width:30px; height:30px; border-radius:8px; cursor:pointer;
    border:1px solid var(--line); background: rgba(214,190,245,0.04); color: var(--ink);
    transition: border-color .2s ease, background .2s ease, color .2s ease;
  }
  .table-pager-btn svg{ width:16px; height:16px; }
  .table-pager-btn:hover:not(:disabled){ border-color: var(--blue); background: rgba(168,85,247,0.12); }
  /* Disabilitata agli estremi invece che nascosta: le due frecce restano al
     loro posto, così l'indicatore in mezzo non si sposta cambiando pagina. */
  .table-pager-btn:disabled{ opacity:.3; cursor:default; }

  .admin-user-card{ max-width:none; margin-top: 22px; }
  .admin-user-card-title{ font-size:15px; margin-bottom:16px; }
  /* Due colonne invece delle tre della .profile-grid normale: qui le etichette
     sono lunghe ("Attivazione manuale scade il") e a tre colonne andavano a
     capo tutte. */
  .admin-user-card .profile-grid{ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

  .user-detail-loading{ color: var(--muted); font-size: 14px; padding: 12px 0; }
  .user-detail-empty{ color: var(--muted); font-size: 13.5px; padding: 4px 0; }
  .user-detail-total{ margin-top:12px; font-size: 14px; }
  .user-detail-total strong{ font-family:'Baloo 2'; font-size:17px; }

  /* Sotto-tab Configurazione/Sessione di Gioco dentro il tab Minecraft. */
  .mc-subtabs{ display:flex; gap:8px; margin: 18px 0 26px; border-bottom: 1px solid var(--line); }
  .mc-subtab-btn{
    background:none; border:none; color: var(--muted); font-family:'Nunito Sans', sans-serif;
    font-size: 14px; font-weight:600; padding: 10px 10px; cursor:pointer; border-bottom: 2px solid transparent;
    transition: color .2s ease, border-color .2s ease;
  }
  .mc-subtab-btn:hover{ color: var(--ink); }
  .mc-subtab-btn.active{ color: var(--ink); border-bottom-color: var(--blue); text-shadow: 0 0 18px rgba(168,85,247,0.5); }
  .mc-subpanel[hidden]{ display:none; }

  /* Griglia di card per i 20 slot e gli eventi aggiuntivi (v2): rimpiazza la
     tabella della v1, troppo stretta per Modalità di Esecuzione + Effetti. */
  .mc-slots-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:16px; }
  .mc-slot-card{
    border:1px solid var(--line); border-radius:12px; padding:16px; background: rgba(214,190,245,0.02);
    display:flex; flex-direction:column; gap:12px;
  }
  /* Tutta l'intestazione (non solo l'iconcina ⠿) è il punto da tenere premuto
     per trascinare/riordinare lo slot (vedi initSlotCardDrag in
     js/roblox-panel.js e js/minecraft-panel.js): cursor:grab segnala che si
     può trascinare, touch-action:none impedisce allo scroll della pagina di
     "rubare" il gesto su schermi touch, user-select:none evita che
     tenere-premuto-e-trascinare selezioni il testo del titolo invece di
     spostare la card (comportamento predefinito del browser altrimenti). */
  .mc-slot-card-head{
    display:flex; align-items:center; justify-content:space-between;
    cursor:grab; touch-action:none; user-select:none;
  }
  .mc-slot-card-head:active{ cursor:grabbing; }
  .mc-slot-card-head-left{ display:flex; align-items:center; gap:6px; min-width:0; }
  .mc-slot-card-head h4{ margin:0; font-size:14px; }
  .mc-slot-drag-handle{ color: var(--muted); font-size:16px; line-height:1; flex-shrink:0; }
  .mc-slot-remove-btn{
    background:none; border:none; color: var(--muted); cursor:pointer; font-size:16px; line-height:1; padding:2px 6px;
  }
  .mc-slot-remove-btn:hover{ color: var(--ink); }
  .mc-slot-card.mc-slot-card-dragging{ opacity:0.5; border-style:dashed; }
  .mc-field-label{ font-size:11px; text-transform:uppercase; letter-spacing:.04em; color: var(--muted); margin-bottom:4px; display:block; }
  .mc-effects-box{ border-top:1px solid var(--line); padding-top:10px; display:flex; flex-direction:column; gap:8px; }
  /* Opzione "Riproduci audio": indipendente dall'azione scelta sopra (non è
     .mc-effects-box, che è specifico dei parametri DELL'azione), un
     checkbox che mostra/nasconde le proprie impostazioni (picker + volume). */
  .mc-audio-option{ border-top:1px solid var(--line); padding-top:10px; }
  .mc-audio-toggle{
    display:flex; align-items:center; gap:8px; cursor:pointer;
    color: var(--ink); font-size:12.5px; margin-bottom:8px;
  }
  .mc-audio-toggle input[type="checkbox"]{ accent-color: var(--blue); cursor:pointer; width:16px; height:16px; }
  [data-audio-settings]{ display:flex; flex-direction:column; gap:6px; }
  [data-audio-settings] input[type="range"]{ width:100%; accent-color: var(--blue); cursor:pointer; }
  /* Card "Coda delle Azioni" nella tab Sessione di Gioco. */
  .mc-queue-count{ font-family:'Baloo 2', sans-serif; font-size:40px; font-weight:700; margin-top:10px; }
  .mc-queue-label{ color: var(--muted); font-size:13px; }
  .mc-queue-reset-btn{ margin-top:16px; }
  .mc-empty-state{ text-align:center; color: var(--muted); padding: 20px 0; }

  /* Statistiche live della sessione in corso (regali/diamanti/messaggi/durata),
     mostrate dentro la card "Controllo Sessione" solo mentre si è collegati. */
  .mc-session-stats{ display:grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap:16px; margin-top:18px; padding-top:16px; border-top:1px solid var(--line); }
  .mc-stat-value{ font-family:'Baloo 2', sans-serif; font-size:24px; font-weight:700; }
  .mc-stat-label{ color: var(--muted); font-size:12px; margin-top:2px; }

  /* Utility usate al posto di style="..." inline: la CSP del sito (style-src
     'self', niente unsafe-inline) blocca qualsiasi attributo/assegnazione style
     scritta a mano, sia in markup che via JS (.style.xxx). */
  .mc-hidden{ display:none !important; }
  .mc-input-sm{ max-width: 90px; }
  .mc-input-md{ max-width: 120px; }
  .mc-input-lg{ max-width: 280px; }
  .mc-mt-sm{ margin-top: 6px; }
  .mc-field-hint{ text-transform:none; margin-top:4px; }

  /* ---------- DASHBOARD: layout dedicato (solo dashboard.html, via body.page-dashboard) ----------
     Stessa palette premium della home, ridefinita qui sopra le variabili globali
     così ogni componente esistente (sidebar, card, tabelle, badge, form, modali)
     la eredita in automatico SOLO nella dashboard, senza toccare admin.html o
     le altre pagine del sito che riusano le stesse classi. */
  body.page-dashboard{
    --bg: #000000;
    --bg-panel: #0F0817;
    --bg-panel-2: #150C20;
    --blue: #A855F7;
    --red: #7C1FD4;
    --ink: #F1E7FF;
    --muted: #B6A0CF;
    --line: rgba(214,190,245,0.08);
    background: var(--bg);
  }

  body.page-dashboard .app-sidebar{
    background: var(--bg-panel);
    box-shadow: 1px 0 0 var(--line);
  }
  body.page-dashboard .app-sidebar-brand{ border-bottom-color: var(--line); }

  body.page-dashboard .dash-nav-btn{ position:relative; }
  body.page-dashboard .dash-nav-btn.active{
    background: rgba(168,85,247,0.14);
  }
  body.page-dashboard .dash-nav-btn.active::before{
    content:''; position:absolute; left:-18px; top:50%; transform: translateY(-50%);
    width:3px; height:18px; border-radius: 0 3px 3px 0; background: var(--blue);
  }
  @media (max-width: 860px){ body.page-dashboard .dash-nav-btn.active::before{ display:none; } }

  body.page-dashboard .dash-avatar{ color: var(--bg); }

  /* La foto del profilo TikTok sta SOPRA l'iniziale, non al posto suo: se
     l'immagine non carica (gli indirizzi della CDN di TikTok scadono, vedi
     refreshTiktokAvatarInBackground lato server) js/dashboard.js la toglie e
     sotto ricompare la lettera, senza un riquadro rotto in mezzo. */
  body.page-dashboard .dash-avatar{ position: relative; overflow: hidden; }
  body.page-dashboard .dash-avatar .dash-avatar-photo{
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; border-radius: 50%; display: block;
  }

  body.page-dashboard .badge-admin{ color: var(--red); border-color: rgba(124,31,212,0.4); background: rgba(124,31,212,0.08); }
  body.page-dashboard .badge-active{ color: var(--blue); border-color: rgba(168,85,247,0.4); background: rgba(168,85,247,0.08); }
  body.page-dashboard .badge-trial{ color: #FFB020; border-color: rgba(255,176,32,0.4); background: rgba(255,176,32,0.08); }
  body.page-dashboard .badge-subscriber{ color: #4ADE80; border-color: rgba(74,222,128,0.4); background: rgba(74,222,128,0.08); }

  body.page-dashboard .connections-card,
  body.page-dashboard .sub-card,
  body.page-dashboard .mc-slot-card{
    border-radius: 16px;
    transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
  }
  body.page-dashboard .connections-card:hover,
  body.page-dashboard .sub-card:hover{
    border-color: rgba(214,190,245,0.16);
    box-shadow: 0 18px 40px rgba(0,0,0,0.4);
  }

  body.page-dashboard .admin-stat{
    border-radius: 14px;
    transition: border-color .25s ease, transform .25s ease;
  }
  body.page-dashboard .admin-stat:hover{ border-color: rgba(214,190,245,0.18); transform: translateY(-2px); }

  body.page-dashboard .admin-table tbody tr,
  body.page-dashboard #mc-sessions-table tbody tr,
  body.page-dashboard #billing-history-table tbody tr{
    transition: background .15s ease;
  }
  body.page-dashboard .admin-table tbody tr:hover,
  body.page-dashboard #mc-sessions-table tbody tr:hover,
  body.page-dashboard #billing-history-table tbody tr:hover{
    background: rgba(214,190,245,0.03);
  }

  /* Anche qui rosso: questi override esistevano solo per ripetere il viola del
     marchio, che sull'eliminazione dell'account non allarma nessuno. Restano
     per non lasciare che le regole generiche vengano scavalcate da altro. */
  body.page-dashboard .danger-zone{ border-top-color: rgba(239,68,68,0.32); }
  body.page-dashboard .danger-zone h3{ color: #F87171; }
  body.page-dashboard .danger-zone .btn-danger{
    background: rgba(239,68,68,0.08); border-color: rgba(239,68,68,0.5); color: #F87171;
  }
  body.page-dashboard .danger-zone .btn-danger:hover{
    background: #EF4444; border-color: #EF4444; color: #FFFFFF;
  }
  body.page-dashboard .danger-confirm{ border-color: rgba(239,68,68,0.4); background: rgba(239,68,68,0.07); }
  body.page-dashboard .form-message.is-error{ background: rgba(124,31,212,0.10); border-color: rgba(124,31,212,0.4); }
  body.page-dashboard .form-message.is-success{ background: rgba(168,85,247,0.10); border-color: rgba(168,85,247,0.4); }

  body.page-dashboard .payment-method:hover{ border-color: rgba(168,85,247,0.4); }
  body.page-dashboard .payment-method.selected{ border-color: var(--blue); background: rgba(168,85,247,0.08); }

  body.page-dashboard .field input:focus{ background: rgba(168,85,247,0.05); }

  body.page-dashboard .game-card:hover,
  body.page-dashboard .game-platform-tile:hover{ box-shadow: 0 18px 40px rgba(0,0,0,0.5); }

  body.page-dashboard .mc-action-menu,
  body.page-dashboard .mc-color-panel,
  body.page-dashboard .lang-dropdown-list{
    box-shadow: 0 20px 44px rgba(0,0,0,0.5);
  }
  /* Le finestre modali tengono anche in dashboard l'ombra a strati con
     l'alone viola della regola base (solo su base nera invece che viola
     scurissimo): l'override piatto di prima le faceva sembrare adesivi. */
  body.page-dashboard .gift-modal,
  body.page-dashboard .mc-prompt-modal{
    box-shadow: 0 24px 60px rgba(0,0,0,0.6), 0 4px 16px rgba(0,0,0,0.45), 0 0 44px rgba(168,85,247,0.08);
  }
  /* ...e la variante distruttiva non perde il suo alone viola nemmeno qui
     (questa regola batte per specificità quella qui sopra, apposta). */
  body.page-dashboard .mc-prompt-modal.is-danger{
    box-shadow: 0 24px 60px rgba(0,0,0,0.6), 0 0 44px rgba(124,31,212,0.28);
  }
  body.page-dashboard .gift-modal-overlay,
  body.page-dashboard .mc-prompt-overlay{ background: rgba(0,0,0,0.75); }
  body.page-dashboard .mc-action-menu::-webkit-scrollbar-thumb{ background: rgba(168,85,247,0.45); }
  body.page-dashboard .overlay-style-fields-scroll::-webkit-scrollbar-thumb{ background: rgba(168,85,247,0.45); }
  body.page-dashboard .mc-action-option.is-selected{ background: rgba(168,85,247,0.16); color: var(--blue); }
  body.page-dashboard .gift-combo-trigger:hover, body.page-dashboard .gift-combo-trigger.is-open{ border-color: rgba(168,85,247,0.45); }
  body.page-dashboard .mc-action-trigger:hover, body.page-dashboard .mc-action-trigger[aria-expanded="true"]{ border-color: rgba(168,85,247,0.45); }

  body.page-dashboard .toast{ box-shadow: 0 18px 40px rgba(0,0,0,0.5); }

  /* =================================================================
     DASHBOARD 2026 — shell, barra superiore e Panoramica
     ------------------------------------------------------------------
     Estende (non sostituisce) il blocco DASHBOARD / APP SHELL più sopra.
     Tutto è agganciato a body.page-dashboard, quindi il sito pubblico
     (body.page-site) non viene toccato.

     Nota sugli identificatori: le voci del menu conservano i data-tab
     storici (profilo, giochi, aggiornamenti…) anche dove l'etichetta è
     cambiata. Cambiarli avrebbe rotto gli URL /dashboard/<tab>, i
     deep-link da minecraft.html/roblox.html e syncTabFromPath in
     js/dashboard.js.
     ================================================================= */
  body.page-dashboard{
    --panel: #100A1A;
    --panel-2: #160E24;
    --line-2: rgba(206,186,255,0.16);
    --violet: #8B5CF6;
    --violet-2: #A855F7;
    --violet-3: #C084FC;
    --dim: #8B81A3;
    --ok: #4ADE80;
  }

  /* ---------- SIDEBAR ---------- */
  body.page-dashboard .app-sidebar{ width: 248px; padding: 18px 14px; gap: 0; }
  /* Stesso trabocchetto del footer in home: questa regola è più specifica
     della media query generica su .app-sidebar (che a ≤860px la rende
     "width:auto" per farla diventare una barra orizzontale), e senza la
     ripetizione qui sotto la sidebar restava una colonna da 248px anche su
     telefono, schiacciando tutto il resto. */
  @media (max-width: 860px){ body.page-dashboard .app-sidebar{ width: auto; padding: 16px 16px 14px; } }
  body.page-dashboard .app-sidebar-brand{
    padding: 4px 6px 16px; margin-bottom: 14px;
  }
  body.page-dashboard .app-sidebar-brand-name{
    font-size: 17px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase;
  }
  body.page-dashboard .app-sidebar-brand-sub{ display: none; }

  /* Il logo resta agganciato in cima mentre il resto della barra gli scorre
     sotto. Con dodici voci di menu su uno schermo basso la barra laterale
     scorre, e prima se ne andava su anche il logo: chi scorreva perdeva il
     riferimento di dove si trovava.

     Solo da 861px in su: sotto quella soglia la barra diventa orizzontale e non
     scorre affatto, quindi lo sticky non avrebbe un contenitore a cui
     agganciarsi e finirebbe per attaccarsi alla FINESTRA, restando incollato
     sopra il contenuto della pagina.

     Il padding superiore si sposta dalla barra al logo. Sembra un dettaglio ma
     non lo è: lo sticky si aggancia al bordo del contenitore, padding compreso,
     quindi lasciandolo sulla barra il logo si sarebbe fermato appiccicato al
     bordo dello schermo. Dentro al logo, invece, quello spazio viaggia con lui
     ed è coperto dal suo stesso sfondo — che serve comunque, altrimenti le voci
     di menu si vedrebbero passare in trasparenza. */
  @media (min-width: 861px){
    body.page-dashboard .app-sidebar{ padding-top: 0; }
    body.page-dashboard .app-sidebar-brand{
      position: sticky; top: 0; z-index: 2;
      padding-top: 22px;
      background: var(--bg-panel);
    }
  }

  /* Scheda utente in cima, come nel riferimento (prima era in fondo). */
  body.page-dashboard .app-sidebar > .dash-user{
    display: flex; align-items: center; gap: 11px;
    padding: 0 6px 16px; margin-bottom: 14px;
    border-bottom: 1px solid var(--line);
  }
  body.page-dashboard .dash-avatar{
    width: 42px; height: 42px; border-radius: 50%; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--violet-3), var(--violet));
    color: #fff; font-family: 'Baloo 2', sans-serif; font-weight: 800; font-size: 17px;
  }
  /* La colonna di testo deve poter rimpicciolire sotto la larghezza del suo
     contenuto, altrimenti i troncamenti con i puntini qui sotto non scattano
     mai (regola di default dei flex item: min-width: auto). */
  body.page-dashboard .app-sidebar > .dash-user > div:last-child{ min-width: 0; }
  body.page-dashboard .dash-user-hello{
    font-family: 'Baloo 2', sans-serif; font-size: 14.5px; font-weight: 700; color: var(--ink);
    display: flex; align-items: baseline; gap: 5px;
  }
  /* Il nome viene dall'email (vedi js/dashboard-overview.js) e può essere
     lungo quanto si vuole: la riga andava a capo e la manina 👋 restava da
     sola sulla seconda riga, sballando l'allineamento con l'avatar. Ora si
     accorcia il saluto con i puntini e la manina, che sta fuori dalla parte
     troncabile, resta sempre in fondo alla stessa riga. */
  body.page-dashboard .dash-hello-text{
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  body.page-dashboard .dash-hello-wave{ flex: none; }
  body.page-dashboard .dash-user-email{
    font-size: 11.5px; color: var(--dim);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 150px;
  }
  /* Il pill del ruolo è lo <span class="badge badge-admin|-trial|-inactive">
     che inserisce js/dashboard.js (renderProfile): questo contenitore deve
     restare nudo. Stilizzandolo a sua volta come pill si vedevano due bordi
     arrotondati uno dentro l'altro, e il viola fisso del contenitore copriva
     il colore del ruolo (arancione per la prova, grigio per l'utente base). */
  body.page-dashboard .dash-role-badge:not(:empty){ display: block; margin-top: 6px; }

  /* Agenzia dell'utente: logo a sinistra, nome a destra, sotto la riga che
     chiude la scheda utente. La riempie renderAgency (js/dashboard.js) e la
     vede solo chi in un'agenzia ci sta davvero — per tutti gli altri il <div>
     resta hidden e la barra laterale è identica a prima.
     :not([hidden]) obbligatorio: un display esplicito d'autore vince sul
     display:none dell'attributo hidden, e il blocco vuoto comparirebbe a
     tutti. Stessa trappola già annotata su .overlay-subpanes. */
  body.page-dashboard .app-sidebar > .dash-agency:not([hidden]){
    display: flex; align-items: center; gap: 10px;
    padding: 0 6px 14px; margin-bottom: 14px;
    border-bottom: 1px solid var(--line);
  }
  /* Riquadro con l'iniziale, e il logo vero ci va sopra: stesso meccanismo
     dell'avatar (position:relative + overflow:hidden), così un file mancante
     lascia la lettera invece di un riquadro rotto. Angoli smussati e non
     tondo: i loghi delle agenzie sono marchi, non facce. */
  body.page-dashboard .dash-agency-logo{
    position: relative; overflow: hidden; flex: none;
    width: 30px; height: 30px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(214,190,245,0.06); border: 1px solid var(--line);
    color: var(--muted); font-family: 'Baloo 2', sans-serif; font-weight: 800; font-size: 13px;
  }
  body.page-dashboard .dash-agency-logo-img{
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  }
  /* min-width:0 come per il saluto qui sopra: senza, il nome lungo allarga la
     riga invece di accorciarsi con i puntini. */
  body.page-dashboard .dash-agency-name{
    min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  body.page-dashboard .dash-nav{ flex: none; gap: 3px; }
  body.page-dashboard .dash-nav-btn{
    font-size: 14px; font-weight: 600; padding: 10px 12px; border-radius: 10px;
  }
  body.page-dashboard .dash-nav-btn.active{
    background: rgba(139,92,246,0.14); color: var(--ink);
    box-shadow: inset 0 0 0 1px rgba(168,85,247,0.28);
  }
  body.page-dashboard .nav-icon{ width: 17px; height: 17px; flex: none; }

  /* Riquadro "Stato sistema" in fondo alla barra. */
  body.page-dashboard .dash-sysbox{
    margin-top: 16px; padding: 14px; border-radius: 14px;
    background: rgba(206,186,255,0.03); border: 1px solid var(--line);
  }
  body.page-dashboard .dash-sysbox-head{
    display: flex; align-items: center; gap: 8px;
    font-size: 12.5px; font-weight: 700; color: var(--ink);
  }
  body.page-dashboard .dash-sysbox-head svg{ width: 14px; height: 14px; color: var(--violet-3); }
  body.page-dashboard .dash-sysbox-sub{
    display: flex; align-items: center; gap: 6px;
    margin: 6px 0 12px; font-size: 11px; color: var(--ok);
  }
  body.page-dashboard .dash-sysbox-rows{ display: flex; flex-direction: column; gap: 7px; }
  body.page-dashboard .dash-sysrow{
    display: flex; align-items: center; justify-content: space-between;
    font-size: 11.5px; color: var(--dim);
  }
  body.page-dashboard .dash-sysrow b{ font-weight: 600; color: var(--ok); }
  body.page-dashboard .dash-sysrow.is-down b{ color: #F87171; }
  body.page-dashboard .dash-sysbox-link{
    display: flex; align-items: center; justify-content: space-between;
    margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line);
    font-size: 11.5px; color: var(--violet-3);
  }
  body.page-dashboard .dash-sysbox-link svg{ width: 13px; height: 13px; }

  body.page-dashboard .app-sidebar-footer{
    margin-top: auto; padding-top: 14px; border-top: 1px solid var(--line);
  }
  /* Centrata sul pulsante che introduce, e in --muted invece di --dim: a
     11.5px il grigio più scuro si leggeva a fatica sul fondo della barra. */
  body.page-dashboard .dash-help-label{
    font-size: 12.5px; color: var(--muted); text-align: center; margin-bottom: 8px;
  }

  /* Il pulsante Esci vive nella barra superiore: nella barra laterale
     resterebbe duplicato. Il ":has" limita la regola alle pagine che una
     barra superiore ce l'hanno davvero: admin.html condivide
     body.page-dashboard ma il suo unico Esci è quello qui nel fondo della
     barra laterale, e senza questa condizione spariva, lasciando quella
     pagina senza modo di uscire. */
  body.page-dashboard .app-shell:has(.dash-topbar) .app-sidebar-footer .dash-logout{ display: none; }

  /* ---------- BARRA SUPERIORE ---------- */
  body.page-dashboard .app-main{ min-width: 0; flex: 1; display: flex; flex-direction: column; }
  /* Azzerare il padding non è una rifinitura: il padding generico di .app-main
     (44px 48px, pensato per le pagine senza barra superiore) teneva la barra
     staccata di 44px dal bordo alto e di 48px dai lati, quindi non partiva mai
     attaccata allo schermo — si incollava sì scorrendo, ma da lì sembrava non
     ancorata. La spaziatura del contenuto la mette .app-main-wrap più sotto.
     Il ":has" limita la regola alle pagine che la barra ce l'hanno davvero:
     admin.html usa la stessa classe .app-main ma non ha barra superiore e
     tiene la spaziatura di prima. */
  body.page-dashboard .app-main:has(> .dash-topbar){ padding: 0; }
  body.page-dashboard .dash-topbar{
    position: sticky; top: 0; z-index: 30;
    display: flex; align-items: center; gap: 16px;
    padding: 14px 26px; background: rgba(8,5,14,0.86);
    backdrop-filter: blur(16px); border-bottom: 1px solid var(--line);
  }
  body.page-dashboard .dash-search{
    position: relative; flex: 0 1 420px; min-width: 0;
  }
  body.page-dashboard .dash-search svg{
    position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
    width: 16px; height: 16px; color: var(--dim); pointer-events: none;
  }
  body.page-dashboard .dash-search input{
    width: 100%; padding: 11px 14px 11px 38px; border-radius: 11px;
    background: rgba(206,186,255,0.04); border: 1px solid var(--line);
    color: var(--ink); font-family: 'Nunito Sans', sans-serif; font-size: 14px;
    transition: border-color .2s ease, background .2s ease;
  }
  body.page-dashboard .dash-search input::placeholder{ color: var(--dim); }
  body.page-dashboard .dash-search input:focus{
    outline: none; border-color: rgba(168,85,247,0.5); background: rgba(139,92,246,0.07);
  }
  /* Risultati della ricerca: saltano alla sezione, non cercano nei dati. */
  body.page-dashboard .dash-search-results{
    position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 40;
    padding: 6px; border-radius: 14px;
    background: var(--panel); border: 1px solid var(--line-2);
    box-shadow: 0 26px 60px rgba(0,0,0,0.6);
  }
  body.page-dashboard .dash-search-results[hidden]{ display: none; }
  body.page-dashboard .dash-search-results button{
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 10px 12px; border: none; border-radius: 10px; cursor: pointer;
    background: transparent; color: var(--ink);
    font-family: 'Nunito Sans', sans-serif; font-size: 13.5px; text-align: left;
  }
  body.page-dashboard .dash-search-results button:hover,
  body.page-dashboard .dash-search-results button.is-active{ background: rgba(139,92,246,0.14); }
  body.page-dashboard .dash-search-empty{ padding: 10px 12px; font-size: 13px; color: var(--dim); }

  body.page-dashboard .dash-topbar-actions{
    display: flex; align-items: center; gap: 10px; margin-left: auto;
    /* Con cinque controlli la riga può non bastare su schermi stretti: vanno
       a capo invece di schiacciarsi, restando allineati a destra. */
    flex-wrap: wrap; justify-content: flex-end;
  }
  /* "Connetti Live" nella barra superiore: stessa forma degli altri pulsanti
     in alto, ma tiene lo stato pieno quando è collegato (data-connected="1",
     lo imposta js/overlay-panel.js) — è l'unico pulsante qui che ha uno stato
     acceso/spento da far vedere a colpo d'occhio. */
  body.page-dashboard .dash-topbar .app-overlay-btn{
    padding: 10px 16px; border-radius: 11px; gap: 8px;
    background: rgba(206,186,255,0.04); border: 1px solid var(--line);
    font-size: 13.5px; font-weight: 600;
  }
  body.page-dashboard .dash-topbar .app-overlay-btn:hover:not(:disabled){
    border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-dashboard .dash-topbar .app-overlay-btn[data-connected="1"]{
    background: var(--violet); border-color: var(--violet); color: #fff;
  }
  body.page-dashboard .dash-topbar .app-overlay-btn .nav-icon{ width: 16px; height: 16px; }
  /* Selettore lingua: altezza allineata agli altri pulsanti in alto. La
     tendina si apre da sola verso destra grazie a .lang-dropdown-list
     (position:absolute; right:0), non serve altro. */
  body.page-dashboard .dash-topbar-lang .lang-dropdown-btn{
    padding: 11px 12px; border-radius: 11px;
    background: rgba(206,186,255,0.04); border-color: var(--line);
  }
  body.page-dashboard .dash-topbar-lang[open] .lang-dropdown-btn,
  body.page-dashboard .dash-topbar-lang:hover .lang-dropdown-btn{
    border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-dashboard .dash-top-btn{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 10px 16px; border-radius: 11px; cursor: pointer;
    background: rgba(206,186,255,0.04); border: 1px solid var(--line);
    color: var(--ink); font-family: 'Nunito Sans', sans-serif; font-size: 13.5px; font-weight: 600;
    transition: border-color .2s ease, background .2s ease;
  }
  body.page-dashboard .dash-top-btn:hover{
    border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-dashboard .dash-top-btn svg{ width: 16px; height: 16px; flex: none; }
  body.page-dashboard .dash-top-btn.is-icon{ padding: 10px; position: relative; }
  body.page-dashboard .dash-bell-badge{
    position: absolute; top: -6px; right: -6px; min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 999px; background: #E0245E; color: #fff;
    font-size: 10.5px; font-weight: 800; line-height: 18px; text-align: center;
  }
  body.page-dashboard .dash-bell-badge[hidden]{ display: none; }
  body.page-dashboard .dash-topbar .dash-logout{
    display: inline-flex; align-items: center; gap: 8px;
    width: auto; margin: 0; padding: 10px 16px; border-radius: 11px;
    background: rgba(206,186,255,0.04); border: 1px solid var(--line); color: var(--ink);
    font-size: 13.5px; font-weight: 600;
  }
  body.page-dashboard .dash-topbar .dash-logout:hover{
    border-color: rgba(224,36,94,0.5); background: rgba(224,36,94,0.1);
  }
  @media (max-width: 860px){
    body.page-dashboard .dash-topbar{ padding: 12px 16px; flex-wrap: wrap; }
    body.page-dashboard .dash-search{ flex: 1 1 100%; order: 3; }
  }

  body.page-dashboard .app-main-wrap{ padding: 26px; flex: 1; }
  @media (max-width: 860px){ body.page-dashboard .app-main-wrap{ padding: 18px 16px; } }

  /* ---------- INTESTAZIONE DELLA PANORAMICA ---------- */
  body.page-dashboard .ov-head{
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
  }
  body.page-dashboard .ov-head h1{
    font-family: 'Baloo 2', sans-serif; font-size: 28px; font-weight: 800; letter-spacing: -0.02em;
  }
  body.page-dashboard .ov-head p{ margin-top: 6px; font-size: 14.5px; color: var(--dim); }

  /* ---------- QUATTRO CONTATORI ---------- */
  body.page-dashboard .ov-stats{
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 18px;
  }
  @media (max-width: 1200px){ body.page-dashboard .ov-stats{ grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 620px){ body.page-dashboard .ov-stats{ grid-template-columns: 1fr; } }
  body.page-dashboard .ov-stat{
    display: flex; gap: 14px; padding: 18px 18px 20px; border-radius: 16px;
    background: var(--panel); border: 1px solid var(--line);
  }
  body.page-dashboard .ov-stat-ico{
    width: 42px; height: 42px; border-radius: 12px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.14); color: var(--violet-3);
  }
  body.page-dashboard .ov-stat-ico svg{ width: 20px; height: 20px; }
  body.page-dashboard .ov-stat-label{ font-size: 12.5px; color: var(--dim); }
  body.page-dashboard .ov-stat-value{
    margin-top: 4px; font-family: 'Baloo 2', sans-serif; font-size: 26px; font-weight: 800; line-height: 1.15;
  }
  body.page-dashboard .ov-stat-value small{ font-size: 15px; font-weight: 600; color: var(--dim); }
  body.page-dashboard .ov-stat-note{ margin-top: 6px; font-size: 11.5px; color: var(--dim); }
  body.page-dashboard .ov-stat-note.is-ok{ color: var(--ok); }
  /* Contatore senza fonte dati: valore neutro, mai un numero inventato. */
  body.page-dashboard .ov-stat.is-empty .ov-stat-value{ color: var(--dim); font-size: 30px; }

  /* ---------- GRIGLIA PRINCIPALE ---------- */
  /* minmax(0, …) invece del solo "1fr": una traccia "1fr" vale
     minmax(auto, 1fr), e quel minimo automatico è il min-content del suo
     contenuto — così una riga larga dentro una card allargava la colonna
     oltre il contenitore, sfondando la dashboard di 52px in orizzontale su
     schermo da 390px. Con minimo 0 la colonna resta dentro e a stringersi è
     il contenuto (che sa già farlo: .ov-conn-name ha l'ellissi). */
  body.page-dashboard .ov-grid{
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 0.95fr);
    gap: 16px; align-items: start;
  }
  @media (max-width: 1280px){ body.page-dashboard .ov-grid{ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
  @media (max-width: 860px){ body.page-dashboard .ov-grid{ grid-template-columns: minmax(0, 1fr); } }

  body.page-dashboard .ov-card{
    padding: 20px; border-radius: 16px;
    background: var(--panel); border: 1px solid var(--line);
  }
  body.page-dashboard .ov-card + .ov-card{ margin-top: 16px; }
  body.page-dashboard .ov-card-head{
    display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px;
  }
  body.page-dashboard .ov-card-head h2{
    font-family: 'Baloo 2', sans-serif; font-size: 17px; font-weight: 700;
    display: flex; align-items: center; gap: 9px;
  }
  body.page-dashboard .ov-card-head h2 svg{ width: 16px; height: 16px; color: var(--violet-3); }
  body.page-dashboard .ov-link{
    display: inline-flex; align-items: center; gap: 5px;
    background: none; border: none; cursor: pointer; padding: 0;
    font-family: 'Nunito Sans', sans-serif; font-size: 12.5px; font-weight: 600; color: var(--violet-3);
  }
  body.page-dashboard .ov-link:hover{ text-decoration: underline; }
  body.page-dashboard .ov-pill{
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 11px; border-radius: 999px;
    font-size: 11.5px; font-weight: 700;
    background: rgba(74,222,128,0.12); color: var(--ok);
  }
  body.page-dashboard .ov-pill.is-off{ background: rgba(206,186,255,0.08); color: var(--dim); }
  body.page-dashboard .ov-dot{
    width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none;
  }

  /* ---------- CONNESSIONI ---------- */
  body.page-dashboard .ov-conn{
    display: flex; align-items: center; gap: 14px;
    padding: 14px; border-radius: 13px;
    background: rgba(206,186,255,0.03); border: 1px solid var(--line);
  }
  body.page-dashboard .ov-conn + .ov-conn{ margin-top: 10px; }
  body.page-dashboard .ov-conn-ico{
    width: 46px; height: 46px; border-radius: 11px; flex: none;
    background-size: cover; background-position: center;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
  }
  body.page-dashboard .ov-conn-body{ flex: 1; min-width: 0; }
  body.page-dashboard .ov-conn-title{
    display: flex; align-items: center; gap: 9px; flex-wrap: nowrap; min-width: 0;
    font-family: 'Baloo 2', sans-serif; font-size: 15px; font-weight: 700;
  }
  /* Il nome si accorcia, la pastiglia di stato non va mai a capo. */
  body.page-dashboard .ov-conn-name{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  body.page-dashboard .ov-conn-title .ov-pill{ flex: none; white-space: nowrap; }
  body.page-dashboard .ov-conn-meta{ margin-top: 5px; font-size: 12px; color: var(--dim); line-height: 1.5; }
  body.page-dashboard .ov-conn-meta span{ display: block; }
  body.page-dashboard .ov-conn .ov-manage{
    flex: none; display: inline-flex; align-items: center; gap: 7px;
    padding: 9px 14px; border-radius: 10px; cursor: pointer;
    background: rgba(206,186,255,0.05); border: 1px solid var(--line);
    color: var(--ink); font-family: 'Nunito Sans', sans-serif; font-size: 13px; font-weight: 600;
  }
  body.page-dashboard .ov-conn .ov-manage:hover{
    border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1);
  }
  body.page-dashboard .ov-conn .ov-manage svg{ width: 14px; height: 14px; }
  body.page-dashboard .ov-add{
    display: inline-flex; align-items: center; gap: 8px; margin-top: 14px;
    background: none; border: none; padding: 0; cursor: pointer;
    font-family: 'Nunito Sans', sans-serif; font-size: 13px; font-weight: 600; color: var(--violet-3);
  }
  body.page-dashboard .ov-add svg{ width: 16px; height: 16px; }

  /* ---------- ELENCHI (azioni recenti, annunci) ---------- */
  body.page-dashboard .ov-feed-row{
    display: flex; align-items: center; gap: 12px; padding: 11px 0;
    border-bottom: 1px solid var(--line);
  }
  body.page-dashboard .ov-feed-row:last-child{ border-bottom: none; }
  body.page-dashboard .ov-feed-ico{
    width: 34px; height: 34px; border-radius: 10px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: rgba(139,92,246,0.13); color: var(--violet-3);
  }
  body.page-dashboard .ov-feed-ico svg{ width: 16px; height: 16px; }
  body.page-dashboard .ov-feed-body{ flex: 1; min-width: 0; }
  body.page-dashboard .ov-feed-title{ font-size: 13.5px; font-weight: 700; color: var(--ink); }
  body.page-dashboard .ov-feed-sub{ margin-top: 2px; font-size: 12px; color: var(--dim); }
  body.page-dashboard .ov-feed-time{ flex: none; font-size: 11.5px; color: var(--dim); }

  /* Stato vuoto onesto: usato ovunque manchi la fonte dati lato server. */
  body.page-dashboard .ov-empty{
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 30px 16px; text-align: center;
  }
  body.page-dashboard .ov-empty svg{ width: 26px; height: 26px; color: var(--dim); opacity: .7; }
  body.page-dashboard .ov-empty p{ font-size: 13px; color: var(--dim); max-width: 260px; line-height: 1.55; }

  /* ---------- ABBONAMENTO ---------- */
  body.page-dashboard .ov-card.is-plan{
    border-color: rgba(168,85,247,0.3);
    background: linear-gradient(168deg, rgba(38,24,62,0.7), rgba(16,10,26,0.9));
  }
  body.page-dashboard .ov-plan-name{
    font-family: 'Baloo 2', sans-serif; font-size: 22px; font-weight: 800; color: var(--violet-3);
  }
  body.page-dashboard .ov-plan-price{ margin-top: 8px; font-size: 18px; font-weight: 700; }
  body.page-dashboard .ov-plan-price small{ font-size: 13px; font-weight: 500; color: var(--dim); }
  body.page-dashboard .ov-plan-renew{ margin-top: 6px; font-size: 12.5px; color: var(--dim); }
  body.page-dashboard .ov-plan-cta{
    display: block; width: 100%; margin-top: 16px; padding: 13px; border-radius: 11px;
    border: none; cursor: pointer; text-align: center;
    background: linear-gradient(135deg, #9B6BFF, #7C3AED); color: #fff;
    font-family: 'Nunito Sans', sans-serif; font-size: 14px; font-weight: 700;
    box-shadow: 0 10px 26px rgba(124,58,237,0.35);
  }
  body.page-dashboard .ov-plan-cta:hover{ filter: brightness(1.06); }

  /* ---------- AZIONI RAPIDE ---------- */
  body.page-dashboard .ov-quick{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
  body.page-dashboard .ov-quick button,
  body.page-dashboard .ov-quick a{
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 14px 8px; border-radius: 12px; cursor: pointer; text-align: center;
    background: rgba(206,186,255,0.03); border: 1px solid var(--line);
    color: var(--ink); font-family: 'Nunito Sans', sans-serif; font-size: 11.5px; font-weight: 600;
    transition: border-color .2s ease, background .2s ease, transform .15s ease;
  }
  body.page-dashboard .ov-quick button:hover,
  body.page-dashboard .ov-quick a:hover{
    border-color: rgba(168,85,247,0.45); background: rgba(139,92,246,0.1); transform: translateY(-2px);
  }
  body.page-dashboard .ov-quick svg{ width: 18px; height: 18px; color: var(--violet-3); }

  /* ---------- RIQUADRI OVERLAY E TTS ---------- */
  body.page-dashboard .ov-bottom{
    display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 16px;
  }
  @media (max-width: 1000px){ body.page-dashboard .ov-bottom{ grid-template-columns: 1fr; } }
  body.page-dashboard .ov-split{ display: flex; gap: 18px; flex-wrap: wrap; }
  body.page-dashboard .ov-preview{
    width: 200px; height: 130px; flex: none; border-radius: 12px; overflow: hidden;
    background: linear-gradient(160deg, #241a38, #0e0a18);
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
  }
  body.page-dashboard .ov-preview svg{ width: 34px; height: 34px; color: rgba(206,186,255,0.35); }
  body.page-dashboard .ov-split-body{ flex: 1; min-width: 190px; }
  body.page-dashboard .ov-kv{ margin-top: 10px; font-size: 12.5px; color: var(--dim); line-height: 1.7; }
  body.page-dashboard .ov-kv b{ color: var(--ink); font-weight: 600; }
  body.page-dashboard .ov-actions{ display: flex; align-items: center; gap: 14px; margin-top: 16px; flex-wrap: wrap; }
  body.page-dashboard .ov-btn{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 11px 18px; border-radius: 11px; border: none; cursor: pointer;
    background: linear-gradient(135deg, #9B6BFF, #7C3AED); color: #fff;
    font-family: 'Nunito Sans', sans-serif; font-size: 13.5px; font-weight: 700;
  }
  body.page-dashboard .ov-btn:hover{ filter: brightness(1.06); }
  body.page-dashboard .ov-btn svg{ width: 14px; height: 14px; }

  /* Onda del TTS: pura decorazione CSS, non rappresenta audio reale. */
  body.page-dashboard .ov-wave{
    display: flex; align-items: center; gap: 3px; height: 62px; margin-top: 4px;
  }
  body.page-dashboard .ov-wave i{
    flex: 1; border-radius: 2px; background: linear-gradient(180deg, var(--violet-3), var(--violet));
    animation: ov-wave 1.4s ease-in-out infinite;
  }
  @keyframes ov-wave{ 0%,100%{ height: 18%; opacity:.55; } 50%{ height: 86%; opacity:1; } }
  @media (prefers-reduced-motion: reduce){ body.page-dashboard .ov-wave i{ animation: none; height: 45%; } }

  /* ---------- PIÈ DI PAGINA ---------- */
  body.page-dashboard .dash-footer{
    display: flex; align-items: center; justify-content: center; gap: 26px; flex-wrap: wrap;
    padding: 22px 26px; border-top: 1px solid var(--line);
    font-size: 12.5px; color: var(--dim);
  }
  body.page-dashboard .dash-footer a{ color: var(--dim); }
  body.page-dashboard .dash-footer a:hover{ color: var(--ink); }

  /* ---------- MANUTENZIONE (js/maintenance.js) ----------
     Schermata a tutto schermo quando è fermo il sito o la dashboard, più il
     contrassegno sulle card di piattaforme e giochi fermi. Lo stato arriva da
     GET /api/maintenance, scritto dal bot Discord con /manutenzione. */
  .maint-screen{
    position: fixed; inset: 0; z-index: 9999;
    display: flex; align-items: center; justify-content: center; padding: 24px;
    background:
      radial-gradient(720px 420px at 50% 18%, rgba(139,92,246,0.22), transparent 62%),
      rgba(6,4,10,0.97);
    backdrop-filter: blur(6px);
  }
  .maint-box{
    max-width: 560px; text-align: center;
    border: 1px solid rgba(168,85,247,0.28); border-radius: 28px; padding: 44px 38px;
    background: linear-gradient(168deg, rgba(30,21,48,0.94), rgba(13,10,20,0.97));
    box-shadow: 0 44px 96px -40px rgba(124,58,237,0.6);
  }
  .maint-badge{
    display: inline-flex; align-items: center; padding: 6px 14px; border-radius: 999px;
    background: rgba(255,176,32,0.14); border: 1px solid rgba(255,176,32,0.4);
    font-size: 11.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: #FFB020;
  }
  .maint-box h1{
    margin: 18px 0 12px; font-family:'Baloo 2', sans-serif;
    font-size: clamp(26px, 4vw, 36px); letter-spacing: -0.02em; color: #F1E7FF;
  }
  .maint-box p{ font-size: 15px; line-height: 1.7; color: #B6A0CF; }
  /* Il motivo lo scrive lo staff: può essere lungo o assente, quindi si stacca
     dal testo fisso invece di continuarlo. */
  .maint-reason{
    margin-top: 14px; padding-top: 14px; border-top: 1px solid rgba(214,190,245,0.12);
    font-size: 14px !important; color: #8B81A3 !important;
  }
  .maint-actions{ display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 26px; }

  /* Card di una piattaforma o di un gioco fermo. */
  .maint-tag{
    position: absolute; top: 14px; right: 14px; z-index: 3;
    padding: 5px 12px; border-radius: 999px;
    background: rgba(7,2,13,0.78); border: 1px solid rgba(255,176,32,0.45);
    font-size: 11.5px; font-weight: 700; color: #FFB020; backdrop-filter: blur(6px);
  }
  .is-maintenance{ cursor: not-allowed; }
  /* Selettori lunghi apposta: .lib-card.is-locked e .game-platform-tile.is-locked
     hanno gia una loro sfumatura piu leggera, e senza scendere a questo
     livello di specificita vincerebbero loro lasciando la card quasi accesa. */
  body.page-site .lib-card.is-maintenance .lib-media,
  body.page-dashboard .game-platform-tile.is-maintenance .game-thumb,
  body.page-dashboard .game-card.is-maintenance .game-thumb,
  .is-maintenance .lib-media,
  .is-maintenance .game-thumb{ filter: grayscale(0.9) brightness(0.42); }
  /* Niente inviti ad aprire una cosa che non si apre. */
  .is-maintenance .lib-go,
  .is-maintenance .game-play-btn{ display: none; }
  .is-maintenance:hover{ transform: none !important; box-shadow: none !important; }

  /* ---------- WIKI: schermata di scelta della guida ----------
     Le pagine wiki non hanno body.page-site, quindi non ereditano la griglia
     della libreria: qui basta una griglia che stia bene anche con una sola
     tessera, senza lasciarla larga un quarto di riga. */
  .wiki-guides{
    display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 280px));
    gap: 18px; margin: 26px 0 18px;
  }
  .wiki-guides .game-platform-tile{ text-decoration: none; }
  .wiki-guides h3 small{
    display: block; margin-top: 4px;
    font-family:'Nunito Sans', sans-serif; font-size: 12.5px; font-weight: 500; color: var(--muted);
  }
  .wiki-soon{ font-size: 13.5px; color: var(--muted); margin-bottom: 34px; }

  /* ---------- VETRINA ABBONATI CHE SCORRE (js/showcase.js) ----------
     La riga passa da "centrata e a capo" a nastro continuo: niente wrap,
     niente centratura, e l'overflow tagliato ai bordi del contenitore. */
  body.page-site .proof-row.proof-marquee{
    display: block; overflow: hidden; flex-wrap: nowrap; gap: 0;
    /* Sfuma agli estremi invece di tagliare di netto: senza, i nomi
       comparivano e sparivano di colpo contro il bordo. */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  }
  body.page-site .proof-track{
    display: flex; align-items: center; gap: 76px; width: max-content;
    animation: tf-proof-scroll linear infinite;
    /* Ripiego se il JS non arriva a misurare: mezzo nastro. Il valore vero lo
       scrive js/showcase.js in pixel, pari a UNA sequenza di nomi. */
    --proof-shift: -50%;
  }
  /* Si scorre verso DESTRA: si parte spostati a sinistra di una sequenza e si
     torna a zero, cosi' i nomi entrano da sinistra ed escono a destra. Alla
     fine del giro l'immagine coincide con quella di partenza — le sequenze
     sono tutte uguali — quindi il ritorno a capo non si vede. */
  @keyframes tf-proof-scroll{
    from{ transform: translateX(var(--proof-shift)); }
    to{ transform: translateX(0); }
  }
  body.page-site .proof-marquee .proof-item{ flex: none; }
  /* Fermare lo scorrimento al passaggio del mouse serve a poter leggere un
     nome senza inseguirlo. */
  body.page-site .proof-marquee:hover .proof-track{ animation-play-state: paused; }
  @media (prefers-reduced-motion: reduce){
    body.page-site .proof-track{ animation: none; }
    body.page-site .proof-row.proof-marquee{ overflow-x: auto; }
  }
  @media (max-width: 700px){
    body.page-site .proof-track{ gap: 44px; }
  }

  /* =================================================================
     TELEFONO — ADATTAMENTO MOBILE DI TUTTO IL SITO
     ------------------------------------------------------------------
     Questa sezione sta in fondo al foglio per un motivo solo: la cascata.
     Ogni regola qui dentro vive dentro una @media (max-width: N) e deve
     poter sovrascrivere quella scritta più sopra per il desktop senza che
     quella venga toccata. Essendo l'ultima cosa che il browser legge, a
     parità di specificità vince lei — e il file resta leggibile in due
     tempi: chi cerca com'è fatto un componente sul monitor lo trova dove
     è sempre stato, chi cerca perché sul telefono si comporta in un altro
     modo lo trova qui, tutto in un posto solo.

     Sopra i 1020px (860 per la barra laterale di dashboard e admin) non
     cambia niente rispetto a prima: fuori dalle @media non c'è nessuna
     dichiarazione, con una sola eccezione dichiarata — il
     ".discord-pending[hidden]" della sezione 3, che non è un adattamento
     mobile ma la correzione di un riquadro che doveva già essere
     invisibile ovunque (il perché è scritto lì).

     L'ordine dei blocchi è quello con cui sono stati scritti e conta:
       1. elementi globali (header, menu, footer, banner cookie, moduli)
       2. home e pagine prodotto
       3. autenticazione, checkout, pagine legali, pagine di errore
       4. pannelli della dashboard cliente
       5. pannello admin e tabelle dati (.admin-table)
       6. wiki
       7. barra laterale di dashboard e admin -> menu a scomparsa
     Il menu a scomparsa è l'ultimo perché deve vincere sulle regole della
     barra laterale scritte al punto 4. Dove un blocco toglie o sovrascrive
     di proposito qualcosa scritto in un altro, c'è un commento "MERGE:"
     che dice cosa è stato tolto e perché.
     ================================================================= */

  /* ============================================================================
     TELEFONO — ELEMENTI GLOBALI
     Header e menu, footer, banner cookie, controlli di modulo, tipografia
     minima e le reti di sicurezza contro lo scroll orizzontale: la roba che
     sta su tutte e 70 le pagine del sito pubblico, in tutte e quattro le
     lingue. Ogni regola vive dentro una @media: da 1021px in su non cambia
     niente rispetto a prima.
     ============================================================================ */

  /* ---------- RETI DI SICUREZZA CONTRO LO SCROLL ORIZZONTALE ---------- */
  /* Una pagina che scorre di lato su un telefono non è un difetto estetico:
     il testo finisce sotto il bordo e ci si accorge dello scroll solo quando
     si è già persi. Basta un token di configurazione, l'URL di una guida o un
     indirizzo email lungo dentro un contenitore stretto per provocarlo, e in
     quel caso è la PAGINA intera a scorrere, non il singolo blocco. */
  @media (max-width: 1020px){
    /* Le parole che non ci stanno vanno a capo dentro sé stesse invece di
       sfondare il contenitore. break-word (non anywhere) interviene solo
       quando la parola da sola supera la riga: la giustificazione normale
       resta quella di prima. */
    body.page-site{ overflow-wrap: break-word; }
    /* I titoli hanno letter-spacing negativo e corpo grande: una singola
       parola composta ("Configurazione", nomi di comandi) supera facilmente
       i 360px di uno schermo stretto. */
    body.page-site h1, body.page-site h2, body.page-site h3{ overflow-wrap: break-word; }
    /* Comandi, chiavi e percorsi: qui si spezza ovunque, perché una stringa
       tipo /opt/tikforge/plugins/config.yml non ha spazi dove andare a capo. */
    code, kbd, samp{ overflow-wrap: anywhere; }
    pre{ max-width: 100%; overflow-x: auto; }
    /* Media con dimensioni scritte nell'attributo HTML o viewBox largo: non
       guardano il contenitore, escono e basta. Solo dentro .page-site: la
       wiki, la dashboard e la pagina di stato hanno il loro agente e le loro
       misure, e una rete di sicurezza tirata su tutto il documento è il tipo
       di regola che rompe qualcosa tre cartelle più in là. */
    body.page-site img,
    body.page-site svg,
    body.page-site video,
    body.page-site iframe,
    body.page-site canvas,
    body.page-site table{ max-width: 100%; }

    /* ---------- HEADER: BERSAGLI DA POLLICE ---------- */
    /* Da 1020px in giù compare l'hamburger: da lì in giù la barra si usa col
       dito, e sotto i 44px un bersaglio si sbaglia. Sono gli elementi più
       ripetuti del sito — stanno su ogni pagina, in ogni lingua.
       (MERGE: questa era una @media a sé, identica e attaccata a quella
       qui sopra: accorpate, l'ordine delle regole non cambia.) */
    /* Logo: l'immagine è alta 34px e la parola 26. Invece di ingrandire la
       grafica si allarga la SCATOLA con del padding — il marchio resta della
       stessa dimensione di prima, ma la zona sensibile arriva a 44x44. Il
       gap scende da 11 a 6 perché i 5px di padding del marchio fanno già da
       distanza: lo spazio visibile fra icona e parola non cambia. */
    body.page-site header .logo{ min-height: 44px; gap: 6px; flex: none; }
    body.page-site header .logo-mark{ height: 44px; padding: 5px; }
    body.page-site header .logo-word{ padding: 9px 0; }

    /* Ordine della barra: prima il logo, poi lingua e CTA, e l'hamburger
       ultimo a destra — dove il pollice lo cerca. Prima l'hamburger stava in
       mezzo, fra il logo e i due pulsanti.
       flex-wrap: nowrap è il punto chiave: la barra deve restare UNA riga in
       tutte e quattro le lingue. Con l'a capo permesso, "Empieza ahora" (che
       è più lungo di "Inizia ora" di tre lettere) bastava a mandare
       l'hamburger su una seconda riga e a raddoppiare l'altezza di un header
       che è sticky, cioè sempre lì. Se proprio non ci sta, a cedere è la
       larghezza del CTA (vedi min-width: 0 qui sotto), non l'impaginazione. */
    body.page-site header nav{ flex-wrap: nowrap; }
    body.page-site .nav-right{ order: 2; margin-left: auto; gap: 6px; flex: 0 1 auto; min-width: 0; }
    /* Hamburger: 40x40 non è abbastanza, ed è il pulsante da cui passa tutta
       la navigazione del telefono. */
    body.page-site .nav-toggle{
      order: 3; margin-left: 0; flex: none;
      width: 44px; height: 44px; font-size: 18px;
    }
    body.page-site .lang-dropdown{ flex: none; }

    /* Selettore lingua: 72x37. Il padding verticale si sposta sul codice
       lingua interno, così anche lo <span> che il dito colpisce davvero
       misura 44 in altezza e il pulsante non cresce due volte. */
    body.page-site .lang-dropdown-btn{ min-height: 44px; padding: 0 10px; }
    body.page-site .lang-code{ padding: 12px 0; }
    /* Le voci del menu lingua erano alte 37px, e le bandierine 17x13: la
       riga intera diventa il bersaglio. */
    body.page-site .lang-dropdown-list{ min-width: 190px; padding: 6px; }
    body.page-site .lang-dropdown-list a{ min-height: 46px; padding: 0 12px; font-size: 15px; gap: 11px; }
    body.page-site .lang-dropdown-list .fi{ width: 1.5em; height: 1.1em; }

    /* CTA "Inizia ora": stesso trucco del selettore lingua, il padding
       verticale sta sull'etichetta interna. white-space serve anche per le
       pagine di login/abbonamento/legali, dove il CTA non ha lo <span>
       ("← Torna al sito"): lì il testo è figlio diretto. */
    body.page-site .nav-cta{
      min-height: 44px; padding: 0 20px;
      flex: 0 1 auto; min-width: 0;
      white-space: nowrap; overflow: hidden;
    }
    /* display:block, non inline-flex: text-overflow non funziona su un
       contenitore flex, e senza questo l'etichetta si taglierebbe a metà
       lettera invece di finire con i puntini. È la rete di sicurezza per
       quando il webfont non carica e le lettere di sistema sono più larghe. */
    body.page-site .nav-cta .nav-btn-label{
      display: block; padding: 12px 0;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }

    /* ----- IL MENU APERTO -----
       Com'era: il menu cresceva DENTRO l'header, e aprendolo si srotolavano
       anche tutte le tendine ("Funzionalità", "Giochi", "Risorse") — 15 voci
       in colonna. L'header diventava alto 1054px su uno schermo da 844, e
       siccome è in position:sticky la parte che sborda non si raggiunge
       scorrendo: da "Prezzi" in giù le voci erano semplicemente
       irraggiungibili, il menu del telefono era rotto.
       Ora il pannello esce dal flusso e galleggia SOTTO la barra, con un suo
       fondo e un suo bordo come le tendine del desktop: la barra resta alta
       una riga, il pannello ha un'altezza massima e scorre da solo. Le
       tendine partono chiuse e si aprono a fisarmonica col click che
       js/nav-dropdown.js gestisce già tramite .is-open. */
    body.page-site .nav-links.open{
      display: flex;
      position: absolute; z-index: 55;
      top: calc(100% + 10px); left: 0; right: 0;
      width: auto; margin: 0;
      padding: 8px;
      padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
      background: var(--panel);
      border: 1px solid var(--line-2);
      border-radius: 18px;
      box-shadow: 0 28px 64px rgba(0,0,0,0.62);
      max-height: calc(100vh - 110px);
      max-height: calc(100dvh - 110px);
      overflow-y: auto;
      overscroll-behavior: contain;
    }
    body.page-site .nav-drop-menu{ display: none; }
    body.page-site .nav-drop.is-open .nav-drop-menu{ display: block; }
    /* Su touch il :hover resta "appiccicato" dopo un tocco: la tendina si
       apre solo con .is-open, mai passandoci sopra per sbaglio. Serve display
       (non opacity) proprio perché vince sulle regole :hover del desktop. */

    /* Voci del menu: erano alte 37-38px, con 2px di stacco fra una e l'altra.
       Col pollice si sbaglia riga. */
    body.page-site .nav-links > a,
    body.page-site .nav-drop-btn{
      min-height: 48px; padding: 12px 14px; font-size: 15.5px; border-radius: 12px;
    }
    /* Sottovoci: rientrate e con una guida verticale, altrimenti aperta la
       fisarmonica non si capisce più dove finisce una sezione e comincia
       l'altra. */
    body.page-site .nav-drop.is-open .nav-drop-menu{
      /* transform:none è obbligatorio: la regola desktop con la stessa
         identica specificità imposta translateX(-50%) per centrare la
         tendina sotto la voce, e qui — dove il pannello è in flusso — quel
         -50% lo spostava mezza larghezza fuori dal bordo sinistro. */
      transform: none;
      padding: 2px 0 8px 14px;
      margin-left: 14px;
      border-left: 1px solid var(--line-2);
    }
    body.page-site .nav-drop-menu a{ min-height: 48px; align-items: center; padding: 6px 12px; }
    body.page-site .nav-drop-menu strong{ font-size: 14.5px; }
  }

  /* ---------- HEADER SU TELEFONO: UNA RIGA SOLA ---------- */
  @media (max-width: 560px){
    /* Logo + parola + lingua + CTA + hamburger non ci stanno nei 326px utili
       di un iPhone: la barra andava a capo e l'header sticky diventava alto
       118px, un settimo dello schermo occupato per sempre da un logo scritto
       due volte. Delle cinque cose la parola "TIKFORGE" è l'unica che non
       serve a fare niente — il marchio accanto la ripete già — quindi è
       quella che salta, e tutto il resto rientra in una riga. */
    body.page-site header .logo-word{ display: none; }
    body.page-site header nav{ gap: 8px; padding: 10px 12px; }
    /* La freccina ▾ costa 16px per ripetere quello che il mappamondo dice
       già: su un telefono quei 16px servono al CTA. */
    body.page-site .lang-dropdown-btn::after{ display: none; }
    body.page-site .lang-dropdown-btn{ padding: 0 8px; gap: 6px; }
    body.page-site .nav-cta{ padding: 0 15px; font-size: 13.5px; }
    /* La barra è più bassa: il pannello può essere più alto. */
    body.page-site .nav-links.open{
      max-height: calc(100vh - 96px);
      max-height: calc(100dvh - 96px);
    }
  }

  @media (max-width: 380px){
    /* Telefoni piccoli (iPhone SE, 320px): restano 272px per logo, lingua,
       CTA e hamburger. Il caso peggiore è lo spagnolo — "Empieza ahora" è
       tre lettere più lungo di "Inizia ora" e con i respiri di prima
       sforava di 5px. Si stringono gli spazi vuoti: nessuno dei quattro
       elementi viene tolto, e la lingua corrente resta leggibile. */
    body.page-site header nav{ gap: 4px; padding: 9px 8px; }
    body.page-site .nav-right{ gap: 4px; }
    body.page-site .nav-cta{ padding: 0 12px; font-size: 13px; }
    body.page-site .lang-dropdown-btn{ padding: 0 6px; gap: 5px; }
  }

  /* ---------- SHELL: TACCA E BORDI CURVI DELL'IPHONE ---------- */
  /* La safe area conta soprattutto in ORIZZONTALE, dove la tacca sta di
     fianco al contenuto — e un telefono in orizzontale è largo 844 o 932px,
     ben oltre i 560 del blocco "telefono". Per questo la soglia qui è la
     stessa dell'hamburger: 1020px vuol dire "sito in modalità mobile", non
     "schermo stretto". max() lascia intatto il padding di prima (24px sopra
     i 520, 16 sotto) quando non c'è nessuna tacca da schivare. */
  @media (max-width: 1020px){
    body.page-site .site-shell{
      padding-left: max(24px, env(safe-area-inset-left, 0px));
      padding-right: max(24px, env(safe-area-inset-right, 0px));
    }
  }
  @media (max-width: 520px){
    body.page-site .site-shell{
      padding-left: max(16px, env(safe-area-inset-left, 0px));
      padding-right: max(16px, env(safe-area-inset-right, 0px));
    }
  }

  /* ---------- FOOTER ---------- */
  @media (max-width: 1020px){
    /* Gli elenchi del footer erano righe di testo alte 21px separate da 12px
       di vuoto: tre bersagli su quattro sotto la soglia, e il vuoto in mezzo
       non è cliccabile. Lo stacco diventa padding DENTRO il link: stessa
       spaziatura a occhio, ma adesso ogni riga è alta 44 ed è tutta sensibile. */
    body.page-site .footer-col-links{ gap: 0; }
    body.page-site .footer-col-links a,
    body.page-site .footer-links a{
      display: flex; align-items: center; min-height: 44px;
    }
    body.page-site .footer-social a{
      display: inline-flex; align-items: center; gap: 8px; min-height: 44px;
    }
    /* Barra gesti dell'iPhone: senza questo l'ultima riga del footer ci
       finisce sotto. */
    body.page-site footer{ padding-bottom: calc(36px + env(safe-area-inset-bottom, 0px)); }
  }
  @media (max-width: 760px){
    body.page-site .footer-col-links a,
    body.page-site .footer-links a{ font-size: 15px; }
    /* Il footer semplice (404, 403, pagine legali) mette i link in fila: su
       un telefono la fila diventa una colonna, altrimenti sono quattro
       bersagli attaccati che si toccano di lato. */
    body.page-site .footer-links{ flex-direction: column; gap: 0; width: 100%; }
    /* 11.5px maiuscolo e spaziato è il testo più piccolo del sito e fa da
       titolo a un'intera colonna. */
    body.page-site .footer-col-title{ font-size: 12.5px; margin-bottom: 4px; }
    body.page-site .footer-social a{ font-size: 14.5px; }
    body.page-site .footer-copy{ font-size: 12.5px; }
    body.page-site .footer-note{ font-size: 14px; }
    body.page-site .footer-bottom{ margin-top: 28px; gap: 6px; }
  }

  /* ---------- BANNER COOKIE ---------- */
  @media (max-width: 1020px){
    /* Il banner è largo quanto lo schermo, ma il suo contenitore è un .wrap
       che dentro body.page-site ha padding 0: il testo arrivava a filo dei
       due bordi, anche col telefono in orizzontale dove c'è pure la tacca.
       Il selettore nomina .wrap apposta: "body.page-site .wrap" pesa due
       classi PIÙ un elemento, e un ".cookie-banner .cookie-banner-inner"
       (due sole classi) perdeva il confronto — il padding restava a zero. */
    .cookie-banner .wrap.cookie-banner-inner{
      padding-left: max(24px, env(safe-area-inset-left, 0px));
      padding-right: max(24px, env(safe-area-inset-right, 0px));
    }
  }
  @media (max-width: 600px){
    /* Il banner si prendeva 433px degli 844 dello schermo — metà telefono per
       tre righe di testo. La colpa è di "flex: 1 1 320px" sul paragrafo:
       scritto per la fila orizzontale del desktop, dove 320px sono la
       larghezza minima. Qui sotto il contenitore diventa una colonna, l'asse
       principale è quello verticale, e quei 320px diventano un'ALTEZZA
       minima. Sull'asse verticale il testo deve prendersi solo lo spazio che
       gli serve. */
    .cookie-banner-text{ flex: 0 0 auto; max-width: none; font-size: 13.5px; }
    .cookie-banner .wrap.cookie-banner-inner{
      gap: 14px; text-align: left;
      padding-left: max(16px, env(safe-area-inset-left, 0px));
      padding-right: max(16px, env(safe-area-inset-right, 0px));
    }
    .cookie-banner{ padding-top: 14px; padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
    /* "Ho capito" si prende la riga e diventa il bersaglio grande e ovvio;
       il link alla policy resta accanto ma con un'area sensibile vera.
       Anche qui il selettore è appesantito per superare "body.page-site .btn"
       e "body.page-site .auth-link". */
    .cookie-banner-actions{ gap: 10px; }
    .cookie-banner .cookie-banner-actions .cookie-banner-btn{
      flex: 1 1 auto; justify-content: center; min-height: 48px; padding: 12px 18px;
    }
    .cookie-banner .cookie-banner-actions .auth-link{
      display: inline-flex; align-items: center; justify-content: center;
      flex: 0 0 auto; min-height: 48px; padding: 0 10px;
    }
  }

  /* ---------- CAMPI DEI MODULI E BERSAGLI DEL CORPO PAGINA ---------- */
  /* Anche qui la soglia è 1020 e non 760: lo zoom automatico di iOS sui campi
     scatta a qualunque larghezza, e un iPhone in orizzontale è largo 844px. */
  @media (max-width: 1020px){
    /* Sotto i 16px iOS Safari ingrandisce la pagina da solo appena tocchi il
       campo, e non torna indietro: resti con la pagina zoomata e sfalsata per
       tutto il resto della compilazione. 16px è la soglia esatta, non un
       arrotondamento per eccesso. */
    body.page-site input,
    body.page-site select,
    body.page-site textarea{ font-size: 16px; }
    body.page-site .field input[type="email"],
    body.page-site .field input[type="password"],
    body.page-site .field input[type="text"],
    body.page-site .field input[type="number"],
    body.page-site select{ min-height: 48px; }
    /* Occhio mostra/nascondi password: 38x38 appiccicato dentro il campo. */
    body.page-site .field-toggle{ width: 44px; height: 44px; padding: 0; right: 3px; }
    body.page-site .field-input-wrap input{ padding-right: 52px; }
    /* Casella di spunta: 16px è la dimensione di una capocchia di spillo. Il
       bersaglio diventa l'ETICHETTA intera (44px di altezza, testo compreso)
       e la casella sale a 20 — è l'unico caso in cui vale la pena ingrandire
       la grafica, perché sotto i 20px la casella non si centra col dito
       nemmeno mirando. */
    body.page-site .checkbox{ min-height: 44px; align-items: center; }
    body.page-site .checkbox input{ width: 20px; height: 20px; }
    /* Link testuali dentro moduli e note ("Password dimenticata?", "Cookie
       Policy"): riga di testo alta 20px, impossibile da centrare. Il padding
       resta su un elemento INLINE apposta — così allarga la zona sensibile e
       il rettangolo di hit-testing senza toccare l'interlinea del paragrafo
       che lo contiene (un inline-block invece allargherebbe la riga). */
    body.page-site .auth-link{ padding: 12px 0; }
    /* Ogni pulsante sotto il pollice, comprese le varianti con padding
       ridotto sparse per il sito. */
    body.page-site .btn{ min-height: 48px; }
  }

  /* ---------- TIPOGRAFIA MINIMA ---------- */
  @media (max-width: 760px){
    /* Etichette e occhielli: 11.5px maiuscolo con letter-spacing largo si
       legge peggio di quanto dica il numero. Il minimo per un'etichetta è 12. */
    body.page-site .section-kicker{ font-size: 12px; padding: 7px 14px; }
    .badge{ font-size: 11px; }
    body.page-site .checkbox{ font-size: 14.5px; }
    body.page-site .field-label{ font-size: 14px; }
    body.page-site .field-hint{ font-size: 12.5px; }
    /* MERGE — REGOLA TOLTA IN FASE DI UNIONE. Qui c'era, per 404 e 403,
       "body.page-site .error-404/.error-403 .hero-ctas > .btn{ flex:1 1 220px }",
       scritta quando .hero-ctas era ancora una fila che va a capo. Il blocco
       "home e pagine prodotto" qui sotto mette però .hero-ctas in COLONNA
       sotto i 760px, e su un asse verticale quel 220px non è più una
       larghezza minima: è l'altezza di partenza di ogni pulsante. I due
       bottoni delle pagine di errore sarebbero diventati alti 220px l'uno.
       L'impilamento di 404/403 lo fa già il blocco "auth e legali" (sezione
       3), che quelle pagine le possiede. */
  }

  /* ==========================================================================
     TELEFONO — HOME E PAGINE PRODOTTO
     index.html, minecraft.html, roblox.html, browser.html, giochi/*.html,
     tutorial-tntcube.html.

     Il problema di partenza non era il layout — a 390px non c'era scorrimento
     laterale da nessuna parte — ma la SCALA: la home era alta 13421px, sedici
     schermate di telefono da scorrere col pollice, perché ogni respiro pensato
     per un monitor da 1440px restava identico su uno schermo largo un quarto.
     Qui si stringono i vuoti, si mettono in riga i blocchi che in colonna
     sprecavano mezzo schermo, e si portano a misura di dito i bersagli che
     erano alti 20px. La home scende a 10834px (-19%) e il mockup del telefono
     nell'hero, che era un francobollo da 260px, arriva a occupare la larghezza
     dello schermo.

     Tutto sta dentro media query: l'aspetto desktop non cambia di un pixel.
     ========================================================================== */

  @media (max-width: 760px){

    /* ---------- RITMO VERTICALE DELLE SEZIONI ----------
       94px sopra e 94px sotto vogliono dire 188px di nero fra una sezione e
       l'altra: su un telefono è una schermata intera di niente, e la pagina
       sembra finita quando invece continua. Il taglio è mirato ai <section>
       di QUESTE pagine e non a "body.page-site section", che vale anche per
       checkout, login e pagine legali (aree di altri).
       Solo index.html ha un <main>: è il modo più diretto per prendere le sue
       sezioni senza elencarle una per una. */
    body.page-site main > section{ padding: 56px 0; }
    body.page-site .hero{ padding-top: 18px; }
    body.page-site .pillars-section{ padding-top: 30px; }
    body.page-site .cta-band{ padding: 14px 0 56px; }
    /* Pagine piattaforma e pagine gioco: intestazione + sezioni che seguono. */
    body.page-site .platform-hero{ padding: 44px 0 20px; }
    body.page-site .platform-hero ~ section{ padding: 30px 0 56px; }

    /* Selettore lungo per necessità: .section-head vive anche su login,
       registrazione e checkout, che sono di un'altra area. Le due radici qui
       sotto ("main" e ".platform-hero") esistono solo sulle pagine mie. */
    body.page-site main .section-head,
    body.page-site .platform-hero .section-head,
    body.page-site .platform-hero ~ section .section-head{ margin-bottom: 28px; }
    body.page-site main .section-head p,
    body.page-site .platform-hero .section-head p,
    body.page-site .platform-hero ~ section .section-head p{
      margin-top: 12px; font-size: 15.5px; line-height: 1.62;
    }
    /* 11.5px su un pannello di vetro non si legge da 30cm: i kicker vanno a 12,
       la soglia sotto cui non si scende su questo sito. Stessa cosa per tutte
       le etichette maiuscole più sotto (step-tag, lib-chip, plan-tag, ...).
       Anche qui il selettore resta chiuso alle mie pagine: lo stesso kicker da
       11.5px compare su login, registrazione, checkout e pagine legali, che
       sono di un'altra area — alzarlo da qui vorrebbe dire scriverci sopra. */
    body.page-site main .section-kicker,
    body.page-site .platform-hero .section-kicker,
    body.page-site .platform-hero ~ section .section-kicker,
    /* La guida rapida sta in una <section class="legal"> come privacy e
       termini: la sola cosa che la distingue è che dentro ha i passi del
       tutorial, e quella è la chiave con cui la prendo senza prendere anche
       le pagine legali. */
    body.page-site .legal-wrap:has(.tutorial-steps) .section-kicker{
      font-size: 12px; margin-bottom: 14px; padding: 6px 13px;
    }

    /* ---------- HERO ---------- */
    body.page-site .hero h1{
      margin-top: 20px;
      font-size: clamp(31px, 9vw, 42px); line-height: 1.08;
    }
    body.page-site .hero p.lead{ margin-top: 16px; font-size: 15.5px; line-height: 1.62; }
    body.page-site .hero-flag{ gap: 10px; padding: 5px 14px 5px 5px; }
    body.page-site .hero-flag-chip{ font-size: 12px; padding: 5px 12px; }
    body.page-site .hero-flag-text{ font-size: 13.5px; line-height: 1.4; }
    body.page-site .hero-assur{ gap: 10px 20px; margin-top: 22px; }

    /* Due pulsanti affiancati a 390px si spezzano su due righe con larghezze
       diverse e sembrano un errore di impaginazione. In colonna a tutta
       larghezza diventano due bersagli da 52px pieni, che è anche il gesto
       naturale col pollice. Vale sia per l'hero sia per il pannello finale,
       che riusa la stessa classe. */
    body.page-site .hero-ctas{ flex-direction: column; align-items: stretch; gap: 10px; margin-top: 22px; }
    body.page-site .hero-ctas .btn,
    body.page-site .hero-ctas .btn-primary{
      width: 100%; justify-content: center; padding: 16px 20px;
    }

    /* ---------- IL MOCKUP DEL TELEFONO NELL'HERO ----------
       È l'immagine su cui si regge tutta la promessa della home, e su un
       telefono vero era largo 260px: un francobollo con dentro scritte da
       8,5px. Ora occupa la larghezza disponibile (fino a 344px), e tutto il
       suo contenuto è espresso in cqw — percentuali della larghezza dello
       schermo disegnato — invece che in pixel fissi.
       Il motivo non è la pigrizia: un modellino in scala deve restare in
       scala. Con i px avrei dovuto riscrivere trenta misure per ogni
       larghezza di telefono e a 320px la riga dell'intestazione si sarebbe
       tagliata; con cqw le proporzioni sono le stesse da 320 a 760px e non
       c'è nessuna soglia in cui qualcosa esce dallo schermo.
       Bonus: i tre numeri della Dynamic Island tornano a essere i rapporti
       veri dell'iPhone 15 Pro citati nel commento originale (125/393 = 31.8%,
       36.7/393 = 9.3%, 11/393 = 2.8%) invece della loro conversione a mano. */
    body.page-site .hero-window-wrap{ width: 100%; max-width: 344px; }
    body.page-site .hero-window{
      width: 100%; padding: 9px;
      border-radius: clamp(42px, 13vw, 50px);
    }
    body.page-site .phone-screen{
      container-type: inline-size;
      border-radius: clamp(35px, 11vw, 43px);
      --isola-larghezza: 31.8cqw;
    }
    body.page-site .phone-notch{ top: 2.8cqw; height: 9.3cqw; }
    /* I max() sulle scritte sono la sola deroga alla scala: sotto i ~360px di
       schermo la proporzione pura porterebbe "LIVE" a 9,7px, e a quel punto il
       modellino è fedele ma illeggibile. Il fondo è 11px per le etichette e
       11,5px per il testo, cioè il minimo che questo sito si dà. Sopra i 360px
       il max() non entra mai in gioco e vince la proporzione. */
    body.page-site .phone-status{ height: 14.8cqw; font-size: max(4cqw, 11.5px); }
    body.page-site .phone-status-ico{ gap: 1.9cqw; }
    body.page-site .phone-status-ico svg{ width: 5.2cqw; height: 4.3cqw; }

    body.page-site .live-head{ padding: 6.2cqw 4.3cqw 0; gap: 2.2cqw; }
    body.page-site .live-host{ gap: 2.5cqw; padding: 1.2cqw 3.7cqw 1.2cqw 1.2cqw; }
    body.page-site .live-host-av{ width: 8.6cqw; height: 8.6cqw; }
    body.page-site .live-host-txt strong{ font-size: max(4cqw, 11.5px); gap: 0.9cqw; }
    body.page-site .live-host-txt strong svg{ width: 3.4cqw; height: 3.4cqw; }
    body.page-site .live-host-txt span{ font-size: max(3.6cqw, 11px); }
    body.page-site .live-badge{ font-size: max(3.6cqw, 11px); padding: 1.5cqw 2.8cqw; border-radius: 1.9cqw; }
    body.page-site .live-count{ font-size: max(3.7cqw, 11.5px); gap: 1.2cqw; padding: 1.5cqw 3.1cqw; }
    body.page-site .live-count svg{ width: 3.7cqw; height: 3.7cqw; }
    body.page-site .live-close svg{ width: 5.2cqw; height: 5.2cqw; }

    body.page-site .live-events{ gap: 2.5cqw; padding: 0 4.3cqw; }
    body.page-site .live-event{ gap: 3.7cqw; }
    body.page-site .live-event-pill{ gap: 3.1cqw; padding: 1.9cqw 3.7cqw 1.9cqw 1.9cqw; }
    body.page-site .live-event-av{ width: 9.9cqw; height: 9.9cqw; }
    body.page-site .live-event-txt strong{ font-size: max(4cqw, 11.5px); }
    body.page-site .live-event-txt span{ font-size: max(3.6cqw, 11px); }
    body.page-site .live-event-gift{ font-size: 5.9cqw; }
    body.page-site .live-event-mult{ font-size: 4.9cqw; }

    body.page-site .live-chat{ padding: 3.1cqw 4.3cqw 0; gap: 3.1cqw; }
    body.page-site .live-chat-av{ width: 8.6cqw; height: 8.6cqw; }
    body.page-site .live-chat p{ font-size: max(3.7cqw, 11.5px); }

    body.page-site .live-composer{ padding: 3.7cqw 4.3cqw 6.2cqw; gap: 3.1cqw; }
    body.page-site .live-composer-input{ font-size: max(3.7cqw, 11.5px); padding: 3.1cqw 4.3cqw; }
    body.page-site .live-composer-btn{ font-size: 2.8cqw; gap: 0.6cqw; }
    body.page-site .live-composer-btn i{ width: 9.9cqw; height: 9.9cqw; font-size: 4.6cqw; }

    /* Le due card "evento attivato" sotto al telefono: l'immagine era alta
       112px per stare accanto a un telefono da 274px, qui sotto ne bastano
       meno e la coppia risparmia mezza schermata. */
    body.page-site .hero-stage{ gap: 22px; padding-bottom: 8px; }
    body.page-site .hero-events{ gap: 12px; }
    body.page-site .event-card{ padding: 12px; }
    body.page-site .event-card-media{ height: 96px; }
    body.page-site .event-card p{ margin-top: 9px; font-size: 13px; }
    body.page-site .event-card-state{ font-size: 12px; }

    /* ---------- QUATTRO PILASTRI ----------
       In colonna ogni pilastro era icona, vuoto di 24px, titolo, testo: 150px
       a testa per una frase sola. Icona accanto al titolo e frase sotto a
       tutta larghezza: metà dell'ingombro e si legge in un colpo d'occhio.
       Griglia e non flex perché icona, <h3> e <p> sono tre fratelli senza
       contenitore comune: con flex finirebbero in tre colonne e il titolo
       resterebbe strizzato in mezzo. */
    body.page-site .pillars{ gap: 10px; }
    body.page-site .pillar{
      display: grid; grid-template-columns: auto minmax(0, 1fr);
      align-items: center; gap: 0 13px;
      padding: 18px 18px 20px;
    }
    body.page-site .pillar-ico{ grid-column: 1; grid-row: 1; width: 40px; height: 40px; margin-bottom: 0; }
    body.page-site .pillar h3{ grid-column: 2; grid-row: 1; font-size: 16.5px; margin-bottom: 0; }
    body.page-site .pillar p{ grid-column: 1 / -1; margin-top: 11px; font-size: 13.5px; }

    /* ---------- COME FUNZIONA: tre passi ----------
       Stesso ragionamento: il numero del passo va in riga col titolo invece
       che sopra, e il paragrafo passa sotto a tutta larghezza. */
    body.page-site .steps-grid{ gap: 12px; }
    body.page-site .step-card{
      display: grid; grid-template-columns: auto minmax(0, 1fr);
      align-items: center; gap: 0 13px;
      padding: 20px 18px 22px;
    }
    body.page-site .step-badge{ width: 36px; height: 36px; margin-bottom: 0; border-radius: 12px; }
    body.page-site .step-card h3{ font-size: 18px; margin-bottom: 0; }
    body.page-site .step-card p{ grid-column: 1 / -1; margin-top: 14px; font-size: 14px; }
    body.page-site .step-tags{ grid-column: 1 / -1; margin-top: 14px; gap: 7px; }
    body.page-site .step-tag{ font-size: 12px; padding: 6px 12px; }

    /* ---------- LIBRERIA GIOCHI ---------- */
    body.page-site .lib-grid{ gap: 14px; }
    body.page-site .lib-media{ height: 168px; }
    body.page-site .lib-body{ padding: 18px 18px 20px; }
    body.page-site .lib-body h3{ font-size: 18px; margin-bottom: 6px; }
    body.page-site .lib-body p{ font-size: 13.8px; }
    body.page-site .lib-chip,
    body.page-site .lib-soon{ font-size: 12px; top: 12px; padding: 5px 12px; }
    body.page-site .lib-chip{ left: 12px; }
    body.page-site .lib-soon{ right: 12px; }
    body.page-site .lib-genre{ font-size: 12px; }
    body.page-site .lib-foot{ margin-top: 12px; }
    /* "Scopri" era una scritta alta 20px in fondo alla card: l'intera card è
       cliccabile, ma il dito va dove c'è scritto di andare. Diventa una
       pillola da 44px, cioè un bersaglio vero. */
    body.page-site .lib-go{
      min-height: 44px; padding: 0 16px; border-radius: 999px;
      background: rgba(139,92,246,0.14); border: 1px solid rgba(168,85,247,0.26);
      font-size: 14px;
    }
    /* Sulle card con la targhetta "In arrivo" la pillola prometterebbe un
       tocco che porta a un gioco che ancora non c'è: lì resta testo. Il
       riconoscimento passa dalla targhetta (:has) e non dal nome della
       piattaforma, così il giorno che GTA V o Stack diventano giocabili basta
       togliere lo <span class="lib-soon"> e la pillola ricompare da sola. */
    body.page-site .lib-card.is-locked .lib-go,
    body.page-site .lib-card:has(.lib-soon) .lib-go{
      background: none; border-color: transparent; padding: 0; min-height: 0;
      color: var(--dim);
    }
    body.page-site .lib-note{ margin-top: 18px; font-size: 13.5px; }

    /* ---------- FUNZIONALITÀ ---------- */
    body.page-site .cap-grid{ gap: 10px; }
    body.page-site .cap{ padding: 18px 18px 20px; gap: 14px; }
    body.page-site .cap-ico{ width: 40px; height: 40px; }
    body.page-site .cap h3{ font-size: 16px; margin-bottom: 6px; }
    body.page-site .cap p{ font-size: 13.8px; }

    /* ---------- ABBONAMENTO (il blocco prezzo della home) ----------
       Metà di queste classi (.plan-tag, .plan-price, .plan-feats, .plan-side,
       .plan-note) sono in comune con il checkout, il login e la dashboard, che
       sono di altri. .plan-card e .plan-wrap invece esistono solo qui: sono la
       radice sotto cui tutto il resto va infilato per non uscire di casa. */
    body.page-site .plan-wrap{ gap: 14px; }
    body.page-site .plan-card{ padding: 26px 20px 24px; border-radius: 24px; }
    body.page-site .plan-card .plan-tag{ font-size: 12px; padding: 6px 12px; }
    body.page-site .plan-card .plan-switch{ margin-top: 16px; }
    /* 38px non bastano per due frecce che si premono al volo per confrontare
       i prezzi: portate a 44, la misura minima di un bersaglio tattile. */
    body.page-site .plan-card .plan-switch-arrow{ width: 44px; height: 44px; }
    body.page-site .plan-card .plan-price{ margin: 16px 0 8px; }
    body.page-site .plan-card .plan-price .amount{ font-size: 46px; }
    body.page-site .plan-card .plan-flag{ font-size: 12px; }
    body.page-site .plan-card .plan-feats{ gap: 11px; margin: 20px 0 22px; }
    body.page-site .plan-card .plan-feats li{ font-size: 14px; }
    body.page-site .plan-card .plan-note{ margin-top: 12px; font-size: 12.5px; }
    body.page-site .plan-wrap .plan-side{ gap: 12px; }
    body.page-site .plan-wrap .plan-side-item{ padding: 20px 18px; border-radius: 18px; }
    body.page-site .plan-wrap .plan-side-item h3{ font-size: 16px; margin-bottom: 8px; }
    body.page-site .plan-wrap .plan-side-item p{ font-size: 13.8px; }

    /* ---------- CHI SIAMO ---------- */
    body.page-site .about-band{ padding: 26px 20px; gap: 24px; border-radius: 24px; }
    body.page-site .about-band p{ margin-top: 12px; font-size: 15px; line-height: 1.66; }
    body.page-site .about-stats{ gap: 10px; }
    body.page-site .about-stat{ padding: 16px 14px; border-radius: 15px; }
    body.page-site .about-stat strong{ font-size: 24px; }
    body.page-site .about-stat span{ font-size: 12px; }

    /* ---------- FAQ ----------
       Il <summary> era alto 26px: il padding stava sulla card, non sulla riga
       cliccabile, quindi metà del riquadro non rispondeva al tocco. Spostando
       il padding verticale sul summary tutta la fascia visibile diventa il
       bersaglio, e passa da 26 a 60px. */
    body.page-site .faq-list{ gap: 10px; }
    body.page-site .faq-item{ padding: 0 18px; border-radius: 16px; }
    body.page-site .faq-item[open]{ padding-bottom: 18px; }
    body.page-site .faq-q{ padding: 17px 0; gap: 12px; font-size: 15.5px; line-height: 1.3; }
    body.page-site .faq-a{ font-size: 14px; }
    body.page-site .faq-item[open] .faq-a{ margin-top: 4px; }

    /* ---------- PANNELLO FINALE ---------- */
    body.page-site .cta-panel{ padding: 44px 22px; border-radius: 26px; }
    body.page-site .cta-panel p{ margin-top: 14px; font-size: 15.5px; }
    body.page-site .cta-panel .hero-ctas{ margin-top: 24px; }

    /* ---------- PAGINE PIATTAFORMA (minecraft / roblox / browser) ---------- */
    /* Il "torna indietro" era alto 38px e attaccato al titolo: gli si dà
       l'altezza di un dito senza ingrandire il testo. */
    body.page-site .platform-hero-back{
      min-height: 44px; margin-bottom: 6px; padding: 0 2px; font-size: 14px;
    }
    body.page-site .game-brief-grid{ gap: 14px; }
    body.page-site .game-brief-media{ height: 156px; }
    body.page-site .game-brief-body{ padding: 16px 18px 18px; }
    body.page-site .game-brief-body p{ font-size: 13.8px; }
    /* Come .lib-go: è l'invito all'azione della card, deve essere toccabile. */
    body.page-site .game-brief-more{
      display: inline-flex; align-items: center; min-height: 44px;
      padding-top: 12px; font-size: 14px;
    }
    body.page-site .game-soon-grid{ gap: 10px; margin-top: 18px; }
    body.page-site .game-soon-card{ padding: 14px; gap: 12px; }
    body.page-site .game-soon-card .game-thumb{ width: 46px; height: 46px; }
    body.page-site .soon-chip{ font-size: 12px; padding: 3px 10px; margin-left: 8px; }
    body.page-site .games-note{ margin-top: 18px; font-size: 13.5px; }

    /* ---------- PAGINA DEL SINGOLO GIOCO (giochi/*.html) ---------- */
    /* Le briciole di navigazione sono tre link alti 18px in fila: senza aria
       intorno si sbaglia bersaglio una volta su due. */
    body.page-site .crumbs{ gap: 4px 8px; margin-bottom: 6px; }
    body.page-site .crumbs a{ display: inline-flex; align-items: center; min-height: 40px; }
    body.page-site .game-page-media{ margin-bottom: 26px; }
    body.page-site .game-page-grid{ gap: 24px; }
    body.page-site .game-page-main h2,
    body.page-site .game-page-side h2,
    body.page-site .game-page-more h2{ font-size: 19px; margin-bottom: 12px; }
    body.page-site .game-page-main p{ font-size: 15px; line-height: 1.7; }
    body.page-site .game-page-side{ padding: 20px 18px; }
    body.page-site .game-page-more{ margin-top: 34px; padding-top: 26px; }
    body.page-site .game-feature-list{ gap: 16px; }
    body.page-site .game-feature-media{ min-height: 170px; }
    body.page-site .game-feature-body{ padding: 22px 18px; }
    body.page-site .game-feature-body h3{ font-size: 20px; }
    body.page-site .game-feature-actions{ padding-top: 20px; gap: 12px; }

    /* ---------- GUIDA RAPIDA (tutorial-tntcube.html) ---------- */
    body.page-site .tutorial-steps{ gap: 22px; margin: 22px 0 32px; }
    body.page-site .tutorial-step{ gap: 13px; }
    body.page-site .tutorial-step-num{ width: 30px; height: 30px; font-size: 14px; }
  }

  /* Telefono verticale: qui la larghezza utile scende sotto i 360px e le
     ultime cose pensate a due colonne vanno messe in fila. */
  @media (max-width: 560px){
  }

  /* Sotto i 520px lo shell stringe già il suo padding a 16px: è la soglia in
     cui il sito ammette di essere su un telefono, e le sezioni possono
     avvicinarsi ancora. 46+46 fra una e l'altra restano un respiro
     riconoscibile senza essere mezza schermata. */
  @media (max-width: 520px){
    body.page-site main > section{ padding: 46px 0; }
    body.page-site .cta-band{ padding: 12px 0 46px; }
    body.page-site .platform-hero{ padding: 36px 0 18px; }
    body.page-site .platform-hero ~ section{ padding: 26px 0 46px; }
  }

  @media (max-width: 420px){
    body.page-site .hero-window-wrap{ max-width: 100%; }
    body.page-site .plan-card .plan-price .amount{ font-size: 40px; }
    body.page-site .lib-media{ height: 150px; }
    body.page-site .game-brief-media{ height: 142px; }
    body.page-site .about-band{ padding: 22px 16px; }
    body.page-site .about-stat{ padding: 14px 12px; }
    body.page-site .cta-panel{ padding: 36px 18px; }
    body.page-site .faq-item{ padding: 0 15px; }
    body.page-site .plan-card{ padding: 22px 16px 20px; }
    body.page-site .plan-wrap .plan-side-item{ padding: 18px 15px; }
    body.page-site .step-card{ padding: 18px 15px 20px; }
    body.page-site .pillar{ padding: 16px 15px 18px; }
    body.page-site .cap{ padding: 16px 15px 18px; }
    body.page-site .lib-body{ padding: 16px 15px 18px; }
  }

  /* ==========================================================================
     TELEFONO — AUTENTICAZIONE, CHECKOUT, PAGINE LEGALI, PAGINE DI ERRORE
     login / register / forgot-password / subscribe / cookie-policy /
     privacy-policy / terms-of-service / 403 / 404 (tutte e quattro le lingue).

     Tutto quello che segue vive dentro una @media (max-width: N): il desktop
     resta esattamente com'era. L'unica eccezione è la prima regola, che non è
     un adattamento ma la correzione di un elemento che doveva già essere
     invisibile ovunque — il perché è scritto lì.
     ========================================================================== */

  /* Il riquadro "Discord collegato" della registrazione nasce con l'attributo
     hidden e lo toglie js/discord-register.js solo a chi arriva dal pulsante
     "Accedi con Discord" senza avere un account. Ma .discord-pending dichiara
     display:flex, e una regola d'autore batte sempre il display:none che il
     browser dà a [hidden]: il risultato è un rettangolo blurple vuoto in cima
     al modulo di registrazione in tutte e quattro le lingue — su un telefono
     si mangia la prima schermata utile senza dire niente. Stessa correzione
     già applicata nel foglio a .btn[hidden], .dash-nav-btn[hidden] e
     .checkout-step .plan-options[hidden]. */
  .discord-pending[hidden]{ display: none; }

  @media (max-width: 760px){

    /* ---------- AUTH: RESPIRO E LARGHEZZA UTILE ----------
       Fra i 16px per lato dello shell e i 40px per lato della card, su un
       telefono da 390px il modulo lavora dentro 278px: 112px di schermo, quasi
       un terzo, se ne vanno in cornice prima ancora di disegnare un campo. Su
       desktop quel margine è ciò che dà peso alla card in mezzo alla pagina;
       sul telefono la pagina è la card, e il margine è solo larghezza tolta ai
       campi. Stesso ragionamento sul padding verticale della sezione. */
    body.page-site .auth-section{ padding: 40px 0 52px; }
    body.page-site .auth-section .section-head{ margin-bottom: 24px; }
    body.page-site .auth-card{ padding: 28px 20px; border-radius: 20px; }
    body.page-site .auth-grid{ gap: 16px; }
    body.page-site .auth-side{ gap: 12px; }
    /* Solo i riquadri di contorno di QUESTE pagine: la stessa classe la usa
       anche la sezione prezzi della home, che non è roba di quest'area. */
    body.page-site .auth-side .plan-side-item,
    body.page-site .checkout-side .plan-side-item{ padding: 20px 18px; border-radius: 16px; }

    /* ---------- OCCHIO "MOSTRA PASSWORD" ----------
       38x38, sotto i 44px, e appiccicato al bordo destro del campo: il punto
       dove il pollice arriva peggio. È l'unico modo per rileggere una password
       digitata alla cieca su una tastiera del telefono, quindi vale la pena
       allargarlo. Cresce solo l'area premibile, l'icona resta 18px. right:0 al
       posto di 2px perché il bottone più largo, tenuto a 2px dal bordo, sarebbe
       finito sotto il testo del campo: il padding-right dell'input cresce di
       conseguenza. */
    /* MERGE — DUE REGOLE TOLTE IN FASE DI UNIONE: ".auth-card .field-toggle"
       (44x44, right:0) e ".auth-card .field-input-wrap input"
       (padding-right:48px). Le stesse due misure le fissa già il blocco
       "elementi globali" (sezione 1) con "body.page-site .field-toggle" e
       "body.page-site .field-input-wrap input": 44x44 a right:3px con
       padding-right 52px. Quei selettori pesano di più (un elemento in
       più: body), quindi vincevano comunque a ogni larghezza — le due
       righe qui non hanno mai avuto effetto. Il bersaglio resta 44x44. */

    /* ---------- CASELLE DI SPUNTA ("Ricordami", accettazione dei termini) ----
       La casella nativa da 16px è un bersaglio da 16px: qui la <label> avvolge
       casella e testo, quindi basta darle 44px di altezza perché TUTTA la riga
       diventi premibile. La casella cresce solo fino a 22px — ingrandirla
       ancora la renderebbe un quadratone fuori scala rispetto ai campi. */
    .auth-card .checkbox{ min-height: 44px; gap: 12px; line-height: 1.5; }
    /* MERGE: ".auth-card .checkbox input{ width:22px; height:22px }" tolta
       per lo stesso motivo — "body.page-site .checkbox input" del blocco
       globale è più specifica e porta comunque la casella a 20px. */

    /* I due link dentro l'accettazione dei termini stanno DENTRO la label:
       allargarli a 44px coprirebbe l'intera riga e rubarebbe alla casella il
       tocco che la spunta. Il padding verticale su un elemento inline allarga
       l'area premibile senza spostare di un pixel il testo: 6px bastano a
       portarli a ~30px senza che le aree delle due righe si sovrappongano. */
    .auth-card .checkbox .auth-link{ padding: 6px 0; }

    /* Link che stanno da soli su una riga (password dimenticata, "Registrati",
       "Modifica email"/"Rimanda mail" della verifica): qui nessuno gli
       contende lo spazio, quindi prendono i 44px pieni. */
    .auth-row .auth-link,
    .auth-footer .auth-link,
    .auth-actions-row .link-btn{
      display: inline-flex; align-items: center; justify-content: center;
      min-height: 44px; padding: 0 4px;
    }
    /* Ora che i due elementi della riga sono alti 44px, lo spazio verticale
       serve solo quando vanno a capo — succede a 320px con le frasi più lunghe
       (francese, spagnolo): 8px fra le due righe, 12px fra i due elementi. */
    .auth-row{ gap: 8px 12px; }

    /* ---------- CHECKOUT ---------- */
    body.page-site .checkout-section{ padding: 34px 0 60px; }
    body.page-site .checkout-section .section-head{ margin-bottom: 26px; }
    body.page-site .checkout-grid{ gap: 16px; }
    body.page-site .checkout-main{ gap: 16px; }
    body.page-site .checkout-side{ gap: 14px; }
    body.page-site .checkout-summary{ padding: 24px 20px; border-radius: 20px; }
    body.page-site .checkout-state{ padding: 24px 20px; border-radius: 20px; }
    /* La cifra del riepilogo è tarata su una colonna da 380px dentro una
       griglia da 1060: a tutta larghezza di telefono resta l'unica cosa da
       44px in una card fatta di righe da 13,5px. Rimpicciolirla rimette in
       proporzione la card e toglie di mezzo il caso limite: "149,99€ /
       settimana" a 44px occupa 227px dei 232 disponibili a 320px, cioè ci sta
       per cinque pixel — basta una lingua con la parola un filo più lunga e va
       a capo in mezzo al prezzo. */
    body.page-site .checkout-summary .plan-price .amount{ font-size: 38px; }
    body.page-site .checkout-summary .plan-tag{ font-size: 11.5px; }

    /* Prezzo scritto a mano nell'HTML (es. "1,79€ / giorno"): è quello che si
       vede finché js/subscribe.js non riceve il listino e lo riscrive in
       importo + periodo, ed è anche quello che RESTA se la chiamata fallisce.
       Con gli 11px ereditati da .plan-option il prezzo risultava più piccolo
       della frasetta che gli sta sotto (12,5px): il dato che fa scegliere il
       piano scritto più in piccolo del suo commento. */
    body.page-site .checkout-step .plan-option-price{ font-size: 13px; }
    /* Etichetta dello sconto e nota "solo pagamento unico": 10,5px e 10px sono
       sotto la soglia leggibile su un telefono. */
    body.page-site .plan-option-flag{ font-size: 11.5px; }
    body.page-site .payment-method-soon{ font-size: 11px; }

    /* ---------- PAGINE LEGALI ----------
       Sono muri di testo: su un telefono conta il ritmo, non la cornice. */
    body.page-site .legal{ padding: 38px 0 58px; }
    .legal-updated{ margin-bottom: 24px; }
    .legal h2{ margin: 28px 0 10px; font-size: 19px; }
    .legal h3{ margin: 18px 0 8px; }
    .legal ul{ padding-left: 20px; }
    /* Rete di sicurezza per le parole che non si spezzano da sole — indirizzi,
       email, nomi di cookie. A 320px la colonna è larga 288px e quelle di oggi
       ci stanno tutte, ma una sola più lunga spingerebbe fuori l'intera pagina
       invece di andare a capo, e in una pagina legale gli indirizzi cambiano. */
    .legal p, .legal li, .legal code{ overflow-wrap: break-word; }
    /* Link dentro il discorso: stesso ragionamento dei termini qui sopra —
       il padding verticale allarga il tocco senza toccare l'impaginazione.
       Qui le righe sono più distanziate (15px per 1.7), quindi si arriva ai
       44px pieni. */
    .legal .auth-link{ padding: 12px 0; }

    /* ---------- LA TABELLA DEI COOKIE DIVENTA UN ELENCO DI SCHEDE ----------
       .cookie-table ha min-width:560px: dentro un viewport da 390px l'ultima
       colonna finiva fuori dallo schermo e le altre si stringevano a una
       parola per riga. La tabella scorreva di lato dentro .table-scroll, ma
       una tabella che si legge scorrendo di lato non la legge nessuno.
       Qui ogni riga diventa una scheda e ogni cella una voce, con
       l'intestazione di colonna come etichetta presa da data-label.
       Le <th> restano nel DOM ritagliate a 1px: spariscono dallo schermo ma
       continuano a esistere per chi naviga con lo screen reader.
       ATTENZIONE: la stessa classe la usano le tabelle dei comandi in
       wiki/<lingua>/minecraft/tntcube.html (il percorso è scritto così e non
       con l'asterisco perché la sequenza asterisco-barra chiuderebbe QUESTO
       commento a metà frase: la regola qui sotto finirebbe dentro un
       selettore invalido e il browser la butterebbe via in silenzio — è
       successo davvero, l'ha scoperto il conteggio delle cssRules in fase di
       unione). La regola è scritta per funzionare anche
       senza data-label — in quel caso la cella si limita a impilarsi senza
       etichetta — ma quelle tabelle i data-label ce li hanno già, quindi
       vengono impaginate correttamente anche loro. */
    .table-scroll:has(> .cookie-table){
      overflow-x: visible; border: 0; border-radius: 0; margin: 16px 0 22px;
    }
    .cookie-table{
      display: block; position: relative; min-width: 0; background: transparent;
    }
    .cookie-table thead{
      position: absolute; width: 1px; height: 1px;
      overflow: hidden; clip-path: inset(50%); white-space: nowrap;
    }
    /* Anche le celle vanno rimpicciolite, non solo il <thead> che le contiene:
       ritagliate ma larghe come il loro testo, restano scatole da 80px che
       sporgono oltre il bordo destro del viewport. Non si vedono, ma per
       qualunque misura del layout la pagina risulta più larga dello schermo. */
    .cookie-table thead th{ display: block; width: 1px; height: 1px; padding: 0; overflow: hidden; }
    .cookie-table tbody, .cookie-table tr, .cookie-table td{ display: block; }
    .cookie-table tr{
      border: 1px solid var(--line); border-radius: 14px;
      background: var(--bg-panel); padding: 4px 16px; margin-bottom: 12px;
    }
    .cookie-table tr:last-child{ margin-bottom: 0; }
    .cookie-table td{
      padding: 12px 0; font-size: 14px; line-height: 1.55;
      border-bottom: 1px solid var(--line);
    }
    /* Le due righe qui sotto vanno in quest'ordine: la prima rimette i
       separatori dentro l'ultima scheda (il foglio li toglie tutti con
       "tr:last-child td", che in modalità tabella significava "ultima riga",
       qui significherebbe "ultima scheda"), la seconda toglie il separatore
       sotto l'ultima voce di OGNI scheda, che altrimenti raddoppierebbe il
       bordo della scheda stessa. */
    .cookie-table tr:last-child td{ border-bottom: 1px solid var(--line); }
    .cookie-table tr td:last-child{ border-bottom: none; }
    .cookie-table td[data-label]::before{
      content: attr(data-label);
      display: block; margin-bottom: 5px;
      font-family: 'JetBrains Mono', monospace; font-size: 11.5px;
      text-transform: uppercase; letter-spacing: .06em; color: var(--dim);
    }

    /* ---------- 403 / 404 ----------
       min-height:calc(100vh - 148px) è tarato su header e footer da desktop.
       Sul telefono quei due occupano 418px, non 148: la sezione si teneva 696px
       per un contenuto che ne chiede 340, e la differenza diventava vuoto sopra
       e sotto i pulsanti, con il footer spinto giù a forza. Tolto il minimo, la
       pagina è alta quanto quello che c'è scritto. */
    body.page-site .error-404, body.page-site .error-403{ padding: 44px 0 56px; }
    .error-404, .error-403{ min-height: 0; }
    .error-404 .eyebrow, .error-403 .eyebrow{ margin-bottom: 20px; }
    body.page-site .error-404 .hero-ctas,
    body.page-site .error-403 .hero-ctas{ margin-top: 26px; }
  }

  @media (max-width: 560px){
    /* Sotto i 560px lo shell scende a 16px di padding: la card può stringere
       ancora il proprio, così i campi guadagnano gli ultimi pixel utili. */
    body.page-site .auth-card{ padding: 24px 16px; border-radius: 18px; }
    body.page-site .checkout-summary{ padding: 22px 16px; }
    body.page-site .checkout-state{ padding: 22px 16px; }
    body.page-site .auth-side .plan-side-item,
    body.page-site .checkout-side .plan-side-item{ padding: 18px 16px; }
    body.page-site .checkout-summary .plan-price .amount{ font-size: 34px; }
    .cookie-table tr{ padding: 4px 14px; }

    /* A 320px i due pulsanti non ci stanno affiancati: vanno a capo e restano
       centrati, larghi uno il doppio dell'altro, come se fossero due cose di
       peso diverso capitate lì. In colonna sono due bersagli larghi uguali,
       con la scelta principale sopra. */
    body.page-site .error-404 .hero-ctas,
    body.page-site .error-403 .hero-ctas{
      flex-direction: column; align-items: stretch; width: 100%; max-width: 300px;
    }
    body.page-site .error-404 .hero-ctas .btn,
    body.page-site .error-403 .hero-ctas .btn{ width: 100%; justify-content: center; }
  }

  /* Il foglio ha già un blocco a 380px che rimpicciolisce la cifra dell'OTP:
     stesso punto di rottura, stesso motivo. Su un iPhone SE le sei caselle si
     dividono 256px di card, e con 8px di spazio fra l'una e l'altra restano
     larghe 36px. Tolti tre pixel di spazio, ne guadagnano due e mezzo
     ciascuna: non è molto, ma su sei caselle in fila si sente. */
  @media (max-width: 380px){
    .otp-group{ gap: 5px; }
  }

  /* ====================================================================
     TELEFONO — CONTENUTO DEI PANNELLI DELLA DASHBOARD CLIENTE
     (dashboard.html: barra superiore, panoramica, connessioni, profilo,
     abbonamento, giochi, overlay, TTS, azioni & eventi, e le finestrelle
     che quei pannelli aprono).

     Tutto sta dentro una @media: sul desktop non cambia niente. Dove una
     regola esistente andava corretta non l'ho toccata, l'ho riscritta qui
     dentro. La barra laterale, la sua navigazione e .admin-table non sono
     roba mia e non compaiono in nessun selettore qui sotto.
     ==================================================================== */

  @media (max-width: 760px){

    /* ---------- Le griglie interne tornano a una colonna ----------
       Ogni griglia dei pannelli ha una traccia minima pensata per il
       desktop: 360px l'Overlay, 320 le slot dei giochi, 300 il TTS. Su uno
       schermo da 320px quel minimo è più largo della pagina, la colonna
       esce dal bordo e si tira dietro tutto il documento — è esattamente
       così che il pannello Overlay portava lo scrollWidth a 376 contro i
       320 dello schermo, l'unico scroll orizzontale vero della dashboard.
       A colonna singola il minimo semplicemente non esiste più. */
    .overlay-subpanes,
    .tts-cards-grid,
    .mc-slots-grid{ grid-template-columns: minmax(0, 1fr); }

    /* Stessa storia, ma sui contenitori flex. Attenzione: qui non basta
       azzerare il min-width — con flex:1 e nessun minimo le due colonne si
       dividono lo schermo a metà e diventano due colonnine da 130px. Il
       minimo va sostituito, non tolto: flex-basis 100% le manda una sotto
       l'altra, che è quello che il min-width:320px voleva ottenere (e che a
       320px di schermo non otteneva, sfondava e basta). */
    .mc-config-top > .mc-config-left,
    .mc-config-top > .connections-card,
    .ae-side-row > .ae-screens-panel{ flex: 1 1 100%; min-width: 0; max-width: none; }
    /* La riga Profilo/Gestione profilo: a colonna singola, altrimenti la
       card di sinistra resta a 340px fissi e quella di destra si riduce a
       una striscia. */
    .ae-top-row{ grid-template-columns: minmax(0, 1fr); }

    /* .overlay-preview invece non è dentro un contenitore flex (la card non
       lo è): lì il min-width:260px è una larghezza imposta a un blocco che
       ne avrebbe 240 — si toglie e basta. */
    .overlay-preview{ min-width: 0; }

    .ae-game-action-field,
    #ae-tts-voice-field,
    #ae-event-gift-trigger,
    .tts-special-item .mc-action-field{ flex-basis: 100%; min-width: 0; }
    /* Le righe etichetta+campo di Azioni & Eventi non andavano a capo: con i
       campi qui sopra a piena larghezza l'etichetta resterebbe schiacciata a
       zero invece di salire sopra al campo. */
    .ae-field-row{ flex-wrap: wrap; }
    /* Sotto i 700px due tendine affiancate diventano due monconi in cui non si
       legge nessun id: una per riga. */
    .ae-game-action-row > .ae-game-action-field,
    .ae-vanilla-arg-row.is-pick{ flex:1 1 100%; min-width:0; }

    /* Niente esce mai dalla propria card, nemmeno le anteprime overlay
       (iframe) e le copertine dei giochi. */
    .dash-panel img,
    .dash-panel iframe,
    .dash-panel video,
    .dash-panel canvas{ max-width: 100%; }

    /* ---------- Campi di testo: 16px e alti 44 ----------
       I 16px non sono una scelta estetica: sotto quella misura iOS Safari
       ingrandisce la pagina da solo appena si tocca il campo, e non la
       rimpicciolisce più quando si esce — da lì in poi si naviga una
       dashboard zoomata di cui si vede metà. I 44 di altezza servono a
       centrare il campo col pollice. Le caselle a larghezza fissa crescono
       di conseguenza: col testo più grande il numero dentro non ci stava. */
    body.page-dashboard .dash-search input,
    .win-target-input,
    .ae-profile-code-input,
    .ae-field-row-input,
    .ae-alert-text-input,
    .ae-action-modal .ae-alert-text-input,
    .mc-prompt-input,
    .gift-modal-search,
    .tts-voice-search,
    .tts-allowed-sub-input,
    .tts-special-item input[type="text"],
    #tts-test-input,
    .mc-color-hex-input,
    .search-combo-input,
    .search-combo-search,
    .overlay-style-row .overlay-style-number-input,
    .overlay-style-row .overlay-style-text-input{ font-size: 16px; min-height: 44px; }

    .tts-allowed-sub-input{ width: 62px; }
    .ae-field-row-input{ width: 86px; }
    .win-target-input{ width: 104px; }
    .overlay-style-row .overlay-style-number-input{ width: 78px; }

    /* ---------- Bersagli tattili da 44px ----------
       44x44 è il minimo che un pollice centra senza sbagliare (Apple HIG,
       WCAG 2.5.5). Qui si alza solo l'altezza minima: la grafica dei
       pulsanti resta quella, cambia quanto sono alti. */
    body.page-dashboard .ov-link,
    body.page-dashboard .ov-add,
    body.page-dashboard .ov-conn .ov-manage,
    body.page-dashboard .ov-btn,
    body.page-dashboard .dash-search-results button,
    .mc-action-trigger,
    .mc-action-option,
    .mc-subtab-btn,
    .audio-picker-tab,
    .ae-screen-copy-btn,
    .ae-sort-btn,
    .tts-allowed-manage-btn,
    .mc-token-row .btn,
    .mc-prompt-actions .btn,
    .gift-modal-item,
    .audio-picker-tile{ min-height: 44px; }
    .mc-color-trigger{ width: 44px; height: 44px; }

    /* Comandi nati come testo-link (Vedi tutti, Aggiungi connessione,
       Gestisci): senza inline-flex l'altezza minima non li tocca nemmeno,
       perché una riga di testo inline non ha una scatola da alzare. */
    body.page-dashboard .ov-link,
    body.page-dashboard .ov-add,
    .tts-allowed-manage-btn{ display: inline-flex; align-items: center; }
    /* .mc-action-option è block: senza flex il testo resterebbe incollato
       in alto nella scatola appena alzata. */
    .mc-action-option{ display: flex; align-items: center; }

    /* La casella di spunta resta piccola, è l'etichetta che la contiene a
       diventare alta 44: su un <label> il tocco vale come tocco sulla
       casella, quindi diventa bersaglio la riga intera senza gonfiare il
       quadratino e senza sfasciare le liste dense (Utenti consentiti del
       TTS, opzioni della finestrella Nuova azione). */
    .dash-panel .checkbox,
    .tts-checkbox,
    .mc-audio-toggle,
    .ae-action-option,
    .tts-voice-option{ min-height: 44px; }

    /* Comandi quadrati minuscoli: qui non basta l'altezza, servono anche i
       44 di larghezza. */
    .tts-special-remove-btn,
    .ae-pagination-btn,
    .mc-slot-remove-btn{ width: 44px; height: 44px; }
    .tts-voice-test-btn{ width: 44px; height: 44px; font-size: 14px; }
    /* Il ▶ di prova cresce da 24 a 44: la riga della voce si stringe nel
       margine interno per non far diventare l'elenco una scala, e in cambio
       se ne vedono comunque quattro alla volta invece di tre. */
    .tts-voice-option{ padding: 4px 6px; }
    .tts-voice-list{ max-height: 300px; }
    /* MERGE — TRE REGOLE TOLTE IN FASE DI UNIONE. Qui i quattro comandi per
       riga delle tabelle Azioni/Eventi (.ae-action-tool-btn 44x44 font 16px,
       .ae-action-row-tools gap 6px, .ae-col-icon larga 200px) erano tarati
       su una tabella che scorre di lato dentro il suo .table-scroll. Il
       blocco "admin e tabelle" (sezione 5) riscrive gli stessi identici
       selettori più avanti, nella stessa @media, perché lì la tabella non
       scorre più: diventa una pila di schede. Vinceva comunque lui (stessa
       specificità, ma viene dopo), quindi resta solo la sua versione —
       44x44 font 15px, gap 4px, colonna a larghezza automatica. */

    /* Spunta di selezione delle righe Azioni/Eventi: il quadratino resta di
       18px (è dentro una cella stretta) ma un ::before trasparente più
       grande lo circonda e raccoglie i tocchi. Non ::after: quello è già
       occupato dalla spunta a "V" quando la casella è accesa. La larghezza
       del ::before è tarata sulla colonna qui sotto, così l'area sensibile
       non sconfina nella cella dei pulsanti accanto. */
    .ae-col-check{ width: 52px; }
    .ae-col-check input[type="checkbox"]::before{
      content: ''; position: absolute; left: 50%; top: 50%;
      width: 48px; height: 44px; transform: translate(-50%, -50%);
    }

    /* Cursori a slitta (velocità/tono/volume del TTS, opacità e dimensioni
       negli overlay): 16px di altezza sono impossibili da agganciare col
       dito. La barra resta sottile — è la scatola del controllo a diventare
       alta 44, il pallino ci si centra dentro da solo. */
    .dash-panel input[type="range"],
    .mc-prompt-modal input[type="range"]{ height: 44px; }

    /* Occhio mostra/nascondi password (card "Cambia password" del profilo).
       Ambito .dash-panel: lo stesso .field-toggle sta anche nelle pagine di
       accesso e registrazione, che non sono di questa area. */
    .dash-panel .field-toggle{ min-width: 44px; min-height: 44px; right: 3px; }
    .dash-panel .field-input-wrap input{ padding-right: 50px; }

    /* ---------- Righe di controlli che vanno a capo ----------
       Il link OBS più i suoi quattro comandi non stanno su una riga da
       320px: il link si prende una riga tutta sua (tanto è già troncato con
       i puntini) e i pulsanti si dividono quella sotto in parti uguali. */
    .overlay-link-row .mc-token-value{ flex: 1 1 100%; }
    .overlay-link-row .btn,
    .mc-token-row .btn{ flex: 1 1 auto; justify-content: center; }

    /* "Personalizza overlay": etichetta a sinistra e controllo a destra
       lasciavano al controllo una trentina di pixel scarsi. Qui l'etichetta
       si prende la riga e il controllo quella sotto, a piena larghezza. */
    .overlay-style-row{ flex-wrap: wrap; }
    .overlay-style-row-label{ flex: 1 1 100%; }
    .overlay-style-row-control{ flex: 1 1 100%; justify-content: space-between; }
    .overlay-style-row .mc-action-field,
    .overlay-style-row .overlay-style-text-input{ width: 100%; flex: 1 1 auto; }
    .overlay-style-row-control input[type="range"]{ flex: 1 1 auto; width: auto; }

    /* Barre di pulsanti (Profili, slot, toolbar Azioni/Eventi): invece di
       stringersi al testo si dividono la riga, così hanno tutti la stessa
       larghezza e nessuno resta un francobollo. */
    .ae-profile-manage-row .btn,
    .mc-slots-actions .btn,
    .ae-actions-toolbar .btn,
    .tutorial-download-links .btn{ flex: 1 1 auto; justify-content: center; }

    /* Importa/Esporta: la card del profilo è align-items:center, quindi la
       riga si stringe al contenuto e non ha spazio da distribuire — un
       flex:1 1 auto sui due <details> non farebbe niente. Si allarga la
       riga, poi i due menu si dividono lo spazio.
       E i .btn compattati per il desktop qui sopra (13.5px, padding 10px)
       scendono a 35-40px: sotto il polpastrello ci vogliono 44, come per
       ogni altro comando del pannello. */
    .ae-profile-io{ width: 100%; }
    .ae-profile-io > .ae-io-menu{ flex: 1 1 auto; }
    .ae-io-menu > summary{ width: 100%; justify-content: center; }
    .ae-actions-toolbar .btn,
    .ae-profile-manage-row .btn,
    .ae-io-menu > summary,
    .ae-io-pop .btn{ min-height: 44px; }
    .ae-profile-arrow{ width: 44px; height: 44px; }

    /* Riga di una connessione in Panoramica: nome, stato e "Gestisci" sulla
       stessa riga si schiacciano a vicenda finché il nome resta un moncone.
       Il pulsante scende su una riga sua e il testo si riprende la card. */
    body.page-dashboard .ov-conn{ flex-wrap: wrap; }
    body.page-dashboard .ov-conn .ov-manage{ flex: 1 1 100%; justify-content: center; }

    /* ---------- Finestrelle ----------
       Le tre grandi (Nuova azione 960x680, Elenco Audio/Libreria Media
       640x600, Personalizza overlay) hanno misure fisse da desktop. Sul
       telefono diventano larghe quanto lo schermo meno un margine e alte al
       massimo quanto lo schermo: dentro scorre solo la parte centrale, che è
       già predisposta, quindi titolo e pulsanti Annulla/Salva restano
       sempre in vista invece di finire sotto il bordo. */
    .mc-prompt-overlay{
      padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
    }
    .mc-prompt-modal.ae-action-modal,
    .mc-prompt-modal.audio-picker-modal{
      width: 100%; max-width: 100%; height: auto; max-height: calc(100vh - 24px);
    }
    /* selettore combinato: deve battere .mc-prompt-modal.overlay-style-modal
       della regola desktop (max-height:88vh), non solo .overlay-style-modal */
    .mc-prompt-modal.overlay-style-modal{ max-height: calc(100vh - 24px); }
    /* Tre pulsanti in fondo (Annulla/Ripristina/Salva) allineati a destra e
       senza andare a capo: il primo finiva fuori dal bordo SINISTRO della
       finestrella. Qui vanno a capo e si dividono la riga. */
    .mc-prompt-actions{ flex-wrap: wrap; }
    .mc-prompt-actions .btn{ flex: 1 1 auto; justify-content: center; }

    .gift-modal-overlay{
      padding: 4vh 12px calc(4vh + env(safe-area-inset-bottom));
    }
    .gift-modal{ padding: 22px 16px 16px; }
    .gift-modal-grid{ max-height: 56vh; }
    .gift-modal-close{
      top: 10px; right: 10px; width: 44px; height: 44px;
      display: flex; align-items: center; justify-content: center;
    }
    /* La griglia audio restava a una colonna sola: minmax(120px) più il
       padding non ci stava due volte nella modale ristretta. */
    .audio-picker-grid{ grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); }

    /* Tre schede (Audio pubblici / Audio locali / Cerca online) su una riga
       sola qui non ci stanno: a un terzo di larghezza le etichette più lunghe
       ("Audios publics", "Chercher en ligne") uscivano dal pulsante. Due per
       riga, con la terza che si prende tutta la riga sotto: nessuna etichetta
       da accorciare lingua per lingua e nessuna che venga tagliata. */
    .audio-picker-tabs{ display:grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .audio-picker-tab:nth-child(3){ grid-column: 1 / -1; }
    /* minmax(0, 1fr) e non 1fr: con "1fr" una colonna non scende sotto la
       larghezza minima del suo contenuto, quindi due etichette lunghe
       potevano allargare la finestrella oltre il bordo dello schermo invece
       di stringersi. Padding e corpo più piccoli qui sotto servono allo
       stesso scopo dall'altro lato — far entrare l'etichetta nello spazio
       che c'è, invece di pretenderne di più. */
    .audio-picker-tab{ padding:9px 8px; font-size:11px; letter-spacing:.02em; }

    /* Riquadri fissi agli angoli: erano larghi 260 e 320px fissi, su uno
       schermo da 320 uscivano dal bordo opposto. */
    .ae-alert-preview{ top: 12px; right: 12px; width: min(260px, calc(100vw - 24px)); }
    .ae-media-preview{ top: 12px; left: 12px; width: min(320px, calc(100vw - 24px)); }
    .tts-voice-popup{ width: 280px; max-width: calc(100vw - 32px); }
    .mc-color-panel{ max-width: calc(100vw - 24px); }
    /* Il toast è ancorato a destra con una larghezza fissa da 320px: a
       telefono verticale sarebbe largo quanto tutto lo schermo più i
       margini. Qui si appoggia a entrambi i bordi. */
    .toast-stack{ left: 12px; right: 12px; align-items: stretch; }
    .toast{ max-width: none; }

    /* ---------- Testo leggibile ----------
       Sotto i 12px su un telefono si legge a fatica. Le note e i testi
       scorrevoli salgono a 12; i badge e le intestazioni di gruppo — che si
       leggono a colpo d'occhio, non riga per riga — al minimo di 11. */
    body.page-dashboard .ov-stat-note,
    body.page-dashboard .ov-feed-time,
    body.page-dashboard .ov-quick button,
    body.page-dashboard .ov-quick a,
    .game-lock-note,
    .ae-lock-note{ font-size: 12px; }

    .dash-panel .badge,
    body.page-dashboard .dash-bell-badge,
    .tts-voice-cloud-badge,
    .tts-voice-group-header,
    .mc-action-group-label{ font-size: 11px; }

    /* ---------- Bordi dello schermo ----------
       Sull'iPhone in orizzontale il notch mangia un pezzo di lato, e in
       verticale la barra gesti copre il fondo: il contenuto del pannello si
       tiene alla larga da entrambi. */
    body.page-dashboard .app-main-wrap{
      padding-left: max(16px, env(safe-area-inset-left));
      padding-right: max(16px, env(safe-area-inset-right));
      padding-bottom: calc(26px + env(safe-area-inset-bottom));
    }
    body.page-dashboard .dash-footer{
      gap: 14px 20px; padding: 20px 16px calc(20px + env(safe-area-inset-bottom));
    }
    body.page-dashboard .dash-footer a{
      display: inline-flex; align-items: center; min-height: 44px;
    }
  }

  @media (max-width: 560px){

    /* ---------- Barra superiore su una riga sola ----------
       Cinque comandi con l'etichetta scritta (Connetti Live, Guida rapida,
       campanella, lingua, Esci) più la ricerca non stanno in 320px: andando
       a capo la barra diventava alta tre righe, e siccome è appiccicata in
       alto (sticky) quelle tre righe restavano lì a mangiarsi mezzo schermo
       per tutto lo scorrimento.
       Qui la ricerca si prende la prima riga intera e i comandi la seconda.
       "Connetti Live" tiene la sua etichetta — è l'azione che si usa di più
       e l'unica con uno stato acceso/spento da leggere — mentre "Guida
       rapida" ed "Esci" restano la sola icona (campanella e bandiera lo
       erano già). font-size:0 è il modo di spegnere un'etichetta che nel
       markup è un nodo di testo nudo, senza un elemento suo da nascondere:
       il nome accessibile non cambia, gli screen reader la leggono ancora. */
    body.page-dashboard .dash-topbar{ padding: 10px 12px; gap: 8px; }
    body.page-dashboard .dash-search{ order: 1; flex: 1 1 100%; min-width: 0; }
    /* min-width:0 non è decorativo: senza, la riga dei comandi non può
       restringersi sotto la somma dei suoi pulsanti (min-width:auto è il
       valore di partenza di ogni elemento flex) e sfonda la barra portando
       lo scroll orizzontale su TUTTA la pagina, non solo qui dentro. */
    body.page-dashboard .dash-topbar-actions{
      order: 2; flex: 1 1 100%; min-width: 0; margin-left: 0;
      gap: 8px; justify-content: flex-end; flex-wrap: nowrap;
    }
    /* Connetti Live a sinistra (margin-right:auto), i tre comandi di
       servizio raggruppati a destra: sparpagliarli tutti e cinque a
       distanza uguale li faceva sembrare cinque cose dello stesso peso. */
    body.page-dashboard .dash-topbar .app-overlay-btn{
      flex: 0 1 auto; min-width: 0; min-height: 44px; margin-right: auto;
      padding: 10px 12px; font-size: 13px; overflow: hidden; white-space: nowrap;
    }
    body.page-dashboard .dash-top-btn,
    body.page-dashboard .dash-topbar .dash-logout{
      flex: 0 0 auto; width: 44px; height: 44px; min-height: 44px;
      padding: 0; gap: 0; font-size: 0; justify-content: center;
    }
    body.page-dashboard .dash-topbar-lang .lang-dropdown-btn{
      min-width: 44px; min-height: 44px; padding: 10px;
      display: flex; align-items: center; justify-content: center;
    }

    /* ---------- Più larghezza utile dentro le card ----------
       24px di margine interno per lato su uno schermo da 320 sono il 15%
       della pagina buttato: qui il contenuto guadagna quasi 20px. */
    .connections-card,
    .sub-card{ padding: 18px 16px; }
    body.page-dashboard .ov-card{ padding: 16px; }
    .mc-prompt-modal{ padding: 18px 16px; }
    /* Il rientro di 24px allineava il pannello "Riproduci audio" al testo
       della casella che lo apre: un allineamento che su un telefono costa
       un decimo della larghezza della finestrella. */
    .ae-audio-inline{ margin-left: 0; }

    /* ---------- Giochi: scegliere la piattaforma in una schermata ----------
       Quattro tessere alte 216px l'una fanno 860px di scorrimento solo per
       decidere se si gioca su Minecraft o su Roblox. Sul telefono diventano
       righe di elenco — copertina piccola a sinistra, nome a destra — e la
       scelta sta tutta in una schermata. Selettore ancorato a
       .dash-panel .game-platforms: la stessa .game-platform-tile la usano
       anche le tessere del wiki, che restano come sono. */
    .dash-panel .game-platforms{ gap: 12px; }
    .dash-panel .game-platforms .game-platform-tile{
      position: relative; display: flex; align-items: center; gap: 14px; min-height: 44px;
    }
    .dash-panel .game-platforms .game-platform-tile .game-thumb{
      flex: 0 0 104px; height: 78px;
    }
    .dash-panel .game-platforms .game-platform-tile h3{
      padding: 0 14px 0 0; font-size: 16px;
    }
    /* Il contrassegno "In arrivo" sta nell'angolo in alto a destra della
       copertina: su una copertina da 104px larga quell'angolo non esiste, il
       contrassegno da solo è largo i due terzi dell'immagine. Diventa una
       fascetta appoggiata al bordo basso, che l'immagine se la può
       permettere. */
    .dash-panel .game-platforms .badge-coming-soon{
      top: auto; bottom: 5px; left: 5px; right: 5px;
      justify-content: center; padding: 2px 4px;
    }

    /* Le card dei singoli giochi restano verticali (hanno una descrizione da
       leggere e un pulsante), ma con la copertina più bassa e meno aria:
       quattro card in colonna erano 1500px di scorrimento. */
    .dash-panel .dash-games{ gap: 14px; }
    .dash-panel .dash-games .game-thumb{ height: 118px; }
    .dash-panel .dash-games .game-body{ padding: 14px 16px 18px; gap: 10px; }

    .win-row{ justify-content: space-between; }

    /* Riga di uno Schermo (Azioni & Eventi): nome a sinistra, stato e copia
       a destra — a 320px il nome finiva su tre righe. */
    .ae-screen-row{ flex-wrap: wrap; }
    .ae-screen-row-right{ flex: 1 1 100%; justify-content: space-between; }

    /* Riquadri Overlay e TTS della Panoramica: l'anteprima da 200x130 fissi
       accanto al testo lasciava al testo una colonna da 38px. Sul telefono
       l'anteprima si prende la larghezza intera e il testo va sotto. */
    body.page-dashboard .ov-split{ gap: 14px; }
    body.page-dashboard .ov-preview{ width: 100%; height: 140px; }
    body.page-dashboard .ov-split-body{ flex: 1 1 100%; min-width: 0; }
  }

  @media (max-width: 420px){
    /* Sotto i 420px anche "Connetti Live" perde l'etichetta: cinque comandi
       da 44px più i loro margini sono già tutto lo spazio che c'è, e con
       l'etichetta scritta il pulsante finiva tagliato a metà parola. Lo
       stato acceso/spento continua a leggersi dal colore pieno (lo imposta
       data-connected, vedi js/overlay-panel.js), che è comunque il modo in
       cui lo si guarda mentre si è in diretta. */
    body.page-dashboard .dash-topbar .app-overlay-btn{
      flex: 0 0 auto; width: 44px; padding: 0; gap: 0; font-size: 0; justify-content: center;
    }

    /* Sei scorciatoie su tre colonne diventano etichette di due parole
       spezzate su tre righe: a due colonne il testo sta su una riga sola. */
    body.page-dashboard .ov-quick{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Il regalo si riconosce dall'icona, e a tre per riga l'icona da 56px
       non lascia spazio al nome sotto. */
    .gift-modal-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  /* ==========================================================================
     PANNELLO ADMIN E TABELLE DATI SUL TELEFONO
     ==========================================================================
     .admin-table nasce con min-width:900px. Dentro un telefono da 390px la
     tabella scorreva in orizzontale dentro .table-scroll: si vedeva la prima
     colonna e, incollata al bordo destro, la colonna sticky "Gestisci" — in
     mezzo un vuoto da attraversare alla cieca, senza intestazioni, senza
     sapere cosa si sta leggendo. Nove pannelli admin su dieci erano fatti
     così, più i due riquadri della dashboard cliente che riusano la stessa
     classe (storico Pagamenti, tabelle Azioni ed Eventi).

     Sotto i 760px la tabella smette di comportarsi da tabella: ogni <tr>
     diventa una scheda con bordo e ogni <td> una riga "etichetta / valore".
     L'etichetta la stampa ::before leggendo data-label, che il JavaScript
     incolla su ogni cella COPIANDOLO DAL <thead> della tabella stessa — vedi
     labelRowCells in js/admin.js, labelTableCells in js/azioni-eventi-panel.js
     e renderBilling in js/dashboard.js. Le colonne quindi continuano ad avere
     un nome solo, quello scritto nell'HTML, anche nelle altre tre lingue.
     Una cella senza data-label (celle con colspan, righe di dettaglio) si
     impila lo stesso, semplicemente senza etichetta: la regola degrada. */
  @media (max-width: 760px){
    /* Non c'è più niente da scorrere: la tabella sta tutta nella pagina. Via
       anche bordo e angoli arrotondati, altrimenti raddoppierebbero quelli
       che ogni scheda si è appena data.
       Ambito body.page-dashboard (cioè admin e dashboard cliente) e non
       .table-scroll in generale: lo stesso contenitore avvolge anche la
       tabella dei cookie nelle quattro cookie-policy.html e le tabelle della
       wiki, che non diventano schede e senza lo scorrimento sfonderebbero
       la pagina. */
    .page-dashboard .table-scroll{ overflow-x: visible; border: none; border-radius: 0; margin: 14px 0; }

    .admin-table{ display: block; width: 100%; min-width: 0; }
    /* display:block e display:flex qui sotto sono regole d'autore e battono il
       display:none che il browser dà da sé all'attributo hidden — lo stesso
       inciampo già capitato con .btn[hidden] e .table-pager[hidden]. Senza
       queste due righe si vedrebbero la tabella vuota dei pannelli che si
       nascondono da soli (Abbonamenti, Trial, Live, Avvisa, Manutenzione,
       Audio pubblici) e, sotto ogni codice referral, la riga di dettaglio
       chiusa: una striscia vuota tra una scheda e l'altra. */
    .admin-table[hidden]{ display: none; }
    .admin-table tr[hidden]{ display: none; }
    /* L'intestazione ora vive dentro ogni cella. Lasciarla sopra la pila di
       schede non aiuterebbe nessuno, e si porterebbe dietro la spunta
       "seleziona tutto" delle tabelle Azioni/Eventi: un bersaglio invisibile
       ma raggiungibile col Tab. display:none la toglie anche da lì. */
    .admin-table thead{ display: none; }
    .admin-table tbody{ display: block; }

    /* La riga è un contenitore flex e non un semplice blocco per un motivo
       solo: nelle tabelle Azioni/Eventi la spunta di selezione e i pulsanti
       ▶✎⧉🗑️ sono due celle separate che devono stare sulla stessa riga in
       cima alla scheda. Tutte le altre celle prendono flex-basis 100% e si
       comportano esattamente come blocchi impilati. */
    .admin-table tr{
      display: flex; flex-wrap: wrap; overflow: hidden;
      margin-bottom: 12px; border: 1px solid var(--line); border-radius: 12px;
      background: var(--bg-panel-2);
    }
    .admin-table tr:last-child{ margin-bottom: 0; }

    .admin-table td{
      flex: 1 1 100%;
      display: flex; align-items: flex-start; gap: 10px;
      padding: 10px 14px; font-size: 13.5px; line-height: 1.45;
      border-bottom: 1px solid var(--line);
      /* Email, ID transazione e nomi file non hanno spazi dove andare a capo:
         senza questo escono dalla scheda invece di spezzarsi. Serve anche a
         disinnescare il white-space:nowrap di .admin-users-table td, pensato
         per tenere in riga le nove colonne del desktop. */
      overflow-wrap: anywhere; white-space: normal;
    }
    /* L'ultima cella chiude la scheda: il bordo del contenitore fa già da
       riga di fondo. */
    .admin-table tr > td:last-child{ border-bottom: none; }

    .admin-table td[data-label]::before{
      content: attr(data-label);
      flex: 0 0 38%; max-width: 130px;
      font-family:'JetBrains Mono'; font-size: 11px; line-height: 1.55;
      text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
    }

    /* Celle che non appartengono a una colonna sola — "Nessun account
       corrisponde alla ricerca", la riga di dettaglio dei codici referral con
       l'elenco di chi si è registrato — restano senza etichetta e vanno a
       tutta larghezza invece di dividersi in due colonne. */
    .admin-table td[colspan]{ display: block; }
    .admin-table td.admin-table-empty{ display: block; text-align: center; }

    /* La colonna "Gestisci" era incollata al bordo destro (position:sticky)
       perché la tabella scorreva e altrimenti l'azione principale finiva
       fuori vista. Adesso non scorre più niente: una cella ancorata a destra
       dentro una scheda alta trecento pixel sarebbe solo un rettangolo nero
       sospeso a mezz'aria. Torna una cella come le altre, e il fondo pieno
       che le serviva da sticky (var(--bg), #0A0410 nell'hover) lascia il
       posto a quello della scheda. */
    .admin-users-table th:last-child,
    .admin-users-table td:last-child{
      position: static; background: transparent; border-left: none; text-align: left;
    }
    .admin-users-row:hover td:last-child{ background: transparent; }

    /* Ultima cella quando contiene i pulsanti della riga: il JavaScript le
       mette la classe .is-row-actions (vedi labelRowCells in js/admin.js).
       Non è un valore, è il piede della scheda — niente etichetta, sfondo
       appena staccato e pulsanti larghi quanto la scheda. Su desktop la
       classe c'è ma nessuna regola la guarda. */
    .admin-table td.is-row-actions{
      display: flex; flex-wrap: wrap; gap: 8px;
      padding: 10px 12px; background: rgba(214,190,245,0.035);
    }
    /* Un pulsante solo si prende tutta la riga, due se la dividono: il
       flex-basis a 120px è la soglia sotto la quale mandano a capo invece di
       stringersi fino a spezzare l'etichetta. Vale sia per i pulsanti figli
       diretti della cella sia per quelli dentro .admin-row-actions. */
    .admin-table td.is-row-actions > *,
    .admin-table td.is-row-actions .admin-row-actions > *{ flex: 1 1 120px; }
    .admin-table td.is-row-actions .admin-row-actions{ gap: 8px; }

    /* Bersagli da 44px. Nella tabella desktop questi pulsanti stanno dentro
       una cella di sette-nove colonne e devono restare minuscoli; nella
       scheda hanno tutta la larghezza a disposizione, e 26px di altezza col
       pollice si sbagliano — soprattutto "Elimina" e "Termina", che stanno
       accanto a pulsanti innocui. */
    .admin-manage-btn{ width: 100%; min-height: 44px; font-size: 14px; padding: 10px 16px; }
    .admin-action-btn{ min-height: 44px; padding: 10px 14px; font-size: 12.5px; border-radius: 8px; }
    /* La ✕ dei movimenti (tab Business) si capisce finché sta in fondo a una
       riga, sotto l'intestazione "Azioni": da sola in fondo a una scheda è un
       quadrato muto, e cancella un movimento per sempre. Qui si porta accanto
       il proprio title — "Elimina movimento", che js/admin.js le mette già
       per il suggerimento del mouse — invece di ripetere quella stringa in
       una regola CSS, dove nessuno andrebbe a cercarla se cambiasse. */
    .admin-remove-btn{
      width: auto; min-width: 44px; height: 44px; padding: 0 16px;
      display: inline-flex; align-items: center; justify-content: center; gap: 8px;
      font-size: 15px;
    }
    .admin-table td.is-row-actions > .admin-remove-btn::after{
      content: attr(title);
      font-family:'Nunito Sans', sans-serif; font-size: 12.5px; font-weight: 600;
    }

    /* Tab Live, colonna dei bridge: i due badge devono restare uno sopra
       l'altro come sul desktop (.live-bridges-cell è già flex in colonna), ma
       l'etichetta finirebbe a fianco del primo e non sopra la coppia. Qui
       l'etichetta prende una riga sua e i badge la seguono incolonnati. */
    .admin-table td.live-bridges-cell{ flex-direction: column; align-items: flex-start; gap: 6px; }
    .admin-table td.live-bridges-cell::before{ flex: 0 0 auto; max-width: none; }

    /* MERGE: ".badge{ font-size:11px }" tolta qui — stesso selettore, stesso
       valore e stessa @media del blocco "elementi globali" (sezione 1), che
       la scrive per tutto il sito. Il motivo vale anche per l'admin: a
       10.5px il badge è sotto il minimo leggibile, e nelle schede è spesso
       l'unica cosa che distingue una riga dall'altra (Attivo / Offline /
       In prova / Admin). */

    /* Le due celle di testo lungo (Messaggio in Avvisa, Motivo in
       Manutenzione) hanno il max-width scritto nell'attributo style dalle
       rispettive render in js/admin.js: da lì batte qualunque regola del
       foglio, e nella scheda le lascerebbe più strette del bordo, con un
       buco a destra. !important è l'unico modo di arrivarci senza spostare
       quegli stili in una classe, cosa che cambierebbe l'aspetto desktop. */
    #announcements-table td,
    #maintenance-table td{ max-width: none !important; }

    /* ---- Tabelle Azioni ed Eventi (dashboard cliente) ----
       Hanno regole proprie legate all'id, che per specificità battono tutto
       quello che c'è qui sopra: vanno annullate una per una o la scheda si
       ritrova le larghezze fisse e i divisori verticali del desktop. */
    #ae-actions-card .admin-table td,
    #ae-events-card .admin-table td{ padding: 10px 14px; font-size: 14px; }
    #ae-actions-table td, #ae-events-table td{ border-right: none; }
    #ae-actions-table td:nth-child(3),
    #ae-actions-table td:nth-child(4),
    #ae-actions-table td:nth-child(5){ width: auto; text-align: left; }

    /* Spunta di selezione e pulsanti della riga: gli unici due che NON vanno
       a tutta larghezza, così formano insieme la barra in cima alla scheda.
       flex-basis 0 (non auto) sulla cella dei pulsanti: con "auto" chiederebbe
       la propria larghezza naturale — cinque bottoni da 44 negli Eventi — e
       bastava un pixel di troppo per mandarla a capo, lasciando la spunta da
       sola su una riga con un mozzicone di bordo sotto. Partendo da zero si
       prende quello che avanza e, se davvero non basta, sono i bottoni a
       andare a capo dentro di lei. */
    .admin-table td.ae-col-check{ flex: 0 0 auto; width: auto; align-items: center; }
    .admin-table td.ae-col-icon{ flex: 1 1 0; min-width: 0; width: auto; align-items: center; }
    /* Imbottitura stretta per le due celle-comando: senza il selettore con
       l'id perderebbero contro il "padding: 10px 14px" qui sopra, che l'id ce
       l'ha, e i 28px sprecati ai lati della spunta mandavano a capo l'ultimo
       dei cinque pulsanti degli Eventi. */
    #ae-actions-card .admin-table td.ae-col-check,
    #ae-events-card .admin-table td.ae-col-check{ padding: 8px 0 8px 8px; }
    #ae-actions-card .admin-table td.ae-col-icon,
    #ae-events-card .admin-table td.ae-col-icon{ padding: 8px 8px 8px 2px; }
    .ae-action-row-tools{ flex-wrap: wrap; justify-content: flex-end; gap: 4px; }
    #ae-actions-card .ae-action-tool-btn,
    #ae-events-card .ae-action-tool-btn,
    .ae-action-tool-btn{ width: 44px; height: 44px; font-size: 15px; }

    /* La spunta di riga e l'interruttore "Attivo" restano grandi come sono
       (18px e 36x20: sono <input> con appearance:none, bordo e sfondo SONO il
       controllo, e allargarli col padding li deformerebbe). A fare da
       bersaglio da 44x44 ci pensa il <label class="ae-cell-hit"> che li
       avvolge, aggiunto nei template di js/azioni-eventi-panel.js: cliccare
       un label che avvolge un checkbox lo attiva, quindi il bersaglio è vero
       anche fuori dai diciotto pixel disegnati. */
    .ae-cell-hit{
      display: inline-flex; align-items: center; justify-content: center;
      min-width: 44px; min-height: 44px; cursor: pointer;
    }

    /* ---- Filtri, ricerche e sfogliapagine ---- */
    /* Sotto i 16px iOS Safari zooma da solo appena si tocca il campo, e da
       zoomato la pagina resta larga il doppio finché non si pizzica per
       tornare indietro. Vale per il campo di ricerca degli utenti (era 14px)
       e per quelli di Azioni/Eventi (13 e 15px). */
    .admin-search input{ font-size: 16px; padding: 13px 48px 13px 42px; }
    .admin-search{ margin-bottom: 12px; }
    .admin-search-clear{ width: 44px; height: 44px; right: 2px; font-size: 20px; }
    .admin-search-count{ font-size: 13px; }
    /* "Nuova azione" ed "Elimina azioni" uno sotto l'altro e a tutta
       larghezza: stretti al proprio testo, sul telefono restano due
       francobolli in cima a una pila di schede. */
    .ae-actions-toolbar{ gap: 10px; }
    .ae-actions-toolbar > .btn{ width: 100%; justify-content: center; }

    /* Frecce di pagina: 30x30 è un bersaglio da mouse. Centrate invece che
       allineate a destra — sotto una pila di schede il bordo destro non è
       più un punto di riferimento. */
    .table-pager{ justify-content: center; gap: 14px; }
    .table-pager-btn, .ae-pagination-btn{ width: 44px; height: 44px; }
    .table-pager-state{ font-size: 13px; }
    .ae-pagination-label{ font-size: 13px; }

    /* ---- Statistiche in cima ai pannelli ---- */
    /* Sei riquadri uno sotto l'altro (tab Business) volevano mezzo metro di
       scorrimento prima di arrivare alla tabella: due per riga, con numeri
       proporzionati allo spazio che resta. */
    .admin-stats{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 22px; }
    .admin-stat{ padding: 14px; border-radius: 10px; }
    .admin-stat-num{ font-size: 22px; }

    /* ---- Form dei pannelli admin ---- */
    /* Il pulsante di invio in fondo a un form a campi impilati: mezza
       larghezza a caso accanto all'ultimo campo si legge come se
       appartenesse a quel campo. A tutta riga è chiaramente la conclusione. */
    .dash-panel[data-panel="trial"] .sub-card .btn,
    .dash-panel[data-panel="referral"] .sub-card .btn,
    .dash-panel[data-panel="avvisa"] .sub-card .btn,
    .dash-panel[data-panel="manutenzione"] .sub-card .btn{ width: 100%; justify-content: center; }

    /* Le due textarea (Messaggio in Avvisa, Motivo in Manutenzione) hanno il
       font-size nell'attributo style dentro it/admin.html: stesso discorso
       del max-width qui sopra, !important è l'unica strada che non tocca il
       desktop. Sotto i 16px il campo fa zoomare iOS. */
    #announcement-form-body,
    #maintenance-form-reason{ font-size: 16px !important; }

    /* Le tendine "Cosa fermare" e "Visibile a" sono alte 33px: sono l'unico
       modo di compilare quel form e vanno prese col pollice. Ambito ristretto
       al pannello Manutenzione perché .mc-action-* è condiviso con i pannelli
       Minecraft/Roblox/TTS della dashboard cliente, che hanno una densità
       loro e non vanno toccati da qui. */
    .dash-panel[data-panel="manutenzione"] .mc-action-trigger{ min-height: 44px; font-size: 14px; padding: 10px 12px; }
    .dash-panel[data-panel="manutenzione"] .mc-action-option{
      display: flex; align-items: center; min-height: 44px; font-size: 14px; padding: 10px 12px;
    }
    .dash-panel[data-panel="manutenzione"] .mc-action-group-label{ font-size: 11px; }
    .dash-panel[data-panel="manutenzione"] .mc-action-trigger-caret{ font-size: 12px; }
    .dash-panel[data-panel="manutenzione"] .search-combo-search{ font-size: 16px; padding: 11px 12px; }
    .dash-panel[data-panel="manutenzione"] .mc-action-menu{ max-height: 60vh; }

    /* Il link a status.tikforge.net dentro il testo di apertura: è alto quanto
       la riga di testo, cioè diciannove pixel. Il padding verticale su un
       elemento inline allarga l'area cliccabile senza spostare di un pixel il
       testo intorno (deborda dalla riga invece di allargarla). */
    .dash-panel[data-panel="manutenzione"] > .dash-sub a{ padding: 13px 0; }

    /* Scheda utente: quaranta campi in riquadri da 85px l'uno (una riga di
       etichetta e una di valore, con 34px di imbottitura intorno) facevano
       tre metri e mezzo di scorrimento per leggere un'anagrafica. Stessa
       griglia a una colonna, ma riquadri bassi: si dimezza la pagina senza
       togliere niente. Ambito .admin-user-card perché .profile-grid è la
       stessa griglia di "Info account" e dei piani nel tab Pagamenti della
       dashboard cliente, che hanno pochi campi e stanno bene larghi. */
    .admin-user-card .profile-grid{ grid-template-columns: 1fr; gap: 8px; }
    .admin-user-card .profile-item{ padding: 10px 12px; gap: 2px; border-radius: 10px; }
    .admin-user-card .profile-value{ font-size: 14.5px; }
    .admin-user-card{ margin-top: 16px; }

    /* Riquadri dei form e delle sezioni della scheda utente: 24px di
       imbottitura per lato su uno schermo da 360 sono un settimo della
       larghezza. Elencati uno per uno invece di toccare .sub-card in
       generale: la stessa classe la usano le card della dashboard cliente. */
    .dash-panel[data-panel="trial"] .sub-card,
    .dash-panel[data-panel="referral"] .sub-card,
    .dash-panel[data-panel="avvisa"] .sub-card,
    .dash-panel[data-panel="manutenzione"] .sub-card,
    .admin-user-card{ padding: 18px 16px; }

    /* "Torna agli utenti" è un pulsante di solo testo alto 19px, ed è l'unica
       via d'uscita dalla scheda di un utente. L'area cliccabile cresce con il
       padding; il margine negativo la riporta a filo del titolo sotto, così
       visivamente non si sposta niente. */
    .admin-back-btn{ min-height: 44px; padding: 10px 12px; margin-left: -12px; margin-bottom: 10px; }
  }

  /* ==========================================================================
     TELEFONO STRETTO (sotto i 380px)
     ==========================================================================
     Il taglio è basso apposta: fino a 390 l'etichetta a colonna sta comoda e
     tiene le schede corte, e con dodici account in pagina la differenza è
     mezzo metro di scorrimento. Sotto, al valore resterebbero centodieci
     pixel e ci finirebbe dentro poco più di una parola per riga. */
  @media (max-width: 380px){
    /* Etichetta sopra il valore, che si prende tutta la larghezza della
       scheda. Le schede si allungano, ma un'email ci sta in una riga o due
       invece che in quattro. */
    .admin-table td{ flex-direction: column; gap: 3px; padding: 9px 13px; }
    .admin-table td[data-label]::before{ flex: 0 0 auto; max-width: none; }

    /* Le celle-comando delle tabelle Azioni/Eventi restano in riga: dentro
       non c'è nessuna etichetta da mandare a capo. Qui però prendono una riga
       per uno invece di dividersene una: la spunta col suo bersaglio da 44 più
       i cinque pulsanti degli Eventi fanno 264 pixel, più di quanti ne abbia
       una scheda a 360, e l'ultimo pulsante cadeva da solo sotto gli altri
       quattro. Con una riga a testa i cinque ci stanno in fila, allineati a
       sinistra sotto la spunta invece che spinti al bordo opposto. */
    .admin-table td.ae-col-check,
    .admin-table td.ae-col-icon{ flex-direction: row; flex: 1 1 100%; }
    .ae-action-row-tools{ justify-content: flex-start; }

    /* Due statistiche per riga a 320px vorrebbero dire numeri a 22px in
       colonne da 140: sotto questa soglia una per riga, ma bassa e compatta,
       non il riquadro alto del desktop. */
    .admin-stats{ grid-template-columns: 1fr; gap: 8px; }
    .admin-stat{ display: flex; align-items: baseline; gap: 10px; padding: 12px 14px; }
    .admin-stat-num{ font-size: 20px; }
    .admin-stat-label{ margin-top: 0; }

  }

  /* ==========================================================================
     WIKI SU TELEFONO
     wiki/{it,en,es,fr}/index.html + wiki/{it,en,es,fr}/minecraft/tntcube.html
     Le pagine wiki riusano il guscio .legal delle pagine legali ma non sono
     body.page-site: da qui in avanti hanno un aggancio tutto loro,
     body.page-wiki, aggiunto nell'HTML insieme a <span class="logo-word">,
     al data-short della CTA, agli id delle sezioni e all'indice a scomparsa.
     Tutto quello che segue vive dentro una @media: il desktop non cambia.
     ========================================================================== */

  @media (max-width: 760px){

    /* ---------- Intestazione ----------
       Era la parte messa peggio: marchio, tendina lingua e "Torna alla
       Dashboard" tutti su una riga da 28px di margine, con la CTA spezzata
       su tre righe e l'header che sporgeva di 5px oltre il viewport a 320px
       (scrollWidth 325). Qui si recupera spazio dai margini e dalle
       spaziature, e i bersagli salgono a 44px allungando il riempimento
       verticale invece di ingrandire logo e bandierine. */
    body.page-wiki header nav{
      padding: 9px 16px;
      /* La barra e' incollata in cima e larga tutto: in orizzontale su
         iPhone il notch mangerebbe il marchio da un lato e la CTA dall'altro. */
      padding-left: max(16px, env(safe-area-inset-left));
      padding-right: max(16px, env(safe-area-inset-right));
      gap: 10px;
    }
    body.page-wiki header .logo{
      min-width: 0; min-height: 44px; gap: 8px; font-size: 18px;
    }
    body.page-wiki header .logo-mark{ height: 28px; }
    body.page-wiki .nav-right{ gap: 8px; }

    body.page-wiki .lang-dropdown-btn{ min-height: 44px; padding: 7px 10px; }
    body.page-wiki .lang-dropdown-list{ min-width: 168px; }
    body.page-wiki .lang-dropdown-list a{ min-height: 44px; padding: 10px 12px; font-size: 15px; }

    /* inline-flex + min-height: la pillola diventa un bersaglio pieno da
       44px senza gonfiare il testo. nowrap perche' spezzata su piu' righe
       era illeggibile e alzava la barra di 40px. */
    body.page-wiki .nav-cta{
      display: inline-flex; align-items: center; justify-content: center;
      min-height: 44px; padding: 8px 14px; font-size: 13.5px; white-space: nowrap;
    }

    /* L'hamburger arriva da js/script.js, aggiunto ora anche alle pagine
       wiki: prima "Giochi" e "Minecraft" erano nel DOM ma nascosti dalla
       regola condivisa .nav-links sotto i 760px, e senza pulsante non li
       riapriva nessuno. Il pannello che si apre e' quello di sempre, qui
       diventano solo righe da toccare. */
    body.page-wiki .nav-toggle{ width: 44px; height: 44px; font-size: 18px; }
    body.page-wiki .nav-links{
      padding: 6px 16px 10px;
      padding-left: max(16px, env(safe-area-inset-left));
      padding-right: max(16px, env(safe-area-inset-right));
      gap: 0;
    }
    body.page-wiki .nav-links a{
      display: flex; align-items: center; width: 100%;
      min-height: 44px; font-size: 15px;
    }

    /* ---------- Corpo della guida ---------- */
    /* 64px di aria sopra il titolo sono un terzo di schermo buttato: il
       telefono ha gia' la barra incollata in cima a fare da stacco. */
    body.page-wiki .legal{ padding: 28px 0 56px; }
    body.page-wiki .legal h1{ font-size: 28px; line-height: 1.16; }
    /* scroll-margin serve ai link dell'indice: senza, l'header sticky
       (44px + margini) copre il titolo su cui si e' appena saltati. */
    body.page-wiki .legal h2{ font-size: 19px; margin: 30px 0 10px; scroll-margin-top: 74px; }

    /* I <code> del wiki sono comandi interi (/bedrock prison_time_type
       <bossbar|titolo>) o identificatori senza spazi (tikforge.tntcube.use):
       il piu' lungo da solo usciva dal margine destro a 390px. "anywhere"
       e non "break-word" perche' deve contare anche nel calcolo della
       larghezza minima, altrimenti la cella della tabella non si stringe. */
    body.page-wiki .legal code{ overflow-wrap: anywhere; }

    /* Link dentro il testo: alti quanto la riga, 20px, impossibili da
       centrare col pollice. Il riempimento verticale su un elemento inline
       allarga l'area toccabile senza spostare di un pixel il testo attorno.
       La sottolineatura serve perche' su un telefono non c'e' l'hover a
       dire che quella parola e' un link. */
    body.page-wiki .legal p > a,
    body.page-wiki .legal li > a{
      padding: 12px 0; text-decoration: underline; text-underline-offset: 3px;
    }

    /* ---------- Indice della guida (solo telefono) ----------
       Sta nell'HTML con l'attributo hidden: cosi' su desktop resta
       invisibile senza bisogno di una regola fuori dalla @media, ed e' qui
       che lo si riapre. La guida in verticale supera i 5000px e con le
       tabelle impilate in schede cresce ancora: senza un salto rapido si
       arriva ai permessi solo scorrendo. */
    /* I selettori dell'indice ripetono .legal apposta: le voci sono <a>
       dentro un <li> dentro .legal, quindi senza quella classe in piu' se
       le prenderebbe la regola dei link nel testo qui sopra (piu'
       specifica) e le righe perderebbero riempimento laterale. */
    body.page-wiki .legal .wiki-toc[hidden]{ display: block; }
    body.page-wiki .legal .wiki-toc{
      margin: 0 0 26px; overflow: hidden;
      background: var(--bg-panel); border: 1px solid var(--line); border-radius: 12px;
    }
    body.page-wiki .legal .wiki-toc > summary{
      display: flex; align-items: center; justify-content: space-between; gap: 10px;
      min-height: 44px; padding: 10px 16px; cursor: pointer;
      font-family:'Baloo 2'; font-weight: 700; font-size: 15px; color: var(--ink);
    }
    body.page-wiki .legal .wiki-toc > summary::after{
      content: '▾'; font-size: 11px; opacity: .7; transition: transform .2s ease;
    }
    body.page-wiki .legal .wiki-toc[open] > summary::after{ transform: rotate(180deg); }
    body.page-wiki .legal .wiki-toc ol{
      counter-reset: wiki-toc; list-style: none;
      margin: 0; padding: 4px 0 6px; border-top: 1px solid var(--line);
    }
    body.page-wiki .legal .wiki-toc li{ counter-increment: wiki-toc; margin: 0; }
    body.page-wiki .legal .wiki-toc a{
      display: flex; align-items: center; gap: 10px;
      min-height: 44px; padding: 8px 16px;
      color: var(--muted); font-size: 14.5px; line-height: 1.3; text-decoration: none;
    }
    /* Il numero e' il riferimento rapido ("sono alla 3 di 7") e tiene le
       voci allineate anche quando il titolo va a capo. */
    body.page-wiki .legal .wiki-toc a::before{
      content: counter(wiki-toc);
      flex: none; width: 18px;
      font-family:'JetBrains Mono'; font-size: 12px; color: var(--blue); text-align: right;
    }

    /* ---------- Tabelle dei comandi ----------
       .cookie-table nasce con min-width:560px, pensata per le due colonne
       corte delle pagine legali. Qui sono 34 righe di comandi: a 390px la
       colonna "Cosa fa" finiva tagliata a meta' parola ("Collega il server
       al tuo acco...") e la guida era inutilizzabile. L'impilamento in
       schede con data-label arriva dalla regola condivisa di .cookie-table
       (ogni <td> del wiki ha ora il suo data-label tradotto); questa riga
       toglie soltanto il pavimento dei 560px, che e' cio' che impedisce
       comunque alla tabella di stringersi. */
    body.page-wiki .cookie-table{ min-width: 0; }
    /* Stessa rete: se le celle restano celle, la colonna deve poter
       scendere sotto la parola piu' lunga, altrimenti la tabella pretende
       377px in un contenitore da 284 e torna a scorrere. A schede impilate
       le celle sono blocchi a tutta larghezza e questa riga non ha effetto. */
    body.page-wiki .cookie-table th,
    body.page-wiki .cookie-table td{ overflow-wrap: anywhere; }
    /* 11.5px erano sotto la soglia leggibile su un telefono. */
    body.page-wiki .cookie-table th{ font-size: 12px; }
    body.page-wiki .table-scroll{ margin: 14px 0; }
    /* Il riempimento delle celle non si tocca da qui, nemmeno sugli schermi
       piu' stretti: a schede impilate la spaziatura interna e' della regola
       condivisa, e sovrascriverla darebbe un doppio rientro all'etichetta. */

    /* ---------- Schermata di scelta della guida (le index del wiki) ---------- */
    body.page-wiki .wiki-soon{ font-size: 14px; }
  }

  @media (max-width: 560px){
    /* Sotto questa soglia "← Torna alla Dashboard" non entra piu' nella
       riga insieme a marchio, hamburger e tendina lingua: resta la forma
       breve, che sta nell'HTML come data-short ed e' quindi gia' tradotta
       lingua per lingua (niente testo dentro il CSS). Il selettore chiede
       [data-short]: se domani nasce una pagina wiki senza quell'attributo
       si tiene la scritta lunga invece di ritrovarsi una pillola vuota. */
    body.page-wiki .nav-cta[data-short] .nav-cta-label{ display: none; }
    body.page-wiki .nav-cta[data-short]::after{ content: attr(data-short); }

    /* Il margine largo del .wrap costava 20px di larghezza utile proprio
       dove serviva: nelle celle con i comandi. */
    body.page-wiki .legal .wrap{
      padding-left: max(18px, env(safe-area-inset-left));
      padding-right: max(18px, env(safe-area-inset-right));
    }

    /* Una tessera per riga: la griglia a colonne da 280px lasciava un
       vuoto a destra invece di usare tutto lo schermo. */
    body.page-wiki .wiki-guides{ grid-template-columns: 1fr; gap: 14px; }
  }

  @media (max-width: 420px){
    /* Il titolo a 28px prendeva tre righe piene su un iPhone SE. */
    body.page-wiki .legal h1{ font-size: 25px; }
  }

  @media (max-width: 380px){
    /* Ultimo taglio prima di riaprire lo scroll orizzontale: resta il
       simbolo, che e' comunque il link alla home. La parola "TikForge"
       vale 80px e a 360px sono esattamente quelli che mancano. */
    body.page-wiki header .logo-word{ display: none; }
    body.page-wiki header .logo{ min-width: 44px; justify-content: center; }
    body.page-wiki .nav-cta{ padding: 8px 12px; }
  }

  /* ====================================================================
     TELEFONO — LA BARRA LATERALE DI DASHBOARD E ADMIN DIVENTA UN MENU
     A SCOMPARSA
     --------------------------------------------------------------------
     Riguarda solo le cinque pagine che hanno lo shell applicativo
     (it|en|es|fr/dashboard.html e it/admin.html): sono le uniche del sito
     con .app-shell/.app-sidebar, e portano tutte body.page-dashboard.

     COSA SOSTITUISCE. Sotto gli 860px la barra laterale non diventava una
     colonna troppo alta — quello era già stato risolto — ma una striscia
     orizzontale sopra il contenuto, con le voci in fila e lo scorrimento
     laterale (.app-shell flex-direction:column, .app-sidebar position:
     static + border-bottom, .dash-nav flex-direction:row + overflow-x:auto,
     .app-sidebar-footer in riga). Con dodici voci nella dashboard e dieci
     nell'admin quella striscia non è mai stata usabile: misurata su uno
     schermo da 390px l'ultima voce della dashboard cadeva a 511px dal bordo
     sinistro e quella dell'admin a 1177px, cioè fuori dallo schermo, senza
     nessun indizio visivo che ci fosse altro da scorrere — chi apriva la
     dashboard dal telefono semplicemente non sapeva che Overlay, TTS o
     Impostazioni esistessero. E la striscia si mangiava comunque la prima
     schermata prima di arrivare al contenuto.

     Le regole vecchie NON sono state cancellate da css/styles.css: sono
     riscritte qui dentro, nella stessa media query, così il file storico
     resta leggibile e questa sostituzione è tutta in un posto solo.
     ==================================================================== */

  @media (max-width: 860px){

    /* ---------- IL PANNELLO ----------
       Fissato al bordo sinistro e alto quanto lo schermo: fuori campo di
       default, entra scivolando quando si preme l'hamburger. Non è largo
       quanto lo schermo di proposito — la striscia di pagina che resta
       visibile a destra è ciò che fa capire che è un pannello temporaneo
       sopra la dashboard e non una schermata nuova in cui si è finiti. */
    body.page-dashboard .app-sidebar{
      position: fixed; z-index: 200;
      top: 0; left: 0; bottom: 0; height: auto;
      width: min(304px, 84vw);
      /* La striscia orizzontale si separava dal contenuto con un bordo
         sotto; il pannello ha il contenuto a destra, quindi il bordo (e
         l'ombra che lo stacca dal fondo) vanno a destra. */
      border-right: 1px solid var(--line-2); border-bottom: none;
      box-shadow: 16px 0 48px rgba(0,0,0,0.6);
      background: var(--panel);
      /* Il pannello tocca i bordi fisici dello schermo: in orizzontale su
         un iPhone col notch il lato sinistro finisce sotto la tacca, e in
         verticale il fondo finisce sotto la barra gesti. Le safe area
         valgono 0 sui dispositivi che non ne hanno, quindi il calc non
         cambia niente altrove. */
      padding: 16px 14px calc(18px + env(safe-area-inset-bottom))
               calc(14px + env(safe-area-inset-left));
      overflow-y: auto; overscroll-behavior: contain;
      -webkit-overflow-scrolling: touch;
      transform: translateX(-100%);
      /* visibility, non solo transform: un pannello soltanto traslato resta
         nel flusso del focus e i lettori di schermo lo leggono lo stesso.
         Il ritardo sulla visibility serve perché la chiusura si veda: senza,
         sparirebbe di colpo invece di scivolare via. All'apertura il ritardo
         non c'è (vedi la regola dello stato aperto), altrimenti il pannello
         entrerebbe invisibile. */
      visibility: hidden;
      transition: transform .26s cubic-bezier(.4, 0, .2, 1), visibility 0s linear .26s;
    }
    body.page-dashboard.is-drawer-open .app-sidebar{
      transform: none; visibility: visible;
      transition: transform .26s cubic-bezier(.4, 0, .2, 1), visibility 0s;
    }

    /* ---------- LO SFONDO SCURO ----------
       È uno pseudo-elemento di .app-shell invece di un <div> nuovo, e non
       per risparmiare markup: un elemento vero avrebbe avuto bisogno di un
       display:none fuori da questa media query per non comparire sul
       desktop, cioè esattamente la regola desktop che qui non si scrive.
       Il click ci arriva lo stesso: il bersaglio dell'evento di uno
       pseudo-elemento è l'elemento che lo genera, quindi js/dash-drawer.js
       ascolta su .app-shell e chiude quando il click è sullo shell stesso. */
    body.page-dashboard .app-shell::before{
      content: ''; position: fixed; inset: 0; z-index: 190;
      background: rgba(0, 0, 0, 0.62);
      opacity: 0; pointer-events: none;
      transition: opacity .26s ease;
    }
    body.page-dashboard.is-drawer-open .app-shell::before{
      opacity: 1; pointer-events: auto;
    }

    /* La pagina sotto non deve scorrere mentre il menu è aperto: senza
       questo, arrivati in fondo al pannello il dito continua a trascinare il
       contenuto dietro, e alla chiusura ci si ritrova in un punto diverso da
       dove si era. Sono due regole separate e non un selettore solo: se il
       browser non conosce :has scarta la prima e la seconda vale lo stesso.
       (Il pannello si ferma da sé grazie a overscroll-behavior:contain.) */
    html:has(body.page-dashboard.is-drawer-open){ overflow: hidden; }
    body.page-dashboard.is-drawer-open{ overflow: hidden; }

    /* ---------- LE VOCI TORNANO UNA COLONNA ----------
       Dentro un pannello alto quanto lo schermo le dodici voci si vedono
       tutte insieme senza toccare niente (misurate: l'ultima chiude a 687px
       su un iPhone da 844), e su schermi più corti quelle che avanzano si
       raggiungono scorrendo IN VERTICALE — il gesto che su un menu si prova
       per istinto, al contrario dello scorrimento laterale di prima. */
    body.page-dashboard .dash-nav{
      flex-direction: column; flex: 1 1 auto;
      overflow-x: visible; gap: 3px; margin: 0; padding: 0;
    }
    /* 46px di altezza minima: la voce diventa un bersaglio largo quanto il
       pannello, impossibile da sbagliare col pollice. 15px di testo perché
       una voce di menu su cui si deve prendere la mira si legge di
       sfuggita, non ci si mette a fuoco sopra. */
    body.page-dashboard .dash-nav-btn{
      flex-shrink: 0; white-space: normal;
      min-height: 46px; padding: 11px 12px; font-size: 15px;
    }
    /* L'indicatore della voce attiva era spento sul telefono perché nella
       striscia orizzontale sarebbe finito addosso alla voce accanto. Nel
       pannello è il contrario: è la cosa che risponde a "dove sono?" nel
       momento in cui si apre il menu, quindi torna. left:-14px lo porta a
       filo del bordo del pannello, che ha 14px di margine interno. */
    body.page-dashboard .dash-nav-btn.active::before{
      display: block; left: -14px;
    }

    /* ---------- INTESTAZIONE DEL PANNELLO ----------
       Il marchio si sposta a sinistra (sul desktop è centrato nella
       colonna) per lasciare l'angolo destro al pulsante di chiusura, e il
       margine destro tiene il testo lontano da quel pulsante. */
    body.page-dashboard .app-sidebar-brand{
      justify-content: flex-start; gap: 10px; min-height: 44px;
      padding: 4px 50px 14px 4px; margin-bottom: 12px;
    }

    /* ---------- FONDO DEL PANNELLO ----------
       Nella striscia orizzontale scheda utente, Discord ed Esci stavano in
       riga per stare in poco spazio; nella colonna tornano impilati e larghi
       tutta la colonna, con l'altezza minima che li rende premibili. */
    body.page-dashboard .dash-user{
      order: 0; flex: 0 0 auto; min-width: 0;
    }
    body.page-dashboard .app-sidebar-footer{
      flex-direction: column; flex-wrap: nowrap; align-items: stretch;
      margin-top: 16px; padding-top: 14px; gap: 10px;
    }
    body.page-dashboard .app-discord-btn,
    body.page-dashboard .app-sidebar-footer .dash-logout{
      order: 0; flex: 0 0 auto; min-width: 0; min-height: 46px;
    }
    /* Il badge "Area admin" nel fondo della barra di admin.html: a 10.5px
       era la scritta più piccola della pagina. */
    body.page-dashboard .app-sidebar-footer .badge-admin{
      font-size: 12px; min-height: 30px;
    }

    /* ---------- TESTINE MINUSCOLE DENTRO IL PANNELLO ----------
       Nella colonna da 248px del desktop questi 11/11.5px sono una scelta
       di densità; su un telefono, con il pannello a tutta altezza e lo
       spazio che avanza, sono solo testo che non si legge. Il tetto di
       150px sull'email era lì per non sfondare la colonna stretta: il
       pannello è più largo e la troncatura con i puntini resta comunque. */
    body.page-dashboard .dash-user-email{ font-size: 12.5px; max-width: none; }
    body.page-dashboard .dash-sysbox-sub{ font-size: 12px; }
    body.page-dashboard .dash-sysrow{ font-size: 12.5px; }
    body.page-dashboard .dash-sysbox-link{
      font-size: 13px; min-height: 44px; padding-bottom: 6px;
    }

    /* ---------- HAMBURGER ----------
       Nel markup nasce spento con l'attributo hidden (nella dashboard sul
       pulsante, nell'admin sulla barra che lo contiene) e lo riaccende questa
       regola. È il modo di aggiungere un comando che esiste solo sul telefono
       senza scrivere per lui una regola fuori da questa media query: sopra gli
       860px non c'è nessuna dichiarazione che lo riguardi e resta spento dal
       foglio di stile del browser. Il display dichiarato qui vince
       sull'attributo perché le regole d'autore battono quelle del browser, a
       prescindere dalla specificità. */
    body.page-dashboard .app-drawer-toggle{
      display: flex; align-items: center; justify-content: center;
      flex: 0 0 auto; width: 44px; height: 44px; padding: 0;
      border: 1px solid var(--line); border-radius: 11px;
      background: rgba(206, 186, 255, 0.04); color: var(--ink);
      cursor: pointer; font-family: inherit;
      transition: border-color .2s ease, background .2s ease;
    }
    body.page-dashboard .app-drawer-toggle:hover{
      border-color: rgba(168, 85, 247, 0.45); background: rgba(139, 92, 246, 0.1);
    }
    body.page-dashboard .app-drawer-toggle svg{ width: 21px; height: 21px; }
    /* Nella barra superiore della dashboard va per primo e non deve
       schiacciarsi: è l'unico modo di raggiungere le altre undici sezioni. */
    body.page-dashboard .dash-topbar .app-drawer-toggle{ order: -1; }

    /* ---------- BARRA DEL TELEFONO DELL'ADMIN ----------
       admin.html non ha la barra superiore della dashboard (il suo unico
       Esci sta nel fondo della barra laterale), quindi senza questa
       striscia l'hamburger non avrebbe dove stare. Resta appiccicata in
       alto perché il titolo <h1> del pannello scorre via subito e da metà
       di una tabella lunga non si saprebbe più né dove si è né come tornare
       al menu. Anche lei nasce con hidden nel markup. */
    body.page-dashboard .app-drawer-bar{
      display: flex; align-items: center; gap: 10px;
      position: sticky; top: 0; z-index: 30;
      padding: 10px max(12px, env(safe-area-inset-right))
               10px max(12px, env(safe-area-inset-left));
      background: rgba(8, 5, 14, 0.9); backdrop-filter: blur(16px);
      border-bottom: 1px solid var(--line);
    }
    body.page-dashboard .app-drawer-current{
      min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      font-family: 'Baloo 2', sans-serif; font-size: 16px; font-weight: 700;
      color: var(--ink);
    }
    /* Il padding di .app-main (44px 48px, o 28px 20px sotto i 600) è pensato
       per il contenuto: applicato anche alla barra qui sopra la staccherebbe
       dai bordi e la lascerebbe fluttuare invece di sembrare ancorata in
       alto. Lo spazio attorno al contenuto lo mette già .app-main-wrap, che
       a queste larghezze ha il suo. Il :has esclude la dashboard, che una
       barra superiore ce l'ha davvero e ha già padding:0 per lo stesso
       motivo. */
    body.page-dashboard .app-main:not(:has(> .dash-topbar)){ padding: 0; }

    /* ---------- CHIUSURA DAL PANNELLO ----------
       Serve un modo di chiudere visibile da dentro: aperto, il pannello
       copre l'hamburger che l'ha aperto. Sta in alto a destra, cioè dal
       lato del pollice e sopra il velo scuro, e per un utente da tastiera è
       il primo elemento che riceve il fuoco all'apertura. */
    body.page-dashboard .app-drawer-close{
      display: inline-flex; align-items: center; justify-content: center;
      position: absolute; top: 14px; right: 10px;
      width: 44px; height: 44px; padding: 0;
      border: 1px solid var(--line); border-radius: 11px;
      background: rgba(206, 186, 255, 0.04); color: var(--ink);
      cursor: pointer; font-family: inherit;
      transition: border-color .2s ease, background .2s ease;
    }
    body.page-dashboard .app-drawer-close:hover{
      border-color: rgba(168, 85, 247, 0.45); background: rgba(139, 92, 246, 0.1);
    }
    body.page-dashboard .app-drawer-close svg{ width: 19px; height: 19px; }
  }

  /* Telefono girato in orizzontale: lo schermo è alto 375px e l'intestazione
     del pannello (marchio + scheda utente) da sola se ne prende i primi 140.
     Le voci restano tutte e restano premibili — 44px sono il minimo, non un
     obiettivo — ma stringendo l'intestazione se ne vedono due in più prima di
     dover scorrere. È una media query sull'ALTEZZA: le larghezze in uso nel
     progetto non c'entrano, qui il problema è quanto schermo c'è in verticale. */
  @media (max-width: 860px) and (max-height: 480px){
    body.page-dashboard .app-sidebar-brand{ padding: 2px 50px 10px 4px; margin-bottom: 8px; }
    body.page-dashboard .app-sidebar > .dash-user{ padding-bottom: 10px; margin-bottom: 8px; }
    body.page-dashboard .dash-avatar{ width: 34px; height: 34px; font-size: 15px; }
    body.page-dashboard .dash-nav-btn{ min-height: 44px; padding: 9px 12px; }
  }

  /* Il progetto spegne già le animazioni con la regola globale su * in cima
     al foglio, ma quella agisce solo sulla DURATA: il ritardo di 260ms sulla
     visibility del pannello resterebbe, e chi ha chiesto meno movimento si
     vedrebbe il menu sparire un quarto di secondo dopo averlo chiuso, come
     se il tocco non avesse funzionato. Qui la transizione si toglie tutta. */
  @media (max-width: 860px) and (prefers-reduced-motion: reduce){
    body.page-dashboard .app-sidebar,
    body.page-dashboard.is-drawer-open .app-sidebar,
    body.page-dashboard .app-shell::before{ transition: none; }
  }

  @media (max-width: 560px){
    /* A questa larghezza la barra superiore della dashboard manda la ricerca
       su una riga tutta sua (flex-basis:100%): con l'hamburger davanti quella
       riga resterebbe occupata da un solo pulsante da 44px e la barra
       crescerebbe di un piano intero, per giunta appiccicata in alto. Qui i
       due si dividono la prima riga — hamburger a sinistra, ricerca per tutto
       il resto — e i comandi restano sulla seconda come previsto. */
    body.page-dashboard .dash-topbar .app-drawer-toggle{ order: 1; }
    body.page-dashboard .dash-topbar .dash-search{ flex: 1 1 0; min-width: 0; }
  }

  /* ====================================================================
     TELEFONO — RIFINITURE DELLA REVISIONE
     --------------------------------------------------------------------
     Riletta a 320, 360, 390 e 414px una per una tutte e 96 le pagine, e
     pannello per pannello dashboard e admin: qui sotto c'è solo quello che
     i blocchi più sopra non avevano preso. Sta in fondo al foglio perché
     ognuna di queste regole ne corregge una mobile già scritta, e l'ordine
     è ciò che le fa vincere senza doverne gonfiare la specificità.
     ==================================================================== */

  @media (max-width: 860px){
    /* Le voci della tendina lingua nella barra della dashboard erano rimaste
       a 38px, mentre l'hamburger che le sta accanto ne misura 44. La tendina
       si apre in mezzo ai comandi della barra e prendere la bandiera
       sbagliata significa ricaricare la pagina in un'altra lingua. */
    body.page-dashboard .dash-topbar-lang .lang-dropdown-list a{ min-height: 44px; }
  }

  @media (max-width: 760px){
    /* Le briciole delle pagine gioco (Libreria › Minecraft › TntCube) erano
       ferme a 40px di altezza minima: quattro meno del bersaglio che tutto
       il resto del sito rispetta, e su tre link in fila separati da "›"
       quei quattro pixel sono la differenza fra prendere il link e prendere
       il separatore. Le più corte ("Roblox", "Library") restavano larghe 41:
       il padding allarga il rettangolo del tocco e il margine negativo lo
       restituisce al layout, così la fila di link e i separatori non si
       spostano di un pixel rispetto a prima. */
    body.page-site .crumbs a{ min-height: 44px; padding: 0 3px; margin: 0 -3px; }

    /* "Accedi" / "Log in" in fondo al modulo: alti 44 ma larghi 37-40, perché
       la parola è corta e il padding orizzontale di 4px non bastava. Sono già
       inline-flex centrati, quindi la larghezza minima non sposta il testo:
       gli mette solo aria intorno. */
    .auth-row .auth-link,
    .auth-footer .auth-link,
    .auth-actions-row .link-btn{ min-width: 44px; }

    /* "Guida completa" in coda a una risposta delle FAQ: con i 12px di
       padding del blocco globale arrivava a 43px per via dell'interlinea più
       stretta della risposta. Mancava un pixel, ma il bersaglio o è da 44 o
       non lo è. Padding su un elemento inline: allarga il rettangolo del
       tocco senza spostare di nulla la riga di testo che lo contiene. */
    body.page-site .faq-a .auth-link{ padding: 13px 0; }

    /* "pagamento unico" nella nota sotto i piani è un <a> senza classe
       dentro un paragrafo: nessuna delle regole per i link testuali lo
       pescava e restava alto quanto la riga, 17px. Padding di 14 e non 12 perché la
       nota è scritta a 13,5px: l'interlinea di partenza è più bassa. */
    body.page-site .plan-note a{ padding: 14px 0; }

    /* Campo "frase di prova" del TTS: il font-size sta nell'attributo style
       dentro i quattro dashboard.html, quindi la regola del blocco "Campi di
       testo: 16px e alti 44" non lo raggiunge. Come per le due textarea
       dell'admin, !important è l'unica strada che non richiede di mettere
       mano all'HTML — e sotto i 16px iOS Safari ingrandisce la pagina da solo
       appena si tocca il campo, senza più tornare indietro. */
    #tts-test-input{ font-size: 16px !important; }

    /* "Attiva TTS" si fermava a 41px di altezza; le "✕" che cancellano una
       scorciatoia da tastiera sono alte 44 ma larghe 32, strette come
       l'icona che contengono. */
    #tts-enable-btn{ min-height: 44px; }

    /* Link dentro il discorso nella dashboard, che il blocco dei bersagli
       tattili non elencava: "Guida ai comandi →" in fondo alla nota di
       installazione del plugin (36px) e "pagamento unico" nella nota sotto i
       piani (16px, e scritto ancora più fitto: servono 14 di padding).
       Stesso meccanismo del padding su inline usato nel sito pubblico. */
    body.page-dashboard .connections-sub .auth-link{ padding: 14px 0; }
    body.page-dashboard .sub-plans-foot a{ padding: 14px 0; }

    /* I due link del piè di pagina della dashboard stanno affiancati su una
       riga: "Privacy" da solo è largo 40px, e in orizzontale il minimo vale
       quanto in verticale. */
    body.page-dashboard .dash-footer a{ min-width: 44px; justify-content: center; }
  }
