﻿/* ============================================================================
   Order Mgmt — UI system
   1. Fonts & reset          8.  Buttons            15. Avatars
   2. Design tokens          9.  Forms              16. Tabs
   3. Base elements          10. Cards & panels     17. Accordion
   4. Utilities              11. Stat cards         18. Empty state
   5. App shell              12. Tables             19. Progress & charts
   6. Sidebar                13. Toolbar            20. Pagination
   7. Topbar & page head     14. Badges & status    21. Inbox
   22. Responsive            23. Motion
   ========================================================================== */

/* =========================== 1. Fonts & reset ============================= */
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@600;700;800&display=swap");

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* ============================ 2. Design tokens ============================ */
:root {
  /* ---- brand: refreshed indigo, softer and more luminous than the old #2a2185 */
  --primary-50: #eef1ff;
  --primary-100: #e0e5ff;
  --primary-200: #c7cfff;
  --primary-400: #7c7bf0;
  --primary-500: #6366f1;
  --primary-600: #5145cd;
  --primary-700: #423bb0;
  --primary-900: #241f5c;

  /* ---- accent: emerald marks "active" and "positive" */
  --accent-400: #34d399;
  --accent-500: #10b981;
  --accent-600: #059669;

  /* ---- semantic */
  --success: #059669;
  --success-bg: #e7f8f1;
  --warning: #b45309;
  --warning-bg: #fdf3e2;
  --danger: #be2f36;
  --danger-bg: #fdeaeb;
  --info: #0e7490;
  --info-bg: #e2f4fa;

  /* ---- surfaces (light) */
  --bg: #f6f7fb;
  --surface: #ffffff;
  --surface-2: #fafbff;
  --surface-3: #f1f3fa;
  --border: #e8eaf3;
  --border-strong: #d6dae8;

  /* ---- text (light) */
  --text: #16192c;
  --text-2: #565b7d;
  --text-3: #868bab;
  --text-on-primary: #ffffff;

  /* ---- sidebar: stays dark in both themes */
  --nav-bg: #1b1a3a;
  --nav-bg-2: #232152;
  --nav-text: #a9abd0;
  --nav-text-strong: #ffffff;
  --nav-hover: rgba(255, 255, 255, 0.07);
  --nav-active: rgba(52, 211, 153, 0.14);
  --nav-accent: var(--accent-400);
  --nav-border: rgba(255, 255, 255, 0.08);

  /* ---- type scale */
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Plus Jakarta Sans", var(--font-ui);
  --fs-xs: 0.75rem;
  --fs-sm: 0.8125rem;
  --fs-md: 0.875rem;
  --fs-base: 0.9375rem;
  --fs-lg: 1.0625rem;
  --fs-xl: clamp(1.125rem, 1.6vw, 1.3rem);
  --fs-2xl: clamp(1.35rem, 2.4vw, 1.75rem);
  --fs-3xl: clamp(1.75rem, 3.4vw, 2.35rem);

  /* ---- spacing */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-7: 32px;
  --s-8: 40px;
  --gutter: clamp(16px, 2.4vw, 32px);
  --gap: clamp(16px, 1.8vw, 24px);

  /* ---- radii */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-full: 999px;

  /* ---- elevation: low-spread, layered, never muddy */
  --shadow-xs: 0 1px 2px rgba(22, 25, 44, 0.05);
  --shadow-sm: 0 2px 6px rgba(22, 25, 44, 0.06);
  --shadow-md: 0 6px 18px rgba(22, 25, 44, 0.08);
  --shadow-lg: 0 18px 40px rgba(22, 25, 44, 0.14);
  --ring: 0 0 0 3px rgba(99, 102, 241, 0.3);

  /* ---- layout */
  --nav-w: 264px;
  --nav-w-collapsed: 80px;
  --topbar-h: 68px;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --t-fast: 0.15s var(--ease);
  --t: 0.25s var(--ease);
  --t-slow: 0.35s var(--ease);
}

/* ---------------------------- dark theme --------------------------------- */
[data-theme="dark"] {
  --bg: #10111f;
  --surface: #181a2c;
  --surface-2: #1e2036;
  --surface-3: #23263e;
  --border: #2a2d47;
  --border-strong: #383c5c;

  --text: #eceefb;
  --text-2: #a3a7c6;
  --text-3: #7c81a3;

  --primary-50: #232455;
  --primary-100: #2b2c68;
  --primary-500: #8183f5;
  --primary-600: #6f70ef;

  --success-bg: #10352b;
  --warning-bg: #3a2a12;
  --danger-bg: #3a1c20;
  --info-bg: #12303c;
  --success: #4ade9f;
  --warning: #f0b45f;
  --danger: #f4868c;
  --info: #56c4e4;

  --nav-bg: #14152b;
  --nav-bg-2: #1c1d3e;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 18px 40px rgba(0, 0, 0, 0.55);
}

/* =========================== 3. Base elements ============================= */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--text);
  background: var(--bg);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--t), color var(--t);
}

h1,
h2,
h3,
h4,
h5 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--text);
}

a {
  color: var(--primary-600);
  text-decoration: none;
}
a:hover {
  color: var(--primary-500);
}

img {
  max-width: 100%;
  display: block;
}

ul {
  list-style: none;
}

/* numbers line up in tables and stat tiles */
.tnum,
table td,
.stat__value {
  font-variant-numeric: tabular-nums;
}

::selection {
  background: var(--primary-200);
  color: var(--primary-900);
}

/* one consistent focus ring for every interactive element */
:is(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-sm);
}

/* scrollbars */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
*::-webkit-scrollbar {
  width: 9px;
  height: 9px;
}
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--r-full);
  border: 2px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover {
  background: var(--text-3);
  background-clip: content-box;
}

/* ============================= 4. Utilities =============================== */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.muted {
  color: var(--text-2);
}
.dim {
  color: var(--text-3);
}
.row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.row--between {
  justify-content: space-between;
}
.row--wrap {
  flex-wrap: wrap;
}
.grow {
  flex: 1 1 auto;
  min-width: 0;
}
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.up {
  color: var(--success);
}
.down {
  color: var(--danger);
}
.grid {
  display: grid;
  gap: var(--gap);
}
.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.grid--cards {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
/* main content + rail, collapsing to one column when cramped */
.grid--split {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}
@media (max-width: 1100px) {
  .grid--split {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ============================= 5. App shell =============================== */
.app {
  display: grid;
  grid-template-columns: var(--nav-w) minmax(0, 1fr);
  min-height: 100vh;
  transition: grid-template-columns var(--t-slow);
}
.app.is-collapsed {
  grid-template-columns: var(--nav-w-collapsed) minmax(0, 1fr);
}

.app__main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  padding: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.app__backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(16, 17, 31, 0.55);
  backdrop-filter: blur(2px);
  z-index: 900;
}

/* ============================== 6. Sidebar ================================ */
.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--nav-bg) 0%, var(--nav-bg-2) 100%);
  border-right: 1px solid var(--nav-border);
  overflow: hidden;
  z-index: 1000;
}

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  height: var(--topbar-h);
  padding: 0 var(--s-5);
  flex: 0 0 auto;
  color: var(--nav-text-strong);
  border-bottom: 1px solid var(--nav-border);
}
.sidebar__logo {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--primary-500), var(--accent-500));
  color: #fff;
  font-size: 1.25rem;
  box-shadow: 0 4px 14px rgba(99, 102, 241, 0.45);
}
.sidebar__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-lg);
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.sidebar__nav {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--s-4) var(--s-3);
}

.nav__section {
  padding: var(--s-5) var(--s-3) var(--s-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--nav-text);
  opacity: 0.55;
  white-space: nowrap;
}
.nav__section:first-child {
  padding-top: 0;
}

.nav__link {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  height: 46px;
  padding: 0 var(--s-3);
  margin-bottom: 2px;
  border-radius: var(--r-md);
  color: var(--nav-text);
  font-size: var(--fs-md);
  font-weight: 500;
  white-space: nowrap;
  transition: background-color var(--t), color var(--t);
}
.nav__link ion-icon {
  flex: 0 0 auto;
  font-size: 1.3rem;
  min-width: 24px;
}
.nav__label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: opacity var(--t);
}

.nav__link:hover {
  background: var(--nav-hover);
  color: var(--nav-text-strong);
}
.nav__link:hover ion-icon {
  color: var(--nav-accent);
}

/* current page: tinted panel + accent bar + accent icon */
.nav__link.is-active {
  background: var(--nav-active);
  color: var(--nav-text-strong);
  font-weight: 600;
}
.nav__link.is-active::before {
  content: "";
  position: absolute;
  left: calc(var(--s-3) * -1);
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 26px;
  border-radius: 0 4px 4px 0;
  background: var(--nav-accent);
}
.nav__link.is-active ion-icon {
  color: var(--nav-accent);
}

/* count pill on the right of a nav row */
.nav__count {
  flex: 0 0 auto;
  min-width: 22px;
  height: 22px;
  padding: 0 7px;
  display: grid;
  place-items: center;
  border-radius: var(--r-full);
  background: var(--primary-500);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 600;
}

/* NOTE: the sidebar once ended with a name/role footer. It was removed — the
   topbar profile dropdown carries the user's identity now, and repeating it
   at the bottom of the nav was redundant. */

/* ---- collapsed rail: icons only -------------------------------------------
   Only exists above the drawer breakpoint — below it the sidebar is an
   overlay drawer that always shows full labels, so scoping the whole rail to
   a min-width keeps the two modes from fighting each other.

   Labels are removed with display:none, not opacity:0 — an invisible label
   still takes its flex width and shoves the icon off-centre.              */
@media (min-width: 901px) {
  .app.is-collapsed .sidebar__name,
  .app.is-collapsed .nav__label,
  .app.is-collapsed .nav__count {
    display: none;
  }

  /* section headings become plain dividers when there's no room for words */
  .app.is-collapsed .nav__section {
    height: 1px;
    margin: var(--s-4) var(--s-2);
    padding: 0;
    font-size: 0;
    overflow: hidden;
    background: var(--nav-border);
  }
  .app.is-collapsed .nav__section:first-child {
    display: none;
  }

  /* with the labels gone, each row is a single centred icon */
  .app.is-collapsed .sidebar__brand,
  .app.is-collapsed .nav__link {
    justify-content: center;
    gap: 0;
    padding-inline: 0;
  }
  .app.is-collapsed .nav__link ion-icon {
    min-width: 0;
  }

}

/* ---- rail tooltip ---------------------------------------------------------
   Positioned fixed and appended to <body> by main.js. It cannot be a ::after
   on .nav__link: the sidebar clips with overflow:hidden and .sidebar__nav
   scrolls with overflow-y:auto, so a child pseudo-element is cut off at the
   rail's edge and never becomes visible.                                  */
.nav-tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1200;
  padding: 7px 11px;
  border-radius: var(--r-sm);
  background: var(--text);
  color: var(--bg);
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--t-fast), transform var(--t-fast);
}
.nav-tip.is-visible {
  opacity: 1;
  transform: none;
}
/* little arrow pointing back at the icon */
.nav-tip::before {
  content: "";
  position: absolute;
  top: 50%;
  right: 100%;
  transform: translateY(-50%);
  border: 5px solid transparent;
  border-right-color: var(--text);
}

/* ========================= 7. Topbar & page head ========================== */
.topbar {
  position: sticky;
  top: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--topbar-h);
  padding: var(--s-2) var(--gutter);
  background: var(--surface); /* fallback where color-mix() is unsupported */
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}

.icon-btn {
  position: relative;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text-2);
  font-size: 1.3rem;
  cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast),
    border-color var(--t-fast);
}
.icon-btn:hover {
  background: var(--surface-3);
  color: var(--text);
}

