/* ABOUTME: Neumorphism (Soft UI) design system — shadows, tokens, components.
 * ABOUTME: Loaded after nexus.css in owner layout; wins specificity ties.
 *
 * COEXISTENCE RULES (owner layout loads both nexus.css and this file):
 *
 * 1. LOAD ORDER: neumorphism.css loads after nexus.css — wins specificity ties.
 *
 * 2. STRUCTURAL COMPONENTS: Don't override DaisyUI collapse, modal, table,
 *    or form-control. Work around them with scoped selectors (.neu-sidebar .collapse).
 *
 * 3. OVERFLOW: Don't place neu-* shadow elements inside DaisyUI components
 *    with overflow: hidden (modals, drawers, card-body) without a wrapper
 *    that sets overflow: visible.
 *
 * 4. COLORS (new code): Color values should reference design-tokens.css
 *    variables via var(--color-neu-*) with fallbacks. Legacy hex values remain.
 *
 * 5. ICONS: nexus provides .iconify base rendering (mask-image: var(--svg)).
 *    lucide_icons.css provides icon shapes via background-image.
 *    This file MUST NOT set mask-image on .iconify elements.
 */

/* ===== NEXUS.CSS UTILITY GAPS =====
 * nexus.css is a pre-built, static Tailwind bundle — NOT recompiled by bin/dev.
 * Common utility classes (margins, tabular-nums, flex-1, small fixed widths,
 * items-baseline, etc.) can be silently absent with no build error; the class
 * just renders as a no-op. Verified against the compiled bundle with:
 *   grep -c '^\.classname{' app/assets/stylesheets/nexus.css
 * before using ANY Tailwind utility not already proven elsewhere in the owner
 * dashboard. When a needed utility is missing, add a small neu-* primitive
 * here (this file IS live-compiled) rather than an inline style — inline
 * styles scattered per-view are what caused this gap to be rediscovered
 * (and reintroduced) multiple times in the same session before this section
 * existed. Add to this list as new gaps are found; don't duplicate an
 * existing entry.
 */
.neu-mb-4 {
  margin-bottom: 1rem;
}

.neu-mb-6 {
  margin-bottom: 1.5rem;
}

.neu-my-4 {
  margin-top: 1rem;
  margin-bottom: 1rem;
}

.neu-ml-auto {
  margin-left: auto;
}

.neu-items-baseline {
  align-items: baseline;
}

.neu-tabular-nums {
  font-variant-numeric: tabular-nums;
}

.neu-flex-1 {
  flex: 1 1 0%;
}

.neu-text-right {
  text-align: right;
}

/* nexus.css's .hidden{display:none} and this file's .neu-btn/.neu-badge
   (display:inline-flex) are both single-class selectors — a tie the cascade
   breaks by source order, and this file loads after nexus.css and wins. That
   silently un-hides a .neu-btn/.neu-badge also carrying .hidden (e.g. a
   Stimulus-toggled button on Growth > Acquisition). Scoped to the compound
   selector — not a bare .hidden — so it wins ONLY against .neu-btn/.neu-badge
   on specificity alone, with no !important and no effect on the ~181 other
   views that use the plain .hidden utility class. */
.neu-btn.hidden,
.neu-badge.hidden {
  display: none;
}

.neu-dot {
  display: inline-block;
  width: 0.625rem;
  height: 0.625rem;
  flex-shrink: 0;
}

/* ===== INTER FONT (self-hosted — latin, latin-ext, cyrillic subsets) ===== */
/* Variable font: font-weight 400 800 covers all weights in a single file.    */

/* cyrillic (Russian UI) */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/inter-v20-cyrillic-a10feb6d.woff2") format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* latin-ext (accented characters for Spanish, French) */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/inter-v20-latin-ext-5a6754fc.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin (English and core ASCII) */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/assets/inter-v20-latin-496a588b.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Type-to-sign: the same OFL font owner/memberships_controller.rb already renders
   typed cancellation names in for its legacy PDF export, now used to rasterize a
   typed signature client-side (app/javascript/utils/typed_signature.js). */
@font-face {
  font-family: 'Dancing Script';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/DancingScript-9c7c30eb.ttf") format('truetype');
}

/* ===== SAFE AREA (iOS notch / dynamic island / home indicator) ===== */
@supports (padding: env(safe-area-inset-top)) {
  .neu-topbar {
    padding-top: env(safe-area-inset-top);
  }

  .container.mx-auto {
    padding-left: max(0.75rem, env(safe-area-inset-left));
    padding-right: max(0.75rem, env(safe-area-inset-right));
  }

  #layout-sidebar.neu-sidebar {
    padding-top: env(safe-area-inset-top);
  }
}

/* ===== COLOR TOKENS ===== */
:root {
  /* Color tokens reference design-tokens.css as single source of truth.
     To change neumorphic colors, edit design-tokens.css, not here. */
  --neu-bg: var(--color-neu-bg, #E0E5EC);
  --neu-text: var(--color-neu-text, #3D4852);
  --neu-muted: var(--color-neu-muted, #6B7280);
  --neu-accent: var(--color-neu-primary, #F0880F);
  --neu-accent-light: var(--color-neu-primary-light, #F5A640);
  --neu-accent-deep: #D97308;
  --neu-accent-soft: rgba(240, 136, 15, 0.08);
  --neu-accent-secondary: var(--color-neu-secondary, #38B2AC);

  /* Shadow colors (RGBA for smooth blending) */
  --neu-shadow-dark: rgb(163, 177, 198, 0.6);
  --neu-shadow-dark-strong: rgb(163, 177, 198, 0.7);
  --neu-shadow-light: rgba(255, 255, 255, 0.5);
  --neu-shadow-light-strong: rgba(255, 255, 255, 0.6);
  /* Depth hierarchy — elevated surfaces are slightly brighter, recessed slightly darker */
  --neu-bg-elevated: #E8ECF3;
  --neu-bg-recessed: #D6DBE3;
  /* Inner highlight for top-left light source */
  --neu-highlight: rgba(255, 255, 255, 0.7);

  /* Subtle border / divider */
  --neu-border-subtle: rgba(163, 177, 198, 0.35);

  /* Interactive tints — accent-derived, theme-aware */
  --neu-hover-tint: rgba(240, 136, 15, 0.08);
  --neu-hover-tint-faint: rgba(240, 136, 15, 0.04);
  --neu-focus-ring: rgba(240, 136, 15, 0.2);
  /* Neutral surface tint — skeletons, ghost badges, dividers */
  --neu-surface-tint: rgba(163, 177, 198, 0.3);

  /* Chart neutrals (read by soft_ui_chart_config.js at render time) */
  --neu-chart-grid: rgba(163, 177, 198, 0.2);

  /* Semantic status colors (design-system canon; NOT for chart series —
     chart semantics live in utils/chart_colors.js) */
  --neu-success: #10B981;
  --neu-warning: #F59E0B;
  --neu-error: #EF4444;
  --neu-info: #3B82F6;
  /* Darker variants for white-text-on-solid-fill badges (e.g. the sidebar
     open/closed status pill) — --neu-success/--neu-error above are tuned
     for use as text color against the neutral background and fail WCAG
     4.5:1 with white text as a fill (2.5-3.8:1 measured). Scoped to this
     one usage rather than changing the shared tokens everywhere else.
     Literal hex, matching every other token in this section (this file's
     own header comment says colors should reference design-tokens.css,
     but that file isn't actually linked on any owner-dashboard page —
     --neu-error-solid's value is a coincidental match with that file's
     unused --color-error, not a reference to it). */
  --neu-success-solid: #047857;
  --neu-error-solid: #DC2626;
  /* Darker still, for SMALL error text (form-level validation messages) on the
     neutral background. --neu-error above measures 2.97:1 at 12px against
     --neu-bg and --neu-error-solid only reaches 3.81:1 — both fail WCAG AA's
     4.5:1. This one measures 5.11:1. Scoped to that usage, following the same
     rule as the -solid pair above: add a purpose-tuned variant rather than
     re-tint the shared --neu-error every other view already depends on. */
  --neu-error-text: #B91C1C;

  /* Typeface roles */
  --font-display: 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Fluid unit: 0.92rem @ 1024px → 1rem @ 1440px
     Derivation (breakpoints in rem at 16px root font size):
       slope     = (1.0 - 0.92) / (90 - 64) = 0.08/26 ≈ 0.3077vw coefficient
       intercept = 0.92rem − (0.08/26) × 64rem = 0.7231rem  */
  --fluid-unit: clamp(0.92rem, 0.7231rem + 0.3077vw, 1rem);

  /* ===== FLUID DESIGN TOKENS =====
     Single source of truth for responsive sizing.
     All values scale with viewport: clamp(min, preferred, max)
     min  = floor at ~1024px tablet
     pref = scales with vw
     max  = ceiling at ~1440px+ desktop */

  /* Typography scale */
  --fluid-xs: clamp(0.625rem, 0.9vw, 0.875rem);
  /* counts, helpers */
  --fluid-sm: clamp(0.875rem, 1.2vw, 1.25rem);
  /* labels, badges */
  --fluid-base: clamp(1rem, 1.4vw, 1.5rem);
  /* body, buttons */
  --fluid-lg: clamp(1.25rem, 1.7vw, 1.75rem);
  /* subheadings */
  --fluid-xl: clamp(1.5rem, 2.2vw, 2.5rem);
  /* stat values */
  --fluid-2xl: clamp(1.75rem, 2.5vw, 2.75rem);
  /* emphasis numbers */
  --fluid-3xl: clamp(2.25rem, 3.2vw, 3.5rem);
  /* major headings */
  --fluid-4xl: clamp(2.5rem, 3.8vw, 4rem);
  /* giant display */

  /* Spacing scale */
  --fluid-gap-xs: clamp(0.125rem, 0.2vw, 0.375rem);
  /* micro gaps */
  --fluid-gap-sm: clamp(0.25rem, 0.3vw, 0.5rem);
  /* small gaps */
  --fluid-pad-sm: clamp(0.375rem, 0.6vw, 1rem);
  /* small padding */
  --fluid-pad-md: clamp(0.75rem, 1vw, 1.25rem);
  /* medium padding/gaps */
  --fluid-pad-lg: clamp(1rem, 1.3vw, 1.75rem);
  /* large padding */
  --fluid-pad-xl: clamp(1.5rem, 2vw, 2.75rem);
  /* XL padding */
  --fluid-gap-lg: clamp(1rem, 1.8vw, 2.25rem);
  /* large section gaps */

  /* Touch target sizes */
  --fluid-touch-sm: clamp(2.5rem, 2.5vw, 3.5rem);
  /* small targets */
  --fluid-touch-md: clamp(3rem, 3vw, 4.5rem);
  /* standard buttons */
  --fluid-touch-lg: clamp(4rem, 3.5vw, 5.5rem);
  /* large buttons */
  --fluid-touch-xl: clamp(5rem, 4.5vw, 7rem);
  /* XL buttons */

  /* Border radius */
  --fluid-radius: clamp(0.75rem, 1vw, 1.25rem);
  /* standard */
  --fluid-radius-lg: clamp(1rem, 1.3vw, 1.75rem);
  /* large elements */

  /* Sidebar nav — min(vw, vh) ensures buttons shrink on short viewports */
  --fluid-sidebar-btn: clamp(2.25rem, min(3.2vw, 6vh), 5rem);

  /* Neumorphic shadow breathing room — must exceed neu-extruded-sm extent (5+10=15px) */
  --fluid-neu-space: clamp(0.625rem, 1.1vw, 1.25rem);

  /* Icon / emoji */
  --fluid-icon: clamp(1rem, 1.8vw, 2rem);
}

/* ===== SHADOW TOKENS ===== */
/* Stepped bilateral shadow tokens — breakpoints mirror the --fluid-unit responsive range
   Tablet  ≤1279 px : 7 / 14 px  (~88 % of desktop)
   Laptop  1280–1439px: 8 / 16 px
   Desktop ≥1440 px : 9 / 16 px  (original values, no visual change) */
:root {
  --shadow-offset: 7px;
  --shadow-blur: 14px;
}

@media (min-width: 1280px) {
  :root {
    --shadow-offset: 8px;
    --shadow-blur: 16px;
  }
}

@media (min-width: 1440px) {
  :root {
    --shadow-offset: 9px;
    --shadow-blur: 16px;
  }
}

/* Plate state abbreviation — hidden below 1440px, visible on wide screens */
.plate-state-responsive {
  display: none;
}

@media (min-width: 1440px) {
  .plate-state-responsive {
    display: inline;
  }
}

/* ===== DARK MODE ===== */
/* Single source of the dark --neu-* token overrides. neumorphism-dark.css keeps
   only the landing-page neu-dark-* utility classes; it must not redefine these. */
[data-theme="dark"] {
  --neu-bg: #2D3436;
  --neu-text: #E4E6E8;
  --neu-muted: #9CA3AF;
  --neu-accent: #F5A640;
  --neu-accent-light: #F5A640;
  --neu-accent-deep: #F0880F;
  --neu-accent-soft: rgba(245, 166, 64, 0.1);
  --neu-accent-secondary: #4FD1C5;
  --neu-shadow-dark: rgba(0, 0, 0, 0.5);
  --neu-shadow-dark-strong: rgba(0, 0, 0, 0.6);
  --neu-shadow-light: rgba(69, 75, 78, 0.4);
  --neu-shadow-light-strong: rgba(69, 75, 78, 0.5);
  --neu-bg-elevated: #353B3D;
  --neu-bg-recessed: #252A2C;
  --neu-highlight: rgba(69, 75, 78, 0.5);
  --neu-border-subtle: rgba(0, 0, 0, 0.15);
  --neu-hover-tint: rgba(245, 166, 64, 0.14);
  --neu-hover-tint-faint: rgba(245, 166, 64, 0.08);
  --neu-focus-ring: rgba(245, 166, 64, 0.35);
  --neu-surface-tint: rgba(255, 255, 255, 0.08);
  --neu-chart-grid: rgba(69, 75, 78, 0.35);
  /* Status colors lifted one step for legibility on charcoal */
  --neu-success: #34D399;
  --neu-success-solid: #34D399;
  --neu-warning: #FBBF24;
  --neu-error: #F87171;
  --neu-info: #60A5FA;
  /* On charcoal the light-theme #B91C1C would read at 2.0:1. The lifted red
     already clears AA here (4.67:1), so small error text uses it unchanged. */
  --neu-error-text: #F87171;
  /* RGB channel overrides for Tailwind opacity modifier support */
  --color-neu-bg-rgb: 45 52 54;
  --color-neu-text-rgb: 228 230 232;
  --color-neu-muted-rgb: 156 163 175;
}

/* Dark mode overrides for hardcoded Tailwind colors */
[data-theme="dark"] body {
  background-color: #2D3436 !important;
}

[data-theme="dark"] footer {
  background-color: #2D3436 !important;
}

[data-theme="dark"] nav {
  background-color: #2D3436 !important;
}

/* Dashboard background with subtle noise texture for depth */
.neu-dashboard-bg {
  background-color: var(--neu-bg);
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.03'/%3E%3C/svg%3E");
}

[data-theme="dark"] .neu-dashboard-bg {
  background-color: var(--neu-bg);
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
}

/* ===== BACKGROUND UTILITIES ===== */
.neu-bg {
  background: var(--neu-bg, #E0E5EC);
}

/* ===== SHADOW UTILITIES ===== */
.neu-extruded {
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
}

/* Highlighted card with accent glow - no ring */
.neu-card-highlighted {
  box-shadow: 0 0 0 3px var(--neu-accent),
    calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light-strong);
}

.neu-extruded-hover {
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light-strong);
}

.neu-extruded-sm {
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-inset {
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-inset-deep {
  box-shadow: inset calc(var(--shadow-offset) + 1px) calc(var(--shadow-offset) + 1px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) + 1px)) calc(-1 * (var(--shadow-offset) + 1px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light-strong);
}

.neu-inset-sm {
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

/* Hardware status glyph — shared by owner topbar and operator footer strips. */
.neu-device-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 0.5rem;
  background: var(--neu-bg);
  cursor: pointer;
}

.neu-device-glyph-icon {
  width: 1rem;
  height: 1rem;
}

/* Small inset stat tile — used for chart summary totals (cash/card, confirmed/pending/disputed).
   Uses --neu-shadow-light-strong (not the plain -light used by .neu-inset-sm above) to exactly
   preserve the original inline style this replaced — not a typo. */
.neu-stat-tile {
  border-radius: 1rem;
  background: var(--neu-bg);
  box-shadow: inset 3px 3px 6px var(--neu-shadow-dark),
    inset -3px -3px 6px var(--neu-shadow-light-strong);
}

/* ===== DEPTH HIERARCHY ===== */
/* Elevated surface — sits above the base plane */
.neu-elevated {
  background: var(--neu-bg-elevated);
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light);
}

/* Recessed surface — sits below the base plane */
.neu-recessed {
  background: var(--neu-bg-recessed);
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light);
}

/* Inner highlight for top-left light source on interactive elements */
.neu-interactive-highlight {
  position: relative;
}

.neu-interactive-highlight::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 50%;
  bottom: 50%;
  border-radius: inherit;
  background: radial-gradient(ellipse at 20% 20%, var(--neu-highlight) 0%, transparent 70%);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 1;
}

.neu-interactive-highlight:hover::before {
  opacity: 1;
}

/* Neumorphic tinted button — accent color as surface tint + colored glow instead of opaque gradient */
.neu-btn-tinted {
  background: var(--neu-bg);
  border: none;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-btn-tinted.btn-tint-green {
  background: linear-gradient(135deg,
      color-mix(in srgb, var(--neu-bg) 85%, #10B981 15%),
      color-mix(in srgb, var(--neu-bg) 80%, #059669 20%));
  box-shadow: 6px 6px 12px var(--neu-shadow-dark),
    -6px -6px 12px var(--neu-shadow-light),
    0 0 20px rgba(16, 185, 129, 0.15);
  color: #059669;
}

.neu-btn-tinted.btn-tint-green:hover {
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light),
    0 0 30px rgba(16, 185, 129, 0.25);
  transform: translateY(-2px);
}

.neu-btn-tinted.btn-tint-green:active {
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light),
    0 0 15px rgba(16, 185, 129, 0.1);
  transform: translateY(1px);
}

.neu-btn-tinted.btn-tint-blue {
  background: linear-gradient(135deg,
      color-mix(in srgb, var(--neu-bg) 85%, #3B82F6 15%),
      color-mix(in srgb, var(--neu-bg) 80%, #2563EB 20%));
  box-shadow: 6px 6px 12px var(--neu-shadow-dark),
    -6px -6px 12px var(--neu-shadow-light),
    0 0 20px rgba(59, 130, 246, 0.15);
  color: #2563EB;
}

.neu-btn-tinted.btn-tint-blue:hover {
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light),
    0 0 30px rgba(59, 130, 246, 0.25);
  transform: translateY(-2px);
}

.neu-btn-tinted.btn-tint-blue:active {
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light),
    0 0 15px rgba(59, 130, 246, 0.1);
  transform: translateY(1px);
}

.neu-btn-tinted.btn-tint-amber {
  background: linear-gradient(135deg,
      color-mix(in srgb, var(--neu-bg) 85%, #F59E0B 15%),
      color-mix(in srgb, var(--neu-bg) 80%, #D97706 20%));
  box-shadow: 6px 6px 12px var(--neu-shadow-dark),
    -6px -6px 12px var(--neu-shadow-light),
    0 0 20px rgba(245, 158, 11, 0.15);
  color: #D97706;
}

.neu-btn-tinted.btn-tint-amber:hover {
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light),
    0 0 30px rgba(245, 158, 11, 0.25);
  transform: translateY(-2px);
}

.neu-btn-tinted.btn-tint-amber:active {
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light),
    0 0 15px rgba(245, 158, 11, 0.1);
  transform: translateY(1px);
}

.neu-btn-tinted.btn-tint-red {
  background: linear-gradient(135deg,
      color-mix(in srgb, var(--neu-bg) 85%, #EF4444 15%),
      color-mix(in srgb, var(--neu-bg) 80%, #DC2626 20%));
  box-shadow: 6px 6px 12px var(--neu-shadow-dark),
    -6px -6px 12px var(--neu-shadow-light),
    0 0 20px rgba(239, 68, 68, 0.15);
  color: #DC2626;
}

.neu-btn-tinted.btn-tint-red:hover {
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light),
    0 0 30px rgba(239, 68, 68, 0.25);
  transform: translateY(-2px);
}

.neu-btn-tinted.btn-tint-red:active {
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light),
    0 0 15px rgba(239, 68, 68, 0.1);
  transform: translateY(1px);
}

.neu-btn-tinted.btn-tint-purple {
  background: linear-gradient(135deg,
      color-mix(in srgb, var(--neu-bg) 85%, #6366F1 15%),
      color-mix(in srgb, var(--neu-bg) 80%, #8B5CF6 20%));
  box-shadow: 6px 6px 12px var(--neu-shadow-dark),
    -6px -6px 12px var(--neu-shadow-light),
    0 0 20px rgba(99, 102, 241, 0.15);
  color: #6366F1;
}

.neu-btn-tinted.btn-tint-purple:hover {
  box-shadow: 8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light),
    0 0 30px rgba(99, 102, 241, 0.25);
  transform: translateY(-2px);
}

.neu-btn-tinted.btn-tint-purple:active {
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark),
    inset -4px -4px 8px var(--neu-shadow-light),
    0 0 15px rgba(99, 102, 241, 0.1);
  transform: translateY(1px);
}

/* ===== TYPOGRAPHY ===== */
/* Matches designprompts.dev/neumorphism reference exactly */
/* Hero: 800 weight | Section headings: 700 weight | Subheadings: 600 weight */

/* Section headings (h2) - 700 weight like reference */
.neu-heading {
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: "wght" 700;
  color: var(--neu-text);
  letter-spacing: -0.025em;
  line-height: 1.1;
}

/* Hero heading (h1) - 800 weight extra bold */
.neu-heading-xl {
  font-family: var(--font-display);
  font-weight: 800;
  font-variation-settings: "wght" 800;
  color: var(--neu-text);
  letter-spacing: -0.03em;
  line-height: 1.05;
}

/* Subheadings (h3, h4, benefit titles) - 700 weight like reference */
.neu-heading-md {
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: "wght" 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.neu-body {
  font-family: 'DM Sans', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  font-weight: 400;
  /* Color controlled by Tailwind utilities for flexibility */
}

.neu-muted {
  color: var(--neu-muted);
}

/* ===== TRANSITIONS ===== */
.neu-transition {
  transition: all 300ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Ensure all shadow utilities animate smoothly for neumorphic state changes */
.neu-extruded,
.neu-extruded-sm,
.neu-extruded-hover,
.neu-inset,
.neu-inset-deep,
.neu-inset-sm,
.neu-elevated,
.neu-recessed {
  transition: box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1), transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), background 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Respect prefers-reduced-motion: kill hover/press lift + inset transforms
   dashboard-wide, keep color/shadow feedback so state changes stay legible. */
@media (prefers-reduced-motion: reduce) {

  .neu-dashboard-bg *,
  .neu-dashboard-bg *::before,
  .neu-dashboard-bg *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .neu-dashboard-bg [class*="neu-"]:hover,
  .neu-dashboard-bg [class*="neu-"]:active {
    transform: none !important;
  }
}

/* ===== FOCUS STATES ===== */
.neu-focus {
  outline: none;
  ring: 2px solid var(--neu-accent);
  ring-offset: 2px;
  ring-offset-color: var(--neu-bg);
}

/* ===== SCROLL ANIMATIONS ===== */
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }

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

@keyframes fadeInLeft {
  from {
    opacity: 0;
    transform: translateX(-30px);
  }

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

@keyframes fadeInRight {
  from {
    opacity: 0;
    transform: translateX(30px);
  }

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

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }

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

/* Animation utility classes */
.animate-fade-in-up {
  animation: fadeInUp 0.6s ease-out forwards;
}

.animate-fade-in-left {
  animation: fadeInLeft 0.6s ease-out forwards;
}

.animate-fade-in-right {
  animation: fadeInRight 0.6s ease-out forwards;
}

.animate-scale-in {
  animation: scaleIn 0.5s ease-out forwards;
}

/* Scroll-triggered animations (initially hidden) */
[data-animate] {
  opacity: 0;
}

[data-animate].is-visible {
  animation-fill-mode: forwards;
}

[data-animate="fade-up"].is-visible {
  animation: fadeInUp 0.6s ease-out forwards;
}

[data-animate="fade-left"].is-visible {
  animation: fadeInLeft 0.6s ease-out forwards;
}

[data-animate="fade-right"].is-visible {
  animation: fadeInRight 0.6s ease-out forwards;
}

[data-animate="scale"].is-visible {
  animation: scaleIn 0.5s ease-out forwards;
}

/* Stagger delays */
[data-delay="100"] {
  animation-delay: 100ms;
}

[data-delay="200"] {
  animation-delay: 200ms;
}

[data-delay="300"] {
  animation-delay: 300ms;
}

[data-delay="400"] {
  animation-delay: 400ms;
}

[data-delay="500"] {
  animation-delay: 500ms;
}

[data-delay="600"] {
  animation-delay: 600ms;
}

/* ===== GRADIENT TEXT ===== */
.neu-gradient-text {
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-secondary) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ===== GLOW EFFECTS ===== */
.neu-glow {
  box-shadow: 0 0 40px rgba(240, 136, 15, 0.3),
    9px 9px 16px var(--neu-shadow-dark),
    -9px -9px 16px var(--neu-shadow-light);
}

.neu-glow-accent {
  box-shadow: 0 0 30px rgba(240, 136, 15, 0.4);
}

/* ===== FEATURE ICON STYLE ===== */
.neu-icon-box {
  width: 4rem;
  height: 4rem;
  border-radius: 1rem;
  background: var(--neu-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
}

.neu-icon-box-lg {
  width: 5rem;
  height: 5rem;
  border-radius: 1.25rem;
}

/* ===== STATS PILL ===== */
.neu-stat-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-radius: 9999px;
  background: var(--neu-bg);
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

/* ===== BADGE STYLES =====
   Single canonical .neu-badge base + variants (was previously duplicated at two
   locations in this file; the later block silently won the cascade and dropped
   -accent/-muted). Keep all variants here going forward. */
.neu-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.25rem 0.625rem;
  border-radius: 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  /* A badge owns its own typography. Display-scale tracking (.neu-stat-value's
     -0.02em, ~-1px at 28px) inherits into a 12px badge as ~8% negative tracking,
     which swallows the word space outright: "Membership discounted" rendered as
     "Membershipdiscounted". */
  letter-spacing: normal;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  box-shadow: 2px 2px 4px var(--neu-shadow-dark),
    -2px -2px 4px var(--neu-shadow-light);
}

.neu-badge-ghost {
  background-color: var(--neu-surface-tint);
  /* --neu-muted alone passes 4.5:1 against the plain --neu-bg (that's what
     it's tuned for) but not against this badge's own tinted background —
     measured 3.27:1 light / 3.9:1 dark. Darker/lighter overrides below
     restore 4.5:1+ without touching the shared --neu-muted token used
     elsewhere against the untinted background. */
  color: #4B5563;
}

[data-theme="dark"] .neu-badge-ghost {
  color: #AEB4BF;
}

.neu-badge-outline {
  background-color: transparent;
  border: 1px solid var(--neu-border-subtle);
  color: var(--neu-muted);
  box-shadow: none;
}

.neu-badge-muted {
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
}

/* Color variants — DO NOT add box-shadow: none here.
   neu-badge base class provides the raised neumorphic shadow;
   suppressing it makes badges look flat and indistinct. */
.neu-badge-success {
  background-color: #10B981;
  color: white;
}

.neu-badge-warning {
  background-color: #F59E0B;
  color: white;
}

.neu-badge-error {
  background-color: #EF4444;
  color: white;
}

.neu-badge-info {
  background-color: #3B82F6;
  color: white;
}

.neu-badge-primary {
  background-color: var(--neu-accent);
  color: white;
}

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

.neu-badge-secondary {
  background-color: var(--color-neu-secondary, #38B2AC);
  color: white;
}

/* Size modifiers — adjust font-size + padding only; color/shadow inherit from base */
.neu-badge-sm {
  padding: 0.125rem 0.5rem;
  font-size: calc(var(--fluid-unit) * 0.6875);
}

.neu-badge-lg {
  padding: 0.375rem 0.875rem;
  font-size: calc(var(--fluid-unit) * 0.875);
}

/* Section label badge - indented/inset style like "Sponsors" */
.neu-section-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 1.25rem;
  border-radius: 9999px;
  background: var(--neu-bg);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-section-badge-icon {
  color: var(--neu-accent);
}

/* Trust strip badge with green dot */
.neu-trust-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 1.25rem;
  border-radius: 9999px;
  background: var(--neu-bg);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-trust-badge .dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: #10B981;
}

/* ===== DIVIDER ===== */
.neu-divider {
  height: 2px;
  background: linear-gradient(90deg,
      transparent 0%,
      var(--neu-shadow-dark) 20%,
      var(--neu-shadow-dark) 80%,
      transparent 100%);
  border: none;
  margin: 3rem 0;
}

/* ===== QUOTE STYLE ===== */
.neu-quote {
  position: relative;
  padding-left: 1.5rem;
  border-left: 4px solid var(--neu-accent);
  font-style: italic;
}

.neu-quote::before {
  content: '"';
  position: absolute;
  top: -0.5rem;
  left: -0.5rem;
  font-size: 3rem;
  color: var(--neu-accent);
  opacity: 0.3;
  font-family: Georgia, serif;
}

/* ===== FORM INPUT STYLES ===== */
/* Remove browser default focus rings on neumorphic inputs */
.neu-inset input,
.neu-inset select,
.neu-inset textarea {
  outline: none !important;
  box-shadow: none !important;
  border: none !important;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}

.neu-inset input:focus,
.neu-inset select:focus,
.neu-inset textarea:focus {
  outline: none !important;
  box-shadow: none !important;
  border: none !important;
}

/* Custom select dropdown arrow */
.neu-inset select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%236B7280'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 1.25rem;
  padding-right: 3rem;
}

/* ===== ANTI-FLICKER ===== */
/* Prevent flashing during page load - elements start visible, then animate on scroll */
[data-animate] {
  opacity: 0;
  will-change: opacity, transform;
}

/* Ensure smooth animation without flickering */
.is-visible {
  animation-fill-mode: forwards !important;
}

/* Reduce bubble animation intensity to prevent flicker */
@keyframes bubble-rise-smooth {
  0% {
    transform: translateY(0) scale(1);
    opacity: 0.5;
  }

  100% {
    transform: translateY(-100vh) scale(1.1);
    opacity: 0;
  }
}

/* Override bubble animation with smoother version */
.animate-bubble-rise {
  animation: bubble-rise-smooth linear infinite;
  will-change: transform, opacity;
}

/* ===== SLIDER STYLES ===== */
/* Neumorphic range sliders for calculators */
.neu-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 0.75rem;
  border-radius: 9999px;
  background: linear-gradient(to right, var(--neu-accent) 0%, var(--neu-accent) 50%, #C1CCD6 50%, #C1CCD6 100%);
  cursor: pointer;
  outline: none;
}

.neu-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px var(--neu-accent);
  cursor: grab;
  transition: transform 0.15s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.15s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-slider::-webkit-slider-thumb:hover {
  transform: scale(1.1);
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 0 0 4px var(--neu-accent);
}

.neu-slider::-webkit-slider-thumb:active {
  cursor: grabbing;
  transform: scale(0.95);
}

.neu-slider::-moz-range-thumb {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px var(--neu-accent);
  cursor: grab;
  border: none;
  transition: transform 0.15s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.15s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-slider::-moz-range-thumb:hover {
  transform: scale(1.1);
}

/* Red slider variant (for damage/cost inputs) */
.neu-slider-red::-webkit-slider-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #EF4444;
}

.neu-slider-red::-moz-range-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #EF4444;
}

/* Amber slider variant (for upsell rate) */
.neu-slider-amber::-webkit-slider-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #F59E0B;
}

.neu-slider-amber::-moz-range-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #F59E0B;
}

/* Purple slider variant (for time inputs) */
.neu-slider-purple::-webkit-slider-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #8B5CF6;
}

.neu-slider-purple::-moz-range-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 3px #8B5CF6;
}

/* Focus state for accessibility */
.neu-slider:focus {
  outline: none;
}

.neu-slider:focus::-webkit-slider-thumb {
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light),
    0 0 0 4px var(--neu-accent),
    0 0 12px rgba(240, 136, 15, 0.4);
}

/* ===== MICRO-INTERACTIONS ===== */

/* Card hover lift effect */
.neu-card-interactive {
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  cursor: pointer;
}

.neu-card-interactive:hover {
  transform: translateY(-4px);
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 8px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 8px) var(--neu-shadow-light-strong);
}

/* Subtle card hover (less dramatic) */
.neu-card-hover {
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-card-hover:hover {
  transform: translateY(-2px);
  box-shadow: calc(var(--shadow-offset) + 1px) calc(var(--shadow-offset) + 1px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) + 1px)) calc(-1 * (var(--shadow-offset) + 1px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light);
}

/* Button press effect - extruded to inset */
.neu-btn-press {
  transition: all 0.15s cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
}

.neu-btn-press:hover {
  box-shadow: calc(var(--shadow-offset) - 1px) calc(var(--shadow-offset) - 1px) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 1px)) calc(-1 * (var(--shadow-offset) - 1px)) var(--shadow-blur) var(--neu-shadow-light);
  transform: translateY(-1px);
}

