/*
 * Adaptive Minimal -- the business/admin dashboard's own theme layer,
 * loaded *after* static/css/material.css in templates/base.html (the
 * dashboard shell only -- never templates/storefront/base.html, which
 * has its own, entirely independent theming system driven by
 * storefront.context_processors.store_theme; see DashboardTheme's model
 * docstring in businesses/models.py for why the two are deliberately
 * separate).
 *
 * Strategy: material.css already built almost every dashboard component
 * (navbar, card, btn, form-control, dropdown-menu, table, badge, the
 * sidebar) on top of a small set of its own CSS custom properties
 * (--store-primary/--store-accent/--store-font, --md-surface,
 * --md-surface-variant, --md-on-surface, --md-on-surface-variant,
 * --md-outline, --md-radius-*, --md-elevation-*). Rather than
 * re-declaring every one of those component selectors, this file mostly
 * just overrides the *values* those variables resolve to -- redirecting
 * the whole existing component set from material.css's fixed Material
 * palette onto this system's neutral/brand tokens. A handful of
 * Bootstrap's own theme variables (semantic colors, links, dropdown)
 * are bridged the same way so status badges/alerts/links pick up the
 * new palette with zero per-template changes. Anything material.css
 * hardcoded outside a variable (the page background, alert/btn-variant
 * colors) is overridden explicitly below instead.
 *
 * Business-configurable values (businesses.DashboardTheme, fields:
 * primary_color/secondary_color/radius/density/font/default_mode) are
 * injected by templates/base.html as an inline <style> block placed
 * *after* this file's <link>, overriding --dash-primary/--dash-secondary
 * /--dash-font at :root and setting [data-theme]/[data-radius]
 * /[data-density] on <html> -- the same "static file default, inline
 * per-tenant override" split templates/storefront/base.html already
 * uses for store_theme.
 */

:root {
  /* ---- Adaptive Minimal primitives (light, the default) ---- */
  --dash-bg: #f7f8fa;
  --dash-surface: #ffffff;
  --dash-surface-subtle: #f3f4f6;
  --dash-surface-hover: #eef0f3;
  --dash-border: #e5e7eb;
  --dash-border-strong: #d1d5db;
  --dash-text: #111827;
  --dash-text-muted: #6b7280;
  --dash-text-faint: #9ca3af;

  --dash-shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
  --dash-shadow-sm: 0 2px 8px rgba(16, 24, 40, 0.06);
  --dash-shadow-md: 0 8px 24px rgba(16, 24, 40, 0.1);

  /* Brand tokens -- overridden per-business by templates/base.html's
     inline block; these are the platform fallback only. */
  --dash-primary: #4f46e5;
  --dash-secondary: #0ea5e9;
  --dash-on-primary: #ffffff;
  --dash-on-secondary: #ffffff;
  --dash-font: -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;

  /* Auto-generated shades/states from the brand color -- computed at
     paint time via color-mix(), not baked into the database, so the
     hover/active/subtle-background states always stay in sync with
     whatever --dash-primary/--dash-secondary actually resolve to. */
  --dash-primary-hover: color-mix(in srgb, var(--dash-primary) 88%, black);
  --dash-primary-active: color-mix(in srgb, var(--dash-primary) 76%, black);
  --dash-primary-subtle: color-mix(in srgb, var(--dash-primary) 10%, var(--dash-surface));
  --dash-primary-subtle-strong: color-mix(in srgb, var(--dash-primary) 18%, var(--dash-surface));
  --dash-primary-ring: color-mix(in srgb, var(--dash-primary) 25%, transparent);
  --dash-secondary-hover: color-mix(in srgb, var(--dash-secondary) 88%, black);
  --dash-secondary-active: color-mix(in srgb, var(--dash-secondary) 76%, black);
  --dash-secondary-subtle: color-mix(in srgb, var(--dash-secondary) 10%, var(--dash-surface));

  /* Semantic colors -- fixed platform tokens, deliberately independent
     of whatever brand color a business picks (see DashboardTheme's
     docstring): a "Paid"/"Low stock" badge must always read as
     green/amber, never tinted by --dash-primary. */
  --dash-success: #16a34a;
  --dash-success-rgb: 22, 163, 74;
  --dash-success-subtle: color-mix(in srgb, var(--dash-success) 12%, var(--dash-surface));
  --dash-warning: #d97706;
  --dash-warning-rgb: 217, 118, 6;
  --dash-warning-subtle: color-mix(in srgb, var(--dash-warning) 14%, var(--dash-surface));
  --dash-danger: #dc2626;
  --dash-danger-rgb: 220, 38, 38;
  --dash-danger-subtle: color-mix(in srgb, var(--dash-danger) 12%, var(--dash-surface));
  --dash-info: #2563eb;
  --dash-info-rgb: 37, 99, 235;
  --dash-info-subtle: color-mix(in srgb, var(--dash-info) 12%, var(--dash-surface));
  --dash-neutral: #6b7280;
  --dash-neutral-rgb: 107, 114, 128;
  --dash-neutral-subtle: color-mix(in srgb, var(--dash-neutral) 12%, var(--dash-surface));

  /* A fifth, deliberately *not*-brand-tinted semantic tone for "closed/
     final" states that read as more definitive than the plain neutral
     gray above (Product.ARCHIVED, Employee.TERMINATED) -- a dark slate
     rather than another shade of the same gray, so "archived" doesn't
     look like just a duller "pending". */
  --dash-dark: #334155;
  --dash-dark-rgb: 51, 65, 85;
  --dash-dark-subtle: color-mix(in srgb, var(--dash-dark) 12%, var(--dash-surface));

  /* ---- Bridge into material.css's existing tokens (see file header) ---- */
  --store-primary: var(--dash-primary);
  --store-accent: var(--dash-secondary);
  --store-font: var(--dash-font);
  --md-surface: var(--dash-surface);
  --md-surface-variant: var(--dash-surface-subtle);
  --md-on-surface: var(--dash-text);
  --md-on-surface-variant: var(--dash-text-muted);
  --md-outline: var(--dash-border);
  --md-elevation-1: var(--dash-shadow-xs);
  --md-elevation-2: var(--dash-shadow-sm);

  /* ---- Bridge into Bootstrap's own theme variables ---- */
  --bs-body-bg: var(--dash-bg);
  --bs-body-color: var(--dash-text);
  --bs-border-color: var(--dash-border);
  --bs-primary: var(--dash-primary);
  --bs-link-color: var(--dash-primary);
  --bs-link-hover-color: var(--dash-primary-hover);
  --bs-success: var(--dash-success);
  --bs-success-rgb: var(--dash-success-rgb);
  --bs-warning: var(--dash-warning);
  --bs-warning-rgb: var(--dash-warning-rgb);
  --bs-danger: var(--dash-danger);
  --bs-danger-rgb: var(--dash-danger-rgb);
  --bs-info: var(--dash-info);
  --bs-info-rgb: var(--dash-info-rgb);
  --bs-secondary: var(--dash-neutral);
  --bs-secondary-rgb: var(--dash-neutral-rgb);
  --bs-dropdown-bg: var(--dash-surface);
  --bs-dropdown-link-hover-bg: var(--dash-surface-subtle);
  --bs-dropdown-link-active-bg: var(--dash-primary-subtle-strong);
}

/* --bs-primary-rgb needs a real R,G,B triple, not a hex string -- but
   the actual R,G,B values only exist once --dash-primary is resolved
   from the business's own hex color (set inline by base.html), which
   plain CSS can't split into channels. rgba(var(--bs-primary-rgb), a)
   usages are rare in this codebase's own component CSS (mostly
   material.css's own color-mix()-based rules, already bridged above),
   so this is left as a graceful no-op rather than a broken value --
   any component that *does* need the primary color at a given opacity
   should use color-mix(in srgb, var(--dash-primary) N%, transparent)
   instead, the same pattern material.css's own focus-ring rule uses. */

/* ============================================================
 * Dark mode -- toggled via [data-theme="dark"] on <html>
 * (templates/base.html's pre-paint script; see its own comment for
 * why light/dark is resolved before first paint, not after).
 * ============================================================ */