/* unread dot on the bell */
.icon-btn[data-dot]::after {
  content: "";
  position: absolute;
  transform: translate(11px, -11px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  border: 2px solid var(--surface);
}

.search {
  position: relative;
  flex: 1 1 auto;
  max-width: 420px;
}
.search ion-icon {
  position: absolute;
  top: 50%;
  left: 14px;
  transform: translateY(-50%);
  font-size: 1.15rem;
  color: var(--text-3);
  pointer-events: none;
}
.search input {
  width: 100%;
  height: 42px;
  padding: 0 var(--s-4) 0 42px;
  font: inherit;
  font-size: var(--fs-md);
  color: var(--text);
  background: var(--surface-3);
  border: 1px solid transparent;
  border-radius: var(--r-full);
  outline: none;
  transition: background-color var(--t), border-color var(--t),
    box-shadow var(--t);
}
.search input::placeholder {
  color: var(--text-3);
}
.search input:focus {
  background: var(--surface);
  border-color: var(--primary-500);
  box-shadow: var(--ring);
}
.search kbd {
  position: absolute;
  top: 50%;
  right: 12px;
  transform: translateY(-50%);
  padding: 2px 7px;
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  color: var(--text-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  pointer-events: none;
}
.search input:focus ~ kbd {
  opacity: 0;
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  margin-left: auto;
}
.topbar__actions .avatar {
  margin-left: var(--s-2);
  border: 2px solid var(--border);
}

/* ---- dropdown menu (topbar profile) ---- */
.menu {
  position: relative;
  flex: 0 0 auto;
}
.menu__trigger {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  padding: 3px 6px 3px 3px;
  margin-left: var(--s-2);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-full);
  cursor: pointer;
  transition: background-color var(--t-fast), border-color var(--t-fast);
}
.menu__trigger:hover,
.menu__trigger[aria-expanded="true"] {
  background: var(--surface-3);
  border-color: var(--border);
}
.menu__caret {
  font-size: 0.95rem;
  color: var(--text-3);
  transition: transform var(--t);
}
.menu__trigger[aria-expanded="true"] .menu__caret {
  transform: rotate(180deg);
}

.menu__panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 600;
  min-width: 244px;
  padding: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  animation: menu-in 0.16s var(--ease);
}
.menu__panel[hidden] {
  display: none;
}
@keyframes menu-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.menu__header {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3);
  min-width: 0;
}
.menu__header strong {
  display: block;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
}
.menu__header small {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
}

.menu__sep {
  height: 1px;
  margin: var(--s-2) 0;
  background: var(--border);
}

.menu__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 10px var(--s-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-2);
  transition: background-color var(--t-fast), color var(--t-fast);
}
.menu__item ion-icon {
  font-size: 1.2rem;
  color: var(--text-3);
  transition: color var(--t-fast);
}
.menu__item:hover {
  background: var(--surface-3);
  color: var(--text);
}
.menu__item:hover ion-icon {
  color: var(--primary-600);
}
.menu__item--danger,
.menu__item--danger ion-icon {
  color: var(--danger);
}
.menu__item--danger:hover {
  background: var(--danger-bg);
  color: var(--danger);
}
.menu__item--danger:hover ion-icon {
  color: var(--danger);
}

/* phone: pin the panel to the screen edge so it can't overflow */
@media (max-width: 420px) {
  .menu__panel {
    position: fixed;
    top: var(--topbar-h);
    right: var(--s-3);
    left: var(--s-3);
    min-width: 0;
  }
}

/* ---- page head ---- */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-4);
}
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--text-3);
  margin-bottom: var(--s-2);
}
.breadcrumb a {
  color: var(--text-2);
}
.breadcrumb a:hover {
  color: var(--primary-600);
}
.page-title {
  font-size: var(--fs-2xl);
}
.page-sub {
  margin-top: var(--s-1);
  color: var(--text-2);
  font-size: var(--fs-md);
}
.page-head__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

/* ============================== 8. Buttons ================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  height: 42px;
  padding: 0 var(--s-5);
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background-color var(--t-fast), border-color var(--t-fast),
    color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
}
.btn ion-icon {
  font-size: 1.15rem;
}
.btn:active {
  transform: translateY(1px);
}

.btn--primary {
  background: var(--primary-600);
  color: var(--text-on-primary);
  box-shadow: 0 4px 12px rgba(81, 69, 205, 0.28);
}
.btn--primary:hover {
  background: var(--primary-500);
  color: #fff;
  box-shadow: 0 6px 18px rgba(81, 69, 205, 0.36);
}

.btn--ghost {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text-2);
}
.btn--ghost:hover {
  background: var(--surface-3);
  color: var(--text);
  border-color: var(--text-3);
}

.btn--subtle {
  background: var(--primary-50);
  color: var(--primary-600);
}
.btn--subtle:hover {
  background: var(--primary-100);
  color: var(--primary-600);
}

.btn--danger {
  background: var(--danger);
  color: #fff;
}
.btn--danger:hover {
  background: #a32830;
  color: #fff;
}

.btn--sm {
  height: 34px;
  padding: 0 var(--s-3);
  font-size: var(--fs-sm);
}
.btn--icon {
  width: 42px;
  padding: 0;
}
.btn--block {
  width: 100%;
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* =============================== 9. Forms ================================= */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.field > label,
.label {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
}
.hint {
  font-size: var(--fs-sm);
  color: var(--text-3);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px var(--s-4);
  font: inherit;
  font-size: var(--fs-md);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  outline: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.input::placeholder,
.textarea::placeholder {
  color: var(--text-3);
}
.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--text-3);
}
.input:focus,
.select:focus,
.textarea:focus {
  border-color: var(--primary-500);
  box-shadow: var(--ring);
}
.textarea {
  min-height: 110px;
  resize: vertical;
}
.select {
  appearance: none;
  padding-right: var(--s-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px;
  background-repeat: no-repeat;
  cursor: pointer;
}

/* switch */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  cursor: pointer;
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.switch__track {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 25px;
  border-radius: var(--r-full);
  background: var(--border-strong);
  transition: background-color var(--t);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: #fff;
  box-shadow: var(--shadow-xs);
  transition: transform var(--t);
}
.switch input:checked + .switch__track {
  background: var(--accent-500);
}
.switch input:checked + .switch__track::after {
  transform: translateX(19px);
}
.switch input:focus-visible + .switch__track {
  box-shadow: var(--ring);
}

/* =========================== 10. Cards & panels =========================== */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-5) var(--s-4);
}
.panel__title {
  font-size: var(--fs-lg);
}
.panel__sub {
  font-size: var(--fs-sm);
  color: var(--text-3);
  margin-top: 2px;
}
.panel__body {
  padding: 0 var(--s-5) var(--s-5);
}
.panel__body--flush {
  padding: 0;
}
.panel__foot {
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

/* ============================ 11. Stat cards ============================== */
.stat {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.stat::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--stat-color, var(--primary-500));
  opacity: 0;
  transition: opacity var(--t);
}
.stat:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
}
.stat:hover::after {
  opacity: 1;
}

.stat__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-3);
}
.stat__label {
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-2);
}
.stat__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  font-size: 1.4rem;
  color: var(--stat-color, var(--primary-600));
  background: var(--surface-3); /* fallback where color-mix() is unsupported */
  background: color-mix(in srgb, var(--stat-color, var(--primary-500)) 12%, transparent);
}
.stat__value {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
}
.stat__foot {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--text-3);
}
.delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 8px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 600;
}
.delta--up {
  color: var(--success);
  background: var(--success-bg);
}
.delta--down {
  color: var(--danger);
  background: var(--danger-bg);
}

/* ---- topic card: linked help/category tile ---- */
.topic-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.topic-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--primary-500);
  color: var(--text);
}
.topic-card h3 {
  font-size: var(--fs-lg);
}
.topic-card p {
  color: var(--text-2);
  font-size: var(--fs-md);
  flex: 1;
}
.topic-card__link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--primary-600);
}
.topic-card:hover .topic-card__link ion-icon {
  transform: translateX(3px);
}
.topic-card__link ion-icon {
  transition: transform var(--t);
}

/* ---- person card: profile summary tile ---- */
.person-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-4);
  padding: var(--s-6) var(--s-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.person-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--border-strong);
}
.person-card__name {
  font-size: var(--fs-lg);
}
.person-card__meta {
  font-size: var(--fs-sm);
  color: var(--text-3);
}
.person-card__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-4) 0;
  border-block: 1px solid var(--border);
}
.person-card__stats strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
}
.person-card__stats small {
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.person-card__actions {
  display: flex;
  gap: var(--s-2);
  width: 100%;
}

/* ============================== 12. Tables ================================ */
/* Every table lives in one of these. A wide table scrolls sideways *inside*
   this box; the page itself never gets a horizontal scrollbar. */
.table-wrap {
  width: 100%;
  max-width: 100%;
  /* Without this a wrap that is a flex or grid child takes its width from the
     table's content and refuses to shrink — which is exactly how a wide table
     pushes the whole page sideways instead of scrolling by itself. */
  min-width: 0;
  overflow-x: auto;
  /* the sideways swipe stops at the ends of the table rather than carrying on
     into the page behind it */
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

/* ---- a long table scrolls inside itself ----
   A report can run to hundreds of rows. Capping the box gives the table its
   own vertical scrollbar, so the page heading, the filter bar and the column
   headers all stay put while the rows move. The page keeps its own scrollbar
   too, and the two do not fight: scrolling past the last row inside the table
   carries on scrolling the page, which is how the mouse wheel already
   behaves. */
.table-wrap--tall {
  max-height: min(70vh, 720px);
  overflow-y: auto;
}

/* thead is already sticky; pin the totals row to the bottom edge as well, so
   the figures stay readable no matter where you are in the rows. Both rows
   already carry an opaque background, so nothing shows through them. */
.table-wrap--tall .table tfoot td {
  position: sticky;
  bottom: 0;
  z-index: 2;
  /* border-collapse:collapse hands the borders to the table, and a sticky cell
     that has left its normal position loses them — so the divider above the
     totals is drawn as an inset shadow, which travels with the cell. */
  box-shadow: inset 0 1px 0 var(--border-strong);
}

/* the same reason, one level up: a panel holding a table must be allowed to
   be narrower than the table it holds */
.panel:has(> .table-wrap),
.card:has(> .table-wrap),
.panel:has(.table-wrap),
.card:has(.table-wrap) {
  min-width: 0;
}
/* Small by default, everywhere. These tables carry ten or eleven columns and
   several money figures, and at the old --fs-md an amount like 1,24,536.75 ran
   out of column and wrapped onto a second line, which pushed every row taller
   and broke the alignment down the page. One step down in type, and one step in
   on the cell padding, buys each column roughly 15% more room for the same
   width — the .num rule below then guarantees a figure never breaks at all. */
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--s-2) var(--s-4);
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-3);
  background: var(--surface-2);
  border-block: 1px solid var(--border);
  white-space: nowrap;
}
.table tbody td {
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}
.table tbody tr {
  transition: background-color var(--t-fast);
}
.table tbody tr:hover {
  background: var(--surface-2);
}
.table tbody tr:last-child td {
  border-bottom: none;
}
/* A totals row. Without this it inherits nothing from thead or tbody and
   lands flush against the last row with no padding at all. */
