/* ══════════════════════════════════════════════════════════════════════════
   app.css — sistema visivo dell'APP SpesaChiara.

   Non è il CSS del sito e non deve assomigliargli: qui non esistono hero,
   sezioni lunghe o hover. Esistono superfici a tutto schermo, una barra in
   alto, una barra di tab in basso e fogli che salgono dal fondo.

   I colori arrivano tutti da /css/colors_and_type.css (var(--…)): nessun
   esadecimale scritto a mano, così app e sito restano lo stesso marchio.
   ═════════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, p, figure, ul, ol { margin: 0; padding: 0; }
ul, ol { list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
/* padding: 0 serve: i bottoni "a scatola" (avatar, iconbtn, qty) hanno misura
   fissa e centrano col flex, quindi il padding di default del browser non li
   allarga — rimpicciolisce il contenuto dentro un box già ritagliato. Sull'avatar
   l'immagine finiva su un content box ~22x34 e il cover la tagliava di lato. */
button { background: none; border: none; padding: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }

:root {
  /* Altezze della chrome: servono a più componenti, stanno in un posto solo. */
  --topbar-h: 56px;
  --tabbar-h: 60px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* Il sito prende 'Plus Jakarta Sans' da Google Fonts. L'app è un bundle
     offline: un carattere che arriva dalla rete significa testo che salta al
     primo avvio, o niente carattere in aereo. Inter è servito dai file locali
     in /assets/fonts, quindi qui è quello. */
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* ── Profondità (Fase 0) ──────────────────────────────────────────────────
     Ombre a DUE strati — un contatto stretto e ravvicinato più un'ambiente
     larga e diffusa — invece della singola ombra piatta del sistema: è quello
     che dà alle superfici di Revolut/Apple il senso di stare "sopra" la pagina
     invece di esserci disegnate. La tinta è slate (15,23,42), non nero puro:
     sul bianco il nero puro fa un alone grigio sporco. Sovrascrivono i token di
     /css/colors_and_type.css SOLO qui: app.css lo carica il sito non lo vede, e
     il tema scuro ha già i suoi più giù. */
  --shadow-xs:   0 1px 2px rgba(15, 23, 42, .05);
  --shadow-card: 0 1px 2px rgba(15, 23, 42, .05), 0 6px 16px -6px rgba(15, 23, 42, .12);
  --shadow-soft: 0 2px 6px rgba(15, 23, 42, .06), 0 14px 34px -10px rgba(15, 23, 42, .16);
  --shadow-pop:  0 4px 10px rgba(15, 23, 42, .10), 0 24px 60px -12px rgba(15, 23, 42, .28);

  /* Raggi un filo più ampi: le superfici morbide leggono come più moderne e
     "toccabili". Solo un paio di px, così niente si spacca — le tessere e i
     fogli si arrotondano appena. */
  --r-lg: 14px;
  --r-xl: 18px;
}

html, body {
  height: 100%;
  overflow: hidden;                 /* scorre il contenuto, non la pagina */
  background: var(--bg-2);
}
body {
  font-family: var(--font-sans);
  font-size: var(--fs-15);
  line-height: var(--lh-base);
  color: var(--fg-1);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;        /* niente rimbalzo/pull-to-refresh del browser */
  user-select: none;                /* si sente app, non pagina */
}
input, textarea { user-select: text; }

.hidden { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ── Struttura ─────────────────────────────────────────────────────────── */
/* `position: relative` non è decorativo: nella cornice da computer i fogli
   passano da fixed ad absolute e devono ancorarsi QUI, non alla finestra. */
#sc-root { height: 100%; display: flex; flex-direction: column; position: relative; }

/* Il fondo: tre aloni verdi molto diluiti e una trama di punti quasi
   invisibile. Non è decorazione fine a sé stessa — un bianco piatto su tutto
   lo schermo fa sembrare l'app un foglio, e le schede bianche sopra non si
   staccano da niente. Gli aloni restano fermi mentre il contenuto scorre. */
#sc-root::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(88% 44% at 96% -6%, rgba(var(--green-500-rgb), .16), transparent 62%),
    radial-gradient(72% 38% at -12% 3%,  rgba(56, 189, 248, .11),        transparent 60%),
    radial-gradient(130% 52% at 50% 106%, rgba(var(--green-500-rgb), .12), transparent 64%),
    radial-gradient(rgba(var(--green-500-rgb), .10) 1px, transparent 1px) 0 0 / 22px 22px,
    var(--bg-2);
}
/* Solo le fasce nel flusso vengono alzate sopra gli aloni. NON `#sc-root > *`:
   gate, foglio e toast sono `position: fixed`, e riscriverla in `relative` li
   farebbe scorrere insieme al contenuto invece di stare sopra lo schermo. */
.screen, .installbar { position: relative; z-index: 1; }

/* LA BARRA IN ALTO (rifatta 2026-08-12).
   Com'era: un rettangolo verde chiarissimo con una riga verde sotto, sempre
   accesa. Due difetti veri, non di gusto. Primo: la riga c'era anche a pagina
   ferma in cima, cioè segnalava un contenuto che scorre sotto quando NIENTE
   stava scorrendo — un separatore che non separa niente è la definizione di
   ornamento. Secondo: sulla home la barra era un logo, un vuoto largo mezzo
   schermo e un ritratto; il vuoto non è minimalismo, è spazio che non lavora.

   Adesso: vetro quasi bianco (il verde torna a essere inchiostro, come si è già
   deciso per la home), NESSUNA riga a riposo, e appena il contenuto scorre la
   barra si stacca da sola con un filo e un'ombra bassissima — il separatore
   compare quando c'è davvero qualcosa da separare.

   Il vuoto sulla home resta vuoto (2026-08-25). Per un po' l'ha riempito una
   pastiglia di ricerca che entrava quando il campo grande usciva di scena: sulla
   carta due comandi mai visibili insieme, sotto il pollice una barra che si
   trasforma da sola a metà scorrimento e che al tocco ti sposta di schermata
   perdendo il punto in cui eri. Per cercare c'è la linguetta in fondo, ferma
   nello stesso posto: un vuoto che non fa danni batte un comando che sorprende. */
.topbar {
  flex: 0 0 auto;
  height: calc(var(--topbar-h) + var(--safe-t));
  padding: var(--safe-t) var(--s-4) 0;
  display: flex; align-items: center; gap: var(--s-3);
  /* Verde MESCOLATO al bianco, non appoggiato sopra: il verde è denso in alto
     (dove la barra tocca il bordo dello schermo) e si scioglie nel bianco verso
     il contenuto. Così la barra ha il colore del marchio senza diventare una
     campitura piatta — e quel che ci sta sopra, marchio e ritratto compresi,
     resta su un fondo abbastanza chiaro da leggersi. */
  background: linear-gradient(180deg,
    rgba(209, 250, 229, .96) 0%,
    rgba(236, 253, 244, .90) 52%,
    rgba(255, 255, 255, .84) 100%);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  /* Il bordo esiste sempre (trasparente): animarne il colore non fa sobbalzare
     l'altezza della barra, mentre farlo apparire dal nulla sposterebbe di 1px
     tutto il contenuto sotto. */
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-base), box-shadow var(--t-base);
  z-index: 30;
}
.topbar.scrolled {
  /* Il filo è verde, non grigio: chiude la fascia col colore che ha dentro. */
  border-bottom-color: var(--green-200);
  box-shadow: 0 10px 24px -20px rgba(var(--green-500-rgb), .9);
}
.topbar h1 {
  flex: 1; min-width: 0;
  font-size: var(--fs-18); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* La riga sotto al titolo porta dati veri ("204 supermercati · Roma"): era nel
   grigio più slavato della scala, cioè la cosa meno leggibile della schermata
   pur essendo l'unica che cambia. Sale di un gradino. */
.topbar .sub {
  display: block; margin-top: 1px;
  font-size: var(--fs-12); font-weight: var(--fw-semibold);
  color: var(--fg-3); letter-spacing: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.iconbtn {
  flex: 0 0 auto;
  width: 38px; height: 38px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-2); background: var(--bg-2);
  transition: background var(--t-fast), transform var(--t-fast);
}
.iconbtn svg { width: 20px; height: 20px; }
.iconbtn:active { background: var(--bg-3); transform: scale(.94); }
.iconbtn.plain { background: none; }

/* Il ritratto in barra è il tasto più personale dell'app, ma era un dischetto
   verde piatto uguale a un pallino qualsiasi. Ora ha un anello chiaro che lo
   stacca dalla barra (la barra è quasi bianca: senza anello il cerchio ci
   annega dentro), un filo di luce in alto e un'ombra sotto — la stessa
   rotondità delle foto profilo, così sembra un ritratto anche quando la foto
   non c'è. Il tondo cresce da 34 a 36px: sotto i 36 il tocco è scomodo. */
.avatar {
  position: relative; flex: 0 0 auto;
  width: 36px; height: 36px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, var(--green-400), var(--green-600) 52%, var(--green-800));
  color: #fff; font-size: var(--fs-14); font-weight: var(--fw-extra);
  overflow: hidden;
  box-shadow:
    0 0 0 2px var(--bg-1),
    0 0 0 3px var(--green-100),
    0 6px 14px -6px rgba(var(--green-500-rgb), .85);
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}
.avatar:active { transform: scale(.93); }
/* Il filo di luce: un velo bianco che si spegne a metà, come su una sfera. */
.avatar::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 255, 255, .34), rgba(255, 255, 255, 0) 56%);
  pointer-events: none;
}
/* flex:0 0 auto perche' l'immagine e' un flex item: senza, il ritiro di default
   la stringe e il volto esce dal cerchio. object-position alto perche' nelle foto
   profilo la faccia sta sopra il centro geometrico. */
.avatar img { width: 100%; height: 100%; flex: 0 0 auto; object-fit: cover; object-position: 50% 35%; }
/* La foto vera non vuole il velo sopra: le cambierebbe i colori. */
.avatar.photo::after { display: none; }
.avatar-in { position: relative; z-index: 1; line-height: 1; letter-spacing: .01em; }
.avatar-ic { position: relative; z-index: 1; display: flex; }
.avatar-ic svg { width: 19px; height: 19px; stroke-width: 2.1; }

/* Area schermata: l'unica cosa che scorre. */
.screen {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding-bottom: var(--s-6);
}
.screen.flush { padding: 0; }

/* Le barre di scorrimento del desktop dentro un telefono si vedono e
   tradiscono la pagina web. Il gesto resta, la barra sparisce. */
.screen, .dock-list, .sheet-body, .chiprow { scrollbar-width: none; -ms-overflow-style: none; }
.screen::-webkit-scrollbar, .dock-list::-webkit-scrollbar,
.sheet-body::-webkit-scrollbar, .chiprow::-webkit-scrollbar { width: 0; height: 0; }

/* ── Tab bar ───────────────────────────────────────────────────────────── */
/* Cinque posti: quattro schermate e, al centro, l'AZIONE segnala — rialzata,
   perché è il gesto che deve costare meno di tutti (senza segnalazioni non ci
   sono prezzi per-negozio, e quindi nemmeno punteggi e mappa). Stessa forma
   della barra del sito: 68px, icone 24, etichette 11px, vetro chiaro. */
.tabbar {
  flex: 0 0 auto;
  height: calc(var(--tabbar-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: rgba(255, 255, 255, .9);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-top: 1px solid var(--green-100);
  box-shadow: 0 -8px 24px -16px rgba(15, 23, 42, .18), inset 0 1px 0 rgba(255, 255, 255, .7);
  z-index: 40;
  /* Il tasto centrale esce dalla barra: senza questo verrebbe tagliato. */
  overflow: visible;
}
.tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; color: var(--fg-4); position: relative;
  transition: color var(--t-fast);
}
.tab-ic { position: relative; display: flex; align-items: center; justify-content: center; width: 34px; height: 30px; }
.tab-ic svg { width: 24px; height: 24px; transition: transform var(--t-base); }
.tab-lb { font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: .01em; }
.tab.on { color: var(--green-600); }
/* Pastiglia verde dietro l'icona attiva: dice dove sei anche senza colore. */
.tab.on .tab-ic::before {
  content: ""; position: absolute; inset: 0 1px;
  border-radius: 11px; background: var(--green-50);
}
.tab.on .tab-ic svg { transform: translateY(-1px) scale(1.05); }
.tab:active .tab-ic svg { transform: scale(.9); }
.tab .badge {
  position: absolute; top: -2px; right: 0;
  min-width: 17px; height: 17px; padding: 0 5px;
  border-radius: var(--r-pill);
  background: var(--green-600); color: #fff;
  font-size: var(--fs-10); font-weight: var(--fw-extra);
  display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--bg-1);
}
.tab-pro {
  position: absolute; top: 3px; left: 50%; margin-left: 5px;
  padding: 0 4px; border-radius: var(--r-pill);
  font-size: 8px; font-weight: 900; letter-spacing: .04em; line-height: 13px;
  color: var(--amber-950);
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500));
}

/* Tasto centrale */
.tab-fab { color: var(--green-700); }
.fab-ic {
  display: flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 18px; margin-top: -22px;
  color: #fff;
  background: linear-gradient(135deg, var(--green-400), var(--green-600));
  box-shadow: 0 8px 18px -5px rgba(var(--green-500-rgb), .65), inset 0 1px 0 rgba(255, 255, 255, .4);
  transition: transform var(--t-fast);
}
.fab-ic svg { width: 26px; height: 26px; stroke-width: 2.4; }
.tab-fab:active .fab-ic { transform: scale(.92); }

/* Marchio sulla home (dove il tasto casa non serve) e tasto casa altrove.
   Simbolo ufficiale + logotipo "SpesaChiara", "Chiara" in verde come sul sito.
   NIENTE tessera bianca sotto: il PNG è trasparente e il verde si legge su
   entrambi i temi, mentre il riquadro chiaro si vedeva come una macchia
   attaccata al logo. Il testo è var(--fg-1), così in scuro schiarisce da solo
   (un PNG col testo dentro resterebbe nero). */
.brandmark {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px;
}
.brandmark img { width: 34px; height: 34px; object-fit: contain; display: block; }
/* La scritta va alla pari col simbolo: 21px accanto a 34px di marchio è il
   rapporto del sito. ATTENZIONE: la scala dei caratteri salta da 18 a 21 —
   `--fs-20` NON esiste, e qui c'era proprio quello: dichiarazione non valida,
   quindi la scritta ereditava i 15px del corpo del testo ed era la metà del
   simbolo. Prima di scrivere un `--fs-*` controllare colors_and_type.css. */
.brandmark b {
  font-size: var(--fs-21); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); color: var(--fg-1); line-height: 1;
}
.brandmark b span { color: var(--green-600); }
/* Il tasto casa: tondo come il ritratto all'altro capo della barra, così i due
   estremi si rispondono invece di essere un quadrato e un cerchio. Bianco su
   vetro bianco (il verde è nell'icona) e ombra bassa: è un comando, non una
   tessera colorata. */
.homebtn {
  width: 36px; height: 36px; border-radius: var(--r-pill);
  background: var(--bg-1); color: var(--green-700);
  border: 1px solid var(--green-200);
  box-shadow: var(--shadow-xs);
}
.homebtn svg { width: 18px; height: 18px; }
.homebtn:active { background: var(--green-50); border-color: var(--green-200); }

/* ══════════════════════════════════════════════════════════════════════════
   HOME — la prima risposta, non il primo strumento
   ═════════════════════════════════════════════════════════════════════════ */
/* L'apertura della home.
   La tessera di verde pieno è stata prima abbassata, poi alleggerita di un
   alone, e non bastava: il problema non era QUANTO verde, era che ci fosse una
   campitura. Tutto quello che finisce sopra una campitura satura deve essere
   bianco — il titolo, la pastiglia, le pastiglie delle spese al volo — e quindi
   finisce per avere tutto lo stesso peso; l'unico modo di dare rilievo a una
   cosa diventa aggiungere un altro verde sopra il verde (il tasto lente), che è
   il punto in cui ci si era arrivati.

   Qui la campitura non c'è: il titolo sta sul fondo dell'app — che i suoi aloni
   verdi diluiti ce li ha già — in nero, che è il contrasto più alto disponibile
   e non costa niente. Il verde torna a essere INCHIOSTRO e non sfondo: una
   parola del titolo, la lente, il tasto di partenza, i punteggi. Dove c'è, dice
   qualcosa. */
.hero { position: relative; padding: var(--s-5) var(--s-4) 0; }
.hero-glow { display: none; }               /* niente più verde pieno da illuminare */
.hero-in { position: relative; }
/* Il saluto era a 13px in --fg-4: sul fondo scuro spariva, e una riga che
   chiama l'utente per nome non ha senso se non si legge. Sedici pixel, il
   nome in pieno contrasto, il momento della giornata un gradino sotto. */
.hero-hi {
  font-size: var(--fs-16); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-normal); color: var(--fg-3);
  line-height: 1.25;
}
.hero-hi b { color: var(--fg-1); font-weight: var(--fw-extra); }
.hero-t {
  margin-top: 4px; font-size: var(--fs-24); line-height: 1.14;
  font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); color: var(--fg-1);
}
/* Una parola sola in verde. Sottolineare tutta la frase sarebbe un titolo
   decorato; così è il verbo — "conviene" — a portare il colore del marchio, ed
   è anche la parola che dice cosa fa l'app. */
.hero-t em { font-style: normal; color: var(--green-600); }

/* La ricerca è l'UNICA della home (la lente nella barra in alto è stata tolta:
   portava allo stesso posto). Su fondo chiaro non deve più gridare per staccarsi
   dal verde: le bastano il bianco, un filo di bordo e l'ombra bassa delle
   schede. A destra resta il solo tasto verde, che è il punto in cui si parte
   davvero.
   UNA lente sola (2026-08-13): quella grigia a sinistra è stata togliata. Era
   lo stesso segno del tasto verde ripetuto a tre centimetri di distanza, e per
   giunta quello inerte — a campo vuoto due lenti fanno chiedere quale delle due
   cerca. Il testo del campo dice già cosa si fa lì. */
/* Wrapper con posizione-relativa per il dropdown autocomplete. */
.hero-sw { position: relative; margin-top: var(--s-4); }
.hero-search {
  display: flex; align-items: center; gap: var(--s-3);
  height: 54px; padding: 0 5px 0 var(--s-4);
  border-radius: var(--r-xl);
  background: var(--bg-1);
  border: 1.5px solid var(--border-2);
  box-shadow: 0 4px 20px -6px rgba(15,23,42,.12), 0 1px 4px -1px rgba(15,23,42,.06);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.hero-sw:focus-within .hero-search {
  border-color: var(--green-400);
  box-shadow: 0 4px 20px -6px rgba(15,23,42,.14), 0 0 0 3px rgba(var(--green-500-rgb),.14);
}
.hero-search:active { border-color: var(--green-300); }
.hero-search input {
  flex: 1; min-width: 0; border: none; outline: none; background: none;
  font-size: max(var(--fs-15), 16px); font-weight: var(--fw-semibold); color: var(--fg-1);
  text-overflow: ellipsis;
}
.hero-search input::placeholder { color: var(--fg-4); font-weight: var(--fw-medium); }
/* Il tasto verde: unica cosa colorata dentro la barra — l'occhio ci arriva da solo. */
.hs-go {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green-500), var(--green-700));
  color: #fff; border: none; cursor: pointer;
  box-shadow: 0 4px 12px -4px rgba(var(--green-500-rgb), .7);
  transition: box-shadow var(--t-fast), transform var(--t-fast);
}
.hs-go:active { transform: scale(.93); }
.hs-go svg { width: 19px; height: 19px; stroke-width: 2.3; }
/* Il microfono della home. Esisteva già nel DOM ed era già collegato a
   SC.Voice, ma `.mic` era disegnato SOLO dentro `.sfield` e `.stsearch`: qui
   restava un bottone senza misura, quindi 0×0 — invisibile. Nudo di proposito
   (nessun riempimento): il verde dentro la barra deve restare uno solo, quello
   del tasto cerca, o si smette di capire dove si parte. */
.hero-search .mic {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-4); background: transparent; border: none; cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast), transform var(--t-fast);
}
.hero-search .mic svg { width: 19px; height: 19px; }
.hero-search .mic:hover { color: var(--green-600); background: var(--green-50); }
.hero-search .mic:active { transform: scale(.9); }
.hero-search .mic.listening {
  color: var(--conv-bad-dot); background: var(--conv-bad-bg);
  animation: micPulse 1.2s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .hero-search .mic.listening { animation: none; } }

/* Dropdown autocomplete della ricerca home */
.hs-drop {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 50;
  background: var(--bg-1); border: 1.5px solid var(--border-2);
  border-radius: var(--r-xl); overflow: hidden;
  box-shadow: 0 20px 50px -12px rgba(15,23,42,.24), 0 4px 14px -4px rgba(15,23,42,.10);
}
.hs-drop-label {
  padding: 10px 16px 6px;
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: .06em; color: var(--fg-4);
}
/* Cronologia: righe, non più chip (vedi hsShowRecent in home.js). Una riga ha
   due tasti distinti — il termine, largo, e la × in fondo — perché toccare per
   sbaglio la × mentre si voleva cercare è il modo più veloce per far odiare la
   cronologia. */
.hs-rc-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-2); padding: 10px 8px 6px 16px;
}
.hs-rc-head .hs-drop-label { padding: 0; }
.hs-rc-clear {
  flex: 0 0 auto; padding: 5px 8px; border: none; background: none; cursor: pointer;
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--green-700);
  border-radius: var(--r-md);
}
.hs-rc-clear:active { background: var(--green-50); }
.hs-rc-row { display: flex; align-items: center; border-top: 1px solid var(--border-1); }
.hs-rc-go {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s-3);
  padding: 10px 4px 10px var(--s-4);
  background: none; border: none; border-radius: 0; text-align: left;
  color: var(--fg-1); cursor: pointer;
}
.hs-rc-go:active { background: var(--bg-2); }
.hs-rc-ic {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-2); color: var(--fg-4);
}
.hs-rc-ic svg { width: 15px; height: 15px; }
.hs-rc-t {
  flex: 1; min-width: 0; font-size: var(--fs-14); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hs-rc-x {
  flex: 0 0 auto; width: 38px; height: 38px; margin-right: 4px;
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-4); background: none; border: none; border-radius: var(--r-pill);
  cursor: pointer;
}
.hs-rc-x svg { width: 14px; height: 14px; }
.hs-rc-x:active { background: var(--bg-2); color: var(--fg-2); }
.hs-drop-item {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; padding: 11px var(--s-4);
  border-bottom: 1px solid var(--border-1);
  background: none; text-align: left; cursor: pointer; color: var(--fg-1);
  border-radius: 0;
}
.hs-drop-item:last-child { border-bottom: none; }
.hs-drop-item:active { background: var(--bg-2); }
.hdi-ic {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: var(--r-md); flex-shrink: 0;
  background: var(--bg-2);
}
.hdi-ic svg { width: 17px; height: 17px; }
.hdi-tx { flex: 1; min-width: 0; }
.hdi-name {
  display: block; font-size: var(--fs-14); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdi-meta {
  display: block; font-size: var(--fs-12); color: var(--fg-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hdi-price {
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--green-700);
  flex-shrink: 0;
}
.hs-drop-empty {
  padding: 20px 16px; text-align: center;
  color: var(--fg-3); font-size: var(--fs-14);
}
.hs-drop-load { padding: 8px 16px 4px; }

/* I titoli di sezione della HOME (e solo di questa: `.sect-head` è condiviso con
   mappa, carrello e profilo, che non erano in discussione).
   Erano maiuscoletto grigio con un trattino verde davanti: tre segnali — tutto
   maiuscolo, spaziatura larga, barretta colorata — per dire una cosa sola, e per
   giunta in grigio chiaro, cioè gridati e insieme illeggibili. Qui sono titoli
   veri: tondo, nero, 18px. Il rango si legge dalla dimensione, che è come
   funzionano i titoli da sempre. */
.home .sect-head { align-items: center; }
.home .sect-head h2 {
  font-size: var(--fs-18); font-weight: var(--fw-extra);
  text-transform: none; letter-spacing: var(--ls-tight);
  color: var(--fg-1);
}
.home .sect-head h2::before { display: none; }
/* "Come funziona" è un comando, non un'etichetta: la pastiglia lo dice senza
   dover aggiungere altre parole. */
.home .sect-head .link {
  font-size: var(--fs-12); font-weight: var(--fw-bold);
  padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--green-50); color: var(--green-700);
  border: 1px solid var(--green-100);
}
.home .sect-head .link:active { background: var(--green-100); }

/* ── Ricette pronte in home ────────────────────────────────────────────── */
/* Una fascia che scorre di lato, non una griglia: otto ricette su due colonne
   facevano quattro file e spingevano la classifica sotto il bordo dello
   schermo. Così costano 120px e restano tutte raggiungibili. */
.sect-strip { padding-bottom: 0; }
.sect-note { font-size: var(--fs-12); color: var(--fg-4); font-weight: var(--fw-semibold); }
.recstrip {
  display: flex; gap: var(--s-2); overflow-x: auto;
  padding: 0 var(--s-4) 2px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.recstrip::-webkit-scrollbar { display: none; }
/* Le categorie delle ricette (primi, secondi, dolci…), sopra la fascia. Con
   trentuno ricette in un nastro solo i dolci arrivavano dopo dieci secondi di
   scorrimento; con le portate si trova al primo colpo, ed è anche il modo in
   cui uno pensa alla cena. La fila delle pastiglie ha il rientro della fascia
   sotto, così le due partono dalla stessa linea. */
.recstrip-cats { padding: 0 0 8px; }
/* `.chiprow.reccats` e non `.reccats`: `.chiprow-flush` azzera il rientro ed è
   dichiarata più in basso nel foglio, quindi a pari specificità vincerebbe lei
   e le pastiglie partirebbero dal bordo dello schermo. */
.chiprow.reccats { padding: 0 var(--s-4) 8px; }
.rectile {
  flex: 0 0 auto; width: 104px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 10px; text-align: left;
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-lg); box-shadow: var(--shadow-card);
  transition: transform var(--t-fast), border-color var(--t-fast), opacity var(--t-fast);
}
.rectile:active { transform: scale(.95); border-color: var(--green-300); }
.rectile[disabled] { opacity: .5; }
.rectile-ic {
  width: 38px; height: 38px; margin-bottom: 6px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, var(--green-100), var(--green-50));
  color: var(--green-700); border: 1px solid var(--green-100);
}
.rectile-ic svg { width: 21px; height: 21px; }
/* Due righe al massimo: "Pasta al pomodoro" ci sta, e le tessere restano
   tutte della stessa altezza anche con nomi di lunghezza diversa. */
.rectile-n {
  font-size: var(--fs-12); font-weight: var(--fw-extra); line-height: 1.25;
  letter-spacing: var(--ls-normal);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.5em;
}
.rectile-c { font-size: var(--fs-10); color: var(--fg-4); font-weight: var(--fw-bold); }
.rectile.busy { border-color: var(--green-400); }
.rectile.busy .rectile-ic { animation: recPulse 1s ease-in-out infinite; }

/* ── Classifica in zona ────────────────────────────────────────────────── */
/* Un elenco solo, righe tutte uguali. Le tre schede grandi di prima erano
   belle una per una ma impedivano la cosa per cui una classifica esiste:
   confrontare in un colpo d'occhio. Nove catene ci stanno in una schermata. */
.zone-note { margin: -8px 0 var(--s-3); }

/* Riga d'ordinamento. La parola "Ordina" davanti costa dodici pixel e toglie
   ogni dubbio: senza, le due linguette attaccate all'elenco sembravano il suo
   titolo. Il respiro sotto (--s-4) è quello che stacca il comando dai dati. */
.sortrow {
  display: flex; align-items: center; gap: var(--s-3);
  margin: 0 0 var(--s-4);
}
.sortrow-lb {
  flex: 0 0 auto;
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--fg-4);
}
.segment-sm { flex: 1; min-width: 0; margin: 0; }
.segment-sm button { height: 32px; font-size: var(--fs-12); }

/* Barra posizione: si tocca per cambiare zona. Stato auto / manuale / spenta.
   Era una scheda BIANCA col filo grigio e l'ombra — cioè identica all'elenco
   della classifica venti pixel più sotto: sembrava la prima riga della lista,
   non il comando che decide quali righe si vedono. Adesso è verde chiaro col
   filo verde: nella schermata è l'unico blocco tinto, quindi si legge subito
   come "impostazione", e il tasto a destra è una pastiglia piena, non due
   parole grigie che nessuno prendeva per un tasto.
   Il fondo verde chiaro però è stato tolto: sotto un'intestazione tutta verde
   faceva tre blocchi verdi di fila. Basta la tessera del segnaposto a dire che
   la fascia è "attiva"; il resto è bianco, come l'elenco che comanda. */
