/* ============================================================================
   BUDTELLO DESIGN SYSTEM v1 — components.css (ADR-0329)
   ----------------------------------------------------------------------------
   CANONICAL: dispensary-ai/public/components.css.  SYNCED COPY (byte-identical,
   hash-checked by ops/ui-check.sh): askbud-marketplace/app/components.css.
   Edit the canonical file, then re-copy — never edit the copy.

   Built FROM David's picks (docs/pending/ui-shape-decisions.json, 2026-08-19).
   Every geometry/colour comes from a role token in tokens.css — no raw colour
   here, and px only where a component defines its own geometry (hairlines, icon
   boxes, rings); spacing/padding use the --space / --control / --table roles.

   PRIMER-STYLE STRUCTURE:
   - Size tiers sm / md / lg. A component reads --control-h/-pad/-font (md by
     default); put data-density="sm|lg" on ANY container to rescale everything
     inside it. One geometry per family, function naming, states defined once.
   - Both themes work through the existing data-theme mechanism (tokens flip).

   Look at every component at /ui.  Never invent a class — if you need something
   that is not here, STOP and ask David (docs/ui-standard.md).
   ========================================================================== */

/* ── Size-tier mechanic ──────────────────────────────────────────────────── */
[data-density="sm"] {
  --control-h: var(--control-h-sm); --control-pad: var(--control-pad-sm); --control-font: var(--control-font-sm);
  --table-head-pad: var(--table-head-sm); --table-cell-pad: var(--table-cell-sm);
}
[data-density="lg"] {
  --control-h: var(--control-h-lg); --control-pad: var(--control-pad-lg); --control-font: var(--control-font-lg);
  --table-head-pad: var(--table-head-lg); --table-cell-pad: var(--table-cell-lg);
}

/* ── Global interactive states (defined once) ────────────────────────────── */
.btn, .input, .tab, .page-link, .theme-toggle, .pill-account, .tab-filter {
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
:where(.btn, .input, .tab, .tab-filter, .page-link, .theme-toggle, .pill-account, .breadcrumb a):focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
:where(.btn, .input, .tab-filter, .page-link).is-disabled,
:where(.btn, .input, .tab-filter, .page-link):disabled {
  opacity: .5; cursor: not-allowed; pointer-events: none;
}
.is-loading { position: relative; color: transparent !important; pointer-events: none; }
.is-loading::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 15px; height: 15px;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: var(--radius-circle);
  color: var(--text); animation: bds-spin .6s linear infinite;
}
@keyframes bds-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .is-loading::after { animation: none; } }

/* ── Button ──────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  height: var(--control-h); padding: var(--control-pad);
  font-family: var(--display); font-weight: var(--btn-weight); font-size: var(--control-font); line-height: var(--lh-1);
  text-transform: var(--btn-case); letter-spacing: var(--btn-tracking);
  border-radius: var(--radius-control); border: var(--border-width) solid var(--btn-border);
  background: var(--btn-bg); color: var(--btn-fg); cursor: pointer; white-space: nowrap;
}
.btn:hover { border-color: var(--border-strong); }
.btn--primary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); border-color: var(--btn-primary-border); }
.btn--primary:hover { opacity: .9; border-color: var(--btn-primary-border); }
.btn--secondary { background: var(--btn-secondary-bg); color: var(--btn-secondary-fg); border-color: var(--btn-secondary-border); }
.btn--danger { background: var(--sem-fail); color: var(--canvas); border-color: color-mix(in srgb, var(--sem-fail) 55%, var(--text)); }
.btn--danger:hover { opacity: .9; }
.btn--sm { height: var(--control-h-sm); padding: var(--control-pad-sm); font-size: var(--control-font-sm); }
.btn--lg { height: var(--control-h-lg); padding: var(--control-pad-lg); font-size: var(--control-font-lg); }

/* ── Input + form field ──────────────────────────────────────────────────── */
.input {
  height: var(--control-h); padding: 0 var(--space-3);
  font-family: var(--sans); font-size: var(--control-font); color: var(--text);
  background: var(--surface-raised); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-control); width: 100%;
}
.input::placeholder { color: var(--text-secondary); }
.input:hover { border-color: var(--border-strong); }
textarea.input { height: auto; min-height: 44px; padding: var(--space-2) var(--space-3); resize: vertical; }
/* Size tier: the ONE small input, 32px (David 7 Sept, ADR-0411 clause 2).
   I22 (.mi-filter) defines the tier; the $/lb box joins it. Height and type
   only - horizontal padding already matches --control-pad-sm. */
