/* ============================================================
   OLBIA — Design System
   Flat modern UI · Lavatera palette · WCAG 2.2 AA
   ============================================================

   Palette root: Lavatera olbia flower — #593A5D
   Neutrals and surfaces share the same purple hue angle
   for perceptual cohesion. Green is reserved exclusively
   for semantic success / positive-balance states.

   Sections:
   1.  Tokens
   2.  Pico overrides
   3.  Base & typography
   4.  Focus management
   5.  Layout (header, nav, main)
   6.  Buttons
   7.  Forms & inputs
   8.  Tables
   9.  Cards & articles
   10. Flash messages
   11. Badges (status chips)
   12. Quantity stepper
   13. Order total bar
   14. Balance / ledger
   15. Provider picker grid
   16. Empty states
   17. Login page
   18. Utilities
   19. Reduced motion
   ============================================================ */

/* === 1. TOKENS ============================================== */

:root {
  /* Surfaces */
  --ob-bg: #ddc8e8; /* page background — lavender per design */
  --ob-surface: #ffffff; /* cards, panels, inputs */
  --ob-surface-warm: #f0e6f8; /* producer info card tint */

  /* Primary — nav/button purple per design */
  --ob-primary: #694677;
  --ob-primary-dark: #4c1860; /* hover / pressed — header deep */
  --ob-primary-xdark: #38104e; /* deepest — pressed states */
  --ob-primary-mid: #7c3e92; /* medium — header mid */
  --ob-primary-tint: #eee3ef; /* light background tint */
  --ob-primary-border: #bea8d0; /* border on white */

  /* Header gradient tokens */
  --ob-header-start: #4c1860;
  --ob-header-mid: #7c3e92;
  --ob-header-end: #9852a4;
  --ob-nav-bg: #694677;
  --ob-nav-height: 36px; /* nav.ob-nav's rendered height — also used as the sticky table-header offset */

  /* Error / negative — deep rose-red
     #B5234C on #fff → 6.3:1 ✓ AA+ */
  --ob-rose: #b5234c; /* text / icons / negative balance */
  --ob-rose-light: #fceef4; /* background tint */
  --ob-rose-border: #eea0bc; /* decorative border */
  --ob-rose-decor: #d97fa3; /* non-text decoration only */

  /* Secondary — warm gold (earthy complement to purple)
     #8B6B3A on #fff → 4.7:1 ✓ AA */
  --ob-tan: #8b6b3a;
  --ob-tan-dark: #6f5429;
  --ob-tan-tint: #f5eed9;

  /* Neutral scale — purple-hue bias, not warm-brown
     ── All text roles verified against their backgrounds ── */
  --ob-n900: #1c1120; /* headings       ~18:1 on #fff ✓ AAA */
  --ob-n700: #3d2645; /* body text      ~12:1 on #fff ✓ AAA */
  --ob-n500: #7a617f; /* muted text      5.3:1 on #fff ✓ AA  */
  --ob-n400: #9e88a2; /* placeholders    3.2:1 — decorative   */
  --ob-n300: #ccb8d0; /* borders */
  --ob-n200: #e3d8e6; /* subtle dividers */
  --ob-n100: #efe8f1; /* subtle backgrounds */
  --ob-n50: #f5f1f7; /* page background */

  /* Semantic — success / positive (forest green, unchanged)
     #2A6B3A on #fff → 6.1:1 ✓ AA+ */
  --ob-success-text: #2a6b3a;
  --ob-success-bg: #e4f2e8;
  --ob-success-border: #9dcca8;

  /* Semantic — error (reuses rose tokens above) */
  --ob-error-text: var(--ob-rose);
  --ob-error-bg: var(--ob-rose-light);
  --ob-error-border: var(--ob-rose-border);

  /* Semantic — warning */
  --ob-warning-text: #785800;
  --ob-warning-bg: #fef5d9;
  --ob-warning-border: #f0cc60;

  /* Spacing — 8px base grid */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  /* Typography */
  --font:
    "Source Sans 3", system-ui, -apple-system, "Segoe UI", "Helvetica Neue",
    Arial, sans-serif;

  --text-xs: 0.75rem; /* 12px — captions, hints */
  --text-sm: 0.875rem; /* 14px — table cells, secondary labels */
  --text-base: 0.875rem; /* 14px — body, inputs */
  --text-lg: 1.125rem; /* 18px — lead text */
  --text-xl: 1.25rem; /* 20px — section titles */
  --text-2xl: 1.5rem; /* 24px — page subtitles */
  --text-3xl: 1.875rem; /* 30px — page titles */

  /* Radii */
  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 10px;
  --radius-full: 9999px;

  /* Shadows — purple-tinted, not brown */
  --shadow-sm: 0 1px 3px rgba(50, 20, 55, 0.07);
  --shadow: 0 2px 8px rgba(50, 20, 55, 0.09);
  --shadow-lg: 0 4px 20px rgba(50, 20, 55, 0.12);

  /* Transitions */
  --t-fast: 120ms ease;
  --t: 160ms ease;
}

/* === 2. PICO OVERRIDES ====================================== */