.locbar {
  width: 100%; display: flex; align-items: center; gap: var(--s-3);
  margin: 0 0 var(--s-4); padding: var(--s-3) var(--s-3) var(--s-3) var(--s-4);
  background: var(--bg-1);
  border: 1px solid var(--border-1);
  border-radius: var(--r-xl); box-shadow: var(--shadow-xs); text-align: left;
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}
.locbar:active { transform: scale(.99); box-shadow: var(--shadow-soft); }
.locbar-ic {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green-500), var(--green-700));
  color: #fff; box-shadow: 0 6px 14px -8px rgba(var(--green-500-rgb), 1);
}
.locbar-ic svg { width: 20px; height: 20px; }
.locbar-tx { flex: 1; min-width: 0; }
.locbar-tx em {
  display: block; font-style: normal; font-size: var(--fs-11);
  font-weight: var(--fw-bold); text-transform: uppercase;
  letter-spacing: var(--ls-wide); color: var(--fg-4);
}
.locbar-tx b {
  display: block; font-size: var(--fs-16); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); color: var(--fg-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.locbar-cta {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 1px;
  height: 32px; padding: 0 var(--s-2) 0 var(--s-3); border-radius: var(--r-pill);
  background: var(--bg-1); border: 1px solid var(--green-200);
  font-size: var(--fs-13); font-weight: var(--fw-extra); color: var(--green-700);
}
.locbar-cta svg { width: 15px; height: 15px; }
/* Posizione spenta: ambra, perché è l'unico stato in cui manca qualcosa. */
.locbar.off {
  background: linear-gradient(140deg, var(--conv-mid-bg), var(--bg-1) 78%);
  border-color: var(--conv-mid-line, var(--border-1));
}
.locbar.off .locbar-ic {
  background: var(--conv-mid-bg); color: var(--conv-mid-fg); box-shadow: none;
}
.locbar.off .locbar-tx em { color: var(--conv-mid-fg); }
.locbar.off .locbar-cta { color: var(--conv-mid-fg); border-color: var(--conv-mid-line); }

.ranklist {
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-xl); box-shadow: var(--shadow-card); overflow: hidden;
}
.ranklist-note { margin: var(--s-3) 2px 0; }

.rkrow {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%; text-align: left;
  padding: 10px var(--s-3);
  border-bottom: 1px solid var(--border-2);
  transition: background var(--t-fast);
}
.rkrow:last-child { border-bottom: none; }
.rkrow:active { background: var(--bg-2); }
/* La posizione è un NUMERO, non una tessera. Ridurre le pastiglie verdi da tre
   a una aveva già tolto la colonna di macchie, ma restavano otto rettangoli
   grigi che pesavano quanto i marchi che dovevano soltanto numerare — e un
   numero in una scatola non si legge meglio di un numero. SOLO la prima resta
   in verde, con l'inchiostro invece che con lo sfondo: dice "questa è la più
   conveniente" senza aggiungere una macchia alla riga. */
.rkrow-n {
  flex: 0 0 auto; width: 18px; text-align: center;
  font-size: var(--fs-14); font-weight: var(--fw-extra);
  color: var(--fg-5); font-variant-numeric: tabular-nums;
}
.rkrow.top .rkrow-n { color: var(--green-600); }
.rkrow-body { flex: 1; min-width: 0; }
.rkrow-name {
  display: block; font-size: var(--fs-15); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-normal);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rkrow-sub {
  display: block; font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Il prezzo medio è il numero che si confronta davvero: allineato a destra e
   più grande del sottotitolo, ma sotto al nome nella gerarchia. Le cifre sono
   tabellari — in una classifica i prezzi stanno incolonnati, e con le cifre a
   larghezza variabile la virgola balla di riga in riga. */
.rkrow-price {
  flex: 0 0 auto; text-align: right; line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.rkrow-price b { display: block; font-size: var(--fs-15); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.rkrow-price b.nd { color: var(--fg-5); }
.rkrow-price i { font-style: normal; font-size: 9px; color: var(--fg-5); font-weight: var(--fw-bold); }

/* Il punteggio: pastiglia PIENA, come la goccia sulla mappa.
   Era un riquadro di colore diluito con sopra la cifra dello stesso colore — il
   contrasto più basso di tutta la schermata proprio sul numero che dà il
   verdetto e che decide l'ordine di tutto l'elenco; nove riquadri pallidi in
   fila sembravano campi disattivati. Pieno, con la cifra bianca, dice le stesse
   tre cose della mappa (verde conviene, ambra media, rosso caro) con lo stesso
   segno: chi ha imparato i colori là non deve impararli una seconda volta qui. */
.dotscore {
  flex: 0 0 auto; min-width: 34px; height: 26px; padding: 0 8px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill);
  font-size: var(--fs-13); font-weight: var(--fw-extra); color: #fff;
  font-variant-numeric: tabular-nums; letter-spacing: var(--ls-tight);
}
.dotscore.good { background: var(--conv-good-dot); }
.dotscore.mid  { background: var(--conv-mid-dot); }
.dotscore.bad  { background: var(--conv-bad-dot); }
/* "Senza voto" resta grigio e più piccolo: tre caratteri al posto di due cifre. */
.dotscore.na   { background: var(--fg-4); font-size: var(--fs-10); letter-spacing: -.03em; }

/* "Come si calcola il punteggio". La barra colorata fa capire in mezzo secondo
   il verso della scala — rosso a sinistra (caro), verde a destra (conviene) —
   che tre righe di testo da sole non riescono a dare. Stessi colori dei
   punteggi in elenco, altrimenti la spiegazione parla un'altra lingua. */
.shelp-p { font-size: var(--fs-14); line-height: var(--lh-base); color: var(--fg-2); margin: 0 0 var(--s-3); }
.shelp-p b { color: var(--fg-1); font-weight: var(--fw-extra); }
.shelp-lead {
  font-size: var(--fs-15); line-height: var(--lh-base); color: var(--fg-2);
  margin: 0 0 var(--s-4);
}
.shelp-lead b { color: var(--fg-1); font-weight: var(--fw-extra); }

/* Le tre fasce sono BOTTONI, non decorazione: toccarne una cambia la riga di
   spiegazione qui sotto. La scala da sola diceva il verso (rosso→verde) ma non
   che cosa significhi un 62, che è la domanda vera. Le soglie ripetono quelle
   di SC.scoreTone, così il colore qui e il colore in classifica coincidono. */
.shelp-scale { display: flex; gap: 6px; margin: 0 0 var(--s-3); }
.sband {
  flex: 1; min-width: 0; position: relative; overflow: hidden; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 11px 4px 9px;
  border: 1px solid var(--border-1); border-radius: var(--r-md);
  background: var(--bg-1); text-align: center;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease, background .16s ease;
}
.sband::before { content: ''; position: absolute; inset: 0 0 auto; height: 4px; background: var(--band-c); }
.sband.bad  { --band-c: var(--conv-bad-dot);  --band-bg: var(--conv-bad-bg); }
.sband.mid  { --band-c: var(--conv-mid-dot);  --band-bg: var(--conv-mid-bg); }
.sband.good { --band-c: var(--conv-good-dot); --band-bg: var(--conv-good-bg); }
.sband b { font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1); letter-spacing: -.02em; }
.sband span { font-size: var(--fs-11); font-weight: var(--fw-semibold); color: var(--fg-3); }
.sband[aria-pressed="true"] {
  background: var(--band-bg); border-color: var(--band-c);
  box-shadow: 0 0 0 1px var(--band-c), 0 8px 18px -10px rgba(15, 23, 42, .45);
  transform: translateY(-1px);
}
.sband:active { transform: scale(.97); }

/* La risposta alla fascia toccata. Filo colorato a sinistra: si vede a colpo
   d'occhio che è cambiata anche senza rileggere il testo. */
.shelp-say {
  margin: 0 0 var(--s-4); padding: 11px 13px;
  border-radius: var(--r-md); background: var(--bg-2);
  border-left: 3px solid var(--say-c, var(--border-1));
  font-size: var(--fs-13); line-height: var(--lh-base); color: var(--fg-2);
  transition: border-color .18s ease;
}
.shelp-say b { color: var(--fg-1); font-weight: var(--fw-extra); }
.shelp-say.bad  { --say-c: var(--conv-bad-dot); }
.shelp-say.mid  { --say-c: var(--conv-mid-dot); }
.shelp-say.good { --say-c: var(--conv-good-dot); }

/* Il resto era tre paragrafi in fila: si leggeva come un contratto. Ora sono
   tre blocchi richiudibili — il primo aperto — così chi vuole solo la scala
   chiude tutto e chi vuole il metodo lo apre. */
.shelp-x-list { display: flex; flex-direction: column; gap: var(--s-2); }
.shelp-x {
  border: 1px solid var(--border-1); border-radius: var(--r-md);
  background: var(--bg-1); overflow: hidden;
}
.shelp-x > summary {
  list-style: none; cursor: pointer; padding: 11px 12px;
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1);
}
.shelp-x > summary::-webkit-details-marker { display: none; }
.shelp-x > summary::after {
  content: ''; margin-left: auto; flex: 0 0 auto;
  width: 7px; height: 7px;
  border-right: 2px solid var(--fg-4); border-bottom: 2px solid var(--fg-4);
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform .18s ease;
}
.shelp-x[open] > summary::after { transform: rotate(-135deg) translate(-1px, -1px); }
.shelp-x[open] > summary { border-bottom: 1px solid var(--border-2); }
.shelp-x-ic {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: var(--r-sm);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-50); color: var(--green-600);
}
.shelp-x-ic svg { width: 15px; height: 15px; }
.shelp-x p {
  margin: 0; padding: 10px 12px 13px;
  font-size: var(--fs-13); line-height: var(--lh-base); color: var(--fg-2);
}
.shelp-x p b { color: var(--fg-1); font-weight: var(--fw-extra); }

/* Invito a segnalare in fondo alla home */
.cta {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
  padding: var(--s-4); border-radius: var(--r-xl);
  background: linear-gradient(135deg, var(--green-700), var(--green-900));
  color: #fff; box-shadow: 0 14px 30px -18px rgba(var(--green-500-rgb), 1);
}
.cta-ic {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .28);
}
.cta-ic svg { width: 22px; height: 22px; }
.cta-txt { flex: 1; min-width: 0; }
.cta-txt b { display: block; font-size: var(--fs-15); font-weight: var(--fw-extra); }
.cta-txt span { display: block; font-size: var(--fs-12); opacity: .82; line-height: var(--lh-snug); margin-top: 1px; }
.cta > svg:last-child { width: 16px; height: 16px; opacity: .7; flex: 0 0 auto; }
.cta:active { transform: scale(.99); }

/* ── Blocchi di contenuto ──────────────────────────────────────────────── */
.pad { padding: var(--s-4); }
.stack { display: flex; flex-direction: column; gap: var(--s-3); }

.sect { padding: var(--s-5) var(--s-4) 0; }
.sect-head {
  display: flex; align-items: baseline; gap: var(--s-3);
  margin-bottom: var(--s-3);
}
.sect-head h2 {
  flex: 1;
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-13); font-weight: var(--fw-extra);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
  color: var(--fg-4);
}
/* Trattino verde davanti al titolo: dà un ancoraggio al marchio senza
   aggiungere una riga di testo in più. */
.sect-head h2::before {
  content: ""; flex: 0 0 auto;
  width: 3px; height: 13px; border-radius: 2px;
  background: linear-gradient(180deg, var(--green-400), var(--green-600));
}
.sect-head .link {
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--green-600);
}

.card {
  background: var(--bg-1);
  border: 1px solid var(--border-2);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-card);
}
.card.tappable { transition: transform var(--t-fast); }
.card.tappable:active { transform: scale(.985); }

/* ── Bottoni ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: 50px; padding: 0 var(--s-5); width: 100%;
  border-radius: var(--r-xl);
  font-size: var(--fs-15); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal);
  transition: transform var(--t-fast), opacity var(--t-fast), background var(--t-fast);
}
.btn:active { transform: scale(.98); }
.btn[disabled] { opacity: .5; pointer-events: none; }
.btn svg { width: 19px; height: 19px; flex: 0 0 auto; }
.btn-primary {
  background: linear-gradient(135deg, var(--green-500), var(--green-700));
  color: #fff;
  box-shadow: 0 10px 24px -12px rgba(var(--green-500-rgb), .95),
              inset 0 1px 0 rgba(255,255,255,.28);
}
.btn-soft   { background: var(--green-50); color: var(--green-700); border: 1px solid var(--green-100); }
.btn-outline{ background: var(--bg-1); color: var(--fg-1); border: 1px solid var(--border-1); box-shadow: var(--shadow-xs); }
.btn-ghost  { background: none; color: var(--fg-2); font-weight: var(--fw-bold); }
.btn-danger { background: var(--conv-bad-bg); color: var(--conv-bad-fg); border: 1px solid var(--conv-bad-line); }
.btn-sm     { height: 40px; padding: 0 var(--s-4); font-size: var(--fs-14); width: auto; border-radius: var(--r-lg); }

/* ── Campi ─────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field > label {
  font-size: var(--fs-12); font-weight: var(--fw-bold);
  color: var(--fg-3); letter-spacing: var(--ls-normal);
}
.input {
  height: 50px; padding: 0 var(--s-4);
  background: var(--bg-2);
  border: 1.5px solid var(--border-1); border-radius: var(--r-lg);
  font-size: var(--fs-15); font-weight: var(--fw-semibold);
  outline: none;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
  /* 16px reale evita lo zoom automatico di iOS all'apertura della tastiera. */
  font-size: max(var(--fs-15), 16px);
}
textarea.input { height: auto; min-height: 88px; padding: var(--s-3) var(--s-4); resize: none; line-height: var(--lh-base); }
.input::placeholder { color: var(--fg-4); font-weight: var(--fw-medium); }
.input:focus { border-color: var(--green-400); background: var(--bg-1); box-shadow: var(--shadow-focus-green); }
.input.bad { border-color: var(--conv-bad-dot); box-shadow: var(--shadow-focus-red); }
.hint { font-size: var(--fs-12); color: var(--fg-4); line-height: var(--lh-snug); }

/* ── Barra di ricerca ──────────────────────────────────────────────────── */
/* Appiccicata in alto: scorrendo i risultati il campo spariva, e per cercare
   un'altra cosa bisognava risalire tutto l'elenco. */
.searchbar {
  position: sticky; top: 0; z-index: 12;
  padding: var(--s-3) var(--s-4);
  background: rgba(255, 255, 255, .94);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--green-100);
}
.sfield {
  display: flex; align-items: center; gap: var(--s-2);
  height: 46px; padding: 0 var(--s-3);
  background: var(--bg-2); border: 1.5px solid transparent; border-radius: var(--r-lg);
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.sfield:focus-within { border-color: var(--green-400); background: var(--bg-1); box-shadow: var(--shadow-focus-green); }
.sfield svg { width: 19px; height: 19px; color: var(--fg-4); flex: 0 0 auto; }
.sfield input {
  flex: 1; min-width: 0; border: none; outline: none; background: none;
  font-size: max(var(--fs-15), 16px); font-weight: var(--fw-semibold);
}
.sfield input::placeholder { color: var(--fg-4); font-weight: var(--fw-medium); }
/* `type="search"` porta con sé la ✕ del browser, che sta ACCANTO alla nostra:
   due croci a un centimetro l'una dall'altra, di cui una non fa quello che
   pensi (svuota il campo senza dirlo al codice). Resta la nostra. */
.sfield input::-webkit-search-cancel-button,
.sfield input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.sfield .clear { flex: 0 0 auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; color: var(--fg-4); border-radius: var(--r-pill); }
.sfield .clear svg { width: 15px; height: 15px; }

/* ── Microfono nella barra di ricerca ─────────────────────────────────────── */
/* Stesso tasto in ogni campo (Cerca, quick-add del carrello). Mentre ascolta
   diventa rosso e pulsa: è la convenzione della registrazione, e senza un segno
   vivo non si capisce se sta sentendo. Si disegna solo dove la dettatura esiste
   (SC.Voice.supported), quindi il tasto non è mai muto. */
.sfield .mic {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-4); background: transparent;
  transition: color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.sfield .mic svg { width: 17px; height: 17px; }
.sfield .mic:hover { color: var(--green-600); background: var(--green-50); }
.sfield .mic:active { transform: scale(.9); }
.sfield .mic.listening { color: var(--conv-bad-dot); background: var(--conv-bad-bg); animation: micPulse 1.2s ease-in-out infinite; }
@keyframes micPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--conv-bad-dot) 35%, transparent); }
  50%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--conv-bad-dot) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .sfield .mic.listening { animation: none; } }

/* La riga dei filtri (offerte, marca, catena, prezzo). Scorre in orizzontale
   invece di andare a capo — la barra è appiccicata in alto e una seconda riga
   mangerebbe i risultati. */
.sfilters {
  display: flex; align-items: center; gap: var(--s-2);
  margin-top: var(--s-2); overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
}
.sfilters::-webkit-scrollbar { display: none; }
/* Sopra il campo (il caso normale: si sceglie prima, si chiede dopo). Il
   margine passa da sopra a sotto, o i chip restano incollati al campo. */
.sfilters.above { margin-top: 0; margin-bottom: var(--s-2); }
/* Nella home il campo ha già il suo stacco dall'alto: qui lo stacco lo prende
   la riga dei chip, che ora è la prima cosa sotto al titolo. */
.hero .sfilters.above { margin-top: var(--s-4); margin-bottom: 0; padding-bottom: 2px; }
.hero .sfilters.above + .hero-sw { margin-top: var(--s-2); }
/* Chip che APRE una scelta (non un interruttore): la freccia lo dice prima del
   tocco, e da acceso porta scritto il valore scelto, non il nome del filtro. */
.fsel > svg { width: 12px; height: 12px; transform: rotate(90deg); opacity: .55; }
.fsel.on > svg { opacity: .9; }
.fclear { color: var(--fg-4); }
.fclear svg { width: 12px; height: 12px; }
/* I completamenti hanno una riga propria e sparisce quando è vuota: senza
   `:empty` lascerebbe un gap sotto i filtri a campo pulito. */
.sugg { display: flex; gap: var(--s-2); margin-top: var(--s-2); flex-wrap: wrap; }
.sugg:empty { display: none; }
.snote svg { width: 14px; height: 14px; vertical-align: -2px; color: var(--fg-4); }

/* Campo di ricerca dentro un foglio di scelta (le marche sono centinaia). */
.pickfind {
  display: flex; align-items: center; gap: var(--s-2);
  height: 42px; padding: 0 var(--s-3); margin-bottom: var(--s-3);
  background: var(--bg-2); border: 1.5px solid var(--border-2); border-radius: var(--r-lg);
}
.pickfind svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--fg-5); }
.pickfind input {
  flex: 1; min-width: 0; height: 100%; border: none; background: none;
  font-size: var(--fs-15); font-weight: var(--fw-semibold); color: var(--fg-1);
}
.pickfind input::placeholder { color: var(--fg-5); font-weight: var(--fw-medium); }
.pickfind input:focus { outline: none; }
/* Stessa ragione del campo grande: via la ✕ di sistema di `type="search"`. */
.pickfind input::-webkit-search-cancel-button,
.pickfind input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
.picknote {
  padding: var(--s-2) var(--s-1);
  font-size: var(--fs-12); color: var(--fg-4); line-height: var(--lh-snug);
}
/* "Mostra altre N marche": un TASTO, non una nota. Le marche sono ~400 e se ne
   disegnano 60 per volta; prima la riga in fondo diceva soltanto quante ne
   restavano, quindi chi non conosceva già il nome da scrivere si fermava lì. */
.pickmore {
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  width: 100%; min-height: 46px; margin-top: var(--s-2);
  background: var(--bg-2); border: 1.5px solid var(--border-2);
  border-radius: var(--r-lg); cursor: pointer;
  font-family: inherit; font-size: var(--fs-14); font-weight: var(--fw-bold);
  color: var(--fg-2);
}
.pickmore:active { background: var(--bg-3); }
.pickmore em { font-style: normal; font-size: var(--fs-12); font-weight: var(--fw-medium); color: var(--fg-4); }
/* Il titolino che separa i gruppi del foglio marche ("Marche" / "Marche dei
   supermercati"). Serve perché sono due cose diverse: le insegne rispondono a
   "la più economica", le marche dell'industria a "quella che compro sempre".
   È TESTO e non una scheda: divide, senza sembrare un'altra voce da toccare. */
.pickgrp {
  padding: var(--s-3) var(--s-1) 2px;
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  letter-spacing: .04em; text-transform: uppercase; color: var(--fg-5);
}
.pickgrp:first-child { padding-top: 0; }
/* La voce ombrello "Marca propria": stessa riga delle altre, un filo più
   marcata perché è la scelta che porta più lontano (tutte le insegne insieme). */
.chainopt.own { border-color: var(--green-200); background: var(--green-50); }
.chainopt.own.on { border-color: var(--green-500); }

/* ── Foglio "fascia di prezzo" ───────────────────────────────────────────────
   Era un elenco di quattro righe identiche, dove l'unica differenza fra una e
   l'altra stava dentro il testo: per scegliere bisognava LEGGERLE tutte. Qui le
   fasce diventano tessere con una scala di € che si riempie (una occhiata dice
   quanto si sta salendo) e sotto c'è la via d'uscita per chi ha in testa una
   cifra precisa: "da … a …", che nessuna fascia fissa può indovinare. */
.pricepick { display: flex; flex-direction: column; gap: var(--s-2); }
.pband {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s-3); text-align: left;
  background: var(--bg-1); border: 1.5px solid var(--border-2);
  border-radius: var(--r-lg); cursor: pointer; font-family: inherit;
}
.pband:active { transform: scale(.99); background: var(--bg-2); }
.pband.on { border-color: var(--green-500); background: var(--green-50); }
/* "Qualsiasi prezzo" sta fuori dalla griglia: non è una quinta fascia, è il
   modo di TOGLIERE il filtro — perciò riga larga con icona, come nelle marche. */
.pband.any { flex-direction: row; align-items: center; gap: var(--s-3); min-height: 52px; }
.pband-ic {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: var(--r-md);
  background: var(--green-50); border: 1px solid var(--green-200); color: var(--green-700);
}
.pband-ic svg { width: 18px; height: 18px; }
.pband-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
/* La scala: quattro €, riempiti fino al livello della fascia. È l'unica parte
   che si legge senza leggere — il testo sotto resta, ma serve a confermare. */
.pband-sc { display: flex; gap: 1px; margin-bottom: 2px; }
.pband-sc i {
  font-style: normal; font-size: var(--fs-14); font-weight: var(--fw-extra);
  color: var(--border-2); line-height: 1;
}
.pband-sc i.fill { color: var(--green-600); }
.pband.on .pband-sc i { color: var(--green-200); }
.pband.on .pband-sc i.fill { color: var(--green-700); }
.pband-nm { font-size: var(--fs-14); font-weight: var(--fw-bold); color: var(--fg-1); }
.pband.on .pband-nm { color: var(--green-800); }
.pband-hint { font-size: var(--fs-11); font-weight: var(--fw-medium); color: var(--fg-4); }
.prange {
  margin-top: var(--s-1); padding: var(--s-3);
  background: var(--bg-2); border: 1.5px solid var(--border-2); border-radius: var(--r-lg);
}
.prange.on { border-color: var(--green-500); background: var(--green-50); }
.prange-t {
  margin-bottom: var(--s-2);
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  letter-spacing: .04em; text-transform: uppercase; color: var(--fg-5);
}
.prange-row { display: flex; align-items: center; gap: var(--s-2); }
.prange-f {
  display: flex; align-items: center; gap: 4px; flex: 1; min-width: 0;
  height: 44px; padding: 0 var(--s-2);
  background: var(--bg-1); border: 1.5px solid var(--border-2); border-radius: var(--r-md);
}
.prange-f > span { font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-5); }
.prange-f input {
  flex: 1; min-width: 0; width: 100%; height: 100%;
  border: none; background: none; font-family: inherit;
  font-size: var(--fs-15); font-weight: var(--fw-bold); color: var(--fg-1);
}
.prange-f input:focus { outline: none; }
/* Le frecce su/giù del number rubano metà campo su un telefono e non servono:
   il valore si scrive, non si incrementa di mezzo euro alla volta. */
.prange-f input::-webkit-outer-spin-button,
.prange-f input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.prange-f input[type="number"] { -moz-appearance: textfield; }
.prange-f b { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--fg-4); }
.prange-go {
  height: 44px; padding: 0 var(--s-4); flex: 0 0 auto;
  background: var(--green-600); color: #fff; border-radius: var(--r-md);
  font-family: inherit; font-size: var(--fs-14); font-weight: var(--fw-bold);
}
.prange-go:active { background: var(--green-700); }
[data-theme="dark"] .pband.on,
[data-theme="dark"] .prange.on { background: var(--bg-2); border-color: var(--green-500); }
[data-theme="dark"] .pband.on .pband-nm { color: var(--green-300); }
[data-theme="dark"] .pband.on .pband-sc i.fill { color: var(--green-400); }
[data-theme="dark"] .pband-ic { background: var(--bg-3); border-color: var(--border-1); color: var(--green-400); }
/* La riga che apre i risultati: "12 prodotti per «pasta»" e, a destra, quanti
   filtri stanno tagliando l'elenco. È l'unica frase della schermata che dice
   COSA si sta guardando — senza, sotto la barra partivano subito le schede e un
   elenco corto poteva essere un catalogo povero o un filtro stretto, senza modo
   di distinguerli. Il conteggio filtri è un TASTO: li toglie da qui. */
.reshead {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-3) var(--s-4) 2px;
}
.reshead-t {
  min-width: 0; font-size: var(--fs-13); color: var(--fg-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.reshead-t b { color: var(--fg-1); font-weight: var(--fw-extra); }
.reshead-x {
  display: flex; align-items: center; gap: 5px; flex: 0 0 auto;
  height: 26px; padding: 0 var(--s-2);
  background: var(--green-50); border: 1px solid var(--green-200);
  border-radius: var(--r-pill); color: var(--green-700);
  font-family: inherit; font-size: var(--fs-11); font-weight: var(--fw-bold);
}
.reshead-x svg { width: 12px; height: 12px; }
.reshead-x:active { background: var(--green-100); }
[data-theme="dark"] .reshead-x { background: var(--bg-3); border-color: var(--border-1); color: var(--green-400); }
/* Il separatore fra il prodotto chiesto e i "contiene anche": una riga di
   testo, non una card — deve dividere senza sembrare un altro risultato. */
.sect-split {
  padding: var(--s-4) var(--s-4) var(--s-2);
  font-size: var(--fs-12); font-weight: var(--fw-bold);
  color: var(--fg-4); text-transform: none;
}
/* "Nessun risultato per X: ecco Y" — si legge PRIMA dell'elenco, altrimenti
   sembra che abbiamo risposto a un'altra domanda. */
.snote {
  margin: var(--s-3) var(--s-4) 0; padding: var(--s-3);
  border-radius: var(--r-lg); background: var(--bg-2);
  font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug);
}
.snote b { color: var(--fg-1); font-weight: var(--fw-bold); }

/* ── Barra "aggiungi" del carrello ────────────────────────────────────────── */
/* Sembra un campo di ricerca ma è un tasto: apre il foglio quick-add, dove il
   campo vero scrive e ascolta senza che aggiungere un prodotto cancelli quello
   che stai facendo. */
.cart-addbar {
  display: flex; align-items: center; gap: var(--s-2);
  width: calc(100% - 2 * var(--s-4)); margin: var(--s-3) var(--s-4);
  height: 50px; padding: 0 6px 0 var(--s-3);
  background: var(--bg-1); border: 1.5px solid var(--border-1); border-radius: var(--r-lg);
  color: var(--fg-4); text-align: left;
  box-shadow: var(--shadow-xs);
  transition: border-color var(--t-fast), background var(--t-fast),
              transform var(--t-fast), box-shadow var(--t-fast);
}
.cart-addbar > svg { width: 19px; height: 19px; flex: 0 0 auto; }
/* Il testo prende lo spazio, la pastiglia no. Prima la regola era
   `.cart-addbar span` e colpiva ANCHE la pastiglia del "+": essendo più
   specifica di `.cart-addbar-plus` vinceva lei, e il "+" si stirava per metà
   barra spingendo l'etichetta su due righe (visibile a schermo). */
.cart-addbar > span:not(.cart-addbar-plus) {
  flex: 1; min-width: 0; font-size: var(--fs-15); font-weight: var(--fw-semibold);
}
.cart-addbar:active {
  transform: scale(.985); border-color: var(--green-400);
  box-shadow: 0 0 0 3px rgba(var(--green-500-rgb), .12);
}
.cart-addbar .cart-addbar-plus {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-600); color: #fff;
  box-shadow: 0 6px 14px -8px rgba(var(--green-500-rgb), 1);
}
.cart-addbar .cart-addbar-plus svg { width: 18px; height: 18px; }

/* ── Foglio quick-add ─────────────────────────────────────────────────────── */
.qa { display: flex; flex-direction: column; gap: var(--s-1); }
.qa-body { min-height: 130px; }
.qa-sect {
  padding: var(--s-3) var(--s-1) var(--s-1);
  font-size: var(--fs-12); font-weight: var(--fw-extra); color: var(--fg-4);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
/* I suggerimenti vanno a capo invece di scorrere: nel foglio c'è spazio in
   verticale e vederli tutti insieme è più veloce che scorrerli di lato. */
.chiprow-wrap { flex-wrap: wrap; overflow: visible; padding: var(--s-1) 0 var(--s-2); }

/* Scorciatoie del foglio "aggiungi prodotti" ("La spesa di base", "Le tue
   ricerche recenti", "Forse cerchi"): tre colonne, icona del reparto sopra il
   nome.

   Erano due colonne di righe, icona a sinistra e nome accanto — la stessa forma
   delle righe di prodotto vere, quelle col prezzo e il tasto "+". Due cose che
   si somigliano ma fanno cose diverse: quelle aggiungono un prodotto al
   carrello, queste avviano una ricerca. In griglia, con l'icona sopra, si
   leggono per quello che sono: scorciatoie. E dodici stanno in quattro file
   invece di sei, quindi si vedono senza scorrere. */
.qagrid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2);
  padding: var(--s-1) 0 var(--s-3);
}
.qatile {
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 7px; min-height: 84px; padding: 10px 6px 9px; text-align: center;
  background: var(--bg-1); border: 1px solid var(--border-1);
  border-radius: var(--r-lg);
  transition: transform var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.qatile:active { transform: scale(.96); background: var(--green-50); border-color: var(--green-200); }
/* La tessera dell'icona è la stessa delle righe prodotto (colori per reparto
   inclusi): è il colore a far riconoscere il reparto prima di leggere. */
.qatile .prod-ic { width: 36px; height: 36px; border-radius: var(--r-md); }
.qatile .prod-ic svg { width: 18px; height: 18px; }
/* Il nome può andare a capo (le ricerche recenti dell'utente sono libere:
   "olio extravergine", "carta igienica") ma si ferma a due righe, così le
   tessere di una fila restano alte uguali. */
.qatile-nm {
  min-width: 0; width: 100%;
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-1);
  line-height: var(--lh-snug); overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* ── Ricette pronte ────────────────────────────────────────────────────── */
/* Stanno sotto la barra di ricerca, non in fondo alla schermata: sono una
   scorciatoia DELLA ricerca — "stasera pizza" invece di sei ricerche di fila —
   e riempiono il carrello in un tocco. La riga scorre di lato perché in
   verticale ruberebbe metà schermo ai risultati, che restano la cosa
   principale della pagina. */
.recbar { padding: var(--s-3) 0 var(--s-2); border-bottom: 1px solid var(--border-2); }
.recbar-head {
  display: flex; align-items: flex-start; gap: 6px;
  padding: 0 var(--s-4) var(--s-2);
  font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug);
}
.recbar-head svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--green-600); margin-top: 1px; }
.recbar-head b { color: var(--fg-2); font-weight: var(--fw-extra); }

