﻿/* =============================================================================
   SHARED UI STYLES - Multi-Project CSS Framework
   =============================================================================

   Naming Convention: "su-" prefix (Shared UI)

   RESPONSIVE STRATEGY (clamp vs media queries):
   - clamp(): Used for fluid typography, spacing, and continuous scaling
   - Media queries: Used for layout changes, show/hide, user preferences

   CROSS-PLATFORM (Web + MAUI Hybrid):
   - Uses 100dvh for proper mobile viewport handling
   - Safe-area insets for iPhone notches and Android cutouts
   - Hover effects gated behind @media (hover: hover)
   - Reduced motion support for accessibility

   ============================================================================= */

/* =============================================================================
   CSS CUSTOM PROPERTIES (Design Tokens)
   ============================================================================= */
:root {
    /* Safe Area Insets */
    --su-safe-top: env(safe-area-inset-top, 0px);
    --su-safe-bottom: env(safe-area-inset-bottom, 0px);
    --su-safe-left: env(safe-area-inset-left, 0px);
    --su-safe-right: env(safe-area-inset-right, 0px);
    /* Spacing Scale */
    --su-space-xs: clamp(0.25rem, 0.5vw, 0.5rem);
    --su-space-sm: clamp(0.5rem, 1vw, 0.75rem);
    --su-space-md: clamp(0.75rem, 1.5vw, 1rem);
    --su-space-lg: clamp(1rem, 2vw, 1.5rem);
    --su-space-xl: clamp(1.5rem, 3vw, 2rem);
    /* Typography Scale */
    --su-text-xs: clamp(0.625rem, 0.5vw + 0.5rem, 0.75rem);
    --su-text-sm: clamp(0.75rem, 0.5vw + 0.625rem, 0.875rem);
    --su-text-base: clamp(0.875rem, 0.5vw + 0.75rem, 1rem);
    --su-text-lg: clamp(1rem, 0.75vw + 0.75rem, 1.125rem);
    --su-text-xl: clamp(1.125rem, 1vw + 0.75rem, 1.25rem);
    /* Border Radius */
    --su-radius-sm: 4px;
    --su-radius-md: 8px;
    --su-radius-lg: 12px;
    --su-radius-xl: 16px;
    --su-radius-2xl: 18px;
    --su-radius-full: 24px;
    --su-radius-round: 50%;
    /* Shadows */
    --su-shadow-sm: 0 1px 6px rgba(32, 33, 36, 0.28);
    --su-shadow-md: 0 4px 14px rgba(0, 0, 0, 0.06);
    --su-shadow-lg: 0 6px 20px rgba(0, 0, 0, 0.08);
    --su-shadow-xl: 0 8px 24px rgba(0, 0, 0, 0.08);
    --su-shadow-elevated: 0 12px 32px rgba(0, 0, 0, 0.35);
    /* =========================================================================
       COLOURS - aliases onto the theme tokens in themes.css
       =========================================================================
       These used to be hardcoded light-mode hex, with a dark-mode block below
       and a 218-line force-light block at the end of the file that overrode it
       with !important. Both are gone: THEMES.md design rule 1 requires dark mode
       to work, and nothing themed survives a stylesheet that forces light.

       Pointing the whole --su-* colour layer at the theme tokens means the
       ~7,000 lines below that already say var(--su-text-primary) became
       theme-aware without being touched. The literal hex still scattered through
       this file is migrated section by section; this alias layer is what makes
       that incremental rather than all-or-nothing.

       The second value in each var() is the fallback for themes.css failing to
       load - it reproduces the previous hardcoded value, so a missing stylesheet
       degrades to the old look rather than to no colour at all.
       ========================================================================= */
    --su-bg-primary: var(--bg, #F4F7FA);
    --su-bg-surface: var(--surface, #ffffff);
    --su-bg-surface-alpha: var(--surfaceAlpha, rgba(255, 255, 255, 0.9));
    --su-bg-glass: var(--glass, rgba(255, 255, 255, 0.75));
    --su-bg-hover: var(--hoverWash, rgba(0, 0, 0, 0.04));
    --su-text-primary: var(--text, #111);
    --su-text-secondary: var(--textMut, #5f6368);
    --su-text-muted: var(--textMut, #70757a);
    --su-text-hint: var(--textMut, #9aa0a6);
    --su-border-light: var(--border, rgba(0, 0, 0, 0.06));
    --su-border-default: var(--border, rgba(0, 0, 0, 0.08));
    --su-border-focus: var(--fieldBorder, rgba(0, 0, 0, 0.1));
    /* Transitions */
    --su-transition-fast: 0.15s ease;
    --su-transition-base: 0.2s ease;
    --su-transition-smooth: 0.25s ease;
    --su-transition-slow: 0.3s ease;
    --su-transition-spring: 0.3s ease-in-out;
    /* color-scheme is set by themes.css per RESOLVED mode. It was pinned here to
       "only light", which told the browser to ignore dark mode outright - form
       controls, scrollbars and caret colours would have stayed light while
       everything around them went dark. */
}

/* =============================================================================
   DARK MODE TOKENS
   (Kept for reference — overridden at the bottom of this file for force-light)
   ============================================================================= */
/* =============================================================================
   LEGACY DARK MODE TOKENS - REMOVED in Phase 2 (theme system)
   =============================================================================
   A second set of hardcoded --su-* values used to live here behind
   prefers-color-scheme. It is obsolete twice over: the --su-* colour tokens are
   now aliases onto the theme tokens, which already carry both modes, and keying
   off the device preference would have overridden an explicit light choice.
   ============================================================================= */
/* =============================================================================
   BASE STYLES
   ============================================================================= */
html {
    -webkit-text-size-adjust: 100%;
    background: var(--su-bg-primary);
    /* FIX: allow pull-to-refresh (auto, not none) */
    overscroll-behavior-y: auto;
}

body {
    background: var(--su-bg-primary);
    /* Global typography (DESIGN-BATCHES): Inter for body/UI. MudBlazor's own
       typography covers Mud components; this covers everything else. */
    font-family: var(--font-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    overscroll-behavior-y: auto;
}

html, body {
    height: 100%;
}

/* Remove 300ms tap delay */
button,
[role="button"],
.su-cursor-pointer,
a {
    touch-action: manipulation;
}

/* iOS momentum scrolling */
.su-nav-history-content,
.su-suggestions-dropdown,
.su-recent-scans-list,
.mud-dialog-content {
    -webkit-overflow-scrolling: touch;
}

/* Prevent scroll chaining */
.su-left-drawer,
.su-right-drawer,
.su-suggestions-dropdown {
    overscroll-behavior: contain;
}

/* =============================================================================
   PREVENT FIXED-POSITION BREAKAGE
   transform/perspective/filter on ancestors break position:fixed on descendants
   FIX: remove filter:none (too aggressive) — only neutralise transform/will-change
   ============================================================================= */
.mud-layout,
.mud-main-content,
.su-main-content,
.su-content-area,
.su-main-content-wrapper {
    transform: none !important;
    will-change: auto !important;
    perspective: none !important;
    contain: none !important;
}

/* =============================================================================
   REDUCED MOTION
   ============================================================================= */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* =============================================================================
   ANIMATIONS & KEYFRAMES
   FIX: su-fade-in uses opacity only — NO transform (transform breaks fixed positioning)
   ============================================================================= */
@keyframes su-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes su-slide-down {
    from {
        transform: translateY(-100%);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.su-slide-down {
    animation: su-slide-down 0.3s ease-out;
}

/* =============================================================================
   Z-INDEX HIERARCHY
   =============================================================================
   1350 — Floating back button
   1300 — App bars (top + bottom)
   1200 — Drawers
   1199 — Drawer overlay
   100  — Sticky filter header
   ============================================================================= */

/* =============================================================================
   LAYOUT - APP BAR (consolidated single definition)
   ============================================================================= */
.su-appbar {
    background: var(--su-bg-glass);
    border-radius: var(--su-radius-xl);
    box-shadow: var(--su-shadow-md);
    color: var(--su-text-primary);
    transition: all var(--su-transition-spring);
    z-index: 1100 !important;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .su-appbar {
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
    }
}

@media (hover: hover) and (pointer: fine) {
    .su-appbar:hover {
        box-shadow: var(--su-shadow-lg);
    }
}

/* TOP BAR — fixed, safe-area-aware */
.su-appbar-top-bar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    z-index: 1300 !important;
    transform: none !important;
    will-change: auto !important;
    /* Padding: safe-area top + visual spacing */
    padding-top: calc(var(--su-space-xs) + var(--su-safe-top)) !important;
    padding-bottom: var(--su-space-xs);
    padding-left: clamp(8px, 2vw, 20px);
    padding-right: clamp(8px, 2vw, 20px);
    background: var(--su-bg-glass);
    border-radius: 0 0 var(--su-radius-lg) var(--su-radius-lg);
    box-shadow: var(--su-shadow-md);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .su-appbar-top-bar {
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
    }
}

@media (max-width: 600px) {
    .su-appbar-top-bar {
        padding-top: calc(6px + var(--su-safe-top)) !important;
        padding-bottom: 6px;
        padding-left: 8px;
        padding-right: 8px;
        border-radius: 0 0 var(--su-radius-md) var(--su-radius-md);
    }

    /* Compact icon buttons */
    .su-appbar .mud-icon-button {
        padding: 8px;
        margin: 0 2px;
    }

    /* Minimal spacers on mobile */
    .su-appbar .mud-spacer {
        flex: 0 0 4px;
        min-width: 4px;
    }

    /* Smaller logo in appbar */
    .su-appbar .su-navbar-logo,
    .su-appbar .su-logo-link img {
        max-width: 90px;
        height: auto;
    }
}

/* BOTTOM BAR — fixed, safe-area-aware */
.su-appbar-bottom-bar {
    position: fixed !important;
    bottom: 0 !important;
    left: 0 !important;
    right: 0 !important;
    z-index: 1300 !important;
    padding-top: var(--su-space-sm);
    padding-bottom: calc(var(--su-space-sm) + var(--su-safe-bottom)) !important;
    padding-left: clamp(8px, 2vw, 20px);
    padding-right: clamp(8px, 2vw, 20px);
    background: var(--su-bg-surface-alpha);
    border-radius: var(--su-radius-lg) var(--su-radius-lg) 0 0;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .su-appbar-bottom-bar {
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
    }
}

@media (max-width: 600px) {
    .su-appbar-bottom-bar {
        padding-top: 6px;
        padding-bottom: calc(6px + var(--su-safe-bottom)) !important;
        padding-left: 10px;
        padding-right: 10px;
    }

        /* Smaller logo in bottom bar */
        .su-appbar-bottom-bar .su-logo-link img {
            max-width: 70px;
        }
}

/* =============================================================================
   LAYOUT - DRAWERS / SIDEBARS
   Drawers sit behind app bar (z-index 1200 < app bar 1300)
   Top padding accounts for the fixed app bar height
   ============================================================================= */
/* App-bar clearance is NOT set here. This block used to declare
   padding-top: calc(56px + safe-top) !important, which never took effect: an
   identical selector later in this file declares 72px, also !important, and the
   later one wins. Two numbers for one thing meant editing this one changed
   nothing. The single live declaration is in LAYOUT - DRAWERS, further down. */
.su-left-drawer,
.su-right-drawer,
.mud-drawer {
    background: var(--su-bg-primary);
    transition: transform var(--su-transition-slow), opacity var(--su-transition-slow);
    z-index: 1200 !important;
}

.su-left-drawer {
    border-right: 1px solid var(--su-border-light);
}

.su-right-drawer {
    border-left: 1px solid var(--su-border-light);
}

.mud-drawer-content {
    padding: var(--su-space-md);
}

/* Drawer overlay behind app bar */
.mud-overlay {
    z-index: 1199 !important;
}

/* The 52px mobile counterpart of the rule above was dead for the same reason —
   a later identical selector declares 68px !important. Both live in
   LAYOUT - DRAWERS. */

/* =============================================================================
   LAYOUT - MAIN CONTENT WRAPPER (consolidated single definition)
   ============================================================================= */
.su-main-content-wrapper {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    /* Account for fixed top app bar + safe area */
    padding-top: calc(56px + var(--su-safe-top));
}

@media (max-width: 600px) {
    .su-main-content-wrapper {
        padding-top: calc(52px + var(--su-safe-top));
    }
}

/* Account for fixed bottom bar + safe area on mobile/tablet */
@media (max-width: 959.98px) {
    .su-main-content-wrapper {
        padding-bottom: calc(64px + var(--su-safe-bottom, 0px));
    }
}

.su-content-area {
    flex: 1 0 auto;
    padding-bottom: var(--su-space-md);
}

.su-main-content {
    background: var(--su-bg-primary);
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

/* =============================================================================
   COMPONENTS - LOGO
   ============================================================================= */
.su-logo-link {
    display: flex;
    align-items: center;
}

.su-navbar-logo {
    max-width: clamp(200px, 30vw, 300px);
    width: 100%;
    height: auto;
    padding-right: clamp(12px, 2vw, 20px);
    transition: transform var(--su-transition-smooth), opacity var(--su-transition-slow);
}

@media (hover: hover) and (pointer: fine) {
    .su-navbar-logo:hover {
        transform: scale(1.03);
        opacity: 0.9;
    }
}

/* =============================================================================
   COMPONENTS - BUTTONS
   ============================================================================= */
.mud-button {
    border-radius: 10px;
    font-weight: 600;
    letter-spacing: 0.3px;
    transition: transform var(--su-transition-base), box-shadow var(--su-transition-base);
}

.mud-icon-button {
    transition: background var(--su-transition-base);
    border-radius: var(--su-radius-round);
}

@media (hover: hover) and (pointer: fine) {
    .mud-button:hover:not(:disabled) {
        transform: translateY(-2px);
        box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
    }

    .mud-icon-button:hover {
        background: var(--su-bg-hover);
        transform: scale(1.05);
    }
}

/* Minimum 44px tap targets on mobile */
@media (max-width: 600px) {
    .mud-icon-button {
        min-width: 44px;
        min-height: 44px;
    }
}

/* =============================================================================
   COMPONENTS - MUDSWITCH VERTICAL ALIGNMENT FIX
   Root cause: the 44px tap-target rule above inflates .mud-switch-base
   (which IS a mud-icon-button) and pushes the thumb off-centre on mobile.
   Solution: carve out an exception for switches only, placed AFTER the 44px rule.
   ============================================================================= */
@media (max-width: 600px) {
    .mud-switch .mud-icon-button,
    .mud-switch .mud-button-root.mud-icon-button,
    .mud-switch .mud-switch-base {
        min-width: unset !important;
        min-height: unset !important;
        width: auto !important;
        height: auto !important;
        padding: 9px !important;
        margin: 0 !important;
        margin-top: 0 !important;
    }
}

/* Ensure label-level alignment on all screen sizes */
label.mud-switch {
    display: inline-flex !important;
    align-items: center !important;
    vertical-align: middle !important;
    margin: 0 !important;
}

/* =============================================================================
   COMPONENTS - NAVIGATION HISTORY DRAWER
   ============================================================================= */
.su-nav-history-content {
    /* Leaves room inside the drawer's 60vh ceiling for the header (~55px) and
       the drawer's own 16px padding top and bottom, so the list is the only
       thing that scrolls rather than the list and the drawer both. */
    max-height: calc(60vh - 100px);
    overflow-y: auto;
    overflow-x: hidden;
    padding-bottom: var(--su-space-md);
    scrollbar-width: thin;
    /* Was rgba(0,0,0,.2) — a black thumb on a dark surface is an invisible
       scrollbar. --border tracks the theme. */
    scrollbar-color: var(--border) transparent;
}

    .su-nav-history-content::-webkit-scrollbar {
        width: 6px;
    }

    .su-nav-history-content::-webkit-scrollbar-track {
        background: transparent;
    }

    .su-nav-history-content::-webkit-scrollbar-thumb {
        background-color: var(--border);
        border-radius: 3px;
    }

/* ── Navigation history drawer (Batch 6) ────────────────────────────────────
   The trail is a timeline: one rail, one dot per stop, newest at the top. It
   was a stack of radio circles separated by full-width dividers, which read as
   a list of choices rather than a path already walked.

   Everything is scoped under .su-navhist. The header in particular: the global
   .mud-drawer-header rule paints a primary-tinted gradient on every drawer in
   both apps, and this overrides it here only. */

/* A bottom sheet should be as tall as the trail it holds. Height was pinned at
   60vh, so four rows sat in a 540px panel with 216px of empty space under them.
   60vh is a ceiling now rather than a target, and the list inside scrolls once
   the history outgrows it. */
.su-navhist {
    height: auto !important;
    max-height: 60vh !important;
    padding-bottom: var(--su-safe-bottom);
}

.su-navhist .su-navhist-head {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 14px 16px;
    min-height: 0;
}

.su-navhist-head-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
}

.su-navhist-title {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-ui);
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
}

    .su-navhist-title .mud-icon-root {
        color: var(--primary);
    }

.su-navhist-actions {
    display: flex;
    align-items: center;
    gap: 2px;
}

    .su-navhist-actions .mud-icon-button {
        color: var(--textMut);
    }

@media (hover: hover) and (pointer: fine) {
    .su-navhist-actions .mud-icon-button:hover {
        color: var(--text);
        background: var(--hoverWash);
    }
}

/* Rows ---------------------------------------------------------------------- */

.su-navhist .su-navhist-item {
    padding: 0 !important;
    background: transparent !important;
    border-radius: var(--su-radius-md);
    margin: 0 8px;
    width: auto;
    transition: background-color 0.16s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-navhist .su-navhist-item:not(.is-current):hover {
        background: var(--hoverWash) !important;
    }
}

.su-navhist .su-navhist-item.is-current {
    background: var(--hoverWash) !important;
}

.su-navhist-row {
    display: grid;
    grid-template-columns: 22px minmax(0, 1fr) auto;
    align-items: start;
    gap: 12px;
    width: 100%;
    /* Horizontal only. The vertical padding lives on the body and the time
       instead, so the mark column can stretch the FULL height of the row —
       see the rail note below. */
    padding: 0 10px;
    font-family: var(--font-ui);
}

/* The rail: a line down the dot column, stopped short at the first and last
   stop so it does not dangle past either end of the trail.

   The mark has to stretch edge to edge for that line to be continuous. When the
   row carried the vertical padding, the mark spanned only the row's content box
   — 41px inside a 79px item — and every stop was separated by 38px of nothing.
   Consecutive items touch exactly, so a full-height mark makes the segments
   meet and the trail joins up. */
.su-navhist-mark {
    position: relative;
    width: 22px;
    align-self: stretch;
    min-height: 34px;
}

    /* --border is a divider colour: against the drawer's own background it is
       almost invisible, which left the trail reading as four unconnected rows.
       --textMut is defined to contrast with that background, so dimming it keeps
       the rail quiet without letting it disappear in either theme. */
    .su-navhist-mark::before {
        content: "";
        position: absolute;
        left: 50%;
        /* MudNavLink brings its own 8px of vertical padding, which the mark
           cannot reach: the rail stopped 8px short at both ends of every row
           and left a 16px break between one stop and the next. Bleeding the
           rail through that padding joins the segments without moving the
           dots, the text or the row height. */
        top: -8px;
        bottom: -8px;
        width: 2px;
        transform: translateX(-50%);
        background: var(--textMut);
        opacity: 0.3;
    }

/* The trail has two ends. It starts at the newest stop and finishes at the
   oldest, so the rail is cut back to the centre of the dot at each end rather
   than running on into empty space.
   20px = the body's 11px padding + half a 14px/1.35 title line. */
.su-navhist-item.is-first .su-navhist-mark::before {
    top: 20px;
}

.su-navhist-item.is-last .su-navhist-mark::before {
    bottom: calc(100% - 21px);
}

/* A stop already visited: a small solid dot, centred on the title it belongs to
   rather than on the row. It was a --surface fill ringed in --border, which on a
   --surface drawer is a circle of the background colour outlined in
   near-nothing — invisible in practice. */
.su-navhist-mark::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 16px;
    width: 9px;
    height: 9px;
    transform: translateX(-50%);
    border-radius: 50%;
    background: var(--textMut);
    opacity: 0.55;
    box-sizing: border-box;
}

/* Where you are now: larger, in the primary colour, with a halo. Size and halo
   carry the distinction as well as the colour does, so it survives being
   looked at by someone who cannot separate the two hues. */
.su-navhist-item.is-current .su-navhist-mark::after {
    top: 15px;
    width: 11px;
    height: 11px;
    background: var(--primary);
    opacity: 1;
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), 0.18);
}

.su-navhist-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    /* The row's former vertical padding. It sits here so the rail column can
       run the full height of the row without a gap at either end. */
    padding: 11px 0;
}

.su-navhist-name {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.su-navhist-item.is-current .su-navhist-name {
    color: var(--primary);
}

/* Was Color.Secondary, which is the coral accent in this theme — a URL should
   not read as a warning. */
.su-navhist-path,
.su-navhist-qs {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color: var(--textMut);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.su-navhist-path {
    font-size: 11.5px;
}

.su-navhist-qs {
    font-size: 11px;
    opacity: 0.8;
}

.su-navhist-time {
    flex: none;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
    white-space: nowrap;
    /* 11px to match the body, plus the 2px optical nudge that lines the
       timestamp up with the title rather than the cap height above it. */
    padding: 13px 0 11px;
}

@media (max-width: 600px) {
    .su-navhist-row {
        gap: 9px;
    }

    .su-navhist-time {
        font-size: 11px;
    }
}

.su-navhist-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 40px 24px;
    text-align: center;
    font-family: var(--font-ui);
    color: var(--text);
}

    .su-navhist-empty .mud-icon-root {
        color: var(--textMut);
        opacity: 0.55;
        margin-bottom: 4px;
    }

.su-navhist-empty-sub {
    font-size: 12.5px;
    color: var(--textMut);
}

/* .su-empty-state was declared here as well as under COMPONENTS - EMPTY STATE.
   Neither declaration was complete: this one carried the flex layout, the later
   one won on padding and added the colour, and what every empty state in the app
   actually got was the accidental merge of the two. They are now one rule, in
   the components section, with the same computed result. */

.mud-drawer-header {
    background: linear-gradient(135deg, rgba(var(--mud-palette-primary-rgb), 0.05) 0%, rgba(var(--mud-palette-primary-rgb), 0.02) 100%);
    border-bottom: 1px solid var(--su-border-default);
}

/* =============================================================================
   COMPONENTS - SEARCH
   ============================================================================= */
.su-search-container {
    width: 100%;
    max-width: 584px;
    margin: 0 auto;
    position: relative;
}

    .su-search-container.expanded {
        max-width: 650px;
        transition: max-width var(--su-transition-slow);
    }

.su-search-wrapper {
    border-radius: var(--su-radius-full) !important;
    overflow: visible;
    position: relative;
    background: var(--su-bg-surface);
    transition: box-shadow var(--su-transition-base);
    box-shadow: var(--su-shadow-sm) !important;
}

    .su-search-wrapper:hover {
        box-shadow: var(--su-shadow-sm) !important;
    }

.su-search-field {
    padding: 0 14px;
}

    .su-search-field .mud-input-root {
        margin-top: 0 !important;
    }

    .su-search-field .mud-input {
        font-size: var(--su-text-base);
        color: var(--su-text-primary);
        padding: 12px 0;
        font-family: "Inter", "Segoe UI", arial, sans-serif;
        background: transparent;
    }

    .su-search-field .mud-input-underline:before,
    .su-search-field .mud-input-underline:after {
        display: none !important;
    }

    .su-search-field .mud-input-adornment-start {
        color: var(--su-text-hint);
        margin-right: 13px;
    }

    .su-search-field .mud-icon-button-edge-end {
        color: var(--su-text-muted);
    }

        .su-search-field .mud-icon-button-edge-end:hover {
            color: var(--su-text-primary);
            background-color: transparent;
        }

    .su-search-field.with-end-icons .mud-input {
        padding-right: 64px;
    }

.su-search-row {
    display: flex;
    align-items: center;
    padding: 0 14px;
}

    .su-search-row .mud-input-control {
        flex: 1;
        min-width: 0;
    }

.su-category-menu {
    flex: 0 0 auto;
    min-width: 140px;
    max-width: 160px;
    height: 40px;
    font-size: 15px;
    color: var(--su-text-secondary) !important;
    background: transparent !important;
    border: none !important;
    display: flex;
    align-items: center;
    justify-content: space-between;
    text-transform: none;
    padding: 0 6px;
    overflow: hidden;
}

    .su-category-menu:hover {
        color: var(--su-text-secondary) !important;
        background: transparent !important;
    }

.su-search-divider {
    width: 1px;
    height: 26px;
    background: var(--border);
    margin: 0 4px !important;
    flex-shrink: 0;
}

.su-search-end-icons {
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    gap: 2px;
    align-items: center;
    pointer-events: auto;
    z-index: 2;
}

.su-search-icon-btn {
    color: var(--su-text-muted) !important;
    min-width: 0 !important;
    width: 50px;
    height: 50px;
    border-radius: var(--su-radius-round) !important;
}

@media (hover: hover) and (pointer: fine) {
    .su-search-icon-btn:hover {
        color: var(--su-text-primary) !important;
        background: transparent !important;
    }
}

@media (max-width: 600px) {
    .su-search-icon-btn {
        width: 44px;
        height: 44px;
    }
}

.su-search-spinner {
    width: 20px !important;
    height: 20px !important;
    margin-right: 2px;
    color: var(--su-text-primary) !important;
}

.su-search-buttons {
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: 18px;
}
.su-search-btn {
    min-height: 36px; /* was height: 36px — fixed height clipped the wrapped label */
    height: auto;
    min-width: 54px;
    padding: 0 16px;
    white-space: nowrap; /* keep "I'm Feeling Frisky" on one line */
    border-radius: var(--su-radius-sm) !important;
    font-size: 14px;
    font-family: arial, sans-serif;
    text-transform: none;
    background-color: var(--field) !important;
    color: var(--text) !important;
    border: 1px solid var(--border) !important;
}

    /* MudButton wraps its label span by default — pin it to one line too */
    .su-search-btn .mud-button-label {
        white-space: nowrap;
    }
/*.su-search-btn {
    height: 36px;
    min-width: 54px;
    padding: 0 16px;
    border-radius: var(--su-radius-sm) !important;
    font-size: 14px;
    font-family: arial, sans-serif;
    text-transform: none;
    background-color: #f8f9fa !important;
    color: #3c4043 !important;
    border: 1px solid #f8f9fa !important;
}*/

@media (hover: hover) and (pointer: fine) {
    .su-search-btn:hover {
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;
        background-color: #f8f9fa !important;
        border: 1px solid #dadce0 !important;
    }
}

.mud-progress-circular {
    color: #4285f4 !important;
}

/* Search - Mobile Responsive */
@media (max-width: 600px) {
    .su-search-container {
        max-width: calc(100% - 24px);
        margin: 0 12px;
    }

    .su-appbar .su-search-container {
        flex: 1 1 auto !important;
        width: 100% !important;
        max-width: 100% !important;
        margin: 0 !important;
    }

    .su-appbar .su-search-wrapper {
        width: 100% !important;
        border-radius: var(--su-radius-xl) !important;
        margin: 0 !important;
    }

    .su-appbar .mud-icon-button {
        margin: 0 2px !important;
    }

    .su-search-wrapper {
        border-radius: var(--su-radius-lg) !important;
    }

    .su-suggestions-dropdown.below {
        border-radius: 0 0 var(--su-radius-lg) var(--su-radius-lg) !important;
    }

    .su-suggestions-dropdown.above {
        border-radius: var(--su-radius-lg) var(--su-radius-lg) 0 0 !important;
    }
}

/* =============================================================================
   COMPONENTS - SEARCH SUGGESTIONS DROPDOWN
   ============================================================================= */
.su-suggestions-dropdown {
    position: absolute;
    left: 0;
    right: 0;
    max-height: 400px;
    overflow-y: auto;
    z-index: 1000;
    background: var(--su-bg-surface);
}

    .su-suggestions-dropdown.below {
        top: calc(100% - 1px);
        margin-top: 0;
        border-radius: 0 0 var(--su-radius-full) var(--su-radius-full) !important;
        box-shadow: 0 4px 6px rgba(32, 33, 36, 0.28) !important;
        border-top: 1px solid var(--border);
    }

    .su-suggestions-dropdown.above {
        bottom: calc(100% - 1px);
        margin-bottom: 0;
        border-radius: var(--su-radius-full) var(--su-radius-full) 0 0 !important;
        box-shadow: 0 -4px 6px rgba(32, 33, 36, 0.28) !important;
        border-bottom: 1px solid var(--border);
    }

.su-search-wrapper.open.position-top {
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

.su-search-wrapper.open.position-bottom {
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
}

.su-suggestions-list {
    display: flex;
    flex-direction: column;
}

.su-suggestion-item {
    transition: background-color 0.1s ease;
    min-height: 44px;
    cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
    .su-suggestion-item:hover {
        background-color: var(--field);
    }
}

.su-suggestion-selected {
    background-color: var(--infoSoft) !important;
}

.su-suggestion-content {
    display: flex;
    align-items: center;
    padding: 6px 14px;
    width: 100%;
}

.su-suggestion-icon {
    margin-right: 13px;
    font-size: 20px !important;
    min-width: 20px;
}

.su-suggestion-details {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.su-suggestion-text {
    font-size: var(--su-text-base);
    color: var(--su-text-primary);
    font-family: arial, sans-serif;
}

    .su-suggestion-text .highlight {
        font-weight: 600;
        background-color: transparent;
    }

.su-suggestion-header {
    background-color: var(--field) !important;
    cursor: default !important;
    padding: 4px 0 !important;
    min-height: 32px !important;
}

    .su-suggestion-header:hover {
        background-color: var(--field) !important;
    }

/* =============================================================================
   COMPONENTS - SEARCH BOX MOBILE LOGO
   ============================================================================= */
.su-search-logo-link {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px 4px 12px;
    text-decoration: none;
    flex-shrink: 0;
}

.su-search-logo {
    height: 28px;
    width: auto;
    object-fit: contain;
    display: block;
    background: transparent;
    image-rendering: -webkit-optimize-contrast;
    image-rendering: crisp-edges;
}

@media (max-width: 400px) {
    .su-search-logo {
        height: 24px;
    }

    .su-search-logo-link {
        padding: 4px 6px 4px 10px;
    }
}

.su-search-logo-link + .su-search-divider {
    height: 24px;
    width: 1px;
    background-color: var(--su-border-light, var(--border));
    margin: 0 4px;
    flex-shrink: 0;
}

@media (min-width: 960px) {
    .su-search-logo-link {
        display: none;
    }

        .su-search-logo-link + .su-search-divider {
            display: none;
        }
}

/* =============================================================================
   COMPONENTS - MOBILE EXPANDABLE SEARCH BAR
   ============================================================================= */
.su-search-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1099;
    background: transparent;
}

@media (min-width: 600px) {
    .su-search-backdrop {
        display: none;
    }
}

/* Collapsed state */
.su-mobile-search-collapsed {
    flex: 1;
    min-width: 0;
    max-width: 100%;
    margin: 0 4px !important;
    cursor: text;
}

    .su-mobile-search-collapsed .su-search-wrapper {
        pointer-events: none;
        border-radius: 24px !important;
    }

    .su-mobile-search-collapsed .su-search-container {
        width: 100%;
    }

    .su-mobile-search-collapsed .su-suggestions-dropdown {
        display: none !important;
    }

    .su-mobile-search-collapsed .su-search-field input {
        cursor: pointer;
    }

/* Expanded state
   ---------------------------------------------------------------------------
   THE CONTAINER IS THE BAR. The back arrow is a sibling of the SearchBox, so
   the only way it can sit inside the bar's border — ahead of the logo, part of
   the same control — is for the border to belong to the element that holds
   both. The SearchBox inside is therefore flattened to nothing and the panel
   is anchored out here, which also makes bar and panel exactly the same width.

   Only the chrome differs by branch. LEGACY (no .su-search-hero, which is what
   RotoOs renders) keeps the grey card it always had; the hero chrome lives with
   the rest of the Batch 1 search CSS further down, because it has to win over
   .su-search-hero's own panel rules on document order.
   -------------------------------------------------------------------------- */
.su-mobile-search-expanded {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    animation: su-search-expand 0.2s ease-out;
    padding: 0 4px 0 0;
    margin: 0 4px;
    position: relative;
}

    .su-mobile-search-expanded .su-search-container {
        width: 100%;
        position: static !important;
    }

    .su-mobile-search-expanded .su-search-wrapper {
        pointer-events: auto;
        width: 100%;
        position: static !important;
        background: transparent !important;
        box-shadow: none !important;
        border: none !important;
        border-radius: 0 !important;
    }

    .su-mobile-search-expanded .su-search-field {
        flex: 1;
    }

    .su-mobile-search-expanded .su-suggestions-dropdown {
        position: absolute !important;
        top: 100% !important;
        margin-top: 0 !important;
        z-index: 1100;
        overflow-y: auto;
    }

/* --- legacy chrome ------------------------------------------------------- */
.su-mobile-search-expanded:not(:has(> .su-search-hero)) {
    /* FIX: use CSS variable instead of hardcoded #fff */
    background: var(--su-bg-surface);
    border-radius: 28px;
    box-shadow: 0 1px 6px rgba(32, 33, 36, 0.28);
}

    .su-mobile-search-expanded:not(:has(> .su-search-hero)) .su-search-row {
        padding: 4px 8px 4px 0;
    }

    /* When suggestions are open — flatten bottom corners */
    .su-mobile-search-expanded:not(:has(> .su-search-hero)):has(.su-suggestions-dropdown),
    .su-mobile-search-expanded:not(:has(> .su-search-hero)).suggestions-open {
        border-radius: 20px 20px 0 0;
        box-shadow: 0 1px 3px rgba(32, 33, 36, 0.2);
    }

    /* Dropdown */
    .su-mobile-search-expanded:not(:has(> .su-search-hero)) .su-suggestions-dropdown {
        left: 0 !important;
        right: 0 !important;
        width: 100% !important;
        border-radius: 0 0 20px 20px !important;
        background: var(--su-bg-surface);
        box-shadow: 0 4px 6px rgba(32, 33, 36, 0.25) !important;
        border-top: 1px solid var(--border);
        max-height: 60vh;
    }

.su-search-collapse-btn {
    flex-shrink: 0;
    margin: 0 0 0 4px;
    color: var(--textMut) !important;
}

    .su-search-collapse-btn:hover {
        background-color: var(--hoverWash) !important;
    }

@keyframes su-search-expand {
    from {
        opacity: 0.8;
        transform: scaleX(0.95);
    }

    to {
        opacity: 1;
        transform: scaleX(1);
    }
}

/* Mobile-specific search states */
@media (max-width: 599px) {
    .su-mobile-search-expanded {
        margin: 0 !important;
        margin-left: -4px !important;
        margin-right: -4px !important;
    }

        .su-mobile-search-expanded:not(:has(> .su-search-hero)) {
            border-radius: 20px;
        }

        .su-mobile-search-expanded:not(:has(> .su-search-hero)):has(.su-suggestions-dropdown),
        .su-mobile-search-expanded:not(:has(> .su-search-hero)).suggestions-open {
            border-radius: 16px 16px 0 0;
        }

        .su-mobile-search-expanded:not(:has(> .su-search-hero)) .su-suggestions-dropdown {
            left: 0 !important;
            right: 0 !important;
            border-radius: 0 0 16px 16px !important;
        }

        .su-mobile-search-expanded:not(:has(> .su-search-hero)) .su-search-row {
            padding: 2px 4px 2px 0;
        }

        .su-mobile-search-expanded .su-search-end-icons {
            gap: 2px;
            padding-right: 2px;
        }

            .su-mobile-search-expanded .su-search-end-icons .mud-fab {
                display: flex;
                width: 38px;
                height: 38px;
                min-width: 38px;
                min-height: 38px;
            }

    .su-mobile-search-collapsed .su-search-row {
        min-height: 38px;
    }

    .su-mobile-search-collapsed .su-search-end-icons .mud-fab {
        display: none;
    }

    .su-search-collapse-btn {
        width: 40px;
        height: 40px;
        min-width: 40px;
    }

        .su-search-collapse-btn .mud-icon-root {
            font-size: 22px;
        }
}

/* Bottom bar logo-only variant */
.su-bottom-bar-logo-only {
    justify-content: flex-start;
    min-height: 56px;
    padding: 0 8px;
}

    .su-bottom-bar-logo-only .su-logo-link {
        display: flex;
        align-items: center;
    }

    .su-bottom-bar-logo-only .mud-spacer {
        flex: 1;
    }

/* =============================================================================
   COMPONENTS - ADS (Banner)
   ============================================================================= */
.su-ad-banner-container {
    width: 100%;
    margin: var(--su-space-lg) 0;
    display: flex;
    justify-content: center;
}

    .su-ad-banner-container.compact {
        margin: var(--su-space-sm) 0;
    }

    .su-ad-banner-container.prominent {
        margin: var(--su-space-xl) 0;
        padding: var(--su-space-lg) 0;
        background: linear-gradient(180deg, var(--hoverWash) 0%, transparent 100%);
    }

.su-ad-banner-wrapper {
    position: relative;
    width: 100%;
    max-width: 970px;
    min-height: 90px;
    background: var(--mud-palette-surface);
    border-radius: var(--su-radius-md);
    border: 1px solid var(--su-border-light);
    overflow: hidden;
}

    .su-ad-banner-wrapper.small {
        max-width: 728px;
        min-height: 90px;
    }

    .su-ad-banner-wrapper.medium {
        max-width: 970px;
        min-height: 90px;
    }

    .su-ad-banner-wrapper.large {
        max-width: 970px;
        min-height: 250px;
    }

.su-ad-disclosure {
    position: absolute;
    top: 4px;
    left: 8px;
    font-size: var(--su-text-xs);
    color: var(--su-text-secondary);
    opacity: 0.7;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    z-index: 5;
}

.su-ad-upgrade-hint {
    position: absolute;
    bottom: 4px;
    right: 8px;
    opacity: 1;
    transition: opacity var(--su-transition-base);
}

@media (max-width: 768px) {
    .su-ad-banner-wrapper {
        border-radius: 0;
        border-left: none;
        border-right: none;
    }

        .su-ad-banner-wrapper.small,
        .su-ad-banner-wrapper.medium {
            min-height: 60px;
        }
}

/* =============================================================================
   COMPONENTS - ADS (Card Style)
   ============================================================================= */
.su-ad-card {
    border-radius: var(--su-radius-lg);
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth);
    border: 1px solid var(--su-border-default);
    background-color: var(--mud-palette-surface);
    position: relative;
    overflow: hidden;
}

@media (hover: hover) and (pointer: fine) {
    .su-ad-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
    }
}

.su-ad-image-container {
    position: relative;
    width: 100%;
    min-height: clamp(200px, 30vw, 280px);
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--bg) 0%, var(--border) 100%);
}

.su-ad-label-container {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 10;
}

.su-ad-label {
    background-color: var(--surfaceAlpha) !important;
    font-size: var(--su-text-xs) !important;
    height: 24px !important;
    opacity: 0.9;
}

.su-ad-content {
    width: 100%;
    min-height: clamp(180px, 25vw, 250px);
}

.su-ad-upgrade-prompt {
    background: linear-gradient(90deg, rgba(103, 58, 183, 0.05), rgba(63, 81, 181, 0.05));
    border-top: 1px solid var(--border);
    justify-content: center;
    padding: 4px 8px;
}

/* =============================================================================
   COMPONENTS - ADS (Sticky Mobile)
   ============================================================================= */
.su-sticky-ad-container {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    align-items: center;
    background: var(--mud-palette-background);
    border-top: 1px solid var(--su-border-focus);
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
    transform: translateY(100%);
    transition: transform var(--su-transition-slow), bottom var(--su-transition-slow);
    padding-bottom: env(safe-area-inset-bottom, 0);
}

    .su-sticky-ad-container.visible {
        transform: translateY(0);
    }

.su-sticky-ad-wrapper {
    position: relative;
    padding: var(--su-space-sm);
    display: flex;
    justify-content: center;
}

.su-sticky-ad-close {
    position: absolute;
    top: 4px;
    right: 4px;
    background: rgba(0, 0, 0, 0.6);
    color: white;
    border: none;
    border-radius: var(--su-radius-round);
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 10;
    padding: 0;
}

    .su-sticky-ad-close:hover {
        background: rgba(0, 0, 0, 0.8);
    }

.su-sticky-ad-content {
    max-width: 320px;
    height: 50px;
}

.su-sticky-upgrade-bar {
    width: 100%;
    text-align: center;
    padding: 4px 8px 8px;
    background: linear-gradient(90deg, rgba(103, 58, 183, 0.05), rgba(63, 81, 181, 0.05));
}

@media (min-width: 768px) {
    .su-sticky-ad-container {
        display: none !important;
    }
}

body.has-sticky-ad {
    padding-bottom: 90px;
}

    body.has-sticky-ad.has-bottom-bar {
        padding-bottom: 150px;
    }

body.has-sticky-ad {
    padding-bottom: calc(90px + var(--su-safe-bottom));
}

/* =============================================================================
   COMPONENTS - ADS (Sidebar)
   ============================================================================= */
.su-sidebar-ad-container {
    width: 100%;
    max-width: 336px;
    margin: 0 auto;
}

.su-sidebar-ad-wrapper {
    position: relative;
    background: var(--mud-palette-surface);
    border: 1px solid var(--su-border-default);
    border-radius: var(--su-radius-md);
    overflow: hidden;
    min-height: 280px;
}

.su-sidebar-ad-disclosure {
    position: absolute;
    top: 4px;
    right: 8px;
    font-size: 9px;
    color: var(--su-text-secondary);
    opacity: 0.6;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    z-index: 5;
    background: var(--glass);
    padding: 2px 6px;
    border-radius: 3px;
}

.su-sidebar-ad-content {
    width: 100%;
    min-height: 250px;
}

.su-sidebar-upgrade-hint {
    text-align: center;
    opacity: 0.8;
}

    .su-sidebar-upgrade-hint:hover {
        opacity: 1;
    }

/* =============================================================================
   COMPONENTS - ALTERNATIVES DIALOG
   ============================================================================= */
.su-alternatives-dialog {
    border-radius: var(--su-radius-2xl);
    box-shadow: var(--su-shadow-xl);
    overflow: hidden;
}

.su-alt-card {
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth);
    cursor: pointer;
    height: 100%;
    display: flex;
    flex-direction: column;
    background-color: var(--mud-palette-surface);
}

