/* ==========================================================================
   EliteCraft Admin — design tokens
   Visual language from the SaaS dashboard references: charcoal sidebar,
   light topbar, soft-purple primary, white cards, medium density.
   `--green` is kept as an alias of `--primary` so existing markup/JS that
   references it keeps working without a rebuild.
   ========================================================================== */
@font-face { font-family: 'Inter'; src: url('fonts/inter-variable.woff2') format('woff2'); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url('fonts/inter-variable-italic.woff2') format('woff2'); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: 'Paper Mono'; src: url('fonts/paper-mono-variable.woff2') format('woff2'); font-weight: 100 800; font-style: normal; font-display: swap; }

:root {
  --primary: #1769e0;
  --primary-dark: #0f55bd;
  --primary-light: #4c8ef0;
  --primary-soft: #e8f0fd;
  --green: var(--primary);
  --green-dark: var(--primary-dark);
  --green-light: var(--primary-light);
  --gold: #ff9f43;
  --gold-dark: #ee8b2a;
  --dark: #1f1f1f;
  --sidebar: #1e1e2d;
  --sidebar-active: var(--primary);
  --sidebar-hover: rgba(255,255,255,0.06);
  --topbar: #ffffff;
  --pale-green: #ffffff;
  --pale-green-line: #e8e8e8;
  --cream: #f7f7f7;
  --bg: #f7f7f7;
  --surface: #ffffff;
  --text: #1f1f1f;
  --text-muted: #5f6368;
  --text-faint: #8a8d91;
  --line: #e8e8e8;
  --line-soft: #f0f0f0;
  --danger: #ea5455;
  --danger-bg: #fdeeee;
  --success: #28c76f;
  --success-bg: #e8f9f0;
  --warning: #ff9f43;
  --warning-bg: #fff3e8;
  --info: #00cfe8;
  --info-bg: #e6fbfe;
  --chart-2: #28c76f;

  --radius-lg: 14px;
  --radius-md: 10px;
  --radius-sm: 8px;
  --shadow-sm: 0 2px 8px rgba(37, 49, 76, 0.05);
  --shadow-md: 0 6px 20px rgba(37, 49, 76, 0.08);
  --shadow-card: 0 1px 2px rgba(37, 49, 76, 0.04), 0 8px 24px -12px rgba(37, 49, 76, 0.12);

  /* Shell dimensions — matched to the purchased ArchitectUI template's
     layout scale ($app-sidebar-width: 280px, $app-header-height: 60px,
     $layout-spacer-x: 1.5rem/24px) so the shell reads as the template. */
  --sidebar-w: 280px;
  --header-h: 60px;
  --shell-gutter: 24px;

  /* Shell (sidebar/header) surface tokens — template is a *light* shell
     (white sidebar + white header, shadow-separated) rather than the
     previous dark charcoal sidebar. Kept as their own tokens (rather than
     overloading --sidebar/--topbar) so the login gate, which still uses
     --sidebar as a dark backdrop, is unaffected. */
  --shell-sidebar-bg: #ffffff;
  --shell-sidebar-text: #1f1f1f;
  --shell-sidebar-icon: #6b6f76;
  --shell-sidebar-hover-bg: #f5f5f5;
  --shell-sidebar-active-bg: #eeeeee;
  --shell-sidebar-active-text: #111111;
  --shell-sidebar-heading: #8a8d91;
  --shell-sidebar-shadow: none;
  --shell-header-shadow: none;

  --space-xs: 6px;
  --space-sm: 12px;
  --space-md: 18px;
  --space-lg: 20px;
  --card-pad: var(--space-lg);
  --grid-gap: var(--space-md);
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Paper Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 14px; font-weight: 400; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  font-synthesis: none;
  -webkit-tap-highlight-color: transparent;
}
button, input, textarea, select { font-family: inherit; }
b, strong { font-weight: 600; }
th { font-weight: 550; }
h1 { font-weight: 650; }
h2, h3, h4, h5, h6 { font-weight: 600; }
em, cite { font-style: italic; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }

/* Real animated icons (local, self-contained SVGs — see js/icons.js).
   Icons inherit color from their surrounding element (currentColor) like
   Font Awesome does, so no extra color rules are needed at most call
   sites. This block only sets sizing/alignment where the element
   wrapping the icon changed, plus the reduced-motion opt-out. The actual
   motion is native SVG <animate> (SMIL), so js/icons.js additionally
   fast-forwards each icon's timeline to its finished frame for
   prefers-reduced-motion users (CSS alone can't stop SMIL). */
svg.i-svg { display: inline-flex; vertical-align: middle; flex-shrink: 0; }
.topbar-search svg.i-svg { color: var(--text-faint); }

/* ==========================================================================
   Unified icon family — <i class="ai" data-icon="..."> (js/icons.js)
   Hydrated to the same inline SVG as the Dashboard/Customers nav icons
   (24px grid, currentColor, stroke 2, round caps/joins). The glyph scales with
   the surrounding font-size exactly like the old icon font did, so every
   existing per-context size rule (.search-box i, .toast i, .empty-state i ...)
   keeps controlling icon size. :where() keeps this base at zero specificity so
   those contextual rules always win. --ai-sw lets a small context thicken the
   stroke slightly (thin strokes vanish below ~12px).
   ========================================================================== */
:where(i.ai) { display: inline-flex; align-items: center; justify-content: center; font-style: normal; line-height: 1; flex-shrink: 0; vertical-align: -0.2em; }
:where(i.ai) > svg.i-svg { width: 1.2em; height: 1.2em; }
:where(i.ai) > svg.i-svg g { stroke-width: var(--ai-sw, 2); }
.ai-spin > svg.i-svg { animation: ai-rotate 1s linear infinite; }
@keyframes ai-rotate { to { transform: rotate(360deg); } }
/* Small-context stroke compensation (glyphs render <=15px there; 2 -> 2.3 keeps optical weight) */
.tbl-icon-btn, .view-toggle-btn, .sortable-th, .page-crumb, .search-box, .topbar-search,
.pager-btns button, .validation-item, .stat-card .delta, .radio-card-title, .pos-search-wrap { --ai-sw: 2.3; }
@media (prefers-reduced-motion: reduce) { .ai-spin > svg.i-svg { animation: none; } }
.stat-anim-icon { color: #fff; }
@media (prefers-reduced-motion: reduce) {
  svg.i-svg animate, svg.i-svg animateTransform { animation: none !important; }
}
.num, .mono { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0; font-variant-numeric: tabular-nums; }
::selection { background: var(--primary-soft); color: var(--primary-dark); }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: #d8dbe6; border-radius: 8px; }
::-webkit-scrollbar-track { background: transparent; }

/* ==========================================================================
   LOGIN GATE
   ========================================================================== */
.gate {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--sidebar);
  padding: 24px;
}
.gate-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 36px 32px 32px;
}
.gate-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.gate-brand .mark {
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--primary);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 15px;
}
.gate-brand span { font-weight: 600; font-size: 17px; color: var(--dark); letter-spacing: -0.02em; }
.gate-card p.sub { color: var(--text-muted); font-size: 13.5px; margin: 0 0 26px; }
.gate-card h1 { display: none; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 13px; font-weight: 500; color: var(--text-muted); margin-bottom: 6px; }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--text);
  background: #fff;
  transition: border-color .15s, box-shadow .15s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
.field textarea { resize: vertical; min-height: 90px; }
.field-inline { display: flex; gap: 8px; align-items: stretch; }
.field-inline input { flex: 1; min-width: 0; }
.field-inline .btn { flex: 0 0 auto; white-space: nowrap; }

/* Phase CatBrand-1 — searchable/creatable Category & Brand fields on the
   Add Product form. Same input chrome as .field input (border/radius/focus
   ring) so it reads as one family of controls; only the dropdown panel is
   new. */
.combo { position: relative; }
.combo-input {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--text);
  background: #fff;
  transition: border-color .15s, box-shadow .15s;
}
.combo-input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
.combo-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 40;
  max-height: 220px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(20, 20, 43, 0.12);
  padding: 6px;
}
.combo-panel.open { display: block; }
.combo-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
}
.combo-item:hover, .combo-item.active { background: var(--primary-soft); color: var(--primary-dark); }
.combo-item-create { color: var(--primary); font-weight: 600; }
.combo-item-create:hover, .combo-item-create.active { background: var(--primary-soft); }
.combo-empty { padding: 9px 10px; font-size: 13px; color: var(--text-faint); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  border: none;
  font-size: 14px;
  font-weight: 550;
  transition: transform .1s, box-shadow .15s, background .15s, color .15s;
}
.btn-primary { background: var(--primary); color: #fff; width: 100%; }
.btn-primary:hover { background: var(--primary-dark); }
.btn-gold { background: var(--gold); color: #fff; }
.btn-gold:hover { background: var(--gold-dark); }
.btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--line); }
.btn-ghost:hover { background: var(--bg); }
.btn-danger-outline { background: transparent; color: var(--danger); border: 1px solid #f5c6c6; }
.btn-danger-outline:hover { background: var(--danger-bg); }
.btn-sm { padding: 7px 12px; font-size: 12.5px; }
.btn:active { transform: scale(0.98); }
.btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }
.gate-error {
  background: var(--danger-bg); color: var(--danger); font-size: 13px;
  padding: 10px 12px; border-radius: var(--radius-sm); margin-bottom: 16px; display: none;
}
.gate-note { margin-top: 18px; font-size: 12px; color: var(--text-faint); text-align: center; }

/* ==========================================================================
   APP SHELL
   Restyled from the purchased ArchitectUI admin template (light sidebar +
   white header, 280px/60px scale, soft card-style shadows, animated
   hamburger toggle). Structural class names and every #id used by admin.js
   are unchanged — this is a visual pass over the same DOM contract.
   ========================================================================== */
.app { display: none; min-height: 100vh; }
.app.is-ready { display: flex; }

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--shell-sidebar-bg);
  color: var(--shell-sidebar-text);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 40;
  box-shadow: var(--shell-sidebar-shadow);
  border-right: 1px solid var(--line);
  transition: transform .25s ease;
}
.sidebar-brand {
  display: flex; align-items: center; gap: 12px;
  padding: 20px 22px 16px;
  height: var(--header-h);
  box-sizing: border-box;
}
/* Open, flexible logo area — no background box/border/crop. Sized to a
   sensible maximum (not a tiny fixed icon) and hidden entirely (via JS)
   when the store has no logo, so the name can occupy the space instead. */
.sidebar-brand .mark {
  display: flex; align-items: center; justify-content: center;
  max-width: 140px; max-height: 44px;
  flex-shrink: 0;
}
.sidebar-brand .mark img {
  display: block; width: auto; height: auto;
  max-width: 140px; max-height: 44px;
  object-fit: contain;
}
.sidebar-brand .txt { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.sidebar-brand .txt b { font-size: 15px; color: var(--text); font-weight: 600; letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-brand .txt small { font-size: 10px; color: var(--text-faint); letter-spacing: 0; text-transform: none; margin-top: 2px; }

.sidebar-nav { flex: 1; overflow-y: auto; padding: 6px 14px 18px; border-top: 1px solid var(--line-soft); }
.nav-section { margin-bottom: 6px; }
.nav-section-label {
  font-size: 12px; font-weight: 500; letter-spacing: 0;
  color: var(--shell-sidebar-heading); padding: 18px 12px 6px;
}
.nav-link {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px; font-weight: 450;
  color: var(--shell-sidebar-text);
  margin-bottom: 2px;
  position: relative;
  transition: background .15s ease, color .15s ease;
}
/* Icons sit directly on the sidebar: no background box, one consistent size. */
.nav-link i { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; background: none; text-align: center; font-size: 15px; color: var(--shell-sidebar-icon); flex-shrink: 0; transition: color .15s ease; }
.nav-link i svg.i-svg { width: 17px; height: 17px; }
.nav-link:hover { background: var(--shell-sidebar-hover-bg); color: var(--text); }
.nav-link:hover i { color: var(--text); }
.nav-link.active { background: var(--shell-sidebar-active-bg); color: var(--shell-sidebar-active-text); font-weight: 550; }
.nav-link.active i { color: var(--primary); }
#logoutLink:hover, #logoutLink:hover i { color: var(--danger); }

/* Channels — collapsible nav group (Phase NAV-CHANNELS). ".nav-group-toggle"
   and ".nav-child-link" both inherit the base ".nav-link" look (icon size,
   hover, active state) and only add what's specific to the parent/child
   roles, so this stays visually identical to the rest of the sidebar. */
.nav-group { margin-bottom: 2px; }
.nav-group-toggle {
  width: 100%; background: none; border: none; cursor: pointer;
  font-family: inherit; text-align: left;
}
.nav-group-toggle .nav-group-chevron { margin-left: auto; transition: transform .15s ease; }
.nav-group.expanded .nav-group-toggle .nav-group-chevron { transform: rotate(90deg); }
.nav-group-toggle.has-active-child { color: var(--shell-sidebar-active-text); font-weight: 550; }
.nav-group-toggle.has-active-child > i:first-child { color: var(--primary); }
.nav-group-children { display: none; flex-direction: column; margin-top: 2px; }
.nav-group.expanded .nav-group-children { display: flex; }
.nav-child-link { padding-left: 34px; }
/* Channels sub-nav (View Store / Customize-Edit Store / Open POS / POS
   Sales): text-only, no icon by design. The extra 32px inset (the
   width+gap an icon would otherwise take) keeps their text lined up
   where a child link's text would land if it did have one, matching the
   rest of the sidebar's indent rhythm. Plain-class modifier (not a :has()
   selector) so this doesn't depend on newer CSS support. */
.nav-child-link.nav-child-link--text { padding-left: 66px; }
.nav-divider { height: 1px; background: var(--line-soft); margin: 10px 8px; }

.sidebar-foot { padding: 14px 16px 18px; border-top: 1px solid var(--line-soft); }
.sidebar-user { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--radius-sm); background: var(--bg); }
.sidebar-user .av {
  width: 34px; height: 34px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); font-size: 17px; flex-shrink: 0;
  transition: background .15s ease, color .15s ease;
}
.sidebar-user .av:hover, .sidebar-user .av:focus-visible { background: var(--shell-sidebar-hover-bg, var(--line-soft)); color: var(--text); }
.sidebar-user .av:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.sidebar-user .who { line-height: 1.2; overflow: hidden; }
.sidebar-user .who b { display: block; font-size: 12.5px; color: var(--text); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user .who span { font-size: 10.5px; color: var(--text-faint); }

.main {
  flex: 1;
  margin-left: var(--sidebar-w);
  min-width: 0;
  display: flex; flex-direction: column;
}
.topbar {
  height: var(--header-h);
  background: var(--topbar);
  box-shadow: var(--shell-header-shadow);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--shell-gutter);
  position: sticky; top: 0; z-index: 20;
  gap: 16px;
}
.topbar-left { display: flex; align-items: center; gap: 16px; min-width: 0; flex: 1; }

