[hidden] {
  display: none !important;
}

body.all-stalls-page {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  overflow: hidden;
}

.all-stalls-page .atmosphere {
  position: fixed;
  z-index: 0;
  top: -150px;
  right: -130px;
  width: 430px;
  height: 430px;
  border-radius: 48% 52% 58% 42%;
  background: radial-gradient(
    circle at 35% 35%,
    var(--color-accent-300),
    var(--color-accent-200) 55%,
    transparent 75%
  );
  filter: blur(16px);
  opacity: 0.55;
  pointer-events: none;
}

body.all-stalls-page > header,
body.all-stalls-page > main {
  position: relative;
  z-index: 1;
}

/*
 * The header outranks the workspace, because the filter popover hangs out of
 * it and over the cards. Both were at `z-index: 1`, and `main` comes later in
 * the document, so the board painted straight over the popover: it was
 * anchored correctly and invisible behind the first row of cards.
 */
body.all-stalls-page > header {
  z-index: 3;
}

/* ------------------------------------------------------------------ *
 * Header
 * ------------------------------------------------------------------ */

body.all-stalls-page > header {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-3);
}

.all-stalls-page .brand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 20px;
  color: var(--color-text);
  text-decoration: none;
}

.all-stalls-page .role-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
}

.all-stalls-page .role-nav .role {
  font-size: 12px;
  margin-right: var(--space-2);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}

/* .role-nav-link itself now lives in organic-system.css, composed
 * unqualified (SURF-4f standards remediation) — identical here to the
 * other three surfaces, so one shared definition replaces four copies. */

/* `Log out` is `.logout-link` in organic-system.css now — the body face the
 * artboard sets on it, its Lucide mark's sizing, and the ghost hover, shared
 * by every staff surface rather than restated here. */

/* ------------------------------------------------------------------ *
 * Route state, connectivity, status
 * ------------------------------------------------------------------ */

.all-stalls-page main {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.connectivity-status {
  flex: none;
  margin: 0 var(--space-6) var(--space-3) !important;
}

.all-stalls-route-state {
  flex: none;
  margin: 0 var(--space-6) var(--space-3);
  padding: var(--space-4);
  border-radius: calc(var(--radius-lg) * 1.15); /* the .card/.dialog radius */
  background: var(--color-surface);
  font-size: 13.5px;
  line-height: 1.5;
}

.all-stalls-route-state .eyebrow {
  margin: 0;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-accent-700);
}

.all-stalls-route-state h2 {
  margin: var(--space-1) 0 var(--space-2);
  font-size: 27px;
}

.all-stalls-page .status {
  position: sticky;
  z-index: 2;
  top: 12px;
  flex: none;
  margin: 0 var(--space-6);
  font-size: 13px;
  color: var(--color-accent-700);
}

.all-stalls-page .status:empty {
  margin: 0;
  visibility: hidden;
}

/* ------------------------------------------------------------------ *
 * The workspace: scrolls inside the fixed shell.
 * ------------------------------------------------------------------ */

.all-stalls-workspace {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--space-3) var(--space-6) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hint {
  font-size: 12.5px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}

/*
 * The coverage chips, the stall-selection dialog, the swimlanes, the ticket
 * card and the handoff forms all used to be dressed here. They went with the
 * lanes: `Stalls Overview.dc.html` draws a triage board, and work happens
 * inside a stall. Every one of those rules still exists where the DOM does —
 * `stall-queue-organic.css` and `handoff-organic.css`.
 */

@media (prefers-reduced-motion: reduce) {
  .all-stalls-page * {
    transition: none;
  }
}

/* ------------------------------------------------------------------ *
 * The triage board (Stalls Overview.dc.html, option 5a)
 *
 * The whole surface. The board answers "which stall is in trouble"; that
 * stall's own queue answers "what do I do about it", and the drawer's link is
 * the way across.
 * ------------------------------------------------------------------ */

.overview-header {
  align-items: flex-end;
}

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

.overview-scope {
  margin: 2px 0 0;
  font-size: 13px;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}

