/* ============================================================
   TripsBack — Design system "Executive"
   Corporate-fintech: fiducia, precisione, efficienza.
   Caricato DOPO global.css: qui vivono i token e i componenti nuovi (.tb-*).
   Le classi con hook JS della barra di ricerca (.js-*, .tb-search-*) sono
   mantenute: cambia solo lo stile, non il contratto col JavaScript.
   ============================================================ */

/* Il contratto di questo foglio sta in docs/design/DESIGN.md. Se cambi un token
   qui, cambia anche la' — o il documento comincia a mentire. */

:root {
    /* Colori */
    --tb-ink:          #0E1A33;   /* navy: titoli e testo */
    --tb-ink-hover:    #1C2C4E;   /* navy in hover — bianco sopra: 12.9:1 */
    --tb-ink-soft:     #566079;   /* testo secondario (>=4.5:1 su bianco) */
    --tb-bg:           #FFFFFF;
    --tb-panel:        #F2F5FA;   /* superfici fredde */
    --tb-panel-2:      #E8EDF6;
    --tb-blue:         #2455FF;   /* azione primaria — bianco sopra: 5.50:1 */
    --tb-blue-deep:    #163FCC;   /* hover  — bianco sopra: 8.02:1 */
    --tb-blue-press:   #0F2E99;   /* active — bianco sopra: 11.22:1 */
    --tb-blue-soft:    #EAF0FF;
    --tb-emerald:      #0E9E6E;   /* cashback (riempimenti) */
    --tb-emerald-ink:  #0B7E58;   /* cashback come TESTO su bianco */
    --tb-emerald-soft: #E4F6EF;
    --tb-line:         #E2E7F0;   /* e' IL FILETTO che separa le superfici, non l'ombra */

    /* Stati. Le coppie erano gia' in uso, scritte a mano: #FCE8E6/#A4271B compariva
       7 volte fra auth, account, payout e checkout senza avere un nome. Rapporti
       CALCOLATI: danger-ink su danger-soft 6.18:1, amber-ink su amber-soft 5.43:1. */
    --tb-danger:       #C0392B;   /* icone e bordi su fondo chiaro */
    --tb-danger-ink:   #A4271B;   /* testo d'errore */
    --tb-danger-soft:  #FCE8E6;
    --tb-amber-ink:    #8A5A00;   /* testo "in attesa" */
    --tb-amber-soft:   #FFF4E0;
    /* L'oro #E2A400 su bianco sta a 2.20:1: le stelle sparivano a chi ha poca vista,
       ed e' l'unico posto in cui si legge la categoria. Questo tiene la tinta
       (40deg contro 44) e sale a 5.10:1. */
    --tb-star:         #966400;

    /* Colori per le SUPERFICI SCURE (.tb-slab, hero della home).
       Sul navy --tb-danger sta a 3.18:1 e non regge il testo: serve la variante
       luminosa. Rapporti CALCOLATI su --tb-ink #0E1A33:
       emerald-bright 9.45:1, danger-bright 7.77:1, on-dark 11.16:1, bianco 17.29:1. */
    --tb-emerald-bright: #31D992;
    --tb-danger-bright:  #FF8E80;
    --tb-on-dark:        #C7D0E2;   /* testo secondario su navy */
    --tb-on-dark-line:   rgb(255 255 255 / 12%);

    /* Raggi */
    --tb-r-card: 12px;
    --tb-r-btn:  10px;
    --tb-r-pill: 999px;
    --tb-r-slab: 16px;

    /* --- ELEVAZIONE: un'ombra sola. ---------------------------------------
       Prima ce n'erano tre (sm/md/lg) usate 33 volte, e sette card diverse
       portavano ciascuna la sua ombrellina. Quando tutto galleggia un po',
       niente galleggia: il senso di "premium" nasce dal contrasto fra piatto
       e sollevato, non dalla quantita' d'ombra.
       REGOLA: piatto di default, a separare e' --tb-line. L'ombra e' riservata
       a cio' che sta DAVVERO sopra al piano (dropdown, slab, sticky, pin della
       mappa, barra di ricerca) e al sollevamento in hover delle card cliccabili. */
    --tb-shadow: 0 1px 2px rgb(14 26 51 / 5%), 0 10px 24px -14px rgb(14 26 51 / 22%);
    --tb-scrim:  rgb(14 26 51 / 55%);

    /* Movimento: solo ease-out esponenziali. Niente rimbalzi, niente elastico. */
    --tb-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --tb-dur-fast: 140ms;
    --tb-dur:      200ms;
    /* Il passo lungo e la curva del VIAGGIO: li usa solo il pannello di ricerca,
       l'unico oggetto del sito che si sposta davvero da un punto a un altro.

       --tb-ease (una expo) qui non andava: e' cosi' sbilanciata in avanti che
       copriva meta' strada nei primi 45ms, e il pannello sembrava SCATTARE al
       suo posto invece di andarci. --tb-glide distribuisce il movimento —
       a un terzo del tempo e' a poco piu' di meta' strada — e il pannello
       PLANA. Nessun rimbalzo: la curva e' monotona, non supera mai l'arrivo. */
    --tb-glide:    cubic-bezier(0.32, 0.72, 0, 1);
    --tb-dur-slow: 380ms;

    /* Spaziatura: base 4px. */
    --tb-s-1: 4px;   --tb-s-2: 8px;   --tb-s-3: 12px;  --tb-s-4: 16px;  --tb-s-5: 20px;
    --tb-s-6: 24px;  --tb-s-7: 32px;  --tb-s-8: 48px;  --tb-s-9: 64px;

    /* --- TIPOGRAFIA: per RUOLO, non per taglia. ---------------------------
       La scala xs/sm/md/lg/xl/2xl e' t-shirt sizing, e il difetto non e'
       estetico ma operativo: quando un token si chiama "grande" invece di
       "titolo di sezione", nessuno sa quando usarlo — ed e' per questo che nel
       CSS sono scappati 10px, 11px, 15px, 0.82rem, 1.06rem, 2.6rem...

       Uso:  font: var(--tb-t-body);   (peso  dimensione/interlinea  famiglia)

       DUE TRAPPOLE:
       1. lo shorthand `font:` AZZERA font-variant. `font-variant-numeric:
          tabular-nums` va dichiarato DOPO, mai prima, o le cifre tabulari
          spariscono senza un errore.
       2. `letter-spacing` NON fa parte dello shorthand: sta nei --tb-tr-*. */
    --tb-font: "Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

    --tb-t-hero-figure:    800 3.5rem/1     var(--tb-font);  /* 56 — IL SALDO. L'unico picco del prodotto. */
    --tb-t-hero-figure-sm: 800 2.5rem/1     var(--tb-font);  /* 40 — sotto i 620px */
    --tb-t-figure:         800 1.375rem/1.2 var(--tb-font);  /* 22 — cifre della striscia */
    --tb-t-page-title:     800 1.75rem/1.15 var(--tb-font);  /* 28 — h1 d'app */
    --tb-t-section:        700 1.375rem/1.2 var(--tb-font);  /* 22 */
    --tb-t-card-title:     700 1.125rem/1.3 var(--tb-font);  /* 18 */
    --tb-t-body:           400 1rem/1.55    var(--tb-font);  /* 16 */
    --tb-t-body-strong:    600 1rem/1.55    var(--tb-font);  /* 16 */
    --tb-t-meta:           400 0.875rem/1.45 var(--tb-font); /* 14 */
    --tb-t-label:          600 0.875rem/1.3 var(--tb-font);  /* 14 — etichetta di campo */
    --tb-t-button:         600 0.875rem/1   var(--tb-font);  /* 14 */
    --tb-t-button-lg:      600 1rem/1       var(--tb-font);  /* 16 — CTA a tutta larghezza */
    --tb-t-caption:        400 0.8125rem/1.4 var(--tb-font); /* 13 */
    --tb-t-badge:          700 0.8125rem/1.3 var(--tb-font); /* 13 */
    --tb-t-micro:          700 0.6875rem/1.3 var(--tb-font); /* 11 — occhielli maiuscoli */
    /* Registro MARKETING: solo home.php. Nell'app non entra — un'app la si guarda
       sempre alla stessa distanza, quindi scala fissa e niente clamp(). */
    --tb-t-marketing-hero: 800 clamp(2rem, 5vw, 3rem)/1.05 var(--tb-font);

    --tb-tr-tight:  -0.02em;   /* titoli */
    --tb-tr-figure: -0.035em;  /* il saldo */
    --tb-tr-micro:   0.06em;   /* occhielli maiuscoli */

    /* DEPRECATI: scala per taglia. Restano perche' 191 dichiarazioni nelle pagine
       ancora li usano; si migrano a --tb-t-* pagina per pagina. Non usarli nel
       codice nuovo. */
    --tb-fs-xs:  0.8125rem;  /* 13 */
    --tb-fs-sm:  0.875rem;   /* 14 */
    --tb-fs-md:  1rem;       /* 16 */
    --tb-fs-lg:  1.125rem;   /* 18 */
    --tb-fs-xl:  1.375rem;   /* 22 */
    --tb-fs-2xl: 1.75rem;    /* 28 */
    --tb-fs-3xl: 2.25rem;    /* 36 */
    --tb-fs-4xl: 3rem;       /* 48 */

    /* --- Z-INDEX: una scala semantica, non numeri scelti a mano. -----------
       Prima erano 60, 80, 100, 120, 999, 1200, 1300, 2000, 2100: ogni valore
       nato per vincere contro quello che aveva accanto. I nomi dicono l'ordine,
       e l'ordine e' quello vero della pagina, dal basso verso l'alto.
       I <dialog> aperti con showModal() NON servono qui: il browser li mette nel
       "top layer", sopra qualunque z-index. E' anche il motivo per cui li usiamo. */
    --tb-z-sub:        60;   /* sotto-navigazione appiccicata (dettaglio) */
    --tb-z-sticky:     80;   /* barra dei filtri (ricerca) */
    --tb-z-header:    100;   /* header del sito */
    --tb-z-dropdown:  200;   /* ospiti, autocomplete: sopra l'header che li contiene */
    --tb-z-datepicker:300;   /* flatpickr: sopra i dropdown, li sovrasta quando si apre */
    --tb-z-overlay:   400;   /* mappa a schermo pieno sul telefono */
    --tb-z-overlay-top:410;  /* il bottone per chiuderla */
    --tb-z-loader:    500;   /* velo di caricamento */
    /* toastr (vendor) sta a 999999 e non lo tocchiamo: un toast deve stare sopra
       tutto, quindi il numero assurdo per una volta e' anche quello giusto. */

    --tb-header-h: 68px;
    --tb-container: 1200px;
    --tb-touch: 44px;        /* area minima toccabile: vedi DESIGN.md, "Touch target" */
}