/* Menu toggle — animated 3-bar/X hamburger, in the spirit of the template's
   hamburgers.js component. Pure CSS: uses :has() to react to the sidebar's
   existing .open class, so no admin.js changes were needed for this. */
.menu-toggle {
  display: none;
  background: none; border: none; padding: 0;
  width: 38px; height: 38px; border-radius: 10px;
  align-items: center; justify-content: center;
  position: relative;
}
.menu-toggle:hover { background: var(--bg); }
.menu-toggle .hamburger-box { width: 20px; height: 16px; position: relative; display: inline-block; }
.menu-toggle .hamburger-inner,
.menu-toggle .hamburger-inner::before,
.menu-toggle .hamburger-inner::after {
  width: 20px; height: 2px; border-radius: 2px; background: var(--text-muted);
  position: absolute; left: 0;
  transition: transform .2s cubic-bezier(.4,0,.2,1), opacity .15s ease, background .15s ease;
}
.menu-toggle .hamburger-inner { top: 7px; }
.menu-toggle .hamburger-inner::before { content: ""; top: -6px; }
.menu-toggle .hamburger-inner::after { content: ""; top: 6px; }
#app:has(.sidebar.open) .menu-toggle .hamburger-inner { background: transparent; }
#app:has(.sidebar.open) .menu-toggle .hamburger-inner::before { top: 0; transform: rotate(45deg); background: var(--primary); }
#app:has(.sidebar.open) .menu-toggle .hamburger-inner::after { top: 0; transform: rotate(-45deg); background: var(--primary); }

.topbar h1 { display: none; }
.topbar-crumb { font-size: 12.5px; color: var(--text-faint); }
.topbar-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.topbar-search {
  display: flex; align-items: center; gap: 8px;
  background: var(--bg); border: 1px solid var(--line-soft);
  border-radius: 999px; padding: 9px 16px; width: min(280px, 36vw);
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.topbar-search:focus-within { border-color: var(--primary-soft); background: #fff; box-shadow: 0 0 0 3px var(--primary-soft); }
.topbar-search input { border: none; background: none; font-size: 13.5px; width: 100%; color: var(--text); }
.topbar-search input::placeholder { color: var(--text-faint); }
.topbar-search input:focus { outline: none; }
.topbar-search i { color: var(--text-faint); font-size: 13px; }
.icon-btn {
  width: 38px; height: 38px; border-radius: 50%; border: none;
  background: var(--bg); display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); font-size: 14px; position: relative;
  transition: background .15s ease, color .15s ease;
}
.icon-btn:hover { background: var(--primary-soft); color: var(--primary); }
.icon-btn .notif-dot {
  position: absolute; top: 7px; right: 7px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--danger); border: 2px solid var(--topbar);
}
.topbar-account { display: flex; align-items: center; gap: 10px; padding-left: 12px; margin-left: 4px; border-left: 1px solid var(--line-soft); }
.topbar-account .who { line-height: 1.15; text-align: right; }
.topbar-account .who b { display: block; font-size: 12.5px; font-weight: 600; color: var(--text); }
.topbar-account .who span { font-size: 11.5px; color: var(--text-muted); }
.topbar-account .av {
  width: 38px; height: 38px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); font-size: 19px; flex-shrink: 0;
  transition: background .15s ease, color .15s ease;
}
.topbar-account .av:hover, .topbar-account .av:focus-visible { background: var(--primary-soft); color: var(--primary); }
.topbar-account .av:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

.content { padding: 22px var(--shell-gutter) 40px; flex: 1; }
.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 12px; margin-bottom: 20px; flex-wrap: wrap;
}
.page-head h1 { font-size: 24px; font-weight: 650; margin: 0; letter-spacing: -0.01em; line-height: 1.25; color: var(--text); }
.page-crumb { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-faint); font-weight: 500; }
.page-crumb i { font-size: 9px; }
.page-crumb span:last-child { color: var(--primary); font-weight: 600; }
.app-footer { margin-top: 28px; padding-top: 16px; text-align: center; font-size: 12.5px; color: var(--text-faint); }
.view { display: none; animation: fadeUp .22s ease; }
.view.active { display: block; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .view { animation: none; } }

/* ---------------- Phase NAV-POS-EMBED — POS fills the content viewport ----------------
   #view-pos hosts an iframe onto pos.html (untouched, see admin/pos.html and
   pos.css's own .pos-embedded rules). #content.pos-active drops the normal
   page padding/title so the register UI gets the full viewport, same as
   pos.html's existing standalone Fullscreen mode. */
#content.pos-active { padding: 0; overflow: hidden; }
#content.pos-active .page-head { display: none; }
.view#view-pos { position: relative; height: calc(100vh - var(--header-h)); animation: none; }
.view#view-pos.active { display: block; }
#posFrame { display: block; width: 100%; height: 100%; border: 0; }
.pos-frame-loading {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: var(--bg); color: var(--text-faint); font-size: 13px;
}
.pos-frame-loading.hidden { display: none; }
.pos-frame-spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--line); border-top-color: var(--primary);
  animation: pos-frame-spin .7s linear infinite;
}
@keyframes pos-frame-spin { to { transform: rotate(360deg); } }
@media (max-width: 860px) {
  /* Leaves room for .mobile-bottom-nav (fixed, ~76px incl. safe-area),
     which stays visible here — it's the only way back to the rest of
     Admin, since the POS document's own embedded sidebar is hidden. */
  .view#view-pos { height: calc(100vh - var(--header-h) - 76px - env(safe-area-inset-bottom, 0px)); }
}

/* ==========================================================================
   PRIMITIVES
   ========================================================================== */
.grid { display: grid; gap: var(--grid-gap); }
.stat-grid { grid-template-columns: repeat(3, 1fr); }
.card {
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  padding: var(--card-pad);
  box-shadow: var(--shadow-card);
  transition: box-shadow .15s ease;
}
.card-flush { padding: 0; overflow: hidden; }
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--line);
  gap: var(--space-sm); flex-wrap: wrap;
}

.dash-equal-grid {
  /* Sales Analytics + Recent Orders — always stacked, full width, on every
     breakpoint (previously 2-column above 860px). Only consumer of this
     class (admin/index.html), so safe to change here without affecting
     any other grid. */
  grid-template-columns: 1fr;
  grid-auto-rows: minmax(340px, 1fr);
  align-items: stretch;
}
.dash-equal-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}
.dash-card-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.dash-equal-card .table-wrap { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.card-head h3 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: 0; }
.card-head .sub { font-size: 12px; color: var(--text-faint); margin-top: 2px; }