.table tfoot td {
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text);
  vertical-align: middle;
}
.table tfoot .num {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* ---- fixed column widths ---- */
/* Left to itself a table sizes each column to its widest cell, so an eight
   or ten column order table spills into a sideways scroll and the figures
   never line up down the page. These widths are relative weights: with
   table-layout:fixed the browser scales them to the panel, so the same set
   of classes serves tables with different numbers of columns. */
.table--fixed {
  table-layout: fixed;
}
.table--fixed th,
.table--fixed td {
  padding-left: var(--s-3);
  padding-right: var(--s-3);
  /* a long part number breaks rather than pushing its column wider */
  overflow-wrap: anywhere;
}
/* ...but never a figure. "anywhere" means exactly that, and it was breaking
   amounts after the comma — 1,24,536.75 arriving as two lines. Money and
   quantity columns opt out and keep their own single line. */
.table--fixed th.num,
.table--fixed td.num {
  overflow-wrap: normal;
}

/* Shorter rows: these tables are scanned down a column, and the default
   16px above and below put only a handful of orders on a screen. The row
   height is now set by its tallest control, not by padding. */
.table--fixed thead th,
.table--fixed tbody td,
.table--fixed tfoot td {
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
}
.table--fixed .btn--sm {
  height: 30px;
}
.table--fixed .cell-img {
  width: 34px;
  height: 34px;
}
/* the outer edges keep the panel's own gutter */
.table--fixed th:first-child,
.table--fixed td:first-child {
  padding-left: var(--s-5);
}
.table--fixed th:last-child,
.table--fixed td:last-child {
  padding-right: var(--s-5);
}

/* the row number — three digits at most, so it takes the least of any column */
.table--fixed col.w-no { width: 4%; }
.table--fixed col.w-img { width: 9%; }
/* These are relative weights, not real percentages — with table-layout:fixed
   the browser scales the set to the panel. Weight moved off the name columns
   and onto the money ones: a name wraps to a second line harmlessly, an amount
   must not, so the figures get the room and the names give it up. */
.table--fixed col.w-name { width: 15%; }
/* the dealer's name, which is what these tables are read by. It gets the width
   the Net and GST columns used to take. */
.table--fixed col.w-dealer { width: 22%; }
/* ORD-2026-0032 — 13 monospace characters, the widest fixed-size cell in
   either table, so it gets its own width rather than sharing w-code */
.table--fixed col.w-orderno { width: 16%; }
.table--fixed col.w-code { width: 11%; }
.table--fixed col.w-qty { width: 7%; }
.table--fixed col.w-money { width: 12%; }
.table--fixed col.w-pct { width: 7%; }
/* "19 Sep 2026" needs about 77px and was breaking after the month */
.table--fixed col.w-date { width: 12%; }
.table--fixed col.w-status { width: 8%; }
.table--fixed col.w-act { width: 5%; }
.table--fixed col.w-act--wide { width: 12%; }

/* the date is always "j M Y", so it can never be long enough to need a
   second line — keep it on one */
.table--fixed .cell-date {
  white-space: nowrap;
}

/* The order number reads as one token. Monospace at the table's own size
   needs about 109px for thirteen characters, which the column only clears
   on a wide window — so it is set a step smaller, and if the panel does get
   tight it breaks at its hyphens rather than mid-group the way the
   overflow-wrap rule above would. */
.table--fixed .cell-orderno {
  overflow-wrap: normal;
  word-break: keep-all;
}
.table--fixed .cell-orderno code {
  font-size: var(--fs-sm);
}

/* Icon-only actions, so all three keep to one line. Three 30px buttons plus
   two 4px gaps is 98px, inside the ~106px the column gives them. */
.table--fixed .row-actions {
  flex-wrap: nowrap;
  gap: var(--s-1);
}

/* Every figure column. nowrap is the real fix for an amount splitting over two
   lines: a number is one word to a person but the browser will happily break it
   after a comma or a space. tabular-nums makes each digit the same width, so
   the decimal points line up down the column. */
.table .num {
  text-align: right;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.table .center {
  text-align: center;
}
.table .actions {
  text-align: right;
  white-space: nowrap;
}
/* row actions stay quiet until you're on the row */
.table .actions .icon-btn {
  width: 32px;
  height: 32px;
  font-size: 1.05rem;
  opacity: 0;
  transition: opacity var(--t-fast), background-color var(--t-fast);
}
.table tbody tr:hover .actions .icon-btn,
.table .actions .icon-btn:focus-visible {
  opacity: 1;
}

/* name + avatar cell */
.cell-user {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
}
.cell-user strong {
  display: block;
  font-weight: 600;
  color: var(--text);
}
.cell-user small {
  color: var(--text-3);
  font-size: var(--fs-sm);
}

/* ============================== 13. Toolbar =============================== */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.toolbar .search {
  max-width: 300px;
  flex: 1 1 200px;
}
.toolbar .search input {
  height: 38px;
  background: var(--surface-3);
}
.toolbar__spacer {
  flex: 1 1 auto;
}

/* segmented filter */
.segment {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  background: var(--surface-3);
  border-radius: var(--r-md);
}
/* A label is a phrase, not a paragraph. Without this, a squeezed item breaks
   "Last 30 days" into three lines inside a box that is a fixed 32px tall, so
   the lines spill over the item above and below it. */
.segment a,
.segment button {
  white-space: nowrap;
}
.segment button {
  height: 32px;
  padding: 0 var(--s-4);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-2);
  background: transparent;
  border: none;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.segment button:hover {
  color: var(--text);
}
.segment button.is-active {
  background: var(--surface);
  color: var(--primary-600);
  box-shadow: var(--shadow-xs);
}

/* ========================= 14. Badges & status ============================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 11px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
}
.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.badge--success {
  color: var(--success);
  background: var(--success-bg);
}
.badge--warning {
  color: var(--warning);
  background: var(--warning-bg);
}
.badge--danger {
  color: var(--danger);
  background: var(--danger-bg);
}
.badge--info {
  color: var(--info);
  background: var(--info-bg);
}
.badge--neutral {
  color: var(--text-2);
  background: var(--surface-3);
}
.badge--plain::before {
  display: none;
}

/* ============================== 15. Avatars =============================== */
.avatar {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 50%;
  overflow: hidden;
  background: var(--primary-100);
  color: var(--primary-600);
  font-size: var(--fs-md);
  font-weight: 700;
  font-family: var(--font-display);
  text-transform: uppercase;
}
.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.avatar--sm {
  width: 32px;
  height: 32px;
  font-size: var(--fs-xs);
}
.avatar--lg {
  width: 64px;
  height: 64px;
  font-size: var(--fs-lg);
}
.avatar--xl {
  width: 96px;
  height: 96px;
  font-size: var(--fs-2xl);
}
/* presence dot */
.avatar[data-status]::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 2px solid var(--surface);
  background: var(--text-3);
}
.avatar[data-status="online"]::after {
  background: var(--accent-500);
}
.avatar[data-status="away"]::after {
  background: var(--warning);
}

.avatar-group {
  display: flex;
}
.avatar-group .avatar {
  border: 2px solid var(--surface);
  margin-left: -10px;
}
.avatar-group .avatar:first-child {
  margin-left: 0;
}

/* =============================== 16. Tabs ================================= */
.tabs {
  display: flex;
  gap: var(--s-1);
  overflow-x: auto;
  border-bottom: 1px solid var(--border);
  padding: 0 var(--s-5);
}
.tabs button {
  position: relative;
  padding: var(--s-4) var(--s-4);
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-2);
  background: none;
  border: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-fast);
}
.tabs button::after {
  content: "";
  position: absolute;
  left: var(--s-3);
  right: var(--s-3);
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--primary-600);
  transform: scaleX(0);
  transition: transform var(--t);
}
.tabs button:hover {
  color: var(--text);
}
.tabs button.is-active {
  color: var(--primary-600);
}
.tabs button.is-active::after {
  transform: scaleX(1);
}
.tab-panel[hidden] {
  display: none;
}

/* ============================= 17. Accordion ============================== */
.accordion details {
  border-bottom: 1px solid var(--border);
}
.accordion details:last-child {
  border-bottom: none;
}
.accordion summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.accordion summary::-webkit-details-marker {
  display: none;
}
.accordion summary::after {
  content: "+";
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--text-2);
  font-size: 1.1rem;
  transition: transform var(--t), background-color var(--t);
}
.accordion details[open] summary::after {
  content: "−";
  background: var(--primary-50);
  color: var(--primary-600);
}
.accordion summary:hover {
  color: var(--primary-600);
}
.accordion__body {
  padding: 0 0 var(--s-4);
  color: var(--text-2);
  font-size: var(--fs-md);
  max-width: 70ch;
}

/* =========================== 18. Empty state ============================== */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-3);
  padding: var(--s-8) var(--s-5);
}
.empty ion-icon {
  font-size: 2.4rem;
  color: var(--primary-500);
  background: var(--primary-50);
  padding: var(--s-4);
  border-radius: var(--r-full);
}
.empty h3 {
  font-size: var(--fs-lg);
}
.empty p {
  color: var(--text-2);
  max-width: 42ch;
  font-size: var(--fs-md);
}

/* ======================= 19. Progress & mini chart ======================== */
.progress {
  height: 8px;
  border-radius: var(--r-full);
  background: var(--surface-3);
  overflow: hidden;
}
.progress span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--bar-color, var(--primary-500));
  transition: width var(--t-slow);
}

/* CSS-only bar chart — bars set their own height via --h */
.chart {
  display: flex;
  align-items: flex-end;
  gap: clamp(6px, 1.4vw, 16px);
  height: 220px;
  padding-top: var(--s-4);
}
.chart__bar {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: var(--s-2);
  height: 100%;
  color: var(--text-3);
  font-size: var(--fs-xs);
}
.chart__bar i {
  width: 100%;
  height: var(--h, 40%);
  border-radius: var(--r-sm) var(--r-sm) 4px 4px;
  background: linear-gradient(180deg, var(--primary-400), var(--primary-600));
  opacity: 0.85;
  transition: opacity var(--t), transform var(--t);
}
.chart__bar:hover i {
  opacity: 1;
  transform: scaleY(1.03);
  transform-origin: bottom;
}
.chart__bar[data-peak] i {
  background: linear-gradient(180deg, var(--accent-400), var(--accent-600));
}
/* value tooltip on hover */
.chart__bar::before {
  content: attr(data-value);
  position: absolute;
  bottom: calc(var(--h, 40%) + 28px);
  padding: 4px 8px;
  border-radius: var(--r-sm);
  background: var(--text);
  color: var(--bg);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--t-fast);
  pointer-events: none;
}
.chart__bar:hover::before {
  opacity: 1;
}

/* legend + donut-ish breakdown list */
.breakdown {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.breakdown__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--s-2) var(--s-3);
  font-size: var(--fs-md);
}
.breakdown__row .progress {
  grid-column: 1 / -1;
}

/* ============================ 20. Pagination ============================== */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
}
.pagination__pages {
  display: flex;
  gap: var(--s-1);
}
.pagination button {
  min-width: 36px;
  height: 36px;
  padding: 0 var(--s-2);
  font: inherit;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-2);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.pagination button:hover:not(:disabled) {
  background: var(--surface-3);
  color: var(--text);
}
.pagination button.is-active {
  background: var(--primary-600);
  color: #fff;
}
.pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* =============================== 21. Inbox ================================ */
.inbox {
  display: grid;
  grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
  min-height: 560px;
}
.inbox__list {
  border-right: 1px solid var(--border);
  overflow-y: auto;
  max-height: 640px;
}
.thread {
  display: flex;
  gap: var(--s-3);
  width: 100%;
  padding: var(--s-4) var(--s-5);
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  border-left: 3px solid transparent;
  font: inherit;
  cursor: pointer;
  transition: background-color var(--t-fast);
}
.thread:hover {
  background: var(--surface-2);
}
.thread.is-active {
  background: var(--primary-50);
  border-left-color: var(--primary-600);
}
.thread__body {
  min-width: 0;
  flex: 1;
}
.thread__top {
  display: flex;
  justify-content: space-between;
  gap: var(--s-2);
}
.thread__name {
  font-weight: 600;
  font-size: var(--fs-md);
  color: var(--text);
}
.thread__time {
  font-size: var(--fs-xs);
  color: var(--text-3);
  white-space: nowrap;
}
.thread__preview {
  font-size: var(--fs-sm);
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.thread.is-unread .thread__name::after {
  content: "";
  display: inline-block;
  margin-left: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary-500);
}

.inbox__view {
  display: flex;
  flex-direction: column;
}
.inbox__head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.inbox__messages {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-5);
  overflow-y: auto;
  max-height: 420px;
}
.bubble {
  max-width: 68%;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-lg);
  font-size: var(--fs-md);
  line-height: 1.5;
}
.bubble--in {
  align-self: flex-start;
  background: var(--surface-3);
  color: var(--text);
  border-bottom-left-radius: var(--s-1);
}
.bubble--out {
  align-self: flex-end;
  background: var(--primary-600);
  color: #fff;
  border-bottom-right-radius: var(--s-1);
}
.bubble time {
  display: block;
  margin-top: var(--s-1);
  font-size: var(--fs-xs);
  opacity: 0.7;
}
.inbox__composer {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--border);
}

/* ==================== 21b. Mobile bottom bar & More sheet =================
   Built by main.js and shown only below the drawer breakpoint. The sheet's
   contents are cloned from the rendered sidebar, so the menu has exactly one
   source of truth (NAV_ITEMS in shell.js).                                */
.bottombar {
  display: none; /* desktop: hidden, see the media query below */
  position: fixed;
  inset: auto 0 0 0;
  z-index: 800;
  grid-template-columns: repeat(4, 1fr);
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 20px rgba(22, 25, 44, 0.08);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.bottombar__item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 58px;
  padding: var(--s-2) 4px;
  font: inherit;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-3);
  background: none;
  border: none;
  cursor: pointer;
  transition: color var(--t-fast);
}
.bottombar__item ion-icon {
  font-size: 1.45rem;
}
.bottombar__item:hover {
  color: var(--text-2);
}
.bottombar__item.is-active {
  color: var(--primary-600);
}
/* active indicator sits on the top edge, mirroring the sidebar's accent bar */
.bottombar__item.is-active::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 26px;
  height: 3px;
  border-radius: 0 0 3px 3px;
  background: var(--primary-600);
}
.bottombar__item .nav__count {
  position: absolute;
  top: 6px;
  left: 50%;
  margin-left: 6px;
  min-width: 17px;
  height: 17px;
  padding: 0 5px;
  font-size: 10px;
}