:root[data-theme="dark"] {
  --dash-bg: #0b0d12;
  --dash-surface: #12151c;
  --dash-surface-subtle: #191d27;
  --dash-surface-hover: #202533;
  --dash-border: #262b36;
  --dash-border-strong: #333a48;
  --dash-text: #f3f4f6;
  --dash-text-muted: #9aa3b2;
  --dash-text-faint: #6b7280;

  --dash-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
  --dash-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.45);
  --dash-shadow-md: 0 10px 28px rgba(0, 0, 0, 0.55);

  /* Hover/active states mix toward white, not black, once the surface
     itself is dark -- darkening an already-dark-relative brand color
     further would crush it toward black and lose the hue. */
  --dash-primary-hover: color-mix(in srgb, var(--dash-primary) 85%, white);
  --dash-primary-active: color-mix(in srgb, var(--dash-primary) 70%, white);
  --dash-secondary-hover: color-mix(in srgb, var(--dash-secondary) 85%, white);
  --dash-secondary-active: color-mix(in srgb, var(--dash-secondary) 70%, white);

  /* Slightly brighter semantic tones for legibility against a dark
     surface -- still fixed, still independent of the brand color. */
  --dash-success: #22c55e;
  --dash-success-rgb: 34, 197, 94;
  --dash-warning: #f59e0b;
  --dash-warning-rgb: 245, 158, 11;
  --dash-danger: #f87171;
  --dash-danger-rgb: 248, 113, 113;
  --dash-info: #60a5fa;
  --dash-info-rgb: 96, 165, 250;
  --dash-neutral: #9ca3af;
  --dash-neutral-rgb: 156, 163, 175;
  --dash-dark: #cbd5e1;
  --dash-dark-rgb: 203, 213, 225;
}

/* ============================================================
 * Corner radius -- a business picks a named level, not raw px (see
 * DashboardTheme.Radius), matching this project's "curated tokens,
 * never free-form CSS" convention. Badges/avatars stay a true pill at
 * every level -- a status tag reads as a pill regardless of how
 * rounded the rest of the UI is.
 * ============================================================ */
:root,
:root[data-radius="soft"] {
  --dash-radius-sm: 6px;
  --dash-radius-md: 8px;
  --dash-radius-lg: 12px;
}

:root[data-radius="sharp"] {
  --dash-radius-sm: 3px;
  --dash-radius-md: 4px;
  --dash-radius-lg: 6px;
}

:root[data-radius="round"] {
  --dash-radius-sm: 10px;
  --dash-radius-md: 14px;
  --dash-radius-lg: 18px;
}

:root {
  --dash-radius-pill: 999px;
}

/* Reused as-is by every material.css selector that already reads
   --md-radius variables (see file header) -- --md-radius-pill
   is repurposed here as this system's *button/nav-link* radius, not a
   literal pill shape: Adaptive Minimal buttons are soft rounded
   rectangles. Renaming the variable would mean touching every selector
   in material.css that consumes it; overriding its value is equivalent
   and zero-risk. */
:root {
  --md-radius-sm: var(--dash-radius-sm);
  --md-radius-md: var(--dash-radius-md);
  --md-radius-pill: var(--dash-radius-md);
}

/* ============================================================
 * Density -- comfortable (default) vs compact, via [data-density] on
 * <html>. Consumed by the component rules further down.
 * ============================================================ */
:root,
:root[data-density="comfortable"] {
  --dash-space-1: 4px;
  --dash-space-2: 8px;
  --dash-space-3: 12px;
  --dash-space-4: 16px;
  --dash-space-5: 24px;
  --dash-table-cell-py: 0.85rem;
  --dash-table-cell-px: 1rem;
  --dash-control-py: 0.5rem;
  --dash-control-px: 0.9rem;
  --dash-sidebar-link-py: 0.55rem;
}

:root[data-density="compact"] {
  --dash-space-1: 2px;
  --dash-space-2: 6px;
  --dash-space-3: 8px;
  --dash-space-4: 12px;
  --dash-space-5: 16px;
  --dash-table-cell-py: 0.5rem;
  --dash-table-cell-px: 0.75rem;
  --dash-control-py: 0.35rem;
  --dash-control-px: 0.7rem;
  --dash-sidebar-link-py: 0.4rem;
}

/* ============================================================
 * Base surface + typography.
 * ============================================================ */
body {
  background-color: var(--dash-bg);
  font-family: var(--dash-font);
  font-size: 0.9375rem;
  -webkit-font-smoothing: antialiased;
}

.nav-link {
  color: var(--dash-text-muted);
}

.nav-link:hover,
.nav-link:focus {
  color: var(--dash-text);
}

/* ============================================================
 * Buttons -- soft rounded rectangles, not pills; accessible on-color
 * text computed server-side per business (see
 * businesses.context_processors.accessible_on_color).
 * ============================================================ */
.btn {
  padding-block: var(--dash-control-py);
  padding-inline: var(--dash-control-px);
  font-size: 0.875rem;
}

.btn-sm {
  padding-block: calc(var(--dash-control-py) * 0.6);
  padding-inline: calc(var(--dash-control-px) * 0.75);
}

.btn-primary {
  --bs-btn-color: var(--dash-on-primary);
  --bs-btn-hover-color: var(--dash-on-primary);
  --bs-btn-active-color: var(--dash-on-primary);
  --bs-btn-focus-shadow-rgb: 0, 0, 0;
  box-shadow: none;
}

.btn-outline-primary:hover,
.btn-outline-primary:active {
  color: var(--dash-on-primary) !important;
}

.btn-secondary {
  --bs-btn-color: var(--dash-on-secondary);
  --bs-btn-hover-color: var(--dash-on-secondary);
  --bs-btn-active-color: var(--dash-on-secondary);
}

.btn-outline-secondary {
  --bs-btn-color: var(--dash-text-muted);
  --bs-btn-border-color: var(--dash-border-strong);
  --bs-btn-hover-color: var(--dash-text);
  --bs-btn-hover-bg: var(--dash-surface-subtle);
  --bs-btn-hover-border-color: var(--dash-border-strong);
  --bs-btn-active-color: var(--dash-text);
  --bs-btn-active-bg: var(--dash-surface-hover);
  --bs-btn-active-border-color: var(--dash-border-strong);
}

/* Fixed-color variants (destructive/success confirm actions) --
   Bootstrap bakes these as literal hex at build time, not variables,
   so they need an explicit override to join the rest of the palette. */
.btn-danger {
  --bs-btn-bg: var(--dash-danger);
  --bs-btn-border-color: var(--dash-danger);
  --bs-btn-hover-bg: color-mix(in srgb, var(--dash-danger) 88%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--dash-danger) 88%, black);
  --bs-btn-active-bg: color-mix(in srgb, var(--dash-danger) 76%, black);
  --bs-btn-active-border-color: color-mix(in srgb, var(--dash-danger) 76%, black);
}

.btn-success {
  --bs-btn-bg: var(--dash-success);
  --bs-btn-border-color: var(--dash-success);
  --bs-btn-hover-bg: color-mix(in srgb, var(--dash-success) 88%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--dash-success) 88%, black);
  --bs-btn-active-bg: color-mix(in srgb, var(--dash-success) 76%, black);
  --bs-btn-active-border-color: color-mix(in srgb, var(--dash-success) 76%, black);
}

/* ============================================================
 * Cards, dropdowns, alerts, tables, badges.
 * ============================================================ */
.card {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
}

.card:hover {
  box-shadow: var(--dash-shadow-xs);
}

.dropdown-menu {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
}

.dropdown-item {
  color: var(--dash-text);
}

.dropdown-item.active,
.dropdown-item:active {
  color: var(--dash-on-primary);
}

.alert-success {
  --bs-alert-color: var(--dash-success);
  --bs-alert-bg: var(--dash-success-subtle);
  --bs-alert-border-color: color-mix(in srgb, var(--dash-success) 30%, var(--dash-surface));
}

.alert-warning {
  --bs-alert-color: var(--dash-warning);
  --bs-alert-bg: var(--dash-warning-subtle);
  --bs-alert-border-color: color-mix(in srgb, var(--dash-warning) 30%, var(--dash-surface));
}

.alert-danger {
  --bs-alert-color: var(--dash-danger);
  --bs-alert-bg: var(--dash-danger-subtle);
  --bs-alert-border-color: color-mix(in srgb, var(--dash-danger) 30%, var(--dash-surface));
}

.alert-info {
  --bs-alert-color: var(--dash-info);
  --bs-alert-bg: var(--dash-info-subtle);
  --bs-alert-border-color: color-mix(in srgb, var(--dash-info) 30%, var(--dash-surface));
}

/* Global feedback uses a fixed toast stack so a successful sign-in or form
 * save does not push the destination page downward. These colors inherit the
 * same dashboard tokens in both light and dark mode. */
.app-toast-stack {
  display: grid;
  gap: 10px;
  max-width: min(390px, calc(100vw - 32px));
  right: 20px;
  top: 88px;
  width: 100%;
  z-index: 1090;
}