.board-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.board-sort {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.board-sort-label {
  font-size: 12.5px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}

/*
 * The board's own pills, stated rather than composed from `.btn`.
 *
 * `Stalls Overview.dc.html` draws every one of these with `font: inherit` at
 * 13.5px — the body face. `.btn` is the heading face, which is correct for the
 * real buttons on this page (`Done`, and the drawer's two actions) and wrong
 * here: a row of Caprasimo pills beside the Event's Caprasimo name is one
 * texture where the artboard has two.
 *
 * Everything `.btn` used to supply is restated: the shape, the 999px pill, the
 * hover and the disabled state. The focus ring is not — that is the system's
 * one global `:focus-visible`, and states are built in once.
 */
.board-sort-option,
.board-filter-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--color-accent-200);
  border-radius: 999px;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 13.5px;
  line-height: 1.2;
  cursor: pointer;
}

.board-sort-option:hover,
.board-filter-toggle:hover {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
}

.board-sort-option:active,
.board-filter-toggle:active {
  background: color-mix(in srgb, var(--color-text) 14%, transparent);
}

.board-sort-option:disabled,
.board-filter-toggle:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* The chosen sort, and a filter that is currently narrowing the board. Stated
 * after the hover rules, so a filled pill stays filled under the pointer. */
.board-sort-option[aria-pressed="true"],
.board-sort-option[aria-pressed="true"]:hover,
.board-filter-toggle.board-filter-narrowed,
.board-filter-toggle.board-filter-narrowed:hover {
  background: var(--color-accent-600);
  border-color: var(--color-accent-700);
  color: var(--color-bg);
}

/* The peer pair is `.peer-pair` in organic-system.css now, shared by every
 * staff surface rather than restated per page. */

.all-stalls-page .overview-operations {
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--color-accent-200);
  border-radius: 999px;
  font-size: 13px;
}

/*
 * No horizontal padding: `.all-stalls-workspace` already insets by
 * `--space-6`, and repeating it here indented the board a second time and
 * took 53px off every card. The design insets once.
 */
.board {
  flex: none;
  padding: 0 0 var(--space-4);
}

/* The strip is only ever drawn when a stall needs something, so it carries a
 * tinted ground: an alert row that looks like the page teaches nobody. */
/*
 * `Stalls Overview.dc.html` puts the strip between the header and the
 * scrolling card area: `flex:none`, outside the scroller, so it is still there
 * when the ninth stall is. Here the strip travels with the cards, so it is
 * pinned to the top of the scroller instead — same result, one element.
 */
.board-alerts:not([hidden]) {
  position: sticky;
  z-index: 2;
  top: 0;
}

.board-alerts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: 28px;
  background: var(--color-accent-100);
  list-style: none;
}

.board-alert {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: var(--color-bg);
  box-shadow: var(--shadow-sm);
  color: var(--color-accent-800);
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
}

.board-alert-dot {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: var(--color-accent);
}

/* A paused stall is not an accent-coloured warning: it is a stall somebody
 * switched off, and it reads in the neutral ramp so the accent stays
 * reserved for a stall that is struggling while still trading. */
.board-alert[data-paused="true"] .board-alert-dot {
  background: var(--color-neutral-800);
}

.board-alert-stall {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 14.5px;
}

.board-alert-text {
  opacity: 0.75;
}

.board-cards {
  display: grid;
  /*
   * Three columns at the width the board is drawn for. The design sets
   * `repeat(3, 1fr)` flat; a 340px floor reaches the same three tracks at
   * 1194px while still adapting either way — a wider screen earns a fourth
   * column rather than three stretched ones, and a narrower one drops to two.
   *
   * `min(...)` around the floor is load-bearing: a bare track minimum is a
   * floor the grid cannot go under, and at 200% zoom that pushes the document
   * wider than the viewport.
   */
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.board-card {
  width: 100%;
  height: 100%;
  display: grid;
  gap: var(--space-3);
  align-content: start;
  padding: var(--space-4);
  border: 1px solid transparent;
  border-radius: 30px;
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.board-card:hover {
  background: var(--color-accent-100);
}

/* A stall in trouble is outlined, so worst-first is legible as shape and not
 * only as position: a runner glancing at the board from a metre away sees the
 * ring before they read the sort order. */
.board-card[data-late="true"],
.board-card[data-backlog="true"] {
  border-color: var(--color-accent-300);
}

.board-card[data-capacity-state="Paused"] {
  border-color: var(--color-neutral-400);
}

.board-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}

.board-card-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 20px;
  line-height: 1.15;
}

