/* ============================================================
   Portale ordini — foglio di stile unico.
   Token allineati a design/design-system.html.
   Nessuna dipendenza esterna: funziona offline e da file://.
   ============================================================ */

/* ---------- VARIANTI DI PALETTE ----------
   Cantina e la variante scelta: verde profondo con azioni rosso scuro.
   Sul rosso il testo e bianco: a L 0.45 il contrasto e ampiamente sopra AA. */
[data-theme="cantina"] {
  --p:  42% 0.095 158;   --pc: 98% 0.010 90;
  --a:  45% 0.170 27;    --ac: 98% 0.008 90;
  --n:  28% 0.006 70;    --nc: 96% 0.008 85;
  --b1: 98.5% 0.006 85;  --b2: 95.5% 0.009 82;  --b3: 91% 0.012 80;
  --bc: 22% 0.008 70;
  --er: 45% 0.170 27;
}
[data-theme="bottega"] {
  --p:  42% 0.095 158;   --pc: 98% 0.010 90;
  --a:  70% 0.163 58;    --ac: 22% 0.030 60;
  --n:  28% 0.006 70;    --nc: 96% 0.008 85;
  --b1: 98.5% 0.006 85;  --b2: 95.5% 0.009 82;  --b3: 91% 0.012 80;
  --bc: 22% 0.008 70;
  --er: 58% 0.200 25;
}
[data-theme="espresso"] {
  --p:  28% 0.010 55;    --pc: 97% 0.015 85;
  --a:  55% 0.145 40;    --ac: 98% 0.010 85;
  --n:  30% 0.012 55;    --nc: 96% 0.015 85;
  --b1: 97.5% 0.016 88;  --b2: 94.5% 0.020 86;  --b3: 90% 0.024 84;
  --bc: 24% 0.012 55;
  --er: 54% 0.180 30;
}
[data-theme="forno"] {
  --p:  42% 0.095 45;    --pc: 97% 0.020 85;
  --a:  68% 0.145 62;    --ac: 24% 0.030 60;
  --n:  32% 0.025 50;    --nc: 96% 0.020 85;
  --b1: 97.5% 0.020 82;  --b2: 94.5% 0.026 80;  --b3: 89.5% 0.032 78;
  --bc: 25% 0.020 50;
  --er: 52% 0.185 30;
}

:root {
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px;
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-full: 999px;
  --tocco: 48px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  color: oklch(var(--bc));
  background: oklch(var(--b2));
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}
button, input { font-family: inherit; }

/* ---------- IMPIANTO ---------- */
.app { display: flex; flex-direction: column; height: 100dvh; }

.testata { background: oklch(var(--p)); color: oklch(var(--pc)); padding: var(--s3) var(--s3) var(--s2); flex: none; }
.testata-alto { display: flex; align-items: center; gap: var(--s2); margin-bottom: var(--s3); padding: 0 var(--s1); }
/* Logo a sinistra, e accanto due righe: chi sta ordinando e cosa contiene
   il catalogo. I quattro pallini della palette sono spariti — servivano a
   scegliere la variante durante lo sviluppo, e la scelta e' fatta (cantina). */