/* Pico scales the root font-size up at wider breakpoints (its fluid type
   scale reaches 125%+ on desktop widths) — since our own rem-based tokens
   (--text-*) assume a fixed 16px root, that scaling made every font size,
   and everything sized off it (form control height, spacing), balloon on
   normal desktop screens. Pin it so 1rem is always 16px. */
:root {
  font-size: 100% !important;
}

:root {
  --pico-font-family: var(--font);
  --pico-background-color: var(--ob-bg);
  --pico-color: var(--ob-n700);
  --pico-h1-color: var(--ob-n900);
  --pico-h2-color: var(--ob-n900);
  --pico-h3-color: var(--ob-n900);
  --pico-h4-color: var(--ob-n900);
  --pico-primary: var(--ob-primary);
  --pico-primary-hover: var(--ob-primary-dark);
  --pico-primary-focus: rgba(89, 58, 93, 0.22);
  --pico-primary-inverse: #ffffff;
  --pico-secondary: var(--ob-tan);
  --pico-secondary-hover: var(--ob-tan-dark);
  --pico-secondary-inverse: #ffffff;
  --pico-muted-color: var(--ob-n500);
  --pico-muted-border-color: var(--ob-n300);
  --pico-card-background-color: var(--ob-surface);
  --pico-border-radius: var(--radius);
  --pico-form-element-border-color: var(--ob-n300);
  --pico-form-element-focus-color: var(--ob-primary);
  --pico-table-border-color: var(--ob-n200);
  --pico-table-row-stripped-background-color: var(--ob-n50);
  --olbia-accent: var(--ob-rose-decor);
}

/* === 3. BASE & TYPOGRAPHY =================================== */

:root {
  color-scheme: light only;
}

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

body {
  font-family: var(--font);
  font-size: var(--text-base);
  line-height: 1.55;
  color: var(--ob-n700);
  background-color: var(--ob-bg);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4 {
  color: var(--ob-n900);
  line-height: 1.25;
  letter-spacing: -0.01em;
  font-weight: 700;
}

h1 {
  font-size: var(--text-3xl);
  margin-bottom: var(--sp-6);
}
h2 {
  font-size: var(--text-2xl);
  margin-bottom: var(--sp-4);
}
h3 {
  font-size: var(--text-xl);
  margin-bottom: var(--sp-3);
}

p {
  max-width: 65ch;
}

/* Remove Pico's default serif on headings */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font);
}

small,
.text-sm {
  font-size: var(--text-sm);
  color: var(--ob-n500);
}

a {
  color: var(--ob-primary);
  text-underline-offset: 3px;
  transition: color var(--t-fast);
}

a:hover {
  color: var(--ob-primary-dark);
}

strong {
  font-weight: 600;
  color: var(--ob-n900);
}

/* === 4. FOCUS MANAGEMENT ==================================== */

/* Remove Pico's default focus, replace with our own */
:focus-visible {
  outline: 2px solid var(--ob-primary);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Buttons need tighter offset */
button:focus-visible,
[role="button"]:focus-visible,
a[role="button"]:focus-visible {
  outline-offset: 2px;
}

/* === 5. LAYOUT ============================================== */

/* Gradient header */
header.ob-header {
  background: linear-gradient(
    180deg,
    var(--ob-header-start) 0%,
    var(--ob-header-mid) 55%,
    var(--ob-header-end) 100%
  );
  padding: 12px 24px 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 62px;
}

.ob-header__brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.ob-logo {
  height: 46px;
  width: auto;
}

.ob-header__wordmark {
  color: white;
  font-size: 27px;
  font-weight: 700;
  letter-spacing: -0.3px;
  font-family: var(--font);
}

.ob-header__tagline {
  color: rgba(255, 255, 255, 0.88);
  font-size: 12px;
  text-align: right;
  line-height: 1.6;
}

/* Purple nav bar */
nav.ob-nav {
  background: var(--ob-nav-bg);
  display: flex;
  align-items: stretch;
  min-height: var(--ob-nav-height);
  position: sticky;
  top: 0;
  z-index: 100;
  overflow-x: auto;
  padding: 0;
  margin: 0;
}

.ob-nav__member {
  color: rgba(255, 255, 255, 0.8);
  font-size: 13.5px;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  white-space: nowrap;
  font-family: var(--font);
}

.ob-nav__item {
  color: rgba(255, 255, 255, 0.8);
  font-size: 13.5px;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  white-space: nowrap;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  border-radius: 0;
  border-top: none;
  border-left: none;
  border-right: none;
  height: auto;
  min-height: 36px;
  transition:
    background-color var(--t-fast),
    color var(--t-fast);
  cursor: pointer;
  font-family: var(--font);
  font-weight: 400;
  line-height: 1;
}

.ob-nav__item:hover,
.ob-nav button.ob-nav__item:hover {
  color: white;
  background: rgba(255, 255, 255, 0.08);
  border-bottom-color: transparent;
  border-top: none;
  border-left: none;
  border-right: none;
}

.ob-nav__item--active {
  color: white !important;
  background: rgba(255, 255, 255, 0.13) !important;
  border-bottom: 2px solid rgba(255, 255, 255, 0.65) !important;
}

/* Make the form wrapper transparent to flex layout */
.ob-nav__logout-form {
  display: contents;
}

/* Button reset for the logout nav item.
   margin: 0 overrides Pico's `[type=submit] { margin-bottom: 1rem }` — left
   in place, that 16px margin inflates this flex item's height and stretches
   nav.ob-nav well past --ob-nav-height, throwing off the sticky table
   header's top offset (which assumes that variable matches the nav's real
   rendered height). */
.ob-nav button.ob-nav__item {
  background: transparent;
  border-color: transparent;
  color: rgba(255, 255, 255, 0.8);
  transform: none;
  box-shadow: none;
  margin: 0;
}

.ob-nav button.ob-nav__item:active {
  transform: none;
}

/* Logout button pushed to right */
.ob-nav__item--logout {
  margin-left: auto;
}

/* Balance chip — far right */
.ob-nav__balance {
  color: white;
  font-size: 13.5px;
  padding: 8px 14px;
  background: rgba(0, 0, 0, 0.18);
  white-space: nowrap;
  font-weight: 600;
  border-left: 1px solid rgba(255, 255, 255, 0.15);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font);
  user-select: none;
}