.board-card-status {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--color-accent-2-200);
  color: var(--color-accent-2-800);
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 13px;
}

.board-card[data-capacity-state="Busy"] .board-card-status {
  background: var(--color-accent-200);
  color: var(--color-accent-800);
}

.board-card[data-capacity-state="Paused"] .board-card-status {
  background: var(--color-neutral-800);
  color: var(--color-neutral-100);
}

.board-card-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: currentColor;
}

.board-card-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--space-3);
  row-gap: var(--space-2);
}

.board-figure {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.board-figure-value {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 26px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.board-figure-wait .board-figure-value {
  font-size: 22px;
  line-height: 1.18;
}

/*
 * The same accessibility exception the Stall Queue timers take, for the same
 * reason and against the same rule (`docs/agents/design.md`). These
 * values are 22px and 26px in the heading face at weight 400, so only the 26px
 * one clears WCAG's large-text threshold; the base accent gives 2.69:1 on
 * `--color-surface` and 3.29:1 on `--color-accent-100`. The measured ratios are preserved above.
 */
.board-card[data-late="true"] .board-figure-wait .board-figure-value,
.board-card[data-backlog="true"] .board-figure-ready .board-figure-value {
  color: var(--color-accent-700); /* 5.09:1 / 6.21:1 */
}

.board-figure-label {
  font-size: 11.5px;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}

.board-card-note {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-accent-200);
  font-size: 12.5px;
  color: var(--color-accent-700);
}

.board-empty {
  margin: var(--space-3) 0 0;
}

/* ------------------------------------------------------------------ *
 * Which stalls the board shows, and one stall's detail
 * ------------------------------------------------------------------ */

/*
 * A drawer at the right edge, full height — as the design draws it, not a
 * card floated in the middle. It matters: the board stays visible down the
 * left while a stall is open, so a runner comparing this stall against the
 * others does not have to close it to look.
 */
.stall-detail {
  width: min(480px, 100%);
  max-width: none;
  height: 100%;
  max-height: 100%;
  /* `auto` on the left only: a dialog is centred by its own auto margins, and
     this one belongs against the right edge. */
  margin: 0 0 0 auto;
  padding: var(--space-6);
  border: 0;
  border-radius: 0;
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--shadow-lg);
  overflow-y: auto;
}

.stall-detail::backdrop {
  background: color-mix(in srgb, var(--color-neutral-900) 42%, transparent);
}

/*
 * A popover anchored under the filter button, not a modal — 316px wide at
 * radius 30, as the design draws it. It has no backdrop on purpose: its own
 * copy promises the cards and alerts follow it, which a dimmed board cannot
 * demonstrate.
 */
.board-filter-toggle {
  position: relative;
}

.board-filter-dialog {
  position: absolute;
  z-index: 6;
  inset: auto auto auto 0;
  margin: 0;
  width: min(316px, calc(100vw - 2 * var(--space-6)));
  padding: var(--space-4);
  border: 0;
  border-radius: 30px;
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--shadow-lg);
}

/* The controls group is the positioning context, so the popover hangs from the
   filter button rather than from the page. */
.board-controls {
  position: relative;
}

.board-filter-dialog[open] {
  top: calc(100% + 12px);
}

/*
 * Every mask on this surface points at a file under `/icons`, never at a
 * `data:` URI. The CSP is `img-src 'self'` and a mask image is fetched under
 * `img-src`, so a `data:` mask is blocked — and a mask that fails to load
 * masks its element away completely rather than falling back, which is a glyph
 * that silently never paints while `getComputedStyle` still reports its URL.
 */

/* The mark: an outlined box that fills with a tick when the stall is shown. */
.board-filter-mark {
  flex: none;
  width: 18px;
  height: 18px;
  border: 1.5px solid currentColor;
  border-radius: 6px;
  opacity: 0.45;
}

.board-filter-choice[aria-pressed="true"] .board-filter-mark {
  opacity: 1;
  background: currentColor;
  mask: var(--tick-mark) center / 12px 12px no-repeat;
  -webkit-mask: var(--tick-mark) center / 12px 12px no-repeat;
  border-color: transparent;
  border-radius: 0;
}