/* Class kept for existing markup; visually a light header to match the references. */
.card-head-dark {
  background: #fff;
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 16px 20px;
}
.card-head-dark h3 { color: var(--text); display: flex; align-items: center; gap: 10px; }
.card-head-dark h3 i { font-size: 14px; color: var(--primary); opacity: 1; }
.card-head-dark .sub { color: var(--text-faint); }
.card-head-dark .btn-ghost, .card-head-dark select.filter-select {
  border-color: var(--line); color: var(--text); background: #fff;
}
.card-head-dark .btn-ghost:hover { background: var(--bg); }
.card-head-dark .range-toggle { background: var(--bg); border: 1px solid transparent; border-radius: 10px; padding: 3px; }
.card-head-dark .range-btn { color: var(--text-muted); border: none; background: transparent; }
.card-head-dark .range-btn.active { background: var(--primary); color: #fff; }

.stat-card {
  display: flex; flex-direction: column; justify-content: flex-start; gap: 10px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: none;
  padding: 20px;
  position: relative;
  min-height: 124px;
}
.stat-card .label { font-size: 14px; color: var(--text-muted); font-weight: 450; line-height: 1.3; }
.stat-card .value-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.stat-card .value { font-family: var(--font); font-size: 35px; font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; color: var(--text); line-height: 1.1; }
.stat-card .sub { font-size: 13px; color: var(--text-faint); font-weight: 400; }
/* Change indicator: plain text with arrow, no pill (as in the reference). */
.stat-card .delta { font-size: 14px; font-weight: 450; display: inline-flex; align-items: center; gap: 4px; padding: 0; border-radius: 0; background: none !important; color: var(--text-muted) !important; }
.stat-card .delta i { font-size: 11px; }
/* Mini trend (sparkline): purely decorative layer inside the card — absolutely
   positioned, so it never affects the card's height. Full width along the bottom;
   on cards that also show a sub-line it sits bottom-right so the text stays clear. */
.stat-card.has-trend { overflow: hidden; }
.stat-card.has-trend > .label, .stat-card.has-trend > .value-row, .stat-card.has-trend > .sub { position: relative; z-index: 1; }
.stat-card .stat-trend { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 34px; display: block; pointer-events: none; z-index: 0; }
.stat-card.has-sub .stat-trend { left: auto; width: 52%; height: 40px; }
.stat-card .stat-trend .area { fill: rgba(23,105,224,.07); stroke: none; }
.stat-card .stat-trend .line { fill: none; stroke: var(--primary); stroke-width: 1.4; stroke-linejoin: round; stroke-linecap: round; opacity: .9; }
/* Uniform KPI card height on desktop: rows are fixed so graph/no-graph and sub-line cards align. */
@media (min-width: 861px) { #statGrid.stat-grid { grid-auto-rows: 124px; } }
.stat-spark { position: absolute; right: 16px; bottom: 16px; display: flex; align-items: flex-end; gap: 3px; height: 34px; }
.stat-spark span { width: 5px; border-radius: 2px; background: var(--primary); opacity: .85; min-height: 4px; }
.stat-card.has-spark .value { padding-right: 52px; }

.chart-kpis {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 12px; padding: 4px 20px 18px; border-top: 1px solid var(--line); margin-top: 4px;
}
.chart-kpis .ck { display: flex; flex-direction: column; gap: 2px; }
.chart-kpis .ck span { font-size: 12px; color: var(--text-muted); font-weight: 600; }
.chart-kpis .ck b { font-size: 16px; font-weight: 500; letter-spacing: 0; }
.chart-kpis .ck em { font-size: 11.5px; font-style: normal; font-weight: 600; }

/* ---------------- Dashboard analytics (ECharts) ---------------- */
.chart-box { position: relative; width: 100%; height: 260px; }
.chart-box.chart-box-sm { height: 220px; }
.sales-subcharts-grid {
  display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--space-lg);
  padding: 14px 20px 20px; border-top: 1px solid var(--line); margin-top: 4px;
}
.sales-subchart-head { font-size: 12.5px; font-weight: 600; color: var(--text-muted); margin-bottom: 8px; }
@media (max-width: 720px) {
  .sales-subcharts-grid { grid-template-columns: 1fr; }
  .chart-box { height: 220px; }
  .chart-box.chart-box-sm { height: 200px; }
}

/* ---------------- One-line table rows (global) ----------------
   Every admin table (.dtable) keeps each row on a single line: cells
   never wrap, the "title" cell (thumbnail + name[/meta]) truncates
   with an ellipsis past a sensible max width, and the wrapping
   .table-wrap scrolls horizontally instead of squeezing columns.
   This is the one shared place table row-height/overflow behavior
   lives — view-specific blocks below only add width tweaks. */
.table-wrap { overflow-x: auto; overflow-y: hidden; }
table.dtable { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 640px; }
table.dtable th {
  text-align: left; font-size: 12px; letter-spacing: 0;
  color: var(--text-muted); font-weight: 550; padding: 13px 16px; border-bottom: 1px solid var(--line);
  background: #fafbfe; white-space: nowrap;
}
table.dtable td {
  padding: 13px 16px; border-bottom: 1px solid var(--line-soft); vertical-align: middle;
  white-space: nowrap;
}
table.dtable tbody tr:hover { background: #fafbfe; }
table.dtable tbody tr:last-child td { border-bottom: none; }
.row-thumb { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; background: var(--bg); flex-shrink: 0; }
/* Name/thumbnail cell used across Products, Orders, Customers, Blog,
   Notifications, Inventory history, etc. Capped so one very long name
   can't stretch the whole table — it ellipsizes instead; every other
   column stays free to size to its (short) content. */
.row-title { display: flex; align-items: center; gap: 10px; max-width: 300px; min-width: 0; }
.row-title > img, .row-title > .av { flex-shrink: 0; }
.row-title > *:last-child { min-width: 0; overflow: hidden; }
.row-title .name { font-weight: 500; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meta { font-size: 11.5px; color: var(--text-faint); font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cell-actions { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.cell-actions .tbl-icon-btn { flex-shrink: 0; }
.row-select {
  padding: 6px 26px 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  color: var(--text);
  background: #fff;
  cursor: pointer;
}
.row-select:focus { outline: none; border-color: var(--primary); }
.row-select:disabled { opacity: .55; cursor: not-allowed; }
.tbl-icon-btn {
  width: 30px; height: 30px; border-radius: 8px; border: none; background: var(--bg);
  display: inline-flex; align-items: center; justify-content: center; font-size: 12px; color: var(--text-muted);
}
.tbl-icon-btn:hover { background: var(--primary-soft); color: var(--primary); }
.tbl-icon-btn.danger:hover { background: var(--danger-bg); color: var(--danger); }
.checkbox { width: 16px; height: 16px; accent-color: var(--primary); }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; padding: 4px 10px; border-radius: 20px;
  white-space: nowrap;
}
.badge-success { background: var(--success-bg); color: #1a9d57; }
.badge-warning { background: var(--warning-bg); color: #d67d24; }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-info { background: var(--info-bg); color: #0aa2b5; }
.badge-muted { background: var(--bg); color: var(--text-muted); }

.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.toolbar-left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* .btn-primary defaults to width:100% (see .btn-primary below) for
   contexts like the login gate where a full-width button is wanted; inside
   a toolbar that stretches the button oddly since .toolbar/.toolbar-right
   are flex rows. Same fix already applied to .form-actions/.modal-foot
   buttons below — extended here so every toolbar's primary action sizes
   to its own content instead of relying on a per-button inline style
   (previously only Notifications' and Team's "Add" buttons had that
   inline fix; Attributes/Brands/Blog's did not). */
.toolbar > .btn, .toolbar-left > .btn, .toolbar-right > .btn { width: auto; }
.filter-select, .search-box {
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff;
  padding: 9px 12px; font-size: 13px; color: var(--text);
}
.search-box { display: flex; align-items: center; gap: 8px; padding: 0 12px; min-width: 220px; }
.search-box input { border: none; padding: 9px 0; font-size: 13px; width: 100%; }
.search-box input:focus { outline: none; }
.search-box i { color: var(--text-faint); font-size: 12.5px; }
.bulk-bar {
  display: none; align-items: center; gap: 10px; background: var(--primary-soft); color: var(--primary);
  padding: 10px 14px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 600; margin-bottom: 14px;
}
.bulk-bar.show { display: flex; }
.bulk-bar select { border: 1px solid #d7d3fb; border-radius: 7px; padding: 6px 10px; font-size: 12.5px; background: #fff; }

.pager { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--text-muted); }
.pager-btns { display: flex; gap: 6px; }
.pager-btns button { width: 30px; height: 30px; border-radius: 7px; border: 1px solid var(--line); background: #fff; font-size: 12.5px; }
.pager-btns button:disabled { opacity: .4; }

.empty-state { text-align: center; padding: 56px 20px; color: var(--text-muted); }
.empty-state i { font-size: 30px; color: var(--primary); opacity: .45; margin-bottom: 12px; display: block; }
.empty-state p { margin: 0 0 4px; font-weight: 600; color: var(--text); }
.empty-state span { font-size: 13px; }

/* Empty/error/no-results illustrations — real Storyset SVG artwork (see
   admin/illustrations/, attribution in the app footer) inside a fixed-size
   colored frame, so a card never grows unexpectedly regardless of which
   illustration's native aspect ratio is used. .illo-<color> still picks the
   accent (now the frame's soft background) exactly as before; the artwork
   itself keeps its original Storyset palette and is not recolored. Height
   is fixed (150px desktop / 120px mobile, both inside the 140-160 /
   110-130 target ranges); width flexes with the card but is capped so the
   frame never dominates a narrow card. */
.empty-state .empty-illo {
  position: relative; width: 100%; max-width: 220px; height: 150px;
  margin: 0 auto 14px; padding: 12px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-lg); overflow: hidden;
  background: var(--_illo-bg, var(--primary-soft));
}
.empty-state .empty-illo img.illo-img {
  display: block; width: 100%; height: 100%;
  object-fit: contain; object-position: center;
}
/* Fallback for the rare case an <i> icon is still passed in (e.g. a future
   call site added without an illustration) — keeps the old icon-in-frame
   look instead of an empty box. */
.empty-state .empty-illo i {
  position: relative; z-index: 1; font-size: 26px; opacity: 1;
  margin-bottom: 0; display: block; color: var(--_illo-fg, var(--primary));
}
.empty-state .empty-illo.illo-green { --_illo-bg: var(--success-bg); --_illo-fg: var(--success); }
.empty-state .empty-illo.illo-blue { --_illo-bg: var(--info-bg); --_illo-fg: #1d55c9; }
.empty-state .empty-illo.illo-gold { --_illo-bg: var(--warning-bg); --_illo-fg: var(--gold-dark); }
.empty-state .empty-illo.illo-cyan { --_illo-bg: var(--info-bg); --_illo-fg: #0aa2b5; }
.empty-state .empty-illo.illo-red { --_illo-bg: var(--danger-bg); --_illo-fg: var(--danger); }

@media (max-width: 640px) {
  .empty-state .empty-illo { height: 120px; max-width: 170px; padding: 8px; }
}

/* These SVGs are static Storyset exports (no <animate>/CSS animation), so
   there's nothing to freeze here — this rule is a guard in case a future
   illustration swap introduces motion. */
@media (prefers-reduced-motion: reduce) {
  .empty-state .empty-illo img.illo-img { animation: none !important; }
}

.skel { background: linear-gradient(90deg, #eef0f6 25%, #f7f8fc 37%, #eef0f6 63%); background-size: 400% 100%; animation: skel 1.3s ease infinite; border-radius: 8px; }
@keyframes skel { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.skel-row { height: 46px; margin-bottom: 8px; border-radius: 10px; }
.skel-card { height: 96px; border-radius: var(--radius-lg); }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-grid .span-2 { grid-column: span 2; }

.modal-wide { width:min(760px, calc(100vw - 28px)); }
.bdz-selection-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin:18px 0 8px; }
.bdz-selection-head > label { font-size:12px; font-weight: 600; }
.bdz-selection-head .btn + .btn { margin-left:6px; }
.bdz-county-list { display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:6px; max-height:220px; overflow:auto; padding:10px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--bg); }
.bdz-county-option { display:flex; align-items:center; gap:8px; min-width:0; padding:5px 6px; font-size:12.5px; cursor:pointer; }
.bdz-county-option input { margin:0; accent-color:var(--primary); }
.bdz-config { border-top:1px solid var(--line); padding:16px 0; }
.bdz-config-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:10px; }
.bdz-config-head h5 { margin:0; font-size:14px; }
.bdz-mode-options { display:flex; flex-wrap:wrap; gap:14px; font-size:12.5px; }
.bdz-mode-options label { display:flex; align-items:center; gap:6px; cursor:pointer; }
.bdz-town-entry { display:flex; gap:8px; margin-top:12px; }
.bdz-town-entry input { min-width:0; flex:1; }
.bdz-town-chips { display:flex; flex-wrap:wrap; gap:6px; margin-top:9px; }
.bdz-town-chip { display:inline-flex; align-items:center; gap:6px; padding:5px 7px; border-radius:99px; background:var(--primary-soft); color:var(--primary-dark); font-size:12px; }
.bdz-town-chip button { padding:0; border:0; background:none; color:inherit; font-size:14px; line-height:1; }
.bdz-review { margin-top:8px; padding:12px; border-radius:var(--radius-sm); background:var(--primary-soft); color:var(--primary-dark); font-size:12.5px; }
.bdz-review-title { font-weight: 600; margin-bottom:5px; }
.bdz-review-line + .bdz-review-line { margin-top:3px; }

@media (max-width: 600px) {
  .bdz-selection-head { align-items:flex-start; flex-direction:column; }
  .bdz-town-entry { flex-wrap:wrap; }
  .bdz-town-entry .btn { width:100%; }
}
.form-section { margin-bottom: 22px; }
.form-section h4 { font-size: 12px; text-transform: none; letter-spacing: 0; color: var(--text-faint); margin: 0 0 14px; font-weight: 500; }
.checkbox-row { display: flex; align-items: center; gap: 9px; padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.checkbox-row label { margin: 0; font-size: 13.5px; font-weight: 500; color: var(--text); text-transform: none; letter-spacing: 0; }
.hint { font-size: 11.5px; color: var(--text-faint); margin-top: 5px; }
.form-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 6px; padding-top: 18px; border-top: 1px solid var(--line); }
.form-actions .spacer { margin-right: auto; font-size: 12.5px; color: var(--text-faint); }
.form-actions .btn, .modal-foot .btn { width: auto; }

/* ==========================================================================
   SETTINGS — category navigation + content panels (Shopify Settings-style:
   a left list of settings categories where clicking one swaps the entire
   right-hand content area; the previous category's cards are hidden, not
   scrolled past). Spacing is intentionally generous — large gaps between
   cards, a clear category heading + description above each panel's cards,
   and roomy card padding — to read as calm rather than compressed.
   See view-settings in admin/index.html + initSettingsSectionNav() in
   admin/js/admin.js for the panel-switching logic.
   ========================================================================== */
.settings-shell { display: flex; align-items: flex-start; gap: 40px; }
.settings-nav {
  width: 232px; flex-shrink: 0;
  display: flex; flex-direction: column; gap: 4px;
  padding-top: 4px;
}
.settings-nav-link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px; border-radius: var(--radius-sm);
  font-size: 13.5px; font-weight: 500; color: var(--text-muted);
  transition: background .12s ease, color .12s ease;
}
.settings-nav-link:hover { background: var(--bg); color: var(--text); }
.settings-nav-link.active { background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.settings-nav-link::after { content: ''; }

/* Category icons — same icon system as the main sidebar (.nav-link i /
   svg.i-svg in js/icons.js): same 20px icon box, same 17px svg, same
   currentColor stroke, so a category icon here is visually identical to
   its sidebar counterpart. Grouped with the label in one inner flex
   element so the existing space-between layout (label vs. the mobile
   "›" chevron in ::after) is unaffected by adding a third child. */
.settings-nav-link-label { display: flex; align-items: center; gap: 10px; min-width: 0; }
.settings-nav-link i {
  width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-faint); flex-shrink: 0; transition: color .12s ease;
}
.settings-nav-link i svg.i-svg { width: 17px; height: 17px; }
.settings-nav-link:hover i { color: var(--text); }
.settings-nav-link.active i { color: var(--primary); }

.settings-main { flex: 1; min-width: 0; max-width: 760px; }

/* Only the active category's panel renders; switching categories swaps
   this rather than scrolling — no anchors, no scrollspy. */
.settings-panel { display: none; }
.settings-panel.active { display: block; animation: fadeUp .18s ease; }

.settings-panel-head { margin-bottom: 28px; }
.settings-back-link {
  display: none; align-items: center; gap: 4px;
  background: none; border: none; padding: 0 0 14px; margin: 0;
  font-size: 13px; font-weight: 600; color: var(--text-muted);
}
.settings-back-link i { font-size: 15px; }
.settings-back-link:hover { color: var(--text); }
.settings-panel-head h2 { margin: 0 0 8px; font-size: 20px; font-weight: 650; letter-spacing: -0.01em; color: var(--text); }
.settings-panel-sub { margin: 0; font-size: 13.5px; color: var(--text-faint); max-width: 56ch; line-height: 1.55; }

/* Cards within a panel: generous vertical rhythm between them. */
.settings-panel .settings-card { margin-bottom: 28px; }
.settings-panel .settings-card:last-of-type { margin-bottom: 0; }
.settings-card .card-head-dark { align-items: flex-start; gap: 16px; padding: 22px 26px; }
.settings-card .card-head-dark h3 { font-size: 15.5px; }
.settings-card .card-head-dark .sub { margin-top: 5px; max-width: 50ch; line-height: 1.55; }
.settings-card .card-head-dark .switch { flex-shrink: 0; margin-top: 2px; }
.settings-card-body { padding: 26px; }
.settings-card-body .form-grid:last-child,
.settings-card-body > *:last-child { margin-bottom: 0; }
.settings-card-body-split { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.settings-subgroup-label { font-size: 12px; font-weight: 500; color: var(--text-faint); margin-bottom: 10px; }

.settings-save-bar {
  margin-top: 32px; padding: 20px 2px 4px;
  border-top: 1px solid var(--line);
}

@media (max-width: 980px) {
  .settings-shell { gap: 0; }
  /* Mobile behaves like a settings app: the category list is its own
     full-width screen; tapping a category replaces it with that panel
     and a "‹ Settings" link to go back — never both at once. */
  .settings-nav { display: flex; width: 100%; }
  .settings-main { display: none; max-width: 100%; }
  #settingsShell.settings-panel-open .settings-nav { display: none; }
  #settingsShell.settings-panel-open .settings-main { display: block; }
  .settings-back-link { display: inline-flex; }
  .settings-nav-link::after { content: '\203A'; color: var(--text-faint); font-size: 16px; }
}
@media (max-width: 640px) {
  .settings-card .card-head-dark { padding: 18px 18px; }
  .settings-card-body { padding: 18px; }
  .settings-card-body-split { grid-template-columns: 1fr; gap: 18px; }
  .settings-panel-head { margin-bottom: 20px; }
}


.uploader {
  border: 1.5px dashed var(--line); border-radius: var(--radius-md);
  padding: 22px; text-align: center; cursor: pointer; background: var(--bg);
  transition: border-color .15s, background .15s;
}
.uploader:hover, .uploader.drag { border-color: var(--primary); background: var(--primary-soft); }
.uploader.is-busy { cursor: default; border-color: var(--primary-light); background: var(--primary-soft); }
.uploader.is-busy:hover { border-color: var(--primary-light); background: var(--primary-soft); }
.uploader.is-busy i { color: var(--primary); }
.uploader.is-success { border-color: var(--success); background: var(--success-bg); }
.uploader.is-success:hover { border-color: var(--success); background: var(--success-bg); }
.uploader.is-success i { color: var(--success); }
.uploader.is-success p { color: var(--success); }
.uploader.is-error { border-color: var(--danger); background: var(--danger-bg); }
.uploader.is-error:hover { border-color: var(--danger); background: var(--danger-bg); }
.uploader.is-error i { color: var(--danger); }
.uploader.is-error p { color: var(--danger); }
.uploader.is-error span { color: var(--danger); }
.uploader i { font-size: 22px; color: var(--text-faint); margin-bottom: 8px; display: block; }
.uploader p { margin: 0; font-size: 13px; color: var(--text-muted); font-weight: 600; }
.uploader span { font-size: 11.5px; color: var(--text-faint); }
.img-preview-grid { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.img-preview { position: relative; width: 72px; height: 72px; border-radius: 9px; overflow: hidden; border: 1px solid var(--line); }
.img-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-preview .rm { position: absolute; top: 3px; right: 3px; width: 18px; height: 18px; border-radius: 50%; background: rgba(0,0,0,0.55); color: #fff; font-size: 10px; display: flex; align-items: center; justify-content: center; border: none; }
.img-preview.featured::after { content: 'Main'; position: absolute; bottom: 0; left: 0; right: 0; background: var(--primary); color: #fff; font-size: 8.5px; text-align: center; font-weight: 600; padding: 2px 0; }

/* Hero Slide Manager (Phase Hero-1) — list rows inside the Settings >
   Branding > Homepage Hero section. Mirrors the visual weight of a table
   row without pulling in the full .dtable machinery, since this list is
   always short (a handful of slides) and card-shaped fits the existing
   thumbnail+meta+actions pattern used elsewhere in this file. */
.hero-slide-list { display: flex; flex-direction: column; gap: 10px; }
.hero-slide-row {
  display: flex; align-items: center; gap: 14px;
  border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 10px 14px; background: var(--bg);
}
.hero-slide-thumb { width: 64px; height: 44px; border-radius: 7px; overflow: hidden; flex-shrink: 0; background: var(--line); }
.hero-slide-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-slide-info { flex: 1; min-width: 0; }
.hero-slide-title-row { display: flex; align-items: center; gap: 8px; }
.hero-slide-title-row strong { font-size: 13px; }
.hero-slide-mode { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.hero-slide-headline { font-size: 12.5px; color: var(--text-muted); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hero-slide-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.hero-slide-actions .icon-btn:disabled { opacity: .35; cursor: default; }

.modal-overlay {
  position: fixed; inset: 0; background: rgba(30, 30, 45, 0.45); backdrop-filter: blur(2px);
  display: none; align-items: center; justify-content: center; z-index: 100; padding: 20px;
}
.modal-overlay.show { display: flex; }
.modal {
  background: #fff; border-radius: var(--radius-lg); width: 100%; max-width: 440px;
  box-shadow: var(--shadow-md); max-height: 90vh; overflow-y: auto;
  animation: modalIn .18s ease;
}
@keyframes modalIn { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px; border-bottom: 1px solid var(--line); }
.modal-head h3 { margin: 0; font-size: 15px; font-weight: 600; }
.modal-body { padding: 20px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; padding: 16px 20px; border-top: 1px solid var(--line); }
.modal-close { background: none; border: none; font-size: 16px; color: var(--text-faint); }
.confirm-icon { width: 44px; height: 44px; border-radius: 50%; background: var(--danger-bg); color: var(--danger); display: flex; align-items: center; justify-content: center; font-size: 18px; margin-bottom: 14px; }

.toast-stack { position: fixed; bottom: 22px; right: 22px; z-index: 200; display: flex; flex-direction: column; gap: 10px; }
.toast {
  background: var(--dark); color: #fff; padding: 12px 16px; border-radius: 10px;
  font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 10px;
  box-shadow: var(--shadow-md); min-width: 220px; animation: toastIn .2s ease;
}
.toast i { font-size: 14px; }
.toast.success i { color: #6fd7a8; }
.toast.error i { color: #ef8a80; }
@keyframes toastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

.back-link { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--text-muted); margin-bottom: 14px; }
.back-link:hover { color: var(--primary); }
.detail-grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: 18px; align-items: start; }
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { display: flex; gap: 12px; padding-bottom: 16px; position: relative; }
.timeline li:not(:last-child)::before { content: ''; position: absolute; left: 5px; top: 16px; bottom: 0; width: 1.5px; background: var(--line); }
.timeline .dot { width: 11px; height: 11px; border-radius: 50%; background: var(--primary); margin-top: 3px; flex-shrink: 0; }
.timeline .tl-body b { display: block; font-size: 13px; }
.timeline .tl-body span { font-size: 11.5px; color: var(--text-faint); }
.kv-row { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; }
.kv-row:last-child { border-bottom: none; }
.kv-row .k { color: var(--text-muted); }
.kv-row .v { font-weight: 600; }

.rank-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.rank-row:last-child { border-bottom: none; }
.rank-row .rank-num { font-family: var(--font-mono); font-size: 12px; color: var(--text-faint); width: 16px; }
.rank-row img { width: 34px; height: 34px; border-radius: 7px; object-fit: cover; }
.rank-row .ri { flex: 1; min-width: 0; }
.rank-row .ri b { display: block; font-size: 12.8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rank-row .ri span { font-size: 11px; color: var(--text-faint); }
.bar-track { height: 6px; background: var(--bg); border-radius: 4px; margin-top: 4px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--primary); border-radius: 4px; }

.mini-chart { position: relative; flex: 1 1 auto; min-height: 180px; padding: var(--space-lg) var(--space-lg) var(--space-xs); }
.mini-chart svg { display: block; width: 100%; height: 100%; overflow: visible; }
.mini-chart .mc-gridline { stroke: var(--line); stroke-width: 1; }
.mini-chart .mc-ylabel { font: 600 10.5px var(--font); fill: var(--text-faint); }
.mini-chart .mc-area { fill: var(--primary); fill-opacity: 0.18; stroke: none; }
.mini-chart .mc-line { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.mini-chart .mc-area-2 { fill: var(--chart-2); fill-opacity: 0.12; }
.mini-chart .mc-line-2 { fill: none; stroke: var(--chart-2); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.mini-chart .mc-dot { fill: var(--surface); stroke: var(--primary); stroke-width: 2; }
.mini-chart .mc-dot-hit { fill: transparent; cursor: pointer; }
.mini-chart .mc-dot-hit:hover + .mc-dot, .mini-chart .mc-dot:hover { stroke: var(--primary-dark); }
.mc-labels { display: flex; gap: 6px; padding: 0 var(--space-lg) 10px; flex: 0 0 auto; }
.mc-labels span { flex: 1; text-align: center; font-size: 10.5px; color: var(--text-faint); font-weight: 500; }

.sidebar-backdrop { position: fixed; inset: 0; background: rgba(30,30,45,0.45); z-index: 39; display: none; }
.sidebar-backdrop.show { display: block; }

.mobile-bottom-nav {
  display: none;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  background: #fff;
  border-top: 1px solid var(--line);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
  align-items: stretch;
  justify-content: space-between;
  box-shadow: 0 -4px 18px rgba(37, 49, 76, 0.08);
}
.bottom-nav-link {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  padding: 7px 2px;
  border-radius: 10px;
  border: none;
  background: none;
  color: var(--text-faint);
  font-family: inherit;
  font-size: 10.5px; font-weight: 600;
  min-width: 0;
}
.bottom-nav-link i { font-size: 16px; }
.bottom-nav-link span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.bottom-nav-link.active { color: var(--primary); background: var(--primary-soft); }
.bottom-nav-link:active { background: var(--bg); }

/* POS — center item, always visually primary (not just on active), same
   blue used by .btn-primary elsewhere in the app. A round icon chip
   rather than a full floating button, so it still sits inside the bar. */
.bottom-nav-pos { justify-content: center; }
.bottom-nav-pos i {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--primary); color: #fff;
  box-shadow: 0 3px 10px rgba(23, 105, 224, 0.35);
  transform: translateY(-4px);
  transition: transform .12s ease, background .12s ease;
}
.bottom-nav-pos.active { background: none; }
.bottom-nav-pos.active i, .bottom-nav-pos:active i { background: var(--primary-dark); }
.bottom-nav-pos:active i { transform: translateY(-4px) scale(0.94); }

@media (max-width: 1100px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .detail-grid { grid-template-columns: 1fr; }
  .chart-kpis { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
  .sidebar { transform: translateX(-100%); box-shadow: var(--shadow-md); }
  .sidebar.open { transform: translateX(0); }
  .main { margin-left: 0; }
  .menu-toggle { display: flex; align-items: center; justify-content: center; }
  .topbar-search { display: none; }
  .form-grid { grid-template-columns: 1fr; }
  .form-grid .span-2 { grid-column: span 1; }
  .mobile-bottom-nav { display: flex; }
  /* Mobile-only: icon-only nav — labels stay in the DOM (and each link
     keeps its aria-label) for accessibility, just visually hidden here.
     Desktop/tablet never render .mobile-bottom-nav at all, so nothing
     above this breakpoint is affected. */
  .bottom-nav-link span { display: none; }
  .bottom-nav-link { padding: 9px 2px; }
  .content { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }
  .page-head { margin-bottom: 16px; }
  .page-head h1 { font-size: 20px; }
}
@media (max-width: 640px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .stat-card { padding: 14px; gap: 6px; min-height: 92px; }
  .stat-card .label { font-size: 12.5px; }
  .stat-card .value { font-size: 20px; }
  .stat-card .stat-trend { height: 26px; }
  .stat-card.has-sub .stat-trend { height: 30px; }
  .stat-spark { height: 26px; right: 12px; bottom: 12px; }
  .content { padding: 16px 14px calc(76px + env(safe-area-inset-bottom, 0px)); }
  .topbar { padding: 0 14px; }
  table.dtable { min-width: 560px; }
  .topbar-account .who { display: none; }
  /* Tab strips (Inventory Monitoring, Inventory report, Delivery) wrapped
     onto multiple rows once their buttons no longer fit one line, making
     the tab area unpredictably tall. Below 640px they scroll horizontally
     instead — content stays one row, nothing changes above this width. */
  .tab-strip { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .tab-strip::-webkit-scrollbar { display: none; }
  .tab-btn { flex-shrink: 0; white-space: nowrap; }
}
@media (max-width: 390px) {
  .bottom-nav-link span { font-size: 9.5px; }
}

/* ==========================================================================
   ADMIN EXTENSIONS
   ========================================================================== */
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 13px; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.toggle-row .toggle-label { font-size: 13.5px; font-weight: 500; color: var(--text); }
.toggle-row .toggle-hint { font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.switch { position: relative; display: inline-block; width: 40px; height: 23px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; cursor: pointer; inset: 0; background: var(--line); border-radius: 999px; transition: background .15s; }
.switch .slider::before { content: ''; position: absolute; height: 17px; width: 17px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform .15s; box-shadow: 0 1px 2px rgba(0,0,0,0.2); }
.switch input:checked + .slider { background: var(--primary); }
.switch input:checked + .slider::before { transform: translateX(17px); }
.switch input:disabled + .slider { opacity: .5; cursor: not-allowed; }

.stock-cell { display: flex; align-items: center; gap: 6px; }
.stock-qty-input { width: 56px; padding: 4px 6px; border: 1px solid var(--line); border-radius: 6px; font-family: var(--font-mono); font-size: 12.5px; text-align: center; }
.stock-qty-input:focus { outline: none; border-color: var(--primary); }
.low-stock-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--danger); display: inline-block; flex-shrink: 0; }

.stock-history-list { max-height: 220px; overflow-y: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.stock-history-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 12px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; }
.stock-history-row:last-child { border-bottom: none; }
.stock-history-row .delta.pos { color: var(--success); font-weight: 600; font-family: var(--font-mono); }
.stock-history-row .delta.neg { color: var(--danger); font-weight: 600; font-family: var(--font-mono); }
.stock-history-empty { padding: 16px 12px; font-size: 12.5px; color: var(--text-faint); text-align: center; }

.attr-block { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 13px; margin-bottom: 10px; }
.attr-block .attr-name { font-size: 12.5px; font-weight: 600; color: var(--text); margin-bottom: 8px; display: block; }
.attr-value-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.attr-value-chip { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 999px; font-size: 12px; cursor: pointer; user-select: none; }
.attr-value-chip input { margin: 0; }
.attr-value-chip.checked { border-color: var(--primary); background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.attr-empty-note { font-size: 12.5px; color: var(--text-faint); }

.variant-generate-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.variant-input { width: 100%; min-width: 72px; padding: 7px 9px; font-size: 12.5px; border: 1px solid var(--line); border-radius: var(--radius-sm); }
/* Variant combination label (first column, #pfVariantsTable) — plain
   text, no .row-title wrapper, so it gets the same nowrap+ellipsis cap
   directly instead of inheriting it. Skipped while the cell is in its
   inline "edit combination" state (holds <select> pickers instead of
   text) so those controls never get clipped. */
#pfVariantsTable td:first-child:not(:has(select)) {
  max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.variant-image-cell { display: flex; align-items: center; gap: 8px; min-width: 160px; }
.variant-image-cell .variant-image-preview { width: 28px; height: 28px; }
.variant-image-cell select { flex: 1; min-width: 110px; }
select.variant-combo-attr { padding: 6px 8px; font-size: 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); margin: 2px 6px 2px 0; }
.row-actions { display: flex; align-items: center; gap: 8px; white-space: nowrap; }

table.dtable tr.variant-row-dirty { background: var(--warning-bg); }
table.dtable tr.variant-row-dirty:hover { background: var(--warning-bg); }

.char-counter { font-size: 11px; color: var(--text-faint); text-align: right; margin-top: 4px; }
.char-counter.over { color: var(--danger); font-weight: 600; }
.seo-preview { border: 1px solid var(--line); border-radius: var(--radius-md); padding: 16px; background: var(--bg); }
.seo-preview .sp-url { font-size: 12.5px; color: #1a0dab; opacity: .75; font-family: Arial, sans-serif; margin-bottom: 2px; }
.seo-preview .sp-title { font-size: 17px; color: #1a0dab; font-family: Arial, sans-serif; line-height: 1.3; margin-bottom: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seo-preview .sp-desc { font-size: 13px; color: #4d5156; font-family: Arial, sans-serif; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.seo-preview .sp-label { font-size: 12px; text-transform: none; letter-spacing: 0; color: var(--text-faint); font-weight: 500; margin-bottom: 10px; }

.attr-values-editor { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.attr-value-row { display: flex; gap: 8px; align-items: center; }
.attr-value-row input { flex: 1; }
.attr-value-row .rm-value { background: none; border: none; color: var(--text-faint); cursor: pointer; padding: 6px; }
.attr-value-row .rm-value:hover { color: var(--danger); }

.sortable-th { cursor: pointer; user-select: none; white-space: nowrap; }
.sortable-th i { font-size: 10px; color: var(--text-faint); margin-left: 4px; }
.sortable-th.sort-asc i, .sortable-th.sort-desc i { color: var(--primary); }
.cat-indent { display: inline-block; }
.cat-tree-prefix { color: var(--text-faint); margin-right: 4px; font-family: var(--font-mono); }
.pagination-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--text-muted); flex-wrap: wrap; }
.pagination-bar .pg-pages { display: flex; align-items: center; gap: 6px; }
.pagination-bar button { background: none; border: 1px solid var(--line); border-radius: 7px; padding: 5px 10px; font-size: 12px; color: var(--text-muted); cursor: pointer; }
.pagination-bar button:disabled { opacity: .4; cursor: not-allowed; }
.pagination-bar button.active { border-color: var(--primary); color: var(--primary); font-weight: 600; background: var(--primary-soft); }
.validation-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.validation-item { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 7px 10px; border-radius: 7px; }
.validation-item.warning { background: var(--warning-bg); color: var(--warning); }
.validation-item.success { background: var(--success-bg); color: #1a9d57; }
.validation-item i { font-size: 11px; }

.range-toggle { display: flex; gap: 4px; flex-wrap: wrap; }
.range-btn { background: var(--bg); border: 1px solid var(--line); border-radius: 8px; padding: 6px 12px; font-size: 12px; font-weight: 600; color: var(--text-muted); cursor: pointer; }
.range-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; }

.tab-strip { display: flex; gap: 4px; flex-wrap: wrap; padding: 0 20px 12px; border-bottom: 1px solid var(--line); }
.card:not(.card-flush) > .tab-strip { padding-left: 0; padding-right: 0; }
.tab-btn { background: none; border: none; border-radius: 8px; padding: 7px 12px; font-size: 12px; font-weight: 600; color: var(--text-muted); cursor: pointer; }
.tab-btn.active { background: var(--primary); color: #fff; }

.label-sm { font-size: 12px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--text-faint); margin-bottom: 6px; }
.value-lg { font-family: var(--font-mono); font-size: 26px; font-weight: 500; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--text); }

.stock-status-bar { display: flex; height: 10px; border-radius: 6px; overflow: hidden; background: var(--bg); margin-top: 8px; }
.stock-status-bar span { height: 100%; }
.stock-status-legend { display: flex; gap: 14px; margin-top: 10px; flex-wrap: wrap; }
.stock-status-legend .leg-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.stock-status-legend .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

.alert-banner { display: flex; align-items: center; gap: 12px; padding: 13px 16px; border-radius: var(--radius-md); background: var(--warning-bg); color: #d67d24; border: 0; margin-bottom: 18px; font-size: 13px; box-shadow: var(--shadow-sm); }
.alert-banner i { font-size: 16px; flex-shrink: 0; }
.alert-banner b { font-weight: 600; }
.alert-banner a { margin-left: auto; color: #d67d24; font-weight: 600; text-decoration: underline; white-space: nowrap; }

.radio-card-group { display: flex; flex-direction: column; gap: 10px; }
.radio-card {
  display: flex; align-items: flex-start; gap: 12px;
  border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 12px 14px; cursor: pointer; transition: border-color .12s, background .12s;
}
.radio-card:hover { border-color: var(--primary-light); }
.radio-card input[type="radio"] { margin-top: 2px; width: 16px; height: 16px; accent-color: var(--primary); flex-shrink: 0; cursor: pointer; }
.radio-card.selected { border-color: var(--primary); background: var(--primary-soft); }
.radio-card-body { display: flex; flex-direction: column; gap: 3px; }
.radio-card-title { font-size: 13.5px; font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 8px; }
.radio-card-title i { color: var(--primary); font-size: 13px; width: 16px; text-align: center; }
.radio-card-desc { font-size: 12px; color: var(--text-muted); line-height: 1.4; }

/* ==========================================================================
   DASHBOARD — PHASE 2 (visual refresh, template-inspired)
   Every rule below is scoped to #view-dashboard or a dashboard-exclusive
   element id (#statGrid, #salesRangeButtons, #invTabStrip, #invHistoryTabStrip,
   #popularList, #invMonitorList, #activityList, #dashAlertBanner,
   #recentOrdersTable, #invHistoryTable, #invStatusBar/#invStatusLegend).
   Several class names here (.card-head-dark, .stat-card, .tab-strip/.tab-btn,
   .range-toggle/.range-btn, .rank-row, .dtable) are shared with Stores, Team,
   Notifications, Order detail and other modules — the id-scoping keeps this
   section from touching any of them.
   ========================================================================== */

/* Stat cards — colored top accent + gradient icon per metric type, matching
   the purchased template's widget language without its flat neon fills. */
#statGrid.stat-grid { gap: 18px; }
#statGrid .stat-card { position: relative; }

/* Card-head icon badges — small gradient tile behind each section's icon,
   varied per icon so the dashboard's cards read as distinct "widgets". */
#view-dashboard .card-head-dark h3 i {
  width: 30px; height: 30px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px; font-size: 13px; color: #fff !important;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  box-shadow: 0 3px 8px -2px rgba(23,105,224,.4);
}
#view-dashboard .card-head-dark h3 i[data-icon="clipboard-list-twotone"] { background: linear-gradient(135deg, #2f6fed, #1d55c9); box-shadow: 0 3px 8px -2px rgba(47,111,237,.4); }
#view-dashboard .card-head-dark h3 i[data-icon="boxes"] { background: linear-gradient(135deg, var(--gold), var(--gold-dark)); box-shadow: 0 3px 8px -2px rgba(255,159,67,.4); }
#view-dashboard .card-head-dark h3 i[data-icon="star"] { background: linear-gradient(135deg, #ff6b9d, #c94277); box-shadow: 0 3px 8px -2px rgba(255,107,157,.4); }
#view-dashboard .card-head-dark h3 i[data-icon="history"] { background: linear-gradient(135deg, #00cfe8, #0aa2b5); box-shadow: 0 3px 8px -2px rgba(0,207,232,.4); }
#view-dashboard .card-head-dark h3 i[data-icon="document-list-twotone"] { background: linear-gradient(135deg, var(--success), #1eae60); box-shadow: 0 3px 8px -2px rgba(40,199,111,.4); }

/* Sales analytics range toggle + inventory tab strips — pill shadow on active state */
#salesRangeButtons.range-toggle { padding: 4px; gap: 3px; }
#salesRangeButtons .range-btn { border-radius: 7px; }
#salesRangeButtons .range-btn.active { box-shadow: 0 2px 6px -1px rgba(23,105,224,.45); }
#invTabStrip.tab-strip, #invHistoryTabStrip.tab-strip { gap: 6px; }
/* Inventory Monitoring tabs sat flush against the card-head border (0 top
   padding on .tab-strip) while 12px remained below — rebalance just this
   strip so the buttons sit centered between the two borders. */
#invTabStrip.tab-strip { padding-top: 12px; }
#invTabStrip .tab-btn, #invHistoryTabStrip .tab-btn { border-radius: 999px; border: 1px solid var(--line); }
#invTabStrip .tab-btn.active, #invHistoryTabStrip .tab-btn.active { border-color: var(--primary); box-shadow: 0 2px 6px -1px rgba(23,105,224,.4); }

/* List rows (inventory monitoring / popular products / recent activity) */
#invMonitorList .rank-row, #popularList .rank-row, #activityList .rank-row {
  border-radius: 8px; margin: 0 -8px; padding: 10px 8px; transition: background .12s ease;
}
#invMonitorList .rank-row:hover, #popularList .rank-row:hover, #activityList .rank-row:hover { background: var(--bg); }
#popularList .rank-row .rank-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 6px; background: var(--primary-soft); color: var(--primary);
  font-weight: 600; font-size: 11px;
}
#popularList .bar-fill { background: linear-gradient(90deg, var(--primary), var(--primary-light)); }

/* Alert banner — icon badge + left accent, a touch more premium than a flat strip */
#dashAlertBanner .alert-banner { position: relative; padding-left: 50px; }
#dashAlertBanner .alert-banner i {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; border-radius: 8px; background: rgba(255,159,67,.18);
  display: flex; align-items: center; justify-content: center; font-size: 13px;
}

/* Inventory report — rounded status-bar segments + a touch of card lift */
#invStatusBar.stock-status-bar span:first-child { border-radius: 6px 0 0 6px; }
#invStatusBar.stock-status-bar span:last-child { border-radius: 0 6px 6px 0; }

/* Recent orders / inventory history tables — dashboard-only refinements,
   left untouched for every other module's tables. */
#recentOrdersTable thead th, #invHistoryTable thead th { background: #fafbfe; }
#recentOrdersTable tbody tr:hover, #invHistoryTable tbody tr:hover { background: var(--primary-soft); }

@media (max-width: 640px) {
  #dashAlertBanner .alert-banner { padding-left: 46px; }
}

/* ==========================================================================
   PRODUCTS — PHASE 3 (list, filters, search, table, actions, form)
   Scoped to #view-products / #view-product-form and product-exclusive
   element ids (#productsTbody, #prodBulkBar, #prodSearch,
   #prodCategoryFilter, #prodStatusFilter, #stockAdjustModal, #pfUploader,
   #pfImageGrid, #pfAttributesList, #pfVariantsTable). Classes like
   .toolbar, .search-box, .filter-select, .form-section, .field, .uploader,
   .back-link, .tbl-icon-btn and the base .modal system are shared with
   Orders, Customers, Categories, Brands, Settings and Delivery — every rule
   here is id/ancestor-scoped so those modules are untouched. The "Manage
   brands" modal (#brandModal) is left alone entirely — it belongs to the
   Brands module even though Products links into it.
   ========================================================================== */

/* Toolbar — search + filters */
#view-products .toolbar { margin-bottom: 18px; }
#view-products .search-box { transition: border-color .15s, box-shadow .15s; }
#view-products .search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
#view-products .filter-select { cursor: pointer; transition: border-color .15s; }
#view-products .filter-select:hover { border-color: var(--primary-light); }

/* Bulk action bar */
#prodBulkBar.show { box-shadow: var(--shadow-sm); }
#prodBulkCount { display: inline-flex; align-items: center; gap: 6px; }
#prodBulkCount::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); display: inline-block;
}

/* Products table — thead tint, hover row, thumbnail zoom, tidy actions */
#view-products table.dtable thead th { background: #fafbfe; }
#productsTbody tr { transition: background .12s ease; }
#productsTbody tr:hover .row-thumb { transform: scale(1.06); }
#productsTbody .row-thumb { transition: transform .15s ease; }
#productsTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#productsTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* Stock cell — low-stock indicator gets a soft pulse so it actually draws
   the eye in a dense table; quick-edit qty input gets a tighter focus ring. */
#productsTbody .low-stock-dot { animation: prodLowStockPulse 1.8s ease-in-out infinite; }
@keyframes prodLowStockPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(234,84,85,.45); }
  50% { box-shadow: 0 0 0 4px rgba(234,84,85,0); }
}
#productsTbody .stock-qty-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Product form — image uploader, SEO preview, variants table */
#view-product-form .back-link { transition: gap .12s ease; }
#view-product-form .back-link:hover { gap: 10px; }

#pfUploader:hover { box-shadow: 0 0 0 3px var(--primary-soft) inset; }
#pfImageGrid .img-preview { transition: transform .12s ease, box-shadow .12s ease; }
#pfImageGrid .img-preview:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }

#view-product-form .seo-preview { box-shadow: var(--shadow-sm); }

#pfAttributesList .attr-value-chip { transition: transform .1s ease; }
#pfAttributesList .attr-value-chip:hover { transform: translateY(-1px); }

#pfVariantsTable thead th { background: #fafbfe; }
#pfVariantsTable tbody tr:hover { background: var(--primary-soft); }

/* Product form — Phase 26: reorganized into a stack of independent
   cards (pf-card) matching the reference screenshot's Price/Inventory/
   Shipping layout (header + primary field + a collapsed pill row of
   secondary fields with an expand chevron), extended with the same
   pattern to the sections the screenshot didn't cover. Purely
   presentational — every field keeps its existing id, so no JS
   save/validation/variant/barcode logic changes. */

/* #productForm's direct children (tabs, Basic view, Advanced view, sticky
   actions bar) stack with a consistent gap, all at the same width — same
   feel as the simplified Category form's centered 780px card. */
#productForm { display: flex; flex-direction: column; gap: 18px; max-width: 780px; margin: 0 auto; }

/* BASIC — single clean card (Phase 29), same treatment as the simplified
   Category form's #view-category-form .card: generous padding, one
   column. Scoped to #pfBasicView only — Advanced keeps its existing
   stacked pf-card sections untouched. */
#view-product-form #pfBasicView .card { padding: 32px 36px; }

/* BASIC — Product information / Price / Inventory sub-groups inside the
   single Basic card (Phase 30). Lightweight label only, no card split and
   no border — same treatment as the Category form's Advanced Options
   sub-groups (.cfp-advanced-group h5). */
#pfBasicView .pf-basic-group { margin-bottom: 26px; }
#pfBasicView .pf-basic-group:last-child { margin-bottom: 0; }
#pfBasicView .pf-basic-group h5 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-faint); font-weight: 700; margin: 0 0 12px;
}

/* Basic / Advanced tabs (Phase 28) — simple two-button switch above the
   form. #pfBasicView / #pfAdvancedView hold the actual field markup; this
   only toggles which one is visible (see pfSetView in admin.js). */
.pf-tabs { display: flex; gap: 4px; background: var(--bg); border: 1px solid var(--line-soft); border-radius: var(--radius-md); padding: 4px; width: max-content; }
.pf-tab {
  border: none; background: transparent; padding: 7px 18px; border-radius: calc(var(--radius-md) - 2px);
  font-size: 13px; font-weight: 600; color: var(--text-muted); cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.pf-tab:hover { color: var(--text); }
.pf-tab-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
.pf-view { display: flex; flex-direction: column; gap: 18px; }
.pf-view[hidden] { display: none; }

.pf-card {
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
  padding: 22px 24px;
}
.pf-card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 16px;
}
.pf-card-head h4 { margin: 0; font-size: 14px; font-weight: 650; color: var(--text); letter-spacing: 0; text-transform: none; }
.pf-card-head-toggle { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-muted); font-weight: 500; cursor: pointer; }
.switch-sm { width: 34px; height: 20px; }
.switch-sm .slider::before { height: 14px; width: 14px; }
.switch-sm input:checked + .slider::before { transform: translateX(14px); }

/* Inset box for a card's single primary field (e.g. Inventory's
   Quantity row), echoing the screenshot's shaded inner block. */
.pf-inset-box { background: var(--bg); border: 1px solid var(--line-soft); border-radius: var(--radius-md); padding: 14px; margin-bottom: 14px; }
.pf-inset-box .field label { color: var(--text); font-weight: 600; }

/* Pill row — secondary/less-common fields, collapsed until clicked.
   Each pill toggles its own field via data-target; the trailing
   chevron button expands/collapses every pill in the row at once. */
.pf-pillrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 14px; }
.pf-pill {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--bg);
  color: var(--text-muted); font-size: 12.5px; font-weight: 500; cursor: pointer;
  transition: border-color .12s ease, background .12s ease, color .12s ease;
}
.pf-pill:hover { border-color: var(--primary-light); }
.pf-pill.pf-pill-active { border-color: var(--primary); background: var(--primary-soft); color: var(--primary-dark); font-weight: 600; }
.pf-pill-value { font-weight: 700; color: var(--text); }
.pf-pill.pf-pill-active .pf-pill-value { color: var(--primary-dark); }
.pf-pillrow-more {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--line);
  background: var(--bg); display: flex; align-items: center; justify-content: center;
  margin-left: auto; cursor: pointer; flex-shrink: 0;
}
.pf-pillrow-more::after {
  content: ""; width: 6px; height: 6px; border-right: 1.5px solid var(--text-faint);
  border-bottom: 1.5px solid var(--text-faint); transform: rotate(45deg); margin-top: -2px;
  transition: transform .15s ease;
}
.pf-pillrow-more.open::after { transform: rotate(-135deg); margin-top: 2px; }
.pf-pillrow-more:hover { border-color: var(--primary-light); }

/* Fields revealed by a pill click — grid so span-2 fields line up the
   same way .form-grid does elsewhere in this form. */
.pf-pill-fields:has([data-pf-collapsible]:not([hidden])) { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 14px; }
.pf-pill-fields .field.span-2 { grid-column: span 2; }
.pf-pill-fields [data-pf-collapsible][hidden] { display: none; }
.pf-pill-fields [data-pf-collapsible] { animation: pfPillFieldIn .15s ease; }
@keyframes pfPillFieldIn { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: translateY(0); } }

/* Whole-card collapse (Search Engine Listing) — a native <details> so
   it behaves like the rest of the app's disclosures. */
.pf-card-collapsible { padding: 22px 24px; }
.pf-card-collapsible > .pf-card-head { cursor: pointer; list-style: none; margin-bottom: 0; }
.pf-card-collapsible > .pf-card-head::-webkit-details-marker { display: none; }
.pf-card-collapsible > .pf-card-head::after {
  content: ""; width: 8px; height: 8px; flex-shrink: 0; margin-top: -3px;
  border-right: 1.5px solid var(--text-faint); border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(45deg); transition: transform .15s ease;
}
.pf-card-collapsible[open] > .pf-card-head::after { transform: rotate(-135deg); margin-top: 2px; }
.pf-card-collapsible > .pf-card-head:hover h4 { color: var(--primary); }
.pf-card-collapsible-body { margin-top: 18px; animation: pfAccordionIn .18s ease; }
@keyframes pfAccordionIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* Image — top, primary element. Empty state is the shared product
   placeholder icon (images/placeholder-product.svg) plus "Add Product
   Image"; no gallery/reorder controls shown until pfImageGrid actually
   has thumbnails in it (unchanged — renderImageGrid only populates that
   grid once images exist). */
.pf-hero-section #pfUploader {
  padding: 30px 22px; min-height: 120px;
}
.pf-hero-placeholder-icon { width: 56px; height: 56px; margin-bottom: 10px; opacity: 0.55; }
.pf-hero-section #pfUploader p { font-size: 14px; }
.pf-hero-section .img-preview-grid:not(:empty) { margin-top: 14px; }

/* Inline (required)/(optional)/(recommended) tags next to field labels —
   text-based signal (not just a red asterisk) matching how the labels
   read for a first-time merchant. */
.field-tag {
  display: inline-block; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; padding: 1px 6px; border-radius: 20px; margin-left: 4px;
  vertical-align: middle; position: relative; top: -1px;
}
.field-tag-required { color: var(--danger); background: var(--danger-bg); }
.field-tag-optional { color: var(--text-faint); background: var(--bg); }
.field-tag-recommended { color: #a8710a; background: #fdf3e0; }

/* "+ Create Category" / "Manage brands" — small inline text links under
   their field, same treatment for both. */
.pf-inline-link { display: inline-block; font-size: 12px; font-weight: 600; margin-top: 6px; }
.pf-attr-list-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.pf-attr-list-head label { font-size: 12.5px; font-weight: 600; color: var(--text); }
.pf-attr-list-head .pf-inline-link { margin-top: 0; }

/* Slug lives inside the Search Engine Listing card as the "advanced"
   URL field — a faint left rule distinguishes it from the fields below it. */
.pf-advanced-settings {
  padding-left: 12px; border-left: 2px solid var(--line); margin-bottom: 4px;
}

/* Sticky Save Product bar — now its own card-styled bar (the old
   version bled into the single outer .card via negative margins; that
   card no longer exists, so this bar supplies its own chrome). Purely
   a position/visual change; the buttons and their click handlers are
   untouched. */
#view-product-form .pf-sticky-actions {
  position: sticky; bottom: 0; z-index: 5;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
  padding: 14px 20px;
}

/* ==========================================================================
   CATEGORY FORM SIMPLIFY — mirrors the product-form simplify pass above
   (#view-product-form .pf-* rules) 1:1 for #view-category-form. Same
   reasoning: existing #cfp* ids and form-section/form-grid rhythm are
   untouched, this only adds the hero image treatment, the Advanced Options
   accordion chrome, and a sticky save bar. */
#view-category-form .card { max-width: 780px; margin: 0 auto; padding: 32px 36px; }

.cfp-hero-section #cfpUploader {
  padding: 30px 22px; min-height: 120px;
}
.cfp-hero-placeholder-icon { width: 56px; height: 56px; margin-bottom: 10px; opacity: 0.55; }
.cfp-hero-section #cfpUploader p { font-size: 14px; }
.cfp-hero-section .img-preview-grid:not(:empty) { margin-top: 14px; }

#view-category-form .form-accordion summary {
  cursor: pointer; list-style: none; display: flex; align-items: center;
  justify-content: space-between; gap: 10px;
}
#view-category-form .form-accordion summary::-webkit-details-marker { display: none; }
#view-category-form .form-accordion summary h4 { margin: 0; }
#view-category-form .form-accordion summary::after {
  content: ""; width: 8px; height: 8px; flex-shrink: 0; margin-top: -3px;
  border-right: 1.5px solid var(--text-faint); border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(45deg); transition: transform .15s ease;
}
#view-category-form .form-accordion[open] summary::after { transform: rotate(-135deg); margin-top: 2px; }
#view-category-form .form-accordion summary:hover h4 { color: var(--primary); }
#view-category-form .form-accordion-body {
  margin-top: 18px;
  animation: pfAccordionIn .18s ease;
}