.ob-nav__balance:hover {
  background: rgba(0, 0, 0, 0.28);
}

main.container {
  padding-top: var(--sp-8);
  padding-bottom: var(--sp-16);
}

/* Page header row: title + action button */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
  flex-wrap: wrap;
}

.page-header h2 {
  margin-bottom: 0;
}

.page-header .actions {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  flex-shrink: 0;
}

/* button_to generates a <form> wrapper; make it invisible to the flex layout */
.page-header .actions form {
  display: contents;
}

/* Back link: sits above the page title, upper-left of the main content */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin-bottom: var(--sp-3);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ob-n500);
  text-decoration: none;
}

.back-link:hover {
  color: var(--ob-primary);
}

/* Two-column layout: ledger submenu (left) + page content */
.ledger-layout {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-8);
}

.ledger-layout__content {
  flex: 1 1 0%;
  min-width: 0;
}

.ledger-nav {
  flex: 0 0 220px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  position: sticky;
  top: var(--sp-6);
}

.ledger-nav__section {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ledger-nav__heading {
  padding: 0 var(--sp-3);
  margin-bottom: var(--sp-1);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ob-n500);
}

.ledger-nav__link {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius);
  color: var(--ob-n700);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  transition:
    background-color var(--t-fast),
    color var(--t-fast);
}

.ledger-nav__link:hover {
  background-color: var(--ob-n100);
  color: var(--ob-n900);
}

.ledger-nav__link--active {
  background-color: var(--ob-primary-tint);
  color: var(--ob-primary);
  font-weight: 600;
}

.ledger-nav__account-number {
  flex-shrink: 0;
  min-width: 3.4em;
  color: var(--ob-n500);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ledger-nav__link--active .ledger-nav__account-number {
  color: var(--ob-primary);
}

.ledger-nav__account-name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

@media (max-width: 768px) {
  .ledger-layout {
    flex-direction: column;
  }

  .ledger-nav {
    position: static;
    flex: none;
    width: 100%;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--sp-2);
  }

  .ledger-nav__section {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .ledger-nav__heading {
    width: 100%;
  }
}

/* === 6. BUTTONS ============================================= */

/*
  Visual hierarchy:
  [Primary]      — filled purple  — one per section max
  [Secondary]    — outline        — supporting actions
  [Destructive]  — outline rose   — after confirmation, not first-seen
  [Ghost]        — text-only      — lowest emphasis
*/

a[role="button"],
[role="button"]:not(.switch),
button:not(.ob-nav__item):not(.flash__close):not(.switch),
input[type="submit"],
input[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--font);
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1;
  height: 40px;
  padding: 0 var(--sp-5);
  border-radius: var(--radius);
  border: 1.5px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition:
    background-color var(--t-fast),
    border-color var(--t-fast),
    color var(--t-fast),
    transform var(--t-fast),
    box-shadow var(--t-fast);
  white-space: nowrap;
}

/* Primary — filled purple */
button:not(.outline):not([class*="secondary"]):not([class*="contrast"]):not(
    .ob-nav__item
  ):not(.flash__close):not(.switch),
input[type="submit"]:not(.outline),
[role="button"]:not(.outline):not([class*="secondary"]) {
  background-color: var(--ob-primary);
  border-color: var(--ob-primary);
  color: #ffffff;
}

button:not(.outline):not([class*="secondary"]):not(.ob-nav__item):not(
    .flash__close
  ):not(.switch):hover,
input[type="submit"]:not(.outline):hover,
[role="button"]:not(.outline):not([class*="secondary"]):hover {
  background-color: var(--ob-primary-dark);
  border-color: var(--ob-primary-dark);
}

button:not(.outline):not(.switch):active,
input[type="submit"]:not(.outline):active {
  transform: scale(0.98);
}

/* Outline variants */
button.outline,
a.outline,
[role="button"].outline {
  background-color: transparent;
}

button.outline:not(.secondary):not([class*="secondary"]) {
  border-color: var(--ob-primary);
  color: var(--ob-primary);
}

button.outline:not(.secondary):hover,
a.outline:not(.secondary):hover {
  background-color: var(--ob-primary-tint);
}