.all-stalls-page {
  --tick-mark: url("/icons/check.svg");
}

.board-filter-choice {
  display: flex;
  align-items: center;
  gap: 10px;
}

.board-filter-name {
  flex: 1;
  min-width: 0;
  text-align: left;
}

.board-filter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.board-filter-head h2 {
  margin: 0;
  /* 17px in the artboard, where this is an `h3` inside the board's own
     heading order. Here it names a `<dialog>`, so it is an `h2`; the size is
     the design's. */
  font-size: 17px;
}

/* `Show all` is an underlined text link in the artboard, not a pill: it undoes
 * a narrowing rather than taking an action of its own. Bare, like the pills
 * above, and for the same reason — the artboard sets `font: inherit`. */
#board-filter-all {
  min-height: 32px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: var(--color-accent-700);
  font: inherit;
  font-size: 13px;
  text-decoration: underline;
  cursor: pointer;
}

.board-filter-dialog .hint {
  margin: 4px 0 0;
  font-size: 12px;
}

#board-filter-done {
  min-height: 48px;
}

.board-filter-choices {
  display: grid;
  gap: 4px;
  margin: var(--space-3) 0;
  padding: 0;
  max-height: 296px;
  overflow-y: auto;
  list-style: none;
}

.board-filter-choice {
  width: 100%;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--color-accent-200);
  border-radius: 999px;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}

.board-filter-choice[aria-pressed="true"] {
  background: var(--color-accent-600);
  border-color: var(--color-accent-700);
  color: var(--color-bg);
}

.stall-detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.stall-detail-head h2 {
  margin: 0;
  font-size: 28px;
  line-height: 1.1;
}

.stall-detail-status {
  margin: 4px 0 0;
  font-size: 13px;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}

.stall-detail-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
}

.stall-detail-figure {
  padding: var(--space-3);
  border-radius: 24px;
  background: var(--color-surface);
}