/* --- Base ------------------------------------------------------------- */

body {
    font: var(--tb-t-body);
    color: var(--tb-ink);
    background: var(--tb-bg);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    color: var(--tb-ink);
    letter-spacing: var(--tb-tr-tight);
    text-wrap: balance;
    margin: 0 0 0.5em;
}

/* h1 = titolo di pagina d'APP, 28px. Prima era 48px/800, e ogni pagina privata lo
   disfaceva a mano (account.css lo commentava pure: "il titolo cede il palcoscenico
   al saldo"). Se ogni pagina deve annullare il default, il default e' sbagliato.
   L'unico h1 che vuole davvero essere grande e' l'hero della home: ha la sua classe. */
h1 { font: var(--tb-t-page-title); }
/* font-weight: 750 non esisteva. Il font viene chiesto a Google a pesi discreti
   (400;500;600;700;800): il browser ripiegava su 700 o lo sintetizzava. */
h2 { font: var(--tb-t-section); }
h3 { font: var(--tb-t-card-title); }
.tb-hero-title { font: var(--tb-t-marketing-hero); }

.tb-muted { color: var(--tb-ink-soft); }
.tb-container { max-width: var(--tb-container); margin: 0 auto; padding: 0 24px; }

:where(a, button, input, select, textarea):focus-visible {
    outline: 2px solid var(--tb-blue);
    outline-offset: 2px;
    border-radius: 4px;
}

/* Testo per i soli lettori di schermo.
   ATTENZIONE: e' position:absolute, quindi viene ritagliato solo dagli antenati
   che stanno fra lui e il suo blocco contenitore. Dentro un contenitore con
   overflow (una tabella che scorre) il contenitore deve avere position:relative,
   altrimenti questo 1px sfugge al ritaglio e allarga la pagina. */
.tb-sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --- Bottoni ---------------------------------------------------------- */

/* min-height, non padding: l'area toccabile cresce, il disegno no. Prima nessun
   bottone del prodotto arrivava a 44px — e i peggiori erano quelli che convertono
   (la CTA che sceglie la camera stava a ~34px). */
.tb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: var(--tb-touch);
    font: var(--tb-t-button);
    padding: 11px 16px;
    border-radius: var(--tb-r-btn);
    border: 1px solid var(--tb-line);
    background: var(--tb-bg);
    color: var(--tb-ink);
    cursor: pointer;
    text-decoration: none;
    transition: background var(--tb-dur-fast) var(--tb-ease),
                border-color var(--tb-dur-fast) var(--tb-ease),
                color var(--tb-dur-fast) var(--tb-ease);
}
.tb-btn:hover  { background: var(--tb-panel); border-color: var(--tb-panel-2); }
.tb-btn:active { transform: translateY(1px); }