.recrow {
  display: flex; gap: var(--s-2); overflow-x: auto;
  padding: 0 var(--s-4) var(--s-2);
  scrollbar-width: none; -ms-overflow-style: none;
}
.recrow::-webkit-scrollbar { display: none; }

.reccard {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--s-2);
  height: 52px; padding: 0 var(--s-3) 0 10px;
  border-radius: var(--r-lg);
  background: var(--bg-1); border: 1px solid var(--border-1);
  box-shadow: var(--shadow-xs);
  text-align: left;
  transition: transform var(--t-fast), border-color var(--t-fast), opacity var(--t-fast);
}
.reccard:active { transform: scale(.96); border-color: var(--green-400); }
.reccard[disabled] { opacity: .5; }
.reccard-ic {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, var(--green-100), var(--green-50));
  color: var(--green-700);
}
.reccard-ic svg { width: 19px; height: 19px; }
.reccard-tx { display: flex; flex-direction: column; min-width: 0; }
.reccard-tx b { font-size: var(--fs-13); font-weight: var(--fw-extra); white-space: nowrap; letter-spacing: var(--ls-normal); }
.reccard-tx i { font-style: normal; font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-semibold); white-space: nowrap; }

/* Ricerca in corso: la scheda toccata pulsa. Cercare sei ingredienti richiede
   qualche secondo, e un tasto che non dà segno di vita sembra rotto. */
.reccard.busy { border-color: var(--green-400); }
.reccard.busy .reccard-ic { animation: recPulse 1s ease-in-out infinite; }
@keyframes recPulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .reccard.busy .reccard-ic { animation: none; } }

/* ── Chip / segmenti ───────────────────────────────────────────────────── */
.chiprow {
  display: flex; gap: var(--s-2); overflow-x: auto; padding: var(--s-3) var(--s-4);
  scrollbar-width: none; -ms-overflow-style: none;
}
.chiprow::-webkit-scrollbar { display: none; }
.chip {
  flex: 0 0 auto; height: 34px; padding: 0 var(--s-4);
  display: inline-flex; align-items: center; gap: var(--s-2);
  border-radius: var(--r-pill);
  background: var(--bg-1); border: 1px solid var(--border-1);
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--fg-2);
  transition: all var(--t-fast); white-space: nowrap;
}
.chip.on { background: var(--green-600); border-color: var(--green-600); color: #fff; }
.chip:active { transform: scale(.95); }
/* Versione compatta: sotto la barra di ricerca i chip stanno in fila col campo
   e a 34px rubavano metà dello spazio utile sopra i risultati. */
.chip.sm { height: 28px; padding: 0 var(--s-3); font-size: var(--fs-12); gap: 5px; }
.chip.sm svg { width: 13px; height: 13px; }

.segment {
  display: flex; gap: 4px; padding: 4px; margin: 0 var(--s-4);
  background: var(--bg-3); border-radius: var(--r-lg);
}
.segment button {
  flex: 1; height: 36px; border-radius: var(--r-md);
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--fg-3);
  transition: all var(--t-fast);
}
.segment button.on { background: var(--bg-1); color: var(--fg-1); box-shadow: var(--shadow-xs); }
/* Respiro sotto le linguette. Deve stare DOPO `.segment`: la regola stava in
   cima al foglio, con la stessa specificità, e perdeva contro
   `margin: 0 var(--s-4)` — il margine sotto non arrivava mai e le linguette
   restavano incollate alla scheda successiva. */
.segment.segment-spaced { margin-bottom: var(--s-5); }
/* Quattro linguette in una barra da telefono: a fs-13 "Panoramica" non ci sta
   e sborda sulla voce accanto. I nomi non si accorciano — dicono esattamente
   cosa c'è dietro — quindi si stringe il carattere. */
.segment.seg-4 button { font-size: var(--fs-11); letter-spacing: var(--ls-tight); padding: 0 2px; }
/* Scheda negozio: la linguetta attiva usa il verde del brand per staccare
   nettamente dalle inattive — su quattro tab stretti il bianco puro è troppo
   sottile. Il bordo inferiore agisce come "indicatore" senza dover ridisegnare
   tutto il controllo. */
#st-tabs.segment button.on {
  background: var(--green-50); color: var(--green-700);
  box-shadow: 0 0 0 1px var(--green-200);
}
[data-theme="dark"] #st-tabs.segment button.on {
  background: rgba(var(--green-500-rgb), .15); color: var(--green-300);
  box-shadow: 0 0 0 1px rgba(var(--green-500-rgb), .25);
}

/* ── Punteggio ─────────────────────────────────────────────────────────── */
.score {
  flex: 0 0 auto; width: 48px; height: 48px; border-radius: var(--r-lg);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  font-weight: var(--fw-extra); line-height: 1;
}
.score b { font-size: var(--fs-18); letter-spacing: var(--ls-tight); }
.score i { font-style: normal; font-size: var(--fs-10); font-weight: var(--fw-bold); opacity: .75; margin-top: 2px; }
.score.good { background: var(--conv-good-bg); color: var(--conv-good-fg); border: 1px solid var(--conv-good-line); }
.score.mid  { background: var(--conv-mid-bg);  color: var(--conv-mid-fg);  border: 1px solid var(--conv-mid-line); }
.score.bad  { background: var(--conv-bad-bg);  color: var(--conv-bad-fg);  border: 1px solid var(--conv-bad-line); }
.score.na   { background: var(--bg-3); color: var(--fg-4); border: 1px solid var(--border-1); }
.score.na b { font-size: var(--fs-14); }

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  height: 22px; padding: 0 var(--s-2); border-radius: var(--r-pill);
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-normal); white-space: nowrap;
}
.pill.good { background: var(--conv-good-bg); color: var(--conv-good-fg); }
.pill.mid  { background: var(--conv-mid-bg);  color: var(--conv-mid-fg); }
.pill.bad  { background: var(--conv-bad-bg);  color: var(--conv-bad-fg); }
.pill.na   { background: var(--bg-3);         color: var(--fg-3); }
.pill.info { background: var(--green-50);     color: var(--green-700); }

/* ── Riga negozio ──────────────────────────────────────────────────────── */
.store {
  /* `width:100%` + `text-align:left` non sono decorativi: la riga è un
     <button>, che di suo si dimensiona sul contenuto e centra il testo — senza
     questi, un nome lungo sfonda la riga e spinge fuori il punteggio. */
  width: 100%; text-align: left;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3);
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-xl); box-shadow: var(--shadow-card);
  transition: transform var(--t-fast);
}
.store:active { transform: scale(.985); }
/* Filo colorato a sinistra: il verdetto si legge scorrendo, senza fermarsi a
   guardare il numero in fondo alla riga. */
.store.good { border-left: 4px solid var(--conv-good-dot); }
.store.mid  { border-left: 4px solid var(--conv-mid-dot); }
.store.bad  { border-left: 4px solid var(--conv-bad-dot); }
.store.na   { border-left: 4px solid var(--border-1); }
/* La tessera del marchio è LARGA, non quadrata.
   Metà dei loghi della grande distribuzione è un logotipo disteso: Bennet è
   512×93, Conad 130×30. In un quadrato da 44px con `object-fit: contain` quel
   file veniva rimpicciolito finché ci stava in larghezza, e restavano otto
   pixel di altezza — sul telefono si vedeva una macchia, non un marchio.
   Allargando la tessera lo stesso file raddoppia, mentre i marchi quadrati
   (Lidl, Penny, Aldi, NaturaSì, Carrefour) non cambiano di un pixel perché a
   limitarli è comunque l'altezza. Il fondo bianco fisso, e non var(--bg-2),
   perché i loghi sono disegnati per la carta: su grigio scuro i marchi con le
   parti bianche sparivano. */
.store-logo {
  flex: 0 0 auto; width: 58px; height: 46px; border-radius: var(--r-md);
  background: #fff; border: 1px solid var(--border-2);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; padding: 4px 5px;
}
.store-logo img { width: 100%; height: 100%; object-fit: contain; }
.store-logo span { font-size: var(--fs-16); font-weight: var(--fw-extra); color: var(--fg-3); }

/* Il monogramma — la tessera di una catena di cui NON abbiamo il marchio.
   Il fondo bianco esiste per far risaltare un logo stampato: senza logo resta
   un rettangolo bianco vuoto con una lettera grigia in mezzo, e si legge come
   un'immagine che non si è caricata. Qui diventa una tessera piena, con la
   lettera in negativo: non finge di essere un marchio, ma è chiaramente
   voluta. Il grigio (non il verde) perché il verde nell'app vuol dire
   "conviene" e una catena senza logo non è né meglio né peggio.
   La classe la mette main.js quando l'immagine fallisce. */
.store-logo.is-mono, .cmp-logo.is-mono, .rkrow-logo.is-mono, .chainopt-logo.is-mono {
  background: var(--zinc-100); border: 1px solid var(--border-1);
}
.store-logo.is-mono span, .cmp-logo.is-mono span,
.rkrow-logo.is-mono span, .chainopt-logo.is-mono span {
  color: var(--fg-2); letter-spacing: var(--ls-tight);
}
[data-theme="dark"] .store-logo.is-mono,
[data-theme="dark"] .cmp-logo.is-mono,
[data-theme="dark"] .rkrow-logo.is-mono,
[data-theme="dark"] .chainopt-logo.is-mono {
  background: var(--zinc-800); border-color: rgba(255, 255, 255, .12);
}
[data-theme="dark"] .store-logo.is-mono span,
[data-theme="dark"] .cmp-logo.is-mono span,
[data-theme="dark"] .rkrow-logo.is-mono span,
[data-theme="dark"] .chainopt-logo.is-mono span { color: var(--zinc-300); }

/* Nell'elenco della classifica in home la riga è più bassa: tessera più
   piccola, stesse proporzioni. Qui la CORNICE non c'è: l'elenco è già una
   scheda bianca, quindi ogni riquadro attorno al logo era una scatola dentro
   una scatola — nove rettangoli grigi che pesavano quanto i marchi.
   Il fondo bianco invece RESTA, e non è una svista: di giorno è bianco su
   bianco e quindi invisibile (che è lo scopo), ma di notte la scheda è scura e
   senza di esso i marchi con le parti bianche — il cerchio di Lidl, la "C" di
   Carrefour — sparirebbero nel fondo. */
.rkrow-logo {
  flex: 0 0 auto; width: 46px; height: 32px; border-radius: var(--r-sm, 6px);
  background: #fff;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; padding: 2px 3px;
}
.rkrow-logo img { width: 100%; height: 100%; object-fit: contain; }
.rkrow-logo span { font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-3); }
.store-body { flex: 1; min-width: 0; }
.store-name {
  font-size: var(--fs-15); font-weight: var(--fw-bold); letter-spacing: var(--ls-normal);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.store-meta {
  display: flex; align-items: center; gap: var(--s-2); margin-top: 3px;
  font-size: var(--fs-12); color: var(--fg-3); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.store-meta .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--fg-5); flex: 0 0 auto; }
/* Il troncamento coi puntini non funziona sul contenitore flex: va sul figlio. */
.store-meta > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Riga prodotto ─────────────────────────────────────────────────────── */
.prod {
  width: 100%; text-align: left;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3);
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-xl); box-shadow: var(--shadow-card);
}
/* ── Tinte di famiglia ─────────────────────────────────────────────────────
   Le icone dei prodotti le disegna il classificatore del sito (/js/catIcons.js):
   17 famiglie. Diciassette colori sarebbero un arcobaleno, quindi le famiglie
   vicine condividono la tinta — nove in tutto. Serve a riconoscere il reparto
   prima di leggere il nome, non a codificare un'informazione: sono tinte tenui,
   e il nome del prodotto resta l'unica cosa che si legge davvero.

   Ogni famiglia dichiara solo la terna sfondo/segno/filo; chi disegna la usa.
   Il verde resta il caso di partenza (famiglia non riconosciuta, più frutta e
   dispensa che sul verde ci stanno di casa).

   `:is(…)` copre i tre portatori con una riga sola: la tessera dell'icona, la
   testata di reparto e la RIGA del carrello — che del filo colorato a sinistra
   ha bisogno anche lei, e non contiene la tessera nel senso dell'ereditarietà
   perché le variabili le dichiarerebbe un suo figlio. */
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="latticini"] { --ic-bg: #e0f2fe; --ic-fg: #0369a1; --ic-line: #bae6fd; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="surgelati"] { --ic-bg: #e0f2fe; --ic-fg: #0284c7; --ic-line: #bae6fd; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="acqua"]     { --ic-bg: #cffafe; --ic-fg: #0e7490; --ic-line: #a5f3fc; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="bevande"]   { --ic-bg: #cffafe; --ic-fg: #0e7490; --ic-line: #a5f3fc; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="pasta"]     { --ic-bg: var(--amber-100); --ic-fg: #b45309; --ic-line: var(--amber-200); }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="snack"]     { --ic-bg: #ffedd5; --ic-fg: #c2410c; --ic-line: #fed7aa; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="carne"]     { --ic-bg: #fee2e2; --ic-fg: #b91c1c; --ic-line: #fecaca; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="salumi"]    { --ic-bg: #ffe4e6; --ic-fg: #be123c; --ic-line: #fecdd3; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="dolci"]     { --ic-bg: #fce7f3; --ic-fg: #be185d; --ic-line: #fbcfe8; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="caffe"]     { --ic-bg: #efe3d8; --ic-fg: #7c4a21; --ic-line: #e2cdba; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="detersivi"] { --ic-bg: #ede9fe; --ic-fg: #6d28d9; --ic-line: #ddd6fe; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="cura"]      { --ic-bg: #f3e8ff; --ic-fg: #7e22ce; --ic-line: #e9d5ff; }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="animali"]   { --ic-bg: var(--zinc-100); --ic-fg: var(--zinc-600); --ic-line: var(--zinc-200); }
:is(.prod-ic, .rgroup-head, .cart-prod, .cmp-ic)[data-cat="altro"]     { --ic-bg: var(--zinc-100); --ic-fg: var(--zinc-600); --ic-line: var(--zinc-200); }

.prod-ic {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: var(--r-md);
  /* Il velo bianco in diagonale sostituisce il vecchio gradiente green-100 →
     green-50: stessa luce, ma vale per tutte e nove le tinte senza doverne
     dichiarare due per famiglia. */
  background-color: var(--ic-bg, var(--green-100));
  background-image: linear-gradient(140deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .55));
  color: var(--ic-fg, var(--green-700));
  border: 1px solid var(--ic-line, var(--green-100));
  display: flex; align-items: center; justify-content: center;
}

/* Tasto "aggiungi al carrello" nelle righe di ricerca. Al secondo tocco
   toglie: verde pieno = c'è dentro, contorno = non ancora. */
.addbtn {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-50); color: var(--green-700);
  border: 1.5px solid var(--green-200);
  transition: transform var(--t-fast), background var(--t-fast);
}
.addbtn svg { width: 20px; height: 20px; stroke-width: 2.2; }
.addbtn:active { transform: scale(.9); }
.addbtn.on {
  background: linear-gradient(140deg, var(--green-500), var(--green-700));
  border-color: var(--green-600); color: #fff;
  box-shadow: 0 6px 14px -8px rgba(var(--green-500-rgb), .95);
}
.prod-ic svg { width: 21px; height: 21px; }
.prod-body { flex: 1; min-width: 0; }
.prod-name {
  font-size: var(--fs-14); font-weight: var(--fw-bold); line-height: var(--lh-snug);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.prod-meta { font-size: var(--fs-12); color: var(--fg-4); font-weight: var(--fw-semibold); margin-top: 2px; }
.prod-price { flex: 0 0 auto; text-align: right; }
.prod-price b { display: block; font-size: var(--fs-16); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.prod-price span { font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-semibold); }
/* "0,69 € a bottiglia" sotto il prezzo di una confezione: è la cifra con cui si
   confronta la bottiglia singola, quindi sta lì sotto e non altrove — ma resta
   piccola, il numero che si paga in cassa è quello sopra. */
.per-piece {
  display: block; margin-top: 1px;
  font-size: var(--fs-11); font-weight: var(--fw-semibold);
  color: var(--fg-4); white-space: nowrap;
}
.cmp-price .per-piece { text-align: right; }

/* Contatore quantità */
.qty { display: flex; align-items: center; gap: var(--s-2); flex: 0 0 auto; }
.qty button {
  width: 32px; height: 32px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-2); color: var(--fg-2); border: 1px solid var(--border-1);
  transition: transform var(--t-fast);
}
.qty button:active { transform: scale(.9); }
.qty button svg { width: 15px; height: 15px; }
.qty b { min-width: 20px; text-align: center; font-size: var(--fs-15); font-weight: var(--fw-extra); }

/* ══════════════════════════════════════════════════════════════════════════
   MAPPA — una scheda, non un visore a tutto schermo
   Rifatta il 2026-08-04. La mappa piena schermo costringeva a coprirla di
   pannelli galleggianti per mostrare qualunque altra cosa; e con i pallini
   grigi dei negozi senza prezzi era anche illeggibile. Adesso è un riquadro
   alto poco meno di metà schermo, con la zona sopra e l'elenco sotto — la
   pagina scorre normalmente.
   ═════════════════════════════════════════════════════════════════════════ */
.zonebar {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-4) 0;
}
.zonechip {
  flex: 1; min-width: 0;
  display: inline-flex; align-items: center; gap: 7px;
  height: 44px; padding: 0 var(--s-3);
  border-radius: var(--r-lg);
  background: var(--bg-1); border: 1.5px solid var(--green-200);
  box-shadow: var(--shadow-card);
  font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1);
  text-align: left;
}
.zonechip > svg:first-child { width: 18px; height: 18px; flex: 0 0 auto; color: var(--green-600); }
.zonechip > svg:last-child  { width: 14px; height: 14px; flex: 0 0 auto; color: var(--fg-5); margin-left: auto; }
.zonechip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zonechip:active { transform: scale(.99); border-color: var(--green-400); }
.zone-gps { width: 44px; height: 44px; background: var(--green-50); color: var(--green-700); border: 1.5px solid var(--green-200); }

/* ── Filtri della mappa ────────────────────────────────────────────────── */
/* Il verdetto (conviene / caro) resta in pastiglie sempre visibili: sono
   quattro, ci stanno, e si vede a colpo d'occhio quale è acceso. La CATENA
   invece è passata a una tendina: in città le insegne sono quindici, e
   trovarne una scorrendo la fila di lato col pollice era il primo difetto
   segnalato. Ritoccare una pastiglia accesa la spegne. */
.filterbar { padding: var(--s-3) 0 0; }

.fdrop {
  flex: 1; min-width: 0;
  display: inline-flex; align-items: center; gap: 8px;
  height: 42px; padding: 0 12px 0 8px;
  border-radius: var(--r-lg);
  background: var(--bg-1); border: 1px solid var(--border-1);
  box-shadow: var(--shadow-xs, 0 1px 2px rgba(15, 23, 42, .06));
  font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1);
  text-align: left; transition: all var(--t-fast);
}
.fdrop:active { transform: scale(.99); background: var(--bg-2); }
.fdrop.on { border-color: var(--green-400); background: var(--green-50); }
.fdrop-tx { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fdrop > svg:last-child { width: 15px; height: 15px; flex: 0 0 auto; color: var(--fg-5); }
.fdrop-ic {
  width: 30px; height: 30px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-md); background: var(--bg-3); color: var(--fg-4);
}
.fdrop-ic svg { width: 16px; height: 16px; }
.fdrop-logo {
  width: 30px; height: 30px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-md); background: #fff; padding: 3px;
  border: 1px solid var(--border-2); overflow: hidden;
}
.fdrop-logo img { width: 100%; height: 100%; object-fit: contain; }

/* La tendina vera e propria, dentro il foglio modale. Righe alte 56px con il
   logo a sinistra: si riconosce l'insegna senza leggere il nome. */
.chainpick { display: flex; flex-direction: column; gap: 6px; }
.chainopt {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 9px 12px; border-radius: var(--r-lg);
  background: var(--bg-1); border: 1.5px solid var(--border-2);
  transition: all var(--t-fast);
}
.chainopt:active { transform: scale(.99); background: var(--bg-2); }
.chainopt.on { border-color: var(--green-500); background: var(--green-50); }
.chainopt-logo, .chainopt-ic {
  width: 38px; height: 38px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-md); background: #fff; padding: 4px;
  border: 1px solid var(--border-2); overflow: hidden;
}
/* La tessera del marchio è LARGA, non quadrata — stessa ragione di
   `.store-logo`: metà dei loghi della grande distribuzione è un logotipo
   disteso (Bennet 512×93, Conad 130×30) e dentro un quadrato da 38px si
   riduceva a sette pixel di altezza. Il quadrato resta all'icona "Tutte le
   catene", che è un simbolo. */
.chainopt-logo { width: 52px; padding: 4px 5px; }
.chainopt-logo img { width: 100%; height: 100%; object-fit: contain; }
.chainopt-logo span { font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-3); }
.chainopt-ic { background: var(--green-50); border-color: var(--green-200); color: var(--green-700); padding: 0; }
.chainopt-ic svg { width: 18px; height: 18px; }
.chainopt-nm {
  flex: 1; min-width: 0;
  font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chainopt-nm em {
  display: block; font-style: normal;
  font-size: var(--fs-11); font-weight: var(--fw-semibold); color: var(--fg-4);
}
.chainopt-n {
  flex: 0 0 auto; min-width: 26px; text-align: center;
  padding: 3px 8px; border-radius: var(--r-pill);
  background: var(--bg-3); color: var(--fg-3);
  font-size: var(--fs-12); font-weight: var(--fw-extra);
}
.chainopt.on .chainopt-n { background: var(--green-600); color: #fff; }
.filterline {
  display: flex; align-items: center; gap: 6px; overflow-x: auto;
  padding: 0 var(--s-4) var(--s-2);
  scrollbar-width: none; -ms-overflow-style: none;
}
.filterline::-webkit-scrollbar { display: none; }
.filterlab { flex: 0 0 auto; display: flex; color: var(--fg-5); margin-right: 1px; }
.filterlab svg { width: 16px; height: 16px; }
.fchip {
  flex: 0 0 auto; height: 32px; padding: 0 12px;
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--r-pill);
  background: var(--bg-1); border: 1px solid var(--border-1);
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--fg-3);
  white-space: nowrap; transition: all var(--t-fast);
}
.fchip:active { transform: scale(.95); }
.fchip.on { background: var(--fg-1); border-color: var(--fg-1); color: var(--bg-1); }
/* Quando il filtro acceso è un verdetto, la pastiglia prende il suo colore:
   dice "stai guardando i convenienti" senza una seconda etichetta. */