@media (hover: hover) and (pointer: fine) {
    .su-alt-card:hover {
        transform: translateY(-5px);
        box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12);
    }
}

.su-alt-image-container {
    height: clamp(140px, 20vw, 180px);
    width: 100%;
    background: var(--imgPlate);
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
}

    .su-alt-image-container img {
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

/* Allow more lines for alternative product titles */
.su-alt-title {
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
    line-height: 1.3;
    min-height: auto;
}

.su-dialog-actions {
    padding: var(--su-space-md) clamp(1rem, 2vw, 1.25rem);
    border-top: 1px solid var(--border);
    background-color: var(--mud-palette-background);
}

@media (max-width: 600px) {
    .su-alternatives-dialog {
        margin: 4px !important;
        max-height: calc(100dvh - 8px) !important;
    }

        .su-alternatives-dialog .mud-dialog-content {
            max-height: calc(100dvh - 160px) !important;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }

        .su-alternatives-dialog .su-alt-image-container {
            height: 140px;
        }
}

/* =============================================================================
   COMPONENTS - BARCODE SCANNER
   ============================================================================= */
.su-scanner-dialog {
    min-width: 340px;
}

.su-scanner-container {
    min-height: 280px;
    position: relative;
}

.su-scanner-viewport {
    width: 100%;
    min-height: 260px;
    border-radius: var(--su-radius-md);
    overflow: hidden;
    background: #1a1a1a;
}

    .su-scanner-viewport.loading {
        display: flex;
        align-items: center;
        justify-content: center;
    }

.su-scanner-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    z-index: 10;
    color: white;
}

.su-camera-controls {
    display: flex;
    justify-content: center;
}

.su-manual-entry {
    padding: var(--su-space-sm) 0;
}

.su-barcode-preview {
    background: var(--field);
    border-radius: var(--su-radius-md);
    padding: 12px;
    text-align: center;
}

.su-barcode-display {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.su-quick-formats {
    margin-top: var(--su-space-lg);
}

.su-scanned-result {
    margin-top: 12px;
}

.su-recent-scans-list {
    max-height: 300px;
    overflow-y: auto;
}

.su-recent-scan-item {
    cursor: pointer;
    transition: background-color var(--su-transition-base);
}

    .su-recent-scan-item:hover {
        background-color: var(--su-bg-hover);
    }

/* =============================================================================
   COMPONENTS - SOCIAL LOGIN BUTTONS
   ============================================================================= */
.su-social-btn {
    border-radius: var(--su-radius-md);
    font-weight: 600;
    transition: background-color var(--su-transition-base), color var(--su-transition-base), transform var(--su-transition-base);
}

.su-social-btn-google {
    border-color: #4285f4 !important;
    color: #4285f4 !important;
}

.su-social-btn-microsoft {
    border-color: #0078d4 !important;
    color: #0078d4 !important;
}

.su-social-btn-facebook {
    border-color: #1877f2 !important;
    color: #1877f2 !important;
}

.su-social-btn-github {
    border-color: #333 !important;
    color: #333 !important;
}

.mud-theme-dark .su-social-btn-github {
    border-color: #f0f6fc !important;
    color: #f0f6fc !important;
}

@media (hover: hover) and (pointer: fine) {
    .su-social-btn:hover {
        transform: translateY(-2px);
    }

    .su-social-btn-google:hover {
        background-color: #4285f4 !important;
        color: white !important;
    }

    .su-social-btn-microsoft:hover {
        background-color: #0078d4 !important;
        color: white !important;
    }

    .su-social-btn-facebook:hover {
        background-color: #1877f2 !important;
        color: white !important;
    }

    .su-social-btn-github:hover {
        background-color: #333 !important;
        color: white !important;
    }

    .mud-theme-dark .su-social-btn-github:hover {
        background-color: #f0f6fc !important;
        color: #0d1117 !important;
    }
}

/* =============================================================================
   COMPONENTS - DIALOGS (Base)
   ============================================================================= */
.su-dialog {
    border-radius: var(--su-radius-2xl);
    background-color: var(--su-bg-surface);
    max-width: 600px;
    padding: var(--su-space-md);
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.12);
    animation: su-dialog-pop 0.25s ease;
    /* MudBlazor positions the title's close button with position:absolute and
       never gives .mud-dialog a position of its own — it relies on its own
       open animation, which is declared with fill-mode "both" and so leaves
       transform:scale(1) applied forever, making the dialog a containing
       block. Our animation shorthand above replaces that one and resets the
       fill mode, so the transform lapsed after 0.25s and the close button was
       measured against the full-viewport .mud-dialog-container instead: the X
       flew to the top-right corner of the screen, over the app bar. Say the
       containing block outright rather than depending on an animation for it. */
    position: relative;
}

@keyframes su-dialog-pop {
    0% {
        opacity: 0;
        transform: scale(0.95);
    }

    100% {
        opacity: 1;
        transform: scale(1);
    }
}

@media (max-width: 600px) {
    .mud-dialog {
        margin: 4px !important;
        max-height: calc(100dvh - 8px) !important;
        max-height: calc(100vh - 8px) !important;
    }

    .mud-dialog-content {
        padding: 12px !important;
    }
}

/* UI_12 — su-dialog becomes a bottom sheet on mobile (no floating gap below) */
@media (max-width: 600px) {
    .su-dialog.mud-dialog {
        margin: 0 !important;
        width: 100vw !important;
        max-width: 100vw !important;
        max-height: 92vh !important;
        position: fixed !important;
        bottom: 0 !important;
        top: auto !important;
        border-radius: 16px 16px 0 0 !important;
    }

    /* keep the action buttons clear of the home indicator on the bottom edge */
    .su-dialog .mud-dialog-actions {
        padding-bottom: calc(8px + env(safe-area-inset-bottom, 8px)) !important;
    }
}

/* =============================================================================
   COMPONENTS - DIALOGS (List Selection)
   ============================================================================= */
.su-dialog-section {
    border-radius: var(--su-radius-lg);
    background-color: var(--field);
    transition: all var(--su-transition-slow);
}

    .su-dialog-section:hover {
        background-color: var(--field);
    }

.su-info-alert {
    border-radius: var(--su-radius-md);
    background-color: var(--field);
}

.su-warning-alert {
    border-radius: var(--su-radius-md);
    background-color: var(--warnSoft);
}

.su-list-wrapper {
    background-color: var(--su-bg-surface);
    border-radius: var(--su-radius-md);
    /* An inset ring doing a border's job, so it takes the border token rather
       than being left with the rest of the shadows. */
    box-shadow: inset 0 0 0 1px var(--border);
}

.su-list-item {
    border-radius: var(--su-radius-md);
    padding: 0.6rem 0.75rem;
    transition: background var(--su-transition-base), transform var(--su-transition-base);
    cursor: pointer;
}

    .su-list-item:hover:not(.mud-disabled) {
        background-color: rgba(103, 126, 234, 0.05);
        transform: translateX(2px);
    }

.su-quantity-field {
    width: 90px;
    text-align: center;
}

/* =============================================================================
   COMPONENTS - DIALOGS (Auth)
   ============================================================================= */
.su-auth-dialog {
    max-width: 480px;
}

.su-auth-title {
    padding: var(--su-space-md) var(--su-space-lg) var(--su-space-sm);
}

.su-auth-icon {
    font-size: clamp(2rem, 3vw, 2.5rem);
    margin-right: var(--su-space-sm);
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
}

.su-auth-stack {
    padding: var(--su-space-lg) var(--su-space-xl) var(--su-space-xl);
    text-align: center;
}

.su-auth-btn {
    border-radius: var(--su-radius-md);
    font-weight: 600;
    min-width: 140px;
    transition: all var(--su-transition-smooth);
}

@media (hover: hover) and (pointer: fine) {
    .su-auth-btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }
}

/* =============================================================================
   COMPONENTS - DIALOGS (Filter)
   ============================================================================= */
.su-filter-dialog {
    border-radius: var(--su-radius-xl);
    overflow: hidden;
}

.su-filter-content {
    background-color: var(--field);
    border-top: 1px solid var(--border);
}

.su-filter-select .mud-input-root {
    background-color: var(--su-bg-surface);
    border-radius: var(--su-radius-md);
    transition: box-shadow var(--su-transition-base);
}

    .su-filter-select .mud-input-root:hover {
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    }

.su-filter-numeric .mud-input-root {
    border-radius: var(--su-radius-md);
    background-color: var(--su-bg-surface);
}

.su-filter-switch {
    font-size: 0.95rem;
}

.su-filter-actions {
    padding: 12px 24px;
    border-top: 1px solid var(--border);
    background-color: var(--su-bg-surface);
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* Filter dialog mobile — full height, actions always visible */
@media (max-width: 600px) {
    .su-filter-dialog {
        margin: 2px !important;
        max-height: calc(100dvh - 4px) !important;
        max-height: calc(100vh - 4px) !important;
        display: flex !important;
        flex-direction: column !important;
        border-radius: var(--su-radius-lg);
    }

        .su-filter-dialog .mud-dialog-content {
            flex: 1 1 auto !important;
            min-height: 0 !important;
            max-height: none !important;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }

        /* Actions pinned at bottom */
        /*.su-filter-dialog .mud-dialog-actions,
        .su-filter-dialog .su-filter-actions {
            flex-shrink: 0 !important;
            padding: 8px 12px !important;
            border-top: 1px solid var(--su-border-light);
            background: var(--su-bg-surface);
        }*/

        /* Actions pinned at bottom */
        .su-filter-dialog .mud-dialog-actions,
        .su-filter-dialog .su-filter-actions {
            flex-shrink: 0 !important;
            padding: 8px 12px !important;
            padding-bottom: calc(8px + env(safe-area-inset-bottom, 12px)) !important; /* ADD THIS */
            border-top: 1px solid var(--su-border-light);
            background: var(--su-bg-surface);
        }

        .su-filter-dialog .mud-dialog-title {
            flex-shrink: 0 !important;
        }

        .su-filter-dialog .mud-tabs-header {
            min-height: 40px;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch;
            flex-wrap: nowrap;
        }

        .su-filter-dialog .mud-tab {
            min-height: 40px;
            padding: 6px 12px;
            font-size: 0.8rem;
            white-space: nowrap;
            min-width: auto;
        }

        .su-filter-dialog .su-filter-content {
            padding: 8px !important;
        }

            .su-filter-dialog .su-filter-content .pa-3 {
                padding: 8px !important;
            }
}

@media (min-width: 601px) and (max-width: 959px) {
    .su-filter-dialog .mud-dialog-content {
        max-height: 80vh !important;
    }
}

/* Instant close for filter popover */
/*.su-filter-popover {
    transition-duration: 0ms !important;
}*/
/*
    .su-filter-popover.mud-popover-open-false {
        transition: none !important;
        animation: none !important;
        opacity: 0 !important;
        transform: none !important;
    }*/
/* Suppress all transitions on the filter popover — open AND close */
/*.su-filter-popover,
.su-filter-popover.mud-popover-open-true,
.su-filter-popover.mud-popover-open-false {
    transition: none !important;
    animation: none !important;
}

    .su-filter-popover.mud-popover-open-false {
        opacity: 0 !important;
        pointer-events: none !important;
    }
    .su-filter-popover .mud-popover {
        transition-duration: 0ms !important;
    }*/

/* =============================================================================
   COMPONENTS - TWO-FACTOR DIGIT INPUT
   ============================================================================= */
.su-2fa-container {
    padding: 20px 0;
    animation: su-fade-in 0.3s ease-out;
}

.su-digit-input {
    width: clamp(42px, 6vw, 50px);
    height: clamp(48px, 7vw, 50px);
    text-align: center;
    font-size: clamp(1.2rem, 2vw, 1.5rem);
    font-weight: 600;
    border: 1px solid var(--border);
    border-radius: var(--su-radius-md);
    outline: none;
    transition: border-color var(--su-transition-base), box-shadow var(--su-transition-base);
    background-color: transparent;
    color: inherit;
    margin: 0 4px;
}

    .su-digit-input:focus {
        border-color: rgba(var(--mud-palette-primary-rgb), 0.6);
        box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), 0.15);
    }

    .su-digit-input:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        background-color: var(--hoverWash);
    }

/* =============================================================================
   COMPONENTS - SESSION CARDS (Security Page)
   ============================================================================= */
.su-session-current {
    border: 2px solid var(--mud-palette-primary);
}

.su-session-online {
    border-left: 4px solid var(--mud-palette-success);
}

.su-session-idle {
    border-left: 4px solid var(--mud-palette-warning);
}

.su-session-offline {
    border-left: 4px solid var(--mud-palette-grey);
}

.su-online-indicator {
    position: absolute;
    bottom: 0;
    right: 12px;
    width: 12px;
    height: 12px;
    background-color: var(--mud-palette-success);
    border-radius: var(--su-radius-round);
    border: 2px solid white;
    animation: su-pulse 2s infinite;
}

@keyframes su-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7);
    }

    70% {
        box-shadow: 0 0 0 10px rgba(76, 175, 80, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(76, 175, 80, 0);
    }
}

/* =============================================================================
   COMPONENTS - SHARE DIALOG
   ============================================================================= */
.su-share-dialog {
    border-radius: var(--su-radius-2xl);
    overflow: hidden;
    box-shadow: var(--su-shadow-xl);
}

/* =============================================================================
   COMPONENTS - RECONNECT MODAL
   ============================================================================= */
.components-reconnect-first-attempt-visible,
.components-reconnect-repeated-attempt-visible,
.components-reconnect-failed-visible,
.components-pause-visible,
.components-resume-failed-visible,
.components-rejoining-animation {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible,
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-paused .components-pause-visible,
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible,
#components-reconnect-modal.components-reconnect-retrying,
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible,
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible {
    display: block;
}

#components-reconnect-modal {
    background-color: var(--su-bg-surface, white);
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: var(--su-radius-lg);
    box-shadow: var(--su-shadow-xl);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity 0.5s both;
}

    #components-reconnect-modal[open] {
        animation: components-reconnect-modal-slideUp 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity 0.5s ease-in-out 0.3s;
        animation-fill-mode: both;
    }

    #components-reconnect-modal::backdrop {
        background-color: rgba(0, 0, 0, 0.4);
        animation: components-reconnect-modal-fadeInOpacity 0.5s ease-in-out;
        opacity: 1;
    }

@keyframes components-reconnect-modal-slideUp {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0) scale(1);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p {
    margin: 0;
    text-align: center;
    color: var(--su-text-primary);
}

#components-reconnect-modal button {
    border: 0;
    background-color: var(--mud-palette-primary, var(--primary));
    color: white;
    padding: 8px 24px;
    border-radius: var(--su-radius-md);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--su-transition-base), transform var(--su-transition-base);
}

@media (hover: hover) and (pointer: fine) {
    #components-reconnect-modal button:hover {
        background-color: var(--mud-palette-primary-darken, var(--primaryHover));
        transform: translateY(-1px);
    }
}

#components-reconnect-modal button:active {
    transform: scale(0.98);
}

.components-rejoining-animation {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div {
        position: absolute;
        border: 3px solid var(--mud-palette-primary, var(--primary));
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2) {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0;
        left: 0;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    #components-reconnect-modal,
    #components-reconnect-modal[open],
    #components-reconnect-modal::backdrop,
    .components-rejoining-animation div {
        animation: none;
        transition: none;
    }

        #components-reconnect-modal[open] {
            opacity: 1;
        }
}

/* =============================================================================
   COMPONENTS - EMAIL VERIFICATION ALERT
   ============================================================================= */
.su-email-alert {
    margin-top: var(--su-space-md);
    border-radius: var(--su-radius-md);
}

    .su-email-alert .mud-alert-message {
        width: 100%;
    }

@media (max-width: 600px) {
    .su-email-alert,
    .su-maintenance-banner {
        margin-left: -8px;
        margin-right: -8px;
        border-radius: 0;
    }
}

/* =============================================================================
   COMPONENTS - MAINTENANCE MODE
   ============================================================================= */
.su-maintenance-banner {
    margin-bottom: var(--su-space-md);
    border-radius: var(--su-radius-md);
    animation: su-slide-down 0.3s ease-out;
}

.su-maintenance-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--su-space-sm);
    width: 100%;
}

.su-maintenance-text {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--su-space-xs);
}

.su-maintenance-meta {
    display: flex;
    align-items: center;
    gap: var(--su-space-sm);
    margin-left: auto;
}

.su-maintenance-time {
    opacity: 0.9;
    white-space: nowrap;
}

@media (max-width: 600px) {
    .su-maintenance-content {
        flex-direction: column;
        align-items: flex-start;
    }

    .su-maintenance-meta {
        margin-left: 0;
        margin-top: var(--su-space-xs);
    }

    .su-maintenance-text {
        flex-direction: column;
        align-items: flex-start;
    }

        .su-maintenance-text .ml-2 {
            margin-left: 0 !important;
        }
}

.su-maintenance-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    animation: su-fade-in 0.3s ease-out;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .su-maintenance-overlay {
        -webkit-backdrop-filter: blur(4px);
        backdrop-filter: blur(4px);
    }
}

.su-maintenance-card {
    max-width: 500px;
    width: calc(100% - 32px);
    border-radius: var(--su-radius-2xl);
    background: var(--su-bg-surface);
    animation: su-maintenance-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes su-maintenance-pop {
    0% {
        opacity: 0;
        transform: scale(0.9) translateY(20px);
    }

    100% {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}

.su-maintenance-indicator {
    display: flex;
    align-items: center;
    gap: var(--su-space-xs);
    padding: 4px 12px;
    background: rgba(255, 152, 0, 0.15);
    border-radius: var(--su-radius-full);
    font-size: var(--su-text-sm);
    color: var(--warnStrong);
    font-weight: 600;
}

    .su-maintenance-indicator .mud-icon-root {
        font-size: 16px;
    }

.su-maintenance-dot {
    width: 8px;
    height: 8px;
    background-color: var(--warnStrong);
    border-radius: 50%;
    animation: su-maintenance-pulse 1.5s ease-in-out infinite;
}

@keyframes su-maintenance-pulse {
    0%, 100% {
        opacity: 1;
        transform: scale(1);
    }

    50% {
        opacity: 0.5;
        transform: scale(1.2);
    }
}

.su-maintenance-progress {
    width: 100%;
    max-width: 300px;
    margin: var(--su-space-lg) auto;
}

.su-maintenance-progress-text {
    text-align: center;
    margin-top: var(--su-space-sm);
    font-size: var(--su-text-sm);
    color: var(--su-text-secondary);
}

/* =============================================================================
   COMPONENTS - FLOATING BACK BUTTON (consolidated single definition)
   ============================================================================= */
.su-floating-back-btn {
    position: fixed;
    bottom: 24px;
    left: 24px;
    z-index: 1350;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth), bottom var(--su-transition-slow), opacity var(--su-transition-smooth);
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) and (pointer: fine) {
    .su-floating-back-btn:hover {
        transform: scale(1.08) translateY(-2px);
        box-shadow: var(--su-shadow-elevated);
    }
}

.su-floating-back-btn:active {
    transform: scale(0.95);
}

/* While the history sheet is open the button has nothing left to do: the sheet
   lists every destination it could go back to and carries its own close button.
   Leaving it on screen also put a live navigation control above the sheet
   (z-index 1350 against 1200) and above the modal overlay behind it (1199),
   where it covered whichever row happened to scroll under it.

   After :hover and :active deliberately — all three selectors have the same
   specificity, so source order is what decides, and this one has to win. */
.su-floating-back-btn.is-sheet-open {
    opacity: 0;
    transform: scale(0.85);
    pointer-events: none;
}

/* Mobile < 600px */
@media (max-width: 599px) {
    .su-floating-back-btn {
        bottom: 20px;
        left: 16px;
        width: 44px;
        height: 44px;
    }

        .su-floating-back-btn.with-bottom-bar {
            bottom: 76px;
        }

    body.has-sticky-ad .su-floating-back-btn:not(.with-bottom-bar) {
        bottom: 110px;
    }

    body.has-sticky-ad .su-floating-back-btn.with-bottom-bar {
        bottom: 180px;
    }
}

/* Tablet 600–959px (bottom bar still visible) */
@media (min-width: 600px) and (max-width: 959px) {
    .su-floating-back-btn.with-bottom-bar {
        bottom: 88px;
    }

    body.has-sticky-ad .su-floating-back-btn:not(.with-bottom-bar) {
        bottom: 110px;
    }

    body.has-sticky-ad .su-floating-back-btn.with-bottom-bar {
        bottom: 180px;
    }
}

/* Desktop 960px+ — standard position, no bottom bar */
@media (min-width: 960px) {
    .su-floating-back-btn,
    .su-floating-back-btn.with-bottom-bar {
        bottom: 24px;
        left: 24px;
    }
}

/* MAUI safe area */
body.is-hybrid .su-floating-back-btn {
    bottom: calc(24px + var(--su-safe-bottom));
}

@media (max-width: 599px) {
    body.is-hybrid .su-floating-back-btn {
        bottom: calc(20px + var(--su-safe-bottom));
    }

        body.is-hybrid .su-floating-back-btn.with-bottom-bar {
            bottom: calc(76px + var(--su-safe-bottom));
        }
}

/* =============================================================================
   COMPONENTS - STICKY FILTER HEADER (consolidated single definition)
   ============================================================================= */
.su-sticky-filter-header {
    position: sticky !important;
    /* Sits just below the fixed app bar */
    top: calc(80px + var(--su-safe-top, 0px)) !important;
    z-index: 100 !important;
    animation: none !important;
    transform: none !important;
    will-change: auto !important;
    background: var(--su-bg-primary);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    padding: 8px !important;
    margin: 0 !important;
    transition: box-shadow var(--su-transition-base);
}

    .su-sticky-filter-header::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 1px;
        background: var(--su-border-light);
    }

    .su-sticky-filter-header.pt-8 {
        padding-top: 8px !important;
    }

/* On mobile: disable sticky — too tall when email alerts are showing */
@media (max-width: 599.98px) {
    .su-sticky-filter-header {
        position: sticky !important;
        top: calc(60px + var(--su-safe-top, 0px)) !important;
        /* top: auto !important;*/
        z-index: 100 !important;
        max-height: 45vh;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
}

@media (min-width: 600px) and (max-width: 959px) {
    .su-sticky-filter-header {
        top: calc(52px + var(--su-safe-top, 0px)) !important;
        padding: 6px 8px !important;
        -webkit-backdrop-filter: blur(10px);
        backdrop-filter: blur(10px);
        background: rgba(244, 247, 250, 0.95);
    }
}

/* =============================================================================
   COMPONENTS - BILLING HIGHLIGHT
   ============================================================================= */
.su-billing-highlight {
    background: rgba(var(--mud-palette-primary-rgb), 0.04);
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.18);
    border-radius: var(--su-radius-lg);
    padding: var(--su-space-md) var(--su-space-lg);
    transition: border-color var(--su-transition-base);
}

.su-billing-value {
    font-weight: 800;
    letter-spacing: -0.3px;
}

.su-billing-note {
    color: var(--su-text-muted);
    margin-top: 4px;
}

/* =============================================================================
   MUDBLAZOR OVERRIDES
   ============================================================================= */
.mud-chip {
    font-weight: 600;
    border-radius: 6px;
}

    .mud-chip.mud-chip-size-small {
        height: 28px;
        font-size: 0.8125rem;
    }

.mud-skeleton {
    border-radius: 6px;
}