.app-toast {
  --app-toast-accent: var(--dash-info);
  background: color-mix(in srgb, var(--dash-surface) 96%, var(--app-toast-accent));
  border: 1px solid color-mix(in srgb, var(--app-toast-accent) 24%, var(--dash-border));
  border-left: 3px solid var(--app-toast-accent);
  border-radius: var(--dash-radius-md);
  box-shadow: 0 16px 38px rgba(15, 23, 18, 0.16);
  color: var(--dash-text);
  overflow: hidden;
  width: 100%;
}

.app-toast--success { --app-toast-accent: var(--dash-success); }
.app-toast--warning { --app-toast-accent: var(--dash-warning); }
.app-toast--danger,
.app-toast--error { --app-toast-accent: var(--dash-danger); }
.app-toast--info { --app-toast-accent: var(--dash-info); }

.app-toast__content {
  align-items: center;
  display: grid;
  gap: 10px;
  grid-template-columns: auto minmax(0, 1fr) auto;
  min-height: 60px;
  padding: 8px 10px 8px 15px;
}

.app-toast__icon { color: var(--app-toast-accent); display: inline-flex; }
.app-toast .toast-body { font-size: 0.8125rem; font-weight: 590; line-height: 1.45; padding: 10px 0; }
.app-toast__close { filter: none; margin: 0; opacity: 0.55; padding: 9px; }
:root[data-theme="dark"] .app-toast__close { filter: invert(1) grayscale(100%); }

@media (max-width: 600px) {
  .app-toast-stack { left: 16px; right: 16px; top: 76px; width: auto; }
}

.table {
  --bs-table-bg: transparent;
  color: var(--dash-text);
}

.table > thead {
  border-bottom: 1px solid var(--dash-border);
}

.table > thead > tr > th {
  padding-block: var(--dash-table-cell-py);
  padding-inline: var(--dash-table-cell-px);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dash-text-muted);
  border-bottom-width: 1px;
}

.table > tbody > tr > td {
  padding-block: var(--dash-table-cell-py);
  padding-inline: var(--dash-table-cell-px);
  border-bottom-color: var(--dash-border);
}

.table-hover > tbody > tr:hover > * {
  background-color: var(--dash-surface-subtle);
}

.badge {
  font-weight: 600;
  font-size: 0.7rem;
  letter-spacing: 0.01em;
  padding: 0.32em 0.6em;
}

/* Status badges (components/status_badge.html + the handful of
 * inline `badge bg-*` spans) come through as plain Bootstrap
 * `.bg-success`/`.bg-warning`/etc utility classes -- solid, saturated
 * fills with white text. Bootstrap bakes several of those as literal
 * hex/rgb rather than reading a variable (same issue as the
 * .btn-danger/.btn-success overrides above), so the fix is the same:
 * an explicit override per color. The look itself is deliberately
 * different from Bootstrap's default too -- a soft tinted background
 * with colored text and a matching hairline border reads as a status
 * *tag*, not an alert; it sits quietly in a table row instead of
 * shouting a solid block of color at every row. */
.badge.bg-primary {
  background-color: var(--dash-primary-subtle) !important;
  color: var(--dash-primary-active) !important;
  border: 1px solid color-mix(in srgb, var(--dash-primary) 28%, transparent);
}

.badge.bg-secondary {
  background-color: var(--dash-neutral-subtle) !important;
  color: var(--dash-text-muted) !important;
  border: 1px solid var(--dash-border-strong);
}

.badge.bg-success {
  background-color: var(--dash-success-subtle) !important;
  color: var(--dash-success) !important;
  border: 1px solid color-mix(in srgb, var(--dash-success) 28%, transparent);
}

.badge.bg-warning {
  background-color: var(--dash-warning-subtle) !important;
  color: var(--dash-warning) !important;
  border: 1px solid color-mix(in srgb, var(--dash-warning) 28%, transparent);
}

.badge.bg-danger {
  background-color: var(--dash-danger-subtle) !important;
  color: var(--dash-danger) !important;
  border: 1px solid color-mix(in srgb, var(--dash-danger) 28%, transparent);
}

.badge.bg-info {
  background-color: var(--dash-info-subtle) !important;
  color: var(--dash-info) !important;
  border: 1px solid color-mix(in srgb, var(--dash-info) 28%, transparent);
}

.badge.bg-dark {
  background-color: var(--dash-dark-subtle) !important;
  color: var(--dash-dark) !important;
  border: 1px solid color-mix(in srgb, var(--dash-dark) 30%, transparent);
}

/* ============================================================
 * Forms.
 * ============================================================ */
.form-control,
.form-select {
  background-color: var(--dash-surface);
  color: var(--dash-text);
}

.form-control::placeholder {
  color: var(--dash-text-faint);
}

.form-control:focus,
.form-select:focus {
  box-shadow: 0 0 0 3px var(--dash-primary-ring);
}

.form-label {
  font-weight: 500;
  font-size: 0.875rem;
  color: var(--dash-text);
}

.form-text,
.text-muted {
  color: var(--dash-text-muted) !important;
}

/* The <select> arrow is a fixed SVG Bootstrap bakes at build time with
 * a literal #343a40 stroke, not a variable -- invisible-in-practice
 * (contrast ~1.4:1) once the surface behind it goes dark. Same fix as
 * .btn-danger/.btn-success/the badge colors above: an explicit
 * override, one SVG per mode since a CSS custom property can't be
 * interpolated into a background-image data URI. */
.form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

:root[data-theme="dark"] .form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239aa3b2' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* Checkboxes/radios -- previously untouched, so every checkbox/radio
 * in the app (store profile amenities, the inventory wizard's
 * tracked-stock toggle, allauth's "remember me") was plain stock
 * Bootstrap blue, the one un-tokenized primary-blue survivor in an
 * otherwise indigo/neutral UI. */
.form-check-input {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border-strong);
}

.form-check-input:checked {
  background-color: var(--dash-primary);
  border-color: var(--dash-primary);
}

.form-check-input:focus {
  border-color: var(--dash-primary);
  box-shadow: 0 0 0 3px var(--dash-primary-ring);
}

/* No separate radio-dot override needed: Bootstrap draws both the
 * checkbox's checkmark and the radio's dot as a plain white glyph
 * inside `background-color`, so the `:checked` rule above already
 * covers both input types. */
.form-check-label {
  color: var(--dash-text);
}

/* Keyboard focus -- project.css/material.css already give .btn,
 * .form-control and the sidebar links a branded :focus-visible ring;
 * this covers the dashboard-only clickable rows/cards that pattern
 * doesn't reach (a whole card-width row, or a link that's just text --
 * exactly where a plain browser outline is easiest to lose against a
 * dark, borderless background). */
.dash-list-row:focus-visible,
.dash-quick-link:focus-visible,
.dash-card-header__action:focus-visible,
.dash-stat-tile:focus-visible,
.page-link:focus-visible {
  outline: 2px solid var(--dash-primary);
  outline-offset: 2px;
}

/* ============================================================
 * Top bar + sidebar.
 * ============================================================ */
.navbar {
  border-bottom: 1px solid var(--dash-border);
}

.dashboard-sidebar {
  background-color: var(--dash-surface);
}

/* ============================================================
 * Premium sidebar pass -- deepens material.css's already-decent pill
 * nav rather than replacing it: smoother hover motion, a firmer active
 * state (bolder label + icon tinted to match, not just a background
 * tint), calmer section rhythm, and a thin custom scrollbar so a long
 * link list never shows the browser's default chrome scrollbar next to
 * an otherwise borderless sidebar.
 * ============================================================ */
.dashboard-sidebar {
  scrollbar-width: thin;
  scrollbar-color: var(--dash-border-strong) transparent;
}

.dashboard-sidebar::-webkit-scrollbar {
  width: 6px;
}

.dashboard-sidebar::-webkit-scrollbar-thumb {
  background-color: var(--dash-border-strong);
  border-radius: var(--dash-radius-pill);
}

.dashboard-sidebar__section {
  margin-bottom: var(--dash-space-2);
}

.dashboard-sidebar__heading {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.07em;
}