.tb-btn-primary         { background: var(--tb-blue);       border-color: var(--tb-blue);       color: #fff; }
.tb-btn-primary:hover   { background: var(--tb-blue-deep);  border-color: var(--tb-blue-deep);  color: #fff; }
.tb-btn-primary:active  { background: var(--tb-blue-press); border-color: var(--tb-blue-press); color: #fff; }

.tb-btn-ink        { background: var(--tb-ink);       border-color: var(--tb-ink);       color: #fff; }
.tb-btn-ink:hover  { background: var(--tb-ink-hover); border-color: var(--tb-ink-hover); color: #fff; }

.tb-btn-ghost       { background: transparent; border-color: transparent; color: var(--tb-ink); }
.tb-btn-ghost:hover { background: var(--tb-panel); }

/* Piu' piccolo di disegno, non di bersaglio: font e padding calano, i 44px restano. */
.tb-btn-sm { padding: 8px 12px; font: var(--tb-t-caption); font-weight: 600; }

/* Lo stato disabilitato era `opacity: .55`, che su un bottone blu produce un azzurro
   slavato dal contrasto IMPREVEDIBILE. In un sistema dove i rapporti li calcoliamo
   col righello, uno stato si nomina e si colora — non si sbiadisce.
   Superficie panel-2 con testo ink-soft: 5.00:1, deterministico. */
.tb-btn[disabled],
.tb-btn[aria-disabled="true"] {
    background: var(--tb-panel-2);
    border-color: var(--tb-panel-2);
    color: var(--tb-ink-soft);
    cursor: not-allowed;
    transform: none;
}

/* --- Chip / tag ------------------------------------------------------- */

.tb-chip {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--tb-fs-xs); font-weight: 500;
    color: var(--tb-ink-soft);
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-pill);
    padding: 6px 11px;
    white-space: nowrap;
}
.tb-chip-on { color: #fff; background: var(--tb-ink); border-color: var(--tb-ink); font-weight: 600; }
.tb-chip-locked { color: var(--tb-ink-soft); background: var(--tb-panel); cursor: pointer; }

.tb-tag {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: var(--tb-fs-xs); color: var(--tb-ink-soft);
    background: var(--tb-panel); border-radius: 7px; padding: 4px 9px;
}

/* --- Card ------------------------------------------------------------- */

/* Piatta. A separarla dalla pagina e' il filetto, non un'ombrellina.
   (Era definita e non la usava nessuno: sette card riscritte a mano nelle pagine.) */
.tb-card {
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
}

/* --- Campo di testo ----------------------------------------------------
   Ne esistevano QUATTRO (.auth-input, .checkout-input, .po-input, .summary-field)
   con quattro altezze diverse (49/44/41/42px) e TRE stili di focus. Uno solo.

   Il focus e' `:focus-visible` con outline, e basta: niente ring a box-shadow.
   .auth-input usava `:focus` (quindi si accendeva anche col mouse) e ci metteva
   sopra un ring che si SOMMAVA all'outline globale — doppio anello, su una pagina
   sola. E `font: inherit` (non `font-family: inherit`): senza l'interlinea il
   campo si accorcia, ed era la causa dei 41px di .po-input. */
.tb-input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    /* Obbligatorio. Dentro una griglia (i campi data del riepilogo) un elemento ha
       min-width: auto, cioe' non scende sotto il proprio contenuto minimo — e un
       <input type="date"> a 16px e' largo. A 320px sfondava il viewport, e siccome
       body ha overflow-x: hidden non si sarebbe visto: si perdeva in silenzio. */
    min-width: 0;
    min-height: var(--tb-touch);
    padding: 11px 13px;
    font: var(--tb-t-body);
    /* Obbligatori: text-transform e letter-spacing si EREDITANO, e lo shorthand
       `font:` non li tocca. Dentro un'etichetta maiuscola (checkout) il campo
       scriverebbe in maiuscolo mentre l'utente digita. */
    text-transform: none;
    letter-spacing: normal;
    color: var(--tb-ink);
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-btn);
    transition: border-color var(--tb-dur-fast) var(--tb-ease);
}
.tb-input::placeholder     { color: var(--tb-ink-soft); }
.tb-input:hover            { border-color: var(--tb-ink-soft); }
.tb-input:focus-visible    { border-color: var(--tb-blue); }
.tb-input[aria-invalid="true"] { border-color: var(--tb-danger); }
.tb-input[disabled]        { background: var(--tb-panel); color: var(--tb-ink-soft); cursor: not-allowed; }

.tb-label { display: block; margin-bottom: 6px; font: var(--tb-t-label); color: var(--tb-ink); }
/* Il messaggio d'errore e' TESTO, non solo un bordo rosso: il colore da solo non
   e' informazione (PRODUCT.md, accessibilita'). */
.tb-field-error {
    display: none; margin-top: 6px;
    font: var(--tb-t-caption); color: var(--tb-danger-ink);
}
.tb-field-error.is-on { display: flex; align-items: center; gap: 6px; }
.tb-field-error svg { width: 14px; height: 14px; flex: none; }

/* --- STATI ------------------------------------------------------------------
   Il movimento racconta uno stato (PRODUCT.md, principio 5). Quindi prima gli
   stati esistono, poi si animano. Queste sono le primitive che mancavano: senza
   di loro, ogni animazione sarebbe decorazione.
   ---------------------------------------------------------------------------- */

/* --- Bottone occupato --------------------------------------------------
   Prima l'attesa si comunicava scambiando l'etichetta ("Attendere…"), che sposta
   il testo e non dice che qualcosa sta girando. Qui l'etichetta resta al suo
   posto e scompare, e al suo posto gira un anello: il bottone non cambia
   larghezza, quindi la pagina non salta.
   aria-busy e aria-live li mette il JS: senza, chi usa uno screen reader non
   sente nulla. */
.tb-btn.is-busy {
    position: relative;
    cursor: progress;
    pointer-events: none;
    /* Obbligatorio, e non e' ridondante con la riga sotto: l'etichetta di un bottone
       e' quasi sempre un NODO DI TESTO nudo, e visibility su ':> *' tocca solo i figli
       ELEMENTO. Senza color:transparent il testo resta visibile e si sovrappone
       all'anello che gira. */
    color: transparent;
}
.tb-btn.is-busy > * { visibility: hidden; }   /* <svg>, <span>: figli elemento */

/* OCCUPATO NON E' DISABILITATO. Sono due stati diversi e vanno letti diversi:
   "sta lavorando" e "e' morto". Ma SM.ui.busy() mette disabled sul bottone — e
   deve farlo, o un doppio invio parte col tasto Invio — e la regola del
   disabilitato gli rubava la superficie: il bottone blu diventava grigio, e
   l'utente leggeva "non funziona" invece di "la mia richiesta e' partita".
   Stessa specificita' di .tb-btn[disabled] (0,2,0), ma dichiarato dopo: vince
   l'ordine, ed e' l'unica ragione per cui questo blocco sta QUI e non piu' su. */
.tb-btn.is-busy                    { background: var(--tb-bg);   border-color: var(--tb-line); }
.tb-btn-primary.is-busy            { background: var(--tb-blue); border-color: var(--tb-blue); }
.tb-btn-ink.is-busy                { background: var(--tb-ink);  border-color: var(--tb-ink); }
.tb-slab .tb-btn-primary.is-busy   { background: var(--tb-emerald-bright); border-color: var(--tb-emerald-bright); }
.tb-dialog .tb-btn-danger.is-busy  { background: var(--tb-danger); border-color: var(--tb-danger); }

.tb-btn.is-busy::after {
    content: '';
    position: absolute; inset: 0; margin: auto;
    width: 17px; height: 17px;
    /* Il colore NON puo' essere currentColor: l'abbiamo appena reso trasparente per
       nascondere l'etichetta, e l'anello sparirebbe insieme a lei. Va detto a mano,
       una volta per variante. */
    border: 2px solid var(--tb-ink);
    border-right-color: transparent;   /* l'arco mancante e' cio' che rende visibile la rotazione */
    border-radius: 50%;
    animation: tb-spin 620ms linear infinite;
}
.tb-btn-primary.is-busy::after,
.tb-btn-ink.is-busy::after { border-color: #fff; border-right-color: transparent; }
/* Sul navy dello slab il bottone primario e' emerald con testo navy: l'anello segue. */
.tb-slab .tb-btn-primary.is-busy::after { border-color: var(--tb-ink); border-right-color: transparent; }
@keyframes tb-spin { to { transform: rotate(360deg); } }

/* TRAPPOLA: la regola globale in fondo a questo foglio spegne ogni animation con
   !important. Senza questo blocco, chi ha il movimento ridotto vedrebbe l'anello
   fermo E l'etichetta nascosta: un bottone VUOTO. Qui l'attesa torna a dirsi con
   la superficie inerte e l'etichetta al suo posto; aria-busy fa il resto per chi
   usa uno screen reader. */
@media (prefers-reduced-motion: reduce) {
    .tb-btn.is-busy > *      { visibility: visible; }
    .tb-btn.is-busy::after   { content: none; }
    .tb-btn.is-busy          { background: var(--tb-panel-2); border-color: var(--tb-panel-2); color: var(--tb-ink-soft) !important; }
}

/* --- Skeleton ----------------------------------------------------------
   La regola: skeleton al posto degli spinner in mezzo al contenuto. Uno skeleton
   dice DOVE arrivera' la roba, uno spinner dice solo "aspetta".
   Vale solo se copre un'attesa VERA: quello del dettaglio era un setTimeout(360)
   su HTML gia' completo, cioe' una bugia con l'aria di una cortesia. */
.tb-skeleton {
    position: relative;
    overflow: hidden;
    background: var(--tb-panel-2);
    border-radius: var(--tb-r-btn);
    /* Un blocco vuoto non ha altezza: senza questo lo skeleton non si vede. */
    min-height: 1em;
}
.tb-skeleton::after {
    content: '';
    position: absolute; inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgb(255 255 255 / 65%), transparent);
    animation: tb-shimmer 1.4s var(--tb-ease) infinite;
}
@keyframes tb-shimmer { to { transform: translateX(100%); } }
.tb-skeleton-text { height: 0.8em; margin: 0.28em 0; border-radius: 4px; }
.tb-skeleton-text.is-short { width: 45%; }
.tb-skeleton-text.is-mid   { width: 70%; }

/* --- Stato vuoto -------------------------------------------------------
   Uno stato vuoto insegna l'interfaccia, non annuncia il vuoto: dice cosa manca,
   perche', e da dove si comincia. Prima ce n'erano sette, tutti diversi. */
.tb-empty {
    display: grid;
    justify-items: center;
    gap: 6px;
    padding: 44px 24px;
    text-align: center;
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
}
.tb-empty-icon {
    width: 40px; height: 40px; margin-bottom: 6px;
    display: grid; place-items: center;
    color: var(--tb-ink-soft);
    background: var(--tb-panel);
    border-radius: var(--tb-r-btn);
}
.tb-empty-icon svg { width: 20px; height: 20px; }
.tb-empty h2, .tb-empty h3 { margin: 0; font: var(--tb-t-card-title); color: var(--tb-ink); }
.tb-empty p { margin: 0; max-width: 46ch; font: var(--tb-t-meta); color: var(--tb-ink-soft); text-wrap: pretty; }
.tb-empty .tb-btn { margin-top: 12px; }
/* Variante compatta: dentro una sezione che ha gia' il suo titolo. */
.tb-empty-sm { padding: 28px 24px; }
.tb-empty-sm p { font: var(--tb-t-meta); }

/* --- Avvisi ------------------------------------------------------------
   Ce n'erano sette implementazioni. Il colore non e' mai l'unica informazione:
   c'e' sempre un'icona e c'e' sempre il testo. */
.tb-alert {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 13px 15px;
    border: 1px solid transparent;
    border-radius: var(--tb-r-btn);
    font: var(--tb-t-meta);
}
.tb-alert svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.tb-alert strong { display: block; font: var(--tb-t-body-strong); font-size: var(--tb-fs-sm); }
.tb-alert p { margin: 2px 0 0; text-wrap: pretty; }

.tb-alert-info { background: var(--tb-blue-soft);    border-color: color-mix(in srgb, var(--tb-blue) 20%, transparent); color: var(--tb-ink); }
.tb-alert-info svg { color: var(--tb-blue-deep); }
.tb-alert-ok   { background: var(--tb-emerald-soft); border-color: color-mix(in srgb, var(--tb-emerald) 22%, transparent); color: var(--tb-emerald-ink); }
.tb-alert-warn { background: var(--tb-amber-soft);   border-color: color-mix(in srgb, var(--tb-amber-ink) 22%, transparent); color: var(--tb-amber-ink); }
.tb-alert-err  { background: var(--tb-danger-soft);  border-color: color-mix(in srgb, var(--tb-danger) 24%, transparent);   color: var(--tb-danger-ink); }

/* --- Badge di stato ----------------------------------------------------
   Era copiato byte per byte fra account.css e payout.css. */
.tb-badge {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 10px;
    border-radius: var(--tb-r-pill);
    font: var(--tb-t-badge);
    white-space: nowrap;
}
.tb-badge-ok      { background: var(--tb-emerald-soft); color: var(--tb-emerald-ink); }
.tb-badge-pending { background: var(--tb-amber-soft);   color: var(--tb-amber-ink); }
.tb-badge-fail    { background: var(--tb-danger-soft);  color: var(--tb-danger-ink); }
.tb-badge-muted   { background: var(--tb-panel-2);      color: var(--tb-ink-soft); }

/* --- Dialogo di conferma -----------------------------------------------
   Sostituisce window.confirm(), che non si puo' tradurre, non si puo' stilare e
   dice "localhost dice:" davanti a una domanda sui soldi di qualcuno.
   <dialog> + showModal(): il browser lo mette nel top layer (nessuno z-index),
   intrappola il focus e chiude con Escape senza che dobbiamo scrivere nulla. */
.tb-dialog {
    width: min(440px, calc(100vw - 32px));
    padding: 0;
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
    background: var(--tb-bg);
    color: var(--tb-ink);
    box-shadow: var(--tb-shadow);
}
.tb-dialog::backdrop { background: var(--tb-scrim); }
.tb-dialog-body { padding: 22px 22px 0; }
.tb-dialog h2 { margin: 0 0 8px; font: var(--tb-t-card-title); }
.tb-dialog p  { margin: 0; font: var(--tb-t-meta); color: var(--tb-ink-soft); text-wrap: pretty; }
.tb-dialog-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 20px 22px 22px;
}
.tb-dialog .tb-btn-danger {
    background: var(--tb-danger); border-color: var(--tb-danger); color: #fff;
}
.tb-dialog .tb-btn-danger:hover { background: #A4271B; border-color: #A4271B; color: #fff; }

@media (prefers-reduced-motion: no-preference) {
    .tb-dialog[open]            { animation: tb-dialog-in 220ms var(--tb-ease); }
    .tb-dialog[open]::backdrop  { animation: tb-fade-in 220ms var(--tb-ease); }
}
@keyframes tb-dialog-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } }
@keyframes tb-fade-in   { from { opacity: 0; } }