/* ---- the More sheet ---- */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 950;
  visibility: hidden;
}
.sheet.is-open {
  visibility: visible;
}
.sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(16, 17, 31, 0.55);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--t);
}
.sheet.is-open .sheet__backdrop {
  opacity: 1;
}

.sheet__panel {
  position: absolute;
  inset: auto 0 0 0;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--shadow-lg);
  transform: translateY(100%);
  transition: transform var(--t-slow);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.sheet.is-open .sheet__panel {
  transform: translateY(0);
}

.sheet__grip {
  width: 40px;
  height: 4px;
  margin: var(--s-3) auto var(--s-1);
  border-radius: var(--r-full);
  background: var(--border-strong);
  flex: 0 0 auto;
}
.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-5) var(--s-3);
  border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
.sheet__head h2 {
  font-size: var(--fs-lg);
}
.sheet__list {
  overflow-y: auto;
  padding: var(--s-3);
  -webkit-overflow-scrolling: touch;
}

.sheet__item {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: 13px var(--s-4);
  border-radius: var(--r-md);
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--text);
  transition: background-color var(--t-fast);
}
.sheet__item ion-icon {
  flex: 0 0 auto;
  font-size: 1.4rem;
  color: var(--text-3);
}
.sheet__item:hover {
  background: var(--surface-3);
  color: var(--text);
}
.sheet__item.is-active {
  background: var(--primary-50);
  color: var(--primary-600);
}
.sheet__item.is-active ion-icon {
  color: var(--primary-600);
}

@media (max-width: 900px) {
  .bottombar {
    display: grid;
  }
  /* keep the last rows of content clear of the fixed bar */
  .content {
    padding-bottom: calc(58px + var(--gutter) + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================= 22. Responsive ============================= */

/* NOTE: no auto-collapse breakpoint here on purpose. Pinning .app to the rail
   width by media query narrowed the column without adding .is-collapsed, so
   the full-width labels stayed in an 80px column and the toggle could no
   longer widen it. Sidebar width is driven by .is-collapsed alone. */

/* tablet & phone: sidebar becomes an overlay drawer */
@media (max-width: 900px) {
  .app,
  .app.is-collapsed {
    grid-template-columns: minmax(0, 1fr);
  }
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--nav-w);
    transform: translateX(-100%);
    transition: transform var(--t-slow);
  }
  .app.is-drawer-open .sidebar {
    transform: translateX(0);
    box-shadow: var(--shadow-lg);
  }
  .app.is-drawer-open .app__backdrop {
    display: block;
  }
  /* the rail styles are scoped to min-width: 901px, so the drawer keeps its
     full labels here with no overrides needed */

  .inbox {
    grid-template-columns: minmax(0, 1fr);
  }
  .inbox__list {
    border-right: none;
    border-bottom: 1px solid var(--border);
    max-height: 260px;
  }
}

/* phone: search moves to its own row, tables become stacked cards */
@media (max-width: 640px) {
  .topbar {
    flex-wrap: wrap;
    padding-bottom: var(--s-3);
  }
  .search {
    order: 3;
    flex-basis: 100%;
    max-width: none;
  }
  .search kbd {
    display: none;
  }
  .page-head__actions .btn {
    flex: 1 1 auto;
  }

  /* A stacking table turns into cards down here, so its wrap has nothing left
     to scroll and the overflow box would only clip the row shadows.
     Scoped with :has() on purpose — this used to apply to every .table-wrap,
     which switched off sideways scrolling for the tables that do NOT stack
     (the mini tables on the dashboard, the catalogue, the specs) and left them
     dragging the whole page sideways instead. */
  .table-wrap:has(.table--stack) {
    overflow-x: visible;
  }

  /* Down here the rows have become cards and the screen is short. A box
     within a box to scroll is no help — let the page carry them. */
  .table-wrap--tall:has(.table--stack) {
    max-height: none;
    overflow-y: visible;
  }
  .table-wrap--tall:has(.table--stack) .table tfoot td {
    position: static;
  }

  /* A table that does not stack keeps its own scrollbar, and keeps a width
     worth reading: squeezing ten columns into 360px is not "responsive". */
  .table-wrap:not(:has(.table--stack)) > .table {
    min-width: 560px;
  }

  .table--stack thead {
    display: none;
  }
  .table--stack,
  .table--stack tbody,
  .table--stack tfoot,
  .table--stack tr,
  .table--stack td {
    display: block;
    width: 100%;
  }
  .table--stack tr {
    padding: var(--s-3) var(--s-5);
    border-bottom: 8px solid var(--bg);
  }
  .table--stack td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    padding: var(--s-2) 0;
    text-align: right;
    border-bottom: 1px dashed var(--border);
  }
  .table--stack td:last-child {
    border-bottom: none;
  }
  .table--stack td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-3);
    text-align: left;
  }
  /* the identity cell reads better as a normal row, unlabelled */
  .table--stack td:has(.cell-user) {
    text-align: left;
  }
  .table--stack td:has(.cell-user)::before {
    display: none;
  }
  .table--stack .actions .icon-btn {
    opacity: 1;
  }

  .bubble {
    max-width: 85%;
  }
}

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

/* gentle entrance for content panels */
@media (prefers-reduced-motion: no-preference) {
  .content > * {
    animation: rise 0.45s var(--ease) both;
  }
  .content > *:nth-child(2) {
    animation-delay: 0.05s;
  }
  .content > *:nth-child(3) {
    animation-delay: 0.1s;
  }
  .content > *:nth-child(4) {
    animation-delay: 0.15s;
  }
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}


/* ============================ 20. Modal =================================== */
/* Centred dialog on desktop; a near-full-height sheet on phones so the form
   has room and the keyboard doesn't cover the fields. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 960;
}
.modal[hidden] {
  display: none;
}
.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(16, 17, 31, 0.55);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--t);
}
.modal.is-open .modal__backdrop {
  opacity: 1;
}

.modal__panel {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -46%);
  width: min(880px, calc(100vw - 2 * var(--s-4)));
  max-height: min(86vh, 900px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transition: opacity var(--t), transform var(--t);
}
.modal.is-open .modal__panel {
  opacity: 1;
  transform: translate(-50%, -50%);
}

.modal__head,
.modal__foot {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  flex: 0 0 auto;
}
.modal__head {
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
}
.modal__head h2 {
  margin: 0;
  font-size: var(--fs-lg);
}
.modal__foot {
  justify-content: flex-end;
  border-top: 1px solid var(--border);
  padding-bottom: max(var(--s-4), env(safe-area-inset-bottom, 0px));
}

/* the only scrolling region, so head and footer stay put */
.modal__body {
  padding: var(--s-5);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1 1 auto;
}

.modal__panel form {
  display: contents;
}

/* auto-fitting columns: 3-up on wide, 2-up on tablet, 1-up on phone,
   with no media query needed for the columns themselves */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--s-4);
}
.form-grid .field--wide {
  grid-column: 1 / -1;
}
.form-grid .req {
  color: var(--danger);
}
.field-error {
  font-size: var(--fs-sm);
  color: var(--danger);
}
.form-alert {
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger);
}
.form-grid input[type="file"] {
  width: 100%;
  font-size: var(--fs-sm);
}
/* radios (price inclusive/exclusive) read better stacked */
.form-grid ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}
.form-grid ul label {
  font-weight: 400;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
}

@media (max-width: 640px) {
  .modal__panel {
    inset: auto 0 0 0;
    left: 0;
    top: auto;
    transform: translateY(100%);
    width: 100%;
    max-height: 92vh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-bottom: 0;
  }
  .modal.is-open .modal__panel {
    transform: translateY(0);
  }
  .modal__head,
  .modal__body,
  .modal__foot {
    padding-left: var(--s-4);
    padding-right: var(--s-4);
  }
  .modal__foot .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .modal__backdrop,
  .modal__panel {
    transition: none;
  }
}


/* ======================= 21. Product table cells ========================== */
.cell-img {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--bg);
  display: block;
}

/* keep long descriptions from stretching the row */
.cell-desc {
  max-width: 260px;
  color: var(--text-2);
  font-size: var(--fs-sm);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 860px) {
  /* On a phone each row becomes a card, so only the fields worth reading
     there are kept: name, price, stock, status, description. Image, part
     no, brand and unit stay available on the wider layout. */
  .table--stack .hide-sm,
  .table--stack thead .hide-sm {
    display: none !important;
  }

  .table--stack .cell-desc {
    max-width: none;
    -webkit-line-clamp: 3;
    text-align: right;
  }

  /* the name cell carries the brand underneath, so nothing is lost */
  .table--stack .cell-user small {
    display: block;
    color: var(--text-3);
  }
}


/* success variant of the form alert (dealer profile saved, etc.) */
.form-alert--ok {
  background: color-mix(in srgb, var(--success, #16a34a) 12%, transparent);
  color: var(--success, #16a34a);
}


/* ========================= 22. Orders & printout ========================== */
.om-totals {
  margin-left: auto;
  border-collapse: collapse;
  min-width: 260px;
}
.om-totals td {
  padding: var(--s-2) 0 var(--s-2) var(--s-6);
}
.om-totals .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* the same reason as .table .num — a grand total on two lines reads wrong */
  white-space: nowrap;
}
.om-totals__grand td {
  border-top: 1px solid var(--border-strong);
  font-weight: 700;
  font-size: var(--fs-lg);
}

.order-actions {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  margin-top: var(--s-4);
}

/* the reason a disabled Place Order button is disabled */
.hint--bad {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--danger);
}
.hint--bad ion-icon {
  flex: 0 0 auto;
  font-size: 1.1rem;
}

/* ---------------------------------------------------- pre-flight checklist */
/* One row per order line: a tick when the quantity fits what is on the shelf,
   a cross and the shortfall when it does not. */
.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
}

.checklist__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-3);
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.checklist__row:last-child {
  border-bottom: none;
}
.checklist__row.is-short {
  background: var(--danger-bg);
}

.checklist__mark {
  flex: 0 0 auto;
  font-size: 1.25rem;
  color: var(--success);
}
.checklist__row.is-short .checklist__mark {
  color: var(--danger);
}

/* min-width:0 so a long product name wraps instead of shoving the stock
   figures off the end of the row */
.checklist__name {
  flex: 1 1 220px;
  min-width: 0;
  font-weight: 600;
  color: var(--text);
}
.checklist__name small {
  display: block;
  font-weight: 400;
  font-size: var(--fs-sm);
}