.dashboard-sidebar__link {
  padding-block: var(--dash-sidebar-link-py);
  font-size: 0.875rem;
  gap: 0.7rem;
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.dashboard-sidebar__link svg {
  opacity: 0.72;
  transition: opacity 0.15s ease;
}

.dashboard-sidebar__link:hover {
  transform: translateX(2px);
}

.dashboard-sidebar__link:hover svg {
  opacity: 0.9;
}

.dashboard-sidebar__link.active {
  font-weight: 600;
}

.dashboard-sidebar__link.active svg {
  opacity: 1;
}

.dashboard-main {
  padding: var(--dash-space-5) var(--dash-space-5) calc(var(--dash-space-5) * 2);
}

/* ============================================================
 * Shared list-view component system (see components/page_header.html,
 * components/toolbar.html, components/stat_tile.html) -- applied
 * consistently across products/inventory/orders/payments, per the
 * design-system-refresh request.
 * ============================================================ */
.dash-page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-5);
}

.dash-page-header__title {
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--dash-text);
  margin: 0;
}

.dash-page-header__subtitle {
  color: var(--dash-text-muted);
  font-size: 0.875rem;
  line-height: 1.5;
  margin: 0.25rem 0 0;
}

.dash-page-header__actions {
  display: flex;
  gap: var(--dash-space-2);
  flex-wrap: wrap;
}

/* Three deliberate weights, not one card repeated everywhere -- see
 * dashboard_home.html for the reference mix (recent orders --elevated,
 * low stock left at the plain default, shortcuts/homepage-request
 * --flat). Picking a weight is a per-template editorial call about how
 * much attention that module earns on its page, not a mechanical rule;
 * a page with only one card just uses the plain default.
 *
 * .dash-card (default) -- the workhorse: hairline border + a whisper
 * of shadow. Correct for most content modules.
 */
.dash-card {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  box-shadow: var(--dash-shadow-xs);
}

/* .dash-card--flat -- recedes into the page instead of sitting on top
 * of it: no shadow, no border, filled with the subtle surface tone.
 * For secondary/incidental modules (a settings side-panel, a list of
 * navigation shortcuts) that shouldn't visually compete with the
 * page's actual content. */
.dash-card--flat {
  background-color: var(--dash-surface-subtle);
  border: 1px solid transparent;
  box-shadow: none;
}

/* .dash-card--elevated -- more shadow plus a brand-colored top edge,
 * reserved for the single most important module on a page (a
 * dashboard's primary content card, never more than one per page --
 * spending emphasis everywhere spends it nowhere). */
.dash-card--elevated {
  position: relative;
  box-shadow: var(--dash-shadow-md);
  border-color: var(--dash-border-strong);
  /* No border-top color here -- a plain border can't take a gradient,
     and border-image paints *all four* sides from the same source, so
     the ::before strip below is what actually draws it, confined to
     the top edge only. A two-color gradient, not a flat --dash-primary
     line, because this (and .dash-brand-icon above) is one of only two
     places in the whole dashboard chrome that render the business's
     *pair* of brand colors together -- a business with a logo uploaded
     never sees .dash-brand-icon's own gradient (the image covers it),
     so this is the one guaranteed-visible surface for --dash-secondary
     regardless of whether a logo is set. */
}

.dash-card--elevated::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: 2px;
  border-radius: var(--dash-radius-lg) var(--dash-radius-lg) 0 0;
  background-image: linear-gradient(90deg, var(--dash-primary), var(--dash-secondary));
}

.dash-card > .card-body {
  padding: var(--dash-space-5);
}

@media (max-width: 575.98px) {
  .dash-card > .card-body {
    padding: var(--dash-space-4);
  }
}

.dash-table-card {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  box-shadow: var(--dash-shadow-xs);
  overflow: hidden;
}

.dash-table-card .table {
  margin-bottom: 0;
}

.dash-table-card .table > :not(caption) > * > * {
  background-color: transparent;
}

.dash-toolbar {
  display: flex;
  align-items: center;
  gap: var(--dash-space-2);
  flex-wrap: wrap;
  padding: var(--dash-space-3) var(--dash-space-4);
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  margin-bottom: var(--dash-space-4);
}

.dash-toolbar .form-control,
.dash-toolbar .form-select {
  border-color: var(--dash-border);
}

.dash-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-4);
}

.dash-stat-tile {
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  padding: var(--dash-space-4);
  color: inherit;
  text-decoration: none;
}

.dash-stat-tile__label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dash-text-muted);
  margin: 0 0 var(--dash-space-1);
}

.dash-stat-tile__value {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--dash-text);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
 * Quick-link tiles (businesses/dashboard_home.html) -- a grid of
 * clickable cards instead of a flat button wall (see §7's
 * "dashboard button-wall redundancy" open question in the
 * architecture doc; this redesign round finally resolves it).
 * ============================================================ */
.dash-quick-links {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-5);
}

.dash-quick-link {
  display: flex;
  align-items: center;
  gap: var(--dash-space-3);
  padding: var(--dash-space-4);
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  color: var(--dash-text);
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.dash-quick-link:hover {
  color: var(--dash-text);
  border-color: var(--dash-border-strong);
  box-shadow: var(--dash-shadow-xs);
}

.dash-quick-link__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: 0 0 auto;
  border-radius: var(--dash-radius-md);
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
}

.dash-quick-link__label {
  font-size: 0.875rem;
  font-weight: 500;
}

/* ============================================================
 * Light/dark toggle control (templates/base.html navbar).
 * ============================================================ */
.dash-mode-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--dash-radius-md);
  border: 1px solid var(--dash-border);
  background-color: var(--dash-surface);
  color: var(--dash-text-muted);
}

.dash-mode-toggle:hover {
  background-color: var(--dash-surface-subtle);
  color: var(--dash-text);
}

.dash-mode-toggle__icon {
  display: inline-flex;
}

.dash-mode-toggle__icon--moon {
  display: none;
}

:root[data-theme="dark"] .dash-mode-toggle__icon--sun {
  display: none;
}

:root[data-theme="dark"] .dash-mode-toggle__icon--moon {
  display: inline-flex;
}

/* ============================================================
 * Top navbar polish -- brand icon, icon-led nav links, business
 * switcher caret, avatar badge (templates/base.html). Pure visual
 * layer on top of Bootstrap's navbar; no markup this file doesn't
 * already assume changed underneath it.
 * ============================================================ */
.dash-navbar {
  /* Bootstrap 5.3's navbar theming is CSS-variable-based (--bs-navbar-*),
     scoped per .navbar -- overriding them here (rather than only the
     handful of selectors .navbar-light/.bg-light paint) is what actually
     routes the top bar through Adaptive Minimal's own palette. Without
     this, .bg-light's hardcoded light-gray background and .navbar-light's
     fixed rgba(0,0,0,*) text stayed on screen even in dark mode -- a
     light bar sitting on a dark page. */
  --bs-navbar-color: var(--dash-text-muted);
  --bs-navbar-hover-color: var(--dash-text);
  --bs-navbar-disabled-color: var(--dash-text-faint);
  --bs-navbar-active-color: var(--dash-primary);
  --bs-navbar-brand-color: var(--dash-text);
  --bs-navbar-brand-hover-color: var(--dash-text);
  --bs-navbar-toggler-border-color: var(--dash-border);
  background-color: var(--dash-surface) !important;
  padding-block: 0.75rem;
}

.dropdown-item.active, .dropdown-item:active {
    color: #305138 !important;
    text-decoration: none;
    background-color: #eaf1eb;
}

.dash-header {
  position: relative;
  z-index: 1040;
}

.dash-navbar > .container-fluid {
  gap: 1rem;
  padding-inline: clamp(1rem, 2.5vw, 2rem);
}

.dash-navbar .navbar-brand {
  margin-right: 1.5rem;
  min-width: 0;
}

.dash-navbar .navbar-collapse {
  min-width: 0;
}

.dash-navbar-primary {
  margin-right: auto;
}

.dash-navbar-actions {
  margin-left: auto;
}

.dash-theme-item { order: 2; }
.dash-user-item { order: 3; }

.dash-navbar .nav-link[type="button"] {
  background: transparent;
  border: 0;
}

.dash-navbar-cta {
  font-size: 0.82rem;
  margin-left: 0.25rem;
  padding: 0.48rem 0.9rem;
}

.dash-navbar .navbar-toggler-icon {
  filter: var(--dash-navbar-toggler-filter, none);
}

:root[data-theme="dark"] .dash-navbar .navbar-toggler-icon {
  --dash-navbar-toggler-filter: invert(1);
}

.dash-navbar-nav {
  gap: 0.35rem;
  align-items: center;
}

.dash-navbar-nav .nav-item {
  display: flex;
  align-items: center;
}