.fchip.on.good { background: var(--conv-good-dot); border-color: var(--conv-good-dot); color: #fff; }
.fchip.on.mid  { background: var(--conv-mid-dot);  border-color: var(--conv-mid-dot);  color: #fff; }
.fchip.on.bad  { background: var(--conv-bad-dot);  border-color: var(--conv-bad-dot);  color: #fff; }
/* "Senza voto": grigio, non un quarto colore da imparare. */
.fchip.on.na   { background: var(--fg-4); border-color: var(--fg-4); color: var(--bg-1); }
.fdot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.fdot.good { background: var(--conv-good-dot); }
.fdot.mid  { background: var(--conv-mid-dot); }
.fdot.bad  { background: var(--conv-bad-dot); }
.fdot.na    { background: var(--fg-4); }
.fdot.blind { background: var(--zinc-400, #a1a1aa); }
.fchip.on .fdot { background: rgba(255, 255, 255, .85); }
/* "Senza prezzo" non è un verdetto come gli altri tre: è un interruttore, e
   acceso deve sembrare acceso ma non gridare quanto "Conviene". */
.fchip-blind.on { background: var(--fg-2); border-color: var(--fg-2); color: var(--bg-1); }
.fnum {
  font-style: normal; font-size: var(--fs-10); font-weight: var(--fw-extra);
  padding: 1px 5px; border-radius: var(--r-pill);
  background: var(--bg-3); color: var(--fg-4);
}
.fchip.on .fnum { background: rgba(255, 255, 255, .22); color: inherit; }

.mapcard {
  margin: var(--s-3) var(--s-4) 0;
  background: var(--bg-1);
  border: 1px solid var(--border-2); border-radius: var(--r-xl);
  box-shadow: var(--shadow-card); overflow: hidden;
}
.mapbox { position: relative; height: min(46vh, 380px); background: var(--bg-3); }
#sc-map { position: absolute; inset: 0; }
/* Tutti i comandi di serie di MapLibre restano fuori: bussola, zoom e crediti.
   Sulla mappa non compare nessuna scritta, esattamente come sul sito; il
   credito a OpenStreetMap (ODbL) e CARTO è nei Termini, che dal Profilo si
   aprono nel browser. */
.maplibregl-ctrl-attrib,
.maplibregl-ctrl-bottom-left, .maplibregl-ctrl-bottom-right,
.maplibregl-ctrl-top-right, .maplibregl-ctrl-top-left { display: none !important; }
.maploading {
  position: absolute; inset: 0; z-index: 4;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .6);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}

/* Cinque voci più il conteggio non ci stanno in una riga da 390px, e senza
   `nowrap` sulle etichette la riga si spezzava DENTRO una voce ("Senza /
   prezzo"), che è il modo peggiore di andare a capo. Le voci restano intere e
   vanno a capo per intero; `row-gap` dà aria alla seconda riga. */
.maplegend {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 4px var(--s-2); row-gap: 3px;
  padding: var(--s-2) var(--s-3);
  border-top: 1px solid var(--border-2);
  font-size: var(--fs-11); font-weight: var(--fw-bold); color: var(--fg-3);
}
/* Pallino + parola sono UNA voce e vanno a capo insieme. */
.lgi { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.lg { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.lg.good { background: var(--conv-good-dot); }
.lg.mid  { background: var(--conv-mid-dot); }
.lg.bad  { background: var(--conv-bad-dot); }
/* Due grigi diversi per due cose diverse: N/D è il grigio pieno del testo
   (sappiamo dei prezzi, manca il voto), "senza prezzo" è il grigio slavato dei
   negozi muti. Con un grigio solo la legenda diceva due volte la stessa cosa. */
.lg.na    { background: var(--fg-4); }
.lg.blind { background: var(--zinc-400, #a1a1aa); }
.lg-n { margin-left: auto; color: var(--green-700); font-weight: var(--fw-extra); }

/* Segnaposto DRITTO col punteggio dentro.
   Era una goccia ruotata di 45°: la punta indicava il posto, ma il numero
   dentro andava contro-ruotato e a schermo pieno di punti l'insieme sembrava
   storto. Adesso è una pastiglia dritta con una punta sotto, disegnata col
   pseudo-elemento: sta in piedi come i segnaposti di Apple Maps, e il punto
   indicato resta esattamente sotto la punta (`anchor: 'bottom'`). */
.pin {
  --pin-c: var(--zinc-400, #a1a1aa);
  position: relative;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 7px;                       /* lo spazio della punta */
  border-radius: 50%;
  background: var(--pin-c);
  border: 2.5px solid #fff;
  box-shadow: 0 3px 8px -1px rgba(15, 23, 42, .38), 0 1px 2px rgba(15, 23, 42, .2);
  cursor: pointer; transition: transform var(--t-fast);
}
.pin::after {
  content: ''; position: absolute; top: 100%; left: 50%;
  width: 0; height: 0; margin-left: -5px; margin-top: -1px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 8px solid #fff;
  filter: drop-shadow(0 2px 1px rgba(15, 23, 42, .18));
}
.pin span {
  font-size: var(--fs-12); font-weight: var(--fw-extra); color: #fff;
  letter-spacing: -.02em; line-height: 1;
}
.pin:active { transform: scale(1.14); }
.pin.good { --pin-c: var(--conv-good-dot); }
.pin.mid  { --pin-c: var(--conv-mid-dot); }
.pin.bad  { --pin-c: var(--conv-bad-dot); }
.pin.na   { --pin-c: var(--zinc-400, #a1a1aa); }
/* Prezzi sì, voto no. Grigio come i muti — perché un giudizio non ce l'ha — ma
   della misura piena dei colorati, perché un prezzo ce l'ha eccome: è il caso
   di Lidl, di cui conosciamo centinaia di prezzi ma pochi prodotti del paniere.
   Dentro c'è scritto N/D: tre caratteri al posto di due cifre, quindi vanno
   rimpiccioliti o escono dal cerchio. */
.pin.nd   { --pin-c: var(--fg-4); }
.pin.nd span { font-size: var(--fs-10); letter-spacing: -.04em; }
/* Segnaposto dei negozi SENZA prezzi sulla mappa Negozi: cerchietto più
   piccolo, grigio e col punto interrogativo. Non è un verdetto, è una domanda
   aperta — e non deve rubare l'occhio a quelli che un prezzo ce l'hanno. */
.pin.blind {
  --pin-c: var(--zinc-400, #a1a1aa);
  width: 26px; height: 26px; margin-bottom: 6px;
  border-width: 2px; opacity: .92;
  box-shadow: 0 2px 6px -1px rgba(15, 23, 42, .3);
}
.pin.blind::after { border-top-width: 7px; margin-left: -4px; border-left-width: 4px; border-right-width: 4px; }
.pin.blind span { font-size: var(--fs-12); }

/* ── Segnaposto col MARCHIO E il voto (mappa Negozi) ─────────────────────────
   Prima qui c'era il solo punteggio dentro un cerchio colorato: il colore si
   leggeva da lontano, ma per sapere QUALE catena fosse bisognava aprire il
   segnaposto. Con dieci pastiglie verdi identiche a schermo, "dove conviene"
   restava senza risposta finché non le si toccava tutte.

   Adesso è una targhetta bianca: a sinistra il marchio, a destra la pastiglia
   col voto, che tiene tutto il colore di prima (è la parte piena, quella che si
   vede a colpo d'occhio da lontano). La base `.pin` dà l'ombra, la punta e la
   scala al tocco; qui si rifanno forma e riempimento. */
.pin.brand {
  /* Larghezza dal contenuto, come la targhetta delle segnalazioni: un marchio
     lungo (Bennet 5,5:1) e uno quadrato (Lidl) non possono stare nella stessa
     scatola senza schiacciarsi. `fit-content` e non `auto`: MapLibre posiziona
     in assoluto e `auto` stirava la targhetta per tutta la larghezza. */
  width: fit-content; height: fit-content;
  gap: 5px;
  padding: 3px 3px 3px 6px;
  margin-bottom: 7px;                        /* lo spazio della punta */
  border-radius: var(--r-pill);
  background: #fff;
  border: 1.5px solid var(--pin-c);          /* il bordo ripete il giudizio */
}
/* La punta resta quella della base, ma bianca sopra il colore del bordo:
   ridisegnata come mezzo quadrato ruotato, così i due lati che restano in vista
   portano il colore del giudizio come il resto del contorno. */
.pin.brand::after {
  content: ''; position: absolute; top: auto; left: 50%; bottom: -6px;
  margin: 0; width: 10px; height: 10px;
  border: 0;
  border-right: 1.5px solid var(--pin-c);
  border-bottom: 1.5px solid var(--pin-c);
  border-bottom-right-radius: 2px;
  transform: translateX(-50%) rotate(45deg);
  background: #fff;
  filter: none;
}
/* La targhetta è rimpicciolita (vedi sopra): quello che NON deve rimpicciolirsi
   è il bersaglio del dito. Un riquadro trasparente attorno la rende toccabile
   come prima senza farla vedere più grande — è la ragione per cui il pollice
   non deve prendere la mira su un logo alto dodici pixel. Sta DIETRO
   (`z-index: 0`, e logo e voto sono a 1) per non coprire nulla. */
.pin.brand::before,
.pin.plate::before {
  content: ''; position: absolute; z-index: 0;
  inset: -8px -6px -10px -6px;
  border-radius: var(--r-pill);
}
/* Il voto: pastiglia piena del colore del giudizio, cioè quel che il
   segnaposto era per intero fino a ieri. Larghezza minima e non fissa perché
   "N/D" sono tre caratteri dove il punteggio ne ha due. */
.pin.brand > .pinscore {
  position: relative; z-index: 1;            /* sopra la punta, che passa dietro */
  flex: 0 0 auto;
  min-width: 24px; height: 22px; padding: 0 5px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill);
  background: var(--pin-c);
  font-size: var(--fs-12); font-weight: var(--fw-extra); color: #fff;
  letter-spacing: -.02em; line-height: 1;
}
/* "N/D" e "?" non sono un voto: stessa forma, ma senza il colore pieno che
   griderebbe un giudizio che non abbiamo. */
.pin.brand.nd > .pinscore,
.pin.brand.blind > .pinscore {
  font-size: var(--fs-10); letter-spacing: -.04em;
}
/* I muti stanno un gradino indietro: non hanno un prezzo da dire, e non devono
   rubare l'occhio a quelli che ce l'hanno. */
.pin.brand.blind { opacity: .9; }
/* UNA MISURA PER TUTTI (2026-08-12). Il problema non era la misura — era che
   ogni targhetta ne aveva una sua: la casella seguiva le proporzioni del
   marchio, quindi Esselunga (col suo lockup lungo) usciva larga il doppio di
   Lidl e sulla mappa si leggeva una fila di cartelli disuguali. Ora la casella è
   FISSA e identica per tutti, il marchio ci sta dentro con `contain`, e i due
   logotipi che in una casella fissa diventerebbero una striscia (Esselunga,
   Bennet) passano dalla lettera del marchio — vedi PIN_LETTER in ui.js. */
.pin.brand > .pinlogo { width: 26px; height: 16px; }

/* Segnaposto col MARCHIO (mappa dentro le segnalazioni): targhetta bianca col
   logo della catena, contorno grigio a dire "nessun prezzo". Lì la mappa serve
   a RICONOSCERE il supermercato in cui ci si trova e toccarlo — una fila di
   cerchietti identici costringeva ad aprirli uno per uno. NON è una goccia ma
   una targhetta: dentro un cerchio da 34px un logotipo largo (Conad 130×30,
   Bennet 512×93) si riduce a cinque pixel — la stessa ragione per cui le
   tessere dei marchi nel resto dell'app sono rettangolari. */
.pin.plate {
  /* La targhetta si adatta al MARCHIO: l'altezza la decide il logo (18px,
     uguale per tutti), la larghezza segue le sue proporzioni. `fit-content` e
     non `auto`: MapLibre la posiziona in assoluto e `auto` la stirava per
     tutta la larghezza. */
  width: fit-content; height: fit-content;
  padding: 5px 7px; margin-bottom: 6px;   /* 6px = la punta, che sta sotto */
  border-radius: var(--r-md);
  background: #fff;
  border: 1.5px solid var(--zinc-400, #a1a1aa);
}
.pin.plate:active { transform: scale(1.1); }
/* La punta: mezzo quadratino ruotato sotto la targhetta. Azzera la freccetta
   bianca della base (.pin::after) e la sostituisce. */
.pin.plate::after {
  content: ""; position: absolute; top: auto; left: 50%; bottom: -6px;
  margin: 0; width: 10px; height: 10px;
  border: 0;
  border-right: 1.5px solid var(--zinc-400, #a1a1aa);
  border-bottom: 1.5px solid var(--zinc-400, #a1a1aa);
  border-bottom-right-radius: 2px;
  transform: translateX(-50%) rotate(45deg);
  background: #fff;
  filter: none;
}
.pin > .pinlogo {
  position: relative; z-index: 1;   /* sopra la punta, che le passa dietro */
  /* Casella FISSA, uguale per ogni catena: è questo che rende le targhette
     confrontabili sulla mappa. Prima l'altezza era fissa e la larghezza la
     dettava il marchio, quindi due targhette accanto non avevano mai la stessa
     misura. Un filo più larga che alta perché nessun marchio è più alto che
     largo. */
  width: 30px; height: 18px;
  display: flex; align-items: center; justify-content: center;
  /* Molti marchi sono un rettangolo pieno fino al bordo (blu Lidl, rosso
     Conad): senza smusso gli angoli vivi stonavano dentro la targhetta. */
  border-radius: 3px; overflow: hidden;
}
/* Il marchio riempie la casella fissa senza deformarsi e senza sbordare: è
   `contain` a decidere se lo limita l'altezza (marchi quadrati) o la larghezza
   (i lockup). Niente `max-width` in pixel: il tetto ora È la casella. */
.pin > .pinlogo img { width: 100%; height: 100%; object-fit: contain; }
/* L'iniziale quando il file del logo non c'è: scura, perché la targhetta è
   bianca (le pastiglie col punteggio hanno il testo bianco su fondo pieno). */
.pin > .pinlogo > span {
  font-size: var(--fs-12); font-weight: var(--fw-extra);
  color: var(--zinc-600, #52525b); letter-spacing: -.02em;
}

/* Nota sui negozi esclusi: sono spariti dalla mappa, non dal discorso. */
.blindnote {
  display: flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left;
  margin-top: var(--s-3); padding: var(--s-3);
  border-radius: var(--r-lg);
  background: var(--bg-1); border: 1px dashed var(--green-200);
  font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug);
}
.blindnote svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--green-600); margin-top: 1px; }
.blindnote b { color: var(--fg-1); font-weight: var(--fw-extra); }
.blindnote:active { background: var(--green-50); }

/* ── Foglio modale ─────────────────────────────────────────────────────── */
.sheet-back {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(9, 9, 11, .42);
  opacity: 0; pointer-events: none; transition: opacity var(--t-base);
}
.sheet-back.on { opacity: 1; pointer-events: auto; }
/* Il foglio non è incollato ai bordi: 8px di aria su tre lati e gli angoli
   tondi anche in basso. Appiccicato allo schermo sembrava una parte fissa
   dell'app; staccato si legge per quello che è — una cosa sopra le altre, che
   si può spingere via. Da chiuso deve uscire di tutta la sua altezza PIÙ lo
   stacco, altrimenti resterebbe una striscia in vista in fondo. */
.sheet {
  position: fixed; left: 12px; right: 12px; z-index: 61;
  bottom: calc(12px + var(--safe-b));
  max-height: calc(88% - var(--safe-b));
  display: flex; flex-direction: column;
  background: var(--bg-1);
  border-radius: var(--r-2xl);
  box-shadow: 0 -10px 40px rgba(0, 0, 0, .22), 0 2px 8px rgba(0, 0, 0, .10);
  transform: translateY(calc(100% + 16px + var(--safe-b)));
  transition: transform var(--t-slow);
  overflow: hidden;              /* gli angoli tondi valgono anche per il piede */
}
.sheet.on { transform: translateY(0); }
.sheet-head {
  flex: 0 0 auto; padding: var(--s-3) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--border-2);
}
.sheet-head .bar { width: 38px; height: 4px; border-radius: var(--r-pill); background: var(--border-1); margin: 0 auto var(--s-3); }
.sheet-head .row { display: flex; align-items: flex-start; gap: var(--s-3); }
.sheet-head h2 { flex: 1; font-size: var(--fs-18); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal); line-height: var(--lh-snug); }
.sheet-head p { font-size: var(--fs-13); color: var(--fg-3); margin-top: 2px; font-weight: var(--fw-semibold); }
.sheet-body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: var(--s-4); }
.sheet-foot { flex: 0 0 auto; padding: var(--s-3) var(--s-4) var(--s-4); border-top: 1px solid var(--border-2); background: var(--bg-1); }

/* ── Confronto prezzi per catena ───────────────────────────────────────── */
.cmp { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3) 0; border-bottom: 1px solid var(--border-2); }
.cmp:last-child { border-bottom: none; }
.cmp-rank { flex: 0 0 auto; width: 22px; font-size: var(--fs-13); font-weight: var(--fw-extra); color: var(--fg-4); text-align: center; }
/* Stessa ragione di `.store-logo`: larga, e su fondo bianco. */
.cmp-logo { flex: 0 0 auto; width: 46px; height: 34px; border-radius: var(--r-sm, 6px); background: #fff; border: 1px solid var(--border-2); display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 3px 4px; }
.cmp-logo img { width: 100%; height: 100%; object-fit: contain; }
.cmp-logo span { font-size: var(--fs-13); font-weight: var(--fw-extra); color: var(--fg-3); }
.cmp-body { flex: 1; min-width: 0; }
.cmp-name { font-size: var(--fs-14); font-weight: var(--fw-bold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmp-sub { font-size: var(--fs-12); color: var(--fg-4); font-weight: var(--fw-semibold); margin-top: 1px; }
.cmp-price { flex: 0 0 auto; font-size: var(--fs-16); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
/* Prezzo e "Portami lì" incolonnati a destra (2026-08-13): il tasto sta sotto la
   cifra, non accanto — accanto rubava larghezza al nome della catena, che su un
   telefono da 390px va già a puntini. */
.cmp-right { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
/* Il tasto: piccolo, verde di solo inchiostro. Non deve competere col prezzo —
   che è la ragione per cui uno sta guardando quella riga — ma deve rispondere
   alla domanda che viene subito dopo, "e dov'è?". */
.cmp-go {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 5px 9px; border-radius: var(--r-pill);
  background: var(--green-50); border: 1px solid var(--green-100);
  color: var(--green-700); font-size: var(--fs-11); font-weight: var(--fw-bold);
  white-space: nowrap;
}
.cmp-go svg { width: 13px; height: 13px; }
.cmp-go:active { background: var(--green-100); }
/* La riga del confronto si apre (storico, orari, "Portami lì"): il tocco deve
   vedersi, o sembra che non ci sia niente da toccare. */
.cmp-tap { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.cmp-tap:active { background: var(--bg-2); }
.cmp-tap.best:active { background: var(--conv-good-line); }

/* Il foglio del supermercato: marchio, nome e prezzo in cima. È la risposta
   alla riga che si è toccata, quindi il prezzo resta la cosa più grossa. */
.csheet-top { display: flex; align-items: center; gap: var(--s-3); }
.csheet-tx { flex: 1; min-width: 0; }
.csheet-n {
  font-size: var(--fs-16); font-weight: var(--fw-extra);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.csheet-p {
  margin-top: 2px;
  font-size: var(--fs-24); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); color: var(--green-700);
}
/* La riga più economica si distingue, ma resta una riga: prima ereditava per
   sbaglio il blocco verde pieno di `.winner` e il prezzo diventava illeggibile. */
.cmp.best {
  margin: 0 calc(var(--s-4) * -1); padding-left: var(--s-4); padding-right: var(--s-4);
  background: var(--conv-good-bg); border-bottom-color: var(--conv-good-line);
}
.cmp.best .cmp-price { color: var(--green-700); }
.cmp.best .cmp-rank  { color: var(--green-600); }
.cmp.best .cmp-name  { color: var(--green-900); }
/* Dove si trova quel supermercato. Va a capo sotto la copertura: due
   informazioni sulla stessa riga si troncano a vicenda su uno schermo stretto,
   e l'indirizzo troncato non porta da nessuna parte. */
.cmp-where { display: block; margin-top: 1px; color: var(--fg-3); font-weight: var(--fw-medium); }

/* ── Scheda negozio (foglio a linguette) ───────────────────────────────── */
/* L'intestazione sta FUORI dalle linguette: è l'identità della scheda, e
   sparire cambiando linguetta farebbe perdere il filo di dove si è. */
.sthead { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); }
.sthead-tx { flex: 1; min-width: 0; }
.sthead-addr {
  margin-top: 4px; font-size: var(--fs-12); color: var(--fg-4);
  font-weight: var(--fw-semibold); line-height: var(--lh-snug);
}
/* "Perché questo punteggio": la riga che apre la spiegazione dentro la scheda.
   Non è una scheda piena — deve leggersi come un chiarimento, non come un altro
   dato — quindi filo e fondo tenui, e la freccia che ruota quando è aperta. */
.whyrow {
  width: 100%; display: flex; align-items: center; gap: var(--s-3);
  text-align: left; padding: var(--s-3); margin-bottom: var(--s-4);
  border-radius: var(--r-lg);
  background: var(--bg-2); border: 1px solid var(--border-2);
  transition: background var(--t-fast);
}
.whyrow:active { background: var(--bg-3); }
.whyrow-ic {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-1); color: var(--fg-3); border: 1px solid var(--border-2);
}
.whyrow-ic svg { width: 16px; height: 16px; }
.whyrow-tx { flex: 1; min-width: 0; }
.whyrow-tx b { display: block; font-size: var(--fs-13); font-weight: var(--fw-extra); color: var(--fg-1); }
.whyrow-tx span {
  display: block; margin-top: 1px; font-size: var(--fs-11);
  font-weight: var(--fw-semibold); color: var(--fg-4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.whyrow-ch { flex: 0 0 auto; color: var(--fg-4); display: flex; transition: transform var(--t-fast); }
.whyrow-ch svg { width: 16px; height: 16px; transform: rotate(90deg); }
.whyrow.on .whyrow-ch svg { transform: rotate(-90deg); }
.shelp { padding: var(--s-4) var(--s-4) var(--s-2); margin-bottom: var(--s-4); }

/* I riquadri dei numeri e gli elenchi: erano stili in riga dentro il JS,
   ripetuti in quattro punti e impossibili da ritoccare in un colpo solo. */
.stfacts { padding: 0 var(--s-4); margin-top: var(--s-3); margin-bottom: var(--s-4); }
.stlist  { padding: 0 var(--s-4); }

/* "Stai visualizzando il carrello di [foto] Nome" in cima al foglio del
   carrello condiviso. Chi apre il link arriva da un messaggio: il mittente
   deve vedersi prima della lista, con la stessa faccia che ha nel profilo. */
.shcart-who {
  display: flex; align-items: center; gap: var(--s-3);
  margin: 0 var(--s-4) var(--s-4);
  padding: var(--s-3); border-radius: var(--r-lg);
  background: var(--green-50); border: 1px solid var(--green-100);
}
.shcart-av {
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: 50%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--green-600); color: #fff;
  font-weight: var(--fw-bold); font-size: var(--fs-14);
}
.shcart-av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shcart-tx { font-size: var(--fs-13); color: var(--fg-2); line-height: 1.35; }
.shcart-tx b { color: var(--fg-1); font-weight: var(--fw-bold); }
[data-theme="dark"] .shcart-who {
  background: color-mix(in srgb, var(--green-600) 14%, transparent);
  border-color: color-mix(in srgb, var(--green-600) 28%, transparent);
}
/* Riga dati (etichetta + valore): separatore leggero tra righe invece di
   spazio vuoto — rende le informazioni più facili da scansionare. */
.fact {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 0; border-bottom: 1px solid var(--border-2);
}
.fact:last-child { border-bottom: none; }
.fact-lbl { font-size: var(--fs-13); color: var(--fg-3); font-weight: var(--fw-semibold); }
.fact-val { font-size: var(--fs-15); font-weight: var(--fw-extra); }
/* Il conteggio sopra un elenco ("12 prodotti rilevati", "3 su 47"): dice
   subito se il filtro ha morso, senza contare le righe a occhio. */
.paneinfo {
  margin: 0 0 var(--s-2); font-size: var(--fs-11); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--fg-4);
}
/* Il campo che filtra l'elenco prodotti. Non è la ricerca dell'app: cerca
   DENTRO questo negozio, quindi sta dentro la scheda e non nella barra. */
.stsearch {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-3); margin: var(--s-3) 0 var(--s-3);
  height: 42px; border-radius: var(--r-lg);
  background: var(--bg-2); border: 1px solid var(--border-2);
}
.stsearch svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--fg-4); }
.stsearch input {
  flex: 1; min-width: 0; height: 100%; border: 0; background: none;
  font-size: var(--fs-14); font-weight: var(--fw-semibold); color: var(--fg-1);
}
.stsearch input::placeholder { color: var(--fg-4); font-weight: var(--fw-semibold); }
.stsearch input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.stsearch .mic {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-4); transition: all var(--t-fast);
}
.stsearch .mic svg { width: 16px; height: 16px; }
.stsearch .mic:hover { color: var(--green-600); background: var(--green-50); }
.stsearch .mic.listening { color: var(--conv-bad-dot); background: var(--conv-bad-bg); animation: micPulse 1.2s ease-in-out infinite; }
/* La tessera della famiglia nelle righe di confronto: stessa tinta delle
   righe prodotto, misura ridotta perché qui la riga è più stretta. */
.cmp-ic {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-sm, 6px);
  display: flex; align-items: center; justify-content: center;
  background-color: var(--ic-bg, var(--green-100));
  color: var(--ic-fg, var(--green-700));
  border: 1px solid var(--ic-line, var(--green-100));
}
.cmp-ic svg { width: 17px; height: 17px; }

/* Gli orari. In cima la sola cosa che si vuole sapere davvero — se adesso è
   aperto, e fino a quando — e sotto la settimana per chi sta programmando. */
.sthours { padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4); }
.sthours-now {
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-14); font-weight: var(--fw-extra);
}
.sthours-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.sthours-now.open  { color: var(--conv-good-fg); }
.sthours-now.open  .sthours-dot { background: var(--conv-good-dot); }
.sthours-now.shut  { color: var(--fg-3); }
.sthours-now.shut  .sthours-dot { background: var(--zinc-400); }
.sthours-week { margin-top: var(--s-3); border-top: 1px solid var(--border-2); padding-top: var(--s-2); }
.sthours-row {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s-3);
  padding: 3px 0; font-size: var(--fs-12); color: var(--fg-4); font-weight: var(--fw-semibold);
}
.sthours-row b { font-weight: var(--fw-bold); color: var(--fg-3); font-variant-numeric: tabular-nums; }
/* Oggi in evidenza: in sette righe uguali la propria si perde. */
.sthours-row.today { color: var(--fg-1); }
.sthours-row.today b { color: var(--fg-1); }

/* ── Stati ─────────────────────────────────────────────────────────────── */
.state { padding: var(--s-10) var(--s-6); text-align: center; }
.state-ic {
  width: 56px; height: 56px; margin: 0 auto var(--s-4); border-radius: var(--r-xl);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-3); color: var(--fg-4);
}
.state-ic svg { width: 26px; height: 26px; }
.state h3 { font-size: var(--fs-16); font-weight: var(--fw-extra); margin-bottom: var(--s-2); }
.state p { font-size: var(--fs-14); color: var(--fg-3); line-height: var(--lh-base); max-width: 30ch; margin: 0 auto var(--s-4); }

.skel-wrap { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-4); }
.skel {
  border-radius: var(--r-xl);
  background: linear-gradient(90deg, var(--bg-3) 25%, var(--zinc-200) 37%, var(--bg-3) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease infinite;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

.spinner {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2.5px solid rgba(255,255,255,.35); border-top-color: #fff;
  animation: spin .7s linear infinite;
}
.spinner.dark { border-color: var(--border-1); border-top-color: var(--green-600); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Richiamo al carrello ──────────────────────────────────────────────── */
/* Sale sopra la tab bar dopo un "aggiungi". Non è un toast: contiene UN'azione
   (il confronto) e vive più a lungo, perché serve a portare da qualche parte,
   non solo a confermare. */
.cue {
  position: fixed; left: 50%; z-index: 88;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--s-3));
  /* Percentuale e non `vw`: da telefono valgono lo stesso, ma nell'anteprima
     da computer la fascetta è dentro la cornice — con `vw` si misurava sulla
     finestra intera e usciva dai bordi, col tasto "Confronta" tagliato. */
  width: min(92%, 440px);
  transform: translate(-50%, 24px);
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-2) var(--s-2) var(--s-3);
  border-radius: var(--r-xl);
  background: linear-gradient(140deg, var(--green-700), var(--green-900));
  color: #fff; box-shadow: 0 16px 34px -14px rgba(15, 23, 42, .6);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-base), transform var(--t-base);
}
.cue.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.cue-ic {
  position: relative; flex: 0 0 auto;
  width: 38px; height: 38px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .16);
}
.cue-ic svg { width: 19px; height: 19px; }
.cue-ic i {
  position: absolute; top: -5px; right: -5px;
  min-width: 19px; height: 19px; padding: 0 5px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  background: #fff; color: var(--green-800);
  font-style: normal; font-size: var(--fs-11); font-weight: var(--fw-extra);
}
.cue-tx { flex: 1; min-width: 0; }
.cue-tx b { display: block; font-size: var(--fs-13); font-weight: var(--fw-extra); }
.cue-tx span {
  display: block; font-size: var(--fs-11); opacity: .8;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cue-go {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px;
  height: 38px; padding: 0 var(--s-3); border-radius: var(--r-lg);
  background: #fff; color: var(--green-800);
  font-size: var(--fs-13); font-weight: var(--fw-extra);
}
.cue-go svg { width: 14px; height: 14px; }
.cue-go:active { transform: scale(.96); }

/* ── Toast ─────────────────────────────────────────────────────────────── */
.toast {
  position: fixed; left: 50%; z-index: 90;
  bottom: calc(var(--tabbar-h) + var(--safe-b) + var(--s-4));
  transform: translate(-50%, 20px);
  max-width: min(92%, 420px);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-lg);
  background: var(--zinc-900); color: #fff;
  font-size: var(--fs-13); font-weight: var(--fw-bold); line-height: var(--lh-snug);
  box-shadow: var(--shadow-pop);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-base), transform var(--t-base);
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }
.toast.good { background: var(--green-700); }
.toast.bad  { background: var(--conv-bad-fg); }

/* ── Schermata di accesso ──────────────────────────────────────────────── */
.gate {
  position: fixed; inset: 0; z-index: 80;
  display: flex; flex-direction: column;
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: calc(var(--safe-t) + var(--s-6)) var(--s-5) calc(var(--safe-b) + var(--s-5));
  background:
    radial-gradient(120% 62% at 88% -8%, var(--green-100) 0%, transparent 58%),
    radial-gradient(96% 50% at -12% 4%, #e0f2fe 0%, transparent 52%),
    var(--bg-1);
}
/* Il marchio della schermata d'accesso è lo STESSO blocco della barra in alto,
   solo più grande: chi installa l'app deve vedere due volte la stessa cosa.
   Prima era l'icona di sistema dentro una tessera bianca, e l'icona porta con
   sé il proprio fondo: sul tema scuro si vedeva un rettangolo chiaro attorno
   al carrello. Qui il simbolo è trasparente e la tessera non c'è più. */
.gate-brand { gap: 10px; margin-bottom: var(--s-5); }
.gate-brand img { width: 52px; height: 52px; }
.gate-brand b { font-size: var(--fs-24); }

/* Chiaro/scuro già dalla schermata d'accesso: due sole icone, in alto a destra,
   fuori dal flusso così non spingono giù il titolo e non competono coi tasti
   d'accesso. Il tasto attivo si distingue per contrasto, non per colore pieno. */
.gate-theme {
  position: absolute; z-index: 2;
  top: calc(var(--safe-t) + var(--s-4)); right: var(--s-5);
  display: inline-flex; align-items: center; gap: 2px; padding: 3px;
  border-radius: var(--r-pill);
  background: var(--bg-1); border: 1px solid var(--border-1);
  box-shadow: var(--shadow-xs);
}
.gate-theme button {
  width: 30px; height: 30px; border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-4); transition: background var(--t-fast), color var(--t-fast);
}
.gate-theme button svg { width: 16px; height: 16px; }
.gate-theme button.on { background: var(--green-50); color: var(--green-700); }
.gate-theme button:active { transform: scale(.92); }

.gate h1 {
  font-size: var(--fs-32); line-height: var(--lh-tight); letter-spacing: var(--ls-tight);
  font-weight: var(--fw-extra); margin-bottom: var(--s-3);
}
.gate h1 em { font-style: normal; color: var(--green-600); }
.gate .lead { font-size: var(--fs-15); color: var(--fg-3); line-height: var(--lh-loose); max-width: 34ch; }
.gate-mid { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; gap: var(--s-4); padding: var(--s-6) 0; }
.gate-foot { flex: 0 0 auto; display: flex; flex-direction: column; gap: var(--s-3); }

.feat { display: flex; align-items: flex-start; gap: var(--s-3); }
.feat-ic {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-1); color: var(--green-600);
  border: 1px solid var(--green-100); box-shadow: var(--shadow-xs);
}
.feat-ic svg { width: 19px; height: 19px; }
.feat-t { font-size: var(--fs-14); font-weight: var(--fw-extra); }
.feat-d { font-size: var(--fs-13); color: var(--fg-3); line-height: var(--lh-snug); margin-top: 1px; }

.sep {
  display: flex; align-items: center; gap: var(--s-3);
  font-size: var(--fs-11); font-weight: var(--fw-bold); color: var(--fg-4);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.sep::before, .sep::after { content: ""; flex: 1; height: 1px; background: var(--border-1); }

.alert {
  padding: var(--s-3) var(--s-4); border-radius: var(--r-lg);
  font-size: var(--fs-13); font-weight: var(--fw-semibold); line-height: var(--lh-snug);
}
.alert.bad  { background: var(--conv-bad-bg);  color: var(--conv-bad-fg);  border: 1px solid var(--conv-bad-line); }
.alert.good { background: var(--conv-good-bg); color: var(--conv-good-fg); border: 1px solid var(--conv-good-line); }
.alert.info { background: var(--green-50);     color: var(--green-800);    border: 1px solid var(--green-100); }

.legal { font-size: var(--fs-12); color: var(--fg-4); text-align: center; line-height: var(--lh-base); }
.legal a { color: var(--fg-3); text-decoration: underline; }

/* ── Profilo ───────────────────────────────────────────────────────────── */
.profile-head {
  padding: var(--s-6) var(--s-4) var(--s-5); text-align: center;
  background: linear-gradient(180deg, var(--green-50), var(--bg-2));
  border-bottom: 1px solid var(--border-2);
}
.profile-av {
  width: 76px; height: 76px; margin: 0 auto var(--s-3); border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green-500), var(--green-700));
  color: #fff; font-size: var(--fs-24); font-weight: var(--fw-extra);
  box-shadow: 0 12px 28px -12px rgba(var(--green-500-rgb), .95);
  overflow: hidden;
}
.profile-av img { width: 100%; height: 100%; flex: 0 0 auto; object-fit: cover; object-position: 50% 35%; }
.profile-name { font-size: var(--fs-21); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal); }
.profile-mail { font-size: var(--fs-13); color: var(--fg-3); margin-top: 2px; }