.input--sm { height: var(--control-h-sm); font-size: var(--control-font-sm); }
/* Role: the market search stays a round pill, as a named class rather than a
   one-off (David 7 Sept, ADR-0411 clause 2). Radius only. */
.input--pill { border-radius: var(--radius-pill); }
.field { display: flex; flex-direction: column; gap: var(--space-1); }
.field__label { font-size: var(--font-sm); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-secondary); font-weight: 600; }
.field__hint { font-size: var(--font-sm); color: var(--text-secondary); }
.field__error { font-size: var(--font-sm); color: var(--sem-fail); }
.field.is-invalid .input { border-color: var(--sem-fail); }

/* ── Table (pick t.md: mi-table md geometry — horizontal rules, no vertical
      separators; row density via [data-density]) ───────────────────────────── */
.table { width: 100%; border-collapse: collapse; font-size: var(--table-font); }
.table th {
  text-align: left; padding: var(--table-head-pad); white-space: nowrap; font-weight: var(--table-head-weight);
  text-transform: var(--table-head-case); color: var(--text-secondary); border-bottom: var(--border-width) solid var(--border-strong);
  height: var(--table-head-h); /* Lane F (ADR-0467): a min-height on a table
                                    cell, so this only ever grows a header,
                                    never shrinks one */
}
.table td { padding: var(--table-cell-pad); border-bottom: var(--border-width) solid var(--table-line); vertical-align: middle; }
.table tbody tr:hover { background: var(--table-hover); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { border: var(--border-width) solid var(--border); border-radius: var(--table-radius); overflow-x: auto; background: var(--surface-raised); } /* Lane F (ADR-0467): was --radius-container directly; now its own token, same default */

/* ── Badge / status chip (pick bs.pill + pal.cool; NOWRAP LAW) ────────────── */
.badge {
  display: inline-flex; align-items: center; white-space: nowrap;   /* never wraps to two rows */
  padding: 0 var(--space-2); font: 600 var(--font-sm) var(--sans); line-height: var(--lh-tight);
  border-radius: var(--radius-pill); border: var(--border-width) solid var(--border); color: var(--text);
}
.badge--rect { border-radius: var(--radius-control); }
.badge--ok      { color: var(--sem-ok);      background: color-mix(in srgb, var(--sem-ok) 14%, transparent);      border-color: color-mix(in srgb, var(--sem-ok) 30%, transparent); }
.badge--warn    { color: var(--sem-warn);    background: color-mix(in srgb, var(--sem-warn) 16%, transparent);    border-color: color-mix(in srgb, var(--sem-warn) 32%, transparent); }
.badge--fail    { color: var(--sem-fail);    background: color-mix(in srgb, var(--sem-fail) 12%, transparent);    border-color: color-mix(in srgb, var(--sem-fail) 30%, transparent); }
.badge--info    { color: var(--sem-info);    background: color-mix(in srgb, var(--sem-info) 14%, transparent);    border-color: color-mix(in srgb, var(--sem-info) 30%, transparent); }
.badge--neutral { color: var(--sem-neutral); background: var(--surface-recessed);                                  border-color: var(--border); }
.badge--overlay { position: absolute; border: none; color: var(--text); background: color-mix(in srgb, var(--canvas) 72%, transparent); } /* media-tile overlay; the SURFACE sets the offsets */

/* ── Status chip (display-weight confirmation chip, e.g. "Verified licensee":
      neutral surface carries the chip, the semantic colour rides the icon) ── */
.status-chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font: 700 var(--font-body) var(--display); color: var(--text);
  border: var(--border-width) solid var(--border-strong); background: var(--surface-raised);
  border-radius: var(--radius-control); padding: var(--space-2) var(--space-3);
}
.status-chip__icon { display: inline-flex; }
.status-chip--ok .status-chip__icon { color: var(--sem-ok); }

/* ── Card (pick containers=12, border=1, elevation=flat) ─────────────────── */
.card {
  background: var(--surface-raised); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-container); box-shadow: var(--elevation-card); padding: var(--space-4);
}
.card--pad-lg { padding: var(--space-5); }