.cfp-advanced-group { margin-bottom: 26px; }
.cfp-advanced-group:last-child { margin-bottom: 0; }
.cfp-advanced-group h5 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-faint); font-weight: 700; margin: 0 0 12px;
}

.cfp-advanced-settings {
  padding-left: 12px; border-left: 2px solid var(--line); margin-bottom: 4px;
}

#view-category-form .cfp-sticky-actions {
  position: sticky; bottom: 0; background: var(--surface);
  margin-left: calc(-1 * var(--card-pad)); margin-right: calc(-1 * var(--card-pad)); margin-bottom: calc(-1 * var(--card-pad));
  padding: 16px var(--card-pad); border-top: 1px solid var(--line);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg); z-index: 5;
}

/* Adjust-stock modal — dashboard-style icon badge in the header, without
   touching the shared .modal/.modal-head/.modal-body used by every other
   modal in the app. */
#stockAdjustModal .modal-head h3 { display: flex; align-items: center; gap: 10px; }
#stockAdjustModal .modal-head h3::before {
  content: "";
  width: 28px; height: 28px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17 3l3 3-3 3'/%3E%3Cpath d='M4 11v-1a4 4 0 0 1 4-4h12'/%3E%3Cpath d='M7 21l-3-3 3-3'/%3E%3Cpath d='M20 13v1a4 4 0 0 1-4 4H4'/%3E%3C/g%3E%3C/svg%3E") center / 15px 15px no-repeat, linear-gradient(135deg, var(--primary), var(--primary-dark));
}