/* ── Rank card ────────────────────────────────────────────────────────────
   Due strati: una FASCIA dipinta col gradiente del grado (il grado si vede
   prima di leggerlo) e sotto, su fondo neutro, i dati misurabili. La versione
   piatta precedente lasciava il grado indistinguibile da una riga di menu. */
.rank-card {
  margin: var(--s-3) var(--s-4) 0;
  background: var(--bg-1);
  border: 1px solid var(--border-2);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.rank-band {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4);
  color: #fff;
}
/* Velo scuro sopra il gradiente del grado. Serve: i gradienti di Apprendista
   (#cbd5e1) e Campione (#fbbf24) sono chiari, e il bianco sopra stava sotto
   2:1 di contrasto — illeggibile. Il velo tiene la tinta del grado e porta il
   testo oltre 4.5:1. */
.rank-band::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(15,23,42,.58), rgba(15,23,42,.34));
  pointer-events: none;
}
/* Alone diagonale: dà profondità alla fascia senza aggiungere un'immagine. */
.rank-band-glow {
  position: absolute; inset: -40% -10% auto auto;
  width: 190px; height: 190px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.28), rgba(255,255,255,0) 70%);
  pointer-events: none;
}
.rank-medal {
  position: relative; flex: 0 0 auto;
  width: 48px; height: 48px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.18);
  border: 1px solid rgba(255,255,255,.35);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45), 0 6px 14px -6px rgba(0,0,0,.45);
}
.rank-identity { position: relative; flex: 1; min-width: 0; }
.rank-eyebrow {
  font-size: var(--fs-10, 10px); font-weight: var(--fw-extra);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
  opacity: .82;
}
.rank-cur-name {
  font-size: var(--fs-20); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); line-height: 1.15;
  text-shadow: 0 1px 2px rgba(0,0,0,.18);
}
.rank-pct {
  position: relative; flex: 0 0 auto; text-align: right; line-height: 1.1;
}
.rank-pct b { display: block; font-size: var(--fs-22); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.rank-pct b i { font-style: normal; font-size: var(--fs-13); opacity: .8; }
.rank-pct span { display: block; font-size: 10px; font-weight: var(--fw-bold); opacity: .85; margin-top: 1px; }
.rank-pct-max b { font-size: var(--fs-16); letter-spacing: var(--ls-wide); }

.rank-progress { padding: var(--s-3) var(--s-4) var(--s-2); }
.rank-bar {
  height: 8px; background: var(--border-2);
  border-radius: 8px; overflow: hidden;
}
.rank-bar-fill { height: 100%; border-radius: 8px; transition: width .5s ease; }
/* TUTTI i requisiti mancanti, non solo il primo: se ne vedi uno solo non sai
   se completandolo sali davvero di grado. */
.rank-needs {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: var(--s-3);
}
.rn-lbl {
  font-size: var(--fs-11); font-weight: var(--fw-extra); color: var(--fg-4);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.rn-chip {
  display: inline-flex; align-items: center;
  padding: 4px 9px; border-radius: var(--r-pill);
  background: var(--bg-2); border: 1px solid var(--border-2);
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--fg-2);
}
.rn-done {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--green-700);
}
.rn-done svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* Tre numeri integrati nella card, separati da divisori sottili */
.rank-stats {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--border-2);
}
.rstat {
  display: flex; flex-direction: column; align-items: center;
  gap: 2px; padding: var(--s-3) var(--s-2); text-align: center;
}
.rstat-mid { border-left: 1px solid var(--border-2); border-right: 1px solid var(--border-2); }
.rstat b {
  font-size: var(--fs-18); font-weight: var(--fw-extra);
  color: var(--fg-1); letter-spacing: var(--ls-tight);
}
.rstat span { font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: var(--ls-wide); }
/* Azione principale del profilo: un bottone vero, largo quanto la schermata,
   staccato dalle righe di menu che lo seguono. */
.profile-cta { padding: var(--s-3) var(--s-4) var(--s-1); }

/* Bottone "eroe": due righe (cosa fai + perché) invece di una scritta piatta,
   così l'azione principale non sembra un bottone di sistema qualsiasi. */
.btn-hero {
  height: auto; min-height: 62px; padding: var(--s-3) var(--s-4);
  justify-content: flex-start; gap: var(--s-3); text-align: left;
  border-radius: var(--r-xl);
  box-shadow: 0 10px 24px -10px rgba(var(--green-500-rgb), .85),
              inset 0 1px 0 rgba(255,255,255,.28);
}
.btn-hero .hero-ic {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.2);
  border: 1px solid rgba(255,255,255,.3);
}
.btn-hero .hero-ic svg { width: 19px; height: 19px; }
.btn-hero .hero-tx { flex: 1; min-width: 0; line-height: 1.25; }
.btn-hero .hero-tx b { display: block; font-size: var(--fs-16); font-weight: var(--fw-extra); }
.btn-hero .hero-tx i {
  display: block; font-style: normal; font-size: var(--fs-12);
  font-weight: var(--fw-semibold); opacity: .88; margin-top: 1px;
}
.btn-hero > svg:last-child { width: 17px; height: 17px; opacity: .75; }

/* Testatina di sezione: separa "contributi", "app" e "account" così l'elenco
   lungo si legge a colpo d'occhio invece di essere un muro di righe uguali. */
.menu-label {
  padding: var(--s-4) var(--s-4) var(--s-2);
  font-size: var(--fs-12); font-weight: var(--fw-extra); color: var(--fg-4);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}

.menu { margin: 0 var(--s-4); background: var(--bg-1); border: 1px solid var(--border-2); border-radius: var(--r-xl); overflow: hidden; box-shadow: var(--shadow-card); }
.menu-item { display: flex; align-items: center; gap: var(--s-3); width: 100%; padding: var(--s-4); border-bottom: 1px solid var(--border-2); text-align: left; transition: background var(--t-fast); }
.menu-item:last-child { border-bottom: none; }
.menu-item:active { background: var(--bg-2); }
.menu-ic { flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; background: var(--green-50); color: var(--green-600); }
.menu-ic svg { width: 18px; height: 18px; }
.menu-txt { flex: 1; min-width: 0; }
.menu-txt b { display: block; font-size: var(--fs-14); font-weight: var(--fw-bold); }
.menu-txt span { font-size: var(--fs-12); color: var(--fg-4); }
.menu-item > svg:last-child { width: 16px; height: 16px; color: var(--fg-5); flex: 0 0 auto; }
.menu-item.danger .menu-ic { background: var(--conv-bad-bg); color: var(--conv-bad-fg); }
/* Voce scelta in un menu che è un elenco di scelte (l'aspetto): la spunta a
   destra prende il posto della freccia — quella prometterebbe un altro
   passaggio che non c'è. */
.menu-item.on { background: var(--primary-tint); }
.menu-item.on .menu-txt b { color: var(--green-700); }
.menu-check { flex: 0 0 auto; display: flex; color: var(--green-600); }
.menu-check svg { width: 18px; height: 18px; }
/* Form modifica profilo / sicurezza (fogli) */
/* Un campo per riga, etichetta sopra e la spiegazione sotto: il foglio si legge
   scorrendo, non saltando fra due colonne. L'altezza 48px è la soglia sotto la
   quale un campo diventa difficile da centrare col pollice. */
.edit-profile-form { padding: var(--s-2) 0 var(--s-4); }
.ef-label {
  display: block; font-size: var(--fs-12); font-weight: var(--fw-extra);
  color: var(--fg-3); text-transform: uppercase; letter-spacing: var(--ls-wide);
  margin: var(--s-5) 0 var(--s-2);
}
.edit-profile-form > .ef-label:first-child { margin-top: 0; }
.ef-input {
  width: 100%; height: 48px; padding: 0 var(--s-4);
  background: var(--bg-2); border: 1.5px solid var(--border-1);
  border-radius: var(--r-lg); font-size: var(--fs-16);
  color: var(--fg-1); transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.ef-input:focus { border-color: var(--green-400); box-shadow: 0 0 0 3px rgba(var(--green-500-rgb), .15); outline: none; }
.ef-hint { margin-top: var(--s-2); font-size: var(--fs-12); color: var(--fg-4); line-height: 1.45; }

/* Foto profilo */
.ef-avarow { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); }
.ef-ava {
  position: relative; flex: 0 0 auto; width: 68px; height: 68px;
  border-radius: 9999px; border: 0; padding: 0; overflow: visible;
  background: var(--green-600); color: #fff;
  font-size: var(--fs-24); font-weight: var(--fw-extra); line-height: 1;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px -10px rgba(var(--green-500-rgb), 1);
  transition: transform var(--t-fast);
}
.ef-ava:active { transform: scale(.96); }
.ef-ava img { width: 100%; height: 100%; border-radius: 9999px; object-fit: cover; display: block; }
.ef-ava-edit {
  position: absolute; right: -2px; bottom: -2px;
  width: 26px; height: 26px; border-radius: 9999px;
  background: var(--bg-1); color: var(--fg-2);
  border: 1.5px solid var(--border-1);
  display: flex; align-items: center; justify-content: center;
}
.ef-ava-edit svg { width: 13px; height: 13px; }
.ef-avatx { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ef-avatx b { font-size: var(--fs-15); font-weight: var(--fw-bold); color: var(--fg-1); }
.ef-avatx span { font-size: var(--fs-13); color: var(--fg-4); line-height: 1.4; }

/* Campo col prefisso @ — la chiocciola è decorazione, non testo da digitare */
.ef-at { position: relative; }
.ef-at > span {
  position: absolute; left: var(--s-4); top: 50%; transform: translateY(-50%);
  font-size: var(--fs-16); font-weight: var(--fw-semibold); color: var(--fg-4);
  pointer-events: none;
}
.ef-at .ef-input { padding-left: 30px; }

/* Interruttore (nome pubblico, 2FA) */
.ef-switch {
  display: flex; align-items: center; gap: var(--s-3);
  margin-top: var(--s-5); padding: var(--s-3) var(--s-4);
  background: var(--bg-2); border: 1.5px solid var(--border-1);
  border-radius: var(--r-lg);
}
.edit-profile-form > .ef-switch:first-child { margin-top: 0; }
.ef-switch-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ef-switch-tx b { font-size: var(--fs-15); font-weight: var(--fw-bold); color: var(--fg-1); }
.ef-switch-tx span { font-size: var(--fs-13); color: var(--fg-4); line-height: 1.4; }
.ef-toggle { flex: 0 0 auto; position: relative; width: 50px; height: 30px; }
.ef-toggle input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.ef-toggle > span {
  position: absolute; inset: 0; border-radius: 9999px;
  background: var(--zinc-300); transition: background var(--t-fast);
  pointer-events: none;
}
.ef-toggle > span::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: 9999px; background: #fff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .3);
  transition: transform var(--t-fast);
}
.ef-toggle input:checked + span { background: var(--green-600); }
.ef-toggle input:checked + span::after { transform: translateX(20px); }
.ef-toggle input:focus-visible + span { box-shadow: 0 0 0 3px rgba(var(--green-500-rgb), .25); }
.ef-toggle input:disabled + span { opacity: .55; }

/* Valore che si legge ma non si tocca (email attuale) */
.ef-static {
  min-height: 48px; padding: 13px var(--s-4);
  background: var(--bg-3); border: 1.5px dashed var(--border-1);
  border-radius: var(--r-lg); font-size: var(--fs-15);
  color: var(--fg-2); word-break: break-word;
}
/* Bottone secondario dentro al form: azione del blocco, non del foglio. Il
   btn-ghost nudo, in mezzo ai campi, si legge come una scritta e non come una
   cosa da toccare: il bordo è quello che lo rimette fra i bottoni. */
.ef-act {
  width: 100%; margin-top: var(--s-3);
  border: 1.5px solid var(--green-600); color: var(--green-700);
  background: var(--primary-tint);
}
.ef-act:active { background: rgba(var(--green-500-rgb), .16); }
[data-theme="dark"] .ef-act { color: var(--green-300, #86efac); }

/* ── Grafico dell'andamento (scheda negozio) ───────────────────────────── */
/* Il prezzo di oggi in grande, la variazione a destra, la linea sotto e i due
   estremi in fondo. Serve a rispondere a una domanda sola — "questa catena sta
   rincarando?" — quindi il numero viene prima del disegno: chi guarda un
   grafico su uno schermo da telefono legge la cifra, non l'inclinazione. */
.chart {
  padding: var(--s-3) var(--s-4) var(--s-2);
  border-radius: var(--r-xl);
  background: var(--bg-1); border: 1px solid var(--border-2);
  box-shadow: var(--shadow-card);
}
.chart-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }
.chart-now b { display: block; font-size: var(--fs-24); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.chart-now span { display: block; font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-bold); }
.chart-delta {
  flex: 0 0 auto; text-align: right;
  padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--bg-3); color: var(--fg-3);
  font-size: var(--fs-14); font-weight: var(--fw-extra);
}
/* Su un prezzo il verso conta: salire è male, scendere è bene. Il verde e il
   rosso qui dicono questo, non "buono/cattivo" in astratto. */
.chart-delta.up   { background: var(--conv-bad-bg);  color: var(--conv-bad-fg); }
.chart-delta.down { background: var(--conv-good-bg); color: var(--conv-good-fg); }
.chart-delta em { display: block; font-style: normal; font-size: 9px; font-weight: var(--fw-bold); opacity: .75; }
.chart-svg { width: 100%; height: 96px; margin-top: var(--s-2); overflow: visible; }
.ch-grid { stroke: var(--border-2); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ch-line { fill: none; stroke-width: 2.4; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.ch-area { stroke: none; opacity: .14; }
.ch-dot { stroke: var(--bg-1); stroke-width: 1.6; }
.chart.good .ch-line, .chart.good .ch-dot { stroke: var(--green-600); }
.chart.good .ch-area, .chart.good .ch-dot { fill: var(--green-500); }
.chart.mid .ch-line, .chart.mid .ch-dot { stroke: var(--conv-mid-dot); }
.chart.mid .ch-area, .chart.mid .ch-dot { fill: var(--conv-mid-dot); }
.chart.bad .ch-line, .chart.bad .ch-dot { stroke: var(--conv-bad-dot); }
.chart.bad .ch-area, .chart.bad .ch-dot { fill: var(--conv-bad-dot); }
.chart.na .ch-line, .chart.na .ch-dot { stroke: var(--zinc-400, #a1a1aa); }
.chart.na .ch-area, .chart.na .ch-dot { fill: var(--zinc-400, #a1a1aa); }
.ch-dot.last { stroke-width: 2; }
.chart-foot {
  display: flex; justify-content: space-between;
  margin-top: 2px; font-size: var(--fs-10); font-weight: var(--fw-bold); color: var(--fg-5);
}

/* ── Carrello ──────────────────────────────────────────────────────────── */
/* Testata bianca con accento verde: sfondo chiaro rende i numeri leggibili
   a colpo d'occhio senza bisogno di adattarsi al contrasto bianco/verde. */
.carthead {
  display: flex; flex-direction: column; gap: var(--s-3);
  margin: var(--s-3) var(--s-4) 0; padding: var(--s-4);
  border-radius: var(--r-xl);
  background: var(--bg-1);
  border: 1px solid var(--border-2);
  border-top: 3px solid var(--green-500);
  box-shadow: var(--shadow-card);
}
.carthead-row { display: flex; align-items: center; gap: var(--s-3); }
.carthead-ic {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-50); border: 1px solid var(--green-200);
  color: var(--green-600);
}
.carthead-ic svg { width: 22px; height: 22px; }
.carthead-tx { flex: 1; min-width: 0; }
.carthead-tx b { display: block; font-size: var(--fs-18); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); color: var(--fg-1); }
.carthead-tx span { display: block; font-size: var(--fs-12); color: var(--fg-3);
  line-height: var(--lh-snug); margin-top: 1px; }
/* I tre numeri su sfondo leggermente diverso: si leggono come dati, non come testo. */
.carthead-stats {
  display: flex; align-items: stretch;
  border-radius: var(--r-lg);
  background: var(--bg-2); border: 1px solid var(--border-2);
}
.cstat {
  flex: 1; min-width: 0; padding: 10px 4px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  border-left: 1px solid var(--border-2);
}
.cstat:first-child { border-left: 0; }
.cstat b { font-size: var(--fs-20); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); line-height: 1.1; color: var(--green-700); }
.cstat span { font-size: var(--fs-10); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: .04em; color: var(--fg-4); }
/* Condividi = verde pieno, Svuota = outline sottile. */
.carthead-acts { display: flex; gap: var(--s-2); }
.carthead-b {
  flex: 1; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  height: 38px; padding: 0 var(--s-2); border-radius: var(--r-lg);
  font-size: var(--fs-13); font-weight: var(--fw-extra);
  transition: transform var(--t-fast), opacity var(--t-fast);
}
.carthead-b svg { width: 16px; height: 16px; flex: 0 0 auto; }
.carthead-b:active { transform: scale(.97); opacity: .85; }
.carthead-share { background: var(--green-600); color: #fff; border: none; }
.carthead-clear { background: transparent; color: var(--fg-3);
  border: 1.5px solid var(--border-1); }
/* ── Lo scontrino ──────────────────────────────────────────────────────────
   Dieci tessere bianche staccate una dall'altra sembravano un modulo da
   compilare. Qui l'elenco è UN oggetto solo: una striscia di carta, dentellata
   sopra e sotto come uno scontrino strappato. È la forma che il contenuto ha
   già — e rende evidente dove finisce la spesa e dove comincia il verdetto.

   Le dentellature sono due gradienti conici ripetuti: nessuna immagine, e la
   frequenza è in `px` così i dentini restano uguali su qualunque larghezza. */
.receipt {
  position: relative;
  margin: 7px var(--s-4);
  padding: var(--s-2) 0;
  background: var(--bg-1);
  /* L'ombra come `filter` e non come `box-shadow`: box-shadow segue il
     rettangolo, e sotto una carta dentellata si vedrebbe un'ombra dritta che
     taglia le sporgenze. `drop-shadow` segue la sagoma vera, dentini inclusi. */
  filter: drop-shadow(0 2px 8px rgba(15, 23, 42, .10));
}
/* I dentini sono sporgenze FUORI dalla carta, non morsi dentro: un morso
   dovrebbe lasciar vedere il fondo, e il fondo qui non è una tinta piatta ma
   tre aloni verdi (#sc-root::before) — una tacca dipinta di bianco si
   vedrebbe. Una gobba invece è solo carta in più, e sta bene su qualunque
   sfondo. */
.receipt::before,
.receipt::after {
  content: ""; position: absolute; left: 0; right: 0; height: 7px;
  background-size: 15px 7px;
  background-repeat: repeat-x;
}
.receipt::before {
  top: -7px;
  background-image: radial-gradient(circle at 7.5px 7px, var(--bg-1) 6px, transparent 6.5px);
}
.receipt::after {
  bottom: -7px;
  background-image: radial-gradient(circle at 7.5px 0, var(--bg-1) 6px, transparent 6.5px);
}

/* Intestazione di reparto: è una didascalia, non un titolo — sta sopra le sue
   righe in maiuscoletto spaziato, con l'icona nella tinta della famiglia e il
   conteggio a destra. */
.rgroup + .rgroup { margin-top: var(--s-1); }
.rgroup-head {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 9px var(--s-4) 5px;
}
.rgroup-ic {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: var(--r-xs);
  display: flex; align-items: center; justify-content: center;
  background-color: var(--ic-bg, var(--green-100));
  color: var(--ic-fg, var(--green-700));
}
.rgroup-ic svg { width: 13px; height: 13px; }
.rgroup-name {
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-10); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-wide); text-transform: uppercase;
  color: var(--fg-4);
}
/* Il filo che unisce l'intestazione al conteggio: senza, il numero a destra
   galleggiava a mezz'aria in mezzo al bianco. È un ELEMENTO a sé e non uno
   pseudo dentro `.rgroup-name`: là dentro contava come testo, e il
   troncamento coi puntini mangiava il nome del reparto per far posto al filo
   ("LATTICINI E UOVA…" con lo spazio tutto libero a destra). */
.rgroup-line {
  flex: 1 1 auto; min-width: var(--s-4);
  border-top: 1px dashed var(--border-2);
}
.rgroup-n {
  flex: 0 0 auto;
  font-size: var(--fs-11); font-weight: var(--fw-extra); color: var(--fg-4);
  font-variant-numeric: tabular-nums;
}

/* Le righe: dentro lo scontrino non sono più schede: niente bordo, niente
   ombra, niente angoli — le separa un filo tratteggiato, come le voci di uno
   scontrino vero. Il filo colorato a sinistra prende la tinta della famiglia. */
.cart-prod {
  border: 0; border-radius: 0; box-shadow: none; background: none;
  border-left: 3px solid var(--ic-line, var(--green-200));
  padding: 9px var(--s-4) 9px 13px;
}
.cart-prod + .cart-prod,
.rgroup .cart-prod + .cart-prod { border-top: 1px dashed var(--border-2); }
.cart-prod .prod-ic { width: 38px; height: 38px; }
.cart-prod .prod-ic svg { width: 19px; height: 19px; }
.cart-prod .prod-name { font-size: var(--fs-15); }
/* I tre comandi della quantità diventano un blocco solo: si legge "meno,
   tre, più" come un oggetto, e il numero non balla più quando passa da 9 a 10. */
.cart-prod .qty {
  gap: 0; padding: 3px; border-radius: var(--r-lg);
  background: var(--bg-2); border: 1px solid var(--border-2);
}
.cart-prod .qty button { width: 30px; height: 30px; background: none; border: none; }
.cart-prod .qty button:active { background: var(--bg-3); }
.cart-prod .qty b { min-width: 24px; font-size: var(--fs-14); }

.cartbar {
  position: sticky; bottom: 0; z-index: 10;
  margin-top: var(--s-4); padding: var(--s-3) var(--s-4) var(--s-4);
  background: linear-gradient(180deg, rgba(255,255,255,0), var(--bg-1) 32%);
}
/* Il risultato del confronto: la risposta per cui esiste tutta la schermata.
   Era una lastra VERDE PIENA con tutto scritto sopra in bianco — nome, totale,
   risparmio, copertura, indirizzo: cinque informazioni diverse tutte dello
   stesso colore e quasi dello stesso peso, quindi nessuna gerarchia e niente
   che si leggesse per primo. Il verde pieno per giunta consumava l'unico
   colore con cui l'app dice "qui risparmi": usato come sfondo, non poteva più
   dirlo dentro la scheda.
   Ora è una scheda BIANCA come le altre, e il verde torna INCHIOSTRO: il
   totale, il riquadro del risparmio, il bollo della copertura. Il rilievo lo
   danno le fasce (intestazione tenue, corpo bianco, riquadro verde) e i corpi
   del testo, non una campitura. */
.winner {
  position: relative; overflow: hidden; border-radius: var(--r-xl);
  background: var(--bg-1); border: 1px solid var(--border-1);
  box-shadow: 0 12px 28px -18px rgba(0, 0, 0, .28);
}
/* Il filo verde in alto: dice "questo è il vincitore" senza rubare l'intera
   superficie. */
.winner::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: linear-gradient(90deg, var(--green-500), var(--green-700));
}
.winner-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  padding: var(--s-3) var(--s-4) 0;
}
.winner-lab {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-11); font-weight: var(--fw-extra); text-transform: uppercase;
  letter-spacing: var(--ls-wide); color: var(--green-700);
}
.winner-lab svg { width: 13px; height: 13px; }
/* Quanti prodotti hanno un prezzo VERO in quella catena. È il primo dato da
   leggere dopo il nome: un totale su 5 prodotti e uno su 8 non sono lo stesso
   numero, e prima non si diceva da nessuna parte. */
.winner-cov {
  display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--bg-2); border: 1px solid var(--border-2);
  font-size: var(--fs-11); font-weight: var(--fw-extra); color: var(--fg-3);
  white-space: nowrap;
}
.winner-cov svg { width: 12px; height: 12px; }
.winner-cov.is-full {
  background: var(--conv-good-bg); border-color: var(--conv-good-line); color: var(--green-700);
}
.winner-main {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
}
.winner-logo { width: 52px; height: 40px; }
.winner-id { flex: 1; min-width: 0; }
.winner-name {
  font-size: var(--fs-18); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.winner-price { flex: 0 0 auto; text-align: right; }
.winner-tot {
  font-size: var(--fs-24); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); line-height: 1; color: var(--green-700);
}
.winner-sub { margin-top: 3px; font-size: var(--fs-11); font-weight: var(--fw-semibold); color: var(--fg-4); }
/* Il risparmio: l'unico riquadro pieno della scheda, perché è l'unica riga che
   l'utente è venuto a cercare. La riga piccola sotto dichiara su quanti
   prodotti è calcolato — senza, è un numero che non si può verificare. */
.winner-save {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 var(--s-4) var(--s-3); padding: 9px 12px; border-radius: var(--r-md);
  background: var(--conv-good-bg); border: 1px solid var(--conv-good-line);
  font-size: var(--fs-13); font-weight: var(--fw-semibold); color: var(--green-800);
  line-height: var(--lh-snug);
}
.winner-save svg { width: 15px; height: 15px; flex: 0 0 auto; margin-top: 1px; }
.winner-save b { font-weight: var(--fw-extra); }
.winner-save em { display: block; margin-top: 2px; font-style: normal; font-size: var(--fs-11); opacity: .78; }
/* Quello che in quella catena NON c'è. Grigio e in fondo: è un limite del
   confronto, non un allarme — ma va scritto, o il totale sembra riferito a
   tutto il carrello. */
.winner-note {
  display: flex; align-items: flex-start; gap: 7px;
  padding: var(--s-3) var(--s-4); border-top: 1px dashed var(--border-2);
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-4);
  line-height: var(--lh-snug);
}
.winner-note svg { width: 14px; height: 14px; flex: 0 0 auto; margin-top: 1px; }
/* L'indirizzo del punto vendita più vicino di quella catena: "costa meno da
   Eurospin" senza un dove costringe a rifare la ricerca da capo altrove. */
.winner-where {
  display: flex; align-items: flex-start; gap: 4px; margin-top: 3px;
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-3);
  line-height: var(--lh-snug);
}
.winner-where svg { width: 13px; height: 13px; flex: 0 0 auto; margin-top: 1px; }

/* ── I due numeri: misurato e stimato ─────────────────────────────────────
   Nessuna catena ha mai tutto il carrello, quindi il totale grande contiene
   anche una stima. Qui sotto la stima si SEPARA dal misurato: due righe, due
   cifre, due etichette. Fonderle in un numero solo sarebbe il modo più veloce
   per far sembrare rilevato quello che non lo è. La riga della stima è un
   TASTO, perché da lì si arriva a cosa quel supermercato ha davvero al posto
   del prodotto che manca. */
.brk { margin: 0 var(--s-4) var(--s-3); border-radius: var(--r-md); background: var(--bg-2); border: 1px solid var(--border-2); }
.brk-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; text-align: left;
  border-bottom: 1px solid var(--border-2); background: none;
}
.brk-row:last-child { border-bottom: none; }
.brk-v {
  flex: 0 0 auto; min-width: 68px;
  font-size: var(--fs-14); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight);
}
.brk-l { flex: 1; min-width: 0; font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-4); line-height: var(--lh-snug); }
.brk-tap .brk-v, .brk-tap .brk-l { color: var(--green-700); }
.brk-tap svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--green-600); }
.brk-tap:active { background: var(--conv-good-bg); }
/* Quando la stima non poggia sul carrello ma sul listino della catena, il
   totale vale meno e deve dirlo dentro il riquadro, non in una nota lontana. */
.brk-basis {
  display: flex; align-items: flex-start; gap: 7px;
  padding: 9px 12px; border-top: 1px solid var(--border-2);
  font-size: var(--fs-11); font-weight: var(--fw-semibold); color: var(--fg-4);
  line-height: var(--lh-snug);
}
.brk-basis svg { width: 13px; height: 13px; flex: 0 0 auto; margin-top: 1px; }
/* Nessuna stima: è il caso migliore e va detto — la differenza fra un totale
   che si può portare in cassa e uno che è una previsione. */
.winner-ok {
  display: flex; align-items: center; gap: 7px;
  margin: 0 var(--s-4) var(--s-3); padding: 8px 12px; border-radius: var(--r-md);
  background: var(--conv-good-bg); border: 1px solid var(--conv-good-line);
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--green-800);
}
.winner-ok svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* ── Pannello dei prodotti stimati ────────────────────────────────────────
   Prima il METODO in una riga (da dove esce il numero), poi prodotto per
   prodotto l'alternativa vera a scaffale. Toccarla la mette nel carrello e
   quella riga smette di essere una stima: è l'unico modo che l'utente ha di
   migliorare il confronto da solo. */
.gapx-how {
  display: flex; align-items: flex-start; gap: 7px;
  margin-bottom: var(--s-3); padding: 9px 12px; border-radius: var(--r-md);
  background: var(--bg-2); border: 1px solid var(--border-2);
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-3);
  line-height: var(--lh-snug);
}
.gapx-how svg { width: 14px; height: 14px; flex: 0 0 auto; margin-top: 1px; }
.gapx { padding: var(--s-3) 0; border-bottom: 1px solid var(--border-2); }
.gapx:last-child { border-bottom: none; }
/* L'intestazione è un tasto: apre la scheda del prodotto (marca, formato, dove
   costa meno, andamento). `align-items: flex-start` e non `baseline` perché
   sotto al nome adesso c'è la riga della marca. */
