/* ═══════════ Glass HUD · dockside family ═══════════
   Everything dockside.js, ops-props.js, ops-scene.js and cargo-art.js render:
   #dockside-terminal (hold, shed, manifests, port market, purchasing funds),
   #dockside-supplies (Engineering), the dockside consent sheet, #ops-mini-hold,
   the receipt spike and the Ops work-station switches. Built on the gl-
   primitives in glass.css (rows, buttons, notices, selects, titles); this file
   only lays them out. Spec: design/design_handoff_bridge_glass/README.md.
   Linked by bridge.html after glass-shell.css; nothing here applies outside
   body.glass-bridge. Sections:
     1  shared marks               6  stores (Engineering)
     2  terminal and sections      7  consent sheet and quote
     3  manifests                  8  receipt spike
     4  port market and funds      9  Ops switches and hold strip
     5  disclosures                10 small screens, motion, forced colours */

/* ── 1 · Shared marks ─────────────────────────────────────────────────────
   The retired steel, paper and enamel classes are no longer emitted, so they
   have no rules here. */
:where(body.glass-bridge) :where(.ops-reference) { margin: 4px 0; font: 400 11px/1.4 var(--font-mono); letter-spacing: .04em; color: var(--ink-muted); }
/* A closed control: the disabled button look, with its reason under it. */
body.glass-bridge .ops-closed-shutter {
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  box-sizing: border-box; min-height: 38px; max-width: 100%; padding: 5px 12px;
  border: 1px dashed var(--muted-40); background: transparent; color: var(--ink-muted); text-align: center;
}
body.glass-bridge .ops-closed-shutter > strong { font: 500 13px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: inherit; }
body.glass-bridge .ops-closed-shutter > small { font: 400 11px/1.25 var(--font-ui); letter-spacing: 0; text-transform: none; color: inherit; }
button > .ops-closed-shutter { border: 0; min-height: 0; padding: 0; }
/* A credit figure against its scale (balances, reservations, port funds). */
body.glass-bridge .ops-chit-ledger { min-width: 0; }
body.glass-bridge .ops-chit-ledger > .ops-reference { margin: 4px 0 0; }
body.glass-bridge .ops-credit-bar { display: block; height: 4px; margin: 6px 0 2px; background: var(--ring-track); overflow: hidden; }
body.glass-bridge .ops-credit-bar > i { display: block; height: 100%; background: var(--accent); }
body.glass-bridge .ops-credit-chit { font: 400 13px/1.4 var(--font-mono); color: var(--ink); }
/* One bar style for every native meter the dockside renders. */
body.glass-bridge .dockside-meter {
  -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 4px; margin: 6px 0 2px;
  border: 0; border-radius: 0; background: var(--ring-track);
}
body.glass-bridge .dockside-meter::-webkit-meter-bar { height: 4px; border: 0; border-radius: 0; background: var(--ring-track); }
body.glass-bridge .dockside-meter::-webkit-meter-optimum-value,
body.glass-bridge .dockside-meter::-webkit-meter-suboptimum-value,
body.glass-bridge .dockside-meter::-webkit-meter-even-less-good-value { border-radius: 0; background: var(--accent); }
body.glass-bridge .dockside-meter::-moz-meter-bar { border-radius: 0; background: var(--accent); }
/* Goods thumbnails keep their artwork; the frame is a glass field. */
/* Held to goods.css's own weight, so a room's rule for its thumbnails wins. */
:where(body.glass-bridge) .goods-thumb { background: var(--field); border: 1px solid var(--line); box-shadow: none; }
:where(body.glass-bridge) .goods-chip { gap: 8px; }

/* typography.css (linked after cargo-art.css) still gives the cargo labels the
   retired heading face and the material-era market-row phone layout; the
   glass type and layout are restated here at the weight that wins. */
body.glass-bridge :is(.cargo-state-mark, .cargo-level-mark b, .cargo-stage-mark, .cargo-more-lots) { font: 400 11px/1.3 var(--font-mono); letter-spacing: 0; }
body.glass-bridge .cargo-stage-mark { letter-spacing: .06em; }   /* as the chart's sector label */
body.glass-bridge .cargo-capacity-text strong { font: 500 11px/1 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--accent); }
body.glass-bridge .cargo-placard strong { font: 400 12px/1.3 var(--font-ui); padding-inline: 0; }
body.glass-bridge .cargo-placard b { font: 400 12px/1.3 var(--font-mono); padding-inline: 0; }
body.glass-bridge #dockside-terminal .dockside-market-row { grid-template-rows: none; }
body.glass-bridge #dockside-terminal .dockside-market-row h4 { align-self: auto; padding: 0; }
body.glass-bridge #dockside-terminal .dockside-market-row .market-footer { padding-top: 0; }
body.glass-bridge #dockside-terminal .market-flow { min-width: 0; font: 400 12px/1.45 var(--font-ui); }