button.outline.secondary,
a.outline.secondary,
[role="button"].outline.secondary {
  border-color: var(--ob-n300);
  color: var(--ob-n500);
}

button.outline.secondary:hover,
a.outline.secondary:hover {
  border-color: var(--ob-n500);
  color: var(--ob-n700);
  background-color: var(--ob-n100);
}

/* Destructive */
button.destructive,
.btn-destructive {
  border-color: var(--ob-rose);
  color: var(--ob-rose);
  background-color: transparent;
}

button.destructive:hover {
  background-color: var(--ob-rose-light);
}

/* Disabled */
button:disabled,
input[type="submit"]:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Small button variant */
.btn-sm {
  height: 32px;
  padding: 0 var(--sp-3);
  font-size: var(--text-xs);
}

/* Extra-small button variant: tight inline row actions (e.g. table action columns) */
.btn-xs {
  height: 22px;
  padding: 0 var(--sp-2);
  font-size: var(--text-xs);
}

/* === 7. FORMS & INPUTS ====================================== */

label {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ob-n700);
  margin-bottom: var(--sp-1);
  display: block;
}

input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not(
    [type="button"]
  ),
select,
textarea {
  font-family: var(--font);
  font-size: var(--text-base);
  color: var(--ob-n900);
  background-color: var(--ob-surface);
  border: 1.5px solid var(--ob-n300);
  border-radius: var(--radius);
  padding: var(--sp-1) var(--sp-2);
  min-height: 36px;
  width: 100%;
  transition:
    border-color var(--t-fast),
    box-shadow var(--t-fast);
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--ob-primary);
  box-shadow: 0 0 0 3px rgba(89, 58, 93, 0.15);
  outline: none;
}

input::placeholder {
  color: var(--ob-n400);
}

/* Checkbox & radio */
input[type="checkbox"],
input[type="radio"] {
  width: 18px;
  height: 18px;
  accent-color: var(--ob-primary);
  cursor: pointer;
}

/* Inline checkbox+label pair */
.field-check {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  cursor: pointer;
}

.field-check input[type="checkbox"] {
  flex-shrink: 0;
}

/* Field hint */
.field-hint {
  font-size: var(--text-xs);
  color: var(--ob-n500);
  margin-top: var(--sp-1);
}

/* Field error */
.field-error {
  font-size: var(--text-xs);
  color: var(--ob-rose);
  margin-top: var(--sp-1);
}

/* Form layout: 2-column grid */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
}

@media (max-width: 640px) {
  .form-grid-2 {
    grid-template-columns: 1fr;
  }
}

/* Form actions row */
.form-actions {
  display: flex;
  gap: var(--sp-3);
  align-items: center;
  margin-top: var(--sp-6);
}

/* Pico sizes form buttons (and role="button" links) at width: 100% by
   default; size them to their content here instead. */
.form-actions button,
.form-actions [role="button"],
.form-actions input[type="submit"] {
  width: auto;
}

fieldset {
  border: 1.5px solid var(--ob-n200);
  border-radius: var(--radius-lg);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-4);
}

legend {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ob-n700);
  padding: 0 var(--sp-2);
}

/* === 8. TABLES ============================================== */

/* border-collapse must be "separate" (not "collapse") here: collapsed
   borders are not well-defined for sticky-positioned cells, and browsers
   respond by dropping the header's background while sticky, which reads as
   a duplicated/blank header and can also stop the sticky positioning from
   taking effect at all. Border widths below are trimmed on adjoining edges
   to reproduce the same single-pixel grid lines collapse would have given
   us, with border-spacing: 0 keeping cells flush. */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--text-base);
}

thead th {
  font-size: var(--text-base);
  font-weight: 700;
  color: #2a0a3a;
  background-color: #b6ccd8;
  padding: 2px 13px;
  border: 1px solid #98aeba;
  border-left-width: 0;
  text-align: left;
  white-space: nowrap;
  position: sticky;
  top: var(--ob-nav-height);
  z-index: 10;
}

thead th:first-child {
  border-left-width: 1px;
}

/* .table-wrap no longer clips overflow (see below, needed for sticky headers
   to work), so round the table's own corners to match the wrapper visually. */
thead tr:first-child th:first-child {
  border-top-left-radius: var(--radius-lg);
}

thead tr:first-child th:last-child {
  border-top-right-radius: var(--radius-lg);
}

tbody tr:last-child td:first-child {
  border-bottom-left-radius: var(--radius-lg);
}

tbody tr:last-child td:last-child {
  border-bottom-right-radius: var(--radius-lg);
}

tbody td {
  padding: 2px 13px;
  border: 1px solid #d6c0e2;
  border-top-width: 0;
  border-left-width: 0;
  vertical-align: middle;
  color: var(--ob-n700);
}

tbody td:first-child {
  border-left-width: 1px;
}

tbody tr:last-child td {
  border-bottom: 1px solid #d6c0e2;
}

tbody tr:hover td {
  background-color: #faf5fc;
}