.mud-tabs {
    border-radius: var(--su-radius-md);
    background-color: var(--mud-palette-surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

    .mud-tabs .mud-tab {
        min-width: 100px;
    }

.mud-tabpanel {
    padding-top: var(--su-space-sm);
}

.mud-collapse {
    background: var(--mud-palette-surface);
    border-radius: var(--su-radius-md);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
    padding: var(--su-space-md);
}

.mud-fab {
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth);
}

    .mud-fab:hover {
        transform: scale(1.08);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
    }

.mud-alert {
    border-radius: var(--su-radius-md);
    font-size: 0.85rem;
}

.mud-dialog {
    border-radius: 14px;
}

    .mud-dialog .mud-textfield {
        margin-bottom: 0.75rem;
    }

.mud-dialog-content {
    max-height: 70vh;
    overflow-y: auto;
}

.mud-autocomplete-popover {
    margin-top: 8px;
    border-radius: var(--su-radius-lg);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
}

.mud-simple-table {
    border-radius: var(--su-radius-md);
    overflow: hidden;
}

    .mud-simple-table td {
        padding: 6px 8px;
        vertical-align: middle;
    }

.mud-table {
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    background-color: var(--su-bg-surface);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

    .mud-table th {
        font-weight: 600;
        background-color: rgba(var(--mud-palette-primary-rgb), 0.05);
    }

    .mud-table tr:hover td {
        background-color: rgba(var(--mud-palette-primary-rgb), 0.03);
    }

.mud-expansionpanel {
    border-radius: 10px;
    overflow: hidden;
}

    .mud-expansionpanel:not(:last-child) {
        margin-bottom: 6px;
    }

    .mud-expansionpanel .mud-expansionpanel-header {
        background: var(--mud-palette-background-grey);
        border-bottom: 1px solid var(--border);
    }

@media (max-width: 600px) {
    .mud-expansionpanel .mud-expansionpanel-header {
        padding: 8px 12px;
    }

    .mud-expansionpanel .mud-expansionpanel-content {
        padding: 8px 12px;
    }
}

.mud-radio-group {
    gap: 12px;
}

.mud-radio {
    margin: 8px 0;
}

.mud-select {
    margin-bottom: 8px;
}

.mud-button .mud-chip {
    margin-left: 8px;
    height: 20px;
    padding: 0 6px;
}

/* MudDialogFullscreen sizing */
@media (max-width: 960px) {
    .mud-dialog-fullscreen {
        width: 93vw !important;
        height: 90vh !important;
        max-width: 93vw !important;
        max-height: 90vh !important;
    }
}

@media (min-width: 960px) {
    .mud-dialog-fullscreen {
        width: 80vw !important;
        height: 80vh !important;
        max-width: 80vw !important;
        max-height: 80vh !important;
    }
}

/* Browser autofill label fix */
input:-webkit-autofill ~ label.mud-input-label,
input:-webkit-autofill ~ .mud-input-label {
    transform: translateY(-1.5rem) scale(0.75) !important;
    transform-origin: top left;
}

.mud-input-outlined input:-webkit-autofill ~ .mud-input-label-outlined,
.mud-input-outlined input:-webkit-autofill ~ label {
    transform: translateY(-1.5rem) scale(0.75) !important;
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 1000px var(--mud-palette-surface) inset !important;
    -webkit-text-fill-color: var(--mud-palette-text-primary) !important;
    transition: background-color 5000s ease-in-out 0s;
}

/* MudSwitch fix for mobile — see above for full explanation */
/* (Rule is placed earlier in this file, after the 44px tap-target rule) */

/* =============================================================================
   PAGES - BASE AUTH/ACCOUNT PAGE LAYOUT
   ============================================================================= */
.su-auth-page {
    min-height: 80vh;
    min-height: 80dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: clamp(1rem, 3vw, 2rem) var(--su-space-md);
    animation: su-fade-in 0.4s ease-in-out;
}

.su-account-page {
    min-height: 100vh;
    min-height: 100dvh;
    padding: clamp(1rem, 3vw, 2rem) var(--su-space-md) clamp(2rem, 5vw, 4rem);
    animation: su-fade-in 0.4s ease-in-out;
}

/* =============================================================================
   PAGES - HERO HEADER
   ============================================================================= */
.su-hero-header {
    text-align: center;
    margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
    animation: su-fade-in 0.4s ease-in-out 0.05s both;
}

.su-hero-icon {
    font-size: clamp(2.5rem, 4vw, 3rem);
    color: var(--mud-palette-primary);
    margin-bottom: var(--su-space-sm);
}

.su-hero-title {
    font-weight: 800;
    color: var(--mud-palette-primary);
    letter-spacing: 0.3px;
}

.su-hero-subtitle {
    color: var(--mud-palette-text-secondary);
}

/* =============================================================================
   PAGES - CARDS
   ============================================================================= */
.su-page-card {
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-2xl);
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.08);
    padding: clamp(1.5rem, 4vw, 3rem) clamp(1.5rem, 4vw, 2.5rem);
    width: 100%;
    max-width: 520px;
    animation: su-fade-in 0.5s ease-in-out 0.1s both;
}

    .su-page-card.wide {
        max-width: 800px;
    }

.su-section-card {
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-2xl);
    box-shadow: 0 6px 28px rgba(0, 0, 0, 0.08);
    padding: clamp(1.25rem, 3vw, 2rem);
    margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
    animation: su-fade-in 0.3s ease-in-out;
}

.su-section-title {
    font-weight: 700;
    color: var(--mud-palette-primary);
    margin-bottom: var(--su-space-md);
}

/* =============================================================================
   PAGES - ACCESS DENIED HEADER
   ============================================================================= */
.su-access-header {
    /* Was a saturated red gradient carrying diagonal stripes on a 20s infinite
       loop. Being told you lack permission is a routine outcome, usually just
       "sign in" or "upgrade" — an alarm-coloured banner overstates it, and a
       perpetual animation is CPU spent on every device to say nothing. It also
       ran with no prefers-reduced-motion guard.

       Soft error tint instead, which is the .err treatment in
       cuugo-states-preview.html: tinted surface, tone-matched text, no fill. */
    background: var(--errSoft);
    padding: clamp(2rem, 4vw, 3rem) clamp(1.5rem, 3vw, 2rem);
    text-align: center;
    color: var(--errText);
    border-top-left-radius: var(--su-radius-2xl);
    border-top-right-radius: var(--su-radius-2xl);
}

.su-access-icon {
    font-size: clamp(3rem, 5vw, 4rem) !important;
    color: var(--errText);
}

.su-access-title {
    font-weight: 800;
    color: var(--errText);
}

.su-access-subtitle {
    /* Tone-matched rather than a second colour: same ink, less weight. */
    color: var(--errText);
    opacity: .82;
    font-weight: 500;
}

.su-tip-card {
    margin-top: var(--su-space-lg);
    border-radius: var(--su-radius-xl);
    background: var(--su-bg-surface);
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.05);
    padding: var(--su-space-lg);
    max-width: 800px;
    width: 100%;
}

.su-current-row {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
}

/* =============================================================================
   PAGES - FOOTER
   ============================================================================= */
.su-page-footer {
    flex-shrink: 0;
    text-align: center;
    color: var(--mud-palette-text-secondary);
    font-size: var(--su-text-sm);
    padding: var(--su-space-lg) var(--su-space-md);
    margin-top: clamp(1.5rem, 3vw, 2rem);
    border-top: 1px solid var(--su-border-light);
    background: var(--su-bg-primary);
}

    .su-page-footer a {
        color: var(--mud-palette-primary);
        font-weight: 600;
        text-decoration: none;
    }

/* =============================================================================
   PAGES - HOME PAGE
   ============================================================================= */
.su-home {
    min-height: calc(100vh - 64px);
    min-height: calc(100dvh - 64px);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding-top: clamp(6vh, 10vh, 14vh); /* was clamp(12vh, 18vh, 22vh) */
    padding-bottom: var(--su-space-lg);
    padding-left: var(--su-space-md);
    padding-right: var(--su-space-md);
}

@media (max-width: 600px) {
    .su-home {
        padding-top: clamp(4vh, 7vh, 10vh); /* was clamp(8vh, 12vh, 15vh) */
        min-height: calc(100vh - 56px);
        min-height: calc(100dvh - 56px);
        padding-left: 12px;
        padding-right: 12px;
    }
}

@media (min-width: 601px) and (max-width: 960px) {
    .su-home {
        padding-top: clamp(5vh, 8vh, 12vh); /* was clamp(10vh, 15vh, 18vh) */
    }
}

.su-home-logo-container {
    margin-bottom: 0.75rem; /* was: clamp(1rem, 2.5vw, 1.5rem) */
    animation: su-float 3s ease-in-out infinite;
}

.su-home-logo {
    width: clamp(180px, 35vw, 272px);
    max-width: 80%;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

/* The full wordmark (CuugoLogo.png) has near-black "c" and "go" glyphs baked
   into the raster, so on a dark background most of the brand disappears.
   --logoFilter is "none" in light and invert+hue-rotate in dark, which flips
   lightness while keeping the teal and coral recognisable.

   Matched on the FILE, not on a container: the same asset is used by the Home
   hero and by the desktop app bar, while the compact search-bar mark
   (CuugoSearchBarLogo.png) is coral-and-teal with no black and must not be
   inverted. Targeting the src is the only selector that separates them.

   Stopgap. The real fix is an SVG wordmark with token fills, which belongs with
   the Home hero in Batch 1 — see DEVIATIONS D12. */
img[src*="CuugoLogo"] {
    filter: var(--logoFilter, none);
}

@keyframes su-float {
    0%, 100% {
        transform: translateY(0px);
    }

    50% {
        transform: translateY(-10px);
    }
}

.su-trending-list {
    flex-wrap: wrap;
    max-width: 584px;
    gap: 6px;
}

.su-trending-chip {
    cursor: pointer;
    font-weight: 500;
    height: 30px;
    font-size: 0.8rem;
    transition: all var(--su-transition-smooth);
    background-color: var(--field);
}

@media (max-width: 600px) {
    .su-trending-chip {
        height: 26px;
        font-size: 0.75rem;
        padding: 0 10px;
    }
}

@media (hover: hover) and (pointer: fine) {
    .su-trending-chip:hover {
        transform: translateY(-3px);
        background-color: var(--field);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        color: var(--primary);
    }
}

/* =============================================================================
   PAGES - SUBSCRIPTION / PRICING
   ============================================================================= */
.su-subscription-wrapper {
    animation: su-fade-in 0.35s ease-in-out both;
    padding-bottom: clamp(2rem, 4vw, 3rem);
}

.su-current-plan-card {
    border-radius: var(--su-radius-xl);
    border: 1px solid var(--border);
    background: var(--su-bg-surface);
    transition: all var(--su-transition-smooth);
    padding: var(--su-space-lg);
}

@media (hover: hover) and (pointer: fine) {
    .su-current-plan-card:hover {
        transform: translateY(-4px);
        box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
        border-color: rgba(var(--mud-palette-primary-rgb), 0.25);
    }
}

.su-plans-grid .mud-item {
    display: flex;
}

.su-plan-card {
    position: relative;
    border-radius: var(--su-radius-xl);
    border: 1px solid var(--border);
    background: var(--su-bg-surface);
    width: 100%;
    transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-plan-card:hover {
        transform: translateY(-6px);
        box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12);
        border-color: rgba(var(--mud-palette-primary-rgb), 0.28);
    }
}

.su-plan-card.recommended {
    border: 2px solid rgba(var(--mud-palette-primary-rgb), 0.55);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.10);
}

.su-ribbon {
    /* Was absolutely positioned over the card's top-right corner, where it sat
       on top of the plan name -- "Cuugo Ultimate" rendered as "Cuugo Ul".
       In normal flow it cannot collide with the title however long the name is.
       Shared with ManageUserSubscriptions, which had the same collision. */
    display: inline-flex;
    align-self: flex-start;
    margin: 14px 0 -6px 20px;
    background: var(--primary);
    color: var(--onPrimary);
    font-size: 0.75rem;
    font-weight: 700;
    padding: 5px 12px;
    border-radius: 999px;
    align-items: center;
    gap: 6px;
    letter-spacing: 0.3px;
}

    .su-ribbon .mud-icon-root {
        opacity: 0.95;
    }

.su-plan-name {
    font-weight: 800;
}

.su-price-line {
    font-weight: 800;
}

    .su-price-line sub {
        font-weight: 600;
        font-size: 0.75rem;
        color: var(--mud-palette-text-secondary);
        margin-left: 2px;
    }

.su-plan-divider {
    margin: 12px 0 16px 0;
}

.su-plan-features .mud-list {
    background: transparent;
}

.su-plan-features .mud-list-item {
    border-radius: var(--su-radius-md);
    padding: 6px 10px;
    transition: background-color 0.18s ease;
}

    .su-plan-features .mud-list-item:hover {
        background: rgba(var(--mud-palette-primary-rgb), 0.05);
    }

.su-cta-btn {
    border-radius: var(--su-radius-lg);
    font-weight: 700;
    letter-spacing: 0.3px;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-cta-btn:hover:not(:disabled) {
        transform: translateY(-2px);
        box-shadow: 0 10px 20px rgba(0, 0, 0, 0.12);
    }
}

/* =============================================================================
   PAGES - ONBOARDING
   ============================================================================= */
.su-onboarding {
    padding-top: clamp(32px, 6vw, 64px);
    padding-bottom: clamp(32px, 6vw, 64px);
}

@media (max-width: 900px) {
    .su-onboarding {
        padding-top: 32px;
        padding-bottom: 48px;
    }
}

.su-onb-header {
    display: grid;
    gap: var(--su-space-sm);
    justify-items: center;
    text-align: center;
    margin-bottom: 24px;
}

.su-onb-subtitle {
    color: var(--mud-palette-text-secondary);
    max-width: 720px;
}

.su-onb-card {
    border-radius: 14px;
    border: 1px solid var(--border);
}

.su-onb-hero {
    border-radius: var(--su-radius-xl);
    padding: 12px 16px;
}

.su-onb-divider {
    height: 1px;
    background: var(--hoverWash);
    margin: 12px 0;
}

.su-pulse {
    animation: su-pulse-scale 2s infinite;
}

@keyframes su-pulse-scale {
    0% {
        transform: translateZ(0) scale(1);
    }

    50% {
        transform: translateZ(0) scale(1.02);
    }

    100% {
        transform: translateZ(0) scale(1);
    }
}

/* =============================================================================
   PAGES - ADMIN
   ============================================================================= */
.su-admin-container {
    padding-top: var(--su-space-md);
    padding-bottom: clamp(2rem, 5vw, 4rem);
}

.su-admin-header {
    background: linear-gradient(90deg, var(--field) 0%, var(--surface) 100%);
    border-radius: var(--su-radius-lg);
    padding: var(--su-space-lg) clamp(1.25rem, 2vw, 1.75rem);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
}

.su-admin-card {
    background-color: var(--su-bg-surface);
    border-radius: var(--su-radius-lg);
    padding: var(--su-space-lg);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}

.su-stat-card {
    transition: transform var(--su-transition-base), box-shadow var(--su-transition-base);
}

@media (hover: hover) and (pointer: fine) {
    .su-stat-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
    }
}

.su-admin-tabs {
    margin-top: var(--su-space-md);
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    background-color: var(--su-bg-surface);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.su-tab-panel {
    padding: var(--su-space-lg);
    background-color: var(--su-bg-surface);
}

.su-admin-table {
    border-radius: var(--su-radius-md);
    overflow: hidden;
}

/* -----------------------------------------------------------------------------
   ADMIN DENSITY

   Applied by the layout to /admin routes only (`su-is-admin` on the content
   area). Admin tables carry far more columns than any storefront table — the
   users grid has eight — and MudBlazor's default cell padding put the Actions
   column past the right edge of the content area, so the buttons that open the
   edit dialogs could not be clicked without horizontal scrolling.

   The bigger half of that fix is the category rail no longer opening on admin
   (SharedLayout). This closes the remaining ~60px, and matches what
   DESIGN-BATCHES asks of admin anyway: "denser spacing, smaller scale".
   -------------------------------------------------------------------------- */
.su-is-admin .mud-table-dense .mud-table-cell {
    padding-left: 8px;
    padding-right: 8px;
}

/* Row actions are icon buttons; they do not need the default 8px gutter each
   and they are what runs out of room first. */
.su-is-admin .mud-table-cell .mud-icon-button {
    padding: 5px;
}

/* -----------------------------------------------------------------------------
   ADMIN OPS (Batch 7)

   Admin is a working surface, not a shopfront: DESIGN-BATCHES asks for "denser
   spacing, smaller scale, no seasonal art". Everything below runs one step
   tighter and one step smaller than the customer-facing equivalents, and none of
   it uses --accent, --heroA or any other token that moves with the season.

   THEMES.md rule 7 already forces /admin to render the Default palette, so these
   only ever resolve against Default light or Default dark.
   -------------------------------------------------------------------------- */
.su-adm {
    font-size: 13.5px;
    line-height: 1.5;
}

.su-adm-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.su-adm-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: -0.02em;
    margin: 0;
}

.su-adm-sub {
    font-size: 12.5px;
    color: var(--textMut);
    margin: 2px 0 0;
    flex-basis: 100%;
}

.su-adm-grow {
    flex: 1;
}

/* --- KPI strip ------------------------------------------------------------ */
.su-adm-kpis {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-bottom: 16px;
}

.su-adm-kpis.is-three {
    grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 860px) {
    .su-adm-kpis,
    .su-adm-kpis.is-three {
        grid-template-columns: repeat(2, 1fr);
    }
}

.su-adm-kpi {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 11px 14px;
    min-width: 0;
}

.su-adm-kpi .k {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-adm-kpi .v {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 20px;
    letter-spacing: -0.02em;
    margin-top: 1px;
    /* Every KPI is a number that gets watched over time; proportional digits
       make the value jitter horizontally as it ticks. */
    font-variant-numeric: tabular-nums;
}

.su-adm-kpi .v.ok {
    color: var(--savings);
}

.su-adm-kpi .v.warn {
    color: var(--warnText);
}

/* The preview reaches for --accentText here. Accent is a seasonal colour and is
   green in several Cuugo palettes, so a failure count would have matched the
   healthy one -- the same trap as DEVIATIONS D53/D98. Errors take the error
   ramp, which is fixed across every theme. */
.su-adm-kpi .v.err {
    color: var(--errText);
}

.su-adm-kpi .s {
    font-size: 11px;
    color: var(--textMut);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- row groups (scrapers, posts) ----------------------------------------- */
.su-adm-rows {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    overflow: hidden;
    margin-bottom: 14px;
}

/* Fractional rather than the preview's fixed pixel columns. Admin renders
   inside the same shell as the storefront -- nav drawer on the left, category
   rail on the right -- so the md=9 column is around 680px, not the preview's
   1180px. Fixed columns overflowed it and clipped the last header. minmax(0,…)
   on the flexible column stops long category names widening the track. */
.su-adm-row {
    display: grid;
    gap: 12px;
    align-items: center;
    padding: 11px 16px;
    border-top: 1px solid var(--border);
    font-size: 13px;
    grid-template-columns: minmax(90px, 1.3fr) 104px minmax(0, 2.2fr) minmax(0, 1fr) 78px;
}

.su-adm-row > * {
    min-width: 0;
}

.su-adm-row:first-child {
    border-top: none;
}

.su-adm-row.is-head {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--textMut);
    background: var(--rowBg2);
    padding: 8px 16px;
}

/* Hover, no zebra -- DESIGN-BATCHES is explicit about this for the blog table,
   and the scraper rows read the same way. */
.su-adm-row:not(.is-head):hover {
    background: var(--hoverWash);
}

.su-adm-row .su-adm-end {
    display: flex;
    gap: 6px;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.su-adm-row.is-head .su-adm-end {
    display: block;
    text-align: right;
}

@media (max-width: 860px) {
    .su-adm-row {
        grid-template-columns: 1fr 110px;
        row-gap: 6px;
    }

    .su-adm-row .hide-m {
        display: none;
    }
}

.su-adm-name {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 700;
    min-width: 0;
}

/* Store brand dot. The one place hard rule 8 allows a fixed colour, and it is
   still not written here: the value comes from --store-{name}, generated from
   the StoreColor attribute on the enum. */
.su-adm-sq {
    width: 9px;
    height: 9px;
    border-radius: 3px;
    flex: none;
    background: var(--textMut);
}

/* --- status chip ---------------------------------------------------------- */
.su-adm-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    font-weight: 800;
    border-radius: 999px;
    padding: 4px 10px;
    white-space: nowrap;
    background: var(--field);
    color: var(--textMut);
}

.su-adm-chip .pulse {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: none;
    background: currentColor;
}

/* Only the live states animate. A finished or idle row that pulsed would say
   "something is happening here" when nothing is. */
.su-adm-chip.is-running .pulse,
.su-adm-live .pulse {
    animation: su-adm-pulse 1.2s infinite;
}

@keyframes su-adm-pulse {
    50% {
        opacity: .35;
    }
}

.su-adm-chip.is-running {
    background: var(--okSoft);
    color: var(--savings);
}

.su-adm-chip.is-ok {
    background: var(--okSoft);
    color: var(--okText);
}

.su-adm-chip.is-failed {
    background: var(--errSoft);
    color: var(--errText);
}

.su-adm-chip.is-warn {
    background: var(--warnSoft);
    color: var(--warnText);
}

.su-adm-chip.is-info {
    background: var(--infoSoft);
    color: var(--infoText);
}

/* Archived. Quieter than draft rather than louder: an outline on no fill reads
   as "put away" where a second filled neutral chip would just look like a
   different kind of draft. */
.su-adm-chip.is-outline {
    background: transparent;
    border: 1px solid var(--border);
    padding: 3px 9px;
}

.su-adm-chip.is-outline .pulse {
    display: none;
}

/* --- progress ------------------------------------------------------------- */
.su-adm-prog {
    display: block;
    height: 6px;
    border-radius: 4px;
    background: var(--field);
    overflow: hidden;
}

.su-adm-prog i {
    display: block;
    height: 100%;
    border-radius: 4px;
    background: var(--primary);
    transition: width .3s ease;
}

.su-adm-prog i.is-bad {
    background: var(--errStrong);
}

.su-adm-prog-lab {
    display: block;
    font-size: 11px;
    color: var(--textMut);
    margin-top: 3px;
    font-variant-numeric: tabular-nums;
}

.su-adm-last {
    font-size: 12px;
    color: var(--textMut);
    min-width: 0;
}

.su-adm-last b {
    color: var(--text);
    font-weight: 700;
}

/* --- streaming log panel -------------------------------------------------- */
.su-adm-log {
    background: var(--logBg);
    border: 1px solid var(--border);
    border-radius: 14px;
    overflow: hidden;
    margin-bottom: 14px;
}

.su-adm-log-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-adm-live {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--savings);
}

.su-adm-live .pulse {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.su-adm-log-body {
    padding: 10px 14px;
    font-family: var(--font-mono);
    font-size: 11.5px;
    line-height: 1.75;
    color: var(--logText);
    overflow: auto;
    /* The virtualised message lists need a fixed height to scroll inside. */
    height: 300px;
}

.su-adm-log-body.is-short {
    height: 180px;
}

/* An empty console does not need to reserve its scroll height. Three of these
   stacked -- activity, post-processing, errors -- put 700px of black on an idle
   page, which is most of a screen saying nothing. */
.su-adm-log-body.is-empty {
    height: auto;
}

.su-adm-line {
    display: flex;
    gap: 8px;
    align-items: baseline;
}

.su-adm-line .t {
    color: var(--logMut);
    flex: none;
    font-variant-numeric: tabular-nums;
}

.su-adm-line .src {
    flex: none;
    font-weight: 600;
}

.su-adm-line .msg {
    min-width: 0;
    word-break: break-word;
}

/* Severity in the log. Matches the shared ramps everywhere else in the app, so
   a WARN here is the same amber as a warning snackbar. */
.su-adm-sev-success {
    color: var(--savings);
}

.su-adm-sev-info {
    color: var(--infoText);
}

.su-adm-sev-warning {
    color: var(--warnText);
}

.su-adm-sev-error,
.su-adm-sev-critical {
    color: var(--errText);
}

.su-adm-sev-critical {
    font-weight: 700;
}

/* --- quiet placeholder inside a panel ------------------------------------- */
.su-adm-quiet {
    padding: 18px 4px;
    text-align: center;
    font-size: 12.5px;
    color: var(--textMut);
}

.su-adm-quiet.on-log {
    color: var(--logMut);
}

/* --- key/value status list ------------------------------------------------ */
.su-adm-kv {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 12px;
    align-items: center;
    font-size: 12.5px;
}

.su-adm-kv dt {
    color: var(--textMut);
    margin: 0;
}

.su-adm-kv dd {
    margin: 0;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* --- blog workflow table -------------------------------------------------- */
.su-adm-row.is-posts {
    grid-template-columns: minmax(0, 2.6fr) 132px 64px minmax(0, 1fr) 148px;
}

@media (max-width: 860px) {
    .su-adm-row.is-posts {
        grid-template-columns: 1fr 132px;
    }
}

.su-adm-ttl {
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-adm-tsub {
    font-size: 11.5px;
    color: var(--textMut);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-adm-num {
    font-variant-numeric: tabular-nums;
    color: var(--textMut);
    font-size: 12.5px;
}

/* --- search analytics panels ---------------------------------------------- */
.su-adm-an-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
}

@media (max-width: 860px) {
    .su-adm-an-grid {
        grid-template-columns: 1fr;
    }
}

/* The generic admin panel. The analytics columns and the scraping config both
   sit in one, so it is not named after either. */
.su-adm-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 15px 17px;
    min-width: 0;
    margin-bottom: 14px;
}

.su-adm-panel h3 {
    font-weight: 800;
    font-size: 13.5px;
    margin: 0 0 11px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.su-adm-panel hr {
    border: none;
    border-top: 1px solid var(--border);
    margin: 14px 0;
}

.su-adm-anrow {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    font-size: 12.5px;
    border-top: 1px solid var(--border);
}

.su-adm-anrow:first-of-type {
    border-top: none;
}

.su-adm-anrow .q {
    flex: 1;
    font-weight: 600;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-adm-anrow .bar {
    flex: 2;
    height: 7px;
    border-radius: 4px;
    background: var(--field);
    overflow: hidden;
}

.su-adm-anrow .bar i {
    display: block;
    height: 100%;
    border-radius: 4px;
    background: var(--primary);
}

/* A zero-result query is a failure, so its bar takes the error ramp rather than
   the preview's --accent -- see the KPI note above. */
.su-adm-anrow.is-bad .bar i {
    background: var(--errStrong);
}

.su-adm-anrow .n {
    font-variant-numeric: tabular-nums;
    color: var(--textMut);
    min-width: 44px;
    text-align: right;
    font-size: 12px;
    flex: none;
}

/* =============================================================================
   COMPONENTS - PRODUCT CARDS
   ============================================================================= */
.su-product-card {
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    border: 1px solid var(--su-border-light);
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth);
    background-color: var(--mud-palette-surface);
    height: 100%;
    min-height: auto;
    display: flex;
    flex-direction: column;
    position: relative;
}

@media (hover: hover) and (pointer: fine) {
    .su-product-card:hover {
        transform: translateY(-5px);
        box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
    }
}

.su-product-card.has-unavailable-price {
    border-left: 3px solid var(--warnStrong);
}

.su-product-card.out-of-stock {
    opacity: 0.85;
}

.su-product-image-container {
    position: relative;
    width: 100%;
    height: clamp(180px, 25vw, 250px);
    overflow: hidden;
    background-color: var(--imgPlate);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-bottom: 1px solid var(--border);
}

    .su-product-image-container img {
        width: 100%;
        height: 100%;
        object-fit: contain;
        transition: transform var(--su-transition-slow);
    }

@media (hover: hover) and (pointer: fine) {
    .su-product-card:hover .su-product-image-container img {
        transform: scale(1.05);
    }
}

.su-product-card .mud-card-content {
    flex: 1;
    overflow: hidden;
}

.su-product-card .mud-card-actions {
    margin-top: auto;
}

.su-product-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    min-height: 48px;
    height: 48px;
}

.su-product-brand,
.su-product-store,
.su-product-package {
    color: var(--mud-palette-text-secondary);
}

.su-badge-sale {
    position: absolute;
    top: 10px;
    left: 10px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    z-index: 10;
}

.su-badge-stock {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 10;
}

.su-badge-store {
    position: absolute;
    bottom: 10px;
    left: 10px;
    z-index: 10;
}

.su-product-image-container .mud-chip {
    font-weight: 600;
    border-radius: 6px;
    font-size: 0.75rem;
    opacity: 0.95;
}

.su-price-was {
    text-decoration: line-through;
    opacity: 0.6;
    font-size: 0.9rem;
    color: var(--textMut);
}

/* Mobile product cards */
@media (max-width: 600px) {
    .su-product-card {
        border-radius: var(--su-radius-md);
    }

    .su-product-image-container {
        height: clamp(110px, 32vw, 160px);
    }

    .su-product-card .mud-card-content {
        padding: 8px !important;
    }

    .su-product-title {
        font-size: 0.8rem;
        min-height: 32px;
        height: auto;
        line-height: 1.25;
    }

    .su-product-brand, .su-product-store {
        font-size: 0.7rem;
    }

    .su-product-card .mud-typography-h6 {
        font-size: 0.95rem;
    }

    .su-badge-sale, .su-badge-stock, .su-badge-store {
        top: 4px;
        left: 4px;
        right: auto;
    }

    .su-badge-stock {
        left: auto;
        right: 4px;
    }

    .su-badge-store {
        top: auto;
        bottom: 4px;
        left: 4px;
    }

    .su-product-image-container .mud-chip {
        height: 18px !important;
        font-size: 0.6rem !important;
        padding: 0 5px !important;
    }

    .su-product-card .mud-card-actions {
        padding: 4px 8px 6px !important;
    }

    .su-product-card .su-cta-btn {
        display: none;
    }

    .su-price-was {
        font-size: 0.75rem;
    }
}

/* =============================================================================
   COMPONENTS - LIST CARDS
   ============================================================================= */
.su-list-card {
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth);
    cursor: pointer;
    border: 1px solid var(--su-border-light);
    background-color: var(--mud-palette-surface);
}

@media (hover: hover) and (pointer: fine) {
    .su-list-card:hover {
        transform: translateY(-4px);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
    }
}

.su-list-card .mud-card-content {
    padding: 1.25rem 1rem;
}

.su-list-card .mud-card-actions {
    border-top: 1px solid var(--border);
    padding: 0.75rem 1rem;
}

.su-list-card.has-unavailable-prices {
    border-left: 3px solid var(--warnStrong);
}

.su-list-item-unavailable {
    border-left: 3px solid var(--warnStrong);
    background-color: rgba(255, 193, 7, 0.05);
}

@media (max-width: 600px) {
    .su-list-card .mud-card-content {
        padding: 0.75rem !important;
    }

    .su-list-card .mud-card-actions {
        padding: 0.5rem 0.75rem !important;
    }
}

.su-create-list-card {
    border-radius: var(--su-radius-lg);
    border: 2px dashed var(--mud-palette-primary);
    background-color: var(--mud-palette-surface);
    transition: all var(--su-transition-smooth);
    cursor: pointer;
    min-height: 150px;
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (hover: hover) and (pointer: fine) {
    .su-create-list-card:hover {
        transform: translateY(-4px);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
        border-color: var(--mud-palette-primary-darken);
    }
}

.su-create-list-card.disabled {
    cursor: not-allowed;
    opacity: 0.6;
    border-color: var(--mud-palette-text-disabled);
}

    .su-create-list-card.disabled:hover {
        transform: none;
        box-shadow: none;
        background-color: var(--mud-palette-surface);
    }

.su-create-list-content {
    text-align: center;
    padding: clamp(1rem, 3vw, 2rem);
}

    .su-create-list-content .mud-icon-root {
        font-size: clamp(2.5rem, 5vw, 4rem);
        color: var(--mud-palette-primary);
        margin-bottom: var(--su-space-md);
    }

.su-create-list-card.disabled .su-create-list-content .mud-icon-root {
    color: var(--mud-palette-text-disabled);
}

@media (max-width: 600px) {
    .su-create-list-card {
        min-height: 120px;
    }
}

.su-summary-card {
    border-radius: 10px;
    border: 1px solid var(--su-border-light);
    transition: box-shadow var(--su-transition-base);
    background-color: var(--mud-palette-surface);
}

@media (hover: hover) and (pointer: fine) {
    .su-summary-card:hover {
        box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
    }
}

/* =============================================================================
   COMPONENTS - PRODUCT DETAIL PAGE
   ============================================================================= */
.su-product-left {
    position: relative;
}

.su-product-right {
    position: sticky;
    top: 96px;
}

.su-gallery-card {
    border-radius: var(--su-radius-xl);
    overflow: hidden;
    background-color: var(--mud-palette-surface);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
    transition: box-shadow var(--su-transition-slow);
}

@media (hover: hover) and (pointer: fine) {
    .su-gallery-card:hover {
        box-shadow: 0 8px 28px rgba(0, 0, 0, 0.08);
    }
}

.su-thumbs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: 8px;
    margin-top: 10px;
}

.su-thumb {
    border: 1px solid var(--su-border-default);
    border-radius: 10px;
    cursor: pointer;
    overflow: hidden;
    transition: transform var(--su-transition-base), box-shadow var(--su-transition-base), border-color var(--su-transition-base);
    background-color: var(--mud-palette-surface);
}

@media (hover: hover) and (pointer: fine) {
    .su-thumb:hover {
        transform: translateY(-2px);
        box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
        border-color: rgba(var(--mud-palette-primary-rgb), 0.4);
    }
}

.su-thumb.active {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 0;
}

.su-buy-box {
    background: var(--mud-palette-surface);
    border: 1px solid var(--su-border-light);
    border-radius: 14px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
    transition: box-shadow var(--su-transition-smooth), transform var(--su-transition-smooth);
}

@media (hover: hover) and (pointer: fine) {
    .su-buy-box:hover {
        transform: translateY(-3px);
        box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
    }
}

.su-price-wrap {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.su-price-main {
    font-weight: 800;
    line-height: 1;
    color: var(--mud-palette-primary);
}

.su-price-unit {
    color: var(--mud-palette-text-secondary);
}

.su-save-badge {
    animation: su-badge-pulse 2s infinite;
}

@keyframes su-badge-pulse {
    0%, 100% {
        transform: scale(1);
    }

    50% {
        transform: scale(1.06);
    }
}

.su-card-slim {
    border-radius: 14px;
    border: 1px solid var(--su-border-light);
    background-color: var(--mud-palette-surface);
    overflow: hidden;
    transition: transform var(--su-transition-smooth), box-shadow var(--su-transition-smooth), border-color var(--su-transition-smooth);
    height: 100%;
}

@media (hover: hover) and (pointer: fine) {
    .su-card-slim:hover {
        transform: translateY(-4px);
        box-shadow: 0 12px 28px rgba(0, 0, 0, 0.10);
        border-color: rgba(var(--mud-palette-primary-rgb), 0.3);
    }
}

.su-section {
    margin-top: 32px;
}

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

.su-section-divider {
    height: 1px;
    background: var(--hoverWash);
    margin: 12px 0;
}

.su-store-chip {
    font-weight: 600;
}

.su-product-sidebar-ad {
    border-radius: var(--su-radius-md);
    overflow: hidden;
    min-height: 250px;
}

.su-upgrade-cta-card {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primaryHover) 100%);
    border-radius: var(--su-radius-lg);
    color: white;
}

    .su-upgrade-cta-card .mud-text-secondary {
        color: rgba(255, 255, 255, 0.8) !important;
    }

@media (max-width: 600px) {
    .su-gallery-card .mud-carousel {
        height: 260px !important;
    }

    .su-thumbs {
        gap: 6px;
    }

    .su-thumb {
        width: 52px;
        height: 52px;
    }

    .su-buy-box {
        padding: 12px;
        border-radius: var(--su-radius-md);
    }

    .su-price-main {
        font-size: 1.5rem;
    }

    .su-card-slim .mud-card-media {
        height: 90px !important;
    }

    .su-card-slim .mud-card-content {
        padding: 8px !important;
    }

    .su-section {
        margin-top: 20px;
    }

    .su-section-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }
}

/* =============================================================================
   COMPONENTS - STICKY HEADER (Generic)
   ============================================================================= */
.su-sticky-header {
    position: sticky;
    top: 64px;
    z-index: 100;
}