.neu-btn-press:active {
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transform: translateY(1px);
}

/* Icon pulse animation */
@keyframes iconPulse {

  0%,
  100% {
    transform: scale(1);
    box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
      calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
  }

  50% {
    transform: scale(1.05);
    box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
      calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light);
  }
}

.neu-icon-pulse {
  animation: iconPulse 2s ease-in-out infinite;
}

.neu-icon-pulse-hover:hover {
  animation: iconPulse 1s ease-in-out infinite;
}

/* Accent icon with glow pulse */
@keyframes accentGlow {

  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(240, 136, 15, 0.4);
  }

  50% {
    box-shadow: 0 0 20px 4px rgba(240, 136, 15, 0.3);
  }
}

.neu-icon-glow {
  animation: accentGlow 2.5s ease-in-out infinite;
}

/* ===== GLASSMORPHISM ===== */
.neu-glass {
  background: rgba(255, 255, 255, 0.25);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.3);
}

.neu-glass-subtle {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.neu-glass-card {
  background: linear-gradient(135deg,
      rgba(255, 255, 255, 0.4) 0%,
      rgba(255, 255, 255, 0.1) 100%);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.4);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

/* ===== ENHANCED QUOTE/TESTIMONIAL CARDS ===== */
.neu-testimonial {
  position: relative;
  padding: 2rem;
  border-radius: 1.5rem;
  background: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 1px) calc(var(--shadow-offset) - 1px) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 1px)) calc(-1 * (var(--shadow-offset) - 1px)) var(--shadow-blur) var(--neu-shadow-light);
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-testimonial:hover {
  transform: translateY(-3px);
  box-shadow: calc(var(--shadow-offset) + 1px) calc(var(--shadow-offset) + 1px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) + 1px)) calc(-1 * (var(--shadow-offset) + 1px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light);
}

.neu-testimonial::before {
  content: '"';
  position: absolute;
  top: 1rem;
  left: 1.5rem;
  font-size: 4rem;
  font-family: Georgia, serif;
  color: var(--neu-accent);
  opacity: 0.2;
  line-height: 1;
}

.neu-testimonial-accent {
  border-left: 4px solid var(--neu-accent);
}

/* Quote icon circle */
.neu-quote-icon {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 1.25rem;
  box-shadow: 0 4px 15px rgba(240, 136, 15, 0.3);
}

/* ===== VERTICAL TIMELINE (Numbered Steps) ===== */
.neu-timeline-vertical {
  position: relative;
  padding-left: 0;
}

/* The connecting line */
.neu-timeline-vertical::before {
  content: '';
  position: absolute;
  left: 2.75rem;
  top: 3.5rem;
  bottom: 3.5rem;
  width: 4px;
  background: linear-gradient(180deg,
      var(--neu-accent) 0%,
      rgba(240, 136, 15, 0.3) 50%,
      var(--neu-accent) 100%);
  border-radius: 2px;
}

/* ===== HORIZONTAL TIMELINE (How It Works) ===== */
.neu-timeline-horizontal {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: 2rem;
}

/* Horizontal connecting line */
.neu-timeline-horizontal::before {
  content: '';
  position: absolute;
  top: calc(2rem + 2rem);
  /* padding-top + half of circle height */
  left: 15%;
  right: 15%;
  height: 4px;
  background: linear-gradient(90deg,
      var(--neu-accent) 0%,
      rgba(240, 136, 15, 0.5) 50%,
      var(--neu-accent) 100%);
  border-radius: 2px;
  z-index: 1;
}

@media (min-width: 768px) {
  .neu-timeline-horizontal::before {
    left: 10%;
    right: 10%;
  }
}

/* Timeline step for horizontal layout */
.neu-timeline-h-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  position: relative;
  z-index: 2;
  flex: 1;
  max-width: 280px;
}

/* Large neumorphic circle with number (horizontal) */
.neu-timeline-h-number {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 1px) calc(var(--shadow-offset) - 1px) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 1px)) calc(-1 * (var(--shadow-offset) - 1px)) var(--shadow-blur) var(--neu-shadow-light);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.5rem;
}

/* Inner accent circle */
.neu-timeline-h-number-inner {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.125rem;
  box-shadow: inset 2px 2px 4px rgba(255, 255, 255, 0.3),
    0 4px 12px rgba(240, 136, 15, 0.4);
}

/* Timeline step item */
.neu-timeline-step {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  position: relative;
  padding-bottom: 2rem;
}

.neu-timeline-step:last-child {
  padding-bottom: 0;
}

/* Large neumorphic circle with number */
.neu-timeline-number {
  flex-shrink: 0;
  width: 5.5rem;
  height: 5.5rem;
  border-radius: 50%;
  background: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 1px) calc(var(--shadow-offset) - 1px) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 1px)) calc(-1 * (var(--shadow-offset) - 1px)) var(--shadow-blur) var(--neu-shadow-light);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 2;
}

/* Inner circle with accent color */
.neu-timeline-number-inner {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.5rem;
  box-shadow: inset 2px 2px 4px rgba(255, 255, 255, 0.3),
    0 4px 15px rgba(240, 136, 15, 0.4);
}

/* Red variant for pain points */
.neu-timeline-number-inner.is-red {
  background: linear-gradient(135deg, #EF4444 0%, #F87171 100%);
  box-shadow: inset 2px 2px 4px rgba(255, 255, 255, 0.3),
    0 4px 15px rgba(239, 68, 68, 0.4);
}

/* Timeline content card */
.neu-timeline-content {
  flex: 1;
  padding-top: 1rem;
}

/* ===== PDF PREVIEW EFFECTS ===== */
@keyframes floatSubtle {

  0%,
  100% {
    transform: translateY(0);
  }

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

.neu-float {
  animation: floatSubtle 4s ease-in-out infinite;
}

/* Gentle floating animation for stat cards */
@keyframes floatGently {

  0%,
  100% {
    transform: translateY(0);
  }

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

@keyframes floatGentlyDelayed {

  0%,
  100% {
    transform: translateY(0);
  }

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

.neu-float-gentle {
  animation: floatGently 3s ease-in-out infinite;
}

.neu-float-gentle-delayed {
  animation: floatGentlyDelayed 3s ease-in-out infinite;
  animation-delay: 1.5s;
}

/* Shine effect overlay */
@keyframes shine {
  0% {
    transform: translateX(-100%) rotate(25deg);
  }

  100% {
    transform: translateX(200%) rotate(25deg);
  }
}

.neu-shine {
  position: relative;
  overflow: hidden;
}

.neu-shine::after {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 50%;
  height: 200%;
  background: linear-gradient(90deg,
      transparent,
      rgba(255, 255, 255, 0.3),
      transparent);
  transform: rotate(25deg);
  animation: shine 4s ease-in-out infinite;
  pointer-events: none;
}

/* ===== COUNTER ANIMATION ===== */
.neu-counter {
  font-variant-numeric: tabular-nums;
  transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

/* ===== STAGGERED GRID ANIMATION ===== */
.neu-grid-stagger>* {
  opacity: 0;
  transform: translateY(20px);
}

.neu-grid-stagger.is-visible>*:nth-child(1) {
  animation: fadeInUp 0.5s ease forwards 0.1s;
}

.neu-grid-stagger.is-visible>*:nth-child(2) {
  animation: fadeInUp 0.5s ease forwards 0.2s;
}

.neu-grid-stagger.is-visible>*:nth-child(3) {
  animation: fadeInUp 0.5s ease forwards 0.3s;
}

.neu-grid-stagger.is-visible>*:nth-child(4) {
  animation: fadeInUp 0.5s ease forwards 0.4s;
}

.neu-grid-stagger.is-visible>*:nth-child(5) {
  animation: fadeInUp 0.5s ease forwards 0.5s;
}

.neu-grid-stagger.is-visible>*:nth-child(6) {
  animation: fadeInUp 0.5s ease forwards 0.6s;
}

.neu-grid-stagger.is-visible>*:nth-child(7) {
  animation: fadeInUp 0.5s ease forwards 0.7s;
}

.neu-grid-stagger.is-visible>*:nth-child(8) {
  animation: fadeInUp 0.5s ease forwards 0.8s;
}

/* ===== KEY INSIGHT CARD (Glassmorphism) ===== */
.neu-insight-card {
  background: linear-gradient(135deg,
      rgba(240, 136, 15, 0.1) 0%,
      rgba(240, 136, 15, 0.05) 100%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(240, 136, 15, 0.2);
  box-shadow: 0 8px 32px rgba(240, 136, 15, 0.15),
    8px 8px 16px var(--neu-shadow-dark),
    -8px -8px 16px var(--neu-shadow-light);
}

/* ===== FEATURE CARD WITH ICON ===== */
.neu-feature-card {
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-feature-card:hover {
  transform: translateY(-4px);
}

.neu-feature-card:hover .neu-feature-icon {
  animation: iconPulse 0.6s ease;
}

/* ===== ANIMATED GRADIENT ORBS ===== */
@keyframes orbFloat {

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

  25% {
    transform: translate(5%, 10%) scale(1.05);
  }

  50% {
    transform: translate(-5%, 5%) scale(0.95);
  }

  75% {
    transform: translate(10%, -5%) scale(1.02);
  }
}

@keyframes orbPulse {

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

  50% {
    opacity: 0.6;
    transform: scale(1.1);
  }
}

.neu-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
  will-change: transform, opacity;
}

.neu-orb-accent {
  background: radial-gradient(circle, var(--neu-accent) 0%, transparent 70%);
  animation: orbFloat 20s ease-in-out infinite, orbPulse 8s ease-in-out infinite;
}

.neu-orb-teal {
  background: radial-gradient(circle, var(--neu-accent-secondary) 0%, transparent 70%);
  animation: orbFloat 25s ease-in-out infinite reverse, orbPulse 10s ease-in-out infinite;
  animation-delay: -5s;
}

.neu-orb-success {
  background: radial-gradient(circle, #10B981 0%, transparent 70%);
  animation: orbFloat 22s ease-in-out infinite, orbPulse 9s ease-in-out infinite;
  animation-delay: -3s;
}

/* ===== ENHANCED CTA BUTTON ===== */
.neu-cta-primary {
  position: relative;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-deep) 100%);
  border-radius: 1rem;
  padding: 1rem 2rem;
  font-weight: 600;
  color: white;
  border: none;
  cursor: pointer;
  overflow: hidden;
  box-shadow:
    0 10px 30px -5px rgba(240, 136, 15, 0.4),
    0 4px 6px -2px rgba(240, 136, 15, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: all 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-cta-primary::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 50%;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.15), transparent);
  border-radius: 1rem 1rem 0 0;
  pointer-events: none;
}

.neu-cta-primary:hover {
  transform: translateY(-2px);
  box-shadow:
    0 14px 35px -5px rgba(240, 136, 15, 0.5),
    0 8px 12px -4px rgba(240, 136, 15, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.neu-cta-primary:active {
  transform: translateY(0);
  box-shadow:
    0 6px 20px -3px rgba(240, 136, 15, 0.35),
    0 2px 4px -1px rgba(240, 136, 15, 0.2),
    inset 0 2px 4px rgba(0, 0, 0, 0.1);
}

/* Ripple effect for CTA */
@keyframes ripple {
  to {
    transform: scale(4);
    opacity: 0;
  }
}

.neu-cta-primary .ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  animation: ripple 0.6s linear;
  pointer-events: none;
}

/* ===== TEXT DEPTH & SHADOWS ===== */
.neu-heading-shadow {
  text-shadow:
    1px 1px 0 rgba(255, 255, 255, 0.8),
    -1px -1px 2px rgba(163, 177, 198, 0.3);
}

.neu-heading-shadow-dark {
  text-shadow:
    2px 2px 4px rgba(163, 177, 198, 0.4),
    -1px -1px 2px rgba(255, 255, 255, 0.6);
}

/* Embossed text effect */
.neu-text-embossed {
  text-shadow:
    1px 1px 1px rgba(255, 255, 255, 0.9),
    -1px -1px 1px rgba(163, 177, 198, 0.5);
}

/* Inset text effect */
.neu-text-inset {
  text-shadow:
    -1px -1px 1px rgba(255, 255, 255, 0.6),
    1px 1px 1px rgba(163, 177, 198, 0.5);
}

/* ===== LINK HOVER EFFECTS ===== */
.neu-link {
  color: var(--neu-accent);
  text-decoration: none;
  position: relative;
  transition: color 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-link::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--neu-accent), var(--neu-accent-secondary));
  transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-link:hover::after {
  width: 100%;
}

.neu-link:hover {
  color: var(--neu-accent-light);
}

/* ===== PAGE LOAD ANIMATION ===== */
@keyframes pageLoad {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

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

.neu-page-enter {
  animation: pageLoad 0.5s ease-out;
}

/* ===== SMOOTH SCROLLBAR ===== */
.neu-scrollbar::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.neu-scrollbar::-webkit-scrollbar-track {
  background: var(--neu-bg);
  border-radius: 4px;
}

.neu-scrollbar::-webkit-scrollbar-thumb {
  background: var(--neu-shadow-dark);
  border-radius: 4px;
  border: 2px solid var(--neu-bg);
}

.neu-scrollbar::-webkit-scrollbar-thumb:hover {
  background: var(--neu-accent);
}

/* ===== SKELETON LOADING ===== */
@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }

  100% {
    background-position: 200% 0;
  }
}

.neu-skeleton {
  background: linear-gradient(90deg,
      var(--neu-bg) 0%,
      rgba(255, 255, 255, 0.5) 50%,
      var(--neu-bg) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 0.5rem;
}

/* ===== ACCENT GLOW BACKGROUND ===== */
.neu-bg-glow {
  position: relative;
  overflow: hidden;
}

.neu-bg-glow::before {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: radial-gradient(circle at 30% 30%,
      rgba(240, 136, 15, 0.1) 0%,
      transparent 50%),
    radial-gradient(circle at 70% 70%,
      rgba(56, 178, 172, 0.08) 0%,
      transparent 50%);
  pointer-events: none;
  animation: orbFloat 30s ease-in-out infinite;
}

/* ===== FOCUS RING UTILITY ===== */
.neu-focus-ring:focus {
  outline: none;
  box-shadow:
    0 0 0 3px var(--neu-bg),
    0 0 0 5px var(--neu-accent);
}

/* ===== SUBTLE BORDER GRADIENTS ===== */
.neu-border-gradient {
  position: relative;
  background: var(--neu-bg);
  border-radius: 1.5rem;
}

.neu-border-gradient::before {
  content: '';
  position: absolute;
  inset: 0;
  padding: 2px;
  border-radius: inherit;
  background: linear-gradient(135deg,
      rgba(240, 136, 15, 0.3) 0%,
      rgba(255, 255, 255, 0.5) 50%,
      rgba(56, 178, 172, 0.3) 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

/* ===== DASHBOARD-SPECIFIC STYLES ===== */

/* Dashboard Layout Background */
.neu-dashboard-bg {
  background-color: var(--neu-bg);
}

/* Dashboard Card (replaces card bg-base-100 shadow) */
.neu-card {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  /* rounded-2xl equivalent */
  padding: 1.25rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  transition: all 300ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-card:hover {
  transform: translateY(-2px);
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light-strong);
}

.neu-card-flat {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.25rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
}

/* Dashboard Sidebar */
.neu-sidebar {
  background-color: var(--neu-bg);
  box-shadow: var(--shadow-offset) 0 var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset) / 3) 0 calc(var(--shadow-blur) / 2) var(--neu-shadow-light);
}

/* Owner layout: keep sidebar pinned to the viewport on desktop.
   On mobile (<64rem), nexus handles fixed positioning + margin-based show/hide.
   We only force fixed positioning on desktop where the sidebar is always visible. */
@media (min-width: 64rem) {
  #layout-sidebar.neu-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--layout-sidebar-width);
    min-width: var(--layout-sidebar-width);
    height: 100vh;
    max-height: 100vh;
  }

  @supports (height: 100dvh) {
    #layout-sidebar.neu-sidebar {
      height: 100dvh;
      max-height: 100dvh;
    }
  }
}

/* On mobile the off-canvas drawer block below owns positioning (fixed +
   margin-inline-start). Here we size it and kill the shadow when closed — it
   bleeds into the viewport from off-screen — restoring it only when open. */
@media (max-width: 63.999rem) {
  #layout-sidebar.neu-sidebar {
    width: var(--layout-sidebar-width);
    min-width: var(--layout-sidebar-width);
    height: 100vh;
    max-height: 100vh;
    box-shadow: none;
  }

  /* Restore shadow only when sidebar is open */
  #layout-sidebar-toggle-trigger:checked~#layout-sidebar.neu-sidebar {
    box-shadow: var(--shadow-offset) 0 var(--shadow-blur) var(--neu-shadow-dark),
      calc(-1 * var(--shadow-offset) / 3) 0 calc(var(--shadow-blur) / 2) var(--neu-shadow-light);
  }

  @supports (height: 100dvh) {
    #layout-sidebar.neu-sidebar {
      height: 100dvh;
      max-height: 100dvh;
    }
  }
}

.neu-sidebar-menu-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.75rem;
  color: var(--neu-text);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-sidebar-menu-item:hover {
  background-color: var(--neu-hover-tint);
  transform: translateX(2px);
}

.neu-sidebar-menu-item.active {
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  color: var(--neu-accent);
  font-weight: 600;
}

/* Sidebar Menu Item (for existing .menu-item class) */
.neu-sidebar .menu-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.75rem;
  color: var(--neu-muted);
  font-size: calc(var(--fluid-unit) * 0.875);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-sidebar .menu-item:hover {
  color: var(--neu-text);
}

.neu-sidebar .menu-item:hover .iconify {
  color: var(--neu-accent);
}

/* Active menu item - EXTRUDED (raised) appearance like Vuse Admin reference */
.neu-sidebar .menu-item.active {
  background-color: var(--neu-bg-elevated);
  color: var(--neu-accent);
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
}

/* Sidebar Icons — plain SVG shapes from lucide_icons.css.
   lucide icons are mask-image shapes painted with background-color: currentColor,
   so this rule must keep the paint (a transparent background erases the icon)
   and recolors purely through `color`. */
.neu-sidebar .menu-item .iconify,
.neu-sidebar .collapse-title .iconify:first-child {
  width: 1.75rem;
  height: 1.75rem;
  padding: 0.325rem;
  border-radius: 0.5rem;
  background-color: currentColor;
  box-shadow: none;
  color: var(--neu-muted);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Collapse-content sub-menu icons are smaller */
.neu-sidebar .collapse-content .menu-item {
  padding: 0.5rem 0.75rem;
  font-size: calc(var(--fluid-unit) * 0.8125);
}

.neu-sidebar .collapse-content .menu-item .iconify {
  width: 1.25rem;
  height: 1.25rem;
  padding: 0;
}

/* Arrow and external-link icons — no padding/radius */
.neu-sidebar .collapse-title .arrow-icon,
.neu-sidebar .menu-item .iconify.lucide--external-link {
  padding: 0;
  border-radius: 0;
}

/* Hover: icon turns accent */
.neu-sidebar .menu-item:hover .iconify,
.neu-sidebar .collapse-title:hover .iconify:first-child {
  color: var(--neu-accent);
}

/* Active / expanded: currentColor-painted masks recolor with plain `color`
   (the old background-image SVGs needed a filter hack; masks don't). */
.neu-sidebar .menu-item.active .iconify,
.neu-sidebar .collapse:has(input:checked)>.collapse-title .iconify:first-child {
  color: var(--neu-accent);
}

/* Collapse-content active icons just get accent color, no filter */
.neu-sidebar .collapse-content .menu-item.active .iconify {
  color: var(--neu-accent);
}

/* Shadow-safe overflow for sidebar containers.
   DaisyUI .collapse sets overflow: hidden for expand/collapse animation.
   The .sidebar-menu scroll wrapper uses overflow-auto which clips shadows.
   Fix: overflow-visible on collapse, split overflow axes on scroll area
   so vertical scrolling works but horizontal shadows paint outside. */
.neu-sidebar .collapse {
  overflow: visible;
}

.neu-sidebar .sidebar-menu.grow {
  overflow-y: auto;
  overflow-x: visible;
}

.neu-sidebar .collapse-title {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.75rem;
  color: var(--neu-muted);
  font-size: calc(var(--fluid-unit) * 0.875);
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-sidebar .collapse-title:hover {
  color: var(--neu-text);
}

/* Expanded collapse menu — active parent styling */
.neu-sidebar .collapse:has(input:checked)>.collapse-title {
  color: var(--neu-text);
  font-weight: 600;
}

/* Area Chart Gradient Fill */
.neu-chart-gradient {
  fill: url(#neuGradient);
}

.neu-chart-line {
  stroke: var(--neu-accent);
  stroke-width: 2;
  fill: none;
}

/* Dashboard Topbar */
.neu-topbar {
  background-color: var(--neu-bg);
  box-shadow: 0 4px 12px var(--neu-shadow-dark);
  overflow: visible;
}

/* nexus.css ships xl:block but not xl:flex — owner device strip needs both. */
@media (min-width: 80rem) {
  .xl\:flex {
    display: flex;
  }
}

/* Dashboard KPI Card - Matches reference image style */
.neu-kpi-card {
  position: relative;
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: calc(var(--fluid-unit) * 1.25) calc(var(--fluid-unit) * 1.5);
  box-shadow: calc(var(--shadow-offset) - 1px) calc(var(--shadow-offset) - 1px) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 1px)) calc(-1 * (var(--shadow-offset) - 1px)) var(--shadow-blur) var(--neu-shadow-light);
  transition: all 300ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-kpi-card:hover {
  transform: translateY(-2px);
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 4px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 4px) var(--neu-shadow-light-strong);
}

.neu-kpi-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.neu-kpi-icon {
  width: calc(var(--fluid-unit) * 2.5);
  height: calc(var(--fluid-unit) * 2.5);
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-kpi-value {
  font-family: var(--font-display);
  font-size: calc(var(--fluid-unit) * 1.75);
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.neu-kpi-label {
  font-size: calc(var(--fluid-unit) * 0.875);
  font-weight: 500;
  color: var(--neu-muted);
}

/* Dashboard Button Styles */
.neu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.625rem 1.25rem;
  border-radius: 0.75rem;
  font-weight: 600;
  font-size: calc(var(--fluid-unit) * 0.875);
  background-color: var(--neu-bg);
  color: var(--neu-text);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-btn:hover {
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light);
}

.neu-btn:active {
  transform: translateY(1px);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

/* Visible keyboard focus — only on keyboard interaction (:focus-visible),
   never on mouse click. Works in both themes via --neu-focus-ring. */
.neu-btn:focus-visible {
  outline: none;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-btn-primary {
  background-color: var(--neu-accent);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 4px 15px rgba(240, 136, 15, 0.3);
}

.neu-btn-primary:hover {
  background-color: var(--neu-accent-light);
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light),
    0 6px 20px rgba(240, 136, 15, 0.4);
}

/* Success/teal — same extrusion as .neu-btn-primary with a teal accent glow */
.neu-btn-success {
  background-color: var(--color-neu-secondary, #38B2AC);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 4px 15px rgba(56, 178, 172, 0.3);
}

.neu-btn-success:hover {
  background-color: #2C9A95;
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light),
    0 6px 20px rgba(56, 178, 172, 0.4);
}

/* Secondary/purple — same extrusion as .neu-btn-primary with a purple accent glow */
.neu-btn-secondary {
  background-color: #9c5de8;
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 4px 15px rgba(156, 93, 232, 0.3);
}

.neu-btn-secondary:hover {
  background-color: #ab74ec;
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light),
    0 6px 20px rgba(156, 93, 232, 0.4);
}

.neu-btn-sm {
  padding: 0.5rem 1rem;
  font-size: calc(var(--fluid-unit) * 0.8125);
  border-radius: 0.625rem;
}

/* Owner refund-reason grid. Declared here rather than as utilities on the
   element because .neu-btn/.neu-btn-sm set their own font-size and padding,
   and this control has a hard floor: it is the only way to set a refund
   reason, and it is tapped on the two register tablets (1004x627 and
   1177x706, tools/device-registry.json). Pinned by
   test/system/owner_refund_modal_register_layout_test.rb. */
.owner-refund-reason-btn {
  min-height: 44px;
  padding: 0.5rem 0.625rem;
  font-size: 0.875rem;
  line-height: 1.2;
  text-align: center;
  white-space: normal;
}

/* Remaining owner refund-modal type roles. Sizes live here rather than as raw
   Tailwind text-* utilities on the elements, which bin/lint-owner-typography
   rejects in app/views/owner. */
.owner-refund-type-label {
  font-size: 0.875rem;
  font-weight: 500;
}

/* The required-reason error is the ONLY feedback for that field, so it carries
   the AA-compliant red rather than --neu-error (2.97:1 at this size). */
.owner-refund-reason-error {
  margin-top: 0.25rem;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--neu-error-text);
}

.neu-btn-lg {
  padding: 1rem 1.5rem;
  font-size: calc(var(--fluid-unit) * 1.125);
  border-radius: 1rem;
  min-height: 3.5rem;
}

.neu-btn-giant {
  padding: 1.5rem 2rem;
  font-size: 1.375rem;
  border-radius: 1.5rem;
  min-height: 5rem;
  font-weight: 800;
}

/* Shape modifiers — size-only, inherit the .neu-btn extrusion and base radius */
.neu-btn-circle {
  width: var(--fluid-touch-md);
  height: var(--fluid-touch-md);
  padding: 0;
  border-radius: 9999px;
}

.neu-btn-square {
  width: var(--fluid-touch-md);
  height: var(--fluid-touch-md);
  padding: 0;
}

.neu-btn-block {
  width: 100%;
}

/* Dashboard Input Styles */
.neu-input {
  width: 100%;
  padding: 0.75rem 1rem;
  border-radius: 0.75rem;
  border: none;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  font-size: 0.875rem;
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-input:focus {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light-strong),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-input:focus-visible {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light-strong),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-input::placeholder {
  color: var(--neu-muted);
}

.neu-input[type="date"],
.neu-input[type="datetime-local"],
.neu-input[type="time"] {
  min-height: 2.75rem;
  font-family: inherit;
  color-scheme: light dark;
}

.neu-input[type="date"]::-webkit-calendar-picker-indicator,
.neu-input[type="datetime-local"]::-webkit-calendar-picker-indicator,
.neu-input[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 0.6;
  cursor: pointer;
  filter: invert(0.5);
  transition: opacity 150ms ease;
  margin-right: -0.25rem;
}

.neu-input[type="date"]::-webkit-calendar-picker-indicator:hover,
.neu-input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover,
.neu-input[type="time"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
}

.neu-input[type="date"]::-webkit-datetime-edit,
.neu-input[type="datetime-local"]::-webkit-datetime-edit,
.neu-input[type="time"]::-webkit-datetime-edit {
  padding: 0;
  color: inherit;
}

/* Input wrapper for icon positioning */
.neu-input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.neu-input-wrapper>.iconify:first-child {
  position: absolute;
  left: 0.75rem;
  z-index: 10;
  pointer-events: none;
}

.neu-input-wrapper .neu-input {
  padding-left: 2.5rem;
}

.neu-select {
  width: 100%;
  padding: 0.75rem 1rem;
  padding-right: 2.5rem;
  border-radius: 0.75rem;
  border: none;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  font-size: 0.875rem;
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-select:focus {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light-strong),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-select:focus-visible {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light-strong),
    0 0 0 3px var(--neu-focus-ring);
}

/* Dashboard Toggle Group (Date presets) - Matches reference image */
.neu-toggle-group {
  display: inline-flex;
  gap: 0.5rem;
  background-color: var(--neu-bg);
  border-radius: 2rem;
  padding: 0.375rem;
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-toggle-btn {
  padding: 0.625rem 1.25rem;
  border-radius: 1.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-toggle-btn:hover {
  color: var(--neu-text);
}

.neu-toggle-btn.active {
  background-color: var(--neu-bg);
  color: var(--neu-text);
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

/* Custom Date Range Container */
.neu-date-range-container {
  background-color: var(--neu-bg);
  color: var(--neu-text);
}

.neu-date-range-label {
  color: var(--neu-text);
}

.neu-date-range-separator {
  color: var(--neu-muted);
}

/* Shared owner filter toolbar needs explicit desktop hooks because the
   responsive utility chain is not reliably producing a horizontal layout. */
#owner-shared-filter-toolbar {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

#owner-shared-filter-fields {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
}

#owner-shared-filter-actions {
  width: 100%;
}

/* Owner dashboard filter bar needs explicit desktop layout hooks so it does
   not inherit the stacked mobile presentation on wider screens. */
#owner-dashboard-filter-bar {
  display: flex;
  justify-content: center;
}

#owner-dashboard-filter-content {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
}

#owner-dashboard-filter-location,
#owner-dashboard-filter-range {
  width: 100%;
}

@media (min-width: 640px) {
  #owner-shared-filter-toolbar {
    flex-direction: row;
    align-items: flex-end;
    gap: 1rem;
  }

  #owner-shared-filter-fields {
    flex: 1 1 auto;
    min-width: 0;
    flex-direction: row;
    /* gh#1624 — wrap (not nowrap) so dense filter rows (e.g. customers: search +
       membership + plate + min/max spend) flow onto a second line instead of
       overflowing past #layout-main-content's overflow-x-hidden edge and getting
       clipped (the "license-plate filter breaks containment" report). */
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
  }

  #owner-shared-filter-toolbar .owner-shared-filter-field {
    width: auto;
    min-width: 0;
    flex: 0 0 auto;
  }

  #owner-shared-filter-toolbar .owner-shared-filter-field-flex {
    flex: 1 1 20rem;
    min-width: 16rem;
  }

  #owner-shared-filter-actions {
    display: flex;
    flex: 0 0 auto;
    width: auto;
    flex-direction: row;
    gap: 0.5rem;
    align-self: flex-end;
  }

  #owner-dashboard-filter-bar {
    justify-content: center;
  }

  #owner-dashboard-filter-content {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 1.25rem;
    width: 100%;
  }

  #owner-dashboard-filter-content .neu-toggle-group {
    border-radius: 0.75rem;
    padding: 0.25rem;
  }

  #owner-dashboard-filter-content .neu-toggle-btn {
    border-radius: 0.5rem;
    padding: 0.6rem 1rem;
  }

  #owner-dashboard-filter-location {
    flex: 0 0 auto;
    min-width: 10rem;
    max-width: 14rem;
  }

  #owner-dashboard-filter-range {
    flex: 0 0 auto;
    width: auto;
  }

  #owner-dashboard-filter-range-row {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 1rem;
  }

  #owner-dashboard-custom-date-range {
    flex: 0 0 auto;
    width: auto;
    flex-wrap: nowrap;
  }

  #owner-dashboard-custom-date-range .neu-input {
    width: 9rem;
    min-width: 9rem;
    flex: none;
  }

}

