/**
 * EverShelf - UI Styles
 * Mobile-first PWA design with CSS custom properties.
 *
 * @author Stimpfl Daniel <evershelfproject@gmail.com>
 * @license MIT
 */

/* ===== CSS VARIABLES & RESET ===== */
:root {
    /* Brand emerald — same as --brand-primary in surfaces.css (no olive/military green). */
    --primary: #059669;
    --primary-light: #10b981;
    --primary-dark: #047857;
    --success: #16a34a;
    --success-light: #22c55e;
    --danger: #dc2626;
    --danger-light: #ef4444;
    --warning: #f59e0b;
    --warning-light: #fbbf24;
    --accent: #7c3aed;
    --accent-light: #8b5cf6;
    --bg: #f0f4e8;
    --bg-card: #ffffff;
    --bg-dark: #1a1a2e;
    --text: #1a1a1a;
    --text-light: #6b7280;
    --text-muted: #9ca3af;
    --border: #e5e7eb;
    --shadow: 0 2px 8px rgba(0,0,0,0.1);
    --shadow-lg: 0 4px 16px rgba(0,0,0,0.15);
    --radius: 16px;
    --radius-sm: 10px;
    --nav-height: 70px;
    --header-height: 56px;
    /* EverShelf corporate tokens */
    --es-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --es-radius-card: var(--radius-sm);
    --es-btn-height: 48px;
    --es-btn-height-lg: 52px;
    --es-space-xs: 4px;
    --es-space-sm: 8px;
    --es-space-md: 12px;
    --es-space-lg: 16px;
    --es-space-xl: 24px;
    --es-action-use: var(--warning);
    --es-action-success: var(--success);
    --es-action-recipe: var(--accent);
    --es-action-danger: var(--danger);
    --es-shadow-card: 0 2px 12px color-mix(in srgb, var(--primary-dark) 8%, transparent);
    --es-shadow-elevated: 0 8px 28px color-mix(in srgb, #000 14%, transparent);
    --es-border-subtle: color-mix(in srgb, var(--border) 88%, var(--primary) 12%);
    --es-surface-tint: color-mix(in srgb, var(--bg-card) 94%, var(--primary) 6%);
    --es-focus-ring: 0 0 0 3px color-mix(in srgb, var(--primary-light) 22%, transparent);
    --es-text-title: 1.12rem;
    --es-text-body: 0.9rem;
    --es-text-small: 0.78rem;
    --es-text-micro: 0.68rem;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
}

/* The root element paints the canvas *before* body does, and it is white by
   default: on Android any frame where the WebView surface is not painted yet
   (renderer restart, navigation start, surface re-attach) showed a white flash.
   Painting it with the app background makes those frames invisible. */
html {
    background: var(--bg);
}

body {
    font-family: var(--es-font);
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    overflow-x: hidden;
    padding-top: var(--header-height);
    padding-bottom: var(--nav-height);
    -webkit-font-smoothing: antialiased;
}

/* ===== HEADER ===== */
.app-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-height);
    background: linear-gradient(135deg, var(--primary), var(--primary-light));
    color: white;
    z-index: 100;
    display: flex;
    align-items: center;
    padding: 0 16px;
    box-shadow: var(--shadow);
}

/* ===== PRELOADER ===== */
#app-preloader {
    position: fixed;
    inset: 0;
    /* Light canvas ≈ Home: no dark→white flashbang on a kitchen wall display. */
    background: #f4f7f5;
    z-index: 200000;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow-y: auto;
    transition: opacity 0.55s cubic-bezier(0.4, 0, 0.2, 1),
                background-color 0.4s ease;
}
#app-preloader.fade-out {
    opacity: 0;
    pointer-events: none;
}
#app-preloader.is-lifting { background-color: var(--bg-app, #f8fafc); }
#app-preloader.is-lifting .app-preloader-inner { opacity: 0; }
.app-preloader-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* margin:auto (not align-items on the parent) so a tall splash scrolls instead
       of being clipped at the top on a short viewport. */
    margin: auto;
    width: 100%;
    padding: 24px 0;
    gap: clamp(18px, 3.5vh, 28px);
    transition: opacity 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Crossfade splash → Home: shell stays invisible under the overlay, then fades in
   with the same curve as the splash opacity drop (no hard cut). */
body.is-booting .app-header,
body.is-booting .app-content,
body.is-booting .bottom-nav {
    opacity: 0;
}
body.is-booting .page {
    animation: none;
}
body.is-booting.is-revealing .app-header,
body.is-booting.is-revealing .app-content,
body.is-booting.is-revealing .bottom-nav {
    opacity: 1;
    transition: opacity 0.55s cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
    #app-preloader {
        transition: opacity 0.2s ease, background-color 0.15s ease;
    }
    .app-preloader-inner { transition: opacity 0.15s ease; }
    body.is-booting.is-revealing .app-header,
    body.is-booting.is-revealing .app-content,
    body.is-booting.is-revealing .bottom-nav {
        transition: opacity 0.2s ease;
    }
}
.app-preloader-label {
    color: #64748b;
    font-size: 1.1rem;
    font-weight: 500;
    letter-spacing: 0.5px;
}
.app-preloader-logo {
    height: 150px;
    width: auto;
    object-fit: contain;
    /* Soft green lift that follows the PNG alpha (no rectangular box). */
    filter: drop-shadow(0 10px 22px rgba(5, 150, 105, 0.15));
    animation: logoPulse 2.8s ease-in-out infinite;
}
@keyframes logoPulse {
    0%, 100% { filter: drop-shadow(0 10px 22px rgba(5, 150, 105, 0.15)); transform: scale(1); }
    50%       { filter: drop-shadow(0 14px 28px rgba(5, 150, 105, 0.22)); transform: scale(1.015); }
}
/* ── Brand: logo + version chip ──────────────────────────────────────── */
.app-preloader-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}
/* The version is deliberately loud: the splash is where it gets read out when
   someone opens a bug report. `#preloader-version` must keep the
   `preloader-version">v1.2.3` shape — scripts/bump-version.sh rewrites it. */
.app-preloader-verchip {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    padding: 5px 16px;
    border-radius: 99px;
    background: rgba(5,150,105,0.08);
    border: 1px solid rgba(5,150,105,0.28);
    box-shadow: 0 0 16px rgba(5,150,105,0.1);
}
.app-preloader-verchip-label {
    font-size: 0.58rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: #64748b;
}
.app-preloader-verchip-value {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: #166534;
}
/* The branch label: which line of work a WORK-IN-PROGRESS build came from, deliberately
   small next to the version (a git ref, never translated). `scripts/bump-version.sh` fills
   it only on a feature branch and leaves it empty on `main`/`develop`, where `:empty` above
   hides it — a released install shows the version and nothing else. */
.app-preloader-verchip-branch {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.62rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: #94a3b8;
    max-width: 12em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* ── The foot of the splash: ONE signature ────────────────────────────────
   Open-data credit + project chip + SHELFY are one block, so the space that
   separates them is THIS gap (8 px), and the parent's own 18–28 px gap stays
   what it was meant for: the distance between the boot rail and the foot.
   Before, the three elements were siblings of the rail and every gap between
   them had to be cancelled with a negative margin — the layout was correct by
   subtraction, and the credit line floated away from the chip it explains. */
.preloader-foot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: 100%;
}
.preloader-powered {
    /* Margin lives in `.preloader-foot`'s gap: never both (that is how a 20 px
       hole appeared between the credit and the chip). */
    margin: 0;
    padding: 0 16px;
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: #94a3b8;
    text-align: center;
    max-width: 22rem;
    line-height: 1.35;
}
/* ── Who makes it, and that it costs nothing ─────────────────────────────
   The line under the open-data credit: a free, open-source project and the
   address of its source. ONE chip — a 16 px mark, two lines of text — never a
   wall of prose: the splash is read in half a second, and this row only has to
   answer "does this thing cost me something?" without competing with the boot
   rail. Slate on purpose: the emerald on this screen belongs to the stage that
   lights up, and nothing here writes stock. */
.preloader-github {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 7px 13px;
    border: 1px solid rgba(148, 163, 184, 0.38);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.62);
    text-decoration: none;
    color: #475569;
    max-width: min(23rem, 90vw);
    transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
.preloader-github:hover,
.preloader-github:focus-visible {
    border-color: rgba(100, 116, 139, 0.55);
    background: #ffffff;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08);
}
.preloader-github-mark {
    width: 16px;
    height: 16px;
    flex: 0 0 16px;
    opacity: 0.85;
}
.preloader-github-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;    /* lets the URL ellipsise instead of widening the chip */
    text-align: left;
}
.preloader-github-title {
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: 0.01em;
    color: #475569;
}
.preloader-github-url {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.66rem;
    font-weight: 500;
    line-height: 1.25;
    color: #64748b;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The two facts under the address, as STANDARD codes rather than prose: the SPDX
   licence identifier (`MIT`, never translated — a code that means the same thing in
   six languages) and the absence of advertising, whose two words are the same English
   in every locale (the splash is painted before the language is known) while its drawn
   mark only says "no". Pills on a hairline, so they read as metadata and not as
   buttons: nothing here is clickable on its own (the whole chip is the link). */
.preloader-github-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 3px;
}
.preloader-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid rgba(148, 163, 184, 0.45);
    background: rgba(255, 255, 255, 0.75);
    font-size: 0.6rem;
    font-weight: 600;
    line-height: 1.45;
    letter-spacing: 0.01em;
    color: #475569;
    white-space: nowrap;
}
.preloader-tag-mark {
    width: 11px;
    height: 11px;
    flex: 0 0 11px;
    opacity: 0.9;
}
/* A code, not a word: monospace + tracking so `MIT` reads as an identifier. */
.preloader-tag-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.06em;
}
@media (max-width: 400px) {
    .preloader-github-title { font-size: 0.64rem; }
    .preloader-github-url { font-size: 0.62rem; }
}
/* ── SHELFY at the foot of the splash ─────────────────────────────────────
   The assistant introduces itself later, in its own sheet; here it only waits,
   small, under the credit and project lines. Same drawing, same breathing halo as the
   button in the bottom nav, so the face is already familiar when the app opens.
   The avatar is a transparent PNG: the soft ring and the drop shadow follow its
   alpha, never a rectangular box. */
.preloader-shelfy {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 68px;
    height: 68px;
    /* The ring is drawn outside the avatar: the breathing halo needs the extra room,
       not a negative margin (the foot's own gap sets the distance from the chip). */
    animation: preloader-shelfy-in 0.55s ease-out 0.15s both;
}
.preloader-shelfy-ring {
    position: absolute;
    inset: 4px;
    border-radius: 50%;
    border: 2px solid rgba(5, 150, 105, 0.3);
    animation: preloader-shelfy-ring 3s ease-out infinite;
    pointer-events: none;
}
.preloader-shelfy-avatar {
    width: 56px;
    height: 56px;
    object-fit: contain;
    filter: drop-shadow(0 6px 12px rgba(5, 150, 105, 0.22));
    animation: preloader-shelfy-float 3.4s ease-in-out infinite;
}
@keyframes preloader-shelfy-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes preloader-shelfy-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}
@keyframes preloader-shelfy-ring {
    0%   { transform: scale(0.86); opacity: 0.55; }
    70%  { transform: scale(1.18); opacity: 0; }
    100% { transform: scale(1.18); opacity: 0; }
}
/* Short viewports (a phone in landscape): the avatar gives way to the stages. */
@media (max-height: 620px) {
    .preloader-shelfy { width: 54px; height: 54px; }
    .preloader-shelfy-avatar { width: 44px; height: 44px; }
    /* The foot also gets tighter: on 620 px of height every row counts. */
    .preloader-foot { gap: 6px; }
    .preloader-github { padding: 5px 10px; }
}
@media (prefers-reduced-motion: reduce) {
    .preloader-shelfy { animation: none; }
    .preloader-shelfy-avatar,
    .preloader-shelfy-ring { animation: none; }
}
/* ── Boot rail: three steps + ONE continuous connector behind the dots ──
   Do not use per-item ::after segments (they gap/misalign). A single
   `.preloader-stages::before` draws the track; each icon shares the splash
   background and sits above it (z-index) so the line looks seamless. */
.preloader-stages {
    --preloader-dot: 40px;
    position: relative;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    width: min(100% - 32px, 360px);
    margin: 0 auto;
    padding: 0;
    list-style: none;
    gap: 0;
}
/* Continuous horizontal track, centred on the dots (half of --preloader-dot). */
.preloader-stages::before {
    content: '';
    position: absolute;
    top: calc(var(--preloader-dot) / 2);
    left: calc(100% / 6);
    right: calc(100% / 6);
    height: 2px;
    border-radius: 99px;
    background: rgba(15, 23, 42, 0.12);
    transform: translateY(-50%);
    z-index: 0;
    pointer-events: none;
}
/* Green fill that grows over the grey track as stages complete (no segment gaps). */
.preloader-stages::after {
    content: '';
    position: absolute;
    top: calc(var(--preloader-dot) / 2);
    left: calc(100% / 6);
    width: calc((100% * 2 / 3) * var(--preloader-progress, 0));
    height: 2px;
    border-radius: 99px;
    background: #059669;
    box-shadow: 0 0 8px rgba(5, 150, 105, 0.35);
    transform: translateY(-50%);
    z-index: 0;
    pointer-events: none;
    transition: width 0.3s ease;
}
.preloader-stage {
    position: relative;
    z-index: 1;
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
}
/* Kill the old per-dot connectors if any stylesheet still targets them. */
.preloader-stage:not(:last-child)::after {
    content: none !important;
    display: none !important;
}
.preloader-stage-icon {
    position: relative;
    z-index: 2;
    width: var(--preloader-dot);
    height: var(--preloader-dot);
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 1.05rem;
    line-height: 1;
    /* Same as splash canvas so the track disappears under the disc. */
    background: #f4f7f5;
    border: 1px solid rgba(15,23,42,0.1);
    filter: grayscale(1) opacity(0.55);
    transition: filter 0.45s ease, background 0.45s ease, border-color 0.45s ease,
                box-shadow 0.45s ease, transform 0.3s ease;
}
#app-preloader.is-lifting .preloader-stage-icon {
    background: var(--bg-app, #f8fafc);
}
.preloader-stage-label {
    display: block;
    width: 100%;
    font-size: 0.68rem;
    line-height: 1.25;
    letter-spacing: 0.01em;
    text-align: center;
    color: #94a3b8;
    max-width: 7.5rem;
    margin: 0 auto;
    transition: color 0.4s ease;
}
.preloader-stage.is-active .preloader-stage-icon {
    filter: grayscale(0.2) opacity(0.95);
    border-color: color-mix(in srgb, var(--stage-accent) 55%, #94a3b8);
    animation: stageBlink 1.2s ease-in-out infinite;
}
.preloader-stage.is-active .preloader-stage-label { color: #334155; font-weight: 600; }
@keyframes stageBlink {
    0%, 100% { opacity: 0.7; transform: scale(0.97); box-shadow: 0 0 0 0 rgba(5,150,105,0.1); }
    50%      { opacity: 1;   transform: scale(1.04); box-shadow: 0 0 0 5px rgba(5,150,105,0.06); }
}
.preloader-stage.is-done .preloader-stage-icon,
.preloader-stage.is-warn .preloader-stage-icon,
.preloader-stage.is-error .preloader-stage-icon {
    filter: grayscale(0) opacity(1);
    background: #f4f7f5;
    border-color: var(--stage-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--stage-accent) 14%, transparent),
                0 0 14px var(--stage-glow);
    animation: stagePop 0.5s cubic-bezier(0.22, 1.4, 0.36, 1);
}
.preloader-stage.is-done .preloader-stage-label,
.preloader-stage.is-warn .preloader-stage-label,
.preloader-stage.is-error .preloader-stage-label { color: var(--stage-accent); }
.preloader-stage.is-warn  { --stage-accent: #fbbf24; --stage-glow: rgba(251,191,36,0.5); }
.preloader-stage.is-error { --stage-accent: #f87171; --stage-glow: rgba(248,113,113,0.5); }
@keyframes stagePop {
    0%   { transform: scale(0.72); }
    55%  { transform: scale(1.1); }
    100% { transform: scale(1); }
}
/* Name of the running stage — replaces the per-icon labels on narrow screens */
.preloader-stage-caption {
    font-size: 0.88rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #475569;
    text-align: center;
    max-width: 92vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Splash: the free services we stand on ---------------------------------------------
   A line that says what the marks are, then the official logos of the services the app
   really queries. **Logos only** — the names are not printed here (they wrapped into three
   lines on a phone, and the splash is not a menu): the names, the licences and the
   "why/where" live in Settings → API gratuite. Only logos that read at 22 px are painted
   (`splash` in data/free_apis.json). */
.preloader-apis-title {
    margin: 4px 0 0;
    max-width: 92vw;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: rgba(255, 255, 255, 0.62);
    text-align: center;
}
.preloader-apis {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 10px 18px;
    max-width: 92vw;
    margin-top: 8px;
}
.preloader-api {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: rgba(255, 255, 255, 0.9);
    /* One logo at a time, like a row of lamps: `--i` (set by _renderPreloaderApis) offsets
       each delay, so the light travels along the row while the boot rail settles. */
    opacity: 0.55;
    animation: preloader-api-glow 2.4s ease-in-out infinite;
    animation-delay: calc(var(--i, 0) * 420ms);
    will-change: opacity, filter, transform;
}
@keyframes preloader-api-glow {
    0%, 10%   { opacity: 0.55; filter: none; transform: scale(1); }
    16%, 26%  { opacity: 1; transform: scale(1.12);
                filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.85))
                        drop-shadow(0 0 10px var(--brand-primary, #10b981)); }
    40%, 100% { opacity: 0.55; filter: none; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .preloader-api { animation: none; opacity: 0.8; filter: none; transform: none; }
}
.preloader-api-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    height: 22px;
    padding: 0 5px;
    border-radius: 7px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.06);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.02em;
}
/* Official logos on the splash: small, square, no frame of their own (the icons already
   are the frame). The extra `.preloader-api` parent is on purpose: `surfaces.css` loads
   after this file and sets `.free-api-logo` to 28 px, so a bare class here would lose. */
.preloader-api .preloader-api-logo {
    width: 22px;
    height: 22px;
}
.preloader-api-logo img { border-radius: 5px; }
.preloader-api-logo .free-api-mark {
    min-width: 22px;
    height: 22px;
    padding: 0 3px;
    border-radius: 5px;
    font-size: 8px;
}

@media (min-width: 641px) {
    .preloader-stages { width: min(100% - 48px, 400px); }
    .preloader-stage-icon {
        width: 40px;
        height: 40px;
        font-size: 1.05rem;
    }
    /* The per-icon labels are readable here, so the caption would repeat them */
    .preloader-stage-caption { display: none; }
}
@media (max-width: 640px) {
    /* Icons only: the caption spells out the stage that is running */
    .preloader-stage-label {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}
@media (max-height: 720px) {
    .app-preloader-logo { height: 108px; }
}
@media (prefers-reduced-motion: reduce) {
    .preloader-stage.is-active .preloader-stage-icon,
    .preloader-stage.is-done .preloader-stage-icon,
    .preloader-stage.is-warn .preloader-stage-icon,
    .preloader-stage.is-error .preloader-stage-icon,
    .app-preloader-logo {
        animation: none !important;
    }
}
/* ── Boot diagnostic line (debug only) ─────────────────────────────────────
   THERE IS NO SECOND PROGRESS LINE. The rail already draws one: the connector
   behind the three dots fills left to right as `_preloaderStage()` raises
   `--preloader-progress`, so the 3 px bar that used to sit here was a
   duplicate — and, still coloured for the old DARK splash (a near-transparent
   white track, pale-green digits), on today's light canvas it survived as a
   stray line between the stage caption and the credits, with no readable words
   next to it. What a developer needs from `?debug=1` is the name of the check,
   so only the ticker is left, painted for a light background.
   `#preloader-progress-wrap` stays because `_runStartupCheck()` owns the
   visibility of that line (`display:none` unless `_bootDebug`). */
.preloader-progress-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: min(92vw, 520px);
    animation: zwFadeIn 0.25s ease;
}
.preloader-check-label { display: none; }

/* ── Status line: single element, opacity crossfade via JS ─────────── */
.check-ticker {
    width: 100%;
    min-height: 1.15rem;
    display: flex;
    align-items: center;
    justify-content: center;
}
.preloader-status-text {
    font-size: clamp(0.72rem, 1.9vw, 0.8rem);
    font-weight: 500;
    letter-spacing: 0.02em;
    /* Slate family: this text lives on the LIGHT splash (#f4f7f5). The pale
       green/amber/red it carried before belonged to the dark canvas and was
       invisible here — a diagnostic nobody can read is not a diagnostic. */
    color: #94a3b8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
    padding: 0 12px;
}
.preloader-status-text.state-ok    { color: #475569; }
.preloader-status-text.state-warn  { color: #b45309; }
.preloader-status-text.state-error { color: #b91c1c; }
.preloader-warnings {
    max-width: min(92vw, 600px);
    width: 100%;
    animation: zwFadeIn 0.3s ease;
}

/* ── Warning popup (auto-close 5s) ─────────────────────────── */
.startup-popup {
    border-radius: 12px;
    overflow: hidden;
    width: 100%;
}
.startup-popup-warn {
    background: rgba(30,20,0,0.85);
    border: 1px solid rgba(251,191,36,0.45);
}
.startup-popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 9px 14px 7px;
    font-size: 0.82rem;
    font-weight: 600;
    color: #fcd34d;
    gap: 8px;
}
.startup-popup-countdown {
    background: rgba(251,191,36,0.2);
    color: #fcd34d;
    border-radius: 50%;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    flex-shrink: 0;
}
.startup-popup-body {
    padding: 2px 14px 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.startup-warn-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.startup-warn-icon {
    font-size: 1rem;
    flex-shrink: 0;
    margin-top: 1px;
}
.startup-warn-body {
    font-size: 0.78rem;
    color: #d4c08a;
    line-height: 1.4;
}
.startup-warn-body strong {
    display: block;
    color: #fcd34d;
    font-size: 0.82rem;
    margin-bottom: 2px;
}
.startup-warn-body p {
    margin: 0;
    color: #c8a954;
}
.startup-popup-bar-wrap {
    height: 3px;
    background: rgba(251,191,36,0.15);
}
.startup-popup-bar {
    height: 3px;
    background: #fbbf24;
    width: 100%;
    will-change: width;
}

/* ── Error popup (blocking) ─────────────────────────────────── */
/* Keep .preloader-warn-badge for backward compat */
.preloader-warn-badge {
    background: rgba(251,191,36,0.15);
    color: #fcd34d;
    border: 1px solid rgba(251,191,36,0.35);
    border-radius: 99px;
    padding: 3px 10px;
    font-size: 0.71rem;
    white-space: nowrap;
}
.preloader-error-msg {
    color: #fca5a5;
    background: rgba(239,68,68,0.18);
    border: 1px solid rgba(239,68,68,0.4);
    border-radius: 12px;
    padding: 14px 18px;
    font-size: 0.80rem;
    text-align: left;
    max-width: 300px;
    line-height: 1.6;
    white-space: pre-line;
    animation: zwFadeIn 0.3s ease;
}
.preloader-error-msg strong {
    display: block;
    font-size: 0.9rem;
    color: #f87171;
    margin-bottom: 8px;
    text-align: center;
}
.preloader-retry-btn {
    background: #ef4444;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 9px 22px;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    animation: zwFadeIn 0.3s ease;
}
.preloader-retry-btn:active { opacity: 0.8; }
.header-logo-icon {
    height: 28px;
    width: auto;
    object-fit: contain;
    display: inline-block;
    vertical-align: middle;
    margin-right: 4px;
    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.3));
    /* The mark is the last thing that may give way: it is what still says which app
       this is when the name and the branch are gone. */
    flex: 0 0 auto;
}

.header-content {
    display: flex;
    align-items: center;
    width: 100%;
    position: relative;
    gap: 8px;
}

/* Kiosk-only buttons (exit, refresh) — empty/absent on normal browser */
.header-left {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
    position: relative;
    z-index: 1;
}

/* Title wrap — left-aligned by default; centered in kiosk mode */
.header-title-wrap {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    overflow: hidden;
}
.header-title-wrap > * {
    pointer-events: auto;
}

/* Kiosk mode: center title absolutely across full header width */
.kiosk-mode .header-title-wrap {
    position: absolute;
    left: 0;
    right: 0;
    flex: unset;
    justify-content: center;
    pointer-events: none;
}

.header-title {
    font-size: 1.3rem;
    font-weight: 700;
    cursor: pointer;
    display: flex;
    align-items: baseline;
    gap: 5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: auto;
    flex-shrink: 1;
    /* WITHOUT THIS THE MEASUREMENT LIES. As a flex item the default `min-width: auto`
       pins the row to its min-content width (the whole nowrap title), so it never
       shrank: it simply overflowed `.header-title-wrap`, which clips it. `scrollWidth`
       then equalled `clientWidth` at every viewport and `_paintKioskVersion()` had
       nothing to measure — which is how a phone ended up showing "E…" forever. */
    min-width: 0;
}

.header-version {
    font-size: 0.6rem;
    font-weight: 400;
    opacity: 0.7;
    letter-spacing: 0.03em;
}

/*
 * The demo marker, beside the logo. It used to carry its own inline style with cream text on
 * a translucent amber, written for the old dark header: on the white header the text was
 * invisible and the chip looked EMPTY. One class, theme-aware, like every other chip — the
 * amber says "sample data", the contrast says what it says.
 */
.header-demo-badge {
    display: inline-flex;
    align-items: center;
    padding: 1px 6px;
    border-radius: 6px;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    line-height: 1.5;
    white-space: nowrap;
    background: #FEF3C7;
    color: #92400E;
    border: 1px solid #F59E0B;
}
[data-theme="dark"] .header-demo-badge {
    background: rgba(251, 191, 36, 0.18);
    color: #FCD34D;
    border-color: rgba(251, 191, 36, 0.45);
}

/* The kiosk APK version, beside the app version and only when the row has room for it
   (`_paintKioskVersion()` hides it first, then the branch, never the app version).
   A dot separates the two so "v1.31.5" and "kiosk 1.7.26" are never read as one thing. */
.header-kiosk-version {
    font-size: 0.58rem;
    font-weight: 600;
    opacity: 0.62;
    letter-spacing: 0.02em;
    color: var(--primary, #10b981);
    white-space: nowrap;
}
.header-kiosk-version::before {
    content: '·';
    margin-right: 4px;
    opacity: 0.7;
    color: var(--text-muted, #64748b);
}
.header-kiosk-version[hidden] { display: none; }

/* When the header runs out of room it is the TITLE that gives way, never the versions: the
   household asked to always see at least the app version, and an ellipsised "EverShelf" still
   says which app this is. THE NAME GOES ENTIRELY, THOUGH, and only at the very end: an
   ellipsis that leaves "E…" (a 360 px phone) is not a shorter title, it is a broken one. The
   order is `_paintKioskVersion()`'s: kiosk label → branch → the name, and with the name gone
   the logo and the app version carry the row (the version is raised a notch, because it is
   then the only text up there). */
.header-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.header-title.is-name-hidden .header-name { display: none; }
.header-title.is-name-hidden .header-version {
    font-size: 0.72rem;
    font-weight: 500;
    opacity: 0.85;
}
.header-title .header-version,
.header-title .header-kiosk-version,
.header-title .header-branch { flex: 0 0 auto; }

/* Branch label beside the version: smaller and dimmer than the semver, ellipsised
   so a long branch name can never push the title out of the header. Refreshed by
   scripts/bump-version.sh; `.header-version` keeps ONLY the semver because
   reportError() reads its text as the app version. */
.header-branch {
    font-size: 0.52rem;
    font-weight: 400;
    opacity: 0.55;
    letter-spacing: 0.02em;
    margin-left: 0.4em;
    max-width: 9em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * An EMPTY branch label is a release build: `scripts/bump-version.sh` fills it from git only
 * on a feature branch and clears it on `main`/`develop`. An empty span still carries its
 * `margin-left`, i.e. a gap in the header — so an empty chip is not painted at all.
 */
.header-branch:empty,
.app-preloader-verchip-branch:empty,
.about-branch:empty { display: none; }

/* Same label in Settings → Info, next to the version line. */
.about-branch {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.66rem;
    opacity: 0.6;
    margin-left: 0.5em;
    letter-spacing: 0.02em;
}

/* Update badge — shown beside title, title stays intact */
.header-update-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: rgba(251,191,36,0.15);
    border: 1px solid rgba(251,191,36,0.45);
    border-radius: 20px;
    padding: 2px 6px 2px 5px;
    white-space: nowrap;
    flex-shrink: 0;
    animation: header-update-pulse 2s ease-in-out infinite;
}
.header-update-badge-label {
    font-size: 0.7rem;
    font-weight: 600;
    color: #fde68a;
}
.header-update-btn {
    background: #fbbf24;
    color: #1e293b;
    border: none;
    border-radius: 20px;
    padding: 2px 9px;
    font-size: 0.7rem;
    font-weight: 800;
    cursor: pointer;
    letter-spacing: 0.02em;
    transition: background 0.15s, transform 0.1s;
}
.header-update-btn:active {
    background: #f59e0b;
    transform: scale(0.96);
}
.header-update-close {
    background: none;
    border: none;
    color: rgba(255,255,255,0.5);
    font-size: 0.8rem;
    cursor: pointer;
    padding: 0;
    line-height: 1;
    display: flex;
    align-items: center;
}
@keyframes header-update-pulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.7; }
}

/* Actions — fixed-width, no stretching */
.header-actions {
    flex: 0 0 auto;
    margin-left: auto;
    display: flex;
    gap: 8px;
    align-items: center;
    position: relative;
    z-index: 1;
}

/* ── Base header button — all action icons use this ─────────────────── */
.header-btn {
    background: rgba(255,255,255,0.18);
    border: 1.5px solid rgba(255,255,255,0.28);
    color: white;
    font-size: 1.25rem;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, border-color 0.2s;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.header-btn:active {
    background: rgba(255,255,255,0.38);
}

/* Scan button — slightly larger + pulse to draw attention */
.header-scan-btn {
    background: rgba(255,255,255,0.28);
    border: 2px solid rgba(255,255,255,0.6);
    font-size: 1.35rem;
    width: 48px;
    height: 48px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.18);
    animation: pulse-scan 2s ease-in-out infinite;
    touch-action: manipulation; /* prevent 300ms delay and double-tap zoom on mobile */
}
.header-scan-btn:active {
    background: rgba(255,255,255,0.45);
    transform: scale(0.93);
}

/* ── Smart Scale status indicator ───────────────────────────────────── */
/* Scale emoji with a small colored status dot in the lower-right corner */
.scale-status-indicator {
    cursor: pointer;
}
.scale-icon-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
}
.scale-icon-emoji {
    font-size: 20px;
    line-height: 1;
    /* Force white icon regardless of connection status — only the dot changes color */
    filter: brightness(0) invert(1);
    opacity: 0.9;
}
.scale-status-dot {
    position: absolute;
    bottom: 1px;
    right: 0px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 1.5px solid rgba(0,0,0,0.35);
    background: #94a3b8;
    transition: background 0.4s, box-shadow 0.4s, border-color 0.4s;
    pointer-events: none;
}
/* Connected: white fill + bright-green border ring — clearly visible on any dark/green bg */
.scale-status-connected    .scale-status-dot { background: #ffffff; border-color: #4ade80; box-shadow: 0 0 0 1px rgba(0,0,0,0.25), 0 0 8px #4ade80cc, 0 0 2px #fff; }
.scale-status-searching    .scale-status-dot { background: #f59e0b; border-color: rgba(0,0,0,0.35); animation: scaleStatusPulse 1.4s infinite; }
.scale-status-disconnected .scale-status-dot { background: #64748b; border-color: rgba(0,0,0,0.35); }
.scale-status-disconnected .scale-icon-emoji  { opacity: 0.55; }
.scale-status-error        .scale-status-dot { background: #ef4444; border-color: rgba(0,0,0,0.35); box-shadow: 0 0 5px #ef4444aa; }
@keyframes scaleStatusPulse {
    0%, 100% { box-shadow: 0 0 3px #f59e0b88; }
    50%       { box-shadow: 0 0 9px #f59e0bcc; }
}

/* ── Scale read button (add/use forms) ──────────────────────────────── */
.scale-read-btn {
    width: 100%;
    margin-top: 8px !important;
    font-size: 0.88rem;
    padding: 8px 12px;
    border-radius: 10px;
    border: 1.5px dashed rgba(124,58,237,0.5);
    background: rgba(124,58,237,0.06);
    color: #7c3aed;
    font-weight: 600;
}
.scale-read-btn:active { background: rgba(124,58,237,0.15); }

/* ── Scale reading modal live display ──────────────────────────────── */
.scale-reading-live {
    font-size: 2.8rem;
    font-weight: 800;
    color: var(--accent, #7c3aed);
    letter-spacing: 0.04em;
    line-height: 1;
    padding: 12px 0;
}

/* Gemini button — indigo tint */
.header-gemini-btn {
    background: rgba(99,102,241,0.32);
    border-color: rgba(199,210,254,0.55);
}
.header-gemini-btn:active {
    background: rgba(99,102,241,0.55);
}

/* Spesa (shopping) mode — green tint when active */
.header-spesa-btn {
    background: rgba(34,197,94,0.22);
    border-color: rgba(187,247,208,0.55);
    font-size: 1.2rem;
}
.header-spesa-btn:active {
    background: rgba(34,197,94,0.42);
}
.header-spesa-btn.spesa-on {
    background: rgba(34,197,94,0.55);
    border-color: rgba(187,247,208,0.95);
    box-shadow: 0 0 0 2px rgba(34,197,94,0.35);
}

.header-gemini-btn.header-btn-no-ai {
    opacity: 0.45;
    filter: grayscale(0.7);
    border-color: rgba(255,255,255,0.22);
    background: rgba(255,255,255,0.1);
    position: relative;
}
.header-gemini-btn.header-btn-no-ai::after {
    content: '';
    position: absolute;
    bottom: 2px;
    right: 2px;
    width: 8px;
    height: 8px;
    background: #f59e0b;
    border-radius: 50%;
    border: 1.5px solid rgba(0,0,0,0.3);
}

.gemini-icon {
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.2));
}

/* (scan active is defined above in .header-scan-btn:active) */

/* ── Offline / server-unreachable banner (non-blocking strip) ─────────── */
.offline-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: #d97706;
    color: #fff;
    padding: 8px 14px;
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.35;
    position: sticky;
    top: 0;
    z-index: 950;
    box-shadow: 0 2px 8px rgba(217, 119, 6, 0.28);
    transition: opacity 0.4s, background 0.25s;
}
.offline-banner.is-synced {
    background: #059669;
    box-shadow: 0 2px 8px rgba(5, 150, 105, 0.28);
}
.offline-banner.is-fading { opacity: 0; }
.offline-banner-icon { font-size: 1rem; line-height: 1; flex: 0 0 auto; }
.offline-banner-text { flex: 1; text-align: center; }
.offline-banner-retry {
    background: rgba(255,255,255,0.22);
    border: 1px solid rgba(255,255,255,0.55);
    color: #fff;
    border-radius: 6px;
    padding: 3px 11px;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s;
}
.offline-banner-retry:hover { background: rgba(255,255,255,0.38); }
/* A green «Sincronizzato!» has nothing left to retry: the button belongs to the orange
   strip. `_paintOfflineStrip()` also hides it in JS — this keeps the two in step even if
   a stylesheet is the only thing that loads. */
.offline-banner.is-synced .offline-banner-retry,
.offline-banner-retry[hidden] { display: none; }

/* Pulsing dot shown in the banner while the offline cache is being read */
.offline-banner-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #fde68a;
    margin-right: 6px;
    vertical-align: middle;
    animation: offline-dot-pulse 1.1s ease-in-out infinite;
}
@keyframes offline-dot-pulse {
    0%, 100% { opacity: 0.3; transform: scale(0.8); }
    50%       { opacity: 1;   transform: scale(1.15); }
}

/* Never grey-out / lock the pantry on a Wi-Fi blip — the strip is enough. */
body.server-offline .app-content,
body.server-offline .bottom-nav {
    opacity: 1;
    pointer-events: auto;
    user-select: auto;
}
/* In offline-mode the app is usable; a soft left rail marks the mode. */
body.offline-mode .app-content {
    border-left: 3px solid rgba(217, 119, 6, 0.55);
}
body.offline-mode .offline-banner-retry {
    display: none;
}

/* Spesa mode banner */
.spesa-mode-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: linear-gradient(135deg, #f59e0b, #d97706);
    color: #fff;
    padding: 10px 16px;
    border-radius: var(--radius-sm);
    margin-bottom: 10px;
    font-weight: 600;
    font-size: 0.95rem;
    box-shadow: var(--shadow);
}
.spesa-banner-left {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.spesa-stat {
    font-size: 0.78rem;
    font-weight: 400;
    opacity: 0.92;
}
.spesa-mode-banner .btn {
    background: rgba(255,255,255,0.25);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.5);
    font-weight: 600;
    padding: 6px 14px;
    flex-shrink: 0;
}

/* Family sibling hint (spesa mode) — compact card with thumbnail */
.family-sibling-prompt {
    position: fixed;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9998;
    background: linear-gradient(145deg, #1e3a5f 0%, #0f2744 100%);
    color: #fff;
    border-radius: 14px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
    max-width: min(440px, calc(100vw - 20px));
    width: calc(100% - 20px);
    box-sizing: border-box;
    border: 1px solid rgba(255, 255, 255, 0.12);
    animation: family-sibling-in 0.22s ease-out;
}
@keyframes family-sibling-in {
    from { opacity: 0; transform: translateX(-50%) translateY(10px); }
    to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.family-sibling-prompt-body {
    display: flex;
    gap: 10px;
    align-items: flex-start;
}
.family-sibling-prompt-thumb {
    flex-shrink: 0;
    width: 52px;
    height: 52px;
    border-radius: 10px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.1);
    display: flex;
    align-items: center;
    justify-content: center;
}
.family-sibling-prompt-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.family-sibling-prompt-icon {
    font-size: 1.6rem;
    line-height: 1;
}
.family-sibling-prompt-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.family-sibling-prompt-title {
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.2;
    margin: 0;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: rgba(255, 255, 255, 0.85);
}
.family-sibling-prompt-name {
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.25;
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.family-sibling-prompt-stock {
    font-size: 1.05rem;
    font-weight: 800;
    line-height: 1.3;
    margin: 4px 0 0;
    color: #bbf7d0;
}
.family-sibling-prompt-meta {
    font-size: 0.8rem;
    line-height: 1.3;
    margin: 0;
    color: rgba(255, 255, 255, 0.78);
}
.family-sibling-prompt-question {
    font-size: 0.82rem;
    line-height: 1.25;
    margin: 2px 0 0;
    color: #f8fafc;
    font-weight: 600;
}
.family-sibling-prompt-actions {
    display: flex;
    gap: 8px;
}
.family-sibling-prompt-actions button {
    flex: 1;
    border: none;
    border-radius: 10px;
    padding: 9px 10px;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    min-height: 38px;
}
.family-sibling-prompt-yes {
    background: #22c55e;
    color: #fff;
}
.family-sibling-prompt-no {
    background: #475569;
    color: #fff;
}

@keyframes pulse-scan {
    0%, 100% { box-shadow: 0 2px 8px rgba(0,0,0,0.2); }
    50% { box-shadow: 0 2px 16px rgba(255,255,255,0.4); }
}

/* ===== MAIN CONTENT ===== */
.app-content {
    max-width: 600px;
    margin: 0 auto;
    padding: 12px;
    min-height: calc(100vh - var(--header-height) - var(--nav-height));
}

/* ===== PAGE MANAGEMENT ===== */
.page {
    display: none;
    animation: fadeIn 0.2s ease;
}

.page.active {
    display: block;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}
@keyframes inputShake {
    0%, 100% { transform: translateX(0); }
    20%       { transform: translateX(-6px); }
    40%       { transform: translateX(6px); }
    60%       { transform: translateX(-4px); }
    80%       { transform: translateX(4px); }
}
.input-shake { animation: inputShake 0.5s ease; border-color: var(--danger, #ef4444) !important; }

/* ===== PAGE HEADER ===== */
.page-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--border);
}

.page-header h2 {
    font-size: 1.2rem;
    font-weight: 700;
}

.back-btn {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 8px 14px;
    font-size: 0.95rem;
    color: var(--primary);
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.2s;
}

.back-btn:active {
    background: var(--border);
}

/* ===== DASHBOARD ===== */
.dashboard-stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}

.stat-card {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    text-align: center;
    box-shadow: var(--shadow);
    cursor: pointer;
    transition: transform 0.2s, box-shadow 0.2s;
    display: flex;
    flex-direction: column;
    gap: 4px;
    position: relative;
}

.stat-card:active {
    transform: scale(0.97);
    box-shadow: var(--shadow-lg);
}

.stat-icon {
    font-size: 2rem;
}

.stat-value {
    font-size: 2rem;
    font-weight: 800;
    color: var(--primary);
}

/* Skeleton shimmer while stat card data is loading */
@keyframes stat-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}
.stat-value.stat-loading {
    color: transparent !important;
    background: linear-gradient(90deg, var(--border) 25%, color-mix(in srgb, var(--border) 40%, white) 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: stat-shimmer 1.2s ease-in-out infinite;
    border-radius: 8px;
    min-width: 40px;
    min-height: 2.4rem;
    display: inline-block;
    vertical-align: middle;
    user-select: none;
}

.stat-label {
    font-size: 0.85rem;
    color: var(--text-light);
    font-weight: 600;
}

/* ===== ALERTS ===== */
.alert-section {
    background: #fef3c7;
    border: 2px solid var(--warning);
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 12px;
}

/* Quick recipe bar */
.quick-recipe-bar {
    margin-bottom: 12px;
}
.btn-quick-recipe {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 14px 16px;
    background: linear-gradient(135deg, #f97316, #ea580c);
    color: #fff;
    border: none;
    border-radius: var(--radius);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    text-align: left;
    box-shadow: 0 2px 8px rgba(249,115,22,0.3);
}
.btn-quick-recipe span:first-child { font-size: 1.3rem; }
.btn-quick-recipe .quick-recipe-text { flex: 1; }
.btn-quick-recipe span:last-child { font-size: 1.1rem; opacity: 0.8; }
.btn-quick-recipe:active { transform: scale(0.98); }

/* ── Anti-Waste Report Card — same structure as .alert-section ── */
#waste-chart-section {
    background: #f0fdf4;
    border: 2px solid #86efac;
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 12px;
}

/* Header row — mirrors .alert-section h3 */
.aw-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}
.aw-title-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.aw-title {
    font-size: 1.05rem;
    font-weight: 700;
    margin: 0;
    color: var(--text);
}

/* Live indicator dot */
.aw-live-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}
.aw-live-on {
    background: var(--success);
    animation: aw-pulse 2s ease-in-out infinite;
}
.aw-live-off { background: #9ca3af; }
@keyframes aw-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(34,197,94,.55); }
    60%  { box-shadow: 0 0 0 5px rgba(34,197,94,0); }
    100% { box-shadow: 0 0 0 0 rgba(34,197,94,0); }
}

/* Grade badge */
.aw-grade {
    display: inline-block;
    min-width: 30px;
    text-align: center;
    padding: 2px 7px;
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 900;
    color: #fff;
    cursor: default;
}
.aw-grade-ap { background: #16a34a; }
.aw-grade-a  { background: #22c55e; }
.aw-grade-b  { background: #f59e0b; }
.aw-grade-c  { background: #fb923c; }
.aw-grade-d  { background: #dc2626; }

/* ── Stacked single comparison bar ──────────────────────── */
.aw-cmp-wrap { margin-bottom: 10px; }
/* Track = the outer gray rail */
.aw-cmp-bar-track {
    position: relative;
    height: 18px;
    background: rgba(0,0,0,.07);
    border-radius: 9px;
    overflow: hidden;   /* clip both fills */
    margin-bottom: 5px;
}
/* Avg (orange) fills from the left — always the wider/background layer */
.aw-cmp-bar-fill-avg {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    border-radius: 9px;
    width: 0;
    background: linear-gradient(90deg, #fdba74, #f97316);
    transition: width 1.1s cubic-bezier(.4,0,.2,1);
    overflow: hidden;
}
/* Your bar (green) sits on top, same height */
.aw-cmp-bar-fill-you {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    border-radius: 9px;
    width: 0;
    background: linear-gradient(90deg, #4ade80, #16a34a);
    transition: width 1.1s cubic-bezier(.4,0,.2,1) 0.15s;
    z-index: 1;
    overflow: hidden;
}
/* Shimmer on both fills */
.aw-cmp-bar-fill-avg::after,
.aw-cmp-bar-fill-you::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.35) 50%, transparent 100%);
    animation: aw-shimmer 2.2s ease-in-out infinite;
    opacity: 0;
    transition: opacity 0.5s 1s;
}
.aw-cmp-bar-fill-avg.loaded::after,
.aw-cmp-bar-fill-you.loaded::after { opacity: 1; }
@keyframes aw-shimmer {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(200%); }
}
/* Labels row below the bar */
.aw-cmp-legend {
    display: flex;
    justify-content: space-between;
    font-size: 0.74rem;
    font-weight: 600;
    margin-bottom: 3px;
}
.aw-cmp-legend-you { color: #16a34a; }
.aw-cmp-legend-avg { color: #f97316; }
/* Inline status below bars */
.aw-status-inline {
    font-size: 0.75rem;
    font-weight: 600;
    margin: 2px 0 8px;
    padding: 0;
}
.aw-status-good { color: #16a34a; }
.aw-status-bad  { color: #dc2626; }
.aw-status-ok   { color: #b45309; }

/* ── Savings badges ─────────────────────────────────────── */
.aw-savings-row {
    display: flex;
    flex-wrap: nowrap;
    overflow: hidden;
    justify-content: center;
    gap: 6px;
    margin-bottom: 9px;
    transition: opacity 0.38s ease;
}
.aw-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: 10px;
    font-size: 0.78rem;
    font-weight: 600;
    border: 1px solid transparent;
    white-space: nowrap;
}
.aw-badge-icon { font-size: 0.92rem; flex-shrink: 0; }
.aw-badge-body {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.aw-badge-body b { font-size: 0.86rem; }
.aw-badge-body small { font-size: 0.66rem; font-weight: 500; opacity: .75; }
.aw-badge-rate   { background: #f5f3ff; color: #5b21b6; border-color: #c4b5fd; }
.aw-badge-money  { background: #fef9c3; color: #854d0e; border-color: #fde047; }
.aw-badge-meals  { background: #f0fdf4; color: #166534; border-color: #86efac; }
.aw-badge-co2    { background: #eff6ff; color: #1e40af; border-color: #93c5fd; }
.aw-badge-wasted { background: #fef2f2; color: #991b1b; border-color: #fca5a5; }
.aw-badge-better { background: #f0fdf4; color: #15803d; border-color: #4ade80; }

/* ── Trend mini-cards ───────────────────────────────────── */
.aw-trend-cards {
    display: flex;
    align-items: center;
    gap: 3px;
    margin-bottom: 7px;
}
.aw-tcard {
    flex: 1;
    padding: 5px 4px 4px;
    border-radius: 8px;
    text-align: center;
    border: 1px solid transparent;
}
.aw-tcard-good  { background: #f0fdf4; border-color: #86efac; }
.aw-tcard-ok    { background: #fffbeb; border-color: #fde68a; }
.aw-tcard-bad   { background: #fef2f2; border-color: #fca5a5; }
.aw-tcard-empty { background: var(--bg-main); border-color: var(--border); opacity: 0.45; }
.aw-tc-label {
    display: block;
    font-size: 0.63rem;
    color: var(--text-light);
    margin-bottom: 1px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.aw-tc-rate {
    display: block;
    font-size: 1.1rem;
    font-weight: 900;
    line-height: 1;
    margin-bottom: 4px;
}
.aw-tcard-good  .aw-tc-rate { color: #16a34a; }
.aw-tcard-ok    .aw-tc-rate { color: #b45309; }
.aw-tcard-bad   .aw-tc-rate { color: #dc2626; }
.aw-tcard-empty .aw-tc-rate { color: var(--text-light); }
.aw-tc-minibar { height: 3px; background: rgba(0,0,0,.08); border-radius: 2px; overflow: hidden; }
.aw-tc-minibar > div { height: 100%; border-radius: 2px; }
.aw-tcard-good  .aw-tc-minibar > div { background: var(--success); }
.aw-tcard-ok    .aw-tc-minibar > div { background: #f59e0b; }
.aw-tcard-bad   .aw-tc-minibar > div { background: var(--danger); }
.aw-tcard-empty .aw-tc-minibar > div { background: #d1d5db; }
.aw-tc-arrow { font-size: 0.9rem; flex-shrink: 0; padding: 0 1px; }
.aw-arrow-good { color: var(--success); }
.aw-arrow-bad  { color: var(--danger); }
.aw-arrow-ok   { color: var(--text-light); }

/* ── Rotating food-fact box ─────────────────────────────── */
.aw-fact-rotator {
    display: flex;
    align-items: flex-start;
    gap: 5px;
    padding: 5px 8px;
    background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
    border-radius: 7px;
    border-left: 2px solid #38bdf8;
    margin-bottom: 5px;
    min-height: 26px;
}
.aw-fact-icon { font-size: 0.76rem; flex-shrink: 0; padding-top: 1px; }
.aw-fact-text {
    font-size: 0.76rem;
    color: #0369a1;
    line-height: 1.4;
    flex: 1;
    transition: opacity 0.4s ease;
}
.aw-fact-fade { opacity: 0; }

/* Source footnote */
.aw-source {
    font-size: 0.58rem;
    color: #9ca3af;
    margin-top: 0;
    text-align: right;
}

.alert-section h3 {
    font-size: 1.05rem;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.alert-danger {
    background: #fee2e2;
    border-color: var(--danger);
}

.alert-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 12px;
    margin-bottom: 6px;
    background: rgba(255,255,255,0.7);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    gap: 8px;
}

.alert-item:last-child {
    margin-bottom: 0;
}

.alert-item-clickable {
    cursor: pointer;
    transition: background 0.15s, transform 0.1s;
}

.alert-item-clickable:active {
    background: rgba(255,255,255,0.95);
    transform: scale(0.98);
}

.alert-item-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
    min-width: 0;
}

.alert-item-name {
    font-weight: 600;
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.3;
}

.alert-item-brand {
    font-size: 0.8rem;
    color: var(--text-light);
}

.alert-item-badge {
    font-size: 0.8rem;
    font-weight: 700;
    padding: 4px 10px;
    border-radius: 20px;
    white-space: nowrap;
    flex-shrink: 0;
}

.alert-item-badge.expiring {
    background: var(--warning);
    color: #fff;
}

.alert-item-badge.expiring-soon {
    background: #ffc107;
    color: #333;
}

.alert-item-badge.expiring-later {
    background: #e0e0e0;
    color: #555;
}

.alert-item-badge.expired {
    background: var(--danger);
    color: #fff;
}

.alert-item-badge.today {
    background: var(--danger-light);
    color: #fff;
}

/* Safety badges for expired items */
.alert-item-badges {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
    flex-shrink: 0;
    max-width: 64%;
}

/* Name wraps; brand follows on the same flow when it fits. */
.alert-item-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 2px 6px;
    min-width: 0;
}
.alert-item-head .alert-item-name {
    flex: 1 1 12rem;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
}
.alert-item-head .alert-item-brand {
    flex: 0 1 auto;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Action buttons inside a dashboard row: tappable, 2-3 per line, never a stack. */
.alert-item-badges .btn-banner,
.alert-item-badges .btn-alert-extend {
    flex: 0 1 auto;
    min-width: 0;
    min-height: 34px;
    padding: 7px 12px;
    font-size: 0.82rem;
    line-height: 1.2;
}

.safety-badge {
    font-size: 0.72rem;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 12px;
    white-space: nowrap;
    cursor: help;
}

.safety-badge.safety-danger {
    background: #dc3545;
    color: #fff;
}

.safety-badge.safety-warning {
    background: #ffc107;
    color: #333;
}

.safety-badge.safety-ok {
    background: #28a745;
    color: #fff;
}

/* ===== SECTION CARD ===== */
.section-card {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow);
    margin-bottom: 12px;
}

.section-card h3 {
    font-size: 1rem;
    margin-bottom: 12px;
    color: var(--primary);
}

/* ===== LOCATION FILTER ===== */
/* One dropdown for the places, plus the medicine cabinet as its own always-visible pill:
   a row of tabs stops working at the fourth place, and a cabinet buried in a menu is a
   cabinet nobody opens. */
.location-tabs {
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 12px;
    margin-bottom: 8px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.location-tabs::-webkit-scrollbar { display: none; }

.location-tabs .tab { flex: 0 0 auto; }

.location-tabs .tab-medical {
    border-color: #6366f1;
    background: rgba(99, 102, 241, 0.10);
}

/* While another place is open the cabinet pill is removed from the strip (it sits BEFORE the
   dropdown, so it was the first thing on screen after opening the fridge). */
.location-tabs .tab[hidden] { display: none; }

/* The place dropdown: the pantry filter and the dashboard bar share one control —
   the same grammar in both places, so a native picker (which opens on touch) is what
   the household learns once. */
.location-tabs .location-select,
.location-bar .location-select {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 320px;
    padding: 9px 12px;
    border: 2px solid var(--border);
    border-radius: 25px;
    background: var(--bg-card);
    color: var(--text-main);
    font-size: 0.88rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    text-overflow: ellipsis;
}

.tab {
    background: var(--bg-card);
    border: 2px solid var(--border);
    border-radius: 25px;
    padding: 8px 16px;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: all 0.2s;
}

.tab.active {
    background: var(--primary);
    color: white;
    border-color: var(--primary);
}

.tab:active {
    transform: scale(0.95);
}

/* ===== SEARCH BAR ===== */
.search-bar {
    margin-bottom: 12px;
    position: relative;
}

.search-bar input {
    width: 100%;
    padding: 14px 44px 14px 16px;
    border-radius: var(--radius);
    border: 2px solid var(--border);
    background: var(--bg-card);
    font-size: 1rem;
    outline: none;
    transition: border-color 0.2s;
}

.search-bar input:focus {
    border-color: var(--primary);
}

.search-clear-btn {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: var(--border, #e5e7eb);
    color: var(--text-muted, #6b7280);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    z-index: 1;
}

.search-clear-btn:hover,
.search-clear-btn:focus-visible {
    background: var(--primary, #2563eb);
    color: #fff;
    outline: none;
}

.search-clear-btn[hidden] {
    display: none !important;
}

/* ===== INVENTORY PAGE: sticky toolbar + scrollable list =====
   Internal scroll (not body) so mobile WebViews cannot leave the list stuck
   on the first screen after opening from Home → Cibo & Cucina. */
#page-inventory.page.active {
    display: flex;
    flex-direction: column;
    max-height: calc(100dvh - var(--header-height) - var(--nav-height));
    min-height: 0;
    overflow: hidden;
    padding-bottom: 0;
}
#page-inventory .inv-toolbar {
    flex: 0 0 auto;
    position: sticky;
    top: 0;
    z-index: 6;
    /* Free on the page canvas — no closed card/gabbia around filters. */
    background: transparent;
    border: 0;
    box-shadow: none;
    padding-bottom: 6px;
}
#page-inventory .location-tabs {
    padding-bottom: 8px;
    margin-bottom: 4px;
    border: 0;
}
#page-inventory .search-bar {
    margin-bottom: 8px;
}
#page-inventory .search-bar input {
    border-radius: 999px;
    background: var(--bg-card, #fff);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.inv-view-chips {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 2px 0 10px;
    margin-bottom: 2px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.inv-view-chips::-webkit-scrollbar { display: none; }
.inv-view-chip {
    flex: 0 0 auto;
    min-height: 34px;
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, var(--bg-card));
    color: var(--text);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 650;
    cursor: pointer;
    white-space: nowrap;
}
.inv-view-chip.is-active {
    background: color-mix(in srgb, var(--brand-primary, #10b981) 16%, var(--surface-bg, #fff));
    border-color: color-mix(in srgb, var(--brand-primary, #10b981) 50%, var(--border));
    color: color-mix(in srgb, var(--brand-primary, #059669) 75%, var(--text));
}
/* Grouping switch (Categoria | Posizione): a quiet segmented control under the status chips —
   it reorders the same list, it does not filter it, so it must not compete with them. It shares
   the tools row with the stocktake pill (one of the two is ever visible). */
.inv-group-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 0;
    margin: 0;
}
.inv-group-bar[hidden] { display: none; }
.inv-group-label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-light);
}
.inv-group-switch {
    display: inline-flex;
    padding: 2px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, var(--border));
    background: color-mix(in srgb, var(--border) 30%, transparent);
    gap: 2px;
}
.inv-group-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 30px;
    padding: 4px 12px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 650;
    cursor: pointer;
    white-space: nowrap;
}
.inv-group-btn.is-active {
    background: var(--surface-bg, #fff);
    color: color-mix(in srgb, var(--brand-primary, #059669) 70%, var(--text));
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.10);
}
.inv-group-btn:focus-visible {
    outline: 2px solid var(--brand-primary, #10b981);
    outline-offset: 1px;
}
#page-inventory .inv-page-header {
    /* Compact context line — not a glass "Lista" card with admin icons. */
    background: transparent;
    border: 0;
    box-shadow: none;
    padding: 4px 2px 8px;
    margin-bottom: 4px;
}
#page-inventory .inv-page-header h2 {
    font-size: 1.05rem;
    font-weight: 750;
    line-height: 1.25;
    -webkit-text-fill-color: unset;
    background: none;
    color: var(--text);
}
#page-inventory .inv-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    /* Keep the last rows clear of the bottom nav. */
    padding-bottom: 88px;
}
/* ===== INVENTORY LIST ===== */
.inventory-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.inventory-item {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 0;
    box-shadow: var(--shadow);
    display: block;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.15s;
    /* Vertical pans scroll the list; the row never swallows them as a tap. */
    touch-action: pan-y;
}

.inventory-item.inv-opened-ok .inv-row-content {
    background: #e8f5e9;
}
.inventory-item.inv-opened-expiring .inv-row-content {
    background: #fff3e0;
}
.inventory-item.inv-opened-expired .inv-row-content {
    background: #ffebee;
}

.inv-opened-section {
    color: #2e7d32;
}

.inv-row-content {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px;
    background: var(--bg-card);
    position: relative;
    z-index: 2;
    will-change: transform;
    touch-action: pan-y;
}

.inv-swipe-bg {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 100%;
    display: flex;
    align-items: center;
    padding: 0 18px;
    font-size: 0.85rem;
    font-weight: 600;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 1;
    pointer-events: none;
}

.inv-swipe-bg-right {
    right: 0;
    justify-content: flex-start;
    background: rgba(59, 130, 246, 0.16);
    color: #1d4ed8;
}

.inventory-item.swipe-right .inv-swipe-bg-right {
    opacity: 1;
}

.inventory-list {
    touch-action: pan-y;
}

/* ===== Item detail modal (corporate) ===== */
.item-detail-modal {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.item-detail-modal .modal-header {
    margin-bottom: 0;
}

.item-detail-header {
    align-items: flex-start;
    gap: var(--es-space-sm);
}

.item-detail-header .item-detail-header-row {
    flex: 1 1 auto;
    min-width: 0;
}

.item-detail-title {
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.3;
    flex: 1;
    margin: 0;
}

.item-detail-header-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.item-detail-header-actions .btn-icon-round {
    width: 36px;
    height: 36px;
    border: 1px solid var(--border);
    border-radius: var(--es-radius-card);
    background: var(--bg-card);
    font-size: 1rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.item-detail-hero {
    display: flex;
    gap: var(--es-space-lg);
    padding: var(--es-space-lg);
    background: color-mix(in srgb, var(--bg-card) 92%, var(--primary) 8%);
    border: 1px solid var(--border);
    border-radius: var(--es-radius-card);
}

.item-detail-image {
    width: 72px;
    height: 72px;
    flex-shrink: 0;
    border-radius: var(--es-radius-card);
    overflow: hidden;
    background: var(--bg);
    display: flex;
    align-items: center;
    justify-content: center;
}

.item-detail-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.item-detail-emoji {
    font-size: 2.2rem;
    line-height: 1;
}

.item-detail-hero-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.item-detail-brand {
    font-size: 0.85rem;
    color: var(--text-light);
    margin: 0;
}

.item-detail-qty-pill {
    display: inline-block;
    align-self: flex-start;
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--primary);
    color: #fff;
    font-size: 0.9rem;
    font-weight: 700;
}

.item-detail-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.item-detail-chip {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--bg);
    color: var(--text-light);
    border: 1px solid var(--border);
}

.item-detail-chip--loc { background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary-dark); border-color: transparent; }
.item-detail-chip--danger { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); border-color: transparent; }
.item-detail-chip--warn { background: color-mix(in srgb, var(--warning) 18%, transparent); color: #b45309; border-color: transparent; }
.item-detail-chip--opened { background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); border-color: transparent; }
.item-detail-chip--vacuum { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); border-color: transparent; }

.item-detail-meta {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 0 4px;
}

.item-detail-meta-row {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.82rem;
    color: var(--text);
}

.item-detail-meta-label {
    color: var(--text-muted);
    flex-shrink: 0;
}

.item-detail-mono {
    font-family: ui-monospace, monospace;
    font-size: 0.78rem;
    word-break: break-all;
    text-align: right;
}

.item-detail-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding-top: 4px;
}

.item-detail-action {
    min-height: var(--es-btn-height-lg);
    border: none;
    border-radius: var(--es-radius-card);
    font-family: var(--es-font);
    font-size: 0.95rem;
    font-weight: 700;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 10px 8px;
    cursor: pointer;
    transition: transform 0.12s ease, opacity 0.12s ease;
    color: #fff;
}

.item-detail-action:active {
    transform: scale(0.97);
    opacity: 0.92;
}

.item-detail-action-icon {
    font-size: 1.35rem;
    line-height: 1;
}

.item-detail-action--use { background: linear-gradient(135deg, var(--es-action-use), var(--warning-light)); color: #1a1a1a; }
.item-detail-action--all { background: linear-gradient(135deg, var(--es-action-success), var(--success-light)); }
.item-detail-action--recipe { background: linear-gradient(135deg, var(--es-action-recipe), var(--accent-light)); }
.item-detail-action--throw { background: var(--bg-card); color: var(--es-action-danger); border: 1.5px solid color-mix(in srgb, var(--danger) 45%, transparent); }

.use-idle-hint {
    margin-top: 8px;
    text-align: center;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.inventory-item:active .inv-row-content {
    transform: none;
}

.inventory-item.row-holding .inv-row-content,
.product-item.row-holding,
.alert-item.row-holding,
.shop-row.row-holding .shop-row-content {
    transform: scale(0.985);
    opacity: 0.88;
    transition: transform 0.12s ease, opacity 0.12s ease;
}

.product-item,
.alert-item-clickable {
    touch-action: pan-y;
    -webkit-user-select: none;
    user-select: none;
}

.inv-image {
    width: 50px;
    height: 50px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    background: var(--bg);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
}

.inv-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

.inv-info {
    flex: 1;
    min-width: 0;
}

.inv-name {
    font-weight: 700;
    font-size: 1rem;
    /* Titles wrap to the row width — never a one-line ellipsis on a normal name. */
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.3;
}

.inv-brand {
    font-size: 0.8rem;
    color: var(--text-light);
}

.inventory-item.is-medical-row .inv-brand {
    font-size: 0.75rem;
    margin-top: 1px;
}

.inv-meta {
    display: flex;
    gap: 8px;
    margin-top: 4px;
    flex-wrap: wrap;
}

.inv-badge.badge-med-cat {
    background: #eef2ff;
    color: #4338ca;
}

.inv-badge.badge-sealed {
    background: #ecfdf5;
    color: #047857;
}

.inv-badge.badge-expiry-ok {
    background: #f1f5f9;
    color: #334155;
}

.inv-badge {
    font-size: 0.75rem;
    padding: 2px 8px;
    border-radius: 12px;
    font-weight: 600;
}

.badge-location {
    background: #dbeafe;
    color: #1d4ed8;
}

.badge-category {
    background: #f1f5f9;
    color: #475569;
}

.badge-qty {
    background: #d1fae5;
    color: #047857;
}

.badge-expiry {
    background: #fef3c7;
    color: #92400e;
}

.badge-expired {
    background: #fee2e2;
    color: #dc2626;
}

.inv-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.inv-action-btn {
    background: none;
    border: none;
    font-size: 1.2rem;
    cursor: pointer;
    padding: 4px;
    border-radius: 8px;
    transition: background 0.2s;
}

.inv-action-btn:active {
    background: var(--border);
}

/* ===== BUTTONS ===== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 20px;
    border: none;
    border-radius: var(--radius);
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    text-decoration: none;
    -webkit-user-select: none;
    user-select: none;
}

.btn:active {
    transform: scale(0.97);
}

.btn-large {
    padding: 16px 24px;
    font-size: 1.1rem;
    border-radius: var(--radius);
}

.btn-huge {
    padding: 28px 20px;
    font-size: 1.2rem;
    border-radius: 20px;
    flex: 1;
    flex-direction: column;
    min-height: 120px;
}

.btn-icon {
    font-size: 2.5rem;
}

.btn-text {
    text-align: center;
    line-height: 1.3;
}

.btn-text small {
    font-weight: 400;
    font-size: 0.8rem;
    opacity: 0.85;
}

.btn-primary {
    background: var(--brand-primary, #059669);
    color: white;
}

.btn-primary:active {
    background: var(--brand-primary-hover, #047857);
}

.btn-success {
    background: var(--success);
    color: white;
}

.btn-success:active {
    background: #15803d;
}

.btn-danger {
    background: var(--danger);
    color: white;
}

.btn-danger:active {
    background: #b91c1c;
}

.btn-warning {
    background: var(--warning);
    color: white;
}

#btn-report-bug {
    background: #f97316;
    color: #fff;
    border-color: #ea580c;
}
#btn-report-bug:hover {
    background: #ea580c;
    border-color: #c2410c;
}

.btn-secondary {
    background: var(--bg-card);
    color: var(--text);
    border: 2px solid var(--border);
}

/* The presumed answer of a "dove lo metto?" prompt: a bar that drains right→left with the
   seconds printed next to the label. A promise with nothing moving reads as a frozen app,
   so the countdown is always visible (same grammar as SHELFY's confirmation card). */
.move-countdown-btn {
    position: relative;
    overflow: hidden;
    transition: none;
}
.move-countdown-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 100%;
    pointer-events: none;
    background: rgba(45, 80, 22, 0.18);
    background: color-mix(in srgb, var(--brand-primary) 20%, transparent);
}
.move-countdown-label {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    justify-content: center;
    width: 100%;
}
.move-countdown-secs {
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    opacity: 0.7;
}
.move-countdown-btn.is-presumed,
.loc-btn.is-presumed {
    border-color: var(--brand-primary);
    color: var(--brand-primary);
}
.move-prompt-hint {
    margin: 0 0 12px;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-muted);
}

/* ===== SCALE LIVE BOX ===== */
.scale-live-box {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--bg-card);
    border: 1.5px solid var(--border);
    border-radius: 10px;
    padding: 8px 12px;
    margin-bottom: 10px;
}
.scale-live-icon {
    font-size: 1.3rem;
    flex-shrink: 0;
}
.scale-live-content {
    flex: 1;
    min-width: 0;
}
.scale-live-val {
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--text);
    line-height: 1.2;
}
.scale-live-label {
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: 2px;
}
.scale-live-progress {
    height: 3px;
    background: var(--border);
    border-radius: 2px;
    margin-top: 5px;
    overflow: hidden;
}
.scale-live-progress-bar {
    height: 100%;
    width: 0%;
    background: var(--accent, #7c3aed);
    border-radius: 2px;
    transition: none;
}
.scale-live-box.scale-low-weight {
    border-color: #dc2626;
}
.scale-low-weight .scale-live-val {
    color: #dc2626 !important;
    animation: scaleLowTextBlink 0.65s ease-in-out infinite alternate;
}
.scale-low-weight .scale-live-label {
    color: #dc2626 !important;
    font-weight: 600;
    animation: scaleLowTextBlink 0.65s ease-in-out infinite alternate;
}
@keyframes scaleLowTextBlink {
    from { opacity: 1; }
    to   { opacity: 0.2; }
}

.btn-accent {
    background: var(--accent);
    color: white;
}

.btn-accent:active {
    background: #6d28d9;
}

.full-width {
    width: 100%;
}

.mt-2 {
    margin-top: 12px;
}

/* ===== ACTION BUTTONS (Scan page) ===== */
.action-buttons {
    display: flex;
    gap: 12px;
    margin-top: 16px;
}

/* ===== FORMS =====
   Dense by default: every transactional form (add / use / product / edit sheet)
   shares one vertical rhythm — tight label→input gap, modest field padding,
   side-by-side pairs (expiry|vacuum, brand|category) via .form-pair / .form-row. */
.form {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.form-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
}

/* A group with nothing to choose (e.g. the location of a medicine, which can only live in
   its cabinet) is removed from the form: `display:flex` would otherwise defeat [hidden]. */
.form-group[hidden] { display: none; }

.form-group label,
.form-group > .edit-section-label {
    font-weight: 600;
    font-size: 0.8rem;
    line-height: 1.25;
    color: var(--text);
    margin: 0;
}

.form-input {
    width: 100%;
    padding: 9px 12px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.95rem;
    background: var(--bg-card);
    outline: none;
    transition: border-color 0.2s;
    -webkit-appearance: none;
    appearance: none;
    box-sizing: border-box;
}

.form-input:focus {
    border-color: var(--primary);
}

.form-row {
    display: flex;
    gap: 8px;
    align-items: flex-end;
}

/* Two fields on one row (expiry + vacuum, brand + category, …). When the
   second cell is hidden the first stretches full width. */
.form-pair {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 10px;
    align-items: flex-end;
}
.form-pair > .form-group,
.form-pair > .form-pair-cell {
    margin: 0;
    min-width: 0;
}
.form-pair > .form-pair-grow,
.form-pair > .form-group:first-child {
    flex: 1 1 12rem;
}
.form-pair > .form-pair-aside,
.form-pair > .form-group.form-pair-aside {
    flex: 0 1 auto;
    min-width: 8.5rem;
}
@media (max-width: 380px) {
    .form-pair { align-items: stretch; }
    .form-pair > .form-pair-aside,
    .form-pair > .form-group.form-pair-aside {
        flex: 1 1 100%;
        min-width: 0;
    }
}

.flex-1 {
    flex: 1;
}

/* ===== LOCATION SELECTOR ===== */
.location-selector {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
}

.loc-btn {
    background: var(--bg-card);
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 10px 8px;
    font-size: 0.92rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
}

.loc-btn.active {
    background: var(--primary);
    color: white;
    border-color: var(--primary);
}

.loc-btn:active {
    transform: scale(0.97);
}

.loc-btn-opened {
    border-color: #f59e0b;
    box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.15);
}

.loc-opened-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: #7a4b00;
    background: #fde68a;
    border: 1px solid #f59e0b;
}

.loc-btn.active .loc-opened-badge {
    color: #7a4b00;
    background: #fde68a;
    border-color: #f59e0b;
}

/* ===== QUANTITY CONTROL ===== */
/* A settings row with a stepper: label + explanation on the left, the [−] N [+] block on the
   right. The old markup stacked label, then the control on its own line and the hint UNDER it,
   which left an empty expanse of card to the right of the stepper (very visible on a tablet and
   on a desktop). Same grammar as `.toggle-row`: one line, space-between, centred. */
.settings-stepper-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 8px;
}
.settings-stepper-copy { flex: 1 1 220px; min-width: 0; }
.settings-stepper-copy .settings-hint { margin: 2px 0 0; }
.settings-stepper-control {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}
.settings-row-label {
    display: block;
    font-weight: 600;
    font-size: 0.8rem;
    line-height: 1.25;
    color: var(--text);
}
.settings-stepper-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
}
.settings-stepper-row .qty-control { flex: 0 0 auto; }
.settings-stepper-row .qty-input { width: 64px; text-align: center; }

.qty-control {
    display: flex;
    align-items: center;
    gap: 4px;
}

.qty-btn {
    width: 44px;
    height: 44px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
}

.qty-btn:active {
    background: var(--primary);
    color: white;
    border-color: var(--primary);
}

.qty-input {
    width: 80px;
    height: 44px;
    text-align: center;
    font-size: 1.2rem;
    font-weight: 700;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    outline: none;
    -webkit-appearance: none;
    -moz-appearance: textfield;
}

.qty-input:focus {
    border-color: var(--primary);
}

/* Unit lives inside the number box: [ − ] [ 10 g ] [ + ] — never a floating filled circle. */
.qty-control-with-unit {
    display: grid;
    grid-template-columns: 44px minmax(88px, 1fr) 44px;
    grid-template-areas: "minus value plus";
    align-items: center;
    gap: 8px;
    width: 100%;
    max-width: 280px;
}

.qty-control-with-unit .qty-control {
    display: contents;
}

.qty-control-with-unit .qty-btn:first-of-type { grid-area: minus; }
.qty-control-with-unit .qty-input {
    grid-area: value;
    width: 100%;
    padding-right: 2.4rem;
}
.qty-control-with-unit .qty-btn:last-of-type { grid-area: plus; }

.qty-unit-badge {
    grid-area: value;
    justify-self: end;
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
    height: auto;
    padding: 0 12px 0 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: var(--text-muted, #6b7280);
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: lowercase;
    white-space: nowrap;
    box-shadow: none;
    pointer-events: none;
    z-index: 1;
}

.qty-unit-badge.qty-unit-muted {
    background: transparent;
    color: var(--text-muted, #6b7280);
    border: none;
}

/* Positive "finished the pack" — emerald tint, never danger red. */
.use-all-btn,
.btn.use-all-btn {
    background: color-mix(in srgb, var(--brand-primary, #059669) 12%, #fff);
    color: var(--brand-primary-hover, #047857);
    border: 1.5px solid color-mix(in srgb, var(--brand-primary, #059669) 45%, transparent);
}
.use-all-btn:active,
.btn.use-all-btn:active {
    background: color-mix(in srgb, var(--brand-primary, #059669) 22%, #fff);
}
[data-theme="dark"] .use-all-btn,
[data-theme="dark"] .btn.use-all-btn {
    background: color-mix(in srgb, var(--brand-primary, #34D399) 18%, #1E293B);
    color: var(--brand-primary, #34D399);
}

/* ===== USE OPTIONS ===== */
.use-options {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.use-unit-switch {
    display: flex;
    gap: 0;
    margin-bottom: 12px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    border: 2px solid var(--primary);
}
.use-unit-btn {
    flex: 1;
    padding: 10px 12px;
    border: none;
    background: var(--bg);
    color: var(--text);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
}
.use-unit-btn.active {
    background: var(--primary);
    color: #fff;
}

.use-confirm-btn,
.use-all-btn {
    min-height: 52px;
    font-size: 1.02rem;
    font-weight: 700;
}
.use-all-btn {
    margin-top: 10px;
}
#page-use.is-medical-use #use-location-group,
#page-use.is-medical-use #btn-scale-use,
#page-use.is-medical-use #scale-live-box,
#page-use.is-medical-use #btn-use-recipe {
    display: none !important;
}
/* Medicines are never weighed — no scale CTA on the add form either. */
#page-add.is-medical-add #btn-scale-add {
    display: none !important;
}
#page-use .use-med-summary {
    margin: 8px 0 12px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, #6366f1 28%, var(--border, #e2e8f0));
    background: color-mix(in srgb, #6366f1 7%, var(--bg, #fff));
    font-size: 0.9rem;
}

/* —— Use-all safety confirm (checkbox + slide) —— */
.use-all-safety {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 4px 2px 8px;
    text-align: center;
}
.use-all-safety-banner {
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: #fff;
    background: linear-gradient(135deg, #b91c1c, #dc2626);
    border-radius: 12px;
    padding: 14px 12px;
    text-transform: uppercase;
}
.use-all-safety-headline {
    margin: 4px 0 0;
    font-size: 1.25rem;
    font-weight: 800;
    color: var(--danger, #dc2626);
    line-height: 1.25;
}
.use-all-safety-product {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--text);
}
.use-all-safety-qty {
    margin: 0;
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--danger, #dc2626);
}
.use-all-safety-warn {
    margin: 0;
    font-size: 0.92rem;
    color: var(--text-muted);
    line-height: 1.4;
}
.use-all-safety-check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    text-align: left;
    font-size: 0.95rem;
    font-weight: 600;
    padding: 12px;
    border: 2px solid var(--border);
    border-radius: 12px;
    background: var(--bg);
    cursor: pointer;
    user-select: none;
}
.use-all-safety-check input {
    width: 22px;
    height: 22px;
    margin-top: 2px;
    flex-shrink: 0;
    accent-color: var(--danger, #dc2626);
}
.slide-confirm {
    position: relative;
    user-select: none;
    touch-action: none;
    margin-top: 4px;
}
.slide-confirm.is-disabled {
    opacity: 0.45;
    pointer-events: none;
}
.slide-confirm-track {
    position: relative;
    height: 56px;
    border-radius: 999px;
    background: rgba(220, 38, 38, 0.12);
    border: 2px solid var(--danger, #dc2626);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.slide-confirm-label {
    position: relative;
    z-index: 1;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--danger, #dc2626);
    pointer-events: none;
    padding: 0 56px;
}
.slide-confirm-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 0;
    background: rgba(220, 38, 38, 0.28);
    z-index: 0;
}
.slide-confirm-thumb {
    position: absolute;
    left: 4px;
    top: 4px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--danger, #dc2626);
    color: #fff;
    font-size: 1.4rem;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    box-shadow: 0 2px 8px rgba(0,0,0,0.25);
    cursor: grab;
}
.slide-confirm-thumb:active {
    cursor: grabbing;
}
.slide-confirm.is-done .slide-confirm-track {
    background: #16a34a;
    border-color: #16a34a;
}
.slide-confirm.is-done .slide-confirm-label {
    color: #fff;
}
.slide-confirm.is-done .slide-confirm-thumb {
    background: #15803d;
}

.use-partial {
    background: var(--bg);
    border-radius: var(--radius);
    padding: 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.use-partial p {
    font-size: 0.9rem;
    color: var(--text-light);
}

/* Fraction quick-select for pz unit */
.pz-fraction-btns {
    width: 100%;
}
.pz-fraction-btns .form-hint {
    font-size: 0.82rem;
    color: var(--text-light);
    text-align: center;
    margin: 0 0 6px;
}
.fraction-btn-row {
    display: flex;
    gap: 6px;
}
.frac-btn {
    flex: 1;
    padding: 8px 4px;
    border: 2px solid var(--primary);
    background: transparent;
    color: var(--primary);
    border-radius: var(--radius-sm);
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.frac-btn.active {
    background: var(--primary);
    color: #fff;
}
.frac-btn:hover:not(.active) {
    background: var(--primary-light, rgba(74,158,255,0.12));
}

/* ===== SCANNER ===== */
/* Fit rail + stream + actions in one screen — no forced scroll to reach buttons */
body:has(#page-scan.active) .app-content {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - var(--header-height) - var(--nav-height) - env(safe-area-inset-bottom, 0px));
    max-height: calc(100dvh - var(--header-height) - var(--nav-height) - env(safe-area-inset-bottom, 0px));
    min-height: 0;
    overflow: hidden;
    padding-top: 8px;
    padding-bottom: 8px;
}
#page-scan.page.active {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    max-height: 100%;
    overflow: hidden;
    padding-bottom: 0;
}
#page-scan .page-header {
    flex-shrink: 0;
    margin-bottom: 6px;
    padding-bottom: 6px;
}
.scan-container {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}
/* Spesa session / name search may scroll in-page; AI match is a full overlay (below) */
#page-scan .spesa-session-list,
#page-scan .scan-search-sheet {
    flex-shrink: 1;
    min-height: 0;
    max-height: 30%;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* — Spesa chip nel page-header — */
.scan-spesa-chip {
    margin-left: auto;
    padding: 5px 12px;
    border-radius: 20px;
    border: 1.5px solid var(--primary);
    background: color-mix(in srgb, var(--primary) 10%, transparent);
    color: var(--primary);
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s;
}
.scan-spesa-chip:active { background: color-mix(in srgb, var(--primary) 20%, transparent); }

/* — Quick rail (favourites + recents) above stream — */
.scan-quick-rail {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex-shrink: 0;
    max-height: 22%;
    overflow: hidden;
}
.scan-quick-section {
    display: flex;
    align-items: center;
    gap: 6px;
    overflow: hidden;
    min-height: 0;
}
.scan-quick-label {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
    flex-shrink: 0;
}
.scan-quick-chips {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    flex: 1;
}
.scan-quick-chips::-webkit-scrollbar { display: none; }

/* Stream fills leftover height between rail and action bar */
.scanner-viewport {
    position: relative;
    width: 100%;
    flex: 1 1 0;
    /* The stream is the only thing that can give space back. It used to stop shrinking at
       120 px, so the moment the controls moved UNDER the picture (the status + torch/flip row,
       v1.31.4) the column no longer fit the one-screen height the page is locked to — and the
       last row (Identifica AI · Cerca · Manuale) ended up half behind the bottom nav, where it
       cannot be tapped. 72 px still shows a usable picture and keeps every control on screen. */
    min-height: 72px;
    max-height: none;
    aspect-ratio: unset;
    background: #000;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: var(--es-shadow-card, 0 4px 18px rgba(0,0,0,0.12));
}

/* Spesa: hide quick rail; keep action bar + session list */
#page-scan.spesa-scan-layout .scan-quick-rail {
    display: none !important;
}
#page-scan.spesa-scan-layout .scan-action-bar .scan-action-btn:not(.scan-action-ai) {
    display: none;
}

.spesa-session-list {
    margin: 10px 0 4px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.spesa-session-list-title {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text-muted);
    padding: 0 2px;
}
.spesa-session-item {
    display: grid;
    grid-template-columns: 1fr 1fr auto;
    gap: 6px;
    align-items: center;
    padding: 8px 10px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #e5e7eb);
    border-radius: 10px;
}
.spesa-session-item input {
    width: 100%;
    min-width: 0;
    border: 1px solid transparent;
    background: var(--bg-light, #f3f4f6);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 0.86rem;
}
.spesa-session-item input:focus {
    border-color: var(--accent, #2d5016);
    outline: none;
    background: #fff;
}
.spesa-session-item .spesa-session-qty {
    width: 4.5rem;
    text-align: right;
}
.spesa-session-empty {
    font-size: 0.85rem;
    color: var(--text-muted);
    text-align: center;
    padding: 6px;
}

/* Absolute fill — never letterbox / never show a half-size native play poster */
.scanner-viewport video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: #000;
    transform-origin: center center;
    transition: transform 0.2s ease;
}
.scanner-viewport video::-webkit-media-controls,
.scanner-viewport video::-webkit-media-controls-start-playback-button,
.scanner-viewport video::-webkit-media-controls-enclosure {
    display: none !important;
    -webkit-appearance: none;
    opacity: 0;
    pointer-events: none;
}
/* Solid black while stream is off — hides the browser's grey ▶ poster */
.scanner-viewport.scanner-off::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 5;
    background: #000;
    border-radius: inherit;
    pointer-events: none;
}

/* ── The camera stream carries ONE thing: the box on a read barcode ──────────
   Everything else that used to be drawn over the picture is gone: the moving scan
   line (three keyframes), the particle cloud, the pulsing ring, the drifting dots,
   the lookup spinner, the live digits, the green ✓ flash and the corner brackets.
   A viewfinder full of animation is noise while you aim, and on a low-end tablet
   it is a repaint per frame. What stays is the lock box: it appears when a code is
   actually read, and that is the feedback that matters. */
.scan-tracking-layer {
    position: absolute;
    inset: 0;
    z-index: 11;
    pointer-events: none;
}
.scan-lock-box {
    position: absolute;
    border: 2px solid #4ade80;
    border-radius: 10px;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
    background: rgba(74, 222, 128, 0.06);
    /* No animation: the box is placed where the code was read and stays put. */
    left: 50%;
    top: 50%;
    width: 60%;
    height: 20%;
    margin-left: -30%;
    margin-top: -10%;
    display: none;
}
.scan-lock-box[hidden] { display: none; }
.scan-lock-box.is-visible { display: block; }
.scan-lock-box.is-locked { border-width: 2.5px; }

/* ── Under the picture: status + the camera's own controls ───────────────────
   These used to float over the stream (a translucent chip at the top, buttons in a
dark gradient at the bottom). The stream now holds only the barcode box, and these
   live on the page background where they are easier to read and easier to hit. */
.scan-below-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 2px 0;
    flex-wrap: wrap;
    /* The controls under the picture never grow: the stream is what yields space, and the row
       that follows (`Identifica AI · Cerca · Manuale`) must never be pushed behind the nav. */
    flex: 0 0 auto;
}
.scan-viewport-left {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}
/* ── The scanner's action strip: three real buttons ──────────────────────────
 * These had NO styling at all, so the browser drew them: grey 3D borders, the default font, no
 * touch target, no pressed state — "grezzi" next to everything else in the app. They now follow
 * the house grammar: ONE emerald for the action that does the work (Identifica AI), neutral
 * secondaries for the other two, no pastel colours, `--touch-min` so a finger can hit them.
 * ========================================================================= */
.scan-action-bar {
    flex: 0 0 auto;
    display: flex;
    gap: 8px;
    margin-top: 8px;
}
.scan-action-btn {
    min-height: var(--touch-min, 44px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 10px;
    border-radius: var(--radius-sm, 10px);
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, var(--bg-card));
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.84rem;
    font-weight: 700;
    line-height: 1.1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: background 0.15s, border-color 0.15s, transform 0.08s;
}
.scan-action-btn:active {
    transform: scale(0.97);
    background: color-mix(in srgb, var(--surface-border, var(--border)) 55%, transparent);
}
/* The primary of the strip: the one that actually identifies something. */
.scan-action-btn.scan-action-ai {
    background: var(--brand-primary);
    border-color: var(--brand-primary);
    color: #fff;
}
.scan-action-btn.scan-action-ai:active {
    background: var(--brand-primary-hover, var(--brand-primary));
}
.scan-action-icon {
    font-size: 1rem;
    line-height: 1;
    flex: 0 0 auto;
}
.scan-action-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
    .scan-action-btn { transition: none; }
    .scan-action-btn:active { transform: none; }
}
/* Equal shares INSIDE the strip only: the medicine panel keeps a lone button of the same kind
   (`#scan-med-code-open`) as a direct child of the page, where `flex: 1 1 0` would make it grow
   vertically and eat the camera. */
.scan-action-bar > .scan-action-btn {
    flex: 1 1 0;
    min-width: 0;
}

.scan-ctrl-btn {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 50%;
    width: 40px;
    height: 40px;
    font-size: 1.05rem;
    color: var(--text-main);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.scan-ctrl-btn:active { background: var(--bg-muted, #e2e8f0); }
.scan-ctrl-btn.torch-on { background: rgba(255,214,0,0.28); border-color: #e6c200; }
.scan-ctrl-btn.spesa-on { background: rgba(34,197,94,0.18); border-color: rgba(34,197,94,0.85); }

.scan-status-bar {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    flex: 1 1 140px;
    min-width: 0;
}
.scan-status-method {
    font-size: 0.58rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-family: monospace;
}
.scan-status-method:empty { display: none; }
.scan-status-msg {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-main);
    max-width: 100%;
    overflow-wrap: anywhere;
    /* Two lines, never more: a long status ("Leggo i numeri sotto il codice…") used to wrap the
       row taller and push the action bar out of the one-screen height — the buttons then sat
       behind the bottom nav. The text is still complete, the layout is fixed. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.scan-status-msg:empty { visibility: hidden; }
.scan-status-msg.state-partial { color: #b45309; }
.scan-status-msg.state-invalid { color: #b91c1c; }
.scan-status-msg.state-confirmed { color: #047857; }
.scan-status-msg.state-retry { color: #b45309; }

/* — Scan result: full-page sheet over the camera (not a strip under the stream) — */
.scan-result {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow);
}
#page-scan .scan-result {
    position: absolute;
    inset: 0;
    z-index: 60;
    margin: 0;
    max-height: none;
    border-radius: 16px 16px 0 0;
    padding: 12px 14px 20px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    box-shadow: 0 -8px 28px rgba(0,0,0,0.18);
    background: var(--bg-main, var(--bg-card));
}
.scan-result-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-main, var(--bg-card));
}
.scan-result-sheet-title {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text);
}
.scan-result-sheet-close {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    border: 1.5px solid var(--border);
    background: var(--bg-card);
    color: var(--text);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

.scan-ai-match-box {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.scan-ai-hero {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px;
    background: linear-gradient(135deg, rgba(124,58,237,0.12), rgba(34,197,94,0.1));
    border-radius: 14px;
    border: 1px solid var(--border);
}
.scan-ai-hero-icon {
    font-size: 2.6rem;
    line-height: 1;
    flex-shrink: 0;
}
.scan-ai-hero-text {
    min-width: 0;
    flex: 1;
}
.scan-ai-match-title {
    font-size: 0.82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 4px;
}
.scan-ai-hero-name {
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.2;
    color: var(--text);
    word-break: break-word;
}
.scan-ai-hero-brand {
    font-size: 1rem;
    color: var(--text-muted);
    margin-top: 2px;
}
.scan-ai-action-hint {
    margin: -6px 0 0;
    font-size: 0.92rem;
    line-height: 1.4;
    color: var(--text-muted);
    text-align: center;
}
.scan-ai-or-divider {
    margin: 0;
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
}
.scan-ai-match-subtitle {
    font-size: 0.82rem;
    color: var(--text-muted);
}
.scan-ai-match-list-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.scan-ai-match-list-title {
    font-size: 0.88rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 700;
}
.scan-ai-match-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.scan-ai-candidate-item {
    border: 1px solid var(--border);
    background: var(--bg-main);
    border-radius: 12px;
    padding: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    text-align: left;
}
.scan-ai-candidate-item:active { transform: scale(0.99); }
.scan-ai-candidate-thumb {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-card);
    display: flex;
    align-items: center;
    justify-content: center;
}
.scan-ai-candidate-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.scan-ai-candidate-icon {
    font-size: 1.3rem;
    flex-shrink: 0;
}
.scan-ai-candidate-info {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
}
.scan-ai-candidate-name {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.scan-ai-candidate-meta {
    font-size: 0.84rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.scan-ai-candidate-cta {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--accent);
    border: 1px solid var(--accent);
    border-radius: 999px;
    padding: 6px 10px;
    flex-shrink: 0;
}
.scan-ai-match-empty {
    font-size: 0.86rem;
    color: var(--text-muted);
    background: var(--bg-main);
    border: 1px dashed var(--border);
    border-radius: 10px;
    padding: 10px 12px;
}
.scan-ai-add-btn {
    width: 100%;
    font-size: 1.15rem !important;
    font-weight: 800 !important;
    padding: 16px 20px !important;
    min-height: 54px;
    border-radius: 14px !important;
    box-shadow: 0 4px 14px rgba(34, 197, 94, 0.35);
}
.scan-ai-detected-label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.scan-ai-detected-pill {
    font-size: 0.8rem;
    color: var(--text-muted);
    background: var(--bg-main);
    border-radius: 999px;
    border: 1px solid var(--border);
    padding: 6px 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.scan-recent-chip,
.scan-fav-chip {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    background: var(--bg-card);
    border-radius: 20px;
    border: 1px solid var(--border);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    flex-shrink: 0;
    box-shadow: var(--shadow);
    transition: background 0.12s, transform 0.1s;
}
.scan-fav-chip {
    border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
    background: color-mix(in srgb, var(--primary) 8%, var(--bg-card));
}
.scan-recent-chip:active,
.scan-fav-chip:active { background: var(--bg-main); transform: scale(0.96); }
.scan-recent-chip-icon { font-size: 1rem; }

/* — Barcode / name input row (search sheet) — */
.barcode-input-row {
    display: flex;
    gap: 8px;
    align-items: center;
}
.barcode-input-row .form-input {
    flex: 1;
    margin: 0;
    font-size: 1.05rem;
}
.barcode-input-row .btn {
    white-space: nowrap;
    flex-shrink: 0;
}

.scan-num-ocr-btn { display: none !important; }

/* — Quick name results (dropdown inside name tab) — */
.quick-name-results {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 200px;
    overflow-y: auto;
}
.quick-name-result-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--bg-main);
    border-radius: calc(var(--radius) - 2px);
    border: 1px solid var(--border);
    cursor: pointer;
    transition: transform 0.1s;
}
.quick-name-result-item:active { transform: scale(0.98); }
.quick-name-result-item .qnr-icon { font-size: 1.4rem; flex-shrink: 0; }
.quick-name-result-item .qnr-info { flex: 1; min-width: 0; }
.quick-name-result-item .qnr-name {
    font-weight: 600;
    font-size: 0.92rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.quick-name-result-item .qnr-detail { font-size: 0.78rem; color: var(--text-muted); }
.quick-name-result-item.qnr-new {
    border: 1px dashed var(--accent);
    background: rgba(124,58,237,0.05);
}

/* ===== SHOPPING LIST (BRING!) ===== */
.shopping-container {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* ===== SHOPPING TABS ===== */
.shopping-tabs {
    display: flex;
    gap: 6px;
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 4px;
    box-shadow: var(--shadow);
}

.shopping-tab {
    flex: 1;
    padding: 9px 8px;
    border-radius: calc(var(--radius) - 2px);
    border: none;
    background: transparent;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    white-space: nowrap;
}

.shopping-tab.active {
    background: var(--accent);
    color: #fff;
    box-shadow: 0 2px 6px rgba(45, 80, 22, 0.25);
}

.shopping-tab-count {
    background: rgba(255,255,255,0.25);
    border-radius: 10px;
    padding: 1px 6px;
    font-size: 0.75rem;
    font-weight: 700;
}

.shopping-tab:not(.active) .shopping-tab-count {
    background: var(--bg);
    color: var(--accent);
}

.tab-panel-shopping {
    display: none;
}

.tab-panel-shopping.active {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* ===== SHOPPING ITEM ENHANCEMENTS ===== */
.shopping-item {
    cursor: pointer;
    transition: background 0.15s, transform 0.1s;
}

.shopping-item:active {
    transform: scale(0.99);
    background: #f0fdf4;
}

.shopping-item-name-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.shopping-item-scan-hint {
    font-size: 0.75rem;
    opacity: 0.4;
    flex-shrink: 0;
}

.shopping-item-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 3px;
}

/* Generic small item badge (sinv = shopping inventory) */
.sinv-badge {
    display: inline-block;
    font-size: 0.62rem;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 8px;
    white-space: nowrap;
    line-height: 1.6;
}

.badge-critical { background: #fee2e2; color: #dc2626; }
.badge-high     { background: #ffedd5; color: #c2410c; }
.badge-medium   { background: #fef9c3; color: #a16207; }
.badge-low      { background: #dcfce7; color: #15803d; }

.badge-freq-high { background: #fce7f3; color: #be185d; }
.badge-freq-med  { background: #ede9fe; color: #6d28d9; }
.badge-freq-low  { background: #f1f5f9; color: #64748b; }

.badge-local-tag { background: #e0f2fe; color: #0369a1; cursor: pointer; }
.badge-local-tag:hover { background: #bae6fd; }

/* ─── Shopping price badge ─── */
.shopping-item-price-badge {
    margin-top: 4px;
    min-height: 1.2rem;
}
.price-badge-value {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    color: #15803d;
    background: #dcfce7;
    border-radius: 8px;
    padding: 1px 7px;
    white-space: nowrap;
}
.price-badge-loading {
    display: inline-block;
    font-size: 0.7rem;
    color: #94a3b8;
    font-style: italic;
}
.price-badge-error {
    display: inline-block;
    font-size: 0.65rem;
    color: #94a3b8;
}

/* ─── Price column — right-side per-item price display ─── */
.shopping-item-price-col {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    flex-shrink: 0;
    min-width: 58px;
    text-align: right;
    padding: 0 4px;
}
.price-col-main {
    font-size: 1.05rem;
    font-weight: 700;
    color: #15803d;
    white-space: nowrap;
    line-height: 1.25;
}
.price-col-main.price-col-approx {
    color: #64748b;
    font-weight: 600;
}
.price-col-unit {
    font-size: 0.62rem;
    color: #94a3b8;
    white-space: nowrap;
    line-height: 1.2;
    margin-top: 1px;
}
.price-col-loading {
    font-size: 0.7rem;
    color: #cbd5e1;
    font-style: italic;
}
.price-col-error {
    font-size: 0.75rem;
    color: #cbd5e1;
}

/* ─── Price summary bar (top of shopping tab) ─── */
.shopping-price-total-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px 4px;
    background: linear-gradient(135deg, #f0fdf4, #dcfce7);
    border-radius: 10px;
    margin: 8px 0 4px;
    font-size: 0.88rem;
    font-weight: 600;
    color: #166534;
    box-shadow: 0 1px 4px rgba(21,128,61,0.08);
}
.price-total-label {
    flex: 1;
}
.price-total-value {
    font-size: 1rem;
    font-weight: 700;
}
.btn-price-refresh {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 0.85rem;
    padding: 2px 6px;
    border-radius: 6px;
    transition: background 0.15s;
}
.btn-price-refresh:hover { background: rgba(0,0,0,0.07); }
.btn-price-refresh:disabled { opacity: 0.5; cursor: default; }

/* Loading progress bar */
.price-loading-bar {
    height: 3px;
    background: #dcfce7;
    border-radius: 2px;
    overflow: hidden;
    margin: 0 12px 6px;
}
.price-loading-inner {
    height: 100%;
    width: 0%;
    background: #16a34a;
    border-radius: 2px;
    transition: width 0.3s ease;
}
@keyframes price-sweep {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(350%); }
}

/* Tag add button */
.shopping-item-tag-btn {
    background: none;
    border: none;
    font-size: 0.75rem;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    opacity: 0.5;
    transition: opacity 0.2s;
}
.shopping-item-tag-btn:hover { opacity: 1; }

/* Tag menu dropdown */
.shopping-tag-menu-container {
    margin-top: 6px;
    padding: 6px 8px;
    background: #f8fafc;
    border-radius: var(--radius);
    border: 1px solid var(--border);
}

.shopping-tag-menu {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.badge-tag-add {
    background: #f1f5f9;
    color: var(--text-secondary);
    border: 1px solid var(--border);
    cursor: pointer;
    transition: all 0.15s;
    padding: 2px 8px;
}

.badge-tag-add:hover, .badge-tag-add.active {
    background: #e0f2fe;
    color: #0369a1;
    border-color: #7dd3fc;
}

/* ===== SHOPPING SCAN TARGET BANNER ===== */
.shopping-scan-target-banner {
    background: linear-gradient(135deg, #FFF9C4, #FFF3CD);
    border: 1.5px solid #F59E0B;
    border-radius: var(--radius);
    padding: 12px 14px;
    margin: 0 0 4px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.shopping-scan-target-info {
    display: flex;
    align-items: center;
    gap: 8px;
}

.stb-label {
    font-size: 0.8rem;
    color: #92400e;
    font-weight: 600;
    white-space: nowrap;
}

.stb-name {
    font-size: 0.95rem;
    font-weight: 700;
    color: #78350f;
}

.shopping-scan-target-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.stb-btn {
    flex: 1;
    padding: 8px 10px;
    font-size: 0.82rem;
    min-width: 120px;
}


.bring-loading {
    text-align: center;
    padding: 30px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.bring-error {
    text-align: center;
    padding: 20px;
    background: #fef2f2;
    color: #dc2626;
    border-radius: var(--radius);
    font-size: 0.9rem;
}

.shopping-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.shopping-section-header h3 {
    font-size: 1rem;
    margin: 0;
}

.shopping-count {
    background: var(--accent);
    color: #fff;
    border-radius: 50%;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
}

.shopping-items {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Shopping list rows — readable on mobile */
.shop-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin: 14px 0 6px;
    padding: 8px 4px;
    border: none;
    background: transparent;
    font-size: 0.88rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    cursor: pointer;
}
.shop-section-meta {
    display: flex;
    align-items: center;
    gap: 6px;
}
.shop-section-cnt {
    font-size: 0.72rem;
    background: var(--bg-muted, rgba(0,0,0,0.06));
    padding: 1px 6px;
    border-radius: 999px;
}
.shop-section-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 8px;
}
/* The shopping row is the card of the pantry and the Home: ONE grammar, defined in
   `surfaces.css` (`.shop-row` + `--row-photo-w`, 62 px text block, 34 px action line). The
   urgency lives in the state pill (`.shop-row-badge`) — the coloured rail this layer used to
   paint is gone. */
/* A shopping row wears no urgency rail: the pill says it (`surfaces.css`). */
/* The moving layer of the swipe is transparent: the card itself is the paper (`surfaces.css`). */
.shop-row-content {
    position: relative;
    z-index: 1;
    will-change: transform;
}
.shop-row-visual {
    position: relative;
    flex-shrink: 0;
    width: 52px;
    height: 52px;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.25);
}
.shop-row-visual-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    opacity: 0.22;
    transform: scale(1.08);
}
.shop-row-visual-bg--cat.cat-verdura { background: linear-gradient(145deg, rgba(74,222,128,0.45), rgba(22,163,74,0.15)); opacity: 1; }
.shop-row-visual-bg--cat.cat-frutta { background: linear-gradient(145deg, rgba(251,146,60,0.45), rgba(234,88,12,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-latticini { background: linear-gradient(145deg, rgba(147,197,253,0.5), rgba(59,130,246,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-carne { background: linear-gradient(145deg, rgba(252,165,165,0.5), rgba(239,68,68,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-pesce { background: linear-gradient(145deg, rgba(125,211,252,0.5), rgba(14,165,233,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-pane { background: linear-gradient(145deg, rgba(253,230,138,0.55), rgba(217,119,6,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-snack { background: linear-gradient(145deg, rgba(253,186,116,0.5), rgba(249,115,22,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-bevande { background: linear-gradient(145deg, rgba(196,181,253,0.45), rgba(139,92,246,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-pasta { background: linear-gradient(145deg, rgba(254,215,170,0.55), rgba(234,88,12,0.1)); opacity: 1; }
.shop-row-visual-bg--cat.cat-conserve { background: linear-gradient(145deg, rgba(252,211,77,0.45), rgba(202,138,4,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-surgelati { background: linear-gradient(145deg, rgba(186,230,253,0.55), rgba(56,189,248,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-cereali { background: linear-gradient(145deg, rgba(217,249,157,0.5), rgba(132,204,22,0.12)); opacity: 1; }
.shop-row-visual-bg--cat.cat-condimenti { background: linear-gradient(145deg, rgba(254,240,138,0.5), rgba(202,138,4,0.1)); opacity: 1; }
.shop-row-visual-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0.28;
}
.shop-row-visual-icon {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    font-size: 1.65rem;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.15));
}
.shop-row-swipe-bg {
    position: absolute;
    top: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    padding: 0 14px;
    font-size: 0.72rem;
    font-weight: 700;
    color: #fff;
    z-index: 0;
}
.shop-row-swipe-bg-right {
    left: 0;
    right: 50%;
    justify-content: flex-start;
    /* Revealed by swiping RIGHT = "non lo compro": a dismiss is neutral, it never
       writes stock and it comes back on its own in two weeks. */
    background: #94a3b8;
    opacity: 0;
    transition: opacity 0.15s;
}
.shopping-plan-days-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    margin-bottom: 8px;
    background: var(--bg-card);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    font-size: 0.82rem;
}
.shopping-plan-days-hint {
    display: block;
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: 2px;
}
.shopping-plan-days-controls {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}
.shopping-plan-days-input-wrap {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.shopping-plan-days-input {
    width: 3rem;
    padding: 4px 6px;
    border: 1px solid var(--border, #cbd5e1);
    border-radius: 6px;
    font-size: 0.88rem;
    font-weight: 700;
    text-align: center;
    background: var(--bg);
}
.shop-plan-reset {
    padding: 4px 8px;
    border: none;
    border-radius: 6px;
    background: var(--bg-muted, #e2e8f0);
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
}
.shop-row-swipe-bg-left {
    right: 0;
    left: 50%;
    justify-content: flex-end;
    /* Revealed by swiping LEFT = "comprato": this is the gesture that writes the outcome,
       so it wears the one emerald of the row. */
    background: var(--brand-primary);
    opacity: 0;
    transition: opacity 0.15s;
}
.shop-row.swipe-right .shop-row-swipe-bg-right { opacity: 1; }
.shop-row.swipe-left .shop-row-swipe-bg-left { opacity: 1; }
/* The anti-waste advice beside the suggested quantity: emerald, because nothing has
   been lost yet — it is the smaller number that avoids losing it. Never red. */
.shop-row-waste-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 7px;
    border-radius: 9999px;
    border: 1px solid color-mix(in srgb, var(--brand-primary) 35%, transparent);
    background: color-mix(in srgb, var(--brand-primary) 10%, transparent);
    color: var(--brand-primary);
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
}
.shop-row-waste-hint {
    margin-top: 2px;
    font-size: 0.72rem;
    line-height: 1.35;
    color: var(--text-muted);
}
.shop-row-suggest .shop-row-swipe-bg-right {
    right: 0;
    background: rgba(45, 80, 22, 0.85);
}
.shop-row-swipe-hint {
    font-size: 0.78rem;
    color: var(--text-muted);
    opacity: 0.72;
    margin-top: 6px;
    line-height: 1.3;
}

/* ── A shopping row is a ROW, not a card ─────────────────────────────────────────
 * 58 products with nothing but aisle grouping is a wall, and a row carrying a stepper
 * and two 46 px buttons is 140 px tall: fifty-eight of those is a page nobody reaches
 * the end of. The suggested quantity is confirmed by default (tap the number for a
 * micro-popover), the two answers are a swipe — or a discreet ✓ / ✕ on a device with a
 * mouse — and the row stays at 68–72 px.
 */
.shop-row-content {
    padding: 8px 10px;
}
.shop-row-visual {
    width: 44px;
    height: 44px;
    min-width: 44px;
    border-radius: 10px;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-app, #f1f5f9);
    border: 1px solid var(--surface-border, #e2e8f0);
}
/* No photo: the aisle's emoji, on the same neutral frame — never a pastel square that
   reads as a broken image. */
.shop-row-visual--emoji span {
    font-size: 26px;
    line-height: 1;
    filter: saturate(1.05);
}
.shop-row-title {
    align-items: center;
    gap: 8px;
}
.shop-row-title-name {
    flex: 1 1 auto;
}
/* The quantity pill is the pantry's (`surfaces.css`). */
.shop-row-dot { opacity: 0.45; }
/* The frequency is a tooltip on the meta line now (`_shopRowFrequencyLabel`). */
.shop-row-stock { font-weight: 650; }
.shop-row-stock.is-empty { color: #b91c1c; }
/* The two actions of a shopping row are the Home's (`✓` + `✕`), styled in `surfaces.css`. */

/* Micro-popover of the buy quantity (opened by tapping the number). */
.shop-qty-popover {
    position: absolute;
    z-index: 60000;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-radius: 12px;
    background: var(--surface-bg, #fff);
    border: 1px solid var(--surface-border, #e2e8f0);
    box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
}
.shop-qty-pop-btn {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: var(--surface-bg, #fff);
    font-size: 1.15rem;
    font-weight: 800;
    line-height: 1;
    cursor: pointer;
    touch-action: manipulation;
}
.shop-qty-pop-value {
    min-width: 64px;
    text-align: center;
    font-weight: 800;
    font-size: 1rem;
}

/* ── The list's waiting state ───────────────────────────────────────────────────────
 * SHELFY on the same breathing ring as the splash, over skeleton rows that already
 * have the shape of the list. A bare spinner in a status line left the page looking
 * empty; this says "the list is coming, and it will look like this".
 * The same component serves every list (`_listSkeletonHtml()`): the shopping list kept the
 * `shop-*` names, the pantry and the Home use `list-*` — one set of rules, two aliases.
 */
.shop-loading,
.list-loading {
    padding: 18px 6px 10px;
}
.shop-loading-head,
.list-loading-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.shop-loading-avatar-wrap,
.list-loading-avatar-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    flex: 0 0 auto;
}
.shop-loading-avatar,
.list-loading-avatar {
    width: 44px;
    height: 44px;
    object-fit: contain;
    filter: drop-shadow(0 4px 10px rgba(5, 150, 105, 0.22));
    animation: preloader-shelfy-float 3.4s ease-in-out infinite;
}
.shop-loading-ring,
.list-loading-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid rgba(5, 150, 105, 0.35);
    animation: preloader-shelfy-ring 2.6s ease-out infinite;
    pointer-events: none;
}
.shop-loading-text,
.list-loading-text {
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--text-muted, #475569);
}
.shop-loading-rows,
.list-loading-rows { display: flex; flex-direction: column; gap: 8px; }
.shop-skel-row,
.list-skel-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--surface-bg, #fff);
    border: 1px solid var(--surface-border, #e2e8f0);
}
.shop-skel-thumb,
.shop-skel-lines i,
.list-skel-thumb,
.list-skel-lines i {
    display: block;
    border-radius: 8px;
    background: linear-gradient(90deg,
        rgba(148, 163, 184, 0.16) 0%,
        rgba(148, 163, 184, 0.30) 40%,
        rgba(148, 163, 184, 0.16) 80%);
    background-size: 220% 100%;
    animation: shopSkelShimmer 1.4s ease-in-out infinite;
}
.shop-skel-thumb,
.list-skel-thumb { width: 40px; height: 40px; flex: 0 0 auto; }
.shop-skel-lines,
.list-skel-lines { flex: 1 1 auto; display: flex; flex-direction: column; gap: 6px; }
.shop-skel-lines i,
.list-skel-lines i { height: 11px; }
.shop-skel-lines i.w70,
.list-skel-lines i.w70 { width: 70%; }
.shop-skel-lines i.w45,
.list-skel-lines i.w45 { width: 45%; }
@keyframes shopSkelShimmer {
    0%   { background-position: 120% 0; }
    100% { background-position: -120% 0; }
}
/* A remote picture takes a moment (and Open Food Facts is a foreign host): the frame shimmers
   while it travels, so a row never shows an empty square that looks like a missing product.
   `is-loading` is removed by the image's own `onload`/`onerror`. */
.product-thumb.is-loading,
.inv-image.is-loading,
.item-detail-image.is-loading {
    background-image: linear-gradient(90deg,
        rgba(148, 163, 184, 0.16) 0%,
        rgba(148, 163, 184, 0.30) 40%,
        rgba(148, 163, 184, 0.16) 80%);
    background-size: 220% 100%;
    background-color: var(--bg-app, #f8fafc);
    animation: shopSkelShimmer 1.4s ease-in-out infinite;
}
/* While the prices are being recomputed the figure breathes instead of freezing on "…". */
#shopping-price-bar.is-computing .price-total-value {
    opacity: 0.55;
    animation: shopSkelBreathe 1.2s ease-in-out infinite;
}
@keyframes shopSkelBreathe {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 0.85; }
}
@media (prefers-reduced-motion: reduce) {
    .shop-loading-avatar,
    .shop-loading-ring,
    .shop-skel-thumb,
    .shop-skel-lines i,
    .list-loading-avatar,
    .list-loading-ring,
    .list-skel-thumb,
    .list-skel-lines i,
    .product-thumb.is-loading,
    .inv-image.is-loading,
    .item-detail-image.is-loading,
    #shopping-price-bar.is-computing .price-total-value { animation: none; }
}

/* Search: the way into a list of 70 rows that is not scrolling. */
.shop-search-row {
    flex: 0 0 auto;
    display: flex;
    margin-bottom: 2px;
}
.shop-search-input {
    flex: 1 1 auto;
    min-height: 44px;
    padding: 0 14px;
    border-radius: 12px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: var(--surface-bg, #fff);
    color: var(--text-main, #0f172a);
    font-size: 1rem;
    -webkit-appearance: none;
    appearance: none;
}
.shop-search-input::placeholder { color: var(--text-muted, #94a3b8); }
.shop-search-input:focus {
    outline: none;
    border-color: var(--brand-primary, #059669);
    box-shadow: 0 0 0 3px rgba(5, 150, 105, 0.15);
}

/* Priority pills of the shopping list. */
.shop-filter-row {
    display: flex;
    /* A scrolling row inside a column flexbox is SHRUNK by the layout algorithm:
       without this the pills are cut in half and read as a hidden button. */
    flex: 0 0 auto;
    min-height: 46px;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 8px 2px 6px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.shop-filter-row::-webkit-scrollbar { display: none; }
.shop-filter-pill {
    flex: 0 0 auto;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: var(--surface-bg, #fff);
    color: var(--text-main, #0f172a);
    font-size: 0.9rem;
    font-weight: 650;
    cursor: pointer;
    touch-action: manipulation;
    white-space: nowrap;
}
.shop-filter-pill.is-active {
    background: var(--brand-primary, #059669);
    border-color: var(--brand-primary, #059669);
    color: #fff;
}
.shop-filter-count {
    font-variant-numeric: tabular-nums;
    opacity: 0.8;
    font-weight: 800;
}

/* One header line: money on the left, horizon on the right. */
.shop-head-row {
    display: flex;
    align-items: center;
    gap: 10px;
    /* One row: money on the left, horizon on the right. They only stack when there is
       genuinely no room (a phone), never to fill a wide screen with two half-empty
       boxes. */
    flex-wrap: nowrap;
    flex: 0 0 auto;
    margin-bottom: 2px;
}
@media (max-width: 620px) {
    .shop-head-row { flex-wrap: wrap; }
    .shop-head-row #shopping-price-bar,
    .shop-head-row .shopping-plan-days-bar { flex: 1 1 100%; }
}
.shop-head-row #shopping-price-bar { flex: 1 1 200px; }
/* The horizon is ONE line: the sentence, the number, the unit and the reset sit on the
   same baseline. It used to stack a title, an explanatory sentence and a control row —
   the tallest thing in a header where the products should be. */
.shop-head-row .shopping-plan-days-bar {
    flex: 1 1 240px;
    margin: 0;
    padding: 8px 12px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: nowrap;
    gap: 8px;
    box-shadow: var(--shadow);
}
.shopping-plan-days-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text-muted, #475569);
    font-size: 0.84rem;
    font-weight: 600;
}
.shopping-plan-days-label strong { color: var(--text-main, #0f172a); font-weight: 800; }
.shopping-plan-days-input-wrap {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
}
.shopping-plan-days-unit {
    font-size: 0.8rem;
    color: var(--text-muted, #64748b);
}
.shop-plan-reset {
    flex: 0 0 auto;
    min-height: 32px;
    padding: 0 10px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: var(--surface-bg, #fff);
    color: var(--text-muted, #475569);
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
    touch-action: manipulation;
    white-space: nowrap;
}
/* A phone has no room for a sentence and three controls on one line — so the sentence
   SHRINKS. Hiding it left a bare "10 gg" in a box, which says nothing at all. */
@media (max-width: 620px) {
    .shop-head-row .shopping-plan-days-bar { justify-content: space-between; }
    .shopping-plan-days-label {
        font-size: 0.74rem;
        flex: 1 1 auto;
        min-width: 0;
    }
    .shopping-plan-days-input { width: 52px; }
}

/* "Suggeriti": the rarely bought products, out of the way and one tap each. */
.smart-suggested {
    margin-top: 14px;
    border-top: 1px dashed var(--surface-border, #e2e8f0);
    padding-top: 10px;
}
.smart-suggested > summary {
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--text-muted, #475569);
    list-style: none;
    padding: 6px 0;
}
.smart-suggested > summary::-webkit-details-marker { display: none; }
.smart-suggested > summary::before { content: '▸ '; }
.smart-suggested[open] > summary::before { content: '▾ '; }
.smart-suggested-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 4px 0 8px;
}
.smart-suggested-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 0 12px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: var(--surface-bg, #fff);
    color: var(--text-main, #0f172a);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    touch-action: manipulation;
}
.smart-suggested-chip:active { background: var(--bg-app, #f1f5f9); }
.smart-suggested-qty {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-muted, #64748b);
}
/* (the old stepper + big button styles lived here: the row is a ROW now) */

.shop-row-main {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}
.shop-row-text {
    flex: 1;
    min-width: 0;
}
.shop-row-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    font-weight: 650;
    font-size: 1.15rem;
    line-height: 1.35;
}

.shop-row-title-name {
    flex: 1;
    min-width: 0;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
    line-height: 1.3;
}
.shop-row-qty {
    flex-shrink: 0;
    font-weight: 800;
    font-size: 1.15rem;
    color: var(--accent);
    white-space: nowrap;
    text-align: right;
}
.shop-row-qty-antiwaste {
    font-size: 0.85em;
    font-weight: 600;
    opacity: 0.85;
    margin-left: 2px;
}
.shop-row-sub {
    font-size: 0.92rem;
    color: var(--text-muted);
    line-height: 1.35;
    margin-top: 5px;
}
.shop-row-sub.shopping-pantry-hint {
    color: #64748b;
    font-style: italic;
}
.shop-row-price {
    flex-shrink: 0;
    text-align: right;
    min-width: 3.5rem;
    cursor: pointer;
    align-self: center;
}
.shop-row-price .price-col-main {
    font-size: 1.15rem;
    font-weight: 800;
    line-height: 1.25;
    color: var(--text);
}
.shop-row-price .price-col-unit {
    display: none;
}
.shop-row-suggest .shop-row-main {
    align-items: center;
}
.shop-row-more {
    font-size: 0.88rem;
    color: var(--text-muted);
    padding: 6px 10px;
}
.shopping-footer {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 12px;
    margin-top: 8px;
    background: var(--bg-card);
    border-top: 1px solid var(--border, rgba(0,0,0,0.08));
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
}
#tab-panel-acquisto {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    max-height: calc(100dvh - 148px);
}

/* Legacy cards — kept for smart tab / suggestions */
.shopping-item-card {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: 10px;
    padding: 12px;
    border-radius: var(--radius);
    background: var(--bg-card);
    box-shadow: var(--shadow);
    cursor: default;
}

.shopping-qty-hero {
    flex: 0 0 4.75rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 8px 6px;
    border-radius: calc(var(--radius) - 2px);
    background: rgba(45, 80, 22, 0.08);
    border: 2px solid rgba(45, 80, 22, 0.2);
    text-align: center;
    min-height: 4.5rem;
}

.shopping-qty-hero-empty {
    opacity: 0.45;
    border-style: dashed;
}

.shopping-qty-num {
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.15;
    color: var(--accent);
    word-break: break-word;
}

.shopping-qty-sub {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-top: 2px;
}

.shopping-qty-month {
    font-size: 0.62rem;
    color: var(--text-muted);
    margin-top: 4px;
    line-height: 1.2;
}

.shopping-item-card .shopping-item-body {
    flex: 1;
    min-width: 0;
}

.shopping-item-card .shopping-item-top {
    align-items: flex-start;
}

.shopping-item-card .shopping-item-icon {
    font-size: 1.4rem;
    flex-shrink: 0;
}

.shopping-item-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    align-items: center;
}

.btn-bought {
    flex: 1;
    min-height: 44px;
    padding: 10px 12px;
    border: none;
    border-radius: calc(var(--radius) - 2px);
    background: var(--accent);
    color: #fff;
    font-weight: 700;
    font-size: 0.9rem;
    cursor: pointer;
}

.btn-bought:active {
    transform: scale(0.98);
    opacity: 0.92;
}

.shopping-item-price-sub {
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: 4px;
}

.shopping-item-price-sub .price-col-main {
    font-size: 0.72rem;
    font-weight: 500;
}

.shopping-item-price-sub .price-col-unit {
    font-size: 0.65rem;
}

#shopping-price-bar {
    padding: 8px 12px;
    border-radius: var(--radius);
    background: var(--bg-card);
    box-shadow: var(--shadow);
}

#shopping-price-bar .price-total-label {
    font-size: 0.78rem;
}

#shopping-price-bar .price-total-value {
    font-size: 0.85rem;
    font-weight: 600;
}

.shopping-scan-target-banner .stb-hint {
    display: block;
    font-size: 0.82rem;
    color: var(--text-muted);
    margin-top: 4px;
}

@media (max-width: 380px) {
    .shopping-qty-hero {
        flex: 0 0 4.1rem;
    }
    .shopping-qty-num {
        font-size: 1.15rem;
    }
    .btn-bought {
        font-size: 0.82rem;
        padding: 10px 8px;
    }
}

.shopping-item:not(.shopping-item-card) {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    background: var(--bg-card);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    /* tap-to-scan handled by JS; cursor/active defined in ENHANCEMENTS block above */
}

.shopping-item-icon {
    font-size: 1.3rem;
    flex-shrink: 0;
    margin-top: 2px;
}

.shopping-item-body {
    flex: 1;
    min-width: 0;
}

.shopping-item-top {
    display: flex;
    align-items: stretch;
    gap: 8px;
}

.shopping-item-info {
    flex: 1;
    min-width: 0;
}

.shopping-item-name {
    font-weight: 600;
    font-size: 0.95rem;
}

.shopping-item-spec {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.shopping-pantry-hint {
    font-size: 0.72rem;
    color: #15803d;
    font-weight: 500;
    margin-top: 2px;
    opacity: 0.85;
}
[data-theme="dark"] .shopping-pantry-hint {
    color: #4ade80;
}

.shopping-item-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: space-between;
    flex-shrink: 0;
    min-width: 70px;
}

.shopping-item-price {
    font-weight: 800;
    font-size: 1.25rem;
    color: var(--accent);
    line-height: 1.1;
    white-space: nowrap;
    margin-top: auto;
}

.shopping-item-remove {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    padding: 2px 4px;
    cursor: pointer;
    border-radius: 50%;
    transition: background 0.2s;
    flex-shrink: 0;
    line-height: 1;
}

.shopping-item-remove:hover,
.shopping-item-remove:active {
    background: #fee2e2;
    color: #dc2626;
}

.shopping-item-remove:hover,
.shopping-item-remove:active {
    background: #fee2e2;
    color: #ef4444;
}

.shopping-actions {
    margin-top: 8px;
    display: flex;
    flex-direction: row;
    gap: 8px;
}

.shopping-actions .btn {
    flex: 1;
    font-size: 0.8rem;
    padding: 10px 8px;
}

.seasonal-tip {
    background: linear-gradient(135deg, #ecfdf5, #f0fdf4);
    padding: 12px 14px;
    border-radius: var(--radius);
    font-size: 0.85rem;
    color: #065f46;
    margin-bottom: 8px;
    border-left: 3px solid #10b981;
}

.suggestion-items {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.suggestion-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: var(--bg-card);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    cursor: pointer;
    transition: transform 0.1s, background 0.2s;
    border: 2px solid transparent;
}

.suggestion-item.selected {
    border-color: var(--accent);
    background: #faf5ff;
}

.suggestion-item:active {
    transform: scale(0.98);
}

.suggestion-check {
    font-size: 1.1rem;
    flex-shrink: 0;
}

.suggestion-info {
    flex: 1;
    min-width: 0;
}

.suggestion-name {
    font-weight: 600;
    font-size: 0.9rem;
}

.suggestion-name small {
    font-weight: 400;
    color: var(--text-muted);
}

.suggestion-reason {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-top: 2px;
}
.suggestion-ai-tip {
    font-size: 0.75rem;
    color: #6366f1;
    margin-top: 3px;
    opacity: 0.88;
}

.priority-badge {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 8px;
    vertical-align: middle;
    margin-left: 4px;
    text-transform: uppercase;
}

.priority-high {
    background: #fee2e2;
    color: #dc2626;
}

.priority-med {
    background: #fef9c3;
    color: #ca8a04;
}

.priority-low {
    background: #ecfdf5;
    color: #059669;
}
.priority-ai {
    background: #f0f4ff;
    color: #4338ca;
    font-style: italic;
}

.suggestion-actions {
    margin-top: 12px;
    text-align: center;
}

.suggestion-actions .btn-success {
    width: 100%;
}

/* ===== SMART SHOPPING ===== */
.smart-shopping {
    margin-top: 16px;
}

.smart-shopping h3 {
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.smart-shopping h3 .shopping-count {
    font-size: 0.75rem;
    background: var(--accent);
    color: #fff;
    border-radius: 10px;
    padding: 1px 7px;
    font-weight: 600;
}

.smart-last-update-row {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 4px;
}
.smart-last-update {
    font-size: 0.70rem;
    color: rgba(255,255,255,0.30);
    font-style: italic;
}

.smart-filter-row {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 8px;
    margin-bottom: 8px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.smart-filter-row::-webkit-scrollbar {
    display: none;
}

.smart-filter {
    flex-shrink: 0;
    padding: 5px 12px;
    border-radius: 16px;
    border: 1.5px solid var(--border);
    background: var(--bg-card);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    white-space: nowrap;
}

.smart-filter.active {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
}

.smart-items {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.smart-item {
    padding: 10px 12px;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    transition: transform 0.1s;
}

.smart-item:active {
    transform: scale(0.99);
}

.smart-item-top {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.smart-check {
    margin-top: 3px;
    width: 18px;
    height: 18px;
    accent-color: var(--accent);
    flex-shrink: 0;
    cursor: pointer;
}

.smart-item-icon {
    font-size: 1.4rem;
    flex-shrink: 0;
    line-height: 1;
    margin-top: 1px;
}

.smart-item-info {
    flex: 1;
    min-width: 0;
}

.smart-item-name {
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.3;
}

.smart-item-specific {
    font-size: 0.73rem;
    color: var(--text-muted);
    margin-top: 1px;
    line-height: 1.3;
    font-style: italic;
}

.shopping-item-specific {
    font-size: 0.73rem;
    color: var(--text-muted);
    margin-top: 2px;
    line-height: 1.3;
    font-style: italic;
}

.smart-brand {
    font-weight: 400;
    color: var(--text-muted);
    font-size: 0.78rem;
}

.smart-item-reasons {
    font-size: 0.72rem;
    color: var(--text-muted);
    margin-top: 2px;
    line-height: 1.4;
}

.smart-item-reasons span + span::before {
    content: '';
}

.smart-item-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 5px;
}

.smart-urgency-badge,
.smart-freq-badge,
.smart-pred-badge,
.smart-bring-badge {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 8px;
    white-space: nowrap;
}

.smart-urgency-badge {
    background: #f3f4f6;
}

.smart-freq-badge {
    background: #ede9fe;
    color: #6d28d9;
}

.smart-freq-badge.freq-high {
    background: #fce7f3;
    color: #be185d;
}

.smart-freq-badge.freq-med {
    background: #ede9fe;
    color: #6d28d9;
}

.smart-freq-badge.freq-low {
    background: #f0fdf4;
    color: #15803d;
}

.smart-freq-badge.freq-suggest {
    background: #e0f2fe;
    color: #0369a1;
    font-weight: 600;
}
.smart-freq-badge.freq-suggest-approx {
    background: #f0f9ff;
    color: #0284c7;
    font-weight: 500;
    font-style: italic;
}

.smart-pred-badge {
    background: #fefce8;
    color: #a16207;
}

.smart-pred-badge.pred-urgent {
    background: #fee2e2;
    color: #dc2626;
}

.smart-pred-badge.pred-soon {
    background: #fff7ed;
    color: #c2410c;
}

.smart-bring-badge {
    background: #dbeafe;
    color: #1d4ed8;
}

.smart-item-stock {
    text-align: right;
    flex-shrink: 0;
    min-width: 50px;
}

.smart-qty {
    font-size: 0.8rem;
    font-weight: 700;
    display: block;
}

.smart-stock-bar {
    width: 44px;
    height: 5px;
    background: #e5e7eb;
    border-radius: 3px;
    overflow: hidden;
    margin-top: 4px;
    margin-left: auto;
}

.smart-stock-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s;
}

.smart-actions {
    margin-top: 12px;
    text-align: center;
}

.smart-actions .btn {
    width: 100%;
    font-size: 0.85rem;
    padding: 10px;
}

.stat-urgent {
    position: absolute;
    top: 4px;
    right: 4px;
    background: #ef4444;
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 8px;
    line-height: 1.3;
}
.stat-price-total {
    position: absolute;
    top: 4px;
    right: 4px;
    background: #dcfce7;
    color: #15803d;
    font-size: 0.65rem;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 8px;
    line-height: 1.3;
    white-space: nowrap;
}

/* ===== PRODUCT PREVIEW ===== */
.product-preview, .product-preview-small {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 10px 12px;
    box-shadow: var(--shadow);
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Action and Use page hero card */
#page-action .product-preview-small,
#page-use .product-preview-small {
    padding: 14px 16px;
    gap: 14px;
    border-left: 4px solid var(--primary);
    align-items: flex-start;
    position: relative;
}

/* action page: slightly larger name */
#page-action .use-hero-name {
    font-size: 1.15rem;
}

/* barcode pill on action page */
.action-pill-barcode { background: #f1f5f9; color: #64748b; }

.use-hero-icon {
    font-size: 2.4rem;
    width: 52px;
    text-align: center;
    flex-shrink: 0;
    line-height: 1;
    padding-top: 2px;
}

.use-hero-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.use-hero-name {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.use-hero-brand {
    font-size: 0.8rem;
    color: var(--text-light);
}

.use-hero-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 5px;
}

.use-meta-pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 3px 8px;
    border-radius: 99px;
    line-height: 1.3;
    white-space: nowrap;
}

/* Expiry pill colours */
.use-pill-ok       { background: #dcfce7; color: #166534; }
.use-pill-warn     { background: #fef9c3; color: #854d0e; }
.use-pill-soon     { background: #fed7aa; color: #7c2d12; }
.use-pill-expired  { background: #fee2e2; color: #991b1b; }
/* Quantity pill */
.use-pill-qty      { background: #e0f2fe; color: #0c4a6e; }

.product-preview img, .product-preview-small img {
    width: 60px;
    height: 60px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    background: var(--bg);
}

.product-preview-small img {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-sm);
    object-fit: cover;
    flex-shrink: 0;
}

.product-preview-emoji {
    font-size: 2.5rem;
    width: 60px;
    text-align: center;
}

.product-preview-info h3 {
    font-size: 1.1rem;
    font-weight: 700;
}

.product-preview-info p {
    font-size: 0.85rem;
    color: var(--text-light);
}

.product-image-preview {
    text-align: center;
    margin: 8px 0;
}

.product-image-preview img {
    max-width: 120px;
    border-radius: var(--radius-sm);
}

/* ===== AI PAGE ===== */
.ai-container {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.ai-capture {
    position: relative;
    width: 100%;
    aspect-ratio: 4/3;
    background: #000;
    border-radius: var(--radius);
    overflow: hidden;
}

.ai-capture video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.ai-preview {
    text-align: center;
}

.ai-preview img {
    max-width: 100%;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.ai-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ai-result {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow);
}

/* ===== BOTTOM NAV ===== */
.bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--nav-height);
    background: var(--bg-card);
    display: flex;
    justify-content: space-around;
    align-items: center;
    box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
    z-index: 100;
    padding-bottom: env(safe-area-inset-bottom, 0);
}

/* ── The band behind the bottom navigation ─────────────────────────────────
   A page that scrolls VISIBLY under the bar reads as unfinished, and here the bar
   is a floating pill (`elegant.css`: rounded, `bottom: 10px`, `width: 100% - 20px`),
   so the rows travelled across the 10 px gaps and through its rounded corners —
   the one thing a household notices first, because it moves while they read.
   This band is what the page must NOT be seen through: the pill paints at
   `z-index: 100`, so anything below it is what its translucency and its margins
   reveal — this layer, not the content. It is opaque by the time it reaches the
   bar and dissolves over the last ~12 px above it, so a row is never sliced: it
   fades out before the navigation starts.
   No `backdrop-filter` on purpose: a blur over a scrolling list repaints every
   frame, and the opaque part of the gradient already hides everything — the wall
   tablet pays for what it can see, not for a filter.
   `pointer-events: none` keeps every tap for the bar and for the page below it,
   and `z-index: 90` is deliberately just under the bar: modals, toasts, the
   capture sheet, the screensaver and the auth overlays all live far above. */
body::after {
    content: '';
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--nav-height) + 14px + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(
        to bottom,
        transparent 0,
        /* The dissolve is PIXELS, not a percentage: the floating pill rises
           `--es-nav-height + --es-nav-gap` (72 px) from the bottom edge, and the band
           is `--nav-height + 14px` (84 px), so everything from 10 px down is opaque
           — including the notch of its rounded corners, where a row used to peek. */
        color-mix(in srgb, var(--bg) 55%, transparent) 5px,
        var(--bg) 10px
    );
    pointer-events: none;
    z-index: 90;
}

.nav-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 600;
    cursor: pointer;
    padding: 6px 6px;
    border-radius: var(--radius-sm);
    transition: all 0.2s;
    /* Fluid slots. A fixed `min-width: 56px` floor × 7 tabs (plus the 62px
       FAB) needed ~398px — 462px with the German labels — against the 338px a
       360px phone can give: the row overflows, and because `body` hides
       overflow-x the clipped tabs (⚙️ Config) were unreachable, not just ugly.
       `min-width: 0` lets the row shrink to fit any width; `flex-grow` shares
       the leftover space, `flex-basis: auto` keeps today's label widths when
       there is room, so nothing is truncated on tablets/desktop. */
    flex: 1 1 auto;
    min-width: 0;
}
/* `display:flex` above would otherwise defeat the HTML hidden attribute
   (pharmacy mode hides the Recipes tab). */
.nav-btn[hidden] { display: none !important; }

.nav-btn.active {
    color: var(--primary);
}

.nav-icon {
    /* Scales with the viewport so 7 tabs always fit the bar on a phone. */
    font-size: clamp(1.05rem, 4.6vw, 1.4rem);
    display: flex;
    align-items: center;
    justify-content: center;
}

.nav-logo-icon {
    height: clamp(20px, 5.4vw, 24px);
    width: auto;
    object-fit: contain;
    display: block;
}

.nav-label {
    font-size: clamp(0.58rem, 2.3vw, 0.65rem);
    /* Below ~540px the labels are hidden (see elegant.css §13): these guards
       keep a long translation ("Einstellungen") from overflowing the slot. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Gemini — center tab, elevated like mobile FAB */
/* The centre of the nav is the capture button now (assets/css/surfaces.css):
   it carries no brand and stays visible offline, because "use" and "add" work
   without a server. */


/* ===== TOAST ===== */
/* Floats above the bottom nav + SHELFY mic (never covers the centre slot). */
.toast {
    position: fixed;
    bottom: 88px;
    left: 50%;
    transform: translateX(-50%) translateY(24px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    max-width: min(92vw, 420px);
    padding: 12px 18px;
    border-radius: 9999px;
    background: #0F172A;
    color: #F8FAFC;
    font-size: 0.92rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
    z-index: 1000;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease, transform 0.25s ease;
    box-shadow: 0 10px 28px rgba(15, 23, 42, 0.35);
}
.toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    pointer-events: auto;
}
.toast.action {
    text-align: left;
}
.toast-msg {
    flex: 1 1 auto;
    min-width: 0;
}
.toast-action {
    flex-shrink: 0;
    background: transparent;
    border: 1px solid rgba(248, 250, 252, 0.35);
    color: #F8FAFC;
    border-radius: 9999px;
    padding: 6px 12px;
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
}
.toast-action:active {
    background: rgba(248, 250, 252, 0.12);
}
.price-spark-wrap {
    display: inline-flex;
    vertical-align: middle;
    margin-left: 4px;
    opacity: 0.75;
}
.price-sparkline {
    display: block;
    color: var(--accent, #2d5016);
}
/* Same slate pill for every tone — colour lives in the wording, not a red slab. */
.toast.success,
.toast.error,
.toast.info,
.toast.action {
    background: #0F172A;
    color: #F8FAFC;
}
.toast.action .toast-action {
    border-color: color-mix(in srgb, #34d399 55%, #F8FAFC);
    color: #6EE7B7;
}

/* ===== LOADING ===== */
.loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.5);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    color: white;
    gap: 12px;
}

.loading-spinner {
    width: 40px;
    height: 40px;
    border: 4px solid rgba(255,255,255,0.3);
    border-top-color: white;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

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

/* ===== MODAL ===== */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,0.5);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    z-index: 200;
    padding: 0;
}

#modal-overlay {
    z-index: 250;
}

/* Raise modal above cooking overlay when in cooking mode */
.cooking-mode-active #modal-overlay {
    z-index: 99999;
}

.modal-content {
    background: var(--bg-card);
    border-radius: var(--radius) var(--radius) 0 0;
    width: 100%;
    max-width: 600px;
    max-height: 92vh;
    overflow-y: auto;
    padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    animation: slideUp 0.3s ease;
}
.modal-content:has(.item-detail-modal) {
    /* Weight sheets (g/ml chips + scale + finish) run taller than piece sheets —
       clip+hidden made the tablet look like the row "did not open". */
    max-height: min(640px, 92vh);
    overflow-x: hidden;
    overflow-y: auto;
    padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
}
.edit-form-actions {
    display: flex;
    gap: 10px;
    margin-top: 8px;
}
.edit-form-actions .btn {
    flex: 1 1 0;
}

@keyframes slideUp {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}

.modal-header h3 {
    font-size: 1.15rem;
}

.edit-modal-header .edit-modal-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35em 0.5em;
    margin: 0;
    padding-right: 8px;
    flex: 1;
    min-width: 0;
    line-height: 1.3;
}

.edit-modal-prefix {
    font-weight: 600;
    opacity: 0.65;
    flex-shrink: 0;
}

.edit-title-tap {
    appearance: none;
    background: none;
    border: none;
    border-bottom: 1.5px dashed transparent;
    color: inherit;
    cursor: text;
    font: inherit;
    font-weight: 700;
    padding: 0;
    margin: 0;
    text-align: left;
    max-width: 100%;
    overflow-wrap: anywhere;
    transition: border-color 0.15s ease, color 0.15s ease;
}

.edit-title-tap:hover,
.edit-title-tap:focus-visible {
    border-bottom-color: currentColor;
    outline: none;
    opacity: 1;
}

.edit-title-input {
    flex: 1;
    min-width: 0;
    font-size: inherit;
    font-weight: 700;
    padding: 4px 8px;
    margin: 0;
}

/* The line under a tappable title (scan/add preview, AI match card) is a second
   "tap to correct" target: same affordance, lighter weight, inherits the colour
   of the line it replaces. */
.edit-subtitle-tap {
    appearance: none;
    background: none;
    border: none;
    border-bottom: 1.5px dashed transparent;
    color: inherit;
    cursor: text;
    font: inherit;
    padding: 0;
    margin: 0;
    text-align: left;
    max-width: 100%;
    overflow-wrap: anywhere;
    transition: border-color 0.15s ease;
}

.edit-subtitle-tap:hover,
.edit-subtitle-tap:focus-visible {
    border-bottom-color: currentColor;
    outline: none;
}

/* No brand yet: show the field label so the tap target stays visible and honest. */
.edit-subtitle-empty {
    font-style: italic;
    opacity: 0.75;
}

.edit-brand-input {
    width: 100%;
}

.scan-ai-hero-name .edit-title-tap {
    font-weight: inherit;
}

.modal-close {
    background: var(--bg);
    border: none;
    font-size: 1.3rem;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ── Bug report form ── */
.bug-type-pills {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.bug-type-pill {
    flex: 1;
    min-width: 80px;
    padding: 7px 10px;
    border: 1.5px solid #cbd5e1;
    border-radius: 20px;
    background: #fff;
    color: #475569;
    font-size: 0.88rem;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.bug-type-pill.active {
    border-color: var(--primary, #2d5016);
    background: var(--primary, #2d5016);
    color: #fff;
    font-weight: 600;
}
.bug-type-pill:not(.active):hover {
    border-color: var(--primary, #2d5016);
    color: var(--primary, #2d5016);
}

.modal-detail {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.modal-detail-row {
    display: flex;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.95rem;
}

.modal-detail-label {
    color: var(--text-light);
    font-weight: 500;
}

.modal-detail-value {
    font-weight: 600;
}

.modal-actions {
    display: flex;
    gap: 10px;
    margin-top: 16px;
}

/* ===== TRANSACTIONS LIST ===== */
.transaction-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.9rem;
}

.transaction-item:last-child {
    border-bottom: none;
}

.tx-icon {
    font-size: 1.3rem;
    width: 32px;
    text-align: center;
}

.tx-info {
    flex: 1;
}

.tx-name {
    font-weight: 600;
}

.tx-detail {
    font-size: 0.8rem;
    color: var(--text-light);
}

.tx-qty {
    font-weight: 700;
    font-size: 0.9rem;
}

.tx-qty.in {
    color: var(--success);
}

.tx-qty.out {
    color: var(--danger);
}

/* ===== PRODUCTS LIST ===== */
.products-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.product-item {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 14px;
    box-shadow: var(--shadow);
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
}

.product-item:active {
    transform: scale(0.98);
}

/* ===== USE INVENTORY INFO ===== */
.use-inventory-info {
    background: #dbeafe;
    border-radius: var(--radius);
    padding: 12px 16px;
    margin-bottom: 12px;
    font-size: 0.9rem;
    color: #1d4ed8;
    font-weight: 500;
}

#use-expiry-hint {
    background: #fef3c7;
    border: 1.5px solid #f59e0b;
    border-radius: var(--radius);
    padding: 10px 14px;
    margin-bottom: 12px;
    font-size: 0.9rem;
    color: #92400e;
    font-weight: 500;
    line-height: 1.45;
}

/* ===== EMPTY STATE ===== */
.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--text-muted);
}

.empty-state-icon {
    font-size: 3rem;
    margin-bottom: 12px;
}

.empty-state p {
    font-size: 0.95rem;
}

/* ===== CATEGORY GROUP HEADERS (full-width section rules) ===== */
.cat-group-header,
.inv-section-header {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 14px 2px 8px;
    margin-top: 4px;
    font-size: 0.95rem;
    font-weight: 750;
    color: #0f172a;
    border-bottom: 0;
}
.cat-group-header:first-child,
.inv-section-header:first-child { margin-top: 0; padding-top: 4px; }
.cat-group-icon { font-size: 1.05rem; line-height: 1; display: inline-flex; }
.cat-group-label { font-weight: 750; color: #0f172a; }
.cat-group-count {
    background: transparent;
    color: #94a3b8;
    font-size: 0.82rem;
    font-weight: 650;
    padding: 0;
    border-radius: 0;
    margin-left: 0;
}
.cat-group-rule {
    flex: 1 1 auto;
    min-width: 24px;
    height: 1px;
    background: #e2e8f0;
    margin-left: 4px;
}
[data-theme="dark"] .cat-group-label,
.dark .cat-group-label { color: var(--text); }
[data-theme="dark"] .cat-group-rule,
.dark .cat-group-rule { background: color-mix(in srgb, var(--border) 80%, transparent); }

/* ===== EDIT UNKNOWN PRODUCT ===== */
.edit-unknown-card {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    margin: 12px 0;
    box-shadow: var(--shadow);
    border: 2px solid var(--border);
}

.edit-unknown-card.highlight {
    border-color: var(--warning);
    background: #fffbeb;
}

.edit-unknown-card h4 {
    font-size: 1rem;
    margin-bottom: 4px;
}

.edit-unknown-hint {
    font-size: 0.85rem;
    color: var(--text-light);
    margin-bottom: 12px;
}

.edit-unknown-form .form-group {
    margin-bottom: 10px;
}

.edit-unknown-form .form-group label {
    font-size: 0.85rem;
    font-weight: 600;
    display: block;
    margin-bottom: 4px;
}

/* ===== COMPACT INVENTORY ON DASHBOARD ===== */
.inventory-list.compact {
    gap: 4px;
}

.compact-item {
    padding: 10px 12px;
    border-radius: 12px;
    box-shadow: none;
    border-bottom: 1px solid var(--border);
    background: transparent;
}

.compact-item:last-child {
    border-bottom: none;
}

.compact-item .inv-image {
    width: 36px;
    height: 36px;
    font-size: 1.2rem;
}

.compact-item .inv-image img {
    width: 36px;
    height: 36px;
}

.compact-item .inv-info {
    flex: 1;
    min-width: 0;
}

.compact-item .inv-name {
    font-size: 0.92rem;
}

.compact-item .inv-brand {
    font-size: 0.75rem;
}

.inv-qty-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
    flex-shrink: 0;
}

.inv-qty-value {
    font-weight: 800;
    font-size: 1rem;
    color: var(--primary);
    white-space: nowrap;
}

.inv-qty-value small {
    font-size: 0.7rem;
    font-weight: 600;
    color: #4b5563;
}

.inv-qty-pkg-detail {
    font-size: 0.65rem;
    color: #6b7280;
    font-weight: 500;
    white-space: nowrap;
}

.inv-expiry-small {
    font-size: 0.7rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.inv-expiry-small.expiring {
    color: var(--warning);
    font-weight: 600;
}

.inv-expiry-small.expired {
    color: var(--danger);
    font-weight: 600;
}

.section-card h3 {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ===== RESPONSIVE ===== */
@media (min-width: 768px) {
    .dashboard-stats {
        grid-template-columns: repeat(4, 1fr);
    }
    
    .location-selector {
        grid-template-columns: repeat(4, 1fr);
    }
}

/* Safe area for notched phones */
@supports (padding: env(safe-area-inset-bottom)) {
    .bottom-nav {
        padding-bottom: env(safe-area-inset-bottom);
        height: calc(var(--nav-height) + env(safe-area-inset-bottom));
    }
    body {
        padding-bottom: calc(var(--nav-height) + env(safe-area-inset-bottom));
    }
}

/* ===== PURCHASE TYPE SELECTOR ===== */
.purchase-type-selector {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    margin: 4px 0 8px;
}

.purchase-type-btn {
    padding: 8px 8px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s;
    text-align: center;
}

.purchase-type-btn.active {
    border-color: var(--primary);
    background: rgba(45, 80, 22, 0.08);
    color: var(--primary);
}

/* ===== EXPIRY DETAIL ===== */
.expiry-detail {
    margin-top: 4px;
    padding: 8px 10px;
    background: #f8faf5;
    border-radius: var(--radius-sm);
    border: 1px solid rgba(45, 80, 22, 0.1);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.expiry-estimate {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0;
    margin: 0;
    gap: 8px;
}

.expiry-estimate-label {
    font-size: 0.82rem;
    color: var(--text-light);
}

.expiry-estimate-date {
    font-size: 0.82rem;
    color: var(--primary);
    font-weight: 600;
}

/* Date + vacuum on one line inside the add form */
.expiry-date-vacuum {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.expiry-date-vacuum .expiry-input-row {
    flex: 1 1 11rem;
    min-width: 0;
}
.expiry-date-vacuum #add-vacuum-group {
    flex: 0 1 auto;
    margin: 0;
    min-width: 0;
}
.expiry-date-vacuum .toggle-row,
.expiry-date-vacuum .edit-vacuum-row {
    gap: 8px;
    padding: 6px 10px;
    min-height: 40px;
    box-sizing: border-box;
}

.history-badge {
    font-size: 0.75rem;
    background: var(--primary);
    color: #fff;
    border-radius: 10px;
    padding: 1px 7px;
    vertical-align: middle;
    font-weight: 500;
    cursor: default;
}

.form-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin: 0;
    line-height: 1.35;
}

/* ===== TOGGLE SWITCH ===== */
.toggle-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.toggle-switch {
    position: relative;
    display: inline-block;
    width: 48px;
    height: 28px;
    flex-shrink: 0;
}
.toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}
.toggle-slider {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: #ccc;
    border-radius: 28px;
    transition: background 0.2s;
}
.toggle-slider::before {
    content: '';
    position: absolute;
    width: 22px;
    height: 22px;
    left: 3px;
    bottom: 3px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.2s;
}
.toggle-switch input:checked + .toggle-slider {
    background: var(--primary, #3b82f6);
}
.toggle-switch input:checked + .toggle-slider::before {
    transform: translateX(20px);
}
.vacuum-badge {
    font-size: 0.7rem;
    background: rgba(59, 130, 246, 0.12);
    color: #2563eb;
    padding: 1px 6px;
    border-radius: 8px;
    font-weight: 600;
    white-space: nowrap;
}

.opened-badge {
    font-size: 0.7rem;
    background: rgba(245, 158, 11, 0.12);
    color: #d97706;
    padding: 1px 6px;
    border-radius: 8px;
    font-weight: 600;
    white-space: nowrap;
}

/* ===== REMAINING QUANTITY OPTIONS ===== */
.remaining-options {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-top: 6px;
}

.remaining-btn {
    padding: 8px 4px;
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    font-size: 0.85rem;
    cursor: pointer;
    text-align: center;
    transition: all 0.2s;
}

.remaining-btn.active {
    border-color: var(--primary);
    background: rgba(45, 80, 22, 0.08);
    font-weight: 600;
}

/* ===== MULTI-BATCH EXPIRY (conf products with different expiry dates) ===== */
.multi-batch-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 10px;
    background: rgba(0,0,0,0.04);
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
}

.multi-batch-qty {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.multi-batch-unit {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.multi-batch-date {
    flex: 1;
    min-width: 0;
    font-size: 0.85rem !important;
}

.btn-icon-sm {
    background: none;
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 4px 8px;
    font-size: 0.75rem;
    cursor: pointer;
    color: var(--text-muted);
    flex-shrink: 0;
}

.btn-link-small {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.8rem;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 6px;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* ── Preferred use-location (collapsed row) ── */
.pref-loc-info {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
}
.pref-loc-name {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text);
}
.btn-link {
    background: none;
    border: none;
    color: var(--accent);
    font-size: 0.82rem;
    cursor: pointer;
    padding: 2px 6px;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.pref-loc-full-btns {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* ===== PRODUCT DETAILS CARD (Action Page) ===== */
.product-details-card {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 14px;
    margin: 0 16px 16px;
    box-shadow: var(--shadow);
}

.product-detail-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.product-detail-tag {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 20px;
    background: #f3f4f6;
    font-size: 0.8rem;
    color: #374151;
    white-space: nowrap;
}

.product-allergens {
    padding: 8px 10px;
    background: #fef3cd;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    margin-bottom: 8px;
    color: #856404;
}

.product-ingredients {
    margin-top: 6px;
}

.product-ingredients summary {
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-light);
    padding: 6px 0;
}

.product-ingredients p {
    font-size: 0.8rem;
    color: var(--text-light);
    line-height: 1.5;
    padding: 6px 0;
}

.product-conservation {
    font-size: 0.8rem;
    color: var(--text-light);
    padding: 6px 0;
    border-top: 1px solid var(--border);
    margin-top: 6px;
}

/* ===== QUANTITY + UNIT ROW ===== */
.qty-unit-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.unit-select {
    width: 70px;
    min-width: 70px;
    padding: 10px 4px;
    text-align: center;
    font-weight: 600;
    font-size: 0.95rem;
    border-radius: var(--radius-sm);
}

/* ===== CONF PACKAGE SIZE ROW ===== */
.conf-size-row {
    margin-top: 8px;
    padding: 10px 12px;
    background: #f0f9ff;
    border: 1.5px solid #bae6fd;
    border-radius: var(--radius-sm);
}

.conf-size-label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 6px;
    color: #0369a1;
}

.conf-size-inputs {
    display: flex;
    gap: 8px;
    align-items: center;
}

.conf-size-input {
    flex: 1;
    max-width: 120px;
}

.conf-size-unit {
    width: 65px;
    min-width: 65px;
}

.conf-size-info {
    font-size: 0.75em;
    color: var(--text-light);
    font-weight: 500;
}

/* ===== EXPIRY INPUT + CAMERA ROW ===== */
.expiry-input-row {
    display: flex;
    gap: 8px;
    align-items: center;
}

.expiry-input-row .form-input {
    flex: 1;
}

.btn-scan-expiry {
    padding: 10px 14px !important;
    font-size: 1.2rem;
    min-width: 48px;
    border-radius: var(--radius-sm);
}

/* ===== EXPIRY SCANNER MODAL ===== */
.expiry-scanner {
    padding: 4px 0;
}

.expiry-scanner-actions {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* ===== RECIPE DIALOG ===== */
.recipe-dialog {
    position: relative;            /* the ✕ is pinned to this corner */
    max-height: 85vh;
    overflow-y: auto;
    width: 94%;
    max-width: 500px;
}

/* The one way out of the sheet: a quiet ✕ in the corner, over all three of its views
   (generator, loading, result). A tap outside closes it too. */
.recipe-dialog-close {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 5;
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.recipe-dialog-close:hover,
.recipe-dialog-close:active {
    background: var(--bg, #f8fafc);
    color: var(--text-main, #0f172a);
}

.recipe-ask {
    text-align: center;
}

.recipe-ask h3 {
    font-size: 1.4rem;
    margin-bottom: 8px;
}

.recipe-desc {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin-bottom: 16px;
    line-height: 1.5;
}

.recipe-ask .form-group {
    margin-bottom: 20px;
}

.recipe-ask .qty-control {
    justify-content: center;
}

.recipe-loading {
    text-align: center;
    padding: 40px 16px;
}
/* SHELFY's own face over the wait: the assistant is the one working, and the drawing is the
   only thing in the app that says so without a word. */
.recipe-loading-avatar {
    width: 84px;
    height: 84px;
    object-fit: contain;
    display: block;
    margin: 0 auto 10px;
    animation: recipeLoadingFloat 2.6s ease-in-out infinite;
}
.recipe-loading-step {
    margin: 6px 0 0;
    font-size: 0.82rem;
    color: var(--text-muted);
    min-height: 1.2em;
}
@keyframes recipeLoadingFloat {
    0%, 100% { transform: translateY(0) scale(1); }
    50%      { transform: translateY(-4px) scale(1.03); }
}
@media (prefers-reduced-motion: reduce) {
    .recipe-loading-avatar { animation: none; }
}

.recipe-loading p {
    margin-top: 16px;
    color: var(--text-muted);
    font-weight: 600;
    transition: opacity 0.25s ease;
    min-height: 1.4em;
}

.recipe-result {
    text-align: left;
}

.recipe-result h2 {
    font-size: 1.3rem;
    color: var(--primary);
    margin-bottom: 4px;
}

.recipe-result h3 {
    font-size: 1.1rem;
    margin-top: 16px;
    margin-bottom: 8px;
    color: var(--text);
}

.recipe-result ul {
    padding-left: 20px;
    margin-bottom: 8px;
}

.recipe-result li {
    margin-bottom: 4px;
    line-height: 1.5;
}

.recipe-result ol {
    padding-left: 20px;
    margin-bottom: 8px;
}

.recipe-result ol li {
    margin-bottom: 8px;
    line-height: 1.5;
}

.recipe-result .recipe-tag {
    display: inline-block;
    background: var(--bg-light);
    color: var(--primary);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 12px;
    margin: 2px 4px 2px 0;
}

.recipe-result .recipe-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.recipe-result .recipe-expiry-note {
    background: #fff3cd;
    color: #856404;
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    margin-bottom: 12px;
    line-height: 1.5;
}

/* ===== RECIPE NUTRITION BLOCK ===== */
.recipe-nutrition-block {
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    border-radius: var(--radius-sm);
    padding: 12px 14px 8px;
    margin-top: 16px;
}
.recipe-section-heading {
    font-size: 0.85rem;
    font-weight: 700;
    color: #15803d;
    margin: 0 0 10px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.recipe-nutrition-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    text-align: center;
}
.recipe-nutrition-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}
.recipe-nutrition-icon { font-size: 1.2rem; }
.recipe-nutrition-value {
    font-size: 0.95rem;
    font-weight: 700;
    color: #15803d;
}
.recipe-nutrition-label {
    font-size: 0.65rem;
    color: #64748b;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.recipe-nutrition-note {
    font-size: 0.7rem;
    color: #94a3b8;
    text-align: center;
    margin: 6px 0 0;
}
.recipe-nutrition-footnote {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin-top: 12px;
}

/* ===== RECIPE STORAGE CARD ===== */
.recipe-storage-card {
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: var(--radius-sm);
    padding: 12px 14px 8px;
    margin-top: 12px;
}
.recipe-storage-card .recipe-section-heading { color: #b45309; }
.recipe-storage-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}
.recipe-storage-badge {
    background: #fef3c7;
    border: 1px solid #fcd34d;
    border-radius: 20px;
    padding: 2px 12px;
    font-size: 0.8rem;
    font-weight: 600;
    color: #92400e;
    white-space: nowrap;
    text-transform: capitalize;
}
.recipe-storage-days { background: #dbeafe; border-color: #93c5fd; color: #1d4ed8; }
.recipe-storage-now  { background: #fee2e2; border-color: #fca5a5; color: #b91c1c; }
.recipe-storage-tips {
    font-size: 0.82rem;
    color: #78350f;
    margin: 2px 0 0;
    line-height: 1.4;
}

.recipe-tools-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    background: #f0f4ff;
    border: 1px solid #c7d2fe;
    border-radius: var(--radius-sm);
    padding: 8px 12px;
    font-size: 0.85rem;
    color: #3730a3;
    margin-bottom: 12px;
    line-height: 1.5;
}
.recipe-tool-chip {
    background: #e0e7ff;
    border-radius: 20px;
    padding: 2px 10px;
    font-size: 0.8rem;
    color: #3730a3;
    white-space: nowrap;
}
/* Appliance/mode badge shown inline next to a step text */
.recipe-step-appliance {
    display: inline-block;
    margin-left: 6px;
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    border-radius: 12px;
    padding: 1px 8px;
    font-size: 0.72rem;
    color: #15803d;
    vertical-align: middle;
    white-space: nowrap;
}

/* Recipe → shopping list panel: what the pantry does not cover */
.recipe-shopping-suggestions {
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    margin-top: 16px;
    font-size: 0.85rem;
    color: #92400e;
    line-height: 1.5;
}
.recipe-shopping-suggestions p {
    margin: 0 0 8px;
}
.recipe-plan-list {
    list-style: none;
    padding: 0;
    margin: 0 0 10px;
}
.recipe-plan-row {
    display: flex;
    flex-direction: column;
    padding: 4px 0;
    border-bottom: 1px solid #fef3c7;
}
.recipe-plan-row:last-child {
    border-bottom: none;
}
.recipe-plan-row label {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #78350f;
    cursor: pointer;
}
.recipe-plan-row input[type="checkbox"] {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
}
.recipe-plan-row small {
    margin-left: 24px;
    color: #a16207;
}
.recipe-plan-note {
    display: block;
    margin-top: 4px;
    color: #a16207;
}

/* Regen choice panel */
.recipe-regen-choice {
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 12px;
    padding: 14px;
    margin-top: 10px;
}
.recipe-regen-choice-title {
    font-size: 0.9rem;
    font-weight: 600;
    color: #475569;
    margin: 0 0 10px 0;
    text-align: center;
}

/* Recipe ingredient use buttons */
.recipe-ingredients {
    list-style: none;
    padding: 0;
}

.recipe-ingredient {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid var(--bg-light);
}

.recipe-ingredient:last-child {
    border-bottom: none;
}

.recipe-ing-text {
    flex: 1;
    min-width: 0;
    line-height: 1.4;
}
.recipe-ing-open-use {
    cursor: pointer;
    border-radius: 6px;
    padding: 2px 4px;
    margin: -2px -4px;
    transition: background 0.15s, color 0.15s;
}
.recipe-ing-open-use:active,
.recipe-ing-open-use:focus-visible {
    background: rgba(45, 80, 22, 0.1);
    outline: 2px solid rgba(45, 80, 22, 0.35);
    outline-offset: 1px;
}
.recipe-ing-name {
    color: var(--primary, #2d5016);
    border-bottom: 1px solid rgba(45, 80, 22, 0.45);
    transition: color 0.15s, border-color 0.15s;
}
.recipe-ing-open-use:hover .recipe-ing-name,
.recipe-ing-name:hover {
    color: #1a3a0c;
    border-bottom-color: #1a3a0c;
}

/* Recipe ingredient Usa (use) button: a primary action, sized like one.
   Double the old 0.78rem — it was the smallest control on the recipes screen. */
/* The per-ingredient "Usa" is a SECONDARY escape hatch: the one green action of a recipe is
   "Ho cucinato questo piatto" in the footer, which scales the whole list in one tap. A solid
   green 1.55 rem button on every row competed with it and turned a two-tap cook into three
   separate sheets. */
/* "Usa" writes the stock: it is the ONE action of an ingredient row and it must be a
   thumb target, not a 34 px pill with 0.78rem text next to a 1.1rem ingredient name. */
.btn-use-ingredient {
    flex-shrink: 0;
    align-self: center;
    background: rgba(5, 150, 105, 0.10);
    color: var(--brand-primary, #059669);
    border: 1px solid rgba(5, 150, 105, 0.42);
    border-radius: 12px;
    padding: 0 18px;
    min-height: 44px;
    min-width: 76px;
    font-size: 0.95rem;
    font-weight: 800;
    line-height: 1;
    letter-spacing: 0.01em;
    cursor: pointer;
    touch-action: manipulation;
    white-space: nowrap;
    transition: background 0.2s, color 0.2s;
}

.btn-use-ingredient:active {
    background: var(--brand-primary, #059669);
    color: #fff;
}

.btn-use-ingredient:disabled {
    cursor: default;
    opacity: 0.55;
}

/* The deducted label (✔ Scalato) is a status, not a tap target: bigger than
   before but it must not squeeze the ingredient name on a phone. */
.btn-use-ingredient.btn-used {
    background: transparent;
    border-color: transparent;
    color: var(--success);
    font-size: 0.78rem;
    min-height: 30px;
    padding: 4px 8px;
}

.recipe-ing-used .recipe-ing-text {
    text-decoration: line-through;
    opacity: 0.5;
}

/* ===== An ingredient the pantry no longer has =====
   Struck through like a used one, but for the opposite reason: the product is GONE. The row is
   not a control any more (no checkbox, no "Usa"), and the sheet says at the top that the dish as
   written cannot be cooked — a strike-through alone would read as "already done". */
.recipe-ing-missing .recipe-ing-text {
    text-decoration: line-through;
    text-decoration-color: #dc2626;
    text-decoration-thickness: 2px;
    opacity: 0.6;
}
.recipe-ing-missing .recipe-ing-name { color: #b91c1c; }
.recipe-ing-missing .recipe-ing-detail { color: #b91c1c; opacity: 0.8; }
.btn-use-ingredient.btn-missing {
    background: transparent;
    border-color: transparent;
    color: #b91c1c;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 4px 8px;
    cursor: default;
}

.recipe-missing-banner {
    margin: 0 0 10px;
    padding: 12px 14px;
    border-radius: var(--radius-sm, 10px);
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-left: 4px solid #dc2626;
    color: #7f1d1d;
    text-align: left;
}
.recipe-missing-banner strong {
    display: block;
    margin-bottom: 4px;
    font-size: 0.92rem;
}
.recipe-missing-banner p {
    margin: 0;
    font-size: 0.84rem;
    line-height: 1.45;
}
[data-theme="dark"] .recipe-missing-banner {
    background: #2a0a0a;
    border-color: #7f1d1d;
    border-left-color: #ef4444;
    color: #fecaca;
}
[data-theme="dark"] .recipe-ing-missing .recipe-ing-name,
[data-theme="dark"] .recipe-ing-missing .recipe-ing-detail,
[data-theme="dark"] .btn-use-ingredient.btn-missing { color: #fca5a5; }

.recipe-ing-detail {
    color: var(--text-muted);
    font-size: 0.78rem;
    line-height: 1.3;
}

.recipe-ing-stock {
    color: var(--text-muted);
    font-size: 0.72rem;
    line-height: 1.35;
    opacity: 0.9;
}

/* ===== SHOPPING SECTION (REPARTO) HEADERS ===== */
.shopping-section-divider {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 2px 4px;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-bottom: 1px solid var(--border);
    margin-top: 4px;
}

.shopping-section-divider:first-child {
    margin-top: 0;
    padding-top: 2px;
    border-bottom: none;
}

.shopping-section-divider span.sec-icon {
    font-size: 1rem;
}

/* ===== WEEKLY MEAL PLAN ===== */
.mplan-grid {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mplan-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 4px 2px;
    padding-left: 44px;
}
.mplan-col-header {
    flex: 1;
    text-align: center;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
}
.mplan-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 4px;
    border-radius: var(--radius-sm);
    background: var(--bg);
}
.mplan-row-today {
    background: rgba(45,80,22,0.08);
    outline: 2px solid var(--primary-light);
    border-radius: var(--radius-sm);
}
.mplan-day-name {
    width: 36px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-muted);
    flex-shrink: 0;
    text-align: center;
}
.mplan-badge {
    flex: 1;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    background: var(--primary);
    color: #fff;
    border-radius: 20px;
    padding: 7px 6px;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background 0.15s, transform 0.1s;
    text-align: center;
    line-height: 1.2;
}
.mplan-badge:active { transform: scale(0.93); }
.mplan-badge-pranzo { background: var(--primary-light); }
.mplan-badge-cena   { background: #1e3a6e; }

/* Meal plan picker popup */
.mplan-picker {
    position: fixed;
    z-index: 600;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    left: 50% !important;
    transform: translateX(-50%);
    width: min(320px, 92vw);
}
.mplan-pick-btn {
    background: var(--bg);
    border: 1.5px solid var(--border);
    border-radius: 20px;
    padding: 7px 12px;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background 0.15s;
}
.mplan-pick-btn.active {
    background: var(--primary);
    color: #fff;
    border-color: var(--primary);
}
.mplan-pick-btn:active { opacity: 0.7; }

/* Legend in settings */
.mplan-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

/* Recipe dialog banner (top strip) */
.recipe-mealplan-banner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: var(--primary);
    color: #fff;
    padding: 11px 20px;
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
    border-radius: var(--radius) var(--radius) 0 0;
    margin: -20px -20px 16px;
    letter-spacing: 0.2px;
}

/* Recipe dialog hint */
.recipe-mealplan-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(45,80,22,0.07);
    border: 1px solid rgba(45,80,22,0.18);
    border-radius: var(--radius-sm);
    padding: 8px 12px;
    margin: 4px 0 12px;
    font-size: 0.88rem;
}
.mplan-hint-badge {
    background: var(--primary);
    color: #fff;
    border-radius: 20px;
    padding: 3px 10px;
    font-size: 0.82rem;
    font-weight: 700;
    white-space: nowrap;
}
.mplan-hint-label {
    color: var(--text-muted);
    font-size: 0.80rem;
}

/* ===== COOKING MODE ===== */
.cooking-overlay {
    position: fixed;
    inset: 0;
    background: #0a0a0a;
    z-index: 99998; /* above every fixed UI: header, update banner, etc. */
    display: flex;
    flex-direction: column;
    color: #fff;
    overflow: hidden;
    touch-action: pan-y;
}

/* Hide update banner, app-header and any other fixed-top chrome while in cooking mode */
body.cooking-mode-active #_evershelf_update_banner,
body.cooking-mode-active .app-header {
    display: none !important;
}

.cooking-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    background: rgba(255,255,255,0.05);
    border-bottom: 1px solid rgba(255,255,255,0.10);
    flex-shrink: 0;
    min-height: 54px;
}

.cooking-title {
    flex: 1;
    text-align: center;
    font-size: 0.95rem;
    font-weight: 600;
    color: rgba(255,255,255,0.8);
    margin: 0 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cooking-close-btn,
.cooking-tts-btn {
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    border-radius: 50%;
    width: 38px;
    height: 38px;
    font-size: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s;
    flex-shrink: 0;
}

.cooking-close-btn:active,
.cooking-tts-btn:active {
    background: rgba(255,255,255,0.2);
}

.cooking-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px 20px;
    gap: 20px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.cooking-step-header {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-shrink: 0;
    width: 100%;
}

.cooking-step-num {
    font-size: 0.85rem;
    font-weight: 700;
    color: rgba(255,255,255,0.4);
    letter-spacing: 0.1em;
    text-align: center;
    flex-shrink: 0;
}

.cooking-restart-btn {
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.14);
    color: rgba(255,255,255,0.45);
    border-radius: 14px;
    padding: 4px 11px;
    font-size: 0.72rem;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
    white-space: nowrap;
}
.cooking-restart-btn:active {
    background: rgba(255,255,255,0.18);
    color: #fff;
}

/* Progress dots */
.cooking-progress-dots {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    flex-shrink: 0;
    max-width: 320px;
    width: 100%;
}
.cprog-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: rgba(255,255,255,0.18);
    border: 1.5px solid rgba(255,255,255,0.18);
    transition: background 0.25s, border-color 0.25s, transform 0.2s;
    flex-shrink: 0;
}
.cprog-dot.visited {
    background: rgba(255,255,255,0.50);
    border-color: rgba(255,255,255,0.50);
}
.cprog-dot.current {
    background: #f59e0b;
    border-color: #fbbf24;
    transform: scale(1.35);
}

.cooking-wheel {
    position: relative;
    --wheel-tilt-x: 0deg;
    --wheel-tilt-y: 0deg;
    --wheel-glow: 0.45;
    width: min(90vw, 680px);
    max-width: 680px;
    min-height: clamp(240px, 36vh, 340px);
    display: flex;
    align-items: center;
    justify-content: center;
    perspective: 1100px;
    overflow: hidden;
    border-radius: 24px;
    background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.07), rgba(255,255,255,0.02) 58%, transparent 100%);
    border: 1px solid rgba(255,255,255,0.08);
    box-shadow: inset 0 0 48px rgba(0,0,0,0.35);
    touch-action: pan-y;
}

.cooking-wheel::before,
.cooking-wheel::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.cooking-wheel::before {
    background: radial-gradient(circle at 50% 50%, rgba(56, 189, 248, 0.18), rgba(251, 191, 36, 0.08) 36%, transparent 72%);
    opacity: var(--wheel-glow);
    transition: opacity 0.2s ease;
}

.cooking-wheel::after {
    background: linear-gradient(180deg, rgba(0,0,0,0.34) 0%, transparent 20%, transparent 80%, rgba(0,0,0,0.34) 100%);
}

.cooking-step-text,
.cooking-step-ghost {
    width: min(88vw, 620px);
    text-align: center;
    line-height: 1.5;
    padding: 18px 20px;
    border-radius: 20px;
    transform-style: preserve-3d;
    transition: transform 0.22s ease, opacity 0.22s ease;
}

.cooking-step-text {
    position: relative;
    z-index: 3;
    font-size: clamp(1.35rem, 4.6vw, 2.1rem);
    font-weight: 600;
    color: #fff;
    background: linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0.06));
    border: 1px solid rgba(255,255,255,0.20);
    box-shadow: 0 18px 35px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.24);
    transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y));
    animation: cookingCardFloat 4.2s ease-in-out infinite;
}

/* The duration inside the step is the button: a pill in the middle of the sentence, tappable
   with a wet hand, which starts the same countdown the suggestion chip does. */
.cooking-step-timer {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin: 0 3px;
    padding: 2px 12px;
    border: none;
    border-radius: 999px;
    background: var(--brand-primary, #10b981);
    color: #06301f;
    font: inherit;
    font-size: 0.72em;
    font-weight: 800;
    cursor: pointer;
    vertical-align: baseline;
    box-shadow: 0 4px 12px rgba(0,0,0,0.28);
}
.cooking-step-timer:active { transform: scale(0.96); }

.cooking-step-ghost {
    position: absolute;
    left: 50%;
    top: 0;
    transform-origin: center center;
    font-size: clamp(1.08rem, 3.9vw, 1.52rem);
    font-weight: 560;
    color: rgba(255,255,255,0.95);
    background: linear-gradient(180deg, rgba(255,255,255,0.18), rgba(255,255,255,0.08));
    border: 1px solid rgba(255,255,255,0.22);
    box-shadow: 0 12px 28px rgba(0,0,0,0.38), inset 0 1px 0 rgba(255,255,255,0.22);
    text-shadow: 0 1px 2px rgba(0,0,0,0.34);
    opacity: 0.66;
    max-height: 42%;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cooking-step-prev {
    color: rgba(255, 243, 210, 0.97);
    background: linear-gradient(180deg, rgba(251, 191, 36, 0.24), rgba(251, 191, 36, 0.10));
    border-color: rgba(251, 191, 36, 0.36);
    transform: translateX(-50%) rotateX(56deg) rotateY(calc(var(--wheel-tilt-y) * 0.28)) scale(0.9);
}

.cooking-step-next {
    color: rgba(220, 243, 255, 0.97);
    background: linear-gradient(180deg, rgba(56, 189, 248, 0.24), rgba(56, 189, 248, 0.10));
    border-color: rgba(56, 189, 248, 0.36);
    transform: translateX(-50%) rotateX(-56deg) rotateY(calc(var(--wheel-tilt-y) * 0.28)) scale(0.9);
}

.cooking-step-ghost.is-empty {
    opacity: 0;
}

.cooking-wheel.turn-next .cooking-step-text {
    animation: cookingWheelCenterNext 0.34s ease;
}

.cooking-wheel.turn-prev .cooking-step-text {
    animation: cookingWheelCenterPrev 0.34s ease;
}

.cooking-wheel.turn-next .cooking-step-prev {
    animation: cookingWheelGhostNext 0.34s ease;
}

.cooking-wheel.turn-prev .cooking-step-next {
    animation: cookingWheelGhostPrev 0.34s ease;
}

.cooking-wheel.snap .cooking-step-text {
    animation: cookingWheelSnap 0.28s ease;
}

@keyframes cookingWheelCenterNext {
    from { transform: translateY(20px) rotateX(-10deg); opacity: 0.75; }
    to   { transform: translateY(0) rotateX(0); opacity: 1; }
}

@keyframes cookingWheelCenterPrev {
    from { transform: translateY(-20px) rotateX(10deg); opacity: 0.75; }
    to   { transform: translateY(0) rotateX(0); opacity: 1; }
}

@keyframes cookingWheelGhostNext {
    from { opacity: 0.1; transform: translateX(-50%) rotateX(68deg) scale(0.84); }
    to   { opacity: 0.66; transform: translateX(-50%) rotateX(56deg) scale(0.9); }
}

@keyframes cookingWheelGhostPrev {
    from { opacity: 0.1; transform: translateX(-50%) rotateX(-68deg) scale(0.84); }
    to   { opacity: 0.66; transform: translateX(-50%) rotateX(-56deg) scale(0.9); }
}

@keyframes cookingCardFloat {
    0%, 100% { transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y)) translateY(0); }
    50%      { transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y)) translateY(-3px); }
}

@keyframes cookingWheelSnap {
    0%   { transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y)) scale(0.97); }
    70%  { transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y)) scale(1.018); }
    100% { transform: rotateX(var(--wheel-tilt-x)) rotateY(var(--wheel-tilt-y)) scale(1); }
}

.cooking-replay-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.20);
    color: #fff;
    border-radius: 20px;
    padding: 7px 18px;
    font-size: 0.95rem;
    cursor: pointer;
    transition: background 0.2s;
    flex-shrink: 0;
}

.cooking-replay-btn:active {
    background: rgba(255,255,255,0.22);
}

.cooking-timer-wrap {
    display: none; /* legacy - replaced by cooking-timers-bar */
}

/* ===== Persistent timers bar (fixed below header, survives step changes) ===== */
.cooking-timers-bar {
    display: flex;
    gap: 8px;
    padding: 8px 12px;
    overflow-x: auto;
    background: rgba(255,255,255,0.04);
    border-bottom: 1px solid rgba(255,255,255,0.10);
    flex-shrink: 0;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.cooking-timers-bar::-webkit-scrollbar { display: none; }

.cooking-tools-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    background: rgba(99,102,241,0.15);
    border-bottom: 1px solid rgba(99,102,241,0.25);
    flex-shrink: 0;
    font-size: 0.78rem;
    color: #c7d2fe;
}
.cooking-tool-chip {
    background: rgba(99,102,241,0.25);
    border: 1px solid rgba(99,102,241,0.4);
    border-radius: 20px;
    padding: 2px 9px;
    font-size: 0.76rem;
    color: #e0e7ff;
    white-space: nowrap;
}

.cooking-timer-card {
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(255,255,255,0.09);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 14px;
    padding: 6px 10px 6px 14px;
    flex-shrink: 0;
    white-space: nowrap;
}

.ctimer-ring {
    --ctimer-pct: 100;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex-shrink: 0;
    background: conic-gradient(
        #22c55e calc(var(--ctimer-pct) * 1%),
        rgba(255,255,255,0.12) 0
    );
    display: grid;
    place-items: center;
}
.cooking-timer-card.is-done .ctimer-ring {
    background: conic-gradient(#ef4444 100%, rgba(255,255,255,0.12) 0);
}
.ctimer-ring-inner {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #0f172a;
}

.ctimer-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: rgba(255,255,255,0.60);
    max-width: 85px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ctimer-display {
    font-size: 1.15rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: #fff;
    letter-spacing: 0.03em;
    min-width: 48px;
    text-align: center;
}
.ctimer-display.ctimer-warning { color: #f97316; }
.ctimer-display.ctimer-done {
    color: #ef4444;
    animation: timerPulse 0.8s ease-in-out infinite alternate;
}

@keyframes timerPulse {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0.5; transform: scale(1.06); }
}

/* ===== COOKING SCREEN FLASH ===== */
.cooking-flash-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 50;
    background: transparent;
}
.cooking-flash-overlay.flash-warning {
    animation: cookFlashOrange 1.1s ease-in-out infinite;
}
.cooking-flash-overlay.flash-done {
    animation: cookFlashRed 0.65s ease-in-out infinite;
}
@keyframes cookFlashOrange {
    0%, 100% { background: transparent; }
    50%       { background: rgba(249, 115, 22, 0.28); }
}
@keyframes cookFlashRed {
    0%, 100% { background: transparent; }
    50%       { background: rgba(220, 38, 38, 0.42); }
}

.ctimer-btns {
    display: flex;
    gap: 4px;
    align-items: center;
}
.ctimer-btn {
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.15);
    color: #fff;
    border-radius: 8px;
    width: 28px;
    height: 28px;
    font-size: 0.80rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s;
    flex-shrink: 0;
}
.ctimer-btn:active { background: rgba(255,255,255,0.25); }
.ctimer-toggle.running {
    background: rgba(239,68,68,0.28);
    border-color: rgba(239,68,68,0.55);
}
.ctimer-remove {
    background: rgba(255,255,255,0.04);
    border-color: rgba(255,255,255,0.10);
    color: rgba(255,255,255,0.45);
    font-size: 0.65rem;
}
.ctimer-remove:active { background: rgba(239,68,68,0.25); }

/* ===== Step timer suggestion button ===== */
.cooking-timer-suggest {
    display: flex;
    justify-content: center;
    width: 100%;
}
.cooking-timer-add-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(251,191,36,0.12);
    border: 1.5px dashed rgba(251,191,36,0.45);
    color: #fbbf24;
    border-radius: 22px;
    padding: 10px 22px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s;
}
.cooking-timer-add-btn:active { background: rgba(251,191,36,0.26); }

.cooking-step-ings {
    width: 100%;
    max-width: 480px;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
}

/* The doses of the ingredients THIS step names: small translucent pills on the dark cooking
   screen, so nothing has to be remembered while both hands are busy. */
.cooking-ing-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 5px 11px;
    border-radius: 999px;
    background: rgba(255,255,255,0.10);
    border: 1px solid rgba(255,255,255,0.16);
    color: rgba(255,255,255,0.94);
    font-size: 0.78rem;
    line-height: 1.25;
}
.cooking-ing-chip strong { font-weight: 700; }
.cooking-ing-tool { opacity: 0.82; }

.cooking-ing-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 10px;
    padding: 10px 14px;
}

.cooking-ing-name {
    font-size: 0.95rem;
    color: rgba(255,255,255,0.9);
    flex: 1;
    min-width: 0;
}

.cooking-ing-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 5px;
}

.cooking-ing-chip {
    font-size: 0.72rem;
    background: rgba(255,255,255,0.12);
    border-radius: 5px;
    padding: 2px 7px;
    color: rgba(255,255,255,0.75);
    white-space: nowrap;
}

.cooking-ing-chip.exp-soon {
    background: rgba(239,68,68,0.3);
    color: #fca5a5;
}

.cooking-ing-chip.exp-close {
    background: rgba(234,179,8,0.3);
    color: #fde047;
}

.cooking-use-btn {
    flex-shrink: 0;
    background: #16a34a;
    border: none;
    color: #fff;
    border-radius: 8px;
    padding: 6px 14px;
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s;
    white-space: nowrap;
}

.cooking-use-btn:active {
    background: #15803d;
}

.cooking-use-btn.btn-used {
    background: #374151;
    cursor: default;
}

.cooking-nav {
    display: flex;
    gap: 12px;
    padding: 14px 16px;
    background: rgba(255,255,255,0.04);
    border-top: 1px solid rgba(255,255,255,0.08);
    flex-shrink: 0;
}

.cooking-nav-btn {
    flex: 1;
    padding: 14px 10px;
    border-radius: 10px;
    font-size: 1rem;
    font-weight: 700;
    border: 1.5px solid rgba(255,255,255,0.2);
    background: rgba(255,255,255,0.08);
    color: #fff;
    cursor: pointer;
    transition: background 0.2s;
    text-align: center;
}

.cooking-prev-btn {
    border: 1px solid #475569;
    color: #E2E8F0;
    background: rgba(71, 85, 105, 0.35);
}

.cooking-nav-btn:disabled {
    opacity: 0.3;
    cursor: default;
}

.cooking-next-btn {
    background: rgba(22, 163, 74, 0.35);
    border-color: rgba(22, 163, 74, 0.6);
}

.cooking-next-btn.is-finish {
    background: rgba(22, 163, 74, 0.6);
}

.cooking-nav-btn:not(:disabled):active {
    background: rgba(255,255,255,0.2);
}

@media (max-width: 640px) {
    .cooking-wheel {
        min-height: clamp(210px, 34vh, 300px);
        border-radius: 18px;
    }

    .cooking-step-text,
    .cooking-step-ghost {
        padding: 14px 14px;
    }

}

@media (prefers-reduced-motion: reduce) {
    .cooking-step-text,
    .cooking-step-ghost,
    .cooking-wheel.turn-next .cooking-step-text,
    .cooking-wheel.turn-prev .cooking-step-text,
    .cooking-wheel.turn-next .cooking-step-prev,
    .cooking-wheel.turn-prev .cooking-step-next,
    .cooking-wheel.snap .cooking-step-text {
        animation: none !important;
        transition: none !important;
    }
}

/* Cooking button in recipe dialog */
.btn-cooking {
    background: linear-gradient(135deg, #1e3a5f, #2d5016);
    color: #fff;
}

.btn-cooking:hover, .btn-cooking:active {
    opacity: 0.9;
}

/* The three actions of a recipe are a FOOTER, not a divider.
   They used to sit between the ingredients and the steps: reading how to cook the dish meant
   scrolling past three buttons that END the meal. Sticky at the bottom of the sheet, so they
   are always one tap away without ever standing in front of the procedure. */
.recipe-primary-actions {
    position: sticky;
    bottom: -1px;
    z-index: 3;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px 0 calc(10px + env(safe-area-inset-bottom, 0px));
    margin-top: 18px;
    /* OPAQUE. It used to be a 82%->transparent gradient, so every line scrolled behind the
       buttons and showed through them: the worst thing in the sheet. The soft edge now lives
       ABOVE the bar (::before), where it can fade the text without letting it show. */
    background: var(--bg-card, #fff);
}
.recipe-primary-actions::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -18px;
    height: 18px;
    pointer-events: none;
    background: linear-gradient(to top, var(--bg-card, #fff) 35%, transparent);
}

/* "Ripeti pasto" lands on this footer: it pulses once, so the one action that scales the whole
   ingredient list is where the eye lands. */
.recipe-primary-actions.is-prompted {
    animation: recipePromptFooter 1.9s ease-out 1;
}
@keyframes recipePromptFooter {
    0%, 100% { box-shadow: none; }
    30%      { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-primary, #10b981) 45%, transparent); }
    65%      { box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand-primary, #10b981) 28%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .recipe-primary-actions.is-prompted { animation: none; }
}

.recipe-primary-actions .btn {
    width: 100%;
}

/* The prominent action of the sheet is cooking mode; the bookkeeping ones (did I cook it,
   save it) sit under it as one quiet row: two thirds as tall, neutral, half as loud. */
.recipe-secondary-actions {
    display: flex;
    gap: 8px;
    align-items: stretch;
}
.recipe-secondary-actions .btn {
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    min-height: 36px;
    padding: 8px 10px;
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.2;
    white-space: normal;
}

.recipe-title-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 4px;
}

/* "Altra idea" (🎲) and Share, side by side in the head: the re-roll used to live only at the
   very bottom of the sheet, under nutrition and storage, so a dish that does not convince meant
   scrolling the whole recipe to ask for another. */
.recipe-title-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.recipe-title-row h2 {
    margin: 0;
    flex: 1;
    min-width: 0;
}

.btn-recipe-share-icon {
    flex-shrink: 0;
    margin-top: 2px;
    background: none;
    border: none;
    padding: 4px;
    line-height: 1;
    cursor: pointer;
    color: var(--text-muted, #6b7280);
    opacity: 0.4;
    border-radius: 6px;
    transition: opacity 0.15s, color 0.15s, background 0.15s;
}

.btn-recipe-share-icon:hover,
.btn-recipe-share-icon:focus-visible {
    opacity: 0.85;
    color: var(--text, #1f2937);
    background: rgba(0, 0, 0, 0.04);
    outline: none;
}

.btn-recipe-share-icon svg {
    display: block;
}

.recipe-share-overlay {
    z-index: 280;
}

.recipe-share-sheet h3 {
    margin: 0 0 8px;
}

.recipe-share-hint {
    margin: 0 0 16px;
    color: var(--text-muted);
    font-size: 0.92rem;
}

.btn-share-whatsapp {
    background: #25d366;
    color: #fff;
    border: none;
}

.btn-share-whatsapp:hover,
.btn-share-whatsapp:active {
    opacity: 0.92;
}

/* ===== LOG PAGE ===== */
.log-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 var(--space-sm);
}

.log-date-header {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: capitalize;
    padding: 12px 0 4px;
    border-bottom: 1px solid var(--bg-light);
    margin-bottom: 2px;
}

.log-entry {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: var(--bg-card);
}

.log-entry.log-in {
    border-left: 3px solid var(--success);
    background: rgba(40, 167, 69, 0.06);
}

.log-entry.log-out {
    border-left: 3px solid var(--danger);
    background: rgba(220, 53, 69, 0.06);
}

.log-entry.log-bring {
    border-left: 3px solid var(--primary);
    background: rgba(52, 120, 246, 0.06);
}

.log-entry.log-undone {
    opacity: 0.45;
    filter: grayscale(60%);
    text-decoration: line-through;
}

.log-undone-badge {
    display: inline-block;
    font-size: 0.68rem;
    font-weight: 600;
    color: #fff;
    background: var(--text-muted);
    border-radius: 4px;
    padding: 1px 5px;
    text-decoration: none;
    vertical-align: middle;
    margin-left: 4px;
}

.log-recipe-note {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 2px;
    font-style: italic;
}

.btn-log-undo {
    flex-shrink: 0;
    background: rgba(248, 113, 113, 0.12);
    border: 1px solid rgba(248, 113, 113, 0.4);
    color: #f87171;
    border-radius: 6px;
    padding: 5px 10px;
    font-size: 1rem;
    cursor: pointer;
    line-height: 1.4;
    transition: background 0.15s, color 0.15s;
}
.btn-log-undo:hover {
    background: rgba(248, 113, 113, 0.25);
    color: #fca5a5;
}


.log-icon {
    font-size: 1.2rem;
    flex-shrink: 0;
}

.log-info {
    flex: 1;
    min-width: 0;
}

.log-product {
    font-size: 0.9rem;
    line-height: 1.3;
}

.log-product em {
    font-weight: 400;
    color: var(--text-muted);
    font-size: 0.82rem;
}

.log-detail {
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.3;
    margin-top: 1px;
}

/* ===== AI IDENTIFICATION RESULTS ===== */
.ai-identified-card {
    background: var(--bg-light);
    border-radius: var(--radius-sm);
    padding: 12px;
    margin-top: 8px;
}

.ai-matches-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 8px;
}

.ai-match-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    background: var(--bg-card);
    border: 2px solid var(--bg-light);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
}

.ai-match-item:active {
    border-color: var(--primary);
    background: var(--bg-light);
}

.ai-match-img {
    width: 48px;
    height: 48px;
    object-fit: contain;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
    background: #fff;
}

.ai-match-info {
    flex: 1;
    min-width: 0;
    font-size: 0.9rem;
    line-height: 1.4;
}

.ai-match-info strong {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-match-barcode {
    font-size: 0.7rem;
    color: var(--text-muted);
    font-family: monospace;
    flex-shrink: 0;
}

/* ===== SETTINGS PAGE =====
   A control panel, not one endless page: a rail of six sections (sticky sidebar on a
   monitor, a swipeable strip of pills on a phone) and, for the section that is open,
   its own topics. Everything reads the app's own tokens, so the page belongs to the
   site and not to a different app. */
.settings-shell { display: block; }
.settings-nav { margin-bottom: 12px; }

.settings-groups {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    overflow-y: visible;
    padding: 2px 2px 6px;
    margin: 0;
    border: none;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.settings-groups::-webkit-scrollbar { display: none; }

.settings-group-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 9px 14px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-card);
    color: var(--text-light);
    font-size: 0.86rem;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    min-width: 0;
    transition: color 0.18s, border-color 0.18s, background 0.18s;
}

.settings-group-btn:hover { border-color: var(--primary-light); color: var(--primary); }

.settings-group-btn.active {
    background: color-mix(in srgb, var(--primary) 12%, var(--bg-card));
    border-color: var(--primary);
    color: var(--primary-dark);
}

.settings-group-icon { font-size: 1rem; line-height: 1; }

/* How many options of this section still wait for a decision. */
.settings-group-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--warning);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 800;
    line-height: 1;
}

.settings-group-count[hidden] { display: none; }

@media (min-width: 980px) {
    .settings-shell {
        display: grid;
        grid-template-columns: 212px minmax(0, 1fr);
        gap: 22px;
        align-items: start;
    }
    .settings-nav { position: sticky; top: 76px; margin-bottom: 0; }
    .settings-groups { flex-direction: column; overflow: visible; gap: 4px; padding: 0; }
    .settings-group-btn {
        width: 100%;
        justify-content: flex-start;
        border-radius: 10px;
        padding: 10px 12px;
    }
    .settings-group-count { margin-left: auto; }
}

/* Setup checklist: one line while everything is configured, the full list once
   something still needs a decision (rendered by _renderSettingsChecklist()). */
.checklist-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
}

.checklist-card h4 { margin-bottom: 0; }

.checklist-summary {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text-muted);
}

.checklist-card[data-state="todo"] .checklist-summary { color: #d97706; }
.checklist-card[data-state="ok"]   .checklist-summary { color: #059669; }

.checklist-items {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.checklist-item {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 10px;
}

.checklist-item-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 160px; }

.checklist-item-title { font-weight: 600; font-size: 0.88rem; }

.checklist-item-hint {
    font-size: 0.76rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.checklist-state { font-size: 0.76rem; font-weight: 700; white-space: nowrap; }
.checklist-state.ok   { color: #059669; }
.checklist-state.todo { color: #d97706; }
.checklist-state.news { color: #4f46e5; }

/* The card only lists what needs a decision: "Da configurare" and "Novità". */
.checklist-group-title {
    font-size: 0.7rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    margin: 8px 0 4px;
}
.checklist-group-title:first-child { margin-top: 0; }

.checklist-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* Highlight the card a checklist row just opened. */
@keyframes settings-card-flash {
    0%   { box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.55); }
    100% { box-shadow: var(--shadow); }
}

.settings-card.settings-card-flash { animation: settings-card-flash 1.6s ease-out; }

/* ===== LEVEL 2: the topics of the open section — quiet chips, one row ===== */
.settings-main { min-width: 0; }

.settings-tabs {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 2px 8px;
    margin: 0 0 12px;
    border-bottom: 1px solid var(--border);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.settings-tabs::-webkit-scrollbar { display: none; }

.settings-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    padding: 8px 12px;
    border: none;
    border-radius: 8px;
    background: none;
    color: var(--text-muted);
    font-size: 0.84rem;
    font-weight: 600;
    white-space: nowrap;
    min-width: 0;
    cursor: pointer;
    transition: color 0.18s, background 0.18s;
}

.settings-tab:hover { background: var(--bg); color: var(--text-light); }

.settings-tab.active {
    background: color-mix(in srgb, var(--primary) 10%, transparent);
    color: var(--primary-dark);
}

/* Tabs of the sections that are not selected stay out of the way. */
.settings-tab.settings-tab-hidden { display: none; }

/* ===== ESSENTIALS — access token, pairing code, last backup, version =====
   A household looks for these four facts before anything else, so they sit above the
   sections and never behind a tab. Tiles, not another card of prose: a label, the
   value, the state, two actions. */
.ess-panel {
    background: var(--es-surface-tint, var(--bg-card));
    border: 1px solid var(--es-border-subtle, var(--border));
    border-radius: var(--es-radius-card, 12px);
    padding: 14px;
    margin: 0 0 14px;
}

.ess-panel-head { margin-bottom: 10px; }

.ess-panel-title {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main, var(--text));
    display: flex;
    align-items: center;
    gap: 7px;
}

.ess-panel-sub {
    margin: 4px 0 0;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--text-muted);
}

.ess-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
}

.ess-tile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px;
}

.ess-tile-head {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.ess-tile-icon { font-size: 0.95rem; line-height: 1; }

.ess-tile-label {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.ess-pill {
    margin-left: auto;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 800;
    white-space: nowrap;
    background: var(--bg);
    color: var(--text-muted);
    border: 1px solid var(--border);
}

.ess-pill[data-state="on"] {
    background: color-mix(in srgb, var(--primary) 14%, transparent);
    color: var(--primary-dark);
    border-color: color-mix(in srgb, var(--primary) 40%, transparent);
}

.ess-pill[data-state="off"] {
    background: color-mix(in srgb, var(--warning) 16%, transparent);
    color: #92400e;
    border-color: color-mix(in srgb, var(--warning) 45%, transparent);
}

.ess-tile-value {
    margin: 2px 0 0;
    font-size: 0.98rem;
    font-weight: 800;
    color: var(--text-main, var(--text));
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.ess-tile-value.is-secret,
.ess-tile-value.is-revealed {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.86rem;
    letter-spacing: 0.02em;
}

.ess-tile-hint {
    margin: 0;
    font-size: 0.72rem;
    line-height: 1.4;
    color: var(--text-muted);
    overflow-wrap: anywhere;
}

.ess-tile-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    /* At the foot of the tile: the four tiles are one row, and the actions of the
       tallest one set the height — an action row that floats under the value makes
       the other three look broken. */
    margin-top: auto;
    padding-top: 6px;
}

.ess-tile-actions .btn { padding: 5px 10px; font-size: 0.78rem; }

/* The pairing code is drawn by _loadPairingCodePanel at 2.1 rem: inside a tile it has
   to fit the column, or it overflows on a phone. */
.ess-pairing-body { min-width: 0; }

.ess-pairing-body .pairing-code-display {
    font-size: 1.5rem !important;
    letter-spacing: 0.16em !important;
    padding: 8px 6px !important;
}

.ess-pairing-body .settings-hint { margin: 6px 0 0; font-size: 0.72rem; }

@media (min-width: 560px) {
    .ess-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 980px) {
    .ess-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* A phone gets the same four facts in ~250 px instead of ~620: the label and the value
   on the left, the two actions on the right, no long explanation (the pill already says
   the verdict) and no "Gestisci" links (the section rail is one scroll below). Measured
   in headless Chromium at 500 px. */
@media (max-width: 559px) {
    .ess-panel { padding: 12px; }
    .ess-grid { gap: 8px; }
    .ess-tile {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "head actions" "value actions";
        align-items: center;
        column-gap: 8px;
        padding: 9px 11px;
        gap: 1px 8px;
    }
    .ess-tile-head { grid-area: head; min-width: 0; }
    .ess-tile-value { grid-area: value; }
    .ess-pairing-body { grid-area: value; min-width: 0; }
    .ess-tile-hint { display: none; }
    .ess-tile-actions { grid-area: actions; margin: 0; gap: 4px; justify-content: flex-end; }
    .ess-tile-actions .btn { padding: 4px 8px; font-size: 0.74rem; }
    /* They repeat what the section rail already offers a few lines below. */
    .ess-tile-actions .btn-link { display: none; }
    .ess-pairing-body .pairing-code-display {
        font-size: 1.05rem !important;
        letter-spacing: 0.08em !important;
        padding: 2px 3px !important;
    }
    .ess-pairing-body .settings-hint { font-size: 0.66rem; margin-top: 2px; }
}

/* The receipt floats above the bottom nav, so the page needs room for it or the last
   button sits under the pill. */
#page-settings { padding-bottom: 52px; }

/* ===== AUTOSAVE BAR — the receipt, never a Save button ===== */
.settings-savebar {
    position: fixed;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(var(--nav-height, 70px) + 12px);
    z-index: 95;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    max-width: calc(100vw - 28px);
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    box-shadow: var(--es-shadow-elevated, 0 6px 20px rgba(0, 0, 0, 0.16));
    pointer-events: none;
    transition: background 0.18s, color 0.18s, border-color 0.18s;
}

.settings-savebar-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.settings-savebar-icon { font-weight: 800; }

.settings-savebar[data-state="saving"] {
    border-color: color-mix(in srgb, var(--primary) 45%, transparent);
    color: var(--primary-dark);
}

.settings-savebar[data-state="saved"] {
    background: color-mix(in srgb, var(--primary) 14%, var(--bg-card));
    border-color: color-mix(in srgb, var(--primary) 45%, transparent);
    color: var(--primary-dark);
}

.settings-savebar[data-state="error"] {
    background: color-mix(in srgb, var(--danger) 12%, var(--bg-card));
    border-color: color-mix(in srgb, var(--danger) 45%, transparent);
    color: var(--danger);
}

@media (prefers-reduced-motion: reduce) {
    .settings-savebar { transition: none; }
}

/* A row of actions inside a settings card (download + help, panels without a Save). */
.settings-form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

/* ===== CA help dialog: the numbered guide, one tap away ===== */
.ca-help-dialog {
    max-width: 540px;
    width: 100%;
    max-height: 86vh;
    overflow-y: auto;
    padding: 22px 20px 18px;
}

.ca-help-dialog h3 { margin: 0 0 10px; font-size: 1.02rem; color: var(--primary); }

.settings-cert-steps {
    font-size: 0.85rem !important;
    line-height: 1.65 !important;
    color: var(--text-light) !important;
    margin-bottom: 14px !important;
}

.settings-cert-steps strong { color: var(--text-main, var(--text)); }

/* ===== Settings search: the shortcut hint ===== */
.settings-search-kbd {
    display: none;
    position: absolute;
    right: 10px;
    font-family: inherit;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: 5px;
    padding: 1px 5px;
    background: var(--bg);
    pointer-events: none;
}

@media (min-width: 720px) {
    .settings-search-kbd { display: inline-block; }
    .settings-search-box .form-input { padding-right: 82px; }
}

.settings-tab-icon {
    font-size: 1rem;
    line-height: 1;
}

.settings-tab-text {
    font-size: 0.85rem;
    font-weight: 700;
    max-width: none;
    opacity: 1;
    overflow: visible;
    text-overflow: clip;
}

.settings-panel {
    display: none;
}

.settings-panel.active {
    display: block;
}

.settings-card {
    background: var(--bg-card);
    border-radius: var(--radius);
    padding: 16px;
    box-shadow: var(--shadow);
    margin-bottom: 12px;
}

.settings-card h4 {
    font-size: 1.05rem;
    margin-bottom: 4px;
    color: var(--primary);
}

/* ===== SETTINGS CARDS ARE SUB-SECTIONS: COLLAPSED UNTIL OPENED =====
   A panel with ten open cards buried the option you came for, so every card
   with a heading starts closed and only one is open at a time. The heading and
   the first hint line stay visible, so a closed card still says what it holds. */
.settings-card-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 8px;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}

.settings-card-head h4 {
    margin-bottom: 0;
}

.settings-card-head > .settings-hint {
    flex: 1 1 100%;
    margin: 2px 0 0;
}

.settings-card-chevron {
    margin-left: auto;
    font-size: 0.85rem;
    color: var(--text-muted);
    transition: transform 0.18s ease;
}

.settings-card[data-accordion].open > .settings-card-head .settings-card-chevron {
    transform: rotate(90deg);
}

.settings-card[data-accordion] > .settings-card-body {
    display: none;
}

.settings-card[data-accordion].open > .settings-card-body {
    display: block;
    margin-top: 10px;
    animation: settings-card-open 0.18s ease-out;
}

@keyframes settings-card-open {
    from { opacity: 0; transform: translateY(-2px); }
    to   { opacity: 1; transform: none; }
}

.settings-hint {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin-bottom: 12px;
    line-height: 1.4;
}

/* A failed AI test can carry a long provider sentence ("No endpoints found for
   <model>…"): show all of it instead of clipping the part that matters. */
#ai-test-result {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 40vh;
    overflow-y: auto;
}

.settings-panel-intro {
    font-size: 0.88rem;
    color: var(--text-muted);
    margin: 0 0 12px;
    line-height: 1.45;
}

.settings-info-box {
    font-size: 0.82rem;
    background: var(--bg, #f3f4f6);
    border-radius: 8px;
    padding: 10px 12px;
    margin-top: 4px;
    line-height: 1.45;
    color: var(--text-muted);
}

.settings-btn-row {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.settings-progress-track {
    background: var(--border, #e5e7eb);
    border-radius: 6px;
    height: 8px;
    overflow: hidden;
}

.settings-progress-fill {
    background: var(--accent, #6366f1);
    height: 100%;
    width: 0%;
    transition: width 0.5s ease;
}

.settings-details {
    margin-top: 12px;
    border-top: 1px solid var(--border);
    padding-top: 8px;
}

.settings-details summary {
    cursor: pointer;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--primary);
    list-style: none;
    padding: 6px 0;
}

.settings-details summary::-webkit-details-marker { display: none; }

.settings-details-body {
    padding-top: 8px;
}

.settings-status {
    margin-top: 12px;
    padding: 12px;
    border-radius: var(--radius-sm);
    text-align: center;
    font-weight: 600;
    font-size: 0.9rem;
}

.settings-status.success {
    background: #d1fae5;
    color: #047857;
}

.settings-status.error {
    background: #fee2e2;
    color: #dc2626;
}

.btn-small {
    padding: 6px 12px;
    font-size: 0.82rem;
    border-radius: var(--radius-sm);
}

.checkbox-label {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--bg);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    cursor: pointer;
    transition: background 0.2s;
}

.checkbox-label:active {
    background: var(--border);
}

.checkbox-label input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--primary);
}

.recipe-pref-checks {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Appliances */
.appliances-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.appliance-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--bg);
    border-radius: var(--radius-sm);
    font-size: 0.95rem;
    font-weight: 500;
}

.appliance-item .appliance-remove {
    background: none;
    border: none;
    color: var(--danger);
    font-size: 1.1rem;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 50%;
    transition: background 0.2s;
}

.appliance-item .appliance-remove:active {
    background: #fee2e2;
}

/* Deleted places, with their way back: a one-way destructive action is a trap, and a deleted
   built-in has no other door (its name lives in the translations). */
.deleted-locations {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--border);
}
.deleted-locations[hidden] { display: none; }
.deleted-locations-title {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.appliance-item-gone {
    background: transparent;
    border: 1px dashed var(--border);
    color: var(--text-muted);
}
.appliance-item-gone .btn { flex: 0 0 auto; }

/* A custom location can be renamed as well as removed: the pencil sits next to the ✕,
   neutral, because it does not destroy anything. */
.appliance-actions {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
}
.appliance-item .appliance-rename {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 7px;
    border-radius: 50%;
    transition: background 0.2s, color 0.2s;
}
.appliance-item .appliance-rename:hover { color: var(--text-main); }
.appliance-item .appliance-rename:active { background: var(--surface-bg); }

.appliance-quick-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.common-appliances .btn-small {
    font-size: 0.78rem;
    padding: 5px 10px;
}

/* ===== RECIPE OPTIONS GRID ===== */
/* ===== RECIPE OPTIONS: real chips =====
   A chip is the CONTROL, not a checkbox inside a balloon: 36 px tall, 8 px radius, one line of
   text that never wraps, its whole surface turning emerald when it is on. The native checkbox
   is still in the DOM (state + keyboard + screen reader) but it is invisible — it was the 2000s
   square that broke the design, and it also forced the 60 px height nobody asked for. */
.recipe-options-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
}

.recipe-chip-group-label {
    margin: 10px 0 2px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.recipe-option-chip {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 0 14px;
    border-radius: 8px;
    border: 1px solid var(--surface-border, #e2e8f0);
    background: #f8fafc;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

/* The control the label wraps: present, focusable, invisible. */
.recipe-option-chip input[type="checkbox"] {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    opacity: 0;
    pointer-events: none;
}

.recipe-option-chip:has(input:checked) {
    background: var(--brand-primary, #10b981);
    border-color: var(--brand-primary, #10b981);
    color: #fff;
}

/* "A ritmo mio" is a different promise from a pantry option (it changes the portions), so it
   answers in amber instead of the emerald of the ordinary preferences. */
.recipe-opt-fuel-wrap:has(input:checked) {
    background: #f59e0b;
    border-color: #f59e0b;
    color: #fff;
}

/* Keyboard focus stays visible even with the input hidden. */
.recipe-option-chip:has(input:focus-visible) {
    outline: 2px solid var(--brand-primary, #10b981);
    outline-offset: 2px;
}

/* The ✕ of the meal-plan chip: it takes the tag off without touching the others. */
.recipe-chip-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-left: 2px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.28);
    color: inherit;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
}
.recipe-chip-x:active { background: rgba(255, 255, 255, 0.45); }

[data-theme="dark"] .recipe-option-chip {
    background: var(--bg-card, #1e293b);
    border-color: #334155;
}
[data-theme="dark"] .recipe-chip-x { background: rgba(0, 0, 0, 0.25); }

/* Persons stepper + this week's suggestion on ONE row (they are two settings, not two
   sections): 80 px of height back inside a dialog that must fit an iPad without scrolling.
   Flex, not a fixed two-column grid: when there is no meal-plan hint the stepper is alone on
   the row and takes its width instead of leaving a half-empty column. */
.recipe-ask-2col {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 10px;
    text-align: left;
}
.recipe-ask-2col > .form-group {
    flex: 1 1 140px;
    margin: 0;
    min-width: 0;
}
.recipe-ask-2col .recipe-mealplan-hint {
    flex: 1 1 160px;
    margin: 0;
    font-size: 0.8rem;
}

.recipe-meal-compact .recipe-meal-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.recipe-meal-compact > label {
    font-size: 0.78rem;
    opacity: 0.75;
}
.recipe-meal-compact .recipe-meal-chip {
    padding: 6px 10px;
    font-size: 0.78rem;
}

.recipe-view-tabs {
    display: flex;
    gap: 6px;
    margin: 10px 0 8px;
    padding: 4px;
    background: var(--bg-muted, rgba(0,0,0,0.04));
    border-radius: 12px;
}
.recipe-view-tab {
    flex: 1;
    border: none;
    background: transparent;
    border-radius: 10px;
    padding: 10px 8px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
}
.recipe-view-tab.is-active {
    background: var(--bg-card, #fff);
    color: var(--text-primary);
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

/* Quick filters of the book: one scrolling row of chips, right under the generate button.
   A cookbook of 50 recipes with no filter is a scroll, not a shelf. */
.recipe-filter-bar {
    display: flex;
    gap: 6px;
    margin: 10px 0 2px;
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: none;
}
.recipe-filter-bar::-webkit-scrollbar { display: none; }
.recipe-filter-chip {
    flex: 0 0 auto;
    border: 1px solid var(--surface-border, rgba(0,0,0,0.08));
    background: var(--bg-card, #fff);
    color: var(--text-muted);
    border-radius: 999px;
    padding: 7px 12px;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.recipe-filter-chip.is-active {
    background: var(--brand-primary, #10b981);
    border-color: var(--brand-primary, #10b981);
    color: #fff;
}

/* Mealie at the end of the same row: it opens the other ricettario, it does not filter. */
.recipe-mealie-chip {
    border-style: dashed;
    border-color: color-mix(in srgb, var(--brand-primary, #10b981) 45%, transparent);
    color: var(--brand-primary, #10b981);
}

/* ===== Mealie panel: browse, import, push ===== */
.mealie-overlay {
    z-index: 300;                 /* over the pantry list, under the auth overlays */
    align-items: center;
    padding: 16px;
}
.mealie-card {
    position: relative;
    width: 100%;
    max-width: 460px;
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    padding: 18px 16px 14px;
}
.mealie-card h3 { margin: 0 0 4px; padding-right: 34px; font-size: 1.12rem; }
.mealie-list {
    flex: 1 1 auto;
    min-height: 80px;
    overflow-y: auto;
    margin: 10px 0 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.mealie-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--radius-sm, 10px);
    background: var(--bg, #f8fafc);
    border: 1px solid var(--surface-border, #e2e8f0);
}
.mealie-row-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.88rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mealie-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}
.mealie-actions .btn-large { flex: 1 1 100%; }
.mealie-actions .btn-small { flex: 0 1 auto; }
[data-theme="dark"] .mealie-row {
    background: var(--bg-card, #1e293b);
    border-color: #334155;
}

.recipe-archive-meal-lg { font-size: 1.55rem; }
.recipe-archive-badge {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px 7px;
    border-radius: 999px;
    background: rgba(0,0,0,0.05);
    font-size: 0.72rem;
    font-weight: 600;
}

.recipe-ing-include {
    display: inline-flex;
    align-items: center;
    margin-right: 6px;
    flex-shrink: 0;
}
.recipe-ing-include input {
    width: 18px;
    height: 18px;
    accent-color: var(--brand-primary, #16a34a);
}
.recipe-ingredients .recipe-ingredient {
    display: flex;
    align-items: flex-start;
    gap: 4px;
}
.recipe-ingredients .recipe-ing-text { flex: 1; min-width: 0; }
.recipe-ingredients .btn-use-ingredient {
    flex-shrink: 0;
    opacity: 0.85;
    font-size: 0.78rem;
    padding: 6px 10px;
}

.recipe-fuel-panel {
    margin-top: 10px;
    padding: 12px;
    border-radius: var(--radius-sm);
    background: linear-gradient(135deg, rgba(45, 80, 22, 0.06), rgba(180, 83, 9, 0.08));
    border: 1px solid rgba(45, 80, 22, 0.15);
    text-align: left;
}
.recipe-fuel-status {
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 10px;
    color: var(--text);
}
.recipe-fuel-manual-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}
.recipe-fuel-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.78rem;
    font-weight: 500;
}
.recipe-fuel-hint {
    margin: 8px 0 0;
    font-size: 0.75rem;
    opacity: 0.75;
}
.recipe-fuel-lead {
    margin: 0 0 8px;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text);
}
.recipe-fuel-why {
    margin: 0 0 12px;
    padding: 12px 14px;
    border-radius: var(--radius-sm);
    background: rgba(45, 80, 22, 0.07);
    border-left: 3px solid var(--primary);
    font-size: 0.88rem;
    line-height: 1.45;
    color: var(--text);
    text-align: left;
}
.recipe-fuel-why strong {
    display: block;
    margin-bottom: 4px;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--primary);
}
.recipe-fuel-status div + div {
    margin-top: 4px;
}
.recipe-fuel-badge {
    margin: 0 0 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: rgba(180, 83, 9, 0.12);
    border: 1px solid rgba(180, 83, 9, 0.25);
    font-size: 0.82rem;
    font-weight: 600;
}
.recipe-weather-badge {
    margin: 0 0 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: rgba(14, 165, 233, 0.10);
    border: 1px solid rgba(14, 165, 233, 0.28);
    font-size: 0.82rem;
    font-weight: 600;
    color: #0369a1;
}
[data-theme="dark"] .recipe-weather-badge {
    background: rgba(56, 189, 248, 0.12);
    border-color: rgba(56, 189, 248, 0.3);
    color: #7dd3fc;
}
.weather-geocode-results {
    max-height: 200px;
    overflow-y: auto;
}
.health-settings-body.is-disabled {
    opacity: 0.45;
    filter: grayscale(0.85);
    pointer-events: none;
    user-select: none;
}
.settings-subheading {
    margin: 16px 0 8px;
    font-size: 0.92rem;
    font-weight: 700;
}
.health-bridge-download {
    margin-bottom: 12px;
    padding: 12px;
    border-radius: var(--radius-sm);
    background: rgba(45, 80, 22, 0.06);
    border: 1px solid rgba(45, 80, 22, 0.15);
}
.health-today-status {
    font-size: 0.85rem;
    padding: 10px;
    border-radius: var(--radius-sm);
    background: var(--bg);
}
.health-bridge-qr img {
    max-width: 180px;
    border-radius: 8px;
    background: #fff;
    padding: 8px;
}
.recipe-opt-fuel-wrap.is-disabled {
    opacity: 0.4;
    pointer-events: none;
    filter: grayscale(1);
}
[data-theme="dark"] .recipe-fuel-panel {
    background: linear-gradient(135deg, rgba(74, 222, 128, 0.08), rgba(251, 146, 60, 0.1));
    border-color: rgba(74, 222, 128, 0.2);
}
[data-theme="dark"] .recipe-fuel-badge {
    background: rgba(251, 146, 60, 0.15);
    border-color: rgba(251, 146, 60, 0.3);
}

/* Meal type selector — five chips on ONE row: a sixth (a juice is a drink, not a meal)
   left an orphan on its own line and pushed the whole dialog out of an iPad viewport. */
.recipe-meal-grid {
    display: grid;
    /* auto-fit + a 58 px floor: five chips share one row wherever it fits (a tablet, a phone
       in portrait) instead of being squeezed into five fixed fractions that clip the labels. */
    grid-template-columns: repeat(auto-fit, minmax(58px, 1fr));
    gap: 6px;
    margin-top: 4px;
}
.recipe-meal-chip {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 8px 3px;
    background: var(--bg);
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
    border: 2px solid transparent;
    text-align: center;
    white-space: nowrap;
    min-width: 0;
    overflow: hidden;
}
@media (max-width: 380px) {
    .recipe-meal-chip { font-size: 0.64rem; padding: 8px 2px; }
}
.recipe-meal-chip:has(input:checked) {
    background: rgba(45, 80, 22, 0.1);
    border-color: var(--primary);
    font-weight: 600;
}
.recipe-meal-chip input[type="radio"] {
    display: none;
}

/* Sub-type grid for dolce/succo */
.recipe-subtype-grid {
    margin-top: 8px;
    grid-template-columns: 1fr 1fr;
    animation: bannerSlideIn 0.25s ease-out;
}
.recipe-subtype-chip {
    font-size: 0.75rem;
    padding: 8px 6px;
    background: #fef9ef;
    border-color: #f0e4cc;
}
.recipe-subtype-chip:has(input:checked) {
    background: #fff3d4;
    border-color: #e6a817;
}

/* ===== LARGER PRODUCT PREVIEW (Action page) ===== */
.product-preview-large {
    flex-direction: column;
    text-align: center;
    padding: 20px;
}

.product-preview-large img {
    width: 120px;
    height: 120px;
    border-radius: var(--radius);
    object-fit: cover;
    margin-bottom: 8px;
}

.product-preview-large .product-preview-emoji {
    font-size: 4rem;
    width: auto;
    margin-bottom: 8px;
}

.product-preview-large .product-preview-info {
    text-align: center;
}

.product-preview-large .product-preview-info h3 {
    font-size: 1.4rem;
    margin-bottom: 4px;
}

.product-preview-large .product-preview-info p {
    font-size: 0.95rem;
}

.btn-edit-inline {
    position: absolute;
    top: 8px;
    right: 8px;
    background: rgba(255,255,255,0.9);
    border: 1px solid #ddd;
    border-radius: 50%;
    width: 36px;
    height: 36px;
    font-size: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}

.product-preview-large {
    position: relative;
}

/* ===== INVENTORY STATUS BAR ===== */
.inventory-status-bar {
    background: linear-gradient(135deg, #dbeafe 0%, #c7d2fe 100%);
    border: 2px solid #93b4f8;
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.inventory-status-bar .inv-status-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.inventory-status-bar .inv-status-title {
    font-size: 1rem;
    font-weight: 700;
    color: #1e40af;
}

.inventory-status-bar .inv-status-total {
    font-size: 2.2rem;
    font-weight: 900;
    color: #1e3a8a;
    background: rgba(255,255,255,0.8);
    padding: 8px 22px;
    border-radius: 24px;
    letter-spacing: 0.5px;
    line-height: 1.1;
}

.inventory-status-bar .inv-status-items {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.inventory-status-bar .inv-status-item {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    color: #1d4ed8;
    padding: 5px 10px;
    background: rgba(255,255,255,0.55);
    border-radius: var(--radius-sm);
}

.inventory-status-bar .inv-status-item .inv-status-qty {
    font-weight: 700;
}

.inventory-status-bar .inv-status-item-clickable {
    cursor: pointer;
    transition: background 0.15s;
}
.inventory-status-bar .inv-status-item-clickable:active {
    background: rgba(59, 130, 246, 0.15);
}

/* Related stock hint (same generic family, different brand/product) */
.action-related-stock-card {
    background: #f0fdf4;
    border: 1.5px solid #86efac;
    border-radius: var(--radius);
    padding: 10px 14px;
    font-size: 0.82rem;
    color: #166534;
    margin-bottom: 12px;
    line-height: 1.5;
}
.action-related-stock-card strong { color: #15803d; }
.related-stock-item { display: inline-block; margin-right: 8px; }
[data-theme="dark"] .action-related-stock-card {
    background: rgba(21, 128, 61, 0.12);
    border-color: #166534;
    color: #86efac;
}
[data-theme="dark"] .action-related-stock-card strong { color: #4ade80; }

/* ===== ACTION BUTTONS GRID ===== */
.action-buttons-3col {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 10px;
    margin-top: 16px;
}

.action-buttons-4col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 16px;
}

.action-buttons-3col .btn-huge,
.action-buttons-4col .btn-huge {
    min-height: 100px;
    padding: 18px 8px;
    font-size: 1rem;
}

.action-buttons-3col .btn-icon,
.action-buttons-4col .btn-icon {
    font-size: 2rem;
}

.btn-throw {
    background: #f97316;
    color: white;
}

.btn-throw:active {
    background: #ea580c;
}

.btn-edit {
    background: #6366f1;
    color: white;
}

.btn-edit:active {
    background: #4f46e5;
}

.btn-recipe-from-ingredient {
    grid-column: 1 / -1;
    background: linear-gradient(135deg, var(--es-action-recipe, #7c3aed), var(--accent-light, #8b5cf6));
    color: white;
    border: none;
    border-radius: 14px;
    padding: 14px 20px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
}

#page-use .btn-recipe-from-ingredient {
    margin-top: 12px;
    margin-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
}

.modal-content .btn-recipe-from-ingredient {
    margin-top: 10px;
}

.btn-recipe-from-ingredient:active {
    opacity: 0.85;
}

/* ===== INVENTORY CARD (Home-aligned hierarchy) ===== */
.inv-row-content.inv-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding: 12px;
}
.inv-card-top {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-width: 0;
}
.inv-card-top .inv-info { flex: 1 1 auto; min-width: 0; }
.inv-name-row {
    display: flex;
    align-items: flex-start; /* fav/menu stay top while the title wraps */
    gap: 4px;
    min-width: 0;
}
.inv-name-row .inv-name-block {
    flex: 1 1 auto;
    min-width: 0;
}
.inv-name-row .inv-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.95rem;
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.3;
    /* Safety only for absurd titles (full ingredient/legal runs) — normal names wrap fully. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
}
/* A medicine wears the SAME name as a food row: the size, the weight and the two-line clamp
   come from `.inv-name-row .inv-name`. The old medical override (0.94rem, 700, four lines) was
   a second grammar inside the same list — the two cabinets must be read at the same speed. */
.inv-med-sub {
    margin-top: 1px;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.3;
    color: #64748b;
    white-space: normal;
    overflow-wrap: anywhere;
}
.med-form-emoji {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.35rem;
    line-height: 1;
}
.med-form-emoji.med-icon-lg { font-size: 1.55rem; }
.inv-brand-inline {
    font-weight: 550;
    color: var(--text-light);
}
.inv-meta-line {
    margin-top: 4px;
    font-size: 0.8rem;
    color: #64748b;
    line-height: 1.35;
}
.inv-card-menu {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted, #94a3b8);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
}
.inv-card-menu:active { background: color-mix(in srgb, var(--border) 55%, transparent); }
.inv-card-bottom {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;
    min-width: 0;
}
.inv-card-bottom .inv-time {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.inv-qty-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 3px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--brand-primary, #10b981) 12%, #fff);
    color: #047857;
    font-size: 0.8rem;
    font-weight: 750;
    font-variant-numeric: tabular-nums;
}
.inv-qty-pill.is-low {
    background: #fffbeb;
    color: #b45309;
}
.inv-time {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.78rem;
    font-weight: 650;
    color: #475569;
    line-height: 1.3;
}
.inv-time-urgent { color: #b45309; }
.inv-time-expired { color: #b91c1c; }
.inv-time-soon { color: #a16207; }
.inv-time-opened { color: #0f766e; }
.inv-time-ok,
.inv-time-far { color: #64748b; }
.inv-quick-use {
    flex: 0 0 auto;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 34px;
    padding: 0 12px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--brand-primary, #059669) 40%, var(--border));
    background: color-mix(in srgb, var(--brand-primary, #059669) 14%, var(--bg-card));
    color: var(--brand-primary-hover, #047857);
    font-size: 0.82rem;
    font-weight: 800;
    cursor: pointer;
    line-height: 1;
    white-space: nowrap;
}
.inv-quick-use:active { transform: scale(0.96); }
.inv-quick-use-label { font-weight: 750; }
.btn-inv-fav {
    align-self: flex-start;
    font-size: 1.15rem;
    padding: 2px 2px;
}
/* Legacy qty column kept for compact dash rows only. */
.inv-qty-actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.inv-qty-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
    min-width: 56px;
    background: #ecfdf5;
    border-radius: 14px;
    padding: 6px 12px;
}
.inv-qty-number {
    font-size: 1.55rem;
    font-weight: 900;
    color: var(--primary);
    line-height: 1.1;
    letter-spacing: -0.5px;
}
.inv-qty-unit {
    font-size: 0.7rem;
    font-weight: 600;
    color: #4b5563;
    white-space: nowrap;
    line-height: 1.2;
    text-align: center;
}

/* Package fraction indicators (used elsewhere) */
.pkg-fraction {
    font-size: 1rem;
    font-weight: 700;
    color: #6b7280;
    white-space: nowrap;
}

.inv-pkg-frac {
    display: block;
    text-align: center;
}

.inv-status-total-col {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
}

.inv-status-total-frac {
    font-size: 0.8rem;
}

/* ===== REVIEW SECTION ===== */
/* ===== ALERT TOP BANNER ===== */
.alert-banner {
    /* The surface is one soft wash per reason (`--banner-hue`, surfaces.css). */
    border: 1.5px solid #f59e0b;
    border-radius: var(--radius);
    margin-bottom: 12px;
    overflow: hidden;
    animation: bannerSlideIn 0.35s ease-out;
}
@keyframes bannerSlideIn {
    from { opacity: 0; transform: translateY(-12px); }
    to   { opacity: 1; transform: translateY(0); }
}
.alert-banner.banner-prediction { /* hue: surfaces.css */ }
.alert-banner.banner-anomaly { /* hue: surfaces.css */ }
.banner-anomaly .alert-banner-title { color: #9a3412; }
.banner-anomaly .alert-banner-counter .banner-dot.active { background: #ea580c; }
.alert-banner.banner-dup-loss { /* hue: surfaces.css */ }
.banner-dup-loss .alert-banner-title { color: #991b1b; }
.banner-dup-loss .alert-banner-counter .banner-dot.active { background: #dc2626; }
.alert-banner.banner-no-expiry { /* hue: surfaces.css */ }
.banner-no-expiry .alert-banner-title { color: #14532d; }
.banner-no-expiry .alert-banner-counter .banner-dot.active { background: #16a34a; }
.alert-banner-inner {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 44px 8px 12px; /* right pad reserves space for abs-positioned close btn */
    position: relative;
}
.alert-banner-icon {
    font-size: 1.5rem;
    flex-shrink: 0;
    line-height: 1;
}
.alert-banner-body {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
}
.alert-banner-title {
    font-weight: 700;
    font-size: 0.95rem;
    color: #92400e;
    line-height: 1.3;
    word-break: break-word;
    overflow-wrap: break-word;
}
.banner-prediction .alert-banner-title {
    color: #5b21b6;
}
.alert-banner-detail {
    font-size: 0.82rem;
    color: #78716c;
    margin-top: 2px;
    line-height: 1.4;
}
.alert-banner-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: none;
    background: rgba(0,0,0,0.08);
    font-size: 0.9rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #78716c;
    z-index: 1;
}
.alert-banner-actions {
    display: flex;
    gap: 8px;
    padding: 0 12px 10px;
    flex-wrap: wrap;
}
.btn-banner {
    flex: 1;
    min-width: 80px;
    padding: 8px 12px;
    border-radius: 8px;
    border: none;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
}
.alert-banner-actions .btn-banner {
    flex: 1;
    min-width: 80px;
}
.btn-banner-ok {
    background: #d1fae5;
    color: #059669;
}
.btn-banner-edit {
    background: #e0e7ff;
    color: #4338ca;
}
.btn-banner-ai {
    background: #ede9fe;
    color: #7c3aed;
}
.btn-banner-weigh {
    background: #f3e8ff;
    color: #7c3aed;
}
.btn-banner-confirm {
    background: #d1fae5;
    color: #059669;
}
.alert-banner-counter {
    font-size: 0.72rem;
    color: #a1977a;
    text-align: center;
    padding: 0 12px 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.banner-prediction .alert-banner-counter {
    color: #7c6cb0;
}

/* Dot indicators */
.banner-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgba(0,0,0,0.18);
    cursor: pointer;
    transition: background 0.2s, transform 0.2s;
}
.banner-dot.active {
    background: rgba(0,0,0,0.55);
    transform: scale(1.3);
}
.banner-expired .banner-dot.active { background: #dc2626; }
.banner-expiring .banner-dot.active { background: #ea580c; }
.banner-prediction .banner-dot.active { background: #7c3aed; }

/* Nav arrows */
.banner-nav-arrow {
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
    color: rgba(0,0,0,0.35);
    user-select: none;
    padding: 0 2px;
    line-height: 1;
    transition: color 0.15s;
}
.banner-nav-arrow:active { color: rgba(0,0,0,0.7); }

/* Swipe slide animations */
@keyframes bannerSlideInLeft {
    from { opacity: 0; transform: translateX(60px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes bannerSlideInRight {
    from { opacity: 0; transform: translateX(-60px); }
    to   { opacity: 1; transform: translateX(0); }
}
.banner-slide-left .alert-banner-inner,
.banner-slide-left .alert-banner-actions {
    animation: bannerSlideInLeft 0.25s ease-out;
}
.banner-slide-right .alert-banner-inner,
.banner-slide-right .alert-banner-actions {
    animation: bannerSlideInRight 0.25s ease-out;
}

.alert-review {
    background: #fffbeb;
    border-color: #f59e0b;
}

.alert-review h3 {
    color: #92400e;
}

/* ===== OPENED PRODUCTS SECTION ===== */
.alert-opened {
    background: #eff6ff;
    border-color: #3b82f6;
}

.alert-opened h3 {
    color: #1e40af;
}

/* ===== STALE / UNUSED STOCK ===== */
.alert-stale {
    background: #faf5ff;
    border-color: #a78bfa;
}
.alert-stale h3 {
    color: #5b21b6;
}
.alert-section-hint {
    margin: -4px 0 10px;
    font-size: 0.8rem;
    color: var(--text-muted, #6b7280);
    line-height: 1.35;
}
/* `.stale-item` used to align its content to the centre (`align-items: center`) and carried its
   own `.stale-actions` strip, which is why the forgotten rows were a few pixels off every other
   Home card. Both lists now share the row grammar of «In scadenza»: nothing here but the class
   the JS needs to recognise the row. */

/* ===== SEASONAL SHOPPING REVIEW ===== */
.seasonal-review {
    margin: 12px 0 4px;
    padding: 12px;
    border-radius: 12px;
    background: #ecfdf5;
    border: 1px solid #6ee7b7;
}
.seasonal-review-head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 8px;
}
.seasonal-review-tip {
    font-size: 0.8rem;
    color: #047857;
}
.seasonal-block {
    margin-top: 8px;
}
.seasonal-block-title {
    font-size: 0.8rem;
    font-weight: 600;
    color: #065f46;
    margin-bottom: 6px;
}
.seasonal-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 0;
    border-top: 1px solid rgba(6, 95, 70, 0.12);
    font-size: 0.9rem;
}
.seasonal-row-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
/* Why the row is suggested: habits + pantry, one short line. */
.seasonal-reason {
    font-size: 0.75rem;
    line-height: 1.25;
    color: #047857;
    opacity: 0.9;
}
.seasonal-row .btn-banner {
    flex: 0 0 auto;
    min-width: 0;
    min-height: 30px;
    padding: 6px 10px;
    font-size: 0.8rem;
    line-height: 1.2;
}
.seasonal-remove-all {
    margin-top: 6px;
    width: 100%;
    min-width: 0 !important;
    min-height: 30px;
    padding: 6px 10px !important;
    font-size: 0.8rem !important;
}
.seasonal-bought {
    font-size: 0.75rem;
    color: #059669;
    font-style: normal;
    opacity: 0.85;
}
.seasonal-note {
    margin-top: 6px;
    font-size: 0.75rem;
    line-height: 1.35;
    color: #047857;
    opacity: 0.9;
}

[data-theme="dark"] .alert-stale {
    background: #1e1230;
    border-color: #5b21b6;
}
[data-theme="dark"] .alert-stale h3 { color: #c4b5fd; }
[data-theme="dark"] .seasonal-review {
    background: #0c1f1a;
    border-color: #065f46;
}
[data-theme="dark"] .seasonal-review-tip,
[data-theme="dark"] .seasonal-block-title { color: #6ee7b7; }
[data-theme="dark"] .seasonal-note { color: #6ee7b7; }
[data-theme="dark"] .seasonal-row { border-top-color: rgba(110, 231, 183, 0.15); }

/* The opened list draws the same state badge as every other Home row (`_alertStateBadge`): the
   three blue `opened-expiry-*` pills it used to own are gone, because a tab of the same block may
   not paint a different control. The inedible case is the shared `expired` (or the amber
   `expiring-soon` when the safety rules still call it edible). */
.alert-item-spoiled {
    opacity: 0.75;
}
.alert-item-spoiled .alert-item-name {
    color: var(--text-light);
}

.alert-more-note {
    font-size: 0.8rem;
    color: var(--text-light);
    text-align: center;
    padding: 6px 0 2px;
}

.review-hint {
    font-size: 0.8rem;
    color: #92400e;
    margin: -4px 0 10px;
    opacity: 0.8;
}

.review-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: rgba(255,255,255,0.7);
    border-radius: var(--radius-sm);
    margin-bottom: 6px;
}

.review-item-info {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    min-width: 0;
}

.review-item-icon {
    font-size: 1.5rem;
    flex-shrink: 0;
    width: 36px;
    text-align: center;
}

.review-item-icon img {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    object-fit: cover;
}

.review-item-text {
    min-width: 0;
}

.review-item-name {
    font-weight: 600;
    font-size: 0.9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.review-item-meta {
    font-size: 0.75rem;
    color: #78716c;
}

.review-warn {
    color: #dc2626;
    font-weight: 600;
}

.review-item-qty {
    flex-shrink: 0;
}

.review-qty-value {
    font-size: 1.1rem;
    font-weight: 800;
    color: #dc2626;
    background: #fee2e2;
    padding: 3px 10px;
    border-radius: 16px;
    white-space: nowrap;
}

.review-item-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

.btn-review {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    font-size: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.btn-review-ok {
    background: #d1fae5;
    color: #059669;
}

.btn-review-ok:active {
    background: #a7f3d0;
}

.btn-review-edit {
    background: #e0e7ff;
    color: #4338ca;
}

.btn-review-edit:active {
    background: #c7d2fe;
}

/* ===== ALERT QUANTITY BADGES ===== */
.alert-item-qty {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-light);
    padding: 2px 8px;
    background: rgba(255,255,255,0.6);
    border-radius: 12px;
    white-space: normal;
    align-self: flex-start;
    max-width: 100%;
}

/* ===== GEMINI CHAT (sheet over the current page) ===== */
#chat-overlay.chat-overlay {
    align-items: stretch;
    justify-content: center;
    padding: 10px 10px calc(10px + env(safe-area-inset-bottom, 0px));
    /* Above page content; below #modal-overlay (250) so "Usa" product sheets still open on top. */
    z-index: 180;
}
.chat-sheet {
    display: flex;
    flex-direction: column;
    width: min(640px, 100%);
    height: min(780px, calc(100dvh - 20px - env(safe-area-inset-bottom, 0px)));
    max-height: calc(100dvh - 20px);
    margin: auto;
    background: var(--bg, #f8fafc);
    border-radius: 18px;
    overflow: hidden;
    box-shadow: 0 18px 50px rgba(15, 23, 42, 0.28);
    border: 1px solid var(--border, #e2e8f0);
}

.chat-header-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 12px;
    background: white;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.chat-back-btn {
    flex-shrink: 0;
    min-width: 40px;
    min-height: 36px;
    padding: 0 10px;
    border-radius: 10px;
    border: 1px solid var(--border, #e2e8f0);
    background: var(--bg, #f8fafc);
    color: var(--text, #0f172a);
    font: inherit;
    font-size: 1.05rem;
    font-weight: 700;
    cursor: pointer;
}
.chat-back-btn:active {
    transform: scale(0.97);
}

.chat-header-info {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.chat-title {
    font-weight: 700;
    font-size: 1rem;
    color: #4338ca;
}

.btn-chat-clear {
    background: none;
    border: none;
    font-size: 1.2rem;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 8px;
    opacity: 0.6;
}

.btn-chat-clear:active {
    background: var(--bg);
    opacity: 1;
}

.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    -webkit-overflow-scrolling: touch;
    min-height: 0;
}

.chat-welcome {
    text-align: center;
    padding: 30px 16px;
    color: var(--text-light);
}

.chat-welcome h3 {
    margin: 12px 0 6px;
    color: var(--text);
    font-size: 1.1rem;
}

.chat-welcome p {
    font-size: 0.85rem;
    line-height: 1.5;
    max-width: 300px;
    margin: 0 auto 20px;
}

.gemini-icon-lg {
    opacity: 0.3;
}

.chat-suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
}

.chat-suggestion {
    background: white;
    border: 1.5px solid #e0e7ff;
    border-radius: 20px;
    padding: 8px 14px;
    font-size: 0.82rem;
    cursor: pointer;
    color: #4338ca;
    font-weight: 500;
    transition: all 0.15s;
}

.chat-suggestion:active {
    background: #e0e7ff;
    transform: scale(0.97);
}

.chat-bubble {
    max-width: 85%;
    padding: 10px 14px;
    border-radius: 18px;
    font-size: 0.9rem;
    line-height: 1.5;
    word-break: break-word;
    animation: chatFadeIn 0.2s ease;
}

@keyframes chatFadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

.chat-user {
    align-self: flex-end;
    background: #4338ca;
    color: white;
    border-bottom-right-radius: 6px;
}

.chat-gemini {
    align-self: flex-start;
    background: white;
    color: var(--text);
    border-bottom-left-radius: 6px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}

.chat-gemini strong {
    color: #4338ca;
}

.chat-gemini ul, .chat-gemini ol {
    margin: 4px 0;
    padding-left: 20px;
}

.chat-gemini li {
    margin-bottom: 2px;
}

.chat-input-bar {
    display: flex;
    gap: 8px;
    padding: 10px 12px;
    background: white;
    border-top: 1px solid var(--border);
}

.chat-input {
    flex: 1;
    border: 1.5px solid var(--border);
    border-radius: 24px;
    padding: 10px 16px;
    font-size: 0.9rem;
    outline: none;
    transition: border-color 0.2s;
}

.chat-input:focus {
    border-color: #6366f1;
}

.btn-chat-send {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    border: none;
    background: #4338ca;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s;
    flex-shrink: 0;
}

.btn-chat-send:active {
    transform: scale(0.92);
    background: #3730a3;
}

.btn-chat-send:disabled {
    background: #a5b4fc;
    cursor: default;
}

/* Typing indicator */
.chat-typing {
    display: flex;
    gap: 4px;
    padding: 4px 0;
}

.chat-typing span {
    width: 8px;
    height: 8px;
    background: #a5b4fc;
    border-radius: 50%;
    animation: chatTyping 1.4s infinite;
}

.chat-typing span:nth-child(2) { animation-delay: 0.2s; }
.chat-typing span:nth-child(3) { animation-delay: 0.4s; }

@keyframes chatTyping {
    0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
    30% { transform: translateY(-6px); opacity: 1; }
}

/* ====== Chat Transfer to Recipes button ====== */
.btn-chat-use-recipe {
    display: inline-block;
    margin-top: 10px;
    padding: 7px 14px;
    background: var(--card-bg, #1e293b);
    border: 1px solid #6366f1;
    color: #a5b4fc;
    border-radius: 20px;
    font-size: 0.82rem;
    cursor: pointer;
    transition: all 0.15s;
}
.btn-chat-use-recipe:hover {
    background: #312e81;
    color: white;
}
.btn-chat-use-recipe:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Products named in a SHELFY reply → one-tap Usa (opens the item sheet). */
.chat-use-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid color-mix(in srgb, var(--surface-border, #e2e8f0) 80%, transparent);
}
.chat-use-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 7px 14px;
    border-radius: 999px;
    border: none;
    background: var(--brand-primary, #10b981);
    color: #fff;
    font: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    box-shadow: 0 1px 0 rgba(15, 23, 42, 0.08);
}
.chat-use-btn:hover,
.chat-use-btn:focus-visible {
    filter: brightness(1.05);
    outline: none;
}
.chat-use-btn:active {
    transform: scale(0.98);
}
.chat-use-name {
    font-weight: 600;
    opacity: 0.95;
}
[data-theme="dark"] .chat-use-actions {
    border-top-color: rgba(148, 163, 184, 0.25);
}

/* ====== Recipe Archive ====== */
.recipe-archive {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding-bottom: 16px;
}

.recipe-archive-day {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.recipe-archive-date {
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--text-primary);
    padding: 2px 0;
    /* A neutral hairline, never the violet `--accent`: the accent is a recipe ACTION colour,
       and a 2 px violet rule under every date read as a second, wrong palette. */
    border-bottom: 1px solid color-mix(in srgb, var(--surface-border, #e2e8f0) 90%, transparent);
    margin-bottom: 2px;
}

.recipe-archive-card {
    background: var(--bg-card);
    border-radius: 10px;
    padding: 10px 14px;
    cursor: pointer;
    transition: box-shadow 0.2s, transform 0.15s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}

.recipe-archive-card:hover,
.recipe-archive-card:active {
    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
    transform: translateY(-1px);
}

.recipe-archive-card-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* The quick action of a past meal, on the right of the card: one tap reopens the saved recipe
   (no generation, no shopping of the same ingredients twice). */
.recipe-archive-repeat {
    margin-left: auto;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid var(--surface-border, rgba(0,0,0,0.1));
    background: var(--bg-card, #fff);
    color: var(--text-muted);
    border-radius: 999px;
    padding: 5px 10px;
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}
.recipe-archive-repeat:active { background: var(--bg, #f8fafc); }
@media (max-width: 420px) {
    /* On a phone the label costs the title its room: the icon carries the action. */
    .recipe-archive-repeat span { display: none; }
    .recipe-archive-repeat { padding: 5px 8px; font-size: 0.9rem; }
}

.recipe-archive-meal {
    font-size: 1.3rem;
    flex-shrink: 0;
}

.recipe-archive-title {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Without this a long title pushes the badges out of the row instead of ellipsing. */
    min-width: 0;
    flex: 1 1 auto;
}

.recipe-archive-card-meta {
    display: flex;
    gap: 10px;
    margin-top: 4px;
    font-size: 0.72rem;
    color: var(--text-muted);
    flex-wrap: wrap;
}

/* ===== RECIPE FAVORITES (#124) ===== */
.recipe-fav-badge {
    margin-left: auto;
    font-size: 1.1rem;
    color: #f59e0b;
    flex-shrink: 0;
}

.recipe-archive-card-fav {
    border-left: 3px solid #f59e0b;
}

.btn-recipe-fav {
    background: none;
    border: none;
    font-size: 1.8rem;
    cursor: pointer;
    color: var(--text-muted);
    padding: 0 4px;
    line-height: 1;
    vertical-align: middle;
    transition: color 0.2s, transform 0.15s;
    margin-left: auto;
}

.btn-recipe-fav:hover { color: #f59e0b; transform: scale(1.2); }
.btn-recipe-fav.active { color: #f59e0b; }

/* ===== Recipe vote, 0–5 stars =====
   Five buttons in the recipe's meta line: the vote is one tap on the star you mean, and the
   number is what the book filters by. 0 exists — it is what tapping the current value gives. */
.recipe-rating {
    display: inline-flex;
    align-items: center;
    gap: 1px;
    padding: 1px 5px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--surface-border, #e2e8f0) 45%, transparent);
}
.recipe-rating-star {
    border: none;
    background: none;
    padding: 0 1px;
    font-size: 1.12rem;
    line-height: 1;
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.15s, transform 0.15s;
}
.recipe-rating-star.is-on { color: #f59e0b; }
.recipe-rating-star:active { transform: scale(0.88); }

/* The same vote on the card of the book, compact. */
.recipe-archive-rating {
    font-size: 0.8rem;
    letter-spacing: 0.5px;
    color: #f59e0b;
}
.recipe-archive-rating-off { color: var(--text-muted); opacity: 0.45; }

/* "Manca 1 ingrediente": a SOFT AMBER chip in the meta row (never in front of the title, which
   must start on the same margin on every card). Amber and not red: a missing yoghurt is a
   pantry condition, not a crash — and it is a button, because it says WHICH one and puts it on
   the shopping list. */
.recipe-missing-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: #FEF3C7;
    border: 1px solid #FDE68A;
    color: #92400E;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.45;
    cursor: pointer;
    white-space: nowrap;
}
.recipe-missing-chip:active { background: #FDE68A; }

/* The popover: what is missing, by name, with the shopping list one tap away. */
.recipe-missing-popover {
    position: fixed;
    z-index: 340;
    width: min(280px, calc(100vw - 16px));
    padding: 12px;
    border-radius: 12px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--surface-border, #e2e8f0);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.16);
    text-align: left;
}
.recipe-missing-popover strong {
    display: block;
    margin-bottom: 6px;
    font-size: 0.82rem;
    color: var(--text-main, #0f172a);
}
.recipe-missing-popover ul {
    margin: 0 0 10px;
    padding-left: 18px;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--text-main, #0f172a);
}
.recipe-missing-qty { color: var(--text-muted); }
[data-theme="dark"] .recipe-missing-chip {
    background: #3a2a05;
    border-color: #92400E;
    color: #FDE68A;
}
[data-theme="dark"] .recipe-missing-popover {
    background: var(--bg-card, #1e293b);
    border-color: #334155;
}
[data-theme="dark"] .recipe-missing-popover strong,
[data-theme="dark"] .recipe-missing-popover ul { color: var(--text, #f1f5f9); }

.btn-inv-fav {
    flex-shrink: 0;
    align-self: center;
    background: none;
    border: none;
    font-size: 1.45rem;
    cursor: pointer;
    color: var(--text-muted);
    padding: 6px 4px;
    line-height: 1;
    transition: color 0.2s, transform 0.15s;
    z-index: 3;
}
.btn-inv-fav:hover { color: #f59e0b; transform: scale(1.15); }
.btn-inv-fav.active { color: #f59e0b; }

.inv-section-header.inv-fav-section {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 4px 4px;
    font-size: 0.85rem;
    font-weight: 700;
    color: #b45309;
    border-bottom: 1px solid var(--border);
    margin-top: 0;
}

.inventory-item.inv-item-fav {
    box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.35), var(--shadow);
}

/* ===== PORTION RESCALER (#123) ===== */
.recipe-persons-ctrl {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 0 6px;
    vertical-align: middle;
    line-height: 1;
}

.btn-persons-adj {
    background: none;
    border: none;
    color: var(--text-primary);
    border-radius: 50%;
    width: 18px;
    height: 18px;
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    flex-shrink: 0;
    transition: background 0.15s;
}

.btn-persons-adj:hover { background: var(--accent, #6366f1); color: #fff; }

#recipe-persons-display {
    white-space: nowrap;
    font-size: 0.82rem;
}

/* ===== MACRONUTRIENT PANEL (#118) ===== */
.macro-bars {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 12px 0 8px;
}

.macro-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.macro-label {
    font-size: 0.75rem;
    color: var(--text-muted);
    min-width: 70px;
    flex-shrink: 0;
}

.macro-bar-wrap {
    flex: 1;
    height: 8px;
    background: var(--bg-secondary, #1e2a3a);
    border-radius: 4px;
    overflow: hidden;
}

.macro-bar-fill {
    height: 100%;
    width: 0%;
    border-radius: 4px;
    transition: width 0.6s ease;
}

.macro-val {
    font-size: 0.72rem;
    color: var(--text-primary);
    text-align: right;
    min-width: 80px;
    flex-shrink: 0;
}

.macro-val small {
    color: var(--text-muted);
}

/* ===== IDLE SCREEN — ambient kitchen dashboard =====
   Pure black for OLED walls; the app's own palette on the cards (emerald = do it now /
   positive, amber = expiring, coral = critical, sky = context), one card at a time, a
   footer with the numbers that matter. Rendered by assets/js/screensaver.js. */
.screensaver-overlay {
    position: fixed;
    inset: 0;
    background: #000;
    z-index: 10000;
    display: flex;
    align-items: stretch;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.8s ease;
    /* The idle screen's palette: the app's accents, on the dark surface. */
    --ss-card: #121514;
    --ss-card-border: #222926;
    --ss-text: rgba(255, 255, 255, 0.94);
    --ss-muted: rgba(255, 255, 255, 0.55);
    --ss-emerald: #10b981;
    --ss-amber: #f59e0b;
    --ss-coral: #ef4444;
    --ss-sky: #38bdf8;
    --ss-radius: 20px;
}
.screensaver-overlay.visible { opacity: 1; }

/* Pixel drift: the stage moves a few pixels every couple of minutes (burn-in on a wall
   that shows the same clock for hours). Transform only — no layout, no repaint. */
.ss-stage {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    gap: clamp(14px, 2.6vh, 30px);
    width: min(1100px, 100%);
    /* The bottom room keeps the footer clear of the «Sblocca» pill. */
    padding: clamp(20px, 4.5vh, 54px) clamp(18px, 5vw, 64px)
             max(64px, calc(env(safe-area-inset-bottom, 0px) + 52px));
    box-sizing: border-box;
    transition: transform 1.4s ease;
    will-change: transform;
}

/* ── head: the clock, the date, the context pill ── */
.ss-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}
.ss-clock {
    color: var(--ss-text);
    font-size: clamp(3.4rem, 11vw, 7.5rem);
    font-weight: 200;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    line-height: 1;
    text-align: center;
    user-select: none;
}
.ss-date {
    margin-top: 6px;
    font-size: clamp(0.9rem, 2vw, 1.25rem);
    font-weight: 300;
    color: var(--ss-muted);
    letter-spacing: 0.02em;
}
/* Capitalise the first letter only: `text-transform: capitalize` turned «mercoledì 12
   novembre» into «Mercoledì 12 Novembre». */
.ss-date::first-letter { text-transform: uppercase; }
.ss-context {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 16px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--ss-sky) 34%, transparent);
    background: color-mix(in srgb, var(--ss-sky) 12%, transparent);
    color: color-mix(in srgb, var(--ss-sky) 55%, white);
    font-size: clamp(0.8rem, 1.5vw, 0.95rem);
    font-weight: 600;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ss-context[hidden] { display: none; }
.ss-context-sep { opacity: 0.45; }

/* ── core: ONE card ── */
.ss-core {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    padding: 4px 0;
}
.ss-card {
    width: min(760px, 100%);
    max-height: 100%;
    overflow-y: auto;
    background: var(--ss-card);
    border: 1px solid var(--ss-card-border);
    border-radius: var(--ss-radius);
    padding: clamp(16px, 2.6vh, 26px) clamp(18px, 3vw, 30px);
    box-sizing: border-box;
    color: var(--ss-text);
    transition: opacity 0.28s ease, transform 0.28s ease;
}
/* ── the change of card ──────────────────────────────────────────────────────
   The old card dissolves going UP, the new one comes back DOWN from the top and its blocks
   settle one after the other (a `transition-delay` per child, no keyframes: an animation with
   `fill: both` would fight the exit transition of the next change). `is-pre` is the pose the
   new card is laid out in for one frame; removing it is what starts the movement. */
.ss-card {
    transition: opacity 0.42s cubic-bezier(0.4, 0, 0.2, 1),
                transform 0.42s cubic-bezier(0.4, 0, 0.2, 1),
                filter 0.42s ease;
}
.ss-core.is-out .ss-card {
    opacity: 0;
    transform: translateY(-30px) scale(0.985);
    filter: blur(5px);
}
.ss-core.is-out .ss-card > * {
    transition-duration: 0.22s;
    transition-delay: 0ms !important;
}
.ss-card > * {
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 0.8, 0.28, 1);
    transition-delay: var(--ss-el-delay, 0ms);
}
.ss-core.is-pre .ss-card,
.ss-core.is-pre .ss-card > * { transition: none; }
.ss-core.is-pre .ss-card {
    opacity: 0;
    transform: translateY(-30px) scale(0.985);
    filter: blur(5px);
}
.ss-core.is-pre .ss-card > * {
    opacity: 0;
    transform: translateY(-14px);
}
/* The cascade: the eyebrow first, then the title, the facts, the numbers and the action. */
.ss-core .ss-card > *:nth-child(1) { --ss-el-delay: 110ms; }
.ss-core .ss-card > *:nth-child(2) { --ss-el-delay: 170ms; }
.ss-core .ss-card > *:nth-child(3) { --ss-el-delay: 230ms; }
.ss-core .ss-card > *:nth-child(4) { --ss-el-delay: 290ms; }
.ss-core .ss-card > *:nth-child(5) { --ss-el-delay: 350ms; }
/* A wall is left alone for hours: the movement is welcome once every 30 s, never at the cost
   of a low-end renderer. Who asks for less motion gets a plain, quick fade. */
@media (prefers-reduced-motion: reduce) {
    .ss-card,
    .ss-card > * {
        transition: opacity 0.2s linear !important;
        filter: none !important;
        transform: none !important;
    }
    .ss-core.is-out .ss-card { opacity: 0; }
    .ss-core.is-pre .ss-card,
    .ss-core.is-pre .ss-card > * { opacity: 0; }
}
.ss-card[data-accent="emerald"] { --ss-accent: var(--ss-emerald); }
.ss-card[data-accent="amber"]   { --ss-accent: var(--ss-amber); }
.ss-card[data-accent="coral"]   { --ss-accent: var(--ss-coral); }
.ss-card[data-accent="sky"]     { --ss-accent: var(--ss-sky); }

.ss-eyebrow {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ss-accent, var(--ss-muted));
}
/* «· fatta 11 giorni fa»: one unit, so the dot is never left dangling at the end of a line. */
.ss-eyebrow-sub { white-space: nowrap; }

.ss-title {
    margin: 8px 0 0;
    font-size: clamp(1.2rem, 3.2vw, 1.9rem);
    font-weight: 700;
    line-height: 1.2;
}
.ss-sub {
    margin: 6px 0 0;
    font-size: clamp(0.86rem, 1.7vw, 1rem);
    color: var(--ss-muted);
    line-height: 1.45;
}
.ss-meta {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 14px;
}
.ss-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 600;
    border: 1px solid #2a322e;
    background: #171c1a;
    color: rgba(255, 255, 255, 0.8);
}
.ss-chip.is-ok {
    border-color: color-mix(in srgb, var(--ss-emerald) 40%, transparent);
    background: color-mix(in srgb, var(--ss-emerald) 14%, transparent);
    color: #6ee7b7;
}
.ss-chip.is-warn {
    border-color: color-mix(in srgb, var(--ss-amber) 40%, transparent);
    background: color-mix(in srgb, var(--ss-amber) 14%, transparent);
    color: #fcd34d;
}
.ss-chip.is-danger {
    border-color: color-mix(in srgb, var(--ss-coral) 45%, transparent);
    background: color-mix(in srgb, var(--ss-coral) 14%, transparent);
    color: #fca5a5;
}
/* rows of the alerts card — they open the product sheet, so they are buttons */
.ss-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 14px;
}
.ss-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 14px;
    border: 1px solid #222926;
    background: #161a18;
    text-align: left;
    color: inherit;
    font: inherit;
    width: 100%;
    cursor: pointer;
}
.ss-row[data-tone="coral"] { border-color: color-mix(in srgb, var(--ss-coral) 34%, #222926); }
.ss-row-icon { flex: 0 0 auto; font-size: 1.15rem; line-height: 1; }
.ss-row-info { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
.ss-row-name {
    font-size: clamp(0.92rem, 1.8vw, 1.05rem);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ss-row-meta { margin-top: 2px; font-size: 0.82rem; color: var(--ss-muted); }
.ss-row-badge {
    flex: 0 0 auto;
    font-size: 0.78rem;
    font-weight: 800;
    padding: 4px 10px;
    border-radius: 999px;
    white-space: nowrap;
}
.ss-row[data-tone="amber"] .ss-row-badge {
    background: color-mix(in srgb, var(--ss-amber) 18%, transparent);
    color: #fcd34d;
}
.ss-row[data-tone="coral"] .ss-row-badge {
    background: color-mix(in srgb, var(--ss-coral) 18%, transparent);
    color: #fca5a5;
}

/* «Fatta 12 giorni fa: ti era piaciuta?» — a question the household answers with a thumb, so
   the archive learns. Neutral pills: it is not the action that writes the pantry. */
.ss-ask {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 16px;
    font-size: clamp(0.86rem, 1.7vw, 0.98rem);
    color: var(--ss-muted);
}
.ss-ask-q { font-weight: 600; }
.ss-ask.is-done { color: #6ee7b7; font-weight: 700; }
.ss-thumb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 999px;
    border: 1px solid #2a322e;
    background: #171c1a;
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
}
.ss-thumb:active { background: #232b28; transform: scale(0.96); }

/* the action of a card: ONE emerald, and only when it does something */
.ss-action {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    padding: 10px 18px;
    border-radius: 999px;
    border: none;
    background: var(--ss-emerald);
    color: #04231a;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 800;
    cursor: pointer;
}
.ss-action:active { transform: scale(0.98); }

/* ── nutrition: the ring + the three scores, high contrast ── */
.ss-nutr {
    display: flex;
    gap: clamp(14px, 3vw, 28px);
    align-items: center;
    flex-wrap: wrap;
    margin-top: 12px;
}
.ss-pie {
    width: clamp(116px, 22vw, 164px);
    height: clamp(116px, 22vw, 164px);
    border-radius: 50%;
    flex: 0 0 auto;
    /* A donut, not a pancake: the middle is punched out with a mask. */
    mask: radial-gradient(circle, transparent 46%, #000 47%);
    -webkit-mask: radial-gradient(circle, transparent 46%, #000 47%);
}
.ss-rings {
    display: flex;
    gap: clamp(10px, 2.4vw, 22px);
    flex: 1 1 220px;
    justify-content: center;
    flex-wrap: wrap;
}
.ss-ring-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.ss-ring {
    width: clamp(62px, 11vw, 82px);
    height: clamp(62px, 11vw, 82px);
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-weight: 800;
    font-size: clamp(0.8rem, 1.6vw, 0.95rem);
    color: #fff;
    /* --pct and --ring-color are set inline by the renderer */
    background: conic-gradient(var(--ring-color) calc(var(--pct) * 1%), #1d2422 0);
    box-shadow: inset 0 0 0 8px #121514;
}
.ss-ring-label {
    font-size: 0.72rem;
    color: var(--ss-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.ss-legend { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
.ss-leg { display: flex; align-items: center; gap: 8px; font-size: 0.82rem; color: var(--ss-muted); }
.ss-leg-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.ss-leg b { color: var(--ss-text); margin-left: auto; }

/* ── footer: the vital numbers, one line ── */
.ss-foot {
    display: flex;
    gap: clamp(10px, 2.4vw, 22px);
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    font-size: clamp(0.78rem, 1.5vw, 0.95rem);
    color: var(--ss-muted);
}
.ss-foot[hidden] { display: none; }
.ss-kpi { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.ss-kpi b { color: var(--ss-text); font-weight: 700; }
.ss-kpi-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; }

/* ── A phone is not a small tablet ───────────────────────────────────────────
   The portrait scale is tuned on a 700–1000 px wide tablet; below ~460 px the same numbers
   make the card taller than the band and the primary action ends up half cut. Everything here
   is one step smaller, nothing is hidden. */
@media (max-width: 460px) {
    .ss-head { gap: 6px; }
    .ss-clock { font-size: clamp(2.6rem, 13vw, 4rem); }
    .ss-date { font-size: 0.95rem; margin-top: 4px; }
    .ss-context { font-size: 0.82rem; padding: 6px 12px; }
    .ss-card { padding: 12px 12px 14px; border-radius: 18px; }
    .ss-eyebrow { font-size: 0.78rem; gap: 6px; }
    .ss-title { font-size: 1.35rem; margin-top: 6px; }
    .ss-sub { font-size: 0.9rem; }
    .ss-meta { margin-top: 10px; gap: 6px; }
    .ss-chip { font-size: 0.86rem; padding: 5px 10px; }
    .ss-ask { margin-top: 10px; gap: 8px; font-size: 0.82rem; }
    .ss-thumb { width: 40px; height: 40px; font-size: 1.05rem; }
    .ss-action { margin-top: 12px; padding: 10px 18px; font-size: 0.9rem; }
    .ss-rows { margin-top: 10px; gap: 6px; }
    .ss-row { padding: 8px 10px; gap: 10px; }
    .ss-row-icon { font-size: 1.1rem; }
    .ss-row-name { font-size: 0.95rem; }
    .ss-row-meta { font-size: 0.82rem; }
    .ss-row-badge { font-size: 0.78rem; padding: 4px 9px; }
    .ss-pie { width: min(46vw, 150px); height: min(46vw, 150px); }
    .ss-ring { width: 56px; height: 56px; font-size: 0.8rem; }
    .ss-ring-label { font-size: 0.7rem; }
    .ss-leg { font-size: 0.82rem; }
    .ss-foot { font-size: 0.85rem; }
}

/* The one-off hint («tap for the next view · swipe up to leave»), under the vitals. */
#screensaver-hint {
    justify-self: center;
    align-self: end;
    margin-top: -6px;
    font-size: clamp(0.76rem, 1.4vw, 0.86rem);
    color: var(--ss-muted);
    opacity: 0.75;
    text-align: center;
}

/* ── unlock: the way back (a tap flips the view, it must NOT close) ── */
.ss-unlock {
    position: absolute;
    bottom: max(18px, env(safe-area-inset-bottom, 18px));
    left: 50%;
    transform: translateX(-50%);
    z-index: 10003;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 18px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.8);
    font: inherit;
    font-size: 0.84rem;
    font-weight: 700;
    cursor: pointer;
}
.ss-unlock:active { background: rgba(255, 255, 255, 0.16); }

/* A phone turns the card into a stack: the charts over the length, the rows on one column.
   The controls of a pinned run move to the BOTTOM here: at the top-right they covered the
   clock on a 393 px screen (measured), and the clock is the one thing that must stay whole. */
@media (max-width: 640px) {
    /* 76 px clear the «Sblocca» pill; a pinned run adds the room its own bar needs. */
    .ss-stage { padding: 16px 12px 76px; gap: 10px; }
    .screensaver-overlay.is-pinned .ss-stage { padding-bottom: 152px; }
    .ss-card {
        padding: 14px 14px 16px;
        /* A phone has no room for the portrait panel's floor: `min-height` wins over
           `max-height`, and a 240 px card in a 180 px band overflows *above* the top edge. */
        min-height: 0;
        /* `center` on a flex column whose content is TALLER than the box pushes the first
           block above the top edge, where no scroll can reach it — the recipe's eyebrow was
           printed over the date. Start at the top and let the card scroll. */
        justify-content: flex-start;
    }
    /* The charts stack instead of sharing one row: at 360 px the pie plus three rings do not
       fit, and the row used to push the whole card past the right edge. */
    .ss-nutr { flex-direction: column; justify-content: center; gap: 14px; }
    .ss-pie { width: min(54vw, 180px); height: min(54vw, 180px); }
    .ss-rings { flex: 0 0 auto; gap: 10px; }
    .ss-ring { width: clamp(58px, 16vw, 72px); height: clamp(58px, 16vw, 72px); font-size: 0.82rem; }
    /* A long ingredient list or a long place name may not become a horizontal scroll. */
    .ss-title, .ss-sub, .ss-row-name, .ss-chip, .ss-row-badge { overflow-wrap: anywhere; }
    .ss-chip, .ss-row-badge { max-width: 100%; }
    .ss-kpi { white-space: normal; }
    .ss-rows { gap: 6px; }
    .ss-foot { gap: 8px 14px; }
}

/* A short screen (a small phone, or a landscape one): the panel may never be taller than the
   band it lives in, whatever the portrait scale asks for. */
@media (max-height: 760px) {
    .ss-card { min-height: 0; justify-content: flex-start; }
}

/* ── Portrait (a tablet standing on the counter) ─────────────────────────────
   Every size above is tuned on the WIDTH of a landscape screen; standing upright the same
   `vw` is a third of it while the height is all free, so the clock looked tiny and the card
   floated in a black field. Here the scale follows the narrow side instead: a bigger clock,
   a full-width card and type that can be read from a metre away. The composition stays the
   three bands of the landscape one (head / card / vitals), it is the sizes that change. */
@media (orientation: portrait) and (min-width: 461px) {
    .ss-stage {
        width: 100%;
        max-width: 760px;
        padding-top: clamp(16px, 3.2vh, 40px);
        gap: clamp(16px, 2.6vh, 34px);
    }
    .ss-clock { font-size: clamp(4.4rem, 17vw, 9rem); }
    .ss-date { font-size: clamp(1.05rem, 3.2vw, 1.6rem); margin-top: 10px; }
    .ss-context {
        /* A flex row broke the separator onto its own column when the text wrapped:
           inline-block flows the spans like a sentence. */
        display: inline-block;
        max-width: 100%;
        font-size: clamp(0.95rem, 2.3vw, 1.2rem);
        padding: 9px 20px;
        white-space: normal;
        text-align: center;
        line-height: 1.35;
    }
    /* The card is a PANEL, not a slip of paper in a black field: it takes the height the band
       gives it (up to a limit, so a short card never looks stretched) and its blocks are
       centred inside. That is what fills the portrait screen instead of leaving a void. */
    .ss-card {
        width: 100%;
        display: flex;
        flex-direction: column;
        justify-content: center;
        justify-content: safe center;   /* falls back to flex-start when it does not fit */
        min-height: clamp(240px, 40vh, 520px);
        padding: clamp(20px, 3.2vw, 32px) clamp(18px, 3.4vw, 32px);
        border-radius: 24px;
    }
    .ss-card > * { flex: 0 0 auto; }
    .ss-eyebrow { font-size: clamp(0.9rem, 2vw, 1.05rem); gap: 10px; }
    .ss-title { font-size: clamp(1.7rem, 5.2vw, 2.6rem); margin-top: 10px; }
    .ss-sub { font-size: clamp(1.05rem, 2.7vw, 1.3rem); }
    .ss-meta { gap: 10px; margin-top: 16px; }
    .ss-chip { font-size: clamp(0.95rem, 2.3vw, 1.15rem); padding: 8px 14px; }
    .ss-action { font-size: clamp(1.05rem, 2.5vw, 1.25rem); padding: 14px 26px; margin-top: 20px; align-self: flex-start; }
    .ss-row { padding: 14px 16px; gap: 14px; }
    .ss-row-icon { font-size: 1.5rem; }
    .ss-row-name { font-size: clamp(1.1rem, 2.9vw, 1.4rem); }
    .ss-row-meta { font-size: clamp(0.95rem, 2.2vw, 1.1rem); }
    .ss-row-badge { font-size: clamp(0.9rem, 2.1vw, 1.1rem); padding: 6px 12px; }
    /* The rows share the panel's height: three lines spread over a tall card look like a
       dashboard, three lines bunched at the top look like a hole underneath. */
    .ss-rows { gap: 10px; margin-top: 18px; flex: 1 1 auto; justify-content: space-evenly; }
    .ss-nutr { gap: clamp(18px, 4vw, 34px); }
    .ss-pie { width: clamp(150px, 34vw, 220px); height: clamp(150px, 34vw, 220px); }
    .ss-ring { width: clamp(78px, 16vw, 108px); height: clamp(78px, 16vw, 108px); font-size: clamp(1rem, 2.6vw, 1.25rem); }
    .ss-ring-label { font-size: clamp(0.82rem, 2vw, 1rem); }
    .ss-leg { font-size: clamp(0.95rem, 2.2vw, 1.1rem); }
    .ss-foot { font-size: clamp(0.95rem, 2.3vw, 1.2rem); gap: 12px 20px; }
    .ss-kpi { gap: 9px; }
}

/* Settings: the four view switches of the idle screen, two by two */
.ss-views-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 8px 16px;
    margin-top: 8px;
}
/* Shortcuts of the idle screen (recipe / scan) and the controls of a PINNED run. */
.screensaver-shortcuts {
    position: absolute;
    bottom: max(32px, env(safe-area-inset-bottom, 32px));
    right: 28px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    z-index: 10001;
}
.screensaver-pin-bar {
    position: absolute;
    top: max(18px, env(safe-area-inset-top, 18px));
    right: 18px;
    z-index: 10002;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
    max-width: calc(100vw - 36px);
}
.screensaver-pin-bar[hidden] { display: none; }
.screensaver-pin-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.10);
    color: rgba(255, 255, 255, 0.92);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}
.screensaver-pin-btn:active { background: rgba(255, 255, 255, 0.2); }
.screensaver-exit-count {
    font-variant-numeric: tabular-nums;
    opacity: 0.72;
    font-size: 0.76rem;
}
.screensaver-shortcut-btn {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,0.25);
    background: rgba(255,255,255,0.1);
    color: white;
    font-size: 1.8rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.15s;
    user-select: none;
    -webkit-user-select: none;
}
.screensaver-shortcut-btn:active {
    background: rgba(255,255,255,0.25);
    transform: scale(0.92);
}

/* On a phone the pinned controls move to the BOTTOM: at the top-right they covered the
   clock on a 393 px screen (measured), and the clock is the one thing that must stay whole.
   This block sits after the base rules on purpose — before them, `top` would win. */
@media (max-width: 640px) {
    .screensaver-pin-bar {
        top: auto;
        bottom: max(62px, calc(env(safe-area-inset-bottom, 0px) + 58px));
        left: 12px;
        right: 12px;
        justify-content: center;
    }
    .ss-unlock { bottom: max(14px, env(safe-area-inset-bottom, 14px)); }
    /* The two round shortcuts are a wall feature: on a phone «Sblocca» + the nav are enough,
       and they would overlap the pinned controls. */
    .screensaver-shortcuts { display: none; }
}

/* ── Dashboard nutrition card ── */
.nutr-card {
    background: var(--bg-card, #fff);
    border-radius: 14px;
    padding: 16px;
    box-shadow: var(--shadow);
    margin-bottom: 16px;
}

/* ── Extra insight panels (overview, freshness, trend) ──
   They reuse the .nutr-card shell; these blocks keep them in the same language
   as the waste/nutrition/monthly panels they rotate with. */
.insight-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
    gap: 8px;
    margin-top: 10px;
}

.insight-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 10px 6px;
    border-radius: 12px;
    background: rgba(148, 163, 184, 0.14);
    text-align: center;
}

.insight-tile-value {
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.1;
}

.insight-tile-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted, #6b7280);
}

.insight-foot {
    margin-top: 10px;
    font-size: 0.78rem;
    line-height: 1.4;
    color: var(--text-muted, #6b7280);
}

.insight-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border, #e5e7eb);
}

.insight-row:last-of-type { border-bottom: none; }

.insight-row-value {
    font-size: 1.5rem;
    font-weight: 800;
    min-width: 52px;
    text-align: center;
}

.insight-row-body {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.insight-row-label {
    font-size: 0.85rem;
    font-weight: 600;
}

.insight-row-diff {
    font-size: 0.76rem;
    color: var(--text-muted, #6b7280);
}

.fresh-bars { margin-top: 10px; }

.nutr-body {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    margin: 12px 0;
}
.nutr-pie-wrap {
    position: relative;
    flex-shrink: 0;
}
.nutr-pie-3d {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    transform: perspective(180px) rotateX(38deg) scale(0.82);
    box-shadow: 0 8px 20px rgba(0,0,0,0.18);
    transition: transform 0.7s cubic-bezier(.34,1.56,.64,1);
    will-change: transform;
}
.nutr-pie-3d.nutr-pie-ready {
    transform: perspective(180px) rotateX(28deg) scale(1);
    animation: nutr-pie-spin 22s linear infinite;
}
@keyframes nutr-pie-spin {
    from { transform: perspective(180px) rotateX(28deg) rotate(0deg) scale(1); }
    to   { transform: perspective(180px) rotateX(28deg) rotate(360deg) scale(1); }
}
.nutr-pie-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.nutr-pie-total {
    font-size: 1.4rem;
    font-weight: 700;
    line-height: 1;
}
.nutr-pie-label {
    font-size: .6rem;
    color: var(--text-secondary);
}
.nutr-legend {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.nutr-leg-row {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: .78rem;
}
.nutr-leg-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.nutr-leg-pct {
    margin-left: auto;
    color: var(--text-secondary);
    font-weight: 600;
}
/* Score bars */
.nutr-scores {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 6px;
}
.nutr-score-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .78rem;
}
.nutr-score-label { flex: 0 0 80px; white-space: nowrap; }
.nutr-score-track {
    flex: 1;
    height: 7px;
    border-radius: 4px;
    background: rgba(0,0,0,0.07);
    overflow: hidden;
}
.nutr-score-fill {
    height: 100%;
    border-radius: 4px;
    width: 0%;
    transition: width 1s ease;
}
.nutr-score-val { flex: 0 0 32px; text-align: right; font-weight: 600; }

/* ===== MONTHLY STATS PANEL ===== */
.ms-main-row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 12px 0 8px;
}
.ms-main-num {
    font-size: 2.8rem;
    font-weight: 700;
    color: #6366f1;
    line-height: 1;
    letter-spacing: -0.02em;
}
.ms-main-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ms-main-label {
    font-size: .85rem;
    color: #94a3b8;
}
.ms-trend {
    font-size: .8rem;
    font-weight: 500;
}
.ms-cats-section {
    margin: 6px 0 4px;
}
.ms-cats-title {
    font-size: .68rem;
    font-weight: 600;
    color: #64748b;
    text-transform: uppercase;
    letter-spacing: .06em;
    margin-bottom: 7px;
}
.ms-cat-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 5px;
}
.ms-cat-name {
    font-size: .74rem;
    color: #cbd5e1;
    min-width: 78px;
    max-width: 78px;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ms-cat-bar-wrap {
    flex: 1;
    height: 8px;
    background: #1e293b;
    border-radius: 4px;
    overflow: hidden;
}
.ms-cat-bar {
    height: 100%;
    border-radius: 4px;
    width: 0;
}
.ms-cat-cnt {
    font-size: .7rem;
    color: #64748b;
    min-width: 22px;
    text-align: right;
}
.ms-badges-row {
    margin-top: 6px;
}

/* ===== Spend (shopping spend) panel ===== */
#spend-section .spend-card {
    background: rgba(99,102,241,0.06);
    border: 1.5px solid rgba(99,102,241,0.18);
}
.spend-bars {
    display: flex;
    gap: 10px;
    align-items: flex-end;
    margin-top: 10px;
}
.spend-bar-col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
}
.spend-bar-rail {
    width: 100%;
    height: 78px;
    background: rgba(0,0,0,0.07);
    border-radius: 10px;
    overflow: hidden;
    position: relative;
}
.spend-bar-fill {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 0%;
    background: linear-gradient(180deg, rgba(99,102,241,0.95), rgba(34,197,94,0.55));
    border-radius: 10px;
    transition: height 0.7s ease;
}
.spend-bar-month {
    font-size: .7rem;
    color: #94a3b8;
    max-width: 90px;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}


/* ===== SETUP WIZARD ===== */
.setup-wizard-content {
    max-width: 480px;
    width: 95%;
    margin: auto;
    border-radius: 20px;
    overflow: hidden;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}
.setup-header {
    background: var(--primary);
    color: #fff;
    padding: 24px 20px 16px;
    text-align: center;
}
.setup-header h2 {
    margin: 0 0 12px;
    font-size: 1.5rem;
}
.setup-progress {
    display: flex;
    gap: 8px;
    justify-content: center;
}
.setup-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(255,255,255,0.3);
    transition: background 0.3s, transform 0.3s;
}
.setup-dot.active {
    background: #fff;
    transform: scale(1.3);
}
.setup-dot.done {
    background: var(--success-light);
}
.setup-body {
    padding: 24px 20px;
    overflow-y: auto;
    flex: 1;
}
.setup-body h3 {
    margin: 0 0 8px;
    font-size: 1.2rem;
}
.setup-body p {
    color: #666;
    margin: 0 0 16px;
    font-size: 0.9rem;
    line-height: 1.5;
}
.setup-body .form-group {
    margin-bottom: 16px;
}
.setup-body .form-input {
    width: 100%;
    box-sizing: border-box;
}
.setup-lang-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 10px;
    margin: 12px 0;
}
.setup-lang-btn {
    padding: 14px 12px;
    border: 2px solid #e2e8f0;
    border-radius: 12px;
    background: #fff;
    cursor: pointer;
    text-align: center;
    font-size: 1rem;
    transition: border-color 0.2s, background 0.2s;
}
.setup-lang-btn.selected {
    border-color: var(--primary);
    background: rgba(45,80,22,0.08);
}
.setup-lang-btn:hover {
    border-color: var(--primary-light);
}
.setup-footer {
    padding: 16px 20px;
    display: flex;
    justify-content: space-between;
    border-top: 1px solid #e2e8f0;
    gap: 12px;
}
.setup-footer .btn {
    flex: 1;
    padding: 12px;
    font-size: 1rem;
}
.setup-skip-link {
    display: block;
    text-align: center;
    color: #999;
    font-size: 0.8rem;
    margin-top: 12px;
    cursor: pointer;
    text-decoration: underline;
}
.setup-skip-link:hover {
    color: #666;
}

/* ===== QUICK ACCESS BUTTONS ===== */
#quick-access-section {
    margin-bottom: 12px;
}
.quick-access-details {
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--bg-card);
    padding: 0 10px;
}
.quick-access-summary {
    cursor: pointer;
    list-style: none;
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--text-main);
    padding: 10px 2px;
}
.quick-access-summary::-webkit-details-marker { display: none; }
.quick-access-body { padding-bottom: 10px; }
.quick-access-group {
    margin-bottom: 10px;
}
.quick-access-label {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text-light);
    margin-bottom: 8px;
    padding-left: 2px;
}
.quick-access-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
}
.quick-access-grid-8 {
    grid-template-columns: repeat(4, 1fr);
}
.quick-access-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 4px 8px;
    background: var(--bg-card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
    box-shadow: var(--shadow);
    min-width: 0;
}
.quick-access-btn:active {
    transform: scale(0.95);
}
.quick-access-btn:hover {
    box-shadow: var(--shadow-lg);
    border-color: var(--primary-light);
}
.qa-img {
    width: 44px;
    height: 44px;
    border-radius: 8px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    background: var(--bg);
    flex-shrink: 0;
}
.qa-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.qa-name {
    font-size: 0.72rem;
    font-weight: 600;
    text-align: center;
    line-height: 1.2;
    max-height: 2.4em;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
    color: var(--text);
}
.qa-brand {
    font-size: 0.62rem;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* ===== BANNER VARIANTS: EXPIRED & EXPIRING ===== */
.alert-banner.banner-expired { /* hue: surfaces.css */ }
.banner-expired .alert-banner-title {
    color: #991b1b;
}
.banner-expired .alert-banner-counter {
    color: #b91c1c;
}
.alert-banner.banner-expiring { /* hue: surfaces.css */ }
.banner-expiring .alert-banner-title {
    color: #9a3412;
}
.banner-expiring .alert-banner-counter {
    color: #c2410c;
}
.btn-banner-use {
    background: #dbeafe;
    color: #1d4ed8;
}
.btn-banner-throw {
    background: #fee2e2;
    color: #dc2626;
}
.alert-banner.banner-expired-ok { /* hue: surfaces.css */ }
.banner-expired-ok .alert-banner-title {
    color: #14532d;
}
.banner-expired-ok .alert-banner-counter {
    color: #15803d;
}
.banner-expired-ok .banner-dot.active { background: #16a34a; }
.alert-banner.banner-expired-warning { /* hue: surfaces.css */ }
.banner-expired-warning .alert-banner-title {
    color: #78350f;
}
.banner-expired-warning .alert-banner-counter {
    color: #92400e;
}
.banner-expired-warning .banner-dot.active { background: #d97706; }
.alert-banner.banner-expired-danger {
    /* hue: surfaces.css */
    border-width: 2px;
}
.banner-expired-danger .alert-banner-title {
    color: #7f1d1d;
}
/* Product + brand on the banner title, one line */
.banner-brand {
    font-size: 0.9em;
    font-weight: 600;
    opacity: 0.75;
}
/* Banner detail: one fact per line, then the verdict sentence */
.banner-fact {
    font-size: 0.82rem;
    line-height: 1.4;
}
.banner-verdict {
    margin-top: 4px;
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.4;
}
/* Same verdict line inside a dashboard row */
.alert-item-verdict {
    margin-top: 2px;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.35;
}
/* ── Safety verdict badges ───────────────────────────────────────────────────
   One word + emoji on the row (Va bene / Controlla / Non mangiare / Buttalo);
   the long advice lives in the title tooltip, never as a paragraph. Declared
   after .banner-verdict / .alert-item-verdict, which survive as the base. */
.safety-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
    border: 1px solid transparent;
}
.safety-pill-ok {
    background: #dcfce7;
    color: #166534;
    border-color: #86efac;
}
.safety-pill-warning {
    background: #fef3c7;
    color: #92400e;
    border-color: #fcd34d;
}
.safety-pill-danger {
    background: #fee2e2;
    color: #b91c1c;
    border-color: #fca5a5;
}
[data-theme="dark"] .safety-pill-ok      { background: rgba(22, 101, 52, 0.28);  color: #86efac; border-color: rgba(134, 239, 172, 0.45); }
[data-theme="dark"] .safety-pill-warning { background: rgba(146, 64, 14, 0.28);  color: #fdba74; border-color: rgba(253, 186, 116, 0.45); }
[data-theme="dark"] .safety-pill-danger  { background: rgba(153, 27, 27, 0.28);  color: #fca5a5; border-color: rgba(252, 165, 165, 0.45); }
.btn-banner-throw-primary {
    background: #dc2626;
    color: #fff;
    font-weight: 600;
}
.btn-banner-use-danger {
    background: #f3f4f6;
    color: #9ca3af;
    font-size: 0.8em;
}
.btn-banner-vacuum {
    background: #ede9fe;
    color: #6d28d9;
}
.btn-banner-extend {
    background: #ecfdf5;
    color: #047857;
}
.btn-banner-edit2 {
    background: #e0f2fe;
    color: #0369a1;
}

.btn-alert-extend {
    border: 0;
    background: #ecfdf5;
    color: #047857;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 4px 8px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
}
.btn-alert-extend:active {
    transform: scale(0.97);
}

/* ===== PAGE HEADER ACTION BUTTON (export etc.) ===== */
.page-header-actions {
    margin-left: auto;
    display: flex;
    gap: 6px;
    align-items: center;
}
.page-header-action-btn {
    margin-left: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 8px 12px;
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.2s;
    color: var(--primary);
}
.page-header-action-btn:active {
    transform: scale(0.95);
    opacity: 0.8;
}

/* ===== CSV IMPORT MODAL ===== */
.import-modal {
    padding: 0 4px 8px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.import-schema {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    font-size: 0.82rem;
}
.import-schema h4 {
    margin: 0 0 8px;
    font-size: 0.9rem;
}
.import-schema-cols {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 8px;
}
.import-schema-cols code {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 2px 6px;
    font-size: 0.75rem;
}
.import-schema-cols code.required {
    border-color: var(--primary);
    color: var(--primary);
    font-weight: 600;
}
.import-schema ul {
    margin: 0;
    padding-left: 18px;
    color: var(--text-light);
    line-height: 1.45;
}
.import-file-row {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.import-file-row input[type="file"] {
    font-size: 0.9rem;
}
.import-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.85rem;
}
.import-pill {
    border-radius: 999px;
    padding: 4px 10px;
    border: 1px solid var(--border);
    background: var(--bg);
}
.import-pill.ok { border-color: #86efac; background: #f0fdf4; color: #166534; }
.import-pill.warn { border-color: #fcd34d; background: #fffbeb; color: #92400e; }
.import-pill.err { border-color: #fca5a5; background: #fef2f2; color: #991b1b; }
.import-preview-wrap {
    max-height: 36vh;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.import-preview-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.78rem;
}
.import-preview-table th,
.import-preview-table td {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
    text-align: left;
    vertical-align: top;
}
.import-preview-table th {
    position: sticky;
    top: 0;
    background: var(--bg-card);
    z-index: 1;
}
.import-preview-table tr.status-error td { background: #fef2f2; }
.import-preview-table tr.status-warning td { background: #fffbeb; }
.import-status-badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 2px 6px;
    border-radius: 4px;
}
.import-status-badge.ok { background: #dcfce7; color: #166534; }
.import-status-badge.warning { background: #fef3c7; color: #92400e; }
.import-status-badge.error { background: #fee2e2; color: #991b1b; }
.import-row-issues {
    color: var(--text-light);
    font-size: 0.72rem;
    margin-top: 2px;
}
.import-error-box {
    background: #fef2f2;
    border: 1px solid #fca5a5;
    color: #991b1b;
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    font-size: 0.88rem;
}
[data-theme="dark"] .import-pill.ok { background: #14532d; color: #bbf7d0; border-color: #166534; }
[data-theme="dark"] .import-pill.warn { background: #78350f; color: #fde68a; border-color: #92400e; }
[data-theme="dark"] .import-pill.err { background: #7f1d1d; color: #fecaca; border-color: #991b1b; }
[data-theme="dark"] .import-preview-table tr.status-error td { background: rgba(127, 29, 29, 0.35); }
[data-theme="dark"] .import-preview-table tr.status-warning td { background: rgba(120, 53, 15, 0.35); }
[data-theme="dark"] .import-error-box { background: rgba(127, 29, 29, 0.4); color: #fecaca; }

/* ===== ZERO-WASTE TIP CARD (cooking mode) ===== */
.cooking-zerowaste-tip {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: rgba(16, 185, 129, 0.10);
    border: 1.5px solid rgba(16, 185, 129, 0.35);
    border-radius: 12px;
    padding: 12px 14px;
    margin: 10px 16px 0;
    position: relative;
    animation: zwFadeIn 0.3s ease;
    flex-direction: column;
}
@keyframes zwFadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.cooking-zerowaste-label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #059669;
}
.cooking-zerowaste-scrap {
    font-size: 0.85rem;
    font-weight: 700;
    color: #065f46;
    margin-left: 4px;
}
.cooking-zerowaste-text {
    font-size: 0.85rem;
    color: var(--text);
    margin: 4px 0 0;
    line-height: 1.45;
}
.cooking-zerowaste-close {
    position: absolute;
    top: 8px;
    right: 10px;
    background: none;
    border: none;
    font-size: 0.85rem;
    cursor: pointer;
    color: #6b7280;
    padding: 2px 4px;
    line-height: 1;
}
.cooking-zerowaste-close:hover { color: #374151; }
[data-theme="dark"] .cooking-zerowaste-tip {
    background: rgba(16, 185, 129, 0.08);
    border-color: rgba(16, 185, 129, 0.25);
}
[data-theme="dark"] .cooking-zerowaste-scrap { color: #6ee7b7; }
[data-theme="dark"] .cooking-zerowaste-label { color: #34d399; }
[data-theme="dark"] .cooking-zerowaste-close { color: #9ca3af; }

/* ===== DARK MODE ===== */
[data-theme="dark"] {
    --bg: #0f172a;
    --bg-card: #1e293b;
    --bg-dark: #020617;
    --bg-secondary: #263448;
    --text: #e2e8f0;
    --text-light: #94a3b8;
    --text-muted: #64748b;
    --text-secondary: #94a3b8;
    --border: #334155;
    --shadow: 0 2px 8px rgba(0,0,0,0.45);
    --shadow-lg: 0 4px 16px rgba(0,0,0,0.6);
    color-scheme: dark;
}
[data-theme="dark"] body {
    background: var(--bg);
    color: var(--text);
}
/* Bottom nav */
[data-theme="dark"] .bottom-nav {
    box-shadow: 0 -2px 10px rgba(0,0,0,0.4);
}
/* Location tabs */
[data-theme="dark"] .tab {
    background: var(--bg-card);
    color: var(--text-light);
}
[data-theme="dark"] .tab.active {
    background: var(--primary);
    color: #fff;
}
/* Location selector (add/use modal) */
[data-theme="dark"] .location-option {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
}
[data-theme="dark"] .location-option.selected {
    border-color: var(--primary);
    background: rgba(45,80,22,0.3);
}
/* Inputs & selects */
[data-theme="dark"] .form-input,
[data-theme="dark"] .form-control,
[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="email"],
[data-theme="dark"] input[type="password"],
[data-theme="dark"] input[type="number"],
[data-theme="dark"] textarea,
[data-theme="dark"] select {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--border);
}
[data-theme="dark"] input::placeholder,
[data-theme="dark"] textarea::placeholder {
    color: var(--text-muted);
}
/* Buttons */
[data-theme="dark"] .btn:not(.btn-primary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-accent):not(.btn-link),
[data-theme="dark"] .btn-secondary,
[data-theme="dark"] .btn-ghost,
[data-theme="dark"] .btn-outline,
[data-theme="dark"] .back-btn,
[data-theme="dark"] .page-header-action-btn {
    background: color-mix(in srgb, var(--bg) 35%, var(--bg-card) 65%);
    color: var(--text);
    border-color: color-mix(in srgb, var(--border) 70%, var(--text-muted) 30%);
}
[data-theme="dark"] .btn-outline {
    color: var(--primary-light);
    border-color: var(--primary-light);
}
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .btn-success,
[data-theme="dark"] .btn-danger,
[data-theme="dark"] .btn-accent {
    color: #fff;
}
/* Inventory items */
[data-theme="dark"] .inventory-item {
    background: var(--bg-card);
}
[data-theme="dark"] .inv-location-badge {
    background: rgba(45,80,22,0.35);
    color: #86efac;
}
/* Shopping items */
[data-theme="dark"] .shopping-item {
    background: var(--bg-card) !important;
}
[data-theme="dark"] .shopping-item-tag-menu-container {
    background: var(--bg-card);
    border-color: var(--border);
}
[data-theme="dark"] .shopping-item-tag-btn {
    background: #1e293b;
    color: var(--text-light);
    border-color: var(--border);
}
[data-theme="dark"] .badge-local-tag {
    background: #0c2a4e;
    color: #7dd3fc;
}
[data-theme="dark"] .badge-freq-med {
    background: #2e1a4a;
    color: #c4b5fd;
}
[data-theme="dark"] .badge-freq-low {
    background: #1e293b;
    color: #94a3b8;
}
/* Settings rows */
[data-theme="dark"] .settings-row {
    border-color: var(--border);
}
[data-theme="dark"] .settings-label {
    color: var(--text);
}
[data-theme="dark"] .settings-hint {
    color: var(--text-muted);
}
/* Toggle switch */
[data-theme="dark"] .toggle-slider {
    background: #334155;
}
/* Search bar */
[data-theme="dark"] .search-bar input {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--border);
}
[data-theme="dark"] .search-clear-btn {
    background: #334155;
    color: #cbd5e1;
}
/* Action modal location selector */
[data-theme="dark"] .action-location-btn {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
}
/* Scan page */
[data-theme="dark"] .scan-input-row {
    background: var(--bg-card);
}
[data-theme="dark"] .scan-result-item {
    background: var(--bg-card);
    border-color: var(--border);
}
/* Quick access chips */
[data-theme="dark"] .quick-access-chip {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
}
/* Scan recents */
[data-theme="dark"] .scan-recent-chip {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text-light);
}
/* Alert banners */
[data-theme="dark"] .alert-banner { /* the wash is mixed over --surface-bg in surfaces.css */ }
[data-theme="dark"] .alert-banner.banner-expiring { /* hue: surfaces.css */ }
[data-theme="dark"] .alert-banner.banner-expired { /* hue: surfaces.css */ }
[data-theme="dark"] .alert-banner.banner-finished { /* hue: surfaces.css */ }
[data-theme="dark"] .alert-banner.banner-anomaly { /* hue: surfaces.css */ }
/* Recipe dialog */
[data-theme="dark"] .recipe-dialog-content {
    background: var(--bg-card);
}
[data-theme="dark"] .recipe-option-btn {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
}
[data-theme="dark"] .recipe-option-btn.active {
    background: rgba(45,80,22,0.4);
    border-color: var(--primary-light);
    color: var(--primary-light);
}
/* Log rows */
[data-theme="dark"] .log-item {
    background: var(--bg-card);
    border-color: var(--border);
}
/* Dashboard stat cards */
[data-theme="dark"] .stat-card {
    background: var(--bg-card);
}
/* Screensaver */
[data-theme="dark"] .screensaver-overlay {
    background: #020617;
}
/* Charts / nutrition */
[data-theme="dark"] .nutrition-chart-bg {
    background: var(--bg-card);
}
/* AW badges */
[data-theme="dark"] .aw-badge-rate  { background: #2e1a4a; color: #c4b5fd; border-color: #6d28d9; }
[data-theme="dark"] .aw-badge-money { background: #1c1300; color: #fde047; border-color: #78350f; }
[data-theme="dark"] .aw-badge-meals { background: #0f1f0f; color: #4ade80; border-color: #166534; }
[data-theme="dark"] .aw-badge-co2   { background: #0c1f3a; color: #7dd3fc; border-color: #1e3a5f; }
[data-theme="dark"] .aw-badge-wasted{ background: #1f0808; color: #fca5a5; border-color: #7f1d1d; }
[data-theme="dark"] .aw-badge-better{ background: #0f1f0f; color: #4ade80; border-color: #166534; }
/* Chat */
[data-theme="dark"] .chat-input {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--border);
}
[data-theme="dark"] .chat-message.user {
    background: var(--primary-dark);
}
[data-theme="dark"] .chat-message.bot {
    background: var(--bg-card);
}
/* Smart shopping forecast */
[data-theme="dark"] .smart-item {
    background: var(--bg-card);
    border-color: var(--border);
}
[data-theme="dark"] .smart-filter-btn {
    background: var(--bg-card);
    color: var(--text-light);
    border-color: var(--border);
}
[data-theme="dark"] .smart-filter-btn.active {
    background: var(--primary);
    color: #fff;
    border-color: var(--primary);
}
/* Offline banner */
[data-theme="dark"] #offline-banner {
    background: #450a0a;
    border-color: #7f1d1d;
}
/* Setup wizard */
[data-theme="dark"] .setup-content {
    background: var(--bg-card);
}
[data-theme="dark"] .setup-lang-btn {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--border);
}
[data-theme="dark"] .setup-lang-btn.selected {
    background: rgba(45,80,22,0.4);
    border-color: var(--primary-light);
    color: var(--primary-light);
}
/* @media prefers-color-scheme: auto handled in JS */

/* ===== DARK MODE — EXTENDED COMPONENT OVERRIDES ===== */

/* ── Inventory badges ── */
[data-theme="dark"] .badge-location { background: #0c2a4e; color: #7dd3fc; }
[data-theme="dark"] .badge-category { background: #1e293b; color: #94a3b8; }
[data-theme="dark"] .badge-qty      { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .badge-expiry   { background: #2a1a00; color: #fcd34d; }
[data-theme="dark"] .badge-expired  { background: #2a0808; color: #fca5a5; }

/* ── Urgency / priority badges ── */
[data-theme="dark"] .badge-critical  { background: #2a0808; color: #fca5a5; }
[data-theme="dark"] .badge-high      { background: #2a1200; color: #fdba74; }
[data-theme="dark"] .badge-medium    { background: #2a1e00; color: #fde68a; }
[data-theme="dark"] .badge-low       { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .badge-freq-high { background: #2e0d1a; color: #f9a8d4; }
[data-theme="dark"] .badge-tag-add   { background: #1e293b; color: #94a3b8; }

/* ── Smart shopping badges ── */
[data-theme="dark"] .smart-freq-badge.freq-suggest        { background: #0c2a4e; color: #7dd3fc; }
[data-theme="dark"] .smart-freq-badge.freq-suggest-approx { background: #0c1f3a; color: #93c5fd; font-style: italic; }
[data-theme="dark"] .smart-pred-badge                     { background: #2a1e00; color: #fde68a; }
[data-theme="dark"] .smart-pred-badge.pred-urgent         { background: #2a0808; color: #fca5a5; }
[data-theme="dark"] .smart-pred-badge.pred-soon           { background: #2a1200; color: #fdba74; }
[data-theme="dark"] .smart-bring-badge                    { background: #0c2a4e; color: #7dd3fc; }

/* ── AW trend mini-cards ── */
[data-theme="dark"] .aw-tcard-good { background: #0f2a1a; border-color: #166534; }
[data-theme="dark"] .aw-tcard-ok   { background: #1c1300; border-color: #78350f; }
[data-theme="dark"] .aw-tcard-bad  { background: #2a0808; border-color: #7f1d1d; }

/* ── Alert sections ── */
[data-theme="dark"] .alert-danger                { background: #2a0808; border-color: var(--danger); }
[data-theme="dark"] .alert-item                  { background: rgba(255,255,255,0.04); }
[data-theme="dark"] .alert-item-qty              { background: rgba(255,255,255,0.06); }
[data-theme="dark"] .alert-review                { background: #1c1300; border-color: #78350f; }
[data-theme="dark"] .alert-review h3             { color: #fcd34d; }
[data-theme="dark"] .alert-opened               { background: #0c1f3a; border-color: #1e3a8a; }
[data-theme="dark"] .alert-opened h3             { color: #7dd3fc; }

/* ── Alert banner: gradient overrides ── */
[data-theme="dark"] .alert-banner.banner-expired            { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-expired .alert-banner-title     { color: #fca5a5; }
[data-theme="dark"] .banner-expired .alert-banner-counter   { color: #f87171; }
[data-theme="dark"] .alert-banner.banner-expiring           { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-expiring .alert-banner-title    { color: #fdba74; }
[data-theme="dark"] .banner-expiring .alert-banner-counter  { color: #fb923c; }
[data-theme="dark"] .alert-banner.banner-expired-ok              { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-expired-ok .alert-banner-title       { color: #86efac; }
[data-theme="dark"] .banner-expired-ok .alert-banner-counter     { color: #4ade80; }
[data-theme="dark"] .alert-banner.banner-expired-warning         { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-expired-warning .alert-banner-title  { color: #fde68a; }
[data-theme="dark"] .banner-expired-warning .alert-banner-counter { color: #fcd34d; }
[data-theme="dark"] .alert-banner.banner-expired-danger          { /* hue: surfaces.css */ border-width: 2px; }
[data-theme="dark"] .banner-expired-danger .alert-banner-title   { color: #fca5a5; }
[data-theme="dark"] .alert-banner.banner-prediction              { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-prediction .alert-banner-title       { color: #c4b5fd; }
[data-theme="dark"] .banner-prediction .alert-banner-counter     { color: #a78bfa; }
[data-theme="dark"] .alert-banner.banner-anomaly                 { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-anomaly .alert-banner-title          { color: #fdba74; }
[data-theme="dark"] .alert-banner.banner-dup-loss                { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-dup-loss .alert-banner-title         { color: #fca5a5; }
[data-theme="dark"] .alert-banner.banner-no-expiry               { /* hue: surfaces.css */ }
[data-theme="dark"] .banner-no-expiry .alert-banner-title        { color: #86efac; }

/* ── Alert banner: default text & close ── */
[data-theme="dark"] .alert-banner-title  { color: #e2e8f0; }
[data-theme="dark"] .alert-banner-detail { color: #94a3b8; }
[data-theme="dark"] .alert-banner-close  { color: #94a3b8; background: rgba(255,255,255,0.06); }

/* ── Banner action buttons ── */
[data-theme="dark"] .btn-banner-ok           { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .btn-banner-edit         { background: #1a1040; color: #c4b5fd; }
[data-theme="dark"] .btn-banner-ai           { background: #2e1a4a; color: #c4b5fd; }
[data-theme="dark"] .btn-banner-weigh        { background: #2e1a4a; color: #c4b5fd; }
[data-theme="dark"] .btn-banner-confirm      { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .btn-banner-use          { background: #0c2a4e; color: #7dd3fc; }
[data-theme="dark"] .btn-banner-throw        { background: #2a0808; color: #fca5a5; }
[data-theme="dark"] .btn-banner-throw-primary { background: #dc2626; color: #fff; }
[data-theme="dark"] .btn-banner-use-danger   { background: #1e293b; color: #64748b; }
[data-theme="dark"] .btn-banner-vacuum       { background: #2e1a4a; color: #c4b5fd; }
[data-theme="dark"] .btn-banner-extend       { background: #064e3b; color: #6ee7b7; }
[data-theme="dark"] .btn-banner-edit2        { background: #0c2a4e; color: #7dd3fc; }
[data-theme="dark"] .btn-alert-extend        { background: #064e3b; color: #6ee7b7; }

/* ── Review items ── */
[data-theme="dark"] .review-item          { background: rgba(255,255,255,0.04); }
[data-theme="dark"] .review-item-meta     { color: #94a3b8; }
[data-theme="dark"] .review-warn          { color: #fca5a5; }
[data-theme="dark"] .review-qty-value     { background: #2a0808; color: #fca5a5; }
[data-theme="dark"] .btn-review-ok        { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .btn-review-ok:active { background: #0d2416; }
[data-theme="dark"] .btn-review-edit        { background: #1a1040; color: #c4b5fd; }
[data-theme="dark"] .btn-review-edit:active { background: #140d36; }

/* ── Chat UI ── */
[data-theme="dark"] .chat-sheet          { background: var(--bg-card); border-color: var(--border); }
[data-theme="dark"] .chat-header-bar    { background: var(--bg-card); border-color: var(--border); }
[data-theme="dark"] .chat-back-btn      { background: var(--bg); border-color: var(--border); color: var(--text); }
[data-theme="dark"] .chat-title         { color: #818cf8; }
[data-theme="dark"] .chat-suggestion    { background: #1a1040; border-color: #3730a3; color: #a5b4fc; }
[data-theme="dark"] .chat-suggestion:active { background: #2e1a4a; }
[data-theme="dark"] .chat-gemini        { background: var(--bg-card); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
[data-theme="dark"] .chat-gemini strong { color: #818cf8; }
[data-theme="dark"] .chat-input-bar     { background: var(--bg-card); border-color: var(--border); }

/* ── Settings status ── */
[data-theme="dark"] .settings-status.success { background: #0f2a1a; color: #86efac; }
[data-theme="dark"] .settings-status.error   { background: #2a0808; color: #fca5a5; }

/* ── Inventory status bar ── */
[data-theme="dark"] .inventory-status-bar {
    background: linear-gradient(135deg, #0c2a4e 0%, #1a1040 100%);
    border-color: #1e3a8a;
}
[data-theme="dark"] .inventory-status-bar .inv-status-title { color: #7dd3fc; }
[data-theme="dark"] .inventory-status-bar .inv-status-total { color: #e2e8f0; background: rgba(0,0,0,0.3); }
[data-theme="dark"] .inventory-status-bar .inv-status-item  { color: #93c5fd; background: rgba(0,0,0,0.2); }

/* ── Use inventory info ── */
[data-theme="dark"] .use-inventory-info { background: #0c2a4e; color: #7dd3fc; }
[data-theme="dark"] #use-expiry-hint    { background: #2a1e00; border-color: #78350f; color: #fde68a; }
[data-theme="dark"] #page-use .product-preview-small  { border-left-color: var(--primary); }
[data-theme="dark"] #page-action .product-preview-small { border-left-color: var(--primary); }
[data-theme="dark"] .action-pill-barcode { background: #1e293b; color: #94a3b8; }
[data-theme="dark"] .use-pill-ok       { background: #14532d; color: #86efac; }
[data-theme="dark"] .use-pill-warn     { background: #422006; color: #fde68a; }
[data-theme="dark"] .use-pill-soon     { background: #431407; color: #fdba74; }
[data-theme="dark"] .use-pill-expired  { background: #450a0a; color: #fca5a5; }
[data-theme="dark"] .use-pill-qty      { background: #0c2a4e; color: #7dd3fc; }

/* ── Recipe components ── */
[data-theme="dark"] .recipe-expiry-note  { background: #2a1e00; color: #fde68a; }
[data-theme="dark"] .recipe-nutrition-block { background: #052e16; border-color: #166534; }
[data-theme="dark"] .recipe-section-heading { color: #4ade80; }
[data-theme="dark"] .recipe-storage-card .recipe-section-heading { color: #fbbf24; }
[data-theme="dark"] .recipe-nutrition-value { color: #4ade80; }
[data-theme="dark"] .recipe-nutrition-label { color: #94a3b8; }
[data-theme="dark"] .recipe-nutrition-note  { color: #64748b; }
[data-theme="dark"] .recipe-nutrition-footnote { color: var(--text-muted); }
[data-theme="dark"] .recipe-storage-card { background: #1c1400; border-color: #78350f; }
[data-theme="dark"] .recipe-storage-badge { background: #2a1e00; border-color: #92400e; color: #fde68a; }
[data-theme="dark"] .recipe-storage-days { background: #0c1a2e; border-color: #1d4ed8; color: #93c5fd; }
[data-theme="dark"] .recipe-storage-now  { background: #2a0a0a; border-color: #b91c1c; color: #fca5a5; }
[data-theme="dark"] .recipe-storage-tips { color: #fde68a; }
[data-theme="dark"] .recipe-tools-banner { background: #1a1040; border-color: #3730a3; color: #c4b5fd; }
[data-theme="dark"] .recipe-shopping-suggestions { background: #241a02; border-color: #78350f; color: #fde68a; }
[data-theme="dark"] .recipe-plan-row { border-color: #78350f; }
[data-theme="dark"] .recipe-plan-row label { color: #fde68a; }
[data-theme="dark"] .recipe-plan-row small,
[data-theme="dark"] .recipe-plan-note { color: #fbbf24; }
[data-theme="dark"] .recipe-tool-chip    { background: #2e1a4a; color: #c4b5fd; }
[data-theme="dark"] .recipe-step-appliance { background: #052e16; border-color: #166534; color: #4ade80; }
[data-theme="dark"] .recipe-regen-choice { background: #1e293b; border-color: #334155; }
[data-theme="dark"] .recipe-regen-choice-title { color: #94a3b8; }
[data-theme="dark"] .recipe-subtype-chip { background: #1c1300; border-color: #78350f; color: var(--text); }
[data-theme="dark"] .recipe-subtype-chip:has(input:checked) { background: #2a1e00; border-color: #d97706; }

/* ── Bug report pills ── */
[data-theme="dark"] .bug-type-pill { background: var(--bg-card); border-color: var(--border); color: var(--text-light); }

/* ── Shopping tag menu ── */
[data-theme="dark"] .shopping-tag-menu-container { background: #1a2336; }

/* ── Edit unknown card ── */
[data-theme="dark"] .edit-unknown-card.highlight { background: #1c1300; border-color: var(--warning); }

/* ── AI match image ── */
[data-theme="dark"] .ai-match-img { background: var(--bg-card); }

/* ── Inline edit button ── */
[data-theme="dark"] .btn-edit-inline { background: rgba(30,41,59,0.92); border-color: var(--border); color: var(--text); }

/* ── Setup wizard ── */
[data-theme="dark"] .setup-body p    { color: var(--text-muted); }
[data-theme="dark"] .setup-footer    { border-color: var(--border); }
[data-theme="dark"] .setup-skip-link       { color: var(--text-muted); }
[data-theme="dark"] .setup-skip-link:hover { color: var(--text-light); }

/* ── Appliance remove active ── */
[data-theme="dark"] .appliance-item .appliance-remove:active { background: #2a0808; }

/* ===== NETWORK ERROR OVERLAY ===== */
#network-error-overlay {
    position: fixed;
    inset: 0;
    background: rgba(6, 8, 20, 0.97);
    z-index: 300000; /* highest: above screensaver(10000), cooking(99999), preloader(200000) */
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
}
#network-error-overlay.visible {
    opacity: 1;
    pointer-events: auto;
}
.net-error-body {
    text-align: center;
    padding: 2.5rem 2rem;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.net-error-icon {
    font-size: 5.5rem;
    line-height: 1;
    margin-bottom: 1.75rem;
    animation: net-pulse 2.2s ease-in-out infinite;
    display: block;
    filter: drop-shadow(0 0 32px rgba(248, 113, 113, 0.35));
}
#network-error-overlay.restored .net-error-icon {
    animation: none;
    filter: drop-shadow(0 0 32px rgba(74, 222, 128, 0.45));
}
#network-error-overlay.checking .net-error-icon {
    animation: net-spin 1.2s linear infinite;
}
@keyframes net-pulse {
    0%, 100% { opacity: 0.45; transform: scale(0.92); }
    50%       { opacity: 1;    transform: scale(1.06); }
}
@keyframes net-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.net-error-title {
    font-size: 2.5rem;
    font-weight: 700;
    color: #f87171;
    margin-bottom: 0.75rem;
    letter-spacing: -0.02em;
    transition: color 0.4s;
}
#network-error-overlay.restored .net-error-title {
    color: #4ade80;
}
.net-error-subtitle {
    font-size: 1.1rem;
    color: #94a3b8;
    max-width: 420px;
    line-height: 1.6;
    margin: 0 auto;
}
.net-error-status {
    margin-top: 1.5rem;
    font-size: 0.88rem;
    color: #475569;
    min-height: 1.3em;
    letter-spacing: 0.01em;
}
/* "Continue in offline mode" button — appears after 3 s */
.net-error-continue-btn {
    margin-top: 2.2rem;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.22);
    color: #94a3b8;
    border-radius: 10px;
    padding: 0.7rem 1.6rem;
    font-size: 0.92rem;
    cursor: pointer;
    transition: background 0.2s, color 0.2s, transform 0.3s, opacity 0.3s;
    opacity: 0;
    transform: translateY(8px);
}
.net-error-continue-btn.visible {
    opacity: 1;
    transform: translateY(0);
}
.net-error-continue-btn:hover {
    background: rgba(255,255,255,0.16);
    color: #e2e8f0;
}

/* ─── Offline mode: hide AI and network-dependent UI ────────────────────────
   Sections that require a live server response or AI are hidden so the user
   isn't confronted with empty/broken widgets while offline.               */
body.offline-mode #waste-chart-section,
body.offline-mode #nutrition-section,
body.offline-mode #quick-recipe-bar,
body.offline-mode #btn-suggest,
body.offline-mode #btn-fetch-prices,
body.offline-mode .recipe-generate-btn {
    display: none !important;
}
/* Smart-shopping AI section: show as disabled rather than disappearing entirely */
body.offline-mode #smart-shopping {
    opacity: 0.45;
    pointer-events: none;
    filter: grayscale(0.6);
}

/* ===== RECIPE USE MODAL (ingredient → Usa) ===== */
.ruse-modal {
    padding: 0 16px 18px;
}
/* Head of the sheet: the product's own facts (thumb, name, brand, place, opened, expiry)
   in the exact grammar of the product sheet, above the "need" card. The doubled class is
   deliberate: surfaces.css owns .item-detail-header-row and loads after this file. */
.ruse-product-head.item-detail-header-row {
    margin: 0 0 12px;
    align-items: center;
}
.ruse-target-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 16px 14px 18px;
    margin-bottom: 14px;
    border-radius: 14px;
    background: linear-gradient(160deg,
        color-mix(in srgb, var(--primary) 14%, var(--bg-card)),
        color-mix(in srgb, var(--primary-light) 8%, var(--bg-card)));
    border: 1.5px solid color-mix(in srgb, var(--primary) 28%, var(--border));
    text-align: center;
}
.ruse-target-label {
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--primary-dark, var(--primary));
    opacity: 0.85;
}
.ruse-target-value {
    font-size: clamp(2rem, 8vw, 2.75rem);
    font-weight: 800;
    line-height: 1.05;
    color: var(--primary-dark, var(--primary));
    font-variant-numeric: tabular-nums;
}
.ruse-target-unit {
    font-size: 0.55em;
    font-weight: 700;
    margin-left: 0.2em;
    opacity: 0.85;
}
.ruse-stock-line {
    margin: 0 0 14px;
    font-size: 0.82rem;
    color: var(--text-muted);
    text-align: center;
}

.ruse-scale-box {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px 14px 12px;
    margin-bottom: 14px;
    border-radius: 14px;
    background: var(--bg-card);
    border: 1.5px solid color-mix(in srgb, var(--primary) 35%, var(--border));
    box-shadow: var(--es-shadow-card, 0 2px 10px rgba(0,0,0,0.04));
}
.ruse-scale-top {
    display: flex;
    align-items: center;
    gap: 8px;
}
.ruse-scale-icon {
    font-size: 1.25rem;
    flex-shrink: 0;
}
.ruse-scale-ratio {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15em 0.25em;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
    min-width: 0;
}
.ruse-scale-now {
    font-size: clamp(1.85rem, 7vw, 2.4rem);
    font-weight: 800;
    color: var(--primary);
}
.ruse-scale-sep {
    font-size: clamp(1.2rem, 5vw, 1.6rem);
    font-weight: 600;
    color: var(--text-muted);
    margin: 0 0.05em;
}
.ruse-scale-need {
    font-size: clamp(1.35rem, 5.5vw, 1.85rem);
    font-weight: 700;
    color: var(--text);
}
.ruse-scale-unit {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-muted);
    margin-left: 0.15em;
}
.ruse-scale-status {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-left: auto;
    white-space: nowrap;
}
.ruse-scale-target-track,
.ruse-scale-stability-track,
.ruse-scale-confirm-track {
    height: 8px;
    background: var(--border);
    border-radius: 999px;
    overflow: hidden;
}
.ruse-scale-target-bar {
    height: 100%;
    width: 0%;
    border-radius: 999px;
    background: var(--primary);
    transition: width 0.12s linear, background-color 0.2s ease;
}
.ruse-scale-box.is-near .ruse-scale-target-bar {
    background: #16a34a;
}
.ruse-scale-box.is-over .ruse-scale-target-bar {
    background: #ea580c;
}
.ruse-scale-box.is-near .ruse-scale-now {
    color: #16a34a;
}
.ruse-scale-box.is-over .ruse-scale-now {
    color: #ea580c;
}
.ruse-scale-stability-track {
    height: 4px;
}
.ruse-scale-stability-bar {
    height: 100%;
    width: 0%;
    background: color-mix(in srgb, var(--primary) 70%, #94a3b8);
    border-radius: 999px;
}
.ruse-scale-confirm-track {
    height: 4px;
}
.ruse-scale-confirm-bar {
    height: 100%;
    width: 100%;
    background: #22c55e;
    border-radius: 999px;
}
.ruse-scale-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    text-align: center;
}
.ruse-scale-hint {
    display: none;
    margin-top: 6px;
    font-size: 0.8rem;
    color: var(--primary);
    font-weight: 600;
}
.ruse-qty-block .qty-control-with-unit {
    margin-top: 6px;
}
.ruse-qty-block .qty-input {
    font-size: 1.45rem;
    font-weight: 700;
    min-height: 48px;
}
.ruse-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 14px;
}

/* ===== SUPPORT DIALOG (donation) ============================================
   The one-off donation/banner question (assets/js/core/support.js) and the two
   slots it can switch on. The dialog is deliberately quiet: a short paragraph,
   the real costs, four cards. No countdown, no full-screen orange. */
.support-dialog {
    position: relative;
    max-width: 620px;
    width: calc(100vw - 32px);
    padding: 26px 24px 18px;
}
.support-close {
    position: absolute;
    top: 10px;
    right: 12px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.1rem;
    line-height: 1;
    padding: 8px;
    cursor: pointer;
}
.support-close:hover { color: var(--text); }
.support-hero { text-align: center; }
.support-logo { width: 44px; height: 44px; }
.support-hero h2 {
    margin: 8px 0 6px;
    font-size: 1.2rem;
    line-height: 1.3;
}
.support-hero p {
    margin: 0 auto;
    max-width: 480px;
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--text-muted);
}
.support-costs {
    margin-top: 16px;
    background: var(--bg, #f8fafc);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 12px 14px;
}
.support-costs-title {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.support-costs-list {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.support-costs-list li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.88rem;
}
.support-cost-amount {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.support-cost-amount em {
    font-style: normal;
    font-weight: 500;
    font-size: 0.76rem;
    color: var(--text-muted);
}
.support-costs-total {
    margin: 10px 0 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}
.support-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
    margin: 18px 0 4px;
}
.support-option {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    text-align: left;
    font: inherit;
    color: var(--text);
    background: var(--bg-card);
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 12px 14px;
    cursor: pointer;
    min-width: 0;
    transition: border-color 0.15s, background-color 0.15s, transform 0.15s;
}
.support-option:hover { border-color: var(--primary-light, var(--primary)); transform: translateY(-1px); }
/* Selected: filled green, white text. A border-only highlight left the label
   unreadable next to the "already on" badge, so the state is unmistakable. */
.support-option.is-active {
    background: var(--success);
    border-color: var(--success);
    transform: none;
}
.support-option.is-active:hover { border-color: var(--success); }
.support-option.is-active .support-option-title { color: #ffffff; }
.support-option.is-active .support-option-desc { color: rgba(255, 255, 255, 0.9); }
.support-option.is-active .support-option-check { opacity: 1; color: #ffffff; }
.support-option.is-active .support-option-chip {
    color: #ffffff;
    background: rgba(255, 255, 255, 0.22);
}
/* Answers the owner has switched off (the banners, for now): greyed out and not
   clickable, with a "not available" badge instead of a promise. */
.support-option.is-disabled,
.support-option:disabled {
    cursor: not-allowed;
    opacity: 0.6;
    filter: grayscale(0.4);
    background: color-mix(in srgb, var(--text-muted) 7%, var(--bg-card));
    border-color: var(--border);
    transform: none;
}
.support-option.is-disabled:hover,
.support-option:disabled:hover {
    border-color: var(--border);
    transform: none;
}
.support-option.is-disabled .support-option-title { color: var(--text-light); }
.support-option-chip.is-muted {
    color: var(--text-muted);
    background: color-mix(in srgb, var(--text-muted) 16%, transparent);
}
.support-option-icon { font-size: 1.5rem; line-height: 1; flex: 0 0 auto; }
.support-option-body {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 1 1 auto;
    min-width: 0;
}
.support-option-title {
    font-weight: 700;
    font-size: 0.92rem;
    overflow-wrap: anywhere;
}
.support-option-desc { font-size: 0.78rem; line-height: 1.35; color: var(--text-muted); }
.support-option-chip {
    /* Under the text, on its own line: beside the label it stole the width the
       title needed. */
    align-self: flex-start;
    margin-top: 5px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--primary);
    background: color-mix(in srgb, var(--primary) 14%, transparent);
    border-radius: 999px;
    padding: 3px 8px;
}
.support-option-check {
    flex: 0 0 auto;
    margin-top: 1px;
    font-weight: 800;
    color: var(--primary);
    opacity: 0;
}
.support-option.is-active .support-option-check { opacity: 1; }
.support-options-inline { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin: 12px 0 0; }
.support-card-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.support-footnote {
    margin: 16px 0 0;
    font-size: 0.76rem;
    line-height: 1.45;
    text-align: center;
    color: var(--text-muted);
}

/* ── Donation panel: amount chips + QR ── */
.support-donate {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}
.support-donate-head { display: flex; gap: 12px; align-items: flex-start; }
.support-donate-icon { font-size: 1.5rem; line-height: 1; }
.support-amounts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 12px 0 0;
}
.support-amounts-label {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-muted);
}
.support-amount {
    font: inherit;
    font-size: 0.84rem;
    font-weight: 700;
    color: var(--text);
    background: var(--bg-card);
    border: 1.5px solid var(--border);
    border-radius: 999px;
    padding: 6px 14px;
    cursor: pointer;
}
.support-amount:hover { border-color: var(--primary-light, var(--primary)); }
.support-amount.is-active {
    color: var(--primary);
    border-color: var(--primary);
    background: color-mix(in srgb, var(--primary) 10%, var(--bg-card));
}
.support-qr-block {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-start;
    margin-top: 14px;
}
.support-qr-frame {
    line-height: 0;
    background: #ffffff;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 10px;
}
.support-qr-frame img { display: block; width: 240px; height: 240px; }
.support-qr-side {
    flex: 1 1 200px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.support-donate-url {
    font-size: 0.72rem;
    line-height: 1.4;
    word-break: break-all;
    color: var(--text-muted);
}
.support-qr-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* ── Thank-you view: the answer includes donating ── */
/* The four cards step aside and the thanks sit *under* the QR code, where the eye
   lands right after scanning: a warm line, then a discreet way to change your mind. */
.support-thanks { text-align: center; margin: 20px 0 2px; }
.support-thanks-icon { display: block; font-size: 2rem; line-height: 1; }
.support-thanks h3 {
    margin: 6px 0 6px;
    font-size: 1.15rem;
    color: var(--success);
}
.support-thanks p {
    margin: 0 auto;
    max-width: 480px;
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--text-muted);
}
.support-change { text-align: center; margin-top: 4px; }
.support-change-btn {
    border: none;
    background: none;
    padding: 6px 8px;
    font: inherit;
    font-size: 0.78rem;
    color: var(--text-muted);
    text-decoration: underline;
    cursor: pointer;
}
.support-change-btn:hover { color: var(--text); }
.support-donate.is-focused {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.support-donate.is-focused .support-qr-block {
    flex-direction: column;
    align-items: center;
}
.support-donate.is-focused .support-qr-side {
    flex: 0 0 auto;
    align-items: center;
    text-align: center;
}
.support-donate.is-focused .support-qr-frame img { width: 260px; height: 260px; }
.support-donate.is-focused .support-qr-actions { justify-content: center; }

/* ── PARKED: banner slots (dashboard + screensaver) ──────────────────────────
   EverShelf does not run ads: the two slots are commented out in index.html and
   `_renderAdSlots()` is a no-op. The rules stay here, commented, next to the
   checklist in docs/wiki/Support-and-ads.md ("Banner slots (parked)").

.ad-slot { margin-top: 18px; }
.house-ad {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border: 1.5px dashed color-mix(in srgb, var(--primary) 40%, var(--border));
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--primary) 6%, var(--bg-card));
}
.house-ad-logo { width: 32px; height: 32px; flex-shrink: 0; }
.house-ad-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.house-ad-text strong { font-size: 0.92rem; }
.house-ad-text span { font-size: 0.8rem; line-height: 1.4; color: var(--text-muted); }
.house-ad .btn { white-space: nowrap; }


.house-ad-screensaver {
    border-style: solid;
    border-color: rgba(255,255,255,0.18);
    background: rgba(255,255,255,0.06);
}
.house-ad-screensaver .house-ad-text strong { color: rgba(255,255,255,0.85); }
.house-ad-screensaver .house-ad-text span { color: rgba(255,255,255,0.5); }
*/

@media (max-width: 560px) {
    .support-dialog { padding: 22px 16px 14px; }
    .support-options { grid-template-columns: 1fr; }
    .support-hero h2 { font-size: 1.08rem; }
    /* PARKED with the slots: .house-ad { flex-wrap: wrap; } .house-ad .btn { width: 100%; } */
    .support-qr-frame img { width: 210px; height: 210px; }
}

/* Corporate UI: see assets/css/corporate.css */

/* Custom product tags (#97): pills on the card, chips above the list. */
.inv-tag-list { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: 4px; }
.inv-tag-pill,
.inv-tag-filter-chip { font: inherit; font-size: 0.72rem; line-height: 1; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--border-color, #d8d8d8); background: transparent; color: var(--text-muted, inherit); cursor: pointer; }
.inv-tag-pill:hover,
.inv-tag-filter-chip:hover { border-color: var(--accent-color, #2e7d32); color: var(--text-color, inherit); }
.inv-tag-filter { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.inv-tag-filter-chip.is-active { background: var(--accent-color, #2e7d32); border-color: var(--accent-color, #2e7d32); color: #fff; }
.inv-tag-filter-clear { font: inherit; font-size: 0.72rem; background: none; border: none; color: var(--accent-color, #2e7d32); cursor: pointer; text-decoration: underline; }

/* Quick audit mode (#285): one card at a time, three big answers. */
.inv-quick-actions { display: flex; gap: 8px; margin: 8px 0; }
.audit-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}
.audit-overlay[hidden] { display: none; }
.audit-panel {
    width: min(560px, 100%);
    max-height: 90vh;
    overflow-y: auto;
    padding: 20px;
    border-radius: 16px;
    background: var(--bg-card, #fff);
    color: var(--text-color, inherit);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.audit-top {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}
.audit-progress {
    flex: 1 1 auto;
    height: 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--border) 55%, transparent);
    overflow: hidden;
}
.audit-progress > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--brand-primary, #059669);
    transition: width 0.22s ease;
}
.audit-count {
    margin: 0;
    flex: 0 0 auto;
    font-size: 0.76rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}
/* ── THE progress bar of the stocktake ───────────────────────────────────────
   One widget, painted by the three mode sheets, by every card (a proposed one and a single
   question alike) and by the camera. It is the acknowledgement that the three ways are one
   stocktake: it must never come and go with the mode — a bar that only the propose run has
   cannot show a shelf being checked by barcode, and a fresh session used to print no line at
   all, which read as "the run is lost". Same numbers everywhere, from the first card on. */
.audit-progress-wrap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    min-width: 0;
}
/* The bar never disappears behind a long count: it keeps a readable width and the count wraps
   under it (a phone, a big font, the four kinds of answer on one line). */
.audit-progress-wrap .audit-progress { min-width: 64px; }
.audit-progress-tally { font-weight: 600; color: var(--text-muted); }
/* In the card's head it shares the line with the ✕; in the session bar it takes its own. */
.audit-top > .audit-progress-wrap { flex: 1 1 auto; }
.audit-session-bar > .audit-progress-wrap { flex: 1 1 100%; margin-top: 4px; }
/* On the camera the chrome is white on black: the bar follows it, never the page. */
.audit-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
/* The stocktake panel has NO title: "Verifica la dispensa" said nothing a household did not
   already know (the mode switch and «Inventario di …» below say it), and it stole the first line
   of a phone screen. The head exists only to hold the ✕, which stays top-right where a thumb
   looks for it. */
.audit-head--bare { justify-content: flex-end; margin-bottom: 2px; }
.audit-head h3 { margin: 0; font-size: 1.35rem; line-height: 1.25; }
.audit-close { background: none; border: none; font-size: 1.2rem; cursor: pointer; color: var(--text-muted, #666); }
.audit-meta { margin: 6px 0 0; color: var(--text-muted, #666); font-size: 0.9rem; }
.audit-hint { margin: 12px 0; font-size: 0.95rem; }
/* The note under the "which product is this?" hint: a product standing in several places is one
   line per place, and that needs saying — otherwise three identical names look like a bug. */
.audit-hint.audit-assign-note { margin-top: -6px; font-size: 0.82rem; opacity: 0.85; }
/* The question of the «is it here?» panel: it is the REASON the sheet is open, so it is not set as
   a footnote. Same size as the facts around it, one weight up, in the text colour. */
.audit-hint.audit-elsewhere-hint {
    margin: 12px 0 14px;
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--text-main, inherit);
    line-height: 1.35;
}
.audit-scopes { display: flex; flex-direction: column; gap: 10px; }
.audit-scope, .audit-done {
    width: 100%;
    padding: 16px;
    font: inherit;
    font-size: 1.1rem;
    font-weight: 600;
    border-radius: 12px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #f8fafc);
    color: var(--text-main, inherit);
    cursor: pointer;
    text-align: left;
}
.audit-scope:hover, .audit-done:hover { border-color: var(--brand-primary, #059669); }
/* A place with nothing left to check is NOT a button: it is a line that says "done". A control
   that opens an empty run is worse than a label, and the count is the proof the stocktake moved. */
.audit-scope.is-done,
.audit-scope.is-done:hover {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: default;
    color: var(--text-muted, #64748b);
    background: transparent;
    border-style: dashed;
    border-color: var(--surface-border, var(--border));
    font-weight: 500;
}
.audit-scope.is-done span[aria-hidden] { color: var(--brand-primary, #059669); font-weight: 700; }

/* ── The three ways to run a stocktake, as TABS ─────────────────────────────
   «Uno per uno» (the app proposes) | «Ti dico io» (the household names it) | «Codice a barre»
   (the camera). One segmented row of three, the chosen one emerald: it is a choice between equal
   ways, not a primary action, so none of them wears the solid emerald of the confirm.
   The row is painted at the top of EVERY view (the three sheets, the card of the run, the picker
   of an unreadable code): the banner opens straight into a card, and a mode switch that only the
   sheets carry disappears the moment the stocktake starts. */
.audit-modes {
    display: flex;
    gap: 4px;
    margin: 8px 0 12px;
    padding: 4px;
    border-radius: 14px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--bg-app, #f8fafc);
}
.audit-mode {
    flex: 1 1 0;
    min-width: 0;
    min-height: 40px;
    padding: 8px 6px;
    font: inherit;
    font-size: 0.92rem;
    font-weight: 700;
    border-radius: 10px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-main, inherit);
    cursor: pointer;
    /* Two elements, one control: the glyph and the word, 6 px apart. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.audit-mode-icon { font-size: 1.15rem; line-height: 1; }
/* A narrow phone cannot hold three labels (in six languages) on one line: the switch becomes
   three big ICONS. The word does not disappear — it is the `title`/`aria-label` of the button —
   and the tap target grows instead of shrinking, because this is the one control that decides
   how the stocktake is run. 480 px is the same phone breakpoint the lists use. */
@media (max-width: 480px) {
    .audit-mode {
        min-height: 52px;
        padding: 8px 6px;
        gap: 0;
    }
    .audit-mode-icon { font-size: 1.6rem; }
    .audit-mode-label { display: none; }
}
.audit-mode.is-active {
    border-color: var(--brand-primary, #059669);
    background: color-mix(in srgb, var(--brand-primary, #059669) 12%, transparent);
    color: var(--brand-primary, #059669);
}
/* The shared tally of the three ways: one stocktake, printed under the switch. */
.audit-session-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin: 8px 0 4px;
    padding: 8px 10px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--brand-primary, #059669) 28%, transparent);
    background: color-mix(in srgb, var(--brand-primary, #059669) 8%, transparent);
    font-size: 0.84rem;
}
.audit-session-line { min-width: 0; color: var(--text-main, inherit); }
.audit-session-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.audit-session-btn {
    min-height: 30px;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #fff);
    color: var(--text-main, inherit);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
}
.audit-session-btn:hover { border-color: var(--brand-primary, #059669); }
/* The camera is the stocktake's third door: one emerald button that opens the app's scanner. */
.audit-scan-open {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
}
/* ── The stocktake's OWN camera, INSIDE the panel ────────────────────────────
   A stream of its own (the shopping trip keeps its scanner, its AI and its session), but no longer
   a takeover: the viewfinder sits in the sheet's body as a framed 4:3 box, so the header, the three
   tabs and the running tally stay on screen while the household scans a shelf — «puoi lasciarlo
   dentro al tab e non farlo a tutto schermo?». */
.audit-cam {
    position: relative;
    margin: 0 0 10px;
    border-radius: 14px;
    overflow: hidden;
    background: #000;
    aspect-ratio: 4 / 3;
    max-height: 46vh;
}
#audit-scan-video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: #000;
}
/* WHERE to aim: one still frame (the shopping scanner's lock box lives on its own page). */
.audit-scan-frame {
    position: absolute;
    left: 50%;
    top: 50%;
    width: min(78%, 420px);
    height: min(38%, 150px);
    transform: translate(-50%, -50%);
    border: 2px solid rgba(255, 255, 255, 0.85);
    border-radius: 14px;
    box-shadow: 0 0 18px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}
/* The ✕ ON the picture turns the camera off; the sheet stays open on its tab. */
.audit-cam-stop {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.45);
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}
.audit-scan-status {
    margin: 0 0 6px;
    min-height: 1.2em;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-muted, #64748b);
}
.audit-scan-progress { margin: 0 0 6px; }
.audit-search-input { margin: 6px 0 10px; }
.audit-search-results { display: flex; flex-direction: column; gap: 8px; }
/* A hit is a row: the place mark, the thumb, the name and where it is, then ONE action. The mark is
   the fact the stocktake is about — ✓ it stands in the place you are inventorying, ✕ it does not —
   and the action answers the same question: «✓ C'è» (emerald: it confirms the shelf) or «Sposta
   qui» (neutral: a correction). Both are small pills, so the name keeps the line on a phone.
   The row WRAPS when the action cannot fit beside the text (a long label such as the German
   «Hierher verschieben» beside a place and a date on a 320 px phone): the action moves under the
   row, right-aligned, instead of squeezing the text column to 16 px — the wrap is decided by
   `flex-basis: 60%` plus `flex-wrap`, so a row whose action DOES fit keeps one line. */
.audit-hit {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border-radius: 12px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #f8fafc);
    color: var(--text-main, inherit);
}
.audit-hit.is-elsewhere { background: var(--bg-app, #f8fafc); }
/* A row this stocktake already ANSWERED stays in the list, and it says so.
   It used to be filtered out, so the article the household had just confirmed could not be found
   again: typing its name answered «Nessun prodotto per …» and offered to CREATE it, as if the
   confirmation had never happened. The row now keeps its place with the answer in a badge and a
   warmer surface, and it sinks below the open questions of the same section. */
.audit-hit.is-answered {
    background: color-mix(in srgb, var(--brand-primary, #059669) 7%, var(--surface-bg, #f8fafc));
    border-color: color-mix(in srgb, var(--brand-primary, #059669) 30%, var(--surface-border, var(--border)));
}
.audit-hit-badge {
    align-self: flex-start;
    padding: 1px 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--brand-primary, #059669) 14%, transparent);
    color: var(--brand-primary, #059669);
    font-size: 0.72rem;
    font-weight: 800;
    line-height: 1.6;
    white-space: nowrap;
}
[data-theme="dark"] .audit-hit-badge { color: #6ee7b7; }
.audit-hit-open {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 60%;
    min-width: 0;
    padding: 2px;
    font: inherit;
    text-align: left;
    border: none;
    background: none;
    color: inherit;
    cursor: pointer;
}
.audit-hit-mark { flex: 0 0 auto; font-size: 1.15rem; font-weight: 800; line-height: 1; }
.audit-hit-mark.is-here { color: var(--brand-primary, #059669); }
.audit-hit-mark.is-elsewhere { color: var(--tone-danger, #dc2626); }
.audit-hit-quick,
.audit-hit-move,
.audit-hit-reopen {
    flex: 0 0 auto;
    /* On its own line (see `.audit-hit`) the action sits at the RIGHT, under the row. */
    margin-left: auto;
    min-height: 36px;
    padding: 6px 10px;
    border-radius: 10px;
    font: inherit;
    font-size: 0.86rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
}
.audit-hit-quick {
    border: 1px solid transparent;
    background: var(--brand-primary, #059669);
    color: #fff;
}
.audit-hit-quick:active { background: var(--brand-primary-hover, #047857); }
.audit-hit-move,
.audit-hit-reopen {
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #fff);
    color: var(--text-main, inherit);
}
.audit-hit-move:hover,
.audit-hit-reopen:hover { border-color: var(--brand-primary, #059669); }
.audit-search-scope { margin: 10px 0 0; font-weight: 700; }
.audit-search-scope-note { margin: 4px 0 8px; font-weight: 600; }
.audit-hit-thumb { flex: 0 0 auto; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: 1.4rem; }
.audit-hit-thumb img { width: 44px; height: 44px; object-fit: contain; border-radius: 8px; }
.audit-hit-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.audit-hit-name { font-size: 1rem; font-weight: 700; overflow-wrap: anywhere; }
.audit-hit-brand {
    /* The BRAND is a line of its own under the name — the card puts it under the title too, and
       the box is recognised by its brand before the name is read: «Fusilli Pasta di Semola di
       Grano Duro» is the same sentence on a premium pack and on the discount one. One line; only
       its tail may be ellipsised, the NAME above it is never cut. */
    display: block;
    font-size: 0.84rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--text-muted, #64748b);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* ── The two facts of a hit, one per line: where + how much, then WHEN ────────
   The list showed the place and the stock and nothing else, so two packs of the same article —
   the rice in the pantry expiring in March, the one in the cupboard expiring next month — looked
   identical, and picking the wrong one answers the wrong question. The date is the card's own
   fact, in the card's words (`audit.expiry_on` / `expiry_was` / `expiry_none`), on a line of its
   own with its mark; it and the stock are bold and a notch larger than the place line around them
   (`0.95rem/800` against `0.82rem`), so a hit reads like the card it opens. The date itself never
   breaks in half (`.audit-expiry`): only its mark can move down when a locale needs the room. */
.audit-hit-facts {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.audit-hit-fact {
    font-size: 0.82rem;
    line-height: 1.3;
    color: var(--text-muted, #64748b);
}
/* The place and the stock are two GROUPS: they may wrap between each other, never inside one of
   them. A group that alone is wider than the column ends in an ellipsis (a long place name)
   instead of sliding under the action button — on a 393 px phone "Mobile Soggiorno" was painted
   UNDER «È questo», half covered by the pill. */
.audit-hit-fact-place {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 6px;
    min-width: 0;
}
.audit-hit-seg {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.audit-hit-qty,
.audit-hit-fact-expiry .audit-expiry {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main, inherit);
    font-variant-numeric: tabular-nums;
    /* "1 kg" never splits in half when the place line wraps on a 320 px phone. */
    white-space: nowrap;
    min-width: 0;
    max-width: 100%;
}
/* In a hit the date may wrap BETWEEN «Scade il» and the date (the date itself has no space, so it
   never breaks in half) — a 320 px phone gives this line less than the sentence needs. */
.audit-hit-fact-expiry .audit-expiry {
    white-space: normal;
}
.audit-hit-fact-expiry .audit-expiry.is-expired { color: var(--tone-danger, #dc2626); }

/* ── Below 520 px the action is ONE ICON ─────────────────────────────────────
   «Sposta qui» / «È questo» are three words that only fit beside the name by squeezing it: on a
   393 px phone the text column fell to 123 px, the product name took three lines and the place
   was printed under the pill. The icon keeps the meaning (`title` + `aria-label` carry the words,
   the same rule the mode tabs follow) and the row gets its width back; 44 px is the tap target. */
.audit-hit-action-label { display: none; }
@media (min-width: 520px) {
    .audit-hit-action-label { display: inline; }
}
@media (max-width: 519px) {
    .audit-hit-quick,
    .audit-hit-move,
    .audit-hit-reopen {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
        padding: 0;
        font-size: 1.05rem;
    }
}
.audit-search-create { border-style: dashed; }

/* The ONE answer that writes the stock: full width, emerald, 56 px tall. */
.audit-there {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 56px;
    padding: 14px 16px;
    border: 1px solid var(--brand-primary, #059669);
    border-radius: 14px;
    background: var(--brand-primary, #059669);
    color: #fff;
    font: inherit;
    font-size: 1.12rem;
    font-weight: 800;
    line-height: 1.25;
    text-align: center;
    cursor: pointer;
}
.audit-there:active { background: var(--brand-primary-hover, #047857); }
/* The question is the button: quantity, place and date. It may wrap onto two lines; past that
   `_auditFitConfirm()` swaps in the short answer (`is-compact`), measured on the real width. */
.audit-there .audit-there-full { display: inline; }
.audit-there .audit-there-short { display: none; }
.audit-there.is-compact .audit-there-full { display: none; }
.audit-there.is-compact .audit-there-short { display: inline; }
/* The date is part of the fact line: red only when it has already gone. */
.audit-expiry { white-space: nowrap; }
.audit-expiry.is-expired { color: var(--tone-danger, #dc2626); font-weight: 700; }
/* The four exceptions: same weight, same colour, no alarm palette — the emoji says what they
   are. "Finito" and "andato a male" are twins and must not look like two different apps.
   TWO BY TWO at every width: the labels are short by construction («Finito», «Andato a male»,
   «Modifica», «Sposta»), and a column of four pushed the question off a phone screen — the report
   «metti i 4 bottoni in griglia 2 x 2». A long locale («Se ha estropeado») wraps inside its cell,
   never widens the grid, and the two cells of a row always share the height. */
.audit-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-top: 10px;
}
.audit-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: 46px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #f8fafc);
    color: var(--text-main, inherit);
    font: inherit;
    font-size: 0.86rem;
    font-weight: 650;
    line-height: 1.2;
    text-align: center;
    white-space: normal;
    overflow-wrap: anywhere;
    cursor: pointer;
}
.audit-cell:active { background: var(--bg-app, #f1f5f9); }
/* ── The card of a row this stocktake ALREADY answered ───────────────────────
   A barcode re-scanned, a pack line of «Anche in», a name picked a second time: the card
   used to look exactly like an open one — the emerald «Confermo …» included — and answering
   it counted nothing and closed the sheet, which reads as the app ignoring the tap. The line
   says what happened (and when, when the answer is ours) and the two doors are neutral, because
   nothing is wrong: the question is simply already in the ledger. Mint, never alarm colours. */
.audit-answered {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 6px 0 10px;
    padding: 8px 12px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--brand-primary, #059669) 32%, transparent);
    background: #F0FDF4;
    color: var(--text-main, inherit);
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.25;
}
.audit-answered-ico { flex: 0 0 auto; font-size: 1rem; line-height: 1; }
.audit-answered-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.audit-answered-time {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--text-muted, #64748b);
}
/* The two doors replace the primary and the 2×2: same grid grammar, wrapping on a phone. */
.audit-answered-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-top: 10px;
}
.audit-answer-again {
    border-color: color-mix(in srgb, var(--brand-primary, #059669) 45%, transparent);
}
.audit-answer-next { color: var(--text-muted, #64748b); }
/* A pack of «Anche in» that this stocktake already answered: a mint ✓ on its own line. */
.audit-pack-done { flex: 0 0 auto; color: var(--brand-primary, #059669); font-weight: 800; }
.audit-pack-line.is-answered .audit-pack-qty,
.audit-pack-line.is-answered .audit-pack-date { color: var(--text-muted, #64748b); }
.audit-product-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 2px 0 14px;
    padding: 12px;
    border-radius: 14px;
    border: 1px solid var(--surface-border, var(--border));
    background: var(--surface-bg, #fff);
}
.audit-product-thumb { flex: 0 0 56px; }
.audit-product-main { min-width: 0; }
.audit-product-name { margin: 0; font-weight: 700; font-size: 1.05rem; line-height: 1.25; }
.audit-product-brand { margin: 2px 0 0; font-weight: 500; color: var(--text-muted, #64748b); font-size: 0.82rem; }
/* ── The card's two facts: stock and date, one per line ───────────────────────
   They are the two things the household checks against the shelf, so they are bold and a notch
   larger than the line around them (`0.95rem/800` against `0.82rem`). The date sits on a line of
   ITS OWN with its mark (⏳): on one line, «📦 Giacenza: 1500 ml · ⏳ Scade il 31/01/2027» put two
   number pairs side by side — the stock read as if it were part of the date — and it was the
   first thing to wrap on a phone. The date itself never breaks in half (`.audit-expiry`), only
   the mark can move to the next line if a long locale needs it. */
.audit-product-facts {
    margin-top: 4px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
}
.audit-fact-line {
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.3;
    color: var(--text-muted, #64748b);
}
.audit-fact-qty {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main, inherit);
    font-variant-numeric: tabular-nums;
    /* "1,5 l" is one fact: it never splits in half when the line above wraps. */
    white-space: nowrap;
}
/* A medicine's number (the AIC, or the country's own) is the fact that card is read for: it
   tells one box from the next, and it is what the household compares with the pack in their
   hand. So it wears the same weight and size as the stock and the date, while the ingredient
   beside it stays a quiet line. */
.audit-fact-line-med .audit-fact-code {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main, inherit);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    white-space: nowrap;
}
.audit-fact-line-expiry .audit-expiry {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main, inherit);
    font-variant-numeric: tabular-nums;
}
.audit-fact-line-expiry .audit-expiry.is-expired { color: var(--tone-danger, #dc2626); }
/* ── The other packs of the same article ─────────────────────────────────────
   A barcode points at an ARTICLE, not at a package: «6 pz» on a shelf that also holds a 30-pack
   is only half the answer, and the scan used to open one row with no way to reach the other.
   One line per pack (place, stock, date) and a tap opens THAT row's card inside the same
   stocktake (`_auditOpenPack`). */
.audit-packs {
    margin: 0 0 10px;
    padding: 8px 10px;
    border: 1px solid var(--surface-border, var(--border));
    border-radius: 12px;
    background: var(--surface-bg, #f8fafc);
}
.audit-packs-title {
    margin: 0 0 6px;
    font-size: 0.74rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted, #64748b);
}
.audit-packs-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.audit-pack-line {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 34px;
    padding: 4px 6px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--text-main, inherit);
    font: inherit;
    font-size: 0.86rem;
    line-height: 1.2;
    text-align: left;
    cursor: pointer;
}
.audit-pack-line:active { background: color-mix(in srgb, var(--border) 35%, transparent); }
.audit-pack-ico { font-size: 1rem; line-height: 1; flex: 0 0 auto; }
.audit-pack-place {
    font-weight: 650;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.audit-pack-qty {
    margin-left: auto;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: #047857;
    white-space: nowrap;
}
.audit-pack-date {
    font-size: 0.76rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted, #64748b);
    white-space: nowrap;
}
.audit-pack-go { flex: 0 0 auto; color: var(--text-muted, #64748b); font-weight: 800; }
/* A scale reading is a shortcut, not a warning: a mint pill like the product sheet. */
.audit-scale-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    margin-top: 10px;
    padding: 10px 14px;
    border-radius: 999px;
    border: 1px solid var(--brand-primary, #059669);
    background: #F0FDF4;
    color: color-mix(in srgb, var(--brand-primary, #059669) 75%, var(--text-main));
    font: inherit;
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
}

.inv-tools-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 0 0 10px;
    margin-bottom: 2px;
}
/* The stocktake is a procedure, not a notice: one quiet pill with a dashed frame (a notice
   would be a card, and in the whole-house view this button does not exist at all). */
.inv-stocktake-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    min-height: 34px;
    padding: 6px 13px;
    border-radius: 999px;
    border: 1px dashed color-mix(in srgb, var(--brand-primary, #10b981) 45%, var(--border));
    background: transparent;
    color: color-mix(in srgb, var(--brand-primary, #059669) 65%, var(--text));
    font: inherit;
    font-size: 0.78rem;
    font-weight: 650;
    cursor: pointer;
    white-space: nowrap;
}
.inv-stocktake-btn[hidden] { display: none !important; }
.inv-stocktake-btn:active { background: color-mix(in srgb, var(--brand-primary, #10b981) 12%, transparent); }

.audit-skip {
    margin-top: 10px;
    background: none;
    border: none;
    color: var(--text-muted, #666);
    font: inherit;
    cursor: pointer;
    text-decoration: underline;
}
.audit-summary { font-size: 1.05rem; line-height: 1.5; }
.audit-done { margin-top: 12px; text-align: center; background: var(--brand-primary, #059669); color: #fff; border-color: transparent; }

/* The card reads a sentence: quantity, article, brand and place are the facts
   being checked, so the quantity is deliberately the loudest thing on screen. */
.audit-head-text { min-width: 0; }
.audit-eyebrow {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted, #666);
}
.audit-resume { border-color: var(--brand-primary, #059669); background: #F0FDF4; }
.audit-resume-hint { margin-bottom: 6px; }
.audit-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 12px;
    flex-wrap: wrap;
}
.audit-foot .audit-skip { margin-top: 0; }
.audit-back,
.audit-undo {
    font: inherit;
    font-weight: 600;
    border-radius: 12px;
    border: 1px dashed var(--brand-primary, #059669);
    background: none;
    color: var(--brand-primary, #059669);
    cursor: pointer;
}
.audit-back { padding: 8px 12px; }
.audit-undo { width: 100%; margin-top: 12px; padding: 14px; }
.audit-back:hover,
.audit-undo:hover { background: #F0FDF4; }
/* The edit sheet opens above the card; this ring says which field was asked for. */
.audit-edit-focus { animation: auditFieldFocus 1.5s ease-out; border-radius: 10px; }
@keyframes auditFieldFocus {
    0%   { box-shadow: 0 0 0 0 rgba(5, 150, 105, 0.55); }
    60%  { box-shadow: 0 0 0 12px rgba(5, 150, 105, 0); }
    100% { box-shadow: 0 0 0 0 rgba(5, 150, 105, 0); }
}
/* A phone's cell is narrower, never fewer: the 2×2 stays. */
@media (max-width: 480px) {
    .audit-grid { gap: 6px; }
    .audit-cell { min-height: 44px; padding: 8px 8px; font-size: 0.82rem; gap: 5px; }
}

/* Receipt OCR (#114): the review table is the safety net before the pantry. */
.receipt-table-wrap { max-height: 45vh; overflow: auto; margin: 8px 0; }
.receipt-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.receipt-table th { text-align: left; font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--border-color, #e0e0e0); }
.receipt-table td { padding: 4px 6px; vertical-align: middle; }
.receipt-table .form-input { padding: 4px 6px; font-size: 0.85rem; }
.receipt-name { min-width: 150px; }
.receipt-qty, .receipt-price { width: 80px; }
.receipt-unit { width: 70px; }
.receipt-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }

/* Settings search: one field over the whole page, results jump to the control. */
.settings-search { margin: 0 0 14px; }
.settings-search-box { position: relative; display: flex; align-items: center; gap: 8px; }
.settings-search-icon { position: absolute; left: 12px; pointer-events: none; opacity: 0.7; }
.settings-search-box .form-input { padding-left: 36px; padding-right: 36px; width: 100%; }
.settings-search .settings-hint { margin: 4px 0 0 4px; }
.settings-search-results {
    margin-top: 6px;
    max-height: 46vh;
    overflow-y: auto;
    border: 1px solid var(--border-color, #e0e0e0);
    border-radius: 12px;
    background: var(--bg-card, #fff);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16);
}
.settings-search-count,
.settings-search-empty { margin: 0; padding: 8px 12px; font-size: 0.8rem; color: var(--text-muted, #666); }
.settings-search-hit {
    display: block;
    width: 100%;
    padding: 8px 12px;
    text-align: left;
    background: none;
    border: 0;
    border-top: 1px solid var(--border-color, #f0f0f0);
    cursor: pointer;
    font: inherit;
    color: var(--text-color, inherit);
}
.settings-search-hit:hover,
.settings-search-hit.is-active { background: var(--bg-subtle, #f4f6f4); }
.settings-search-hit-label { display: block; font-weight: 600; font-size: 0.92rem; }
.settings-search-hit-label code { font-size: 0.72rem; opacity: 0.65; font-weight: 400; }
.settings-search-hit-hint { display: block; font-size: 0.8rem; color: var(--text-muted, #666); margin-top: 2px; }
.settings-field-hit {
    outline: 2px solid var(--accent-color, #2e7d32);
    outline-offset: 3px;
    border-radius: 8px;
    animation: settings-hit-pulse 1.3s ease-in-out 2;
}
@keyframes settings-hit-pulse {
    0%, 100% { background: transparent; }
    50% { background: rgba(46, 125, 50, 0.10); }
}

/* ===== End of cooking: the ONE question =====
   Over the dark cooking screen, centred, with the emerald answer for the action that writes
   the pantry and a neutral one for "not now". It replaces the old bounce back to the recipe
   sheet, where the meal still had to be registered by scrolling to the footer. */
.cooking-finish-overlay {
    z-index: 99999;               /* one above .cooking-overlay (99998) */
    align-items: center;
    padding: 20px;
}
.cooking-finish-card {
    width: 100%;
    max-width: 420px;
    text-align: center;
    padding: 22px 20px 18px;
    border-radius: 20px;
}
.cooking-finish-icon {
    display: block;
    font-size: 2.1rem;
    line-height: 1;
    margin-bottom: 8px;
}
.cooking-finish-card h3 {
    margin: 0 0 8px;
    font-size: 1.22rem;
}
.cooking-finish-body {
    margin: 0 0 16px;
    font-size: 0.92rem;
    line-height: 1.45;
    color: var(--text-muted);
}
.cooking-finish-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.cooking-finish-actions .btn { width: 100%; }

/* ===============================================================
 * COOKING MODE — "Deep Slate & Emerald"
 *
 * Read from 1,5–2 m away, with steam and wet hands: ONE card, ONE sentence, big type, no
 * ghosts. This block overrides the older cooking styles on purpose (it is loaded last), so the
 * markup and the JS stay untouched where they already work.
 * =============================================================== */
.cooking-overlay {
    background: #0F172A;                 /* never pure black: less glare, softer edges */
}

/* ── Header: out, the dish, the voice ─────────────────────────────── */
.cooking-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-bottom: 1px solid rgba(148, 163, 184, 0.18);
}
.cooking-close-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    min-height: 40px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid rgba(148, 163, 184, 0.35);
    background: rgba(148, 163, 184, 0.12);
    color: #E2E8F0;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}
.cooking-header .cooking-title {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    font-size: 1rem;
    font-weight: 700;
    color: #E2E8F0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cooking-header-actions { display: inline-flex; gap: 6px; flex-shrink: 0; }
.cooking-header .cooking-tts-btn,
.cooking-mic-btn {
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(148, 163, 184, 0.35);
    background: rgba(148, 163, 184, 0.12);
    color: #E2E8F0;
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}
.cooking-mic-btn.is-listening {
    background: #10B981;
    border-color: #10B981;
    color: #052e1f;
    animation: cookingMicPulse 1.1s ease-in-out infinite;
}
@keyframes cookingMicPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.55); }
    50%      { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
}

/* ── Where we are: passo n di m + the running timer ───────────────── */
.cooking-status {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px 2px;
}
.cooking-status .cooking-step-header { display: none; }
.cooking-step-num {
    flex-shrink: 0;
    font-size: 0.76rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #94A3B8;
    white-space: nowrap;
}
.cooking-status .cooking-progress-dots {
    display: flex;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
}
.cooking-status .cprog-dot {
    flex: 1 1 0;
    width: auto;
    height: 5px;
    border-radius: 999px;
    background: rgba(148, 163, 184, 0.28);
}
.cooking-status .cprog-dot.visited { background: rgba(16, 185, 129, 0.45); }
.cooking-status .cprog-dot.current { background: #10B981; }
.cooking-restart-btn {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 1px solid rgba(148, 163, 184, 0.3);
    background: transparent;
    color: #94A3B8;
    font-size: 0.95rem;
    cursor: pointer;
}
.cooking-status .cooking-timers-bar {
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
    max-width: 46vw;
    overflow: visible;
}

/* ── The card: one, centred, nothing around it ────────────────────── */
.cooking-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 10px 14px;
    min-height: 0;
    overflow-y: auto;
}
.cooking-card {
    width: 100%;
    max-width: 760px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 20px;
    border-radius: 16px;
    background: #1E293B;
    border: 1px solid rgba(148, 163, 184, 0.18);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
}
/* No half-cut neighbours: the ghosts stay in the DOM for the navigation code, never on screen. */
.cooking-step-ghost { display: none !important; }
.cooking-card .cooking-wheel {
    position: static;
    width: 100%;
    transform: none !important;
    display: block;
}
.cooking-card .cooking-step-text {
    width: 100%;
    max-width: none;
    padding: 0;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    color: #F1F5F9;
    text-align: left;
    font-size: clamp(24px, 3.2vw, 34px);
    line-height: 1.5;
    font-weight: 600;
    transform: none !important;
    animation: none;
}
.cooking-card .cooking-step-text.is-entering {
    animation: cookingStepIn 220ms ease-out;
}
@keyframes cookingStepIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .cooking-card .cooking-step-text.is-entering { animation: none; }
}

/* Amounts and food stand out: the eye catches "200 g di spinaci" without re-reading. */
.cooking-card .cooking-step-text mark {
    background: none;
    color: inherit;
}
.cooking-card .cooking-step-text mark.ck-qty { color: #6EE7B7; font-weight: 800; }
.cooking-card .cooking-step-text mark.ck-ing { color: #A7F3D0; font-weight: 700; }

/* The duration inside the sentence is the timer button. */
.cooking-card .cooking-step-timer {
    padding: 4px 14px;
    border-radius: 10px;
    background: #10B981;
    color: #052e1f;
    font-size: 0.62em;
    font-weight: 800;
    box-shadow: 0 6px 16px rgba(16, 185, 129, 0.35);
}

/* ── Ingredients for THIS step: first thing in the card ───────────── */
.cooking-card .cooking-step-ings {
    justify-content: flex-start;
    gap: 8px;
    max-width: none;
    margin: 0;
}
.cooking-card .cooking-ing-chip {
    height: 36px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 12px;
    border-radius: 10px;
    background: #0F172A;
    border: 1px solid rgba(16, 185, 129, 0.55);
    color: #E2E8F0;
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
}
.cooking-card .cooking-ing-tool { border-color: rgba(148, 163, 184, 0.5); color: #CBD5E1; }

/* ── "SHELFY sta leggendo" ────────────────────────────────────────── */
.cooking-reading {
    display: none;
    align-items: center;
    gap: 8px;
    color: #94A3B8;
    font-size: 0.78rem;
}
.cooking-reading img { width: 32px; height: 32px; object-fit: contain; }
.cooking-reading-waves { display: inline-flex; align-items: flex-end; gap: 3px; height: 18px; }
.cooking-reading-waves i {
    width: 3px;
    height: 6px;
    border-radius: 2px;
    background: #10B981;
    animation: cookingWave 900ms ease-in-out infinite;
}
.cooking-reading-waves i:nth-child(2) { animation-delay: 150ms; }
.cooking-reading-waves i:nth-child(3) { animation-delay: 300ms; }
@keyframes cookingWave {
    0%, 100% { height: 6px; opacity: 0.6; }
    50%      { height: 16px; opacity: 1; }
}

/* ── Rileggi + navigation ─────────────────────────────────────────── */
.cooking-replay-btn {
    min-height: 44px;
    padding: 0 18px;
    border-radius: 999px;
    border: 1px solid rgba(148, 163, 184, 0.35);
    background: rgba(148, 163, 184, 0.12);
    color: #E2E8F0;
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}
.cooking-nav {
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 10px 14px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(148, 163, 184, 0.18);
}
.cooking-nav-btn {
    min-height: 52px;
    border-radius: 999px;
    font-size: 1rem;
    font-weight: 700;
    cursor: pointer;
}
.cooking-prev-btn {
    flex: 0 0 auto;
    padding: 0 20px;
    background: rgba(148, 163, 184, 0.12);
    border: 1px solid rgba(148, 163, 184, 0.3);
    color: #E2E8F0;
}
.cooking-next-btn {
    flex: 1 1 auto;
    background: #10B981;
    border: none;
    color: #052e1f;
}
.cooking-next-btn:disabled { opacity: 0.45; }

/* ── Running timers: a clean name, never "Avvia Cookeo…" ──────────── */
.cooking-timers-bar .cooking-timer-card { max-width: 240px; }
.cooking-timers-bar .ctimer-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
}

/* "Già in lista" inside the missing-ingredients popover. */
.recipe-missing-inlist {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: rgba(16, 185, 129, 0.14);
    border: 1px solid rgba(16, 185, 129, 0.4);
    color: #047857;
    font-size: 0.7rem;
    font-weight: 700;
    white-space: nowrap;
}
[data-theme="dark"] .recipe-missing-inlist {
    background: rgba(16, 185, 129, 0.18);
    color: #6EE7B7;
}

/* ── Cooking: the step is CENTRED and large, and the SHELFY button lives in the header ── */
.cooking-card {
    align-items: center;
    text-align: center;
}
.cooking-card .cooking-step-ings {
    justify-content: center;
    width: 100%;
}
.cooking-card .cooking-step-text {
    text-align: center;
    font-size: clamp(26px, 3.6vw, 40px);
}
.cooking-card .cooking-ing-left {
    display: block;
    margin-top: 2px;
    font-size: 11px;
    font-weight: 600;
    color: #94A3B8;
}
.cooking-card .cooking-ing-chip {
    height: auto;
    min-height: 36px;
    padding: 6px 12px;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    line-height: 1.25;
}
.cooking-card .cooking-ing-chip em { font-style: normal; color: #94A3B8; }

/* The inside of the card scrolls smoothly; the auto-scroll drives scrollTop gently. */
.cooking-body { scroll-behavior: auto; }

/* The step action ("Avvia il timer di 6 minuti per Cookeo"), bottom-left above the navigation. */
.cooking-action-row {
    display: none;
    justify-content: flex-start;
    padding: 0 14px 6px;
}
.cooking-step-action {
    min-height: 46px;
    padding: 0 18px;
    border-radius: 12px;
    border: 1px solid rgba(16, 185, 129, 0.55);
    background: rgba(16, 185, 129, 0.16);
    color: #6EE7B7;
    font-size: 0.92rem;
    font-weight: 700;
    line-height: 1.25;
    text-align: left;
    cursor: pointer;
}
.cooking-step-action:active { background: rgba(16, 185, 129, 0.28); }

/* SHELFY is reachable from the stove too: her avatar, in the header. */
.cooking-shelfy-btn {
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 50%;
    border: 1px solid rgba(16, 185, 129, 0.55);
    background: rgba(16, 185, 129, 0.14);
    cursor: pointer;
    overflow: hidden;
}
.cooking-shelfy-btn img { width: 32px; height: 32px; object-fit: contain; }

/* The capture sheet must sit ABOVE the cooking overlay (99998), or SHELFY opens invisibly. */
body.cooking-mode-active #capture-sheet { z-index: 100000; }
body.cooking-mode-active #shelfy-intro { z-index: 100001; }

/* ===============================================================
 * COOKING MODE — layout pass (supersedes the sizes above)
 * Full width, centred stack, SHELFY in the middle of the navigation.
 * =============================================================== */

/* ── Header: a bare, evident ✕ ────────────────────────────────────── */
.cooking-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
}
.cooking-close-btn {
    width: 44px;
    height: 44px;
    min-height: 0;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    border: 1px solid rgba(148, 163, 184, 0.4);
    background: rgba(148, 163, 184, 0.14);
    color: #F1F5F9;
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
}

/* ── Status: full width, the bar in the middle ────────────────────── */
.cooking-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    width: 100%;
    padding: 10px 16px 6px;
}
.cooking-status .cooking-step-num {
    flex: 0 0 auto;
    font-size: 0.8rem;
}
.cooking-status .cooking-progress-dots {
    flex: 1 1 auto;
    display: flex;
    gap: 5px;
    margin: 0 6px;
    min-width: 0;
}
.cooking-status .cprog-dot {
    flex: 1 1 0;
    height: 6px;
    border-radius: 999px;
}
.cooking-status .cooking-restart-btn {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    font-size: 1rem;
}
/* The running timers get their own full-width row under the status. */
#cooking-timers-bar {
    width: 100%;
    margin: 0;
    padding: 0 16px;
    max-width: none;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
}

/* ── Card: fills the width, content centred VERTICALLY ────────────── */
.cooking-body {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* `margin: auto` on the card (below) centres it when it fits AND leaves the top reachable
       when it does not: `justify-content: center` on an overflowing flex box clips the start. */
    justify-content: flex-start;
    gap: 12px;
    width: 100%;
    padding: 10px 16px;
    min-height: 0;
    overflow-y: auto;
}
.cooking-card {
    width: 100%;
    max-width: 980px;                 /* use the screen, not a 760px column */
    margin: auto 0;                   /* vertical centring even when it does not fill */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;          /* chips + sentence + action centred inside the card */
    gap: 16px;
    padding: 22px 24px;
    min-height: 0;
}
.cooking-card .cooking-wheel {
    width: 100%;
    flex: 1 1 auto;
    display: flex;
    align-items: center;              /* the sentence is centred in its own area */
    justify-content: center;
    min-height: 0;
}
.cooking-card .cooking-step-text {
    width: 100%;
    text-align: center;
    font-size: clamp(26px, 3.6vw, 40px);
    line-height: 1.5;
    margin: auto 0;
}

/* ── Ingredient chips: across the whole width ─────────────────────── */
.cooking-card .cooking-step-ings {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}
.cooking-card .cooking-ing-chip {
    flex: 1 1 220px;
    min-width: 0;
    max-width: none;
    text-align: left;
}

/* ── Step action: centred ─────────────────────────────────────────── */
.cooking-action-row {
    width: 100%;
    display: none;
    justify-content: center;
    padding: 0 16px 8px;
}
.cooking-step-action {
    text-align: center;
    padding: 0 22px;
}

/* ── Navigation: [ ◀ Precedente ]  (SHELFY)  [ Successivo ▶ ] ─────── */
.cooking-nav {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 10px 16px calc(12px + env(safe-area-inset-bottom, 0px));
}
.cooking-nav .cooking-nav-btn {
    flex: 1 1 0;                      /* the two are EQUAL */
    min-width: 0;
    min-height: 56px;
    border-radius: 999px;
    font-size: 1rem;
    font-weight: 700;
}
.cooking-prev-btn {
    background: rgba(148, 163, 184, 0.14);
    border: 1px solid rgba(148, 163, 184, 0.32);
    color: #E2E8F0;
}
.cooking-next-btn {
    background: #10B981;
    border: none;
    color: #052e1f;
}
/* SHELFY in the middle, as big as the home button and with the same ring. */
.cooking-shelfy-fab {
    flex: 0 0 auto;
    width: clamp(56px, 12vw, 64px);
    height: clamp(56px, 12vw, 64px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 50%;
    border: 3px solid #10B981;
    background: radial-gradient(circle at 50% 30%, #10B981 0%, #047857 100%);
    box-shadow: 0 8px 20px rgba(16, 185, 129, 0.35);
    cursor: pointer;
    overflow: hidden;
}
.cooking-shelfy-fab img {
    width: 82%;
    height: 82%;
    object-fit: contain;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}
.cooking-shelfy-fab:active { transform: scale(0.96); }

/* ===============================================================
 * COOKING MODE — layout pass 2
 * One line per chip, real breathing room around the sentence, and a scroll
 * area that exists (so the auto-scroll has something to move).
 * =============================================================== */

/* The strip: small label on top, chips in a wrapping row below. */
.cooking-card .cooking-step-ings {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
}
.cooking-ings-label {
    flex: 0 0 100%;
    text-align: center;
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: #64748B;
    margin-bottom: 2px;
}

/* ONE line per chip: name (brand) · dose — “ne restano X” all on the same row. */
.cooking-card .cooking-ing-chip {
    flex: 1 1 260px;
    min-width: 0;
    max-width: none;
    height: auto;
    min-height: 36px;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;          /* the chip content is centred, like the sentence */
    gap: 4px;
    padding: 6px 12px;
    white-space: nowrap;
    overflow: hidden;
    line-height: 1.3;
    text-align: center;
}
.cooking-card .cooking-ing-chip > strong,
.cooking-card .cooking-ing-chip > em,
.cooking-card .cooking-ing-chip > .cooking-ing-left {
    display: inline;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cooking-card .cooking-ing-chip > em { color: #94A3B8; }
.cooking-card .cooking-ing-left {
    margin: 0 0 0 4px;
    font-size: 12px;
    font-weight: 700;
    color: #6EE7B7;
}

/* The sentence breathes above and below, and it is its own scroll area. */
.cooking-card .cooking-wheel { padding: 6px 0; }
.cooking-card .cooking-step-text {
    padding: 22px 4px;
    max-height: min(52vh, 440px);
    overflow-y: auto;
    scrollbar-width: none;
}
.cooking-card .cooking-step-text::-webkit-scrollbar { display: none; }

/* ── The 🎤 coach mark: 8 seconds, once per device ────────────────── */
.cooking-voice-hint {
    position: fixed;
    z-index: 100002;                  /* above the cooking overlay */
    width: min(300px, calc(100vw - 16px));
    padding: 12px 13px 11px;
    border-radius: 14px;
    background: #1E293B;
    border: 1px solid rgba(16, 185, 129, 0.55);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
    color: #E2E8F0;
    text-align: left;
    animation: cvhIn 240ms ease-out;
}
@keyframes cvhIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .cooking-voice-hint { animation: none; } }
/* little arrow pointing up at the microphone */
.cooking-voice-hint::before {
    content: '';
    position: absolute;
    top: -6px;
    right: 16px;
    width: 10px;
    height: 10px;
    background: #1E293B;
    border-left: 1px solid rgba(16, 185, 129, 0.55);
    border-top: 1px solid rgba(16, 185, 129, 0.55);
    transform: rotate(45deg);
}
.cvh-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}
.cvh-head img { width: 26px; height: 26px; object-fit: contain; flex-shrink: 0; }
.cvh-head strong { flex: 1 1 auto; font-size: 0.9rem; font-weight: 800; color: #F1F5F9; }
.cvh-close {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border: none;
    border-radius: 50%;
    background: rgba(148, 163, 184, 0.18);
    color: #CBD5E1;
    font-size: 0.72rem;
    line-height: 1;
    cursor: pointer;
}
.cvh-intro, .cvh-foot {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
    color: #CBD5E1;
}
.cvh-foot { margin-top: 7px; color: #94A3B8; }
.cvh-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 7px 0;
}
.cvh-chip {
    padding: 4px 10px;
    border-radius: 999px;
    background: rgba(16, 185, 129, 0.16);
    border: 1px solid rgba(16, 185, 129, 0.5);
    color: #6EE7B7;
    font-size: 0.8rem;
    font-weight: 700;
    white-space: nowrap;
}
/* the microphone announces itself while the card is up */
.cooking-mic-btn.is-hinting {
    border-color: #10B981;
    color: #6EE7B7;
    animation: cookingMicPulse 1.6s ease-in-out infinite;
}

/* ── Shopping: counts on the pills + the "Non comprati" drawer ──────── */
.smart-filter-count {
    display: inline-block;
    min-width: 18px;
    padding: 0 5px;
    margin-left: 2px;
    border-radius: 999px;
    background: rgba(148, 163, 184, 0.22);
    color: inherit;
    font-size: 0.7rem;
    font-weight: 800;
    line-height: 1.6;
    text-align: center;
}
.smart-filter.active .smart-filter-count {
    background: rgba(16, 185, 129, 0.22);
    color: #047857;
}

.shopping-dismissed {
    margin: 12px 0 4px;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--bg, #f8fafc);
    border: 1px solid var(--surface-border, #e2e8f0);
}
.shopping-dismissed[hidden] { display: none; }
.shopping-dismissed > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--text-muted);
    list-style: none;
}
.shopping-dismissed > summary::-webkit-details-marker { display: none; }
.shopping-dismissed > summary::after {
    content: '▾';
    margin-left: auto;
    font-size: 0.8rem;
    color: var(--text-muted);
}
.shopping-dismissed[open] > summary::after { content: '▴'; }
.shopping-dismissed-count {
    padding: 0 6px;
    border-radius: 999px;
    background: rgba(148, 163, 184, 0.2);
    font-size: 0.72rem;
    font-weight: 800;
}
.shopping-dismissed-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    border-top: 1px solid color-mix(in srgb, var(--surface-border, #e2e8f0) 70%, transparent);
}
.shopping-dismissed-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--text);
}
.shopping-dismissed-until {
    display: block;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--text-muted);
}
[data-theme="dark"] .shopping-dismissed {
    background: var(--bg-card, #1e293b);
    border-color: #334155;
}


/* ── Stocktake: «da quanti giorni è aperto?» (medicines) ───────────────────
   «Aperto» is two facts: that it is open and since when. The card asks the second one in place,
   hiding the confirm it can no longer answer honestly (a box marked open three weeks late must
   not get a PAO date three weeks too far). Same mint pills as the rest of the card. */
.audit-panel.is-med-days-ask .audit-there,
.audit-panel.is-med-days-ask .audit-grid { display: none; }
.audit-med-days-panel { margin-top: 12px; }
.audit-med-days-q {
    margin: 0 0 8px;
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--text-main);
}
.audit-med-days {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.audit-med-days .audit-med-day {
    flex: 1 1 auto;
    min-width: 76px;
    min-height: 44px;
    padding: 8px 12px;
    border-radius: 12px;
    border: 1px solid #86efac;
    background: #f0fdf4;
    color: #14532d;
    font-weight: 800;
}
.audit-med-days-panel .audit-skip { margin-top: 8px; }

/* ── The medicine edit sheet, condensed ───────────────────────────────────
   «Modifica farmaco Connettivina plus» and «Già aperta · 29/10/2026 01:00» were separated by a
   band of empty space (the heading carried its own line-height and the header its own margin):
   on a phone that is a third of the sheet. Prefix + name on one line, the state right under it. */
/* The ✕ button sets the header's height (44 px) and the modal's own 16 px margin stacked on
   top of it: on a phone that is a band of empty space before the first line of the form. The
   id makes these win over corporate.css `.modal-header`, which loads later. */
#modal-content .modal-header.edit-modal-header { margin-bottom: 4px; padding-bottom: 0; align-items: flex-start; }
#modal-content .modal-header.edit-modal-header .edit-modal-heading { margin: 0; line-height: 1.2; }
#modal-content .modal-header.edit-modal-header .edit-modal-prefix { margin-right: 6px; }
#modal-content .form.is-medical-edit .item-detail-med-summary { margin-top: 0; }

/* «Da quanti giorni è aperto?» — the same five answers as the stocktake, in the edit sheet. */
.med-open-since { margin: 0 0 12px; }
.med-open-since .settings-hint { margin: 0 0 6px; }
/* The answer that is STORED wears the mark (same grammar as `.med-cat-chip.is-on`): a row of
   identical chips said nothing about what the app had saved, so a correct write looked lost. */
.med-open-since-chips .btn.is-on {
    background: var(--brand-surface);
    border-color: var(--brand-primary, #059669);
    color: var(--brand-primary-hover, #047857);
}
.med-open-since-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.med-open-since-chips .btn { min-height: 40px; }
/* «Non aperta» — the second door of the same block, and the only way to take a wrong «aperta»
   back without a lie about the stock. It sits UNDER the chips (its own line: seven presets plus
   this would squeeze the last one), neutral rather than emerald, because it undoes a state
   instead of answering a question. It exists only on a whole pack (`_medPackIsWhole`); where it
   cannot be true, the hint above says why. */
.med-open-since .med-unopen { margin-top: 8px; }
.med-open-since .med-unopen-why { margin: 8px 0 0; }

/* ── No camera → no camera icons, anywhere ────────────────────────────────
   Asked for: «se non ci sono le autorizzazioni o non si può usare la fotocamera NON far vedere
   l'icona in ogni parte del programma, è inutile far vedere qualcosa che non può funzionare».
   `_detectCameraAvailability()` (app.js) puts `no-camera` on <html> the moment the answer is no —
   no getUserMedia, the permission already refused, or a camera that just failed — and every scan
   entry point disappears: the inline handlers are matched by attribute, so a button added later
   is covered without touching it. */
/* Kept VISIBLE, wearing the ✕ (asked for: «meglio mettere una X sulla fotocamera quando non è
   disponibile, e se la clicchi viene fuori il messaggio»): hiding the button left the household
   wondering where the scanner went, while a grey box answered "impossibile accedere". The tap
   now OPENS the scan page, and the page says it: only the stream is off (see below). */
html.no-camera #btn-header-scan,
html.no-camera #pf-barcode-scan-btn,
html.no-camera #screensaver-scan-btn,
html.no-camera [onclick*="showPage('scan')"],
html.no-camera [onclick*="_medGoToCabinetScan"],
html.no-camera [onclick*="startSpesaMode"],
html.no-camera [onclick*="_auditSetMode('scan')"],
html.no-camera [data-camera-only] { position: relative; opacity: 0.6; }

html.no-camera #btn-header-scan::after,
html.no-camera #pf-barcode-scan-btn::after,
html.no-camera #screensaver-scan-btn::after,
html.no-camera [onclick*="showPage('scan')"]::after,
html.no-camera [onclick*="_medGoToCabinetScan"]::after,
html.no-camera [onclick*="startSpesaMode"]::after,
html.no-camera [onclick*="_auditSetMode('scan')"]::after {
    content: '✕';
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 15px;
    height: 15px;
    border-radius: 999px;
    background: #dc2626;
    color: #fff;
    font-size: 9px;
    font-weight: 800;
    line-height: 15px;
    text-align: center;
    pointer-events: none;
}

/* ON THE SCAN PAGE the answer is different: the page OPENS and only the STREAM is off. The
   camera's own furniture goes away — an empty viewport is the «riquadro grigio» the wall kept
   reporting — while the manual doors under it (Cerca · Manuale, and the typed barcode in the
   medicine panel) stay exactly where they are. `!important` because those elements also carry
   inline `display` written by the shopping mode. */
html.no-camera #scanner-viewport,
html.no-camera .scan-below-bar { display: none !important; }
/* Shopping-while-scanning is a camera flow (the bags in one hand, the phone in the other): its
   two entries have no meaning without a stream. Manual adding to the pantry is untouched. */
html.no-camera #scan-spesa-btn,
html.no-camera #scan-spesa-quick-btn { display: none !important; }

/* The notice itself — a CARD, not the capsule toast this message used to be («il popup è rotondo
   ed è brutissimo»): a two-line sentence inside a 9999 px pill reads as a bubble, and it left
   while the household was still reading it. The page keeps this on screen as long as it lives. */
.scan-nocamera {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 0 0 12px;
    padding: 12px 14px;
    border: 1px solid color-mix(in srgb, var(--tone-warning, #b45309) 35%, var(--surface-border, var(--border)));
    border-radius: 14px;
    background: color-mix(in srgb, var(--tone-warning, #b45309) 8%, var(--surface-bg, #fff));
    color: var(--text-main, inherit);
}
.scan-nocamera[hidden] { display: none; }
.scan-nocamera-icon { flex: 0 0 auto; font-size: 1.3rem; line-height: 1.2; }
.scan-nocamera-text { min-width: 0; }
.scan-nocamera-title { display: block; font-size: 0.95rem; font-weight: 800; }
.scan-nocamera-body {
    margin: 4px 0 0;
    font-size: 0.85rem;
    line-height: 1.35;
    color: var(--text-muted, #475569);
}

/* A toast that carries a sentence instead of a word: same card grammar as a panel (the pill stays
   for «Salvato» and the action toasts). */
.toast.card {
    border-radius: 14px;
    padding: 12px 16px;
    text-align: left;
    line-height: 1.35;
}

/* The camera takes the AI door away: it says so, it does not pretend to be tappable. */
.scan-action-btn[disabled],
.scan-action-btn.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* A stocktake answer that is already given cannot be given again. */
.audit-cell[disabled],
.audit-cell.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}