/* =============================================================================
   COMPONENTS - GRADIENT ICON CIRCLE
   ============================================================================= */
.su-gradient-icon-circle {
    background: linear-gradient(135deg, var(--primary) 0%, var(--primaryHover) 100%);
    border-radius: var(--su-radius-round);
    width: 100px;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

/* =============================================================================
   COMPONENTS - PAGINATION
   ============================================================================= */
.su-pagination {
    margin-top: clamp(2rem, 4vw, 3rem);
    margin-bottom: clamp(2rem, 4vw, 3rem);
    display: flex;
    justify-content: center;
}

.su-pagination-modern {
    margin-top: clamp(2rem, 4vw, 3rem);
    margin-bottom: clamp(3rem, 6vw, 5rem);
    display: flex;
    justify-content: center;
    align-items: center;
    padding-bottom: var(--su-space-xl);
}

.su-pagination-container {
    padding: 0.75rem 1.25rem;
    border-radius: var(--su-radius-xl);
    background: var(--mud-palette-surface);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.05);
    display: inline-flex;
    justify-content: center;
}

.mud-pagination button {
    border-radius: var(--su-radius-round);
    width: 38px;
    height: 38px;
    margin: 0 4px;
    transition: all var(--su-transition-smooth);
}

    .mud-pagination button:hover {
        background-color: rgba(var(--mud-palette-primary-rgb), 0.1);
        transform: translateY(-2px);
    }

.mud-pagination .mud-selected {
    box-shadow: 0 3px 10px rgba(var(--mud-palette-primary-rgb), 0.3);
    color: white !important;
}

    .mud-pagination .mud-selected:hover {
        transform: scale(1.05);
    }

@media (max-width: 600px) {
    .su-pagination-modern {
        margin-top: var(--su-space-md);
        margin-bottom: var(--su-space-lg);
    }

    .su-pagination-container {
        width: 100%;
        border-radius: var(--su-radius-md);
        padding: 6px 10px;
    }

    .mud-pagination button {
        width: 30px;
        height: 30px;
        min-width: 30px;
        margin: 0 2px;
        font-size: 0.75rem;
    }
}

/* =============================================================================
   COMPONENTS - EMPTY STATE
   ============================================================================= */
/* The single declaration. The flex properties come from the duplicate that used
   to sit up near the drawer rules; padding and colour are what that duplicate
   pair already resolved to, so nothing moves. */
.su-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: clamp(2rem, 5vw, 4rem) var(--su-space-md);
    color: var(--mud-palette-text-secondary);
}

    /* Was .su-empty-state .mud-icon, which matches nothing: MudBlazor renders an
       <svg class="mud-icon-root mud-svg-icon">. So this rule had never applied,
       and every empty-state icon in both apps was drawing at MudBlazor's default
       24px rather than the intended display size. It also asked for
       --mud-palette-secondary — an accent, and the wrong role for the quietest
       thing on the page — so the colour is stated as --textMut now. */
    .su-empty-state .mud-icon-root {
        font-size: clamp(3rem, 6vw, 5rem);
        color: var(--textMut);
        opacity: 0.7;
    }

    .su-empty-state h5 {
        margin-top: var(--su-space-lg);
        color: var(--mud-palette-text-primary);
    }

@media (max-width: 600px) {
    .su-empty-state {
        padding: 2rem 1rem;
    }

        .su-empty-state .mud-icon-root {
            font-size: 3rem;
        }
}

/* ── EmptyState component (Batch 6) ──────────────────────────────────────────
   The one formula: art with an action mini-badge, a headline, one sentence,
   buttons. Geometry from cuugo-states-preview.html — a 76px rounded art tile on
   --field, a 28px badge overlapping its corner, ringed in the surface colour so
   it reads as sitting on top.

   Separate class from .su-empty-state, which nine pages still use. Pages move
   across one at a time rather than all at once behind a rewritten shared rule. */

.su-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: clamp(2rem, 5vw, 3.5rem) var(--su-space-md);
}

.su-empty-art {
    position: relative;
    width: 76px;
    height: 76px;
    border-radius: 22px;
    background: var(--field);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 10px;
}

    .su-empty-art .mud-icon-root {
        font-size: 36px;
        color: var(--textMut);
    }

/* Only a genuine failure gets the failure colour. An empty list is not an
   error, and colouring it like one is how a blank page starts to feel broken.

   --errSoft/--errText, NOT --accentSoft/--accentText. The states preview maps
   its error toast onto the accent, which reads correctly only while the accent
   happens to be red: under matariki the accent is teal, so a failed load was
   rendering in the colour of success. The error ramp is semantic and means the
   same thing in all fourteen themes. See DEVIATIONS D98. */
.su-empty.is-problem .su-empty-art {
    background: var(--errSoft);
}

    .su-empty.is-problem .su-empty-art .mud-icon-root {
        color: var(--errText);
    }

.su-empty-badge {
    position: absolute;
    bottom: -4px;
    right: -6px;
    width: 28px;
    height: 28px;
    border-radius: 10px;
    background: var(--primary);
    color: var(--onPrimary);
    display: flex;
    align-items: center;
    justify-content: center;
    /* The ring is the surface, not a colour, so the badge lifts off the art on
       whatever the state is sitting on. */
    border: 3px solid var(--surface);
}

    .su-empty-badge .mud-icon-root {
        font-size: 14px;
        color: inherit;
    }

.su-empty-title {
    margin: 0;
    font-family: var(--font-ui);
    font-weight: 800;
    font-size: 18px;
    letter-spacing: -0.02em;
    color: var(--text);
}

.su-empty-text {
    margin: 0 0 14px;
    max-width: 320px;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--textMut);
}

.su-empty-actions {
    display: flex;
    gap: 9px;
    flex-wrap: wrap;
    justify-content: center;
}

/* =============================================================================
   COMPONENTS - FEATURE MATRIX
   ============================================================================= */
.su-category-header {
    background-color: var(--mud-palette-background-grey);
    font-weight: 500;
}

.su-feature-matrix {
    position: relative;
}

.su-centered-col {
    display: flex;
    justify-content: center;
}

/* =============================================================================
   GLOBAL CONTAINER SPACING
   ============================================================================= */
.mud-container {
    padding-left: clamp(12px, 3vw, 24px) !important;
    padding-right: clamp(12px, 3vw, 24px) !important;
}

@media (max-width: 600px) {
    .mud-container {
        padding-left: 8px !important;
        padding-right: 8px !important;
    }

        .mud-container .mud-container {
            padding-left: 4px !important;
            padding-right: 4px !important;
        }
}

/* =============================================================================
   UTILITY CLASSES
   ============================================================================= */
.su-text-muted {
    color: var(--textMut);
}

.su-gap-2 {
    gap: 8px;
}

.su-cursor-pointer {
    cursor: pointer;
}

.su-create-btn {
    font-weight: 500;
    border-radius: var(--su-radius-md);
}

.su-flex-wrap {
    flex-wrap: wrap;
}

.su-truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-muted {
    color: var(--mud-palette-text-secondary);
}

.su-rounded-xl {
    border-radius: var(--su-radius-xl);
}

.su-rounded-lg {
    border-radius: var(--su-radius-lg);
}

.su-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
}

/* Circular branded bottom bar buttons */
.su-bottom-btn {
    width: 42px !important;
    height: 42px !important;
    border-radius: 50% !important;
    border: 2px solid transparent !important;
    margin: 0 4px;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

    .su-bottom-btn:hover {
        transform: scale(1.1);
        box-shadow: 0 2px 8px rgba(0,0,0,0.18);
    }

.su-bottom-btn-teal {
    color: var(--primary) !important;
    border-color: var(--primary) !important;
    background-color: rgba(38, 198, 218, 0.08) !important;
}

    .su-bottom-btn-teal:hover {
        background-color: rgba(38, 198, 218, 0.18) !important;
    }

.su-bottom-btn-coral {
    color: var(--accent) !important;
    border-color: var(--accent) !important;
    background-color: rgba(255, 107, 107, 0.08) !important;
}

    .su-bottom-btn-coral:hover {
        background-color: rgba(255, 107, 107, 0.18) !important;
    }

/* Store column responsive grid */
@media (max-width: 768px) {
    .su-store-columns {
        grid-template-columns: repeat(2, 1fr) !important;
    }
}

@media (max-width: 480px) {
    .su-store-columns {
        grid-template-columns: 1fr !important;
    }
}

/* =============================================================================
   MAUI HYBRID SPECIFIC STYLES
   Add class="is-hybrid" to <body> in your BlazorWebView
   ============================================================================= */
body.is-hybrid .su-appbar {
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
}

body.is-hybrid a {
    -webkit-touch-callout: none;
}

body.is-hybrid .su-appbar-bottom-bar {
    padding-bottom: var(--su-safe-bottom);
}

/* Force-light override REMOVED in Phase 2 (theme system). It pinned these
   rules to their light colours whenever the DEVICE asked for dark, which both
   defeats the theme system and ignores an explicit light/dark choice. The base
   rules are token-driven and cover both modes. See DEVIATIONS D11. */
/* =============================================================================
   END OF SHARED UI STYLES
   ============================================================================= */

/* =============================================================================
   FIX 1: MudSwitch — suppress thumb movement on hover
   MudBlazor translates the thumb left on hover when switch is ON
   ============================================================================= */
.mud-switch:hover .mud-switch-thumb,
.mud-switch .mud-button-root:hover .mud-switch-thumb {
    transform: none !important;
    transition: none !important;
}

/* Also suppress the ripple/scale effect on the button itself */
.mud-switch .mud-button-root:hover {
    transform: none !important;
    background: transparent !important;
}

/* =============================================================================
   FIX 2: Bottom bar icon consistency
   All action icons in the bottom bar should be the same visual size
   ============================================================================= */

/* Make ALL bottom bar icon buttons the same circle size */
.su-appbar-bottom-bar .mud-icon-button,
.su-appbar-bottom-bar .mud-button-root {
    width: 42px !important;
    height: 42px !important;
    min-width: 42px !important;
    min-height: 42px !important;
    border-radius: 50% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 0 !important;
}

    /* Ensure icons inside are the same size */
    .su-appbar-bottom-bar .mud-icon-button .mud-icon-root,
    .su-appbar-bottom-bar .mud-button-root .mud-icon-root {
        font-size: 22px !important;
        width: 22px !important;
        height: 22px !important;
    }

/* Avatar/initial chips in bottom bar — match the circle size */
.su-appbar-bottom-bar .mud-avatar {
    width: 42px !important;
    height: 42px !important;
    font-size: 16px !important;
}

/* Override the tap-target minimum that inflates some icons */
@media (max-width: 600px) {
    .su-appbar-bottom-bar .mud-icon-button {
        min-width: 42px !important;
        min-height: 42px !important;
    }
}

/* =============================================================================
   FIX 3: Page content margins — prevent content bleeding to edges
   ============================================================================= */

/* Ensure account/subscription pages have consistent side padding */
.su-account-page {
    padding-left: clamp(12px, 4vw, 2rem) !important;
    padding-right: clamp(12px, 4vw, 2rem) !important;
}

    /* Ensure section cards inside account pages don't bleed */
    .su-account-page .su-section-card,
    .su-account-page .su-page-card,
    .su-account-page .su-current-plan-card {
        margin-left: 0;
        margin-right: 0;
    }

    /* Any MudText headings that are direct children shouldn't touch the edge */
    .su-account-page > .mud-typography,
    .su-account-page > .mud-container > .mud-typography {
        padding-left: 0;
        padding-right: 0;
    }

/* Global safety net — any full-width content sections */
@media (max-width: 600px) {
    .su-content-area > .mud-container {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    /* Section titles should have breathing room */
    .mud-typography.mud-typography-h5,
    .mud-typography.mud-typography-h6 {
        padding-left: 4px;
    }
}

/* =============================================================================
   ADD THESE RULES TO SharedUI.css
   Section: COMPONENTS — Bottom bar / nav icon consistency
   ============================================================================= */

/* -----------------------------------------------------------------------------
   Neutral variant — Menu hamburger, MenuBook, unauthenticated account icon
   Matches the su-bottom-btn base (42px circle, border, hover scale) but uses
   a subtle grey palette instead of the branded teal/coral colours.
   ----------------------------------------------------------------------------- */
.su-bottom-btn-neutral {
    color: var(--su-text-primary, var(--text)) !important;
    border-color: var(--border) !important;
    background-color: var(--hoverWash) !important;
}

    .su-bottom-btn-neutral:hover {
        background-color: var(--hoverWash) !important;
    }

/* -----------------------------------------------------------------------------
   Unauthenticated account circle
   Uses su-bottom-btn + su-bottom-btn-neutral already — these rules just centre
   the icon and ensure the cursor is correct since it's a <div>, not a button.
   ----------------------------------------------------------------------------- */
.su-login-anon-btn {
    cursor: pointer;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}

.su-login-anon-icon {
    font-size: 22px !important;
    color: var(--su-text-primary, var(--text));
    pointer-events: none; /* let clicks fall through to the div */
}

/* -----------------------------------------------------------------------------
   Authenticated avatar — sized to match the 42px circle system exactly
   ----------------------------------------------------------------------------- */
.su-login-avatar {
    width: 42px !important;
    height: 42px !important;
    font-size: 16px !important;
    font-weight: 700 !important;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    border: 2px solid rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
}

    .su-login-avatar:hover {
        transform: scale(1.08);
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
    }

/* -----------------------------------------------------------------------------
   MudSwitch hover fix — suppress thumb sliding left on hover when ON
   ----------------------------------------------------------------------------- */
.mud-switch .mud-button-root:hover {
    transform: none !important;
    background: transparent !important;
}

.mud-switch:hover .mud-switch-thumb {
    transform: none !important;
}

/* =============================================================================
   FIX: Right drawer scroll clearance for mobile bottom bar
   ============================================================================= */
@media (max-width: 959.98px) {
    .su-right-drawer .mud-drawer-content,
    .su-left-drawer .mud-drawer-content {
        padding-bottom: calc(64px + var(--su-safe-bottom, 0px) + var(--su-space-md)) !important;
        overflow-y: auto !important;
    }
}

/* FIX: Pin switch thumb position on hover */
.mud-switch .mud-switch-base:not(.mud-checked):hover {
    transform: translateX(0) !important;
}

.mud-switch .mud-switch-base.mud-checked:hover {
    transform: translateX(20px) !important;
}

/* =============================================================================
   FIX: MudSelect dropdown clipped by bottom app bar on mobile
   Bottom bar height = 64px (matches su-main-content-wrapper padding-bottom)
   ============================================================================= */
@media (max-width: 959.98px) {
    .mud-popover-open {
        z-index: 1500 !important; /* ✅ above overlay (1401) and app bar (1300) */
    }

    /* ✅ Only add bottom clearance OUTSIDE dialogs */
    body:not(:has(.mud-dialog-container)) .mud-popover-open .mud-list {
        padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
    }

    /* ✅ Inside dialogs — reset to normal */
    .mud-dialog-container .mud-popover-open .mud-list {
        padding-bottom: 8px !important;
    }

       /* .mud-popover-open .mud-list {
            padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
        }*/
}

/* Clearance for the fixed app bar, so a drawer's first row is not hidden behind
   it. Bottom-anchored drawers are excluded: they open from the bottom edge and
   never pass under the app bar, so this only put 72px of empty panel above their
   header. The navigation history drawer is the one such drawer today. */
.su-left-drawer,
.su-right-drawer,
.mud-drawer:not(.mud-drawer-pos-bottom) {
    padding-top: calc(72px + var(--su-safe-top)) !important; /* +16px breathing room */
}

@media (max-width: 600px) {
    .su-left-drawer,
    .su-right-drawer,
    .mud-drawer:not(.mud-drawer-pos-bottom) {
        padding-top: calc(68px + var(--su-safe-top)) !important;
    }
}

/* LOGIN MENU — cancel the select-dropdown bottom padding fix.
   The login menu is anchored to the top bar, not the bottom, so it
   doesn't need clearance for the bottom app bar. */
@media (max-width: 959.98px) {
    .su-login-menu-popover .mud-list {
        padding-bottom: 8px !important;
    }
}

/* Prevent logo swap from being jarring */
.su-appbar .su-logo-link {
    transition: opacity 0.15s ease;
}

.su-mobile-search-expanded {
    /* existing styles... */
    
    /* ✅ Cancel out the app bar's side padding to go edge-to-edge */
    margin-left: calc(-1 * clamp(8px, 2vw, 20px)) !important;
    margin-right: calc(-1 * clamp(8px, 2vw, 20px)) !important;
    
    width: calc(100% + (2 * clamp(8px, 2vw, 20px))) !important;
}

@media (max-width: 599px) {
    /* 4px short of full bleed: the bar is a pill now, and a rounded corner
       sitting exactly on the viewport edge reads as content running off the
       screen rather than as a deliberate edge-to-edge control. */
    .su-mobile-search-expanded {
        margin-left: -20px !important;
        margin-right: -20px !important;
        width: calc(100% + 40px) !important;
    }
}

@media (max-width: 600px) {
    .su-home .su-search-container {
        /*   max-width: calc(100% + 16px) !important;*/
        width: calc(100% + 16px) !important;
        margin-left: -8px !important;
        margin-right: -8px !important;
    }

   
}

.su-mobile-search-expanded .su-suggestions-dropdown {
    overscroll-behavior: contain; /* ✅ prevents scroll leaking to body */
}

/* ✅ Prevent flicker during dialog open animation */
.su-filter-dialog {
    overflow: hidden;
    /* Add this: */
    backface-visibility: hidden !important;
    -webkit-backface-visibility: hidden !important;
}

/* =============================================================================
   COMPONENTS - FILTER AUTOCOMPLETE + CHIP ROW
   Add these rules into your SharedUI.css under the filter dialog section
   ============================================================================= */

/* Chip row sits just below each autocomplete field */
.su-filter-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    min-height: 0;
    padding-top: 6px;
}

    /* Hide the chip row entirely when empty so it takes no space */
    .su-filter-chip-row:empty {
        display: none;
        padding-top: 0;
    }

/* Tighten the autocomplete field bottom margin so chips sit snug */
.su-filter-autocomplete.mud-input-control {
    margin-bottom: 0 !important;
}

/* Chips — slightly smaller close icon on mobile */
@media (max-width: 600px) {
    .su-filter-chip-row .mud-chip {
        font-size: 0.75rem;
    }
}

/* Make MudMenu popover match the activator button width */
.mud-menu-popover-full-width .mud-popover {
    width: 100% !important;
    min-width: unset !important;
}

/* =============================================================================
   LIST DETAIL PAGE — ld- prefix (List Detail)
   Add this block to the bottom of SharedUI.css
   ============================================================================= */

/* =============================================================================
   SIDEBAR — sticky, hidden on mobile
   ============================================================================= */
.ld-sidebar {
    display: flex;
    flex-direction: column;
    gap: 10px;
    position: sticky;
    top: calc(72px + var(--su-safe-top));
    max-height: calc(100vh - 140px);
    overflow-y: auto;
    scrollbar-width: none;
    padding-bottom: 80px; /* clearance for bottom bar */
}

    .ld-sidebar::-webkit-scrollbar {
        display: none;
    }

/* =============================================================================
   ACTIONS ROW — rename / share / delete
   ============================================================================= */
.ld-actions-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 0 2px;
}

.ld-action-btn {
    width: 36px !important;
    height: 36px !important;
    min-width: 36px !important;
    border-radius: 50% !important;
    border: 1.5px solid var(--su-border-default) !important;
    background: var(--su-bg-surface) !important;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease !important;
}

    .ld-action-btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0,0,0,0.10) !important;
        background: var(--su-bg-hover) !important;
    }

    .ld-action-btn.danger {
        border-color: rgba(211, 47, 47, 0.3) !important;
    }

        .ld-action-btn.danger:hover {
            background: rgba(211, 47, 47, 0.06) !important;
        }

/* =============================================================================
   BUDGET CARD — desktop sidebar
   ============================================================================= */
.ld-budget-card {
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-lg);
    overflow: hidden;
    box-shadow: 0 2px 10px rgba(0,0,0,0.06);
    border: 1px solid var(--su-border-light);
}

.ld-budget-card-header {
    background: linear-gradient( 135deg, rgba(var(--mud-palette-primary-rgb), 0.09) 0%, rgba(var(--mud-palette-primary-rgb), 0.03) 100% );
    padding: 10px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--su-border-light);
}

.ld-budget-card-body {
    padding: 14px;
}

.ld-budget-amount {
    font-size: 1.45rem;
    font-weight: 800;
    letter-spacing: -0.5px;
    line-height: 1;
    color: var(--mud-palette-text-primary);
}

.ld-budget-period {
    font-size: 0.75rem;
    color: var(--su-text-muted);
    font-weight: 500;
}

.ld-budget-progress-track {
    height: 6px;
    border-radius: 3px;
    background: var(--hoverWash);
    overflow: hidden;
    margin: 10px 0 6px;
}

.ld-budget-progress-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.5s ease;
}

.ld-budget-remaining-label {
    font-size: 0.78rem;
    font-weight: 600;
}

.ld-budget-divider {
    height: 1px;
    background: var(--su-border-light);
    margin: 10px 0;
}

.ld-budget-monthly-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.75rem;
}

.ld-budget-explanation {
    font-size: 0.68rem;
    color: var(--su-text-hint);
    line-height: 1.4;
    margin-top: 6px;
}

/* =============================================================================
   STAT CARDS — desktop sidebar
   ============================================================================= */
.ld-stat-card {
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-md);
    padding: 10px 14px;
    border: 1px solid var(--su-border-light);
    box-shadow: 0 1px 4px rgba(0,0,0,0.04);
    display: flex;
    align-items: center;
    gap: 10px;
    position: relative;
    overflow: hidden;
}

    .ld-stat-card::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        width: 3px;
        border-radius: 0 2px 2px 0;
    }

    .ld-stat-card.items::before {
        background: var(--mud-palette-info);
    }

    .ld-stat-card.total::before {
        background: var(--mud-palette-primary);
    }

    .ld-stat-card.diff::before {
        background: var(--mud-palette-success);
    }

    .ld-stat-card.diff.up::before {
        background: var(--mud-palette-warning);
    }

.ld-stat-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 18px !important;
}

.ld-stat-card.items .ld-stat-icon {
    background: rgba(var(--mud-palette-info-rgb), 0.12);
}

.ld-stat-card.total .ld-stat-icon {
    background: rgba(var(--mud-palette-primary-rgb), 0.10);
}

.ld-stat-card.diff .ld-stat-icon {
    background: rgba(var(--mud-palette-success-rgb), 0.10);
}

.ld-stat-card.diff.up .ld-stat-icon {
    background: rgba(var(--mud-palette-warning-rgb), 0.10);
}

.ld-stat-label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--su-text-muted);
    font-weight: 600;
    line-height: 1;
    margin-bottom: 3px;
}

.ld-stat-value {
    font-size: 1rem;
    font-weight: 800;
    letter-spacing: -0.2px;
    line-height: 1;
}

/* =============================================================================
   SORT INDICATOR — current sort shown in sticky header
   ============================================================================= */
.ld-sort-chip {
    font-size: 0.72rem !important;
    height: 26px !important;
    padding: 0 8px !important;
    font-weight: 600 !important;
    border-radius: 6px !important;
    cursor: pointer;
}

/* =============================================================================
   MOBILE BUDGET BAR — compact pill, xs only
   ============================================================================= */
.ld-mobile-budget-bar {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 10px 14px;
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-lg);
    border: 1px solid var(--su-border-light);
    box-shadow: 0 2px 8px rgba(0,0,0,0.05);
    cursor: pointer;
    margin: 0 0 6px 0;
    -webkit-tap-highlight-color: transparent;
    transition: box-shadow 0.15s ease;
}

    .ld-mobile-budget-bar:active {
        box-shadow: 0 1px 4px rgba(0,0,0,0.08);
    }

.ld-mobile-budget-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.ld-mobile-budget-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--su-text-muted);
}

.ld-mobile-budget-main {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
}

.ld-mobile-budget-remaining {
    font-size: 0.75rem;
    font-weight: 600;
}

.ld-mobile-budget-tap {
    font-size: 0.68rem;
    color: var(--su-text-hint);
    display: flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
}

.ld-mobile-progress-track {
    height: 4px;
    border-radius: 2px;
    background: var(--hoverWash);
    overflow: hidden;
}

.ld-mobile-progress-fill {
    height: 100%;
    border-radius: 2px;
    transition: width 0.4s ease;
}

/* =============================================================================
   MOBILE BOTTOM SHEET — budget breakdown modal
   ============================================================================= */
.ld-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 2100;
    display: flex;
    align-items: flex-end;
    animation: ld-overlay-fade 0.2s ease forwards;
}

@keyframes ld-overlay-fade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.ld-sheet {
    width: 100%;
    background: var(--su-bg-surface);
    border-radius: var(--su-radius-xl) var(--su-radius-xl) 0 0;
    padding: 8px 20px 0;
    padding-bottom: calc(24px + var(--su-safe-bottom));
    max-height: 88vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    animation: ld-sheet-slide 0.32s cubic-bezier(0.32, 0.72, 0, 1) forwards;
}

@keyframes ld-sheet-slide {
    from {
        transform: translateY(100%);
    }

    to {
        transform: translateY(0);
    }
}

.ld-sheet-handle {
    width: 40px;
    height: 4px;
    background: var(--hoverWash);
    border-radius: 2px;
    margin: 4px auto 18px;
}

.ld-sheet-title {
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: -0.2px;
    margin-bottom: 14px;
}

/* Sheet stat row — large display */
.ld-sheet-stats {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
    margin-bottom: 16px;
}

.ld-sheet-stat {
    background: rgba(var(--mud-palette-primary-rgb), 0.04);
    border-radius: var(--su-radius-md);
    padding: 10px 8px;
    text-align: center;
    border: 1px solid var(--su-border-light);
}

.ld-sheet-stat-value {
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: -0.2px;
    line-height: 1;
    margin-bottom: 3px;
}

.ld-sheet-stat-label {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--su-text-muted);
    font-weight: 600;
}

/* Sheet budget progress section */
.ld-sheet-budget-section {
    background: rgba(var(--mud-palette-primary-rgb), 0.04);
    border-radius: var(--su-radius-lg);
    padding: 14px;
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.1);
    margin-bottom: 12px;
}

.ld-sheet-budget-amount {
    font-size: 1.6rem;
    font-weight: 900;
    letter-spacing: -0.5px;
    line-height: 1;
    margin-bottom: 2px;
}

.ld-sheet-budget-period {
    font-size: 0.75rem;
    color: var(--su-text-muted);
    font-weight: 500;
    margin-bottom: 10px;
}

.ld-sheet-progress-track {
    height: 8px;
    border-radius: 4px;
    background: var(--hoverWash);
    overflow: hidden;
    margin-bottom: 6px;
}

.ld-sheet-progress-fill {
    height: 100%;
    border-radius: 4px;
    transition: width 0.5s ease;
}

.ld-sheet-budget-remaining {
    font-size: 0.82rem;
    font-weight: 700;
    margin-bottom: 6px;
}

.ld-sheet-budget-note {
    font-size: 0.68rem;
    color: var(--su-text-hint);
    line-height: 1.4;
}

.ld-sheet-monthly-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 7px 0;
    border-top: 1px solid var(--su-border-light);
    font-size: 0.78rem;
}

    .ld-sheet-monthly-row:first-of-type {
        margin-top: 8px;
    }

/* =============================================================================
   PRODUCT CARD REFINEMENTS — list detail specific
   ============================================================================= */

/* Taller image on desktop */
@media (min-width: 960px) {
    .su-product-card .su-product-image-container {
        height: 200px;
    }
}

/* Quantity controls alignment */
.ld-qty-row {
    display: flex;
    align-items: center;
    gap: 0;
}

.ld-qty-badge {
    min-width: 36px;
    text-align: center;
    font-weight: 700;
    font-size: 0.85rem;
}

/* =============================================================================
   STORE FILTER CHIPS — refined
   ============================================================================= */
.ld-store-chips {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    padding: 2px 0 6px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

    .ld-store-chips::-webkit-scrollbar {
        display: none;
    }

    /* UI_14 — keep each chip at its natural width so the row scrolls
       sideways instead of squeezing and clipping the labels */
    .ld-store-chips .mud-chip {
        flex: 0 0 auto;
    }
/*.ld-store-chips {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    padding: 2px 0 6px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

    .ld-store-chips::-webkit-scrollbar {
        display: none;
    }*/

/* =============================================================================
   ITEM LIMIT BADGE — counts in header
   ============================================================================= */
.ld-item-limit-badge {
    font-size: 0.68rem;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
    background: rgba(var(--mud-palette-primary-rgb), 0.10);
    color: var(--mud-palette-primary);
    white-space: nowrap;
}

/* =============================================================================
   SET BUDGET EMPTY STATE
   ============================================================================= */
.ld-set-budget-btn {
    border: 1.5px dashed rgba(var(--mud-palette-primary-rgb), 0.4) !important;
    border-radius: var(--su-radius-md) !important;
    width: 100%;
    font-size: 0.78rem !important;
    font-weight: 600 !important;
    padding: 8px 0 !important;
    color: var(--mud-palette-primary) !important;
    transition: all 0.15s ease !important;
}

    .ld-set-budget-btn:hover {
        background: rgba(var(--mud-palette-primary-rgb), 0.05) !important;
        border-color: var(--mud-palette-primary) !important;
    }

/* =============================================================================
   ALERTS — warning / out of stock in header area
   ============================================================================= */
.ld-status-chips {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}

/* =============================================================================
   RESPONSIVE OVERRIDES
   ============================================================================= */

/* Mobile: hide sidebar entirely */
@media (max-width: 599px) {
    .ld-sidebar-item {
        display: none !important;
    }

    .ld-products-item {
        /* Takes full 12 cols on mobile */
    }
}

/* Tablet: sidebar takes less space */
@media (min-width: 600px) and (max-width: 959px) {
    .ld-mobile-budget-bar {
        display: none !important;
    }

    .ld-overlay {
        display: none !important;
    }
}

/* Desktop */
@media (min-width: 960px) {
    .ld-mobile-budget-bar {
        display: none !important;
    }

    .ld-overlay {
        display: none !important;
    }
}

/* Autocomplete adornment — red close icon with border when open */
.su-filter-autocomplete.ac-open .mud-input-adornment-end .mud-icon-button {
    color: var(--mud-palette-error) !important;
    border: 1.5px solid var(--mud-palette-error) !important;
    border-radius: 50% !important;
    transition: background 0.15s ease, color 0.15s ease;
}

    .su-filter-autocomplete.ac-open .mud-input-adornment-end .mud-icon-button:hover {
        background: rgba(var(--mud-palette-error-rgb), 0.08) !important;
    }

/* =============================================================================
   COMPONENTS - PRICE HISTORY SECTION — ph- prefix (Price History)
   Used in: PriceHistorySection.razor (embedded in ProductDetail page)
   Follows the same patterns as ld- (list detail) section above.
   ============================================================================= */

/* =============================================================================
   SECTION WRAPPER
   ============================================================================= */
.ph-section {
    margin-top: clamp(1.5rem, 3vw, 2rem);
    animation: su-fade-in 0.35s ease-in-out;
}

/* =============================================================================
   SECTION HEADER — title + period selector row
   ============================================================================= */
.ph-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 1rem;
}

/* =============================================================================
   KPI CARDS — 4-up grid (Current / Lowest / Highest / Trend)
   ============================================================================= */
.ph-kpi-card {
    border-radius: var(--su-radius-lg) !important;
    border: 1px solid var(--su-border-light) !important;
    background: var(--su-bg-surface);
    padding: 12px 14px;
    height: 100%;
    transition: box-shadow var(--su-transition-base), transform var(--su-transition-smooth);
    position: relative;
    overflow: hidden;
}

    /* Accent left-edge stripe — mirrors ld-stat-card pattern */
    .ph-kpi-card::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        width: 3px;
        border-radius: 0 2px 2px 0;
        background: var(--mud-palette-primary);
        opacity: 0.5;
    }

    .ph-kpi-card.current::before {
        background: var(--mud-palette-primary);
    }

    .ph-kpi-card.lowest::before {
        background: var(--savings);
    }

    .ph-kpi-card.highest::before {
        background: var(--errStrong);
    }

    .ph-kpi-card.trend::before {
        background: var(--mud-palette-secondary);
    }

@media (hover: hover) and (pointer: fine) {
    .ph-kpi-card:hover {
        box-shadow: var(--su-shadow-md) !important;
        transform: translateY(-2px);
    }
}

/* Label — small caps above the value, mirrors ld-stat-label */
.ph-kpi-label {
    font-size: var(--su-text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--su-text-muted);
    line-height: 1;
    margin-bottom: 5px;
}

/* Main value — bold, fluid size */
.ph-kpi-value {
    font-size: clamp(1.25rem, 2.5vw, 1.6rem) !important;
    font-weight: 800 !important;
    letter-spacing: -0.5px;
    line-height: 1;
}

/* Change percentage line below value */
.ph-kpi-change {
    font-size: var(--su-text-xs);
    font-weight: 600;
    margin-top: 4px;
    line-height: 1.3;
}

.ph-kpi-change--up {
    color: var(--errStrong);
}

.ph-kpi-change--down {
    color: var(--savings);
}

.ph-kpi-change--flat {
    color: var(--su-text-muted);
}

/* Date hint below lowest/highest value */
.ph-kpi-date {
    font-size: var(--su-text-xs);
    color: var(--su-text-muted);
    margin-top: 3px;
    line-height: 1.2;
}

/* Trend pill chip */
.ph-trend-chip {
    font-weight: 700 !important;
    font-size: 0.78rem !important;
    border-radius: 50px !important;
    height: 26px !important;
    padding: 0 10px !important;
}

.ph-trend-note {
    font-size: var(--su-text-xs);
    color: var(--su-text-muted);
    margin-top: 5px;
    line-height: 1.3;
}

/* =============================================================================
   PERIOD SELECTOR — button group (30d / 90d / 6m / 1y)
   ============================================================================= */