/* Mobile: location + date inputs side-by-side, presets full-width below */
@media (max-width: 639px) {
  #owner-dashboard-filter-content {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "location dates"
      "range    range";
    gap: 0.5rem;
  }

  #owner-dashboard-filter-location {
    grid-area: location;
  }

  #owner-dashboard-custom-date-range {
    grid-area: dates;
    flex-wrap: nowrap;
    gap: 0.25rem;
  }

  #owner-dashboard-custom-date-range .neu-input {
    flex: 1 1 0%;
    min-width: 0;
    font-size: 0.75rem;
    padding: 0.75rem 0.3rem;
  }

  #owner-dashboard-filter-range {
    grid-area: range;
  }
}

/* Card Menu Icon (three dots) */
.neu-card-menu {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 0.5rem;
  border-radius: 0.5rem;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-card-menu:hover {
  background-color: var(--neu-hover-tint);
}

.neu-card-menu-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: var(--neu-muted);
}

/* Circular Progress (neumorphism style) */
.neu-progress-circle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light),
    calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
}

.neu-progress-value {
  font-size: calc(var(--fluid-unit) * 1.5);
  font-weight: 700;
  color: var(--neu-accent);
}

/* Toggle Switch (neumorphism style) */
.neu-switch {
  position: relative;
  width: 3.5rem;
  height: 1.75rem;
  border-radius: 1rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-switch-knob {
  position: absolute;
  top: 0.25rem;
  left: 0.25rem;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background-color: var(--neu-bg);
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-switch.active .neu-switch-knob {
  left: calc(100% - 1.5rem);
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
}

.neu-switch.active {
  background: linear-gradient(135deg, rgba(240, 136, 15, 0.2) 0%, rgba(240, 136, 15, 0.1) 100%);
}

/* Dashboard Chart Card */
.neu-chart-card {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: calc(var(--fluid-unit) * 1.5);
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  height: 100%;
}

.neu-chart-title {
  font-family: var(--font-display);
  font-size: calc(var(--fluid-unit) * 1);
  font-weight: 700;
  color: var(--neu-text);
  margin-bottom: 0.25rem;
}

.neu-chart-subtitle {
  font-size: calc(var(--fluid-unit) * 0.8125);
  color: var(--neu-muted);
}

/* ===== SOFT UI CHART ENHANCEMENTS ===== */

/* Chart container with inset shadow for depth */
.neu-chart-container {
  position: relative;
  padding: calc(var(--fluid-unit) * 1);
  margin-top: 1rem;
  border-radius: 1rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

/* Chart value displays (like reference Temperature/Energy values) */
.neu-chart-value {
  font-size: calc(var(--fluid-unit) * 2);
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
  line-height: 1.2;
}

.neu-chart-value-sm {
  font-size: calc(var(--fluid-unit) * 1.5);
}

.neu-chart-value-lg {
  font-size: calc(var(--fluid-unit) * 2.5);
}

.neu-chart-label {
  font-size: calc(var(--fluid-unit) * 0.8125);
  font-weight: 500;
  color: var(--neu-muted);
  margin-top: 0.25rem;
}

.neu-chart-timestamp {
  font-size: calc(var(--fluid-unit) * 0.75);
  color: var(--neu-muted);
  opacity: 0.7;
}

/* Chart time filter pills (Today/Week/Month like reference) */
.neu-chart-filters {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.25rem;
  background-color: var(--neu-bg);
  border-radius: 2rem;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-chart-filter-btn {
  padding: 0.5rem 1rem;
  border-radius: 1.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-chart-filter-btn:hover {
  color: var(--neu-text);
}

.neu-chart-filter-btn.active {
  background-color: var(--neu-bg);
  color: var(--neu-text);
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

/* Chart action buttons (download svg like reference) */
.neu-chart-action {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.875rem;
  border-radius: 0.75rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-muted);
  background-color: var(--neu-bg);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-chart-action:hover {
  color: var(--neu-accent);
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-chart-action:active {
  transform: translateY(0);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
}

/* Chart legend styling for Soft UI */
.neu-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--neu-border-subtle);
}

.neu-chart-legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--neu-muted);
}

.neu-chart-legend-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  flex-shrink: 0;
}

.neu-chart-legend-dot.primary {
  background: linear-gradient(135deg, #E8B4CB 0%, #9B8AC4 100%);
}

.neu-chart-legend-dot.secondary {
  background: linear-gradient(135deg, #82D9D9 0%, #5BC0C0 100%);
}

.neu-chart-legend-dot.tertiary {
  background: linear-gradient(135deg, #F5A962 0%, #E08942 100%);
}

/* Soft UI metric cards row (like reference KPI cards) */
.neu-metrics-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.neu-metric-card {
  background-color: var(--neu-bg);
  border-radius: 1rem;
  padding: 1rem 1.25rem;
  box-shadow: calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
  position: relative;
}

.neu-metric-card::after {
  content: '';
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: var(--neu-muted);
  box-shadow: 0 6px 0 var(--neu-muted), 0 12px 0 var(--neu-muted);
  opacity: 0.5;
}

.neu-metric-value {
  font-size: calc(var(--fluid-unit) * 1.75);
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
}

.neu-metric-label {
  font-size: calc(var(--fluid-unit) * 0.8125);
  font-weight: 500;
  color: var(--neu-muted);
  margin-top: 0.25rem;
}

.neu-metric-timestamp {
  font-size: calc(var(--fluid-unit) * 0.6875);
  color: var(--neu-muted);
  opacity: 0.6;
  margin-top: 0.5rem;
}

/* Chart canvas wrapper for proper sizing */
.neu-chart-canvas-wrapper {
  position: relative;
  min-height: 250px;
  margin-top: 1rem;
}

.neu-chart-canvas-wrapper canvas {
  max-width: 100%;
}

/* Soft UI area chart gradient animation */
@keyframes chartFadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

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

.neu-chart-animated {
  animation: chartFadeIn 0.6s ease-out forwards;
}

/* Chart loading skeleton */
.neu-chart-skeleton {
  position: relative;
  overflow: hidden;
  background: linear-gradient(90deg,
      var(--neu-bg) 0%,
      rgba(255, 255, 255, 0.3) 50%,
      var(--neu-bg) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 1rem;
}

@keyframes shimmer {
  0% {
    background-position: 200% 0;
  }

  100% {
    background-position: -200% 0;
  }
}

.neu-chart-skeleton-line {
  height: 3px;
  background-color: var(--neu-surface-tint);
  border-radius: 2px;
  margin: 0.5rem 0;
}

.neu-chart-skeleton-area {
  height: 200px;
  background: linear-gradient(180deg,
      rgba(232, 180, 203, 0.2) 0%,
      transparent 100%);
  border-radius: 0.5rem;
}

/* Dashboard Section Headers */
.neu-section-title {
  font-family: var(--font-display);
  font-size: calc(var(--fluid-unit) * 1.125);
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
}

.neu-section-subtitle {
  font-size: calc(var(--fluid-unit) * 0.875);
  color: var(--neu-muted);
}

/* ===== DASHBOARD SHADOW-SAFE LAYOUT UTILITIES ===== */
/*
 * Neumorphic shadows (box-shadow offset + blur) extend OUTSIDE element
 * border-box. Grid gaps and container padding must exceed the maximum shadow
 * reach so shadows are never visually clipped at cell or container edges.
 *
 * At 1440 px: hover shadow = (9+3)px offset + (16+4)px blur/2 = 22px reach.
 * At 1024 px: hover shadow = (7+3)px offset + (14+4)px blur/2 = 19px reach.
 * Gap of 1.75 × fluid-unit = 28px at 1440px / 25.8px at 1024px → safe buffer.
 */

/* Explicit overflow: visible on all neumorphic card primitives ensures no
   ancestor with border-radius clips painted shadows on WebKit. */
.neu-card,
.neu-card-flat,
.neu-kpi-card,
.neu-chart-card {
  overflow: visible;
}

/* Responsive 3-column operations grid with tablet support and shadow-safe gap */
.neu-ops-grid {
  display: grid;
  gap: calc(var(--fluid-unit) * 1.75);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .neu-ops-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .neu-ops-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Responsive 2-column chart grid — last odd item spans full width at lg+ */
.neu-chart-grid {
  display: grid;
  gap: calc(var(--fluid-unit) * 1.75);
  grid-template-columns: 1fr;
}

@media (min-width: 1024px) {
  .neu-chart-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .neu-chart-grid>.neu-chart-full {
    grid-column: span 2;
  }
}

/* KPI card grid: 2-up on sm+, 4-up on xl with shadow-safe gap */
.neu-kpi-grid {
  display: grid;
  gap: calc(var(--fluid-unit) * 1.75);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .neu-kpi-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1280px) {
  .neu-kpi-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Dashboard Progress Bar */
.neu-progress-bar {
  height: 0.5rem;
  border-radius: 9999px;
  background-color: var(--neu-bg);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
  overflow: hidden;
}

.neu-progress-fill {
  height: 100%;
  border-radius: 9999px;
  background: linear-gradient(90deg, var(--neu-accent) 0%, var(--neu-accent-secondary) 100%);
  transition: width 500ms ease-out;
}

/* Dashboard Avatar/User Circle */
.neu-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  color: white;
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-avatar-sm {
  width: 2rem;
  height: 2rem;
  font-size: 0.75rem;
}

.neu-avatar-md {
  width: 2.5rem;
  height: 2.5rem;
  font-size: 0.875rem;
}

/* Dashboard Dropdown */
.neu-dropdown {
  background-color: var(--neu-bg);
  border-radius: 1rem;
  padding: 0.5rem;
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 8px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 8px) var(--neu-shadow-light-strong);
}

.neu-dropdown-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.75rem;
  border-radius: 0.5rem;
  color: var(--neu-text);
  font-size: 0.875rem;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-dropdown-item:hover {
  background-color: var(--neu-hover-tint);
}

/* Dashboard Table Styles */
.neu-table-container {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 0;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  overflow: hidden;
}

.neu-table-row {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--neu-border-subtle);
  transition: background-color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-table-row:last-child {
  border-bottom: none;
}

.neu-table-row:hover {
  background-color: var(--neu-hover-tint-faint);
}

/* Clickable rows (clickable_row_controller.js) — the row is an enhancement on
   top of a real <a> in the row's primary cell, so this is presentation only. */
[data-controller~="clickable-row"] {
  cursor: pointer;
  transition: background-color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

[data-controller~="clickable-row"]:hover {
  background-color: var(--neu-hover-tint-faint);
}

[data-controller~="clickable-row"]:focus-visible {
  outline: 2px solid var(--neu-focus-ring);
  outline-offset: -2px;
}

/* Dashboard Footer */
.neu-footer {
  background-color: var(--neu-bg);
  box-shadow: 0 -4px 12px var(--neu-shadow-dark);
}

/* Dashboard Alert/Flash Messages */
.neu-alert {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-radius: 9999px;
  font-weight: 600;
  font-size: 0.875rem;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-alert-success {
  background-color: rgba(16, 185, 129, 0.15);
  color: #059669;
}

.neu-alert-error {
  background-color: rgba(239, 68, 68, 0.15);
  color: #DC2626;
}

/* Dashboard Icon Button */
.neu-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-icon-btn:hover {
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
}

.neu-icon-btn:active {
  transform: translateY(0);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-icon-btn-sm {
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
}

/* DaisyUI .swap stacks swap-on/swap-off via CSS grid (inline-grid + place-content:
   center, children pinned to grid-row/column-start: 1). .neu-icon-btn's flex
   display overrides .swap's inline-grid, so the stacked children fall back to
   flex layout and collapse to the left instead of centering. Re-assert the grid
   stacking so swap icons (e.g. the topbar theme toggle) stay centered inside the
   icon button in both swap states, light and dark. */
.neu-icon-btn.swap {
  display: inline-grid;
  place-content: center;
}

.neu-icon-btn.swap>* {
  grid-column-start: 1;
  grid-row-start: 1;
}

/* Dashboard Pill/Tag */
.neu-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.75rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

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

.neu-pill-success {
  background-color: #10B981;
  color: white;
}

.neu-pill-warning {
  background-color: #F59E0B;
  color: white;
}

.neu-pill-error {
  background-color: #EF4444;
  color: white;
}

.neu-pill-info {
  background-color: #3B82F6;
  color: white;
}

/* ===== PAGE HEADER STYLES ===== */
.neu-page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 1.5rem;
}

.neu-page-title {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.025em;
}

.neu-page-subtitle {
  font-size: 0.875rem;
  color: var(--neu-muted);
  margin-top: 0.25rem;
}

/* Breadcrumbs */
.neu-breadcrumbs {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--neu-muted);
}

.neu-breadcrumbs a {
  color: var(--neu-muted);
  transition: color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-breadcrumbs a:hover {
  color: var(--neu-accent);
}

.neu-breadcrumbs-separator {
  color: rgba(163, 177, 198, 0.6);
}

.neu-breadcrumbs-current {
  color: var(--neu-text);
  font-weight: 500;
}

/* ===== TABLE STYLES ===== */
.neu-table-card {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  overflow: hidden;
}

/* Opt-in column priority: hide low-priority columns on narrower viewports.
   secondary -> visible at >=1280px (xl); tertiary -> visible at >=1536px (2xl). */
.neu-col-secondary,
.neu-col-tertiary {
  display: none;
}

@media (min-width: 1280px) {
  .neu-col-secondary {
    display: table-cell;
  }
}

@media (min-width: 1536px) {
  .neu-col-tertiary {
    display: table-cell;
  }
}

.neu-table {
  width: 100%;
  border-collapse: collapse;
  background-color: var(--neu-bg);
}

.neu-table thead {
  background-color: var(--neu-bg);
}

.neu-table th {
  padding: 1rem 1.25rem;
  font-weight: 600;
  font-size: 0.75rem;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--neu-muted);
  text-align: left;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.neu-table td {
  padding: 1rem 1.25rem;
  color: var(--neu-text);
  font-size: 0.875rem;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.neu-table tbody tr:last-child td {
  border-bottom: none;
}

/* Standard th eyebrow treatment for tables that build their own <thead>
   markup instead of using .neu-table th directly (fleets/show,
   coupon_reports/index, quickbooks_connections/show). */
.neu-table-header-cell {
  padding: 1rem 1.25rem;
  font-weight: 600;
  font-size: 0.75rem;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--neu-muted);
  text-align: left;
  border-bottom: 1px solid var(--neu-border-subtle);
}

/* Numeric-column and empty-cell conventions (money/count columns right-align
   with tabular numerals; absence is a muted em-dash, not a loud badge). */
.neu-cell-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.neu-cell-empty {
  color: var(--neu-muted);
}

/* Recessed frame for in-table thumbnails (plate crops, evidence tiles). */
.neu-thumb-frame {
  border: 1px solid var(--neu-border-subtle);
  background-color: var(--neu-bg-recessed);
}

/* Compact density is the owner-dashboard standard: every table inside a
   neu-table-card uses it so all owner tables look and fit consistently. */
.neu-table--compact th,
.neu-table-card .neu-table th {
  padding: 0.5rem 0.75rem;
}

.neu-table--compact td,
.neu-table-card .neu-table td {
  padding: 0.5rem 0.75rem;
}

/* Captions aren't th/td, so without this they get no horizontal padding
   and their leading character clips against the card's rounded corner
   (border-radius + overflow: hidden on .neu-table-card). */
.neu-table-card .neu-table caption {
  padding: 0.5rem 0.75rem;
}

/* Operator visit history table — 9 columns inside the ~614px main-content
   column on the narrower of the two live register tablets (rugking-pad-2-pro,
   1004x627 CSS viewport). GH#2440: table-layout:auto let column widths follow
   content (image natural size, badge text length, locale string length), so
   the table's own rendered width could exceed the panel — the container
   (overflow-x:auto) then had to scroll to show Total/Action, hiding the
   Refund button on the register hardware. table-layout:fixed makes the
   table's width authoritative: every column gets a fixed share of 100% and
   content that doesn't fit clips (overflow:hidden below) instead of growing
   the table. This is a structural guarantee, not a content-fit tuned to
   today's strings — it holds for any locale (fr's "Remboursement" included)
   and for whatever a future column's content turns out to be.

   JPB design ruling (GH#2440, supersedes an earlier plate-column-merge plan):
   the real width cost was two columns carrying noise, not signal — an
   11-value full-label State pill (~95px) and a date repeated identically down
   every row of an already-single-day-filtered table. State renders the
   EXISTING Visit#visit_state_group predicate (GH#1902) as a single letter,
   not a new taxonomy (see the JS controller), and Entry Time drops to
   time-only except on a day-boundary row. Plate and License Plate stay two
   columns — that split carries real signal (crop vs. recognized text). */
.neu-table--operator-visits {
  table-layout: fixed;
  width: 100%;
}

.neu-table--operator-visits th,
.neu-table--operator-visits td {
  /* 0.25rem horizontal (was 0.375rem): buys back the width the GH #1902 State
     column costs so Total/Action stay on-screen at the 1004px review viewport. */
  padding: 0.3125rem 0.25rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Register-tablet fit (GH #2410): at the real register viewports — RugKing Pad 2
   Pro (1004x627 CSS) and Ulefone Armor Pad 4 Ultra (1177x706 CSS) — the eight
   content-sized columns plus the Action column summed ~23px past the ~614px
   History panel on origin/main, so the table scrolled horizontally and the
   rightmost controls (Refund, and now the reprint Receipt button) were only
   reachable by scrolling. Shaving the per-cell horizontal padding from 0.25rem
   to 0.125rem reclaims ~36px across the nine columns (2px x 2 sides x 9) — more
   than enough to seat the whole row inside the panel — without shrinking any
   image tile, badge, or plate read. Scoped to landscape tablet widths so the
   roomier desktop layout keeps its original padding. */
@media (min-width: 900px) and (max-width: 1200px) and (orientation: landscape) {
  .neu-table--operator-visits th,
  .neu-table--operator-visits td {
    padding-left: 0.125rem;
    padding-right: 0.125rem;
  }

  .neu-table--operator-visits th:first-child,
  .neu-table--operator-visits td:first-child {
    padding-left: 0.375rem;
  }

  .neu-table--operator-visits th:last-child,
  .neu-table--operator-visits td:last-child {
    padding-right: 0.375rem;
  }
}

.neu-table--operator-visits th:first-child,
.neu-table--operator-visits td:first-child {
  padding-left: 0.625rem;
}

.neu-table--operator-visits th:last-child,
.neu-table--operator-visits td:last-child {
  padding-right: 0.625rem;
  text-align: right;
}

/* Fixed-width columns, in DOM order (Entry Time, State, ALPR, Plate, License
   Plate, Package, Payment, Total, Action). Percentages of the panel so both
   register viewports (1004px and 1177px, GH#2440) scale proportionally
   instead of needing separate breakpoints. State is narrow by design (single-
   char badge). Entry Time is NOT as narrow as the single-char State column —
   design review on this ruling (2026-07-29) measured the time-only string
   alone (e.g. "12:31am") already overflowing an 8% column, before even
   accounting for the rarer date-prefixed row; 17% is sized for the
   date-prefixed case (the widest content this column ever renders) so
   neither ever clips. Total similarly needs room for a 6-7 char currency
   value ("$100.00"), not just "$25.00". Package still carries real slack
   since its content (wash tier name) already wraps onto two lines
   (.op-package-name), the graceful way to absorb a long name instead of
   widening the table. */
.neu-table--operator-visits th:nth-child(1),
.neu-table--operator-visits td:nth-child(1) {
  width: 17%;
}

.neu-table--operator-visits th:nth-child(2),
.neu-table--operator-visits td:nth-child(2) {
  width: 5%;
  text-align: center;
}

.neu-table--operator-visits th:nth-child(3),
.neu-table--operator-visits td:nth-child(3) {
  width: 5%;
}

.neu-table--operator-visits th:nth-child(4),
.neu-table--operator-visits td:nth-child(4) {
  width: 9%;
}

.neu-table--operator-visits th:nth-child(5),
.neu-table--operator-visits td:nth-child(5) {
  width: 19%;
}

.neu-table--operator-visits th:nth-child(6),
.neu-table--operator-visits td:nth-child(6) {
  width: 7%;
  white-space: normal;
}

.neu-table--operator-visits th:nth-child(7),
.neu-table--operator-visits td:nth-child(7) {
  width: 16%;
}

.neu-table--operator-visits th:nth-child(8),
.neu-table--operator-visits td:nth-child(8) {
  width: 10%;
}

.neu-table--operator-visits th:nth-child(9),
.neu-table--operator-visits td:nth-child(9) {
  width: 12%;
}

/* Absolute (not percentage) caps: percentage max-width on an img inside an
   inline-block ancestor that isn't itself width-constrained resolves to
   "none" (the containing block's width is indeterminate), so it wouldn't
   actually cap anything. height:auto alongside max-height lets the browser
   shrink the image proportionally (object-fit:contain-style sizing) rather
   than the td's overflow:hidden hard-clipping it. */
.neu-table--operator-visits .op-img-clip img {
  width: auto;
  height: auto;
  max-width: 44px;
  max-height: 2rem;
}

/* Action buttons (Refund) truncate with an ellipsis rather than relying on
   the td's clip: a button is its own box, so text-overflow must be set on
   the button itself to render "…" instead of a hard cut mid-word — matters
   most for fr's "Remboursement" (GH#2440 i18n trap: longer than the column
   at any locale-agnostic width budget that also fits Entry Time/State/etc). */
.neu-table--operator-visits td:last-child button {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Entry-time column: monospace so digits align across rows. */
.neu-table--operator-visits td:first-child span {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
}

/* Date prefix on a day-boundary row (GH#2440) — smaller and muted so it reads
   as context, not the primary value; the time is still the thing an operator
   scans for on every row. Higher specificity than the mono rule above so it
   wins despite matching later in the cascade. */
.neu-table--operator-visits td:first-child .op-entry-date {
  font-size: 0.625rem;
  font-weight: 500;
  color: var(--neu-muted);
  margin-right: 0.125rem;
}

/* Region plate badge inside the history table. Sizing only — per-region
   colors come from the .plate-xx classes shared with the operator hero chip. */
.op-plate-badge {
  /* Padding/symmetry comes from the base .neu-plate-badge (0.25rem 0.5rem). */
  border: 1px solid var(--neu-shadow-dark);
  max-width: 100%;
}

.op-plate-badge .plate-number {
  font-family: var(--font-mono);
  font-weight: 900;
  font-size: 0.8125rem;
  letter-spacing: 0.05em;
}

.op-plate-badge .plate-divider {
  opacity: 0.5;
  font-weight: 400;
  margin: 0 1px;
}

.op-plate-badge .plate-state-name {
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* Payment badge — compact, single line. */
.op-pay-badge {
  padding: 0.2rem 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Single-letter badge for Visit#visit_state_group ("C" confirmed / "P"
   proposed, GH#2440 corrected 2026-07-29). Both are bold, full-height,
   vividly-colored letters (success/warning) — no contrast-boost modifier
   needed the way an earlier dot-glyph design required. */
.op-state-badge {
  padding: 0.2rem 0.3rem;
  font-size: 0.6875rem;
  font-weight: 700;
  white-space: nowrap;
  text-transform: none;
  letter-spacing: normal;
  min-width: 1.25rem;
  justify-content: center;
  border: 1px solid var(--neu-shadow-dark);
}

/* Package name — same family/weight as the rest of the table, ellipsis on
   line so a long name wraps onto multiple lines inside the flex column. */
.op-package-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.6875rem;
  line-height: 1.25;
  font-weight: 500;
}

.neu-table tbody tr {
  transition: background-color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-table tbody tr:hover {
  background-color: var(--neu-hover-tint-faint);
}

/* Table Sort Link */
.neu-sort-link {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  color: var(--neu-muted);
  transition: color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-sort-link:hover {
  color: var(--neu-accent);
}

/* ===== ACTION BUTTON GROUP ===== */
.neu-action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-action-btn:hover {
  color: var(--neu-accent);
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-action-btn:active {
  transform: translateY(0);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
}

/* ===== EMPTY STATE ===== */
.neu-empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
}

.neu-empty-state-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5rem;
  height: 5rem;
  margin: 0 auto 1.5rem;
  border-radius: 1.25rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light);
  color: var(--neu-muted);
}

.neu-empty-state-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--neu-text);
  margin-bottom: 0.5rem;
}

.neu-empty-state-desc {
  font-size: 0.875rem;
  color: var(--neu-muted);
}

/* ===== IMAGE PLACEHOLDERS ===== */
.neu-image-placeholder {
  aspect-ratio: 16/9;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.75rem;
  background: var(--neu-bg);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark), inset -2px -2px 4px var(--neu-shadow-light);
  color: var(--neu-muted);
}

.neu-image-frame {
  aspect-ratio: 16/9;
  width: 100%;
  border-radius: 0.75rem;
  overflow: hidden;
  box-shadow: inset 2px 2px 4px rgba(163, 177, 198, 0.6), inset -2px -2px 4px rgba(255, 255, 255, 0.8);
  cursor: pointer;
}

.neu-image-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.neu-image-frame--contain img {
  object-fit: contain;
}

.neu-table-empty {
  text-align: center;
  color: var(--neu-muted);
  padding: 2rem;
}

/* ===== PAGINATION ===== */
.neu-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  padding: 1rem;
}

.neu-pagination-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 2.25rem;
  height: 2.25rem;
  padding: 0 0.5rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-pagination-btn:hover {
  color: var(--neu-accent);
}

.neu-pagination-btn.active {
  background-color: var(--neu-accent);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light),
    0 4px 12px rgba(240, 136, 15, 0.3);
}

.neu-pagination-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.neu-pagination-gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.5rem;
  color: var(--neu-muted);
  font-size: 0.875rem;
}

/* ===== FORM LABEL ===== */
.neu-label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-text);
  margin-bottom: 0.375rem;
}

label.neu-label,
span.neu-label {
  display: block;
}

/* .neu-caption otherwise only exists scoped under .neu-dashboard-bg (below) --
   the signature pad renders on two motorist pages that never carry that
   class, where it was falling through to unstyled browser default text. */
[data-signature-pad-target="panel"] .neu-caption {
  font-size: var(--fluid-xs);
  line-height: 1.4;
  font-weight: 400;
  color: var(--neu-muted);
}

/* ===== FORM GROUP ===== */
.neu-form-group {
  margin-bottom: 1rem;
}

/* ===== LINK STYLES ===== */
.neu-link {
  color: var(--neu-accent);
  transition: color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-link:hover {
  color: var(--neu-accent-light);
}

/* ===== CARD HEADER (shared across neu-card, neu-detail-card, neu-table-card) ===== */
.neu-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 0.75rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.neu-card-title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
  margin: 0;
}

/* Table card header — uses same pattern but with internal padding */
.neu-table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--neu-border-subtle);
}

/* ===== DETAIL/SHOW PAGE STYLES ===== */
.neu-detail-card {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.5rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
}

.neu-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.neu-detail-title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
}

.neu-detail-row {
  display: flex;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.neu-detail-row:last-child {
  border-bottom: none;
}

.neu-detail-label {
  flex-shrink: 0;
  width: 10rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
}

.neu-detail-value {
  flex: 1;
  min-width: 0;
  overflow-wrap: break-word;
  word-break: break-word;
  font-size: 0.875rem;
  color: var(--neu-text);
}

/* ===== TABS ===== */
.neu-tabs {
  display: flex;
  gap: 0.25rem;
  padding: 0.25rem;
  background-color: var(--neu-bg);
  border-radius: 0.75rem;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-tab {
  padding: 0.625rem 1.25rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-tab:hover {
  color: var(--neu-text);
}

.neu-tab.active {
  background-color: var(--neu-bg);
  color: var(--neu-accent);
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

/* ===== STAT CARD (for index pages) ===== */
.neu-stat-card {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.25rem 1.5rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
}

.neu-stat-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
}

.neu-stat-value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--neu-text);
  margin-top: 0.5rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.neu-stat-icon {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-stat-desc {
  font-size: 0.8125rem;
  color: var(--neu-muted);
  margin-top: 0.5rem;
}

/* ===== VEHICLE/LICENSE PLATE BADGE ===== */
.neu-plate-badge {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  gap: 0.375rem;
  padding: 0.25rem 0.5rem;
  border-radius: 0.375rem;
  font-size: 0.75rem;
  font-weight: 600;
  font-family: var(--font-mono);
  background-color: var(--neu-bg);
  color: var(--neu-text);
  box-shadow: 2px 2px 4px var(--neu-shadow-dark),
    -2px -2px 4px var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-plate-badge:hover {
  color: var(--neu-accent);
  transform: translateY(-1px);
}

/* ===== US LICENSE PLATE STATE COLOR THEMES =====
   Source: Wikipedia "United States license plate designs" table (2024/2025)
   Co-located here so any layout loading neumorphism.css gets plate colors automatically —
   avoids per-layout stylesheet_link_tag drift (the bug that caused owner dashboard to show
   unstyled grey badges despite correct .plate-xx classes being present in the DOM).

   Pattern (operator dashboard):
     Hero chip:        <button class="plate-xx"><span class="plate-number">...</span><span class="plate-state-name">XX</span></button>
     Filmstrip/owner badge: <span class="neu-plate-badge plate-xx">...</span>

   WCAG AA (4.5:1) verified for .plate-number against effective background at text position.
*/

/* Generic fallback — white with dark border */
.plate-generic {
  background: #ffffff;
  border-color: #666;
  color: #1a1a1a;
}

.plate-generic .plate-state-name {
  color: #666;
}

.plate-generic .plate-number {
  color: #1a1a1a;
}

/* Alabama — bay and sky travel graphic */
.plate-al {
  background: linear-gradient(to bottom, #8fc7e8 0%, #d8edf7 48%, #f7f2dc 49%, #d8b46a 100%);
  border-color: #2b6f96;
  color: #173f5f;
}

.plate-al .plate-state-name {
  color: #1d4f73;
}

.plate-al .plate-number {
  color: #173f5f;
}

/* Alaska — blue on gold, state flag cue */
.plate-ak {
  background: linear-gradient(135deg, #f5d45b, #d9a928);
  border-color: #123a6f;
  color: #123a6f;
}

.plate-ak .plate-state-name {
  color: #123a6f;
}

.plate-ak .plate-number {
  color: #123a6f;
}

/* Arizona — dark green on desert landscape */
.plate-az {
  background: linear-gradient(to bottom, #7ec0d6 0%, #f5c06d 42%, #d88442 72%, #9b5a30 100%);
  border-color: #2d5e46;
  color: #1e4c38;
}

.plate-az .plate-state-name {
  color: #2d5e46;
}

.plate-az .plate-number {
  color: #1e4c38;
}

/* Arkansas — black on white/cream with diamond cue */
.plate-ar {
  background: #f8f8f2;
  border-color: #444;
  color: #111;
}

.plate-ar .plate-state-name {
  color: #333;
}

.plate-ar .plate-number {
  color: #111;
}

/* California — dark blue on white, red state name */
.plate-ca {
  background: #ffffff;
  border-color: #24436f;
  color: #1a3a6b;
}

.plate-ca .plate-state-name {
  color: #c92323;
}

.plate-ca .plate-number {
  color: #1a3a6b;
}

/* Colorado — dark green on Rocky Mountains scene */
.plate-co {
  background: linear-gradient(to bottom, #dfe9e4 0%, #ffffff 46%, #c8d8ce 100%);
  border-color: #1f5b42;
  color: #1f5b42;
}

.plate-co .plate-state-name {
  color: #1f5b42;
}

.plate-co .plate-number {
  color: #1f5b42;
}

/* Connecticut — dark blue text on light blue fading to white */
.plate-ct {
  background: linear-gradient(to bottom, #5a9fd4, #ffffff);
  border-color: #1e3a5f;
  color: #1e3a5f;
}

.plate-ct .plate-state-name {
  color: #1e3a5f;
}

.plate-ct .plate-number {
  color: #1e3a5f;
}

/* Delaware — gold on navy blue */
.plate-de {
  background: #071c3a;
  border-color: #d7b548;
  color: #f2d36b;
}

.plate-de .plate-state-name {
  color: #d7b548;
}

.plate-de .plate-number {
  color: #f2d36b;
}

/* District of Columbia — blue on white */
.plate-dc {
  background: #ffffff;
  border-color: #24436f;
  color: #24436f;
}

.plate-dc .plate-state-name {
  color: #24436f;
}

.plate-dc .plate-number {
  color: #24436f;
}

/* Florida — green on white with orange cue */
.plate-fl {
  background: #ffffff;
  border-color: #2f7d46;
  color: #24703b;
}

.plate-fl .plate-state-name {
  color: #2f7d46;
}

.plate-fl .plate-number {
  color: #24703b;
}

/* Georgia — blue sky top, peach center, green bottom */
.plate-ga {
  background: linear-gradient(to bottom, #3a72a8 0%, #f0c09a 35%, #f0c09a 65%, #2d7a4f 100%);
  border-color: #1e3a6b;
  color: #1a1a1a;
}

.plate-ga .plate-state-name {
  color: #1a3a6b;
}

.plate-ga .plate-number {
  color: #1a1a1a;
}

/* Hawaii — sky blue top, white text zone, rainbow decorative band at bottom */
.plate-hi {
  background: linear-gradient(to bottom,
      #4a90d9 0%, #74b3e8 12%,
      #ffffff 22%, #ffffff 72%,
      #e84040 75%, #f09020 80%,
      #f0e020 84%, #38b038 88%,
      #3880d0 92%, #7038c0 95%,
      #f8f8ff 97%, #ffffff 100%);
  border-color: #333;
  color: #111;
}

.plate-hi .plate-state-name {
  color: #111;
}

.plate-hi .plate-number {
  color: #111;
}

/* Idaho — black on white with red gradient and blue mountains
   WCAG: state-name adjusted #ffffff → #111 (white on red top band fails 4.5:1) */
.plate-id {
  background: linear-gradient(to bottom, #b9232d 0%, #ffffff 34%, #ffffff 72%, #1d4b7a 100%);
  border-color: #1d4b7a;
  color: #111;
}

.plate-id .plate-state-name {
  color: #111;
}

.plate-id .plate-number {
  color: #111;
}

/* Illinois — gradient blue-to-white with skyline cue */
.plate-il {
  background: linear-gradient(to bottom, #4c83bd 0%, #eef5fb 55%, #ffffff 100%);
  border-color: #315f91;
  color: #111;
}

.plate-il .plate-state-name {
  color: #111;
}

.plate-il .plate-number {
  color: #111;
}

/* Indiana — dark blue on country scene */
.plate-in {
  background: linear-gradient(to bottom, #b9d9ef 0%, #f1f7fb 45%, #d9b884 100%);
  border-color: #1e3a5f;
  color: #15365d;
}

.plate-in .plate-state-name {
  color: #1e3a5f;
}

.plate-in .plate-number {
  color: #15365d;
}

/* Iowa — black on sky/skyline/farm/field graphic
   WCAG: state-name adjusted #ffffff → #0f3452 (white on #4f9ed8 blue = 2.76:1, fails) */
.plate-ia {
  background: linear-gradient(to bottom, #4f9ed8 0%, #d8edf9 45%, #ffffff 58%, #5aa05a 100%);
  border-color: #2a6f9f;
  color: #111;
}

.plate-ia .plate-state-name {
  color: #0f3452;
}

.plate-ia .plate-number {
  color: #111;
}

/* Kansas — black on light blue/white/gold gradient */
.plate-ks {
  background: linear-gradient(to bottom, #b7dcef 0%, #ffffff 56%, #e8c36a 100%);
  border-color: #666;
  color: #111;
}

.plate-ks .plate-state-name {
  color: #111;
}

.plate-ks .plate-number {
  color: #111;
}

/* Kentucky — dark blue on light blue gradient */
.plate-ky {
  background: linear-gradient(to bottom, #d9eefb, #9ec9e7);
  border-color: #1c4775;
  color: #123d6b;
}

.plate-ky .plate-state-name {
  color: #1c4775;
}

.plate-ky .plate-number {
  color: #123d6b;
}

/* Louisiana — blue on white */
.plate-la {
  background: #ffffff;
  border-color: #1e5a9b;
  color: #174c88;
}

.plate-la .plate-state-name {
  color: #1e5a9b;
}

.plate-la .plate-number {
  color: #174c88;
}

/* Maine — blue on white with pine tree cue */
.plate-me {
  background: #ffffff;
  border-color: #24436f;
  color: #24436f;
}

.plate-me .plate-state-name {
  color: #24436f;
}

.plate-me .plate-number {
  color: #24436f;
}

/* Maryland — white top fading to gold bottom (flag cue) */
.plate-md {
  background: linear-gradient(to bottom, #ffffff 0%, #ffffff 55%, #f5c518 100%);
  border-color: #111;
  color: #111;
}

.plate-md .plate-state-name {
  color: #111;
}

.plate-md .plate-number {
  color: #111;
}

/* Massachusetts — red serial on white; blue state name/slogan */
.plate-ma {
  background: #ffffff;
  border-color: #24436f;
  color: #b21f2d;
}

.plate-ma .plate-state-name {
  color: #24436f;
}

.plate-ma .plate-number {
  color: #b21f2d;
}

/* Michigan — white with royal blue bottom band */
.plate-mi {
  background: linear-gradient(to bottom, #ffffff 0%, #ffffff 62%, #1a4fa8 62%, #1a4fa8 100%);
  border-color: #1a4fa8;
  color: #1a4fa8;
}

.plate-mi .plate-state-name {
  color: #1a4fa8;
}

.plate-mi .plate-number {
  color: #1a4fa8;
}

/* Minnesota — black on white with lake scene */
.plate-mn {
  background: linear-gradient(to bottom, #dff1fb 0%, #ffffff 52%, #b9d7b6 100%);
  border-color: #24436f;
  color: #111;
}

.plate-mn .plate-state-name {
  color: #24436f;
}

.plate-mn .plate-number {
  color: #111;
}

/* Mississippi — dark blue on white with magnolia cue */
.plate-ms {
  background: #ffffff;
  border-color: #183b6b;
  color: #183b6b;
}

.plate-ms .plate-state-name {
  color: #183b6b;
}

.plate-ms .plate-number {
  color: #183b6b;
}

/* Missouri — dark blue on white with red and blue wave accents */
.plate-mo {
  background: #ffffff;
  border-color: #183b6b;
  color: #183b6b;
}

.plate-mo .plate-state-name {
  color: #183b6b;
}

.plate-mo .plate-number {
  color: #183b6b;
}

/* Montana — white on blue with state outline */
.plate-mt {
  background: #1f5e9d;
  border-color: #ffffff;
  color: #ffffff;
}

.plate-mt .plate-state-name {
  color: #ffffff;
}

.plate-mt .plate-number {
  color: #ffffff;
}

/* Nebraska — dark blue on white with mosaic cue */
.plate-ne {
  background: #ffffff;
  border-color: #1d3f71;
  color: #1d3f71;
}

.plate-ne .plate-state-name {
  color: #1d3f71;
}

.plate-ne .plate-number {
  color: #1d3f71;
}

/* Nevada — black on sky blue with mountain range */
.plate-nv {
  background: linear-gradient(to bottom, #9ed2f0 0%, #dff4ff 62%, #c2b28a 100%);
  border-color: #333;
  color: #111;
}

.plate-nv .plate-state-name {
  color: #111;
}

.plate-nv .plate-number {
  color: #111;
}

/* New Hampshire — green on Old Man mountain graphic */
.plate-nh {
  background: linear-gradient(to bottom, #c9d7cb 0%, #e7eee8 55%, #9caf9d 100%);
  border-color: #1f5b42;
  color: #1f5b42;
}

.plate-nh .plate-state-name {
  color: #1f5b42;
}

.plate-nh .plate-number {
  color: #1f5b42;
}

/* New Jersey — black on yellow/buff gradient */
.plate-nj {
  background: linear-gradient(135deg, #f5e6a3, #e8d47a);
  border-color: #8b7d3c;
  color: #1a1a2e;
}

.plate-nj .plate-state-name {
  color: #2a4a2a;
}

.plate-nj .plate-number {
  color: #1a1a2e;
}

/* New Mexico — red on yellow with turquoise/Zia cue
   WCAG: color darkened #b42126 → #8b1a20 (red on #f4d34f yellow was 4.35:1, now ~5.5:1) */
.plate-nm {
  background: #f4d34f;
  border-color: #8b1a20;
  color: #8b1a20;
}

.plate-nm .plate-state-name {
  color: #8b1a20;
}

.plate-nm .plate-number {
  color: #8b1a20;
}

/* New York — blue top band, gold bottom; state name dark so it reads on gold */
.plate-ny {
  background: linear-gradient(to bottom, #1a3a6b 30%, #f0c040 30%);
  border-color: #1a3a6b;
  color: #1a3a6b;
}

.plate-ny .plate-state-name {
  color: #1a3a6b;
}

.plate-ny .plate-number {
  color: #1a3a6b;
}

/* North Carolina — blue on white */
.plate-nc {
  background: #ffffff;
  border-color: #1e5a9b;
  color: #1e5a9b;
}

.plate-nc .plate-state-name {
  color: #1e5a9b;
}

.plate-nc .plate-number {
  color: #1e5a9b;
}

/* North Dakota — black on light blue sunrise/prairie/buffalo */
.plate-nd {
  background: linear-gradient(to bottom, #b9e1f5 0%, #f6d38d 48%, #d6b36b 100%);
  border-color: #333;
  color: #111;
}

.plate-nd .plate-state-name {
  color: #111;
}

.plate-nd .plate-number {
  color: #111;
}

/* Ohio — dark blue on sunrise scene */
.plate-oh {
  background: linear-gradient(to bottom, #f9d56a 0%, #b7dcef 45%, #ffffff 68%, #d8c48a 100%);
  border-color: #1d4778;
  color: #1d4778;
}

.plate-oh .plate-state-name {
  color: #1d4778;
}

.plate-oh .plate-number {
  color: #1d4778;
}

/* Oklahoma — white serial on reflective red */
.plate-ok {
  background: #b9202a;
  border-color: #7f1118;
  color: #ffffff;
}

.plate-ok .plate-state-name {
  color: #ffffff;
}

.plate-ok .plate-number {
  color: #ffffff;
}

/* Oregon — dark blue on Douglas Fir and mountain graphic */
.plate-or {
  background: linear-gradient(to bottom, #d4e3ed 0%, #ffffff 52%, #a8c0a0 100%);
  border-color: #1e3f69;
  color: #1e3f69;
}

.plate-or .plate-state-name {
  color: #1e3f69;
}

.plate-or .plate-number {
  color: #1e3f69;
}

/* Pennsylvania — tricolor blue/white/yellow */
.plate-pa {
  background: linear-gradient(to bottom, #1a3a6b 25%, #ffffff 25%, #ffffff 75%, #f0c040 75%);
  border-color: #1a3a6b;
  color: #1a3a6b;
}

.plate-pa .plate-state-name {
  color: #1a3a6b;
}

.plate-pa .plate-number {
  color: #1a3a6b;
}

/* Rhode Island — navy on light blue with wave graphic */
.plate-ri {
  background: #d9eefb;
  border-color: #153c6b;
  color: #153c6b;
}

.plate-ri .plate-state-name {
  color: #153c6b;
}

.plate-ri .plate-number {
  color: #153c6b;
}

/* South Carolina — black on white and blue with palmetto cue */
.plate-sc {
  background: linear-gradient(to bottom, #ffffff 0%, #ffffff 60%, #8fb9d8 100%);
  border-color: #111;
  color: #111;
}

.plate-sc .plate-state-name {
  color: #111;
}

.plate-sc .plate-number {
  color: #111;
}

/* South Dakota — blue on Mount Rushmore graphic */
.plate-sd {
  background: linear-gradient(to bottom, #8fc4e8 0%, #dcecf5 48%, #c8c0ad 100%);
  border-color: #174c88;
  color: #174c88;
}

.plate-sd .plate-state-name {
  color: #174c88;
}

.plate-sd .plate-number {
  color: #174c88;
}

/* Tennessee — white on blue */
.plate-tn {
  background: #234f8a;
  border-color: #15345f;
  color: #ffffff;
}

.plate-tn .plate-state-name {
  color: #ffffff;
}

.plate-tn .plate-number {
  color: #ffffff;
}

/* Texas — black on white with lone star cue */
.plate-tx {
  background: #ffffff;
  border-color: #111;
  color: #111;
}

.plate-tx .plate-state-name {
  color: #111;
}

.plate-tx .plate-number {
  color: #111;
}

/* Utah — dark blue on skier/Delicate Arch landscape */
.plate-ut {
  background: linear-gradient(to bottom, #e7f2f8 0%, #ffffff 45%, #c27d48 100%);
  border-color: #1b477a;
  color: #1b477a;
}

.plate-ut .plate-state-name {
  color: #1b477a;
}

.plate-ut .plate-number {
  color: #1b477a;
}

/* Vermont — white on green */
.plate-vt {
  background: #194f35;
  border-color: #ffffff;
  color: #ffffff;
}

.plate-vt .plate-state-name {
  color: #ffffff;
}

.plate-vt .plate-number {
  color: #ffffff;
}

/* Virginia — blue on white */
.plate-va {
  background: #ffffff;
  border-color: #174c88;
  color: #174c88;
}

.plate-va .plate-state-name {
  color: #174c88;
}

.plate-va .plate-number {
  color: #174c88;
}

/* Washington — dark blue on white with Mount Rainier light blue cue */
.plate-wa {
  background: linear-gradient(to bottom, #ffffff 0%, #ffffff 54%, #cde6f4 100%);
  border-color: #1e3f69;
  color: #1e3f69;
}

.plate-wa .plate-state-name {
  color: #1e3f69;
}

.plate-wa .plate-number {
  color: #1e3f69;
}

/* West Virginia — blue on white with dark blue state name bar
   WCAG: state-name adjusted #ffffff → #1a3a6b (white-on-white invisible) */
.plate-wv {
  background: linear-gradient(to bottom, #1a3a6b 0 24%, #ffffff 24% 100%);
  border-color: #1a3a6b;
  color: #1a3a6b;
}

.plate-wv .plate-state-name {
  color: #1a3a6b;
}

.plate-wv .plate-number {
  color: #1a3a6b;
}

/* Wisconsin — black on white with lake and farm graphic */
.plate-wi {
  background: linear-gradient(to bottom, #ffffff 0%, #ffffff 62%, #c7d6b6 100%);
  border-color: #333;
  color: #111;
}

.plate-wi .plate-state-name {
  color: #111;
}

.plate-wi .plate-number {
  color: #111;
}

/* Wyoming — white on navy/gray Bucking Horse graphic with red border cue */
.plate-wy {
  background: linear-gradient(to bottom, #243a5a 0%, #5f6772 100%);
  border-color: #b21f2d;
  color: #ffffff;
}

.plate-wy .plate-state-name {
  color: #ffffff;
}

.plate-wy .plate-number {
  color: #ffffff;
}

/* ---- US Territories ---- */

/* American Samoa — black on Fatu Rock graphic */
.plate-as {
  background: linear-gradient(to bottom, #e9f2f5, #c9d8df);
  border-color: #111;
  color: #111;
}

.plate-as .plate-state-name {
  color: #111;
}

.plate-as .plate-number {
  color: #111;
}

/* Guam — black on white with latte stone and bougainvillea cue */
.plate-gu {
  background: #ffffff;
  border-color: #333;
  color: #111;
}

.plate-gu .plate-state-name {
  color: #111;
}

.plate-gu .plate-number {
  color: #111;
}

/* Northern Mariana Islands — dark blue on white with seal */
.plate-mp {
  background: #ffffff;
  border-color: #1d4778;
  color: #1d4778;
}

.plate-mp .plate-state-name {
  color: #1d4778;
}

.plate-mp .plate-number {
  color: #1d4778;
}

/* Puerto Rico — black on white with fort graphic */
.plate-pr {
  background: #ffffff;
  border-color: #333;
  color: #111;
}

.plate-pr .plate-state-name {
  color: #111;
}

.plate-pr .plate-number {
  color: #111;
}

/* Diplomatic (DP), Consul (CD), Foreign Mission (FC) — red top bar, light blue field, black serial */
.plate-dp,
.plate-cd,
.plate-fc {
  background: linear-gradient(to bottom, #cc0000 0%, #cc0000 10%, #add8e6 10%, #add8e6 100%);
  border-color: #555;
  color: #111;
}

.plate-dp .plate-state-name,
.plate-cd .plate-state-name,
.plate-fc .plate-state-name {
  color: #111;
}

.plate-dp .plate-number,
.plate-cd .plate-number,
.plate-fc .plate-number {
  color: #111;
}

/* US Government (GSA) plates — white field, blue outer border, blue inner rule with white gap */
.plate-us {
  background: #ffffff;
  border-color: #24436f;
  color: #24436f;
  box-shadow: inset 0 0 0 3px #ffffff, inset 0 0 0 5px #24436f;
}

.plate-us .plate-state-name {
  color: #24436f;
}

.plate-us .plate-number {
  color: #24436f;
}

/* U.S. Virgin Islands — teal top, white middle, orange bottom, black serial
   WCAG: state-name adjusted #ffffff → #003d40 (white on #008c95 teal = 3.74:1, fails) */
.plate-vi {
  background: linear-gradient(to bottom, #008c95 0 20%, #ffffff 20% 78%, #f28c2b 78% 100%);
  border-color: #333;
  color: #111;
}

.plate-vi .plate-state-name {
  color: #003d40;
}

.plate-vi .plate-number {
  color: #111;
}

/* No plate detected — inverse of plate-generic (dark field, white text) */
.plate-noplate {
  background: #1a1a1a;
  border-color: #555;
  color: #ffffff;
}

.plate-noplate .plate-state-name {
  color: #aaaaaa;
}

.plate-noplate .plate-number {
  color: #ffffff;
}

/* ===== SEARCH BOX ===== */
.neu-search-box {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-search-input {
  background: transparent;
  border: none;
  outline: none;
  font-size: 0.875rem;
  color: var(--neu-text);
  min-width: 0;
}

.neu-search-input::placeholder {
  color: var(--neu-muted);
}

/* ===== SIZE VARIANTS ===== */
.neu-input-sm {
  padding: 0.5rem 0.75rem;
  font-size: 0.8125rem;
}

.neu-select-sm {
  padding: 0.5rem 0.75rem;
  padding-right: 2rem;
  font-size: 0.8125rem;
}

.neu-select-xs {
  padding: 0.375rem 0.5rem;
  padding-right: 1.5rem;
  font-size: 0.75rem;
  border-radius: 0.5rem;
}

/* ===== CHECKBOX ===== */
.neu-checkbox {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 0.375rem;
  background-color: var(--neu-bg);
  border: none;
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
  appearance: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  flex-shrink: 0;
  margin: 0;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-checkbox:checked {
  background-color: var(--neu-accent);
  box-shadow: 2px 2px 4px var(--neu-shadow-dark),
    -2px -2px 4px var(--neu-shadow-light);
}

.neu-checkbox:focus-visible {
  outline: none;
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-checkbox:checked::after {
  content: '✓';
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 0.8125rem;
  font-weight: bold;
  line-height: 1;
}

/* ===== TOGGLE (Checkbox input styled as toggle switch) ===== */
.neu-toggle {
  width: 2.75rem;
  height: 1.5rem;
  border-radius: 1rem;
  background-color: var(--neu-bg-recessed, #D6DBE3);
  border: none;
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
  appearance: none;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-toggle::after {
  content: '';
  position: absolute;
  top: 0.1875rem;
  left: 0.1875rem;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  background-color: #FFFFFF;
  box-shadow: 1px 1px 3px var(--neu-shadow-dark);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-toggle:checked {
  background-color: var(--neu-accent, #F0880F);
  box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.2);
}

.neu-toggle:checked::after {
  left: calc(100% - 1.3125rem);
  background-color: #FFFFFF;
}

.neu-toggle:focus-visible {
  outline: none;
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light),
    0 0 0 3px var(--neu-focus-ring);
}

/* ===== MAINTENANCE TASK ROW (checklist item: checkbox + text + completion meta) ===== */
.neu-task-row {
  padding: calc(var(--fluid-unit) * 0.5) 0;
}

.neu-task-row+.neu-task-row {
  border-top: 1px solid var(--neu-border-subtle);
}

.neu-task-label {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--fluid-unit) * 0.75);
  cursor: pointer;
}

.neu-task-checkbox {
  flex-shrink: 0;
  margin-top: 0.2em;
}

.neu-task-text {
  flex: 1;
  min-width: 0;
}

.neu-task-meta {
  display: block;
  margin-top: calc(var(--fluid-unit) * 0.2);
  margin-left: calc(var(--fluid-unit) * 1.875);
}

/* ===== BUTTON VARIANTS ===== */
.neu-btn-ghost {
  background: transparent;
  box-shadow: none;
  color: var(--neu-muted);
}

.neu-btn-ghost:hover {
  background-color: var(--neu-hover-tint);
  color: var(--neu-accent);
  box-shadow: none;
  transform: none;
}

.neu-btn-outline {
  background: transparent;
  border: 1px solid var(--neu-border-subtle);
  box-shadow: none;
  color: var(--neu-text);
}

.neu-btn-outline:hover {
  border-color: var(--neu-accent);
  color: var(--neu-accent);
  box-shadow: none;
  transform: none;
}

/* Colored neumorphic variants */
.neu-btn-warning {
  background: linear-gradient(145deg, #f59e0b, #d97706);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-btn-warning:hover {
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light);
}

.neu-btn-warning:focus-visible {
  outline: none;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 0 0 3px rgba(245, 158, 11, 0.3);
}

.neu-btn-warning:active {
  transform: translateY(1px);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-btn-info {
  background: linear-gradient(145deg, #3b82f6, #2563eb);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

/* Informational, non-actionable state (e.g. "Uses Google Login"): keep the
   full blue treatment but signal it cannot be pressed. */
.neu-btn-info:disabled,
.neu-btn-info[disabled] {
  opacity: 1;
  transform: none;
  cursor: not-allowed;
}

.neu-btn-error {
  background: linear-gradient(145deg, #ef4444, #dc2626);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-btn-error:hover {
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light);
}

.neu-btn-error:focus-visible {
  outline: none;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 0 0 3px rgba(239, 68, 68, 0.3);
}

.neu-btn-error:active {
  transform: translateY(1px);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-btn-error-subtle {
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.15), rgba(239, 68, 68, 0.05));
  color: #EF4444;
}

.neu-btn-error-subtle:hover {
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.25), rgba(239, 68, 68, 0.1));
}

/* Inset display (for amount field) */
.neu-inset {
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  background-color: var(--neu-bg);
}

/* ===== MODAL ===== */
/* For native <dialog> elements, respect the open state */
dialog.neu-modal {
  display: none;
  border: none;
  padding: 0;
  max-width: none;
  max-height: none;
}

dialog.neu-modal[open] {
  display: flex;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(4px);
  z-index: 9999;
}

/* For non-dialog modals (legacy support) */
.neu-modal:not(dialog) {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(4px);
  z-index: 9999;
}

.neu-modal-box {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.5rem;
  box-shadow: 15px 15px 30px var(--neu-shadow-dark-strong),
    -15px -15px 30px var(--neu-shadow-light-strong);
  position: relative;
  max-height: 90vh;
  overflow-y: auto;
}

.neu-modal-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-modal-close:hover {
  color: var(--neu-text);
}

/* QR code container — flex item that fills remaining modal height.
   The modal-box is height: 90vh with display: flex flex-direction: column.
   Header and footer are flex-shrink: 0; this div takes the rest via flex: 1.
   SVG is sized by its height so the square viewBox preserves the QR aspect ratio. */
.qr-code-responsive {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.qr-code-responsive svg {
  height: 100%;
  width: auto;
  max-width: 100%;
  display: block;
}

/* ===== FORM CONTROL ===== */
.neu-form-control {
  display: flex;
  flex-direction: column;
}

.neu-label-text {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-text);
  margin-bottom: 0.375rem;
}

.neu-label-text-alt {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--neu-muted);
  margin-bottom: 0.375rem;
}

/* ===== PAGINATION ACTIVE/DISABLED STATES ===== */
/* Outrank .neu-pagination-btn:hover — otherwise the hovered active chip paints
   accent-on-accent and its label disappears (bitten by the GH #1902 chips). */
.neu-pagination-btn.neu-pagination-active,
.neu-pagination-btn.neu-pagination-active:hover {
  color: white;
}

.neu-pagination-active {
  background-color: var(--neu-accent);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light),
    0 4px 12px rgba(240, 136, 15, 0.3);
}

.neu-pagination-disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* ===== BREADCRUMB LINKS ===== */
.neu-breadcrumb-link {
  color: var(--neu-muted);
  font-size: 0.875rem;
  transition: color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-breadcrumb-link:hover {
  color: var(--neu-accent);
}

.neu-breadcrumb-separator {
  color: rgba(163, 177, 198, 0.5);
  margin: 0 0.25rem;
}

.neu-breadcrumb-current {
  color: var(--neu-text);
  font-weight: 500;
  font-size: 0.875rem;
}

/* ===== EMPTY STATE ELEMENTS ===== */
.neu-empty-title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--neu-text);
  margin-top: 1rem;
}

.neu-empty-desc {
  font-size: 0.875rem;
  color: var(--neu-muted);
  margin-top: 0.5rem;
}

/* ===== FILTER TOOLBAR ===== */
.neu-filter-toolbar {
  background-color: var(--neu-bg);
  border-radius: 1rem;
  padding: 1rem;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

/* ===== ALERT STYLES ===== */
.neu-alert {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 1rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  font-size: 0.875rem;
  color: var(--neu-text);
}

.neu-alert-info {
  background-color: rgba(59, 130, 246, 0.1);
  color: #2563EB;
}

.neu-alert-warning {
  background-color: rgba(245, 158, 11, 0.1);
  color: #D97706;
}

.neu-alert-success {
  background-color: rgba(16, 185, 129, 0.1);
  color: #059669;
}

.neu-alert-error {
  background-color: rgba(239, 68, 68, 0.1);
  color: #DC2626;
}

[data-theme="dark"] .neu-alert-info {
  background-color: rgba(59, 130, 246, 0.15);
  color: var(--neu-info);
}

[data-theme="dark"] .neu-alert-warning {
  background-color: rgba(245, 158, 11, 0.15);
  color: var(--neu-warning);
}

[data-theme="dark"] .neu-alert-success {
  background-color: rgba(16, 185, 129, 0.15);
  color: var(--neu-success);
}

[data-theme="dark"] .neu-alert-error {
  background-color: rgba(239, 68, 68, 0.15);
  color: var(--neu-error);
}

/* ============================================================
   DaisyUI semantic-utility remap (owner dashboard scope)
   ------------------------------------------------------------
   DaisyUI's .text-primary etc. resolve to its stock palette
   (a blue #167BFF, a pink-red error, …) which clashes with the
   Tux Orange brand and the neumorphic token system. Within the
   owner dashboard (only) we redirect the semantic utilities to the
   theme-aware --neu-* tokens so any lingering DaisyUI color
   class — present or future — renders on-brand in both themes.
   Scoped to .owner-dashboard so operator/motorist/landing
   surfaces keep DaisyUI's own palette. --neu-text is left alone
   (base-content is already theme-aware).
   ============================================================ */
.owner-dashboard .text-primary {
  color: var(--neu-accent) !important;
}

.owner-dashboard .text-success {
  color: var(--neu-success) !important;
}

.owner-dashboard .text-error {
  color: var(--neu-error) !important;
}

.owner-dashboard .text-warning {
  color: var(--neu-warning) !important;
}

.owner-dashboard .text-info {
  color: var(--neu-info) !important;
}

.owner-dashboard .bg-primary {
  background-color: var(--neu-accent) !important;
}

.owner-dashboard .bg-success {
  background-color: var(--neu-success) !important;
}

.owner-dashboard .bg-error {
  background-color: var(--neu-error) !important;
}

.owner-dashboard .bg-warning {
  background-color: var(--neu-warning) !important;
}

.owner-dashboard .bg-info {
  background-color: var(--neu-info) !important;
}

.owner-dashboard .border-primary {
  border-color: var(--neu-accent) !important;
}

.owner-dashboard .ring-primary {
  --tw-ring-color: var(--neu-accent) !important;
}

.owner-dashboard .ring-success {
  --tw-ring-color: var(--neu-success) !important;
}

/* ------------------------------------------------------------
   DaisyUI .stats/.stat remap (owner dashboard scope)
   DaisyUI's stat component is an inline-grid with internal
   dividers and its own shadow — it fights the neu card system
   and reads as "crammed tiles". Redirect it to the neu-stat-card
   look: each stat becomes its own soft card in a wrapping flex
   row, matching .neu-stat-card / -label / -value / -desc exactly.
   ------------------------------------------------------------ */
.owner-dashboard .stats {
  display: flex !important;
  flex-wrap: wrap;
  gap: 1rem;
  background-color: transparent !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

.owner-dashboard .stat {
  display: block !important;
  flex: 1 1 12rem;
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.25rem 1.5rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  border: none !important;
}

.owner-dashboard .stat-title {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--neu-muted);
}

.owner-dashboard .stat-value {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--neu-text);
  margin-top: 0.5rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.owner-dashboard .stat-desc {
  font-size: 0.8125rem;
  color: var(--neu-muted);
  margin-top: 0.5rem;
}

.owner-dashboard .stat-figure {
  color: var(--neu-muted);
}

/* ===== RADIO BUTTONS ===== */
.neu-radio {
  appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background-color: var(--neu-bg);
  border: none;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
  position: relative;
}

.neu-radio:checked {
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-radio:checked::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
}

.neu-radio:focus {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light),
    0 0 0 3px var(--neu-focus-ring);
}

/* ===== NAVIGATION ARROWS ===== */
.neu-nav-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-nav-arrow:hover {
  color: var(--neu-accent);
  transform: translateY(-1px);
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-nav-arrow:active {
  transform: translateY(0);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-nav-arrow:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.neu-nav-arrow-sm {
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
}

/* ===== CALENDAR/DATE PICKER ===== */
.neu-calendar {
  background-color: var(--neu-bg);
  border-radius: 1.5rem;
  padding: 1.25rem;
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
}

.neu-calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.neu-calendar-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--neu-text);
}

.neu-calendar-nav {
  display: flex;
  gap: 0.5rem;
}

.neu-calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.25rem;
}

.neu-calendar-weekday {
  padding: 0.5rem;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--neu-muted);
  text-transform: lowercase;
}

.neu-calendar-day {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.5rem;
  font-size: 0.8125rem;
  color: var(--neu-text);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-calendar-day:hover {
  background-color: var(--neu-hover-tint);
  color: var(--neu-accent);
}

.neu-calendar-day.active {
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  color: white;
  box-shadow: 2px 2px 4px var(--neu-shadow-dark),
    -2px -2px 4px var(--neu-shadow-light);
}

.neu-calendar-day.today {
  font-weight: 700;
  color: var(--neu-accent);
}

.neu-calendar-day.other-month {
  color: var(--neu-muted);
  opacity: 0.5;
}

/* ===== VERTICAL SLIDER BARS ===== */
.neu-slider-vertical {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.neu-slider-track-vertical {
  width: 0.75rem;
  height: 150px;
  border-radius: 0.5rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  position: relative;
  overflow: hidden;
}

.neu-slider-fill-vertical {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  border-radius: 0.5rem;
  background: linear-gradient(180deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  transition: height 300ms ease-out;
}

.neu-slider-label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--neu-muted);
}

/* Horizontal slider */
.neu-slider {
  width: 100%;
  height: 0.5rem;
  border-radius: 0.25rem;
  background-color: var(--neu-bg);
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
  appearance: none;
  cursor: pointer;
}

.neu-slider::-webkit-slider-thumb {
  appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  cursor: pointer;
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-slider::-webkit-slider-thumb:hover {
  transform: scale(1.1);
}

.neu-slider::-moz-range-thumb {
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  border: none;
  cursor: pointer;
}

/* ===== DROPDOWN MENU ===== */
.neu-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 12rem;
  background-color: var(--neu-bg);
  border-radius: 1rem;
  padding: 0.5rem;
  margin-top: 0.5rem;
  box-shadow: calc(var(--shadow-offset) + 3px) calc(var(--shadow-offset) + 3px) calc(var(--shadow-blur) + 8px) var(--neu-shadow-dark-strong),
    calc(-1 * (var(--shadow-offset) + 3px)) calc(-1 * (var(--shadow-offset) + 3px)) calc(var(--shadow-blur) + 8px) var(--neu-shadow-light-strong);
  z-index: 50;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-dropdown-menu.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.neu-dropdown-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.625rem 0.875rem;
  border-radius: 0.625rem;
  font-size: 0.875rem;
  color: var(--neu-text);
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-dropdown-item:hover {
  background-color: var(--neu-hover-tint);
  color: var(--neu-accent);
}

.neu-dropdown-item.active {
  background-color: var(--neu-bg);
  color: var(--neu-accent);
  font-weight: 500;
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
}

.neu-dropdown-divider {
  height: 1px;
  background-color: var(--neu-surface-tint);
  margin: 0.5rem 0;
}

/* ===== ICON BUTTON GRID ===== */
.neu-icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(3rem, 1fr));
  gap: 0.75rem;
}

.neu-icon-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 0.875rem;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-icon-button:hover {
  color: var(--neu-accent);
  transform: translateY(-2px);
  box-shadow: calc(var(--shadow-offset) - 2px) calc(var(--shadow-offset) - 2px) calc(var(--shadow-blur) - 2px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 2px)) calc(-1 * (var(--shadow-offset) - 2px)) calc(var(--shadow-blur) - 2px) var(--neu-shadow-light);
}

.neu-icon-button:active {
  transform: translateY(0);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-icon-button.active {
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  color: white;
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light),
    0 4px 15px rgba(240, 136, 15, 0.3);
}

.neu-icon-button-sm {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.625rem;
}

.neu-icon-button-lg {
  width: 4rem;
  height: 4rem;
  border-radius: 1rem;
}

/* ===== MEDIA CONTROLS ===== */
.neu-media-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.neu-media-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-media-btn:hover {
  color: var(--neu-accent);
}

.neu-media-btn:active {
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-media-btn-play {
  width: 3.5rem;
  height: 3.5rem;
  background: linear-gradient(135deg, var(--neu-accent) 0%, var(--neu-accent-light) 100%);
  color: white;
}

.neu-media-btn-play:hover {
  color: white;
  transform: scale(1.05);
}

/* ===== TEXTAREA ===== */
.neu-textarea {
  width: 100%;
  min-height: 6rem;
  padding: 0.875rem 1rem;
  border-radius: 0.875rem;
  border: none;
  background-color: var(--neu-bg);
  color: var(--neu-text);
  font-family: inherit;
  font-size: 0.875rem;
  line-height: 1.5;
  resize: vertical;
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-textarea:focus {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 4px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 4px) var(--neu-shadow-light-strong),
    0 0 0 3px var(--neu-focus-ring);
}

.neu-textarea::placeholder {
  color: var(--neu-muted);
}

/* ===== FILE INPUT ===== */
.neu-file-input {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-radius: 0.875rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-file-input:hover {
  box-shadow: inset calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark-strong),
    inset calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light-strong);
}

.neu-file-input-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg);
  color: var(--neu-accent);
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-file-input-text {
  font-size: 0.875rem;
  color: var(--neu-muted);
}

.neu-file-input input[type="file"] {
  display: none;
}

/* ===== STEPPER/NUMBER INPUT ===== */
.neu-stepper {
  display: inline-flex;
  align-items: center;
  gap: 0;
  background-color: var(--neu-bg);
  border-radius: 0.75rem;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-stepper-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  background: transparent;
  color: var(--neu-muted);
  border: none;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-stepper-btn:first-child {
  border-radius: 0.75rem 0 0 0.75rem;
}

.neu-stepper-btn:last-child {
  border-radius: 0 0.75rem 0.75rem 0;
}

.neu-stepper-btn:hover {
  color: var(--neu-accent);
  background-color: var(--neu-hover-tint);
}

.neu-stepper-btn:active {
  box-shadow: inset 2px 2px 4px var(--neu-shadow-dark),
    inset -2px -2px 4px var(--neu-shadow-light);
}

.neu-stepper-value {
  min-width: 3rem;
  text-align: center;
  font-size: 1rem;
  font-weight: 600;
  color: var(--neu-text);
  padding: 0 0.5rem;
  border-left: 1px solid var(--neu-border-subtle);
  border-right: 1px solid var(--neu-border-subtle);
}

/* ===== TOOLTIP ===== */
.neu-tooltip {
  position: relative;
  display: inline-block;
}

.neu-tooltip-content {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-8px);
  padding: 0.5rem 0.875rem;
  border-radius: 0.625rem;
  background-color: var(--neu-text);
  color: white;
  font-size: 0.8125rem;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 100;
}

.neu-tooltip-content::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--neu-text);
}

.neu-tooltip:hover .neu-tooltip-content {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(-12px);
}

/* ===== AVATAR GROUP ===== */
.neu-avatar-group {
  display: flex;
  align-items: center;
}

.neu-avatar-group .neu-avatar {
  margin-left: -0.75rem;
  border: 3px solid var(--neu-bg);
}

.neu-avatar-group .neu-avatar:first-child {
  margin-left: 0;
}

.neu-avatar-more {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: -0.75rem;
  border: 3px solid var(--neu-bg);
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  font-size: 0.75rem;
  font-weight: 600;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

/* ===== NOTIFICATION DOT ===== */
.neu-notification-dot {
  position: absolute;
  top: -2px;
  right: -2px;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background-color: #EF4444;
  border: 2px solid var(--neu-bg);
}

.neu-notification-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 0.375rem;
  border-radius: 9999px;
  background-color: #EF4444;
  color: white;
  font-size: 0.6875rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--neu-bg);
}

/* ===== VISIT STATUS STYLES ===== */

/* Proposed visits (in_progress) - dimmed with pulsing indicator */
.proposed-visit {
  opacity: 0.6;
}

.proposed-visit:hover {
  opacity: 0.8;
}

/* Status indicators with emoji and tooltip */
.visit-status-indicator {
  cursor: help;
  font-size: 1rem;
}

.visit-status-indicator[data-status="proposed"] {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.5;
  }
}

/* ===== RESPONSIVE ADJUSTMENTS ===== */

/* --- Handset: ≤480px (iPhone 16 Pro = 393px, Galaxy Fold folded = 344px) --- */
@media (max-width: 480px) {

  /* Tighter page padding on phones */
  .container.mx-auto {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
    padding-top: 1rem;
    padding-bottom: 3rem;
  }

  /* Topbar: compact on phones */
  .neu-topbar {
    gap: 0.375rem;
    padding-left: 0.5rem;
    padding-right: 0.5rem;
    min-height: 3rem;
  }

  /* Hide environmental pills and theme toggle on phones */
  .neu-topbar .neu-inset-sm,
  .neu-topbar .swap {
    display: none;
  }

  /* Shrink search on phones */
  .neu-topbar .relative.grow.max-w-md {
    max-width: 10rem;
  }

  .neu-topbar .neu-input {
    padding: 0.5rem 0.75rem;
    font-size: 0.8125rem;
  }

  /* Sidebar on phones: must match --layout-sidebar-width (256px) so nexus's
     margin-inline-start: -256px fully hides it. Wider = visible sliver. */
  #layout-sidebar.neu-sidebar {
    width: var(--layout-sidebar-width);
    min-width: auto;
  }

  /* Sidebar backdrop opacity increased for focus */
  #layout-sidebar-toggle-trigger:checked~#layout-sidebar-backdrop {
    background-color: rgba(0, 0, 0, 0.4) !important;
  }

  /* Dashboard page header: stack vertically, reduce heading size */
  .neu-heading.text-2xl {
    font-size: 1.25rem;
  }

  /* Filter toolbar: full-width stacked layout */
  .neu-card-flat {
    padding: 0.75rem !important;
  }

  .neu-card-flat .form-control.flex-1 {
    min-width: 100%;
  }

  /* Date range: stack toggles and date inputs */
  .neu-toggle-group {
    display: flex;
    width: 100%;
  }

  .neu-toggle-group .neu-toggle-btn {
    flex: 1;
    font-size: 0.75rem;
    padding: 0.375rem 0.25rem;
  }

  .neu-date-range-container {
    flex-wrap: wrap;
    gap: 0.375rem;
    width: 100%;
  }

  .neu-date-range-container .neu-input-sm {
    width: 100% !important;
    min-width: 0;
  }

  /* KPI cards: reduce internal padding */
  .neu-kpi-card {
    padding: 0.875rem 1rem;
    border-radius: 1rem;
  }

  .neu-kpi-value {
    font-size: 1.5rem;
  }

  .neu-kpi-label {
    font-size: 0.75rem;
  }

  /* Chart cards: tighter padding */
  .neu-chart-card {
    padding: 0.75rem;
    border-radius: 1rem;
  }

  .neu-chart-card .chart-header {
    flex-direction: column;
    gap: 0.5rem;
  }

  /* Section titles */
  .neu-section-title {
    font-size: 1.125rem;
  }

  .neu-section-subtitle {
    font-size: 0.75rem;
  }

  /* Tables: tighter corners on mobile (horizontal scrolling now owned by the inner scroll wrapper) */
  .neu-table-card {
    border-radius: 0.75rem;
  }

  .neu-table th {
    padding: 0.625rem 0.75rem;
    font-size: 0.6875rem;
  }

  .neu-table td {
    padding: 0.625rem 0.75rem;
    font-size: 0.8125rem;
  }

  /* Table action buttons: compact */
  .neu-table td .neu-btn,
  .neu-table td .btn {
    min-height: 2rem;
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
  }

  /* Pagination: tighter on phones */
  .neu-pagination {
    padding: 0.75rem 0.5rem;
    gap: 0.125rem;
    flex-wrap: wrap;
  }

  /* Filter toolbar: stack vertically on phones */
  .neu-filter-toolbar {
    margin-bottom: 1rem;
  }

  /* Stat cards: tighter on phones */
  .neu-stat-card {
    padding: 0.875rem;
  }

  .neu-stat-value {
    font-size: 1.375rem;
  }

  .neu-stat-label {
    font-size: 0.6875rem;
  }

  .neu-stat-desc {
    font-size: 0.6875rem;
    margin-top: 0.25rem;
  }

  /* Page header: tighter on phones */
  .neu-page-title {
    font-size: 1.25rem;
  }

  .neu-page-subtitle {
    font-size: 0.75rem;
  }

  /* Breadcrumbs: already hidden on mobile via hidden sm:flex */

  /* Spacing between sections */
  .space-y-6>*+* {
    margin-top: 1rem;
  }

  /* Touch targets: ensure min 44px */
  .neu-btn,
  .neu-icon-btn,
  .menu-item,
  .neu-toggle-btn {
    min-height: 2.75rem;
  }

  .neu-icon-btn-sm {
    min-height: 2.5rem;
    min-width: 2.5rem;
  }

  /* Shadows: softer on small screens for clarity */
  :root {
    --shadow-offset: 4px;
    --shadow-blur: 10px;
  }
}

/* --- Galaxy Fold folded: ≤360px --- */
@media (max-width: 360px) {

  /* Extra-tight padding for narrow screens */
  .container.mx-auto {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }

  .neu-topbar {
    gap: 0.25rem;
    padding-left: 0.375rem;
    padding-right: 0.375rem;
  }

  /* Hide search on Fold folded — not enough room */
  .neu-topbar .relative.grow.max-w-md {
    display: none;
  }

  /* KPI grid: force single column */
  .grid.gap-6.sm\\:grid-cols-2 {
    grid-template-columns: 1fr !important;
  }

  /* Even tighter card padding */
  .neu-kpi-card {
    padding: 0.75rem 0.875rem;
  }

  .neu-kpi-value {
    font-size: 1.25rem;
  }

  /* Location badge: truncate aggressively */
  .badge.badge-ghost span {
    max-width: 6rem;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Sidebar: match --layout-sidebar-width so nexus hides it fully */
  #layout-sidebar.neu-sidebar {
    width: var(--layout-sidebar-width);
    min-width: auto;
  }
}

/* --- Tablet and below (existing, expanded) --- */
@media (max-width: 768px) {
  .neu-page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
  }

  .neu-stat-card {
    padding: 1rem;
  }

  .neu-stat-value {
    font-size: 1.5rem;
  }

  .neu-table-card {
    border-radius: 1rem;
  }

  .neu-table th,
  .neu-table td {
    padding: 0.75rem;
    font-size: 0.8125rem;
  }

  .neu-pagination {
    flex-wrap: wrap;
    justify-content: center;
  }

  /* AI action buttons: icon-only on tablet */
  .neu-btn .iconify+span {
    display: none;
  }

  /* Topbar: hide pollen buttons */
  .pollen-btn-group {
    display: none;
  }
}

/* ===== CPW WIZARD ===== */
/* Using hardcoded RGBA shadows (not CSS vars) to guarantee visibility */

.cpw-wizard {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 4rem);
  margin-top: -1.5rem;
  margin-bottom: -5rem;
}

.cpw-wizard-content {
  flex: 1 1 0%;
  padding: 1rem 1.5rem;
}

.cpw-wizard-inner {
  max-width: 72rem;
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}

/* Two-column grid: narrow left (upload) + wide right (form) */
.cpw-grid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: 1.25rem;
  align-items: start;
}

/* Equal two-column grid */
.cpw-grid-equal {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  align-items: start;
}

@media (max-width: 767px) {

  .cpw-grid,
  .cpw-grid-equal {
    grid-template-columns: 1fr;
  }
}

/* Force visible neumorphic shadows inside CPW wizard — hardcoded RGBA */
.cpw-wizard .neu-card-flat {
  background-color: #E0E5EC;
  border-radius: 1.5rem;
  padding: 1.25rem;
  box-shadow: 8px 8px 16px rgba(163, 177, 198, 0.6),
    -8px -8px 16px rgba(255, 255, 255, 0.5) !important;
}

.cpw-wizard .neu-inset-sm {
  background-color: #E0E5EC;
  border-radius: 1rem;
  box-shadow: inset 4px 4px 8px rgba(163, 177, 198, 0.5),
    inset -4px -4px 8px rgba(255, 255, 255, 0.45) !important;
}

/* CPW header bar */
.cpw-header {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 0.5rem 1.5rem;
  background-color: #E0E5EC;
  box-shadow: 0 3px 10px rgba(163, 177, 198, 0.45);
}

.cpw-header-inner {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: nowrap;
}

/* CPW footer bar */
.cpw-footer {
  position: sticky;
  bottom: 0;
  z-index: 10;
  padding: 0.625rem 1.5rem;
  background-color: #E0E5EC;
  box-shadow: 0 -3px 10px rgba(163, 177, 198, 0.35);
}

.cpw-footer-inner {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Step description bar — neumorphic inset strip */
.cpw-step-desc {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin-bottom: 1rem;
  padding: 0.75rem 1rem;
  font-size: 0.8125rem;
  color: #6B7280;
  background-color: #E0E5EC;
  border-radius: 1rem;
  box-shadow: inset 3px 3px 6px rgba(163, 177, 198, 0.45),
    inset -3px -3px 6px rgba(255, 255, 255, 0.4);
  line-height: 1.5;
}

.cpw-step-desc .cpw-step-title {
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--neu-text);
}

/* Upload drop zone — larger padding, dashed border hint */
.cpw-wizard .cpw-upload-drop {
  border: 2px dashed rgba(163, 177, 198, 0.5);
  border-radius: 1rem;
  padding: 1.25rem 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
  background-color: rgba(224, 229, 236, 0.5);
  box-shadow: inset 3px 3px 6px rgba(163, 177, 198, 0.35),
    inset -3px -3px 6px rgba(255, 255, 255, 0.3);
}

.cpw-wizard .cpw-upload-drop:hover {
  border-color: rgba(240, 136, 15, 0.4);
  background-color: rgba(240, 136, 15, 0.03);
}

/* Utility fallbacks for Tailwind classes missing from nexus.css JIT build */
.cpw-wizard .flex-shrink-0 {
  flex-shrink: 0;
}

.cpw-wizard .flex-1 {
  flex: 1 1 0%;
}

.cpw-wizard .overflow-auto {
  overflow: auto;
}

/* Dark mode CPW overrides */
[data-theme="dark"] .cpw-wizard .neu-card-flat {
  background-color: #2D3436;
  box-shadow: 8px 8px 16px rgba(0, 0, 0, 0.5),
    -8px -8px 16px rgba(69, 75, 78, 0.4) !important;
}

[data-theme="dark"] .cpw-wizard .neu-inset-sm,
[data-theme="dark"] .cpw-step-desc {
  background-color: #2D3436;
  box-shadow: inset 4px 4px 8px rgba(0, 0, 0, 0.5),
    inset -4px -4px 8px rgba(69, 75, 78, 0.4) !important;
}

[data-theme="dark"] .cpw-header,
[data-theme="dark"] .cpw-footer {
  background-color: #2D3436;
}

[data-theme="dark"] .cpw-step-desc .cpw-step-title {
  color: #E4E6E8;
}

[data-theme="dark"] .cpw-step-desc {
  color: #9CA3AF;
}

/* ===== DASHBOARD COMPONENT UTILITIES ===== */

/* Inset stat/metric box — used for summary grids inside cards */
.neu-stat-box {
  text-align: center;
  padding: 0.875rem 1rem;
  border-radius: 0.875rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light);
}

.neu-stat-box-title {
  font-size: calc(var(--fluid-unit) * 0.6875);
  font-weight: 600;
  line-height: 1.4;
  color: var(--neu-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.375rem;
}

.neu-stat-box-value {
  font-family: var(--font-display);
  font-size: calc(var(--fluid-unit) * 1.375);
  font-weight: 700;
  color: var(--neu-text);
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

/* Actionable insight callout boxes */
.neu-insight-box {
  padding: 1rem;
  border-radius: 0.875rem;
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-insight-box-success {
  background-color: rgba(16, 185, 129, 0.08);
  box-shadow: none;
  border-left: 3px solid rgba(16, 185, 129, 0.5);
}

.neu-insight-box-warning {
  background-color: rgba(245, 158, 11, 0.08);
  box-shadow: none;
  border-left: 3px solid rgba(245, 158, 11, 0.5);
}

/* Subtle divider line */
.neu-divider {
  height: 1px;
  background: linear-gradient(to right, transparent, var(--neu-border-subtle), transparent);
  margin: 1rem 0;
  border: none;
}

/* Neumorphic override for DaisyUI btn-group inside chart cards.
   Keeps Stimulus controller JS working (class names unchanged) while
   making the toggle group visually consistent with the design system. */
.neu-chart-card .btn-group {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 0.75rem;
  background-color: var(--neu-bg) !important;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
  border: none !important;
}

.neu-chart-card .btn-group .btn {
  background: transparent !important;
  border: none !important;
  border-radius: 0.5rem !important;
  color: var(--neu-muted) !important;
  font-size: 0.8125rem;
  font-weight: 500;
  box-shadow: none !important;
  min-height: unset;
  height: auto;
  padding: 0.375rem 0.875rem;
  transition: all 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.neu-chart-card .btn-group .btn-primary {
  background-color: var(--neu-bg) !important;
  color: var(--neu-text) !important;
  font-weight: 600 !important;
  box-shadow: calc(var(--shadow-offset) - 5px) calc(var(--shadow-offset) - 5px) calc(var(--shadow-blur) - 8px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 5px)) calc(-1 * (var(--shadow-offset) - 5px)) calc(var(--shadow-blur) - 8px) var(--neu-shadow-light) !important;
}

.neu-chart-card .btn-group .btn:hover:not(.btn-primary) {
  color: var(--neu-text) !important;
}

/* Day-of-week checkbox label buttons inside chart cards */
.neu-chart-card .btn-xs.btn-outline {
  background-color: var(--neu-bg) !important;
  border: none !important;
  border-radius: 0.5rem !important;
  color: var(--neu-muted) !important;
  font-size: 0.75rem;
  font-weight: 500;
  box-shadow: calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light) !important;
  padding: 0.25rem 0.5rem;
  min-height: unset;
  height: auto;
}

/* Owner desktop drawer responsiveness */
@media (min-width: 64rem) {
  #layout-main-content {
    margin-left: var(--layout-sidebar-width);
    transition: margin-left 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }

  #layout-sidebar-toggle-trigger:checked~#layout-sidebar+#layout-main-content {
    margin-left: 0;
  }
}

/* gh#1624 — Below lg (Galaxy Z Fold cover screen ~360px AND unfolded inner
   screen ~850px, both < 64rem) the 256px sidebar must NOT sit in-flow eating
   the viewport. Make it a fixed off-canvas drawer: hidden by default so
   #layout-main-content (flex-1) gets the full width, sliding in over a backdrop
   when the hamburger toggle is checked. These selectors outrank nexus's
   `:checked ~ #layout-sidebar` rule (which hides it), so the drawer wins. */
@media (max-width: 63.999rem) {

  /* Off-canvas by default: fixed overlay pulled fully off the left edge. */
  #layout-sidebar.neu-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 501;
    /* above the z-499 backdrop */
    margin-inline-start: calc(var(--layout-sidebar-width) * -1);
    transition: margin-inline-start 0.25s ease-out;
  }

  /* Slide the drawer in when the hamburger toggle is checked. */
  #layout-sidebar-toggle-trigger:checked~#layout-sidebar.neu-sidebar {
    margin-inline-start: 0;
  }

  /* Backdrop is visible (and dimmed) only while the drawer is open. */
  #layout-sidebar-toggle-trigger:checked~#layout-sidebar-backdrop {
    display: block;
    background-color: rgba(0, 0, 0, 0.35) !important;
    backdrop-filter: blur(1px);
  }

  /* Smooth slide-in transition for sidebar */
  #layout-sidebar.neu-sidebar {
    transition: margin-inline-start 0.25s cubic-bezier(0.22, 1, 0.36, 1), transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

  /* Ensure sidebar sits above backdrop */
  #layout-sidebar.neu-sidebar {
    z-index: 501;
  }
}


/* --- Plate chip (tappable, replaces static plate display) --- */
.op-plate-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  cursor: pointer;
  user-select: none;
  border-radius: 0.375rem;
  transition: border-color 0.15s, opacity 0.15s;
}

.op-plate-chip:hover {
  border-color: var(--neu-text);
}

.op-plate-chip-chevron {
  font-size: 0.625rem;
  color: var(--neu-muted);
  margin-left: 0.125rem;
}

/* --- Idle state plate placeholder --- */
.op-idle-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.5rem 1rem;
}

.op-idle-plate-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--neu-bg);
  border: 1px dashed var(--neu-shadow-dark);
  border-radius: 0.375rem;
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  color: var(--neu-muted);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
  min-height: 3.75rem;
}

.op-idle-plate-btn:hover {
  border-color: var(--neu-text);
  color: var(--neu-text);
}

.op-idle-hint {
  font-size: 0.75rem;
  color: var(--neu-muted);
  opacity: 0.6;
}

/* --- Motorist state header label --- */
.op-motorist-label {
  font-size: 1rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.op-motorist-label--new {
  color: #3b82f6;
}

.op-motorist-label--returning {
  color: #f59e0b;
}

.op-motorist-label--member {
  color: var(--neu-text);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  font-size: 1.125rem;
}

.op-motorist-label--lapsed {
  color: var(--neu-text);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  font-size: 1.125rem;
}

/* Idle inherits the base label shape (1rem / 800 / uppercase / 0.05em) just like
   --new and --returning. Yellow color matches the idle assistant-bar palette so
   the whole hero reads as one consistent visual block per motorist state. */
.op-motorist-label--idle {
  color: #f59e0b;
}

/* --- Plan name badge (active member = green, lapsed = red, no strikethrough) ---
   Lapsed-payment members are still members; the badge stays legible so the operator
   can read the plan name. The lapsed signal is conveyed by color + the assistant
   bar's "payment failed · update card" message and Offer CTA. */
.op-plan-badge {
  display: inline-flex;
  align-items: center;
  font-size: 0.6875rem;
  font-weight: 700;
  padding: 0.125rem 0.5rem;
  border-radius: 0.75rem;
  margin-left: 0.375rem;
  max-width: 5.5rem;
  white-space: normal;
  word-break: break-word;
  line-height: 1.2;
  text-align: center;
}

.op-plan-badge--active {
  background: rgba(16, 185, 129, 0.15);
  color: #059669;
}

.op-plan-badge--lapsed {
  background: rgba(239, 68, 68, 0.12);
  color: #dc2626;
}

/* --- Assistant bar ---
   min-height keeps every state pill the same vertical footprint regardless of
   whether a CTA button is present or which line-height the content text picks. */
.op-assistant-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  min-height: 2rem;
  box-sizing: border-box;
  font-size: 0.8125rem;
  line-height: 1.4;
  margin-top: 0.5rem;
  border-left: 3px solid transparent;
}

.op-assistant-bar--new {
  background: rgba(59, 130, 246, 0.08);
  border-left-color: #3b82f6;
  color: #1d4ed8;
}

.op-assistant-bar--idle {
  /* Same shape/sizing as --new, in yellow — operator should see the same
     visual chrome regardless of motorist state so the hero never collapses
     into plain text. */
  background: rgba(245, 158, 11, 0.08);
  border-left-color: #f59e0b;
  color: #92400e;
}

.op-assistant-bar--member {
  background: rgba(16, 185, 129, 0.08);
  border-left-color: #10b981;
  color: #065f46;
}

.op-assistant-bar--returning {
  background: rgba(245, 158, 11, 0.08);
  border-left-color: #f59e0b;
  color: #92400e;
}

.op-assistant-bar--lapsed {
  background: rgba(239, 68, 68, 0.08);
  border-left-color: #ef4444;
  color: #991b1b;
}

/* GH#2093: past_due (declined/failed card) is a critical state — a member is
   enrolled but not being billed. Distinct, stronger red than --lapsed's
   win-back framing; matches the #DC2626 critical accent used elsewhere
   (operator_instructions pill, PILL_STYLES.critical). Also allows the text to
   wrap instead of clipping — this bar replaces the narrow instruction-pill
   rendering of this same signal (design-review bounce on PR #2485). */
.op-assistant-bar--past_due {
  background: rgba(220, 38, 38, 0.1);
  border-left-color: #dc2626;
  color: #991b1b;
  flex-wrap: wrap;
  min-height: 2.75rem;
}

[data-theme="dark"] .op-assistant-bar--past_due {
  color: #fca5a5;
}

[data-theme="dark"] .op-assistant-bar--new {
  color: #93c5fd;
}

[data-theme="dark"] .op-assistant-bar--idle {
  color: #fcd34d;
}

[data-theme="dark"] .op-assistant-bar--member {
  color: #6ee7b7;
}

[data-theme="dark"] .op-assistant-bar--returning {
  color: #fcd34d;
}

[data-theme="dark"] .op-assistant-bar--lapsed {
  color: #fca5a5;
}

.op-assistant-bar-cta {
  background: var(--neu-bg);
  color: var(--neu-text);
  font-size: 0.6875rem;
  font-weight: 700;
  /* Match the text-span's rendered height (18px) so a CTA-bearing bar is the
     same height as a CTA-less bar. The 1px border on each side is part of the
     box, so line-height: 16px + 2px border = 18px total. */
  padding: 0 0.5rem;
  line-height: 16px;
  border-radius: 0.25rem;
  border: 1px solid var(--neu-shadow-dark);
  white-space: nowrap;
  flex-shrink: 0;
  cursor: pointer;
}

.op-assistant-bar-cta--offer {
  background: #ef4444;
  color: #fff;
  border-color: #dc2626;
}

/* GH#2093: the pm_update-modal affordance for a declined/past_due member —
   the ONLY way to open that flow from the register page. Overrides the base
   .op-assistant-bar-cta's ~18px footprint (sized to match a CTA-less bar) with
   a real ≥44px touch target, per design-review bounce on PR #2485 (measured
   ~17px tall in the previous narrow-pill rendering). */
.op-assistant-bar-cta--critical {
  background: #dc2626;
  color: #fff;
  border-color: #b91c1c;
  min-height: 44px;
  min-width: 44px;
  padding: 0 1rem;
  font-size: 0.8125rem;
  line-height: 1.2;
  white-space: normal;
}

/* ============================================================================
   OPERATOR HERO v3 — three voices + columnar ontology (GH#1816)
   Display surface (columns): IDENTITY · ACTIONS · VEHICLE · MEMBERSHIP
   Coaching surface (band):   the assistant instruction, a different VOICE that
                              breaks the columns as a full-width horizontal band.
   THREE VOICES:
     SYSTEM  — Inter; roles snap to a strict scale; weights 400/700 only.
     MACHINE — the skeuomorphic plate (mono).
     COACH   — the assistant voice: warm humanist italic, never Inter/mono.
   Ported from docs/plans/hero-redesign-mockup.html onto the app's --neu-* tokens.
   ========================================================================= */
:root {
  --oph-t-xl: 1.75rem;
  /* headline    */
  --oph-t-l: 1.125rem;
  /* sub / coach */
  --oph-t-m: 0.875rem;
  /* body        */
  --oph-t-s: 0.75rem;
  /* small       */
  --oph-t-xs: 0.625rem;
  /* micro label */
  --oph-go: #059669;
  --oph-wash: #2563eb;
  --oph-lapse: #d97706;
  --oph-alert: #dc2626;
}

/* ---------- voices ---------- */
.oph-greeting {
  font-size: var(--oph-t-xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--neu-text);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.oph-membership {
  font-size: var(--oph-t-m);
  font-weight: 700;
  color: var(--neu-accent);
  font-variant-numeric: tabular-nums;
}

.oph-meta {
  font-size: var(--oph-t-m);
  font-weight: 400;
  color: var(--neu-muted);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

.oph-meta b {
  color: var(--neu-text);
  font-weight: 700;
}

.oph-meta p {
  margin: 0;
}

/* ---------- stat children of .oph-meta ---------- */
.oph-stat {
  margin: 0;
}

.oph-stat--washes {
  font-weight: 700;
  color: var(--neu-muted);
}

.oph-stat--washes.active {
  color: #059669;
}

.oph-stat--renewal {
  color: var(--neu-muted);
}

.oph-stat--duration {
  color: var(--neu-muted);
}

.oph-stat--visits {
  font-weight: 700;
  color: var(--neu-muted);
}

.oph-stat--ltv {
  font-weight: 700;
  color: var(--neu-accent, #6366f1);
}

.oph-stat--seen {
  color: var(--neu-muted);
}

.oph-stat--card-warning {
  display: block;
  font-weight: 700;
  color: #DC2626;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  text-align: left;
  font-size: inherit;
  font-family: inherit;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.oph-stat--lapsed {
  font-weight: 700;
  color: #D97706;
}

.oph-stat--rewash {
  display: inline-block;
  font-weight: 800;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  white-space: nowrap;
  color: #D97706;
  background: rgba(217, 119, 6, 0.12);
  border: 1px solid rgba(217, 119, 6, 0.3);
}

.oph-stat--completed-wash {
  display: inline-block;
  font-weight: 800;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  white-space: nowrap;
  color: #059669;
  background: rgba(5, 150, 105, 0.12);
  border: 1px solid rgba(5, 150, 105, 0.3);
}

.oph-stat--in-progress {
  display: inline-block;
  font-weight: 800;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.75rem;
  white-space: nowrap;
  color: #2563eb;
  background: rgba(37, 99, 235, 0.1);
  border: 1px solid rgba(37, 99, 235, 0.25);
}

.oph-stat--detection {
  font-weight: 700;
  font-size: 0.8rem;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(245, 158, 11, 0.15);
  color: #D97706;
}

.oph-label {
  font-size: var(--oph-t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--neu-muted);
}

.oph-machine {
  font-family: var(--font-mono);
  font-size: var(--oph-t-m);
  font-weight: 700;
  color: var(--neu-text);
  font-variant-numeric: tabular-nums;
}

.oph-coach {
  font-family: 'Iowan Old Style', Georgia, 'Palatino Linotype', Palatino, serif;
  font-style: italic;
  font-size: var(--oph-t-l);
  font-weight: 400;
  color: var(--neu-text);
  letter-spacing: 0;
}

.oph-empty {
  color: var(--neu-muted);
  font-weight: 400;
}

/* ---------- scaffold (columnar grid) ---------- */
.op-hero {
  display: grid;
  grid-template-columns: 1fr auto 1.35fr 1.1fr;
  /* Identity · Actions · Vehicle · Membership */
  gap: 1.1rem;
  align-items: stretch;
}

.op-hero__col {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

.op-hero__col--id {
  grid-column: 1;
  justify-content: flex-start;
}

.op-hero__actions {
  grid-column: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.4rem;
}

.op-hero__col--veh {
  grid-column: 3;
}

.op-hero__col--mem {
  grid-column: 4;
}

.op-hero__col--veh,
.op-hero__col--mem {
  /* unified card = inset well */
  background: var(--neu-bg);
  border-radius: 1rem;
  padding: 0.8rem 0.9rem;
  overflow: hidden;
  box-shadow: inset 4px 4px 8px var(--neu-shadow-dark), inset -4px -4px 8px var(--neu-shadow-light);
}

.op-hero__coach {
  grid-column: 1 / -1;
}

@media (max-width: 959px) {
  .op-hero {
    grid-template-columns: 1fr 1fr;
  }

  .op-hero__col--id {
    grid-column: 1 / -1;
  }

  .op-hero__actions {
    grid-column: 1 / -1;
    flex-direction: row;
  }

  .op-hero__col--veh {
    grid-column: 1;
  }

  .op-hero__col--mem {
    grid-column: 2;
  }
}

/* Tablet landscape (RugKing class): the hero is ONE compact band — identity,
   actions, vehicle, membership across a single row — designed for the height
   instead of clip-compressed (JPB, PR #2007 round-3). */
@media (min-width: 960px) and (max-width: 1366px) and (orientation: landscape) {
  .op-hero {
    gap: 0.45rem;
    grid-template-columns: minmax(7rem, 0.7fr) auto 1.35fr 1.1fr;
  }

  .op-hero__col--id {
    grid-column: 1;
  }

  .op-hero__actions {
    grid-column: 2;
    gap: 0.25rem;
  }

  .op-hero__col--veh {
    grid-column: 3;
  }

  .op-hero__col--mem {
    grid-column: 4;
  }

  .op-hero__col--veh,
  .op-hero__col--mem {
    max-height: 8rem;
    overflow: hidden;
    padding: 0.45rem 0.55rem;
  }

  /* Cap id and actions so the grid row stays at ≤8rem even if id content grows
     (many instruction pills). Row height is set by the tallest cell; without a
     cap the id column can push the row past 8rem and clip veh content again. */
  .op-hero__col--id {
    max-height: 8rem;
    overflow: hidden;
  }

  .op-hero__actions {
    max-height: 8rem;
    overflow: hidden;
  }

  .oph-meta {
    font-size: 0.72rem;
    line-height: 1.2;
  }

  .oph-act-btn {
    font-size: 0.62rem;
    padding: 0.22rem 0.5rem;
  }

  /* Plate + camera stay side by side in the narrower hero band column.
     Scoped to --veh so filmstrip and other plate contexts are unaffected. */
  .op-hero__col--veh .oph-plates {
    flex-wrap: nowrap;
  }

  .op-hero__col--veh .oph-plate,
  .op-hero__col--veh .oph-alpr {
    width: 5.5rem;
  }

  .op-hero__col--veh .oph-plate__number {
    font-size: 0.9rem;
    letter-spacing: 0.03em;
  }

  .op-hero__coach {
    max-height: 1.7rem;
    overflow: hidden;
  }

  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section>.op-card {
    flex: 0 1 auto;
    min-height: 0;
    overflow: hidden;
  }
}

/* ---------- identity ---------- */
.oph-id-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.oph-id-row .sep {
  color: var(--neu-muted);
  padding: 0 0.3rem;
  opacity: 0.5;
}

.oph-badge-banned {
  font-size: var(--oph-t-s);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #fff;
  background: linear-gradient(135deg, #dc2626, #991b1b);
  padding: 0.15rem 0.45rem;
  border-radius: 0.35rem;
  white-space: nowrap;
}

/* ---------- vehicle ---------- */
.oph-plates {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.oph-plate-wrap {
  display: flex;
  flex-direction: column;
}

.oph-plate-wrap .cap {
  font-size: var(--oph-t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--neu-muted);
  margin-bottom: 0.15rem;
  text-align: center;
}

.oph-plate,
.oph-alpr {
  width: 7rem;
  aspect-ratio: 2 / 1;
  border-radius: 0.45rem;
  overflow: hidden;
  cursor: pointer;
}

.oph-plate {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  border: 2px solid #666;
  background: #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.22);
}

.oph-plate__state {
  flex: 0 0 auto;
  text-align: center;
  padding-top: 0.14rem;
  font-size: 0.5rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  color: #666;
}

.oph-plate__number {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 1.15rem;
  font-weight: 900;
  letter-spacing: 0.06em;
  line-height: 1;
  color: #1a1a1a;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.45);
  overflow: hidden;
}

.oph-plate__number>span {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.oph-alpr {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #3a3f45, #23272b);
  border: 1px solid #11141a;
  box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.6);
  font-family: var(--font-mono);
  color: #e8eaed;
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: 0.06em;
}

.oph-alpr.is-empty {
  background: var(--neu-bg);
  border: 1px dashed var(--neu-muted);
  color: var(--neu-muted);
  box-shadow: none;
}

.oph-car {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.oph-swatch {
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.2);
  flex-shrink: 0;
}

/* ---------- membership ---------- */
.oph-mem-badge {
  display: inline-flex;
  align-self: flex-start;
  gap: 0.35rem;
  align-items: center;
  background: linear-gradient(135deg, var(--neu-accent), var(--neu-accent-light));
  color: #fff;
  font-weight: 700;
  font-size: var(--oph-t-s);
  padding: 0.2rem 0.6rem;
  border-radius: 0.45rem;
}

.oph-mem-badge.is-lapsed {
  background: none;
  color: var(--oph-lapse);
  border: 1px solid #f0c894;
}

.oph-bubbles {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.oph-bubble-row {
  display: flex;
  gap: 3px;
  flex-wrap: wrap;
}

.oph-bubble {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
}

.oph-bubble.is-used {
  background: var(--oph-go);
}

.oph-bubble.is-free {
  background: var(--neu-bg);
  box-shadow: inset 1px 1px 2px var(--neu-shadow-dark), inset -1px -1px 2px var(--neu-shadow-light);
}

.oph-bubble.is-active {
  background: var(--oph-wash);
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.25);
  animation: oph-pulse 1.4s ease-in-out infinite;
}

@keyframes oph-pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.45;
  }
}

.oph-bubble-count {
  font-weight: 700;
  color: var(--oph-go);
  white-space: nowrap;
  font-size: var(--oph-t-m);
}

.oph-mem-line {
  color: var(--neu-accent);
  font-size: var(--oph-t-m);
}

.oph-mem-line.is-lapse {
  color: var(--oph-lapse);
  font-weight: 700;
}

.oph-wash-chip {
  display: inline-flex;
  align-self: flex-start;
  gap: 0.3rem;
  align-items: center;
  font-size: var(--oph-t-s);
  font-weight: 700;
  padding: 0.16rem 0.45rem;
  border-radius: 0.35rem;
}

.oph-wash-chip.is-done {
  color: var(--oph-go);
  background: rgba(5, 150, 105, 0.14);
}

.oph-wash-chip.is-prog {
  color: var(--oph-wash);
  background: rgba(37, 99, 235, 0.12);
}

.oph-mem-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--neu-accent);
  color: #fff;
  font-weight: 700;
  font-size: var(--oph-t-m);
  padding: 0.55rem;
  border-radius: 0.6rem;
  cursor: pointer;
  border: none;
}

.oph-mem-cta.is-resign {
  background: var(--oph-lapse);
}

.oph-mem-not-yet {
  color: var(--neu-muted);
  font-size: var(--oph-t-s);
  font-weight: 600;
}

.oph-mem-pay {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.4rem;
  padding-top: 0.4rem;
  font-size: var(--oph-t-s);
  font-weight: 400;
  color: var(--neu-text);
}

.oph-mem-pay.is-alert {
  color: var(--oph-alert);
  font-weight: 700;
}

.oph-mem-update {
  font-size: var(--oph-t-s);
  font-weight: 700;
  color: var(--neu-accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.12rem 0.35rem;
  border-radius: 0.35rem;
  white-space: nowrap;
}

.oph-mem-update.is-primary {
  background: var(--oph-alert);
  color: #fff;
  padding: 0.3rem 0.65rem;
  border-radius: 0.5rem;
}

/* ---------- action column (control surface) ---------- */
.oph-act-btn {
  font-size: var(--oph-t-s);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.45rem 0.8rem;
  border-radius: 0.6rem;
  background: var(--neu-bg);
  color: var(--neu-muted);
  cursor: pointer;
  border: none;
  white-space: nowrap;
  box-shadow: 4px 4px 8px var(--neu-shadow-dark), -4px -4px 8px var(--neu-shadow-light);
}

.oph-act-btn.is-on {
  color: #fff;
  box-shadow: inset 3px 3px 6px rgba(0, 0, 0, 0.25);
}

.oph-act-btn--fleet.is-on {
  background: linear-gradient(135deg, #3B82F6, #2563EB);
}

.oph-act-btn--taxi.is-on {
  background: linear-gradient(135deg, #F59E0B, #D97706);
}

.oph-act-btn.is-disabled {
  opacity: 0.4;
  cursor: default;
  box-shadow: none;
}

/* ---------- coach band (instruction surface — breaks the vertical) ---------- */
.op-hero__coach {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-top: 0.4rem;
  padding: 0.65rem 1rem;
  border-radius: 0.9rem;
  background: color-mix(in srgb, var(--neu-accent) 12%, var(--neu-bg));
  border-left: 4px solid var(--neu-accent);
}

.op-hero__coach .oph-coach-icon {
  font-size: 1.1rem;
  flex-shrink: 0;
}

.op-hero__coach .oph-coach-text {
  flex: 1;
}

.op-hero__coach .oph-coach-cta {
  font-size: var(--oph-t-s);
  font-weight: 700;
  color: #fff;
  background: var(--neu-accent);
  border: none;
  border-radius: 0.55rem;
  padding: 0.4rem 0.8rem;
  cursor: pointer;
  white-space: nowrap;
}

.op-hero__coach.is-warn {
  background: color-mix(in srgb, var(--oph-lapse) 14%, var(--neu-bg));
  border-left-color: var(--oph-lapse);
}

.op-hero__coach.is-warn .oph-coach-cta {
  background: var(--oph-lapse);
}

.op-hero__coach.is-idle {
  background: color-mix(in srgb, var(--neu-muted) 12%, var(--neu-bg));
  border-left-color: var(--neu-muted);
}

.op-hero__coach.is-idle .oph-coach {
  color: var(--neu-muted);
}

/* --- Package grid: member state dimming --- */
.op-single-wash-btn {
  transition: opacity 0.2s, filter 0.2s;
}

.op-single-wash-btn:disabled {
  opacity: 0.42;
  filter: grayscale(30%);
  pointer-events: none;
  cursor: default;
}

/* --- Current plan indicator on membership cards --- */
.op-current-plan-label {
  font-size: 0.625rem;
  font-weight: 700;
  color: #f97316;
  margin-left: 0.25rem;
}

.op-membership-btn.is-current-plan {
  box-shadow: 0 0 0 2px #f97316;
}

/* --- Package card min-heights (prevents 6-package layout collapse) --- */
.op-pkg-card {
  min-height: 5rem;
}

.op-price-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  gap: 0.1rem;
}

.op-price-total {
  color: var(--neu-text);
  display: inline-flex;
  align-items: flex-end;
  gap: 0.05em;
  font-size: 1.5rem;
  line-height: 1;
  white-space: nowrap;
}

.op-price-suffix {
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1;
}

.op-price-breakdown {
  color: rgba(107, 114, 128, 0.68);
  color: color-mix(in srgb, var(--neu-muted) 64%, var(--neu-bg) 36%);
  font-size: 0.625rem;
  font-weight: 500;
  line-height: 1.15;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}



/* ============================================================
   Operator Dashboard — Responsive Layout
   ============================================================ */

/* --- Video pane: 16:9 aspect ratio, scales with container ---- */
.op-video-pane {
  aspect-ratio: 16 / 9;
  width: 100%;
  min-height: 8rem;
}

/* --- Filmstrip card baseline styles (mobile overrides below) - */
.filmstrip-card {
  transition: box-shadow 0.15s, background 0.15s;
}

/* Fade-in only fires on JS-driven inserts (class added in operator_detection_controller),
   so initial server-rendered cards on page load don't all animate at once. */
@keyframes filmstrip-card-fade-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }

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

@keyframes filmstrip-card-fade-out {
  from {
    opacity: 1;
    transform: translateY(0);
  }

  to {
    opacity: 0;
    transform: translateY(-4px);
  }
}

.filmstrip-card.is-fresh {
  animation: filmstrip-card-fade-in 220ms ease-out;
}

.filmstrip-card.is-leaving {
  animation: filmstrip-card-fade-out 180ms ease-in forwards;
  pointer-events: none;
}

/* Smooth pill state transitions when data-visit-status-badge text/styles swap */
.filmstrip-card [data-visit-status-badge] {
  transition: background-color 200ms cubic-bezier(0.22, 1, 0.36, 1), color 200ms cubic-bezier(0.22, 1, 0.36, 1), border-color 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- Desktop (≥ 1440px): generous spacing -------------------- */
@media (min-width: 1440px) {
  .op-main-grid {
    gap: 1.5rem;
    padding: 1.5rem;
  }

  .op-pkg-card {
    min-height: 6rem;
  }
}

/* --- Tablet landscape primary target (960px – 1366px) --------
   RugKing Pad 2 Pro is 1280x800 physical at ~204dpi, which maps
   to roughly 1004x627 CSS px in Android WebView. */
@media (min-width: 960px) and (max-width: 1366px) and (orientation: landscape) {
  .op-main-grid {
    gap: 0.875rem;
    padding: 0.875rem;
  }

  /* Tighten package card text so 6-card layout always fits */
  .op-pkg-card {
    min-height: 4.75rem;
    padding: 0.75rem !important;
  }

  #filmstrip .filmstrip-card {
    min-width: 0;
    width: 100%;
  }

  #filmstrip .filmstrip-card>div,
  #filmstrip .filmstrip-card>div>div {
    min-width: 0;
  }

  #filmstrip .filmstrip-card .font-mono {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  #filmstrip .filmstrip-card [data-visit-status-badge] {
    flex-shrink: 0;
    max-width: 7.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Motorist label: slightly smaller so it never wraps */
  .op-motorist-label {
    font-size: 0.9375rem;
  }

  .op-motorist-label--member,
  .op-motorist-label--lapsed {
    font-size: 1.0625rem;
  }

  /* Assistant bar: tighter vertical footprint */
  .op-assistant-bar {
    padding: 0.375rem 0.625rem;
    font-size: 0.75rem;
  }

  /* Plate chip: ensure 60px touch target met on tablet */
  .op-plate-chip {
    min-height: 3.75rem;
  }

  /* Prevent site name from wrapping when right group has weather/pollen pills */
  .op-header .flex.justify-between>div:first-child {
    min-width: 0;
    overflow: hidden;
  }

  .op-header-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Prevent center column from overflowing its grid track */
  .op-center {
    min-width: 0;
    overflow-x: hidden;
  }
}

/* --- Portrait tablet / narrow tablet (768px – 959px) --------- */
@media (max-width: 959px) and (min-width: 768px),
(max-width: 1023px) and (min-width: 768px) and (orientation: portrait) {

  /* Reflow: single column stacked — sidebar, center, right */
  .op-main-grid {
    grid-template-columns: 1fr !important;
    gap: 0.625rem;
    padding: 0.75rem;
    /* gh#1624 — fold inner (~850px): keep the reflowed grid from forcing a
       horizontal page scroll if a child runs wide. */
    overflow-x: hidden !important;
  }

  /* All columns go full width */
  .op-main-grid>* {
    grid-column: 1 / -1 !important;
  }

  /* Sidebar: compact height — show icon pad + short filmstrip */
  .op-main-grid .op-sidebar {
    height: auto !important;
  }

  .op-main-grid .op-sidebar>div {
    height: auto !important;
    max-height: none !important;
  }

  /* Filmstrip: horizontal scroll strip on portrait tablet */
  #filmstrip {
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    max-height: 4rem !important;
    gap: 0.5rem !important;
  }

  .filmstrip-card {
    flex-shrink: 0 !important;
    min-width: 6rem !important;
    max-width: 7rem !important;
  }

  /* Package cards: comfortable height at tablet portrait width */
  .op-pkg-card {
    min-height: 4.5rem;
  }

  /* Assistant bar: allow wrap */
  .op-assistant-bar {
    flex-wrap: wrap;
    gap: 0.375rem;
  }

  /* Right panel package grid: 2x2 grids have full width */
  .op-right .grid.grid-cols-2 {
    gap: 0.75rem;
  }
}

/* --- Mobile (< 768px): stacked single column ----------------- */
@media (max-width: 767px) {
  .op-main-grid {
    grid-template-columns: 1fr !important;
    gap: 0.5rem;
    padding: 0.5rem 0.375rem;
    overflow-y: auto !important;
    overflow-x: hidden !important;
  }

  /* All grid children go full width */
  .op-main-grid>* {
    grid-column: 1 / -1 !important;
  }

  /* Sidebar: compact, auto height (not full viewport) */
  .op-main-grid .op-sidebar {
    height: auto !important;
  }

  .op-main-grid .op-sidebar>div {
    height: auto !important;
    max-height: none !important;
    padding: 0.375rem 0.5rem !important;
    gap: 0.5rem !important;
    min-height: 0;
  }

  /* Filmstrip on mobile: horizontal compact scroll strip */
  #filmstrip {
    flex-direction: row !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    max-height: 3.5rem !important;
    gap: 0.375rem !important;
  }

  /* Filmstrip cards: compact chips on mobile */
  .filmstrip-card {
    flex-shrink: 0 !important;
    min-width: 5rem !important;
    max-width: 5rem !important;
    border-radius: 0.5rem !important;
  }

  /* Center: full width, visible overflow for content */
  .op-main-grid .op-center {
    overflow-y: visible !important;
    overflow-x: hidden !important;
  }

  /* Package cards: comfortable 2-column grid on mobile */
  .op-pkg-card {
    min-height: 4rem;
    padding: 0.625rem !important;
  }

  /* Package card text: scale down */
  .op-pkg-card .text-2xl,
  .op-pkg-card .text-3xl {
    font-size: 1.25rem !important;
  }

  .op-pkg-card .text-lg {
    font-size: 0.9375rem !important;
  }

  /* Motorist label: compact on phone */
  .op-motorist-label {
    font-size: 0.875rem;
  }

  .op-motorist-label--member,
  .op-motorist-label--lapsed {
    font-size: 1rem;
  }

  /* Plan badge: slightly smaller */
  .op-plan-badge {
    font-size: 0.625rem;
    padding: 0.125rem 0.375rem;
  }

  /* Assistant bar: allow text wrap, smaller font */
  .op-assistant-bar {
    flex-wrap: wrap;
    gap: 0.375rem;
    font-size: 0.75rem;
    padding: 0.375rem 0.625rem;
  }

  /* Plate chip: guaranteed 60px touch target */
  .op-plate-chip {
    min-height: 3.75rem;
    width: 100%;
    justify-content: center;
  }

  .op-idle-plate-btn {
    width: 100%;
    justify-content: center;
    min-height: 3.75rem;
  }

  /* Package section headings: slightly smaller */
  .op-single-washes-section h3,
  .op-single-washes-label {
    font-size: 1rem !important;
  }

  /* Visit history search: full width + stacked dates */
  #history-section .flex.flex-wrap {
    flex-direction: column;
    align-items: stretch;
  }

  #history-section input[type="date"] {
    width: 100%;
  }

  /* Reduce right panel padding for mobile */
  .op-right .neu-extruded,
  .op-right .neu-extruded-sm {
    padding: 0.875rem !important;
  }
}

/* --- Ultra-small phones (< 375px) ---------------------------- */
@media (max-width: 374px) {
  .op-main-grid {
    padding: 0.25rem;
    gap: 0.375rem;
  }

  .op-pkg-card {
    min-height: 3.5rem;
    padding: 0.5rem !important;
  }

  .op-assistant-bar {
    font-size: 0.6875rem;
  }

  /* Package grid: single column on very small phones */
  .op-single-washes-section .grid,
  [data-tour="membership-plans"] .grid {
    grid-template-columns: 1fr !important;
  }
}

/* ============================================================
   Operator Dashboard — Section-Level Responsive Fixes
   ============================================================ */

/* --- Equipment section: override JS-generated 3-column grids --- */
/* The equipment report controller generates HTML with hard-coded grid-cols-3.
   These CSS overrides collapse the grid on small screens. */
@media (max-width: 767px) {
  #equipment-section [class*="grid-cols-3"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}

@media (max-width: 479px) {
  #equipment-section [class*="grid-cols-3"] {
    grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
  }
}

/* --- Customer profile header: stack vertically on mobile --- */
@media (max-width: 767px) {
  .op-customer-profile-header {
    flex-direction: column;
  }

  /* Stats pane: horizontal row with spacing when stacked */
  .op-customer-profile-header>div.shrink-0 {
    border-left: none !important;
    border-top: 1px solid rgba(0, 0, 0, 0.1);
    padding-left: 0 !important;
    padding-top: 0.625rem;
    text-align: left !important;
    min-width: 0 !important;
    display: flex !important;
    flex-direction: row !important;
    gap: 1.5rem !important;
    flex-wrap: wrap;
    width: 100%;
  }

  /* Each stat: side-by-side label + value */
  .op-customer-profile-header>div.shrink-0>div {
    display: flex;
    align-items: baseline;
    gap: 0.375rem;
  }

  .op-customer-profile-header>div.shrink-0>div>div:last-child {
    font-size: 1rem !important;
  }
}

/* --- Tables: scroll polish + touch-friendly buttons on mobile --- */
#history-section .overflow-x-auto,
#customer-section .overflow-x-auto {
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}

/* --- Motorist Profile pane: tablet-landscape readability (GH #1734) ----------
   The profile pane (#customer-section → _motorist_profile) crams a customer
   summary plus two data tables into a single column. At the tablet-landscape
   sizes operators actually use (~1004–1072px wide, viewed at arm's length) the
   default compact type is hard to read. Bump the type scale, row height, and
   touch targets here — scoped to this breakpoint and pane so phone, portrait,
   and desktop layouts are untouched. */
@media (min-width: 960px) and (max-width: 1366px) and (orientation: landscape) {

  /* Pane padding: a little more breathing room around the content */
  .op-profile-pane {
    padding: 1rem !important;
  }

  /* Pane title (👤 Motorist Profile) */
  #customer-section .neu-heading-md {
    font-size: 1.625rem;
  }

  /* Customer summary line: name + at-a-glance stats */
  .op-profile-name {
    font-size: 1.375rem !important;
  }

  .op-profile-stats {
    font-size: 1.0625rem !important;
    /* Let the stats wrap instead of truncating with an ellipsis — at this size
       the operator needs every stat (visits, LTV, renewal, card warnings). */
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    line-height: 1.6 !important;
  }


  /* Section labels — RECENT ORDERS / VISIT HISTORY */
  .op-profile-table-label {
    font-size: 0.9375rem;
  }

  /* Data tables: larger type and taller rows for legibility + touch */
  #customer-section table {
    font-size: 1.0625rem;
  }

  #customer-section table th {
    font-size: 0.9375rem !important;
    padding-top: 0.625rem;
    padding-bottom: 0.625rem;
  }

  #customer-section table td {
    padding-top: 0.875rem;
    padding-bottom: 0.875rem;
  }

  /* Row action buttons (refund) — comfortable touch target */
  #customer-section table button {
    min-height: 2.75rem;
    padding: 0.375rem 0.875rem;
    font-size: 0.875rem;
  }

  /* Pagination count footer */
  .op-profile-pagination {
    font-size: 0.9375rem;
  }
}

@media (max-width: 767px) {

  /* Action buttons in tables: meet 44px touch target */
  #history-section table button,
  #customer-section table button {
    min-height: 2.75rem;
    padding: 0.375rem 0.75rem;
    font-size: 0.75rem;
  }

  /* Date filter inputs: meet touch target height */
  #history-section input[type="date"] {
    min-height: 2.75rem;
    font-size: 0.9375rem;
  }

  /* Pagination area: tighter gap on small screens */
  #history-section [data-operator-visit-table-target="pagination"] .flex {
    gap: 0.5rem !important;
    flex-wrap: wrap;
    justify-content: center;
  }

  #history-section [data-operator-visit-table-target="pagination"] button {
    min-height: 2.75rem;
    padding: 0.375rem 0.875rem;
  }
}

/* --- Sales section: stats always 3-col; monthly bonus 2-col on tablet+, 1-col on mobile --- */
@media (max-width: 639px) {
  #sales-section .grid.grid-cols-2 {
    grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
  }
}

/* --- AI detected objects: CSS fallback --- */
@media (max-width: 479px) {
  .op-ai-objects-grid {
    grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
  }
}

/* --- Vehicle metadata grid: CSS fallback for col-2 on mobile --- */
/* Primary fix is via Tailwind grid-cols-2 md:grid-cols-4 in ERB */
@media (max-width: 767px) {
  .op-vehicle-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}

/* ========================================================================
   Operator Dashboard — Modal Responsive Fixes (mobile ≤767px)
   Cash Drop + AI modals only. Desktop appearance is unchanged.
   ======================================================================== */

/* --- Cash Drop Modal --- */
@media (max-width: 767px) {
  #cashDropModal .modal-box {
    padding: 1.25rem;
  }

  #cashDropModal h3 {
    font-size: 1.5rem;
    margin-bottom: 0.875rem;
  }

  /* Stack info + keypad from 2 columns to 1 */
  #cashDropModal .grid-cols-2 {
    grid-template-columns: 1fr !important;
    gap: 1rem !important;
  }

  /* Scale label text */
  #cashDropModal .text-3xl {
    font-size: 1.125rem;
  }

  #cashDropModal .text-2xl {
    font-size: 1rem;
  }

  /* Scale the giant drop number */
  #cashDropModal .text-7xl {
    font-size: 2.25rem;
  }

  #cashDropModal .text-8xl {
    font-size: 2.75rem;
  }

  /* Amount display — inline style requires !important */
  #cashDropAmount {
    font-size: 2.25rem !important;
  }

  /* Info cards: reduce padding */
  #cashDropModal .p-8 {
    padding: 0.875rem;
  }

  /* Operator select */
  #cashDropModal select {
    font-size: 1rem;
    padding: 0.5rem 0.75rem;
  }

  /* Keypad digit buttons — height is inline, needs !important */
  #cashDropModal .grid-cols-3 button {
    height: 3.5rem !important;
    font-size: 1.25rem;
  }

  #cashDropModal .text-4xl {
    font-size: 1.25rem;
  }

  /* Action row (Cancel + Submit) */
  #cashDropModal .flex.gap-6 {
    gap: 0.5rem;
  }

  #cashDropModal .flex.gap-6 button {
    height: 3rem !important;
    font-size: 0.875rem;
  }
}