/* Numeric columns: right-align */
td.num,
th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Adjustment tables (marketplace order quantities/prices tabs): the plain
   number inputs would otherwise inherit width: 100% from the base input
   rule, stretching them across the whole table column instead of sitting
   next to a single number. !important is needed because the base rule's
   chained :not([type=...]) selectors give it higher specificity than a
   plain td.num input[type="number"] selector. */
td.num input[type="number"] {
  width: 6rem !important;
  text-align: right;
}

/* Action column: right-align, no wrap */
td.td-actions {
  text-align: right;
  white-space: nowrap;
}

td.td-actions a,
td.td-actions button,
td.td-actions form {
  display: inline-flex;
  margin: 0;
}

td.td-actions a + a,
td.td-actions a + button,
td.td-actions a + form,
td.td-actions button + button,
td.td-actions button + form,
td.td-actions form + button,
td.td-actions form + form {
  margin-left: var(--sp-2);
}

/* Order breakdown: a product row followed by one indented row per member */
.order-item-row__member td {
  border-top-width: 0;
}

.order-item-row__member-name {
  padding-left: var(--sp-8);
  color: var(--ob-n500);
  font-size: var(--text-sm);
}

/* Table wrapper. overflow-x must stay "visible" (not "auto") at this width:
   per the CSS overflow spec, setting overflow-x to anything but visible forces
   overflow-y's computed value to "auto" even when overflow-y: visible is
   written explicitly — and an ancestor with overflow-y other than visible
   becomes the sticky containing block for `thead th`. Since this wrapper is
   always exactly as tall as its content, that silently breaks the sticky
   table header (it would never have room to detach and "stick" — it renders
   permanently offset by `top`, on top of the first row).

   Below the tablet breakpoint we still need horizontal scroll for wide
   tables, which means turning overflow-x: auto back on and re-triggering
   that exact problem. Nesting an extra wrapper div just to hold overflow-x
   does NOT avoid it — the new wrapper becomes the sticky containing block
   instead and reproduces the identical bug one level deeper (verified: any
   ancestor with non-visible overflow breaks `position: sticky` regardless of
   nesting, since sticky positioning fundamentally needs a containing block
   that can actually scroll vertically, which neither wrapper ever does).
   So instead we disable sticky itself for this breakpoint, in the media
   query below — a plain top row is strictly better than one that overlaps
   content. */
.table-wrap {
  width: 100%;
  overflow-x: visible;
  overflow-y: visible;
  border: 1px solid var(--ob-primary-border);
  border-radius: var(--radius-lg);
  background: var(--ob-surface);
  box-shadow: 0 1px 5px rgba(70, 20, 90, 0.1);
}

@media (max-width: 768px) {
  .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* overflow-x: auto above forces .table-wrap to become the sticky
     containing block for thead th (see comment above), which would make the
     header render stuck-in-place on top of the first row instead of
     scrolling normally. Disable sticky here rather than fight it. */
  thead th {
    position: static;
    top: auto;
  }
}

.table-wrap table {
  margin: 0;
}

/* === 9. CARDS & ARTICLES ==================================== */