.gapx-head { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.gapx-head:active { opacity: .7; }
.gapx-tx { flex: 1; min-width: 0; }
.gapx-nm { font-size: var(--fs-14); font-weight: var(--fw-bold); }
.gapx-meta {
  display: flex; align-items: center; gap: 2px; margin-top: 2px;
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-4);
}
.gapx-meta svg { width: 13px; height: 13px; flex: 0 0 auto; }
.gapx-q { margin-left: 5px; font-size: var(--fs-12); color: var(--fg-4); }
.gapx-est { flex: 0 0 auto; font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-3); letter-spacing: var(--ls-tight); }
.gapx-lab { margin: 8px 0 5px; font-size: var(--fs-11); font-weight: var(--fw-extra); text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--fg-4); }
.gapx-alt {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin-bottom: 6px; padding: 9px 11px; border-radius: var(--r-md);
  background: var(--bg-1); border: 1px solid var(--border-1); text-align: left;
  cursor: pointer;
}
.gapx-alt:last-child { margin-bottom: 0; }
.gapx-alt:active { background: var(--conv-good-bg); border-color: var(--conv-good-line); }
.gapx-alt-tx { flex: 1; min-width: 0; }
.gapx-alt-nm { display: block; font-size: var(--fs-13); font-weight: var(--fw-semibold); line-height: var(--lh-snug); }
.gapx-alt-meta { display: block; margin-top: 1px; font-size: var(--fs-11); font-weight: var(--fw-semibold); color: var(--fg-4); }
.gapx-alt-pr { flex: 0 0 auto; font-size: var(--fs-14); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
/* Adesso è un <button> vero dentro la riga (la riga apre la scheda, il tasto
   sostituisce): senza `border:none` prenderebbe il bordo di default del
   browser, e senza altezza minima resterebbe sotto il bersaglio da pollice. */
.gapx-alt-go {
  flex: 0 0 auto; min-height: 30px; padding: 4px 10px; border-radius: var(--r-pill);
  background: var(--conv-good-bg); color: var(--green-700); border: none; cursor: pointer;
  font-size: var(--fs-11); font-weight: var(--fw-extra); white-space: nowrap;
}
.gapx-alt-go:active { background: var(--green-500); color: #fff; }
.gapx-none { margin-top: 6px; font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-4); }
[data-theme="dark"] .brk-tap .brk-v,
[data-theme="dark"] .brk-tap .brk-l,
[data-theme="dark"] .gapx-alt-go { color: var(--green-400); }
[data-theme="dark"] .winner-ok { color: var(--green-300); }

/* Di notte il verde-inchiostro va ALZATO: green-700/800 sono pensati per stare
   sul bianco e sul fondo scuro si spengono fino a sembrare grigi. */
[data-theme="dark"] .winner { background: var(--bg-2); border-color: var(--border-1); }
[data-theme="dark"] .winner-lab,
[data-theme="dark"] .winner-tot,
[data-theme="dark"] .winner-cov.is-full { color: var(--green-400); }
[data-theme="dark"] .winner-save { color: var(--green-300); }

/* ══════════════════════════════════════════════════════════════════════════
   OFFERTE E PREZZI — stesso linguaggio del sito
   Rosso = offerta (è un richiamo, non un giudizio), verde = risparmio,
   barrato grigio = prezzo da listino. Le tre cose insieme dicono in un colpo
   d'occhio "costa meno di prima, e di quanto".
   ═════════════════════════════════════════════════════════════════════════ */
.tag-offer {
  display: inline-flex; align-items: center;
  height: 18px; padding: 0 7px; border-radius: var(--r-sm, 6px);
  background: var(--conv-bad-bg); color: #dc2626;
  border: 1px solid var(--conv-bad-line);
  font-size: var(--fs-10); font-weight: var(--fw-extra);
  letter-spacing: .04em; white-space: nowrap;
}
.tag-save {
  display: inline-block; margin-top: 2px;
  padding: 1px 7px; border-radius: var(--r-pill);
  background: var(--green-600); color: #fff;
  font-size: var(--fs-10); font-weight: var(--fw-extra); white-space: nowrap;
}
.tag-best {
  display: inline-flex; align-items: center;
  height: 18px; padding: 0 8px; border-radius: var(--r-pill);
  background: var(--green-500); color: #fff;
  font-size: var(--fs-10); font-weight: var(--fw-extra); white-space: nowrap;
}
/* "≈ equivalente" e "Più caro": due distintivi neutri, non due allarmi. Il
   primo dice che l'articolo è simile e non identico (l'`≈` stava nella colonna
   dei numeri e mangiava la posizione in classifica); il secondo chiude la
   classifica dall'altro capo — senza, si legge solo dove conviene e mai quanto
   si perde a sbagliare negozio. Il rosso resta all'OFFERTA e al sopra-media:
   essere l'ultimo di un elenco non è un errore. */
.tag-alt {
  display: inline-flex; align-items: center;
  height: 18px; padding: 0 8px; border-radius: var(--r-pill);
  background: var(--bg-2); color: var(--fg-3); border: 1px solid var(--border-2);
  font-size: var(--fs-10); font-weight: var(--fw-extra); white-space: nowrap;
}
.tag-worst {
  display: inline-flex; align-items: center;
  height: 18px; padding: 0 8px; border-radius: var(--r-pill);
  background: var(--bg-2); color: var(--fg-4); border: 1px solid var(--border-2);
  font-size: var(--fs-10); font-weight: var(--fw-extra); white-space: nowrap;
}
.cmp.worst .cmp-rank { color: var(--fg-4); }
.was {
  display: block; margin-top: 1px;
  font-size: var(--fs-11); font-weight: var(--fw-medium);
  color: var(--fg-4); text-decoration: line-through;
}
.price-vs {
  display: inline-block; margin-top: 3px;
  padding: 1px 7px; border-radius: var(--r-pill);
  font-size: var(--fs-10); font-weight: var(--fw-extra); white-space: nowrap;
}
.price-vs.under { background: var(--conv-good-bg); color: var(--green-700); }
.price-vs.over  { background: var(--conv-bad-bg);  color: #b91c1c; }
.on-offer { color: #dc2626; }

/* Riga prodotto in offerta: filo rosso a sinistra, non l'intera scheda
   colorata (in un elenco tutto rosso non si legge più niente). */
.prod.offer { border-color: var(--conv-bad-line); }
.prod.offer::before {
  content: ""; position: absolute; left: 0; top: 12%; bottom: 12%;
  width: 3px; border-radius: 0 3px 3px 0; background: #ef4444;
}
.prod { position: relative; }
.prod-meta { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
/* Logo catena nell'offerta: pill compatta con solo il marchio */
.prod-chain-logo {
  display: inline-flex; align-items: center; justify-content: center;
  height: 18px; padding: 0 6px; border-radius: var(--r-sm);
  background: var(--bg-2); border: 1px solid var(--border-1);
  overflow: hidden;
}
.prod-chain-logo img { height: 12px; width: auto; max-width: 52px; object-fit: contain; }
.cmp-body .tag-offer, .cmp-body .tag-best,
.cmp-body .tag-alt, .cmp-body .tag-worst { margin-top: 4px; margin-right: 4px; }
.cmp-price { display: flex; flex-direction: column; align-items: flex-end; }

/* Tre riquadri: più basso / più alto / risparmio */
.factgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2); margin-bottom: var(--s-4); }
.fbox {
  padding: var(--s-3) var(--s-2); border-radius: var(--r-lg); text-align: center;
  background: var(--bg-2); border: 1px solid var(--border-2);
}
.fbox span { display: block; font-size: var(--fs-10); font-weight: var(--fw-bold); color: var(--fg-4); text-transform: uppercase; letter-spacing: var(--ls-wide); }
.fbox b { display: block; margin-top: 3px; font-size: var(--fs-16); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.fbox.good { background: var(--conv-good-bg); border-color: var(--conv-good-line); }
.fbox.good b { color: var(--green-700); }
.fbox.save b { color: var(--green-600); }

/* ══════════════════════════════════════════════════════════════════════════
   PRO — cornice ambra, azione verde (identico a pro-gate.css del sito)
   L'ambra dice "a pagamento", il verde resta l'azione del marchio. Una
   funzione Pro non si nasconde: si mostra sfocata, così si vede che esiste.
   ═════════════════════════════════════════════════════════════════════════ */
.pgate {
  display: block; width: 100%; text-align: left; padding: var(--s-4);
  border: 1.5px solid var(--amber-500); border-radius: var(--r-xl);
  background: linear-gradient(135deg, var(--amber-50), var(--bg-1));
  box-shadow: 0 10px 26px -18px rgba(245, 158, 11, .9);
}
.pgate-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500));
  color: var(--amber-950); font-size: var(--fs-10); font-weight: var(--fw-extra);
  letter-spacing: .06em; margin-bottom: var(--s-2);
}
.pgate-badge svg { width: 11px; height: 11px; }
.pgate-title { font-size: var(--fs-16); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal); }
.pgate-sub { font-size: var(--fs-13); color: var(--fg-3); margin-top: 3px; line-height: var(--lh-snug); }
.pgate-preview {
  margin: var(--s-3) 0; border: 1px solid var(--amber-200);
  border-radius: var(--r-lg); background: var(--bg-1); overflow: hidden;
}
.pgate-blur { filter: blur(4px); opacity: .75; user-select: none; pointer-events: none; }
.pgate-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border-2);
}
.pgate-row:last-child { border-bottom: none; }
.pgate-row .l { display: flex; align-items: center; gap: 8px; color: var(--fg-3); font-size: var(--fs-14); font-weight: var(--fw-semibold); }
.pgate-row .val { color: var(--fg-3); font-size: var(--fs-14); font-weight: var(--fw-semibold); }
.pgate-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  margin-top: var(--s-2); height: 46px; width: 100%; padding: 0 var(--s-5);
  border-radius: var(--r-lg); color: #fff; font-size: var(--fs-14); font-weight: var(--fw-extra);
  background: linear-gradient(135deg, var(--green-500), var(--green-600));
  box-shadow: 0 8px 20px -8px rgba(var(--green-500-rgb), .7);
}
.pgate-cta svg { width: 17px; height: 17px; }
.pgate:active { transform: scale(.99); }

.tag-pro {
  display: inline-flex; align-items: center; gap: 3px; vertical-align: middle;
  padding: 2px 8px; border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500));
  color: var(--amber-950); font-size: var(--fs-10); font-weight: var(--fw-extra);
}
.tag-pro svg { width: 10px; height: 10px; }
.profile-av.pro { box-shadow: 0 0 0 3px var(--amber-400), 0 12px 28px -12px rgba(var(--green-500-rgb), .95); }

.beta {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-lg);
  background: linear-gradient(135deg, var(--amber-50), var(--bg-1));
  border: 1px solid var(--amber-200);
}
.beta-ic {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500)); color: var(--amber-950);
}
.beta-ic svg { width: 17px; height: 17px; }
.beta b { display: block; font-size: var(--fs-14); font-weight: var(--fw-extra); }
.beta span { display: block; font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug); margin-top: 1px; }

.plan {
  padding: var(--s-4); border-radius: var(--r-xl);
  border: 1.5px solid var(--green-200);
  background: linear-gradient(140deg, var(--green-50), var(--bg-1));
}
.plan-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }
.plan-name { font-size: var(--fs-12); font-weight: var(--fw-extra); text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--green-700); }
.plan-price { display: flex; align-items: baseline; gap: 5px; margin-top: 2px; }
.plan-price b { font-size: var(--fs-32); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.plan-price span { font-size: var(--fs-13); color: var(--fg-3); font-weight: var(--fw-semibold); }
.plan-badge {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  padding: 4px 9px; border-radius: var(--r-pill);
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500));
  color: var(--amber-950); font-size: var(--fs-10); font-weight: var(--fw-extra); letter-spacing: .04em;
}
.plan-badge svg { width: 11px; height: 11px; }
.plan-note { font-size: var(--fs-12); color: var(--fg-3); margin-top: var(--s-2); }

.prohead {
  padding: var(--s-5) var(--s-4); border-radius: var(--r-xl); text-align: center;
  background: linear-gradient(140deg, var(--green-600), var(--green-800)); color: #fff;
  box-shadow: 0 14px 34px -16px rgba(var(--green-500-rgb), 1);
}
.prohead-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px; border-radius: var(--r-pill); margin-bottom: var(--s-3);
  background: linear-gradient(135deg, var(--amber-400), var(--amber-500));
  color: var(--amber-950); font-size: var(--fs-10); font-weight: var(--fw-extra); letter-spacing: .06em;
}
.prohead-badge svg { width: 11px; height: 11px; }
.prohead-t { font-size: var(--fs-21); font-weight: var(--fw-extra); letter-spacing: var(--ls-normal); }
.prohead-d { font-size: var(--fs-13); opacity: .85; margin-top: 3px; }
.feat-ic.on { background: var(--green-600); color: #fff; border-color: var(--green-600); }

/* Confronto Gratis / Pro */
.ptable { border: 1px solid var(--border-2); border-radius: var(--r-xl); overflow: hidden; background: var(--bg-1); }
.pt-row { display: grid; grid-template-columns: 1fr 74px 74px; align-items: center; border-bottom: 1px solid var(--border-2); }
.pt-row:last-child { border-bottom: none; }
.pt-row > span { padding: var(--s-3); font-size: var(--fs-13); font-weight: var(--fw-semibold); color: var(--fg-2); }
.pt-row > b { padding: var(--s-3) 4px; text-align: center; font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--fg-3); }
.pt-row > b.pro { background: var(--green-50); color: var(--green-800); }
.pt-row > b.yes { color: var(--green-600); font-size: var(--fs-15); }
.pt-row > b.no  { color: var(--fg-5); }
.pt-head > span, .pt-head > b { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--fg-4); }
.pt-head > b.pro { color: var(--green-700); }

/* Dove sono io. Blu e non verde: il verde qui vuol dire "conveniente", e un
   punto verde che invece è la posizione direbbe una cosa per un'altra. */
.me-dot {
  width: 16px; height: 16px; border-radius: 50%;
  background: #2563eb; border: 3px solid #fff;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .22), 0 2px 8px rgba(0, 0, 0, .3);
}

/* ══════════════════════════════════════════════════════════════════════════
   SEGNALAZIONI — deve costare pochi secondi, o non le fa nessuno
   ═════════════════════════════════════════════════════════════════════════ */

/* I QUATTRO PASSI (2026-08-13). Prima era tutto in una schermata e la prima
   cosa che chiedeva era di SCRIVERE il nome del prodotto: la cosa più lenta e
   più sbagliabile che si possa chiedere a chi è in piedi davanti allo scaffale
   con una mano sola. Ora si tocca: negozio, reparto, prodotto — e si scrive
   solo il prezzo, che è l'unica cosa che nessuno può indovinare.

   La griglia dei reparti. Tre colonne: con due le tessere diventano larghe e
   sembrano righe d'elenco, con quattro l'etichetta va a capo due volte. */
.catgrid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2); margin-top: var(--s-3);
}
.cattile {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: var(--s-3) 6px;
  border-radius: var(--r-lg);
  background: var(--bg-1); border: 1px solid var(--border-2);
  box-shadow: var(--shadow-xs);
  transition: border-color var(--t-fast), transform var(--t-fast);
}
.cattile:active { border-color: var(--green-300); transform: scale(.96); }
/* L'icona è la stessa tessera colorata delle famiglie nel carrello e nella
   ricerca (`.prod-ic[data-cat]`): il reparto scelto qui si riconosce là senza
   dover imparare due alfabeti. Un filo più piccola, che in una griglia da tre
   i 42px del carrello mangiano l'etichetta. */
.cattile .prod-ic { width: 38px; height: 38px; }
.cattile .prod-ic svg { width: 20px; height: 20px; }
.cattile-n {
  font-size: var(--fs-11); font-weight: var(--fw-bold); color: var(--fg-2);
  text-align: center; line-height: 1.2;
}

/* La riga di riepilogo di una scelta già fatta ("Conad · Cambia negozio").
   Serve a due cose insieme: ricordare dove si è arrivati e dare la strada per
   tornare indietro senza usare il tasto del piede — perché la correzione più
   probabile è proprio il negozio (si è entrati in uno diverso dal più vicino). */
.picked {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
  margin-top: var(--s-2); padding: 10px var(--s-3);
  border-radius: var(--r-lg);
  background: var(--green-50); border: 1px solid var(--green-100);
}
.picked:active { background: var(--green-100); }
.picked-tx {
  flex: 1; min-width: 0;
  font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.picked-go {
  flex: 0 0 auto;
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--green-700);
}

/* Le righe dell'elenco prodotti. `text-align: left` non è pignoleria: sono
   <button>, e un bottone centra il testo per conto suo — i nomi finivano in
   mezzo alla riga, che in un elenco da scorrere si legge peggio di tutto. */
.repitem { width: 100%; text-align: left; }
.repitem:active { background: var(--bg-2); }
.repitem .prod-ic { width: 34px; height: 34px; }
.repitem .prod-ic svg { width: 18px; height: 18px; }

/* La corsia veloce in cima al modulo: lo scontrino.
   Ha preso il posto dei due riquadroni del vecchio pannello di mezzo, che
   costringevano a scegliere prima di poter scrivere e portavano due targhette
   colorate ("CONSIGLIATO" verde, "SERVONO A TUTTI" ambra) illeggibili l'una
   accanto all'altra. Qui è una riga sola: si nota perché è la prima cosa della
   scheda, non perché urla. */
.fastlane {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
  padding: var(--s-3);
  background: var(--bg-2); border: 1px solid var(--border-2);
  border-radius: var(--r-lg);
  transition: background var(--t-fast);
}
.fastlane:active { background: var(--bg-3); }
.fastlane-ic {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  color: #fff; background: linear-gradient(135deg, var(--green-500), var(--green-700));
}
.fastlane-ic svg { width: 20px; height: 20px; }
.fastlane-tx { flex: 1; min-width: 0; }
.fastlane-tx b { display: block; font-size: var(--fs-14); font-weight: var(--fw-extra); color: var(--fg-1); }
.fastlane-tx span {
  display: block; margin-top: 1px; font-size: var(--fs-12); color: var(--fg-4);
  font-weight: var(--fw-semibold); line-height: var(--lh-snug);
}
.fastlane-ch { flex: 0 0 auto; display: flex; color: var(--fg-5); }
.fastlane-ch svg { width: 16px; height: 16px; }

/* Suggerimenti dal catalogo sotto il campo prodotto */
.ac { position: relative; }
.ac-menu {
  display: none; position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 20;
  background: var(--bg-1); border: 1px solid var(--border-1);
  border-radius: var(--r-lg); box-shadow: var(--shadow-pop);
  overflow: hidden; max-height: 246px; overflow-y: auto;
}
.ac-menu.on { display: block; }
.ac-row {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border-2);
}
.ac-row:last-child { border-bottom: none; }
.ac-row:active { background: var(--green-50); }
.ac-n { flex: 1; min-width: 0; font-size: var(--fs-14); font-weight: var(--fw-semibold); line-height: var(--lh-snug); }
/* Icona a sinistra di una riga di suggerimento (il segnaposto dei luoghi nella
   ricerca per via). Va vincolata qui: dentro `.ac-n`, che è un blocco di testo
   largo, un SVG senza misura si prende tutta la riga — 200px di spillo nero. */
.ac-ic {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: var(--r-md);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--green-50); color: var(--green-700); border: 1px solid var(--green-100);
}
.ac-ic svg { width: 15px; height: 15px; }
.ac-p { flex: 0 0 auto; font-size: var(--fs-12); font-weight: var(--fw-extra); color: var(--green-700); }

/* Prezzo: il campo più importante della schermata, quindi il più grande. */
.pricefield {
  display: flex; align-items: center; gap: var(--s-2);
  height: 62px; padding: 0 var(--s-4);
  background: var(--bg-1);
  border: 1.5px solid var(--border-1); border-radius: var(--r-lg);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.pricefield:focus-within { border-color: var(--green-400); box-shadow: var(--shadow-focus-green); }
.pricefield span { font-size: var(--fs-24); font-weight: var(--fw-extra); color: var(--fg-4); }
.pricefield input {
  flex: 1; min-width: 0; border: none; outline: none; background: none;
  font-size: 28px; font-weight: var(--fw-extra); letter-spacing: var(--ls-tight);
}
.pricefield input::placeholder { color: var(--fg-5); }

.more-toggle {
  display: inline-flex; align-items: center; gap: 6px; margin-top: var(--s-4);
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--green-700);
}
.more-toggle svg { width: 15px; height: 15px; }
.opt { font-weight: var(--fw-medium); color: var(--fg-5); }

/* Pastiglie negozio con la distanza: la più vicina è già scelta. */
.chiprow-flush { padding: 0; margin: 0 -2px; }
.chip-km { font-style: normal; font-size: var(--fs-11); font-weight: var(--fw-semibold); opacity: .65; }
.chip.on .chip-km { opacity: .85; }

.okrow {
  display: flex; align-items: center; gap: 7px; margin-top: var(--s-2);
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--green-700);
}
.okrow svg { width: 15px; height: 15px; flex: 0 0 auto; }
.okrow.soft { color: var(--fg-3); font-weight: var(--fw-semibold); }
.okrow.soft svg { color: var(--green-500); }

.state-ic.ok   { background: var(--conv-good-bg); color: var(--green-600); }
.state-ic.wait { background: var(--conv-mid-bg);  color: var(--conv-mid-fg); }

/* ── Il foglio della scansione ─────────────────────────────────────────────
   Due strade, entrambe dichiarate: scattare la foto (l'area grande) e caricarne
   una che c'è già (la riga sotto). Prima la seconda esisteva solo nel testo di
   un consiglio — "va bene anche una foto dalla galleria" — mentre il codice
   apriva l'obiettivo e basta.

   Sul "meno piatto": il rilievo lo fanno tre piani reali — la carta inclinata
   con la sua ombra, il bollino che le sta sopra, la riga di carico staccata dal
   fondo — non un'ombra spalmata su un rettangolo. */
.shot {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  width: 100%; padding: var(--s-6) var(--s-5) var(--s-5);
  border: 2px dashed var(--green-300); border-radius: var(--r-2xl);
  background: linear-gradient(160deg, var(--green-50), var(--bg-1));
  transition: transform var(--t-fast);
}
.shot:active { transform: scale(.99); }
/* La carta: la STESSA dell'attesa, ferma e in piccolo. Chi guarda vede cosa gli
   stiamo chiedendo di inquadrare prima ancora di leggere la scritta — e quando
   la lettura parte ritrova la stessa figura, non un disegno diverso. */
.shot-art {
  position: relative; width: 106px; margin-bottom: var(--s-3);
  transform: rotate(-3.5deg);
  filter: drop-shadow(0 8px 16px rgba(15, 23, 42, .16));
}
.scanx-paper.is-mini { border-radius: var(--r-md); padding: 9px 10px 8px; }
.is-mini .scanx-hd   { height: 5px; margin-bottom: 7px; }
.is-mini .scanx-cut  { margin: 5px 0; }
.is-mini .scanx-ln   { padding: 2.5px 0; gap: 6px; }
.is-mini .scanx-ln i,
.is-mini .scanx-ln b { height: 4px; }
.is-mini .scanx-ln b { flex: 0 0 16px; }
.is-mini .scanx-tot i,
.is-mini .scanx-tot b { height: 6px; }
.is-mini .scanx-code { height: 13px; margin-top: 8px; }
/* Il raggio che passa: lo stesso gesto dell'attesa, lento, su una carta ferma. */
.shot-beam {
  position: absolute; left: -7px; right: -7px; height: 10px; border-radius: 2px;
  background: linear-gradient(180deg,
    rgba(var(--green-500-rgb), 0), rgba(var(--green-500-rgb), .55), rgba(var(--green-500-rgb), 0));
  box-shadow: 0 0 14px rgba(var(--green-500-rgb), .55);
  animation: shotBeam 3.4s ease-in-out infinite;
}
@keyframes shotBeam {
  0%, 100% { top: 12%; }
  50%      { top: 74%; }
}
/* Il bollino sale SOPRA la carta: è il piano più vicino, ed è quello che dice
   l'azione. Il bordo del colore del foglio lo stacca da ciò che copre. */
.shot-ic {
  width: 46px; height: 46px; border-radius: var(--r-xl);
  margin: -26px 0 var(--s-3); position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  color: #fff; background: linear-gradient(135deg, var(--green-400), var(--green-600));
  border: 3px solid var(--bg-1);
  box-shadow: 0 10px 22px -10px rgba(var(--green-500-rgb), .9);
}
.shot-ic svg { width: 22px; height: 22px; }
.shot b { font-size: var(--fs-16); font-weight: var(--fw-extra); }
.shot span { font-size: var(--fs-13); color: var(--fg-3); margin-top: 3px; max-width: 30ch; line-height: var(--lh-snug); }

/* La foto che c'è già: una riga cliccabile, non un consiglio scritto. */
.pickrow {
  display: flex; align-items: center; gap: var(--s-3); width: 100%; text-align: left;
  margin-top: var(--s-3); padding: var(--s-3) var(--s-4);
  background: var(--bg-1); border: 1px solid var(--border-2); border-radius: var(--r-xl);
  box-shadow: var(--shadow-card); transition: transform var(--t-fast);
}
.pickrow:active { transform: scale(.99); }
.pickrow-ic {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-50); color: var(--green-600);
}
.pickrow-ic svg { width: 20px; height: 20px; }
.pickrow-tx { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pickrow-tx b { font-size: var(--fs-14); font-weight: var(--fw-extra); }
.pickrow-tx i { font-style: normal; font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug); }
.pickrow-go { flex: 0 0 auto; display: flex; color: var(--fg-4); }
.pickrow-go svg { width: 16px; height: 16px; }

/* I consigli erano tre spunte verdi uguali: tre cose diverse con lo stesso
   peso si leggono come un elenco da saltare. Numerati e con il perché sotto,
   diventano istruzioni. */
.howto {
  margin-top: var(--s-5); padding: var(--s-4);
  background: var(--bg-2); border-radius: var(--r-xl);
}
.howto h4 {
  font-size: var(--fs-11); font-weight: var(--fw-extra); color: var(--fg-3);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: var(--s-3);
}
.howto-s { display: flex; align-items: flex-start; gap: var(--s-3); }
.howto-s + .howto-s { margin-top: var(--s-3); }
.howto-n {
  flex: 0 0 auto; width: 21px; height: 21px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  background: var(--green-600); color: #fff;
}
.howto-t { display: flex; flex-direction: column; gap: 1px; }
.howto-t b { font-size: var(--fs-13); font-weight: var(--fw-bold); }
.howto-t i { font-style: normal; font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug); }

.privnote {
  display: flex; align-items: center; gap: 7px; margin-top: var(--s-3); padding: 0 var(--s-1);
  font-size: var(--fs-12); color: var(--fg-4); line-height: var(--lh-snug);
}
.privnote svg { flex: 0 0 auto; width: 14px; height: 14px; }

.recap {
  padding: var(--s-4); border-radius: var(--r-xl); text-align: center;
  background: linear-gradient(140deg, var(--green-600), var(--green-800)); color: #fff;
  box-shadow: 0 14px 34px -16px rgba(var(--green-500-rgb), 1);
}
.recap-t { font-size: var(--fs-18); font-weight: var(--fw-extra); }
.recap-n { font-size: var(--fs-13); opacity: .85; margin-top: 2px; }

/* ── L'attesa della lettura dello scontrino ────────────────────────────────
   La foto sale al server e per dieci-quaranta secondi non succede niente di
   visibile. Invece di una rotella: una striscia di carta con la fascia che la
   percorre su e giù, e l'elenco dei passi accanto.

   La carta NON ha testo. Prima ci stavano quattro voci e un totale inventati:
   in un'app di prezzi, quattro prezzi scritti si leggono come prezzi, per
   quanto una didascalia dica il contrario. Restano le sole barre — la forma
   dello scontrino la fanno i dentelli, le righe e il codice a barre, che sono
   figure, non dati. È la stessa carta del carrello (`.receipt`): stessi
   dentelli tondi, stessa ombra sulla sagoma. */
.scanx { padding: var(--s-6) var(--s-4) var(--s-4); text-align: center; }
.scanx-doc {
  position: relative; width: 178px; margin: 0 auto calc(var(--s-6) + 7px);
  /* `drop-shadow` e non `box-shadow`: sotto una carta dentellata un'ombra
     rettangolare taglierebbe le gobbe (stessa ragione di `.receipt`). */
  filter: drop-shadow(0 6px 14px rgba(15, 23, 42, .14));
}
/* Le dentellature sopra e sotto: gobbe di carta FUORI dal foglio, quindi
   funzionano su qualunque sfondo (il foglio del modale non è a tinta unita). */
.scanx-doc::before,
.scanx-doc::after {
  content: ''; position: absolute; left: 0; right: 0; height: 7px;
  background-size: 15px 7px; background-repeat: repeat-x;
}
.scanx-doc::before {
  top: -7px;
  background-image: radial-gradient(circle at 7.5px 7px, var(--bg-1) 6px, transparent 6.5px);
}
.scanx-doc::after {
  bottom: -7px;
  background-image: radial-gradient(circle at 7.5px 0, var(--bg-1) 6px, transparent 6.5px);
}
.scanx-paper { background: var(--bg-1); padding: 13px 14px 12px; }
/* L'intestazione (dove sullo scontrino vero c'è il nome del negozio): una
   barra più scura e centrata, larga quanto basta a sembrare una scritta. */