/* ── Section header ──────────────────────────────────────────────────────── */
.section-header { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); margin: 0 0 var(--space-3); }
.section-header__title { font: 600 var(--font-h3) var(--display); letter-spacing: var(--tracking-tight); margin: 0; }
.section-header__meta { font-size: var(--font-base); color: var(--text-secondary); }

/* ── Tabs: nav (underline) + filter (segmented) ──────────────────────────── */
.tabs { display: flex; gap: var(--space-1); border-bottom: var(--border-width) solid var(--border); }
.tab {
  height: var(--control-h); padding: 0 var(--space-3); display: inline-flex; align-items: center;
  font: 600 var(--font-body) var(--display); color: var(--text-secondary); background: none;
  border: none; border-bottom: 2px solid transparent; cursor: pointer; margin-bottom: -1px;
}
.tab:hover { color: var(--text); }
.tab.is-active { color: var(--text); border-bottom-color: var(--accent); }
.tabs-filter { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); }
.tab-filter {
  padding: var(--control-pad-sm); font: var(--font-base) var(--display); color: var(--text);
  background: var(--surface-recessed); border: var(--border-width) solid var(--border); border-radius: var(--radius-control); cursor: pointer;
}
.tab-filter.is-active { background: var(--text); color: var(--canvas); border-color: var(--text); }

/* ── Alert / notice (badge-colour trick: tinted bg + border of the semantic hue) */
.alert {
  display: flex; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-control);
  font-size: var(--font-base); border: var(--border-width) solid var(--border); background: var(--surface-raised); color: var(--text);
}
.alert--ok   { color: var(--sem-ok);   background: color-mix(in srgb, var(--sem-ok) 8%, transparent);   border-color: color-mix(in srgb, var(--sem-ok) 30%, transparent); }
.alert--warn { color: var(--sem-warn); background: color-mix(in srgb, var(--sem-warn) 10%, transparent); border-color: color-mix(in srgb, var(--sem-warn) 32%, transparent); }
.alert--fail { color: var(--sem-fail); background: color-mix(in srgb, var(--sem-fail) 8%, transparent); border-color: color-mix(in srgb, var(--sem-fail) 32%, transparent); }
.alert--info { color: var(--sem-info); background: color-mix(in srgb, var(--sem-info) 10%, transparent); border-color: color-mix(in srgb, var(--sem-info) 30%, transparent); }

/* ── Empty state ─────────────────────────────────────────────────────────── */
.empty-state { padding: var(--space-7) var(--space-5); text-align: center; color: var(--text-secondary); border: var(--border-width) dashed var(--border); border-radius: var(--radius-container); }
.empty-state__title { font: 600 var(--font-body) var(--display); color: var(--text); margin: 0 0 var(--space-1); }

/* ── Breadcrumb / back link ──────────────────────────────────────────────── */
.breadcrumb { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--font-base); color: var(--text-secondary); }
.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb__sep { color: var(--border-strong); }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; padding: var(--space-5) 0; border-top: var(--border-width) solid var(--border); font-size: var(--font-base); color: var(--text-secondary); }
.footer a { color: var(--text-secondary); text-decoration: none; }
.footer a:hover { color: var(--text); }

/* ── Account pill (pick pill full-radius) ────────────────────────────────── */
.pill-account { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1); border-radius: var(--radius-pill); background: var(--surface-raised); border: var(--border-width) solid var(--border); box-shadow: var(--elevation); cursor: pointer; color: var(--text); }
.pill-account:hover { border-color: var(--border-strong); }
.pill-account__avatar { width: 30px; height: 30px; border-radius: var(--radius-circle); display: inline-flex; align-items: center; justify-content: center; background: var(--surface-recessed); font: 700 var(--font-base) var(--display); overflow: hidden; }
.pill-account__caret { color: var(--text-secondary); font-size: var(--font-sm); }

/* Theme toggle: NOT here. It is header furniture and lives in the one
   header stylesheet, shared/partials/header.css (ADR-0345). This file keeps
   only its shared interaction states, above, alongside the other controls. */

/* ── Modal overlay (fixed shell: the panel never scrolls — chrome stays put,
      the .modal__body slot scrolls; adopted from the marketplace fork,
      convergence decision 2026-09-03) ───────────────────────────────────── */