/* --- Cash Drop Modal at tablet landscape (960–1366px, landscape) ---
   The mobile MQ (≤767px) doesn't fire at RugKing's 1004×627 CSS viewport.
   Scale the desktop-huge font sizes down so the modal fits without scrolling. */
@media (min-width: 960px) and (max-width: 1366px) and (orientation: landscape) {
  #cashDropModal .modal-box {
    padding: 0.875rem 1.125rem;
  }

  #cashDropModal h3 {
    font-size: 1.5rem;
    margin-bottom: 0.5rem;
    gap: 0.5rem;
  }

  /* Inline style at 3.5rem needs !important to be overridden */
  #cashDropAmount {
    font-size: 2.25rem !important;
  }

  #cashDropModal .text-2xl {
    font-size: 1.0rem;
  }

  #cashDropModal .text-3xl {
    font-size: 1.25rem;
  }

  #cashDropModal .text-4xl {
    font-size: 1.25rem;
  }

  #cashDropModal .grid-cols-3 button {
    height: 2.75rem !important;
    font-size: 1.1rem;
  }

  #cashDropModal .flex.gap-6 {
    gap: 0.375rem;
  }

  #cashDropModal .flex.gap-6 button {
    height: 2.25rem !important;
    font-size: 0.875rem;
  }

  #cashDropModal .p-8 {
    padding: 0.75rem;
  }

  #cashDropModal select {
    font-size: 0.875rem;
    padding: 0.25rem 0.5rem;
  }
}