article {
  background-color: var(--ob-surface);
  border: 1px solid var(--ob-primary-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  box-shadow: 0 1px 5px rgba(70, 20, 90, 0.1);
}

article header {
  border-bottom: 1px solid var(--ob-n100);
  padding-bottom: var(--sp-4);
  margin-bottom: var(--sp-4);
  /* Reset sticky header inside article */
  position: static;
  box-shadow: none;
  background: transparent;
}

article > header h2 {
  margin-bottom: 0;
}

/* === 10. FLASH MESSAGES ==================================== */

.flash-container {
  position: fixed;
  top: var(--sp-4);
  right: var(--sp-4);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  width: min(360px, calc(100vw - var(--sp-8)));
}

.flash {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  font-weight: 500;
  border-left: 3px solid;
  box-shadow: var(--shadow-lg);
  animation: flash-in var(--t) both;
}

.flash--leaving {
  animation: flash-out var(--t) both;
}

.flash--notice {
  background-color: var(--ob-success-bg);
  border-color: var(--ob-success-text);
  color: var(--ob-success-text);
}

.flash--alert {
  background-color: var(--ob-rose-light);
  border-color: var(--ob-rose);
  color: var(--ob-rose);
}

.flash__close {
  margin-left: auto;
  height: auto;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  opacity: 0.6;
}

.flash__close:hover {
  opacity: 1;
}

@keyframes flash-in {
  from {
    opacity: 0;
    transform: translateX(24px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes flash-out {
  from {
    opacity: 1;
    transform: translateX(0);
  }
  to {
    opacity: 0;
    transform: translateX(24px);
  }
}

/* === 11. BADGES (status chips) ============================= */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 2px var(--sp-2);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  letter-spacing: 0.02em;
}

/* Provider status */
.badge--active {
  background-color: var(--ob-success-bg);
  color: var(--ob-success-text);
}

.badge--inactive {
  background-color: var(--ob-n100);
  color: var(--ob-n500);
}

/* Order status */
.badge--future {
  background-color: var(--ob-n100);
  color: var(--ob-n500);
}

.badge--open {
  background-color: #d2ecd2;
  color: #285a28;
}

.badge--adjustments {
  background-color: #e8d2d6;
  color: #5a2030;
}

.badge--closed {
  background-color: #e8d2d6;
  color: #5a2030;
}

/* Dot indicator — prepend to badge text */
.badge::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background-color: currentColor;
  flex-shrink: 0;
}

/* === 12. QUANTITY STEPPER =================================== */

/*
  Decision: Purpose-built stepper rather than a raw <input type="number">.
  Why: 0.5-unit precision on mobile is near-impossible with a numeric keyboard
  or browser spinners. The +/− button pattern (stepper) is the canonical mobile
  solution for small, bounded increments. Each button is 44×44px (touch target).
*/

[data-controller="quantity-stepper"] {
  display: inline-flex;
  align-items: stretch;
  border: 1.5px solid var(--ob-n300);
  border-radius: var(--radius);
  background-color: var(--ob-surface);
  overflow: hidden;
  height: 44px;
}

[data-controller="quantity-stepper"] button[data-action] {
  all: unset;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  font-size: 1.25rem;
  font-weight: 400;
  color: var(--ob-n700);
  background-color: var(--ob-n50);
  cursor: pointer;
  transition:
    background-color var(--t-fast),
    color var(--t-fast);
  flex-shrink: 0;
  user-select: none;
}

[data-controller="quantity-stepper"] button[data-action]:hover {
  background-color: var(--ob-primary-tint);
  color: var(--ob-primary-dark);
}

[data-controller="quantity-stepper"] button[data-action]:active {
  background-color: var(--ob-primary-border);
}

[data-controller="quantity-stepper"] button[data-action]:focus-visible {
  outline: 2px solid var(--ob-primary);
  outline-offset: -2px;
  border-radius: 0;
}

[data-controller="quantity-stepper"] input[type="number"] {
  all: unset;
  width: 52px;
  text-align: center;
  font-family: var(--font);
  font-size: var(--text-base);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ob-n900);
  background-color: var(--ob-surface);
  border-left: 1px solid var(--ob-n200);
  border-right: 1px solid var(--ob-n200);
  padding: 0 var(--sp-1);
  min-height: unset;
  border-radius: 0;
}

[data-controller="quantity-stepper"] input[type="number"]:focus {
  background-color: var(--ob-primary-tint);
  box-shadow: none;
}

/* Hide browser spinner arrows on the number input */
[data-controller="quantity-stepper"]
  input[type="number"]::-webkit-outer-spin-button,
[data-controller="quantity-stepper"]
  input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

[data-controller="quantity-stepper"] input[type="number"] {
  -moz-appearance: textfield;
}

/* When quantity > 0, highlight the stepper */
[data-controller="quantity-stepper"]:has(input[value]:not([value="0"])) {
  border-color: var(--ob-primary);
}

/* === 13. ORDER CART SIDEBAR ================================== */

/* Two-column layout for the open-order selection form: the item table on
   the left, a persistent cart summary on the right. Neither column may set
   overflow-x/y to anything but visible — an ancestor with non-visible
   overflow becomes the sticky containing block for `thead th` and silently
   breaks the table's sticky header (see the .table-wrap comment above). The
   cart itself is a flex sibling of the table column, not its ancestor, so
   its own overflow-y: auto below is safe. */
.order-cart-layout {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-6);
}

.order-cart-layout__content {
  flex: 1 1 0%;
  min-width: 0;
}

.order-cart {
  flex: 0 0 300px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  position: sticky;
  top: calc(var(--ob-nav-height) + var(--sp-4));
  max-height: calc(100vh - var(--ob-nav-height) - var(--sp-8));
  overflow-y: auto;
  background-color: var(--ob-surface);
  border: 1.5px solid var(--ob-n200);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  box-shadow: 0 1px 5px rgba(70, 20, 90, 0.1);
}

.order-cart__title {
  margin: 0;
  font-size: var(--text-lg);
  color: var(--ob-n900);
}

.order-cart__empty {
  color: var(--ob-n500);
  font-size: var(--text-sm);
  margin: 0;
}

.order-cart__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.order-cart__line {
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--ob-n100);
  font-size: var(--text-sm);
}

.order-cart__line:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.order-cart__line-name {
  display: block;
  font-weight: 600;
  color: var(--ob-n900);
}

.order-cart__line-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-2);
  color: var(--ob-n500);
  font-variant-numeric: tabular-nums;
}

.order-cart__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: var(--sp-4);
  border-top: 1.5px solid var(--ob-n200);
}

.order-cart__total .total-label {
  font-size: var(--text-sm);
  color: var(--ob-n500);
  font-weight: 500;
}

.order-cart__total .total-amount {
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--ob-n900);
  font-variant-numeric: tabular-nums;
  min-width: 8ch;
  text-align: right;
}

.order-cart__submit {
  width: 100%;
  margin: 0;
}

/* Below the tablet breakpoint the sidebar drops under the table and pins to
   the bottom of the viewport instead, mirroring the mobile total bar
   pattern used elsewhere (e.g. the balance chip). */