.checklist__note {
  flex: 0 1 auto;
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.checklist__row.is-short .checklist__note {
  color: var(--danger);
}

@media (max-width: 560px) {
  .checklist__row {
    padding: var(--s-3);
  }
  .checklist__note {
    flex-basis: 100%;
    padding-left: calc(1.25rem + var(--s-3));
  }
}

/* ------------------------------------------------- invoice / printout ----
   A commercial invoice: letterhead, bill-to, fixed-width line items, totals,
   payment details with the UPI QR, terms and signature. */
.print-page {
  background: var(--bg);
  padding: var(--s-5);
}

.print-sheet {
  box-sizing: border-box;
  width: 100%;
  max-width: 210mm;              /* A4 */
  margin: 0 auto;
  padding: 14mm 16mm;            /* the invoice's own left/right margin */
  background: #fff;
  color: #1f2937;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  font-size: 12px;
  line-height: 1.5;
}

/* the sheet is always a white page, even in dark mode — it is paper */
.print-sheet h1,
.print-sheet h2,
.print-sheet h3,
.print-sheet strong { color: #111827; }

.print-sheet p { margin: 0; }

/* ---------- letterhead ---------- */
.inv-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding-bottom: 12px;
  border-bottom: 2px solid #1d4e89;
}

.inv-brand {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  min-width: 0;
}

.inv-brand__logo {
  width: 68px;
  height: 68px;
  object-fit: contain;
  flex: 0 0 auto;
}

.inv-brand__text { min-width: 0; }

.inv-brand h1 {
  margin: 0 0 4px;
  font-size: 19px;
  line-height: 1.2;
  letter-spacing: -.01em;
}

.inv-brand p {
  font-size: 11px;
  line-height: 1.55;
  color: #4b5563;
}

.inv-brand__gstin {
  margin-top: 4px !important;
  font-weight: 600;
  color: #1f2937 !important;
}

.inv-title { text-align: right; flex: 0 0 auto; }

.inv-title h2 {
  margin: 0 0 6px;
  font-size: 26px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #1d4e89;
}

.inv-meta {
  margin-left: auto;
  border-collapse: collapse;
  font-size: 11px;
}

.inv-meta td { padding: 1px 0 1px 12px; text-align: right; white-space: nowrap; }
.inv-meta td:first-child { color: #6b7280; text-align: left; padding-left: 0; }

/* ---------- bill to ---------- */
.inv-bill {
  padding: 10px 0;
  border-bottom: 1px solid #e5e7eb;
}

.inv-bill h3,
.inv-pay h3,
.inv-close h3 {
  margin: 0 0 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: #6b7280;
  font-weight: 700;
}

.inv-bill__name { font-size: 14px; font-weight: 700; margin-bottom: 2px !important; }
.inv-bill p { font-size: 11px; line-height: 1.55; color: #4b5563; }

/* ---------- line items ---------- */
/* fixed layout + colgroup widths: the table can never grow past the sheet,
   long product names wrap inside their column instead */
.inv-items {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  margin-top: 12px;
  font-size: 11px;
}

.inv-items col.c-sr    { width: 4%; }
.inv-items col.c-desc  { width: 30%; }
.inv-items col.c-hsn   { width: 9%; }
.inv-items col.c-qty   { width: 10%; }
.inv-items col.c-rate  { width: 10%; }
.inv-items col.c-net   { width: 11%; }
.inv-items col.c-gstp  { width: 7%; }
.inv-items col.c-gst   { width: 9%; }
.inv-items col.c-total { width: 10%; }

.inv-items th {
  background: #1d4e89;
  color: #fff;
  font-weight: 600;
  text-align: left;
  padding: 7px 6px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.inv-items td {
  padding: 7px 6px;
  border-bottom: 1px solid #e5e7eb;
  vertical-align: top;
  overflow-wrap: anywhere;       /* stop a long code stretching the column */
}

.inv-items .num { text-align: right; font-variant-numeric: tabular-nums; }
.inv-items th.num { text-align: right; }

.inv-items tbody tr:nth-child(even) td { background: #f9fafb; }

.inv-items__name { display: block; font-weight: 600; color: #111827; }
.inv-items__sub { display: block; font-size: 10px; color: #6b7280; margin-top: 1px; }

/* the totals row under the line items */
.inv-items tfoot td {
  padding: 7px 6px;
  background: #eef2f7;
  border-top: 1.5px solid #1d4e89;
  font-weight: 700;
  color: #111827;
}
.inv-items tfoot .num { text-align: right; font-variant-numeric: tabular-nums; }

/* several unit totals on one line — smaller, so "10 SET · 5 BOX · 3 KG"
   still fits the merged HSN+Qty width without wrapping to three rows */
.inv-items__units {
  font-size: 10px;
  letter-spacing: -.01em;
  white-space: normal;
}

/* ---------- tax details ---------- */
/* Narrower and quieter than the line items: this block is read to check the
   tax, not to read the order, so it must not compete with the table above. */
/* Tax details and totals share one row. Stacked, the pair cost about 45mm of
   height and pushed the payment and signature blocks onto a second sheet. */
.inv-close-row {
  display: flex;
  align-items: flex-start;
  gap: 18px;
  margin-top: 14px;
}

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

.inv-tax h3 {
  margin: 0 0 6px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: #6b7280;
  font-weight: 700;
}

.inv-tax__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 10.5px;
}

.inv-tax__table th {
  padding: 6px 8px;
  text-align: left;
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #4b5563;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
}

.inv-tax__table td {
  padding: 6px 8px;
  border: 1px solid #e5e7eb;
}

.inv-tax__table .num { text-align: right; font-variant-numeric: tabular-nums; }
.inv-tax__table th.num { text-align: right; }

.inv-tax__table code { font-family: inherit; color: #111827; }

.inv-tax__table tfoot td {
  font-weight: 700;
  color: #111827;
  background: #f9fafb;
}

/* ---------- totals ---------- */
/* flex-none so the tax table takes the leftover width, not this one */
.inv-sum { display: flex; justify-content: flex-end; flex: 0 0 auto; }

.inv-sum__table {
  border-collapse: collapse;
  min-width: 240px;
  font-size: 11.5px;
}

.inv-sum__table td { padding: 4px 0 4px 18px; text-align: right; }
.inv-sum__table td:first-child { text-align: left; color: #6b7280; padding-left: 0; }

.inv-sum__grand td {
  border-top: 1.5px solid #1d4e89;
  padding-top: 7px;
  font-size: 14px;
  font-weight: 700;
  color: #1d4e89;
}

/* Side by side needs the width of a sheet. On a phone the invoice is being
   read rather than printed, so the pair stacks again. */
@media (max-width: 720px) {
  .inv-close-row {
    flex-direction: column;
    gap: 12px;
  }
  .inv-sum {
    align-self: stretch;
  }
}

/* ---------- payment ---------- */
.inv-pay {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  justify-content: space-between;
  margin-top: 16px;
  padding: 10px 12px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
}

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

.inv-kv { border-collapse: collapse; font-size: 11px; }
.inv-kv td { padding: 2px 14px 2px 0; vertical-align: top; }
.inv-kv td:first-child { color: #6b7280; white-space: nowrap; }
.inv-kv td:last-child { font-weight: 600; overflow-wrap: anywhere; }

.inv-pay__qr { margin: 0; text-align: center; flex: 0 0 auto; }

.inv-pay__qr img {
  width: 104px;
  height: 104px;
  object-fit: contain;
  padding: 5px;
  background: #fff;              /* a QR on a tint will not scan reliably */
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  display: block;
}

.inv-pay__qr figcaption { font-size: 9.5px; color: #6b7280; margin-top: 3px; line-height: 1.4; }

/* ---------- terms + signature ---------- */
.inv-close {
  display: flex;
  gap: 24px;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 18px;
}

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

.inv-close__terms ol {
  margin: 0;
  padding-left: 16px;
  font-size: 10px;
  color: #4b5563;
  line-height: 1.6;
}

.inv-close__sign {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 42px;
  min-width: 190px;
  font-size: 11px;
}

.inv-close__for { font-weight: 600; }

.inv-close__line {
  width: 100%;
  padding-top: 5px;
  border-top: 1px solid #9ca3af;
  text-align: center;
  color: #6b7280;
  font-size: 10px;
}

.inv-note {
  margin-top: 14px !important;
  padding-top: 8px;
  border-top: 1px solid #e5e7eb;
  font-size: 9.5px;
  color: #9ca3af;
  text-align: center;
}

.print-actions { margin-top: var(--s-5); text-align: right; }

/* ---------- small screens ---------- */
@media (max-width: 720px) {
  .print-page { padding: var(--s-3); }
  .print-sheet { padding: 12px; font-size: 11px; }
  .inv-head { flex-direction: column; }
  .inv-title { text-align: left; }
  .inv-meta { margin-left: 0; }
  .inv-meta td { text-align: left; padding-left: 12px; }
  .inv-pay { flex-direction: column; align-items: stretch; }
  .inv-pay__qr { align-self: center; }
  .inv-close { flex-direction: column; align-items: stretch; }
  .inv-close__sign { align-items: flex-start; margin-top: 24px; }

  /* the item table is the one thing allowed to scroll sideways */
  .inv-items { display: block; overflow-x: auto; white-space: nowrap; }
  .inv-items td { overflow-wrap: normal; }
}

/* ---------- print ---------- */
@media print {
  /* margin:0 removes the browser's own header and footer — the date, time,
     page title and URL it otherwise prints into the page margin. The sheet's
     padding supplies the real margin instead. */
  @page {
    size: A4;
    margin: 0;
  }

  html, body { margin: 0; padding: 0; background: #fff; }

  .no-print { display: none !important; }

  /* a scroll box has no meaning on paper — print the table whole, and never
     let the overflow box clip a column off the edge of the sheet */
  .table-wrap {
    overflow: visible !important;
    min-width: 0 !important;
    /* a capped height would print only the rows that happen to fit */
    max-height: none !important;
  }
  .table-wrap > .table { min-width: 0 !important; }
  /* sticky has no meaning on paper and can reprint the row on every sheet */
  .table-wrap--tall .table tfoot td,
  .table thead th { position: static !important; }

  .print-page { padding: 0; background: #fff; }

  .print-sheet {
    max-width: none;
    width: auto;
    margin: 0;
    padding: 10mm 12mm;
    border: 0;
    border-radius: 0;
    font-size: 10pt;
  }

  .inv-items { font-size: 8.5pt; margin-top: 9px; }
  .inv-items th { padding: 4px 5px; }
  .inv-items td { padding: 4px 5px; }
  .inv-items tfoot td { padding: 5px; }

  .inv-tax__table { font-size: 8pt; }
  .inv-tax__table th,
  .inv-tax__table td { padding: 4px 6px; }

  /* Everything below the line items, tightened. A one-page invoice is the
     point: these blocks are read, not studied, and the space between them
     was the difference between one sheet and two. */
  .inv-head { padding-bottom: 9px; }
  .inv-bill { padding: 8px 0; }
  .inv-close-row { margin-top: 10px; gap: 14px; }
  .inv-tax { margin: 0; }
  .inv-pay { margin-top: 10px; padding: 8px 10px; }
  .inv-pay__qr img { width: 86px; height: 86px; }
  .inv-close { margin-top: 12px; }
  .inv-close__sign { gap: 30px; }
  /* !important only to beat the same flag on the base rule */
  .inv-note { margin-top: 10px !important; }

  /* colours must survive the printer's "no background graphics" default */
  .inv-items th,
  .inv-items tfoot td,
  .inv-pay,
  .inv-tax__table th,
  .inv-tax__table tfoot td,
  .inv-items tbody tr:nth-child(even) td {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  thead { display: table-header-group; }
  .inv-items tr,
  .inv-pay,
  .inv-close,
  .inv-close-row,
  .inv-tax,
  .inv-sum { page-break-inside: avoid; }
}
/* ====================== 23. Product cards (shop) ==========================
   Horizontal cards: thumbnail on the left, details and the add control on
   the right — the layout a messaging-app catalogue uses. */
.product-grid {
  display: grid;
  /* three across on desktop. minmax(0,…) not minmax(380px,…): the 0 lets a
     column shrink below its content, which is what stops a long product name
     from pushing the row wider than the panel. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-4);
  padding: var(--s-5);
}

.product-card {
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.product-card:hover {
  border-color: var(--primary-500);
  box-shadow: var(--shadow-lg);
}
.product-card[hidden] {
  display: none;
}

.product-card__media {
  /* roughly 40% of the card — big enough to actually judge the product */
  flex: 0 0 clamp(128px, 40%, 180px);
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-2);
}
.product-card__media img {
  width: 100%;
  height: 100%;
  min-height: 158px;
  /* contain, not cover: cover crops the edges off a product photo, which is
     exactly what you must not do in a catalogue */
  object-fit: contain;
  display: block;
}

/* details above, add control pinned to the bottom of the card */
.product-card__main {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4);
  flex: 1 1 auto;
  min-width: 0;
}
.product-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  align-items: flex-start;
  min-width: 0;
}
.product-card__name {
  font-size: var(--fs-md);
  font-weight: 700;
  color: inherit;
  text-decoration: none;
  line-height: 1.3;
  /* two lines max, so one long name can't make its card taller than the row */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.product-card__body small,
.product-card__name {
  overflow-wrap: anywhere;
}
.product-card__body > small {
  max-width: 100%;
}
.product-card__price {
  display: flex;
  flex-direction: column;
  margin: var(--s-1) 0;
}
.product-card__amount {
  font-size: var(--fs-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.product-card__foot {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-wrap: wrap;          /* qty drops above the button when very narrow */
}
.product-card__foot .input {
  width: 58px;
  flex: 0 0 auto;
  text-align: center;
  min-height: 38px;
  padding-left: var(--s-2);
  padding-right: var(--s-2);
}
.product-card__foot .btn {
  flex: 1 1 88px;
  justify-content: center;
  min-height: 38px;
  padding-left: var(--s-3);
  padding-right: var(--s-3);
}

/* ------------------------------------------------------- live cart panel */
.cart-panel {
  position: sticky;
  bottom: var(--s-3);
  margin-top: var(--s-5);
}

/* compact table — the cart is a glance, not a document */
.table--mini th,
.table--mini td {
  padding: var(--s-2) var(--s-4);
  font-size: var(--fs-sm);
}
.table--mini tfoot td {
  border-top: 1px solid var(--border-strong);
  font-variant-numeric: tabular-nums;
}

/* Three cards need roughly 1180px of viewport once the sidebar is open.
   Below that, drop to two, then to one — the card layout itself is unchanged. */
@media (max-width: 1180px) {
  .product-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .product-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 560px) {
  .product-grid {
    gap: var(--s-3);
    padding: var(--s-3);
  }
  .product-card__media {
    flex: 0 0 clamp(112px, 34%, 140px);
  }
  .product-card__media img {
    min-height: 124px;
  }
  .product-card__main {
    padding: var(--s-3);
  }
}


/* ==================== 24. Product details (one page) ======================
   Used by products/product_detail.html only — every module links to that
   page rather than repeating the product layout. */
.detail {
  display: grid;
  grid-template-columns: minmax(0, 520px) minmax(0, 1fr);
  gap: var(--s-5);
  padding: var(--s-5);
}

/* front view across the full width, the other three sides as thumbnails */
.detail__media {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-3);
  align-content: start;
}
.detail__media .is-main {
  grid-column: 1 / -1;
}

.detail__media figure {
  margin: 0;
  text-align: center;
}

/* the frame clips the image, so scaling it reads as a zoom rather than
   pushing the layout around */
.zoom {
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: zoom-in;
}
.zoom img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  padding: var(--s-2);
  display: block;
  transition: transform var(--t-slow);
}
.zoom:hover img,
.zoom:focus-within img {
  transform: scale(1.9);
}
.detail__media .is-main img {
  aspect-ratio: 4 / 3;
}
.detail__media figcaption {
  font-size: var(--fs-xs);
  padding-bottom: var(--s-1);
}

/* a touch screen has no hover — don't leave the zoom stuck on after a tap */
@media (hover: none) {
  .zoom:hover img,
  .zoom:focus-within img {
    transform: none;
  }
  .zoom {
    cursor: default;
  }
}

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

.detail__buy {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-wrap: wrap;
  margin: var(--s-2) 0;
}
.detail__buy .input {
  width: 84px;
  flex: 0 0 auto;
  text-align: center;
}

.detail__info {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  min-width: 0;
}
.detail__price {
  display: flex;
  flex-direction: column;
}
.detail__amount {
  font-size: var(--fs-xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.detail__specs td:first-child {
  width: 42%;
  color: var(--text-3);
}

@media (max-width: 860px) {
  .detail {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--s-4);
  }
}


/* thumbnails on the details page swap into the large slot when clicked */
.detail__media figure:not(.is-main) {
  cursor: pointer;
}
.detail__media figure:not(.is-main):hover {
  border-color: var(--primary-500);
}

/* the Details column must stay reachable when the table scrolls sideways */
.table .actions .btn {
  opacity: 1;
}


/* stock + New badges sit side by side on a product card */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}


/* ======================== 25. Contact page ================================ */
.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s-5);
  padding: var(--s-5);
}

.contact__info {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
}

.contact__info td:first-child {
  width: 34%;
  color: var(--text-3);
  white-space: nowrap;
}

.contact__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

/* the map keeps its shape at any width */
.contact__map {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg);
}

.contact__map iframe {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 320px;
  border: 0;
}

@media (max-width: 860px) {
  .contact {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--s-4);
  }

  .contact__map iframe {
    min-height: 240px;
  }
}


/* ========================== 26. About us page ============================= */
.about-hero {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  flex-wrap: wrap;
  padding: var(--s-5);
  border-bottom: 1px solid var(--border);
}

.about-hero__logo img {
  width: clamp(96px, 20vw, 160px);
  aspect-ratio: 1;
  object-fit: contain;
  padding: var(--s-3);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  display: block;
}

.about-hero__text {
  min-width: 0;
  flex: 1 1 240px;
}

.about-hero__text h2 {
  margin: 0 0 var(--s-1);
  font-size: var(--fs-xl);
}

/* a comfortable reading measure rather than the full panel width */
.about-body {
  padding: var(--s-5);
  max-width: 78ch;
}

/* ---- rendered rich text (admin-authored HTML) ---- */
.richtext {
  min-width: 0;
  color: var(--text-2);
  line-height: 1.75;
}

.richtext > :first-child { margin-top: 0; }
.richtext > :last-child { margin-bottom: 0; }

.richtext h1,
.richtext h2,
.richtext h3,
.richtext h4 {
  color: var(--text);
  margin: var(--s-5) 0 var(--s-3);
  line-height: 1.3;
}

.richtext p { margin: 0 0 var(--s-4); }

.richtext ul,
.richtext ol {
  margin: 0 0 var(--s-4);
  padding-left: var(--s-6);
}

.richtext li { margin-bottom: var(--s-2); }

.richtext strong,
.richtext b { color: var(--text); }

.richtext a { color: var(--primary-500); }

.richtext hr {
  margin: var(--s-5) 0;
  border: 0;
  border-top: 1px solid var(--border);
}

.richtext blockquote {
  margin: 0 0 var(--s-4);
  padding: var(--s-2) 0 var(--s-2) var(--s-4);
  border-left: 3px solid var(--primary-500);
  color: var(--text-3);
  font-style: italic;
}

/* images and figures the editor inserts */
.richtext img {
  max-width: 100%;
  height: auto;
  border-radius: var(--r-md);
}

.richtext figure {
  margin: 0 0 var(--s-4);
}

.richtext figcaption {
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--text-3);
  text-align: center;
}

/* tables from the table plugin */
.richtext table {
  width: 100%;
  margin: 0 0 var(--s-4);
  border-collapse: collapse;
}

.richtext th,
.richtext td {
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--border);
  text-align: left;
}

.richtext th {
  background: var(--bg);
  color: var(--text);
  font-weight: 600;
}

/* code from the codesample plugin */
.richtext pre {
  margin: 0 0 var(--s-4);
  padding: var(--s-4);
  overflow-x: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
}

.richtext code {
  font-size: .95em;
}

/* the editor writes alignment as inline styles or these classes */
.richtext .mce-content-body [style*="text-align"] { display: block; }

/* embedded video from the media plugin */
.richtext iframe {
  max-width: 100%;
  border: 0;
  border-radius: var(--r-md);
}

@media (max-width: 760px) {
  .about-hero,
  .about-body {
    padding: var(--s-4);
  }

  .richtext table {
    display: block;
    overflow-x: auto;
  }
}


/* ======================== 27. Bank details ================================ */
.bank {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 260px);
  gap: var(--s-5);
  padding: var(--s-5);
  align-items: start;
}

.bank__info {
  min-width: 0;
}

.bank__info td:first-child {
  width: 38%;
  color: var(--text-3);
  white-space: nowrap;
}

/* the QR must stay on a light ground or phone cameras struggle to read it */
.bank__qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  text-align: center;
}

.bank__qr img {
  width: 100%;
  max-width: 240px;
  aspect-ratio: 1;
  object-fit: contain;
  padding: var(--s-3);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  display: block;
}

@media (max-width: 760px) {
  .bank {
    grid-template-columns: minmax(0, 1fr);
    padding: var(--s-4);
  }

  .bank__qr img {
    max-width: 200px;
    margin: 0 auto;
  }
}


/* ==================== 28. Export dropdown (products) ====================== */
.export-menu {
  position: relative;
}

/* hide the default disclosure triangle */
.export-menu > summary {
  list-style: none;
  cursor: pointer;
}

.export-menu > summary::-webkit-details-marker {
  display: none;
}

/* the second chevron rotates when the menu is open */
.export-menu[open] > summary ion-icon:last-child {
  transform: rotate(180deg);
}

.export-menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--s-2));
  z-index: 60;
  min-width: 170px;
  display: block;
  padding: var(--s-2);
}