.stall-detail-figure-value {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 24px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.stall-detail-figure-label {
  margin: 3px 0 0;
  font-size: 11.5px;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}

.stall-detail-sold-out {
  margin-top: var(--space-3);
  padding: var(--space-4);
  border-radius: 30px;
  background: var(--color-surface);
}

.stall-detail-sold-out h3 {
  margin: 0;
  font-size: 18px;
}

.stall-detail-sold-out ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.stall-detail-actions {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.stall-detail-actions .btn-primary {
  min-height: 56px;
}

.stall-detail-actions .btn-secondary {
  min-height: 52px;
}

/* A refusal states what did not happen, against the stall it was refused
 * for. It is not a toast: it stays until the dialog is closed. */
.stall-detail-refusal {
  margin: var(--space-3) 0 0;
  padding: var(--space-3) var(--space-4);
  border-radius: 24px;
  background: var(--color-accent-100);
  color: var(--color-accent-800);
  font-size: 14px;
}

/* The board's own heading and the page title are named for assistive
 * technology and drawn by the header instead. Clipped rather than
 * display:none, which would silence them too. Restated here because this
 * system has no shared clipping utility. */
.board-heading,
.board-page-title {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/*
 * Phone. The board used to be hidden at this width and the lanes below it were
 * the operational task; there are no lanes, so hiding the board would leave a
 * runner holding an empty screen.
 *
 * `Stalls Overview.dc.html` is drawn at 1194x834 and its closing note says what
 * the phone version should be: "the same cards as a single sorted column with
 * the alert strip pinned". That is what this is — no invention, the artboard's
 * own sentence.
 */
@media (max-width: 700px) {
  .board-cards {
    grid-template-columns: 1fr;
  }

  /*
   * At 200% zoom a 390px phone is 195 CSS pixels wide, and three figure
   * columns cannot fit in that: the card's own content, not the grid around
   * it, is what pushed the page sideways. The three numbers stack instead.
   */
  /*
   * One number per row. Three beside each other is a 1194px composition; at
   * 390px — and at 200% zoom, where that is 195 CSS pixels — the row is wider
   * than the card that holds it, and the card clips rather than growing.
   */
  .board-card-figures {
    grid-template-columns: 1fr;
    /* A grid item does not shrink below its own min-content without this, so
       the figures block stayed at the width three numbers wanted and hung out
       of the card holding it. */
    min-width: 0;
  }

  /*
   * `min-width: 0` on the figure is not enough on its own: `oldest ticket` and
   * `waiting to collect` are two words that do not break, so the track keeps
   * their min-content width and the row runs out of the card. The labels wrap
   * here instead.
   */
  .board-figure-label {
    overflow-wrap: anywhere;
  }

  .board:not(:has(.board-alerts:not([hidden]))) {
    padding-bottom: var(--space-4);
  }

  /*
   * The controls wrap rather than sitting on one line with the Event's name,
   * and so does the sort group inside them. At 200% zoom a 390px phone is 195
   * CSS pixels wide: a filter button and three sort pills on one unbreakable
   * row is 592px of it, which is the whole page scrolling sideways.
   */
  .board-controls,
  .board-sort {
    flex-wrap: wrap;
    row-gap: var(--space-2);
  }

  .board-controls {
    width: 100%;
  }

  /*
   * `height: 100%` equalises cards across a row of three. In one column there
   * is no row to equalise against, and at 200% zoom — where the figures wrap
   * to more lines than the row was sized for — it clipped the bottom of every
   * card by 46px.
   */
  .board-card {
    height: auto;
    /*
     * The card is itself a grid, and its implicit column is `auto` — sized to
     * the widest thing in it, which no `min-width` on a child can pull back.
     * `minmax(0, 1fr)` caps the track at the card, so the rows inside it wrap
     * instead of running out of the side.
     */
    grid-template-columns: minmax(0, 1fr);
  }

  /*
   * A grid item will not shrink below its own min-content, and the card's is
   * wide: three figure columns and a status pill. Without this the card stayed
   * 383px inside a 191px track and hung out of the board by 46px, which is a
   * clip, not a scroll — the page around it fits.
   */
  .board-card-item,
  .board-card {
    min-width: 0;
  }
}

/* The brand is the Event's name here, at the size the design draws it. */
.all-stalls-page .brand {
  font-size: 24px;
}

/* Lucide "triangle-alert" at the system's 2.75 stroke, as a mask so it takes
 * currentColor from the note and needs no separate asset. */
.board-card-note-mark {
  flex: none;
  width: 15px;
  height: 15px;
  background: currentColor;
  mask: var(--alert-triangle) center / contain no-repeat;
  -webkit-mask: var(--alert-triangle) center / contain no-repeat;
}

.board-card-note-text {
  min-width: 0;
}

.all-stalls-page {
  --close-mark: url("/icons/x.svg");
  --alert-triangle: url("/icons/triangle-alert.svg");
}

/* The role label repeats what the peer pair already says — both its halves are
 * Stall Staff surfaces — and it was the last thing pushing the bar onto a
 * second row at the width the board is drawn for. Stall Queue drops it for the
 * same reason. The rail keeps its `aria-label="Stall Staff"`, so the role is
 * still announced. */
.all-stalls-page .role-nav .role {
  display: none;
}

/* 48x48, as the design draws it — and above the 44px touch floor, which
 * `.btn-icon`'s own 36px default is not. */
#stall-detail-close {
  flex: none;
  width: 48px;
  height: 48px;
  min-height: 48px;
}

/* Lucide "x" at 20px and the system's 2.75 stroke, as a mask so it takes the
 * button's own colour and needs no separate asset. */
.stall-detail-close-mark {
  width: 20px;
  height: 20px;
  background: currentColor;
  mask: var(--close-mark) center / contain no-repeat;
  -webkit-mask: var(--close-mark) center / contain no-repeat;
}

/*
 * The filter glyph, drawn rather than loaded: three lines narrowing to a
 * point, as `Stalls Overview.dc.html` draws beside this control's label. It is
 * the one icon in this bar, and it says "narrow" before the label is read.
 */
.board-filter-glyph {
  flex: none;
  width: 15px;
  height: 11.5px;
  background:
    linear-gradient(currentColor, currentColor) center 0 / 100% 2.5px no-repeat,
    linear-gradient(currentColor, currentColor) center 4.5px / 58% 2.5px
      no-repeat,
    linear-gradient(currentColor, currentColor) center 9px / 24% 2.5px no-repeat;
}