.dash-brand-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--dash-radius-md);
  /* Both brand colors together, not just primary -- a business picks
     two colors in Appearance settings, but secondary_color previously
     had no real surface anywhere in the dashboard chrome (it only fed
     that settings page's own preview mockup, and --bs-secondary/
     --store-accent, which nothing here actually renders with). This is
     the one piece of chrome on every single page, so it's the natural,
     always-visible home for "both colors, together" rather than
     inventing a one-off swatch just to prove the picker does something. */
  background-image: linear-gradient(135deg, var(--dash-primary), var(--dash-secondary));
  color: var(--dash-on-primary);
  flex: 0 0 auto;
  /* Also doubles as the one-letter monogram fallback (a business with
     no logo uploaded) -- the platform-mark icon and the monogram
     character need the same sizing here, just different content. */
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1;
}

.dash-brand-icon--logo {
  background-image: none;
  background-color: var(--dash-surface);
  object-fit: contain;
  padding: 0.2rem;
  border: 1px solid var(--dash-border);
}

.dash-navbar-nav .nav-link {
  font-size: 0.9rem;
  font-weight: 500;
  padding-inline: 0.65rem;
}

.dash-navbar-nav .nav-link svg {
  flex-shrink: 0;
  opacity: 0.85;
}

/* Business switcher: swap Bootstrap's default border-triangle caret for
   the same line-icon set the rest of the app uses -- {% icon
   "chevron-down" %} rendered explicitly in the template, so the default
   ::after caret is switched off here rather than doubled up. */
.dash-navbar-dropdown-toggle::after {
  display: none;
}

.dash-navbar-caret {
  opacity: 0.6;
}

/* Notification bell: same deal -- a clean bell + badge, no extra caret
   next to it (see templates/components/notification_bell.html). */
#notificationBellToggle::after {
  display: none;
}

.dash-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  margin-inline: 0.15rem;
  border-radius: var(--dash-radius-pill);
  background-color: var(--dash-primary-subtle-strong);
  color: var(--dash-primary);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  flex: 0 0 auto;
}

.dash-mode-toggle {
  text-decoration: none;
}

/* User menu dropdown (avatar + My Profile/Sign Out) -- the identity
   header row at the top of the menu. */
.dash-navbar-usermenu__identity {
  padding-top: 0.5rem;
}

.dash-navbar-usermenu__name {
  font-weight: 600;
  color: var(--dash-text);
  font-size: 0.875rem;
}

.dash-navbar-usermenu__email {
  font-size: 0.75rem;
}

@media (max-width: 767.98px) {
  .dash-navbar > .container-fluid {
    gap: 0.5rem;
  }

  .dash-navbar .navbar-brand {
    margin-right: 0;
  }

  .dash-navbar .navbar-collapse {
    border-top: 1px solid var(--dash-border);
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    width: 100%;
  }

  .dash-navbar-nav,
  .dash-navbar-actions {
    align-items: stretch;
    gap: 0.25rem;
  }

  .dash-navbar-actions {
    align-items: center;
    flex-direction: row;
    flex-wrap: wrap;
  }

  .dash-navbar .nav-item,
  .dash-navbar .nav-link,
  .dash-navbar .dash-navbar-dropdown-toggle {
    width: 100%;
  }

  .dash-navbar-actions > .nav-item,
  .dash-navbar-actions > .nav-item .nav-link,
  .dash-navbar-actions > .nav-item .dash-navbar-dropdown-toggle {
    width: auto;
  }

  .dash-navbar-actions > .dash-business-item,
  .dash-navbar-actions > .dash-business-item .dash-navbar-dropdown-toggle {
    width: 100%;
  }

  .dash-navbar .nav-link,
  .dash-navbar .dash-navbar-dropdown-toggle {
    justify-content: flex-start;
    padding: 0.65rem 0.5rem;
  }

  .dash-navbar-cta {
    display: block;
    margin: 0.35rem 0;
    text-align: center;
  }

  .dash-theme-item {
    align-items: flex-start !important;
  }
}

/* ============================================================
 * Settings pages -- shared header, tabs, sections, color-row inputs
 * and the storefront live-preview mock, used by
 * templates/businesses/theme_settings.html and
 * templates/businesses/appearance_settings.html (see
 * templates/businesses/partials/theme_page_header.html and the two
 * *_settings_panel.html partials). Built entirely on the token set
 * above, so it inherits per-business radius/density/dark-mode for
 * free -- nothing here hardcodes a color or a px radius.
 * ============================================================ */
.dash-page-header__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  border-radius: var(--dash-radius-md);
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
}

.dash-page-header__heading {
  display: flex;
  align-items: center;
  gap: var(--dash-space-3);
}

.dash-tabs {
  display: flex;
  gap: var(--dash-space-5);
  border-bottom: 1px solid var(--dash-border);
  margin-bottom: var(--dash-space-5);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.dash-tabs__link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.75rem 0.1rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--dash-text-muted);
  text-decoration: none;
}

.dash-tabs__link:hover {
  color: var(--dash-text);
}

.dash-tabs__link.active {
  color: var(--dash-text);
  border-bottom-color: var(--dash-primary);
}

.dash-settings-section {
  padding-block: var(--dash-space-5);
}

.dash-settings-section + .dash-settings-section {
  border-top: 1px solid var(--dash-border);
}

.dash-settings-section__header {
  display: flex;
  align-items: flex-start;
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-4);
}

.dash-settings-section__title {
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--dash-text);
  margin: 0;
}

.dash-settings-section__desc {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--dash-text-muted);
  margin: 0.25rem 0 0;
}

.dash-field-label {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--dash-text);
  margin-bottom: var(--dash-space-2);
  margin-top: 0;
}

.dash-field-label__info {
  color: var(--dash-text-faint);
  display: inline-flex;
  cursor: help;
}

/* Logo card -- thumbnail + filename + status + change button, replacing
   the bare <input type=file>. The real file input is kept in the DOM
   (see the panel templates) so the form still submits/validates exactly
   as BusinessLogoForm already expects; this is a styled label wrapping
   it, not a second source of truth. */
.dash-logo-card {
  display: flex;
  align-items: center;
  gap: var(--dash-space-4);
  padding: var(--dash-space-3) var(--dash-space-4);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  background-color: var(--dash-surface-subtle);
}

.dash-logo-card__thumb {
  width: 3.25rem;
  height: 3.25rem;
  flex: 0 0 auto;
  border-radius: var(--dash-radius-md);
  border: 1px solid var(--dash-border);
  background-color: var(--dash-surface);
  object-fit: contain;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--dash-text-faint);
}

.dash-logo-card__thumb img {
  width: 100%;
  height: 100%;
  border-radius: calc(var(--dash-radius-md) - 1px);
  object-fit: contain;
}

.dash-logo-card__meta {
  min-width: 0;
  flex: 1 1 auto;
}

.dash-logo-card__name {
  display: block;
  max-width: 100%;
  margin-bottom: 0.2rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--dash-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-logo-card__hint {
  font-size: 0.75rem;
  color: var(--dash-text-muted);
}

.dash-badge-soft-success {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.55rem;
  border-radius: var(--dash-radius-pill);
  background-color: var(--dash-success-subtle);
  color: var(--dash-success);
  font-size: 0.7rem;
  font-weight: 600;
}

.dash-logo-card__meta .dash-badge-soft-success {
  margin-top: 0.4rem;
}

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

/* Color row: swatch (the real, form-submitted <input type=color>) +
   hex text field + reset button, all three bound to the same Alpine
   value so typing a hex updates the swatch and vice-versa (see
   theme_settings_panel.html / appearance_settings_panel.html). */
.dash-color-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--dash-space-4);
  padding-block: var(--dash-space-3);
  border-bottom: 1px solid var(--dash-border);
  transition: background-color 0.15s ease;
  padding: 10px;
}

.dash-settings-section__header + .dash-color-row {
  padding-top: 0;
}

.dash-color-row:last-of-type {
  padding-bottom: 0;
  border-bottom: none;
}

.dash-color-row:hover {
  background-color: var(--dash-surface-subtle);
}

.dash-color-row__label {
  font-size: 0.875rem;
  color: var(--dash-text);
  flex: 1 1 auto;
}

.dash-color-row__controls {
  display: flex;
  align-items: center;
  gap: var(--dash-space-3);
  flex: 0 0 auto;
  width: min(100%, 270px);
}

.dash-color-swatch {
  -webkit-appearance: none;
  appearance: none;
  width: 2.1rem;
  height: 2.1rem;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-sm);
  background: none;
  cursor: pointer;
}

.dash-color-swatch::-webkit-color-swatch-wrapper {
  padding: 2px;
}