.ph-period-btn {
    border-radius: 50px !important;
    min-width: 44px !important;
    height: 30px !important;
    font-size: 0.75rem !important;
    font-weight: 600 !important;
    padding: 0 12px !important;
    transition: all var(--su-transition-base) !important;
}

/* =============================================================================
   CHART WRAPPER
   ============================================================================= */
.ph-chart-wrap {
    border-radius: var(--su-radius-lg);
    border: 1px solid var(--su-border-light);
    padding: 1rem 0.5rem 0.5rem;
    background: var(--su-bg-surface);
    box-shadow: var(--su-shadow-md);
    transition: box-shadow var(--su-transition-slow);
    overflow: hidden;
}

@media (hover: hover) and (pointer: fine) {
    .ph-chart-wrap:hover {
        box-shadow: var(--su-shadow-lg);
    }
}

/* Ensure MudChart SVG doesn't clip labels */
.ph-chart-wrap .mud-chart-line {
    overflow: visible;
}

/* =============================================================================
   RECENT CHANGES TABLE
   ============================================================================= */
.ph-change-table td {
    padding: 5px 8px;
    font-size: var(--su-text-sm);
    vertical-align: middle;
}

.ph-change-table tr:not(:last-child) td {
    border-bottom: 1px solid var(--su-border-light);
}

.ph-change-amount {
    font-weight: 700;
}

.ph-change-amount--up {
    color: var(--errStrong);
}

.ph-change-amount--down {
    color: var(--savings);
}

/* =============================================================================
   AVERAGE PRICE FOOTER NOTE
   ============================================================================= */
.ph-avg-note {
    font-size: var(--su-text-xs);
    color: var(--su-text-muted);
    margin-top: 8px;
    display: block;
    line-height: 1.5;
}

/* =============================================================================
   EMPTY / NO-DATA STATE
   Reuses su-empty-state aesthetics but with a dashed border variant
   ============================================================================= */
.ph-no-data {
    border-radius: var(--su-radius-lg);
    border: 1.5px dashed var(--su-border-default);
    padding: clamp(1.5rem, 4vw, 2.5rem) var(--su-space-lg);
    text-align: center;
    background: var(--su-bg-primary);
    color: var(--su-text-muted);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

    .ph-no-data .mud-icon-root {
        font-size: clamp(2rem, 4vw, 2.5rem);
        opacity: 0.5;
    }

/* =============================================================================
   RESPONSIVE OVERRIDES
   ============================================================================= */

/* Mobile — tighter padding, smaller KPI values */
@media (max-width: 600px) {
    .ph-section {
        margin-top: 1.25rem;
    }

    .ph-kpi-card {
        padding: 10px 12px;
    }

    .ph-kpi-value {
        font-size: 1.15rem !important;
        letter-spacing: -0.3px;
    }

    .ph-chart-wrap {
        padding: 8px 2px 4px;
        border-radius: var(--su-radius-md);
    }

    /* Period buttons — narrower on small screens */
    .ph-period-btn {
        min-width: 36px !important;
        padding: 0 8px !important;
        font-size: 0.7rem !important;
    }

    /* Expansion panel text is slightly smaller */
    .ph-change-table td {
        font-size: 0.75rem;
        padding: 4px 6px;
    }

    .ph-header-row {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* Tablet — slight reduction only */
@media (min-width: 601px) and (max-width: 959px) {
    .ph-kpi-value {
        font-size: 1.35rem !important;
    }
}

/* =============================================================================
   DARK-MODE FORCE-LIGHT OVERRIDES (matches the pattern at the bottom of the file)
   These rules are placed here for co-location but the actual @media override
   block at the bottom of SharedUI.css must also include these if needed.
   ============================================================================= */
/* Force-light override REMOVED in Phase 2 (theme system). It pinned these
   rules to their light colours whenever the DEVICE asked for dark, which both
   defeats the theme system and ignores an explicit light/dark choice. The base
   rules are token-driven and cover both modes. See DEVIATIONS D11. */
/* =============================================================================
   COMPONENTS - PRICE HISTORY SECTION v2 (ph-v2- prefix)
   Append this block to SharedUI.css after the existing ph- section.

   Design decisions implemented:
   • Desktop: always-visible card — title + trend badge + period selector
     in one header row, then 3 compact stat chips, then chart as hero,
     then recent-changes accordion (collapsed), then avg note.
   • Mobile: collapsed by default — summary row shows Low / High sub-label
     + trend pill + chevron. Tap to expand full card inline.
   • Removed 4-KPI-card layout that ate vertical space before the chart.
   • Trend badge is now inline next to the title, not a full KPI card.
   • Chart renders before period buttons on mobile (chart is the primary goal).
   ============================================================================= */

/* ── Outer shell ─────────────────────────────────────────────────────────────
   Replaces .ph-section so the component doesn't conflict with the old class.
   ─────────────────────────────────────────────────────────────────────────── */
.ph-shell {
    margin-top: clamp(1.5rem, 3vw, 2rem);
    animation: su-fade-in 0.35s ease-in-out;
}

/* ── Desktop card — shown ≥ 600 px, hidden on mobile ────────────────────── */
.ph-desktop-card {
    background: var(--su-bg-surface);
    border: 1px solid var(--su-border-light);
    border-radius: var(--su-radius-xl);
    padding: 1.25rem;
    box-shadow: var(--su-shadow-md);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

@media (max-width: 599px) {
    .ph-desktop-card {
        display: none;
    }
}

/* ── Mobile card — shown < 600 px, hidden on desktop ────────────────────── */
.ph-mobile-card {
    display: none;
    background: var(--su-bg-surface);
    border: 1px solid var(--su-border-light);
    border-radius: var(--su-radius-xl);
    overflow: hidden;
    box-shadow: var(--su-shadow-md);
}

@media (max-width: 599px) {
    .ph-mobile-card {
        display: block;
    }
}

/* ── Skeleton placeholder ─────────────────────────────────────────────────── */
.ph-skeleton-card {
    gap: 10px;
}

/* ── Desktop header row: title group + period buttons ─────────────────────── */
.ph-v2-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
}

.ph-v2-title-group {
    display: flex;
    flex-direction: column;
    gap: 0;
    min-width: 0;
}

.ph-v2-period-wrap {
    flex-shrink: 0;
    align-self: flex-start;
}

/* ── Trend badge — inline next to title ──────────────────────────────────── */
.ph-v2-trend-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.2px;
    padding: 3px 9px 3px 6px;
    border-radius: 50px;
    border: 1px solid transparent;
    white-space: nowrap;
    line-height: 1;
    flex-shrink: 0;
}

/* Smaller variant used in the mobile summary row */
.ph-v2-trend-badge-sm {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 0.68rem;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 50px;
    border: 1px solid transparent;
    white-space: nowrap;
    line-height: 1;
    flex-shrink: 0;
}

/* ── 3-column compact stat row ───────────────────────────────────────────── */
.ph-v2-stats-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
}

.ph-v2-stat {
    border: 1px solid var(--su-border-light);
    border-radius: var(--su-radius-md);
    padding: 10px 12px;
    background: var(--hoverWash);
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: relative;
    overflow: hidden;
}

    /* Accent left stripe — matches the ld-stat-card / ph-kpi-card pattern */
    .ph-v2-stat::before {
        content: '';
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        width: 3px;
        border-radius: 0 2px 2px 0;
    }

    .ph-v2-stat.current::before {
        background: var(--mud-palette-primary);
        opacity: 0.6;
    }

    .ph-v2-stat.lowest::before {
        background: var(--savings);
        opacity: 0.6;
    }

    .ph-v2-stat.highest::before {
        background: var(--errStrong);
        opacity: 0.6;
    }

.ph-v2-stat-label {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--su-text-muted);
    line-height: 1;
}

.ph-v2-stat-value {
    font-size: clamp(1.05rem, 2vw, 1.25rem);
    font-weight: 800;
    letter-spacing: -0.3px;
    line-height: 1.1;
}

.ph-v2-stat-meta {
    font-size: 0.68rem;
    color: var(--su-text-muted);
    line-height: 1.2;
    margin-top: 1px;
}

/* Mobile stat row — slightly tighter */
.ph-v2-stats-row.mobile .ph-v2-stat {
    padding: 8px 10px;
}

.ph-v2-stats-row.mobile .ph-v2-stat-value {
    font-size: 1rem;
}

/* ── Chart wrapper — desktop and mobile variants ─────────────────────────── */
.ph-v2-chart-wrap {
    border: 1px solid var(--su-border-light);
    border-radius: var(--su-radius-lg);
    padding: 10px 4px 4px;
    background: var(--su-bg-surface);
    box-shadow: var(--su-shadow-md);
    overflow: hidden;
    transition: box-shadow var(--su-transition-slow);
}

@media (hover: hover) and (pointer: fine) {
    .ph-v2-chart-wrap:hover {
        box-shadow: var(--su-shadow-lg);
    }
}

.ph-v2-chart-wrap.mobile {
    padding: 6px 2px 2px;
    border-radius: var(--su-radius-md);
}

    /* Prevent chart SVG clipping axis labels */
    .ph-v2-chart-wrap .mud-chart-line,
    .ph-v2-chart-wrap.mobile .mud-chart-line {
        overflow: visible;
    }

/* ── Mobile toggle button ─────────────────────────────────────────────────── */
.ph-v2-mobile-toggle {
    width: 100%;
    background: transparent;
    border: none;
    padding: 14px 16px;
    cursor: pointer;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--su-transition-base);
}

    .ph-v2-mobile-toggle:active {
        background-color: var(--su-bg-hover);
    }

@media (hover: hover) and (pointer: fine) {
    .ph-v2-mobile-toggle:hover {
        background-color: var(--su-bg-hover);
    }
}

.ph-v2-mobile-toggle-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.ph-v2-mobile-left {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.ph-v2-mobile-sublabel {
    font-size: 0.72rem;
    color: var(--su-text-muted);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Mobile expanded body ─────────────────────────────────────────────────── */
.ph-v2-mobile-body {
    padding: 0 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    border-top: 1px solid var(--su-border-light);
    padding-top: 12px;
    animation: su-fade-in 0.2s ease-in-out;
}

/* Period buttons — scroll horizontally if needed */
.ph-v2-mobile-periods {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
}

    .ph-v2-mobile-periods::-webkit-scrollbar {
        display: none;
    }

/* Force-light override REMOVED in Phase 2 (theme system). It pinned these
   rules to their light colours whenever the DEVICE asked for dark, which both
   defeats the theme system and ignores an explicit light/dark choice. The base
   rules are token-driven and cover both modes. See DEVIATIONS D11. */
.phs-trend-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 28px;
    padding: 0 10px;
    border: 1px solid;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    align-self: center; /* use baseline if you want it slightly lower */
}

.phs-trend-icon {
    font-size: 16px !important;
}

.pd-price-was {
    text-decoration: line-through;
    color: var(--mud-palette-text-secondary);
    font-size: 0.95rem;
    align-self: flex-end;
    padding-bottom: 4px;
}

.pd-history-inline {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
    padding: 8px 0 4px;
    font-size: 0.84rem;
    color: var(--mud-palette-text-secondary);
}

.pd-history-pill {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 8px;
    border: 1px solid;
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 700;
    white-space: nowrap;
    flex-shrink: 0;
}

.pd-history-item {
    white-space: nowrap;
}

.pd-history-date {
    color: var(--mud-palette-text-secondary);
    opacity: 0.9;
}

.pd-history-link {
    min-width: auto !important;
    padding: 0 !important;
    font-size: 0.78rem !important;
    text-transform: none !important;
}

@media (max-width: 600px) {
    .pd-history-inline {
        gap: 6px 10px;
        font-size: 0.8rem;
    }

    .pd-history-item {
        white-space: normal;
    }
}

.pd-history-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 6px;
    font-size: 0.82rem;
    color: var(--mud-palette-text-secondary);
}

/* ============================================================
   HOME PAGE — SSR STATIC BLOCK
   These styles apply to the static SSR fallback content.
   The interactive block uses your existing su-home styles.
   ============================================================ */

/* Hero text */
.su-home-static-hero {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 1.5rem;
    padding: 0 1rem;
}

.su-home-static-h1 {
    font-size: 1.4rem;
    font-weight: 600;
    margin-bottom: 0.75rem;
    color: var(--mud-palette-text-primary);
    line-height: 1.3;
}

.su-home-static-tagline {
    color: var(--mud-palette-text-secondary);
    font-size: 0.9rem;
    line-height: 1.6;
    margin: 0;
}

/* Store list */
.su-home-static-stores {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    max-width: 680px;
    margin: 20px auto;
    padding: 0 1rem 1rem;
}

.su-home-static-stores-label {
    font-size: 0.75rem;
    color: var(--mud-palette-text-disabled);
    margin-right: 0.25rem;
}

.su-home-static-store {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 2px 10px;
    border-radius: 999px;
}

    /* Supermarket brands — the one exception to "every colour is a token"
       (hard rule 8), now centralised. These used to be a third, divergent set of
       hex values; they are the same values C# reads off Enums.StoreEnum.

       --brandtext-* is the identity colour nudged until it clears AA against the
       current mode's surface. ALDI's #1B3774 navy is fine on white and 1.6:1 on
       a dark surface, so dark mode lifts it to #7687AC — same hue, still ALDI,
       actually readable. --brandsoft-* is the identity colour at 8%. */
    /* Batch 1 moved the brand colour off the pill and onto a 9px swatch inside
       it, per the Home preview: the pill itself is surface + border like every
       other pill on the page, and the brand reads as a marker rather than as a
       wash. --brandtext-* rather than the raw --store-* value because a solid
       swatch still has to be visible against the current surface. */
    .su-store-square.coles {
        background: var(--brandtext-coles);
    }

    .su-store-square.woolworths {
        background: var(--brandtext-woolworths);
    }

    .su-store-square.aldi {
        background: var(--brandtext-aldi);
    }

    .su-store-square.iga {
        background: var(--brandtext-iga);
    }

    .su-store-square.costco {
        background: var(--brandtext-costco);
    }

@media (max-width: 600px) {

    .su-home-static-h1 {
        font-size: 1.25rem;
    }
}

@media (max-width: 600px) {
    .su-home-static-h1 {
        font-size: 1.1rem; /* was 1.25rem — saves about a line */
    }

    .su-home-static-tagline {
        font-size: 0.78rem; /* was 0.9rem — tighter */
        line-height: 1.5;
    }

    .su-home-static-hero {
        margin-bottom: 1rem; /* was 1.5rem — tighten gap to search */
    }
}

/* =============================================================================
   COMPONENTS - SSR NAVBAR PLACEHOLDER
   Shown during prerender before MudBlazor paints .mud-layout.
   Uses the same design tokens as .su-appbar-top-bar so the transition
   is invisible to the user.
   Hidden automatically via CSS :has() + sibling selector once Blazor
   hydrates and .mud-layout appears — zero JavaScript required.
   ============================================================================= */

.ssr-navbar-placeholder {
    /* Match .su-appbar-top-bar exactly */
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    z-index: 1300 !important;
    transform: none !important;
    will-change: auto !important;
    display: flex;
    align-items: center;
    /* Match the exact padding from .su-appbar-top-bar */
    padding-top: calc(var(--su-space-xs) + var(--su-safe-top)) !important;
    padding-bottom: var(--su-space-xs);
    padding-left: clamp(8px, 2vw, 20px);
    padding-right: clamp(8px, 2vw, 20px);
    /* Glass effect — matches .su-appbar-top-bar */
    background: var(--su-bg-glass);
    border-radius: 0 0 var(--su-radius-lg) var(--su-radius-lg);
    box-shadow: var(--su-shadow-md);
    /* Height matches MudAppBar default */
    height: 64px;
    gap: 12px;
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .ssr-navbar-placeholder {
        -webkit-backdrop-filter: blur(14px) saturate(160%);
        backdrop-filter: blur(14px) saturate(160%);
    }
}

@media (max-width: 600px) {
    .ssr-navbar-placeholder {
        height: 56px;
        padding-top: calc(6px + var(--su-safe-top)) !important;
        padding-bottom: 6px;
        padding-left: 8px;
        padding-right: 8px;
        border-radius: 0 0 var(--su-radius-md) var(--su-radius-md);
        gap: 8px;
    }
}

/* ── Hamburger menu skeleton — left side ───────────────────────────────── */
.ssr-navbar-placeholder__menu {
    width: 40px;
    height: 40px;
    border-radius: var(--su-radius-round);
    background: var(--su-bg-hover);
    flex-shrink: 0;
    /* Subtle shimmer so it doesn't look broken */
    /* Skeleton shimmer. An opaque --field base with a translucent --shine sweep
       over it: --shine is white at 55% in light and 8% in dark, so the highlight
       reads correctly against either. Kept as background-color + background-image
       so the transparent stops composite over the base rather than the page. */
    background-color: var(--field);
    background-image: linear-gradient(90deg, transparent 25%, var(--shine) 50%, transparent 75%);
    background-size: 200% 100%;
    animation: ssr-shimmer 1.5s infinite;
}

@media (max-width: 600px) {
    .ssr-navbar-placeholder__menu {
        width: 36px;
        height: 36px;
    }
}

/* ── Logo skeleton — matches .su-navbar-logo dimensions ───────────────── */
.ssr-navbar-placeholder__logo {
    /* Mirrors the logo image dimensions from su-navbar-logo */
    width: clamp(90px, 15vw, 140px);
    height: 36px;
    border-radius: var(--su-radius-sm);
    flex-shrink: 0;
    /* Skeleton shimmer. An opaque --field base with a translucent --shine sweep
       over it: --shine is white at 55% in light and 8% in dark, so the highlight
       reads correctly against either. Kept as background-color + background-image
       so the transparent stops composite over the base rather than the page. */
    background-color: var(--field);
    background-image: linear-gradient(90deg, transparent 25%, var(--shine) 50%, transparent 75%);
    background-size: 200% 100%;
    animation: ssr-shimmer 1.5s infinite;
    animation-delay: 0.1s;
}

/* Hide logo on mobile — matches your layout B (no logo on small screens) */
@media (max-width: 600px) {
    .ssr-navbar-placeholder__logo {
        display: none;
    }
}

/* ── Search bar skeleton — matches .su-search-wrapper exactly ─────────── */
.ssr-navbar-placeholder__search {
    flex: 1;
    /* Matches su-search-container max-width */
    max-width: 584px;
    height: 46px;
    /* Matches su-search-wrapper: pill shape, surface bg, shadow */
    border-radius: var(--su-radius-full);
    background: var(--su-bg-surface);
    box-shadow: var(--su-shadow-sm);
    border: 1px solid var(--border);
    margin: 0 auto;
    /* Inner search icon hint — mimics the real search bar */
    display: flex;
    align-items: center;
    padding: 0 16px;
    gap: 10px;
    pointer-events: none;
}

    /* Search icon dot */
    .ssr-navbar-placeholder__search::before {
        content: '';
        width: 20px;
        height: 20px;
        border-radius: var(--su-radius-round);
        background: var(--hoverWash);
        flex-shrink: 0;
    }

    /* Search text hint line */
    .ssr-navbar-placeholder__search::after {
        content: '';
        flex: 1;
        height: 14px;
        border-radius: var(--su-radius-sm);
        background: var(--hoverWash);
        max-width: 200px;
    }

/* Mobile: search fills available space between two icon buttons */
@media (max-width: 600px) {
    .ssr-navbar-placeholder__search {
        max-width: 100%;
        height: 40px;
        border-radius: var(--su-radius-xl);
        margin: 0;
        padding: 0 12px;
    }
}

/* ── Right side icon group — account + categories ──────────────────────── */
.ssr-navbar-placeholder__icons {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

.ssr-navbar-placeholder__icon {
    width: 40px;
    height: 40px;
    border-radius: var(--su-radius-round);
    /* Skeleton shimmer. An opaque --field base with a translucent --shine sweep
       over it: --shine is white at 55% in light and 8% in dark, so the highlight
       reads correctly against either. Kept as background-color + background-image
       so the transparent stops composite over the base rather than the page. */
    background-color: var(--field);
    background-image: linear-gradient(90deg, transparent 25%, var(--shine) 50%, transparent 75%);
    background-size: 200% 100%;
    animation: ssr-shimmer 1.5s infinite;
    flex-shrink: 0;
}

    .ssr-navbar-placeholder__icon:nth-child(2) {
        animation-delay: 0.2s;
    }

@media (max-width: 600px) {
    .ssr-navbar-placeholder__icon {
        width: 36px;
        height: 36px;
    }
}

/* ── Shimmer animation ─────────────────────────────────────────────────── */
@keyframes ssr-shimmer {
    0% {
        background-position: 200% 0;
    }

    100% {
        background-position: -200% 0;
    }
}

/* ── Auto-hide once Blazor hydrates ────────────────────────────────────── */
/*
 * Strategy 1: :has() selector — hides placeholder when .mud-layout
 * exists anywhere on the page. Supported in Chrome 105+, Safari 15.4+,
 * Firefox 121+. Covers the vast majority of your users.
 */
body:has(.mud-layout) .ssr-navbar-placeholder {
    display: none !important;
}

/*
 * Strategy 2: Adjacent sibling selector — placeholder must be placed
 * IMMEDIATELY before the Blazor Routes component in App.razor.
 * Works in all browsers as a fallback.
 */
.mud-layout ~ .ssr-navbar-placeholder {
    display: none !important;
}

/*
 * Strategy 3: MAUI hybrid — hide entirely on native app.
 * MAUI renders the nav natively or handles it differently.
 */
body.is-hybrid .ssr-navbar-placeholder {
    display: none !important;
}

/* Force-light override REMOVED in Phase 2 (theme system). It pinned these
   rules to their light colours whenever the DEVICE asked for dark, which both
   defeats the theme system and ignores an explicit light/dark choice. The base
   rules are token-driven and cover both modes. See DEVIATIONS D11. */
/* =============================================================================
   END SSR NAVBAR PLACEHOLDER
   ============================================================================= */

/* =============================================================================
   AUTHORIZING SKELETON — shared shimmer utility
   Used in Routes.razor <Authorizing> block
   ============================================================================= */
.ssr-skel {
    /* Skeleton shimmer. An opaque --field base with a translucent --shine sweep
       over it: --shine is white at 55% in light and 8% in dark, so the highlight
       reads correctly against either. Kept as background-color + background-image
       so the transparent stops composite over the base rather than the page. */
    background-color: var(--field);
    background-image: linear-gradient(90deg, transparent 25%, var(--shine) 50%, transparent 75%);
    background-size: 200% 100%;
    animation: ssr-shimmer 1.5s infinite;
    flex-shrink: 0;
}

/* Mobile — collapse to single column */
@media (max-width: 600px) {
    .ssr-skel[style*="width:420px"],
    .ssr-skel[style*="height:420px"] {
        height: 260px !important;
    }
}

/* Force-light override REMOVED in Phase 2 (theme system). It pinned these
   rules to their light colours whenever the DEVICE asked for dark, which both
   defeats the theme system and ignores an explicit light/dark choice. The base
   rules are token-driven and cover both modes. See DEVIATIONS D11. */
.su-home-static-h1 {
    font-size: 1.4rem;
    font-weight: 600;
    margin-bottom: 0.75rem;
    color: var(--mud-palette-text-primary);
    line-height: 1.3;
    border: none; /* ← add this */
    outline: none; /* ← add this */
}

h1, h2, h3, h4, h5, h6 {
    border: none;
    outline: none;
}

/* ── Blazor reconnect flash suppression ─────────────────────────────────── */

/* Dim content while disconnected — keeps layout stable, no jarring blank */
body.blazor-disconnected .su-main-content {
    opacity: 0.4;
    pointer-events: none;
    transition: opacity 0.2s ease;
}

/* Fade back in smoothly after reconnect */
body.blazor-reconnected .su-main-content {
    opacity: 1;
    transition: opacity 0.3s ease;
}

/* Spinner inside reconnect modal */
.reconnect-spinner {
    width: 24px;
    height: 24px;
    border: 3px solid var(--border);
    border-top-color: var(--mud-palette-primary, var(--infoText));
    border-radius: 50%;
    animation: reconnect-spin 0.8s linear infinite;
    flex-shrink: 0;
}

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

/* =============================================================================
   ONBOARDING MODAL
   ============================================================================= */
.onboarding-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(4px);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.onboarding-card {
    background: var(--su-bg-surface);
    border-radius: 24px;
    width: 100%;
    max-width: 390px;
    padding: 28px 24px 20px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    box-shadow: var(--su-shadow-xl);
}

/* Dots */
.onboarding-dots {
    display: flex;
    justify-content: center;
    gap: 8px;
}

.onboarding-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--su-border-default);
    transition: all 0.25s ease;
}

    .onboarding-dot.active {
        width: 28px;
        border-radius: 4px;
        background: var(--mud-palette-primary);
    }

/* Slide area */
.onboarding-slide {
    min-height: 270px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
}

/* Icon wrapper */
/* The art tile. Each slide used to carry its own inline
   linear-gradient of two pastels — mint, peach, pink, lilac, powder blue —
   with the glyph in a matching dark hue. Sixty hardcoded colours across the
   five slides, all of them light-mode: in dark they would have been pale boxes
   with near-black icons floating on a near-black card. The gradient is the
   preview's --heroA to --field, which follows the theme. */
.ob-icon-wrapper {
    width: 80px;
    height: 80px;
    border-radius: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
    flex-shrink: 0;
    background: linear-gradient(150deg, var(--heroA), var(--field));
}

    /* Sizes live here now too: they were inline on every MudIcon, which is why
       removing the colour meant taking the font-size with it. */
    .ob-icon-wrapper .mud-icon-root {
        font-size: 42px;
        color: var(--primary);
    }

/* Text */
.ob-title {
    font-size: 21px;
    font-weight: 700;
    color: var(--su-text-primary);
    margin: 0;
    line-height: 1.3;
}

.ob-desc {
    font-size: 14px;
    color: var(--su-text-secondary);
    line-height: 1.65;
    margin: 0;
    padding: 0 4px;
}

/* Tags row (slide 0) */
.ob-tags {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 4px;
}

.ob-tag {
    display: inline-flex;
    align-items: center;
    background: rgba(var(--mud-palette-primary-rgb), 0.1);
    color: var(--mud-palette-primary);
    font-size: 12px;
    font-weight: 500;
    padding: 5px 12px;
    border-radius: 20px;
}

/* Feature list (slides 1-4) */
.ob-feature-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 0 2px;
}

.ob-feature {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 14px;
    color: var(--su-text-primary);
    line-height: 1.4;
}

.ob-feature-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--field);
}

    /* Was a different pastel per row — the colours carried no meaning, they
       just cycled. One quiet tile with the glyph in --primary reads as a list
       rather than as five unrelated badges. */
    .ob-feature-icon .mud-icon-root {
        font-size: 18px;
        color: var(--primary);
    }

/* Pro badge */
.ob-pro-badge {
    display: inline-block;
    /* Same as the access header: two amber tones collapse to one token, so the
       second stop is --warnText, the ramp's darker end. */
    background: linear-gradient(135deg, var(--warnStrong), var(--warnText));
    color: white;
    font-size: 10px;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 10px;
    margin-left: 6px;
    vertical-align: middle;
    letter-spacing: 0.3px;
}

/* Nav bar */
.onboarding-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-top: 1px solid var(--su-border-light);
    padding-top: 16px;
}

/* The step label. --primary, small and lettered out, because it is a position
   marker rather than a heading — the preview's .ob-step. */
.onboarding-step {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--primary);
}

/* Skip, top-right as a pill. Replaces both the bare X that sat here and the
   text "Skip" that sat next to Back at the bottom — one control, named for what
   it does. A cross can read as "close this for now"; Skip cannot. */
.onboarding-skip-top {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 5px 13px;
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    color: var(--textMut);
    cursor: pointer;
    transition: color .16s ease, border-color .16s ease;
}

@media (hover: hover) and (pointer: fine) {
    .onboarding-skip-top:hover {
        color: var(--text);
        border-color: var(--textMut);
    }
}

.onboarding-back {
    background: none;
    border: none;
    color: var(--su-text-secondary);
    font-size: 14px;
    cursor: pointer;
    padding: 8px 4px;
    display: flex;
    align-items: center;
    transition: color 0.2s;
}

    .onboarding-back:hover {
        color: var(--su-text-primary);
    }

.onboarding-next {
    background: var(--mud-palette-primary);
    color: white;
    border: none;
    border-radius: 24px;
    padding: 11px 26px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s;
    display: flex;
    align-items: center;
}

    .onboarding-next:hover {
        opacity: 0.9;
    }

/* Fix 1 — nav left side holds both Back and Skip */
.onboarding-nav-left {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* Logo on welcome slide */
.ob-logo-wrapper {
    width: 90px;
    height: 90px;
    border-radius: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--su-bg-elevated);
    padding: 12px;
    margin-bottom: 4px;
}

.ob-logo-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Header row — dots centred, close button right */
.onboarding-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
}

    /* Make dots take up remaining space so they stay centred */
    .onboarding-header .onboarding-dots {
        flex: 1;
        display: flex;
        justify-content: center;
        gap: 8px;
    }

/* Close button */

/* AlternativeProductsDialog — prevent button row overflow on mobile */
.su-alternatives-dialog .mud-card-actions {
    flex-wrap: wrap !important;
    gap: 4px;
    padding: 6px 8px 8px !important;
}

    .su-alternatives-dialog .mud-card-actions .mud-button-root {
        flex: 1 1 auto;
        min-width: 0;
        font-size: 0.65rem !important;
        padding: 4px 6px !important;
    }

/* Tighter card content on mobile */
@media (max-width: 600px) {
    .su-alternatives-dialog .mud-card-content {
        padding: 8px !important;
    }

    .su-alt-image-container {
        height: 120px !important;
    }

    .su-alt-title {
        font-size: 0.78rem;
    }
}

/* Allow page scroll when touch starts on carousel */
.pd-gallery-card .mud-carousel,
.pd-gallery-card .mud-carousel-item,
.pd-gallery-card .mud-carousel-item > div {
    touch-action: pan-y !important;
}

/* Also allow scroll over the carousel arrows */
.pd-gallery-card .mud-carousel-prev,
.pd-gallery-card .mud-carousel-next {
    touch-action: pan-y !important;
}

/* ListAlternativeProductsDialog — 2-up grid on mobile */
.su-alternatives-dialog .mud-card-content.pa-3 {
    padding: 8px 10px 4px !important;
}

.su-alternatives-dialog .mud-card-actions.px-3 {
    padding-left: 8px !important;
    padding-right: 8px !important;
}

.su-alternatives-dialog .su-alt-image-container {
    height: 130px !important;
}

@media (max-width: 400px) {
    .su-alternatives-dialog .su-alt-image-container {
        height: 100px !important;
    }
}

/* Make alternatives dialog wider on mobile — removes default margins */
.su-alternatives-dialog.mud-dialog {
    margin: 0 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    border-radius: 16px 16px 0 0 !important;
    position: fixed !important;
    bottom: 0 !important;
    top: auto !important;
}

/* Full width content inside */
.su-alternatives-dialog .mud-dialog-content {
    padding: 8px 10px !important;
    max-height: 75vh !important;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
}

/* Tighten card actions so buttons don't clip */
.su-alternatives-dialog .mud-card-actions {
    padding: 4px 6px 8px !important;
    flex-wrap: nowrap !important;
    gap: 4px;
    justify-content: space-between;
}

/* Shrink LIST/FAV button text on mobile */
@media (max-width: 480px) {
    .su-alternatives-dialog .mud-card-actions .mud-button-root {
        font-size: 0.6rem !important;
        padding: 4px 5px !important;
        min-width: 0 !important;
    }

    .su-alternatives-dialog .mud-card-actions .mud-icon-root {
        font-size: 14px !important;
        margin-right: 2px !important;
    }

    .su-alternatives-dialog .mud-card-content {
        padding: 6px 8px 2px !important;
    }

    .su-alternatives-dialog .su-alt-image-container {
        height: 110px !important;
    }

    /* Tighter title */
    .su-alternatives-dialog .mud-dialog-title {
        padding: 12px 14px 6px !important;
    }
}

/* Carousel — allow vertical touch scroll to pass through to page */
.pd-gallery-card .mud-carousel {
    touch-action: pan-y !important;
}

.pd-gallery-card .mud-carousel-item {
    touch-action: pan-y !important;
}

    /* The inner slide div MudBlazor generates */
    .pd-gallery-card .mud-carousel-item > div {
        touch-action: pan-y !important;
        pointer-events: none;
    }

/* Re-enable pointer events only on arrows */
.pd-gallery-card .mud-carousel-prev,
.pd-gallery-card .mud-carousel-next {
    pointer-events: auto !important;
    touch-action: manipulation !important;
}

.su-search-skeleton-wrapper {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
    max-width: 680px; /* match SearchBox max-width */
    margin: 0 auto;
    padding: 0 8px;
}

.su-search-skeleton-input {
    border-radius: 24px !important; /* pill shape like the real input */
}

.su-search-skeleton-buttons {
    display: flex;
    gap: 8px;
    justify-content: center;
}

/* wwwroot/css/cuugo-tutorial.css
   Optional styling overrides for the Driver.js popovers.
   Add a <link> for this in App.razor after the Driver.js CSS loads,
   or paste these rules into your existing site CSS. */