/* ── 2 · Terminal and its sections ──────────────────────────────────────── */
body.glass-bridge #dockside-terminal { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* materials.css strips #dockside-terminal to a bare box. Unless the room makes
   it a pane itself (glass-ops.css does) or its detail is one, it is glass. */
body.glass-bridge .gl-detail:not(.gl-pane) #dockside-terminal:not(.gl-pane) {
  padding: var(--pad); background: var(--glass); border: 1px solid var(--line); box-shadow: var(--hairline-top);
  -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
}
body.glass-bridge .dockside-dock { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px 24px; align-items: start; min-width: 0; }
body.glass-bridge .dockside-dock > * { min-width: 0; }
body.glass-bridge .dockside-section { min-width: 0; margin: 0; }
body.glass-bridge .dockside-section > .gl-head { margin: 0 0 8px; }
body.glass-bridge .ops-pending-alert { margin: 0; }
body.glass-bridge .dockside-link-error { margin: 0; }
/* Until the dock readout arrives (bridge.html's markup, which dockside.js
   repeats before the first report): the hold's title over what the terminal
   waits for. With no carrier and no report yet (body[data-link="offline"];
   once a report has come the link reads "stale") the line says the readout
   comes with the ship link. */
body.glass-bridge:not([data-link="offline"]) #dockside-terminal .dockside-waiting > [data-wait="offline"],
body.glass-bridge[data-link="offline"] #dockside-terminal .dockside-waiting > [data-wait="loading"] { display: none; }
body.glass-bridge .dockside-link-error > h3.gl-notice-title { margin: 4px 0 0; }
@media (min-width: 1280px) {
  body.glass-bridge .dockside-dock.is-docked { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  body.glass-bridge .dockside-dock.is-docked > .dockside-bay { grid-column: 1; grid-row: 1; }
  body.glass-bridge .dockside-dock.is-docked > .dockside-shed { grid-column: 2; grid-row: 1; }
  body.glass-bridge .dockside-dock.is-docked > .dockside-ship-manifest { grid-column: 1; grid-row: 2; }
  body.glass-bridge .dockside-dock.is-docked > .dockside-storage { grid-column: 2; grid-row: 2; }
  body.glass-bridge #dockside-terminal .dockside-dock .cargo-stage { height: 240px; max-height: 240px; }
}

/* ── 3 · Manifests: one row per good, the README row rhythm ─────────────── */
body.glass-bridge .dockside-manifest { display: flex; flex-direction: column; min-width: 0; container: manifest / inline-size; }
body.glass-bridge .dockside-manifest-row {
  position: relative; display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 4px 12px;
  min-width: 0; margin: 0; padding: var(--row-pad) 0; border-bottom: 1px solid var(--line-soft);
}
body.glass-bridge .dockside-goods-row { min-width: 0; }
body.glass-bridge .dockside-good-name { display: block; font: 400 13px/1.4 var(--font-ui); color: var(--ink); overflow-wrap: break-word; }
body.glass-bridge .dockside-good-figures { margin: 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); font-variant-numeric: tabular-nums; }
body.glass-bridge .manifest-ink { height: 3px; max-width: 240px; margin-top: 4px; background: var(--ring-track); opacity: 1; mix-blend-mode: normal; }
body.glass-bridge .manifest-ink > span { display: block; width: var(--quantity); height: 100%; background: var(--accent); border: 0; transform: none; }
body.glass-bridge .dockside-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
body.glass-bridge .dockside-manifest-row > .dockside-actions { justify-content: flex-end; }
body.glass-bridge .ops-manifest-verdict {
  display: block; max-width: 16ch; font: 400 11px/1.3 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); text-align: right;
}
body.glass-bridge .ops-manifest-verdict > small { display: block; font: 400 11px/1.3 var(--font-ui); letter-spacing: 0; text-transform: none; }
body.glass-bridge .dockside-empty { padding: var(--row-pad) 0; border-bottom: 1px solid var(--line-soft); }
@container manifest (max-width: 30rem) {
  body.glass-bridge .dockside-manifest-row:has(> .dockside-actions) { grid-template-columns: 40px minmax(0, 1fr); }
  body.glass-bridge .dockside-manifest-row > .dockside-actions { grid-column: 2; justify-content: flex-start; }
  body.glass-bridge .ops-manifest-verdict { text-align: left; }
}