/* ==========================================================================
   PRODUCTS — PHASE 3B (Table / Grid view toggle)
   Scoped to #view-products / #prodViewToggle / #productsGrid / .product-card
   only. The table view (table.dtable, #productsTbody) is untouched — these
   rules only add the toggle control and the new grid, they don't modify a
   single existing table/toolbar rule from Phase 3.
   ========================================================================== */

#view-products .toolbar-right { display: flex; align-items: center; gap: 10px; }

.view-toggle {
  display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: #fff; padding: 3px; gap: 2px;
}
.view-toggle-btn {
  width: 32px; height: 30px; border: none; border-radius: 7px; background: transparent;
  color: var(--text-faint); font-size: 13px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.view-toggle-btn:hover { color: var(--text-muted); }
.view-toggle-btn.active { background: var(--primary-soft); color: var(--primary); }

/* Grid — comfortable multi-column on desktop, narrowing at tablet/mobile */
.products-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px; padding: 18px;
}
@media (max-width: 1024px) {
  .products-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 720px) {
  .products-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; padding: 14px; }
}
@media (max-width: 420px) {
  .products-grid { grid-template-columns: 1fr; }
}

.product-card {
  border: 1px solid var(--line); border-radius: var(--radius-md); background: #fff; overflow: hidden;
  display: flex; flex-direction: column; transition: box-shadow .15s ease, transform .15s ease;
}
.product-card:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }

.product-card-img { position: relative; aspect-ratio: 1 / 1; background: var(--bg); overflow: hidden; }
.product-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.product-card-status { position: absolute; top: 8px; left: 8px; }

.product-card-body { padding: 12px 14px 4px; flex: 1; }
.product-card-name {
  font-size: 13.5px; font-weight: 600; color: var(--text); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 3px;
}
.product-card-meta { font-size: 11.5px; color: var(--text-faint); margin-bottom: 8px; }
.product-card-meta .dot-sep { margin: 0 5px; }
.product-card-price { font-size: 14px; font-weight: 600; color: var(--text); margin-bottom: 8px; }
.product-card-was { margin-left: 6px; font-size: 12px; font-weight: 500; text-decoration: line-through; color: var(--text-faint); }
.product-card-stock {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted);
  margin-bottom: 12px; flex-wrap: wrap;
}
.product-card-stock .low-stock-dot { animation: prodLowStockPulse 1.8s ease-in-out infinite; }

.product-card-actions {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  padding: 10px 14px; border-top: 1px solid var(--line-soft);
}

/* ==========================================================================
   ORDERS — PHASE 4 (toolbar, filters, bulk bar, table, order detail)
   Scoped to #view-orders / #view-order-detail and orders-exclusive element
   ids (#ordersTbody, #orderBulkBar, #orderMoreFilters, #odNotesList,
   #odTimeline). Classes like .toolbar, .search-box, .filter-select,
   .bulk-bar, .dtable, .badge, .card-head-dark, .kv-row, .timeline,
   .rank-row, .back-link and .form-grid/.field are shared with Dashboard,
   Products, Customers, Blog, Notifications and Settings — every rule below
   is id/ancestor-scoped so those modules (including the Dashboard's own
   #recentOrdersTable) are untouched.
   ========================================================================== */

/* Toolbar, search, status filter — same treatment as Products for
   cross-module consistency */
#view-orders .toolbar { margin-bottom: 18px; }
#view-orders .search-box { transition: border-color .15s, box-shadow .15s; }
#view-orders .search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
#view-orders .filter-select { cursor: pointer; transition: border-color .15s; }
#view-orders .filter-select:hover { border-color: var(--primary-light); }
#orderMoreFiltersBtn { transition: background .12s ease, color .12s ease, border-color .12s ease; }

/* More-filters panel — tinted like a nested card so it doesn't compete
   visually with the main toolbar */
#orderMoreFilters { background: #fafbfe; box-shadow: none; }
#orderMoreFilters .field label { color: var(--text-muted); }
#orderMoreFilters input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Bulk action bar — mirrors the Products bulk bar's dot accent + shadow */
#orderBulkBar.show { box-shadow: var(--shadow-sm); }
#orderBulkCount { display: inline-flex; align-items: center; gap: 6px; }
#orderBulkCount::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); display: inline-block;
}

/* Orders table — thead tint + hover row + tidy actions, matching Products */
#view-orders table.dtable thead th { background: #fafbfe; }
#ordersTbody tr { transition: background .12s ease; }
#ordersTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#ordersTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }
#ordersTbody .num a { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; }
#ordersTbody .num a:hover { color: var(--primary); }

/* ---- Order detail ---- */

/* Header card — order code + placed/updated meta + status badge */
#view-order-detail .back-link { transition: gap .12s ease; }
#view-order-detail .back-link:hover { gap: 10px; }

/* Section headers get the same gradient accent bar used on the Product
   form, so Delivery info / Payment info / Update status / Order timeline /
   Admin notes read as one consistent visual language across modules. */
#view-order-detail .card-head:not(.card-head-dark) h3 {
  position: relative; padding-left: 12px;
}
#view-order-detail .card:not(.card-flush) > .card-head:not(.card-head-dark) h3::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--primary), var(--primary-light));
}