@media (max-width: 560px) {
  .export-menu__panel {
    right: auto;
    left: 0;
  }
}


/* ============ 29. Segment + pagination: links as well as buttons ==========
   The products toolbar and pager use <a> now that filtering and paging are
   server side; these mirror the existing button rules onto anchors. */
.segment a {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 var(--s-4);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-2);
  text-decoration: none;
  border-radius: var(--r-sm);
  transition: background-color var(--t-fast), color var(--t-fast);
}

.segment a:hover {
  color: var(--text);
}

.segment a.is-active {
  background: var(--surface);
  color: var(--primary-600);
  box-shadow: var(--shadow-xs);
}

.pagination a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 36px;
  padding: 0 var(--s-2);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text-2);
  text-decoration: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
}

.pagination a:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

/* the search box is a form now — keep it laid out like the old div */
.toolbar form.search {
  margin: 0;
}


/* smaller segment for the page-size switch in the table footer */
.segment--sm a {
  height: 26px;
  padding: 0 var(--s-3);
  font-size: var(--fs-xs);
}


/* the row-number column only ever holds 1-3 digits — width:1% makes an auto
   table shrink the column to its content instead of sharing space evenly */
.table .cell-no {
  width: 1%;
  white-space: nowrap;
  padding-left: var(--s-3);
  padding-right: var(--s-2);
  font-size: var(--fs-sm);
}


/* ============ 30. Products table as cards on mobile =======================
   Below 640px .table--stack already turns each row into a block. These rules
   go further and lay that block out like the shop catalogue card: thumbnail
   on the left, details on the right. Desktop is untouched — everything here
   is inside the media query and scoped to #productsTable. */
@media (max-width: 640px) {

  #productsTable tbody tr {
    display: grid;
    grid-template-columns: 104px minmax(0, 1fr);
    align-items: start;
    gap: 2px var(--s-3);
    padding: var(--s-3);
    border-bottom: 8px solid var(--bg);
  }

  /* the picture sits in column 1 and spans the text lines beside it */
  #productsTable .cell-media {
    display: block;
    grid-column: 1;
    grid-row: 1 / span 4;
    padding: 0;
    border: 0;
  }

  #productsTable .cell-media::before {
    display: none;
  }

  #productsTable .cell-media .cell-img {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    object-fit: contain;
    padding: var(--s-2);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
  }

  /* every other visible cell stacks in column 2 */
  #productsTable tbody td:not(.cell-media) {
    grid-column: 2;
    padding: 1px 0;
    border: 0;
  }

  /* the name leads the card, with no label in front of it */
  #productsTable td[data-label="Name"] {
    display: block;
    text-align: left;
  }

  #productsTable td[data-label="Name"]::before {
    display: none;
  }

  #productsTable td[data-label="Name"] .cell-user {
    gap: 0;
  }

  /* price is the number people scan for */
  #productsTable td[data-label="Price"] {
    font-size: var(--fs-lg);
    font-weight: 700;
    color: var(--text);
  }

  /* status reads better as just the badge */
  #productsTable td[data-label="Status"]::before {
    display: none;
  }

  #productsTable td[data-label="Status"] {
    justify-content: flex-start;
    padding-top: var(--s-2);
  }

  /* the action runs full width under the card, like the shop's Add button */
  #productsTable td.actions {
    grid-column: 1 / -1;
    margin-top: var(--s-3);
  }

  #productsTable td.actions .row-actions {
    display: flex;
    width: 100%;
    gap: var(--s-2);
  }

  /* both actions are icons now — give them wide, thumb-sized targets */
  #productsTable td.actions .icon-btn {
    flex: 1 1 0;
    max-width: 160px;
    width: auto;
    height: 42px;
  }
}


/* ================= 31. Row actions (cart + view) ==========================
   The stock rule fades .actions .icon-btn to opacity:0 until the row is
   hovered — fine for a quiet "more" menu, wrong for an Add to cart control
   that has to be visible and tappable on a touch screen. */
.row-actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
}

/* the form must not add a line box between the two controls */
.row-actions form {
  display: contents;
}

/* the stock rule fades these to opacity:0 until the row is hovered */
.table .actions .row-actions .icon-btn {
  opacity: 1;
}

.table .actions .row-actions .icon-btn:disabled {
  cursor: not-allowed;
}


/* ============= 32. Row action icons: view + add to cart ===================
   Both are icon-only now, so each needs its own colour and a visible border
   to read as a button rather than as decoration. */
/* solid buttons — they must read as actions at a glance, with no hover
   needed, which also matters on touch screens where there is no hover */