.cuugo-driver-popover {
    border-radius: 12px !important;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18) !important;
    font-family: var(--mud-typography-default-family, inherit) !important;
    /* Driver.js ships its own CSS from a CDN and hardcodes a white popover.
       Its title and description are themed just below, so without this the
       tour renders near-white text on a white card in dark mode. The CDN
       stylesheet is injected at runtime and therefore wins on order, which is
       why every rule here is !important. */
    background-color: var(--surface) !important;
    color: var(--text) !important;
}

    /* The arrow is a bordered triangle, so it needs the surface colour on
       whichever side is pointing at the highlighted element. */
    .cuugo-driver-popover .driver-popover-arrow-side-left {
        border-left-color: var(--surface) !important;
    }

    .cuugo-driver-popover .driver-popover-arrow-side-right {
        border-right-color: var(--surface) !important;
    }

    .cuugo-driver-popover .driver-popover-arrow-side-top {
        border-top-color: var(--surface) !important;
    }

    .cuugo-driver-popover .driver-popover-arrow-side-bottom {
        border-bottom-color: var(--surface) !important;
    }

    .cuugo-driver-popover .driver-popover-title {
        font-size: 1.05rem !important;
        font-weight: 600 !important;
        color: var(--mud-palette-text-primary, var(--text)) !important;
    }

    .cuugo-driver-popover .driver-popover-description {
        font-size: 0.9rem !important;
        line-height: 1.5 !important;
        color: var(--mud-palette-text-secondary, var(--textMut)) !important;
    }

    .cuugo-driver-popover .driver-popover-progress-text {
        font-size: 0.75rem !important;
        color: var(--mud-palette-text-disabled, var(--textMut)) !important;
    }

    /* Match MudBlazor primary button styling */
    .cuugo-driver-popover .driver-popover-next-btn {
        background: var(--mud-palette-primary, var(--primary)) !important;
        color: var(--mud-palette-primary-text, #fff) !important;
        border: none !important;
        text-shadow: none !important;
        border-radius: 6px !important;
        padding: 6px 14px !important;
        font-weight: 500 !important;
    }

        .cuugo-driver-popover .driver-popover-next-btn:hover {
            background: var(--mud-palette-primary-darken, var(--primaryHover)) !important;
        }

    .cuugo-driver-popover .driver-popover-prev-btn {
        background: transparent !important;
        color: var(--mud-palette-text-secondary, var(--textMut)) !important;
        text-shadow: none !important;
        border: 1px solid var(--mud-palette-divider, var(--border)) !important;
        border-radius: 6px !important;
        padding: 6px 14px !important;
    }

    .cuugo-driver-popover .driver-popover-close-btn {
        color: var(--mud-palette-text-secondary, var(--textMut)) !important;
    }

/* ============================================================
   Cuugo brand loader ("orbit") — CU. mark with two orbiting dots.
   Reusable: lives in Blerc.SharedUI so any project that links
   this stylesheet gets it. Renders before Blazor boots.
   ============================================================ */

.cuugo-loader {
    position: fixed;
    inset: 0;
    display: grid;
    place-items: center;
    background: var(--surface); /* match the first app screen to avoid a colour flash */
}

.cl-orbit {
    position: relative;
    width: 150px;
    height: 150px;
}

/* the breathing brand mark in the middle */
.cl-mark {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    animation: cl-breathe 1.8s ease-in-out infinite;
}

    .cl-mark img {
        width: 86px;
        height: auto;
    }

/* two rings, each carrying one dot, rotating in sync but 180 degrees apart */
.cl-ring {
    position: absolute;
    inset: 0;
    animation: cl-spin 1.5s linear infinite;
}

    .cl-ring .cl-dot {
        position: absolute;
        top: 0;
        left: 50%;
        width: 15px;
        height: 15px;
        margin-left: -7.5px;
        border-radius: 50%;
        animation: cl-pulse 1.5s ease-in-out infinite;
    }

.cl-ring-coral .cl-dot {
    background: #ff7675;
}

.cl-ring-teal {
    animation-delay: -0.75s; /* sits opposite the coral dot */
}

    .cl-ring-teal .cl-dot {
        background: #00b894;
    }

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

@keyframes cl-breathe {
    0%, 100% {
        transform: scale(0.94);
    }

    50% {
        transform: scale(1);
    }
}

@keyframes cl-pulse {
    0%, 100% {
        transform: scale(0.7);
    }

    50% {
        transform: scale(1.1);
    }
}

/*.su-search-buttons {
    display: flex;
    align-items: center;
    gap: 8px;
}*/

    /* the MudTooltip wrapper around the frisky button + info icon */
    /*.su-search-buttons .mud-tooltip-root {
        display: inline-flex;
        align-items: center;
        gap: 4px;
    }*/

.su-search-buttons {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

    /* the MudTooltip wrapper around the frisky button + info icon */
    .su-search-buttons .mud-tooltip-root {
        display: inline-flex;
        align-items: center;
        gap: 4px;
    }

.cuugo-ptr-indicator {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 56px;
    margin-top: -56px;
    pointer-events: none;
    opacity: 0;
    z-index: 2000;
    transition: transform .2s ease,opacity .2s ease;
}

.cuugo-ptr-spinner {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 3px solid var(--border);
    border-top-color: var(--mud-palette-primary,var(--savings));
}

.cuugo-ptr-refreshing .cuugo-ptr-spinner {
    animation: cuugo-ptr-spin .8s linear infinite;
}

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

/* SharedUI.css */
.su-tz-autocomplete.mud-input-control {
    width: 100% !important;
    min-width: 200px;
}

/* Keyboard-aware: cap the inline home suggestion dropdown to the gap
   above the keyboard so its bottom can't slide underneath. */
.kb-open .su-home .su-suggestions-dropdown.below {
    max-height: calc(var(--vv-height, 100dvh) - 120px);
    overflow-y: auto;
}

/* =============================================================================
   THEME PICKER
   =============================================================================
   Styled entirely from theme tokens - zero hex here, per hard rule 8. The chips
   mirror cuugo-theme-preview.html: a dot swatch plus the name, and the selected
   chip wears its own dot as its background.
   ============================================================================= */
.su-theme-picker {
    display: flex;
    flex-direction: column;
    gap: var(--su-space-md);
    font-family: var(--font-ui);
}

/* -- mode segmented control -- */
.su-theme-modes {
    display: inline-flex;
    align-self: flex-start;
    border: 1px solid var(--border);
    border-radius: var(--su-radius-md);
    overflow: hidden;
    background: var(--surface);
}

.su-theme-mode {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border: none;
    background: transparent;
    color: var(--textMut);
    font: inherit;
    font-size: var(--su-text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: background var(--su-transition-fast), color var(--su-transition-fast);
}

.su-theme-mode + .su-theme-mode {
    border-left: 1px solid var(--border);
}

@media (hover: hover) {
    .su-theme-mode:hover:not(.su-theme-mode-on) {
        background: var(--hoverWash);
        color: var(--text);
    }
}

.su-theme-mode-on {
    background: var(--primary);
    color: var(--onPrimary);
}

.su-theme-mode:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* -- theme chips -- */
.su-theme-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--su-space-sm);
}

.su-theme-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border: 1px solid var(--border);
    border-radius: var(--su-radius-full);
    background: var(--surface);
    color: var(--textMut);
    font: inherit;
    font-size: var(--su-text-sm);
    font-weight: 600;
    cursor: pointer;
    transition: color var(--su-transition-fast), border-color var(--su-transition-fast);
}

@media (hover: hover) {
    .su-theme-chip:hover:not(.su-theme-chip-on) {
        color: var(--text);
        border-color: var(--primary);
    }
}

/* The selected chip is filled with the theme's own dot colour, as in the
   preview. The label cannot inherit --text: the dots run from Melbourne Cup's
   near-black racing green to Halloween's bright pumpkin, so the readable label
   colour differs per theme. --theme-dot-on is computed per theme from the dot's
   own luminance - see ThemeCssBuilder.ReadableOn. */
.su-theme-chip-on {
    color: var(--theme-dot-on);
    font-weight: 700;
}

.su-theme-chip-on .su-theme-dot {
    box-shadow: inset 0 0 0 1px var(--hoverWash), 0 0 0 2px var(--surface);
}

.su-theme-chip:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.su-theme-dot {
    width: 12px;
    height: 12px;
    border-radius: var(--su-radius-round);
    flex: none;
    box-shadow: inset 0 0 0 1px var(--hoverWash);
}

.su-theme-note {
    margin: 0;
    color: var(--textMut);
    font-size: var(--su-text-sm);
    line-height: 1.55;
    max-width: 62ch;
}

.su-theme-note-muted {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    border-radius: var(--su-radius-lg);
    background: var(--infoSoft);
    color: var(--infoText);
}

/* -- app-bar shortcut -- */
.su-theme-menu {
    padding: 10px 14px 4px;
    min-width: 290px;
    max-width: 340px;
}

.su-theme-menu .su-theme-chips {
    max-height: 232px;
    overflow-y: auto;
}

/* =============================================================================
   BATCH 1 — HOME + SEARCHBOX
   =============================================================================

   Everything here is scoped to a modifier class (.su-search-hero, .su-home-*)
   so the same SearchBox keeps its compact app-bar appearance on every other
   page, and so RotoOs — which never sets these classes — is untouched.

   Visual source of truth: docs/redesign/cuugo-home-preview.html.
   Colours are theme tokens only; the store-brand squares reuse the --store-*
   tokens generated from Enums.StoreEnum (hard rule 8's one exception).
   ============================================================================= */

/* -----------------------------------------------------------------------------
   The search bar as the page's hero object
   Preview: .search — pill, 1.5px border, two-layer primary-tinted glow.
   -------------------------------------------------------------------------- */
.su-search-hero {
    max-width: 640px;
    /* One source of truth for the bar's border width: the panel below has to
       cancel it out to line its own border up (see .su-suggestions-dropdown
       below), and the two drifting apart is what produced the 1px step.
       A whole pixel on purpose — 1.5px rounds to 1 device px at DPR 1 while a
       calc(-1 * 1.5px) offset does not, which leaves a half-pixel fringe. */
    --su-hero-border: 1px;
}

.su-search-hero .su-search-wrapper {
    border: var(--su-hero-border) solid var(--fieldBorder);
    border-radius: 999px !important;
    background: var(--surface);
    box-shadow: 0 2px 10px var(--searchGlow1), 0 10px 34px var(--searchGlow2) !important;
    transition: box-shadow .18s ease, border-color .18s ease;
}

.su-search-hero .su-search-wrapper:hover,
.su-search-hero .su-search-wrapper:focus-within {
    border-color: var(--primary);
    box-shadow: 0 2px 12px var(--searchGlow1), 0 12px 40px var(--searchGlow2) !important;
}

/* Open state squares the bottom corners onto the panel and drops the shared
   edge, so bar + panel read as one object. */
.su-search-hero .su-search-wrapper.open.position-top {
    border-color: var(--primary);
    border-bottom-color: transparent;
    border-radius: 26px 26px 0 0 !important;
    /* Glow upward only. A downward offset spills onto the panel below and
       leaves a faint seam across the join — same reasoning as the panel's
       shadow, from the other side. */
    box-shadow: 0 -3px 10px var(--searchGlow1) !important;
}

.su-search-hero .su-search-wrapper.open.position-bottom {
    border-color: var(--primary);
    border-top-color: transparent;
    border-radius: 0 0 26px 26px !important;
}

.su-search-hero .su-search-row {
    padding: 4px 10px 4px 18px;
    gap: 4px;
}

.su-search-hero .su-search-field .mud-input {
    font-size: 16px;
    font-weight: 500;
    font-family: var(--font-ui);
    padding: 11px 0;
}

.su-search-hero .su-search-field .mud-input::placeholder,
.su-search-hero .su-search-field .mud-input input::placeholder {
    color: var(--textMut);
    font-weight: 400;
    opacity: 1;
}

/* The compact bar overlays its end icons on top of the input's right padding.
   The hero bar has a Scan affordance living there, so the icons go back into
   normal flow — otherwise the clear button lands on top of the Scan label. */
.su-search-hero .su-search-end-icons {
    position: static;
    transform: none;
    margin-left: 2px;
}

.su-search-hero .su-search-field.with-end-icons .mud-input {
    padding-right: 0;
}

.su-search-hero .su-search-icon-btn {
    width: 34px;
    height: 34px;
}

/* Leading magnifier — brand-coloured, matching the preview's .sicon */
.su-search-lead-icon {
    color: var(--primary) !important;
    flex: none;
    margin-right: 8px;
}

/* -----------------------------------------------------------------------------
   Integrated Scan affordance
   Preview: .scan — divider, icon, label. The label collapses on mobile so the
   barcode scanner stays a headline capability without eating the input.
   -------------------------------------------------------------------------- */
.su-search-scan {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
    padding: 7px 12px 7px 10px;
    margin-left: 2px;
    border: none;
    background: transparent;
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1;
    border-radius: 999px;
    cursor: pointer;
    text-transform: none;
    transition: color .13s ease, background-color .13s ease;
}

.su-search-scan:hover,
.su-search-scan:focus-visible {
    color: var(--primary);
    background: var(--hoverWash);
}

.su-search-scan .mud-icon-root {
    font-size: 19px;
}

.su-search-scan-divider {
    width: 1px;
    height: 22px;
    flex: none;
    background: var(--border);
    margin: 0 2px;
}

@media (max-width: 700px) {
    .su-search-scan-label {
        display: none;
    }

    .su-search-scan {
        padding: 7px 9px;
    }
}

/* -----------------------------------------------------------------------------
   Autocomplete panel — three zones
   -------------------------------------------------------------------------- */
/* An absolutely positioned child is laid out against its ancestor's PADDING
   box, so `left: 0` puts this panel's border one border-width inside the bar's
   — a 1px step down each side where the two are meant to read as one object.
   Pulling out by the bar's own border width makes the border boxes coincide. */
.su-search-hero .su-suggestions-dropdown {
    left: calc(-1 * var(--su-hero-border));
    right: calc(-1 * var(--su-hero-border));
}

.su-search-hero .su-suggestions-dropdown.below {
    border: var(--su-hero-border) solid var(--primary);
    border-top: none;
    border-radius: 0 0 26px 26px !important;
    /* Blur must not exceed the Y offset. At 44px blur over an 18px offset the
       shadow reached 26px ABOVE this panel's own top edge and tinted the
       bottom of the bar, putting a visible seam across a pair that is supposed
       to read as one object. Equal values keep the shadow entirely below. */
    box-shadow: 0 22px 22px var(--searchGlow2) !important;
    background: var(--surface);
    max-height: 460px;
    overflow-y: auto;
    /* Keeps the last row clear of the rounded corner when the list scrolls. */
    padding-bottom: 6px;
}

.su-search-hero .su-suggestions-dropdown.above {
    border: var(--su-hero-border) solid var(--primary);
    border-bottom: none;
    border-radius: 26px 26px 0 0 !important;
    /* Same rule mirrored: no spill down onto the bar beneath it. */
    box-shadow: 0 -22px 22px var(--searchGlow2) !important;
    background: var(--surface);
    padding-top: 6px;
}

/* Windows draws a full-width classic scrollbar, which lands hard against the
   square top corner and inside the rounded bottom one. Thin and themed. */
.su-search-hero .su-suggestions-dropdown {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

    .su-search-hero .su-suggestions-dropdown::-webkit-scrollbar {
        width: 8px;
    }

    .su-search-hero .su-suggestions-dropdown::-webkit-scrollbar-track {
        background: transparent;
        margin: 4px 0 10px;
    }

    .su-search-hero .su-suggestions-dropdown::-webkit-scrollbar-thumb {
        background: var(--border);
        border-radius: 999px;
    }

        .su-search-hero .su-suggestions-dropdown::-webkit-scrollbar-thumb:hover {
            background: var(--textMut);
        }

/* Zone label — preview .slabel */
.su-suggest-zone {
    cursor: default !important;
    min-height: 0 !important;
    padding: 0 !important;
    background: transparent !important;
}

.su-suggest-zone:hover {
    background: transparent !important;
}

.su-suggest-zone-label {
    display: block;
    padding: 9px 22px 4px;
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--textMut);
}

/* A zone that is not the first gets the hairline separator */
.su-suggest-zone.su-suggest-zone-next .su-suggest-zone-label {
    border-top: 1px solid var(--border);
    margin-top: 5px;
    padding-top: 13px;
}

/* The panel itself is NOT hero-only. SearchBox renders one dropdown whether it
   is in the hero or the app bar, and the two looked like different components
   because these rules were scoped to .su-search-hero. Only the bar's chrome —
   the pill, the glow, the labelled Scan — stays hero-specific below.
   Safe to unscope: SearchBox is the only thing in either app that renders
   .su-suggestion-*, so nothing in RotoOs can be caught by this. */
.su-suggestion-content {
    padding: 8px 22px;
    gap: 13px;
}

.su-suggestion-icon {
    margin-right: 0;
    color: var(--textMut);
}

.su-suggestion-text {
    font-family: var(--font-ui);
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text);
}

    .su-suggestion-text .highlight {
        color: var(--primary);
        font-weight: 700;
    }

.su-suggestion-selected {
    background-color: var(--hoverWash) !important;
}

/* Product row — thumb / name + context line / best price.
   Renders only when the suggestions endpoint returns product-level rows. */
.su-suggestion-thumb {
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 9px;
    background: var(--field);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: var(--textMut);
}

.su-suggestion-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.su-suggestion-sub {
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 400;
    color: var(--textMut);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-suggestion-price {
    flex: none;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
    color: var(--savings);
    font-variant-numeric: tabular-nums;
}

/* -----------------------------------------------------------------------------
   Home — hero copy
   -------------------------------------------------------------------------- */
.su-home-static-h1 {
    font-family: var(--font-display);
    letter-spacing: -0.02em;
}

.su-home-static-tagline b {
    color: var(--savings);
    font-weight: 700;
}

/* -----------------------------------------------------------------------------
   Trending chips — rank number + rising arrow
   -------------------------------------------------------------------------- */
.su-home-trend-label {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-trending-chip {
    border: 1px solid var(--border);
    background: var(--surface) !important;
    color: var(--text);
    font-family: var(--font-ui);
}

@media (hover: hover) and (pointer: fine) {
    .su-trending-chip:hover {
        border-color: var(--primary);
        color: var(--primary);
        background: var(--surface) !important;
    }
}

.su-trend-rank {
    font-size: 11px;
    font-weight: 800;
    color: var(--primary);
    margin-right: 6px;
    font-variant-numeric: tabular-nums;
}

.su-trend-rise {
    font-size: 11px;
    line-height: 1;
    color: var(--savings);
    margin-left: 6px;
}

/* -----------------------------------------------------------------------------
   Proof strip
   -------------------------------------------------------------------------- */
.su-home-proof {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: clamp(18px, 5vw, 54px);
    width: 100%;
    margin: 30px auto 0;
}

.su-proof-stat {
    text-align: center;
}

.su-proof-value {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: clamp(21px, 3.4vw, 28px);
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--primary);
}

.su-proof-key {
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--textMut);
}

@media (max-width: 600px) {
    .su-home-proof {
        gap: 16px;
    }

    .su-proof-value {
        font-size: 19px;
    }
}

/* -----------------------------------------------------------------------------
   Store pills — brand square, name, product count
   -------------------------------------------------------------------------- */
.su-home-static-stores {
    gap: 9px;
    max-width: 760px;
    width: 100%;
    margin: 30px auto 0;
    padding: 24px 0 0;
    border-top: 1px solid var(--border);
}

.su-home-static-stores-label {
    width: 100%;
    margin: 0 0 2px;
    text-align: center;
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 600;
    color: var(--textMut);
}

.su-home-static-store {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 15px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
}

.su-store-square {
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 3px;
}

.su-store-count {
    font-size: 12px;
    font-weight: 600;
    color: var(--textMut);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
    .su-home-static-stores {
        gap: 7px;
    }

    .su-store-count {
        display: none;
    }
}

/* -----------------------------------------------------------------------------
   Blog links as cards
   -------------------------------------------------------------------------- */
.su-home-blog-links {
    width: 100%;
    max-width: 980px;
    margin: 38px auto 0;
    text-align: left;
}

.su-home-blog-heading {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: -0.015em;
    margin-bottom: 3px;
    color: var(--text);
}

.su-home-blog-sub {
    font-family: var(--font-ui);
    font-size: 13.5px;
    color: var(--textMut);
    margin-bottom: 16px;
}

.su-home-blog-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 13px;
}

@media (max-width: 780px) {
    .su-home-blog-grid {
        grid-template-columns: 1fr;
    }
}

.su-blog-card {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 15px 16px;
    border-radius: 15px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: inherit;
    text-decoration: none;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-blog-card:hover {
        border-color: var(--primary);
        transform: translateY(-2px);
        box-shadow: 0 8px 22px var(--searchGlow2);
    }
}

.su-blog-card-tag {
    align-self: flex-start;
    padding: 3px 8px;
    border-radius: 6px;
    background: var(--accentSoft);
    color: var(--accentText);
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.su-blog-card-title {
    font-family: var(--font-ui);
    font-size: 14.5px;
    font-weight: 700;
    line-height: 1.35;
    color: var(--text);
}

.su-blog-card-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: auto;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

/* -----------------------------------------------------------------------------
   FAQ accordions
   -------------------------------------------------------------------------- */
.su-home-faqs {
    width: 100%;
    max-width: 760px;
    margin: 38px auto 40px;
    text-align: left;
}

.su-home-faqs-heading {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: -0.015em;
    margin-bottom: 14px;
    text-align: center;
    color: var(--text);
}

.su-home-faqs .mud-expand-panel {
    margin-bottom: 9px !important;
    border: 1px solid var(--border);
    border-radius: 13px !important;
    background: var(--surface);
    overflow: hidden;
}

.su-home-faqs .mud-expand-panel:before {
    display: none;
}

.su-home-faqs .mud-expand-panel-header {
    padding: 14px 17px;
    font-family: var(--font-ui);
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text);
}

.su-home-faqs .mud-expand-panel-text {
    padding: 0 17px 14px;
    font-family: var(--font-ui);
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--textMut);
}

.su-home-faqs .mud-expand-panel-icon {
    color: var(--textMut);
}

.su-home-faqs .mud-expand-panel.mud-panel-expanded .mud-expand-panel-icon {
    color: var(--primary);
}

/* -----------------------------------------------------------------------------
   Mobile bottom nav
   Replaces the bottom bar's default trio when a page supplies
   MobileBottomNavContent. Five slots, centre one a raised scan FAB.
   -------------------------------------------------------------------------- */
.su-bottom-nav {
    display: flex;
    align-items: flex-end;
    justify-content: space-around;
    width: 100%;
    gap: 2px;
}

.su-bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 2px 10px;
    border: none;
    background: transparent;
    border-radius: 10px;
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--textMut);
    text-decoration: none;
    cursor: pointer;
    text-transform: none;
    min-width: 0;
}

.su-bottom-nav-item:hover {
    color: var(--text);
}

.su-bottom-nav-item.su-bottom-nav-on {
    color: var(--primary);
}

.su-bottom-nav-item .mud-icon-root {
    font-size: 20px;
}

.su-bottom-nav-fab {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-top: -24px;
    border-radius: 50%;
    border: 3px solid var(--surface);
    background: var(--primary);
    color: var(--onPrimary);
    box-shadow: 0 6px 16px var(--searchGlow2);
}

.su-bottom-nav-fab .mud-icon-root {
    font-size: 22px;
}

@media (prefers-reduced-motion: reduce) {
    .su-blog-card,
    .su-search-hero .su-search-wrapper,
    .su-search-scan {
        transition: none;
    }
}

/* =============================================================================
   BATCH 2 — SEARCH RESULTS + PRODUCT DETAIL
   =============================================================================

   Visual source of truth: docs/redesign/cuugo-search-product-preview.html.

   DATA MODEL RULE (spec, hard rule 7): a product is a single store listing.
   Nothing here renders one product with several stores' prices. The only
   cross-store surface is Alternatives — a list of *different* listings — and
   its markup is named accordingly (.su-alt-*), never "compare".
   ============================================================================= */

/* -----------------------------------------------------------------------------
   Result card
   Preview: .pcard — image / name / unit / store + price / alternatives / footer
   -------------------------------------------------------------------------- */
.su-product-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-product-card:hover {
        border-color: var(--primary);
        transform: translateY(-2px);
        box-shadow: 0 10px 26px var(--glow);
    }
}

.su-product-image-container {
    border-radius: 11px;
    /* Product photos are shot on white — see --imgPlate. This rule comes after
       the base one, so it is the one that decides. */
    background: var(--imgPlate);
    overflow: hidden;
}

/* Price drop badge — top left, savings green. Replaces the stacked
   "% OFF" + "ON SALE" chips, which said the same thing twice. */
.su-card-drop {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 2;
    padding: 3px 8px;
    border-radius: 6px;
    background: var(--savings);
    color: var(--onPrimary);
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .03em;
    line-height: 1.5;
}

/* Watch heart — top right, on the image */
.su-card-watch {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    width: 28px;
    height: 28px;
    min-width: 28px;
    border-radius: 8px;
    background: var(--surfaceAlpha);
    border: 1px solid var(--border);
    color: var(--textMut);
}

    .su-card-watch:hover {
        color: var(--accent);
        border-color: var(--accent);
    }

    .su-card-watch.su-card-watching {
        color: var(--accent);
        border-color: var(--accent);
    }

/* Out of stock is worth saying; in stock is the default and does not need a
   chip on every card. */
.su-card-oos {
    position: absolute;
    bottom: 8px;
    left: 8px;
    z-index: 2;
    padding: 3px 8px;
    border-radius: 6px;
    background: var(--surfaceAlpha);
    border: 1px solid var(--border);
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 700;
}

.su-product-title {
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 14px;
    line-height: 1.35;
    color: var(--text);
}

.su-card-unit {
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
}

/* Store band — brand swatch + name on the left, price on the right */
.su-card-band {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}

.su-card-store {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 700;
    color: var(--textMut);
}

/* On a narrow card a long store name plus a was-price overflows the band.
   The store name is what gives way — the price is never the thing that
   gets cut in half. */