/* --- Customer Intelligence partial: member info bar stacks on mobile --- */
@media (max-width: 767px) {
  .op-customer-intel .flex.items-center.justify-between:first-child {
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .op-customer-intel .flex.items-center.justify-between:first-child>div:last-child {
    width: 100%;
  }
}

/* --- AI Modal: wrap the input row so buttons don't overflow --- */
@media (max-width: 767px) {
  #aiModal form[data-agent-target="chatForm"] {
    flex-wrap: wrap;
  }

  /* Input takes full width on its own line */
  #aiModal form[data-agent-target="chatForm"] .neu-input {
    flex-basis: 100%;
    margin-bottom: 0.375rem;
  }

  /* Buttons share the row below, shrink labels to fit */
  #aiModal form[data-agent-target="chatForm"] button {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.5rem 0.5rem;
    font-size: 0.8125rem;
  }

  /* Tighten chat history height on mobile */
  #aiResponseArea {
    min-height: 180px;
    max-height: 260px;
  }
}

/* --- History filter row: constrain date inputs at tablet so all 3 controls stay on one line --- */
@media (min-width: 768px) {
  #history-section input[type="date"] {
    width: 136px;
    flex-shrink: 0;
  }
}

/* --- Equipment zone grid: let rows be naturally tall on mobile so zone names aren't clipped --- */
@media (max-width: 767px) {
  #equipment-section [data-operator-equipment-report-target="content"] .grid {
    height: auto !important;
    grid-auto-rows: auto !important;
  }

  #equipment-section button[data-zone-id] {
    min-height: 5rem;
    padding: 0.75rem 0.5rem !important;
  }
}