@media (max-width: 900px) {
  .order-cart-layout {
    flex-direction: column;
  }

  .order-cart {
    flex: none;
    width: calc(100% + 2 * var(--pico-spacing, 1rem));
    max-height: 60vh;
    position: sticky;
    top: auto;
    bottom: 0;
    margin-left: calc(-1 * var(--pico-spacing, 1rem));
    margin-right: calc(-1 * var(--pico-spacing, 1rem));
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: 0 -4px 16px rgba(50, 20, 55, 0.1);
  }
}

/* === 14. BALANCE / LEDGER ================================== */

.balance--negative {
  color: var(--ob-rose);
  font-weight: 600;
}

.balance-summary {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-6);
  background-color: var(--ob-surface);
  border: 1.5px solid var(--ob-n200);
  border-radius: var(--radius-lg);
  margin-bottom: var(--sp-6);
  box-shadow: var(--shadow-sm);
}

.balance-summary .balance-label {
  font-size: var(--text-sm);
  color: var(--ob-n500);
  font-weight: 500;
}

.balance-summary .balance-amount {
  font-size: var(--text-3xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ob-n900);
  line-height: 1;
}

.balance-summary .balance-amount.is-negative {
  color: var(--ob-rose);
}

.balance-summary .balance-amount.is-positive {
  color: var(--ob-success-text);
}

/* Transaction kind pills in ledger table */
.txn-kind {
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 2px var(--sp-2);
  border-radius: var(--radius-full);
  display: inline-block;
}

.txn-kind--expense {
  background-color: var(--ob-rose-light);
  color: var(--ob-rose);
}

.txn-kind--cash-injection {
  background-color: var(--ob-success-bg);
  color: var(--ob-success-text);
}

/* === 15. PROVIDER PICKER GRID ============================== */

/*
  The order creation step 1: a grid of provider cards.
  Design goal: cards are scannable, feel clickable, and
  show item count at a glance so admins pick without hesitation.
*/

.provider-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}

.provider-card {
  display: block;
  text-decoration: none;
  background-color: var(--ob-surface);
  border: 1.5px solid var(--ob-n200);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  transition:
    border-color var(--t),
    box-shadow var(--t),
    transform var(--t);
  cursor: pointer;
}

.provider-card:hover {
  border-color: var(--ob-primary);
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

.provider-card:active {
  transform: translateY(0);
}

.provider-card strong {
  display: block;
  font-size: var(--text-base);
  color: var(--ob-n900);
  margin-bottom: var(--sp-1);
}

.provider-card .provider-desc {
  font-size: var(--text-sm);
  color: var(--ob-n500);
  margin: var(--sp-1) 0 var(--sp-3);
  line-height: 1.4;
}

.provider-card .provider-meta {
  font-size: var(--text-xs);
  color: var(--ob-n500);
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.provider-card .provider-meta::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-full);
  background-color: var(--ob-primary);
}

.notice-card {
  background-color: var(--ob-primary-tint);
  border: 1.5px solid var(--ob-primary-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-5);
  margin-bottom: var(--sp-6);
}

.notice-card p {
  margin: 0 0 var(--sp-3);
}

.notice-card p:last-of-type {
  margin-bottom: var(--sp-4);
}

/* === 16. EMPTY STATES ====================================== */

/*
  Every empty state: why + what to do + CTA.
  Not a bullet point list — a helpful moment.
*/

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--sp-16) var(--sp-8);
  color: var(--ob-n500);
}

.empty-state__icon {
  font-size: 2.5rem;
  margin-bottom: var(--sp-4);
  opacity: 0.4;
}

.empty-state__title {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ob-n700);
  margin-bottom: var(--sp-2);
}

.empty-state__desc {
  font-size: var(--text-sm);
  max-width: 36ch;
  margin-bottom: var(--sp-5);
  line-height: 1.6;
}

/* === 17. LOGIN PAGE ======================================== */

/*
  Decision: vertically centre the login card on the viewport.
  The cooperative's name and a clean form is all members see.
  No decorative illustration — clarity and speed matter.
*/

.login-wrap {
  min-height: calc(100vh - 80px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-8) var(--sp-4);
}

.login-card {
  width: 100%;
  max-width: 26rem;
  background-color: var(--ob-surface);
  border: 1px solid var(--ob-n200);
  border-radius: var(--radius-lg);
  padding: var(--sp-8) var(--sp-8);
  box-shadow: var(--shadow);
}

.login-card .login-logo {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--ob-primary);
  letter-spacing: -0.03em;
  margin-bottom: var(--sp-1);
  display: block;
}

.login-card .login-tagline {
  font-size: var(--text-sm);
  color: var(--ob-n500);
  margin-bottom: var(--sp-6);
}

.login-card input[type="submit"] {
  width: 100%;
  margin-top: var(--sp-2);
}

.login-links {
  margin-top: var(--sp-4);
  text-align: center;
  font-size: var(--text-sm);
}

/* === 18. UTILITIES ========================================= */

.text-muted {
  color: var(--ob-n500);
}
.text-success {
  color: var(--ob-success-text);
}
.text-error {
  color: var(--ob-rose);
}
.text-right {
  text-align: right;
}
.text-sm {
  font-size: var(--text-sm);
}
.text-xs {
  font-size: var(--text-xs);
}