.dash-color-swatch::-webkit-color-swatch {
  border: none;
  border-radius: calc(var(--dash-radius-sm) - 2px);
}

.dash-color-swatch::-moz-color-swatch {
  border: none;
  border-radius: calc(var(--dash-radius-sm) - 2px);
}

.dash-color-hex {
  flex: 1 1 auto;
  min-width: 0;
  height: 2.1rem;
  font-size: 0.8125rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  text-transform: uppercase;
  padding-block: 0.35rem;
}

.dash-color-reset {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  flex: 0 0 auto;
  border-radius: var(--dash-radius-sm);
  border: 1px solid var(--dash-border);
  background: none;
  color: var(--dash-text-faint);
}

.dash-color-reset:hover {
  color: var(--dash-text);
  background-color: var(--dash-surface-hover);
  border-color: var(--dash-border);
}

/* Desktop/Mobile live-preview toggle. */
.dash-preview-toggle {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  background-color: var(--dash-surface-subtle);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-md);
}

.dash-preview-toggle__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.8rem;
  border: none;
  border-radius: calc(var(--dash-radius-md) - 2px);
  background: none;
  color: var(--dash-text-muted);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.dash-preview-toggle__btn.active {
  background-color: var(--dash-surface);
  color: var(--dash-text);
  box-shadow: var(--dash-shadow-xs);
}

/* Storefront live-preview mock -- an illustrative, non-navigable replica
   of the real storefront chrome (see storefront/base.html for the real
   thing), built from the same theme.* Alpine values the color/font
   inputs already mirror, so it never drifts from what the form actually
   holds. Deliberately mocked with CSS shapes rather than a real image
   asset -- this is a preview of layout + color + type, not a live
   product photo. */
.dash-store-preview {
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  overflow: hidden;
  transition: max-width 0.2s ease;
}

.dash-store-preview--mobile {
  max-width: 320px;
  margin-inline: auto;
}

.dash-store-preview__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--dash-space-3);
  padding: 0.7rem 1rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.dash-store-preview__nav-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.95rem;
  min-width: 0;
}

.dash-store-preview__nav-logo {
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--dash-radius-sm);
  object-fit: contain;
  flex: 0 0 auto;
}

.dash-store-preview__nav-links {
  display: flex;
  gap: 0.85rem;
  font-size: 0.75rem;
  font-weight: 500;
  opacity: 0.8;
}

.dash-store-preview--mobile .dash-store-preview__nav-links {
  display: none;
}

.dash-store-preview__nav-icons {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  opacity: 0.75;
  flex: 0 0 auto;
}

.dash-store-preview__cart {
  position: relative;
}

.dash-store-preview__cart-badge {
  position: absolute;
  top: -0.4rem;
  right: -0.5rem;
  min-width: 1rem;
  height: 1rem;
  padding: 0 0.2rem;
  border-radius: var(--dash-radius-pill);
  font-size: 0.6rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--dash-on-primary);
}

.dash-store-preview__hero {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--dash-space-4);
  padding: 1.5rem 1.25rem;
  align-items: center;
}

.dash-store-preview--mobile .dash-store-preview__hero {
  grid-template-columns: 1fr;
}

.dash-store-preview__eyebrow {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.65;
  margin-bottom: 0.35rem;
}

.dash-store-preview__title {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  margin-bottom: 0.4rem;
}

.dash-store-preview__body {
  font-size: 0.8rem;
  opacity: 0.75;
  margin-bottom: 0.9rem;
}

.dash-store-preview__actions {
  display: flex;
  gap: 0.5rem;
}

.dash-store-preview__btn {
  border: none;
  border-radius: var(--dash-radius-pill);
  padding: 0.45rem 1rem;
  font-size: 0.75rem;
  font-weight: 600;
}

.dash-store-preview__btn--ghost {
  background: none;
  border: 1.5px solid currentColor;
}

.dash-store-preview__art {
  aspect-ratio: 4 / 3;
  border-radius: var(--dash-radius-lg);
  position: relative;
  overflow: hidden;
}

.dash-store-preview--mobile .dash-store-preview__art {
  display: none;
}

.dash-store-preview__dots {
  display: flex;
  justify-content: center;
  gap: 0.3rem;
  padding-bottom: 1.1rem;
}

.dash-store-preview__dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background-color: currentColor;
  opacity: 0.25;
}

.dash-store-preview__dot--active {
  opacity: 1;
}

/* Theme-elements summary grid below the live preview. */
.dash-theme-elements {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: var(--dash-space-3);
  margin-top: var(--dash-space-3);
  margin-bottom: var(--dash-space-5);
}

.dash-theme-elements__tile {
  padding: var(--dash-space-4);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  background-color: var(--dash-surface);
}

.dash-theme-elements__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--dash-radius-md);
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
  margin-bottom: var(--dash-space-3);
}

.dash-theme-elements__label {
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--dash-text);
}

.dash-theme-elements__value {
  font-size: 0.75rem;
  line-height: 1.5;
  margin-top: 0.15rem;
  color: var(--dash-text-muted);
}

/* ============================================================
 * Pagination -- used by components/pagination.html and every list
 * page's own paginator (orders, employees, vouchers, ...). Bootstrap's
 * defaults are bordered squares in its own stock blue, entirely
 * untouched by the --dash-* bridge above (Bootstrap keys pagination off
 * its own --bs-pagination-* custom properties, which nothing upstream
 * of this file re-points) -- so every paginated list was quietly
 * falling back to stock Bootstrap chrome. Restyled here once, for
 * every list page at once, borderless pills matching --dash-primary.
 * ============================================================ */
.pagination {
  gap: 0.25rem;
}

.page-item .page-link {
  border: none;
  border-radius: var(--dash-radius-md);
  padding: 0.45rem 0.85rem;
  color: var(--dash-text-muted);
  font-size: 0.8125rem;
  font-weight: 500;
  background-color: transparent;
}

.page-item .page-link:hover {
  color: var(--dash-text);
  background-color: var(--dash-surface-subtle);
}

.page-item.disabled .page-link {
  color: var(--dash-text-faint);
  background-color: transparent;
}

.page-item.active .page-link {
  color: var(--dash-on-primary);
  background-color: var(--dash-primary);
}

/* ============================================================
 * Generic "list + inline add/edit form" page pattern -- vouchers,
 * sales, charges (and any future module shaped the same way): a
 * dash-table-card above a dash-card holding the crispy-rendered
 * create/edit form. Not its own component system, just the spacing
 * glue between two things that already have their own styling.
 * ============================================================ */
.dash-form-card {
  padding: var(--dash-space-5);
}

.dash-form-card__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--dash-text);
  margin: 0 0 var(--dash-space-4);
}

.dash-form-card .form-label {
  margin-top: 0;
}

.dash-form-card form > .row,
.dash-form-card form > div {
  margin-bottom: var(--dash-space-1);
}

/* ============================================================
 * Product card grid (catalog/partials/product_table.html) --
 * replaces the old dense product table with a spacious card-per-
 * product grid. Reuses the same surface/border/shadow tokens as
 * .dash-card so it sits visually consistent with the rest of the
 * dashboard chrome.
 * ============================================================ */
.product-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--dash-space-4);
}

.product-card {
  display: flex;
  flex-direction: column;
  background-color: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-lg);
  box-shadow: var(--dash-shadow-xs);
  overflow: hidden;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.product-card:hover {
  box-shadow: var(--dash-shadow-sm);
  transform: translateY(-1px);
}

.product-card__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  background-color: var(--dash-surface-subtle);
}

.product-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-card__media-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--dash-text-faint);
}

.product-card__status {
  position: absolute;
  top: var(--dash-space-2);
  right: var(--dash-space-2);
}

.product-card__body {
  padding: var(--dash-space-4);
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--dash-space-1);
}

.product-card__name {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--dash-text);
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product-card__name:hover {
  color: var(--dash-primary);
}

.product-card__category {
  font-size: 0.8125rem;
  color: var(--dash-text-muted);
  margin: 0;
}

.product-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: var(--dash-space-2);
  font-size: 0.8125rem;
}

.product-card__price {
  font-weight: 600;
  color: var(--dash-text);
}

.product-card__variants {
  color: var(--dash-text-muted);
}

.product-card__footer {
  padding: 0 var(--dash-space-4) var(--dash-space-4);
}

/* ============================================================
 * Product manage page (catalog/product_detail.html) -- sticky
 * header, client-side Details/Images/Variants tabs (Alpine
 * x-show, no page reload), image gallery with drag/reorder, and
 * a variant card stack replacing the old dense variant table.
 * ============================================================ */