/* ── 4 · Port market and purchasing funds ───────────────────────────────── */
body.glass-bridge .ops-market-work { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
body.glass-bridge .ops-market-work > .gl-head { margin: 0; flex-wrap: wrap; }
body.glass-bridge .ops-stock-reading { margin: 0; color: var(--ink-muted); letter-spacing: 0; text-transform: none; }
body.glass-bridge .ops-class-placards { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0; }
body.glass-bridge .ops-class-placards:empty { display: none; }
body.glass-bridge .ops-class-placard { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
body.glass-bridge .ops-class-placard > span { font: 400 11px/1.3 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
body.glass-bridge .ops-class-placard > span::before { content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 6px; vertical-align: 0; border-radius: 50%; background: var(--paint-dot, var(--ink-muted)); }
body.glass-bridge .ops-class-placard[data-category="mineral"] { --paint-dot: #ad833e; }
body.glass-bridge .ops-class-placard[data-category="renewable"] { --paint-dot: #688985; }
body.glass-bridge .ops-cash, body.glass-bridge .dockside-industry-reserve { min-width: 0; max-width: 560px; margin: 0; }
body.glass-bridge .ops-cash > .gl-head, body.glass-bridge .dockside-industry-reserve > .gl-head { margin: 0 0 4px; flex-wrap: wrap; }
body.glass-bridge .ops-cash .gl-k > .gl-dot { margin: -2px 8px 0 0; }
body.glass-bridge .ops-cash-total { color: var(--ink); }
body.glass-bridge .dockside-market { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 24px; min-width: 0; }
/* A market row: specimen | name and stock | price | BUY (or why not). */
body.glass-bridge .dockside-market-row {
  display: grid; grid-template-columns: 72px minmax(0, 1fr) auto auto; align-items: center; gap: 6px 14px;
  min-width: 0; margin: 0; padding: 10px 0; border: 0; border-bottom: 1px solid var(--line-soft); background: none; box-shadow: none;
}
body.glass-bridge .dockside-market-row .market-art { grid-column: 1; grid-row: 1 / span 2; align-self: start; width: 72px; height: 72px; }
body.glass-bridge .dockside-market-row .market-art .goods-plate { width: 100%; height: 100%; margin: 0; }
body.glass-bridge .dockside-market-row .market-info { grid-column: 2; grid-row: 1; min-width: 0; }
body.glass-bridge .dockside-market-row h4 { margin: 0; font: 600 16px/1.2 var(--font-head); letter-spacing: 0; text-transform: none; color: var(--ink); overflow-wrap: normal; }
body.glass-bridge .dockside-market-row .market-figures { margin: 4px 0 0; font: 400 12px/1.4 var(--font-mono); letter-spacing: 0; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
body.glass-bridge .dockside-market-row .market-number { color: var(--ink); }
body.glass-bridge .dockside-market-row .market-footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
body.glass-bridge .dockside-market-row .market-footer:empty { display: none; }
body.glass-bridge .dockside-flag {
  display: inline-block; padding: 3px 6px; border: 1px solid var(--bad); background: var(--bad-08);
  font: 400 10px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--bad);
}
body.glass-bridge .dockside-market-row .market-controls { display: contents; }
body.glass-bridge .dockside-market-row .price-window {
  grid-column: 3; grid-row: 1; display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
  min-width: 0; margin: 0; padding: 0; border: 0; background: none; color: var(--ink); white-space: nowrap;
}
body.glass-bridge .dockside-market-row .price-window > strong { font: 400 20px/1 var(--font-mono); letter-spacing: 0; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }
body.glass-bridge .dockside-market-row .market-price-caption { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
body.glass-bridge .dockside-market-row .market-price-caption > small { font: 400 11px/1.2 var(--font-mono); color: var(--ink-muted); white-space: nowrap; }
body.glass-bridge .dockside-market-row .market-controls > :is(.dockside-buy, .ops-closed-shutter) { grid-column: 4; grid-row: 1; justify-self: end; min-width: 9ch; }
body.glass-bridge .dockside-buy small { margin-left: 6px; font: 400 11px/1 var(--font-ui); letter-spacing: 0; text-transform: none; }
/* The colony flow opens under the row, across the name, price and BUY. */
body.glass-bridge .market-flow { position: static; min-width: 0; }
body.glass-bridge .market-flow > p { margin: 6px 0 0; font: 400 12px/1.45 var(--font-ui); color: var(--ink-muted); white-space: normal; }
body.glass-bridge .dockside-market-row:has(.market-flow[open]) .price-window { grid-column: 2 / -1; grid-row: 2; align-items: flex-start; white-space: normal; }
body.glass-bridge .dockside-market-row:has(.market-flow[open]) .price-window > strong { text-align: left; }
body.glass-bridge .dockside-market-row:has(.market-flow[open]) .market-price-caption { align-items: stretch; }
@media (min-width: 1280px) {
  body.glass-bridge .dockside-market { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── 5 · Disclosures: one accent caps summary with a ▸ / ▾ mark ─────────── */
body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing) > summary {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; min-height: 28px; margin: 0; padding: 0;
  list-style: none; cursor: pointer; text-decoration: none;
  font: 500 11px/1.2 var(--font-ui); letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
}
body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing) > summary::-webkit-details-marker { display: none; }
body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing) > summary::before {
  content: "\25B8"; flex: none; width: 10px; font: 400 11px/1 IPTType3UI, sans-serif; color: inherit;
}
body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing)[open] > summary::before { content: "\25BE"; }
body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing) > summary:hover { color: var(--ink-title); }
body.glass-bridge .dockside-storage > summary { margin-bottom: 8px; }
body.glass-bridge .dockside-storage > summary > .gl-title { color: inherit; }
body.glass-bridge .dockside-storage > summary > .gl-meta { letter-spacing: 0; text-transform: none; }
body.glass-bridge .market-flow > summary { min-height: 20px; letter-spacing: .1em; }
body.glass-bridge :is(.ops-cash-details, .ops-band-details, .ops-quote-context) { margin-top: 8px; }
body.glass-bridge :is(.ops-cash-details, .ops-quote-context) > p { margin: 6px 0 0; font: 400 12px/1.45 var(--font-ui); color: var(--ink-muted); }

/* ── 6 · Stores (#dockside-supplies, Engineering) ───────────────────────── */
body.glass-bridge #dockside-supplies > .gl-head { margin: 0 0 6px; }
body.glass-bridge #dockside-supplies > .dockside-recovery { margin-bottom: 12px; }
body.glass-bridge .dockside-supply-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16em), 1fr)); gap: 12px 24px; min-width: 0; }
body.glass-bridge .dockside-supply { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
body.glass-bridge .dockside-supply > .gl-row { align-self: stretch; }
body.glass-bridge .dockside-supply > .gl-btn { margin-top: auto; }

/* ── 7 · Consent sheet and quote ────────────────────────────────────────── */
body.glass-bridge .dockside-sheet {
  width: min(880px, 100%); max-width: 880px; max-height: calc(100dvh - 40px); overflow-y: auto; overscroll-behavior: contain;
  color: var(--ink); color-scheme: dark;
}
/* The sheet is the gl-modal flex column and it scrolls: its sections keep
   their height rather than shrinking under content that would then run
   beneath the sticky foot (the receiver gives #dockside-confirmation a
   min-height on phones, which would otherwise let it shrink to that). */
body.glass-bridge .dockside-sheet > * { flex-shrink: 0; }
body.glass-bridge .dockside-good-heading { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px; align-items: center; margin: 0 0 14px; }
body.glass-bridge #dockside-plate { width: 64px; height: 64px; }
body.glass-bridge #dockside-plate .goods-thumb { --goods-thumb-size: 64px; width: 64px; height: 64px; }
body.glass-bridge .dockside-kicker { margin: 0 0 8px; }
body.glass-bridge #dockside-title { margin: 0; overflow-wrap: anywhere; }
body.glass-bridge #dockside-place { margin: 4px 0 0; font: 400 11px/1.4 var(--font-mono); letter-spacing: 0; text-transform: none; color: var(--ink-muted); }
body.glass-bridge .dockside-sheet label { display: block; margin: 12px 0 6px; font: 500 11px/1 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--ink-muted); }
body.glass-bridge .dockside-quantity-label { display: flex !important; justify-content: space-between; align-items: baseline; gap: 12px; }
body.glass-bridge #dockside-quantity-label { display: inline-flex; align-items: center; gap: 6px; font: 400 13px/1 var(--font-mono); letter-spacing: 0; text-transform: none; color: var(--ink); }
body.glass-bridge #dockside-quantity { display: block; width: 100%; height: 20px; margin: 4px 0; padding: 0; border: 0; background: none; accent-color: var(--accent); }
body.glass-bridge .dockside-quantity-stepper { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
body.glass-bridge .dockside-quantity-stepper > .gl-input { flex: 1; width: auto; min-width: 0; height: 38px; text-align: center; }
body.glass-bridge .dockside-snaps { display: flex; flex-wrap: wrap; gap: 6px; }
body.glass-bridge .dockside-keep-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
body.glass-bridge .dockside-keep-row > label { margin: 0 auto 0 0; }
body.glass-bridge .dockside-keep-row > .gl-input { width: 72px; height: 28px; padding: 0 8px; text-align: center; }
body.glass-bridge .dockside-selects > .gl-select { display: flex; }
body.glass-bridge .dockside-selects > .gl-select > select { width: calc(100% + 2px); height: calc(100% + 2px); }
body.glass-bridge #dockside-confirmation { margin-top: 12px; min-width: 0; }
body.glass-bridge .dockside-review-note { margin: 0; font: 400 13px/1.45 var(--font-ui); color: var(--ink); }
body.glass-bridge .dockside-warning { margin: 10px 0 0; padding: 0 0 0 10px; border-left: 2px solid var(--bad); font: 400 13px/1.4 var(--font-ui); color: var(--ink); }
body.glass-bridge #dockside-error { margin: 10px 0 0; font: 400 13px/1.4 var(--font-ui); color: var(--bad); }
body.glass-bridge #dockside-error:empty { display: none; }
/* Destination picker (buy): a radio group of two tiles, each with its
   stowage; the chosen tile takes the selected-tab look (accent edge, 12% tint). */
body.glass-bridge .dockside-destinations { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
body.glass-bridge .dockside-destinations > * { min-width: 0; }
body.glass-bridge .dockside-sheet label.dockside-destination {
  position: relative; box-sizing: border-box; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; align-content: start; gap: 8px;
  width: 100%; min-width: 0; margin: 0; padding: 10px; cursor: pointer;
  font: 400 13px/1.3 var(--font-ui); letter-spacing: 0; text-transform: none; color: var(--ink);
  background: transparent; border: 1px solid var(--line); border-left: 2px solid transparent; border-radius: 0;
}
body.glass-bridge .dockside-sheet label.dockside-destination:hover { background: rgba(255,255,255,.04); }
body.glass-bridge .dockside-sheet label.dockside-destination:has(> input:checked) { background: var(--accent-12); border-color: var(--accent-60); border-left-color: var(--accent); }
/* The radio covers its whole tile (the tap target), drawn as nothing; its own
   focus ring therefore outlines the tile. The tile's dot shows the choice. */
body.glass-bridge .dockside-destination > input {
  -webkit-appearance: none; appearance: none; position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; cursor: pointer;
}
body.glass-bridge .dockside-sheet label.dockside-destination::before {
  content: ""; box-sizing: border-box; width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--accent-60);
}
body.glass-bridge .dockside-sheet label.dockside-destination:has(> input:checked)::before { border-color: var(--accent); background: var(--accent); box-shadow: 0 0 8px var(--accent); }
body.glass-bridge .dockside-destination > .cargo-stack { grid-column: 1 / -1; pointer-events: none; }
body.glass-bridge .dockside-destination-name { min-width: 0; font: 500 11px/1.2 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--accent); }
body.glass-bridge .dockside-selection { font: 400 11px/1 var(--font-mono); letter-spacing: 0; text-transform: none; color: var(--ink-muted); text-align: right; }
body.glass-bridge .dockside-destination:has(> input:checked) .dockside-selection { color: var(--ink); }
/* The planned movement and the reviewed quote. */
body.glass-bridge .dockside-plan { margin-top: 12px; min-width: 0; }
body.glass-bridge .dockside-plan > .gl-head { margin: 0 0 8px; flex-wrap: wrap; }
body.glass-bridge .dockside-plan-pair { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
body.glass-bridge .dockside-plan-pair > * { min-width: 0; }
body.glass-bridge .dockside-plan-supply { display: block; margin: 10px 0 0 !important; letter-spacing: 0 !important; text-transform: none !important; }
body.glass-bridge .dockside-plan-supply > .gl-row { display: flex; }
body.glass-bridge .dockside-summary {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 6px 16px;
  padding: 0 0 10px; border-bottom: 1px solid var(--line);
}
body.glass-bridge .dockside-summary > strong { font: 600 16px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge .dockside-summary > span { font: 400 20px/1 var(--font-mono); color: var(--ink); white-space: nowrap; }
body.glass-bridge .dockside-summary .goods-chip, body.glass-bridge .dockside-summary .goods-chip span { font: inherit; color: inherit; white-space: normal; }
body.glass-bridge .ops-docket-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 24px; margin-top: 12px; align-items: start; }
body.glass-bridge :is(.ops-docket-load, .ops-docket-settlement) { min-width: 0; }
body.glass-bridge .ops-docket-load .dockside-plan { margin: 0; }
body.glass-bridge .ops-docket-settlement > .gl-head { margin: 0 0 4px; flex-wrap: wrap; }
body.glass-bridge .ops-settlement-math { margin: 0; }
body.glass-bridge .ops-settlement-math > .gl-row > :is(dt, dd) { margin: 0; }
body.glass-bridge .ops-balance-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 12px; }
body.glass-bridge .ops-payment-delta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; margin: 14px 0 0; }
body.glass-bridge .ops-payment-delta > b { font: 400 20px/1 var(--font-mono); font-weight: 400; color: var(--ink); }
body.glass-bridge .ops-payment-delta > span { font: 400 11px/1 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
body.glass-bridge .ops-depth { margin: 14px 0 0; min-width: 0; }
body.glass-bridge .ops-depth > figcaption { margin: 0 0 4px; flex-wrap: wrap; }
body.glass-bridge .dockside-bands { max-height: 210px; overflow: auto; margin-top: 8px; }
body.glass-bridge .dockside-bands table { width: 100%; }
/* Close and Review (Back and Confirm) stay in view at every width: the foot is
   sticky and opaque while the consent body scrolls under it, and it spans the
   sheet's side padding so nothing shows beside it. The sheet's own bottom
   padding moves into the foot. */
body.glass-bridge .dockside-sheet { padding-bottom: 0; }
body.glass-bridge .dockside-sheet .foot {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 10px;
  margin: 16px -18px 0; padding: 12px 18px max(18px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line-soft);
  background: linear-gradient(var(--glass), var(--glass)), var(--bg);
}
body.glass-bridge .ops-quote-seal { display: flex; align-items: center; gap: 10px; margin-right: auto; max-width: 100%; }
body.glass-bridge .ops-quote-seal p { max-width: 34ch; margin: 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }
/* The binding window as an instrument ring: --timer-angle of the minute. */
body.glass-bridge .ops-mechanical-timer {
  position: relative; display: block; flex: none; width: 40px; height: 40px; border-radius: 50%;
  background: conic-gradient(var(--accent) 0 var(--timer-angle, 0deg), var(--ring-track) var(--timer-angle, 0deg) 360deg);
  box-shadow: 0 0 14px var(--accent-20);
}
body.glass-bridge .ops-timer-disc { position: absolute; inset: 4px; border-radius: 50%; background: var(--bg); }
/* An unresolved response: the red notice with its recovery actions. */
body.glass-bridge .dockside-recovery { margin: 0 0 12px; }
body.glass-bridge .dockside-recovery-title { display: flex; align-items: center; gap: 10px; }
body.glass-bridge .dockside-recovery .dockside-actions { margin-top: 2px; }
body.glass-bridge .dockside-recovery .dockside-actions .gl-btn { margin-top: 8px; }

/* ── 8 · Receipt spike ──────────────────────────────────────────────────── */
body.glass-bridge #ops-receipt-spike { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
body.glass-bridge #ops-receipt-spike > .gl-head { margin: 0; flex-wrap: wrap; }
body.glass-bridge .ops-receipts-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
body.glass-bridge .ops-receipt-stack { min-width: 0; }
body.glass-bridge .ops-slip-backings { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 6px; }
body.glass-bridge .ops-slip-backing { padding: 3px 6px; border: 1px solid var(--line-soft); font: 400 10px/1 var(--font-mono); letter-spacing: .08em; color: var(--ink-muted); }
body.glass-bridge .ops-slip-front { margin: 0; }
body.glass-bridge .ops-slip-front > .ops-reference { margin: 0; font: 400 10px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--tone, var(--accent)); }
body.glass-bridge .ops-slip-front > p:not(.ops-reference) { margin: 2px 0 0; font: 400 13px/1.4 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge .ops-slip-title { margin: 4px 0 0; font: 600 16px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge .ops-receipt-identity { display: flex; align-items: center; gap: 10px; min-width: 0; margin-top: 4px; }
body.glass-bridge .ops-receipt-identity > strong { min-width: 0; font: 600 16px/1.2 var(--font-head); color: var(--ink); overflow-wrap: break-word; }
body.glass-bridge .ops-receipt-id { font: 400 11px/1.4 var(--font-mono) !important; color: var(--ink-muted); overflow-wrap: normal; word-break: normal; }
body.glass-bridge .ops-receipt-ledger { min-width: 0; }
body.glass-bridge .ops-receipt-ledger article { padding: var(--row-pad) 0; border-bottom: 1px solid var(--line-soft); }
body.glass-bridge .ops-receipt-ledger article > p { margin: 2px 0 0; font: 400 12px/1.4 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge .ops-receipt-ledger article > .ops-reference { font: 400 11px/1.4 var(--font-mono); }
body.glass-bridge .ops-receipt-ledger .ops-receipt-identity > strong { font: 400 13px/1.4 var(--font-ui); }
body.glass-bridge .ops-receipt-ledger .goods-thumb { --goods-thumb-size: 28px; width: 28px; height: 28px; }
body.glass-bridge .ops-slip-jammed .dockside-recovery { margin: 0; }
@media (min-width: 1024px) {
  body.glass-bridge .ops-receipts-layout { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── 9 · Ops work-station switches and the hold strip ───────────────────── */
/* ops-props.js drives the switches: below 1280 px one station (Hold, Dock,
   Exchange, Papers) at a time via data-ops-pane, at 1280 px and wider the desk
   (Exchange, Prices, Paperwork) via data-ops-desk. glass-ops.css places the
   switches and the exchange and paperwork panes; this file splits the
   terminal's own Hold and Dock stations. A switch button still carrying no
   gl-btn class reads as the README's segmented control. */
body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn) {
  -webkit-appearance: none; appearance: none; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 28px; margin: 0; padding: 0 10px;
  font: 500 12px/1 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
  border-radius: 0; box-shadow: none; filter: none; cursor: pointer;
  background: transparent; color: var(--accent); border: 1px solid var(--accent-60);
}
body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn):hover { background: var(--accent-10); border-color: var(--accent); }
body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn):is([aria-selected="true"], [aria-pressed="true"]) { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
body.glass-bridge #ops-mini-hold { display: none; }
/* The hold strip: ship, tonnage, an accent bar and the free tonnage. */
body.glass-bridge #ops-mini-hold {
  align-items: center; flex-wrap: wrap; gap: 6px 12px; min-height: 44px; box-sizing: border-box; margin: 0; padding: 6px 12px;
  background: var(--glass); -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--line); box-shadow: var(--hairline-top); color: var(--ink);
  font: 400 12px/1.3 var(--font-mono); font-variant-numeric: tabular-nums;
}
body.glass-bridge .ops-mini-label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0; }
body.glass-bridge .ops-mini-label > b { font: 500 11px/1 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--accent); }
body.glass-bridge .ops-hold-punch { flex: 1 1 60px; min-width: 40px; height: 4px; background: var(--ring-track); border: 0; }
body.glass-bridge .ops-hold-punch > span { display: block; height: 100%; background: var(--accent); }
body.glass-bridge .ops-mini-free { color: var(--ink-muted); }
@media (max-width: 1279px) {
  body.glass-bridge #ops-mini-hold { display: flex; }
  body.glass-bridge #panel-ops:not([data-ops-pane="hold"]) :is(.dockside-bay, .dockside-ship-manifest, .dockside-location),
  body.glass-bridge #panel-ops:not([data-ops-pane="dock"]) :is(.dockside-shed, .dockside-storage, .ops-market-work) { display: none; }
  /* The waiting state belongs to both stations; Dock shows its line without
     the hold's title, as it does while a known ship's readout is received. */
  body.glass-bridge #panel-ops[data-ops-pane="dock"] .dockside-waiting > .gl-head { display: none; }
}