.su-card-storename {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.su-card-price {
    flex: none;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 21px;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.su-card-was {
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0;
    color: var(--textMut);
    text-decoration: line-through;
    margin-right: 6px;
}

/* -----------------------------------------------------------------------------
   Inline Alternatives drawer
   Opens in place on the card instead of over the page.
   -------------------------------------------------------------------------- */
.su-alt-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    padding: 8px 10px;
    border-radius: 10px;
    border: 1px solid var(--fieldBorder);
    background: var(--field);
    color: var(--text);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    text-transform: none;
    cursor: pointer;
    transition: border-color .13s ease, color .13s ease, background-color .13s ease;
}

    .su-alt-toggle:hover {
        border-color: var(--primary);
        color: var(--primary);
    }

    .su-alt-toggle.su-alt-open {
        background: var(--primary);
        color: var(--onPrimary);
        border-color: transparent;
    }

    .su-alt-toggle .su-alt-chev {
        transition: transform .15s ease;
    }

    .su-alt-toggle.su-alt-open .su-alt-chev {
        transform: rotate(180deg);
    }

.su-alt-drawer {
    border: 1px solid var(--border);
    border-radius: 11px;
    overflow: hidden;
    background: var(--rowBg);
}

.su-alt-head {
    padding: 8px 12px 4px;
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-alt-line {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 12px;
    border: none;
    background: transparent;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}

    .su-alt-line:hover {
        background: var(--hoverWash);
    }

    .su-alt-line.su-alt-best {
        background: var(--bestBg);
    }

/* A result card is a quarter of the grid, so a single-line row ellipsises two
   different products down to the same "Lactose Fr…". The name gets the width
   and up to two lines; the unit price sits under it. */
.su-alt-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.su-alt-name {
    font-weight: 600;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.su-alt-price {
    flex: none;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.su-alt-more {
    flex: 1;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--primary);
    text-align: center;
}

.su-alt-best .su-alt-price {
    color: var(--savings);
}

.su-alt-unit {
    font-size: 10.5px;
    color: var(--textMut);
    font-variant-numeric: tabular-nums;
}

.su-alt-empty {
    padding: 10px 12px 12px;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

/* -----------------------------------------------------------------------------
   Active filter chips
   -------------------------------------------------------------------------- */
.su-active-filters {
    display: flex;
    gap: 7px;
    flex-wrap: wrap;
    margin-bottom: 15px;
}

.su-af-chip {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border-radius: 999px;
    border: none;
    background: var(--accentSoft);
    color: var(--accentText);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    text-transform: none;
}

    .su-af-chip:hover {
        filter: brightness(0.97);
    }

    .su-af-chip .su-af-x {
        opacity: .7;
        font-size: 14px;
        line-height: 1;
    }

.su-af-clear {
    background: transparent;
    border: none;
    color: var(--primary);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    padding: 5px 4px;
    text-transform: none;
}

/* -----------------------------------------------------------------------------
   Mobile sticky filter pill bar
   -------------------------------------------------------------------------- */
.su-mob-filters {
    display: none;
}

/* Sticky comes from the parent .su-sticky-filter-header, which is already
   sticky at every breakpoint — a second sticky context here would fight it,
   and its own background would punch a hole in the parent's blur. */
@media (max-width: 959.98px) {
    .su-mob-filters {
        display: flex;
        gap: 8px;
        overflow-x: auto;
        padding: 2px 0 4px;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

        .su-mob-filters::-webkit-scrollbar {
            display: none;
        }
}

.su-mob-filter {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
    padding: 8px 13px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    text-transform: none;
}

    .su-mob-filter.su-mob-filter-primary {
        background: var(--primary);
        color: var(--onPrimary);
        border-color: transparent;
    }

.su-mob-filter-badge {
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--accentSoft);
    color: var(--accentText);
    font-size: 10px;
    font-weight: 800;
}

.su-mob-filter-primary .su-mob-filter-badge {
    background: var(--surface);
    color: var(--primary);
}

/* -----------------------------------------------------------------------------
   Product detail — hero best-price box
   THIS listing's price. Never a second store's price in this box.
   -------------------------------------------------------------------------- */
.su-pd-bestbox {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding: 14px 18px;
    margin-bottom: 14px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--bestBg);
}

.su-pd-price {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 32px;
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--savings);
    font-variant-numeric: tabular-nums;
}

.su-pd-unit {
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

.su-pd-drop {
    font-family: var(--font-ui);
    font-size: 13.5px;
    color: var(--text);
}

    .su-pd-drop b {
        font-weight: 700;
        color: var(--savings);
    }

@media (max-width: 600px) {
    .su-pd-bestbox {
        gap: 10px;
        padding: 12px 14px;
    }

    .su-pd-price {
        font-size: 26px;
    }
}

/* -----------------------------------------------------------------------------
   Product detail — panels
   -------------------------------------------------------------------------- */
.su-pd-panel {
    padding: 17px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
}

.su-pd-panel-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15.5px;
    color: var(--text);
}

.su-pd-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 10px;
}

    .su-pd-row + .su-pd-row {
        margin-top: 3px;
    }

    .su-pd-row.su-pd-row-best {
        background: var(--bestBg);
    }

.su-pd-row-label {
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 13.5px;
    color: var(--text);
}

.su-pd-row-value {
    text-align: right;
    font-family: var(--font-ui);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

.su-pd-row-sub {
    font-weight: 400;
    font-size: 11.5px;
    color: var(--textMut);
}

.su-pd-row-good {
    color: var(--savings);
}

.su-pd-tag {
    font-family: var(--font-ui);
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--savings);
}

/* -----------------------------------------------------------------------------
   Price history — stepped line, window tabs, stats
   -------------------------------------------------------------------------- */
.su-hist-tabs {
    display: flex;
    gap: 5px;
    margin-left: auto;
}

.su-hist-tab {
    padding: 4px 11px;
    border-radius: 999px;
    border: none;
    background: var(--field);
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    text-transform: none;
    min-width: 0;
}

    .su-hist-tab.su-hist-tab-on {
        background: var(--primary);
        color: var(--onPrimary);
    }

.su-hist-chart svg {
    display: block;
    width: 100%;
    height: auto;
}

.su-hist-axis {
    font-family: var(--font-ui);
    font-size: 9.5px;
    fill: var(--textMut);
}

.su-hist-stats {
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
    margin-top: 8px;
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
}

    .su-hist-stats b {
        color: var(--text);
        font-variant-numeric: tabular-nums;
    }

    .su-hist-stats .su-hist-low b,
    .su-hist-stats .su-hist-good b {
        color: var(--savings);
    }

.su-hist-empty {
    padding: 18px 4px;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

/* -----------------------------------------------------------------------------
   Alternatives rail
   -------------------------------------------------------------------------- */
.su-alt-rail {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 4px;
}

.su-rail-card {
    flex: 0 0 200px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface);
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: border-color .13s ease;
}

    .su-rail-card:hover {
        border-color: var(--primary);
    }

.su-rail-card-img {
    height: 64px;
    margin-bottom: 8px;
    border-radius: 9px;
    background: var(--field);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

    .su-rail-card-img img {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
    }

.su-rail-card-name {
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 12.5px;
    line-height: 1.3;
    min-height: 33px;
    color: var(--text);
}

.su-rail-card-foot {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-top: 6px;
}

.su-rail-card-price {
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 13.5px;
    color: var(--savings);
    font-variant-numeric: tabular-nums;
}

.su-rail-card-delta {
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    color: var(--savings);
}

.su-rail-card-dearer {
    color: var(--textMut);
}

@media (max-width: 600px) {
    .su-rail-card {
        flex: 0 0 168px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .su-product-card,
    .su-alt-toggle,
    .su-alt-toggle .su-alt-chev,
    .su-rail-card {
        transition: none;
    }
}

/* -----------------------------------------------------------------------------
   BATCH 2 ADDENDUM — Alternatives dialog
   The card's "See alternatives" button opens this, so it is now the whole
   cross-store comparison surface rather than a secondary view. Own prefix
   (su-altd-) so it cannot collide with .su-alt-card, which is what caused
   DEVIATIONS D35.
   -------------------------------------------------------------------------- */
/* .su-altd-title and .su-altd-sub lived here. The Batch 3 dialog template
   replaced them with the shared .su-dlg-title / .su-dlg-sub, so they were
   removed rather than left as a second way to write the same heading. */

/* The listing everything here is being compared against. Without it the prices
   below are just numbers -- hard rule 7 says one card is one store, so the
   comparison needs its anchor stated. */
.su-altd-source {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--rowBg);
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
}

.su-altd-source-label {
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-altd-source-name {
    font-weight: 700;
}

.su-altd-source-price {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.su-altd-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.su-altd-count {
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

.su-altd-card {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface);
    overflow: hidden;
    cursor: pointer;
    transition: border-color .13s ease, box-shadow .13s ease;
}

    .su-altd-card:hover {
        border-color: var(--primary);
        box-shadow: 0 6px 20px var(--searchGlow1);
    }

    .su-altd-card.su-altd-best {
        border-color: var(--savings);
    }

.su-altd-img {
    height: 132px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    background: var(--imgPlate);
}

    .su-altd-img img {
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
    }

.su-altd-badge {
    position: absolute;
    top: 9px;
    left: 9px;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--savings);
    color: var(--onPrimary);
    font-family: var(--font-ui);
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .03em;
}

.su-altd-oos {
    position: absolute;
    top: 9px;
    right: 9px;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 10px;
    font-weight: 700;
}

.su-altd-body {
    display: flex;
    flex-direction: column;
    gap: 5px;
    flex: 1;
    padding: 11px 12px 8px;
}

.su-altd-name {
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 13px;
    line-height: 1.3;
    color: var(--text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.su-altd-store {
    display: flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 700;
    color: var(--textMut);
}

.su-altd-pricerow {
    display: flex;
    align-items: baseline;
    gap: 7px;
    margin-top: auto;
}

.su-altd-price {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 19px;
    letter-spacing: -0.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.su-altd-was {
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
    text-decoration: line-through;
}

.su-altd-unitrow {
    display: flex;
    align-items: baseline;
    gap: 7px;
    flex-wrap: wrap;
    font-family: var(--font-ui);
    font-size: 11.5px;
    color: var(--textMut);
    font-variant-numeric: tabular-nums;
}

.su-altd-delta {
    font-weight: 800;
    color: var(--savings);
}

.su-altd-delta-up {
    font-weight: 800;
    color: var(--textMut);
}

.su-altd-actions {
    padding: 0 8px 8px;
}

.su-altd-empty {
    padding: 26px 18px;
    text-align: center;
    font-family: var(--font-ui);
    font-size: 13.5px;
    color: var(--textMut);
}

@media (prefers-reduced-motion: reduce) {
    .su-altd-card {
        transition: none;
    }
}

/* Full-chart button inside the price history panel (moved out of the old
   .pd-history-summary strip). Matches the new button language. */
.su-hist-full {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    margin-top: 12px;
    padding: 9px 12px;
    border-radius: 10px;
    border: 1px solid var(--fieldBorder);
    background: var(--field);
    color: var(--text);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    text-transform: none;
    cursor: pointer;
    transition: border-color .13s ease, color .13s ease;
}

    .su-hist-full:hover {
        border-color: var(--primary);
        color: var(--primary);
    }

.su-hist-full-icon {
    font-size: 13px;
    line-height: 1;
}

@media (prefers-reduced-motion: reduce) {
    .su-hist-full {
        transition: none;
    }
}

/* -----------------------------------------------------------------------------
   BATCH 2 ADDENDUM 2 — one search bar, two placements
   The app bar and the home hero are the same SearchBox. These rules settle the
   only thing that has to differ: which leading glyph is shown.
   -------------------------------------------------------------------------- */

/* The in-bar "cu." logo stands in for the header logo on narrow screens. The
   existing hide-on-desktop rule targets .su-search-logo-link, but SearchBox
   renders a bare <img class="su-search-logo">, so it never matched and the
   logo showed at every width. */
@media (min-width: 960px) {
    .su-search-row > .su-search-logo,
    .su-search-row > .su-search-logo + .su-search-divider {
        display: none;
    }
}

/* ...and where that logo IS showing, the magnifier would be a second leading
   glyph. One or the other, never both. */
@media (max-width: 959.98px) {
    .su-search-row:has(> .su-search-logo) .su-search-lead-icon {
        display: none;
    }
}

/* In the app bar the bar sits on a white surface a few pixels away, so the
   hero's full drop glow is too much; keep the ring, drop the halo. */
.su-appbar .su-search-hero .su-search-wrapper {
    box-shadow: none !important;
}

.su-appbar .su-search-hero .su-search-wrapper:hover,
.su-appbar .su-search-hero .su-search-wrapper:focus-within {
    box-shadow: 0 2px 10px var(--searchGlow1) !important;
}

/* The bar is focused whenever the panel is open, so the rule above would win
   over the hero's open state and glow DOWNWARD onto the panel — a 10px blur
   over a 2px offset reaches 8px past the join. Same seam, same fix as on the
   home hero: while the two are joined, the bar glows up only. */
.su-appbar .su-search-hero .su-search-wrapper.open.position-top,
.su-appbar .su-search-hero .su-search-wrapper.open.position-top:focus-within {
    box-shadow: 0 -3px 10px var(--searchGlow1) !important;
}

.su-appbar .su-search-hero .su-search-wrapper.open.position-bottom,
.su-appbar .su-search-hero .su-search-wrapper.open.position-bottom:focus-within {
    box-shadow: 0 3px 10px var(--searchGlow1) !important;
}

/* -----------------------------------------------------------------------------
   The same bar, 240px wide
   The hero's padding is sized for a 640px object that owns the middle of the
   page. In a phone app bar the identical markup has to fit beside a hamburger,
   a logo, a scan affordance and a categories button, and every px of chrome
   comes straight out of the input: it was down to 43px, which clipped the
   placeholder mid-word. Trim the chrome, and let whatever still does not fit
   trail off instead of stopping dead.
   -------------------------------------------------------------------------- */
@media (max-width: 599.98px) {
    .su-appbar .su-search-hero .su-search-row {
        padding: 3px 6px 3px 10px;
    }

    .su-appbar .su-search-hero .su-search-field {
        padding: 0 6px;
    }

    .su-appbar .su-search-hero .su-search-scan {
        padding: 7px 7px;
        margin-left: 0;
    }

    .su-appbar .su-search-hero .su-search-logo {
        margin-right: 6px;
    }
}

/* Placeholders and long queries alike: an input that runs out of room should
   trail off. Chromium clips both by default, which reads as a broken layout
   rather than a truncated string. */
.su-search-field input {
    text-overflow: ellipsis;
}

/* -----------------------------------------------------------------------------
   Mobile expanded search — the hero bar with a back arrow in it
   The structural half of this lives up in the MOBILE EXPANDABLE SEARCH BAR
   section: the container is the bar, the SearchBox inside is flattened, and the
   panel is anchored to the container. This is the chrome, and it has to sit
   after .su-search-hero's own panel rules because the two selectors weigh the
   same and document order is what decides.

   The arrow is a sibling of the SearchBox, so putting it inside the bar's
   border means the border has to belong to the element that holds both. That
   is the whole reason the container draws the bar here and the wrapper does on
   the home page.
   -------------------------------------------------------------------------- */
.su-mobile-search-expanded:has(> .su-search-hero) {
    /* Same single source of truth as .su-search-hero: the panel below cancels
       this out to line its border up with the bar's (D44). */
    --su-hero-border: 1px;
    background: var(--surface);
    border: var(--su-hero-border) solid var(--fieldBorder);
    border-radius: 999px;
    box-shadow: 0 2px 10px var(--searchGlow1);
    padding: 0 6px 0 4px;
    transition: box-shadow .18s ease, border-color .18s ease;
}

.su-mobile-search-expanded:has(> .su-search-hero):focus-within {
    border-color: var(--primary);
}

/* Joined onto the panel: square the bottom, drop the shared edge, and glow
   upward only — a downward glow spills across the join (D44). */
.su-mobile-search-expanded:has(> .su-search-hero):has(.su-suggestions-dropdown) {
    border-color: var(--primary);
    border-bottom-color: transparent;
    border-radius: 26px 26px 0 0;
    box-shadow: 0 -3px 10px var(--searchGlow1);
}

/* The container owns the chrome here, so the wrapper must not glow. The hero's
   open state and the app bar's focus ring both target the wrapper with more
   classes than the neutralising rule up in the mobile section, and a shadow on
   a transparent box still paints — it showed as a pale rectangle floating over
   the bar, starting where the wrapper starts rather than where the bar does.

   The :hover / :focus-within variants have to be spelled out: a pseudo-class
   counts toward specificity, so the app bar's focus rule outweighs the plain
   selector and the glow came back the moment the input took focus — which is
   always, while the panel is open. */
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper:hover,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper:focus-within,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-top,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-top:hover,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-top:focus-within,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-bottom,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-bottom:hover,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-wrapper.open.position-bottom:focus-within {
    box-shadow: none !important;
}

/* The arrow already supplies the leading inset that the hero row's 18px of
   left padding provides on the home page. */
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-row {
    padding: 3px 4px 3px 2px;
}

.su-mobile-search-expanded:has(> .su-search-hero) .su-suggestions-dropdown {
    /* An absolutely positioned child is laid out against the PADDING box, so
       pull out by the container's own border width to make the two border
       boxes coincide instead of stepping in 1px each side. */
    left: calc(-1 * var(--su-hero-border)) !important;
    right: calc(-1 * var(--su-hero-border)) !important;
    width: auto !important;
    border: var(--su-hero-border) solid var(--primary);
    border-top: none;
    border-radius: 0 0 26px 26px !important;
    /* Blur equal to the offset, so nothing paints back up across the join. */
    box-shadow: 0 22px 22px var(--searchGlow2) !important;
    background: var(--surface);
    max-height: 60vh;
    padding-bottom: 6px;
}

/* The arrow itself. MudIconButton ships Material's grey on a square-ish target;
   muted like the Scan affordance and brand-coloured on press, it reads as part
   of the same control rather than a button parked in front of one.
   44px square, not smaller: the stylesheet already enforces a 44px min-height
   on every .mud-icon-button below 600px, and a 36px-wide button inside that
   makes the press state an oval. Matching the two keeps it a circle and keeps
   the tap target at the size touch guidance asks for. */
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-collapse-btn {
    flex: none;
    width: 44px;
    height: 44px;
    min-width: 44px;
    margin: 0;
    padding: 0;
    border-radius: 999px;
    color: var(--textMut) !important;
    background-color: transparent !important;
    transition: color .13s ease, background-color .13s ease;
}

.su-mobile-search-expanded:has(> .su-search-hero) .su-search-collapse-btn:hover,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-collapse-btn:focus-visible,
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-collapse-btn:active {
    color: var(--primary) !important;
    background-color: var(--hoverWash) !important;
}

.su-mobile-search-expanded:has(> .su-search-hero) .su-search-collapse-btn .mud-icon-root {
    font-size: 21px;
}

/* On the home page the logo is the row's first item and the bar's padding
   spaces it. Here an arrow sits in front of it, so it needs its own gap or the
   two run together as one glyph cluster. */
.su-mobile-search-expanded:has(> .su-search-hero) .su-search-logo {
    margin-left: 4px;
}

/* -----------------------------------------------------------------------------
   Mobile top app bar — the actions layout (.su-appbar-actions)
   Layout B puts every account action in the bar: lists, watchlists, theme,
   account, categories. On a phone that arrived as five different treatments in
   one row — a teal ring, a coral ring, two grey rings, one bare icon and a
   filled avatar, at three different diameters, with an extra spacer splitting
   the group in half. Six competing shapes for six equal-weight actions.

   This is the bottom nav's language applied to the top: bare icons, one size,
   one muted colour, brand colour on press. The avatar stays filled because it
   is the one item that is not an action — it is you — and being the only solid
   shape in the row is what makes it findable.

   Scoped to Layout B on purpose. Layout A's bar is built around the search
   pill, where the two flanking circles are what keep it from touching the
   screen edges.
   -------------------------------------------------------------------------- */
@media (max-width: 959.98px) {
    .su-appbar-actions {
        gap: 2px;
    }

    /* The inner spacer belongs to the promoted bottom-bar content and split the
       cluster in two — lists over here, account over there. One even row. */
    .su-appbar-actions .d-md-none .mud-spacer {
        display: none;
    }

    /* Every action, whatever component drew it: same box, no chrome. */
    .su-appbar-actions .su-bottom-btn,
    .su-appbar-actions .mud-icon-button {
        width: 40px !important;
        height: 40px !important;
        min-width: 40px !important;
        min-height: 40px !important;
        padding: 0 !important;
        margin: 0 !important;
        border: none !important;
        border-radius: 999px !important;
        background-color: transparent !important;
        box-shadow: none !important;
        color: var(--textMut) !important;
        transform: none !important;
        transition: color .13s ease, background-color .13s ease;
    }

    .su-appbar-actions .su-bottom-btn:hover,
    .su-appbar-actions .su-bottom-btn:focus-visible,
    .su-appbar-actions .su-bottom-btn:active,
    .su-appbar-actions .mud-icon-button:hover,
    .su-appbar-actions .mud-icon-button:focus-visible,
    .su-appbar-actions .mud-icon-button:active {
        background-color: var(--hoverWash) !important;
        color: var(--primary) !important;
        transform: none !important;
        box-shadow: none !important;
    }

    .su-appbar-actions .su-bottom-btn .mud-icon-root,
    .su-appbar-actions .mud-icon-button .mud-icon-root,
    .su-appbar-actions .su-login-anon-icon {
        font-size: 22px !important;
        color: inherit !important;
    }

    /* The avatar is the one solid shape in the row. Sized to sit inside the
       same 40px slot as everything else rather than overhanging it. */
    .su-appbar-actions .su-login-avatar {
        width: 32px !important;
        height: 32px !important;
        font-size: 13px !important;
        border: none;
        margin: 0 2px;
    }

    .su-appbar-actions .su-login-avatar:hover {
        transform: none;
        box-shadow: 0 0 0 3px var(--hoverWash);
    }

    /* The hamburger is the row's other end. Same treatment, and the logo gets
       the gap the removed circle used to provide. */
    .su-appbar-actions .su-logo-link {
        margin-left: 2px;
    }
}

/* -----------------------------------------------------------------------------
   Product image plate
   Every product photo in the catalogue is shot on white, so a tinted plate
   behind it renders as a grey rectangle framing the product. This is a physical
   property of the source imagery rather than a theme decision, which is why it
   is one fixed value in both modes — the same reasoning as the store-brand
   dots, and centralised here in one place per hard rule 8. ProductDetail's
   gallery already hardcoded #fff; this is that value, named.
   -------------------------------------------------------------------------- */
:root {
    --imgPlate: #ffffff;
}

/* =============================================================================
   BATCH 3 — LISTS

   Visual source of truth: docs/redesign/cuugo-lists-preview.html.
   Colours are theme tokens only.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   List summary card
   Preview: .lcard — name and meta, total with its since-added delta, a budget
   meter, shared avatars along the bottom.
   -------------------------------------------------------------------------- */
.su-lc {
    display: flex;
    flex-direction: column;
    gap: 11px;
    height: 100%;
    padding: 16px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    cursor: pointer;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}

.su-lc:hover,
.su-lc:focus-visible {
    border-color: var(--primary);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px var(--glow);
    outline: none;
}

.su-lc.has-unavailable-prices {
    border-color: var(--warnStrong);
}

.su-lc-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.su-lc-ident {
    min-width: 0;
}

.su-lc-name {
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 16px;
    color: var(--text);
    /* Two lines, then ellipsis. A list called after a week's menu plan is long,
       and letting it push the total off the card is worse than truncating. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.su-lc-meta {
    margin-top: 2px;
    font-size: 12.5px;
    color: var(--textMut);
}

.su-lc-menu {
    flex: none;
    margin: -6px -6px 0 0;
    color: var(--textMut);
}

.su-lc-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: -4px;
}

/* --- the number the card exists for -------------------------------------- */
.su-lc-total {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}

.su-lc-value {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 24px;
    letter-spacing: -0.02em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.su-lc-delta {
    font-size: 12px;
    font-weight: 700;
}

.su-lc-delta.down {
    color: var(--savings);
}

/* Same reasoning as the over-budget bar: a price that went UP must not be the
   same colour as money saved. */
.su-lc-delta.up {
    color: var(--errText);
}

/* --- the two states that make a total unreliable -------------------------- */
.su-lc-est,
.su-lc-oos {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.35;
}

.su-lc-est {
    color: var(--warnText);
}

.su-lc-oos {
    color: var(--errText);
}

.su-lc-est .mud-icon-root {
    font-size: 15px;
    flex: none;
}

/* --- budget meter --------------------------------------------------------- */
.su-lc-meter {
    height: 7px;
    border-radius: 5px;
    background: var(--field);
    overflow: hidden;
}

.su-lc-meter i {
    display: block;
    height: 100%;
    border-radius: 5px;
    background: var(--savings);
    transition: width .25s ease;
}

.su-lc-meter i.warn {
    background: var(--warnStrong);
}

/* The preview colours this one --accent. In Cuugo's own palettes --accent is a
   green in four of the fourteen themes (Cuugo Classic has Accent #00B894 next
   to Savings #00806A), so an over-budget bar came out the same colour as an
   under-budget one — verified live: both rendered rgb(18,133,122). Over budget
   is a problem, not an accent, so it takes the error token and is distinct in
   every theme. See DEVIATIONS.md D53. */
.su-lc-meter i.over {
    background: var(--errStrong);
}

.su-lc-blab {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
}

.su-lc-blab .ok {
    color: var(--savings);
    font-weight: 700;
}

.su-lc-blab .bad {
    color: var(--errText);
    font-weight: 700;
}

.su-lc-equiv {
    font-size: 11.5px;
    color: var(--textMut);
    border-bottom: 1px dotted var(--border);
    cursor: help;
    align-self: flex-start;
}

/* --- who else is in here -------------------------------------------------- */
.su-lc-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    /* Pushed to the bottom so a card with a budget and one without still line
       their footers up across a row. */
    margin-top: auto;
    padding-top: 2px;
}

.su-lc-avatars {
    display: flex;
    flex: none;
}

.su-lc-av {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 2px solid var(--surface);
    background: var(--field);
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 10px;
    font-weight: 800;
    flex: none;
}

.su-lc-av + .su-lc-av {
    margin-left: -7px;
}

.su-lc-av.me {
    background: var(--primary);
    color: var(--onPrimary);
}

.su-lc-upd {
    font-size: 11.5px;
    color: var(--textMut);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* -----------------------------------------------------------------------------
   Create-list card
   Preview: .lcard.newlist — dashed, centred, no hover lift. It is an invitation
   in the grid rather than another list, so it reads as an outline of one.
   -------------------------------------------------------------------------- */
.su-create-list-card {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-height: 172px;
    padding: 16px;
    border: 1px dashed var(--border) !important;
    border-radius: 16px !important;
    background: transparent !important;
    color: var(--textMut);
    cursor: pointer;
    transition: border-color .14s ease, color .14s ease;
}

.su-create-list-card:hover {
    border-color: var(--primary) !important;
    color: var(--primary);
    transform: none;
    box-shadow: none !important;
}

.su-create-list-card.disabled {
    cursor: not-allowed;
    opacity: .7;
}

.su-create-list-card.disabled:hover {
    border-color: var(--border) !important;
    color: var(--textMut);
}

.su-create-list-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
}

.su-create-list-content .mud-icon-root {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    background: var(--field);
    color: inherit;
    font-size: 22px;
}

/* -----------------------------------------------------------------------------
   List detail — store groups
   Preview: .sgroup / .sg-head. Every item on a Cuugo list is one store's
   listing, so the store is the grouping that matches how the list gets used:
   this is the walk-the-shops order, and each header carries what that shop
   will cost.
   -------------------------------------------------------------------------- */
.su-sg-head {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 14px 4px 8px;
    font-family: var(--font-ui);
    font-weight: 700;
    font-size: 13.5px;
    color: var(--text);
}

.su-sg-dot {
    width: 9px;
    height: 9px;
    border-radius: 3px;
    flex: none;
}

.su-sg-count {
    color: var(--textMut);
    font-weight: 600;
    font-size: 12px;
}

.su-sg-subtotal {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 13px;
    color: var(--textMut);
}

/* -----------------------------------------------------------------------------
   List detail — per-item price movement and the alternatives link
   Preview: .isub .dropt / .upt / .altl.
   -------------------------------------------------------------------------- */
.su-ld-delta {
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1.3;
    margin-top: 2px;
}

.su-ld-delta.down {
    color: var(--savings);
}

/* Error token, not --accent: --accent is a green in several themes, which would
   make a price rise the same colour as a saving. Same call as D53. */
.su-ld-delta.up {
    color: var(--errText);
}

.su-ld-alt {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    border: none;
    background: transparent;
    color: var(--primary);
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    border-radius: 8px;
    cursor: pointer;
    text-transform: none;
    transition: background-color .13s ease;
}

.su-ld-alt:hover,
.su-ld-alt:focus-visible {
    background: var(--hoverWash);
}

.su-ld-alt-arrow {
    font-size: 13px;
}

/* -----------------------------------------------------------------------------
   List detail — the item row
   Preview: .item. This is what the redesign draws a list as, and it is now the
   default view: a shopping list is a sequence of things to pick up, and a row
   per thing reads in that order. The card grid is still there behind the
   toggle for anyone who wants the pictures bigger.

   Flex rather than grid, and allowed to wrap: on a narrow screen the trailing
   block (quantity, price, menu) drops to its own line by itself, with no
   breakpoint to keep in step with the markup.
   -------------------------------------------------------------------------- */
.su-li {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 13px;
    padding: 10px 13px;
    margin-bottom: 7px;
    font-family: var(--font-ui);
    transition: opacity .18s ease, border-color .13s ease, background-color .13s ease;
}

.su-li:hover {
    border-color: var(--fieldBorder);
}

/* Picked up. The row stays exactly where it was — reordering under the
   shopper's finger loses their place in the aisle. */
.su-li.done {
    opacity: .55;
}

.su-li.done .su-li-name {
    text-decoration: line-through;
}

.su-li.unavail .su-li-price {
    color: var(--textMut);
    font-size: 12px;
    font-weight: 600;
}

/* ── the tick ────────────────────────────────────────────────────────────── */
.su-li-chk {
    width: 22px;
    height: 22px;
    flex: none;
    padding: 0;
    border: 1.5px solid var(--fieldBorder);
    border-radius: 7px;
    background: var(--surface);
    color: transparent;
    font-size: 13px;
    font-weight: 800;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color .13s ease, border-color .13s ease, color .13s ease;
}

.su-li-chk:hover:not(:disabled) {
    border-color: var(--savings);
}

.su-li-chk:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.su-li-chk:disabled {
    cursor: default;
    opacity: .5;
}

/* --onPrimary, not white: in dark themes --savings is a light green and white
   on it fails contrast. --onPrimary flips with the theme in the same
   direction --savings does, so the tick stays legible in both. */
.su-li.done .su-li-chk {
    background: var(--savings);
    border-color: var(--savings);
    color: var(--onPrimary);
}

/* ── thumbnail ───────────────────────────────────────────────────────────── */
.su-li-thumb {
    width: 44px;
    height: 44px;
    flex: none;
    border-radius: 9px;
    background: var(--imgPlate);
    border: 1px solid var(--border);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.su-li-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: 3px;
}

/* ── body ────────────────────────────────────────────────────────────────── */
.su-li-body {
    flex: 1 1 150px;
    min-width: 0;
}

.su-li-name {
    font-weight: 600;
    font-size: 13.5px;
    line-height: 1.35;
    color: var(--text);
    cursor: pointer;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.su-li-sub {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin-top: 2px;
    font-size: 11.5px;
    color: var(--textMut);
}

/* The delta carries its own margin-top for the card layout; on a sub-line it
   must not push the row open. */
.su-li-sub .su-ld-delta {
    margin-top: 0;
    font-size: 11.5px;
}

.su-li-sub .su-ld-alt {
    padding: 0;
    font-size: 11.5px;
}

.su-li-sub .su-ld-alt:hover,
.su-li-sub .su-ld-alt:focus-visible {
    background: transparent;
    text-decoration: underline;
}

.su-li-picked {
    color: var(--savings);
    font-weight: 700;
}

.su-li-flag {
    font-weight: 700;
    color: var(--warnText);
}

.su-li-flag.oos {
    color: var(--errText);
}

/* ── trailing block: quantity, price, menu ───────────────────────────────── */
.su-li-tail {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

.su-li-qty {
    display: flex;
    align-items: center;
    gap: 2px;
    background: var(--field);
    border: 1px solid var(--fieldBorder);
    border-radius: 9px;
    padding: 2px;
}

.su-li-qty button {
    width: 26px;
    height: 26px;
    border: none;
    background: transparent;
    color: var(--textMut);
    font-weight: 800;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background-color .13s ease, color .13s ease;
}

.su-li-qty button:hover:not(:disabled) {
    background: var(--hoverWash);
    color: var(--text);
}

.su-li-qty button:disabled {
    opacity: .4;
    cursor: default;
}

.su-li-qty button.rm:hover:not(:disabled) {
    color: var(--errText);
}

.su-li-qty .qv {
    min-width: 22px;
    text-align: center;
    font-weight: 700;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

.su-li-price {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-size: 14px;
    min-width: 56px;
    text-align: right;
    color: var(--text);
}

.su-li-price .sub {
    display: block;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--textMut);
}

/* -----------------------------------------------------------------------------
   List detail — grid/list view toggle
   Preview: .seg, the segmented control the dialogs use for enumerations.
   -------------------------------------------------------------------------- */
.su-vt {
    display: inline-flex;
    background: var(--field);
    border: 1px solid var(--fieldBorder);
    border-radius: 10px;
    padding: 2px;
    gap: 2px;
}

.su-vt button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 26px;
    border: none;
    background: transparent;
    color: var(--textMut);
    border-radius: 8px;
    cursor: pointer;
    transition: background-color .13s ease, color .13s ease;
}

.su-vt button:hover {
    color: var(--text);
}

.su-vt button.on {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 1px 3px var(--glowSoft);
}

.su-vt button:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

/* Picked-up count beside a group's subtotal. */
.su-sg-picked {
    color: var(--savings);
    font-weight: 700;
    font-size: 12px;
}

/* The whole list's progress, in the sticky header. */
.su-ld-progress {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--textMut);
}

.su-ld-progress .track {
    flex: 1;
    height: 5px;
    border-radius: 999px;
    background: var(--field);
    overflow: hidden;
}

.su-ld-progress .track i {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--savings);
    transition: width .25s ease;
}

.su-ld-progress .clear {
    border: none;
    background: transparent;
    color: var(--primary);
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 6px;
}

.su-ld-progress .clear:hover {
    background: var(--hoverWash);
}

/* -----------------------------------------------------------------------------
   List detail — stats row and budget bar above the items
   Preview: .stats / .stat / .budgetcard. The card view keeps these in its
   sidebar; the row view puts them across the top, which is where the preview
   has them and which leaves the full width for the list itself.
   -------------------------------------------------------------------------- */
.su-lds {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 11px;
    margin-bottom: 14px;
}

@media (max-width: 819.98px) {
    .su-lds {
        grid-template-columns: repeat(2, 1fr);
    }
}

.su-lds-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 12px 15px;
    font-family: var(--font-ui);
    min-width: 0;
}

.su-lds-card .k {
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-lds-card .v {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 21px;
    letter-spacing: -0.02em;
    margin-top: 2px;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.su-lds-card .s {
    font-size: 11.5px;
    color: var(--textMut);
    font-weight: 600;
    margin-top: 2px;
    line-height: 1.35;
}

.su-lds-card.hero .v {
    color: var(--primary);
}

.su-lds-card .v.down {
    color: var(--savings);
}

/* Error token rather than --accent, for the reason recorded in D53: --accent
   is a green in several themes and would read as a saving. */
.su-lds-card .v.up {
    color: var(--errText);
}

.su-lds-card .v.flat {
    color: var(--textMut);
}

/* ── budget bar ──────────────────────────────────────────────────────────── */
.su-ldb {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 13px 16px;
    margin-bottom: 18px;
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    font-family: var(--font-ui);
}

.su-ldb .bt {
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
}

.su-ldb .bs {
    font-size: 12px;
    color: var(--textMut);
    margin-top: 1px;
}

.su-ldb .bmeter {
    flex: 1;
    min-width: 160px;
    height: 7px;
    border-radius: 5px;
    background: var(--field);
    overflow: hidden;
}

.su-ldb .bmeter i {
    display: block;
    height: 100%;
    border-radius: 5px;
    background: var(--savings);
    transition: width .25s ease;
}

.su-ldb .bmeter i.warn {
    background: var(--warnStrong);
}

.su-ldb .bmeter i.over {
    background: var(--errStrong);
}

.su-ldb .edit {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--primary);
    cursor: pointer;
    white-space: nowrap;
    border: none;
    background: transparent;
    font-family: var(--font-ui);
    padding: 4px 8px;
    border-radius: 8px;
}

.su-ldb .edit:hover {
    background: var(--hoverWash);
}

.su-ldb .edit:disabled {
    color: var(--textMut);
    cursor: default;
    background: transparent;
}

/* The dashed "set a budget" prompt, for a list that has none yet. */
.su-ldb.unset {
    border-style: dashed;
    border-color: var(--fieldBorder);
    justify-content: center;
    cursor: pointer;
    color: var(--primary);
    font-size: 13px;
    font-weight: 700;
}

.su-ldb.unset:hover {
    background: var(--hoverWash);
}

/* A picked-up product card. Same fade and strike as a picked-up row, so the
   two views say the same thing about the same item. The tick itself is
   excluded from the fade — it is the control you use to undo this. */
.su-product-card.su-card-done {
    opacity: .55;
    transition: opacity .18s ease;
}

.su-product-card.su-card-done .su-product-title {
    text-decoration: line-through;
}

.su-product-card.su-card-done .su-li-chk {
    opacity: 1;
}

/* -----------------------------------------------------------------------------
   List detail — the mobile sheet's headline figures
   Preview: .sheet — Total, Since added, Budget position, three-up, with the
   middle one centred and the outer two pushed to the edges.

   The item count that used to sit in this row moves to the sheet's subtitle:
   the preview names these three, and a count of things is a different kind of
   fact from three amounts of money sitting beside each other.
   -------------------------------------------------------------------------- */
.su-sh-stats {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    padding: 4px 2px 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 14px;
}

.su-sh-stat {
    min-width: 0;
}

.su-sh-stat.mid {
    text-align: center;
}

.su-sh-stat:last-child {
    text-align: right;
}

.su-sh-v {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 22px;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.su-sh-v.ok {
    color: var(--savings);
}

/* Error tokens rather than --accent — see D53. */
.su-sh-v.bad {
    color: var(--errText);
}

.su-sh-v.flat {
    color: var(--textMut);
}

.su-sh-k {
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--textMut);
    margin-top: 3px;
}

.su-sh-sub {
    font-size: 12px;
    color: var(--textMut);
    font-weight: 600;
    margin-top: 1px;
}

/* -----------------------------------------------------------------------------
   List detail — the item row on a phone
   Everything does not fit on one line at 390px: the tick, thumbnail, quantity
   stepper, price and menu together leave the name about 70px, which is not a
   name. So the trailing block gets its own line — but placed under the *name*
   rather than under the whole row, which is where plain flex-wrap put it and
   which left a dead rectangle beside the thumbnail.
   -------------------------------------------------------------------------- */
@media (max-width: 599.98px) {
    .su-li {
        display: grid;
        grid-template-columns: auto auto minmax(0, 1fr);
        grid-template-areas:
            "chk thumb body"
            "chk thumb tail";
        align-items: start;
        column-gap: 10px;
        row-gap: 7px;
        padding: 10px 11px;
    }

    /* Tick and thumbnail line up with the name, not with the middle of the
       row — they belong to the product, and the trailing line below them is a
       set of controls, not more of the product. The tick keeps a 44px hit area
       even though it draws at 22px: it is what you tap holding a trolley. */
    .su-li-chk {
        grid-area: chk;
        align-self: start;
        margin-top: 2px;
        position: relative;
    }

    .su-li-chk::after {
        content: "";
        position: absolute;
        inset: -11px;
    }

    .su-li-thumb {
        grid-area: thumb;
        align-self: start;
        width: 40px;
        height: 40px;
    }

    .su-li-body {
        grid-area: body;
        align-self: start;
    }

    .su-li-tail {
        grid-area: tail;
        margin-left: 0;
        justify-content: space-between;
        width: 100%;
    }

    /* Price sits hard right, against the row's edge, where the eye adds up. */
    .su-li-price {
        margin-left: auto;
    }
}

/* =============================================================================
   DIALOG TEMPLATE — DESIGN-BATCHES Batch 3
   Preview: .dlg / .dlg-h / .dlg-b / .dlg-f / .fld / .seg.

   Layered on top of the existing .su-dialog, which already handles the shell
   and the mobile bottom-sheet treatment. This adds the redesign's typography:
   a title that names the thing being acted on, a line under it saying what
   will happen, uppercase field labels, and a right-aligned footer whose
   primary button is named after the verb.
   ============================================================================= */

/* ── header ──────────────────────────────────────────────────────────────── */
.su-dlg-h {
    display: block;
    min-width: 0;
}

.su-dlg-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 18px;
    letter-spacing: -0.015em;
    line-height: 1.3;
    color: var(--text);
    /* Long list names go on a second line rather than out of the dialog. */
    overflow-wrap: anywhere;
}

.su-dlg-sub {
    font-family: var(--font-ui);
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--textMut);
    margin-top: 3px;
    font-weight: 500;
}

/* ── body ────────────────────────────────────────────────────────────────── */
.su-dlg .mud-dialog-content {
    padding-top: 14px;
}

/* One field per decision, stacked. */
.su-dlg-b {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.su-fld {
    min-width: 0;
}

.su-fld > label,
.su-fld-label {
    display: block;
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--textMut);
    margin-bottom: 6px;
}

.su-fld-hint {
    font-family: var(--font-ui);
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--textMut);
    margin-top: 6px;
}

/* ── footer ──────────────────────────────────────────────────────────────── */
.su-dlg .mud-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 9px;
    padding: 14px 20px 18px;
}

/* Cancel is the quiet one. It has to be reachable, not persuasive. */
.su-dlg-cancel.mud-button {
    color: var(--textMut);
    font-weight: 700;
}

.su-dlg-cancel.mud-button:hover {
    background: var(--hoverWash);
    color: var(--text);
}

/* -----------------------------------------------------------------------------
   Segmented control
   Preview: .seg. A short closed set, all options visible, the chosen one
   raised onto the surface colour.
   -------------------------------------------------------------------------- */
.su-seg {
    display: flex;
    background: var(--field);
    border: 1px solid var(--fieldBorder);
    border-radius: 11px;
    padding: 3px;
    gap: 3px;
}

.su-seg button {
    flex: 1;
    min-width: 0;
    text-align: center;
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    padding: 8px 4px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--textMut);
    cursor: pointer;
    transition: background-color .13s ease, color .13s ease, box-shadow .13s ease;
}

.su-seg button:hover:not(:disabled):not(.on) {
    color: var(--text);
}

.su-seg button.on {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 1px 3px var(--glowSoft);
}

.su-seg button:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -1px;
}