.modal-backdrop { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: var(--space-5); background: color-mix(in srgb, var(--surface-recessed) 65%, transparent); }
.modal {
  position: relative; width: 100%; max-width: 420px; background: var(--surface-raised); color: var(--text);
  border: var(--border-width) solid var(--border); border-radius: var(--radius-container); box-shadow: var(--elevation);
  padding: var(--space-5); max-height: 90vh; max-height: 90dvh;
  display: flex; flex-direction: column; overflow: hidden;
}
.modal__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.modal--wide { max-width: 720px; }
.modal--media { max-width: 92vw; width: auto; padding: 0; background: transparent; border: none; box-shadow: none; max-height: 92vh; max-height: 92dvh; }
.modal__close { position: absolute; top: var(--space-2); right: var(--space-3); background: none; border: none; color: var(--text-secondary); font-size: var(--font-h2); line-height: var(--lh-1); cursor: pointer; padding: var(--space-1); border-radius: var(--radius-control); }
.modal__close:hover { color: var(--text); }
.modal--media .modal__close { top: 4px; right: 6px; z-index: 3; color: var(--text); background: color-mix(in srgb, var(--canvas) 70%, transparent); }

/* ── Choice group (compact pick-one control: chip trigger + option popover;
      the sell/quick grade picker anatomy, canonicalised 2026-09-03) ───────── */
.choice-group { display: inline-flex; align-items: center; gap: 2px; }
.choice-wrap { position: relative; display: inline-flex; }
.choice-chip {
  display: inline-flex; align-items: center; gap: var(--space-1); cursor: pointer;
  border: var(--border-width) solid var(--border); border-radius: var(--radius-control); padding: 0 var(--space-1);
  background: var(--surface-recessed); color: var(--text-secondary); font-size: var(--font-sm); line-height: var(--lh-tight);
}
.choice-chip.is-assumed { border-style: dashed; } /* assumed, not chosen — the control must not claim a pick */
.choice-info { display: inline-flex; width: 12px; height: 12px; border-radius: var(--radius-circle); border: var(--border-width) solid var(--border-strong); align-items: center; justify-content: center; font-size: var(--font-micro); font-style: italic; }
.choice-pop { position: absolute; top: calc(100% + 4px); left: 0; z-index: 40; display: flex; gap: var(--space-1); padding: var(--space-1); background: var(--surface-raised); border: var(--border-width) solid var(--border); border-radius: var(--radius-control); box-shadow: var(--elevation); }
.choice-pop--wide { flex-wrap: wrap; max-width: 240px; }
.choice-opt { border: var(--border-width) solid var(--border); border-radius: var(--radius-control); background: none; color: var(--text); font-size: var(--font-sm); padding: 0 var(--space-2); cursor: pointer; }
.choice-opt:hover { border-color: var(--border-strong); }
.choice-opt.is-active { border-color: var(--accent); color: var(--accent); }

/* ── Toast (fixed dismissable notice; the SURFACE sets its offsets) ───────── */
.toast {
  position: fixed; z-index: 1000; max-width: 360px;
  display: flex; align-items: flex-start; gap: var(--space-3);
  background: var(--surface-raised); color: var(--text);
  border: var(--border-width) solid var(--border); border-left: 2px solid var(--accent);
  border-radius: var(--radius-container); padding: var(--space-3) var(--space-4);
  box-shadow: var(--elevation); font-size: var(--font-base); line-height: var(--lh-body);
}
.toast__close { background: none; border: none; color: var(--text-secondary); font-size: var(--font-h3); line-height: var(--lh-1); cursor: pointer; padding: 0; }
.toast__close:hover { color: var(--text); }
.toast__action { font-weight: 600; }

/* ── Pagination (NEW — Primer shape: prev / next + numbers on btn-sm) ─────── */
.pagination { display: inline-flex; align-items: center; gap: var(--space-1); }
.page-link {
  height: var(--control-h-sm); min-width: var(--control-h-sm); padding: 0 var(--space-2);
  display: inline-flex; align-items: center; justify-content: center;
  font: 600 var(--control-font-sm) var(--display); color: var(--text);
  background: var(--surface-raised); border: var(--border-width) solid var(--border);
  border-radius: var(--radius-control); cursor: pointer; text-decoration: none;
}
.page-link:hover { border-color: var(--border-strong); }
.page-link.is-current { background: var(--accent); color: var(--on-accent); border-color: var(--accent-edge); cursor: default; }
.page-link.is-ellipsis { border-color: transparent; background: none; cursor: default; color: var(--text-secondary); }