/* --- Slab: la superficie scura dell'area privata -----------------------
   Il saldo non e' una statistica in un riquadro fra tanti: e' un oggetto, e
   sta su una superficie sua. Riusa il navy dell'hero della home, cosi' un
   utente che scende dalla home ritrova la stessa materia.
   Su questa superficie valgono --tb-emerald-bright / --tb-danger-bright:
   le varianti da fondo chiaro non arrivano a 4.5:1 sul navy. */

.tb-slab {
    position: relative;              /* obbligatorio: ritaglia il glow e gli abspos figli */
    isolation: isolate;
    overflow: hidden;
    background: var(--tb-ink);
    color: #fff;
    border-radius: var(--tb-r-slab);
    padding: 26px 28px;
    box-shadow: var(--tb-shadow);
}

/* Un alone dell'emerald del cashback, non un gradiente decorativo: dice
   "qui dentro c'e' il tuo denaro" e si ferma al 14% di opacita'. */
.tb-slab::before {
    content: '';
    position: absolute;
    inset: -60% 30% 20% -25%;
    background: radial-gradient(closest-side, rgb(49 217 146 / 14%), transparent 78%);
    pointer-events: none;
    z-index: -1;
}

.tb-slab-label {
    font-size: var(--tb-fs-xs);
    font-weight: 600;
    color: var(--tb-on-dark);
}
.tb-slab-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-bottom: 18px;
}
.tb-slab-chip {
    width: 34px; height: 34px; flex: none;
    display: grid; place-items: center;
    border-radius: 9px;
    background: rgb(255 255 255 / 8%);
}
.tb-slab-chip svg { width: 18px; height: 18px; flex: none; color: var(--tb-emerald-bright); }

/* Le valute non si sommano: si affiancano, divise da un filetto. */
.tb-slab-figures { display: flex; flex-wrap: wrap; gap: 0 34px; }
.tb-slab-figure { min-width: 0; padding-right: 34px; }
.tb-slab-figure + .tb-slab-figure {
    padding-left: 34px; padding-right: 0;
    border-left: 1px solid var(--tb-on-dark-line);
}
.tb-slab-cur {
    display: block; margin-bottom: 2px;
    font-size: var(--tb-fs-xs); font-weight: 700; letter-spacing: 0.06em;
    color: var(--tb-on-dark);
}
/* Il momento eroe della pagina. 56px contro i 28px del titolo: e' il saldo a
   comandare, non l'intestazione. Scala fissa (non clamp): in un'app si guarda
   sempre alla stessa distanza. */