.icon-btn--view,
.icon-btn--cart {
  border: 1px solid transparent;
  border-radius: var(--r-md);
  color: #fff;
  opacity: 1;
  transition: filter var(--t-fast), box-shadow var(--t-fast);
}

.icon-btn--view {
  background: var(--primary-600);
}

.icon-btn--cart {
  background: var(--accent-600, var(--primary-600));
}

.icon-btn--view:hover,
.icon-btn--cart:hover:not(:disabled) {
  filter: brightness(1.12);
  color: #fff;
}

/* keyboard focus must be obvious on both */
.icon-btn--view:focus-visible,
.icon-btn--cart:focus-visible {
  outline: none;
  border-color: var(--primary-500);
  box-shadow: var(--ring);
}

/* the tick shown for a moment after a successful add */
.icon-btn.is-added {
  color: #fff;
  background: var(--success, #16a34a);
  border-color: var(--success, #16a34a);
}

/* Order-row actions: continue, view/edit and print, all icon-only.
   Outlined rather than solid like --view above: --success and --text-2 both
   flip to light shades in dark mode, where a white glyph on them would be
   unreadable. Tinting the border and the glyph instead works in both. */
.icon-btn--resume,
.icon-btn--print {
  border: 1px solid;
  border-radius: var(--r-md);
  opacity: 1;
  transition: filter var(--t-fast), background-color var(--t-fast),
    color var(--t-fast), box-shadow var(--t-fast);
}

.icon-btn--resume {
  border-color: var(--success);
  background: var(--success-bg);
  color: var(--success);
}
.icon-btn--resume:hover {
  filter: brightness(1.06);
  color: var(--success);
}

.icon-btn--print {
  border-color: var(--border-strong);
  background: var(--surface);
  color: var(--text-2);
}
.icon-btn--print:hover {
  background: var(--surface-3);
  color: var(--text);
}

.icon-btn--resume:focus-visible,
.icon-btn--print:focus-visible {
  outline: none;
  border-color: var(--primary-500);
  box-shadow: var(--ring);
}

/* These are a row's real actions, not incidental ones, so they stay visible
   without hover — the only way they work on a touch screen. The earlier
   ".table .actions .icon-btn { opacity: 0 }" rule hides every icon in an
   actions cell until the row is hovered, and it outranks the opacity:1 each
   variant sets on itself; this matches its specificity and comes later. */
.table .actions .icon-btn--view,
.table .actions .icon-btn--cart,
.table .actions .icon-btn--resume,
.table .actions .icon-btn--print {
  opacity: 1;
}

/* and the same specificity is needed to size them down in a fixed table */
.table--fixed .actions .icon-btn {
  width: 30px;
  height: 30px;
}

/* still a filled button, just clearly inactive */
.icon-btn--cart:disabled {
  background: var(--surface-3);
  color: var(--text-3);
  border-color: var(--border-strong);
  border-style: dashed;
  opacity: 1;
}


/* ========================= 33. Sign-in page =============================== */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-5);
  background: var(--bg);
}

.auth-card {
  width: 100%;
  max-width: 400px;
  padding: var(--s-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}

.auth-card__brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  margin-bottom: var(--s-5);
}

.auth-card h1 {
  margin: 0 0 var(--s-1);
  font-size: var(--fs-xl);
}

.auth-card .muted {
  margin: 0 0 var(--s-5);
}

.auth-card .field {
  margin-bottom: var(--s-4);
}

.auth-card__submit {
  width: 100%;
  justify-content: center;
  margin-top: var(--s-2);
}

/* the sign-out control is a button inside a form, not a link */
.menu__panel form {
  margin: 0;
}

.menu__panel button.menu__item {
  width: 100%;
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}




/* date-range filter on the orders list — stays on one row */
.range-filter {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: nowrap;
  margin: 0;
}

/* the calendar, both dates and the dash read as a single control */
.range-filter__dates {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 0 var(--s-3);
  min-height: 34px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  color: var(--text-3);
  flex: 0 0 auto;
}

/* the calendar on the left opens the picker — see initDatePickers() */
.range-filter__dates ion-icon {
  font-size: 1.05rem;
  flex: 0 0 auto;
  cursor: pointer;
  transition: color var(--t-fast);
}
.range-filter__dates ion-icon:hover {
  color: var(--primary-600);
}

.range-filter__dash {
  color: var(--text-3);
}

/* the inputs sit inside that frame, so they carry no border of their own */
.range-filter__dates .input {
  width: 128px;
  min-height: 30px;
  padding: 2px 0;
  border: 0;
  background: transparent;
  font-size: var(--fs-sm);
  color: var(--text);
}

/* The browser draws its own calendar button inside a date field and colours
   it from the page's colour scheme, not from our text colour. Without this
   the field inherits the light scheme, so in dark mode it was a near-black
   glyph on a near-black field — the "icon is not visible on the right".
   Declaring the scheme also makes the dropdown panel itself match. */
.range-filter__dates .input {
  color-scheme: light;
}
:root[data-theme="dark"] .range-filter__dates .input {
  color-scheme: dark;
}

/* and give that button a little room and a hit area worth tapping */
.range-filter__dates .input::-webkit-calendar-picker-indicator {
  padding: 2px;
  margin-left: 2px;
  border-radius: var(--r-sm);
  cursor: pointer;
  opacity: 0.75;
}
.range-filter__dates .input::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
  background: var(--surface-3);
}

.range-filter__dates .input:focus {
  outline: none;
  box-shadow: none;
}

.range-filter__dates:focus-within {
  border-color: var(--primary-500);
  box-shadow: var(--ring);
}

.range-filter .select {
  min-height: 34px;
  padding-top: 4px;
  padding-bottom: 4px;
  font-size: var(--fs-sm);
  max-width: 170px;
}

.range-filter .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* only below this does it need to wrap */
@media (max-width: 900px) {
  .range-filter { flex-wrap: wrap; }
  .range-filter__dates { flex: 1 1 100%; justify-content: space-between; }
  .range-filter__dates .input { width: auto; flex: 1 1 0; }
  .range-filter .select { max-width: none; flex: 1 1 140px; }
}

/* On a phone the form wrapped but still ran off the side of the panel. A flex
   item defaults to min-width:auto, which means "never narrower than my own
   content" — so the selects and the date boxes refused to shrink, the form
   stayed wider than the toolbar, and the panel spilled past the screen edge,
   clipping the second dropdown and the badge on the right. Letting them shrink
   is the whole fix; the rest is making the row breaks deliberate. */
@media (max-width: 640px) {
  .toolbar { min-width: 0; }

  .range-filter {
    width: 100%;
    min-width: 0;
  }

  .range-filter .select,
  .range-filter__dates,
  .range-filter__dates .input {
    min-width: 0;
  }

  /* the apply button gets its own full-width row rather than sitting alone in
     the corner under the dates */
  .range-filter .btn {
    flex: 1 1 100%;
    justify-content: center;
  }
}

/* Narrower still: the date box holds two pickers, a leading icon and a dash,
   and the pickers cannot shrink past the date they print. Dropping the two
   decorative parts gives that width back — each input keeps its own calendar
   button, so nothing is lost. */
@media (max-width: 430px) {
  .range-filter__dates {
    gap: 4px;
    padding: 0 var(--s-2);
  }
  .range-filter__dates > ion-icon,
  .range-filter__dash {
    display: none;
  }
}
/* place-of-supply line under Bill To */
.inv-bill__supply {
  margin-top: 4px !important;
  font-size: 10px;
  color: #4b5563;
}



/* icon-only buttons in the range filter: keep them square, not letterbox */
.range-filter .btn {
  min-width: 34px;
  min-height: 34px;
  padding-left: var(--s-3);
  padding-right: var(--s-3);
  justify-content: center;
}

.range-filter .btn ion-icon {
  font-size: 1.05rem;
}


/* ---- export dropdown must escape the panel ----------------------------
   .panel sets overflow:hidden to clip the table's rounded corners, which
   also clips the absolutely-positioned dropdown — no z-index can escape an
   ancestor's overflow. Let the panel show overflow only while a dropdown
   inside it is open, so the corners stay clipped the rest of the time. */
.panel:has(.export-menu[open]) {
  overflow: visible;
}

/* the toolbar sits above the table so the open menu is not covered */
.panel:has(.export-menu[open]) .toolbar {
  position: relative;
  z-index: 61;
}

.export-menu[open] > summary {
  position: relative;
  z-index: 62;
}

/* fallback for browsers without :has() — the menu opens upward instead of
   being clipped at the bottom of the toolbar */
@supports not selector(:has(*)) {
  .export-menu__panel {
    bottom: calc(100% + var(--s-2));
    top: auto;
  }
}


/* ========================= 34. Dashboard ================================= */
/* Line chart drawn as inline SVG with the theme's own tokens — no chart
   library, nothing extra to load, and it follows light/dark automatically. */
.chart-wrap {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-5) var(--s-5) 0;
}

/* y scale, so a point's height means a number */
.chart__scale {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 190px;
  padding-bottom: 22px;           /* clears the date ticks under the plot */
  font-size: var(--fs-xs);
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  text-align: right;
  flex: 0 0 auto;
  min-width: 22px;
}

.chart {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 190px;
  padding-bottom: 22px;
}

/* three reference lines behind the plot */
.chart__grid {
  position: absolute;
  inset: 0 0 22px 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  pointer-events: none;
}

.chart__grid i {
  height: 1px;
  background: var(--border);
  opacity: .7;
}

/* the daily average, so a point reads as above or below par */
.chart__avg {
  position: absolute;
  left: 0;
  right: 0;
  margin-bottom: 22px;
  border-top: 1px dashed var(--accent-500, var(--primary-500));
  opacity: .8;
  pointer-events: none;
  z-index: 2;
}

.chart__avg span {
  position: absolute;
  right: 0;
  top: -9px;
  padding: 0 4px;
  font-size: var(--fs-xs);
  color: var(--accent-600, var(--primary-600));
  background: var(--surface);
}

/* the plot itself */
.chart__svg {
  position: absolute;
  inset: 0 0 22px 0;
  width: 100%;
  height: calc(100% - 22px);
  overflow: visible;
}

.chart__area {
  fill: var(--primary-500);
  opacity: .12;
}

.chart__line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.chart__line--total {
  stroke: var(--primary-500);
  opacity: .45;
  stroke-dasharray: 4 3;
}

.chart__line--placed {
  stroke: var(--primary-500);
}

/* dots sit in HTML so they stay round — an SVG circle would stretch into an
   ellipse under preserveAspectRatio="none" */
.chart__dots {
  position: absolute;
  inset: 0 0 22px 0;
  pointer-events: none;
}

.chart__dot {
  position: absolute;
  width: 7px;
  height: 7px;
  margin: 0 0 -3.5px -3.5px;      /* centre on its coordinate */
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--primary-500);
  pointer-events: auto;
  cursor: default;
  transition: transform var(--t-fast);
}

.chart__dot:hover {
  transform: scale(1.5);
}

.chart__dot.is-zero {
  border-color: var(--border-strong);
}

.chart__dot.is-today {
  background: var(--primary-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary-500) 25%, transparent);
}

/* date labels along the bottom */
.chart__ticks {
  position: absolute;
  inset: auto 0 0 0;
  height: 18px;
}

.chart__tick {
  position: absolute;
  transform: translateX(-50%);
  font-size: var(--fs-xs);
  color: var(--text-3);
  white-space: nowrap;
}

.chart__tick.is-today {
  color: var(--primary-600);
  font-weight: 700;
}

/* legend beside the panel title */
.chart__key {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-xs);
  color: var(--text-3);
}

.chart__swatch {
  width: 14px;
  height: 0;
  border-top: 2px solid var(--primary-500);
}

.chart__swatch--total {
  opacity: .45;
  border-top-style: dashed;
}

/* two panels side by side, stacking when there is no room */
.dash-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--s-5);
}

.dash-split > .panel {
  margin: 0;
}

@media (max-width: 640px) {
  .chart-wrap {
    padding: var(--s-4) var(--s-3) 0;
  }

  .chart,
  .chart__scale {
    height: 150px;
  }

  /* fewer, smaller labels and no dots — they crowd at this width */
  .chart__tick {
    font-size: 9px;
  }

  .chart__dot {
    width: 5px;
    height: 5px;
    margin: 0 0 -2.5px -2.5px;
  }
}


