:root {
    --bg: #020617;
    --surface: #0F172A;
    --surface-2: #17213A;
    --border: #253249;
    --text: #F1F5F9;
    --muted: #94A3B8;
    --blue: #2563EB;
    --blue-light: #3B82F6;
    --teal: #14B8A6;
    --danger: #E5536B;
    --danger-bg: #35131C;
    --danger-border: #572230;
    --radius: 16px;
    --amber: #F0A93B;
    --amber-bg: #3A2E12;
    --blue-bg: #13223F;
    --teal-bg: #0F2B35;
    --violet: #C4B5FD;
    --violet-bg: #241A45;
    --green: #4ADE80;
    --green-bg: #12321F;
    --pink: #F472B6;
    --pink-bg: #3A1626;
    --rose: #3B82F6; /* Ripetizione usa il blu, coerente col riferimento */
    --font-body: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --modal-overlay: rgba(2, 6, 23, .65);
  }
  html[data-theme="light"] {
    --bg: #F3F5FA;
    --surface: #FFFFFF;
    --surface-2: #F1F4FA;
    --border: #E1E6F0;
    --text: #0F172A;
    --muted: #64748B;
    --amber-bg: #FDF0D8;
    --blue-bg: #E3ECFD;
    --teal-bg: #DDF4F1;
    --danger: #DC2626;
    --danger-bg: #FCE7E9;
    --danger-border: #F5C4CC;
    --violet: #7C3AED;
    --violet-bg: #EDE7FC;
    --green: #16A34A;
    --green-bg: #DCFCE7;
    --pink: #DB2777;
    --pink-bg: #FCE7F3;
    --modal-overlay: rgba(15, 23, 42, .45);
  }
  html[data-theme="light"] body { background: var(--bg); }
  html[data-theme="light"] .splash-logo { box-shadow: 0 8px 30px rgba(59,130,246,.25); }
  html[data-theme="light"] input, html[data-theme="light"] select, html[data-theme="light"] textarea { background: var(--surface-2); color: var(--text); }
  * { box-sizing: border-box; }

  /* ===================== STATUS BAR BACKGROUND =====================
     Fascia fissa dietro a ora/batteria/wifi del telefono (safe-area-top).
     Indipendente da qualsiasi pagina/scroll dell'app: garantisce che
     nessun contenuto possa mai finire visivamente sotto la status bar,
     anche se in futuro manca un padding-top da qualche parte. Sempre
     sopra a tutto tranne lo splash screen iniziale. */
  #status-bar-bg {
    position: fixed; top: 0; left: 0; right: 0;
    height: 0px;
    background: transparent;
    z-index: 9998;
    pointer-events: none;
  }
  body.has-bottom-nav #status-bar-bg {
    height: max(env(safe-area-inset-top, 0px), 24px);
    /* Vetro smerigliato delicato: blur leggero (8px, contro i 14px
       originali) e sfondo semi-trasparente invece che opaco, senza
       border-bottom, per una transizione morbida col contenuto sotto
       invece di un taglio netto. */
    background: rgba(2, 6, 23, .55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  html[data-theme="light"] body.has-bottom-nav #status-bar-bg {
    background: rgba(243, 245, 250, .55);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  #bottom-safe-bg {
    position: fixed; bottom: 0; left: 0; right: 0;
    height: env(safe-area-inset-bottom, 0px);
    /* Prima era transparent finché JS non aggiungeva body.has-bottom-nav:
       al cold-start (app appena aperta / ripresa dal multitasking) questo
       lasciava per un istante il nero di sistema visibile sotto la safe
       area, prima che lo script facesse in tempo a girare. Partire già
       col colore giusto elimina il flash indipendentemente dal timing di JS. */
    background: var(--surface);
    z-index: 9998;
    pointer-events: none;
  }

  html, body {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
    /* Fix: al cold-start su iOS standalone (app appena aperta o ripresa dal
       multitasking) c'è un breve istante prima che JS aggiunga la classe
       body.has-bottom-nav, che è quella che colora #bottom-safe-bg.
       In quell'istante, senza questo background qui, sotto la safe-area
       si vedeva il nero reale del sistema/webview invece dello sfondo
       dell'app (bug visibile solo al cold-start, corretto da un reflow
       come lo swipe back — da qui il "si aggiusta con lo swipe"). Dando
       il colore già a html/body, quel gap sparisce anche a JS non ancora
       partito. */
    background: var(--bg);
  }
  body {
    margin: 0;
    font-family: var(--font-body);
    background: var(--bg);
    color: var(--text);
  }
  /* Il blocco della selezione testo è pensato per l'esperienza "app"
     (nativa iOS, PWA/TWA installata): lì il testo selezionabile con
     long-press rompeva la sensazione di app vera, facendo sembrare tutto
     un sito dentro un browser. Sul sito web aperto normalmente da
     browser (desktop o mobile, non installato) NON si applica: un sito
     pubblico deve restare selezionabile/copiabile come qualunque altro
     sito, comportamento diverso e distinto da quello dell'app installata.
     Le classi .is-native-ios-app e .has-bottom-nav vengono aggiunte solo
     quando siamo davvero dentro l'app nativa o in standalone (vedi
     core.js e componenti.js). Riabilitiamo comunque esplicitamente solo i
     contenitori di contenuto scritto dagli utenti (domande, risposte,
     messaggi, note) più sotto nel file, dove serve un comportamento
     "copia dedicato" invece della selezione nativa anche in app. */
  html.is-native-ios-app body,
  body.has-bottom-nav {
    -webkit-user-select: none;
    user-select: none;
  }

  .hidden { display: none !important; }
  h1, h2, h3 { margin-top: 0; font-weight: 800; color: var(--text); }
  p { color: var(--muted); }

  input, select, textarea {
    width: 100%;
    padding: 10px 12px;
    margin: 6px 0 14px;
    border: 1.5px solid var(--border);
    border-radius: 10px;
    font-size: 14px;
    font-family: inherit;
    background: var(--surface-2);
    color: var(--text);
  }
  input::placeholder, textarea::placeholder { color: #56637D; }
  input:focus, select:focus, textarea:focus { outline: none; border-color: var(--blue-light); }

  /* ===================== DROPDOWN CUSTOM (sostituisce i <select> nativi) =====================
     I <select> HTML nativi vengono disegnati dal sistema operativo (su
     Android/MIUI ecc. con uno stile scuro pieno, pallini radio, del tutto
     fuori dal nostro controllo via CSS) invece che nello stile dell'app.
     Il markup è: il <select> originale resta nel DOM ma nascosto
     (display:none) — continua a essere la "fonte di verità" per il
     valore, così tutto il codice esistente che legge/scrive .value o
     ascolta l'evento change non necessita di alcuna modifica. Sopra di
     esso, .custom-select-trigger mostra il testo dell'opzione scelta con
     lo stesso stile visivo di un input/select normale, e al click apre
     .custom-select-popover: un piccolo pannello ancorato appena sotto il
     trigger (non un modale a schermo intero), con le opzioni come righe
     cliccabili. Vedi initCustomSelect() in app.js. */
  .custom-select-wrap { position: relative; }
  .custom-select-wrap select { display: none; }
  .custom-select-trigger {
    width: 100%; padding: 10px 12px; margin: 6px 0 14px;
    border: 1.5px solid var(--border); border-radius: 10px;
    font-size: 14px; font-family: inherit;
    background: var(--surface-2); color: var(--text);
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    cursor: pointer; user-select: none;
  }
  .custom-select-trigger.aperto { border-color: var(--blue-light); }
  .custom-select-trigger.disabilitato { opacity: .55; cursor: not-allowed; }
  .custom-select-trigger span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .custom-select-trigger svg { flex: 0 0 auto; width: 16px; height: 16px; color: var(--muted); transition: transform .15s ease; }
  .custom-select-trigger.aperto svg { transform: rotate(180deg); }
  .custom-select-popover {
    position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% - 10px);
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0,0,0,.28);
    max-height: 260px; overflow-y: auto;
    padding: 6px; margin: 0;
  }
  .custom-select-popover.hidden { display: none; }
  .custom-select-opzione {
    padding: 10px 12px; border-radius: 8px; font-size: 14px; cursor: pointer;
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
  }
  .custom-select-opzione:hover, .custom-select-opzione.evidenziata { background: var(--surface-2); }
  .custom-select-opzione.selezionata { color: var(--blue-light); font-weight: 700; }
  .custom-select-opzione.non-selezionabile {
    cursor: default; font-weight: 800; font-size: 12px; text-transform: uppercase;
    letter-spacing: .02em; color: var(--muted); opacity: .8; padding-top: 16px;
  }
  .custom-select-opzione.non-selezionabile:hover { background: none; }
  .custom-select-opzione svg { flex: 0 0 auto; width: 15px; height: 15px; color: var(--blue-light); }

  /* Variante cercabile (combobox): stessa struttura trigger/popover di
     .custom-select-*, ma la barra di ricerca non è più una riga fissa
     dentro il popover — all'apertura il trigger stesso si "trasforma"
     nel campo di ricerca (stesso box/bordo/posizione, come nei combobox
     dei siti moderni: es. Linear, Notion), mentre il popover sotto
     mostra solo la lista filtrata. Vedi initCustomSelect(id, { cercabile:
     true }) in componenti.js. */
  .custom-select-trigger.in-ricerca span { display: none; }
  .custom-select-trigger-input {
    display: none; flex: 1; min-width: 0; border: none; background: none; outline: none;
    font-size: 14px; font-family: inherit; color: var(--text); padding: 0;
  }
  .custom-select-trigger-input::placeholder { color: #56637D; }
  .custom-select-trigger.in-ricerca .custom-select-trigger-input { display: block; }
  /* Trigger cercabile: mostra la freccia a riposo, la lente quando si
     apre in modalità ricerca (il box "diventa" un campo di ricerca). */
  .custom-select-trigger-lente { display: none; }
  .custom-select-trigger.in-ricerca .custom-select-trigger-freccia { display: none; }
  .custom-select-trigger.in-ricerca .custom-select-trigger-lente { display: block; }
  .custom-select-opzione-vuoto { padding: 14px 12px; font-size: 13px; color: var(--muted); text-align: center; }

  /* Pulsante "Fatto" per chiudere manualmente il popover di sel-materia
     dopo aver scelto uno o più moduli della stessa materia madre (vedi
     multiModulo in componenti.js): il popover NON si chiude da solo in
     quel caso, per permettere di selezionarne altri. */
  .custom-select-fatto {
    margin-top: 6px; padding: 10px 12px; border-radius: 8px; font-size: 14px; font-weight: 700;
    cursor: pointer; display: flex; align-items: center; gap: 8px; justify-content: center;
    color: var(--blue-light); border-top: 1px solid var(--border);
  }
  .custom-select-fatto:hover { background: var(--surface-2); }
  .custom-select-fatto svg { flex: 0 0 auto; width: 15px; height: 15px; }

  /* Textarea che si allarga in automatico mentre si scrive, così il testo
     lungo resta sempre visibile per intero (forum, domande d'esame, chat). */
  textarea.autogrow {
    resize: none;
    overflow: hidden;
    line-height: 1.4;
    max-height: 260px;
    overflow-y: auto;
  }
  label { font-size: 13px; font-weight: 600; color: var(--muted); }

  button { font-family: inherit; cursor: pointer; }
  .btn-primary {
    width: 100%; padding: 12px; background: linear-gradient(120deg, var(--blue), var(--teal));
    color: #fff; border: none; border-radius: 10px;
    font-weight: 700; font-size: 15px;
    box-shadow: 0 8px 20px rgba(37, 99, 235, .25);
    transition: transform .15s ease, box-shadow .15s ease;
  }
  .btn-primary:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(37, 99, 235, .32); }
  .btn-primary.disabled { opacity: .45; pointer-events: none; box-shadow: none; }
  .btn-secondary {
    width: 100%; padding: 11px; background: var(--surface-2); color: var(--text);
    border: 1.5px solid var(--border); border-radius: 10px; font-weight: 700; margin-top: 8px;
  }
  .btn-secondary:hover { border-color: var(--blue-light); }
  /* Sfondo pieno (surface) invece di surface-2: prima aveva lo stesso
     grigio degli input di testo e non si leggeva come azione a sé, ora
     con un'ombra leggera si stacca subito come alternativa a "Accedi". */
  .btn-google {
    width: 100%; padding: 11px; background: var(--surface); color: var(--text);
    border: 1.5px solid var(--border); border-radius: 10px; font-weight: 700; margin-top: 8px;
    box-shadow: 0 1px 3px rgba(0,0,0,.06);
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
  }
  .btn-google:hover { border-color: var(--blue-light); box-shadow: 0 4px 14px rgba(37, 99, 235, .12); transform: translateY(-1px); }
  /* Bottone "Entra come Ospite (demo)" nella schermata di login: reso
     visivamente più defilato di "Continua con Google" (nessun bordo
     pieno, sfondo trasparente, testo più tenue) perché non è un vero
     login — è una scorciatoia verso una modalità demo, e non deve avere
     lo stesso peso visivo delle azioni di accesso reali. */
  .btn-ospite-demo {
    width: 100%; padding: 11px; background: transparent; color: var(--blue-light);
    border: 1.5px solid var(--blue-light); border-radius: 10px; font-weight: 700; margin-top: 8px;
    transition: background .15s ease, transform .15s ease;
  }
  .btn-ospite-demo:hover { background: var(--blue-bg); transform: translateY(-1px); }

  .btn-small {
    padding: 7px 12px; background: var(--surface-2); color: var(--text);
    border: 1px solid var(--border); border-radius: 8px; font-size: 13px; font-weight: 600; margin-right: 6px;
  }
  .btn-small:hover { border-color: var(--blue-light); }
  .btn-small:disabled { cursor: default; opacity: .6; }
  .btn-voted { background: var(--amber-bg); color: var(--amber); border-color: var(--amber); }
  .btn-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
  .btn-danger:hover { border-color: var(--danger); }
  .btn-back {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; border-radius: 8px; margin-bottom: 0;
    background: none; border: none; color: var(--muted); padding: 0; flex-shrink: 0;
  }
  .btn-back svg { width: 19px; height: 19px; }
  .btn-back:hover { color: var(--text); }

  /* Riga "freccia indietro + titolo pagina" affiancati, al posto di due righe
     separate (freccia sopra da sola, titolo sotto): risparmia spazio verticale
     ed è più leggero visivamente rispetto al vecchio bottone con bordo/sfondo. */
  .page-header-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
  .page-header-row h2 { margin: 0; }
  .page-header-row .btn-back { margin-bottom: 0; }

  /* Stesso pattern di .page-header-row, riusato dentro la card materia:
     la freccia "indietro" sta appiccicata al nome della materia invece che
     sola in cima alla pagina (ora che la topbar generica è nascosta in
     standalone, ogni pagina di dettaglio porta con sé la propria freccia). */
  .materia-titolo-row { display: flex; align-items: center; gap: 8px; }
  .materia-titolo-row .btn-back { margin-bottom: 0; flex-shrink: 0; }
  .materia-titolo-row h2 { margin: 2px 0 0; }

  /* ===================== AUTH — schermo diviso ===================== */
  #page-auth { display: none; height: 100vh; height: 100dvh; max-width: none; padding: 0; margin: 0; overflow: hidden; }
  #page-auth.active { display: flex; }
  #page-auth.active .auth-hero { display: none; }
  #page-auth.active .auth-form-side { flex: 1 1 100%; }

  .auth-hero {
    position: relative; overflow: hidden; padding: 48px;
    background-image: url('og-image.png');
    background-size: cover; background-position: center;
    display: flex; flex-direction: column; justify-content: center; align-items: center;
    text-align: center; gap: 30px;
  }
  .auth-hero::before {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(135deg, rgba(29,78,216,.88) 0%, rgba(37,99,235,.88) 45%, rgba(14,165,160,.88) 100%),
                radial-gradient(circle at 20% 20%, rgba(255,255,255,.12), transparent 45%),
                radial-gradient(circle at 80% 70%, rgba(255,255,255,.10), transparent 40%);
  }
  .auth-hero-top { position: relative; display: flex; align-items: center; justify-content: center; gap: 10px; font-weight: 800; font-size: 18px; color: #fff; }
  .auth-hero-logo { width: 34px; height: 34px; border-radius: 9px; background: rgba(255,255,255,.18); display: flex; align-items: center; justify-content: center; font-size: 17px; }
  .auth-hero-mid { position: relative; color: #fff; max-width: 520px; display: flex; flex-direction: column; align-items: center; margin: 0 auto; }
  .hero-eyebrow {
    display: inline-block; color: #fff; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.28);
    border-radius: 20px; padding: 5px 14px; font-size: 12px; font-weight: 700; margin-bottom: 16px;
    text-transform: uppercase; letter-spacing: .03em;
  }
  .auth-hero-mid h1 { color: #fff; font-size: 38px; line-height: 1.15; margin-bottom: 14px; }
  .auth-hero-mid p { color: rgba(255,255,255,.85); font-size: 15px; }
  .auth-hero-bottom { position: relative; width: 100%; display: flex; justify-content: center; align-items: center; }

  /* Nascosto su schermo stretto: deve stare DOPO le regole base di .auth-hero
     qui sopra, altrimenti con la stessa specificità vince l'ultima dichiarata
     nel file (è esattamente il bug che ha causato lo schiacciamento visto
     su mobile) */
  @media (max-width: 860px) { .auth-hero { display: none; } }

  /* Mini anteprima decorativa del sito, dentro il pannello hero */
  .hero-mock { background: rgba(15, 23, 42, .55); border: 1px solid rgba(255,255,255,.18); border-radius: 20px;
    padding: 26px; backdrop-filter: blur(6px); max-width: 560px; width: 100%; margin: 0 auto; }
  .hero-mock-row { display: flex; gap: 8px; margin-bottom: 10px; }
  .hero-mock-chip { flex: 1; background: rgba(255,255,255,.1); border-radius: 10px; padding: 10px; }
  .hero-mock-chip .n { color: #fff; font-weight: 800; font-size: 15px; }
  .hero-mock-chip .l { color: rgba(255,255,255,.7); font-size: 10px; }
  .hero-mock-card { background: rgba(255,255,255,.08); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; }
  .hero-mock-card .t { color: #fff; font-weight: 700; font-size: 12.5px; margin-bottom: 6px; }
  .hero-mock-bar { height: 5px; border-radius: 4px; background: rgba(255,255,255,.15); overflow: hidden; }
  .hero-mock-bar span { display: block; height: 100%; background: #fff; border-radius: 4px; }

  .hero-mock-label { color: rgba(255,255,255,.8); font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 18px; text-align: center; }
  .hero-mock-quadrants { display: flex; gap: 16px; justify-content: center; }
  .hero-mock-quad { flex: 1; background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.18); border-radius: 20px; padding: 40px 14px; text-align: center; }
  .hero-mock-quad .ic-box { width: 78px; height: 78px; border-radius: 18px; background: rgba(255,255,255,.16); display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
  .hero-mock-quad .ic-box svg { width: 38px; height: 38px; color: #fff; }
  .hero-mock-quad .lb { color: #fff; font-size: 16px; font-weight: 700; }

  /* Card di benvenuto compatta, solo su mobile: stesso sfondo sfumato del
     pannello desktop, badge+titolo+sottotitolo, sopra al carosello */
  .mobile-hero-header { display: none; }
  @media (max-width: 860px) {
    .mobile-hero-header {
      display: block; margin: 0 auto 20px; max-width: 420px;
      background: linear-gradient(135deg, #1D4ED8 0%, #2563EB 45%, #0EA5A0 100%);
      border-radius: 18px; padding: 26px 22px; position: relative; overflow: hidden;
    }
    .mobile-hero-header::before {
      content: ''; position: absolute; inset: 0;
      background: radial-gradient(circle at 15% 20%, rgba(255,255,255,.14), transparent 45%);
    }
    .mobile-hero-header .hero-eyebrow { position: relative; margin-bottom: 12px; }
    .mobile-hero-header h1 { position: relative; color: #fff; font-size: 25px; line-height: 1.2; margin: 0 0 10px; }
    .mobile-hero-header p { position: relative; color: rgba(255,255,255,.9); font-size: 13.5px; margin: 0; }
  }

  /* Anteprima a carosello, visibile solo su mobile (dove il pannello hero è nascosto).
     Riusa le stesse .hub-card-icon (blu/teal/amber) dell'app vera, per coerenza visiva. */
  .mobile-hero-preview { display: none; }
  @media (max-width: 860px) {
    .mobile-hero-preview { display: block; margin: 0 auto 22px; max-width: 420px; }
  }
  .mobile-hero-preview .hero-mock-label { color: var(--muted); text-align: center; }
  .mobile-hero-carousel {
    display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; padding: 2px 2px 6px; scrollbar-width: thin;
  }
  .mobile-hero-card {
    flex: 0 0 132px; scroll-snap-align: start; background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; padding: 16px 10px; text-align: center;
  }
  .mobile-hero-card .hub-card-icon { margin: 0 auto 10px; }
  .mobile-hero-card .lb { font-size: 12.5px; font-weight: 700; color: var(--text); }

  /* Sfondo "vivo" invece del gradiente statico piatto: due blob sfumati
     blu/teal che si muovono piano (vedi @keyframes auth-blob-float più
     sotto) più un'onda SVG ancorata in basso. position:relative + overflow
     hidden qui servono a contenere i blob (posizionati assoluti, più grandi
     del viewport) senza far comparire scrollbar orizzontali. */
  .auth-form-side {
  position: relative;
  display: flex; align-items: flex-start; justify-content: center; height: 100%;
  padding: calc(40px + env(safe-area-inset-top, 0px)) 24px calc(40px + env(safe-area-inset-bottom, 0px));
  background: var(--bg);
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-y: contain;
}
  .auth-bg-blob {
    position: absolute; border-radius: 50%; filter: blur(50px); pointer-events: none; z-index: 0;
    animation: auth-blob-float 16s ease-in-out infinite;
  }
  .auth-bg-blob.b1 {
    width: 480px; height: 480px; top: -100px; left: -140px;
    background: radial-gradient(circle, rgba(59,130,246,.55), transparent 68%);
  }
  .auth-bg-blob.b2 {
    width: 440px; height: 440px; bottom: -160px; right: -140px;
    background: radial-gradient(circle, rgba(20,184,166,.48), transparent 68%);
    animation-delay: -8s; animation-duration: 19s;
  }
  @keyframes auth-blob-float {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(30px, 25px) scale(1.08); }
  }
  /* Onda SVG ancorata in fondo, sotto ai blob (z-index 0) e sotto al
     contenuto del form (auth-card ha z-index 1, vedi sotto). Il pattern
     è codificato inline come data-URI per non aggiungere una richiesta
     di rete in più solo per una decorazione di sfondo. */
  .auth-bg-wave {
    position: fixed; left: 0; right: 0; bottom: 0;
    height: calc(220px + env(safe-area-inset-bottom, 0px));
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 220' preserveAspectRatio='none'><path d='M0,110 C240,180 480,40 720,90 C960,140 1200,60 1440,110 L1440,220 L0,220 Z' fill='%232563EB' fill-opacity='0.16'/><path d='M0,150 C240,90 480,190 720,140 C960,90 1200,170 1440,130 L1440,220 L0,220 Z' fill='%230EA5A0' fill-opacity='0.16'/></svg>");
    background-repeat: no-repeat; background-size: cover; background-position: bottom;
    pointer-events: none; z-index: 0;
  }
  /* Chi preferisce "riduci animazioni" nel sistema non vede i blob muoversi:
     restano visibili ma fermi, l'onda statica non è comunque un'animazione. */
  @media (prefers-reduced-motion: reduce) {
    .auth-bg-blob { animation: none; }
  }
  /* Su mobile stretto il form partiva a metà schermo (align-items:center su
     min-height:100vh lasciava un vuoto enorme sopra al logo). Ora parte da
     sotto la status bar con un margine fisso, coerente sia su schermi alti
     che bassi. */
  @media (max-width: 480px) {
  .auth-form-side { padding-top: calc(56px + env(safe-area-inset-top, 0px)); }
}

  @media (min-width: 861px) {
    .auth-form-side { padding: 40px 48px; }
  }
  .auth-card { width: 100%; max-width: 380px; position: relative; z-index: 1; }
  @media (min-width: 861px) {
    .auth-card { max-width: 560px; }
    .welcome-title { font-size: 44px; }
    .welcome-sub { font-size: 16.5px; margin-bottom: 34px; }
    .welcome-brand-name { font-size: 19px; }
    .welcome-logo { width: 36px; height: 36px; border-radius: 11px; font-size: 18px; }
    .carousel-arrow { width: 42px; height: 42px; font-size: 22px; }
    #auth-welcome .btn-primary, #auth-welcome .btn-secondary { padding: 15px; font-size: 15.5px; }
    .auth-card h1 { font-size: 32px; }
    .auth-card .subtitle { font-size: 15.5px; }
    .auth-card input, .auth-card select { padding: 13px 14px; font-size: 15px; }
    .auth-card .btn-primary, .auth-card .btn-google, .auth-card .btn-secondary { padding: 14px; font-size: 15px; }
  }
  .auth-card h1 { font-size: 26px; margin-bottom: 4px; }
  .auth-card .subtitle { color: var(--muted); margin-bottom: 24px; font-size: 14px; }
  .auth-card p { font-size: 13px; color: var(--muted); }
  .auth-card a { color: var(--blue-light); text-decoration: none; font-weight: 700; }
  .auth-divider { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; margin: 18px 0; }
  .auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

  /* Checkbox EULA nel tab "Registrati": unica, condivisa da form
     email/password e dai bottoni Google/Apple dello stesso tab (vedi
     accediConGoogleSeAccettato/accediConAppleSeAccettato in core.js). */
  .auth-eula-row {
    display: flex; align-items: flex-start; gap: 9px; margin: 14px 0 4px;
    font-size: 12.5px; color: var(--muted); cursor: pointer; line-height: 1.5;
  }
  .auth-eula-row input[type="checkbox"] {
    flex: 0 0 auto; width: 16px; height: 16px; margin: 2px 0 0; padding: 0;
    border: 1.5px solid var(--border); border-radius: 4px; background: var(--surface-2);
    accent-color: var(--blue-light); cursor: pointer; appearance: auto;
  }
  .auth-eula-row a { color: var(--blue-light); font-weight: 600; text-decoration: underline; }

  /* ===================== SCHERMATA DI BENVENUTO (carosello) ===================== */
  .welcome-brand { display: flex; align-items: center; gap: 9px; margin-bottom: 30px; }
  .welcome-logo {
    width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
    background: linear-gradient(135deg, var(--blue), var(--teal));
    display: flex; align-items: center; justify-content: center; font-size: 15px; color: #fff;
  }
  .welcome-brand-name { font-weight: 800; font-size: 16.5px; color: var(--text); }
  .welcome-uni-pill {
    background: var(--surface-2); border: 1px solid var(--border); color: var(--muted);
    font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 20px; margin-left: 2px;
  }
  .welcome-title { font-size: 32px; line-height: 1.15; margin: 0 0 12px; font-weight: 800; }
  .welcome-sub { font-size: 14.5px; color: var(--muted); margin: 0 0 26px; line-height: 1.5; }

  .welcome-carousel { display: flex; align-items: center; gap: 10px; }
  .welcome-slide {
    flex: 1; min-width: 0; background: var(--surface); border: 1px solid var(--border);
    border-radius: 18px; padding: 22px; min-height: 170px;
    display: flex; flex-direction: column; justify-content: center;
    animation: pageIn .3s ease both;
  }
  .welcome-slide-icon {
    width: 44px; height: 44px; border-radius: 13px; margin-bottom: 14px;
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  }
  .welcome-slide-icon svg { width: 22px; height: 22px; color: #fff; }
  .welcome-slide-title { font-weight: 800; font-size: 17px; margin: 0 0 7px; }
  .welcome-slide-desc { font-size: 13px; color: var(--muted); line-height: 1.5; margin: 0; }
  @media (min-width: 861px) {
    .welcome-slide { padding: 32px; min-height: 190px; }
    .welcome-slide-icon { width: 54px; height: 54px; border-radius: 15px; margin-bottom: 18px; }
    .welcome-slide-icon svg { width: 27px; height: 27px; }
    .welcome-slide-title { font-size: 20px; margin-bottom: 9px; }
    .welcome-slide-desc { font-size: 14.5px; }
  }

  /* ===================== TOUR GUIDATO OSPITI (schermo intero) ===================== */
  #page-guest-tour.active {
    position: fixed; inset: 0; z-index: 250; background: var(--bg);
    display: flex; padding: calc(20px + env(safe-area-inset-top, 0px)) 24px calc(24px + env(safe-area-inset-bottom, 0px)) !important;
    animation: none !important; max-width: none !important; margin: 0 !important;
  }
  .guest-tour-shell { display: flex; flex-direction: column; width: 100%; max-width: 420px; margin: 0 auto; min-height: 0; height: 100%; }
  @media (min-width: 861px) { .guest-tour-shell { max-width: 780px; } }
  @media (min-width: 1180px) { .guest-tour-shell { max-width: 960px; } }
  .guest-tour-top { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; gap: 12px; }
  .guest-tour-salta { background: none; border: none; color: var(--muted); font-weight: 700; font-size: 14px; padding: 8px; }
  .guest-tour-salta:hover { color: var(--text); }
  /* Onboarding leggero (guest): il bottone "Avanti" vive in alto, a fianco
     di "Salta", invece che in fondo alla pagina — lo screenshot grande
     (vedi .onb-slide-stack) può occupare tutto lo spazio verticale sotto
     senza spingere i controlli fuori vista. carousel-dots ha margin-right:
     auto implicito da spazio-between: qui invece i tre elementi (dots,
     avanti, salta) stanno tutti sulla stessa riga con dots a sinistra e
     avanti+salta raggruppati a destra. */
  .onb-bottone-avanti-top {
    margin-left: auto; padding: 9px 22px; font-size: 14px; width: auto; min-width: 0;
  }

  /* Schermata di scelta dipartimento/corso: due liste di voci cliccabili,
     stile simile alle righe di Impostazioni ma pensate per la scelta
     iniziale (bordo tondo, hover, niente icona a sinistra). */
  .scelta-corso-lista { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; overflow-y: auto; }
  .scelta-corso-opzione {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    padding: 14px 16px; cursor: pointer; text-align: left; font-weight: 700; font-size: 14.5px; color: var(--text);
  }
  .scelta-corso-opzione:hover { border-color: var(--blue-light); background: var(--surface-2); }
  .scelta-corso-opzione .chevron { color: var(--muted); flex-shrink: 0; }
  .scelta-corso-step { display: flex; flex-direction: column; min-height: 0; height: 100%; }

  /* Barra di avanzamento a 3 tappe (Benvenuto / Dipartimento / Corso di
     laurea) mostrata sopra i due step della scelta dipartimento/corso. */
  .scelta-corso-progress { display: flex; align-items: center; gap: 4px; flex-shrink: 0; margin-bottom: 22px; flex-wrap: nowrap; width: 100%; }
  .scelta-corso-progress-item { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
  .scelta-corso-progress-dot {
    width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 800; background: var(--surface-2); color: var(--muted); border: 1px solid var(--border);
  }
  .scelta-corso-progress-item.done .scelta-corso-progress-dot { background: var(--green-bg); color: var(--green); border-color: transparent; }
  .scelta-corso-progress-item.current .scelta-corso-progress-dot { background: var(--blue); color: #fff; border-color: transparent; }
  .scelta-corso-progress-label { font-size: 12px; font-weight: 700; color: var(--muted); white-space: nowrap; }
  .scelta-corso-progress-item.done .scelta-corso-progress-label,
  .scelta-corso-progress-item.current .scelta-corso-progress-label { color: var(--text); }
  .scelta-corso-progress-line { flex: 1 1 auto; min-width: 10px; height: 2px; background: var(--border); border-radius: 2px; }
  .scelta-corso-progress-item.done ~ .scelta-corso-progress-line { background: var(--green); opacity: .4; }
  @media (max-width: 420px) {
    .scelta-corso-progress-label { display: none; }
    .scelta-corso-progress { gap: 6px; }
    .scelta-corso-progress-line { min-width: 14px; }
  }

  /* Step 1: lista a colonna singola di card dipartimento (icona + nome + n. corsi). */
  .scelta-corso-grid { display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 16px; overflow-y: auto; }
  .scelta-corso-card-dip {
    display: flex; align-items: center; gap: 12px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 14px 16px; cursor: pointer; text-align: left; width: 100%;
  }
  .scelta-corso-card-dip:hover { border-color: var(--blue-light); background: var(--surface-2); }
  .scelta-corso-card-dip-icon {
    width: 40px; height: 40px; border-radius: 10px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center; font-size: 19px;
  }
  .scelta-corso-card-dip-testi { min-width: 0; }
  .scelta-corso-card-dip-nome { font-weight: 700; font-size: 14.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .scelta-corso-card-dip-count { font-size: 12.5px; color: var(--muted); margin-top: 1px; }

  /* Step 2: lista di card corso (icona libro + nome), stile più semplice. */
  .scelta-corso-card-corso {
    display: flex; align-items: center; gap: 12px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 14px 16px; cursor: pointer; text-align: left; width: 100%;
  }
  .scelta-corso-card-corso:hover { border-color: var(--blue-light); background: var(--surface-2); }
  .scelta-corso-card-corso.selezionata { border-color: var(--blue); background: var(--blue-bg); box-shadow: 0 0 0 1px var(--blue) inset; }
  .scelta-corso-card-corso-check {
    margin-left: auto; width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
    display: none; align-items: center; justify-content: center; background: var(--blue); color: #fff; font-size: 12px; font-weight: 800;
  }
  .scelta-corso-card-corso.selezionata .scelta-corso-card-corso-check { display: flex; }
  .scelta-corso-card-corso-icon {
    width: 36px; height: 36px; border-radius: 9px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-2); color: var(--muted);
  }
  .scelta-corso-card-corso-icon svg { width: 18px; height: 18px; }
  .scelta-corso-card-corso-nome { font-weight: 700; font-size: 14.5px; color: var(--text); }

  #btn-iniziamo-scelta-corso:disabled { opacity: .45; cursor: not-allowed; pointer-events: none; }

  /* Barra di conferma persistente per il dipartimento scelto: sostituisce il
     vecchio popup modale. Resta ancorata in alto sullo step dipartimento,
     non è un overlay bloccante, e l'utente può continuare a esplorare la
     griglia e cambiare scelta prima di premere "Conferma". */
  .scelta-corso-conferma-bar {
    position: sticky; top: 0; z-index: 5;
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    background: var(--surface); border: 1px solid var(--border, var(--surface-2));
    border-radius: 14px; padding: 10px 10px 10px 14px; margin-bottom: 14px;
    box-shadow: 0 4px 16px rgba(0,0,0,.08);
  }
  .scelta-corso-conferma-bar-testo { font-size: 13.5px; color: var(--muted); }
  .scelta-corso-conferma-bar-testo b { color: var(--text); }
  .scelta-corso-conferma-bar-btn { width: auto; padding: 8px 18px; margin: 0; }

  .scelta-corso-card-dip.selezionata {
    border-color: var(--blue-light); background: var(--blue-bg);
  }

  /* Badge di riepilogo dipartimento scelto, mostrato in cima allo step 2. */
  .scelta-corso-badge-dipartimento {
    display: inline-flex; align-items: center; gap: 6px; width: fit-content;
    background: var(--blue-bg); color: var(--blue-light); font-weight: 700; font-size: 13px;
    padding: 6px 12px; border-radius: 999px; margin: 10px 0 14px;
  }

  #btn-torna-scelta-dipartimento { display: inline-flex; align-items: center; gap: 6px; width: auto; padding: 8px 12px 8px 10px; font-size: 13px; font-weight: 700; }
  #btn-torna-scelta-dipartimento svg { width: 15px; height: 15px; }

  /* Placeholder animato durante il caricamento di dipartimenti/corsi. */
  .scelta-corso-skeleton { height: 62px; border-radius: 14px; background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 37%, var(--surface) 63%); background-size: 400% 100%; animation: scelta-corso-shimmer 1.4s ease infinite; }
  @keyframes scelta-corso-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

  /* Step 1: schermata di benvenuto con spiegazione di cosa dovrà fare
     l'utente, prima di scegliere dipartimento e corso. */
  .scelta-corso-benvenuto-badge {
    display: flex; align-items: center; gap: 6px; width: fit-content; margin: 4px auto 16px;
    background: var(--blue-bg); color: var(--blue-light); font-weight: 800; font-size: 12px; letter-spacing: .04em; text-transform: uppercase;
    padding: 7px 14px; border-radius: 999px;
  }
  .scelta-corso-benvenuto-badge svg { width: 14px; height: 14px; }
  .scelta-corso-benvenuto-titolo { text-align: center; font-size: 26px; line-height: 1.25; margin: 0 0 14px; }
  .scelta-corso-benvenuto-sub { text-align: center; max-width: 460px; margin: 0 auto 22px; }
  .scelta-corso-benvenuto-lista { display: flex; flex-direction: column; gap: 10px; }
  .scelta-corso-benvenuto-item {
    display: flex; align-items: flex-start; gap: 12px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 14px 16px;
  }
  .scelta-corso-benvenuto-item strong { display: block; font-size: 14.5px; color: var(--text); }
  .scelta-corso-benvenuto-item small { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
  .scelta-corso-benvenuto-icon {
    width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--blue-bg); color: var(--blue-light);
  }
  .scelta-corso-benvenuto-icon svg { width: 17px; height: 17px; }
  .scelta-corso-benvenuto-btn { margin-top: 22px; display: flex; align-items: center; justify-content: center; gap: 8px; }
  .scelta-corso-benvenuto-btn svg { width: 16px; height: 16px; }
  #tour-bottone-avanti { flex-shrink: 0; }
  .carousel-arrow {
    width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; background: var(--surface-2);
    border: 1px solid var(--border); color: var(--muted); font-size: 18px; line-height: 1;
    display: flex; align-items: center; justify-content: center; padding: 0;
  }
  .carousel-arrow:hover { color: var(--text); border-color: var(--blue-light); }

  /* Contenitore esterno: le frecce sono ancorate qui in posizione assoluta,
     fisse a metà altezza dello schermo (comoda per il pollice), indipendenti
     dall'altezza della card che cambia in base al testo di ogni slide. */
  .tour-carousel-outer { position: relative; flex: 1; min-height: 0; margin: auto 0; display: flex; }
  .tour-arrow-fixed {
    position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  }
  .tour-arrow-fixed:first-child { left: -4px; }
  .tour-arrow-fixed:last-child { right: -4px; }

  /* Layout a due colonne: mockup telefono a sinistra, badge+titolo+checklist
     a destra, verticalmente centrati. Su schermi stretti le due colonne si
     impilano (telefono sopra, testo sotto). Stessa struttura per ogni slide,
     cambia solo il contenuto. */
  .tour-carousel { display: flex; align-items: stretch; gap: 10px; flex: 1; min-height: 0; padding: 0 38px; }
  .tour-slide {
    flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center;
    gap: 22px; overflow: hidden auto; animation: pageIn .3s ease both;
    padding: 6px 4px;
  }
  /* Cornice telefono finta: bordo scuro spesso, angoli molto arrotondati,
     tacca (notch) in alto, screenshot reale incastonato dentro. */
  .tour-slide-shot-wrap {
    flex: 0 0 auto; width: min(220px, 62vw); aspect-ratio: 9 / 19.2;
    background: #04080f; border: 7px solid #04080f; border-radius: 34px;
    box-shadow: 0 0 0 1.5px var(--border), 0 14px 34px rgba(0,0,0,.4);
    position: relative; overflow: hidden; padding: 0;
  }
  .tour-slide-shot-wrap::before {
    content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 46%; height: 20px; background: #04080f; border-radius: 0 0 14px 14px; z-index: 2;
  }
  .tour-slide-shot-wrap img {
    width: 100%; height: 100%; max-width: none; max-height: none;
    display: block; object-fit: cover; object-position: top center;
    border-radius: 27px; border: none; box-shadow: none;
  }
  .tour-slide-text {
    flex: 1 1 auto; min-height: 0; width: 100%; max-width: 360px;
    display: flex; flex-direction: column; align-items: center; text-align: center;
  }
  .tour-slide-title { font-weight: 800; font-size: 19px; margin-bottom: 10px; }
  .tour-slide-desc { font-size: 13.5px; color: var(--muted); line-height: 1.55; margin: 0; }
  .tour-slide-desc ul { margin: 0; padding-left: 0; list-style: none; text-align: left; display: inline-block; }
  .tour-slide-desc li { display: flex; align-items: flex-start; gap: 9px; margin-bottom: 8px; }
  .tour-slide-desc li:last-child { margin-bottom: 0; }
  @media (min-width: 861px) {
    .tour-slide { flex-direction: row; align-items: center; justify-content: center; gap: 60px; padding: 10px; }
    .tour-slide-shot-wrap { width: min(250px, 22vw); }
    .tour-slide-text { align-items: flex-start; text-align: left; max-width: 460px; }
    .tour-slide-desc ul { text-align: left; }
    .tour-slide-title { font-size: 26px; }
    .tour-slide-desc { font-size: 15px; }
  }
  @media (min-width: 1180px) {
    .tour-slide { gap: 90px; }
    .tour-slide-shot-wrap { width: 260px; }
    .tour-slide-text { max-width: 520px; }
    .tour-slide-title { font-size: 30px; }
    .tour-slide-desc { font-size: 16px; }
  }

  .tour-slide-shot-wrap.hidden { display: none; }
  .tour-slide.no-shot .tour-slide-text { flex: 1 1 auto; }
  /* Onboarding leggero (guest e neo-iscritti): layout verticale dedicato —
     titolo grande in alto, screenshot che occupa il massimo spazio
     possibile, una riga di spiegazione breve in fondo. Sovrascrive il
     layout "row" (immagine + testo affiancati) di .tour-slide, pensato
     per TOUR_SLIDES (rimosso). Due screenshot per slide (tablet 4:3 e
     mobile verticale), uno mostrato in base alla viewport — vedi sotto. */
  .onb-slide-stack {
    flex-direction: column !important; justify-content: flex-start; align-items: center;
    gap: 14px; width: 100%; height: 100%; padding: 0;
  }
  .onb-slide-title-top {
    font-weight: 800; font-size: 22px; text-align: center; margin: 0;
    max-width: 560px;
  }
  .onb-slide-desc-bottom {
    font-size: 14px; color: var(--muted); line-height: 1.5; margin: 0;
    text-align: center; max-width: 560px;
  }
  /* Le slide onboarding (sia guest che neo-iscritti) renderizzano sempre
     .punti come <ul><li><svg class="tour-check">…</svg><span>…</span></li></ul>
     (vedi app.js). Il layout "row" vecchio aveva già uno stile per
     .tour-slide-desc ul/li (pensato per testo allineato a sinistra), ma
     .onb-slide-desc-bottom è centrato e non aveva alcuna regola propria
     per ul/li/svg: risultato, niente pallino nativo (tolto da
     list-style: none altrove) e niente spunta SVG (icona senza stile
     esplicito qui restava invisibile/mal posizionata). Qui si dà un
     layout centrato coerente: la lista resta un blocco centrato nella
     slide, ma ogni riga ha icona+testo allineati a sinistra tra loro. */
  .onb-slide-desc-bottom ul {
    margin: 0; padding: 0; list-style: none; text-align: left; display: inline-block;
  }
  .onb-slide-desc-bottom li {
    display: flex; align-items: flex-start; gap: 9px; margin-bottom: 10px;
  }
  .onb-slide-desc-bottom li:last-child { margin-bottom: 0; }
  .onb-slide-desc-bottom .tour-check { flex: 0 0 auto; margin-top: 2px; color: var(--teal); }
  /* Di base il wrap non è mai "hidden" via JS (viene tolto non appena una
     slide ha uno screenshot, tablet o mobile che sia); qui scegliamo quale
     dei due <img> mostrare in base alla viewport. */
  #onb-slide-shot-wrap img.onb-shot-tablet,
  #onb-slide-shot-wrap img.onb-shot-mobile { display: none; }
  @media (max-width: 860px) {
    /* Telefono: frame pulito, SENZA ereditare nulla dalla cornice nera
       "da iPad" di .tour-slide-shot-wrap (background nero, border-color,
       box-shadow, ::before del notch). Prima si toccava solo
       width/border-width e lo sfondo nero della classe base restava
       visibile dietro/attorno allo screenshot — era quello il "frame
       iPad dentro al telefono". Qui si azzera esplicitamente ogni
       proprietà ereditata, non solo quelle geometriche. */
    #onb-slide-shot-wrap {
      width: min(230px, 68vw); height: auto; aspect-ratio: 9 / 19.5; flex: 0 0 auto;
      max-width: none; max-height: 100%;
      background: transparent;
      border: none; border-radius: 18px;
      box-shadow: 0 10px 30px rgba(0,0,0,.18);
    }
    #onb-slide-shot-wrap::before { content: none; display: none; }
    #onb-slide-shot-wrap img { border-radius: 18px; object-fit: cover; object-position: top center; background: #fff; }
    #onb-slide-shot-wrap img.onb-shot-mobile { display: block; }
  }
  @media (min-width: 861px) {
    #onb-slide-shot-wrap img.onb-shot-tablet { display: block; }
    /* Lo screenshot tablet di onboarding guest è stato scattato su iPad
       (orizzontale 4:3), quindi usa un frame da tablet invece del frame
       verticale da telefono. Si espande il più possibile nello spazio
       verticale disponibile tra titolo e testo (vedi .onb-slide-stack
       sopra). Racchiuso nello stesso media query "desktop/tablet" per non
       sovrascrivere più, sotto 860px, le regole del frame mobile qui sopra
       (prima era una regola globale senza media query e vinceva sempre
       per ordine di cascata, anche su telefono: era quello il bug che
       "incrociava" i due frame). */
    #onb-slide-shot-wrap {
      width: 100%; flex: 0 1 auto; min-height: 0; max-width: min(720px, 100%);
      aspect-ratio: 4 / 3; background: #04080f;
      border: 10px solid #04080f; border-radius: 20px;
    }
    #onb-slide-shot-wrap::before { content: none; display: none; }
    #onb-slide-shot-wrap img { border-radius: 10px; object-position: center top; }
  }
  @media (min-width: 1180px) {
    #onb-slide-shot-wrap { max-width: min(820px, 100%); }
  }
  .tour-slide-badge {
    display: inline-block; margin-bottom: 10px;
    padding: 4px 12px; border-radius: 999px; font-size: 11px; font-weight: 800;
    letter-spacing: .04em; text-transform: uppercase; color: #04120e;
    background: linear-gradient(135deg, var(--blue), var(--teal));
  }
  .tour-check { flex: 0 0 auto; margin-top: 2px; color: var(--teal); }
  .tour-slide-counter { text-align: center; color: var(--muted); font-size: 12.5px; font-weight: 600; margin: 10px 0 2px; }
  .carousel-dots { display: flex; justify-content: center; gap: 6px; margin: 16px 0 26px; }
  .carousel-dots span { width: 6px; height: 6px; border-radius: 4px; background: var(--border); transition: width .2s ease, background .2s ease; }
  .carousel-dots span.active { width: 20px; background: var(--text); }

  /* ===================== PRODUCT TOUR (fumetti contestuali) =====================
     A differenza dell'onboarding (pagina piena, mostrata solo prima della
     Dashboard) questo tour naviga davvero tra le pagine e mostra un
     fumetto accanto a un elemento reale ad ogni step (vedi
     PRODUCT_TOUR_STEPS e posizionaFumettoTour in app.js). L'overlay è
     trasparente (solo per intercettare i click fuori): a differenza di
     un tour "spotlight" classico non scuriamo tutto lo schermo, perché
     l'obiettivo è che l'utente continui a vedere l'app reale attorno,
     non un dialogo isolato sopra di essa. */
  .product-tour-overlay {
    position: fixed; inset: 0; z-index: 900;
    /* Rete di sicurezza: l'overlay stesso non intercetta più click
       (pointer-events: none). Se per qualunque motivo restasse visibile
       più del dovuto, non blocca comunque l'uso del resto dell'app —
       solo il fumetto (sotto) riceve pointer-events: auto per i suoi
       bottoni. Il "click fuori chiude" è quindi gestito interamente dal
       fumetto stesso via onclick sull'overlay + stopPropagation su di
       esso (vedi index.html), non da un overlay che cattura tutto. */
    pointer-events: none;
  }
  .product-tour-overlay.hidden { display: none; }
  .product-tour-scurita {
    position: fixed; inset: 0; z-index: 899;
    background: rgba(2,6,23,.6);
    /* Vero spotlight tramite clip-path: l'intero overlay è scuro, ma
       ritagliamo (via JS, vedi posizionaFumettoTour) un "buco" rettangolare
       esattamente sopra l'elemento puntato, lasciando quella zona a piena
       trasparenza/luminosità. A differenza della tecnica box-shadow con
       spread enorme, il clip-path non dipende dal containing block
       dell'elemento fixed e non rischia di essere tagliato da un
       antenato con transform/overflow — resta affidabile in ogni pagina.
       Il clip-path iniziale (prima che JS lo aggiorni) non ha alcun buco:
       tutto scuro fino al primo posizionamento. */
    clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
    pointer-events: auto; /* i click sul resto dello schermo (l'area scura) sono bloccati di proposito */
    transition: clip-path .25s ease, opacity .25s ease;
  }
  .product-tour-fumetto {
    position: fixed; z-index: 902; width: min(300px, calc(100vw - 24px));
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 18px 18px 16px; box-shadow: 0 16px 40px rgba(0,0,0,.35);
    pointer-events: auto;
    transition: top .25s ease, left .25s ease;
  }
  /* Freccina del fumetto: --punta-x è impostata via JS per restare
     allineata all'elemento puntato anche quando il fumetto viene spostato
     per non uscire dai bordi dello schermo. */
  .product-tour-fumetto::after {
    content: ''; position: absolute; left: var(--punta-x, 24px);
    width: 14px; height: 14px; background: var(--surface);
    border: 1px solid var(--border);
    transform: translateX(-50%) rotate(45deg);
  }
  .product-tour-fumetto-sotto::after {
    top: -8px; border-right: none; border-bottom: none;
  }
  .product-tour-fumetto-sopra::after {
    bottom: -8px; border-left: none; border-top: none;
  }
  .product-tour-senza-freccina::after { display: none; }
  .product-tour-chiudi {
    position: absolute; top: 10px; right: 10px;
    width: 26px; height: 26px; border-radius: 50%; border: none;
    background: var(--surface-2); color: var(--muted);
    display: flex; align-items: center; justify-content: center;
  }
  .product-tour-chiudi svg { width: 13px; height: 13px; }
  .product-tour-titolo { font-weight: 800; font-size: 16px; margin: 0 26px 6px 0; }
  .product-tour-testo { font-size: 13.5px; color: var(--muted); line-height: 1.5; margin: 0; }
  .product-tour-dots { display: flex; gap: 6px; margin: 14px 0 14px; }
  .product-tour-dots span { width: 6px; height: 6px; border-radius: 4px; background: var(--border); transition: width .2s ease, background .2s ease; }
  .product-tour-dots span.active { width: 20px; background: var(--teal); }
  .product-tour-azioni { display: flex; gap: 8px; }
  .product-tour-azioni .btn-primary, .product-tour-azioni .btn-secondary { width: auto; flex: 1; padding: 10px 14px; font-size: 14px; }
  .product-tour-indietro.hidden { display: none; }

  /* ===================== SHELL (sidebar + contenuto) ===================== */
  #app-shell {
    display: flex; flex-direction: column;
    height: 100%; height: 100dvh;
    overflow: hidden;
  }
  #app-shell.hidden { display: none; }
  .app-shell-body { display: flex; flex: 1; min-height: 0; }

  /* Hamburger: ora vive DENTRO la topbar (.app-topbar-left), non più
     fisso rispetto al viewport. Prima era position:fixed mentre la topbar
     era position:sticky rispetto al proprio contenitore di scroll: sono
     due sistemi di posizionamento diversi, e in alcune pagine/dispositivi
     potevano disallinearsi, facendo "scivolare" l'hamburger lontano dalla
     topbar durante lo scroll. Stando nello stesso contenitore, i due
     elementi ora si muovono sempre insieme, sia su desktop che su app. */
  .sidebar-burger {
    flex-shrink: 0; position: relative; z-index: 320;
    background: var(--surface); border: 1px solid var(--border); color: var(--text); cursor: pointer;
    width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    transition: opacity .15s ease, visibility .15s ease, background .15s ease;
  }
  /* Quando la sidebar è aperta, l'hamburger si sovrapporrebbe visivamente al
     logo dell'header della sidebar: lo nascondiamo e si chiude con la X
     dentro la sidebar o toccando fuori (overlay). */
  .sidebar-burger.is-hidden { opacity: 0; visibility: hidden; pointer-events: none; }
  .sidebar-burger svg { width: 18px; height: 18px; }
  .sidebar-burger:hover { background: var(--surface-2); }

  /* Overlay scuro dietro la sidebar quando è aperta. */
  .drawer-overlay {
    display: block; position: fixed; inset: 0; background: rgba(2,6,23,.65); z-index: 300;
    opacity: 0; pointer-events: none; transition: opacity .2s ease;
  }
  .drawer-overlay.hidden { opacity: 0; pointer-events: none; }
  .drawer-overlay:not(.hidden) { opacity: 1; pointer-events: auto; }

  /* Sidebar unica: nascosta di default (fuori schermo a sinistra), si apre
     scorrendo sopra il contenuto quando riceve la classe .open dall'hamburger.
     Stessa struttura ed esperienza identica su desktop e su app. */
  #sidebar {
    display: flex; flex-direction: column; position: fixed; top: 0; bottom: 0; left: 0; z-index: 301;
    width: 82%; max-width: 300px; background: var(--surface); border-right: 1px solid var(--border);
    padding: calc(16px + env(safe-area-inset-top, 0px)) 14px calc(16px + env(safe-area-inset-bottom, 0px));
    transform: translateX(-100%); transition: transform .22s ease; box-shadow: 0 0 40px rgba(0,0,0,.5);
    height: 100vh;
  }
  #sidebar.open { transform: translateX(0); }

  .mobile-drawer-header {
    display: flex; align-items: center; gap: 10px; padding: 6px 8px 18px; font-weight: 800; font-size: 15px;
  }
  .mobile-drawer-header .label { flex: 1; }
  .mobile-drawer-close {
    background: var(--surface-2); border: 1px solid var(--border); color: var(--text); cursor: pointer;
    width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; font-size: 13px; padding: 0;
  }

  .sidebar-logo {
    display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 15px;
    text-decoration: none; color: inherit; cursor: pointer; background: none; border: none; flex: 1; text-align: left; font-family: inherit; padding: 0;
  }
  .sidebar-logo .ico { width: 28px; height: 28px; border-radius: 8px; background: linear-gradient(135deg, var(--blue), var(--teal)); display: flex; align-items: center; justify-content: center; font-size: 13px; flex-shrink: 0; }

  .sidebar-nav { display: flex; flex-direction: column; gap: 3px; overflow-y: auto; flex: 1; }
  .sidebar-link {
    display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 9px;
    color: var(--muted); text-decoration: none; font-weight: 600; font-size: 14px; position: relative;
    width: 100%; background: none; border: none; font-family: inherit; text-align: left; cursor: pointer;
  }
  .nav-ico { width: 19px; height: 19px; flex-shrink: 0; }
  .sidebar-link:hover { background: var(--surface-2); color: var(--text); }
  .sidebar-link.active { background: var(--surface-2); color: var(--text); }
  .sidebar-link-logout:hover { background: rgba(239,68,68,.1); color: #EF4444; }
  .nav-badge {
    background: #EF4444; color: #fff; font-size: 10.5px; font-weight: 800;
    min-width: 17px; height: 17px; border-radius: 20px; display: inline-flex;
    align-items: center; justify-content: center; padding: 0 4px; margin-left: auto;
  }

  .drawer-expand-btn { width: 100%; }
  .drawer-chevron { width: 16px; height: 16px; margin-left: auto; flex-shrink: 0; transition: transform .15s ease; }
  .drawer-expand-btn.open .drawer-chevron { transform: rotate(180deg); }

  .drawer-submenu { display: flex; flex-direction: column; gap: 2px; padding: 2px 0 6px 33px; }
  .drawer-submenu.hidden { display: none; }
  .drawer-submenu-link {
    display: block; background: none; border: none; text-align: left; font-family: inherit; cursor: pointer;
    color: var(--muted); font-size: 13px; font-weight: 600; padding: 8px 10px; border-radius: 8px; width: 100%;
  }
  .drawer-submenu-link:hover { background: var(--surface-2); color: var(--text); }
  .drawer-submenu-empty { color: var(--muted); font-size: 12.5px; padding: 6px 10px; }

  .sidebar-bottom { margin-top: auto; display: flex; flex-direction: column; gap: 3px; padding-top: 8px; }
  .sidebar-user { display: flex; align-items: center; gap: 10px; padding: 12px 8px 4px; border-top: 1px solid var(--border); margin-top: 8px; }
  .sidebar-user .avatar {
    width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(135deg, var(--blue), var(--teal));
    display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; color: #fff; flex-shrink: 0;
  }
  #user-name-label { font-size: 13px; font-weight: 700; color: var(--text); }

  .main-column {
    flex: 1; min-width: 0; display: flex; flex-direction: column;
    height: 100vh; height: 100dvh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
  }

  /* Topbar sopra il contenuto: titolo pagina a sinistra, campanella e
     profilo a destra. Presente sia su desktop che su app; l'hamburger
     resta un elemento a parte, fisso, che apre/chiude la sidebar. */
  .app-topbar {
    display: flex; align-items: center; justify-content: space-between;
    position: sticky; top: 0; z-index: 140; background: var(--surface); border-bottom: 1px solid var(--border);
    padding: calc(12px + env(safe-area-inset-top, 0px)) 20px 12px 20px;
  }
  .app-topbar-left { display: flex; align-items: center; gap: 14px; min-width: 0; }
  .app-topbar-titolo { font-weight: 800; font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
  .app-topbar-right { display: flex; align-items: center; gap: 8px; }
  .topbar-icon-btn {
    background: none; border: 1px solid var(--border); color: var(--text); cursor: pointer;
    width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; padding: 0;
  }
  .topbar-icon-btn:hover { background: var(--surface-2); }
  .topbar-icon-btn svg { width: 18px; height: 18px; }

  /* Popover con nome ed email, aperto dall'omino nella topbar */
  .topbar-user-menu { position: relative; }
  .topbar-user-popover {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 200;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 16px; min-width: 220px; box-shadow: 0 10px 30px rgba(0,0,0,.18);
    display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px;
  }
  .topbar-user-popover-avatar { margin-bottom: 8px; }
  .topbar-user-popover-nome { font-weight: 800; font-size: 15px; color: var(--text); }
  .topbar-user-popover-email { font-size: 13px; color: var(--muted); word-break: break-all; }
  .topbar-user-popover-info {
    width: 100%; margin-top: 10px; margin-bottom: 12px;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px;
    padding: 8px 12px;
  }
  .topbar-user-popover-info-row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    text-align: left;
  }
  .topbar-user-popover-info-label {
    font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .03em;
    flex-shrink: 0;
  }
  .topbar-user-popover-info-value {
    font-size: 13px; font-weight: 600; color: var(--text);
    text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .topbar-user-popover-link {
    width: 100%; background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
    padding: 9px 12px; border-radius: 9px; font-weight: 700; font-size: 13px; cursor: pointer;
  }
  .topbar-user-popover-link:hover { border-color: var(--blue-light); color: var(--blue-light); }

  /* Popover con le levette di notifica, aperto dalla campanella nella topbar */
  .topbar-notif-popover {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 200;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 16px; min-width: 260px; box-shadow: 0 10px 30px rgba(0,0,0,.18);
    display: flex; flex-direction: column; gap: 10px; text-align: left;
  }
  .topbar-notif-popover-title { font-weight: 800; font-size: 14px; color: var(--text); margin-bottom: 2px; }
  .topbar-notif-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  .topbar-notif-row-label { font-size: 13.5px; font-weight: 700; color: var(--text); }
  .topbar-notif-row-note { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

  #main-content {
    flex: 1; min-width: 0; min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
  }
  .page { display: none; padding: 30px 32px; max-width: 1100px; margin: 0 auto; }
  .page.active { display: block; }

  /* Pagine "a schermo intero": coprono davvero tutto (sidebar e topbar
     comprese), anche se nel DOM restano dentro l'app-shell. Usate per
     welcome/tour e per la scelta iniziale di dipartimento e corso. */
  #page-welcome.page.active,
  #page-scelta-corso.page.active {
    position: fixed; inset: 0; z-index: 500; background: var(--bg);
    max-width: none; margin: 0; display: flex; flex-direction: column;
    padding: calc(24px + env(safe-area-inset-top, 0px)) 20px calc(20px + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
  }
  @media (max-width: 780px) {
    .app-topbar { padding: calc(12px + env(safe-area-inset-top, 0px)) 16px 12px 16px; }
    .page { padding: 20px 16px; }
  }

  /* ===================== DASHBOARD ===================== */
  /* In standalone il gear impostazioni è fixed e non spinge il layout;
     il padding-top generico di .page (30px) sommato alla safe-area reale
     lasciava troppo spazio bianco sopra "Ciao, Luigi". Lo riduciamo solo
     qui, lasciando .page invariato per tutte le altre pagine. */
  #page-dashboard.page { padding-top: 10px; }
  .dash-header { margin-bottom: 22px; }
  .dash-date { font-size: 13px; color: var(--muted); margin-bottom: 4px; }
  .dash-greeting { font-size: 26px; }
  .dash-sub { margin-top: 2px; }

  .stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 24px; }
  @media (max-width: 780px) { .stat-grid { grid-template-columns: 1fr 1fr; } }
  .stat-grid-3col { grid-template-columns: 1fr 1fr 1fr; }
  @media (max-width: 560px) { .stat-grid-3col { grid-template-columns: 1fr 1fr; } }
  .stat-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; }
  .stat-card.blue { background: linear-gradient(155deg, var(--blue-bg), var(--surface) 75%); border-color: var(--border); }
  .stat-card.amber { background: linear-gradient(155deg, var(--amber-bg), var(--surface) 75%); border-color: var(--border); }
  .stat-card.teal-card { background: linear-gradient(155deg, var(--teal-bg), var(--surface) 75%); border-color: var(--border); }
  .stat-card-top.teal-text { color: var(--teal); }
  .stat-card-top { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 700; color: var(--blue-light); margin-bottom: 10px; }
  .stat-ico { width: 14px; height: 14px; flex-shrink: 0; }
  .stat-card.amber .stat-card-top { color: var(--amber); }
  .stat-icon { width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; font-size: 16px; margin-bottom: 12px; }
  .stat-icon.blue { background: var(--blue-bg); }
  .stat-icon.amber { background: var(--amber-bg); }
  .stat-icon.teal { background: var(--teal-bg); }
  .stat-value { font-size: 26px; font-weight: 800; }
  .stat-label { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

  .stat-grid-quadrata .stat-card { aspect-ratio: 1 / 1; display: flex; flex-direction: column; justify-content: center; }
  .stat-like { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: #22C55E; font-weight: 700; margin-top: 6px; }
  .stat-sub { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

  .btn-outline-add {
    width: 100%; padding: 13px; margin-top: 4px; background: none; color: var(--muted);
    border: 1.5px dashed var(--border); border-radius: 12px; font-weight: 700; font-size: 14px;
  }
  .btn-outline-add:hover { border-color: var(--blue-light); color: var(--blue-light); }

  /* ===================== IMPOSTAZIONI (stile lista righe) ===================== */
  .profile-header-card {
    background: linear-gradient(155deg, var(--blue-bg), var(--surface) 70%); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 20px; margin-bottom: 22px; cursor: pointer;
  }
  .profile-header-top { display: flex; align-items: center; gap: 14px; }
  .profile-header-name { font-weight: 800; font-size: 17px; display: flex; align-items: center; gap: 6px; }
  .profile-header-corso { font-size: 13px; color: var(--muted); margin-top: 2px; }
  .profile-header-tags { display: flex; gap: 8px; margin-top: 14px; }
  .filtro-pillole { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
  .filtro-pill {
    background: var(--surface); border: 1px solid var(--border); color: var(--muted);
    font-size: 12.5px; font-weight: 700; padding: 7px 14px; border-radius: 20px;
    cursor: pointer; white-space: normal; font-family: inherit;
    display: inline-flex; align-items: center; gap: 6px; text-align: left;
    max-width: 100%;
  }
  .filtro-pill:hover { background: var(--surface-2); color: var(--text); }
  .filtro-pill.active { background: var(--blue); border-color: var(--blue); color: #fff; }
  .filtro-pill svg { width: 15px; height: 15px; flex-shrink: 0; }

  /* ===================== INSTALLA APP ===================== */
  .installa-tab-btn {
    display: inline-flex; align-items: center; gap: 7px;
  }
  .installa-tab-btn svg { width: 17px; height: 17px; flex-shrink: 0; }
  .installa-store-icona {
    width: 52px; height: 52px; margin: 0 auto 14px; border-radius: 14px;
    background: var(--surface-2); display: flex; align-items: center; justify-content: center;
  }
  .installa-store-icona svg { width: 26px; height: 26px; stroke: var(--text); }

  .istruzioni-timeline { list-style: none; margin: 0; padding: 0; }
  .istruzioni-timeline li {
    position: relative; display: flex; gap: 14px; padding-bottom: 22px;
  }
  .istruzioni-timeline li:last-child { padding-bottom: 0; }
  .istruzioni-timeline li::before {
    content: ""; position: absolute; left: 15px; top: 32px; bottom: 0;
    width: 2px; background: var(--border);
  }
  .istruzioni-timeline li:last-child::before { display: none; }
  .istruzioni-timeline-num {
    flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%;
    background: var(--blue-bg); color: var(--blue); font-weight: 800; font-size: 13.5px;
    display: flex; align-items: center; justify-content: center; z-index: 1;
  }
  .istruzioni-timeline-body { padding-top: 3px; }
  .istruzioni-timeline-title { font-weight: 800; font-size: 14.5px; color: var(--text); margin-bottom: 3px; }
  .istruzioni-timeline-desc { font-size: 13px; color: var(--muted); line-height: 1.45; }
  .istruzioni-timeline-shot {
    position: relative;
    display: block;
    width: 100%;
    max-width: 260px;
    margin-top: 10px;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--border);
    box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  }
  .istruzioni-timeline-shot img { display: block; width: 100%; height: auto; }
  .istruzioni-timeline-shot-box {
    position: absolute;
    border: 3px solid #ff3b30;
    border-radius: 8px;
    box-shadow: 0 0 0 2000px rgba(0,0,0,0.25);
    pointer-events: none;
  }
  .card-faq-materia-tag {
    display: inline-block; background: var(--surface-2); color: var(--blue-light);
    font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 20px; margin-left: 6px;
  }

  /* ===================== SEZIONE RISORSE ===================== */
  .risorsa-tipo-tag {
    display: inline-block; background: var(--teal-bg, var(--surface-2)); color: var(--teal, var(--blue-light));
    font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 20px; text-transform: uppercase; letter-spacing: .02em;
  }
  .ordinamento-pillole {
    display: inline-flex; gap: 0; margin-bottom: 14px;
    background: var(--surface-2); border-radius: 10px; padding: 3px;
  }
  .pillola-ord {
    background: none; border: none; color: var(--muted);
    font-size: 12.5px; font-weight: 700; padding: 7px 16px; border-radius: 8px;
    cursor: pointer; font-family: inherit;
  }
  .pillola-ord:hover { color: var(--text); }
  .pillola-ord.active { background: var(--surface); color: var(--blue); box-shadow: 0 1px 3px rgba(0,0,0,0.08); }

  /* Etichetta sopra ogni gruppo di filtri (es. "Materia" / "Ordina per" nel
     Forum): senza queste, le pillole materia e i bottoni di ordinamento
     erano visivamente identici (stesso stile, stesso raggio, stesso blu da
     attivi) e si confondevano come fossero un unico gruppo di filtri. */
  .filtro-gruppo-label {
    display: block; font-size: 11.5px; font-weight: 700; color: var(--muted);
    text-transform: uppercase; letter-spacing: .03em; margin: 14px 0 6px;
  }
  .filtro-gruppo-label:first-of-type { margin-top: 0; }
  .empty-state { text-align: center; padding: 28px 16px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
  .empty-state.hidden { display: none; }

  .settings-section-label { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; margin: 22px 2px 8px; }
  .settings-group { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
  .settings-row { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--border); cursor: pointer; }
  .settings-row:last-child { border-bottom: none; }
  .settings-row:hover { background: var(--surface-2); }
  .settings-row-icon {
    width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0; background: var(--blue-bg); color: var(--blue-light);
    display: flex; align-items: center; justify-content: center;
  }
  .settings-row-icon svg { width: 16px; height: 16px; }
  .settings-row-icon.blue { background: var(--blue-bg); color: var(--blue-light); }
  .settings-row-icon.teal { background: var(--teal-bg); color: var(--teal); }
  .settings-row-icon.amber { background: var(--amber-bg); color: #FCD34D; }
  .settings-row-icon.violet { background: var(--violet-bg); color: var(--violet); }
  .settings-row-label { font-weight: 600; font-size: 14px; flex: 1; min-width: 0; }
  .settings-row-value { font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; }
  .settings-row-chevron { color: var(--muted); font-size: 16px; }

  /* Testo "Dipartimento: ... / Corso: ..." nella pagina dedicata di Impostazioni. */
  .settings-row-dipcorso-riga { font-size: 13.5px; color: var(--text); overflow-wrap: break-word; }
  .settings-row-dipcorso-label { font-weight: 700; color: var(--muted); }

  .btn-esci-pill {
    width: 100%; margin-top: 22px; margin-bottom: 20px; padding: 14px; background: var(--danger-bg); color: var(--danger);
    border: 1px solid var(--danger-border); border-radius: 16px; font-weight: 700; font-size: 14.5px;
  }
  .btn-esci-pill:hover { border-color: var(--danger); }
  @media (max-width: 780px) {
    .btn-esci-pill { margin-bottom: calc(20px + env(safe-area-inset-bottom, 0px)); }
  }

  .faq-item { margin-bottom: 16px; }
  .faq-item:last-child { margin-bottom: 0; }
  .faq-q { font-weight: 700; font-size: 14px; margin-bottom: 4px; }
  .faq-a { font-size: 13px; color: var(--muted); line-height: 1.5; }

  .istruzioni-installa { margin: 0; padding-left: 20px; color: var(--text); font-size: 14px; line-height: 1.7; }
  .istruzioni-installa li { margin-bottom: 4px; }
  .istruzioni-installa b { color: var(--blue-light); }

  .campo-password-wrap { position: relative; }
  .campo-password-wrap input { padding-right: 42px; }
  .btn-occhio-password {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    background: none; border: none; width: 32px; height: 32px; padding: 0;
    display: flex; align-items: center; justify-content: center; font-size: 16px;
    opacity: .6; margin: 0;
  }
  .btn-occhio-password:hover { opacity: 1; }
  .btn-occhio-password.attivo { opacity: 1; }

  .toolbar-search-row { display: flex; gap: 10px; margin-bottom: 12px; }
  .toolbar-search-row input[type="text"] { margin: 0; flex: 1; max-width: 320px; }
  .toolbar-search-row .btn-primary { width: auto; padding: 11px 18px; white-space: nowrap; }
  @media (max-width: 600px) {
    .toolbar-search-row { flex-direction: column; }
    .toolbar-search-row input[type="text"] { max-width: none; }
    .toolbar-search-row .btn-primary { width: 100%; }
  }
  .filter-pills-scroll {
    display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 18px;
    -webkit-overflow-scrolling: touch; scrollbar-width: thin;
  }
  .filter-pill {
    flex: 0 0 auto; padding: 8px 14px; border-radius: 20px; border: 1px solid var(--border); background: var(--surface);
    color: var(--muted); font-size: 13px; font-weight: 600; white-space: nowrap;
  }
  .filter-pill.active { background: var(--blue); border-color: var(--blue); color: #fff; }

  .materie-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
  @media (max-width: 780px) { .materie-grid { grid-template-columns: 1fr; } }

  /* Eliminazione card materia in dashboard: solo tramite tenere premuto
     (long-press, gestito in componenti.js), che apre la conferma
     custom. Lo swipe laterale precedente è stato rimosso su richiesta
     esplicita di Luigi. */
  .card-materia-swipe-wrap { position: relative; border-radius: var(--radius); overflow: hidden; }
  .card-materia-swipe-wrap .card-materia { position: relative; background: var(--surface); }

  .card-materia {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 18px; cursor: pointer; transition: border-color .15s ease, transform .15s ease;
  }
  .card-materia:hover { border-color: var(--blue-light); transform: translateY(-2px); }
  .card-materia-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 4px; gap: 8px; }
  .card-materia-badges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .pill-hot { background: var(--amber-bg); color: var(--amber); font-size: 10.5px; font-weight: 800; padding: 3px 8px; border-radius: 20px; white-space: nowrap; }
  .pill-countdown { display: flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 700; color: var(--amber); white-space: nowrap; }
  .card-materia-top h3 { font-size: 16px; margin: 10px 0 0; }
  .card-materia-modulo-tag {
    display: inline-block; background: var(--blue-bg); color: var(--blue-light);
    font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 20px; margin-top: 6px;
  }
  .card-materia .prof { font-size: 12.5px; color: var(--muted); margin-bottom: 12px; }
  .card-materia-progress-row { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted); margin-bottom: 5px; }
  .card-materia-progress-row b { color: var(--text); }
  .card-materia-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; font-size: 12px; color: var(--muted); }

  /* Levetta "visibile ai Buddy" per singola materia */
  .buddy-toggle-row {
    display: flex; align-items: center; gap: 9px; margin-top: 12px; padding-top: 12px;
    border-top: 1px solid var(--border); font-size: 12px; color: var(--muted);
  }
  .bb-switch { position: relative; display: inline-block; width: 34px; height: 19px; flex-shrink: 0; }
  .bb-switch input { opacity: 0; width: 0; height: 0; }
  .bb-switch .slider {
    position: absolute; inset: 0; background: #EF4444; border-radius: 20px; cursor: pointer; transition: background .15s ease;
  }
  .bb-switch .slider::before {
    content: ''; position: absolute; height: 15px; width: 15px; left: 2px; bottom: 2px;
    background: #fff; border-radius: 50%; transition: transform .15s ease;
  }
  .bb-switch input:checked + .slider { background: #22C55E; }
  .bb-switch input:checked + .slider::before { transform: translateX(15px); }

  .pill { padding: 4px 11px; border-radius: 20px; font-size: 11.5px; font-weight: 700; border: 1px solid transparent; white-space: nowrap; }

  /* Card "il tuo profilo Buddy" in cima a "I miei Buddy": stesso stile
     delle card conversazione, con un bordo leggero per distinguerla
     visivamente dalle conversazioni vere (non è una chat, apre le
     Impostazioni). */
  .card-mio-profilo-buddy { border: 1px solid var(--blue); cursor: pointer; }
  .card-mio-profilo-buddy .pill { background: var(--blue-bg); color: var(--blue-light); }
  .pill[data-stato="Da preparare"] { background: var(--surface-2); color: var(--muted); border-color: var(--border); }
  .pill[data-stato="In preparazione"] { background: var(--amber-bg); color: var(--amber); }
  .pill[data-stato="Ripetizione"] { background: var(--blue-bg); color: var(--blue-light); border-color: var(--border); }
  .pill[data-stato="Fase finale"] { background: var(--teal-bg); color: var(--teal); border-color: var(--border); }

  .progress-bar { background: var(--surface-2); border-radius: 20px; height: 7px; overflow: hidden; }
  .progress-fill { height: 100%; border-radius: 20px; background: var(--blue-light); }
  .progress-fill[data-stato="Da preparare"] { background: var(--muted); }
  .progress-fill[data-stato="In preparazione"] { background: var(--amber); }
  .progress-fill[data-stato="Ripetizione"] { background: #6FA8F5; }
  .progress-fill[data-stato="Fase finale"] { background: var(--teal); }

  .empty { color: var(--muted); text-align: center; padding: 32px; grid-column: 1 / -1; }

  /* ===================== STANZA MATERIA ===================== */
  .materia-header-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px 24px; margin: 16px 0 22px; }
  .materia-header-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
  .materia-header-meta { font-size: 13px; color: var(--muted); margin: 8px 0 2px; }
  .materia-header-card h2 { font-size: 24px; margin: 2px 0 10px; }
  .materia-quick-actions { display: flex; gap: 8px; }
  #materia-modulo-tag { margin-bottom: 12px; }
  .btn-icon-mini {
    width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
    background: var(--blue-bg); border: none; color: var(--blue-light);
    display: flex; align-items: center; justify-content: center;
  }
  .btn-icon-mini svg { width: 16px; height: 16px; }
  .btn-icon-mini:hover { background: var(--border); }
  .btn-icon-mini.whatsapp { background: var(--surface-2); }
  .btn-icon-mini.whatsapp:hover { background: var(--border); }
  .btn-icon-mini.danger { background: var(--surface-2); color: var(--danger); }
  .btn-icon-mini.danger:hover { background: var(--border); }
  .materia-header-info { display: flex; gap: 18px; flex-wrap: wrap; font-size: 13px; color: var(--muted); margin-bottom: 14px; }
  .materia-header-pct { text-align: right; }
  .materia-header-pct .n { font-size: 28px; font-weight: 800; }
  .materia-header-pct .l { font-size: 11.5px; color: var(--muted); }
  .materia-ring {
    width: 60px; height: 60px; border-radius: 50%; flex-shrink: 0;
    background: conic-gradient(var(--blue-light) calc(var(--pct) * 1%), var(--surface-2) 0);
    display: flex; align-items: center; justify-content: center;
    transition: background .4s ease;
  }
  .materia-ring-inner {
    width: 47px; height: 47px; border-radius: 50%; background: var(--surface);
    display: flex; align-items: center; justify-content: center;
  }
  .materia-ring .n { font-size: 13.5px; font-weight: 800; }

  .materia-tabs { margin-bottom: 20px; }
  .materia-tabs-scroll {
    display: flex; gap: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 4px;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .materia-tabs-scroll::-webkit-scrollbar { display: none; }
  .materia-tabs-scroll .tab-btn { flex: 1 1 0; }
  .tab-btn {
    background: none; border: none; padding: 10px 8px; color: var(--muted); font-weight: 700; font-size: 13.5px;
    border-radius: 10px; white-space: nowrap; transition: background .15s ease, color .15s ease;
  }
  .tab-btn:hover { color: var(--text); }
  .tab-btn.active { color: var(--text); background: var(--surface-2); }
  .tab-btn.active .tab-count { background: var(--blue); color: #fff; }
  .tab-ico { display: inline-flex; vertical-align: -3px; margin-right: 5px; }
  .tab-ico svg { width: 15px; height: 15px; }

  .search-input-wrap { position: relative; }
  .search-input-ico {
    position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    color: var(--muted); display: flex; pointer-events: none;
  }
  .search-input-ico svg { width: 15px; height: 15px; }
  .search-input-wrap input { padding-left: 38px; }

  /* Hub d'ingresso alla materia: tre card compatte con statistiche reali */
  .materia-hub { display: none !important; }

  .mini-avatar {
    border-radius: 50%; color: #fff; font-weight: 700; display: flex; align-items: center;
    justify-content: center; flex-shrink: 0;
  }
  .card-action-link {
    background: none; border: none; color: var(--muted); font-size: 12.5px; font-weight: 600;
    cursor: pointer; padding: 4px 6px; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
  }
  .card-action-link:hover { color: var(--text); }
  .card-action-link.danger { color: var(--danger); }
  .card-action-link.danger:hover { color: #FF8199; }

  /* Menù a tendina "Contatta" nelle card Buddy */
  .contact-dropdown { position: relative; }
  .contact-dropdown-menu {
    position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 200;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    padding: 6px; box-shadow: 0 14px 34px rgba(0,0,0,.45);
  }
  .contact-dropdown-menu.apri-in-alto { top: auto; bottom: calc(100% + 6px); }
  /* La card che contiene il menù aperto deve salire sopra le card
     successive nella grid: senza questo, essendo #lista-compagni una
     grid con card "static", il dropdown (che sconfina fuori dalla card
     tramite position:absolute) finisce visivamente sotto la card
     successiva invece che sopra, tagliato a metà. */
  .card-compagno:has(.contact-dropdown-menu.mostra),
  .card-compagno.card-menu-attiva { position: relative; z-index: 50; }
  .contact-option {
    display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px;
    background: none; border: none; border-radius: 8px; color: var(--text); font-size: 13.5px; font-weight: 600;
    cursor: pointer; text-align: left;
  }
  .contact-option:hover:not(:disabled) { background: var(--surface-2); }
  .contact-option:disabled { color: var(--muted); opacity: .4; cursor: not-allowed; }
  .contact-option .opt-icon { flex-shrink: 0; display: flex; }
  .contact-option .opt-sub { font-size: 11px; color: var(--muted); font-weight: 500; margin-left: auto; }
  .tab-count {
    display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px;
    padding: 0 6px; border-radius: 20px; background: var(--surface-2); color: var(--muted);
    font-size: 11px; font-weight: 700; margin-left: 6px;
  }
  .hub-card {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 22px; cursor: pointer; transition: border-color .15s ease, transform .15s ease;
  }
  .hub-card:hover { border-color: var(--blue-light); transform: translateY(-2px); }
  .hub-card-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
  .hub-card-icon { width: 46px; height: 46px; border-radius: 12px; display: flex; align-items: center; justify-content: center; }
  .hub-card-icon svg { width: 22px; height: 22px; }
  .hub-card-icon.blue { background: var(--blue-bg); color: var(--blue-light); }
  .hub-card-icon.teal { background: var(--teal-bg); color: var(--teal); }
  .hub-card-icon.amber { background: var(--amber-bg); color: #FCD34D; }
  .hub-card-icon.violet { background: var(--violet-bg); color: var(--violet); }
  .hub-chevron { color: var(--muted); font-size: 20px; }
  .hub-card-title { font-weight: 800; font-size: 16.5px; margin-bottom: 4px; }
  .hub-card-stats { font-size: 12.5px; color: var(--muted); margin-bottom: 12px; padding-bottom: 12px; border-bottom: 1px solid var(--border); min-height: 16px; }
  .hub-card-preview { font-size: 12.5px; color: var(--muted); font-style: italic; min-height: 16px; }
  .hub-avatars-row { display: flex; align-items: center; }
  .hub-avatar {
    width: 26px; height: 26px; border-radius: 50%; background: var(--blue); color: #fff;
    font-size: 11px; font-weight: 700; display: flex; align-items: center; justify-content: center;
    border: 2px solid var(--surface); margin-left: -8px;
  }
  .hub-avatar:first-child { margin-left: 0; }

  .panel-add, .panel-compagni, .panel-faq { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; }

  .verifica-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; }
  .verifica-card-head { display: flex; align-items: flex-start; gap: 12px; }
  .verifica-card-icon {
    width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--blue-bg); color: var(--blue);
  }
  .verifica-card-icon.verificato { background: var(--green-bg); color: var(--green); }
  .verifica-card-icon svg { width: 19px; height: 19px; }
  .verifica-card-titolo { font-size: 16px; font-weight: 700; margin: 0; }
  .verifica-card-sub { font-size: 13px; color: var(--muted); margin: 3px 0 0; }

  .verifica-domanda { background: var(--bg); border-radius: var(--radius); padding: 14px 16px; margin: 16px 0 0; }
  .verifica-domanda-testo { font-size: 14px; font-weight: 700; margin: 0 0 10px; }
  .verifica-domanda-azioni { display: flex; gap: 8px; }
  .verifica-domanda-azioni .btn-primary, .verifica-domanda-azioni .btn-secondary { flex: 1; margin: 0; font-size: 13px; padding: 9px; }

  .verifica-rimuovi-row { border-top: 1px solid var(--border); margin-top: 16px; padding-top: 12px; display: flex; justify-content: flex-end; }
  .verifica-rimuovi-link { background: none; border: none; color: var(--muted); font-size: 12.5px; padding: 4px 2px; }
  .verifica-rimuovi-link:hover { color: var(--danger); }
  .quick-edit-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 6px; }
  .quick-edit-row select, .quick-edit-row input { width: auto; margin: 0; padding: 8px 10px; }

  #lista-compagni { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; padding-bottom: 180px; }
  @media (max-width: 640px) { #lista-compagni { grid-template-columns: 1fr; } }
  /* Fix overflow orizzontale: per spec CSS Grid ogni figlio diretto di
     una grid ha min-width:auto di default, cioè si espande fino alla
     larghezza minima del proprio contenuto (qui il testo del bottone
     "Contatta ⌄") anche oltre la colonna assegnata — è quello che
     sforava lo schermo su mobile. min-width:0 forza invece la card a
     rispettare la colonna e a lasciare che il testo interno vada a capo
     o si tronchi, come previsto dagli altri overflow-wrap già presenti. */
  #lista-compagni > .card-compagno { min-width: 0; }
  .card-compagno, .card-faq {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 12px; padding: 16px; overflow-wrap: break-word; word-break: break-word;
  }
  .card-faq { margin-bottom: 10px; }
  .contatti a { margin-right: 14px; color: var(--blue-light); font-size: 13px; font-weight: 700; text-decoration: none; }
  .privacy-note { font-size: 12px; color: var(--muted); font-style: italic; }
  .note { color: var(--muted); font-size: 13px; margin: 8px 0 0; overflow-wrap: break-word; word-break: break-word; }

  /* Riga espandibile "Come funziona questa sezione": sostituisce il vecchio
     paragrafo fisso in Forum/Domande esame/Risorse/Buddy (sia dentro la
     singola materia sia nelle viste globali). Di default è chiusa e occupa
     una sola riga; il testo esplicativo resta lo stesso di prima, solo
     nascosto finché l'utente non apre la riga. */
  .spiega-sezione { margin: 0 0 14px; }
  .spiega-sezione-toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    width: 100%; background: none; border: none; padding: 10px 0;
    font-size: 14px; font-weight: 700; color: var(--text); text-align: left; cursor: pointer;
    border-bottom: 1px solid var(--border);
  }
  .spiega-sezione-chevron { width: 16px; height: 16px; flex-shrink: 0; color: var(--muted); transition: transform .18s ease; }
  .spiega-sezione.aperta .spiega-sezione-chevron { transform: rotate(180deg); }
  .spiega-sezione-corpo {
    display: grid; grid-template-rows: 0fr; transition: grid-template-rows .2s ease;
  }
  .spiega-sezione.aperta .spiega-sezione-corpo { grid-template-rows: 1fr; }
  .spiega-sezione-corpo-inner { overflow: hidden; }
  .spiega-sezione-corpo .note { margin: 10px 0 0; }

  /* "Mostra altro": il testo lungo (risposte forum, domande d'esame,
     risposte suggerite) resta troncato a poche righe finché non si
     clicca il link, che lo espande senza ricaricare nulla. */
  .mostra-altro-blocco {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
  }
  .mostra-altro-blocco.espanso {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
  }
  .mostra-altro-link {
    display: inline-block;
    margin-top: 4px;
    color: var(--blue-light);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
  }
  .mostra-altro-link:hover { text-decoration: underline; }

  /* ===================== VOTO (su/giù) ===================== */
  .vote-widget { display: flex; flex-direction: column; align-items: center; margin-right: 14px; flex-shrink: 0; width: 30px; }
  .forum-tempo-row { margin-bottom: 8px; }
  .forum-vote-row-h { display: flex; align-items: center; gap: 6px; }
  .forum-vote-row-h .vote-btn { width: auto; padding: 2px 6px; }
  .forum-vote-row-h .vote-score { font-size: 13.5px; }
  .vote-btn { background: none; border: none; font-size: 20px; line-height: 1; cursor: pointer; color: var(--muted); padding: 3px 0; width: 100%; border-radius: 6px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
  .vote-btn:hover { background: var(--surface); color: var(--text); }
  .vote-btn.up.active { color: #22C55E; }
  .vote-btn.down.active { color: #EF4444; }
  .vote-score { display: block; font-weight: 800; font-size: 13.5px; text-align: center; padding: 1px 0; }

  /* ===================== BUDDY / CONVERSAZIONI ===================== */
  .card-conversazione { background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 14px; margin-bottom: 10px; cursor: pointer; display: flex; gap: 12px; align-items: flex-start; }
  .card-conversazione:hover { border-color: var(--blue-light); }
  .card-conversazione-top { display: flex; justify-content: space-between; align-items: center; }

  /* ===================== MODALI (aggiungi materia / chat) ===================== */
  .modal {
    position: fixed; inset: 0; background: var(--modal-overlay);
    display: flex; align-items: center; justify-content: center; z-index: 250;
  }
  .modal-content {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px; width: 90%; max-width: 420px;
    max-height: 85vh; overflow-y: auto; display: flex; flex-direction: column; position: relative;
    box-shadow: 0 20px 60px rgba(0,0,0,.5); padding-bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  }
  .modal-close { position: absolute; top: 14px; right: 16px; background: none; border: none; font-size: 18px; color: var(--muted); }

  /* Modale di conferma custom: sostituisce window.confirm(), che in
     WKWebView (app nativa iOS) non è affidabile — a volte non compare
     affatto, lasciando l'azione bloccata senza feedback per l'utente.
     Vedi confermaCustom() in core.js.
     z-index dedicato: deve stare sopra ai menu contestuali long-press
     (.bb-copia-menu, z-index 500) altrimenti la conferma di "Segnala"/
     "Elimina" su un messaggio in chat resta coperta dal menu e sembra
     non aprirsi affatto finché non si esce dalla chat. */
  #confirm-modal { z-index: 550; }
  #confirm-modal .modal-content { max-width: 360px; text-align: center; gap: 18px; }
  #confirm-modal-testo { font-size: 15px; line-height: 1.5; color: var(--text); margin: 0; }
  #confirm-modal-azioni { display: flex; gap: 10px; }
  #confirm-modal-azioni button { flex: 1; margin: 0; }
  /* Azione "pericolosa" (elimina materia/messaggio/account, blocca
     utente, ecc.): bottone pieno rosso invece del generico .btn-danger
     rosa chiaro, per dare più peso visivo a un'azione irreversibile. */
  #confirm-modal-azioni .btn-danger {
    background: var(--danger); color: #fff; border-color: var(--danger);
  }
  #confirm-modal-azioni .btn-danger:hover { filter: brightness(1.08); }
  #confirm-modal-azioni .btn-danger:active { transform: scale(.97); }

  /* ===================== VARIANTE "PERICOLOSA" (blocca/elimina/segnala) =====================
     Applicata quando confermaCustom() riceve { pericoloso: true }: icona/
     avatar centrato in alto (con badge scudo se è coinvolta una persona),
     titolo in grassetto, testo secondario, separatore, elenco puntato
     delle conseguenze, bottoni pill arrotondati. Le conferme "normali"
     (non pericolose) restano invariate: solo testo + due bottoni. */
  #confirm-modal.confirm-modal-pericoloso .modal-content { max-width: 380px; padding: 28px 24px 24px; gap: 14px; }
  #confirm-modal-icona { display: flex; justify-content: center; position: relative; margin-bottom: 4px; }
  #confirm-modal-icona .mini-avatar { width: 64px !important; height: 64px !important; font-size: 26px !important; }
  .confirm-modal-icona-cerchio {
    width: 64px; height: 64px; border-radius: 50%; background: var(--danger-bg);
    display: flex; align-items: center; justify-content: center;
  }
  /* Badge scudo rosso in basso a destra dell'avatar, come nel riferimento
     visivo: posizionato rispetto al wrapper #confirm-modal-icona (che è
     un flex centrato), quindi ancorato al bordo destro dell'avatar da 64px. */
  .confirm-modal-badge-scudo {
    position: absolute; bottom: -2px; right: calc(50% - 38px);
    width: 24px; height: 24px; border-radius: 50%; background: var(--danger);
    border: 2.5px solid var(--surface); display: flex; align-items: center; justify-content: center;
  }
  #confirm-modal-titolo { font-size: 18px; font-weight: 800; color: var(--text); margin: 0; }
  #confirm-modal.confirm-modal-pericoloso #confirm-modal-testo { color: var(--muted); font-size: 14px; }
  #confirm-modal-dettagli {
    list-style: none; margin: 4px 0 0; padding: 14px 0 0; text-align: left;
    border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px;
  }
  #confirm-modal-dettagli li {
    position: relative; padding-left: 16px; font-size: 13.5px; color: var(--muted); line-height: 1.4;
  }
  #confirm-modal-dettagli li::before {
    content: ''; position: absolute; left: 0; top: 6px; width: 6px; height: 6px;
    border-radius: 50%; background: var(--border);
  }
  #confirm-modal.confirm-modal-pericoloso #confirm-modal-azioni {
    padding-top: 14px; border-top: 1px solid var(--border); margin-top: 2px;
  }
  #confirm-modal.confirm-modal-pericoloso #confirm-modal-azioni button {
    border-radius: 30px; padding: 13px 0; font-size: 14.5px;
  }

  /* ===================== MODALE "COME TI CONTATTANO" =====================
     Stesso linguaggio visivo della variante pericolosa qui sopra (icona a
     cerchio in alto, testo centrato, bottoni pill) ma in blu/neutro
     invece che rosso, essendo puramente informativo. Vedi
     mostraComeContattanoMe() in pagine.js per il contenuto dinamico. */
  #contatti-info-modal { z-index: 550; }
  .contatti-info-modal-content { max-width: 380px; text-align: center; padding: 28px 24px 24px; gap: 14px; }
  .contatti-info-icona {
    width: 64px; height: 64px; margin: 0 auto 4px; border-radius: 50%;
    background: var(--blue-bg); color: var(--blue-light);
    display: flex; align-items: center; justify-content: center;
  }
  .contatti-info-icona svg { width: 26px; height: 26px; }
  .contatti-info-righe {
    display: flex; flex-direction: column; gap: 4px; text-align: left;
    border-top: 1px solid var(--border); padding-top: 14px; margin-top: 2px;
  }
  .contatti-info-riga {
    display: flex; align-items: center; gap: 12px; padding: 10px 0;
  }
  .contatti-info-riga + .contatti-info-riga { border-top: 1px solid var(--border); }
  .contatti-info-riga-icona {
    width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
    background: var(--surface-2); display: flex; align-items: center; justify-content: center;
  }
  .contatti-info-riga-testi { flex: 1; min-width: 0; }
  .contatti-info-riga-label { font-weight: 700; font-size: 14px; color: var(--text); }
  .contatti-info-riga-valore { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .contatti-info-riga-stato {
    flex-shrink: 0; font-size: 12.5px; font-weight: 700; padding: 4px 10px; border-radius: 20px;
  }
  .contatti-info-riga-stato.attivo { background: var(--green-bg); color: var(--green); }
  .contatti-info-riga-stato.off { background: var(--surface-2); color: var(--muted); }
  /* Riga "spenta" (canale non disponibile): icona e testi attenuati, non
     solo lo stato a destra, per rendere subito chiaro visivamente cosa
     manca — coerente con l'icona Telegram sbiadita nel riferimento. */
  .contatti-info-riga.non-attiva .contatti-info-riga-icona,
  .contatti-info-riga.non-attiva .contatti-info-riga-label { opacity: .5; }
  .contatti-info-suggerimento { text-align: left; font-size: 12.5px; margin-top: 4px; }
  .contatti-info-azioni { display: flex; gap: 10px; padding-top: 14px; border-top: 1px solid var(--border); margin-top: 2px; }
  .contatti-info-azioni button { flex: 1; margin: 0; border-radius: 30px; padding: 13px 0; font-size: 14.5px; }

  /* ===================== MODALE "MODIFICA MATERIA" ===================== */
  /* Stesso linguaggio visivo dei due modali sopra (icona a cerchio,
     titolo centrato, separatori) applicato al modale esistente di
     modifica materia — i campi restano quelli di sempre (autosave a ogni
     cambiamento, nessun bottone Salva: vedi cambiaStato/cambiaData/
     cambiaNote in pagine.js), qui solo la cornice visiva è aggiornata. */
  .edit-materia-modal-content { text-align: center; padding: 28px 24px 24px; }
  .edit-materia-icona {
    width: 64px; height: 64px; margin: 0 auto 4px; border-radius: 50%;
    background: var(--blue-bg); color: var(--blue-light);
    display: flex; align-items: center; justify-content: center;
  }
  .edit-materia-icona svg { width: 28px; height: 28px; }
  .edit-materia-sottotitolo { margin: 0 0 4px; font-size: 14px; }
  .edit-materia-separatore { border-top: 1px solid var(--border); margin: 14px 0; }
  /* I campi dentro restano allineati a sinistra come qualunque form,
     nonostante l'header sopra sia centrato. */
  .edit-materia-modal-content label,
  .edit-materia-modal-content .custom-select-wrap,
  .edit-materia-modal-content input,
  .edit-materia-modal-content textarea,
  .edit-materia-modal-content .progress-bar { text-align: left; }
  .edit-materia-progress-bar { margin: -8px 0 16px; }
  .edit-materia-chiudi-bottone { width: 100%; margin: 0; }

  /* ===================== STILE COMUNE POPUP "FORM" =====================
     Applicato a tutti i modali di inserimento/modifica (Aggiungi materia,
     Aggiungi risorsa, Fai una domanda, Segnala domanda d'esame, Modifica
     materia): titolo grande a sinistra (non centrato, a differenza dei
     modali di conferma/info più piccoli sopra) + bottone chiudi rotondo
     in alto a destra, sottotitolo grigio sotto il titolo, ogni campo con
     una piccola icona + etichetta maiuscola sopra, ed eventuale nota
     descrittiva subito sotto l'etichetta. I colori restano quelli
     standard del sito (bottoni pieni, niente gradienti). */
  .form-modal-content { padding: 26px 24px 24px; }
  .form-modal-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
  .form-modal-titoli { min-width: 0; }
  .form-modal-titoli h3 { margin: 0; font-size: 21px; }
  .form-modal-sottotitolo { margin: 4px 0 0; font-size: 13.5px; }
  /* Il bottone chiudi torna a un cerchio pieno (invece della semplice ✕
     fluttuante di .modal-close) per stare all'altezza del titolo grande,
     coerente col mockup fornito. */
  .form-modal-chiudi {
    flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%;
    background: var(--surface-2); border: none; color: var(--muted);
    display: flex; align-items: center; justify-content: center; cursor: pointer;
    font-size: 15px; margin-top: 2px;
  }
  .form-modal-chiudi:hover { color: var(--text); }
  .form-modal-campo { margin-top: 18px; }
  .form-modal-campo-label {
    display: flex; align-items: center; gap: 6px;
    font-size: 11.5px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
    color: var(--muted); margin: 18px 0 6px;
  }
  /* Dentro .form-modal-campo il margine superiore lo dà già il
     contenitore stesso: la label non deve raddoppiarlo. */
  .form-modal-campo .form-modal-campo-label { margin-top: 0; }
  .form-modal-campo-label svg { width: 15px; height: 15px; flex-shrink: 0; }
  .form-modal-campo-nota { margin: -2px 0 8px; font-size: 12.5px; }
  .form-modal-bottone { width: 100%; margin: 22px 0 0; }

  /* Il bottone "Ho già l'app installata" nella schermata di benvenuto
     dell'onboarding (#btn-continua-app-onboarding) riusa .btn-secondary,
     già definito altrove: nessuno stile aggiuntivo necessario. Un margine
     sotto lo separa dal bottone "Inizia" subito dopo. */
  #btn-continua-app-onboarding { margin-bottom: 12px; }

  /* Il modale di conferma dipartimento vive sopra #page-scelta-corso, che è
     una pagina a schermo intero con z-index 500: senza questa regola il
     modale (z-index 250 di default) resterebbe nascosto dietro di essa. */
  #conferma-dipartimento-modal { z-index: 600; }

  /* ===================== CHAT: BLOCCO SIGILLATO A 3 LIVELLI =====================
     #page-chat è un contenitore fisso a schermo intero, sempre sopra a tutto
     il resto (topbar, barra di navigazione, qualunque altra pagina). Dentro,
     .chat-shell è una colonna flex con esattamente 3 figli:
       1. header  → flex-shrink:0, sempre in cima, non si muove mai
       2. messaggi → flex:1 + overflow-y:auto, è l'UNICA parte che scorre
       3. input   → flex-shrink:0, sempre in fondo
     Niente logiche che nascondono/mostrano la barra di navigazione in base
     alla tastiera: il contenitore è già sopra a tutto, quindi non serve. */
  #page-chat.active {
    position: fixed; inset: 0; z-index: 300; background: var(--bg);
    display: flex; /* .page normalmente usa block: qui serve flex per centrare .chat-shell */
    padding: 0 !important; margin: 0 !important; max-width: none !important;
    animation: none !important; /* la pagina chat gestisce la propria "transform" via JS
      per seguire la tastiera: l'animazione generica di apertura pagina la terrebbe
      occupata (anche a fine animazione, per via di "fill-mode: both") e la
      correzione sotto non riuscirebbe mai a muovere davvero il blocco. */
  }
  /* Mentre la chat è aperta, blocchiamo lo scroll di TUTTA la pagina: senza
     questo, quando il telefono porta in vista il campo di testo per aprire
     la tastiera, sposta anche la pagina sotto — e la chat "salta" invece di
     restare ferma con l'input ancorato sopra la tastiera. */
  body.chat-attiva { position: fixed; inset: 0; width: 100%; overflow: hidden; }
  .chat-shell {
    flex: 1; display: flex; flex-direction: column; min-height: 0; width: 100%;
    height: 100vh; height: 100dvh; /* dvh evita i salti dovuti alla tastiera su Safari/Chrome mobile */
  }

  .chat-shell-header {
    flex-shrink: 0; display: flex; align-items: center; gap: 12px;
    /* Su Android (TWA) env(safe-area-inset-top) a volte risulta 0 anche se
       la vera status bar di sistema occupa spazio reale sopra la webview:
       #status-bar-bg (z-index 9998, sempre sopra a tutto) resta quindi
       trasparente proprio dove serve, lasciando una linea bianca/di sistema
       visibile sopra l'header della chat. Usando lo stesso max(...,24px) già
       adottato per #status-bar-bg garantiamo un padding minimo anche quando
       la safe-area reale è 0, così l'header copre sempre quello spazio. */
    padding: calc(max(env(safe-area-inset-top, 0px), 24px) + 14px) 16px 14px;
    border-bottom: 1px solid var(--border); background: var(--surface);
  }
  .chat-shell-header h2 { margin: 0; font-size: 17px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Menu "⋮" nell'header della chat (Blocca utente, ecc.) */
  /* Bottone "chiudi tastiera": visibile solo mentre la tastiera è aperta
     (mostrato/nascosto via JS in aggiornaAltezzaChat/esciDaModalitaTastiera),
     per lasciare all'utente il controllo di quando abbassarla, invece di
     doverla chiudere solo toccando fuori dal campo di testo. */
  .chat-shell-chiudi-tastiera {
    background: none; border: none; padding: 6px; margin: 0; cursor: pointer;
    color: var(--text); display: none; align-items: center; justify-content: center;
    flex: 0 0 auto;
  }
  .chat-shell-chiudi-tastiera.mostra { display: flex; }
  .chat-shell-chiudi-tastiera svg { width: 20px; height: 20px; }

  .chat-shell-menu-wrap { position: relative; flex: 0 0 auto; }
  .chat-shell-menu-btn {
    background: none; border: none; padding: 6px; margin: 0; cursor: pointer;
    color: var(--text); display: flex; align-items: center; justify-content: center;
  }
  .chat-shell-menu-btn svg { width: 20px; height: 20px; }
  .chat-shell-menu {
    position: absolute; top: calc(100% + 4px); right: 0; z-index: 60;
    background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0,0,0,.28); padding: 6px; min-width: 160px;
  }
  .chat-shell-menu.hidden { display: none; }
  .chat-shell-menu button {
    width: 100%; text-align: left; background: none; border: none; padding: 10px 12px;
    border-radius: 8px; font-size: 14px; font-family: inherit; color: var(--danger); cursor: pointer;
  }
  .chat-shell-menu button:hover { background: var(--surface-2); }

  .chat-shell-messaggi {
    flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 14px 16px; display: flex; flex-direction: column; gap: 6px;
  }
  .chat-shell-messaggi .msg { min-width: 0; }

  .chat-shell-input {
    flex-shrink: 0; display: flex; gap: 10px; align-items: flex-end;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--border); background: var(--surface);
  }
  .chat-shell-input input,
  .chat-shell-input textarea { flex: 1; margin: 0; }
  .chat-shell-input textarea { max-height: 160px; }
  .chat-shell-input button { width: auto; padding: 0 20px; margin: 0; flex-shrink: 0; height: 42px; }

  .msg { background: var(--surface-2); padding: 9px 13px; border-radius: 12px; margin-bottom: 8px; max-width: 80%; font-size: 14px; overflow-wrap: break-word; word-break: break-word; }
  .msg.mine { background: var(--blue); color: #fff; margin-left: auto; }

  /* ===================== TOAST ===================== */
  .toast {
    position: fixed; bottom: -80px; left: 50%; transform: translateX(-50%);
    background: var(--surface); border: 1px solid var(--border); color: var(--text); padding: 12px 22px; border-radius: 10px;
    font-size: 14px; font-weight: 600; transition: bottom .3s ease; z-index: 400;
  }
  .toast.show { bottom: calc(70px + env(safe-area-inset-bottom, 0px) + 16px); }
  .toast.error { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger); }

  /* ===================== POPUP FEEDBACK ===================== */
  /* Leggero, in basso, non copre il centro schermo. Compare/scompare con una
     transizione morbida (slide + fade), stesso spirito del toast. */
  .feedback-popup {
    position: fixed; inset: 0; z-index: 390; pointer-events: none;
  }
  .feedback-popup.hidden { display: none; }
  .feedback-popup-card {
    position: fixed; left: 16px; right: 16px; bottom: -140px; max-width: 360px; margin: 0 auto;
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 18px 18px 16px; box-shadow: 0 14px 34px rgba(0,0,0,.35);
    transition: bottom .35s ease; pointer-events: auto;
  }
  .feedback-popup.show .feedback-popup-card { bottom: 24px; }
  .feedback-popup-close {
    position: absolute; top: 8px; right: 10px; background: none; border: none;
    color: var(--muted); font-size: 15px; cursor: pointer; padding: 6px; line-height: 1;
  }
  .feedback-popup-close:hover { color: var(--text); }
  .feedback-popup-domanda { font-size: 14.5px; font-weight: 700; margin: 0 20px 12px 0; }
  .feedback-popup-emoji-row { display: flex; gap: 10px; }
  .feedback-popup-emoji {
    flex: 1; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px;
    padding: 10px 0; font-size: 22px; cursor: pointer; transition: border-color .15s ease, transform .1s ease;
  }
  .feedback-popup-emoji:hover { border-color: var(--blue-light); }
  .feedback-popup-emoji:active { transform: scale(.94); }
  #feedback-popup-step-2-azioni { display: flex; gap: 10px; flex-wrap: wrap; }
  #feedback-popup-step-2-azioni .btn-small { flex: 1; min-width: 120px; }

  /* ===================== RIFINITURE MOBILE ===================== */
  @media (max-width: 780px) {
    /* iOS ingrandisce automaticamente la pagina quando un campo ha font-size sotto i 16px */
    input, select, textarea { font-size: 16px; }
    .btn-small { padding: 9px 14px; font-size: 13.5px; }
    .vote-btn { padding: 7px 0; font-size: 17px; }
  }
  @media (max-width: 600px) {
    .quick-edit-row { flex-direction: column; align-items: stretch; }
    .quick-edit-row select, .quick-edit-row input {
      width: 100%; height: 46px; padding: 0 14px; box-sizing: border-box; margin: 0;
    }
    .quick-edit-row button {
      width: 100%; height: 46px; padding: 0 14px; box-sizing: border-box;
      display: flex; align-items: center; justify-content: center; line-height: 1;
    }
  }

  /* ===================== SPLASH SCREEN ===================== */
  #splash-screen {
    position: fixed; inset: 0; z-index: 9999; background: linear-gradient(160deg, #0B1220, #101B33);
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
    transition: opacity .35s ease, visibility .35s ease;
  }
  #splash-screen.hide { opacity: 0; visibility: hidden; pointer-events: none; }
  .splash-logo {
    width: 78px; height: 78px; border-radius: 22px; background: linear-gradient(135deg, var(--blue), var(--teal));
    display: flex; align-items: center; justify-content: center; font-size: 34px;
    animation: splashPop .55s cubic-bezier(.34,1.56,.64,1);
    box-shadow: 0 8px 30px rgba(59,130,246,.35);
  }
  .splash-title { color: #fff; font-weight: 800; font-size: 19px; letter-spacing: .2px; animation: splashFadeIn .5s ease .1s both; }
  .splash-dots { display: flex; gap: 6px; animation: splashFadeIn .5s ease .2s both; }
  .splash-dots span {
    width: 6px; height: 6px; border-radius: 50%; background: var(--blue-light); opacity: .35;
    animation: splashBlink 1.1s ease-in-out infinite;
  }
  .splash-dots span:nth-child(2) { animation-delay: .15s; }
  .splash-dots span:nth-child(3) { animation-delay: .3s; }
  @keyframes splashPop { from { transform: scale(.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
  @keyframes splashFadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
  @keyframes splashBlink { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

  /* ===================== TRANSIZIONI TRA PAGINE =====================
     from parte da opacity .55 (non 0): la classe .active viene tolta e
     riaggiunta ad ogni showPage(), quindi l'animazione riparte sempre da
     zero anche quando si torna su una pagina già vista poco prima (es. la
     freccia "← Indietro", che richiama showPage sulla stessa pagina di
     partenza) — partire da 0 lasciava vedere per un istante lo sfondo
     sotto, percepito come un flash bianco/vuoto. Con .55 la transizione
     resta visibile sulle pagine nuove ma senza quel buco. */
  .page.active {
    animation: pageIn .28s cubic-bezier(.25,.8,.4,1) both;
  }
  @keyframes pageIn {
    from { opacity: .55; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
  }
  @media (prefers-reduced-motion: reduce) {
    .page.active { animation: none; }
  }

  /* ===================== FEEDBACK TATTILE SUI TAP ===================== */
  .btn-primary, .btn-secondary, .btn-danger, .btn-small, .vote-btn,
  .card-materia, .card-conversazione, .card-compagno, .sidebar-link,
  .contact-option, .stat-card, .btn-back {
    transition: transform .12s ease, opacity .12s ease;
  }
  .btn-primary:active, .btn-secondary:active, .btn-danger:active, .btn-small:active, .vote-btn:active,
  .card-materia:active, .card-conversazione:active, .card-compagno:active, .sidebar-link:active,
  .contact-option:active {
    transform: scale(.96); opacity: .85;
  }

  /* ===================== SKELETON LOADING ===================== */
  .skeleton-riga, .skeleton-card { position: relative; overflow: hidden; background: var(--surface-2); border-radius: 8px; }
  .skeleton-riga::after, .skeleton-card::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.06), transparent);
    animation: skeletonShine 1.3s ease-in-out infinite;
  }
  @keyframes skeletonShine { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
  .skeleton-card { height: 130px; border: 1px solid var(--border); }
  .skeleton-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
  .skeleton-riga { height: 58px; margin-bottom: 10px; border: 1px solid var(--border); }

  /* ===================== PULL-TO-REFRESH ===================== */
  #ptr-indicator {
    position: fixed; top: 0; left: 50%; transform: translate(-50%, -46px);
    width: 34px; height: 34px; border-radius: 50%; background: var(--surface); border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center; font-size: 15px; z-index: 140;
    transition: transform .15s ease, opacity .15s ease; opacity: 0;
    box-shadow: 0 4px 14px rgba(0,0,0,.25);
  }
  #ptr-indicator.spin span { display: inline-block; animation: ptrSpin .6s linear infinite; }
  @keyframes ptrSpin { to { transform: rotate(360deg); } }
  /* ===================================================================
     NUOVA LANDING PAGE (#landing) — navbar, hero, funzionalità, recensioni, CTA
     Le variabili --lp-* puntano a quelle globali del tema, cosi la landing
     segue il tema chiaro/scuro scelto dall'utente come il resto dell'app.
     =================================================================== */

  #landing {
    --lp-bg: var(--bg);
    --lp-surface: var(--surface);
    --lp-border: var(--border);
    --lp-text: var(--text);
    --lp-muted: var(--muted);
    --lp-blue: var(--blue);
    --lp-blue-light: var(--blue-light);
    --lp-teal: var(--teal);
    background: var(--lp-bg);
    color: var(--lp-text);
    height: 100vh;
    height: 100dvh;
    width: 100%;
    flex: 1 1 100%;
    font-family: var(--font-body);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
    scroll-behavior: smooth;
  }
  #landing h1, #landing h2, #landing h3 { color: var(--lp-text); font-family: 'Georgia', 'Times New Roman', serif; }
  #landing p { color: var(--lp-muted); }
  #landing a { text-decoration: none; }

  /* ---------- Navbar ---------- */
  .landing-nav {
    position: sticky; top: 0; z-index: 20;
    background: rgba(243,245,250,.85); backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--lp-border);
  }
  .landing-nav-inner {
    max-width: 1280px; margin: 0 auto; padding: 14px 24px;
    display: flex; align-items: center; gap: 28px;
  }
  .landing-nav-brand {
    display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 17px;
    color: var(--lp-text); font-family: 'Georgia', serif; white-space: nowrap;
  }
  .landing-nav-logo {
    width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
    background: linear-gradient(135deg, var(--lp-blue), var(--lp-teal));
    display: flex; align-items: center; justify-content: center;
  }
  .landing-nav-links { display: flex; align-items: center; gap: 26px; flex: 1; }
  .landing-nav-links a { color: var(--lp-text); font-weight: 500; font-size: 14.5px; opacity: .85; }
  .landing-nav-links a:hover { opacity: 1; color: var(--lp-blue); }

  .landing-nav-right { display: flex; align-items: center; gap: 10px; }
  .landing-device-toggle {
    display: flex; align-items: center; background: var(--lp-surface); border: 1px solid var(--lp-border);
    border-radius: 10px; padding: 3px; gap: 2px;
  }
  .landing-device-toggle button {
    display: flex; align-items: center; gap: 6px; border: none; background: transparent; cursor: pointer;
    padding: 7px 12px; border-radius: 7px; font-size: 13px; font-weight: 600; color: var(--lp-muted);
    transition: background .15s ease, color .15s ease;
  }
  .landing-device-toggle button svg { width: 15px; height: 15px; }
  .landing-device-toggle button.active { background: var(--lp-bg); color: var(--lp-text); box-shadow: 0 1px 2px rgba(15,23,42,.08); }
  .landing-device-toggle button:not(.active):hover { color: var(--lp-text); }

  .landing-btn-ghost {
    background: transparent; border: none; color: var(--lp-text); font-weight: 600; font-size: 14.5px;
    padding: 9px 14px; border-radius: 9px; cursor: pointer; white-space: nowrap;
  }
  .landing-btn-ghost:hover { background: var(--lp-border); }
  .landing-btn-ghost-dark {
    background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.25); color: #fff; font-weight: 700; font-size: 15px;
    padding: 13px 20px; border-radius: 10px; cursor: pointer; white-space: nowrap; transition: background .15s ease;
  }
  .landing-btn-ghost-dark:hover { background: rgba(255,255,255,.18); }
  html[data-theme="light"] .landing-btn-ghost-dark {
    background: var(--lp-bg); border: 1px solid var(--lp-border); color: var(--lp-text);
  }
  html[data-theme="light"] .landing-btn-ghost-dark:hover { background: var(--lp-border); }

  .landing-btn-primary {
    background: linear-gradient(120deg, var(--lp-blue), var(--lp-teal));
    color: #fff; border: none; font-weight: 700; font-size: 14.5px;
    padding: 10px 18px; border-radius: 9px; cursor: pointer; white-space: nowrap;
    transition: transform .12s ease, box-shadow .15s ease;
    box-shadow: 0 2px 10px rgba(37,99,235,.25);
  }
  .landing-btn-primary:hover { box-shadow: 0 4px 16px rgba(37,99,235,.35); }
  .landing-btn-primary:active { transform: scale(.97); }

  .landing-btn-secondary {
    background: var(--lp-surface); color: var(--lp-text); border: 1.5px solid var(--lp-border);
    font-weight: 700; font-size: 14.5px; padding: 10px 18px; border-radius: 9px; cursor: pointer; white-space: nowrap;
    transition: border-color .15s ease;
  }
  .landing-btn-secondary:hover { border-color: var(--lp-blue-light); }

  .landing-btn-lg { padding: 14px 22px; font-size: 15.5px; border-radius: 10px; }

  .landing-nav-burger { display: none; background: none; border: none; color: var(--lp-text); cursor: pointer; padding: 6px; }
  .landing-nav-burger svg { width: 22px; height: 22px; }

  .landing-mobile-menu {
    display: none; flex-direction: column; gap: 4px; padding: 10px 20px 18px;
    border-top: 1px solid var(--lp-border);
  }
  .landing-mobile-menu.open { display: flex; }
  .landing-mobile-menu a { color: var(--lp-text); font-weight: 600; font-size: 15px; padding: 10px 4px; }
  .landing-mobile-menu-actions { display: flex; gap: 10px; margin-top: 10px; }
  .landing-mobile-menu-actions .landing-btn-ghost,
  .landing-mobile-menu-actions .landing-btn-primary { flex: 1; text-align: center; }

  /* ---------- Hero ---------- */
  .landing-hero { padding: 64px 24px 40px; }
  .landing-hero-inner {
    max-width: 1280px; margin: 0 auto;
    display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center;
  }
  .hero-eyebrow {
    display: inline-flex; align-items: center; gap: 6px; background: var(--lp-surface); border: 1px solid var(--lp-border);
    color: var(--lp-blue); font-weight: 700; font-size: 12.5px; padding: 7px 14px; border-radius: 20px; margin-bottom: 20px;
  }
  .landing-hero-title { font-size: 52px; line-height: 1.08; margin: 0 0 18px; font-weight: 800; letter-spacing: -.01em; }
  .landing-hero-sub { font-size: 17px; line-height: 1.55; margin: 0 0 28px; max-width: 480px; }
  .landing-hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 26px; }
  .landing-hero-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 18px 24px; }
  .landing-hero-checks li { display: flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; color: var(--lp-text); }
  .landing-hero-checks svg { width: 17px; height: 17px; flex-shrink: 0; }

  .landing-hero-right { position: relative; }
  .landing-mock-card {
    background: var(--lp-surface); border: 1px solid var(--lp-border); border-radius: 20px; padding: 26px;
    box-shadow: 0 20px 60px -20px rgba(15,23,42,.25); position: relative; max-width: 480px; margin: 0 auto;
  }
  .landing-mock-toast {
    position: absolute; top: -18px; right: 8px; background: #16A34A; color: #fff; font-size: 12.5px; font-weight: 700;
    padding: 9px 14px; border-radius: 12px; box-shadow: 0 8px 20px rgba(22,163,74,.35); z-index: 2;
  }
  .landing-mock-toast b { display: block; font-weight: 800; }
  .landing-mock-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 18px; }
  .landing-mock-label { font-size: 11.5px; font-weight: 700; color: var(--lp-muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 4px; }
  .landing-mock-title { font-size: 19px; font-weight: 800; font-family: 'Georgia', serif; }
  .landing-mock-pill { background: var(--blue-bg); color: var(--lp-blue-light); font-size: 12px; font-weight: 700; padding: 5px 11px; border-radius: 20px; white-space: nowrap; }
  .landing-mock-progress { margin-bottom: 20px; }
  .landing-mock-progress-row { display: flex; justify-content: space-between; font-size: 13px; font-weight: 600; color: var(--lp-muted); margin-bottom: 8px; }
  .landing-mock-bar { height: 8px; border-radius: 6px; background: var(--lp-border); overflow: hidden; }
  .landing-mock-bar span { display: block; height: 100%; background: linear-gradient(90deg, var(--lp-blue), var(--lp-blue-light)); border-radius: 6px; }
  .landing-mock-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 18px; }
  .landing-mock-stat {
    background: var(--lp-bg); border: 1px solid var(--lp-border); border-radius: 12px; padding: 12px 10px; text-align: left;
  }
  .landing-mock-stat svg { width: 17px; height: 17px; color: var(--lp-blue); margin-bottom: 8px; }
  .landing-mock-stat b { display: block; font-size: 18px; font-weight: 800; line-height: 1.2; }
  .landing-mock-stat span { display: block; font-size: 11.5px; color: var(--lp-muted); font-weight: 600; }
  .landing-mock-question { background: var(--lp-bg); border: 1px solid var(--lp-border); border-radius: 14px; padding: 16px; }

  /* Card materia "vera" (stessa struttura di .card-materia nella dashboard)
     riutilizzata nella hero della landing: niente hover/cursor da lista cliccabile,
     e un filo di margine sotto prima delle statistiche. */
  .landing-mock-realcard { cursor: default; margin-bottom: 18px; padding: 20px; }
  .landing-mock-realcard:hover { transform: none; border-color: var(--border); }
  .landing-mock-question-label { font-size: 11px; font-weight: 700; color: var(--lp-muted); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 8px; }
  .landing-mock-question p { font-size: 13.5px; color: var(--lp-text); line-height: 1.45; margin: 0 0 12px; font-weight: 500; }
  .landing-mock-question-tags { display: flex; gap: 8px; flex-wrap: wrap; }
  .tag-amber { background: var(--amber-bg); color: var(--amber); font-size: 11.5px; font-weight: 700; padding: 4px 10px; border-radius: 20px; }
  .tag-neutral { background: var(--lp-border); color: var(--lp-muted); font-size: 11.5px; font-weight: 700; padding: 4px 10px; border-radius: 20px; }

  /* ---------- Sezioni generiche ---------- */
  .landing-section { padding: 72px 24px; scroll-margin-top: 70px; }
  .landing-section-alt { background: var(--lp-surface); }
  .landing-section-inner { max-width: 1180px; margin: 0 auto; }
  .landing-section-head { text-align: center; max-width: 680px; margin: 0 auto 48px; }
  .landing-eyebrow-tag { color: var(--lp-blue); font-weight: 800; font-size: 12.5px; letter-spacing: .06em; margin-bottom: 12px; }
  .landing-section-head h2 { font-size: 36px; line-height: 1.2; margin: 0 0 16px; font-weight: 800; }
  .landing-section-head p { font-size: 16px; line-height: 1.55; margin: 0; }

  /* ---------- Funzionalità ---------- */
  .landing-features-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
  .landing-feature-card {
    background: var(--lp-surface); border: 1px solid var(--lp-border); border-radius: 16px; padding: 26px;
    transition: transform .15s ease, box-shadow .15s ease;
  }
  .landing-feature-card:hover { transform: translateY(-3px); box-shadow: 0 14px 34px -14px rgba(15,23,42,.18); }
  .landing-feature-icon {
    width: 46px; height: 46px; border-radius: 12px; display: flex; align-items: center; justify-content: center; margin-bottom: 16px;
  }
  .landing-feature-icon svg { width: 22px; height: 22px; }
  .icon-blue { background: var(--blue-bg); color: var(--blue-light); }
  .icon-green { background: var(--green-bg); color: var(--green); }
  .icon-amber { background: var(--amber-bg); color: var(--amber); }
  .icon-rose { background: var(--pink-bg); color: var(--pink); }
  .icon-teal { background: var(--teal-bg); color: var(--teal); }
  .landing-feature-card h3 { font-size: 17px; margin: 0 0 8px; font-weight: 800; font-family: var(--font-body); }
  .landing-feature-card p { font-size: 14px; line-height: 1.55; margin: 0; }

  /* ---------- Recensioni ---------- */
  .landing-reviews-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
  .landing-review-card { background: var(--lp-surface); border: 1px solid var(--lp-border); border-radius: 16px; padding: 26px; }
  .landing-review-quote { font-size: 34px; color: var(--lp-blue-light); font-family: Georgia, serif; line-height: 1; margin-bottom: 4px; }
  .landing-review-card p { font-size: 14.5px; line-height: 1.6; color: var(--lp-text); margin: 0 0 20px; }
  .landing-review-author { display: flex; align-items: center; gap: 12px; padding-top: 16px; border-top: 1px solid var(--lp-border); }
  .landing-review-avatar {
    width: 38px; height: 38px; border-radius: 50%; background: var(--blue-bg); color: var(--lp-blue);
    display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; flex-shrink: 0;
  }
  .landing-review-author b { display: block; font-size: 14px; color: var(--lp-text); }
  .landing-review-author span { display: block; font-size: 12.5px; color: var(--lp-muted); }

  /* ---------- CTA finale ---------- */
  .landing-final-cta {
    background: linear-gradient(120deg, #0B1220 0%, #0F1F35 55%, #0C2B28 100%);
    border-radius: 24px; padding: 64px 40px; text-align: center; position: relative; overflow: hidden;
  }
  html[data-theme="light"] .landing-final-cta {
    background: var(--lp-surface);
    border: 1px solid var(--lp-border);
    box-shadow: 0 20px 50px -30px rgba(15, 23, 42, .15);
  }
  html[data-theme="light"] .landing-final-cta::before {
    background: radial-gradient(circle at 20% 20%, rgba(59,130,246,.08), transparent 45%),
                radial-gradient(circle at 85% 85%, rgba(20,184,166,.07), transparent 45%);
  }
  html[data-theme="light"] .landing-final-cta h2 { color: var(--lp-text); }
  html[data-theme="light"] .landing-final-cta p { color: var(--lp-muted); }
  .landing-final-cta::before {
    content: ''; position: absolute; inset: 0;
    background: radial-gradient(circle at 20% 20%, rgba(59,130,246,.25), transparent 45%),
                radial-gradient(circle at 85% 85%, rgba(20,184,166,.2), transparent 45%);
  }
  .landing-final-cta h2 { position: relative; color: #fff; font-size: 36px; margin: 0 0 14px; }
  .landing-final-cta p { position: relative; color: rgba(255,255,255,.75); font-size: 16px; max-width: 560px; margin: 0 auto 32px; line-height: 1.55; }
  .landing-final-cta-actions { position: relative; display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; }
  .landing-final-cta .landing-btn-secondary {
    background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.25); color: #fff;
  }
  .landing-final-cta .landing-btn-secondary:hover { border-color: rgba(255,255,255,.5); }
  .landing-final-cta .landing-btn-ghost { color: rgba(255,255,255,.85); }
  .landing-final-cta .landing-btn-ghost:hover { background: rgba(255,255,255,.12); color: #fff; }
  html[data-theme="light"] .landing-final-cta .landing-btn-secondary {
    background: var(--lp-surface); border-color: var(--lp-border); color: var(--lp-text);
  }
  html[data-theme="light"] .landing-final-cta .landing-btn-secondary:hover { border-color: var(--lp-blue-light); }
  html[data-theme="light"] .landing-final-cta .landing-btn-ghost { color: var(--lp-text); }
  html[data-theme="light"] .landing-final-cta .landing-btn-ghost:hover { background: var(--lp-border); }

  /* ---------- Footer ---------- */
  .landing-footer { text-align: center; padding: 32px 24px 40px; }
  .landing-footer p { font-size: 12.5px; margin: 4px 0; }
  .landing-footer a { color: var(--lp-muted); }
  .landing-footer a:hover { color: var(--lp-blue); }
  .landing-footer span { color: var(--lp-border); }

  /* Anteprima "Mobile" via toggle nella navbar su viewport desktop */
  @media (min-width: 981px) {
    #landing.landing-preview-mobile {
      max-width: 430px; margin: 0 auto; border-left: 1px solid var(--lp-border); border-right: 1px solid var(--lp-border);
      box-shadow: 0 0 60px rgba(15,23,42,.08);
    }
    #landing.landing-preview-mobile .landing-nav-links,
    #landing.landing-preview-mobile .landing-device-toggle { display: none; }
    #landing.landing-preview-mobile .landing-nav-burger { display: block; }
    #landing.landing-preview-mobile .landing-hero-inner { grid-template-columns: 1fr; text-align: left; }
    #landing.landing-preview-mobile .landing-hero-title { font-size: 34px; }
    #landing.landing-preview-mobile .landing-features-grid,
    #landing.landing-preview-mobile .landing-reviews-grid { grid-template-columns: 1fr; }
    #landing.landing-preview-mobile .landing-section-head h2 { font-size: 26px; }
  }

  /* Responsive reale su schermi effettivamente piccoli */
  @media (max-width: 980px) {
    .landing-nav-links, .landing-device-toggle { display: none; }
    .landing-nav-right .landing-btn-ghost { display: none; }
    .landing-nav-burger { display: block; }
    .landing-nav-inner { padding: 12px 18px; gap: 12px; }

    .landing-hero { padding: 40px 20px 32px; }
    .landing-hero-inner { grid-template-columns: 1fr; gap: 36px; }
    .landing-hero-title { font-size: 36px; }
    .landing-hero-sub { font-size: 15.5px; max-width: none; }
    .landing-hero-cta { flex-direction: column; }
    .landing-hero-cta button { width: 100%; }
    .landing-hero-checks { gap: 12px 18px; }

    .landing-section { padding: 52px 18px; }
    .landing-section-head h2 { font-size: 27px; }
    .landing-section-head p { font-size: 14.5px; }

    .landing-features-grid, .landing-reviews-grid { grid-template-columns: 1fr; gap: 16px; }

    .landing-final-cta { padding: 44px 22px; border-radius: 18px; }
    .landing-final-cta h2 { font-size: 27px; }
    .landing-final-cta-actions { flex-direction: column; }
    .landing-final-cta-actions button { width: 100%; }

    .landing-mock-card { padding: 20px; }
    .landing-mock-toast { top: -14px; right: 4px; font-size: 11.5px; padding: 7px 11px; }
  }

  @media (max-width: 480px) {
    .landing-hero-title { font-size: 30px; }
    .landing-mock-stat { padding: 10px 8px; }
    .landing-mock-stat b { font-size: 16px; }
  }

  /* KaTeX (formule LaTeX in forum, chat, domande d'esame): eredita il
     colore del testo dal tema attivo invece del nero fisso di default,
     e le formule "display" ($$...$$) hanno un margine verticale e
     scroll orizzontale proprio per non rompere il layout su schermi
     stretti quando la formula è più larga della card. */
  .katex { color: var(--text); font-size: 1.05em; }
  .katex-display { margin: 10px 0; overflow-x: auto; overflow-y: hidden; padding-bottom: 2px; }
  .msg .katex-display, .card-faq .katex-display { margin: 8px 0; }

  /* ===================== ANTEPRIMA PUBBLICA MATERIA ===================== */
  /* Pagina isolata mostrata a chi non è loggato apre un link diretto a una
     materia: solo nome/professore + numeri aggregati, mai contenuti reali.
     Stile volutamente semplice, coerente col resto (variabili di tema). */
  #page-anteprima-materia { background: var(--bg); min-height: 100vh; }
  .anteprima-materia-shell {
    max-width: 480px; margin: 0 auto; padding: 60px 20px 40px; position: relative;
  }
  .anteprima-materia-chiudi {
    position: absolute; top: 18px; right: 18px; background: var(--surface-2); border: 1px solid var(--border);
    color: var(--muted); width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 15px;
  }
  .anteprima-materia-chiudi:hover { color: var(--text); }
  .anteprima-materia-header { text-align: center; margin-bottom: 26px; }
  .anteprima-materia-icona {
    width: 56px; height: 56px; margin: 0 auto 14px; border-radius: 14px; background: var(--blue-bg);
    color: var(--blue-light); display: flex; align-items: center; justify-content: center;
  }
  .anteprima-materia-icona svg { width: 26px; height: 26px; }
  .anteprima-materia-header h1 { font-size: 22px; font-weight: 800; margin: 0 0 6px; }
  .anteprima-materia-prof { color: var(--muted); font-size: 14px; margin: 0; }
  .anteprima-materia-stats {
    display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 28px;
  }
  .anteprima-materia-stat {
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    padding: 16px 12px; text-align: center;
  }
  .anteprima-materia-stat-val { font-size: 24px; font-weight: 800; color: var(--blue-light); margin-bottom: 4px; }
  .anteprima-materia-stat-label { font-size: 12px; color: var(--muted); font-weight: 600; }
  .anteprima-materia-blocco {
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 22px; text-align: center;
  }
  .anteprima-materia-blocco p { font-size: 14px; color: var(--muted); margin: 0 0 16px; }
  .anteprima-materia-blocco .btn-primary { margin-bottom: 10px; }

/* ===================== BOTTOM NAV BAR — solo PWA installata (standalone) ===================== */
#bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 310;
  display: flex; justify-content: space-around; align-items: stretch;
  background: var(--surface); border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
#bottom-nav.hidden { display: none; }
.bottom-nav-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 8px 4px 7px; background: none; border: none; color: var(--muted);
  font-family: inherit; font-size: 10.5px; font-weight: 700; cursor: pointer; position: relative;
}
.bottom-nav-item svg { width: 22px; height: 22px; }
.bottom-nav-item.active { color: var(--blue-light); }
.bottom-nav-item .bottom-nav-badge {
  position: absolute; top: 4px; right: calc(50% - 16px);
  background: #EF4444; color: #fff; font-size: 9.5px; font-weight: 800;
  min-width: 15px; height: 15px; border-radius: 20px; display: flex;
  align-items: center; justify-content: center; padding: 0 3px;
}
body.has-bottom-nav #main-content { padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)); }
body.has-bottom-nav .sidebar-burger,
body.has-bottom-nav #sidebar,
body.has-bottom-nav #drawer-overlay { display: none !important; }
/* ===================== TOPBAR — nascosta in PWA standalone =====================
   La topbar (titolo generico + campanella + omino) creava un breve flash
   di sovrapposizione durante il cambio pagina (visibile per una frazione
   di secondo mentre il browser finiva il repaint), perché il titolo
   generico duplicava quello già presente nel contenuto di ogni pagina
   (nome materia, "Profilo", ecc.). In standalone la togliamo del tutto:
   ogni pagina di dettaglio ha il proprio titolo e la propria freccia
   "indietro" già nel contenuto (vedi .page-header-row), niente più
   duplicazione né rischio di sovrapposizione visiva tra le due. */
body.has-bottom-nav .app-topbar {
  display: none;
}
body.has-bottom-nav #main-content {
  padding-top: calc(env(safe-area-inset-top, 0px) + 14px);
}
/* ===================== LOGIN/REGISTER — restyling standalone =====================
   In standalone niente landing: il form di login diventa la prima cosa che
   si vede, quindi gli diamo un aspetto da vera schermata di benvenuto app
   (branding sopra, sfondo pieno) invece che "form dentro un sito". Usa le
   variabili di tema (non colori fissi) così segue chiaro/scuro come il
   resto dell'app, invece di restare sempre scuro indipendentemente dalla
   scelta dell'utente. */
body.is-standalone-auth #page-auth { background: var(--bg); }
body.is-standalone-auth .auth-form-side { background: transparent; min-height: 100vh; }
body.is-standalone-auth .auth-card { max-width: 400px; }

.auth-standalone-brand { text-align: center; margin-bottom: 30px; }
.auth-standalone-brand.hidden { display: none; }
.auth-standalone-logo {
  width: 64px; height: 64px; margin: 0 auto 16px; border-radius: 18px;
  background: linear-gradient(135deg, var(--blue), var(--teal));
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 30px rgba(37,99,235,.3);
}
.auth-standalone-logo svg { width: 30px; height: 30px; }
.auth-standalone-title { color: var(--text); font-weight: 800; font-size: 21px; margin-bottom: 6px; }
.auth-standalone-title span { color: var(--blue-light); }
.auth-standalone-sub { color: var(--muted); font-size: 13.5px; margin: 0; }

.auth-btn-back-standalone.hidden { display: none; }

/* ===================== NUOVO HEADER LOGIN: icona+titolo+tab =====================
   Sostituisce i vecchi h1/subtitle ripetuti in ogni blocco (login,
   register) e il link testuale "Non hai un account? Registrati" in
   fondo: ora un solo header condiviso sopra ai tre blocchi (login,
   register, ospite), con tab per passare dall'uno all'altro invece di
   link sparsi. Vedi showAuthTab() in core.js per la logica di
   mostra/nascondi. */
.auth-header-comune.hidden { display: none; }
.auth-brand-block { text-align: center; margin-bottom: 20px; }
.auth-brand-icon {
  width: 60px; height: 60px; margin: 0 auto 12px; border-radius: 16px;
  background: linear-gradient(135deg, var(--blue), var(--teal));
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 22px rgba(37,99,235,.28);
}
.auth-brand-icon svg { width: 30px; height: 30px; }
.auth-brand-name { color: var(--text); font-weight: 800; font-size: 19px; margin: 0; }
.auth-brand-name span { color: var(--blue-light); }

/* Contrasto aumentato tra sfondo della tab-bar e tab attiva: prima erano
   due grigi quasi identici (surface-2 su surface) e la tab selezionata
   sembrava "spenta" invece che un vero toggle. */
.auth-tabs { display: flex; background: var(--border); border-radius: 12px; padding: 4px; margin-bottom: 20px; }
.auth-tab {
  flex: 1; text-align: center; padding: 9px 4px; border-radius: 9px; font-size: 13px;
  font-weight: 700; color: var(--muted); cursor: pointer; user-select: none;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease;
}
.auth-tab.active { background: var(--surface); color: var(--blue-light); box-shadow: 0 3px 10px rgba(0,0,0,.14); }

/* Tab "Ospite": stesso spirito di btn-ospite-demo (bordo tratteggiato,
   meno prominente di un vero login) ma qui è l'unico contenuto del tab,
   quindi centrato con un po' più di spazio attorno. */
/* min-height stimata sulla base dell'altezza di login/register (label+input
   email, label+input password, bottone, divider, bottone Google): evita che
   passando alla tab Ospite il contenuto sotto "salti" per la differenza di
   altezza tra i tre blocchi. */
.auth-ospite-box { text-align: center; padding: 24px 4px 4px; min-height: 260px; display: flex; flex-direction: column; justify-content: center; }
.auth-ospite-box p { color: var(--muted); font-size: 13.5px; line-height: 1.5; margin: 0 0 18px; }
.ospite-lista { list-style: none; margin: 0 0 18px; padding: 0; text-align: left; display: flex; flex-direction: column; gap: 10px; }
.ospite-lista li { color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.ospite-lista li strong { color: var(--text); }

.auth-illustrazione { margin-top: 22px; }
.auth-illustrazione.hidden { display: none; }

/* La bottom bar deve sparire del tutto sulle pagine già a schermo intero
   (chat, welcome, tour, scelta corso), che gestiscono da sole tutto lo
   spazio verticale — altrimenti la bottom bar (z-index 310) si sovrappone
   al loro contenuto/input invece di lasciarlo visibile per intero. */
body.has-bottom-nav.is-pagina-schermo-intero #bottom-nav {
  display: none;
}

/* ===================== BLUR/GLASSMORPHISM — bottom bar in standalone =====================
   Stesso effetto già applicato alla topbar: sfondo semi-trasparente con
   blur, invece di un colore pieno, per un aspetto più "vetro" da app
   nativa (coerente con iOS/Android quando gli elementi di sistema
   scorrono sopra al contenuto). */
body.has-bottom-nav #bottom-nav {
  background: rgba(15, 23, 42, .82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid rgba(255,255,255,.06);
}
html[data-theme="light"] body.has-bottom-nav #bottom-nav {
  background: rgba(255, 255, 255, .82);
  border-top: 1px solid rgba(15,23,42,.06);
}

/* ===================== BADGE/PILL — bordi più morbidi in standalone =====================
   Bagliore leggero sui tag di stato (Hot, Fase finale, ecc.) invece del
   bordo netto piatto, per integrarsi meglio col tema scuro. */
body.has-bottom-nav .pill-hot {
  box-shadow: 0 0 0 1px rgba(240,169,59,.25), 0 0 12px rgba(240,169,59,.15);
}
body.has-bottom-nav .pill[data-stato="Fase finale"] {
  box-shadow: 0 0 0 1px rgba(20,184,166,.25), 0 0 10px rgba(20,184,166,.12);
}
body.has-bottom-nav .pill[data-stato="Ripetizione"] {
  box-shadow: 0 0 0 1px rgba(59,130,246,.25), 0 0 10px rgba(59,130,246,.12);
}

/* ===================== SKELETON — animazione più "viva" in standalone =====================
   Leggero effetto pulse oltre allo shine esistente, per dare più
   sensazione di caricamento reale invece di un semplice rettangolo
   statico con riflesso. */
body.has-bottom-nav .skeleton-card,
body.has-bottom-nav .skeleton-riga {
  animation: skeletonPulse 1.8s ease-in-out infinite;
}
@keyframes skeletonPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .7; }
}

/* ===================== FAB IMPOSTAZIONI — solo PWA standalone =====================
   Pulsante fluttuante tondo, fisso in alto a destra, per raggiungere
   Impostazioni ora che non è più tra le voci della bottom bar (5 voci
   sono il massimo comodo per una bottom bar mobile: Materie, Forum,
   Buddy, Esame, Risorse). Mostrato/nascosto da showPage() in app.js. */
.fab-impostazioni {
  position: fixed !important;
  top: calc(env(safe-area-inset-top, 0px) + 14px) !important;
  right: 16px !important;
  left: auto !important;
  bottom: auto !important;
  z-index: 150;
  width: 40px !important; height: 40px !important;
  max-width: 40px; max-height: 40px;
  border-radius: 50% !important;
  background: rgba(15, 23, 42, .82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,.1);
  color: var(--text);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 4px rgba(0,0,0,.12);
  padding: 0;
  margin: 0;
}
.fab-impostazioni svg { width: 19px; height: 19px; }
.fab-impostazioni.hidden { display: none; }
html[data-theme="light"] .fab-impostazioni {
  background: rgba(255, 255, 255, .82);
  border: 1px solid rgba(15,23,42,.08);
}

/* ============================================================================
   TESTO SCRITTO DAGLI UTENTI — niente selezione nativa, solo long-press
   ============================================================================
   In precedenza qui si riabilitava user-select:text sul testo dei singoli
   messaggi/card, per permettere copia-incolla. Su iOS però la selezione
   nativa via long-press "sfora" facilmente il confine del singolo elemento
   e finisce per selezionare anche il testo di card/messaggi adiacenti
   (bug visibile in chat e forum). La soluzione: disabilitare la selezione
   nativa anche qui, e sostituirla con un menu "Copia" dedicato al
   tenere premuto (vedi initLongPressCopia() in componenti.js), che copia
   sempre e solo il testo del singolo elemento toccato — stesso
   comportamento di iMessage/WhatsApp, mai "sballato". Anche qui, come per
   il blocco body sopra, il comportamento vale solo in app nativa/standalone:
   sul sito web puro questi testi restano selezionabili normalmente. */
html.is-native-ios-app .card-faq > p, body.has-bottom-nav .card-faq > p,
html.is-native-ios-app .riga-risposta p, body.has-bottom-nav .riga-risposta p,
html.is-native-ios-app .msg, body.has-bottom-nav .msg,
html.is-native-ios-app .card-compagno .note, body.has-bottom-nav .card-compagno .note,
html.is-native-ios-app .card-materia .prof, body.has-bottom-nav .card-materia .prof,
html.is-native-ios-app .materia-header-card .note, body.has-bottom-nav .materia-header-card .note,
html.is-native-ios-app .hub-card-preview, body.has-bottom-nav .hub-card-preview {
  -webkit-user-select: none;
  user-select: none;
}

/* Evidenzia ed ingrandisce leggermente l'elemento mentre il long-press è
   in corso (prima che il menu compaia) — stesso effetto di iMessage: il
   messaggio "si solleva" leggermente sopra gli altri, dando un feedback
   visivo immediato che il menu sta per aprirsi su di lui. position:relative
   e z-index servono perché lo scale non venga coperto dai messaggi/card
   adiacenti nel flusso della lista. transform-origin center: si ingrandisce
   dal proprio centro, non da un angolo, così resta visivamente "al suo
   posto" invece di spostarsi verso un lato. */
.bb-longpress-attivo {
  position: relative;
  z-index: 400;
  filter: brightness(0.94);
  transform: scale(1.045);
  transform-origin: center;
  transition: filter .12s ease, transform .12s ease;
}

/* ===================== MENU CONTESTUALE "COPIA" (long-press) =====================
   Piccolo popup ancorato vicino al punto toccato, con un solo pulsante
   Copia — stile coerente con .contact-dropdown-menu già esistente. */
.bb-copia-menu {
  position: fixed;
  z-index: 500;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.28);
  overflow: hidden;
  opacity: 0;
  transform: scale(.92);
  transition: opacity .12s ease, transform .12s ease;
  pointer-events: none;
}
.bb-copia-menu.mostra {
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
}
.bb-copia-menu button {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 11px 16px;
  background: none; border: none;
  font-family: inherit; font-size: 14px; font-weight: 600;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}
.bb-copia-menu button:active { background: var(--surface-2); }
.bb-copia-menu svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--muted); }

/* Pulsante "Elimina": stesso stile del pulsante Copia, colore danger e
   un sottile divisore sopra per separarlo visivamente dall'azione
   "sicura" (Copia), coerente con lo stile pericoloso già usato altrove
   nell'app (es. .card-action-link.danger). */
.bb-copia-menu-danger {
  color: var(--danger) !important;
  border-top: 1px solid var(--border) !important;
}
.bb-copia-menu-danger svg { color: var(--danger) !important; }

/* I campi input/textarea/select restano sempre selezionabili ed editabili,
   qualunque cosa erediti dal body — comportamento nativo necessario per
   scrivere e modificare testo. */
input, textarea, select {
  -webkit-user-select: text;
  user-select: text;
}