.testata-sx { display: flex; align-items: center; gap: var(--s2); flex: 1; min-width: 0; }
.testata-chi { min-width: 0; }
.cliente { font-size: 12px; font-weight: 650; line-height: 1.25;
           white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cliente.anonimo { font-weight: 500; color: oklch(var(--pc) / 0.65); }
/* Il logo e a colori su fondo trasparente, disegnato per la carta bianca:
   sul verde della testata il nero di "Handel" sparirebbe. La tessera bianca
   e una necessita di leggibilita, non una scelta estetica — e vale per tutte
   e quattro le varianti di palette. */
.logo { display: inline-flex; background: #fff; border-radius: var(--r-md); padding: 5px 8px; }
.logo img { height: 24px; width: auto; display: block; }

/* Il select nativo eredita i colori del sistema per le opzioni: senza uno
   sfondo esplicito, su Windows la tendina risulta bianco su bianco. */
/* Stessa altezza dei pallini del tema e del selettore lingua: la fila in
   alto resta di un'altezza sola. Da dentro, il bordo si accende. */
.accesso { display: inline-flex; align-items: center; justify-content: center;
           width: 34px; height: 34px; padding: 0; border-radius: var(--r-md);
           background: oklch(var(--pc) / 0.14); color: oklch(var(--pc));
           border: 1px solid oklch(var(--pc) / 0.35); cursor: pointer; }
.accesso.dentro { background: oklch(var(--pc)); color: oklch(var(--p)); border-color: oklch(var(--pc)); }

.lingua { height: 34px; padding: 0 var(--s1); border-radius: var(--r-md); cursor: pointer;
          background: oklch(var(--pc) / 0.14); color: oklch(var(--pc));
          border: 1px solid oklch(var(--pc) / 0.35);
          font-family: var(--font); font-size: 12px; font-weight: 700; letter-spacing: 0.03em; }
.lingua option { background: #fff; color: #1a1a1a; font-weight: 600; }
.riga-conteggio { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
/* Sotto i 600px il conteggio finisce SOTTO il logo: li deve stare su una riga
   sola, altrimenti fa crescere la testata per niente. */
.conteggio-catalogo { font-size: 11px; line-height: 1.3; color: oklch(var(--pc) / 0.75); }
.conteggio-catalogo .n { font-weight: 700; font-variant-numeric: tabular-nums; }
.conteggio-catalogo .w { margin-left: 4px; }
.conteggio-catalogo .cc-par + .cc-par::before { content: "·"; margin: 0 5px; }
/* Colore d'azione, non del tema: deve staccare dal verde della testata in
   tutte e quattro le varianti senza introdurre un token nuovo. */
.pastiglia-fonte { padding: 2px 7px; border-radius: var(--r-full); cursor: help;
                   background: oklch(var(--a)); color: oklch(var(--ac));
                   font-size: 10px; font-weight: 700; white-space: nowrap; }
.pastiglia-fonte[hidden] { display: none; }

.ricerca { display: flex; align-items: center; gap: var(--s2); background: oklch(var(--b1)); border-radius: var(--r-full); padding: 0 var(--s4); height: var(--tocco); }
.ricerca svg { opacity: 0.45; flex: none; }
.ricerca input { border: none; outline: none; background: none; flex: 1; font-size: 16px; color: oklch(var(--bc)); min-width: 0; }
.ricerca input::placeholder { color: oklch(var(--bc) / 0.45); }
.ricerca .pulisci { border: none; background: none; cursor: pointer; color: oklch(var(--bc) / 0.5); font-size: 20px; line-height: 1; padding: var(--s1); display: none; }
.ricerca.piena .pulisci { display: block; }
.ricerca .scan { flex: none; width: 38px; height: 38px; margin-right: -10px; border: none; border-radius: var(--r-full);
                 background: oklch(var(--a)); color: oklch(var(--ac)); cursor: pointer;
                 display: grid; place-items: center; }

/* ---------- SCANNER EAN ---------- */
.scanner { position: fixed; inset: 0; z-index: 60; background: #000; display: flex; flex-direction: column; }
.scanner[hidden] { display: none; }
.scanner video { flex: 1; width: 100%; object-fit: cover; background: #000; }
.scanner-testata { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4);
                   color: #fff; background: #000;
                   padding-top: calc(var(--s3) + env(safe-area-inset-top, 0px)); }
.scanner-testata h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 650; }
.scanner-testata button { width: 40px; height: 40px; border: none; border-radius: var(--r-full);
                          background: rgba(255,255,255,0.18); color: #fff; font-size: 20px; cursor: pointer; }
.scanner-piede { padding: var(--s4); color: #fff; background: #000; text-align: center; font-size: 13px; line-height: 1.4;
                 padding-bottom: calc(var(--s4) + env(safe-area-inset-bottom, 0px)); }
.scanner-piede .esito { font-family: var(--mono); font-size: 15px; font-weight: 700; margin-top: var(--s2); }

/* mirino: fascia orizzontale, che e la forma di un codice a barre */
.mirino { position: absolute; left: 8%; right: 8%; top: 50%; transform: translateY(-50%);
          height: 130px; border: 2px solid rgba(255,255,255,0.9); border-radius: var(--r-md);
          box-shadow: 0 0 0 100vmax rgba(0,0,0,0.45); pointer-events: none; }
.mirino::after { content: ""; position: absolute; left: 6px; right: 6px; top: 50%;
                 height: 2px; background: oklch(var(--a)); opacity: 0.9; }
.scanner-vista { position: relative; flex: 1; display: flex; overflow: hidden; }

/* messaggio quando la fotocamera non e utilizzabile */
.scanner-avviso { flex: 1; display: grid; place-items: center; padding: var(--s5); text-align: center; color: #fff; }
.scanner-avviso .titolo { font-size: 17px; font-weight: 650; margin-bottom: var(--s3); }
.scanner-avviso p { color: rgba(255,255,255,0.82); font-size: 14px; line-height: 1.5; margin: 0 auto var(--s3); max-width: 36ch; }
.scanner-avviso b { color: #fff; }
.scanner-avviso code { background: rgba(255,255,255,0.15); color: #fff; }

/* EAN mostrato solo quando la ricerca lo ha trovato */
/* Colore d'azione, come la pastiglia dei dati locali: deve saltare all'occhio
   fra le righe, perche' segnala che quella cifra non e' il listino. */
.art-mio { display: inline-block; margin-left: var(--s1); padding: 1px 6px;
           border-radius: var(--r-full); background: oklch(var(--a)); color: oklch(var(--ac));
           font-size: 10px; font-weight: 700; white-space: nowrap; vertical-align: 1px; }

/* Quanto ne compra di solito. Tono neutro, non d azione: e un dato, non
   un avviso — a differenza di "prezzo tuo" che segnala una cifra diversa. */
.art-gia { display: inline-block; margin-left: var(--s1); padding: 1px 6px;
           border-radius: var(--r-full); background: oklch(var(--bc) / 0.10);
           color: oklch(var(--bc) / 0.75); font-size: 10px; font-weight: 650;
           white-space: nowrap; vertical-align: 1px; }

.art-ean { font-size: 10px; font-family: var(--mono); font-weight: 700;
           background: oklch(var(--a) / 0.16); color: oklch(var(--bc));
           border-radius: var(--r-sm); padding: 1px 5px; margin-left: var(--s1); }

.chip-fila { display: flex; gap: var(--s2); overflow-x: auto; padding: var(--s3) var(--s3) var(--s2); scrollbar-width: none; flex: none; background: oklch(var(--b2)); }
.chip-fila::-webkit-scrollbar { display: none; }
.chip {
  flex: none; height: 40px; display: inline-flex; align-items: center; padding: 0 var(--s4);
  border-radius: var(--r-full); background: oklch(var(--b1));
  border: 1px solid oklch(var(--bc) / 0.12);
  font-size: 13px; font-weight: 550; white-space: nowrap; cursor: pointer; color: oklch(var(--bc));
}
.chip[aria-pressed="true"] { background: oklch(var(--p)); color: oklch(var(--pc)); border-color: transparent; }

.lista { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 var(--s3) var(--s4); }
.lista-interna { border-radius: var(--r-md); overflow: hidden; }

/* ---------- RIGA ARTICOLO ----------
   Due colonne: l'immagine occupa tutta l'altezza della riga, il resto sta a destra.
   Il formato verticale 3:4 e quello delle foto fornitore (450x600). */
.art { display: grid; grid-template-columns: 72px 1fr; gap: var(--s2); align-items: stretch;
       padding: var(--s2); background: oklch(var(--b1)); box-shadow: 0 1px 0 oklch(var(--bc) / 0.07); }
.art:last-child { box-shadow: none; }
.art.attiva { background: oklch(var(--a) / 0.07); }
.art-corpo { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; justify-content: center; }
/* Un solo campo quantita per riga: il pulsante decide a quale unita applicarlo.
   Due campi separati occupavano spazio per dire la stessa cosa. */
/* minmax(0,1fr) e non 1fr: con 1fr le due colonne prendono la larghezza del
   proprio contenuto minimo e i pulsanti risultano disuguali (57 contro 61). */
/* ⚠️ Larghezza dello spin scritta a mano invece di auto. "auto" vuol dire
   "da min-content a max-content", e il max-content di una griglia annidata
   Safari lo calcola guardando la dimensione intrinseca dell input invece
   delle colonne fisse: la colonna si gonfia e schiaccia i due pulsanti.
   104 = 30 + 38 + 30 + 3 + 3, cioe esattamente quello che .spin dichiara. */
.art-azioni { display: grid; grid-template-columns: 104px minmax(0, 1fr) minmax(0, 1fr);
              gap: 6px; align-items: center; }

/* Sfondo bianco, non grigio: le foto fornitore hanno tutte fondo bianco, e con
   una tessera grigia le proporzioni diverse lasciavano strisce visibili ai lati. */
/* ⚠️ height fissa, non min-height. Con l'altezza automatica l'immagine
   chiedeva il 100% al contenitore e il contenitore lo chiedeva all'immagine:
   la dipendenza circolare si risolveva sull'altezza naturale della foto, e una
   lattina slim a 72px di larghezza diventava 216px alti trascinandosi dietro
   la riga. Righe da 112 e da 209 nella stessa lista. */
/* Un filo di margine interno: le foto fornitore hanno quantita di bianco
   molto diverse, e quelle ritagliate strette sembravano "ingrandite" accanto
   alle altre perche arrivavano a filo del bordo. Non pareggia i soggetti —
   quello dipende dagli originali — ma toglie l effetto di scoppiare fuori. */
.art-foto { width: 72px; height: 96px; align-self: center; padding: 5px;
            border-radius: var(--r-md); background: #fff;
            display: grid; place-items: center; overflow: hidden; }
.art-foto img { max-width: 100%; max-height: 100%; width: auto; height: auto;
                object-fit: contain; display: block; }
/* il segnaposto sta su tessera bianca: serve un grigio esplicito, non l'alpha del testo */
.art-foto .segnaposto { color: #8b847b; opacity: 1; }

.art-testo { min-width: 0; }
/* Due righe sempre, non "fino a due": cosi ogni riga della lista e alta
   uguale e lo scorrimento non sobbalza. Chi vuole la descrizione intera
   tocca la foto e apre la scheda. */
.art-desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
            overflow: hidden; min-height: 2.5em;
            font-size: 13px; font-weight: 550; line-height: 1.25;
            display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.art-riga2 { display: flex; align-items: baseline; gap: var(--s1); margin-top: 2px; min-width: 0; }
.art-prezzo { font-size: 15px; font-weight: 700; white-space: nowrap; }
.art-prezzo .val { font-variant-numeric: tabular-nums; }
/* alpha 0.68/0.70: sotto queste soglie il testo piccolo non arriva a WCAG AA */
.art-prezzo .cur { font-size: 10px; font-weight: 500; color: oklch(var(--bc) / 0.68); margin-right: 3px; }
.art-meta { font-size: 11px; color: oklch(var(--bc) / 0.70); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- CONTROLLO D'ORDINE ----------
   Un campo quantita condiviso + un pulsante per unita.
   Il pulsante ordina quel numero di colli o di palette. */
/* Spin: − campo + . I tasti sono 34px visibili ma l'area di tocco e estesa
   in verticale a tutta la banda dallo pseudo-elemento. */
.spin { display: grid; grid-template-columns: 30px 38px 30px; gap: 3px; align-items: center; }
.spin button { position: relative; height: 42px; border: none; border-radius: var(--r-md);
               background: oklch(var(--b3)); color: oklch(var(--bc));
               font-size: 20px; font-weight: 600; line-height: 1; cursor: pointer;
               display: grid; place-items: center; transition: transform 0.08s ease; }
.spin button::before { content: ""; position: absolute; inset: -3px 0; }
.spin button:active { transform: scale(0.92); }
.spin button:disabled { opacity: 0.35; cursor: default; }

/* ⚠️ min-width: 0 non e' decorativo. In una griglia un <input type="number">
   ha una larghezza minima automatica pari alla sua dimensione intrinseca —
   una ventina di caratteri — e Safari la rispetta lasciandolo sbordare dalla
   colonna da 38px: su iPhone il tasto meno finiva sopra il campo e il piu'
   andava a capo sotto il pulsante COLLO. Chrome lo comprimeva e il difetto
   restava invisibile in sviluppo. */
.uni-qta { width: 100%; min-width: 0; height: 42px; text-align: center; border-radius: var(--r-md);
           border: 1px solid oklch(var(--bc) / 0.25); background: oklch(var(--b1)); color: oklch(var(--bc));
           font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 0; }
.uni-qta::-webkit-outer-spin-button, .uni-qta::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.uni-qta { -moz-appearance: textfield; appearance: textfield; }

.uni-btn { position: relative; height: 42px; border: none; border-radius: var(--r-md); cursor: pointer;
           background: oklch(var(--a)); color: oklch(var(--ac));
           display: flex; flex-direction: column; justify-content: center; gap: 1px;
           padding: 0 6px; text-align: left;
           transition: transform 0.08s ease; }
.uni-btn:active { transform: scale(0.96); }
.uni-btn:disabled { cursor: default; opacity: 0.35; }
.uni-btn .n { font-size: 11px; font-weight: 700; letter-spacing: 0.02em; line-height: 1.1;
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.uni-btn .d { font-size: 10px; line-height: 1.1; opacity: 0.9; font-variant-numeric: tabular-nums;
              white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* pastiglia con la quantita gia in ordine: senza, lo stato dell'ordine
   non sarebbe leggibile dalla lista */
.uni-btn .gia { position: absolute; top: -6px; right: -4px;
                min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--r-full);
                background: oklch(var(--b1)); color: oklch(var(--bc));
                border: 2px solid oklch(var(--a));
                font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
                display: grid; place-items: center; }

.unita { display: grid; grid-template-columns: 1fr auto; gap: var(--s3); align-items: center;
         padding: var(--s3); background: oklch(var(--b1)); box-shadow: 0 1px 0 oklch(var(--bc) / 0.07); }
.unita:first-child { border-radius: var(--r-md) var(--r-md) 0 0; }
.unita:last-child  { border-radius: 0 0 var(--r-md) var(--r-md); box-shadow: none; }
.unita.scelta { background: oklch(var(--a) / 0.07); }
.unita.non-disponibile { opacity: 0.5; }
.unita-nome { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.unita-pz { font-size: 12px; color: oklch(var(--bc) / 0.70); margin-top: 1px; }
.unita-prezzo { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 2px; }
.unita-prezzo .cur { font-size: 10px; font-weight: 500; color: oklch(var(--bc) / 0.68); margin-right: 4px; }

/* campo quantita digitabile: per 40 colli nessuno preme "+" quaranta volte */
.qta-campo { width: 56px; height: 40px; text-align: center; border-radius: var(--r-md);
             border: 1px solid oklch(var(--bc) / 0.22); background: oklch(var(--b1)); color: oklch(var(--bc));
             font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.qta-campo::-webkit-outer-spin-button, .qta-campo::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qta-campo { -moz-appearance: textfield; appearance: textfield; }

/* Riga del riepilogo su due livelli: sopra cosa e, sotto quanto e quanto costa.
   Su una riga sola, spin + totale + cestino lasciavano 130px alla descrizione. */
.riga-ordine { display: grid; grid-template-columns: 60px 1fr; gap: var(--s2); align-items: stretch;
               padding: var(--s3); background: oklch(var(--b1)); box-shadow: 0 1px 0 oklch(var(--bc) / 0.07); }
.riga-ordine:last-child { box-shadow: none; }
.riga-corpo { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; justify-content: center; }
/* Nel riepilogo la foto e piu piccola che in lista (60 contro 72): qui serve a
   riconoscere quello che si e gia scelto, non a leggere l'etichetta, e i 12px
   recuperati sono esattamente quelli che mancavano all'importo. */
.riga-ordine .art-foto { width: 60px; min-height: 80px; }
.riga-desc { font-size: 13px; font-weight: 550; line-height: 1.25; }
.riga-dettaglio { font-size: 11px; color: oklch(var(--bc) / 0.70); margin-top: 2px; }
/* minmax(0, 1fr) e non 1fr: con 1fr la colonna dell'importo prende la larghezza
   del proprio contenuto e la riga sborda. A 375px non c'e margine. */
.riga-basso { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--s2); }
.riga-tot { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }

/* Spin del riepilogo: qui agisce SUBITO sull'ordine, non su un valore da confermare. */
.spin-ord { display: grid; grid-template-columns: 34px 44px 34px; gap: 3px; align-items: center; }
.spin-ord button { position: relative; height: 40px; border: none; border-radius: var(--r-md);
                   background: oklch(var(--b3)); color: oklch(var(--bc));
                   font-size: 20px; font-weight: 600; line-height: 1; cursor: pointer;
                   display: grid; place-items: center; transition: transform 0.08s ease; }
.spin-ord button::before { content: ""; position: absolute; inset: -3px 0; }
.spin-ord button:active { transform: scale(0.92); }
.spin-ord button:disabled { opacity: 0.35; cursor: default; }
/* stessa ragione di .uni-qta: senza min-width: 0 il campo sborda su Safari */
.qta-ord { width: 100%; min-width: 0; height: 40px; text-align: center; border-radius: var(--r-md);
           border: 1px solid oklch(var(--bc) / 0.25); background: oklch(var(--b1)); color: oklch(var(--bc));
           font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 0; }
.qta-ord::-webkit-outer-spin-button, .qta-ord::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qta-ord { -moz-appearance: textfield; appearance: textfield; }

/* Il cestino e l'unico modo di togliere una riga: lo spin si ferma a 1,
   cosi non si cancella un articolo premendo "meno" una volta di troppo. */
.cestino { width: 40px; height: 40px; flex: none; border: none; border-radius: var(--r-md);
           background: oklch(var(--er) / 0.10); color: oklch(var(--er));
           cursor: pointer; display: grid; place-items: center; transition: transform 0.08s ease; }
.cestino:active { transform: scale(0.92); }

/* ---------- STEPPER: 40px visibili, 48px toccabili ---------- */
.stepper { display: flex; align-items: center; gap: var(--s1); }
.stepper button {
  position: relative; width: 40px; height: 40px; border: none; border-radius: var(--r-md);
  font-size: 20px; font-weight: 600; line-height: 1; cursor: pointer; display: grid; place-items: center;
  /* solo transform: una transition su background-color da var() si blocca al cambio tema */
  transition: transform 0.08s ease;
}
.stepper button::before { content: ""; position: absolute; inset: -4px; }
.stepper button:active { transform: scale(0.92); }
.stepper .meno { background: oklch(var(--b3)); color: oklch(var(--bc)); }
.stepper .piu  { background: oklch(var(--a)); color: oklch(var(--ac)); }
.stepper .qta  { min-width: 30px; text-align: center; font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.stepper.spento .qta, .stepper.spento .meno { display: none; }

/* ---------- BARRA CARRELLO ---------- */
.carrello { display: flex; align-items: center; gap: var(--s3); background: oklch(var(--p)); color: oklch(var(--pc));
            padding: var(--s3) var(--s4); box-shadow: 0 -2px 16px oklch(var(--bc) / 0.10); flex: none;
            padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom, 0px)); }
.carrello[hidden] { display: none; }

/* Invito all'accesso: stessa scatola del carrello, contenuto diverso.
   Riusare .carrello significa non dover ritoccare altezza, ombra e
   posizionamento in due posti quando cambia la barra. */
.inv-titolo { font-size: 15px; font-weight: 700; line-height: 1.2; }
.inv-sotto  { font-size: 11px; opacity: 0.82; line-height: 1.25; margin-top: 2px; }

/* Al posto del prezzo, in lista e nella scheda */
.art-meta.riservato { font-style: italic; }
.sc-riservato { font-size: 13px; font-style: italic; line-height: 1.35;
                padding: 6px 0 2px; color: oklch(var(--bc) / 0.7); }
.uni-btn.vetrina { background: oklch(var(--a)); color: oklch(var(--ac)); }
/* senza spin restano solo i due pulsanti, che si prendono la riga intera */
.art-azioni.vetrina { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
/* .spin e' display:grid, e senza questa riga l'attributo hidden non basta */
.spin[hidden] { display: none; }
/* In vetrina i due pulsanti non sono comandi ma etichette: dicono com'e'
   confezionato l'articolo. Con l'aspetto pieno erano la cosa piu' vistosa
   della riga, e invitavano a premere qualcosa che non fa niente. */
.art-azioni.vetrina .uni-btn,
.uni-btn.largo:disabled {
  background: transparent;
  border: 1px solid oklch(var(--bc) / 0.22);
  color: oklch(var(--bc) / 0.72);
  opacity: 1;
}
.carrello-info { flex: 1; min-width: 0; }
.carrello-righe { font-size: 11px; color: oklch(var(--pc) / 0.8); }
.carrello-tot { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.carrello-btn { height: var(--tocco); padding: 0 var(--s5); border: none; border-radius: var(--r-md);
                background: oklch(var(--a)); color: oklch(var(--ac)); font-size: 15px; font-weight: 700;
                cursor: pointer; white-space: nowrap; }

/* ---------- MINIMO D'ORDINE PER GRUPPO ----------
   Due commande separate, ognuna con un minimo di CHF 2000 imponibile.
   La barra e larga quanto le lascia il contenuto: minmax(0,1fr), non 1fr,
   altrimenti prende la larghezza del proprio contenuto e schiaccia il resto. */
.gr-riga { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
           align-items: center; gap: var(--s2); font-size: 11px; }
.gr-nome { font-weight: 650; white-space: nowrap; }
.gr-imp  { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; white-space: nowrap; }
.min-barra { height: 4px; border-radius: var(--r-full); overflow: hidden;
             background: oklch(var(--bc) / 0.12); }
/* Si transisce solo la larghezza: una transition su background-color preso da
   una var() lascia Chromium bloccato su un colore interpolato al cambio tema. */
.min-barra > i { display: block; height: 100%; border-radius: inherit;
                 background: oklch(var(--p)); transition: width 0.18s ease; }
.gr-titolo { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap;
             padding: var(--s3) var(--s4) var(--s2); font-size: 12px; font-weight: 700;
             text-transform: uppercase; letter-spacing: 0.04em; color: oklch(var(--bc));
             border-bottom: 1px solid oklch(var(--bc) / 0.10); }
.gr-titolo span { text-transform: none; letter-spacing: 0; font-weight: 400;
                  font-size: 11px; color: oklch(var(--bc) / 0.65); }
.gr-piede { padding-bottom: var(--s3); margin-bottom: var(--s3);
            border-bottom: 1px solid oklch(var(--bc) / 0.10); }
.gr-piede:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: none; }
.gr-piede .gr-riga { margin-bottom: var(--s3); font-size: 12px; }
.gr-piede .invia { margin-top: var(--s2); }
.min-nota { font-size: 11px; color: oklch(var(--bc) / 0.7); margin: var(--s2) 0; }

/* ---------- MODULO D'INVIO ----------
   Campi alti quanto il bersaglio di tocco: si compila in piedi, in magazzino,
   spesso con una mano sola. */
.modulo { padding: var(--s4); display: grid; gap: var(--s3); }
.modulo h3 { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
             color: oklch(var(--bc) / 0.6); margin-top: var(--s2); }
.modulo h3:first-of-type { margin-top: 0; }

.mod-testa { padding: var(--s3); border-radius: var(--r-md); font-size: 13px; font-weight: 650;
             background: oklch(var(--p) / 0.10); color: oklch(var(--bc));
             font-variant-numeric: tabular-nums; }

.campo { display: grid; gap: 3px; min-width: 0; }
.campo > span { font-size: 11px; font-weight: 600; color: oklch(var(--bc) / 0.72); }
.campo input, .campo select, .campo textarea {
  width: 100%; min-width: 0; height: var(--tocco); padding: 0 var(--s3);
  border: 1px solid oklch(var(--bc) / 0.20); border-radius: var(--r-md);
  background: oklch(var(--b1)); color: oklch(var(--bc)); font-size: 15px; }
.campo textarea { height: auto; padding: var(--s2) var(--s3); line-height: 1.35; resize: vertical; }
.campo select { cursor: pointer; }
.campo input:focus, .campo select:focus, .campo textarea:focus {
  outline: 2px solid oklch(var(--p)); outline-offset: -1px; border-color: transparent; }
/* Il campo mancante si segnala col bordo, non con un testo sotto: dieci campi
   con dieci messaggi diventano illeggibili. Il perche' sta una volta in fondo. */
.campo.male input, .campo.male select, .campo.male textarea {
  border-color: oklch(var(--er)); background: oklch(var(--er) / 0.06); }

/* minmax(0, 1fr): senza, il campo piu lungo detta la larghezza e la coppia sborda */
.campo-coppia { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s2); }
.campo-coppia.npa { grid-template-columns: 92px minmax(0, 1fr); }

.spunta { display: flex; align-items: center; gap: var(--s2); font-size: 13px; cursor: pointer;
          min-height: var(--tocco); }
.spunta input { width: 22px; height: 22px; flex: none; accent-color: oklch(var(--p)); cursor: pointer; }

.mod-esito { padding: var(--s3); border-radius: var(--r-md); font-size: 13px; line-height: 1.35;
             background: oklch(var(--bc) / 0.06); }
.mod-esito.male { background: oklch(var(--er) / 0.10); border-left: 3px solid oklch(var(--er)); }
.mod-esito.bene { background: oklch(var(--p) / 0.12); border-left: 3px solid oklch(var(--p)); font-weight: 650; }
.gr-conti { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3);
            margin: var(--s2) 0; font-size: 11px; color: oklch(var(--bc) / 0.7); }
.gr-conti .n { font-size: 15px; font-weight: 700; color: oklch(var(--bc));
               font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- STATI ---------- */
.fine { text-align: center; padding: var(--s4) 0 var(--s2); font-size: 11px;
        color: oklch(var(--bc) / 0.55); font-variant-numeric: tabular-nums; }
.vuoto { text-align: center; padding: var(--s6) var(--s4); color: oklch(var(--bc) / 0.65); }
.vuoto-titolo { font-weight: 650; color: oklch(var(--bc)); margin-bottom: var(--s1); }
.errore { margin: var(--s4); padding: var(--s4); border-radius: var(--r-md);
          background: oklch(var(--er) / 0.10); border-left: 3px solid oklch(var(--er)); font-size: 13px; }
.scheletro { background: linear-gradient(90deg, oklch(var(--b3)) 25%, oklch(var(--b2)) 50%, oklch(var(--b3)) 75%);
             background-size: 200% 100%; animation: scorri 1.4s infinite; border-radius: var(--r-sm); }
@keyframes scorri { from { background-position: 200% 0 } to { background-position: -200% 0 } }
@media (prefers-reduced-motion: reduce) {
  .scheletro { animation: none; }
  .stepper button { transition: none; }
}

/* ---------- PANNELLO ORDINE ---------- */
.velo { position: fixed; inset: 0; background: oklch(0% 0 0 / 0.45); z-index: 50; }

/* ---------- SCHEDA ARTICOLO ----------
   Non e' un foglio dal basso come il carrello: copre lo schermo lasciando
   scoperta la testata, cosi si vede sempre dove si e'. Si apre toccando la
   foto, che e' l'unica parte della riga che non ordina niente. */
/* top e bottom li mette il JS: sopra resta scoperta la testata, sotto la
   barra del carrello, cosi aggiungendo dalla scheda il totale si aggiorna
   sotto gli occhi invece che dietro un pannello. */
.scheda { position: fixed; left: 0; right: 0; bottom: 0; top: 0; z-index: 51;
          display: flex; flex-direction: column;
          background: oklch(var(--b1)); }
.scheda[hidden] { display: none; }
.scheda-testata { display: flex; align-items: center; gap: var(--s3); flex: none;
                  padding: var(--s3) var(--s4); border-bottom: 1px solid oklch(var(--bc) / 0.10); }
.scheda-nome { flex: 1; min-width: 0; font-size: 15px; font-weight: 650; line-height: 1.3; }

/* Due colonne anche a 375px. La foto prende quel che resta, i dati stanno in
   168px: e' la larghezza minima perche' un pulsante impilato resti leggibile,
   e cosi alla foto ne restano oltre 160 invece dei 72 della lista. */
.scheda-corpo { flex: 1; overflow-y: auto; display: grid;
                grid-template-columns: minmax(0, 1fr) 168px;
                gap: var(--s3); padding: var(--s4); align-content: start; }

/* width esplicita: con la sola aspect-ratio la tessera si autodimensionava
   sul contenuto (72px) invece di riempire la colonna della griglia. */
.scheda-foto { width: 100%; align-self: start; background: #fff; padding: var(--s3);
               border-radius: var(--r-md); overflow: hidden;
               display: flex; align-items: center; justify-content: center;
               aspect-ratio: 3 / 4; }
/* max-width/max-height invece di width/height 100%: con questi ultimi
   l'immagine chiede l'altezza al contenitore e il contenitore la chiede
   all'immagine. L'altezza la detta solo l'aspect-ratio della tessera. */
.scheda-foto img { max-width: 100%; max-height: 100%; width: auto; height: auto;
                   object-fit: contain; display: block; }
.scheda-foto .segnaposto { color: #8b847b; opacity: 1; width: 40px; height: 40px; }

.scheda-dati { min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }

.sc-prezzo { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px; }
.sc-prezzo .cur { font-size: 11px; font-weight: 500; color: oklch(var(--bc) / 0.68); }
.sc-prezzo .val { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums;
                  line-height: 1; letter-spacing: -0.02em; }
.sc-prezzo .um  { font-size: 11px; color: oklch(var(--bc) / 0.70); }

.sc-voci { display: grid; gap: 5px; }
.sc-voce { display: flex; justify-content: space-between; gap: var(--s2); font-size: 11px;
           line-height: 1.3; border-bottom: 1px solid oklch(var(--bc) / 0.07); padding-bottom: 4px; }
.sc-voce span:first-child { color: oklch(var(--bc) / 0.60); white-space: nowrap; }
.sc-voce span:last-child { text-align: right; font-weight: 600; min-width: 0;
                           overflow-wrap: anywhere; }

/* Pulsanti impilati, non affiancati: e' la scelta che libera larghezza per la
   foto. Uno sotto l'altro possono essere piu' bassi e portare unita, pezzi e
   prezzo su una riga sola. */
.sc-azioni { display: grid; gap: var(--s2); margin-top: auto; }
.sc-azioni .spin { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); }
.uni-btn.largo { height: 46px; flex-direction: column; gap: 1px; padding: 0 var(--s2); }
.uni-btn.largo .d { opacity: 0.85; }

@media (min-width: 600px) {
  /* con lo spazio, la foto diventa il pezzo forte: e' l'unico posto del
     portale dove guardarla per bene ha senso */
  .scheda-corpo { grid-template-columns: minmax(0, 1fr) 260px; gap: var(--s5); padding: var(--s5); }
  .scheda-nome { font-size: 18px; }
  .sc-voce { font-size: 12px; }
  .uni-btn.largo { height: 52px; }
}
@media (min-width: 900px) {
  .scheda { left: 50%; transform: translateX(-50%); max-width: 860px; }
}
.velo[hidden], .foglio[hidden] { display: none; }
.foglio { position: fixed; left: 0; right: 0; bottom: 0; z-index: 51; max-height: 82dvh;
          background: oklch(var(--b2)); border-radius: var(--r-lg) var(--r-lg) 0 0;
          display: flex; flex-direction: column; }
.foglio-testata { display: flex; align-items: center; gap: var(--s3); padding: var(--s4); flex: none;
                  border-bottom: 1px solid oklch(var(--bc) / 0.10); }
.foglio-testata h2 { margin: 0; font-size: 17px; flex: 1; }
.chiudi { width: 40px; height: 40px; border: none; background: oklch(var(--b3)); color: oklch(var(--bc));
          border-radius: var(--r-full); font-size: 20px; cursor: pointer; }
.foglio-corpo { overflow-y: auto; padding: var(--s3); }
.foglio-piede { flex: none; padding: var(--s4); border-top: 1px solid oklch(var(--bc) / 0.10); background: oklch(var(--b1));
                padding-bottom: calc(var(--s4) + env(safe-area-inset-bottom, 0px)); }
.somma { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: var(--s2); }
.somma.totale { font-size: 17px; font-weight: 700; margin-bottom: var(--s3); }
.somma .n { font-variant-numeric: tabular-nums; }
.invia { width: 100%; height: var(--tocco); border: none; border-radius: var(--r-md);
         background: oklch(var(--a)); color: oklch(var(--ac)); font-size: 15px; font-weight: 700; cursor: pointer; }
.invia:disabled { opacity: 0.45; cursor: default; }
.invia.secondario { background: transparent; color: oklch(var(--bc) / 0.75);
                    border: 1px solid oklch(var(--bc) / 0.25); }
.avviso { font-size: 11px; color: oklch(var(--bc) / 0.7); text-align: center; margin-top: var(--s2); }

/* ---------- SELETTORE TEMA ---------- */
.temi { display: flex; gap: var(--s1); }
.tema-pallino { width: 26px; height: 26px; border-radius: var(--r-full); cursor: pointer;
                border: 2px solid oklch(var(--pc) / 0.35); padding: 0; }
.tema-pallino[aria-pressed="true"] { border-color: oklch(var(--pc)); }

/* ---------- DESKTOP: piu respiro, come vetrina ---------- */
/* Dai 600px in su lo spazio c'e davvero: immagine piu grande, spin piu comodo,
   e pulsanti a larghezza fissa — stirati a tutta riga diventano assurdi. */
@media (min-width: 600px) {
  .art { grid-template-columns: 104px 1fr; }
  .art-foto { width: 104px; height: 116px; }
  .art-desc { font-size: 14px; }
  .art-prezzo { font-size: 16px; }
  /* qui .spin diventa 40+48+40+4+4 = 136 */
  .art-azioni { grid-template-columns: 136px 170px 170px; justify-content: start; gap: var(--s2); }
  .spin { grid-template-columns: 40px 48px 40px; gap: var(--s1); }
}

@media (min-width: 900px) {
  .app { max-width: 860px; margin: 0 auto; box-shadow: 0 0 60px oklch(var(--bc) / 0.10); }
  .testata { padding: var(--s5) var(--s5) var(--s3); }
  .logo img { height: 30px; }
  .chip-fila { padding: var(--s3) var(--s5) var(--s2); flex-wrap: wrap; overflow: visible; }
  .lista { padding: 0 var(--s5) var(--s5); }
  .art { padding: var(--s3); gap: var(--s3); }
  .carrello { padding: var(--s4) var(--s5); }
  .foglio { max-width: 860px; margin: 0 auto; }
}