/* ── Table grid (docs/guides/table-pattern.md — the Sheets model) ─────────
   USAGE: wrap a .table in .table-wrap.table-wrap--grid to give the table its
   own scroll viewport: the header row sticks to the wrap's top and a frozen
   column survives horizontal scroll (mobile). The SURFACE sets the height
   via --grid-max-h and the cell background via --grid-cell-bg (must match
   the card the table sits on, so frozen cells cover what slides beneath).
   Freeze a column by putting .is-frozen on its th AND every td; the SURFACE
   sets each frozen cell's `left` offset (canonical carries mechanics only).
   Desktop is fit-and-hide: core columns always visible, optional columns
   behind the surface's Columns toggle — never a horizontal scrollbar on
   desktop; mobile keeps the same table and scrolls sideways (pinch-zoom
   stays enabled — never set user-scalable=no / maximum-scale=1). */
.table-wrap--grid { max-height: var(--grid-max-h, calc(100dvh - 240px)); overflow: auto; }
.table-wrap--grid .table thead th { position: sticky; top: 0; z-index: 3; background: var(--grid-cell-bg, var(--surface-raised)); }
.table .is-frozen { position: sticky; left: 0; z-index: 2; background: var(--grid-cell-bg, var(--surface-raised)); }
.table thead th.is-frozen { z-index: 4; }
.table tbody tr:hover td { background: var(--table-hover); }
/* Row selection (table-pattern.md: click anywhere on the row selects it) */
.table tbody tr.is-rowselect { cursor: pointer; }
.table tbody tr.is-selected td { background: color-mix(in srgb, var(--accent) 9%, var(--grid-cell-bg, var(--surface-raised))); }
.table tbody tr.is-selected:hover td { background: color-mix(in srgb, var(--accent) 14%, var(--grid-cell-bg, var(--surface-raised))); }

/* ── Toolbar (table-pattern.md: FIND locates, CHANGE mutates) ─────────────
   USAGE: fixed strips above a table that NEVER reflow — every control keeps
   one position for life. .toolbar--find always shows (search fields, the
   "+ Filter" button, sort, Columns toggle); .toolbar--change ALSO always
   shows — its controls are disabled at 0 selected, never hidden. The old
   .is-idle rule hid it "via visibility, so its space is kept": the space was
   therefore never reclaimed, so hiding bought nothing and only cost the
   operator sight of the controls (ADR-0457 overturns ADR-0396 rule 6;
   David, 9 Sept: "That should always stay put"). Do not reintroduce it as a
   Gmail-pattern improvement — it was tried, and this is the second removal.
   .toolbar__end pins the trailing cluster right. .toolbar__overflow is the
   overflow slot at the FIXED right end: controls that no longer fit HIDE
   into its menu in a defined order (tag them .tb-hide-1 / .tb-hide-2, and
   render their menu twins inside .toolbar__menu with the same tag) — they
   never rearrange. The slot itself reserves its width at every size. */