/* Order items table — same thead tint + thumbnail zoom as Products */
#view-order-detail table.dtable thead th { background: #fafbfe; }
#view-order-detail table.dtable tbody tr:hover { background: #fafbfe; }
#view-order-detail .row-thumb { transition: transform .15s ease; }
#view-order-detail table.dtable tbody tr:hover .row-thumb { transform: scale(1.06); }

/* kv-rows — tighter label/value rhythm for the customer/delivery/payment cards */
#view-order-detail .kv-row .k { font-size: 12.5px; }
#view-order-detail .kv-row .v { text-align: right; }

/* Timeline — slightly larger, elevated dots so the connector line reads
   clearly against the event list */
#odTimeline .dot { box-shadow: 0 0 0 3px #fff, 0 0 0 4px var(--line); }

/* Admin notes — reuses the shared .rank-row layout; hover feedback + a
   delete button that only asserts itself on hover, scoped to this list so
   the Dashboard's popular-products/activity rank-rows are untouched */
#odNotesList .rank-row { transition: background .12s ease; border-radius: var(--radius-sm); padding-left: 8px; padding-right: 8px; margin: 0 -8px; }
#odNotesList .rank-row:hover { background: #fafbfe; }
#odNotesList .rank-row .tbl-icon-btn { opacity: .5; transition: opacity .12s ease; }
#odNotesList .rank-row:hover .tbl-icon-btn { opacity: 1; }

/* Update-status card — make the primary action feel like the main next step */
#view-order-detail #odStatusSave { font-weight: 600; }

/* ==========================================================================
   CUSTOMERS — PHASE 5 (toolbar, search, list, avatar treatment)
   Scoped to #view-customers and the Customers-exclusive #customersTbody id.
   Classes like .toolbar, .search-box, .row-title, .av, .empty-state and
   table.dtable are shared with Dashboard, Products, Orders and the
   sidebar/topbar — every rule here is id/ancestor-scoped, and the .av
   override uses !important only to beat the pre-existing inline
   background/color on that element (no markup or JS was touched to do
   this — see report).
   ========================================================================== */

#view-customers .toolbar { margin-bottom: 18px; }
#view-customers .search-box { transition: border-color .15s, box-shadow .15s; }
#view-customers .search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Avatar — bring it in line with the soft-primary avatar language already
   used by the topbar/sidebar (.topbar-account .av), instead of the
   green/gold combo it previously had inline */
#customersTbody .av {
  background: var(--primary-soft) !important;
  color: var(--primary) !important;
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--primary-soft);
}

/* Row hover already lifts the whole row (base table.dtable rule); scale the
   avatar slightly on top of that for a touch of life, matching the
   thumbnail-zoom pattern used in Products/Orders */
#customersTbody tr { transition: background .12s ease; }
#customersTbody .av { transition: transform .15s ease; }
#customersTbody tr:hover .av { transform: scale(1.06); }

/* Email column — de-emphasize slightly next to the customer's name */
#customersTbody td:nth-child(3) { color: var(--text-muted); font-size: 13px; }

/* Orders count — centered and slightly emphasized so it reads as a count */
#customersTbody td:nth-child(4) { text-align: center; font-weight: 600; color: var(--text); }

/* Total spent — the number that matters most in this list, so it gets the
   same visual weight as a table total/price elsewhere in the app */
#customersTbody td:nth-child(5) { font-weight: 600; color: var(--text); }

/* Last order — quiet, secondary */
#customersTbody td:nth-child(6) { color: var(--text-faint); font-size: 12.5px; }

/* ==========================================================================
   CATEGORIES + BRANDS — PHASE 6
   Scoped to #view-categories / #view-category-form / #view-brands and
   exclusive ids (#categoriesTbody, #catBulkBar, #catPaginationBar,
   #brandsTbody, #brandManagerList, #brandModal). Classes like .toolbar,
   .search-box, .filter-select, .bulk-bar, .dtable, .badge, .form-section,
   .uploader, .img-preview-grid, .modal/.modal-head and .sortable-th/
   .pagination-bar are shared with (or structurally identical to) Products,
   Orders, Customers, Blog and Settings — every rule below is id/ancestor-
   scoped so those modules are untouched. #brandModal is also opened from
   the Product Editor's "Manage brands" link; styling its own id doesn't
   touch Products' logic or any shared .modal/.modal-head rule, so both
   entry points now just see the same, better-looking modal.
   ========================================================================== */

/* ---- Categories: toolbar, bulk bar, table ---- */
#view-categories .toolbar { margin-bottom: 18px; }
#view-categories .search-box { transition: border-color .15s, box-shadow .15s; }
#view-categories .search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
#view-categories .filter-select { cursor: pointer; transition: border-color .15s; }
#view-categories .filter-select:hover { border-color: var(--primary-light); }

#catBulkBar.show { box-shadow: var(--shadow-sm); }
#catBulkCount { display: inline-flex; align-items: center; gap: 6px; }
#catBulkCount::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); display: inline-block;
}

#view-categories table.dtable thead th { background: #fafbfe; }
#categoriesTbody tr { transition: background .12s ease; }
#categoriesTbody tr:hover .row-thumb { transform: scale(1.06); }
#categoriesTbody .row-thumb { transition: transform .15s ease; }
#categoriesTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#categoriesTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }
#categoriesTbody .cat-tree-prefix { font-weight: 400; }

#view-categories .sortable-th:hover { color: var(--primary); }
#catPaginationBar { background: #fafbfe; }
#catPaginationBar button:hover:not(:disabled) { border-color: var(--primary-light); color: var(--primary); }

/* ---- Category form ---- */
#view-category-form .form-section { padding-bottom: 22px; border-bottom: 1px solid var(--line-soft); }
#view-category-form .form-section:last-of-type { border-bottom: none; padding-bottom: 0; }
#view-category-form .form-section h4 {
  position: relative; padding-left: 12px; letter-spacing: 0.05em;
}
#view-category-form .form-section h4::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--primary), var(--primary-light));
}
#view-category-form .back-link { transition: gap .12s ease; }
#view-category-form .back-link:hover { gap: 10px; }
#cfpUploader:hover { box-shadow: 0 0 0 3px var(--primary-soft) inset; }
#cfpSeoOgUploader:hover { box-shadow: 0 0 0 3px var(--primary-soft) inset; }
#cfpImageGrid .img-preview, #cfpSeoOgImageGrid .img-preview { transition: transform .12s ease, box-shadow .12s ease; }
#cfpImageGrid .img-preview:hover, #cfpSeoOgImageGrid .img-preview:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }

/* ---- Brands: standalone page ---- */
#view-brands .search-box { transition: border-color .15s, box-shadow .15s; }
#view-brands .search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
#view-brands table.dtable thead th { background: #fafbfe; }
#brandsTbody tr { transition: background .12s ease; }
#brandsTbody .name { font-weight: 600; color: var(--text); }
#brandsTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#brandsTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* ---- Brand modal (Manage brands) ---- */
#brandModal .modal-head h3 { display: flex; align-items: center; gap: 10px; }
#brandModal .modal-head h3::before {
  content: "";
  width: 28px; height: 28px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' width='24' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M14.8 9.5a3.5 3.5 0 1 0 0 5'/%3E%3C/g%3E%3C/svg%3E") center / 15px 15px no-repeat, linear-gradient(135deg, var(--primary), var(--primary-dark));
}
/* .brand-row's inline border-bottom references an undefined --border token
   (a pre-existing no-op), so this uses !important to actually draw the
   divider with a real token — no JS/markup change needed. */
#brandManagerList .brand-row {
  border-bottom: 1px solid var(--line-soft) !important;
  border-radius: var(--radius-sm); transition: background .12s ease;
  padding-left: 6px !important; padding-right: 6px !important; margin: 0 -6px;
}
#brandManagerList .brand-row:last-child { border-bottom: none !important; }
#brandManagerList .brand-row:hover { background: #fafbfe; }

/* ==========================================================================
   SETTINGS — PHASE 7
   Single long form, no tabs/sub-navigation exist in the markup, so none are
   introduced here — this is a visual pass over the existing sections
   (Branding, Logo, Favicon, Promotional Banner, Contact, Homepage, About
   page, Social media links, SEO). Scoped to #view-settings and Settings-
   exclusive ids (#stUploader, #stFaviconUploader, #stLaunchUploader,
   #stImageGrid, #stFaviconImageGrid, #stLaunchImageGrid, #stLaunchPreview,
   #stPrimaryColor/#stSecondaryColor/#stAccentColor, #settingsForm). Classes
   like .card, .form-section, .form-grid, .field, .uploader,
   .img-preview-grid, .toggle-row, .switch/.slider, .form-actions and
   .char-counter are shared with Products, Categories and Delivery — every
   rule below is id/ancestor-scoped so those modules are untouched.
   ========================================================================== */

/* A bit more breathing room than the old 640px cap, so the two-column
   .form-grid fields (already used for Contact/Homepage/Social) aren't
   cramped — same width class of container as the Product/Category forms. */
#view-settings .card { max-width: 860px; }

#view-settings .form-section { padding-bottom: 22px; border-bottom: 1px solid var(--line-soft); }
#view-settings .form-section:last-of-type { border-bottom: none; padding-bottom: 0; }
#view-settings .form-section h4 {
  position: relative; padding-left: 12px; letter-spacing: 0.05em;
}
#view-settings .form-section h4::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--primary), var(--primary-light));
}

/* Color pickers — native color inputs look inconsistent next to the rest of
   the form controls by default; give them a fixed, bordered swatch size
   that matches the app's input radius/border language. */
#stPrimaryColor, #stSecondaryColor, #stAccentColor {
  width: 100%; height: 40px; padding: 4px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  cursor: pointer; background: #fff;
}

/* Uploaders + previews — same hover/elevation polish used on the
   Product/Category forms */
#stUploader:hover, #stFaviconUploader:hover, #stLaunchUploader:hover { box-shadow: 0 0 0 3px var(--primary-soft) inset; }
#stImageGrid .img-preview, #stFaviconImageGrid .img-preview, #stLaunchImageGrid .img-preview {
  transition: transform .12s ease, box-shadow .12s ease;
}
#stImageGrid .img-preview:hover, #stFaviconImageGrid .img-preview:hover, #stLaunchImageGrid .img-preview:hover {
  transform: translateY(-2px); box-shadow: var(--shadow-sm);
}

/* Promotional banner toggle + its live preview */
#view-settings .toggle-row { transition: border-color .15s ease; }
#view-settings .toggle-row:has(#stLaunchEnabled:checked) { border-color: var(--primary-light); background: var(--primary-soft); }
#stLaunchPreview > div { box-shadow: var(--shadow-sm); }

/* SEO title counter next to its field, matching the Category form's
   layout so the two "SEO title" fields look identical app-wide */
#stSeoTitleCounter { margin-bottom: 4px; }

/* Save bar — sticks to the bottom of the viewport so it's always reachable
   on a long settings form, without changing the actual save logic */
#view-settings .form-actions {
  position: sticky; bottom: 0; background: var(--surface);
  margin-left: -20px; margin-right: -20px; margin-bottom: -20px;
  padding: 16px 20px; border-top: 1px solid var(--line);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* ==========================================================================
   DELIVERY — PHASE 8 (Delivery channel, Zones, Pickup Stations, Methods)
   Scoped to #view-delivery and delivery-exclusive element ids
   (#deliveryTabStrip, #adcChannelGroup, #deliveryZonesTbody,
   #pickupStationsTbody, #deliveryMethodsTbody, #dmBracketsTable,
   #deliveryZoneModal, #pickupStationModal, #deliveryMethodModal,
   #bulkDeliveryZonesModal). Classes like .card, .form-section, .form-grid,
   .field, .toggle-row, .switch/.slider, .tab-strip/.tab-btn, .radio-card,
   table.dtable, .badge and the base .modal system are shared with
   Products, Orders, Categories, Brands and Settings — every rule below is
   id/ancestor-scoped so those modules are untouched.

   Delivery sits on the Sales/operations side of the app, so its accent is
   the same blue already used for the Orders/Customers/Delivery nav group
   and the "illo-blue" empty-state treatment Delivery already renders
   (#2f6fed / #1d55c9) — not the purple --primary used elsewhere. ========================================================================== */

/* Section header accent bar — same left gradient rule as Orders/Settings,
   but in the blue that marks this module as Sales/operations. */
#view-delivery .form-section h4 { position: relative; padding-left: 12px; }
#view-delivery .form-section h4::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, #2f6fed, #1d55c9);
}

/* Tab strip (Delivery Zones / Pickup Stations / Delivery Methods) — pill
   shape with a blue active state, matching the inventory tab strips'
   treatment but in this module's own accent. */
#deliveryTabStrip.tab-strip { gap: 6px; }
#deliveryTabStrip .tab-btn { border-radius: 999px; border: 1px solid var(--line); transition: border-color .12s ease, box-shadow .12s ease; }
#deliveryTabStrip .tab-btn.active {
  background: linear-gradient(135deg, #2f6fed, #1d55c9); border-color: transparent; color: #fff;
  box-shadow: 0 2px 6px -1px rgba(47,111,237,.45);
}

/* Delivery channel picker — reuse the shared .radio-card component with a
   blue selected state instead of the default purple, since this is the
   single customer-facing Sales choice the page is built around. */
#adcChannelGroup.radio-card-group { gap: 10px; }
#adcChannelGroup .radio-card { transition: border-color .12s ease, background .12s ease, box-shadow .12s ease; }
#adcChannelGroup .radio-card:hover { border-color: #8fb2f5; box-shadow: 0 2px 8px -3px rgba(47,111,237,.3); }
#adcChannelGroup .radio-card.selected { border-color: #2f6fed; background: rgba(47,111,237,.06); }
#adcChannelGroup .radio-card input[type="radio"] { accent-color: #2f6fed; }
#adcChannelGroup .radio-card-title i { color: #1d55c9; }
#adcNullHint { color: var(--warning); }
#adcNullHint i { color: var(--warning); }

/* Zones / Pickup Stations / Methods tables — thead tint + row hover,
   matching the tint already used on Products/Orders/Categories tables. */
#view-delivery table.dtable thead th { background: #fafbfe; }
#view-delivery table.dtable tbody tr:hover { background: #fafbfe; }
#view-delivery .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#view-delivery .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* Toggle rows inside the zone/method modals — a light blue highlight when
   the switch is on, so "Door Delivery" / "Pickup Station" / "Active" read
   at a glance, same pattern Settings uses for its own toggle. */
#deliveryZoneForm .toggle-row:has(input:checked),
#pickupStationForm .toggle-row:has(input:checked),
#deliveryMethodForm .toggle-row:has(input:checked) {
  border-color: #8fb2f5; background: rgba(47,111,237,.06);
}
#deliveryZoneForm .toggle-row, #pickupStationForm .toggle-row, #deliveryMethodForm .toggle-row {
  transition: border-color .15s ease, background .15s ease;
}
#deliveryZoneForm .switch input:checked + .slider,
#pickupStationForm .switch input:checked + .slider,
#deliveryMethodForm .switch input:checked + .slider { background: #2f6fed; }