/* --- Footer stats bar: hide on mobile to prevent horizontal overflow --- */
@media (max-width: 767px) {
  .op-footer [data-tour="footer-stats"] {
    display: none !important;
  }

  /* Left side (user pill + system status) fills the bar without justify-between gap */
  .op-footer .flex.items-center.overflow-visible {
    justify-content: flex-start;
  }
}

/* ============================================================
   Mobile: full-height section layout
   When any non-vehicle section is active, hide op-right so the
   section content fills the full grid height instead of sharing
   it 50/50 with the packages panel.  Vehicle tab keeps op-right
   visible because the package purchase flow depends on it.
   ============================================================ */
@media (max-width: 767px) {

  .op-main-grid:has(#sales-section:not(.hidden)) .op-right,
  .op-main-grid:has(#history-section:not(.hidden)) .op-right,
  .op-main-grid:has(#customer-section:not(.hidden)) .op-right,
  .op-main-grid:has(#settings-section:not(.hidden)) .op-right,
  .op-main-grid:has(#equipment-section:not(.hidden)) .op-right {
    display: none !important;
  }

  /* op-center takes the full grid height when no op-right is competing */
  .op-main-grid:has(#sales-section:not(.hidden)) .op-center,
  .op-main-grid:has(#history-section:not(.hidden)) .op-center,
  .op-main-grid:has(#customer-section:not(.hidden)) .op-center,
  .op-main-grid:has(#settings-section:not(.hidden)) .op-center,
  .op-main-grid:has(#equipment-section:not(.hidden)) .op-center {
    max-height: calc(100dvh - 10rem);
    overflow-y: auto !important;
  }
}

/* --- Leaderboard filter pills: wrap gracefully on very small phones --- */
@media (max-width: 479px) {

  #sales-section [data-operator-leaderboard-target="rankings"]~* .flex,
  #sales-section .flex.justify-between.items-center {
    flex-wrap: wrap;
  }

  #sales-section .flex.justify-between.items-center>div {
    flex-wrap: wrap;
  }
}

/* Selected card state — inset shadow shows the card is pressed/active */
.filmstrip-card--active {
  box-shadow: inset 3px 3px 6px var(--neu-shadow-dark), inset -3px -3px 6px var(--neu-shadow-light) !important;
}

/* ============================================================
   Desktop / tablet landscape: packages grid fills available height
   When the vehicle/scan section is active, chain height from the
   CSS-grid-bounded op-center down to the packages grid so
   grid-auto-rows:1fr can divide the real pixel height and buttons
   scale down rather than overflowing.
   ============================================================ */
@media (min-width: 960px) and (orientation: landscape) {

  /* Switch op-center to a flex column so children can use flex: 1 */
  .op-center:has(#vehicle-section:not(.hidden)) {
    overflow-y: hidden;
    display: flex;
    flex-direction: column;
  }

  /* Vehicle section fills op-center; its children stack vertically */
  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }

  /* Scan card and alert: fixed height — do not shrink */
  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section>.op-card,
  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section>.alert-warning-card {
    flex-shrink: 0;
  }

  /* package-grid-wrapper is a transparent flex pass-through so the extracted
     _package_grid partial (GH#1935) behaves identically to the inline products-area
     that was a direct flex child of #vehicle-section before extraction. */
  .op-center:has(#vehicle-section:not(.hidden)) #package-grid-wrapper {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }

  /* Packages card: fill remaining height below scan card; clip overflow */
  .op-center:has(#vehicle-section:not(.hidden)) .op-packages-center {
    flex: 1 !important;
    min-height: 0 !important;
    overflow: hidden !important;
  }

  /* Package buttons: bottom row anchors itself via margin-top: auto below —
     NOT justify-content: space-between, which collapses to flex-start when a
     card has no top label (most single-wash/membership cards). */
  .op-packages-center button {
    overflow: hidden;
    padding: clamp(0.25rem, 1vh, 0.75rem) !important;
  }

  /* Top row: shrinks if short on height so bottom row is never evicted */
  .op-packages-center button>.op-product-button-top {
    overflow: hidden;
    flex-shrink: 1;
    min-height: 0;
  }

  /* #N / #Mx tile number — small label, like the commission pill */
  .op-packages-center button>.op-product-button-top>span.font-black {
    font-size: 0.6875rem !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    flex-shrink: 0;
  }

  /* Package / membership name — primary text, wraps to 2 lines max */
  .op-packages-center button>.op-product-button-top>span:not(.font-black) {
    font-size: clamp(1rem, 3.5vh, 2rem) !important;
    line-height: 1.2 !important;
    margin-top: -0.1em !important;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  /* Bottom row: never shrinks, always anchored to the bottom of the card —
     price and commission always visible */
  .op-packages-center button>div:last-child {
    flex-shrink: 0 !important;
    margin-top: auto !important;
    padding-top: clamp(0.1rem, 0.6vh, 0.5rem) !important;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
  }

  /* Total price amount — prominent, same scale as name */
  .op-packages-center button .op-price-total {
    font-size: clamp(1rem, 3.5vh, 2rem) !important;
    line-height: 1 !important;
  }

  .op-packages-center button .op-price-suffix {
    font-size: clamp(0.65rem, 1.75vh, 0.9rem) !important;
  }

  .op-packages-center button .op-price-breakdown {
    font-size: clamp(0.55rem, 1.25vh, 0.75rem) !important;
  }
}


/* --- Operator Products Area matrix (GH#1959) ------------------ */
.op-products-area {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  overflow: hidden;
}

.op-products-area-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  flex-shrink: 0;
}

.op-products-title {
  color: var(--neu-text);
  font-size: 0.85rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  line-height: 1.1;
  text-transform: uppercase;
}

.op-products-subtitle {
  color: var(--neu-muted);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.2;
  margin-top: 0.1rem;
}

.op-products-state-hints {
  color: var(--neu-muted);
  display: grid;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.2;
  min-width: min(22rem, 45%);
  text-align: right;
}

.op-products-matrix-scroll {
  display: flex;
  flex: 1;
  height: 100%;
  min-height: 0;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 0.15rem;
}

.op-products-matrix {
  display: flex;
  flex: 1;
  flex-direction: column;
  height: 100%;
  min-width: calc(6.25rem + (var(--op-product-frequency-count, 4) * 7.25rem));
  min-height: 0;
}

.op-products-matrix-heading,
.op-product-row {
  display: grid;
  gap: 0.5rem;
  /* Narrow label column: big #N + wrapping name side-by-side, so the four
     frequency columns reclaim horizontal room (dense operator WebViews). */
  grid-template-columns: minmax(5.5rem, 0.42fr) repeat(var(--op-product-frequency-count, 4), minmax(7rem, 1fr));
}

.op-products-matrix-heading {
  margin-bottom: 0.5rem;
  /* Match op-products-matrix-grid's horizontal padding (added for shadow
     breathing room) so heading columns stay left-aligned with the row/button
     columns below instead of drifting left relative to them. */
  padding: 0 0.75rem 0 0.15rem;
}

/* Rows flex to fill the area but never shrink below a tablet-tappable height —
   with a dense catalog the grid scrolls vertically instead of crushing every
   row into an unreadable sliver (GH#1959 density finding at 1280x800 and the
   real RugKing ~1004x627 CSS viewport). The heading row lives outside this
   element, so it stays put while rows scroll. On genuinely spacious viewports
   (see the min-height: 900px override below) this floor is dropped instead,
   since there's room to shrink-to-fit without ever hitting it. */
.op-products-matrix-grid {
  display: grid;
  flex: 1;
  gap: 0.5rem;
  grid-auto-rows: minmax(6rem, 1fr);
  height: 100%;
  min-height: 0;
  overflow-y: auto;
  /* Breathing room so the edge row/column buttons' neu-extruded-sm shadow
     isn't clipped when this element (or its min-height:900px override below)
     switches to overflow: hidden — needs to be wide enough to contain the
     shadow's full blur radius, not just its offset. */
  padding: 0.75rem 0.75rem 0.75rem 0.15rem;
}
@media (min-width: 1600px) and (min-height: 900px) {
  .op-products-matrix-scroll {
    overflow: hidden;
  }

  .op-products-matrix {
    min-width: 0;
  }

  .op-products-matrix-heading,
  .op-product-row {
    grid-template-columns: minmax(0, 0.72fr) repeat(var(--op-product-frequency-count, 4), minmax(0, 1fr));
  }

  .op-products-matrix-grid {
    grid-auto-rows: minmax(0, 1fr);
    overflow: hidden;
  }
}

/* No overflow:hidden here — it would clip the neu-extruded-sm box-shadow that
   gives each product button its raised, neumorphic look. The button itself
   already clips its own internal text/content. */
.op-product-row {
  min-height: 0;
}

.op-products-heading {
  align-content: end;
  color: var(--neu-muted);
  display: grid;
  padding: 0.2rem 0.4rem;
}

/* "Wash package" is a single line (no hint span below it, unlike the
   frequency column headers), so bottom-anchoring it like its siblings makes
   it sit lower than their top line. Top-align it instead so it lines up with
   "A la carte" / "2x / mo" / etc. */
.op-products-heading--wash {
  align-content: start;
}

.op-products-heading strong {
  color: var(--neu-text);
  font-size: 0.95rem;
  font-weight: 900;
  line-height: 1.05;
}

.op-products-heading span {
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1.15;
  margin-top: 0.12rem;
}

.op-product-row-label {
  align-content: center;
  display: grid;
  gap: 0.15rem;
  min-height: 0;
  min-width: 0;
  overflow: visible;
  padding: 0.15rem 0.15rem 0.15rem 0;
}

/* Large #N left; name wraps beside it — no divider, no ellipsis. */
.op-product-row-title {
  align-items: flex-start;
  display: flex;
  gap: 0.25rem;
  min-width: 0;
}

.op-product-row-number {
  color: var(--neu-text);
  flex-shrink: 0;
  font-size: 1.5rem;
  font-weight: 900;
  line-height: 1;
}

.op-product-row-name {
  color: var(--neu-text);
  flex: 1 1 auto;
  font-size: 0.62rem;
  font-weight: 900;
  line-height: 1.15;
  min-width: 0;
  overflow: visible;
  overflow-wrap: anywhere;
  text-overflow: clip;
  white-space: normal;
  word-break: break-word;
}

.op-product-row-name--other {
  font-size: 1.1rem;
}

.op-product-row-detail {
  color: var(--neu-muted);
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
}

.op-product-cell {
  display: flex;
  min-height: 0;
  min-width: 0;
}

/* Product tiles begin with the price stack so operators always find the amount
   in the same top-left position, regardless of product type. */
.op-product-button {
  background: var(--neu-bg);
  border: 0;
  color: var(--neu-text);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  height: 100%;
  max-height: 100%;
  min-height: 0 !important;
  min-width: 0;
  overflow: hidden;
  padding: 0.6rem !important;
  text-align: left;
  width: 100%;
}

.op-product-button--single {
  background: color-mix(in srgb, #3b82f6 8%, var(--neu-bg));
}

.op-product-button--plan {
  background: color-mix(in srgb, #10b981 12%, var(--neu-bg));
}

.op-product-button--other {
  background: color-mix(in srgb, #d97706 9%, var(--neu-bg));
}

.op-current-plan-label {
  flex-shrink: 0;
  font-size: 0.6rem;
  font-weight: 900;
}

.op-product-button-top {
  align-items: flex-start;
  display: flex;
  gap: 0.35rem;
  justify-content: space-between;
  min-width: 0;
}

.op-product-sku {
  color: #d97706;
  font-size: 0.68rem !important;
  font-weight: 900 !important;
  line-height: 1 !important;
  max-width: 4.75rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.op-products-area .op-product-button>.op-product-button-top>.op-product-sku,
.op-products-area .op-product-button>.op-product-button-top>.op-product-frequency-tag {
  line-height: 1 !important;
  margin-top: 0 !important;
}

.op-products-area .op-product-button>.op-product-button-top>.op-product-sku {
  font-size: 0.68rem !important;
}

.op-product-button--plan .op-product-sku {
  color: #059669;
}

.op-product-frequency-tag {
  background: color-mix(in srgb, var(--neu-text) 8%, transparent);
  border-radius: 999px;
  color: var(--neu-muted);
  flex-shrink: 0;
  font-size: 0.62rem;
  font-weight: 900;
  line-height: 1;
  padding: 0.18rem 0.42rem;
  text-transform: uppercase;
  white-space: nowrap;
}

.op-products-area .op-product-button>.op-product-button-top>.op-product-frequency-tag {
  font-size: 0.62rem !important;
}

.op-product-button-name {
  color: var(--neu-text);
  font-size: 0.92rem;
  font-weight: 900;
  line-height: 1.08;
  min-height: 2rem;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.op-product-button--other .op-product-button-name {
  min-height: 0;
}

.op-product-button-bottom {
  align-items: flex-start;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 0.2rem;
  min-width: 0;
}

/* Compact landscape rules anchor a card's final div for legacy layouts. Product
   tiles always keep their shared price stack at the top-left instead. */
.op-products-area .op-product-button>.op-product-button-bottom {
  margin-top: 0 !important;
  padding-top: 0 !important;
}

.op-product-button .op-price-total {
  font-size: 1.45rem !important;
}

.op-products-area .op-product-button .op-price-total {
  font-size: 1.45rem !important;
}

.op-product-button .op-price-suffix {
  font-size: 0.62rem !important;
}

.op-products-area .op-product-button .op-price-suffix {
  font-size: 0.62rem !important;
}

.op-product-button .op-price-breakdown {
  font-size: 0.58rem !important;
}

.op-products-area .op-product-button .op-price-breakdown {
  font-size: 0.58rem !important;
  overflow: visible;
  white-space: normal;
}

.op-product-pill {
  border-radius: 0.45rem;
  flex-shrink: 0;
  font-size: 0.64rem;
  font-weight: 900;
  line-height: 1;
  padding: 0.25rem 0.38rem;
  white-space: nowrap;
}

.op-product-pill--commission,
.op-product-pill--favorite {
  background: rgba(245, 158, 11, 0.16);
  color: #d97706;
}

.op-product-pill--commission {
  align-self: flex-end;
}

.op-product-pill--favorite {
  background: rgba(5, 150, 105, 0.12);
  color: #059669;
}

.op-product-pill--muted {
  background: color-mix(in srgb, var(--neu-muted) 14%, transparent);
  color: var(--neu-muted);
}

.op-product-cell-empty {
  align-items: center;
  color: color-mix(in srgb, var(--neu-muted) 72%, transparent);
  display: flex;
  flex: 1;
  font-size: 0.72rem;
  font-weight: 700;
  height: 100%;
  justify-content: center;
  max-height: 100%;
  min-height: 0 !important;
}

.op-products-empty {
  grid-column: 1 / -1;
}

.op-products-empty .neu-alert {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.15), rgba(245, 158, 11, 0.05));
  color: #d97706;
}

@media (max-width: 1100px),
(max-height: 720px) {
  .op-products-area {
    gap: 0.25rem;
  }

  .op-products-area-header {
    align-items: center;
  }

  .op-products-title {
    font-size: 0.76rem;
  }

  .op-products-subtitle,
  .op-products-state-hints {
    font-size: 0.62rem;
  }

  .op-products-matrix {
    min-width: calc(5.5rem + (var(--op-product-frequency-count, 4) * 6.35rem));
  }

  .op-products-matrix-heading,
  .op-product-row {
    gap: 0.3rem;
    grid-template-columns: minmax(5rem, 0.38fr) repeat(var(--op-product-frequency-count, 4), minmax(6rem, 1fr));
  }

  .op-products-matrix-heading {
    margin-bottom: 0.25rem;
  }

  .op-products-heading {
    min-height: 0;
    padding: 0.1rem 0.3rem;
  }

  .op-products-heading strong {
    font-size: 0.78rem;
    line-height: 1;
  }

  .op-products-heading span {
    font-size: 0.55rem;
    letter-spacing: 0;
    line-height: 1;
    margin-top: 0;
  }

  .op-product-row-label {
    padding: 0.2rem 0.15rem 0.2rem 0 !important;
  }

  .op-product-button {
    padding: 0.36rem !important;
  }

  .op-product-button,
  .op-product-cell-empty {
    min-height: 0;
  }

  .op-product-row-name {
    font-size: 0.62rem !important;
  }

  .op-product-button-name {
    font-size: 0.82rem !important;
  }

  .op-product-button .op-price-total {
    font-size: 1.05rem !important;
  }

  .op-products-area .op-product-button .op-price-total {
    font-size: 1.05rem !important;
  }

  .op-product-button .op-price-breakdown {
    font-size: 0.52rem !important;
  }

  .op-products-area .op-product-button .op-price-breakdown {
    font-size: 0.52rem !important;
  }
}

/* ============================================================
   Operator Dashboard Redesign — April 2025
   ============================================================ */

/* --- Short landscape tablet (960–1366 x, orientation:landscape,
   height <=720px — RugKing 1004x627, Ulefone Armor Pad 4 Ultra 1177x706
   (the live Advance primary gate device), etc.). Consolidated from three
   duplicate @media blocks sharing this exact condition (td-core#2561) — the
   duplicates let later blocks silently clobber earlier ones on any shared
   selector, so an edit to the first block had no visible effect.
   Deliberately placed here (the position of the LAST of the three originals)
   rather than the first: two other @media blocks in between
   (~L8412 "Tablet landscape primary target" and its siblings) also set
   .op-main-grid for this same viewport range, and this block must keep
   winning that cascade the way the last-positioned original did.
   Threshold was 700px (a RugKing-era number — RugKing is 627 tall) until
   td-core#2676: the primary device is 706px, 6px past the old gate, so the
   compact treatment this whole block exists to provide never actually fired
   on the live register. Widened to 720px — covers the primary device with
   margin, RugKing (627) is unaffected either way. --- */
@media (min-width: 960px) and (max-width: 1366px) and (orientation: landscape) and (max-height: 720px) {

  .auth-shell {
    grid-template-columns: minmax(0, 1fr) minmax(320px, 360px) !important;
    height: 100vh;
    overflow: hidden;
  }

  @supports (height: 100dvh) {
    .auth-shell {
      height: 100dvh;
    }
  }

  .auth-hero-panel {
    display: block !important;
    grid-column: auto !important;
    height: 100% !important;
    min-width: 0;
  }

  .auth-form-panel {
    grid-column: auto !important;
    height: 100% !important;
    overflow: hidden !important;
  }

  .auth-form-content {
    min-height: 100%;
    padding: 1rem 1.25rem !important;
  }

  .auth-hero-card {
    max-width: 28rem;
    padding: 1.5rem !important;
  }

  .auth-hero-card .neu-avatar {
    width: 3rem;
    height: 3rem;
  }

  .auth-hero-card h1 {
    font-size: clamp(2rem, 5vw, 3.5rem) !important;
    line-height: 0.95;
    margin-top: 0.75rem !important;
  }

  .auth-hero-card p:last-child {
    font-size: 1rem !important;
    line-height: 1.45;
    margin-top: 0.75rem !important;
  }

  .auth-login-title {
    margin-top: 1.5rem !important;
    font-size: 1.125rem !important;
  }

  .auth-login-body {
    margin-top: 1.25rem !important;
  }

  .auth-login-body .neu-form-group {
    margin-bottom: 0.75rem !important;
  }

  .auth-login-body .neu-label {
    margin-bottom: 0.375rem !important;
    font-size: 0.8125rem;
  }

  .auth-login-body .neu-input {
    min-height: 2.75rem;
  }

  .auth-login-body .neu-btn {
    min-height: 2.75rem;
  }

  .auth-login-body .my-6 {
    margin-top: 1rem !important;
    margin-bottom: 1rem !important;
  }

  .op-main-grid {
    gap: 0.5rem;
    padding: 0.5rem;
  }

  .op-center {
    padding: 0.375rem;
  }

  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section {
    gap: 0.375rem;
  }

  .op-pkg-card {
    min-height: 3.75rem;
    padding: 0.5rem !important;
  }

  .op-assistant-bar {
    padding: 0.25rem 0.5rem;
    font-size: 0.6875rem;
  }

  .op-plate-chip {
    min-height: 3.25rem;
  }

  .op-packages-center button {
    padding: 0.25rem 0.375rem !important;
  }

  .op-packages-center button>.op-product-button-top>span.font-black {
    font-size: 0.625rem !important;
  }

  .op-packages-center button>.op-product-button-top>span:not(.font-black) {
    font-size: clamp(0.875rem, 3vh, 1.5rem) !important;
  }

  .op-packages-center button .op-price-total {
    font-size: clamp(0.875rem, 3vh, 1.5rem) !important;
  }

  .op-packages-center button .op-price-suffix {
    font-size: clamp(0.55rem, 1.5vh, 0.75rem) !important;
  }

  .op-packages-center button .op-price-breakdown {
    font-size: clamp(0.5rem, 1.1vh, 0.625rem) !important;
  }

  .op-products-area-header {
    display: none;
  }

  .op-products-matrix-heading {
    margin-bottom: 0;
  }

  .op-products-heading {
    min-height: 0;
    padding: 0 0.25rem;
  }

  .op-products-heading strong {
    font-size: 0.68rem;
    line-height: 1;
  }

  /* Hint lines ("Single wash", "Entry club", …) burn a second row of
     heading height on short operator WebViews — drop them so the matrix
     buttons reclaim the space (same density call as hiding row-detail). */
  .op-products-heading span {
    display: none;
  }

  .op-product-row-detail {
    display: none;
  }

  .op-product-row {
    gap: 0.25rem;
  }

  .op-product-row-label {
    gap: 0.12rem;
    padding: 0.1rem 0.1rem 0.1rem 0 !important;
  }

  .op-product-button {
    gap: 0.12rem;
    padding: 0.18rem 0.22rem !important;
  }

  .op-product-row-number {
    font-size: 1.25rem !important;
  }

  .op-product-sku,
  .op-product-frequency-tag,
  .op-product-pill {
    font-size: 0.52rem !important;
  }

  .op-products-area .op-product-button>.op-product-button-top>.op-product-sku,
  .op-products-area .op-product-button>.op-product-button-top>.op-product-frequency-tag,
  .op-products-area .op-product-pill {
    font-size: 0.52rem !important;
  }

  .op-product-row-name {
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    display: -webkit-box;
    font-size: 0.58rem !important;
    line-height: 1.12;
    overflow: hidden;
  }

  .op-product-button-name {
    font-size: 0.66rem !important;
    line-height: 1.02;
    min-height: 0;
  }

  .op-product-button-bottom {
    gap: 0.18rem;
  }

  .op-product-button .op-price-total {
    font-size: 1.05rem !important;
  }

  .op-products-area .op-product-button .op-price-total {
    font-size: 1.05rem !important;
  }

  .op-product-button .op-price-suffix {
    font-size: 0.5rem !important;
  }

  .op-products-area .op-product-button .op-price-suffix {
    font-size: 0.5rem !important;
  }

  /* Four wash packages plus Shop Items must be visible together on the
     1004x627 RugKing register.  A 3rem row keeps the 48px touch target while
     fitting all five rows; the previous 4rem floor required vertical scrolling
     and hid Shop Items below the fold.
     This rule used to be split across three duplicate @media blocks sharing
     this exact condition, so edits to the earlier two never took effect —
     consolidated here; gap/padding are the values from the most recently
     authored (and best-reasoned, per the note above) of the three. */
  .op-products-matrix-grid {
    gap: 0.2rem;
    grid-auto-rows: minmax(3rem, 1fr);
    padding: 0.25rem 0.25rem 0.25rem 0.1rem;
  }

  /* Keep button names and row labels within the compact two-line row budget. */
  .op-product-button-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    white-space: normal;
  }

  .op-product-row-name {
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    display: -webkit-box;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: normal;
  }

  /* Make/model text: reduce from 0.875rem to save vertical space in hero */
  .oph-machine {
    font-size: 0.75rem;
  }

  /* Make logo: 15px height instead of 20px to save vertical space in hero.
     !important needed — the base rule lives in a <style> tag in the layout
     which cascades after linked stylesheets at equal specificity. */
  .make-logo-inline {
    height: 15px !important;
    max-width: 60px !important;
  }

  /* Motorist profile / visit history: undo the tablet upscale at 627px height */
  .op-profile-pane {
    padding: 0.5rem !important;
  }

  .op-profile-name {
    font-size: 1.0rem !important;
  }

  .op-profile-stats {
    font-size: 0.8rem !important;
    line-height: 1.4 !important;
  }

  #customer-section .neu-heading-md {
    font-size: 1.1rem;
  }

  #customer-section table {
    font-size: 0.82rem;
  }

  #customer-section table th {
    font-size: 0.72rem !important;
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
  }

  #customer-section table td {
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
  }

  #customer-section table button {
    min-height: 1.75rem;
    padding: 0.2rem 0.5rem;
    font-size: 0.7rem;
  }

  /* Tighter hero band: reduce gap between columns and cap coach banner height
     so the product grid gains more vertical room for 5 rows. */
  .op-hero {
    gap: 0.3rem;
  }

  .op-hero__col--id,
  .op-hero__col--veh,
  .op-hero__col--mem,
  .op-hero__actions {
    max-height: 7rem;
  }

  .op-hero__coach {
    max-height: 1.4rem;
    overflow: hidden;
  }
}

/* gh#1624 — Fold viewports (<960px: ~850px inner & ~360px cover). The package
   card grid stays 4-column but its internals were only scaled inside the
   >=960px landscape blocks, so below that the raw inline #N/#Mx 2rem numbers and
   full price stacks collide ("the M numbers don't scale nicely"). Mirror the
   landscape compact treatment with fixed (non-vh) sizes that hold up in the
   fold's near-square portrait. */
@media (max-width: 959px) {
  .op-packages-center button {
    padding: 0.5rem !important;
    overflow: hidden;
  }

  /* #N / #Mx tile number — demote from a 2rem headline to a small index label. */
  .op-packages-center button>div:first-child>span.font-black {
    font-size: 0.75rem !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    flex-shrink: 0;
  }

  /* Package / membership name — clamp to 2 lines so it never overruns the tile. */
  .op-packages-center button>div:first-child>span:not(.font-black) {
    font-size: 0.75rem !important;
    line-height: 1.2 !important;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  /* Bottom row never shrinks — price stays anchored and legible. */
  .op-packages-center button>div:last-child {
    flex-shrink: 0 !important;
    margin-top: auto !important;
    gap: 0.25rem;
  }

  .op-packages-center button .op-price-total {
    font-size: 0.9375rem !important;
    line-height: 1 !important;
  }

  .op-packages-center button .op-price-suffix {
    font-size: 0.625rem !important;
  }

  .op-packages-center button .op-price-breakdown {
    font-size: 0.5625rem !important;
    line-height: 1.1 !important;
  }
}

/* Shared image clip container — matches the scan tab plate-crop-container pattern */
.op-img-clip {
  /* inline-block (not flex) so the inner <img> is a normal replaced element:
     its min-content width is the image's natural width, so the tile wraps the
     image 1:1 and the column can't be squeezed narrower than the image. */
  display: inline-block;
  vertical-align: middle;
  line-height: 0;
  overflow: hidden;
  border-radius: 0.5rem;
  border: 1px solid var(--neu-shadow-dark);
}

/* Sizing for tile images. Height-driven (fixed height, natural width) so the
   tile wraps the image 1:1 at its true aspect; `max-width: none` overrides the
   global `img { max-width: 100% }` reset so the column can't be squeezed
   narrower than the image (which would distort it) when Package absorbs the
   slack. The motorist-profile sub-table sets its own inline overrides (a
   shorter plate crop, object-fit) and those still win for that view. */
.op-img-clip img {
  height: 2rem;
  width: auto;
  display: block;
  max-width: none;
  cursor: pointer;
}

/* Static-camera framing (GH#1629). The wash-entrance ALPR camera is fixed and
   cars stop on the same line, so the target vehicle and its plate land in the
   same place in every frame. object-view-box crops the image to that region
   with zero image processing — the ALPR tile shows the car (not driveway/cones),
   and the plate view zooms the full-resolution frame to a legible plate. These
   two boxes are the only thing to tune if the camera or stop line moves.
   inset() order is top right bottom left. */
.op-view-car {
  object-view-box: inset(0% 2% 42% 56%);
}

.op-view-plate {
  object-view-box: inset(25% 14% 58% 66%);
}

/* Hide desktop-only hints on touch devices (tablets/phones) */
@media (pointer: coarse) {
  .hidden-on-touch {
    display: none !important;
  }
}

/* ============================================================
   HANDSET OPERATOR DASHBOARD — GH#1325 / tdc-flnwzz
   Adapts operator dashboard for ≤767px (phone) viewports:
   - Footer stats pinned to top (was bottom on tablet).
   - Confirm Visit CTA sticks above the bottom nav (thumb zone).
   - Camera tile hidden (no live video reaches phones).
   - Existing .op-mobile-nav repurposed for 5 primary + More.
   Spec: docs/plans/2026-05-19-handset-operator-dashboard.md
   ============================================================ */
:root {
  --op-app-bar-height: 2.75rem;
  --op-stats-strip-height: 2.5rem;
  --op-mobile-nav-height: 4.5rem;
  --op-confirm-sticky-height: 3.25rem;
}

@media (max-width: 767px) {

  /* Footer stats: pinned to top of viewport, employee block hidden.
     The pills already render in the DOM; we expose them and reflow as
     a horizontal scroll strip. Employee pill + online dot move to the
     "More" sheet, so we hide them here. */
  .op-footer {
    position: fixed !important;
    top: 0;
    left: 0;
    right: 0;
    z-index: 40;
    border-top: none !important;
    border-bottom: 1px solid var(--neu-border-subtle);
    box-shadow: 0 2px 8px var(--neu-shadow-dark) !important;
    min-height: var(--op-stats-strip-height) !important;
    padding: 0.25rem 0.5rem !important;
  }

  .op-footer [data-tour="footer-stats"] {
    display: flex !important;
    overflow-x: auto;
    flex-wrap: nowrap;
    width: 100%;
    -webkit-overflow-scrolling: touch;
    gap: 0.375rem !important;
  }

  .op-footer [data-tour="footer-stats"]>div {
    flex-shrink: 0;
  }

  /* Hide employee identity + system status block (moved to More sheet). */
  .op-footer>.flex.items-center.justify-between>.flex.items-center.gap-2.shrink-0 {
    display: none !important;
  }

  /* Make room at top of body for the fixed stats strip. */
  body.h-screen {
    padding-top: var(--op-stats-strip-height);
  }

  /* Sticky Confirm Visit CTA — anchored above the bottom nav so the
     thumb always knows where Confirm lives. The op-right container is
     hidden by existing rules for non-vehicle sections; on vehicle, the
     existing inline Confirm form stays inside op-right and a duplicate
     sticky CTA is rendered for handset only via .op-confirm-sticky. */
  .op-confirm-sticky {
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--op-mobile-nav-height);
    z-index: 31;
    padding: 0.5rem 0.75rem 0.375rem;
    background: var(--neu-bg);
    border-top: 1px solid var(--neu-border-subtle);
    box-shadow: 0 -4px 12px var(--neu-shadow-dark);
  }

  .op-confirm-sticky form,
  .op-confirm-sticky .confirm-row {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
  }

  .op-confirm-sticky button[type="submit"] {
    width: 100%;
    min-height: var(--op-confirm-sticky-height);
  }

  /* Mobile bottom nav: enforce explicit height so the sticky CTA above
     it has predictable clearance. */
  .op-mobile-nav {
    min-height: var(--op-mobile-nav-height);
  }

  .op-mobile-nav button {
    min-height: 2.75rem;
    flex: 1;
  }

  /* Reserve bottom padding inside the main grid so the last package row
     isn't covered by the sticky Confirm CTA + bottom nav. */
  .op-main-grid {
    padding-bottom: calc(var(--op-mobile-nav-height) + var(--op-confirm-sticky-height) + 0.5rem) !important;
  }

  /* Camera tile hidden on handset — no live video reaches phones. */
  .op-video-pane {
    display: none !important;
  }

  /* Cash and More sections behave like the existing single-pane sections
     on handset: op-right collapses so the section fills the grid. */
  .op-main-grid:has(#cash-section:not(.hidden)) .op-right,
  .op-main-grid:has(#more-section:not(.hidden)) .op-right {
    display: none !important;
  }

  .op-main-grid:has(#cash-section:not(.hidden)) .op-center,
  .op-main-grid:has(#more-section:not(.hidden)) .op-center {
    max-height: calc(100dvh - 10rem);
    overflow-y: auto !important;
  }

  /* Hide the sticky Confirm CTA on non-vehicle sections — Confirm only
     makes sense in the live-scan view. */
  .op-main-grid:not(:has(#vehicle-section:not(.hidden)))~.op-confirm-sticky,
  body:has(.op-main-grid #cash-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #more-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #sales-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #equipment-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #history-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #settings-section:not(.hidden)) .op-confirm-sticky,
  body:has(.op-main-grid #customer-section:not(.hidden)) .op-confirm-sticky {
    display: none !important;
  }
}

/* Above 767px, the sticky Confirm CTA must not render at all — the
   existing Confirm button inside op-right is the canonical location. */
@media (min-width: 768px) {
  .op-confirm-sticky {
    display: none !important;
  }
}

/* ===== PASSWORD METER ===== */

/* Turn checkmarks green when rules pass */
.group:has([data-pass-r1]) .password-rule-1 {
  color: rgb(34 197 94) !important;
  /* green-500 */
}

.group:has([data-pass-r2][data-pass-r3]) .password-rule-2 {
  color: rgb(34 197 94) !important;
}

.group:has([data-pass-r4][data-pass-r5]) .password-rule-3 {
  color: rgb(34 197 94) !important;
}

/* Show progress bars as password gets stronger */
.group:has([data-pass-p20]) .password-progress-1 {
  transform: scaleX(1);
}

.group:has([data-pass-p40]) .password-progress-2 {
  transform: scaleX(1);
}

.group:has([data-pass-p60]) .password-progress-3 {
  transform: scaleX(1);
}

.group:has([data-pass-p80]) .password-progress-4 {
  transform: scaleX(1);
}

.group:has([data-pass-p100]) .password-progress-5 {
  transform: scaleX(1);
}

/* ===== OWNER DASHBOARD TYPOGRAPHY ===== */
/* Scoped to .neu-dashboard-bg (the owner <body>) so the landing layout — which
   also loads this file and intentionally uses Plus Jakarta/DM Sans — is untouched.
   Body copy renders in Inter (var(--font-body)); headings/titles/KPI values use
   Plus Jakarta Sans (var(--font-display)) per the DS type scale. */
.neu-dashboard-bg,
.neu-dashboard-bg input,
.neu-dashboard-bg select,
.neu-dashboard-bg textarea,
.neu-dashboard-bg button {
  font-family: var(--font-body);
}

/* Override the hardcoded neu-* families within owner only. */
.neu-dashboard-bg .neu-heading,
.neu-dashboard-bg .neu-heading-xl,
.neu-dashboard-bg .neu-heading-md {
  font-family: var(--font-display);
}

.neu-dashboard-bg .neu-body {
  font-family: var(--font-body);
}

/* Semantic type roles — owner scope, sizes on the fluid tokens.
   Display font + DS letter-spacing on headings/titles/KPI values; tabular-nums
   on every numeric value class so digits don't jitter column widths. */
.neu-dashboard-bg .neu-page-title {
  font-family: var(--font-display);
  font-size: var(--fluid-2xl);
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: -0.03em;
}

.neu-dashboard-bg .neu-heading {
  font-family: var(--font-display);
  font-size: var(--fluid-xl);
  line-height: 1.25;
  font-weight: 700;
  letter-spacing: -0.025em;
}

/* .neu-card-title deliberately excluded from fluid sizing here — it's the
   standard header for every card/table/detail tile across the owner
   dashboard, and inflating it via --fluid-lg made every tile title
   inconsistent in size/weight with its neighbors. Keep it at the base
   1.125rem/700 rule (line ~3580) instead. */
.neu-dashboard-bg .neu-body {
  font-size: var(--fluid-base);
  line-height: 1.5;
  font-weight: 400;
}

.neu-dashboard-bg .neu-label {
  font-size: var(--fluid-sm);
  line-height: 1.4;
  font-weight: 500;
}

.neu-dashboard-bg .neu-caption {
  font-size: var(--fluid-xs);
  line-height: 1.4;
  font-weight: 400;
}

.neu-dashboard-bg .neu-stat-value {
  font-family: var(--font-display);
  font-size: var(--fluid-xl);
  line-height: 1.1;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.neu-dashboard-bg .neu-kpi-value {
  font-family: var(--font-display);
  font-size: var(--fluid-2xl);
  line-height: 1.1;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

/* Eyebrow treatment for every stat card label across the owner dashboard
   (Biz, Business Insights, Retention, Analytics, Help): the label recedes
   (small, uppercase, letter-spaced) so the number leads. */
.neu-dashboard-bg .neu-kpi-label {
  font-size: var(--fluid-xs);
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.neu-dashboard-bg .neu-kpi-card .neu-section-subtitle {
  font-size: var(--fluid-xs);
}

.neu-dashboard-bg .neu-section-title {
  font-weight: 700;
  letter-spacing: -0.02em;
}

.neu-dashboard-bg .neu-section-subtitle {
  font-weight: 400;
  line-height: 1.4;
}

/* Scoped to .neu-dashboard-bg deliberately — there is no unscoped .neu-eyebrow
   rule. Using this class anywhere without a .neu-dashboard-bg ancestor (e.g. a
   partial rendered outside layouts/operator_dashboard.html.erb, or a
   standalone/kiosk view) silently drops the styling: no error, no test
   failure, just an unstyled element. */
.neu-dashboard-bg .neu-eyebrow {
  font-size: var(--fluid-xs);
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Two-tier KPI hierarchy for pages with a headline row of business KPIs above
   supporting-metric rows (currently only owner/dashboards/_biz.html.erb).
   --hero deepens the card and keeps the base (larger) value size; --secondary
   shrinks the value for the supporting rows. */
.neu-kpi-card--hero {
  padding: calc(var(--fluid-unit) * 1.5) calc(var(--fluid-unit) * 1.75);
  box-shadow: 8px 8px 16px var(--neu-shadow-dark), -8px -8px 16px var(--neu-shadow-light);
}

.neu-kpi-card--hero:hover {
  box-shadow: 10px 10px 20px var(--neu-shadow-dark-strong), -10px -10px 20px var(--neu-shadow-light-strong);
}

.neu-dashboard-bg .neu-kpi-value.neu-kpi-value--secondary {
  font-size: var(--fluid-lg);
}

/* Revenue summary (owner/dashboards/biz/_revenue_summary.html.erb): recessed
   line-item panel inside a Dashboard::ChartCardComponent plus a separate raised net-revenue card. */
.neu-table-card--recessed {
  /* Vertical padding must clear the inherited 24px border-radius (.neu-table-card) —
     at 6px it left the table's flat, square-cornered top/bottom edge cutting
     into the rounded corner's curve, visible as a sharp notch interfering with
     the inset shadow right where CATEGORY/VOLUME/AMOUNT sits. 1.5rem (24px)
     matches the radius so the corner clears regardless of the horizontal inset. */
  padding: 1.5rem 1.375rem;
  box-shadow: inset calc(var(--shadow-offset) - 3px) calc(var(--shadow-offset) - 3px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 3px)) calc(-1 * (var(--shadow-offset) - 3px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

/* Row rhythm inside the recessed panel: cells run edge-to-edge (the panel's
   own padding provides the horizontal inset) with a lighter hairline between
   rows than the shared .neu-table default, and a slightly heavier one under
   the header — matches the design's two-tier border opacity. */
.neu-table-card--recessed .neu-table th,
.neu-table-card--recessed .neu-table td {
  padding-left: 0;
  padding-right: 0;
  padding-top: 0.8125rem;
  padding-bottom: 0.8125rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--neu-text);
  border-bottom-color: rgba(163, 177, 198, 0.18);
}

/* Column weight rhythm: category label 500, volume count 400, amount 600. */
.neu-table-card--recessed .neu-table td:nth-child(2) {
  font-weight: 400;
}

.neu-table-card--recessed .neu-table td:nth-child(3) {
  font-weight: 600;
}

/* Gross Revenue subtotal row reads slightly larger, in the display font — the
   one row in the table that steps up toward the KPI-card type scale. */
.neu-table-card--recessed .neu-table tr.neu-revenue-summary-emphasis-row td {
  font-weight: 700;
}

.neu-table-card--recessed .neu-table tr.neu-revenue-summary-emphasis-row td:nth-child(3) {
  font-family: var(--font-display);
  font-size: 0.9375rem;
}

/* Explicit color overrides, scoped and specific enough to beat both the base
   rule above and any Tailwind utility (Tailwind v4's @layer utilities lose to
   unlayered author CSS regardless of source order, so a bare `text-neu-muted`
   class silently loses here — these rules sidestep that entirely). Theme-aware
   vars, not literal hex — this table renders in both light and dark mode, and
   --color-error is a different, unrelated pink in this app's theme, not a red. */
.neu-table-card--recessed .neu-table td.neu-revenue-summary-muted {
  color: var(--neu-muted);
}

.neu-table-card--recessed .neu-table td.neu-revenue-summary-negative {
  color: var(--neu-error);
}

.neu-table-card--recessed .neu-table thead th {
  padding-top: 0.875rem;
  padding-bottom: 0.75rem;
  border-bottom-color: rgba(163, 177, 198, 0.3);
}

.neu-table-card--recessed .neu-table th:nth-child(2),
.neu-table-card--recessed .neu-table td:nth-child(2) {
  width: 140px;
}

.neu-table-card--recessed .neu-table th:nth-child(3),
.neu-table-card--recessed .neu-table td:nth-child(3) {
  width: 120px;
}

/* Scoped via :has() to only the 3 Biz cards that actually render a footer
   key list — .neu-chart-card is reused by ~15 other unrelated views
   (ai_coach, operator_agent, memberships, washify competition, etc.) where
   forcing flex-column would risk their own internal layout. This is what
   makes .neu-chart-keys' margin-top: auto below actually push the keys to
   the bottom of the card instead of just trailing the chart. */
.neu-chart-card:has(> .neu-chart-keys) {
  display: flex;
  flex-direction: column;
}

/* Chart footer keys — shared by cars-washed, revenue-donut, and avg-wash-
   ticket charts (owner/dashboards/_cars_washed_per_hour_chart.html.erb,
   _revenue_breakdown_chart.html.erb, _avg_wash_ticket_chart.html.erb).
   9px square-ish dot, 11.5px text, muted label / dark bold value / muted %
   — replaces the ad hoc .neu-label/.neu-muted reuse (a 13px form-field style)
   that doesn't match this at all. Theme-aware vars (this renders in dark mode
   too), so label and value share the two-tier --neu-muted/--neu-text system
   rather than the design source's literal three-tier fg-1/fg-2/fg-3 grays. */
.neu-chart-keys {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: auto;
  padding-top: 0.75rem;
}

.neu-chart-key-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.neu-chart-key-dot {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
}

.neu-chart-key-label {
  font-size: 0.71875rem;
  font-weight: 500;
  color: var(--neu-muted);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.neu-chart-key-value {
  font-size: 0.71875rem;
  font-weight: 600;
  color: var(--neu-text);
  font-variant-numeric: tabular-nums;
  flex: none;
}

.neu-chart-key-percent {
  font-size: 0.71875rem;
  font-weight: 400;
  color: var(--neu-muted);
  font-variant-numeric: tabular-nums;
  width: 34px;
  text-align: right;
  flex: none;
}

/* Nexus/DaisyUI vendor CSS forces `fill: var(--color-base-content) !important`
   on all ApexCharts datalabel text (nexus.css), which beats our SVG `fill`
   attribute on the donut's center total. Scoped override with matching
   !important + higher specificity to win regardless of vendor load order.
   Theme-aware vars — this donut renders in dark mode too. */
#revenue-donut-chart .apexcharts-datalabels-group .apexcharts-datalabel-label {
  fill: var(--neu-muted) !important;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

#revenue-donut-chart .apexcharts-datalabels-group .apexcharts-datalabel-value {
  fill: var(--neu-text) !important;
}

/* The JS stroke.colors config (revenue_donut_chart_controller.js) reads
   SOFT_UI_COLORS.background once at chart-init time — it does not re-render
   on theme toggle, so the slice-gap stroke goes stale (e.g. stuck on dark
   mode's --neu-bg hex after switching to light, showing as a dark ring).
   CSS custom properties recompute live on the data-theme toggle with no
   re-render needed, so overriding the stroke attribute here instead keeps
   it correct through every toggle, not just the theme active at first paint. */
#revenue-donut-chart .apexcharts-pie-area {
  stroke: var(--neu-bg) !important;
}

/* Same stale-JS-color issue as the donut chart above, for the membership-
   lifecycle Sankey's node labels: the D3 controller used to bake a
   SOFT_UI_COLORS.text read into an inline SVG style at chart-init, which
   froze at whichever theme was active on load and went stale (invisible)
   after a live theme toggle without a page reload. CSS custom properties
   recompute live on the toggle, so this replaces that one-time JS read. */
#membership-lifecycle-chart text {
  fill: var(--neu-text) !important;
}

/* Node name / count two-tier styling — matches .neu-chart-key-label /
   .neu-chart-key-value's muted-label + bold-value convention used by the
   other Biz charts' footer keys, instead of the "(123)" parenthetical this
   replaced (nothing else on the page wraps a number in parens). */
#membership-lifecycle-chart .sankey-node-label {
  fill: var(--neu-muted) !important;
  font-weight: 500;
}

#membership-lifecycle-chart .sankey-node-value {
  fill: var(--neu-text) !important;
  font-weight: 700;
}

.neu-net-revenue-card {
  border-radius: 1.25rem;
  padding: calc(var(--fluid-unit) * 1.25) calc(var(--fluid-unit) * 1.5);
  box-shadow: var(--shadow-offset) var(--shadow-offset) var(--shadow-blur) var(--neu-shadow-dark),
    calc(-1 * var(--shadow-offset)) calc(-1 * var(--shadow-offset)) var(--shadow-blur) var(--neu-shadow-light);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* Tailwind v3→v4 compat: text-right/text-left are not emitted by Tailwind v4
   (which prefers logical text-start/text-end). Shim them so existing ERB views
   that use text-right keep working without a full find-and-replace migration. */
.text-right {
  text-align: right !important;
}

.text-left {
  text-align: left !important;
}

/* Table cell guard: role classes must not exceed the cell baseline (0.875rem).
   Fluid-scaled roles are for cards and prose — not dense data columns. body-sm
   (1.5) for prose cells, label/caption (1.4) for the tighter roles, per scale. */
.neu-dashboard-bg .neu-table td.neu-body,
.neu-dashboard-bg .neu-table td .neu-body {
  font-size: 0.875rem;
  line-height: 1.5;
}

.neu-dashboard-bg .neu-table td.neu-label,
.neu-dashboard-bg .neu-table td .neu-label {
  font-size: 0.875rem;
  line-height: 1.4;
}

.neu-dashboard-bg .neu-table td.neu-caption,
.neu-dashboard-bg .neu-table td .neu-caption {
  font-size: 0.75rem;
  line-height: 1.4;
}

/* Card-on-file brand badge — a fixed-size white "mini card" holding the brand
   mark, rendered inline in the motorist-profile stats line. The box is one
   consistent card shape for every brand; each SVG is scaled to fit inside it
   (object-fit: contain) so Visa/Mastercard/Amex all sit in identical badges. */
.op-card-brand-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 2.05em;
  height: 1.35em;
  padding: 0.18em 0.28em;
  background: #ffffff;
  border-radius: 0.28em;
  margin-left: 0.15rem;
  vertical-align: -0.32em;
  box-shadow: 1px 1px 2.5px var(--neu-shadow-dark),
    -1px -1px 2.5px var(--neu-shadow-light);
}

.op-card-brand-badge img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ===== OPERATOR AI ASSISTANT CHAT BUBBLES =====
   agent_controller.js builds `.chat-message`/`.bubble` nodes at runtime for
   every reply after the first (hardcoded) greeting bubble. Those nodes had no
   CSS surface at all, so agent replies rendered as unstyled text — including
   `text-purple-*` utility classes meant for a dark bubble — directly on the
   modal's light neu-inset background. Unreadable. See GH #1940. */
.chat-message {
  display: flex;
  margin-bottom: 1rem;
}

.chat-message-user {
  justify-content: flex-end;
}

.chat-message-agent,
.chat-message-error {
  justify-content: flex-start;
}

.chat-message .bubble {
  max-width: 85%;
  padding: 0.75rem 1.25rem;
  border-radius: 1rem;
  line-height: 1.5;
}

.chat-message-user .bubble {
  background: var(--neu-accent);
  color: white;
}

.chat-message-agent .bubble {
  background: var(--neu-bg);
  color: var(--neu-text);
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.chat-message-error .bubble {
  background: rgba(220, 38, 38, 0.1);
  color: #dc2626;
  border: 1px solid rgba(220, 38, 38, 0.3);
}

/* Rendered Markdown inside an AI coach bubble.
   The coach answers with tables, bold and lists; Owner::AICoachHelper#coach_markdown
   turns that into real elements, and these give them chat-bubble proportions. All
   colors come from the neu- variables so a table themes with light/dark like
   everything else. A wide table scrolls inside its own bubble rather than
   stretching the conversation column. */

.bubble-markdown > :first-child { margin-top: 0; }
.bubble-markdown > :last-child { margin-bottom: 0; }

.bubble-markdown p { margin: 0 0 0.75rem; }

/* The TABLE is the scroll port, not the bubble. Scrolling the whole message took the
   row labels and the surrounding prose out of frame, leaving figures with no row
   identity. Overlay scrollbars mean a clipped table has no at-rest affordance either,
   so this asks for a persistent thin scrollbar: on a register tablet a truncated
   column is otherwise indistinguishable from the end of the data. */
.bubble-markdown table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 0.5rem 0 0.75rem;
  font-size: 0.9375rem;
}

/* Deliberately NOT scrollbar-width/scrollbar-color: where both are supported the
   standard properties win and Chrome falls back to an OVERLAY scrollbar, which paints
   nothing at rest. On a register tablet a clipped column then looks exactly like the
   end of the data. ::-webkit-scrollbar alone forces a persistent, classic scrollbar. */

.bubble-markdown table::-webkit-scrollbar { height: 0.5rem; }
.bubble-markdown table::-webkit-scrollbar-track { background: transparent; }

.bubble-markdown table::-webkit-scrollbar-thumb {
  background: var(--neu-shadow-dark);
  border-radius: 0.25rem;
}

/* No white-space: nowrap. Applying it to every cell made the table unshrinkable, which
   is what pushed it past the bubble and out of sight in the first place — and an
   overflowing table has no at-rest affordance, because Chrome's overlay scrollbars paint
   nothing until you already know to drag. Letting cells wrap means the table simply fits,
   which is a better answer than a scrollbar the owner never sees. Figures rarely wrap in
   practice: "$45,995.86" has no break opportunity. overflow-x below stays as the safety
   net for a table too wide even after wrapping. */
.bubble-markdown th,
.bubble-markdown td {
  padding: 0.375rem 0.75rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--neu-border-subtle);
}

.bubble-markdown th {
  font-weight: 600;
  border-bottom-width: 2px;
}

.bubble-markdown tbody tr:last-child th,
.bubble-markdown tbody tr:last-child td {
  border-bottom: none;
}

/* Tailwind's preflight sets list-style: none on ul/ol, so a numbered list from the
   coach arrives with no numbers at all — verified in Chrome, computed
   list-style-type was "none". Restated explicitly here. */
.bubble-markdown ul,
.bubble-markdown ol {
  margin: 0 0 0.75rem;
  padding-left: 1.5rem;
}

.bubble-markdown ul { list-style-type: disc; }
.bubble-markdown ol { list-style-type: decimal; }

.bubble-markdown li {
  margin-bottom: 0.25rem;
  display: list-item;
}

/* The app-wide <strong> is 500, which against a 400 body is invisible in a table of
   numbers — the whole point of the coach bolding a figure is that it stands out. */
.bubble-markdown strong { font-weight: 700; }

.bubble-markdown h1,
.bubble-markdown h2,
.bubble-markdown h3,
.bubble-markdown h4 {
  font-weight: 600;
  font-size: 1rem;
  margin: 0.75rem 0 0.375rem;
}

.bubble-markdown code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.875em;
  padding: 0.0625rem 0.25rem;
  border-radius: 0.25rem;
  background: var(--neu-shadow-dark);
}

.bubble-markdown pre {
  overflow-x: auto;
  padding: 0.625rem 0.75rem;
  border-radius: 0.5rem;
  background: var(--neu-shadow-dark);
  margin: 0 0 0.75rem;
}

.bubble-markdown pre code {
  padding: 0;
  background: none;
}

.bubble-markdown a {
  color: var(--neu-accent);
  text-decoration: underline;
}

.bubble-markdown blockquote {
  margin: 0 0 0.75rem;
  padding-left: 0.75rem;
  border-left: 3px solid var(--neu-border-subtle);
  opacity: 0.85;
}

/* Structured agent response (Script/Action/detail/follow-ups) built by
   agent_controller.js#buildResponseSection & friends. Colors live in CSS,
   not inline styles, so each page that mounts data-controller="agent" can
   supply its own palette — see the matching block in
   app/views/operator_agent/index.html.erb for the one page that doesn't
   load this stylesheet. */
.chat-response-heading {
  color: var(--neu-accent);
}

.chat-response-body {
  color: var(--neu-text);
}

.chat-response-detail {
  border-top: 1px solid var(--neu-shadow-dark);
}

.chat-response-detail-toggle {
  color: var(--neu-accent);
}

.chat-response-detail-toggle:hover {
  color: var(--neu-text);
}

.chat-response-detail-body {
  color: var(--neu-muted);
}

.chat-response-chip {
  background: var(--neu-shadow-dark);
  color: var(--neu-text);
}

.chat-response-chip:hover {
  background: var(--neu-shadow-dark-strong);
}


/* ============================================================
   GH#1959 reopened: OpDash must be usable as a cash register on
   the RugKing tablet. At tablet-landscape heights the hero was
   ~352px of a 627px viewport, leaving the products grid a 142px
   scrolling sliver. Compress the hero to a compact strip so the
   grid is the dominant surface; the grid (not the page) scrolls.
   ============================================================ */
/* Wide-laptop short-viewport regime (1680×~800 class). Tablet widths get the
   single-band redesign above instead — these caps clipped its plate/greeting
   (PR #2007 round-3). */
@media (min-width: 1367px) and (orientation: landscape) and (max-height: 900px) {
  .op-hero {
    gap: 0.3rem;
  }

  /* The vehicle/membership columns are the big spender.
     Cap them; inner clamp()-sized type keeps the plate readable. */
  .op-hero__col--veh,
  .op-hero__col--mem {
    max-height: 4.75rem;
    min-height: 0;
    overflow: hidden;
  }

  .oph-plate,
  .oph-alpr {
    max-height: 2.2rem;
  }

  /* Match the veh/mem cap: those columns already fill 4.75rem, so the grid row
     is that tall regardless — a tighter id cap saves no height and only clips
     the greeting, stats, and operator-instruction pills (e.g. "Payment method
     needed"), which must stay visible for the operator to act. */
  .op-hero__col--id {
    max-height: 4.75rem;
    overflow: hidden;
    gap: 0.15rem;
  }

  .op-hero__actions {
    flex-direction: row !important;
    gap: 0.3rem;
    max-height: 2rem;
  }

  .op-hero__coach {
    max-height: 1.7rem;
    overflow: hidden;
  }

  /* Hero card yields; the products grid takes the freed height. */
  .op-center:has(#vehicle-section:not(.hidden)) #vehicle-section>.op-card {
    flex: 0 1 auto;
    min-height: 0;
    overflow: hidden;
  }
}

/* A closed <dialog class="modal"> is still a fixed inset-0 element with laid-out
   children; without this, Chrome hit-tests those children and taps on dashboard
   controls underneath (e.g. the hero plate button) are swallowed by an invisible
   overlay. Surfaced by the RugKing plate-entry system test; applies to real
   operator taps too. */
dialog.modal:not([open]) {
  pointer-events: none;
}

/* ===== EYEBROW LABEL ===== */
/* Small uppercase section label — same treatment as .neu-table th, generalized
   for use outside tables (section headers, card kickers). */
.neu-eyebrow {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--neu-muted);
}

/* ===== CHOICE BUTTON (multi-select-style option buttons) ===== */
/* Used by option groups where exactly one button is picked — budget/goal/radius
   pickers in the Growth > Acquisition campaign wizard. */
/* Composes with the base .neu-btn (shadow/background/color/border/cursor/
   transition) — only overrides what a choice chip needs on top of that. */
.neu-choice-btn {
  padding: 1rem 1.625rem;
  border-radius: 1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.0625rem;
}

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

/* ===== WIZARD STEP CIRCLE ===== */
.neu-wizard-step-circle {
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8125rem;
  font-weight: 700;
  cursor: pointer;
  background-color: var(--neu-bg);
  color: var(--neu-muted);
  box-shadow: calc(var(--shadow-offset) - 4px) calc(var(--shadow-offset) - 4px) calc(var(--shadow-blur) - 6px) var(--neu-shadow-dark),
    calc(-1 * (var(--shadow-offset) - 4px)) calc(-1 * (var(--shadow-offset) - 4px)) calc(var(--shadow-blur) - 6px) var(--neu-shadow-light);
}

.neu-wizard-step-circle.done {
  color: var(--neu-accent);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

.neu-wizard-step-circle.current {
  background-color: var(--neu-accent);
  color: white;
  box-shadow: none;
}

/* Manual numeric entry paired with preset choice chips (campaign budget / radius). */
.neu-manual-input {
  width: 10.5rem;
  box-sizing: border-box;
  padding: 1rem 1.25rem;
  border-radius: 1rem;
  border: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--neu-text);
  background-color: var(--neu-bg);
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light);
}

/* Native number-input spinner arrows are unstyled OS chrome — every other
   control in this wizard (choice chips, buttons) is neumorphic, so the
   spinner reads as a foreign, non-neumorphic element sitting inside an
   otherwise-styled field. Hide it; +/- isn't needed when typing a budget or
   radius directly. */
.neu-manual-input::-webkit-inner-spin-button,
.neu-manual-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.neu-manual-input[type="number"] {
  -moz-appearance: textfield;
}

.neu-manual-input:focus-visible {
  outline: none;
  box-shadow: inset calc(var(--shadow-offset) - 6px) calc(var(--shadow-offset) - 6px) calc(var(--shadow-blur) - 10px) var(--neu-shadow-dark),
    inset calc(-1 * (var(--shadow-offset) - 6px)) calc(-1 * (var(--shadow-offset) - 6px)) calc(var(--shadow-blur) - 10px) var(--neu-shadow-light),
    0 0 0 3px var(--neu-focus-ring);
}

/* Marks figures that are illustrative because their real source is not wired up
   yet. Deliberately distinct from a status badge: this is a statement about the
   DATA, not about the business. */
.neu-sample-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.125rem 0.5rem;
  border-radius: 0.375rem;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--neu-muted);
  background-color: transparent;
  border: 1px dashed var(--neu-border-subtle);
}

.neu-sample-value {
  opacity: 0.55;
}

/* ---------------------------------------------------------------------------
   Plan-change summary (operator checkout modal)

   The operator reads this aloud to a customer standing at the counter, so the
   two things they say first — the new plan and what is charged right now — are
   the two largest things on screen. Prices are stated tax-inclusive with the
   subtotal + tax spelled out beneath, matching the wash tiles and the emailed
   receipt; quoting a bare subtotal here made one plan look like two prices.
   Generous line spacing is deliberate: this block is read at arm's length on a
   glare-heavy tablet, not scanned on a desk monitor.
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   Plan-change summary — read at a counter on a short-viewport Android tablet,
   so height is the scarce resource and every rule below is paying for itself.

   ONE type size throughout the money column. Hierarchy is carried by WEIGHT and
   COLOUR, never by size: a receipt where each row is a different size reads as
   a ransom note, and mixed sizes across a single row (small label, large figure)
   break the horizontal rhythm the eye follows from name to amount.
--------------------------------------------------------------------------- */
.op-plan-change-panel {
  padding: 1rem 1.25rem;
  border-radius: 0.875rem;
  background: rgba(16, 185, 129, 0.06);
}

/* Both sides carry equal weight — one is not more important than the other,
   the arrow already says which way this is going. */
.op-plan-change-transition {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
  gap: 0.75rem;
}

.op-plan-change-side { min-width: 0; }

.op-plan-change-eyebrow {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--neu-muted);
  margin-bottom: 0.125rem;
}

.op-plan-change-plan {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--neu-text);
}

/* Inline with the name, lighter so the package still reads first. */
.op-plan-change-amount {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--neu-muted);
  white-space: nowrap;
}