.scanx-hd {
  height: 7px; width: 56%; margin: 0 auto 10px;
  border-radius: 3px; background: var(--fg-4); opacity: .5;
}
.scanx-cut { height: 0; border-top: 1px dashed var(--border-2); margin: 8px 0; }
.scanx-ln { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
/* Le barre prendono il colore del testo spento con l'opacità, non un grigio
   fisso: `--zinc-200` starebbe bene sul bianco e sparirebbe sul tema scuro,
   dove la carta è quasi nera. */
.scanx-ln i, .scanx-ln b { height: 6px; border-radius: 3px; background: var(--fg-4); opacity: .38; }
.scanx-ln i { flex: 1 1 auto; }
.scanx-ln b { flex: 0 0 26px; }
/* Larghezze diverse riga per riga: cinque barre identiche sembrano un grafico,
   non delle voci scritte a lunghezze diverse come su uno scontrino vero. */
/* `nth-child` e non `nth-of-type`: nella carta sono TUTTI div, quindi
   "il secondo del suo tipo" sarebbe la linea tratteggiata, non la seconda
   riga. Le righe stanno dalla terza alla settima posizione. */
.scanx-ln:nth-child(3) i { max-width: 84%; }
.scanx-ln:nth-child(4) i { max-width: 62%; }
.scanx-ln:nth-child(5) i { max-width: 92%; }
.scanx-ln:nth-child(6) i { max-width: 55%; }
.scanx-ln:nth-child(7) i { max-width: 74%; }
.scanx-tot i { max-width: 42%; }
.scanx-tot i, .scanx-tot b { height: 9px; background: var(--fg-4); opacity: .55; }
/* Il codice a barre: barre di spessore irregolare, un gradiente ripetuto e
   nessuna immagine da scaricare. */
.scanx-code {
  height: 22px; margin-top: 12px; opacity: .55;
  background-image: repeating-linear-gradient(90deg,
    var(--fg-3) 0 2px, transparent 2px 4px,
    var(--fg-3) 4px 5px, transparent 5px 8px,
    var(--fg-3) 8px 11px, transparent 11px 13px);
}
/* La fascia. Dentro ci sta una SECONDA copia della carta, in verde: quello che
   passa sotto la lente si accende. Copia e fascia si muovono con la stessa
   animazione al contrario, così la copia resta ferma rispetto alla carta sotto
   e combacia riga per riga.

   I numeri: la fascia è alta il 26% del foglio e scende fino a toccarne il
   fondo, cioè 74% del foglio = 284,6% di sé stessa (74/26). La copia risale
   dello stesso tratto, ma la sua percentuale è sul foglio intero → -74%. */
.scanx-band {
  position: absolute; left: 0; right: 0; top: 0; height: 26%; overflow: hidden;
  animation: scanBand 2.8s ease-in-out infinite;
}
.scanx-lit { position: absolute; top: 0; left: 0; width: 100%; animation: scanLit 2.8s ease-in-out infinite; }
.scanx-paper.is-lit { background: var(--green-50); }
.scanx-paper.is-lit .scanx-hd,
.scanx-paper.is-lit .scanx-tot i,
.scanx-paper.is-lit .scanx-tot b { background: var(--green-700); opacity: .85; }
.scanx-paper.is-lit .scanx-ln i,
.scanx-paper.is-lit .scanx-ln b { background: var(--green-500); }
.scanx-paper.is-lit .scanx-code { background-image: repeating-linear-gradient(90deg,
    var(--green-700) 0 2px, transparent 2px 4px,
    var(--green-700) 4px 5px, transparent 5px 8px,
    var(--green-700) 8px 11px, transparent 11px 13px); opacity: .8; }
.scanx-paper.is-lit .scanx-cut { border-top-color: var(--green-300); }
/* Le due righe nette in cima e in fondo alla fascia: sono loro a leggersi come
   "il raggio sta passando di qui". */
.scanx-band::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-top: 1px solid rgba(var(--green-500-rgb), .75);
  border-bottom: 1px solid rgba(var(--green-500-rgb), .75);
  background: linear-gradient(180deg,
    rgba(var(--green-500-rgb), .16) 0%,
    rgba(var(--green-500-rgb), 0) 45%,
    rgba(var(--green-500-rgb), 0) 55%,
    rgba(var(--green-500-rgb), .16) 100%);
}
@keyframes scanBand {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(284.6%); }
}
@keyframes scanLit {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-74%); }
}
/* ── La stessa lente, ma sulla FOTO VERA (2026-08-25) ──────────────────────
   Identica macchina — lo stesso contenuto stampato due volte, spento sotto e
   acceso dentro la fascia — applicata allo scontrino che ha caricato l'utente.
   Serve a una cosa precisa: far vedere che stiamo leggendo QUELLA foto, non
   riprodurre un'animazione che andrebbe bene per chiunque.

   Perché le misure sono fisse. Uno scontrino fotografato può essere altissimo o
   quasi quadrato: senza un riquadro di misura nota l'attesa cambierebbe altezza
   a ogni foto e spingerebbe i passi fuori schermo. Le due copie hanno la stessa
   misura e lo stesso `object-fit`, quindi il ritaglio è identico — che è la
   condizione perché la lente non mostri un contenuto sfalsato rispetto al
   fondo. L'altezza sta in una variabile perché il riquadro e le due immagini
   DEVONO essere lo stesso numero: le percentuali di `scanBand`/`scanLit` sono
   calcolate su di essa. */
.scanx-doc.is-photo {
  --shot-h: 236px;
  width: 190px; height: var(--shot-h);
  border-radius: var(--r-lg); overflow: hidden;
  background: var(--bg-3);
  box-shadow: inset 0 0 0 1px var(--border-1);
}
/* Niente dentellature su una fotografia: le gobbe di carta hanno senso attorno
   a un foglio disegnato, attorno a una foto sono una cornice che finge. */
.scanx-doc.is-photo::before,
.scanx-doc.is-photo::after { display: none; }
.scanx-shot { display: block; width: 100%; height: var(--shot-h); object-fit: cover; }
/* La copia di sotto è spenta e slavata. Senza, le due copie sarebbero identiche
   e la fascia non si vedrebbe passare: due volte la stessa foto sono una foto. */
.scanx-doc.is-photo > .scanx-shot {
  filter: grayscale(1) brightness(1.06) contrast(.78);
  opacity: .66;
}
/* Dentro la fascia la foto è PIÙ LEGGIBILE, non più colorata: colori pieni,
   contrasto un filo alzato e un velo verde leggero. È il verso giusto del
   racconto — sotto la lente si legge, fuori no — e tiene visibile lo scontrino
   invece di coprirlo con una campitura verde. */
.scanx-doc.is-photo .scanx-lit .scanx-shot { filter: saturate(1.06) contrast(1.08); }
/* Velo con l'alfa e non `mix-blend-mode`: il blend prenderebbe anche la copia
   grigia sotto, e su qualche WebView Android il risultato cambia di colpo. */
.scanx-doc.is-photo .scanx-lit::after {
  content: ''; position: absolute; inset: 0;
  background: rgba(var(--green-500-rgb), .13);
}

.scanx-steps { display: flex; flex-direction: column; gap: var(--s-2); text-align: left; max-width: 260px; margin: 0 auto; }
.scanx-step {
  display: flex; align-items: center; gap: var(--s-3);
  font-size: var(--fs-13); color: var(--fg-4);
  transition: color var(--t-base);
}
.scanx-dot {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--border-1); background: var(--bg-2);
  transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}
.scanx-dot svg { width: 13px; height: 13px; stroke-width: 3; }
.scanx-step.is-done { color: var(--fg-2); }
.scanx-step.is-done .scanx-dot { background: var(--green-600); border-color: var(--green-600); color: #fff; }
.scanx-step.is-now { color: var(--fg-1); font-weight: var(--fw-semibold); }
/* Il passo in corso pulsa: è l'unico modo per distinguerlo da quelli ancora da
   fare senza spuntarlo, cosa che sarebbe una bugia finché non è finito. */
.scanx-step.is-now .scanx-dot {
  border-color: var(--green-500); background: var(--green-50);
  animation: scanPulse 1.1s ease-in-out infinite;
}
@keyframes scanPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--green-500-rgb), .45); }
  60%      { box-shadow: 0 0 0 7px rgba(var(--green-500-rgb), 0); }
}
.scanx-note {
  margin-top: var(--s-4); font-size: var(--fs-11); color: var(--fg-4);
  line-height: var(--lh-snug);
}
/* Chi ha chiesto meno movimento tiene la fascia ferma a metà foglio: i passi
   continuano ad avanzare, quindi l'informazione non si perde. Fascia e copia
   verde vanno fermate INSIEME e alla stessa quota (37% del foglio), altrimenti
   la lente resta ferma su un contenuto sfalsato. */
@media (prefers-reduced-motion: reduce) {
  .scanx-band { animation: none; transform: translateY(142%); }
  .scanx-lit  { animation: none; transform: translateY(-37%); }
  .scanx-step.is-now .scanx-dot { animation: none; }
  /* Fermo a metà carta: il raggio resta leggibile come figura, non si muove. */
  .shot-beam  { animation: none; top: 43%; }
}
[data-theme="dark"] .scanx-step.is-now .scanx-dot { background: rgba(var(--green-500-rgb), .18); }
/* Sul tema scuro la carta accesa non può restare `--green-50` (bianco sporco):
   il verde chiaro su schermo nero abbaglia e il contorno del foglio sparisce. */
[data-theme="dark"] .scanx-paper.is-lit { background: rgba(var(--green-500-rgb), .14); }
[data-theme="dark"] .scanx-paper.is-lit .scanx-hd,
[data-theme="dark"] .scanx-paper.is-lit .scanx-tot i,
[data-theme="dark"] .scanx-paper.is-lit .scanx-tot b { background: var(--green-300); }
/* Tema scuro, foglio della scansione: `--green-50` non è rimappato, quindi una
   superficie verde chiarissima resterebbe tale su fondo nero. E la carta, che è
   `--bg-1` come lo sfondo, senza un contorno sparirebbe: l'ombra non basta. */
[data-theme="dark"] .shot { background: linear-gradient(160deg, rgba(var(--green-500-rgb), .10), var(--bg-1)); }
[data-theme="dark"] .shot-art .scanx-paper { box-shadow: inset 0 0 0 1px var(--border-2); }
[data-theme="dark"] .pickrow-ic { background: rgba(var(--green-500-rgb), .14); color: var(--green-300); }

/* ══════════════════════════════════════════════════════════════════════════
   CLASSIFICA DELLE SEGNALAZIONI
   Segnalare un prezzo è un lavoro fatto per gli altri: l'unica cosa che si
   riceve indietro è vedersi in un elenco. Quindi la propria riga sta in cima,
   staccata, e non va cercata scorrendo cinquanta nomi.
   ═════════════════════════════════════════════════════════════════════════ */
.myrank {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
  border-radius: var(--r-xl);
  background: linear-gradient(140deg, var(--green-600), var(--green-800));
  color: #fff; box-shadow: 0 14px 30px -20px rgba(var(--green-500-rgb), 1);
}
.myrank-n { flex: 0 0 auto; font-size: var(--fs-24); font-weight: var(--fw-extra); letter-spacing: var(--ls-tight); }
.myrank-tx { flex: 1; min-width: 0; }
.myrank-tx b { display: block; font-size: var(--fs-14); font-weight: var(--fw-extra); }
.myrank-tx span { display: block; font-size: var(--fs-12); opacity: .85; }
.myrank > svg { width: 22px; height: 22px; flex: 0 0 auto; opacity: .55; }
/* Chi non è ancora in classifica non riceve un blocco verde di festa: riceve
   una riga neutra e un tasto per entrarci. */
.myrank.empty {
  background: var(--bg-1); color: var(--fg-1);
  border: 1px dashed var(--green-200); box-shadow: none;
}
.myrank.empty .myrank-tx span { color: var(--fg-4); opacity: 1; }

.bdrow { display: flex; align-items: center; gap: var(--s-3); padding: 10px 0; border-bottom: 1px solid var(--border-2); }
.bdrow:last-child { border-bottom: none; }
.bd-n {
  flex: 0 0 auto; width: 24px; text-align: center;
  font-size: var(--fs-13); font-weight: var(--fw-extra); color: var(--fg-5);
}
/* Oro, argento, bronzo per i primi tre — è l'unica convenzione che tutti
   leggono senza spiegazioni. */