/* ===================== 30. Live search & filtering ======================= */
/* A swapped-in region keeps the layout it replaced: the filter block sits in
   the toolbar's flex row, so it must not become a box of its own. */
.toolbar > [data-live-region] {
  display: contents;
}

/* while the server is answering — the delay keeps a fast reply from
   flickering the list */
[data-live].is-loading .table-wrap,
[data-live].is-loading .product-grid {
  opacity: 0.5;
  pointer-events: none;
  transition: opacity var(--t-fast) 150ms;
}

/* ---- topbar suggestions ---- */
.search__panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 600;
  max-height: min(70vh, 460px);
  overflow-y: auto;
  padding: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}
.search__panel[hidden] {
  display: none;
}

.search__hit {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2);
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
}
.search__hit:hover,
.search__hit.is-active {
  background: var(--surface-3);
}

.search__hit img {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  object-fit: cover;
  background: var(--bg);
  border-radius: var(--r-sm);
}

/* min-width:0 so a long product name ellipsises instead of pushing the
   price and the badge off the edge of the panel */
.search__hit > div {
  min-width: 0;
  flex: 1 1 auto;
}
.search__hit strong,
.search__hit small {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.search__hit strong {
  font-weight: 600;
}
.search__hit small {
  font-size: var(--fs-sm);
}

.search__hit-side {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  font-size: var(--fs-sm);
  font-weight: 600;
}

.search__none {
  margin: 0;
  padding: var(--s-4);
  text-align: center;
  color: var(--text-3);
  font-size: var(--fs-sm);
}

.search__more {
  display: block;
  margin-top: var(--s-1);
  padding: var(--s-3);
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--primary-600);
  text-decoration: none;
  border-top: 1px solid var(--border);
  border-radius: var(--r-md);
}
.search__more:hover,
.search__more.is-active {
  background: var(--surface-3);
}

/* the topbar search goes full width on phones, and so does its panel */
@media (max-width: 720px) {
  .search__hit-side {
    display: none;
  }
}

/* The UA's [hidden] rule is a bare attribute selector, so any class that sets
   display beats it and a filtered-out row stays on screen. These are the
   three the search and the segment filter hide. */
.table--stack tbody tr[hidden],
.product-grid[hidden],
.product-card[hidden] {
  display: none;
}

/* ========================== 34. Reports =================================
   The index is a grid of cards, one per report; every report page itself is
   the same panel + toolbar + table the order list uses, so nothing below
   redefines that format. */
.report-grid {
  display: grid;
  /* min(320px, 100%) not 320px: on a phone the column is asked for 320px in
     a track narrower than that, and the grid overflows the panel sideways.
     The min() lets the column shrink to whatever space there actually is. */
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: var(--s-4);
  padding: var(--s-5);
}

/* the card is a name and an icon, so everything sits on one centre line */
.report-card {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--card-tint, var(--primary-500));
  border-radius: var(--r-lg);
  color: var(--text);
  text-decoration: none;
  transition: border-color var(--t-fast), box-shadow var(--t-fast),
    transform var(--t-fast);
}
.report-card:hover {
  border-color: var(--card-tint, var(--primary-500));
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}
.report-card[hidden] {
  display: none;
}

.report-card__icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-md);
  font-size: 1.3rem;
  color: var(--card-tint, var(--primary-500));
  /* a wash of the card's own colour, so the tile reads as part of the card */
  background: color-mix(in srgb, var(--card-tint, var(--primary-500)) 14%, transparent);
}

/* min-width:0 so a long report name wraps instead of stretching the card */
.report-card__body {
  flex: 1 1 auto;
  min-width: 0;
}

.report-card__name {
  display: block;
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1.35;
}

.report-card__go {
  flex: 0 0 auto;
  color: var(--text-3);
  font-size: 1.1rem;
}
.report-card:hover .report-card__go {
  color: var(--card-tint, var(--primary-500));
}

/* a second row of controls under the shared toolbar */
.toolbar--sub {
  background: var(--surface-2);
}

/* the medal tint on the top three rows of a ranked report */
.rank {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: #fff;
  background: var(--text-3);
}
.rank--1 { background: #d4a017; }
.rank--2 { background: #9aa3b2; }
.rank--3 { background: #b06a3b; }

/* ageing summary above the due-count table */
.age-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}

.age-band {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
/* a band with nothing in it stays quiet */
.age-band.is-live {
  background: var(--surface);
  border-color: var(--border-strong);
}

.age-band__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
}
.age-band__count {
  font-size: var(--fs-lg, 1.05rem);
  font-weight: 700;
  color: var(--text);
}
.age-band__amount {
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

/* the rank column in a ranked report */
.table--fixed col.w-rank { width: 5%; }

/* first line of an order group in the order-wise report */
.table--fixed tbody tr.is-group-start td {
  border-top: 1px solid var(--border-strong);
}

/* An order number in a report that opens the order: the code, then a small
   eye so the whole cell reads as something you can click. One link, not two
   — the icon is decorative and the code carries the accessible name. */
.order-ref {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: inherit;
  text-decoration: none;
}

.order-ref code {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 2px;
  transition: color var(--t-fast), text-decoration-color var(--t-fast);
}

.order-ref ion-icon {
  flex: 0 0 auto;
  font-size: 0.95rem;
  color: var(--text-3);
  transition: color var(--t-fast);
}

.order-ref:hover code,
.order-ref:focus-visible code {
  color: var(--primary-600);
  text-decoration-color: currentColor;
}
.order-ref:hover ion-icon,
.order-ref:focus-visible ion-icon {
  color: var(--primary-600);
}

/* the icon would be the only thing on its line in the stacked phone layout */
@media (max-width: 640px) {
  .order-ref {
    gap: 8px;
  }
}

/* ===================== 35. Reports on a phone ===========================
   The reports carry more controls than any other page — a search box, a
   four-way period segment, a dealer picker, date boxes and an export menu —
   and on a narrow screen they had nowhere to go. Everything here is scoped
   to the reports, so the order and product toolbars are untouched. */

/* A segment is inline-flex with no wrap, so a row of chips — "All time /
   Monthly / Yearly / Custom range" on a report, "Today / Last 7 days / Last 30
   days / Last 90 days" on the dashboard — ran past the edge of the panel. Let
   the chips themselves wrap onto a second line and share the width.

   This used to be scoped to .toolbar--report and .toolbar--sub, which left the
   dashboard's own range segment out: its chips had to squeeze instead of wrap,
   and "Last 30 days" came apart into three overlapping lines. It applies to
   every full-size segment now. --sm is left alone: the "100 / page | Show all"
   switch in a table footer is two short chips that already fit. */
@media (max-width: 640px) {
  .segment:not(.segment--sm) {
    flex-wrap: wrap;
    width: 100%;
  }
  .segment:not(.segment--sm) a,
  .segment:not(.segment--sm) button {
    flex: 1 1 auto;
    justify-content: center;
    text-align: center;
  }
}

/* Tighter gutters, so the controls get the width instead of the padding. */
@media (max-width: 560px) {
  .toolbar--report,
  .toolbar--sub {
    padding: var(--s-3);
    gap: var(--s-2);
  }

  /* The export menu and the period badge each get their own line rather than
     being squeezed onto the end of the row. Descendant selectors, not child:
     both sit inside #reportFilters, which is display:contents — that makes
     them flex items of the toolbar, but they are not its DOM children. */
  .toolbar--report .export-menu,
  .toolbar--report .muted {
    flex: 1 1 100%;
  }
  .toolbar--report .export-menu > summary {
    justify-content: center;
  }

  /* the ageing strip above the due-count table */
  .age-strip {
    padding: var(--s-3);
    gap: var(--s-2);
  }

  /* one card per row, and less of the panel spent on padding */
  .report-grid {
    grid-template-columns: 1fr;
    gap: var(--s-3);
    padding: var(--s-3);
  }
  .report-card {
    padding: var(--s-3);
    gap: var(--s-3);
  }
}

/* A stacked table lays each cell out as its own full-width row, so the side
   padding belongs to the row, not the cell. The .table--fixed edge rules are
   more specific than .table--stack's, though, so the first cell of every row
   kept a 20px indent the others did not have. Put them back to zero. */
@media (max-width: 640px) {
  .table--stack.table--fixed th,
  .table--stack.table--fixed td,
  .table--stack.table--fixed th:first-child,
  .table--stack.table--fixed td:first-child,
  .table--stack.table--fixed th:last-child,
  .table--stack.table--fixed td:last-child {
    padding-left: 0;
    padding-right: 0;
  }

  /* a stacked row reads as a card, so it needs room down the sides again */
  .table--stack.table--fixed tr {
    padding: var(--s-3) var(--s-4);
  }

  /* the label and the value must not collide on a narrow screen */
  .table--stack.table--fixed td {
    gap: var(--s-3);
  }
}

/* ============== 36. Who a salesman is ordering for ======================
   A dealer never sees this bar: their own account is the answer. A salesman
   serves many dealers, so the one they are working for has to be on screen
   and changeable at any point. */
.acting-bar {
  padding: var(--s-4) var(--s-5);
}

.acting-bar__form {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin: 0;
}

.acting-bar__who {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding-right: var(--s-4);
  border-right: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.acting-bar__who ion-icon {
  font-size: 1.6rem;
  color: var(--primary-600);
}
.acting-bar__who small {
  display: block;
}

.acting-bar__label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-2);
}

.acting-bar .select {
  flex: 1 1 220px;
  max-width: 340px;
  min-height: 34px;
}

@media (max-width: 560px) {
  .acting-bar {
    padding: var(--s-3);
  }
  .acting-bar__who {
    flex: 1 1 100%;
    padding-right: 0;
    border-right: 0;
  }
  .acting-bar .select {
    max-width: none;
  }
}

/* ================ 37. Drilling from one report into another =============
   A name that opens the rows behind it. The chevron is what says so — the
   text alone reads as a label, not a link. */
.drill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  color: inherit;
  text-decoration: none;
}

.drill strong {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 2px;
  transition: color var(--t-fast), text-decoration-color var(--t-fast);
}

.drill ion-icon {
  flex: 0 0 auto;
  font-size: 0.9rem;
  color: var(--text-3);
  transition: color var(--t-fast), transform var(--t-fast);
}

.drill:hover strong,
.drill:focus-visible strong {
  color: var(--primary-600);
  text-decoration-color: currentColor;
}
.drill:hover ion-icon,
.drill:focus-visible ion-icon {
  color: var(--primary-600);
  transform: translateX(2px);
}

/* the code sits under the name, not beside the chevron */
.drill small {
  flex-basis: 100%;
}

/* ===================== 38. Attendance: marking a visit ==================
   A short form on a phone at a dealer's door, and a grid of what has been
   marked already. */
.visit-form {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-5);
}

/* the photo shown back before it is sent */
.visit-shot {
  margin: var(--s-3) 0 0;
}
.visit-shot img {
  display: block;
  width: 100%;
  max-width: 320px;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
}
.visit-shot[hidden] {
  display: none;
}

/* what the browser said about the location */
.visit-where {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3);
}

.visit-where__state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.visit-where__state.is-ok {
  background: var(--success-bg);
  border-color: var(--success);
  color: var(--success);
}
.visit-where__state.is-warn {
  background: var(--warning-bg);
  border-color: var(--warning);
  color: var(--warning);
}

/* ---- the visits already marked ---- */
.visit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: var(--s-4);
  padding: var(--s-5);
}

.visit-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.visit-card__shot img {
  display: block;
  width: 100%;
  height: 150px;
  object-fit: cover;
  background: var(--bg);
}

.visit-card__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-3);
  min-width: 0;
}

.visit-card__map {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--primary-600);
  text-decoration: none;
  overflow-wrap: anywhere;
}
.visit-card__map:hover {
  text-decoration: underline;
}

@media (max-width: 560px) {
  .visit-form,
  .visit-grid {
    padding: var(--s-3);
  }
}

/* the one map at the top of the visit report */
.visit-map {
  margin: 0;
  padding: var(--s-5) var(--s-5) 0;
}

.visit-map iframe {
  display: block;
  width: 100%;
  height: 260px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface-2);
}

.visit-map figcaption {
  padding: var(--s-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.visit-map figcaption a {
  color: var(--primary-600);
  text-decoration: none;
}
.visit-map figcaption a:hover {
  text-decoration: underline;
}

@media (max-width: 560px) {
  .visit-map {
    padding: var(--s-3) var(--s-3) 0;
  }
  .visit-map iframe {
    height: 200px;
  }
}