/* Centred against the two plan names, not baseline-aligned to the eyebrows
   above them — baseline alignment left it floating beside "NEW PLAN". */
.op-plan-change-arrow {
  align-self: center;
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--neu-muted);
  line-height: 1;
}

/* Both comparisons, one centred row, one weight and one colour — they are a
   single sentence answering the same question from two directions. */
.op-plan-change-savings {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.25rem 0.5rem;
  margin-top: 0.625rem;
  padding: 0.4375rem 0.75rem;
  border-radius: 0.5rem;
  background: rgba(16, 185, 129, 0.12);
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: var(--neu-success-solid);
}

/* An upgrade costs MORE per month. Money-back green on that figure is a claim
   we cannot make, so the whole row goes neutral rather than mixing colours. */
.op-plan-change-savings[data-direction="increase"] {
  background: rgba(120, 120, 120, 0.12);
  color: var(--neu-text);
}

.op-plan-change-vs-plan,
.op-plan-change-vs-retail { color: inherit; }

.op-plan-change-dot { opacity: 0.45; }

.op-plan-change-vs-plan:empty,
.op-plan-change-vs-retail:empty,
/* The separator is meaningless with only one clause either side of it. */
.op-plan-change-vs-plan:empty + .op-plan-change-dot,
.op-plan-change-vs-retail:empty ~ .op-plan-change-dot { display: none; }