.bd-n.top { color: #fff; border-radius: var(--r-sm, 6px); height: 24px; line-height: 24px; }
.bd-n.t1 { background: linear-gradient(140deg, #fbbf24, #d97706); }
.bd-n.t2 { background: linear-gradient(140deg, #cbd5e1, #94a3b8); }
.bd-n.t3 { background: linear-gradient(140deg, #d6a487, #b45309); }
.bd-avwrap { position: relative; flex: 0 0 auto; }
.bd-av {
  display: flex; width: 34px; height: 34px; border-radius: var(--r-pill);
  align-items: center; justify-content: center;
  background: linear-gradient(145deg, var(--green-400), var(--green-600));
  color: #fff; font-size: var(--fs-13); font-weight: var(--fw-extra);
}
/* Pro è un fatto di cassa, non di merito: un punto dorato sull'avatar, non
   una pastiglia che urla più forte del grado. */
.bd-prodot {
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px; border-radius: var(--r-pill);
  background: linear-gradient(140deg, #fbbf24, #d97706);
  border: 2px solid var(--bg-1);
}
.bd-body { flex: 1; min-width: 0; }
.bd-name {
  display: block; font-size: var(--fs-14); font-weight: var(--fw-bold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Riga del grado: è l'informazione della classifica, quindi sta sotto al nome
   con l'icona colorata del grado — come sul sito. */
/* nowrap: con l'a-capo le righe cambiavano altezza fra loro e la classifica
   perdeva il ritmo. Se non ci sta, a cedere è lo @username. */
.bd-meta {
  display: flex; align-items: center; flex-wrap: nowrap; gap: 6px;
  margin-top: 1px; min-width: 0; overflow: hidden;
}
.bd-grade, .bd-staff { flex: 0 0 auto; }
.bd-grade {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-wide); text-transform: uppercase;
}
.bd-grade svg { width: 12px; height: 12px; flex: 0 0 auto; }
.bd-staff {
  padding: 1px 6px; border-radius: var(--r-pill);
  background: var(--slate-100); color: var(--slate-600);
  font-size: 9px; font-weight: var(--fw-extra);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.bd-user {
  font-size: var(--fs-11); color: var(--fg-5); font-weight: var(--fw-semibold);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.bd-n2 { flex: 0 0 auto; text-align: right; line-height: 1.15; }
.bd-n2 b { display: block; font-size: var(--fs-16); font-weight: var(--fw-extra); }
.bd-n2 i { font-style: normal; font-size: 9px; color: var(--fg-5); font-weight: var(--fw-bold); }
/* La propria riga anche dentro l'elenco: senza, chi è 7° vede la sua
   posizione in cima e poi non si ritrova più nella lista. */
.bdrow.me {
  margin: 0 calc(var(--s-4) * -1); padding-left: var(--s-4); padding-right: var(--s-4);
  background: var(--conv-good-bg);
}
.bdrow.me .bd-name { color: var(--green-900); }

/* ══════════════════════════════════════════════════════════════════════════
   MAPPA DEI NEGOZI SENZA PREZZI (dentro le segnalazioni)
   ═════════════════════════════════════════════════════════════════════════ */
.blindwrap {
  border-radius: var(--r-xl); overflow: hidden;
  border: 1px solid var(--border-2); background: var(--bg-1);
  box-shadow: var(--shadow-card);
}
.blindbox { position: relative; height: min(38vh, 260px); background: var(--bg-3); }
#rep-map { position: absolute; inset: 0; }
.blindlegend {
  display: flex; align-items: flex-start; gap: 8px;
  padding: var(--s-3); border-top: 1px solid var(--border-2);
  font-size: var(--fs-12); color: var(--fg-3); line-height: var(--lh-snug);
}
.blindlegend svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--fg-5); margin-top: 1px; }
/* Il "+" a destra della riga: dice che toccando si AGGIUNGE un prezzo, non
   che si apre la scheda del negozio (che qui non esisterebbe, non avendo dati). */
.blindgo {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: var(--green-50); color: var(--green-700); border: 1px solid var(--green-100);
}
.blindgo svg { width: 18px; height: 18px; stroke-width: 2.2; }

/* ══════════════════════════════════════════════════════════════════════════
   GIRO DI PRESENTAZIONE — un faretto sull'app vera, non un mazzo di figurine

   Prima era una scheda a tutto schermo con dentro dei disegnini che imitavano
   l'interfaccia. Copriva l'app per raccontarla, e chiedeva di imparare a
   memoria delle figure da ritrovare poi da soli, in schermate mai viste.

   Adesso il buio ha un buco: il `.tour-hole` è trasparente e la sua ombra —
   un'ombra da 9999px, cioè più grande di qualunque schermo — è ciò che fa il
   nero su tutto il resto. Sotto il buco si vede l'app VERA, con i suoi dati
   veri, non una copia disegnata a mano che invecchia al primo ritocco.
   ═════════════════════════════════════════════════════════════════════════ */
.tour {
  position: fixed; inset: 0; z-index: 85;
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-base);
}
.tour.on { opacity: 1; pointer-events: auto; }

/* Il faretto. Niente `backdrop-filter`: sfocare il fondo servirebbe a
   nascondere l'app, e qui l'app è esattamente ciò che si deve guardare. */
.tour-hole {
  position: fixed; left: 50%; top: 50%; width: 0; height: 0;
  border-radius: var(--r-lg);
  box-shadow: 0 0 0 9999px rgba(9, 9, 11, .72);
  pointer-events: none;
  transition: left var(--t-base), top var(--t-base),
              width var(--t-base), height var(--t-base);
}
/* Il filo verde attorno al buco: senza, il bordo fra luce e buio è solo un
   salto di luminosità, e su una schermata già chiara (la home) il faretto non
   si distingue dal contenuto.

   `outline-offset` NEGATIVO (2026-08-12): il contorno va disegnato DENTRO il
   faretto, non fuori. Con offset 0 l'outline cresce verso l'esterno e, sommato
   al `pad`, il filo verde finiva due-tre pixel sopra la roba accanto — la
   fascia "metti l'app sul telefono", il bordo della mappa: sembrava un contorno
   messo a occhio. Dentro, invece, ripassa esattamente il bordo del bersaglio. */
.tour-hole.on { outline: 2px solid var(--green-400); outline-offset: -2px; }
.tour-hole.pill { border-radius: var(--r-pill); }

/* Il passo "provaci tu": il buco diventa toccabile e pulsa. L'anello che si
   allarga dice "qui", che è la sola cosa che una freccia disegnata direbbe
   meglio — e una freccia andrebbe riposizionata a mano a ogni ritocco. */
.tour-hole.tappable {
  pointer-events: auto; cursor: pointer;
  animation: tourPulse 1.6s ease-out infinite;
}
@keyframes tourPulse {
  0%   { outline-color: var(--green-400); outline-offset: -2px; }
  60%  { outline-color: rgba(var(--green-500-rgb), .25); outline-offset: 5px; }
  100% { outline-color: var(--green-400); outline-offset: -2px; }
}
@media (prefers-reduced-motion: reduce) {
  .tour-hole { transition: none; }
  .tour-hole.tappable { animation: none; }
}

/* "Salta il tutorial" sta in alto a destra ed è SEMPRE lì, da ogni passo — non
   solo dal primo. Sopra il buio serve pieno e bianco: la pastiglia grigia di
   prima stava su una scheda chiara, qui sparirebbe. */
.tour-skip {
  position: fixed; z-index: 2;
  top: calc(var(--safe-t) + var(--s-3)); right: var(--s-3);
  padding: 7px 14px; border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .16); color: #fff;
  border: 1px solid rgba(255, 255, 255, .3);
  font-size: var(--fs-12); font-weight: var(--fw-bold);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.tour-skip:active { background: rgba(255, 255, 255, .3); }

/* La scheda del passo: sta in BASSO, e passa in alto quando il faretto è nella
   metà bassa dello schermo (tab bar, tasto Confronta). Non insegue il bersaglio
   pixel per pixel: una scheda che saltella a ogni ridisegno si legge peggio, e
   sui bersagli a metà schermo finirebbe per coprire proprio ciò che indica. */
.tour-card {
  position: fixed; z-index: 2;
  left: var(--s-3); right: var(--s-3);
  bottom: calc(var(--safe-b) + var(--s-3));
  max-width: 420px; margin: 0 auto;
  padding: var(--s-4);
  border-radius: var(--r-2xl);
  /* Meno piatta (2026-08-12): un velo verdino appena accennato in alto invece
     del bianco unito, il filo di luce sul bordo superiore e DUE ombre — una
     stretta di contatto e una larga d'ambiente. È quel che fa sembrare la scheda
     appoggiata sopra l'app, invece che disegnata dentro il buio. */
  background:
    linear-gradient(180deg, rgba(var(--green-500-rgb), .05), rgba(var(--green-500-rgb), 0) 92px),
    var(--bg-1);
  border: 1px solid var(--border-2);
  box-shadow:
    0 2px 6px rgba(0, 0, 0, .18),
    0 26px 64px -22px rgba(0, 0, 0, .78),
    inset 0 1px 0 rgba(255, 255, 255, .6);
  transform: translateY(14px);
  transition: transform var(--t-slow), opacity var(--t-base);
}
.tour.on .tour-card { transform: translateY(0); }
.tour-card.at-top {
  bottom: auto;
  top: calc(var(--safe-t) + 52px);   /* sotto "Salta", che non va coperto */
}

.tour-top { display: flex; align-items: center; gap: 10px; }
/* L'ICONA DEL PASSO (rifatta 2026-08-12).
   Era un quadratino verde di 30px con dentro un glifo bianco: piatta, e ferma —
   diceva "categoria", non "guarda qui". Ora è un tasto rilevato: sfumatura in
   diagonale, un filo di luce in alto e un'ombra colorata sotto (la stessa
   grammatica del FAB della barra, che è l'oggetto più "toccabile" dell'app),
   dentro un alone verde chiaro che la stacca dalla scheda. */
.tour-ic {
  position: relative;
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  background: linear-gradient(145deg, var(--green-400), var(--green-600) 58%, var(--green-700));
  box-shadow:
    0 0 0 4px rgba(var(--green-500-rgb), .12),
    0 8px 16px -8px rgba(var(--green-500-rgb), .95),
    inset 0 1px 0 rgba(255, 255, 255, .45);
}
.tour-ic svg { position: relative; z-index: 1; width: 20px; height: 20px; stroke-width: 2.2; }
/* L'anello che respira: due cerchi che si allargano e si spengono. Sta SOTTO
   l'icona (`z-index:0` contro l'1 del glifo) e non intercetta tocchi, quindi è
   solo un segnale — nessun bersaglio finto da toccare. */
.tour-ic.act::before,
.tour-ic.act::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  border-radius: inherit;
  border: 2px solid rgba(var(--green-500-rgb), .55);
  animation: tourIcRing 2.2s cubic-bezier(.22, 1, .36, 1) infinite;
  pointer-events: none;
}
.tour-ic.act::after { animation-delay: 1.1s; }
@keyframes tourIcRing {
  0%   { transform: scale(1);    opacity: .7; }
  70%  { transform: scale(1.55); opacity: 0; }
  100% { transform: scale(1.55); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .tour-ic.act::before, .tour-ic.act::after { animation: none; opacity: 0; }
}
.tour-kick {
  flex: 1; min-width: 0;
  font-size: var(--fs-11); font-weight: var(--fw-extra);
  text-transform: uppercase; letter-spacing: var(--ls-wide); color: var(--green-600);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* "3 di 13" invece dei pallini: con tredici passi i pallini diventano una fila
   di puntini indistinguibili, e la domanda a cui devono rispondere — "quanto
   manca?" — resta senza risposta. */
.tour-step {
  flex: 0 0 auto; font-size: var(--fs-11); font-weight: var(--fw-bold);
  color: var(--fg-4); font-variant-numeric: tabular-nums;
}
.tour-t {
  margin-top: var(--s-3); font-size: var(--fs-21); font-weight: var(--fw-extra);
  letter-spacing: var(--ls-tight); line-height: var(--lh-tight);
}
.tour-d { margin-top: 6px; font-size: var(--fs-14); color: var(--fg-3); line-height: var(--lh-loose); }

.tour-bar {
  height: 4px; margin-top: var(--s-4); border-radius: var(--r-pill);
  background: var(--bg-3); overflow: hidden;
}
.tour-bar i {
  display: block; height: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--green-400), var(--green-600));
  /* La barra dice "quanto manca": un filo di luce sulla parte fatta la rende una
     cosa che avanza e non una riga colorata. */
  box-shadow: 0 0 8px -1px rgba(var(--green-500-rgb), .8);
  transition: width var(--t-slow);
}
.tour-foot { display: flex; gap: var(--s-2); margin-top: var(--s-3); }
.tour-foot .btn { flex: 1; height: 46px; }
.tour-foot .btn-ghost { flex: 0 0 auto; width: auto; padding: 0 var(--s-4); }

/* ── Barra "installa sul telefono" ─────────────────────────────────────── */
.installbar {
  flex: 0 0 auto; width: 100%; text-align: left;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: linear-gradient(135deg, var(--green-600), var(--green-800));
  color: #fff; z-index: 25;
}
.ib-ic {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .18);
}
.ib-ic svg { width: 17px; height: 17px; }
.ib-txt { flex: 1; min-width: 0; }
.ib-txt b { display: block; font-size: var(--fs-13); font-weight: var(--fw-extra); }
.ib-txt span { display: block; font-size: var(--fs-11); opacity: .85; }
.ib-x { flex: 0 0 auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: var(--r-pill); background: rgba(255,255,255,.16); }
.ib-x svg { width: 14px; height: 14px; }

/* ── Anteprima da computer: cornice telefono ───────────────────────────── */
/* Sopra i 900px di larghezza l'app non si "allarga": resta un telefono al
   centro. Un'app stirata su un monitor è la cosa che la fa sembrare un sito. */
@media (min-width: 900px) and (pointer: fine) {
  body.frameable {
    background: radial-gradient(120% 100% at 50% 0%, var(--zinc-100), var(--zinc-300));
    padding: 28px 0;
    display: flex; align-items: center; justify-content: center;
  }
  body.frameable #sc-root {
    width: 400px; height: min(860px, calc(100vh - 56px));
    border-radius: 42px; overflow: hidden;
    background: var(--bg-1);
    border: 11px solid var(--zinc-900);
    box-shadow: 0 40px 90px -30px rgba(0,0,0,.55), 0 0 0 1px rgba(0,0,0,.1);
  }
  body.frameable .gate, body.frameable .sheet, body.frameable .sheet-back,
  body.frameable .toast, body.frameable .cue, body.frameable .tour {
    position: absolute;
  }
  /* I fogli sono figli di #sc-root, quindi la cornice li contiene. */
}

/* ══════════════════════════════════════════════════════════════════════════
   MODALITÀ SCURA

   Si accende con <html data-theme="dark"> (SC.Theme in core.js: 'auto' segue il
   telefono, 'chiaro'/'scuro' sono la scelta esplicita dal profilo).

   La gran parte del lavoro la fanno già i token di /css/colors_and_type.css,
   che ha il suo blocco [data-theme="dark"] per fondi, testi e bordi: tutto ciò
   che in app.css è scritto con var(--bg-…) / var(--fg-…) si gira da solo. Qui
   sotto sta SOLO quello che i token non possono raggiungere, in tre gruppi:

    1. i TINTI (verde-50, ambra-50, i fondi conv-*): sono fondi chiarissimi
       pensati per pagina bianca. Restano tinti, ma scuri.
    2. i VERDI SCURI USATI COME TESTO (green-700/800/900, conv-*-fg): su un
       fondo scuro un verde bosco è illeggibile e vanno schiariti. Non si
       rimappa il token — gli stessi verdi disegnano anche i fondi pieni con
       testo bianco sopra (avatar, vincitore, segnaposti), che devono restare
       scuri: qui si cambia il COLORE DEL TESTO, selettore per selettore.
    3. i VETRI E I GRADIENTI scritti a mano in bianco (barre, campo di ricerca,
       velo di caricamento): un rgba(255,255,255,.9) non sa di essere in una
       app scura.

   Regola per chi aggiunge CSS: se usi var(--bg-…)/var(--fg-…)/var(--border-…)
   non devi toccare niente qui. Se scrivi un bianco a mano, sì.
   ═════════════════════════════════════════════════════════════════════════ */

/* ── 1 · Tinti ─────────────────────────────────────────────────────────── */
[data-theme="dark"] {
  --green-50:  #0f2418;
  --green-100: #16341f;
  --green-200: #1e4a2f;

  --conv-good-bg:   #0f2418;
  --conv-good-line: #1e4a2f;
  --conv-good-fg:   #6ee7a0;

  --conv-mid-bg:    #2a2007;
  --conv-mid-line:  #4a380d;
  --conv-mid-fg:    #fcd34d;

  --conv-bad-bg:    #2b1315;
  --conv-bad-line:  #4d2024;
  --conv-bad-fg:    #fca5a5;

  --amber-50:  #241b06;
  --amber-100: #2f2308;
  --amber-200: #4a380d;
  /* Unico ambra scuro usato come TESTO su fondo ambra (il numero
     "affidabilità" nel profilo). --amber-950 NON si tocca: sta sopra i
     gradienti ambra pieni, dove deve restare scuro. */
  --amber-800: #fcd34d;

  /* Luccichio dei riquadri in caricamento: lo zinco chiaro lampeggerebbe. */
  --zinc-100: #1f1f22;
  --zinc-200: #34343a;
  --zinc-300: #0c0c0e;

  --shadow-xs:   0 1px 2px rgba(0, 0, 0, .5);
  --shadow-card: 0 2px 10px rgba(0, 0, 0, .45);
}

/* ── 2 · Verdi scuri usati come testo ──────────────────────────────────── */
/* green-700 / 800 / 900 → verde chiaro leggibile sul tinto scuro. */
[data-theme="dark"] .tab-fab,
[data-theme="dark"] .homebtn,
[data-theme="dark"] .btn-soft,
[data-theme="dark"] .addbtn,
[data-theme="dark"] .reccard-ic,
[data-theme="dark"] .zone-gps,
[data-theme="dark"] .lg-n,
[data-theme="dark"] .pill.info,
[data-theme="dark"] .locbar-cta,
[data-theme="dark"] .rectile-ic,
[data-theme="dark"] .blindgo,
[data-theme="dark"] .bdrow.me .bd-name,
[data-theme="dark"] .cmp.best .cmp-price,
[data-theme="dark"] .cmp.best .cmp-name,
[data-theme="dark"] .price-vs.under,
[data-theme="dark"] .fbox.good b,
[data-theme="dark"] .plan-name,
[data-theme="dark"] .pt-head > b.pro,
[data-theme="dark"] .pt-row > b.pro,
[data-theme="dark"] .ac-p,
[data-theme="dark"] .more-toggle,
[data-theme="dark"] .okrow,
[data-theme="dark"] .alert.info,
[data-theme="dark"] .stat b,
[data-theme="dark"] .menu-item.on .menu-txt b { color: var(--green-300); }

/* green-600 come testo o icona: stesso motivo, un tono più acceso. */
[data-theme="dark"] .tab.on,
[data-theme="dark"] .sect-head .link,
[data-theme="dark"] .recbar-head svg,
[data-theme="dark"] .zonechip > svg:first-child,
[data-theme="dark"] .blindnote svg,
[data-theme="dark"] .cmp.best .cmp-rank,
[data-theme="dark"] .tour-kick,
[data-theme="dark"] .gate h1 em,
[data-theme="dark"] .feat-ic,
[data-theme="dark"] .menu-ic,
[data-theme="dark"] .menu-check,
[data-theme="dark"] .fbox.save b,
[data-theme="dark"] .pt-row > b.yes,
[data-theme="dark"] .state-ic.ok { color: var(--green-400); }

[data-theme="dark"] .spinner.dark { border-top-color: var(--green-400); }

/* Il richiamo del carrello e la fascetta "installa" sono verde pieno: le loro
   pastiglie bianche col testo verde scuro restano com'erano, ma il verde va
   alzato o su fondo bianco piccolo sparisce. */
[data-theme="dark"] .cue-ic i,
[data-theme="dark"] .cue-go { color: var(--green-800); }

/* Il messaggio a comparsa: lo zinco più scuro si confonderebbe col fondo. */
[data-theme="dark"] .toast { background: var(--zinc-700); border: 1px solid var(--zinc-600); }
[data-theme="dark"] .toast.bad { background: #7f1d1d; border-color: #991b1b; color: #fff; }

/* ── 3 · Vetri e gradienti scritti a mano ──────────────────────────────── */
[data-theme="dark"] .topbar {
  background: linear-gradient(180deg, rgba(22, 52, 31, .92), rgba(24, 24, 27, .88));
  border-bottom-color: transparent;         /* il filo compare scorrendo, come in chiaro */
}
[data-theme="dark"] .topbar.scrolled {
  border-bottom-color: var(--border-1);
  box-shadow: 0 10px 24px -18px rgba(0, 0, 0, 1);
}
/* Il tasto casa è una superficie chiara su vetro: di notte va scurito, o resta
   una macchia di luce. */
[data-theme="dark"] .homebtn {
  background: rgba(20, 20, 23, .82);
  border-color: rgba(255, 255, 255, .12);
  color: var(--green-400);
}
[data-theme="dark"] .tabbar {
  background: rgba(20, 20, 23, .92);
  border-top-color: var(--border-1);
  box-shadow: 0 -8px 24px -16px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .05);
}
[data-theme="dark"] .searchbar {
  background: rgba(20, 20, 23, .94);
  border-bottom-color: var(--border-1);
}
/* Il campo di ricerca dell'intestazione è una pastiglia sopra il verde pieno:
   in scuro diventa una pastiglia scura, o sarebbe l'unica cosa bianca a
   schermo. Il filo e il riflesso bianchi vanno spenti insieme al fondo: su una
   pastiglia scura restavano due righe luminose che sembravano un difetto. */
[data-theme="dark"] .hero-search {
  background: rgba(10, 12, 11, .86);
  border-color: rgba(255, 255, 255, .10);
  box-shadow: 0 12px 26px -16px rgba(0, 0, 0, 1);
}
[data-theme="dark"] .maploading { background: rgba(15, 15, 17, .6); }
[data-theme="dark"] .cartbar { background: linear-gradient(180deg, rgba(24, 24, 27, 0), var(--bg-1) 32%); }
/* Spiegazione punteggio: la fascia colorata viaggia sui -dot (colori pieni),
   che di notte restano leggibili; il riempimento della fascia scelta usa i -bg,
   che in dark sono già tinte scure. Qui serve solo l'icona dei blocchi, perché
   --green-50 sul fondo scuro diventa una macchia chiara. */
[data-theme="dark"] .shelp-x-ic {
  background: rgba(var(--green-500-rgb), .14);
  color: var(--green-300, #86efac);
}
/* Interruttore spento: di giorno un grigio chiaro, di notte diventerebbe la cosa
   più luminosa del foglio — va spento anche lui. */
[data-theme="dark"] .ef-toggle > span { background: rgba(255, 255, 255, .16); }
[data-theme="dark"] .ef-toggle > span::after { background: #e4e4e7; }

[data-theme="dark"] .pin { border-color: rgba(255, 255, 255, .55); }
/* La goccia dei negozi senza prezzi resta BIANCA anche di notte — dentro c'è un
   logo disegnato per la carta — quindi il contorno bianco delle altre la
   renderebbe invisibile: qui serve il grigio, che è anche ciò che la distingue
   dalle gocce col punteggio. */
[data-theme="dark"] .pin.blind { border-color: var(--zinc-400, #a1a1aa); }
/* La targhetta col marchio resta bianca anche di notte — i loghi delle catene
   sono disegnati per la carta e su fondo scuro si perdono — e col fondo bianco
   il contorno DEVE tornare al colore del giudizio: quello chiaro qui sopra, su
   bianco, sparirebbe. */
[data-theme="dark"] .pin.brand,
[data-theme="dark"] .pin.brand::after { border-color: var(--pin-c); }

/* ── Tinte di famiglia, di notte ───────────────────────────────────────────
   I pastelli chiari su fondo nero diventano nove lampadine: la riga del
   prodotto sparirebbe dietro la sua icona. Stesse nove tinte, ma ribaltate —
   fondo profondo, segno acceso — così la famiglia si riconosce ancora e a
   dominare resta il nome del prodotto. */
[data-theme="dark"] .prod-ic,
[data-theme="dark"] .cmp-ic {
  /* Il velo bianco del tema chiaro qui sbiadirebbe il fondo scuro. */
  background-image: linear-gradient(140deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .05));
  --ic-bg: rgba(var(--green-500-rgb), .16); --ic-fg: var(--green-300); --ic-line: rgba(var(--green-500-rgb), .24);
}
/* Il valore di partenza va sulla TESTATA, non sull'icona: le variabili le
   dichiara `.rgroup-head[data-cat=…]` e scendono per eredità: riscriverle
   direttamente su `.rgroup-ic` batterebbe la famiglia ereditata dal padre. */
[data-theme="dark"] .rgroup-head { --ic-bg: rgba(var(--green-500-rgb), .16); --ic-fg: var(--green-300); }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="latticini"], [data-theme="dark"] .rgroup-head[data-cat="latticini"] { --ic-bg: #0d2b45; --ic-fg: #7dd3fc; --ic-line: #16405f; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="surgelati"], [data-theme="dark"] .rgroup-head[data-cat="surgelati"] { --ic-bg: #0d2b45; --ic-fg: #7dd3fc; --ic-line: #16405f; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="acqua"],     [data-theme="dark"] .rgroup-head[data-cat="acqua"]     { --ic-bg: #0b3038; --ic-fg: #67e8f9; --ic-line: #114c57; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="bevande"],   [data-theme="dark"] .rgroup-head[data-cat="bevande"]   { --ic-bg: #0b3038; --ic-fg: #67e8f9; --ic-line: #114c57; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="pasta"],     [data-theme="dark"] .rgroup-head[data-cat="pasta"]     { --ic-bg: #3a2a0c; --ic-fg: #fcd34d; --ic-line: #55401a; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="snack"],     [data-theme="dark"] .rgroup-head[data-cat="snack"]     { --ic-bg: #3d230e; --ic-fg: #fdba74; --ic-line: #59341b; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="carne"],     [data-theme="dark"] .rgroup-head[data-cat="carne"]     { --ic-bg: #3d1414; --ic-fg: #fca5a5; --ic-line: #591f1f; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="salumi"],    [data-theme="dark"] .rgroup-head[data-cat="salumi"]    { --ic-bg: #3d1421; --ic-fg: #fda4af; --ic-line: #591f2f; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="dolci"],     [data-theme="dark"] .rgroup-head[data-cat="dolci"]     { --ic-bg: #3a1229; --ic-fg: #f9a8d4; --ic-line: #551c3c; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="caffe"],     [data-theme="dark"] .rgroup-head[data-cat="caffe"]     { --ic-bg: #33220f; --ic-fg: #dcb894; --ic-line: #4a341c; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="detersivi"], [data-theme="dark"] .rgroup-head[data-cat="detersivi"] { --ic-bg: #241a4a; --ic-fg: #c4b5fd; --ic-line: #362a68; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="cura"],      [data-theme="dark"] .rgroup-head[data-cat="cura"]      { --ic-bg: #2a1443; --ic-fg: #d8b4fe; --ic-line: #3e2160; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="animali"],   [data-theme="dark"] .rgroup-head[data-cat="animali"]   { --ic-bg: #27272a; --ic-fg: var(--zinc-400); --ic-line: #3f3f46; }
[data-theme="dark"] :is(.prod-ic, .cmp-ic)[data-cat="altro"],     [data-theme="dark"] .rgroup-head[data-cat="altro"]     { --ic-bg: #27272a; --ic-fg: var(--zinc-400); --ic-line: #3f3f46; }

/* Lo scontrino di notte: l'ombra nera sotto una carta scura non si vede, la
   carta sembra incollata al fondo. Un filo chiaro le ridà lo spessore. */
[data-theme="dark"] .receipt { filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .07)); }

/* Le tessere dei marchi restano BIANCHE anche di notte: i loghi delle catene
   sono disegnati per la carta e molti hanno parti bianche (il cerchio di Lidl,
   la "C" di Carrefour) che su fondo scuro sparirebbero. Cambia solo il filo,
   che in chiaro delimita la tessera e in scuro la staccherebbe troppo. */
[data-theme="dark"] .store-logo,
[data-theme="dark"] .cmp-logo { border-color: rgba(255, 255, 255, .12); }
/* La tessera della classifica in chiaro il filo non ce l'ha (è bianca su una
   scheda bianca, e sparire è il suo mestiere): qui glielo si dà, o il
   rettangolo bianco taglia di netto la riga scura. */
[data-theme="dark"] .rkrow-logo { border: 1px solid rgba(255, 255, 255, .12); }

/* La home ridisegnata usa il verde come INCHIOSTRO (la parola del titolo) invece
   che come campitura. green-600 è pensato per stare sul bianco: sul nero va
   alzato, come per tutti gli altri verdi-testo. */
[data-theme="dark"] .hero-t em { color: var(--green-300); }
/* Le pastiglie delle spese al volo e "Come funziona": in chiaro sono bianche col
   filo grigio e verdi tenui; di notte il fondo chiaro le farebbe esplodere. */
[data-theme="dark"] .home .sect-head .link {
  background: rgba(var(--green-500-rgb), .14);
  border-color: rgba(var(--green-500-rgb), .26);
  color: var(--green-300);
}

/* Il marchio dell'app NON prende una tessera bianca in scuro: il simbolo è
   verde su trasparente e sul fondo scuro si legge benissimo da solo, mentre il
   riquadro chiaro spiccava come una toppa attaccata al logo. */

/* Il buio del giro di presentazione. Va messo sull'OMBRA del faretto, mai su
   `.tour`: un fondo su `.tour` coprirebbe anche il buco, cioè spegnerebbe
   esattamente la cosa che il faretto deve illuminare.
   Di notte l'app è già scura e un velo alla stessa opacità del giorno non si
   distinguerebbe da lei: qui va più fitto, o non si capisce cosa è acceso. */
[data-theme="dark"] .tour-hole { box-shadow: 0 0 0 9999px rgba(0, 0, 0, .8); }
/* Di notte il filo di luce sul bordo della scheda va spento (su una superficie
   scura una riga bianca si legge come un difetto) e l'ombra va più fitta, o la
   scheda si incolla al buio del velo. */
[data-theme="dark"] .tour-card {
  border-color: rgba(255, 255, 255, .10);
  box-shadow:
    0 2px 8px rgba(0, 0, 0, .5),
    0 26px 64px -20px rgba(0, 0, 0, .95),
    inset 0 1px 0 rgba(255, 255, 255, .06);
}

/* Accesso: gli aloni chiari diventano un fondo scuro con un accenno di verde. */
[data-theme="dark"] .gate {
  background:
    radial-gradient(120% 62% at 88% -8%, rgba(var(--green-500-rgb), .16) 0%, transparent 58%),
    radial-gradient(96% 50% at -12% 4%, rgba(56, 189, 248, .10) 0%, transparent 52%),
    var(--bg-2);
}
[data-theme="dark"] .gate-theme { background: var(--bg-3); border-color: rgba(255, 255, 255, .12); }
[data-theme="dark"] .gate-theme button.on { background: rgba(var(--green-500-rgb), .20); color: var(--green-300); }

/* Anteprima da computer: la scrivania attorno al telefono. */
@media (min-width: 900px) and (pointer: fine) {
  [data-theme="dark"] body.frameable {
    background: radial-gradient(120% 100% at 50% 0%, #202024, #0a0a0c);
  }
  [data-theme="dark"] body.frameable #sc-root { border-color: #000; }
}

/* ── Budget e scontrini ──────────────────────────────────────────────────────
   Una sola cifra grande (quanto hai speso questo mese) e sotto il contesto.
   Con due numeri di pari peso affiancati non si capiva quale fosse il dato. */
.budget-hero {
  margin: var(--s-2) var(--s-4) var(--s-3);
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-xl); padding: var(--s-4);
  box-shadow: var(--shadow-card); text-align: center;
}
.budget-month {
  font-size: var(--fs-11); font-weight: var(--fw-extra); color: var(--fg-4);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.budget-big {
  margin-top: 2px; font-size: 38px; font-weight: 800;
  letter-spacing: -0.035em; color: var(--fg-1); line-height: 1.05;
}
.budget-big-lbl { font-size: var(--fs-13); color: var(--fg-3); font-weight: var(--fw-semibold); margin-top: 2px; }
.ba-over { color: var(--red-600); }

.budget-bar-wrap { margin-top: var(--s-4); text-align: left; }
.budget-bar  { height: 8px; background: var(--border-2); border-radius: 8px; overflow: hidden; margin-bottom: 6px; }
.budget-bar-fill { height: 100%; border-radius: 8px; transition: width .5s ease; }
.budget-bar-fill.green { background: var(--green-500); }
.budget-bar-fill.amber { background: var(--amber-400); }
.budget-bar-fill.red   { background: var(--red-500); }
.budget-bar-meta { display: flex; justify-content: space-between; gap: var(--s-2); font-size: var(--fs-12); color: var(--fg-4); font-weight: var(--fw-semibold); }
.budget-bar-meta b { color: var(--fg-1); font-weight: var(--fw-extra); }

.budget-edit-row {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s-2);
  margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--border-2);
  text-align: left;
}
.budget-edit-lbl { font-size: var(--fs-13); color: var(--fg-3); font-weight: var(--fw-semibold); }
.btn-link { font-size: var(--fs-13); color: var(--green-600); font-weight: var(--fw-bold); background: none; border: none; cursor: pointer; padding: 4px 0; }
.budget-edit-form { display: flex; gap: 8px; margin-top: var(--s-3); }
.budget-edit-form[hidden] { display: none; }
.budget-edit-form .sb-input { flex: 1; }
.budget-edit-form .btn { width: auto; flex: 0 0 auto; height: 42px; padding: 0 var(--s-4); font-size: var(--fs-14); }

/* Il bottone sta dentro un contenitore con padding: da solo era largo 100% con
   margini laterali applicati a mano e risultava fuori asse. */
.budget-cta { padding: 0 var(--s-4); }
.budget-cta-note {
  margin-top: 6px; text-align: center;
  font-size: var(--fs-11); color: var(--fg-4); font-weight: var(--fw-semibold);
}

/* Tendina "come funziona": chiusa quando ci sono già scontrini (chi lo usa non
   ha bisogno di rileggerlo), aperta la prima volta. */
.budget-how {
  margin: var(--s-3) var(--s-4) 0;
  background: var(--green-50);
  border: 1px solid var(--green-100); border-radius: var(--r-xl);
  overflow: hidden;
}
.budget-how-title {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  padding: var(--s-3) var(--s-4); cursor: pointer; list-style: none;
  font-size: var(--fs-12); font-weight: var(--fw-extra); color: var(--green-700);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
}
.budget-how-title::-webkit-details-marker { display: none; }
.budget-how-title svg { width: 15px; height: 15px; transform: rotate(90deg); transition: transform .2s ease; flex: 0 0 auto; }
.budget-how[open] .budget-how-title svg { transform: rotate(-90deg); }
.budget-how-body { padding: 0 var(--s-4) var(--s-4); }
.budget-how-step {
  display: flex; align-items: flex-start; gap: var(--s-2); margin-bottom: var(--s-2);
  font-size: var(--fs-13); color: var(--fg-2); line-height: 1.45;
}
.budget-how-step:last-child { margin-bottom: 0; }
.budget-how-step svg { flex-shrink: 0; width: 17px; height: 17px; margin-top: 2px; color: var(--green-600); }

/* Input riutilizzato in budget edit e nell'alert footer */
.sb-input { flex: 1; padding: 9px 12px; border: 1.5px solid var(--border-1); border-radius: var(--r-md); background: var(--bg-2); font-size: var(--fs-14); width: 100%; }
.sb-input:focus { outline: none; border-color: var(--green-500); }

/* Avviso di prezzo nel piede del foglio prodotto.
   Il campo e il bottone si contendevano la riga: `.btn` è largo 100% e il
   campo, pur con flex:1, veniva schiacciato a un rettangolo vuoto largo due
   dita — sembrava un elemento rotto, non un prezzo da scrivere. Ora il
   bottone ha larghezza propria (`flex:0 0 auto`) e lo spazio che avanza è
   tutto del campo, che ha un'etichetta sopra e il simbolo € dentro. */
.alert-box {
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--border-2);
}
.alert-box-lbl {
  display: flex; align-items: center; gap: 6px; margin-bottom: 8px;
  font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--fg-2);
}
.alert-box-lbl svg { width: 16px; height: 16px; color: var(--green-600); flex-shrink: 0; }
.alert-row { display: flex; gap: 8px; align-items: center; }
.alert-field { position: relative; flex: 1 1 auto; min-width: 0; }
.alert-field .sb-input { width: 100%; height: 46px; padding-right: 30px; }
.alert-cur {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-size: var(--fs-14); font-weight: var(--fw-bold); color: var(--fg-4);
  pointer-events: none;
}
.alert-row .btn.alert-go { flex: 0 0 auto; width: auto; height: 46px; padding: 0 var(--s-5); }
/* Il giudizio sulla soglia, mentre la si scrive: "in 9 giorni non è mai sceso
   sotto 1,19 €". Il colore è l'unica gerarchia — verde se l'avviso partirebbe,
   ambra se è raro, rosso se non suonerebbe mai, grigio se non lo sappiamo. */
.alert-box-hint {
  margin: 8px 0 0; font-size: var(--fs-12); line-height: 1.45;
  font-weight: var(--fw-semibold); color: var(--fg-4);
}
.alert-box-hint:empty { display: none; }
.alert-box-hint.ok   { color: var(--green-700); }
.alert-box-hint.warn { color: var(--conv-mid-fg); }
.alert-box-hint.bad  { color: var(--conv-bad-fg); }

/* Versione gratis: un invito leggibile, non una scritta grigia in fondo. */
.alert-pro { margin-top: var(--s-3); font-size: var(--fs-14); }
.alert-pro svg { width: 17px; height: 17px; color: var(--green-600); }
.alert-pro-tag {
  margin-left: 6px; padding: 2px 7px; border-radius: var(--r-pill);
  background: var(--green-50); color: var(--green-700);
  font-size: var(--fs-11); font-weight: var(--fw-extra); letter-spacing: var(--ls-wide);
}

/* ── Pannello alert: una SCHEDA per alert ────────────────────────────────────
   Prima era un elenco di righe dove l'unica azione era la × di cancellazione.
   Un alert ha uno stato, due prezzi e tre azioni: sta in una scheda, non in
   una riga. */
.alcards { display: flex; flex-direction: column; gap: var(--s-4); padding: 0 var(--s-4) var(--s-2); }
.alcard {
  background: var(--bg-1); border: 1px solid var(--border-2);
  border-radius: var(--r-xl); box-shadow: var(--shadow-sm);
  padding: var(--s-4) var(--s-4) 0;
}
.alcard.is-off { opacity: .68; }
.alcard.is-hit { border-color: var(--conv-good-line); }

/* Testa tappabile: nome + contesto, e la freccia dice che porta ai prezzi.
   Prima il nome era testo morto e l'unico modo di arrivare al prodotto era un
   "Vedi prezzi" da 12px in alto a destra. */
.alcard-top {
  display: flex; align-items: center; gap: var(--s-3); width: 100%;
  text-align: left; padding: 0 0 var(--s-3);
}
.alcard-tx { flex: 1; min-width: 0; }
.alcard-tx b {
  display: block; font-size: var(--fs-16); font-weight: var(--fw-extra);
  color: var(--fg-1); line-height: 1.25;
}
/* I nomi prodotto in DB sono a volte tutti minuscoli (titleCase raddrizza solo
   i TUTTO MAIUSCOLO): almeno l'iniziale del titolo va alzata. */
.alcard-tx b::first-letter { text-transform: uppercase; }
.alcard-tx i {
  display: block; font-style: normal; margin-top: 2px;
  font-size: var(--fs-12); font-weight: var(--fw-semibold); color: var(--fg-4);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alcard-ch { flex: 0 0 auto; color: var(--fg-4); display: flex; }
.alcard-ch svg { width: 18px; height: 18px; }

/* La scala dei prezzi: minimo storico, prezzo di oggi e obiettivo sullo stesso
   righello. Un obiettivo fuori da quello che i supermercati hanno mai fatto si
   VEDE (resta schiacciato a sinistra), non va spiegato. */
.alscale { margin-bottom: var(--s-3); }
.alsc-track {
  position: relative; height: 8px; border-radius: var(--r-pill);
  background: var(--bg-3); overflow: visible;
}
.alsc-fill {
  position: absolute; left: 0; top: 0; bottom: 0; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--green-400), var(--green-500));
}
.alsc-tick {
  position: absolute; top: -3px; width: 2px; height: 14px; border-radius: 1px;
  background: var(--fg-4); opacity: .55; transform: translateX(-1px);
}
.alsc-now {
  position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%;
  background: var(--bg-1); border: 3px solid var(--fg-2);
  transform: translate(-50%, -50%);
}
.alscale.is-hit .alsc-now { border-color: var(--green-600); }
.alsc-legend {
  display: flex; justify-content: space-between; gap: var(--s-3); margin-top: 7px;
  font-size: var(--fs-12); font-weight: var(--fw-bold);
}
.alsc-l-t { color: var(--green-700); }
.alsc-l-n { color: var(--fg-3); }

/* Stato: una frase in tondo con la sua icona. La pastiglia MONITORATO in
   maiuscolo col pallino che pulsava occupava la riga migliore della scheda per
   dire una cosa che l'utente sa già (l'alert esiste, l'ha creato lui). */
.alstate {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--fs-13); font-weight: var(--fw-semibold); color: var(--fg-2);
}
.alstate svg { width: 16px; height: 16px; flex: 0 0 auto; }
.alstate.on   { color: var(--fg-2); }
.alstate.hit  { color: var(--green-700); font-weight: var(--fw-bold); }
.alstate.off,
.alstate.wait { color: var(--fg-4); }

/* L'avviso sull'obiettivo irrealistico. */
.alwarn {
  display: flex; gap: 8px; margin-top: var(--s-3);
  padding: 10px 11px; border-radius: var(--r-lg);
  font-size: var(--fs-12); line-height: 1.5; font-weight: var(--fw-semibold);
}
.alwarn-ic { flex: 0 0 auto; display: flex; margin-top: 1px; }
.alwarn-ic svg { width: 15px; height: 15px; }
.alwarn.bad  { background: var(--conv-bad-bg);  color: var(--conv-bad-fg); }
.alwarn.warn { background: var(--conv-mid-bg);  color: var(--conv-mid-fg); }
.alwarn.wait { background: var(--bg-2);         color: var(--fg-4); }
.alwarn-fix {
  display: inline-flex; margin-left: 2px; padding: 2px 9px;
  border-radius: var(--r-pill); background: var(--bg-1);
  border: 1px solid currentColor; color: inherit;
  font-size: var(--fs-12); font-weight: var(--fw-extra);
}

.alcard-edit { margin-top: var(--s-3); }
.alcard-edit[hidden] { display: none; }
.alcard-edit-lbl {
  display: block; font-size: var(--fs-12); font-weight: var(--fw-bold);
  color: var(--fg-3); margin-bottom: 6px;
}
.alcard-edit-row { display: flex; gap: 8px; align-items: center; }
.alcard-edit-fld { position: relative; flex: 1; min-width: 0; }
.alcard-edit-fld .sb-input { width: 100%; padding-right: 26px; }
.alcard-edit-cur {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  font-size: var(--fs-14); font-weight: var(--fw-bold); color: var(--fg-4);
  pointer-events: none;
}
/* Scorciatoie: col pollice, due decimali sono il vero ostacolo alla modifica. */
.alquick { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.alq {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 5px 10px; border-radius: var(--r-pill);
  background: var(--bg-2); border: 1px solid var(--border-2);
  font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--fg-2);
}
/* Quante volte quella soglia sarebbe scattata davvero: è il motivo per cui la
   scorciatoia esiste, quindi si legge — ma sottovoce, il prezzo resta primo. */
.alq i { font-style: normal; font-weight: var(--fw-semibold); color: var(--fg-4); }
.alq:active { background: var(--bg-3); }
.alcard-edit-hint {
  margin: 7px 0 0; font-size: var(--fs-12); line-height: 1.45;
  font-weight: var(--fw-semibold); color: var(--fg-4);
}
.alcard-edit-hint.ok   { color: var(--green-700); }
.alcard-edit-hint.warn { color: var(--conv-mid-fg); }
.alcard-edit-hint.bad  { color: var(--conv-bad-fg); }

.alcard-acts {
  display: flex; margin: var(--s-3) calc(var(--s-4) * -1) 0;
  border-top: 1px solid var(--border-2);
}
.alact {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
  padding: 11px 4px; font-size: var(--fs-12); font-weight: var(--fw-bold);
  color: var(--fg-2);
}
.alact + .alact { border-left: 1px solid var(--border-2); }
.alact svg { width: 15px; height: 15px; flex: 0 0 auto; }
.alact.danger { color: var(--conv-bad-fg); }
.alact[data-armed="1"] { background: var(--conv-bad-bg); }
.alact[disabled] { opacity: .45; pointer-events: none; }

/* Le varianti che NON sono verdi: hanno la stessa specificità delle regole qui
   sopra, quindi senza ripeterle si vedrebbero riverniciate di verde. */
[data-theme="dark"] .addbtn.on { color: #fff; }
[data-theme="dark"] .rank-card { background: var(--bg-2); }
[data-theme="dark"] .budget-hero { background: var(--bg-2); }
[data-theme="dark"] .budget-how { background: rgba(34,197,94,.07); border-color: rgba(34,197,94,.15); }
[data-theme="dark"] .budget-how-title { color: var(--green-400); }
[data-theme="dark"] .budget-how-step { color: var(--fg-3); }
[data-theme="dark"] .alcard { background: var(--bg-2); }
[data-theme="dark"] .alstate.hit { color: var(--green-400); }
[data-theme="dark"] .alwarn.bad  { background: rgba(239,68,68,.12); }
[data-theme="dark"] .alwarn.warn { background: rgba(245,158,11,.12); }
[data-theme="dark"] .alwarn-fix  { background: transparent; }
[data-theme="dark"] .alcard-edit-hint.ok { color: var(--green-400); }
[data-theme="dark"] .bd-prodot { border-color: var(--bg-2); }
[data-theme="dark"] .bd-staff { background: rgba(148,163,184,.16); color: var(--slate-300); }
/* I colori dei gradi arrivano inline da SCRank (gli stessi del sito, tarati su
   fondo bianco): Veterano #15803d e Leggenda #7c3aed sul fondo scuro stanno
   sotto 3.5:1. Non li riscriviamo grado per grado — li schiariamo, così un
   grado nuovo eredita il fix. */
[data-theme="dark"] .bd-grade { filter: brightness(1.5) saturate(1.15); }
[data-theme="dark"] .rn-chip { background: rgba(148,163,184,.12); }
[data-theme="dark"] .rn-done { color: var(--green-400); }

/* I rossi delle offerte sono scritti a mano (non sono token): su fondo scuro un
   rosso pieno vibra e si legge male, quindi si alza il tono. */
[data-theme="dark"] .tag-offer,
[data-theme="dark"] .on-offer,
[data-theme="dark"] .price-vs.over { color: #fca5a5; }