.mt-0 {
  margin-top: 0;
}
.mt-4 {
  margin-top: var(--sp-4);
}
.mt-6 {
  margin-top: var(--sp-6);
}
.mt-8 {
  margin-top: var(--sp-8);
}
.mb-4 {
  margin-bottom: var(--sp-4);
}
.mb-6 {
  margin-bottom: var(--sp-6);
}

.gap-2 {
  gap: var(--sp-2);
}
.gap-3 {
  gap: var(--sp-3);
}

.flex {
  display: flex;
}
.flex-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.flex-end {
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
.items-center {
  align-items: center;
}
.flex-wrap {
  flex-wrap: wrap;
}

.w-full {
  width: 100%;
}

/* Visually hidden but accessible to screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* === 19. TABS & FILTER PILLS =============================== */

.tab-bar {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--ob-n200);
  margin-bottom: var(--sp-4);
}

.tab-link {
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ob-n500);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition:
    color var(--t-fast),
    border-color var(--t-fast);
}

.tab-link:hover {
  color: var(--ob-n900);
}

.tab-link--active {
  color: var(--ob-primary);
  border-bottom-color: var(--ob-primary);
  font-weight: 600;
}

.tab-link__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  padding: 0 var(--sp-1);
  margin-left: var(--sp-1);
  border-radius: var(--radius-full);
  background-color: var(--ob-n200);
  color: var(--ob-n700);
  font-size: var(--text-xs);
  font-weight: 600;
}

.tab-link--active .tab-link__count {
  background-color: var(--ob-primary);
  color: var(--ob-primary-contrast, #fff);
}

.filter-bar {
  display: flex;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}

.date-filter-bar {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}

.date-filter-bar label {
  margin-bottom: 0;
}

.date-filter-bar input[type="date"] {
  width: auto;
  margin-bottom: 0;
}

/* Pico sizes form buttons (and role="button" links) at width: 100% by default,
   which would otherwise drop them onto their own full-width row below the
   date fields. Pico's bottom margin is also stripped so the button's margin
   box lines up with the (already zeroed) labels under align-items: flex-end,
   instead of floating above the row. */
.date-filter-bar button,
.date-filter-bar [role="button"] {
  width: auto;
  flex-shrink: 0;
  margin-bottom: 0;
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
  border: 1.5px solid var(--ob-n300);
  color: var(--ob-n500);
  background-color: var(--ob-surface);
  transition:
    border-color var(--t-fast),
    color var(--t-fast),
    background-color var(--t-fast);
}

.filter-pill:hover {
  border-color: var(--ob-primary);
  color: var(--ob-primary);
}

.filter-pill--active {
  background-color: var(--ob-primary-tint);
  border-color: var(--ob-primary);
  color: var(--ob-primary);
}

.filter-pill--negative.filter-pill--active {
  background-color: var(--ob-rose-light);
  border-color: var(--ob-rose);
  color: var(--ob-rose);
}

/* Toggle switch (role="switch" — not a checkbox) */
.switch-field {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.switch {
  position: relative;
  flex-shrink: 0;
  width: 38px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background-color: var(--ob-n300);
  cursor: pointer;
  transition: background-color var(--t-fast);
}

.switch::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-color: var(--ob-surface);
  transition: transform var(--t-fast);
}

.switch[aria-checked="true"] {
  background-color: var(--ob-primary);
}

.switch[aria-checked="true"]::before {
  transform: translateX(16px);
}

.switch:focus-visible {
  outline: 2px solid var(--ob-primary);
  outline-offset: 2px;
}

.switch-field__label {
  font-size: var(--text-sm);
  color: var(--ob-n700);
}

.order-item-row__member {
  display: none;
}

.show-members .order-item-row__member {
  display: table-row;
}

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}

.pagination__link {
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--ob-primary-border);
  color: var(--ob-primary);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  transition:
    border-color var(--t-fast),
    background-color var(--t-fast);
}

.pagination__link:hover {
  border-color: var(--ob-primary);
  background-color: var(--ob-primary-tint);
}

.pagination__status {
  font-size: var(--text-sm);
  color: var(--ob-n500);
}

/* === 20. DIALOG MODAL ====================================== */

/*
 * Pico CSS makes the <dialog> element itself a fullscreen fixed flex
 * overlay (the "backdrop"), and expects the visible, centered card to be
 * a <dialog><article> child — the box styling below must target that
 * article, not the dialog, or it gets stretched to fill the viewport.
 */
.ob-dialog > article {
  border: 1px solid var(--ob-primary-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 2rem;
  max-width: min(700px, 94vw);
  width: 100%;
  max-height: 80vh;
  overflow-y: auto;
  background: var(--ob-surface);
}

.ob-dialog::backdrop {
  background: rgba(44, 10, 60, 0.45);
  backdrop-filter: blur(2px);
}

.ob-dialog__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--ob-n200);
  position: sticky;
  top: 0;
  background: var(--ob-surface);
  z-index: 1;
}

.ob-dialog__header strong {
  display: block;
  font-size: var(--text-base);
}

.ob-dialog turbo-frame {
  display: block;
  padding: var(--sp-5);
}

.ob-dialog form {
  display: block;
  padding: 0 var(--sp-5) var(--sp-5);
}

/* === 21. REDUCED MOTION ==================================== */

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