.toolbar { display: flex; align-items: center; gap: var(--space-3); min-height: 42px; padding: var(--space-1) 0; flex-wrap: nowrap; }
.toolbar__label { font-size: var(--font-sm); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-secondary); font-weight: 600; }
.toolbar__end { margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-3); }
.toolbar__group { display: inline-flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.toolbar__overflow { position: relative; display: inline-flex; width: 32px; justify-content: center; }
.toolbar__more { height: var(--control-h-sm); width: 30px; display: inline-flex; align-items: center; justify-content: center; border: var(--border-width) solid var(--border); border-radius: var(--radius-control); background: var(--surface-raised); color: var(--text); cursor: pointer; font-size: var(--font-h3); line-height: var(--lh-1); visibility: hidden; }
.toolbar__more:hover { border-color: var(--border-strong); }
.toolbar__menu { display: none; position: absolute; right: 0; top: calc(100% + 4px); z-index: 60; flex-direction: column; align-items: stretch; gap: var(--space-2); min-width: 200px; padding: var(--space-2); background: var(--surface-raised); border: var(--border-width) solid var(--border); border-radius: var(--radius-control); box-shadow: var(--elevation); }
.toolbar__menu.is-open { display: flex; }
.toolbar__menu .tb-hide-1, .toolbar__menu .tb-hide-2, .toolbar__menu .tb-hide-3 { display: none; }
@media (max-width: 1100px) {
  .toolbar > .tb-hide-1, .toolbar > * > .tb-hide-1 { display: none; }
  .toolbar__menu .tb-hide-1 { display: inline-flex; }
  .toolbar__more { visibility: visible; }
}
@media (max-width: 860px) {
  .toolbar > .tb-hide-2, .toolbar > * > .tb-hide-2 { display: none; }
  .toolbar__menu .tb-hide-2 { display: inline-flex; }
}
/* TIER 3 - phone. Added by ADR-0457, which is the first change to run the
   toolbar with canonical's nowrap actually in force: below ~720px two tiers
   are not enough and the row CLIPPED instead of overflowing, which is the
   one thing the pattern forbids. */
@media (max-width: 720px) {
  .toolbar > .tb-hide-3, .toolbar > * > .tb-hide-3 { display: none; }
  .toolbar__menu .tb-hide-3 { display: inline-flex; }
  .toolbar__more { visibility: visible; }
}

/* ── Filter chips (table-pattern.md) ──────────────────────────────────────
   USAGE: .chip-row is a FIXED-HEIGHT row under the FIND toolbar holding the
   active filters as removable chips — empty it still holds its height, so
   adding/clearing filters never moves the table. One .filter-chip per
   active filter; its .filter-chip__x clears that filter. Inactive filter
   controls occupy NO permanent toolbar space (they live behind "+ Filter");
   there are no per-column funnel icons. */
.chip-row { display: flex; align-items: center; gap: var(--space-2); min-height: 34px; padding: 0; overflow-x: auto; }
.filter-chip { display: inline-flex; align-items: center; gap: var(--space-1); height: 24px; padding: 0 var(--space-1) 0 var(--space-2); border-radius: var(--radius-pill); border: var(--border-width) solid var(--border-strong); background: var(--surface-recessed); color: var(--text); font-size: var(--font-sm); white-space: nowrap; }
.filter-chip__x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border: none; border-radius: var(--radius-circle); background: none; color: var(--text-secondary); cursor: pointer; font-size: var(--font-base); line-height: var(--lh-1); }
.filter-chip__x:hover { color: var(--text); background: var(--surface-raised); }

/* ── Tooltip (table-pattern.md; replaces native title tooltips) ───────────
   USAGE: ONE custom tooltip everywhere, INSTANT on hover/focus/tap. The
   trigger is the question-mark affordance (.qmark) rendered by the Tooltip
   component (app/portal/InfoTip.tsx in the marketplace); the bubble
   (.tooltip-bubble) is PORTALED to <body> so no scroll or stacking context
   can clip it — the component sets its fixed-position coordinates. Never
   use the title attribute for help text. */
.qmark { display: inline-flex; align-items: center; justify-content: center; width: 13px; height: 13px; margin-left: 4px; border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-circle); color: var(--text-secondary); font: 600 var(--font-micro) var(--display); cursor: help; flex: none; }
.qmark:hover, .qmark:focus-visible { color: var(--text); border-color: var(--text); outline: none; }
.tooltip-bubble { position: fixed; z-index: 2000; max-width: 300px; padding: var(--space-2) var(--space-3); background: var(--surface-raised); border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-control); box-shadow: var(--elevation); color: var(--text); font-size: var(--font-base); line-height: var(--lh-body); pointer-events: none; }

/* ── Bulk-change guard (ADR-0500): the card that stands in front of a change
      landing on ten rows or more. It lives with the modal family because it
      IS the modal content slot — the panel itself is untouched. ─────────── */
.bulkconfirm { display: flex; flex-direction: column; gap: var(--space-3); }
.bulkconfirm__title { margin: 0; padding-right: var(--space-5); font-size: var(--font-h3); line-height: var(--lh-tight); }
.bulkconfirm__line { margin: 0; color: var(--text-secondary); line-height: var(--lh-body); }
.bulkconfirm__actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }
/* order-david-174611: neither label may ever wrap. On a card too narrow for
   the whole phrase the unit drops and the button reads "Change 65"; it never
   goes to two lines. */
.bulkconfirm__actions .btn { white-space: nowrap; }
@media (max-width: 360px) { .bulkconfirm__unit { display: none; } }