.tb-slab-amount {
    display: block;
    font-size: 3.5rem; line-height: 1; font-weight: 800;
    letter-spacing: -0.035em;
    color: var(--tb-emerald-bright);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.tb-slab-amount.is-negative { color: var(--tb-danger-bright); }
.tb-slab-amount.is-zero     { color: #fff; }
/* Il sottotitolo racconta il denaro che NON e' ancora prelevabile, una tappa per
   riga. Il grassetto e' BIANCO, non emerald: l'emerald dice "questo denaro e'
   tuo", e in maturazione o in arrivo non lo e' ancora. */
.tb-slab-sub {
    display: block; margin-top: 10px;
    font-size: var(--tb-fs-sm); line-height: 1.5; color: var(--tb-on-dark);
}
.tb-slab-sub b { color: #fff; font-weight: 700; font-variant-numeric: tabular-nums; }

.tb-slab-foot {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 14px;
    margin-top: 24px; padding-top: 18px;
    border-top: 1px solid var(--tb-on-dark-line);
}
.tb-slab-note { margin: 14px 0 0; font-size: var(--tb-fs-xs); color: var(--tb-on-dark); max-width: 62ch; }

/* Saldo sotto zero: si spiega dentro lo slab, non in un riquadro rosso a parte.
   Il rosso da fondo chiaro (--tb-danger) sul navy sta a 3.18:1: qui serve la
   variante luminosa, e il corpo del testo va ancora piu' chiaro. */
.tb-slab-alert {
    display: flex; gap: 12px; align-items: flex-start;
    background: rgb(255 142 128 / 10%);
    border: 1px solid rgb(255 142 128 / 30%);
    border-radius: var(--tb-r-card);
    padding: 14px 16px; margin-bottom: 22px;
}
.tb-slab-alert svg { width: 20px; height: 20px; flex: none; color: var(--tb-danger-bright); margin-top: 2px; }
.tb-slab-alert strong { display: block; font-size: var(--tb-fs-sm); color: var(--tb-danger-bright); }
.tb-slab-alert p { margin: 4px 0 0; font-size: var(--tb-fs-sm); color: #FFE3DE; text-wrap: pretty; }

/* Bottone primario sul navy: la superficie blu del brand stacca dal navy solo
   3.14:1, appena sopra la soglia delle superfici UI, e l'azione si perde nel
   fondo. Sul buio l'azione diventa emerald (9.45:1) con il testo in navy: e' il
   colore del cashback, e questo bottone serve a prendersi il cashback. */
.tb-slab .tb-btn-primary {
    background: var(--tb-emerald-bright); border-color: var(--tb-emerald-bright);
    color: var(--tb-ink); font-weight: 700;
}
.tb-slab .tb-btn-primary:hover { background: #58E4A9; border-color: #58E4A9; }
.tb-slab .tb-btn-primary:active { transform: translateY(1px); }
.tb-slab :where(a, button):focus-visible { outline-color: #fff; }

/* Entrata: un solo movimento, sull'unico elemento che lo merita. Il testo e'
   visibile per default; l'animazione lo accompagna, non lo rivela.
   prefers-reduced-motion la spegne (regola globale in fondo al foglio). */
@keyframes tb-slab-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
.tb-slab-amount { animation: tb-slab-in 480ms var(--tb-ease) both; }

@media (max-width: 620px) {
    .tb-slab { padding: 22px 20px; }
    .tb-slab-amount { font-size: 2.5rem; letter-spacing: -0.03em; }
    .tb-slab-figures { gap: 0; display: block; }
    .tb-slab-figure { padding: 0; }
    .tb-slab-figure + .tb-slab-figure {
        padding: 16px 0 0; margin-top: 16px;
        border-left: 0; border-top: 1px solid var(--tb-on-dark-line);
    }
}

/* --- Striscia di cifre: quattro numeri, un contenitore, filetti veri -----
   Sostituisce la griglia di riquadri identici. Il gap di 1px sopra lo sfondo
   della linea disegna i divisori: restano perfetti anche quando la griglia
   va a capo, cosa che un border-left non fa. */

.tb-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
    gap: 1px;
    background: var(--tb-line);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
    overflow: hidden;
}
.tb-figure {
    min-width: 0;
    background: var(--tb-bg);
    padding: 16px 18px;
}
.tb-figure-label { display: block; font-size: var(--tb-fs-xs); font-weight: 600; color: var(--tb-ink-soft); }
.tb-figure-value {
    display: block; margin-top: 2px;
    font-size: var(--tb-fs-xl); font-weight: 800; line-height: 1.2;
    color: var(--tb-ink);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.tb-figure-note { display: block; margin-top: 4px; font-size: var(--tb-fs-xs); color: var(--tb-ink-soft); }
.tb-figure-cash .tb-figure-value,
.tb-figure-cash .tb-figure-note { color: var(--tb-emerald-ink); }

/* --- Righe: un contenitore, filetti fra le voci ------------------------
   Non quattro card identiche impilate. Una lista e' una lista. */

.tb-rows {
    list-style: none; margin: 0; padding: 0;
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
    overflow: hidden;
}
.tb-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 20px; padding: 18px 20px;
    transition: background var(--tb-dur-fast) var(--tb-ease);
}
.tb-row + .tb-row { border-top: 1px solid var(--tb-line); }
.tb-row:hover { background: var(--tb-panel); }

/* --- Rating ----------------------------------------------------------- */

.tb-rating {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 38px; height: 28px; padding: 0 8px;
    background: var(--tb-ink); color: #fff;
    border-radius: 8px; font-weight: 700; font-size: var(--tb-fs-sm);
    font-variant-numeric: tabular-nums;
}

/* --- Cashback --------------------------------------------------------- */

.tb-cashback {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--tb-fs-xs); font-weight: 700;
    color: var(--tb-emerald-ink);
    background: var(--tb-emerald-soft);
    border-radius: var(--tb-r-pill);
    padding: 5px 10px;
    font-variant-numeric: tabular-nums;
}
/* emerald-ink, non emerald: bianco su --tb-emerald sta a 3.42:1, sotto la
   soglia 4.5:1 richiesta per il testo piccolo. Su emerald-ink sale a 5.07:1. */
.tb-cashback-solid { background: var(--tb-emerald-ink); color: #fff; }

/* --- Prezzo -----------------------------------------------------------
   .tb-price          prezzo visibile (utente loggato)
   .tb-price-locked   segnaposto per utenti anonimi: il numero NON è mai
                      il prezzo reale, è un placeholder inerte (il prezzo
                      non viene proprio inviato al browser).
   ---------------------------------------------------------------------- */

.tb-price { font-size: var(--tb-fs-xl); font-weight: 800; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.tb-price small { font-size: var(--tb-fs-xs); font-weight: 500; color: var(--tb-ink-soft); }
.tb-price-real { font-size: var(--tb-fs-xs); color: var(--tb-emerald-ink); font-weight: 600; }

.tb-price-locked { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.tb-price-locked .tb-price-blur {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: var(--tb-fs-xl); font-weight: 800; color: var(--tb-ink);
    user-select: none;
}
.tb-price-locked .tb-price-blur .tb-blur {
    filter: blur(5px);
    letter-spacing: 0.02em;
    opacity: .55;
}
.tb-price-locked .tb-lock { color: var(--tb-ink-soft); flex: none; }
.tb-price-locked .tb-price-cta { font-size: var(--tb-fs-xs); font-weight: 600; color: var(--tb-blue); text-decoration: none; }
.tb-price-locked .tb-price-cta:hover { text-decoration: underline; }

/* Banner "tariffe riservate" in cima ai risultati */
.tb-gate-banner {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    background: var(--tb-panel);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card);
    padding: 14px 18px;
}
.tb-gate-banner .tb-gate-text { flex: 1 1 320px; }
.tb-gate-banner strong { display: block; font-size: var(--tb-fs-sm); }
.tb-gate-banner p { margin: 2px 0 0; font-size: var(--tb-fs-xs); color: var(--tb-ink-soft); }
.tb-gate-banner .tb-gate-actions { display: flex; gap: 8px; }

/* --- Header ----------------------------------------------------------- */

.tb-header {
    position: sticky; top: 0; z-index: 100;
    background: color-mix(in srgb, var(--tb-bg) 88%, transparent);
    -webkit-backdrop-filter: saturate(1.3) blur(10px);
    backdrop-filter: saturate(1.3) blur(10px);
    border-bottom: 1px solid var(--tb-line);
}
.tb-header-inner {
    max-width: var(--tb-container);
    margin: 0 auto; padding: 0 24px;
    min-height: var(--tb-header-h);
    display: flex; align-items: center; gap: 16px;
}

.tb-logo { display: inline-flex; align-items: center; gap: 9px; font-weight: 800; font-size: var(--tb-fs-lg);
    letter-spacing: -0.02em; color: var(--tb-ink); text-decoration: none; flex: none; }
.tb-logo-mark { width: 26px; height: 26px; border-radius: 8px; background: var(--tb-blue); color: #fff;
    display: grid; place-items: center; font-size: 14px; font-weight: 800; }
.tb-logo-trips { color: var(--tb-ink); }
.tb-logo-back  { color: var(--tb-blue); }

.tb-nav { display: flex; align-items: center; gap: 4px; margin-left: 10px; }
/* Le pagine con barra di ricerca in testata cedono la navigazione alla barra:
   i link restano nel footer. Senza questo la barra scende a 439px e tronca. */
.tb-header-with-search .tb-nav { display: none; }
.tb-nav a { font-size: var(--tb-fs-sm); font-weight: 500; color: var(--tb-ink-soft);
    text-decoration: none; padding: 8px 11px; border-radius: 8px; }
.tb-nav a:hover { color: var(--tb-ink); background: var(--tb-panel); }
.tb-nav a[aria-current="page"] { color: var(--tb-ink); font-weight: 600; }

.tb-header-spacer { flex: 1; }
.tb-header-actions { display: flex; align-items: center; gap: 8px; }
.tb-mini-link { font-size: var(--tb-fs-sm); font-weight: 500; color: var(--tb-ink-soft); text-decoration: none; padding: 8px 10px; border-radius: 8px; }
.tb-mini-link:hover { color: var(--tb-ink); background: var(--tb-panel); }

/* Wallet pill nell'header (utente loggato) */
.tb-wallet-pill {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: var(--tb-fs-xs); font-weight: 700;
    color: var(--tb-emerald-ink); background: var(--tb-emerald-soft);
    border: 1px solid color-mix(in srgb, var(--tb-emerald) 22%, transparent);
    border-radius: var(--tb-r-pill); padding: 6px 12px; text-decoration: none;
    font-variant-numeric: tabular-nums;
}
.tb-wallet-pill:hover { background: color-mix(in srgb, var(--tb-emerald-soft) 70%, #fff); }
/* Una <svg> senza width intrinseca dentro un inline-flex e' un flex item con
   min-width:auto e collassa a 0: l'icona diventerebbe invisibile. */
.tb-wallet-pill svg { flex: none; }
/* Saldo sotto zero (storno dopo un payout): il verde del cashback mentirebbe. */
.tb-wallet-pill.is-negative {
    color: var(--tb-danger); background: color-mix(in srgb, var(--tb-danger) 8%, #fff);
    border-color: color-mix(in srgb, var(--tb-danger) 24%, transparent);
}
.tb-wallet-pill.is-negative:hover { background: color-mix(in srgb, var(--tb-danger) 12%, #fff); }

/* Switch lingua */
.tb-lang { display: inline-flex; border: 1px solid var(--tb-line); border-radius: var(--tb-r-pill); overflow: hidden; background: var(--tb-panel); }
.tb-lang a { font-size: 12px; font-weight: 600; color: var(--tb-ink-soft); padding: 6px 10px; text-decoration: none; line-height: 1; display: grid; place-items: center; }
.tb-lang a[aria-current="true"] { background: var(--tb-ink); color: #fff; }

/* Toggle mobile */
.tb-menu-toggle { display: none; flex-direction: column; align-items: center; justify-content: center; gap: 4px; background: none; border: 0; padding: 10px; cursor: pointer; }
/* margin:0 e flex:none sono obbligatori. global.css da' alle barrette
   "margin: 4px auto": 24px di margini verticali dentro un pulsante con 24px di
   contenuto. I margini non si comprimono, quindi il flex shrink azzerava
   l'altezza delle barre e il bottone diventava invisibile su tutti i telefoni. */
.tb-menu-toggle span { display: block; width: 20px; height: 2px; margin: 0; flex: none; background: var(--tb-ink); border-radius: 2px; }

/* --- Barra di ricerca nell'header (hook JS invariati) ------------------ */

.tb-header-search-wrap { display: flex; justify-content: center; flex: 1; min-width: 0; }
.tb-top-search, .tb-search-form {
    display: flex; align-items: stretch;
    background: var(--tb-bg);
    border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-pill);
    box-shadow: var(--tb-shadow);
    padding: 4px 4px 4px 6px;
    max-width: 720px; width: 100%;
}
.tb-search-segment {
    display: flex; flex-direction: column; justify-content: center;
    padding: 4px 14px; min-width: 0; flex: 1;
    border-radius: var(--tb-r-pill);
}
.tb-search-segment:hover { background: var(--tb-panel); }
.tb-search-label { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--tb-ink-soft); }
.tb-text-input, .tb-field-button {
    font: inherit; font-size: var(--tb-fs-sm); font-weight: 600; color: var(--tb-ink);
    background: transparent; border: 0; padding: 0; text-align: left; cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-text-input::placeholder { color: var(--tb-ink-soft); font-weight: 500; }
.tb-search-icon, .tb-search-submit {
    flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-height: var(--tb-touch);   /* stava a 42px: e' il bottone piu' premuto del sito */
    background: var(--tb-blue); color: #fff; border: 0; border-radius: var(--tb-r-pill);
    font: inherit; font-size: var(--tb-fs-sm); font-weight: 600; padding: 10px 18px; cursor: pointer;
    /* L'etichetta NON va a capo. Senza questa riga, nella barra stretta
       dell'header "Cerca hotel" si spezzava su due righe e la pillola, con
       raggio 999px, si richiudeva in un BLOB TONDO. Oltre a essere brutto era
       proprio la forma da non avere: un orb circolare colorato incastonato a
       destra nella barra e' la firma riconoscibile di un concorrente diretto,
       ed e' territorio trade dress. Il bottone resta una pillola con la scritta. */
    white-space: nowrap;
    /* global.css impone width:100% sotto i 768px, pensando a una .tb-top-search
       a griglia impilata. Qui la barra resta in riga fino a 768px, e un bottone
       al 100% con flex:none sfonda il viewport. Le media query non alzano la
       specificita', quindi questa regola (foglio caricato dopo) vince. */
    width: auto;
}
.tb-search-icon:hover, .tb-search-submit:hover { background: var(--tb-blue-deep); }
.tb-header .dot { width: 1px; align-self: center; height: 24px; background: var(--tb-line); }

/* =======================================================================
   BARRA DI RICERCA: LO SPOTLIGHT
   =======================================================================
   Il modo in cui la barra dice "sei qui". Quando un segmento e' aperto la
   guida si SPEGNE (diventa --tb-panel) e il segmento attivo si SOLLEVA in
   bianco: il contrasto lo isola senza bisogno di un bordo colorato.

   E' movimento che racconta uno stato, non decorazione: PRODUCT.md e' netto
   ("mai una coreografia; l'utente sta sbrigando, non guardando"), quindi i
   tempi stanno nei 140-260ms, non nei 450ms di chi vende sogni.

   Il bottone d'invio resta una PILLOLA CON L'ETICHETTA in ogni stato. Non
   diventa mai un cerchio: quello e' il tratto riconoscibile di un altro
   marchio nel nostro stesso settore, ed e' territorio trade dress. -------- */

/* .tb-search-form e' la primitiva: ce l'hanno sia la barra dell'hero
   (.hm-searchbar) sia quella dell'header (.tb-top-search), che restano solo
   varianti di misura. Un solo vocabolario, due taglie. */
.tb-search-form { transition: background var(--tb-dur) var(--tb-ease); }
.tb-search-form[data-open] { background: var(--tb-panel); }

/* In errore la barra va a capo e il messaggio prende una riga tutta sua, sotto i
   segmenti, senza toccarne l'altezza. `flex-wrap` si accende SOLO qui: a barra
   sana non deve poter mandare a capo niente per sbaglio.
   (Il pannello e' fuori flusso — position:fixed, top layer — quindi non entra
   in questo conto. E siccome il messaggio allunga il form, il pannello, che si
   ancora al fondo del form, scende da solo insieme a lui.) */
.tb-search-form.has-error { flex-wrap: wrap; }
.tb-search-form .tb-field-error { flex: 0 0 100%; padding: 0 var(--tb-s-3) var(--tb-s-1); }

/* Il filetto fra i segmenti. Non e' un box-shadow a tutta altezza: e' una riga
   alta poco piu' di meta' segmento, centrata. Un tratto che arriva a filo del
   bordo superiore e inferiore taglia la barra in tre scatole; uno piu' corto la
   lascia leggere come un oggetto solo, diviso.

   Sparisce quando la guida si spegne: due segnali di separazione insieme
   (filetto + rilievo del segmento sollevato) fanno rumore, non gerarchia. */
.tb-search-segment { position: relative; }
.tb-search-form .tb-search-segment + .tb-search-segment::before {
    content: ''; position: absolute; left: 0; top: 50%;
    width: 1px; height: 55%; transform: translateY(-50%);
    background: var(--tb-line);
    transition: opacity var(--tb-dur) var(--tb-ease);
}
.tb-search-form[data-open] .tb-search-segment + .tb-search-segment::before { opacity: 0; }

.tb-search-segment {
    transition: background var(--tb-dur) var(--tb-ease),
                box-shadow var(--tb-dur) var(--tb-ease);
}
.tb-search-form[data-open] .tb-search-segment.is-open {
    background: var(--tb-bg);
    box-shadow: 0 1px 2px rgb(14 26 51 / 6%), 0 8px 20px -10px rgb(14 26 51 / 28%);
}
/* Sulla guida spenta il hover deve solo accennare, se no compete con l'attivo. */
.tb-search-form[data-open] .tb-search-segment:not(.is-open):hover { background: rgb(255 255 255 / 55%); }


/* --- Il pannello ------------------------------------------------------- */
/* popover = top layer: non lo ritaglia ne' un overflow:hidden dell'antenato
   ne' l'overflow-x:hidden che body si porta dietro da global.css. Posizione via
   JS (rect del segmento), perche' anchor-positioning non e' ancora ovunque.

   IL PANNELLO E' UNO SOLO, e questa e' la scelta che conta. Con tre pannelli
   separati, passare da "dove" a "quando" e' una tendina che sparisce e un'altra
   che compare: si legge come due eventi. Con un guscio solo che SCIVOLA sotto il
   nuovo segmento cambiando forma, si legge come un oggetto che ti segue — ed e'
   l'unica cosa che separa una barra di ricerca fatta bene da un dropdown.

   Diviso in due strati per un motivo preciso: il POSIZIONATORE (.tb-sb-panel)
   fa il viaggio (transform + width), il GUSCIO (.tb-sb-shell) fa l'ingresso
   (opacita' + risalita). Sono due animazioni sulla stessa proprieta' transform:
   su un elemento solo si sarebbero mangiate a vicenda. */
/* ATTENZIONE a `top` e `left`: vanno dichiarati, e NON vanno rimessi in
   discussione da una scorciatoia `inset` scritta dopo.

   Qui c'era `inset: auto auto auto 0` in coda a `top: 0; left: 0`. `inset` e' la
   scorciatoia di top/right/bottom/left, arriva dopo, e quindi rimetteva `top` ad
   AUTO. Un elemento `fixed` con `top: auto` si piazza nella sua POSIZIONE
   STATICA — cioe' li' dove sarebbe finito nel flusso, dentro il form, a meta'
   pagina — e il nostro translateY ci si SOMMA sopra. Il pannello usciva in fondo
   alla pagina, fuori dallo schermo.

   Non se n'era accorto nessuno perche' Chromium risolve `top: auto` a 0 per gli
   elementi nel top layer e mascherava l'errore. Firefox no: sulla home dava
   top: 421px (la posizione del form) + 497 di translate = 918px, con un viewport
   alto 900. Provare su un motore solo non e' provare. */
.tb-sb-panel {
    position: fixed; top: 0; left: 0; margin: 0;
    z-index: 120; padding: 0; border: 0; background: transparent;
    /* Il viaggio. Le tre facce hanno larghezze diverse, quindi la larghezza fa
       parte del movimento: senza, il guscio scatterebbe di misura a meta' strada. */
    transform: translate(var(--sb-x, 0px), var(--sb-y, 0px));
    width: var(--sb-w, 420px);
    transition: transform var(--tb-dur-slow) var(--tb-glide),
                width     var(--tb-dur-slow) var(--tb-glide);
}
/* Alla PRIMA apertura non c'e' nessun viaggio da fare: il pannello deve nascere
   gia' sotto il suo segmento, non arrivarci scivolando dall'angolo in alto. */
.tb-sb-panel.is-fermo { transition: none; }

/* Doppia serratura, di proposito. Dove `popover` esiste, e' lo stile UA
   ([popover]:not(:popover-open){display:none}) a tenerlo chiuso e il pannello
   sale nel top layer. Dove non esiste, l'attributo e' inerte e resta `hidden`
   a comandare: il JS li muove tutti e due, e la barra funziona comunque. */
.tb-sb-panel[hidden] { display: none; }

/* Il guscio: la scatola bianca. Scorre il CORPO, non il piede — prima l'overflow
   stava sul contenitore intero e il bottone "Fatto" del calendario scorreva via
   oltre il bordo dello schermo: c'era, ma non lo si poteva premere. */
.tb-sb-shell {
    display: flex; flex-direction: column;
    max-height: var(--sb-maxh, 70vh);
    background: var(--tb-bg); border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-card); box-shadow: var(--tb-shadow);
    color: var(--tb-ink); overflow: hidden;
}

/* Le facce si danno il cambio: una sola alla volta. */
.tb-sb-pane { display: flex; flex-direction: column; min-height: 0; }
.tb-sb-pane[hidden] { display: none; }
/* Attenzione a `overflow-y: auto` qui: per specifica costringe anche `overflow-x`
   da `visible` ad `auto`, e questo rende il corpo un contenitore a SCORRIMENTO.
   Conseguenza non ovvia: il corpo smette di contribuire alla larghezza intrinseca
   del pannello, quindi `max-content` non "vede" piu' il calendario. E' il motivo
   per cui la larghezza della faccia "quando" si stima e si misura a mano in
   app.js invece di lasciarla calcolare al browser. */
.tb-sb-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--tb-s-4); }

.tb-sb-foot {
    flex: none;
    display: flex; align-items: center; justify-content: space-between; gap: var(--tb-s-4);
    padding: var(--tb-s-3) var(--tb-s-4);
    border-top: 1px solid var(--tb-line);
}

/* Quante notti / quanti ospiti: e' informazione, ed e' l'unica cosa che il piede
   del pannello ha il diritto di dire. Su una riga: "1 adulto, 1 / camera"
   spezzato in due sembra un errore, non una nota. */
.tb-sb-note {
    font-size: var(--tb-fs-sm); color: var(--tb-ink-soft);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-sb-note b { color: var(--tb-ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* L'input tecnico di flatpickr: serve al plugin, non all'utente. */
.tb-flatpickr-anchor {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); border: 0;
}

/* DUE VELOCITA'. E' il trucco, e senza di esso il resto non serve a niente:
   il guscio VIAGGIA lento (340ms, e si posa) mentre il contenuto CAMBIA svelto
   (140ms). Se viaggiassero allo stesso passo sembrerebbe una diapositiva; cosi'
   sembra una cosa che ha una massa. */
@media (prefers-reduced-motion: no-preference) {
    .tb-sb-panel:popover-open .tb-sb-shell { animation: tb-sb-in var(--tb-dur) var(--tb-ease) both; }
    .tb-sb-pane:not([hidden])              { animation: tb-fade-in var(--tb-dur-fast) linear both; }

    /* Lo sfalsamento delle scorciatoie: 22ms l'una dall'altra, sei voci = 132ms,
       finito prima che il guscio si sia posato. E' dentro UNA lista, che e' il
       solo posto in cui uno stagger e' informazione ("sono voci di un elenco")
       invece che coreografia. --i lo mette il PHP. */
    .tb-sb-pane[data-pane="where"]:not([hidden]) .tb-sb-item {
        animation: tb-sb-item-in 240ms var(--tb-ease) both;
        animation-delay: calc(var(--i, 0) * 22ms);
    }
}

/* Il guscio nasce OPACO e fermo: l'animazione lo anima, non lo rivela. E' il
   motivo per cui qui sotto non c'e' nessun blocco di ripiego per il movimento
   ridotto, e non e' una dimenticanza: la regola globale in fondo al foglio
   (`* { animation: none !important }`) spegne tutto, e con l'animazione spenta
   il pannello resta semplicemente com'e' nato — visibile. Se invece l'avessimo
   nascosto di base e "rivelato" con i keyframe, con quella regola attiva non
   sarebbe comparso mai piu'. */
@keyframes tb-sb-in {
    from { opacity: 0; transform: translateY(-10px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@keyframes tb-sb-item-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

/* --- Pannello DOVE: suggerimenti -------------------------------------- */
.tb-sb-group + .tb-sb-group { margin-top: var(--tb-s-4); }
.tb-sb-group-title {
    display: block; margin: 0 0 var(--tb-s-2); padding: 0 var(--tb-s-2);
    font-size: var(--tb-fs-xs); font-weight: 600; color: var(--tb-ink-soft);
}
/* La lista dell'autocomplete vive nello stesso pannello delle scorciatoie, e
   quindi si veste allo stesso modo: due elenchi che fanno la stessa cosa non
   possono avere due aspetti. (I nomi .tb-ac-* restano quelli che scrive
   autocomplete.js; qui li facciamo solo sedere al tavolo giusto.) */
.tb-sb-suggest, .tb-ac-list { display: flex; flex-direction: column; gap: 2px; }
.tb-sb-item, .tb-ac-list .tb-ac-item {
    display: flex; align-items: center; gap: var(--tb-s-3); width: 100%;
    padding: 6px var(--tb-s-2); border: 0; border-radius: var(--tb-r-btn);
    background: transparent; font: inherit; color: var(--tb-ink); text-align: left; cursor: pointer;
    transition: background var(--tb-dur-fast) var(--tb-ease);
}
.tb-sb-item:hover, .tb-sb-item.is-active,
.tb-ac-list .tb-ac-item:hover, .tb-ac-list .tb-ac-item.is-active { background: var(--tb-panel); }

.tb-sb-item-icon, .tb-ac-list .tb-ac-icon {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: var(--tb-r-btn);
    background: var(--tb-panel); color: var(--tb-ink-soft);
}
.tb-sb-item:hover .tb-sb-item-icon, .tb-sb-item.is-active .tb-sb-item-icon,
.tb-ac-list .tb-ac-item:hover .tb-ac-icon, .tb-ac-list .tb-ac-item.is-active .tb-ac-icon {
    background: var(--tb-blue-soft); color: var(--tb-blue-deep);
}
.tb-sb-item-icon svg, .tb-ac-list .tb-ac-icon svg { width: 18px; height: 18px; }

.tb-sb-item-text, .tb-ac-list .tb-ac-text { display: flex; flex-direction: column; min-width: 0; }
.tb-sb-item-label, .tb-ac-list .tb-ac-label { font-size: var(--tb-fs-sm); font-weight: 600; }
.tb-sb-item-sub, .tb-ac-list .tb-ac-sub { font-size: var(--tb-fs-xs); color: var(--tb-ink-soft); }

/* --- "Vicino a me" ------------------------------------------------------
   Sta in cima al pannello DOVE, sopra le recenti e le scorciatoie, perche' e'
   l'unica voce che non chiede di sapere gia' la risposta. Ed e' un'AZIONE, non
   un posto: il filetto sotto lo separa dagli elenchi, che invece sono elenchi
   di posti. */
.tb-sb-geo {
    position: relative;
    margin-bottom: var(--tb-s-3);
    padding-bottom: var(--tb-s-3);
    border-bottom: 1px solid var(--tb-line);
    border-radius: var(--tb-r-btn) var(--tb-r-btn) 0 0;
}
.tb-sb-geo[hidden] { display: none; }   /* [hidden] perde contro display:flex */

/* Scelta: l'icona si accende come su hover, e ci resta. Dice "e' questa la
   destinazione", che e' l'unica cosa che il campo di testo non riesce a dire —
   li' c'e' scritto "La tua posizione", e sembra una frase, non una scelta. */
.tb-sb-geo.is-on .tb-sb-item-icon { background: var(--tb-blue-soft); color: var(--tb-blue-deep); }

/* Non ha funzionato. Il bottone resta premibile (riprovare e' gratis) e la
   riga sotto dice cosa fare adesso, non cos'e' fallito. */
.tb-sb-geo.is-ko .tb-sb-item-sub  { color: var(--tb-danger-ink); }
.tb-sb-geo.is-ko .tb-sb-item-icon { background: var(--tb-danger-soft); color: var(--tb-danger); }

.tb-sb-geo-spin {
    flex: none; width: 16px; height: 16px; margin-left: auto;
    border: 2px solid var(--tb-line); border-top-color: var(--tb-blue);
    border-radius: 50%;
    opacity: 0;
    animation: tb-spin 640ms linear infinite;
}
.tb-sb-geo.is-cerca .tb-sb-geo-spin { opacity: 1; }

@keyframes tb-spin { to { transform: rotate(360deg); } }

/* Un anello fermo non dice "sto cercando": dice "sono rotto". Con il movimento
   ridotto la regola globale in fondo al foglio spegne l'animazione, quindi qui
   togliamo proprio l'anello — a dirlo resta la riga di testo ("Cerco dove
   sei…"), che e' poi quella che portava l'informazione anche prima. */
@media (prefers-reduced-motion: reduce) {
    .tb-sb-geo-spin { display: none; }
}

/* I tre stati dell'autocomplete dentro il pannello: sto cercando / non ho
   trovato / non riesco a cercare. Sono righe che si leggono, non si cliccano.
   Sotto di loro restano le scorciatoie (la via d'uscita), e il filetto dice che
   sono due cose diverse: sopra la risposta, sotto cosa puoi fare. */
.tb-ac-list .tb-ac-state {
    display: flex; align-items: center; gap: var(--tb-s-3);
    padding: var(--tb-s-2) var(--tb-s-2) var(--tb-s-3);
    margin-bottom: var(--tb-s-2);
    border-bottom: 1px solid var(--tb-line);
    font-size: var(--tb-fs-sm); color: var(--tb-ink-soft);
}
.tb-ac-list .tb-ac-state.is-error { color: var(--tb-danger-ink); }
.tb-ac-list .tb-ac-retry {
    margin-left: auto; background: transparent; border: 1px solid var(--tb-line);
    border-radius: var(--tb-r-btn); padding: 6px 12px;
    font: inherit; font-size: var(--tb-fs-xs); font-weight: 600;
    color: var(--tb-ink); cursor: pointer;
}
.tb-ac-list .tb-ac-retry:hover { border-color: var(--tb-ink); }

/* --- Pannello CHI: contatori ------------------------------------------ */
.tb-who-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--tb-s-6);
    padding: var(--tb-s-3) 0;
}
.tb-who-row + .tb-who-row { border-top: 1px solid var(--tb-line); }
.tb-who-title { font-size: var(--tb-fs-sm); font-weight: 600; }
.tb-stepper { display: inline-flex; align-items: center; gap: var(--tb-s-3); }
.tb-stepper-btn {
    width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--tb-line);
    background: var(--tb-bg); color: var(--tb-ink); font-size: 16px; line-height: 1; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: border-color var(--tb-dur-fast) var(--tb-ease),
                color var(--tb-dur-fast) var(--tb-ease);
}
.tb-stepper-btn:hover:not(:disabled) { border-color: var(--tb-ink); }
/* Il limite si vede PRIMA di premere: un bottone spento e' una risposta, un
   bottone acceso che non fa niente e' un bug agli occhi di chi lo preme. */
.tb-stepper-btn:disabled { opacity: .4; cursor: not-allowed; }
.tb-stepper-value {
    min-width: 2ch; text-align: center; font-size: var(--tb-fs-sm); font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.tb-who-done {
    background: var(--tb-ink); color: #fff; border: 0; border-radius: var(--tb-r-btn);
    padding: 10px 18px; font: inherit; font-weight: 600; cursor: pointer;
    flex: none; white-space: nowrap;
    /* width e margin-top vanno DICHIARATI, non lasciati stare: global.css (che
       carica prima) mette `.tb-who-done { width: 100% }`, e la cascata non
       azzera cio' che non riscrivi. Finche' il bottone era comprimibile non si
       notava; con `flex: none` quel 100% si e' preso tutta la riga e la nota
       "6 notti" e' sparita dal piede del calendario. */
    width: auto; margin-top: 0;
    transition: background var(--tb-dur-fast) var(--tb-ease);
}
.tb-who-done:hover { background: var(--tb-ink-hover); }

/* --- Pannello QUANDO: il calendario ----------------------------------- */
/* flatpickr resta (i18n e range gia' risolti), ma lo montiamo INLINE dentro
   il pannello invece di lasciarlo galleggiare per conto suo: cosi' i tre
   passi condividono un solo guscio, una sola ombra, una sola animazione. */
/* Niente `width` qui: la calcola flatpickr (stile inline) misurando le colonne
   dei giorni, e sovrascriverla e' il modo piu' rapido per ritrovarsi un
   calendario largo due pixel. Qui gli togliamo solo la pelle: il guscio,
   l'ombra e il bordo ce li mette gia' il pannello. */
.tb-sb-cal .flatpickr-calendar.inline {
    box-shadow: none; border: 0; margin: 0; background: transparent;
}
.tb-sb-cal .flatpickr-months { padding-bottom: var(--tb-s-2); }
.tb-sb-cal .flatpickr-month { color: var(--tb-ink); }
.tb-sb-cal .flatpickr-current-month { font-size: var(--tb-fs-sm); font-weight: 600; }
.tb-sb-cal .flatpickr-weekday { color: var(--tb-ink-soft); font-size: var(--tb-fs-xs); font-weight: 600; }
.tb-sb-cal .flatpickr-prev-month, .tb-sb-cal .flatpickr-next-month { fill: var(--tb-ink); }
.tb-sb-cal .flatpickr-day {
    color: var(--tb-ink); border-radius: var(--tb-r-btn); border: 0;
    font-weight: 500;
}
.tb-sb-cal .flatpickr-day:hover { background: var(--tb-panel); }
.tb-sb-cal .flatpickr-day.today { box-shadow: inset 0 0 0 1px var(--tb-line); }
.tb-sb-cal .flatpickr-day.inRange {
    background: var(--tb-blue-soft); box-shadow: -5px 0 0 var(--tb-blue-soft), 5px 0 0 var(--tb-blue-soft);
    border-radius: 0;
}
.tb-sb-cal .flatpickr-day.startRange,
.tb-sb-cal .flatpickr-day.endRange,
.tb-sb-cal .flatpickr-day.selected {
    background: var(--tb-blue); color: #fff; font-weight: 600;
}
.tb-sb-cal .flatpickr-day.flatpickr-disabled { color: var(--tb-ink-soft); opacity: .35; }

/* --- Footer ----------------------------------------------------------- */

.tb-footer { background: var(--tb-ink); color: #fff; margin-top: 64px; padding: 48px 0 28px; }
.tb-footer .tb-container { display: grid; grid-template-columns: 1.6fr repeat(4, 1fr); gap: 32px; }
.tb-footer-brand .tb-logo { color: #fff; }
.tb-footer-brand .tb-logo-trips { color: #fff; }
.tb-footer-brand .tb-logo-back { color: #7FA0FF; }
.tb-footer-brand p { margin: 12px 0 0; font-size: var(--tb-fs-sm); color: #A8B2C6; max-width: 34ch; }
.tb-footer h4 { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: #8C97AD; font-weight: 700; margin: 0 0 12px; }
.tb-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.tb-footer a { font-size: var(--tb-fs-sm); color: #D5DBE7; text-decoration: none; }
.tb-footer a:hover { color: #fff; }
.tb-footer-bottom {
    max-width: var(--tb-container); margin: 34px auto 0; padding: 18px 24px 0;
    border-top: 1px solid rgb(255 255 255 / 10%);
    display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
    font-size: var(--tb-fs-xs); color: #8C97AD;
}

/* --- Responsive ------------------------------------------------------- */

@media (max-width: 1080px) {
    .tb-nav { display: none; }
    .tb-header-search-wrap { order: 3; flex-basis: 100%; padding-bottom: 12px; }
    .tb-header-inner { flex-wrap: wrap; padding-top: 10px; }
}

@media (max-width: 860px) {
    :root { --tb-fs-4xl: 2.25rem; --tb-fs-3xl: 1.875rem; --tb-fs-2xl: 1.5rem; }
    /* margin-left:auto porta il bottone al bordo destro, dove il pollice lo
       cerca (nel DOM segue il logo). Lo spacer va nascosto: con flex:1 si
       mangia lo spazio libero prima che il margine auto possa assorbirlo. */
    .tb-menu-toggle { display: flex; margin-left: auto; }
    .tb-header-spacer { display: none; }
    .tb-header-actions {
        display: none; order: 5; flex-basis: 100%;
        flex-direction: column; align-items: stretch; gap: 6px; padding-bottom: 14px;
    }
    /* app.js mette la classe is-open sull'header (#tbHeader), non sul pannello.
       Con .tb-header-actions.is-open il selettore non trovava mai nulla: il
       bottone cambiava aria-expanded e il menu restava chiuso su ogni telefono. */
    .tb-header.is-open .tb-header-actions { display: flex; }
    .tb-header-actions .tb-btn { width: 100%; justify-content: center; }
    /* .tb-mini-link e' un <a> inline: width e justify-content non lo toccano.
       Nel menu deve incolonnarsi come gli altri link, non restare a meta' riga. */
    .tb-header-actions .tb-mini-link { display: block; width: 100%; padding: 11px 12px; }
    .tb-lang { align-self: flex-start; margin: 4px 0 6px; }

    /* Sotto gli 860px la nav non ha altro posto dove stare, e sulle pagine con
       la barra di ricerca e' nascosta a ogni larghezza: senza questo i tre link
       non sono raggiungibili da telefono. Batte per specificita' (0,3,0) sia
       .tb-header-with-search .tb-nav sia il .tb-nav della media query sopra. */
    .tb-header.is-open .tb-nav {
        display: flex; order: 4; flex-basis: 100%;
        flex-direction: column; align-items: stretch;
        margin-left: 0; padding: 4px 0 10px;
        border-bottom: 1px solid var(--tb-line);
    }
    .tb-header.is-open .tb-nav a { padding: 11px 12px; }

    .tb-footer .tb-container { grid-template-columns: 1fr 1fr; }
}

/* Stesso breakpoint di global.css: sotto i 768px la barra si impila, cosi' le
   regole legacy (bordi sui segmenti, bottone a tutta larghezza) tornano coerenti.
   width:100% va dato SOLO dentro le barre che impilano davvero: la searchbar
   della home (.hm-searchbar) resta in riga fino a 640px e un bottone a tutta
   larghezza li' sfonderebbe il viewport. */
@media (max-width: 768px) {
    .tb-top-search, .tb-search-form { flex-direction: column; border-radius: var(--tb-r-card); padding: 8px; }
    .tb-top-search .tb-search-segment,
    .tb-search-form .tb-search-segment { border-radius: var(--tb-r-btn); border-bottom: 0; padding-bottom: 4px; }
    .tb-top-search .tb-search-icon, .tb-top-search .tb-search-submit,
    .tb-search-form .tb-search-icon, .tb-search-form .tb-search-submit {
        justify-content: center; margin-top: 6px; width: 100%;
    }
    .tb-header .dot { display: none; }
}

@media (max-width: 560px) {
    .tb-footer .tb-container { grid-template-columns: 1fr; }
}

/* --- MOVIMENTO ---------------------------------------------------------------
   PRODUCT.md, principio 5: "Il movimento racconta uno stato. Mai una coreografia
   di caricamento: l'utente sta sbrigando, non guardando."

   Quindi niente rivelazioni allo scroll, niente entrate di sezione, niente
   sequenze al caricamento della pagina. Il movimento esiste in tre posti soltanto,
   e ognuno dice una cosa che l'utente ha bisogno di sapere:

     1. IL SALDO entra (480ms). E' l'unico momento che ha diritto di emozionare.
     2. LO SCHELETRO pulsa, e le card entrano a scaglioni quando arrivano davvero:
        e' l'unica attesa vera del prodotto (fino a 30 secondi).
     3. LE RISPOSTE al tocco: hover, focus, pressione, il bottone che lavora.

   Tutto il resto sta fermo.
   -------------------------------------------------------------------------- */

/* La pressione si sente: 1px, e basta. Nessun rimbalzo, nessuna scala elastica —
   sono coreografia, e qui si sta sbrigando qualcosa. */
.tb-chip:active,
.tb-btn:not([disabled]):active { transform: translateY(1px); }

/* Le righe rispondono al passaggio, cosi' si capisce quale si sta per aprire. */
.tb-row, .tb-chip, .tb-tag, .tb-wallet-pill, .tb-cashback {
    transition: background-color var(--tb-dur-fast) var(--tb-ease),
                border-color var(--tb-dur-fast) var(--tb-ease),
                color var(--tb-dur-fast) var(--tb-ease),
                transform var(--tb-dur-fast) var(--tb-ease);
}

/* Il campo che si accende sotto il cursore, prima ancora del focus. */
.tb-input { transition: border-color var(--tb-dur-fast) var(--tb-ease); }

/* Gli avvisi non compaiono di scatto: un errore che appare senza preavviso si
   legge come un difetto della pagina, non come una risposta a quello che hai fatto. */
@media (prefers-reduced-motion: no-preference) {
    .tb-alert,
    .tb-field-error.is-on { animation: tb-alert-in 200ms var(--tb-ease); }
}
@keyframes tb-alert-in {
    from { opacity: 0; transform: translateY(-4px); }
}

/* Il movimento ridotto non e' una preferenza estetica: e' una richiesta medica.
   Qui si spegne TUTTO, comprese le animazioni scritte altrove — ed e' il motivo
   per cui il bottone occupato e l'anello dell'autocomplete hanno, ciascuno, il
   loro blocco di ripiego piu' su: senza, mostrerebbero un anello fermo e un
   bottone vuoto. */
@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}