/* ── 10 · Small screens, touch, motion and forced colours ───────────────── */
@media (max-width: 760px), (max-width: 1279px) and (max-height: 500px) and (pointer: coarse) {
  body.glass-bridge .dockside-market-row { grid-template-columns: 64px minmax(0, 1fr); gap: 6px 12px; }
  body.glass-bridge .dockside-market-row .market-art { width: 64px; height: 64px; }
  body.glass-bridge .dockside-market-row .price-window { grid-column: 2; grid-row: 2; align-items: flex-start; }
  body.glass-bridge .dockside-market-row .price-window > strong { text-align: left; }
  body.glass-bridge .dockside-market-row .market-price-caption { align-items: flex-start; }
  body.glass-bridge .dockside-market-row .market-controls > :is(.dockside-buy, .ops-closed-shutter) { grid-column: 1 / -1; grid-row: 3; justify-self: stretch; }
  body.glass-bridge .dockside-market-row:has(.market-flow[open]) .price-window { grid-column: 2; grid-row: 2; }
  body.glass-bridge .dockside-market-row .market-unit-weight { display: none; }
  body.glass-bridge .dockside-manifest-row:has(> .dockside-actions) { grid-template-columns: 40px minmax(0, 1fr); }
  body.glass-bridge .dockside-manifest-row > .dockside-actions { grid-column: 1 / -1; justify-content: flex-start; }
  body.glass-bridge .dockside-manifest-row > .dockside-actions > .gl-btn { flex: 1 1 8ch; }
  body.glass-bridge .ops-manifest-verdict { text-align: left; }
  body.glass-bridge .ops-docket-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  body.glass-bridge .ops-balance-pair { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  body.glass-bridge .dockside-good-heading { grid-template-columns: 48px minmax(0, 1fr); gap: 10px; margin-bottom: 8px; }
  body.glass-bridge #dockside-plate, body.glass-bridge #dockside-plate .goods-thumb { --goods-thumb-size: 48px; width: 48px; height: 48px; }
  /* The sticky foot (section 7) is tighter here; its buttons share the row. */
  body.glass-bridge .dockside-sheet .foot { margin-top: 12px; padding-top: 10px; padding-bottom: max(16px, env(safe-area-inset-bottom)); }
  body.glass-bridge .dockside-sheet .foot > button { flex: 1 1 auto; }
  body.glass-bridge .ops-quote-seal { flex: 1 1 100%; gap: 8px; }
  body.glass-bridge .ops-quote-seal p { max-width: none; font-size: 11px; }
  body.glass-bridge .ops-mechanical-timer { width: 28px; height: 28px; }
  body.glass-bridge .ops-timer-disc { inset: 3px; }
  body.glass-bridge .dockside-bands { max-height: 180px; }
}
@media (max-width: 640px), (pointer: coarse) {
  body.glass-bridge :is(.dockside-storage, .market-flow, .ops-cash-details, .ops-band-details, .ops-quote-context, .ops-receipt-ledger details, .ops-backing) > summary { min-height: 44px; }
  body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn) { height: auto; min-height: 44px; }
  body.glass-bridge .dockside-keep-row > .gl-input, body.glass-bridge .dockside-quantity-stepper > .gl-input { height: 44px; }
  body.glass-bridge #dockside-quantity { height: 44px; }
}
@media (max-width: 640px) {
  /* The bottom sheet of the gl-modal primitive (phone.css pads every legacy
     .modal-scrim by 12px on phones, which would lift the sheet off the edge). */
  body.glass-bridge #dockside-modal.gl-modal-scrim { padding: 0; }
  body.glass-bridge .dockside-sheet { max-height: 92dvh; }
}
@media (forced-colors: active) {
  body.glass-bridge :is(.ops-credit-bar, .ops-hold-punch, .manifest-ink, .dockside-meter) { forced-color-adjust: none; background: GrayText; }
  body.glass-bridge :is(.ops-credit-bar, .ops-hold-punch, .manifest-ink) > :is(i, span) { forced-color-adjust: none; background: CanvasText; }
  body.glass-bridge .ops-mechanical-timer { forced-color-adjust: none; background: conic-gradient(CanvasText 0 var(--timer-angle, 0deg), GrayText var(--timer-angle, 0deg) 360deg); box-shadow: none; }
  body.glass-bridge .ops-timer-disc { background: Canvas; }
  body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn) { forced-color-adjust: none; background: ButtonFace; color: ButtonText; border-color: ButtonText; }
  body.glass-bridge :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > button:not(.gl-btn):is([aria-selected="true"], [aria-pressed="true"]) { background: ButtonText; color: ButtonFace; }
  body.glass-bridge .dockside-sheet label.dockside-destination { border-color: CanvasText; }
  body.glass-bridge .dockside-sheet label.dockside-destination::before { forced-color-adjust: none; border-color: CanvasText; box-shadow: none; }
  body.glass-bridge .dockside-sheet label.dockside-destination:has(> input:checked)::before { background: CanvasText; }
  body.glass-bridge .ops-closed-shutter { border-color: GrayText; color: GrayText; }
  body.glass-bridge .dockside-sheet .foot { background: Canvas; border-color: GrayText; }
  body.glass-bridge .dockside-flag, body.glass-bridge .dockside-warning { border-color: CanvasText; color: CanvasText; }
}