/* Reassurances sit with the plan change, above the rule — inside the money
   column they read as another line item. */
.op-plan-change-assurances {
  margin-top: 0.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.125rem 1rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--neu-success, #10B981);
}

.op-plan-change-rule {
  border: 0;
  border-top: 1px solid var(--neu-border-subtle);
  margin: 0.625rem 0 0.4375rem;
}

/* The money column. Uniform size; tabular figures so the decimal points line up
   down the right edge the way they do on a printed slip. */
.op-plan-change-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--neu-text);
  padding: 0.0625rem 0;
}

.op-plan-change-line-figures {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Same size as its label — a figure that outgrows its own row is what made this
   block read as inconsistent. */
.op-plan-change-line-figures strong {
  font-size: inherit;
  font-weight: inherit;
}

/* Supporting working: recede, do not shrink. */
.op-plan-change-line--detail { color: var(--neu-muted); }

.op-plan-change-line--credit,
.op-plan-change-line--detail.op-plan-change-line--credit { color: var(--neu-success, #10B981); }

/* The figure everything above adds up to: the only bold in the column. */
.op-plan-change-line--total {
  font-weight: 800;
  padding-top: 0.1875rem;
}

.op-plan-change-line--total .op-plan-change-line-figures strong { font-weight: 800; }


/* Ad-preview map pin (Growth > Acquisition, wizard step 5).
   The pulse marks the wash's position on the mocked Maps card. Purely
   decorative — the place card below it carries every word — so it is
   aria-hidden in the markup and stopped entirely under reduced motion,
   matching the rest of this file's animation policy. */
.neu-map-pulse {
  animation: neu-map-pulse 2.4s cubic-bezier(0, 0, 0.2, 1) infinite;
}

@keyframes neu-map-pulse {
  0%   { transform: scale(0.55); opacity: 0.9; }
  70%  { transform: scale(1);    opacity: 0.05; }
  100% { transform: scale(1);    opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .neu-map-pulse { animation: none; opacity: 0.35; }
}

/* ===== SIGN-IN LINK WAITING INDICATOR =====
   A ball bouncing inside a counter-rotating diamond, shown under "Waiting for
   you to open it...". The motion is the point: that screen can sit for minutes
   while someone walks to their phone, and a static line of text gives no sign
   the page is still working rather than wedged.

   Adapted from the "bouncing" set at https://css-loaders.com/bouncing/
   (Temani Afif, MIT). Changes from the original: brand palette — Tux Orange
   ball on a muted frame rather than red/purple — 48px instead of 60px to sit
   under a line of body text, and a prefers-reduced-motion branch. */
.neu-waiting-loader {
  height: 48px;
  aspect-ratio: 1;
  position: relative;
  /* Own the surrounding space here rather than via a Tailwind utility: the
     rotating frame sweeps ~7px past the element box, and a utility class added
     after the last css:build silently computes to 0. */
  margin: 0.25rem auto 2.75rem;
  border: 3px solid #0000;
  animation: neu-waiting-spin 3s linear infinite;
}

.neu-waiting-loader::before {
  content: "";
  position: absolute;
  inset: auto 35% 0;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--neu-accent, #F0880F);
  animation: neu-waiting-bounce 0.5s cubic-bezier(0, 500, 1, 500) infinite;
}

.neu-waiting-loader::after {
  content: "";
  position: absolute;
  --b: 4px;
  inset: calc(-1 * var(--b)) auto calc(-1 * var(--b)) 50%;
  aspect-ratio: 1 / cos(30deg);
  translate: -50% 0;
  clip-path:
    polygon(0 50%, 50% -50%, 100% 50%, 50% 150%, 0 50%,
    var(--b) 50%,
    calc(25% + var(--b) * cos(60deg)) calc(100% - var(--b) * sin(60deg)),
    calc(75% - var(--b) * cos(60deg)) calc(100% - var(--b) * sin(60deg)),
    calc(100% - var(--b)) 50%,
    calc(75% - var(--b) * cos(60deg)) calc(var(--b) * sin(60deg)),
    calc(25% + var(--b) * cos(60deg)) calc(var(--b) * sin(60deg)),
    var(--b) 50%);
  background: var(--neu-muted, #6B7280);
  animation: inherit;
  animation-direction: reverse;
}

@keyframes neu-waiting-bounce {
  0%, 2% { bottom: 0%; }
  98%, to { bottom: 0.1%; }
}

@keyframes neu-waiting-spin {
  to { rotate: 1turn; }
}

/* Someone who has asked for less motion still needs to see that the page is
   waiting, so hold the shape and drop the animation rather than hiding it. */
@media (prefers-reduced-motion: reduce) {
  .neu-waiting-loader,
  .neu-waiting-loader::before,
  .neu-waiting-loader::after {
    animation: none;
  }

  .neu-waiting-loader::before {
    bottom: 0;
  }
}