[x-cloak] {
  display: none !important;
}

.dash-page-header--sticky {
  position: sticky;
  top: 0;
  z-index: 20;
  background-color: var(--dash-surface);
  padding-block: var(--dash-space-4);
  border-bottom: 1px solid var(--dash-border);
}

.dash-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8125rem;
  color: var(--dash-text-muted);
  margin-bottom: var(--dash-space-1);
}

.dash-breadcrumb__link {
  color: var(--dash-text-muted);
  text-decoration: none;
}

.dash-breadcrumb__link:hover {
  color: var(--dash-text);
  text-decoration: underline;
}

.dash-breadcrumb__current {
  color: var(--dash-text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 320px;
}

/* Reset native <button> chrome so .dash-tabs__link looks identical
   whether it's an <a href> (server-navigated tabs, e.g. Theme
   settings) or a <button> driven by Alpine (client-side tabs, e.g.
   this page) -- both share the same visual language. */
button.dash-tabs__link {
  border: none;
  background: none;
  font: inherit;
  cursor: pointer;
}

.image-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-4);
}

.gallery-item {
  position: relative;
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-md);
  overflow: hidden;
  background-color: var(--dash-surface-subtle);
  cursor: grab;
}

.gallery-item--dragging {
  opacity: 0.4;
}

.gallery-item__meta {
  padding: 0.35rem 0.5rem 0;
  font-size: 0.6875rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.gallery-item__media {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--dash-surface-subtle);
}

.gallery-item__badge {
  position: absolute;
  top: var(--dash-space-2);
  left: var(--dash-space-2);
  font-size: 0.6875rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: var(--dash-radius-pill);
  background-color: rgba(17, 24, 39, 0.65);
  color: #fff;
}

.gallery-item__actions {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--dash-space-1);
  padding: var(--dash-space-2);
  background: linear-gradient(to top, rgba(17, 24, 39, 0.75), transparent);
}

.gallery-item__move-group {
  display: flex;
  gap: 2px;
}

.gallery-item__move-btn,
.gallery-item__delete-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.65rem;
  height: 1.65rem;
  border: none;
  border-radius: var(--dash-radius-sm);
  background-color: rgba(255, 255, 255, 0.9);
  color: var(--dash-text);
  font-size: 0.75rem;
  line-height: 1;
  cursor: pointer;
}

.gallery-item__move-btn:hover,
.gallery-item__delete-btn:hover {
  background-color: #fff;
}

.gallery-item__delete-btn {
  color: var(--dash-danger, #dc3545);
}

.gallery-hint {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  color: var(--dash-text-faint);
  margin: -0.5rem 0 var(--dash-space-3);
}

.variant-card-stack {
  display: flex;
  flex-direction: column;
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-4);
}

.variant-card {
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-md);
  padding: var(--dash-space-4);
  background-color: var(--dash-surface);
}

.variant-card--active {
  border-color: var(--dash-primary);
  box-shadow: 0 0 0 1px var(--dash-primary);
}

.variant-card__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--dash-space-3);
  flex-wrap: wrap;
}

.variant-card__sku {
  font-family: var(--bs-font-monospace, monospace);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--dash-text);
}

.variant-card__badges {
  display: flex;
  align-items: center;
  gap: var(--dash-space-1);
  flex-wrap: wrap;
  margin-top: var(--dash-space-1);
}

.variant-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--dash-space-4);
  margin-top: var(--dash-space-3);
  padding-top: var(--dash-space-3);
  border-top: 1px solid var(--dash-border);
}

.variant-card__meta-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.variant-card__meta-label {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--dash-text-faint);
}

.variant-card__meta-value {
  font-size: 0.875rem;
  color: var(--dash-text);
  font-weight: 500;
}

.variant-card__actions {
  display: flex;
  gap: var(--dash-space-2);
  flex-wrap: wrap;
}

/* Read-only field list used by product_info_panel.html's view mode
 * (replaces the old bare <dl class="row"> two-column layout). */
.dash-detail-list {
  margin: 0 0 var(--dash-space-4);
}

.dash-detail-list__row {
  display: flex;
  align-items: baseline;
  gap: var(--dash-space-4);
  padding: var(--dash-space-3) 0;
  border-bottom: 1px solid var(--dash-border);
}

.dash-detail-list__row:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.dash-detail-list__row dt {
  flex: 0 0 140px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--dash-text-muted);
}

.dash-detail-list__row dd {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 0.875rem;
  color: var(--dash-text);
}

.dash-detail-list__row--stacked {
  flex-direction: column;
  align-items: stretch;
  gap: var(--dash-space-1);
}

.dash-detail-list__row--stacked dt {
  flex: none;
}

/* ============================================================
 * Dashboard home page (businesses/dashboard_home.html) -- stat
 * tiles with an icon+color accent per metric, a compact list-row
 * component for "Recent orders"/"Low stock" (replacing what would
 * otherwise be yet another dense table), a small card-header
 * pattern for a title + "View all" link, and a compact quick-links
 * variant now that the link wall is a secondary "Shortcuts" panel
 * rather than the page's main content.
 * ============================================================ */
.dash-stat-tile {
  display: flex;
  align-items: flex-start;
  gap: var(--dash-space-3);
}

.dash-stat-tile__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--dash-radius-md);
  flex: 0 0 auto;
}

.dash-stat-tile__body {
  min-width: 0;
}

.dash-stat-tile--revenue .dash-stat-tile__icon {
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
}

.dash-stat-tile--orders .dash-stat-tile__icon {
  background-color: var(--dash-info-subtle);
  color: var(--dash-info);
}

.dash-stat-tile--pending .dash-stat-tile__icon {
  background-color: var(--dash-warning-subtle);
  color: var(--dash-warning);
}

.dash-stat-tile--stock .dash-stat-tile__icon {
  background-color: var(--dash-danger-subtle);
  color: var(--dash-danger);
}

.dash-stat-tile--storage .dash-stat-tile__icon {
  background-color: var(--dash-neutral-subtle);
  color: var(--dash-neutral);
}

.dash-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--dash-space-3);
  margin-bottom: var(--dash-space-3);
}

.dash-card-header__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--dash-text);
  margin: 0;
}

.dash-card-header__action {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--dash-primary);
  text-decoration: none;
  white-space: nowrap;
}

.dash-card-header__action:hover {
  text-decoration: underline;
}

.dash-list-row {
  display: flex;
  align-items: center;
  gap: var(--dash-space-3);
  padding: var(--dash-space-3) 0;
  border-bottom: 1px solid var(--dash-border);
  text-decoration: none;
  color: inherit;
  transition: background-color 0.15s ease;
}

.dash-list-row {
  margin-inline: calc(var(--dash-space-2) * -1);
  padding-inline: var(--dash-space-2);
  border-radius: var(--dash-radius-md);
}

a.dash-list-row:hover {
  background-color: var(--dash-surface-subtle);
}

.dash-list-row:last-child {
  border-bottom: none;
}

/* Non-link list rows used for inline CRUD (categories, attributes, values):
 * same visual rhythm as the dashboard's link-based list rows, plus an
 * editing/active state and a trailing action-button group. */
.dash-list-row--active {
  background-color: var(--dash-surface-subtle);
  box-shadow: inset 3px 0 0 var(--dash-primary);
}

.dash-list-row__actions {
  display: flex;
  align-items: center;
  gap: var(--dash-space-2);
}

/* Product-creation wizard stepper: numbered circles connected by a line,
 * replacing the plain badge-pill <ol> (was intentionally left plain until
 * the design-system refresh landed -- it now has). */
.dash-stepper {
  display: flex;
  align-items: center;
  list-style: none;
  padding: 0;
  margin: 0 0 var(--dash-space-5) 0;
  flex-wrap: wrap;
  gap: var(--dash-space-2) 0;
}

.dash-stepper__step {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}

.dash-stepper__circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 1.5px solid var(--dash-border-strong);
  background-color: var(--dash-surface);
  color: var(--dash-text-muted);
  font-size: 0.8125rem;
  font-weight: 600;
  flex: 0 0 auto;
  transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.dash-stepper__label {
  margin-inline-start: var(--dash-space-2);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--dash-text-muted);
  white-space: nowrap;
}

.dash-stepper__line {
  flex: 1 1 3rem;
  height: 1.5px;
  min-width: 1.5rem;
  background-color: var(--dash-border-strong);
  margin-inline: var(--dash-space-3);
}

.dash-stepper__line--complete {
  background-color: var(--dash-primary);
}