.su-seg button:disabled {
    cursor: default;
    opacity: .5;
}

/* -----------------------------------------------------------------------------
   Dialog template — a list of things to pick from
   Used where choosing a row IS the action (move/copy to list), so the rows are
   real buttons rather than list items with a click handler: they focus, they
   disable, and they announce themselves.
   -------------------------------------------------------------------------- */
.su-pick {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 320px;
    overflow-y: auto;
}

.su-pick-row {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    text-align: left;
    padding: 11px 13px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 11px;
    cursor: pointer;
    font-family: var(--font-ui);
    color: var(--text);
    transition: border-color .13s ease, background-color .13s ease;
}

.su-pick-row:hover:not(:disabled) {
    border-color: var(--primary);
    background: var(--hoverWash);
}

.su-pick-row:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
}

.su-pick-row:disabled {
    cursor: default;
    opacity: .55;
}

.su-pick-name {
    font-size: 13.5px;
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.su-pick-tag {
    flex: none;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--primary);
    background: var(--hoverWash);
    border-radius: 6px;
    padding: 2px 6px;
}

.su-pick-meta {
    margin-left: auto;
    flex: none;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
}

/* A footer with a destructive or resetting action set apart from the pair that
   completes the dialog. "Clear all" is not a sibling of "Apply" — it throws
   work away — so it sits at the far left with the gap between them doing the
   explaining. */
.su-dlg-f-split {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    flex-wrap: wrap;
}

.su-dlg-f-end {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-left: auto;
}

/* -----------------------------------------------------------------------------
   Product detail — "This product" and the price history, in one card
   The summary states a claim ("$5.15, 3% above its usual price") and the chart
   is the evidence for it. As two cards they were one argument split across a
   seam, and because the summary is the shorter of the two it left a ragged
   band of empty card down the left. Sharing a card, the shorter column simply
   stops where it stops and there is nothing left over to look wrong.
   -------------------------------------------------------------------------- */
.su-pd-combo {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    overflow: hidden;
}

.su-pd-combo-side,
.su-pd-combo-main {
    min-width: 0;
    padding: 17px;
}

/* A hairline, not a gap: the two halves are one argument and should read as
   joined rather than adjacent. */
.su-pd-combo-main {
    border-left: 1px solid var(--border);
}

/* Stacked once two columns stop being readable — measured against the card's
   own width, not the window's. The product page has a nav rail on one side and
   a category rail on the other, so this card is about 500px wide on a 1400px
   screen: a viewport media query would have kept it in two cramped columns
   with "Cheapest similar product" wrapping into a thin tower. The rule turns
   horizontal so it still separates the claim from its evidence. */
.su-pd-combo-wrap {
    container-type: inline-size;
}

@container (max-width: 640px) {
    .su-pd-combo {
        grid-template-columns: minmax(0, 1fr);
    }

    .su-pd-combo-main {
        border-left: none;
        border-top: 1px solid var(--border);
    }
}

/* Browsers without container queries keep the old viewport rule, so they get a
   sensible stacked layout on small screens rather than no rule at all. */
@supports not (container-type: inline-size) {
    @media (max-width: 1279.98px) {
        .su-pd-combo {
            grid-template-columns: minmax(0, 1fr);
        }

        .su-pd-combo-main {
            border-left: none;
            border-top: 1px solid var(--border);
        }
    }
}

/* The panel inside a card that already has a border, a background and padding
   of its own. */
.su-pd-panel-bare {
    padding: 0;
    border: none;
    background: transparent;
    border-radius: 0;
}

/* -----------------------------------------------------------------------------
   Blog — the post card
   Used by the blog index and by both archive pages, so a change here lands on
   all three. The card is one <a>: under static SSR there is no event handler
   to click, and the whole surface should be the link anyway.
   -------------------------------------------------------------------------- */
.su-bpost {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-bpost:hover {
        border-color: var(--primary);
        transform: translateY(-2px);
        box-shadow: 0 10px 26px var(--glow);
    }
}

.su-bpost:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* The image band. Fixed height so a grid of cards keeps its baselines even
   when one post has a wide photo and the next has none. */
.su-bpost-img {
    position: relative;
    height: 168px;
    flex: none;
    background: linear-gradient(140deg, var(--field), var(--heroA));
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* contain, not cover. Cuugo's blog heroes are infographics with words on
   them — a basket comparison, a price-index chart — and cover crops the
   words off. The gradient behind fills whatever the image does not. */
.su-bpost-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* The type glyph shown when a post has no hero image of its own. It carries
   the post type at a glance, which is what the old per-type gradient did with
   four hardcoded palettes. */
.su-bpost-glyph {
    color: var(--primary);
    opacity: .55;
}

.su-bpost-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    padding: 14px 16px 15px;
}

.su-bpost-kicker {
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--accentText);
}

.su-bpost-title {
    font-family: var(--font-ui);
    font-size: 14.5px;
    font-weight: 700;
    line-height: 1.35;
    color: var(--text);
    margin: 0;
}

/* Two lines of summary, then an ellipsis. The redesign's card has no excerpt
   at all, but the summary is written copy and dropping it would lose content
   rather than restyle it — see DEVIATIONS D69. */
.su-bpost-ex {
    font-family: var(--font-ui);
    font-size: 13px;
    line-height: 1.5;
    color: var(--textMut);
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.su-bpost-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: auto;
    padding-top: 2px;
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
}

.su-bpost-meta .sep {
    opacity: .5;
}

/* The saving is the reason to click an essentials post, so it is the only
   coloured thing in the meta line. */
.su-bpost-save {
    color: var(--savings);
    font-weight: 800;
}

.su-bpost-collage {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
/* -----------------------------------------------------------------------------
   Blog index — head, tag row, featured basket, daily pick rail, post grid
   -------------------------------------------------------------------------- */
.su-bi-head {
    margin-bottom: 18px;
}

.su-bi-head h1 {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: clamp(22px, 3.4vw, 30px);
    letter-spacing: -0.025em;
    line-height: 1.15;
    color: var(--text);
    margin: 0;
}

.su-bi-head p {
    font-family: var(--font-ui);
    font-size: 14.5px;
    line-height: 1.55;
    color: var(--textMut);
    margin: 6px 0 0;
    max-width: 68ch;
}

/* The row of pills under the head. These are real links to the series pages,
   not a client-side filter — see DEVIATIONS D69. */
.su-bi-tags {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin: 14px 0 22px;
}

.su-btag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--textMut);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
    transition: border-color .13s ease, color .13s ease, background .13s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-btag:hover {
        border-color: var(--primary);
        color: var(--primary);
    }
}

.su-btag.on {
    background: var(--primary);
    color: var(--onPrimary);
    border-color: transparent;
}

.su-btag:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ── Featured basket ──────────────────────────────────────────────────────
   The most recent essentials basket, given the width its numbers deserve.
   Image left, argument right. */
.su-bfeat {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    border: 1px solid var(--border);
    border-radius: 18px;
    background: var(--surface);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    margin-bottom: 18px;
    transition: border-color .15s ease, box-shadow .15s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-bfeat:hover {
        border-color: var(--primary);
        box-shadow: 0 12px 32px var(--glow);
    }
}

.su-bfeat:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.su-bfeat-img {
    position: relative;
    min-height: 230px;
    background: linear-gradient(140deg, var(--heroA), var(--field));
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.su-bfeat-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.su-bfeat-collage {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.su-bfeat-badge {
    position: absolute;
    top: 14px;
    left: 14px;
    z-index: 1;
    padding: 5px 11px;
    border-radius: 8px;
    background: var(--savings);
    color: var(--onPrimary);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
}

/* Centred against the image column rather than stretched to its full height.
   The collage is tall and the copy is short, so pushing the meta line to the
   bottom with margin-top:auto left a band of empty card between the summary
   and the date. */
.su-bfeat-body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 10px;
    padding: 22px 24px;
}

.su-bfeat-kicker {
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--accentText);
}

.su-bfeat-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(18px, 2.6vw, 23px);
    letter-spacing: -0.02em;
    line-height: 1.25;
    color: var(--text);
    margin: 0;
}

.su-bfeat-ex {
    font-family: var(--font-ui);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--textMut);
    margin: 0;
}

.su-bfeat-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    padding-top: 4px;
    font-family: var(--font-ui);
    font-size: 12.5px;
    color: var(--textMut);
}

.su-bfeat-meta .sep {
    opacity: .5;
}

.su-bfeat-save {
    color: var(--savings);
    font-weight: 800;
}

@media (max-width: 780px) {
    .su-bfeat {
        grid-template-columns: minmax(0, 1fr);
    }

    .su-bfeat-img {
        min-height: 150px;
    }

    .su-bfeat-body {
        padding: 16px;
    }
}

/* ── Daily pick rail ──────────────────────────────────────────────────────
   A horizontal run of recent picks. Scrolls rather than wraps: the picks are
   in date order and a wrapped grid would break that reading. */
.su-drail {
    margin: 22px 0 4px;
}

.su-drail-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 11px;
}

.su-drail-head h2 {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 18px;
    letter-spacing: -0.015em;
    color: var(--text);
    margin: 0;
}

.su-drail-head a {
    margin-left: auto;
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    color: var(--primary);
    text-decoration: none;
    white-space: nowrap;
}

.su-drail-head a:hover {
    text-decoration: underline;
}

.su-drail-row {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 6px;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
}

.su-dpick {
    flex: 0 0 218px;
    scroll-snap-align: start;
    padding: 13px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface);
    color: inherit;
    text-decoration: none;
    transition: border-color .13s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-dpick:hover {
        border-color: var(--primary);
    }
}

.su-dpick:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.su-dpick-day {
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-dpick-prod {
    display: flex;
    gap: 10px;
    align-items: center;
    margin: 8px 0;
}

.su-dpick-th {
    width: 40px;
    height: 40px;
    flex: none;
    border-radius: 10px;
    background: var(--imgPlate);
    object-fit: contain;
    display: block;
}

.su-dpick-th-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--textMut);
}

.su-dpick-name {
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.su-dpick-price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 7px;
}

.su-dpick-now {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 19px;
    color: var(--savings);
}

.su-dpick-was {
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
    text-decoration: line-through;
}

.su-dpick-pct {
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--savings);
    color: var(--onPrimary);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 800;
}

.su-dpick-store {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 5px;
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
}

.su-dpick-dot {
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 3px;
    display: inline-block;
}

/* ── Post grid ──────────────────────────────────────────────────────────── */
.su-bi-gridhead {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: 26px 0 11px;
}

.su-bi-gridhead h2 {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 18px;
    letter-spacing: -0.015em;
    color: var(--text);
    margin: 0;
}

.su-bi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
}

/* -----------------------------------------------------------------------------
   Blog post — the reading column
   -------------------------------------------------------------------------- */
.su-bp-col {
    max-width: 68ch;
    margin: 0 auto;
}

.su-bp-kicker {
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--accentText);
    margin-bottom: 8px;
}

.su-bp-title {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: clamp(23px, 3.6vw, 32px);
    letter-spacing: -0.025em;
    line-height: 1.18;
    color: var(--text);
    margin: 0 0 12px;
}

.su-bp-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 22px;
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--textMut);
}

.su-bp-meta .sep {
    opacity: .5;
}

.su-bp-author {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    color: var(--text);
}

.su-bp-avatar {
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: 50%;
    background: var(--primary);
    color: var(--onPrimary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 800;
}

/* The lead is set larger and in full-strength text. It is the paragraph that
   decides whether the rest gets read. */
.su-bp-lead {
    font-family: var(--font-ui);
    font-size: 16.5px;
    line-height: 1.65;
    color: var(--text);
    margin: 0 0 16px;
}

/* ── Basket snapshot block ────────────────────────────────────────────────
   Header states the total, rows show where each item's total came from. */
.su-snap {
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    overflow: hidden;
    margin: 22px 0;
}

.su-snap-h {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
}

.su-snap-h .t {
    font-family: var(--font-ui);
    font-size: 14.5px;
    font-weight: 800;
    color: var(--text);
}

.su-snap-h .d {
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
}

.su-snap-tot {
    margin-left: auto;
    text-align: right;
}

.su-snap-tot .v {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 20px;
    color: var(--savings);
}

.su-snap-tot .k {
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--textMut);
}

/* The all-at-one-store comparison, kept from the block this replaced: the
   cherry-pick total only means something next to what one store would cost. */
.su-snap-totals {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--rowBg2);
}

.su-snap-tt {
    flex: 1 1 128px;
    padding: 8px 11px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
}

.su-snap-tt.win {
    border-color: var(--savings);
}

.su-snap-tt .lbl {
    display: block;
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 600;
    color: var(--textMut);
}

.su-snap-tt .val {
    display: block;
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 17px;
    color: var(--text);
}

.su-snap-tt.win .val {
    color: var(--savings);
}

.su-snap-tt .miss {
    display: block;
    font-family: var(--font-ui);
    font-size: 10.5px;
    color: var(--warnText);
}

.su-snap-row {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 18px;
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
    text-decoration: none;
}

.su-snap-row + .su-snap-row {
    border-top: 1px solid var(--border);
}

@media (hover: hover) and (pointer: fine) {
    a.su-snap-row:hover {
        background: var(--hoverWash);
    }
}

.su-snap-row .th {
    width: 30px;
    height: 30px;
    flex: none;
    border-radius: 8px;
    background: var(--imgPlate);
    object-fit: contain;
    display: block;
}

.su-snap-row .nm {
    flex: 1;
    min-width: 0;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.su-snap-row .q {
    flex: none;
    font-size: 12px;
    color: var(--textMut);
}

.su-snap-row .st {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
}

.su-snap-dot {
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 3px;
    display: inline-block;
}

.su-snap-row .pr {
    flex: none;
    min-width: 54px;
    text-align: right;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.su-snap-row .pr.none {
    font-weight: 500;
    color: var(--textMut);
}

.su-snap-f {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    background: var(--rowBg2);
}

.su-snap-f .pricenote {
    font-family: var(--font-ui);
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--textMut);
    flex: 1 1 200px;
}

/* The full store-by-store matrix, folded away. It is the evidence behind the
   rows above and most readers do not need to open it, but taking it out
   would remove the comparison the post is about. */
.su-snap-more {
    border-top: 1px solid var(--border);
}

.su-snap-more > summary {
    padding: 11px 18px;
    cursor: pointer;
    list-style: none;
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 700;
    color: var(--primary);
}

.su-snap-more > summary::-webkit-details-marker {
    display: none;
}

.su-snap-more > summary::before {
    content: '▸ ';
    display: inline-block;
}

.su-snap-more[open] > summary::before {
    content: '▾ ';
}

.su-snap-matrix {
    overflow-x: auto;
    padding: 0 18px 14px;
}

.su-snap-matrix table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-ui);
    font-size: 12.5px;
}

.su-snap-matrix th,
.su-snap-matrix td {
    padding: 7px 8px;
    border-bottom: 1px solid var(--border);
    text-align: right;
    white-space: nowrap;
}

.su-snap-matrix th:first-child,
.su-snap-matrix td:first-child {
    text-align: left;
    white-space: normal;
}

.su-snap-matrix th {
    color: var(--textMut);
    font-weight: 700;
}

.su-snap-matrix td.cheap {
    font-weight: 800;
    color: var(--savings);
}

.su-snap-matrix a {
    color: inherit;
    text-decoration: none;
}

.su-snap-matrix a:hover {
    text-decoration: underline;
}

/* Below this the row cannot hold a store name and a quantity as well as a
   name and a price. The quantity moves onto the name and the store keeps
   only its dot. */
@media (max-width: 599.98px) {
    .su-snap-row {
        padding: 9px 13px;
        gap: 9px;
    }

    .su-snap-row .q,
    .su-snap-row .st .stname {
        display: none;
    }

    .su-snap-h,
    .su-snap-f,
    .su-snap-totals {
        padding-left: 13px;
        padding-right: 13px;
    }
}

/* ── Pull quote ─────────────────────────────────────────────────────────── */
.su-bp-col .blog-prose blockquote {
    margin: 20px 0;
    padding: 4px 0 4px 16px;
    border-left: 3px solid var(--primary);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 17px;
    line-height: 1.45;
    color: var(--text);
}

.su-bp-col .blog-prose blockquote p:last-child {
    margin-bottom: 0;
}

/* ── Figures ────────────────────────────────────────────────────────────────
   Screenshots inside a how-to. The border matters: most of these are captures
   of Cuugo's own UI, which is mostly white, so without one the image bleeds
   into the page and the reader cannot tell where the screenshot ends. */
.blog-prose .blog-figure {
    margin: 24px 0;
}

.blog-prose .blog-figure img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--border);
    border-radius: var(--su-radius-md);
    background: var(--su-bg-surface);
}

/* ── Tables ─────────────────────────────────────────────────────────────────
   Basket comparisons are naturally tabular. The wrapper scrolls rather than the
   page: a four-column store comparison does not fit a phone, and a table that
   forces the whole article sideways is worse than one that scrolls itself. */
.blog-prose .blog-table-wrap {
    margin: 22px 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.blog-prose .blog-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-ui);
    font-size: 14px;
    line-height: 1.45;
}

.blog-prose .blog-table th,
.blog-prose .blog-table td {
    padding: 9px 14px;
    border-bottom: 1px solid var(--border);
    text-align: left;
    white-space: nowrap;
}

.blog-prose .blog-table th {
    font-weight: 600;
    color: var(--text);
    border-bottom-width: 2px;
}

.blog-prose .blog-table td {
    color: var(--textMut);
}

/* The first column is the row's subject -- the store, the product -- so it
   reads as a label rather than as another value. */
.blog-prose .blog-table td:first-child {
    color: var(--text);
    font-weight: 500;
}

.blog-prose .blog-table tbody tr:last-child td {
    border-bottom: none;
}

.blog-prose .blog-figure figcaption {
    margin-top: 8px;
    font-family: var(--font-ui);
    font-size: 13px;
    line-height: 1.5;
    color: var(--textMut);
    text-align: center;
}

/* -----------------------------------------------------------------------------
   Daily pick card
   The archive pages' version of a pick. Same vocabulary as the rail on the
   blog index, given a card's proportions instead of a rail's.
   -------------------------------------------------------------------------- */
.su-dcard {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: var(--surface);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}

@media (hover: hover) and (pointer: fine) {
    .su-dcard:hover {
        border-color: var(--primary);
        transform: translateY(-2px);
        box-shadow: 0 10px 26px var(--glow);
    }
}

.su-dcard:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.su-dcard-img {
    height: 148px;
    flex: none;
    background: var(--imgPlate);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.su-dcard-img img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.su-dcard-glyph {
    color: var(--primary);
    opacity: .45;
}

.su-dcard-body {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
    padding: 13px 15px 15px;
}

.su-dcard-day {
    font-family: var(--font-ui);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--textMut);
}

.su-dcard-title {
    font-family: var(--font-ui);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--text);
    margin: 0;
}

.su-dcard-price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 7px;
    margin-top: auto;
    padding-top: 4px;
}

.su-dcard-now {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 19px;
    color: var(--savings);
}

.su-dcard-was {
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
    text-decoration: line-through;
}

.su-dcard-pct {
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--savings);
    color: var(--onPrimary);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 800;
}

.su-dcard-store {
    display: flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--textMut);
}

.su-dcard-dot {
    width: 9px;
    height: 9px;
    flex: none;
    border-radius: 3px;
    display: inline-block;
}

.su-dcard-sav {
    font-family: var(--font-ui);
    font-size: 11.5px;
    color: var(--okText);
}

/* -----------------------------------------------------------------------------
   Blog post — the share card at the foot of an essentials post
   The basket capture graphic draws at a fixed width. Down here it is an
   optional extra rather than the thing between the reader and the article,
   so it scrolls sideways on a narrow screen instead of forcing the page to.
   -------------------------------------------------------------------------- */
.su-bp-sharecard {
    overflow-x: auto;
    border-radius: 14px;
}
/* -----------------------------------------------------------------------------
   Add-basket-to-list dialog
   -------------------------------------------------------------------------- */
.su-bkt-loading {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 2px;
    font-family: var(--font-ui);
    font-size: 13.5px;
    color: var(--textMut);
}

.su-bkt-plan {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 11px;
    background: var(--rowBg2);
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
}

.su-bkt-plan-icon {
    color: var(--primary);
    font-size: 1.1rem;
}

/* The list of things that could not be added. Named, because "3 items were
   skipped" is not something a reader can act on and "Weet-Bix 1.2kg is out of
   stock" is. */
.su-bkt-missing {
    list-style: none;
    margin: 6px 0 0;
    padding: 0;
}

.su-bkt-missing li {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 5px 0;
    font-family: var(--font-ui);
    font-size: 12.5px;
}

.su-bkt-missing li + li {
    border-top: 1px solid var(--border);
}

.su-bkt-missing .nm {
    flex: 1;
    min-width: 0;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.su-bkt-missing .why {
    flex: none;
    color: var(--warnText);
    font-weight: 600;
}

/* Pick-your-own, when the basket does not fit the plan. */
.su-bkt-picklist {
    max-height: 216px;
    overflow-y: auto;
    margin-top: 8px;
    border: 1px solid var(--border);
    border-radius: 11px;
}

.su-bkt-pick {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    cursor: pointer;
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
}

.su-bkt-pick + .su-bkt-pick {
    border-top: 1px solid var(--border);
}

.su-bkt-pick.on {
    background: var(--hoverWash);
}

.su-bkt-pick input {
    accent-color: var(--primary);
    width: 16px;
    height: 16px;
    flex: none;
}

.su-bkt-pick .nm {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.su-bkt-pick .q {
    flex: none;
    color: var(--textMut);
    font-size: 12px;
}

/* The result. */
.su-bkt-done {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 10px 4px 14px;
    text-align: center;
}

.su-bkt-done-icon {
    color: var(--savings);
    font-size: 2.2rem;
}

.su-bkt-done-main {
    font-family: var(--font-ui);
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
}

.su-bkt-done-sub {
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--textMut);
}

/* ── 404 ──────────────────────────────────────────────────────────────────
   The trolley treatment from cuugo-states-preview.html: 4🛒4, sitting where an
   EmptyState would otherwise put its icon tile.

   Still a real <h1>, because this is a routed page like any other and the
   router focuses h1 on navigation. The digits are in --primary rather than
   --text: it is the graphic of the page, not its heading, and the words below
   it do the reading. Replaces .su-404-code, which drew a plain "404". */
.su-404 {
    margin: 0 0 6px;
    font-family: var(--font-display);
    font-size: clamp(3rem, 12vw, 4.5rem);
    font-weight: 800;
    line-height: 1;
    text-align: center;
    color: var(--primary);
    letter-spacing: -.04em;
}

/* The emoji sits high against the digits' cap height; nudging it down puts the
   trolley on the same baseline as the fours it stands between. */
.su-404-trolley {
    display: inline-block;
    transform: translateY(4px);
}

/* ── SkeletonCard (Batch 6) ──────────────────────────────────────────────────
   Two shapes, because the app loads products into two: a list row and a grid
   tile. Geometry from cuugo-states-preview.html for the row.

   .su-shimmer rather than .ssr-skel, which is the same technique but belongs to
   the pre-hydration placeholders written directly into App.razor — that class
   carries flex-shrink:0 for its own layout and is applied to raw HTML this
   component does not own. Same keyframes though, not a second animation.

   No prefers-reduced-motion rule here on purpose: the global block at the top
   of this file already clamps every animation, and a second guard is one more
   thing to keep in step. */

.su-shimmer {
    background-color: var(--field);
    background-image: linear-gradient(90deg, transparent 25%, var(--shine) 50%, transparent 75%);
    background-size: 200% 100%;
    animation: ssr-shimmer 1.5s infinite;
    border-radius: 8px;
    display: block;
}

.su-skel {
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 13px;
}

/* Row: thumb, text, price on one line. */
.su-skel.is-row {
    display: flex;
    align-items: center;
    gap: 11px;
}

    .su-skel.is-row .su-skel-thumb {
        width: 40px;
        height: 40px;
        border-radius: 10px;
        flex: none;
    }

    .su-skel.is-row .su-skel-body {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 7px;
        min-width: 0;
    }

    .su-skel.is-row .su-skel-price {
        width: 52px;
        height: 16px;
        flex: none;
    }

/* Card: image block above the text, price under it. Proportioned to the
   product card it stands in for rather than to the row. */
.su-skel.is-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

    .su-skel.is-card .su-skel-thumb {
        width: 100%;
        aspect-ratio: 1 / 1;
        border-radius: 10px;
    }

    .su-skel.is-card .su-skel-body {
        display: flex;
        flex-direction: column;
        gap: 7px;
    }

    .su-skel.is-card .su-skel-price {
        width: 64px;
        height: 18px;
    }

.su-skel-line-1 {
    height: 12px;
    width: 72%;
}

.su-skel-line-2 {
    height: 10px;
    width: 46%;
}

/* ── Snackbar intents (Batch 6) ──────────────────────────────────────────────
   Four intents on the theme's own semantic ramps, replacing MudBlazor's filled
   palette colours. The preview's toast treatment: a tinted surface with
   tone-matched text, no saturated fill, no border.

   Styled through .mud-alert-filled-* rather than by changing how snackbars are
   raised. There are 726 Snackbar.Add calls across the two apps — 439 error, 160
   success, 83 warning, 15 info — and every one of them picks up this styling
   without being touched.

   Error uses --errSoft/--errText, not the accent the preview's .toast.err maps
   to: the accent is per-theme and is teal under matariki, which would paint a
   failure in the colour of success. See DEVIATIONS D98. */

.mud-snackbar.mud-alert-filled-success {
    background: var(--okSoft) !important;
    color: var(--okText) !important;
}

.mud-snackbar.mud-alert-filled-warning {
    background: var(--warnSoft) !important;
    color: var(--warnText) !important;
}

.mud-snackbar.mud-alert-filled-error {
    background: var(--errSoft) !important;
    color: var(--errText) !important;
}

/* Info and normal are not events with a mood — they are the app saying
   something. A plain field surface with a border, which is the preview's
   .info2, rather than a colour that implies an outcome. */
.mud-snackbar.mud-alert-filled-info,
.mud-snackbar.mud-alert-filled-normal {
    background: var(--field) !important;
    color: var(--text) !important;
    border: 1px solid var(--fieldBorder);
}

/* The icon and the close button inherit the intent's text colour rather than
   carrying MudBlazor's white-on-fill, which is invisible on a tinted surface. */
.mud-snackbar .mud-snackbar-icon,
.mud-snackbar .mud-alert-close,
.mud-snackbar .mud-alert-close .mud-icon-root {
    color: inherit !important;
}

/* The action is the point of a snackbar that has one ("View list", "Retry
   now"), so it reads as a control rather than as more of the sentence. */
.mud-snackbar .mud-snackbar-content-action .mud-button-root {
    color: inherit !important;
    font-weight: 700;
}

/* The support reference on the error page. Quiet by design — it matters only
   to the handful of people who write in, and it should not compete with the
   apology above it. */
.su-error-ref {
    margin: 0;
    text-align: center;
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--textMut);
}

    .su-error-ref code {
        font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
        font-size: 12px;
        word-break: break-all;
        color: var(--text);
    }

/* ── Plan features dialog (Batch 5) ──────────────────────────────────────────
   The list that used to live in PlanSummaryCard's expansion panel. Two groups:
   what the plan includes, and what it does not. The absent rows get an em dash
   rather than a cross — it is an absence, not an error to act on — which is the
   same treatment DESIGN-BATCHES specifies for the Subscribe cards. */

.su-planfeat-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.su-planfeat-group + .su-planfeat-group {
    margin-top: 4px;
    padding-top: 14px;
    border-top: 1px solid var(--border);
}

.su-planfeat-h {
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--textMut);
    margin-bottom: 6px;
}

.su-planfeat-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-family: var(--font-ui);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text);
    padding: 5px 0;
}

.su-planfeat-row.is-off {
    color: var(--textMut);
}

.su-planfeat-mark {
    flex: 0 0 auto;
    line-height: 1.45;
}

.su-planfeat-mark.is-on {
    color: var(--savings);
}

/* Width matches the check icon's box so both groups align on one text column. */
.su-planfeat-mark.is-off {
    width: 20px;
    text-align: center;
    color: var(--textMut);
}

.su-planfeat-empty {
    color: var(--textMut);
}

/* Caption on the plan summary card. Was Color.Secondary, which is the coral
   accent in this theme and read as a warning on a neutral sentence. */
.su-onb-caption {
    color: var(--textMut);
}

/* ── Auth pages (Batch 5) ────────────────────────────────────────────────────
   Polish only — the structure of Login / Register / ForgotPassword /
   ResetPassword is deliberately unchanged. These two classes replace uses of
   MudBlazor's Color.Secondary and Severity.Info, both of which resolved to
   colours outside the theme: Secondary is the coral accent, so neutral
   sentences rendered as if something had gone wrong, and Info is blue, which
   appears nowhere else in the palette. */

.su-auth-sub {
    color: var(--textMut);
}

/* Supporting notes ("we'll only send to your registered email"). A quiet
   surface with a hairline, not a coloured alert — it is reassurance, not an
   event the reader has to respond to. */
.su-auth-note.mud-alert {
    background: var(--hoverWash);
    border: 1px solid var(--border);
    border-radius: var(--su-radius-md);
    box-shadow: none;
}

.su-auth-note.mud-alert,
.su-auth-note.mud-alert .mud-alert-message,
.su-auth-note.mud-alert .mud-typography {
    color: var(--text);
}

.su-auth-note.mud-alert .mud-alert-icon {
    color: var(--textMut);
}


/* ── Subscribe: billing toggle, price line, fine print (Batch 5) ─────────────
   The billing period was a switch whose thumb showed a red cross while monthly
   was selected, so the default state read as "off" or "something is wrong".
   A segmented control has no off state. */

.su-billing-toggle {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-bottom: 28px;
}

.su-billing-note {
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--textMut);
}

/* The per-month figure is the hero; everything qualifying it sits beneath in
   one quiet line, so the eye compares like with like across the cards. */
.su-price-sub {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--textMut);
    min-height: 20px;
}

.su-price-was {
    text-decoration: line-through;
    opacity: .75;
}

.su-plan-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
}

.su-plan-fineprint {
    font-family: var(--font-ui);
    font-size: 12px;
    color: var(--textMut);
    text-align: center;
}

/* Cards are narrower than the dialog, so let long feature names wrap. */
.su-plan-features .su-planfeat-row {
    align-items: flex-start;
}


/* ── Account management hub (Batch 5) ───────────────────────────────────────
   A persistent side nav beside whichever management page is open. The pages
   keep their own routes; this only frames them, so a deep link to
   /Account/Manage/Security still works and still shows where it sits. */

.su-manage {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 28px;
    align-items: start;
    width: 100%;
}

.su-manage-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: sticky;
    top: 88px;
}

.su-manage-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: var(--su-radius-md);
    font-family: var(--font-ui);
    font-size: 14px;
    color: var(--text);
    text-decoration: none;
    border: 1px solid transparent;
    transition: background-color .15s ease, border-color .15s ease;
}

.su-manage-link:hover {
    background: var(--hoverWash);
}

/* Current section is marked by weight and a tinted ground rather than colour
   alone, so it survives both themes and does not rely on hue perception. */
.su-manage-link.is-current {
    background: var(--hoverWash);
    border-color: var(--border);
    font-weight: 600;
}

/* Password, two-factor and close-account sit under a parent section. Indented
   and quieter, but still real links -- they were routes before this hub and
   would otherwise be reachable only from inside another page. */
.su-manage-link.is-sub {
    margin-left: 18px;
    font-size: 13px;
    color: var(--textMut);
}

.su-manage-body {
    min-width: 0;
}

/* Mobile: the rail becomes a horizontal strip of pills above the content,
   which is what DESIGN-BATCHES asks for. */
@media (max-width: 900px) {
    .su-manage {
        grid-template-columns: 1fr;
        gap: 16px;
    }

    .su-manage-nav {
        position: static;
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 8px;
        overflow-x: auto;
        padding-bottom: 4px;
        -webkit-overflow-scrolling: touch;
    }

    .su-manage-link {
        border: 1px solid var(--border);
        border-radius: 999px;
        white-space: nowrap;
        flex: 0 0 auto;
    }

    .su-manage-link.is-sub {
        margin-left: 0;
    }
}

/* ── Product summary prose (SEO Phase 4) ─────────────────────────────────────
   One generated paragraph per product, saying in words what the figures above
   already say in numerals. It exists because two unrelated product pages shared
   85% of their visible text: every sentence on a product page came from the
   shared chrome, and the part that was actually about the product was chips and
   numbers. Measured line length, no colour of its own beyond the body token. */
.pd-summary-prose {
    line-height: 1.55;
    max-width: 68ch;
    color: var(--mud-palette-text-primary);
}

/* ── Category / search page heading ──────────────────────────────────────────
   The results page had no heading naming its own subject. Someone arriving
   from Google on a category page met a filter bar and a grid of products with
   nothing telling them what they were looking at, and the document's only
   heading was the sidebar's "Browse Categories".

   Sits above .su-sticky-filter-header, so it scrolls away instead of following
   the reader. Padding matches that bar's own 8px so the two line up. */
.su-results-heading {
    padding: 0 8px;
    margin: 0 0 4px;
    font-weight: 700;
    letter-spacing: -0.4px;
    color: var(--mud-palette-text-primary);
    text-wrap: balance;
}

/* ── Drawer nav labels stay on one line ──────────────────────────────────────
   A label that wraps does not just look different, it moves every item below
   it. "Grocery Price Index" rendered on one line at first paint and two a
   moment later, taking the rest of the column down 26px: about one load in
   three, worth 0.127 CLS by itself against a 0.1 budget.

   nowrap makes that structurally impossible for any label, present or future.
   The ellipsis is the deliberate trade: a label too long for the drawer gets
   visibly cut, which someone will notice and shorten, rather than silently
   reflowing the column for every visitor. */
.mud-navmenu .mud-nav-link-text {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