/* Weight brackets editor (Delivery Methods modal) — tidy row rhythm for the
   add/remove bracket table, no new columns or behavior. */
#dmBracketsTable td { vertical-align: middle; }
#dmBracketsTable input { width: 100%; }
#dmAddBracketBtn { transition: background .12s ease, color .12s ease, border-color .12s ease; }

/* Default delivery location / Storefront visibility cards — same subtle
   lift on hover as other summary cards in the app. */
#view-delivery .card:hover { box-shadow: var(--shadow-md); }

@media (max-width: 640px) {
  #view-delivery .toolbar { flex-direction: column; align-items: stretch; }
  #view-delivery .toolbar-left { width: 100%; }
  #deliveryTabStrip.tab-strip { width: 100%; }
  #view-delivery .toolbar > .btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   BLOG — PHASE 9A (list + editor)
   Scoped to #view-blog, #view-blog-form and blog-exclusive element ids
   (#blogTbody, #blogSearch, #bfUploader, #bfImageGrid, #blogForm).
   Classes like .toolbar, .search-box, .card, .dtable, .row-title/.row-thumb,
   .badge, .form-grid, .field, .uploader, .img-preview-grid, .form-section
   and .form-actions are shared with Products, Categories and Settings —
   every rule below is id/ancestor-scoped so those modules are untouched.

   Blog is in the Content group, so its accent is cyan — the same
   #00cfe8/#0aa2b5 pair the "illo-cyan" empty state and the Blog nav icon
   already use — not the purple --primary used for primary actions
   elsewhere (the "New post"/"Save post" buttons stay purple, per the
   design brief: purple stays the primary-action color app-wide). ========================================================================== */

/* List — table tint + row hover + thumbnail zoom, matching Products/Categories */
#view-blog table.dtable thead th { background: #fafbfe; }
#blogTbody tr { transition: background .12s ease; }
#blogTbody tr:hover { background: #fafbfe; }
#blogTbody .row-thumb { transition: transform .15s ease; border-radius: 8px; }
#blogTbody tr:hover .row-thumb { transform: scale(1.06); }
#blogTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#blogTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* Search box — cyan focus ring so Blog's toolbar reads as its own module
   at a glance, same pattern as the accent-per-module focus rings elsewhere. */
#view-blog .search-box { transition: border-color .15s, box-shadow .15s; }
#view-blog .search-box:focus-within { border-color: #00cfe8; box-shadow: 0 0 0 3px rgba(0,207,232,.15); }

/* Editor — section header accent bar in cyan, matching the gradient rule
   used on Product/Category/Settings form sections. */
#view-blog-form .form-section h4 { position: relative; padding-left: 12px; }
#view-blog-form .form-section h4::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, #00cfe8, #0aa2b5);
}

/* Title/content fields get a touch more breathing room since Content is
   the primary field on this form — no structural change, just spacing. */
#view-blog-form textarea#bfContent { line-height: 1.6; }
#view-blog-form .card { max-width: 820px; }

/* Featured image uploader — cyan hover/drag state instead of the default
   purple, consistent with this module's accent; success/error states are
   left untouched since those are meaningful status colors, not branding. */
#bfUploader:hover, #bfUploader.drag { border-color: #00cfe8; background: rgba(0,207,232,.06); }
#bfUploader.is-busy, #bfUploader.is-busy:hover { border-color: #00cfe8; background: rgba(0,207,232,.06); }
#bfUploader.is-busy i { color: #0aa2b5; }
#bfImageGrid .img-preview { transition: transform .12s ease, box-shadow .12s ease; }
#bfImageGrid .img-preview:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
#bfImageGrid .img-preview.featured::after { background: #0aa2b5; }

/* Status select — a quick cyan-tinted focus state, and a subtle left
   highlight when Published so list/editor agree at a glance. */
#bfStatus:focus { border-color: #00cfe8; box-shadow: 0 0 0 3px rgba(0,207,232,.15); }

@media (max-width: 640px) {
  #view-blog .toolbar { flex-direction: column; align-items: stretch; }
  #view-blog .toolbar-left, #view-blog .search-box { width: 100%; }
  #view-blog .toolbar > a.btn { width: 100%; justify-content: center; text-align: center; }
}

/* ==========================================================================
   NOTIFICATIONS — PHASE 9B (list, stat cards, send/edit modal)
   Scoped to #view-notifications, #notificationModal and notification-
   exclusive element ids (#notifStatGrid, #notificationsTbody, #notifSearch,
   #notifTypeFilter). Classes like .toolbar, .search-box, .filter-select,
   .card, .stat-card, .dtable, .badge, .row-title, .cell-actions/.tbl-icon-btn,
   .field, .form-grid and the base .modal system are shared with Dashboard,
   Blog, Orders and Settings — every rule below is id/ancestor-scoped so
   those modules are untouched.

   Notifications is in the Content group (cyan accent, #00cfe8/#0aa2b5),
   same as Blog. There is no per-row unread state in the existing data —
   "Sent"/"Read" are aggregate delivery counts per notification, already
   rendered as plain numbers — so no unread tint was invented; the polish
   below is type/expiry hierarchy plus the shared cyan module accent. ========================================================================== */

/* Stat cards — same hover lift as the Dashboard's stat grid, scoped here
   so Dashboard's own stat-card rules are untouched. */

/* Toolbar controls — cyan focus rings, matching Blog's module accent. */
#view-notifications .search-box, #view-notifications .filter-select { transition: border-color .15s, box-shadow .15s; }
#view-notifications .search-box:focus-within { border-color: #00cfe8; box-shadow: 0 0 0 3px rgba(0,207,232,.15); }
#view-notifications .filter-select:focus { border-color: #00cfe8; box-shadow: 0 0 0 3px rgba(0,207,232,.15); outline: none; }

/* Table — header tint + row hover, matching Blog/Products/Categories;
   message preview gets a touch more line-height so longer previews stay
   easy to scan instead of feeling cramped against the title. */
#view-notifications table.dtable thead th { background: #fafbfe; }
#notificationsTbody tr { transition: background .12s ease; }
#notificationsTbody tr:hover { background: #fafbfe; }
#notificationsTbody .row-title .name { margin-bottom: 2px; }
#notificationsTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#notificationsTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* Sent/Read counts — keep the existing .num mono styling but align them
   so the two columns read as a clear before/after pair. */
#notificationsTbody td.num { text-align: right; color: var(--text-muted); }

/* Type badges — no new colors invented; .badge-info/.badge-warning/
   .badge-success/.badge-danger already carry the existing semantic
   mapping (order_update/promotion/announcement/system) from admin.js,
   this only tightens their layout inside the notification row. */
#notificationsTbody .badge { white-space: nowrap; }

/* Send/edit modal — cyan section accent on the type field, matching the
   Blog editor's cyan form-section treatment. */
#notificationModal .field label[for="nfType"] { color: #0aa2b5; }
#notificationModal select#nfType:focus,
#notificationModal input:focus,
#notificationModal textarea:focus { border-color: #00cfe8; box-shadow: 0 0 0 3px rgba(0,207,232,.15); }

@media (max-width: 640px) {
  #view-notifications .toolbar { flex-direction: column; align-items: stretch; }
  #view-notifications .toolbar-left { flex-direction: column; align-items: stretch; width: 100%; }
  #view-notifications .search-box, #view-notifications .filter-select { width: 100%; }
  #view-notifications #addNotificationBtn { width: 100% !important; justify-content: center; }
  #notificationsTbody .row-title .name + div { max-width: none; }
}

/* ==========================================================================
   STORES — PHASE 10 (platform-admin store list + lifecycle actions)
   Scoped to #view-stores, #lifecycleModal and store-exclusive element ids
   (#storesStatGrid, #storesTbody). Classes like .card, .stat-card, .dtable,
   .badge, .cell-actions/.tbl-icon-btn, .confirm-icon, .field and
   .char-counter are shared with Dashboard, Team, Notifications and other
   modules — every rule below is id/ancestor-scoped so those are untouched.

   Stores is in the Platform group (green, #1eae60 / var(--success)), the
   same accent already used for the Stores/Team nav icons and the
   "illo-green" empty state this view already renders. There is no
   search/filter or create/edit form in this module today — stores are
   provisioned outside this view and managed by switching into them — so
   neither was invented; the list is platform-admin-only and reads as a
   status/lifecycle console, not a CRUD list. ========================================================================== */

/* Stat cards — same hover lift as Dashboard/Notifications, scoped here so
   those modules' own stat-card rules are untouched. */

/* Table — header tint + row hover, matching every other redesigned list;
   the store name column gets a touch more weight since it's the primary
   identifier merchants and platform admins scan for first. */
#view-stores table.dtable thead th { background: #fafbfe; }
#storesTbody tr { transition: background .12s ease; }
#storesTbody tr:hover { background: #fafbfe; }
#storesTbody td b { font-weight: 600; color: var(--text); }
#storesTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#storesTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* "Manage store" — the row's primary action, keep it visually anchored
   against the smaller lifecycle icon buttons beside it. */
#storesTbody button[data-store-id] { font-weight: 600; }
#storesTbody button[data-store-id].btn-primary { box-shadow: 0 2px 6px -1px rgba(23,105,224,.35); }

/* Current-store badge and lifecycle reason hint — subtle green tie-in to
   the module accent without touching the shared .badge-info styling. */
#storesTbody .badge-info { background: rgba(30,174,96,.12); color: #1a9d57; }

/* Lifecycle modal — this modal only ever renders store lifecycle actions
   (Suspend/Deactivate/Request deletion/Reactivate/Cancel deletion), so its
   icon/copy get a bit more visual weight; reactivate/cancel actions swap
   the icon out of the "danger" tone via the existing JS class toggles, so
   this only refines layout, not meaning. */
#lifecycleModal .modal { max-width: 440px; }
#lifecycleModal .modal-body { text-align: center; }
#lifecycleModal .confirm-icon { margin-left: auto; margin-right: auto; }

@media (max-width: 640px) {
  #view-stores table.dtable { min-width: 720px; }
  #storesTbody .cell-actions { flex-wrap: wrap; }
}

/* ==========================================================================
   TEAM / USERS — PHASE 11 (store team/member list + Add Member modal;
   relocated from the top-level "Team" nav item into Settings > Users —
   selectors updated from #view-team to #stPanelUsers, ids unchanged)
   Scoped to #stPanelUsers, #addMemberModal and team-exclusive element ids
   (#teamStatGrid, #teamTbody, #teamStoreName/#teamStoreSub). Classes like
   .card, .card-head-dark, .stat-card, .dtable, .badge, .row-select,
   .cell-actions/.tbl-icon-btn, .field and the base .modal system are
   shared with Dashboard, Stores, Products and other modules — every rule
   below is id/ancestor-scoped so those are untouched.

   Team is Platform-group, same green (#1eae60 / var(--success)) already
   used for the Stores/Team nav icons and the "illo-green" empty states
   this view already renders. There's no avatar in the existing markup
   (name is plain text) and no search/filter control on this list — only
   the header card, two stat cards, the member table, and the Add Member
   modal — so none of those were invented. ========================================================================== */

/* Header card — same gradient icon-badge treatment used on Dashboard's
   card-head-dark sections, scoped to this store-context header only. */
#stPanelUsers .card-head-dark h3 { position: relative; }

/* Stat cards — same hover lift as Dashboard/Stores/Notifications. */

/* Table — header tint + row hover, matching every other redesigned list.
   Member name gets a touch more weight as the primary scan target. */
#stPanelUsers table.dtable thead th { background: #fafbfe; }
#teamTbody tr { transition: background .12s ease; }
#teamTbody tr:hover { background: #fafbfe; }
#teamTbody td b { font-weight: 600; color: var(--text); }
#teamTbody .cell-actions .tbl-icon-btn { transition: transform .12s ease, background .12s ease, color .12s ease; }
#teamTbody .cell-actions .tbl-icon-btn:hover { transform: translateY(-1px); }

/* Role select — a green focus ring instead of the default purple, tying
   the in-row role control to this module's Platform accent; it's still
   the same .row-select component used elsewhere, just recolored here. */
#teamTbody .team-role-select:focus { border-color: #1eae60; box-shadow: 0 0 0 3px rgba(30,174,96,.15); }

/* Add Member modal — green section accent + a bit more breathing room
   around the user-search step, matching the gradient-accent form language
   used on Products/Categories/Settings section headers. */
#addMemberModal .field label[for="amUserSearch"] { position: relative; padding-left: 12px; }
#addMemberModal .field label[for="amUserSearch"]::before {
  content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--success), #1eae60);
}
#addMemberModal input:focus, #addMemberModal select:focus {
  border-color: #1eae60; box-shadow: 0 0 0 3px rgba(30,174,96,.15); outline: none;
}
#amSearchNote { color: var(--text-muted); }

@media (max-width: 640px) {
  #stPanelUsers table.dtable { min-width: 640px; }
  #teamTbody .cell-actions { flex-wrap: wrap; }
  #stPanelUsers .card-head-dark { flex-direction: column; align-items: flex-start; }
  #teamAddMemberBtn { width: 100% !important; justify-content: center; }
}