.dash-stepper__step--active .dash-stepper__circle {
  border-color: var(--dash-primary);
  background-color: var(--dash-primary);
  color: var(--dash-on-primary);
}

.dash-stepper__step--active .dash-stepper__label {
  color: var(--dash-text);
}

.dash-stepper__step--complete .dash-stepper__circle {
  border-color: var(--dash-primary);
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
}

.dash-stepper__step--complete .dash-stepper__label {
  color: var(--dash-text);
}

/* Crispy-forms Fieldset wrapper used to group ModelForm fields into named
 * sections (Basics / Organization / Description, etc.) instead of one flat
 * field dump -- Bootstrap resets <fieldset>/<legend> to nothing, so this
 * adds the visual boxing back in with dash tokens. */
/* Deliberately not a boxed/tinted card -- a fieldset per form section
 * repeated as an identical filled box is the "every panel is the same
 * card" sameness called out in the design guidance. A plain sub-heading
 * with a rule underneath groups the fields just as clearly without
 * turning every form into a stack of identical gray boxes, and drops
 * the shouty all-caps/tracked-out legend for a quieter sentence-case
 * one (also a named generic-design tell on its own). */
fieldset.dash-form-section {
  border: 0;
  padding: 0;
  margin: 0 0 var(--dash-space-5);
}

fieldset.dash-form-section:last-of-type {
  margin-bottom: var(--dash-space-3);
}

fieldset.dash-form-section legend {
  float: none;
  width: 100%;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--dash-text);
  padding-bottom: var(--dash-space-2);
  margin-bottom: var(--dash-space-3);
  border-bottom: 1px solid var(--dash-border);
}

/* Modal shell (components/modal.html) -- Categories/Attributes/Attribute
 * Values open their Add/Edit form here via hx-get into #modal-container,
 * instead of the form sitting permanently inline under the list. */
/* backdrop-filter blurs whatever's behind the modal (the dashboard page
   itself) rather than just dimming it, so the modal reads as a distinct
   layer floating above the page -- requested explicitly alongside the
   modal-forms work. -webkit- prefix covers Safari, which still needs it
   for backdrop-filter; the plain background dim stays as a fallback for
   the handful of browsers with neither. */
.dash-modal-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(17, 24, 39, 0.5);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--dash-space-5) var(--dash-space-4);
  z-index: 1050;
  overflow-y: auto;
}

.dash-modal {
  background-color: var(--dash-surface);
  border-radius: var(--dash-radius-lg);
  box-shadow: 0 20px 48px rgba(0, 0, 0, 0.24);
  width: 100%;
  max-width: 32rem;
  margin: auto;
}

.dash-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--dash-space-3);
  padding: var(--dash-space-4) var(--dash-space-5);
  border-bottom: 1px solid var(--dash-border);
}

.dash-modal__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--dash-text);
  margin: 0;
}

.dash-modal__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border: none;
  background: transparent;
  border-radius: var(--dash-radius-md);
  color: var(--dash-text-muted);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.dash-modal__close:hover {
  background-color: var(--dash-surface-subtle);
  color: var(--dash-text);
}

.dash-modal__body {
  padding: var(--dash-space-5);
  max-height: 70vh;
  overflow-y: auto;
}

.dash-modal__footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--dash-space-2);
  padding: var(--dash-space-4) var(--dash-space-5);
  border-top: 1px solid var(--dash-border);
}

.dash-list-row__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--dash-radius-md);
  background-color: var(--dash-surface-subtle);
  color: var(--dash-text-muted);
  flex: 0 0 auto;
}

.dash-list-row__body {
  flex: 1;
  min-width: 0;
}

.dash-list-row__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--dash-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-list-row__meta {
  font-size: 0.75rem;
  color: var(--dash-text-muted);
}

.dash-list-row__trailing {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.25rem;
}

.dash-list-row__value {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--dash-text);
  font-variant-numeric: tabular-nums;
}

.dash-quick-links--compact {
  display: flex;
  flex-direction: column;
  gap: var(--dash-space-2);
  margin-bottom: 0;
}

.dash-quick-links--compact .dash-quick-link {
  padding: var(--dash-space-2) var(--dash-space-3);
}

.dash-quick-links--compact .dash-quick-link__icon {
  width: 1.875rem;
  height: 1.875rem;
}

.dash-quick-links--compact .dash-quick-link__label {
  font-size: 0.8125rem;
}

/* ============================================================
 * Rich text (CKEditor 5) and multi-select (Tom Select) widget
 * theming -- both ship their own default look, this just ties their
 * border/radius/focus color to the same --dash-* tokens everything
 * else on the dashboard uses, so they read as part of one system
 * rather than a pasted-in third-party widget. See common/widgets.py.
 * ============================================================ */
.ck.ck-editor {
  --ck-border-radius: var(--dash-radius-md);
  --ck-color-base-border: var(--dash-border);
  --ck-color-toolbar-border: var(--dash-border);
  --ck-color-focus-border: var(--dash-primary);
  font-family: var(--dash-font);
}

.ck.ck-editor__editable_inline {
  min-height: 10rem;
}

.ts-wrapper.single .ts-control,
.ts-wrapper.multi .ts-control {
  border-radius: var(--dash-radius-md);
  border-color: var(--dash-border);
}

.ts-wrapper.focus .ts-control {
  border-color: var(--dash-primary);
  box-shadow: 0 0 0 0.2rem var(--dash-primary-subtle);
}

.ts-dropdown {
  border-radius: var(--dash-radius-md);
  border-color: var(--dash-border);
}

.ts-dropdown .active {
  background-color: var(--dash-primary-subtle);
  color: var(--dash-primary);
}

.plugin-remove_button .item .remove {
  border-color: var(--dash-border);
}


/* ============================================================
 * Date/time picker (Flatpickr) theming -- retint the calendar
 * dropdown with the dashboard's own --dash-* tokens instead of
 * flatpickr's default light-only palette. Flatpickr 4.6 ships plain
 * hardcoded colors with no CSS custom properties of its own (unlike
 * CKEditor 5 above), so this overrides its actual class selectors
 * rather than redefining variables it exposes -- closer to the
 * Tom Select (.ts-*) approach just above than the CKEditor one. Most
 * of these rules need no [data-theme="dark"] scoping at all: the
 * --dash-* tokens they reference already flip value under dark mode
 * at :root, so the calendar follows automatically. The couple of
 * flatpickr internals that DON'T use any token (the hour/minute
 * spinner arrows, drawn with hardcoded border colors) are the only
 * ones scoped explicitly below. See common/widgets.py and
 * static/vendor/flatpickr/README.md.
 * ============================================================ */
.flatpickr-calendar {
  background: var(--dash-surface);
  border: 1px solid var(--dash-border);
  border-radius: var(--dash-radius-md);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16);
  font-family: var(--dash-font);
}

.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after {
  border-bottom-color: var(--dash-surface);
}

.flatpickr-calendar.arrowBottom:before,
.flatpickr-calendar.arrowBottom:after {
  border-top-color: var(--dash-surface);
}

.flatpickr-months .flatpickr-month,
.flatpickr-weekdays,
span.flatpickr-weekday {
  background: var(--dash-surface);
  color: var(--dash-text);
}

span.flatpickr-weekday {
  color: var(--dash-text-muted);
}

.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year {
  color: var(--dash-text);
}

.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
  background: var(--dash-surface-subtle);
}

.flatpickr-day {
  color: var(--dash-text);
}

.flatpickr-day.today {
  border-color: var(--dash-primary);
}

.flatpickr-day:hover,
.flatpickr-day:focus {
  background: var(--dash-surface-subtle);
  border-color: var(--dash-surface-subtle);
}

.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
  background: var(--dash-primary);
  border-color: var(--dash-primary);
  color: var(--dash-on-primary);
}

.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
  color: var(--dash-text-muted);
}

.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
  fill: var(--dash-text-muted);
}

.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
  fill: var(--dash-primary);
}

.flatpickr-time {
  border-top: 1px solid var(--dash-border);
}

.flatpickr-time input,
.flatpickr-time .flatpickr-am-pm {
  color: var(--dash-text);
  background: var(--dash-surface);
}

.flatpickr-time input:hover,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:focus {
  background: var(--dash-surface-subtle);
}

[data-theme="dark"] .numInputWrapper span.arrowUp:after {
  border-bottom-color: var(--dash-text-muted);
}

[data-theme="dark"] .numInputWrapper span.arrowDown:after {
  border-top-color: var(--dash-text-muted);
}
