/* Ops on glass: the three summary panes (README "Ops") and the room's
   detail below the fold: exchange, order book, observed prices, paperwork,
   holdings, cargo agreements and the order ticket. The dockside terminal's
   internals, the mini hold strip and the receipt spike belong to
   glass-dockside.css; this file only places their containers.
   Every rule is scoped to body.glass-bridge, so other pages never see it. */

/* ── Summary panes: the primitives do the work; only page-level resets here ── */
body.glass-bridge #ops-pane-a > .gl-row > .gl-k { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.glass-bridge #ops-pane-b > .gl-notice > .gl-btn { white-space: normal; }
body.glass-bridge #ops-pane-c .gl-table-row > :first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.glass-bridge #ops-pane-c .gl-table-empty { margin: 0; }
/* A bid above the captain's cost: a glyph in the cell's tone, not colour alone. */
body.glass-bridge #ops-pane-c .ops-above { margin-right: 5px; font-size: 9px; vertical-align: 1px; }

/* ── Detail: a stack of glass panes below the fold ──────────────────────── */
body.glass-bridge #ops-detail { display: flex; flex-direction: column; align-items: stretch; gap: var(--gap); padding: 0; }
body.glass-bridge #panel-ops .ops-runtime-layout { display: flex; flex-direction: column; align-items: stretch; gap: var(--gap); min-width: 0; padding: 0; }
body.glass-bridge #panel-ops .ops-runtime-layout > * { min-width: 0; margin: 0; }
/* materials.css strips #dockside-terminal to a bare box; on the glass bridge
   the container is a pane like every other detail section. */
body.glass-bridge #panel-ops #dockside-terminal.gl-pane {
  margin: 0; padding: var(--pad); border: 1px solid var(--line); border-radius: 0; box-shadow: var(--hairline-top);
  background: var(--glass); -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
}
body.glass-bridge #panel-ops :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) { gap: 6px; margin: 0; padding: 6px; }
/* Equal segments: each button takes the same share whatever its label. */
body.glass-bridge #panel-ops :is(.ops-switch, .ops-desk-switch, .ops-paperwork-rail) > .gl-btn { flex: 1 1 0; width: auto; min-width: 0; font-size: 12px; }
body.glass-bridge #panel-ops .ops-switch { display: none; }
body.glass-bridge #panel-ops .ops-desk-switch { display: flex; }
body.glass-bridge #panel-ops .ops-paperwork-rail { display: flex; }
body.glass-bridge #panel-ops #ops-exchange-zone,
body.glass-bridge #panel-ops #ops-paperwork,
body.glass-bridge #panel-ops .ops-private-ledgers { display: flex; flex-direction: column; align-items: stretch; gap: var(--gap); min-width: 0; margin: 0; }
body.glass-bridge #panel-ops :is(#ops-exchange-zone, #ops-paperwork) > *,
body.glass-bridge #panel-ops .ops-private-ledgers > * { margin: 0; min-width: 0; }

/* Desk selection on wide screens (ops-props.js sets data-ops-desk). Until the
   Ops instruments load the panel carries no desk: the desk bridge.html
   presses, Exchange tickets, shows with its waiting text. */
@media (min-width: 1280px) and (min-height: 501px) {
  body.glass-bridge #panel-ops:not([data-ops-desk="paperwork"]) #ops-paperwork,
  body.glass-bridge #panel-ops[data-ops-desk="paperwork"] #ops-exchange-zone,
  body.glass-bridge #panel-ops[data-ops-desk]:not([data-ops-desk="exchange"]) .ops-orderbook,
  body.glass-bridge #panel-ops:not([data-ops-desk="prices"]) #ops-price-panel { display: none; }
  /* Paperwork: receipts and the private ledgers side by side, agreements below. */
  body.glass-bridge #panel-ops #ops-paperwork { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
  body.glass-bridge #panel-ops:not([data-ops-desk="paperwork"]) #ops-paperwork { display: none; }
  body.glass-bridge #panel-ops #ops-paperwork > :is(.ops-paperwork-rail, #cargo-agreements) { grid-column: 1 / -1; }
}
@media (max-width: 1279px), (max-height: 500px) {
  body.glass-bridge #panel-ops .ops-desk-switch { display: none; }
}
/* One work station at a time below 1280 px (ops-props.js sets data-ops-pane). */
@media (max-width: 1279px) {
  body.glass-bridge #panel-ops .ops-switch { display: flex; }
  body.glass-bridge #panel-ops:not([data-ops-pane="exchange"]) #ops-exchange-zone,
  body.glass-bridge #panel-ops:not([data-ops-pane="papers"]) #ops-paperwork,
  body.glass-bridge #panel-ops:is([data-ops-pane="exchange"], [data-ops-pane="papers"]) #dockside-terminal { display: none; }
}

/* Shared detail type: titles, notes, references and money lines. Scoped to
   the sections this room renders; the dockside terminal and the receipt
   spike style their own insides. */
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements) .gl-head { margin-bottom: 10px; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements) :is(h3, h4, p):not(.gl-title, .gl-notice-tag, .ops-reference) { letter-spacing: 0; text-transform: none; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements) .gl-title { margin: 0; font: 500 11px/1 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--accent); }
body.glass-bridge #ops-detail #ops-exchange,
body.glass-bridge #ops-detail #ops-legend { color: inherit; }
body.glass-bridge #ops-detail #ops-exchange { color: var(--accent); }
body.glass-bridge #ops-detail #ops-legend { color: var(--ink-muted); }
/* Before the first report each waiting line in bridge.html (the mini hold
   strip, the exchange meta, New order's reason, the order table, the Trade
   Routes view, observed prices, my orders, the holdings ledger, the receipt
   spike, the cargo agreements board) holds two wordings. With no carrier and
   no report yet (body[data-link="offline"]; once a report has come the link
   reads "stale") it says what arrives with the ship link, as the terminal
   does (glass-dockside.css); otherwise it is receiving. The Ops scripts
   (ops.js, ops-props.js for the strip and the spike, cargo-agreements.js)
   replace both with readings; journey-ui.js rewrites the Trade Routes view
   (the same pair, then the estimates). */
body.glass-bridge:not([data-link="offline"]) :is(#ops-mini-hold, #ops-legend, #ops-post-reason, #ops-orders, #tab-routes, #ops-prices, #ops-my-orders, #ops-cargo, #ops-receipt-spike, #cargo-agreements) [data-wait="offline"],
body.glass-bridge[data-link="offline"] :is(#ops-mini-hold, #ops-legend, #ops-post-reason, #ops-orders, #tab-routes, #ops-prices, #ops-my-orders, #ops-cargo, #ops-receipt-spike, #cargo-agreements) [data-wait="loading"] { display: none; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) .ops-note { margin: 0; padding: var(--row-pad) 0; font: 400 13px/1.45 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) .ops-reference { margin: 0 0 6px; font: 400 11px/1.4 var(--font-mono); letter-spacing: .04em; color: var(--ink-muted); }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) .ops-escrow {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin: 6px 0 0; padding: var(--row-pad) 0;
  border-top: 1px solid var(--line-soft); font: 400 13px/1.4 var(--font-ui); color: var(--ink-muted);
}
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) .ops-escrow > strong { font: 400 13px/1.4 var(--font-mono); color: var(--ink); text-align: right; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 28px; cursor: pointer;
  padding: 4px 0; list-style: none; text-decoration: none; font: 500 12px/1.2 var(--font-ui); letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
}
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details > summary::-webkit-details-marker { display: none; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details > summary::after { content: "\25BC"; flex: none; font: 400 10px/1 IPTType3UI, sans-serif; color: var(--ink-muted); }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details[open] > summary::after { content: "\25B2"; }
/* A ticket's reserved-credit fold is a small inline fold with its own ▸
   marker (glass-dockside.css); it takes no second glyph at the right. */
body.glass-bridge #panel-ops details.ops-backing > summary { justify-content: flex-start; }
body.glass-bridge #panel-ops details.ops-backing > summary::after,
body.glass-bridge #panel-ops details.ops-backing[open] > summary::after { content: none; }
body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details > p { margin: 6px 0; font: 400 13px/1.45 var(--font-ui); color: var(--ink-muted); }

/* ── Exchange: order book, rail of tickets, accessible table ─────────────── */
body.glass-bridge #panel-ops #ops-exchange-zone .tabs { margin: 0 0 10px; }
body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab {
  min-height: 28px; padding: 2px 10px; font: 500 12px/1.15 var(--font-ui); letter-spacing: .08em; text-transform: uppercase;
  background: transparent; color: var(--accent); border: 1px solid var(--accent-60);
}
body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab:hover { background: var(--accent-10); border-color: var(--accent); }
body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab.active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
body.glass-bridge #panel-ops #ops-order-rail { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); gap: 12px 16px; min-width: 0; }
/* A note in the rail (receiving, empty book, failed read) reads across it. */
body.glass-bridge #panel-ops #ops-order-rail > :is(.ops-note, .ops-retry-note) { grid-column: 1 / -1; }
/* A failed read: the note, then its Retry (ops.js retryNote). */
body.glass-bridge #panel-ops .ops-retry-note { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; min-width: 0; margin: 0 0 6px; }
body.glass-bridge #panel-ops .ops-retry-note > .ops-note { flex: 0 1 auto; min-width: 0; }
body.glass-bridge #panel-ops .ops-ticket-group { min-width: 0; margin: 0; padding: 0; border: 0; background: none; }
body.glass-bridge #panel-ops #ops-order-rail .ops-ticket-group > summary.ops-group-head {
  display: flex; align-items: center; justify-content: flex-start; gap: 10px; min-height: 36px; margin: 0; padding: 0 0 6px;
  border-bottom: 1px solid var(--accent-60); font: 600 15px/1.2 var(--font-head); letter-spacing: 0; text-transform: none; color: var(--ink);
}
body.glass-bridge #panel-ops #ops-order-rail .ops-ticket-group > summary.ops-group-head > .ops-group-count { margin-left: auto; }
body.glass-bridge #panel-ops .ops-group-head .goods-chip { gap: 8px; min-width: 0; }
body.glass-bridge #panel-ops .ops-group-count { flex: none; font: 400 11px/1 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge #panel-ops .ops-tickets,
body.glass-bridge #panel-ops .ops-own-tickets { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; min-width: 0; }
/* auto-fit: one or two records share the ledger's width instead of sitting
   in the first of several empty column tracks. */
body.glass-bridge #panel-ops .ops-own-tickets { grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: 0 16px; }
body.glass-bridge :is(#panel-ops) .ops-order-ticket {
  position: relative; min-width: 0; margin: 0; padding: 8px 0; border: 0; border-bottom: 1px solid var(--line-soft); background: none; color: var(--ink);
}
body.glass-bridge #panel-ops .ops-order-ticket p { margin: 2px 0; font: 400 12px/1.4 var(--font-ui); color: var(--ink-muted); }
/* The ticket's paragraph rule above sets UI type; its reference line stays
   mono, as every other reference in the room. */
body.glass-bridge #panel-ops .ops-order-ticket .ops-reference { margin: 2px 0 0; font: 400 11px/1.4 var(--font-mono); letter-spacing: .04em; }
body.glass-bridge #panel-ops .ops-ticket-good { margin: 0 0 4px; font: 600 15px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge #panel-ops .ops-ticket-side { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
body.glass-bridge #panel-ops .ops-side-tag { font: 400 10px/1 var(--font-mono); letter-spacing: .08em; color: var(--accent); }
body.glass-bridge #panel-ops .ops-order-ticket[data-side="sell"] .ops-side-tag { color: var(--ink); }
body.glass-bridge #panel-ops .ops-ticket-price { font: 400 15px/1.2 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
body.glass-bridge #panel-ops .ops-order-status { text-transform: capitalize; }
body.glass-bridge #panel-ops .ops-order-tally,
body.glass-bridge #panel-ops .stock-reservation { position: relative; height: 3px; margin: 4px 0; overflow: hidden; background: var(--ring-track); border: 0; max-width: none; }
body.glass-bridge #panel-ops .ops-order-tally > span,
body.glass-bridge #panel-ops .stock-reservation > i { display: block; height: 100%; background: var(--accent-60); }
body.glass-bridge #panel-ops .stock-reservation > i { background: var(--ink-muted); }
body.glass-bridge #panel-ops .ops-ticket-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
body.glass-bridge #panel-ops .ops-cancel-review { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line-soft); }
body.glass-bridge #panel-ops .ops-cancel-review[hidden] { display: none; }
body.glass-bridge #panel-ops .ops-cancel-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 0; }
body.glass-bridge #panel-ops .ops-cancel-error { color: var(--bad); }
body.glass-bridge #panel-ops .ops-cancel-error:empty { display: none; }
body.glass-bridge #panel-ops #ops-order-table { margin: 12px 0 0; padding: 0; border: 0; background: none; color: var(--ink); }
body.glass-bridge #panel-ops #ops-order-table .market-scroll { max-height: 60vh; overflow: auto; margin-top: 6px; }
body.glass-bridge #panel-ops #ops-order-table table { min-width: 560px; }
body.glass-bridge #panel-ops #ops-order-table :is(th, td) { white-space: normal; }
body.glass-bridge #panel-ops #ops-order-table td { color: var(--ink); }
body.glass-bridge #panel-ops #ops-order-table :is(.age, td.age) { color: var(--ink-muted); }
body.glass-bridge #panel-ops #ops-order-table .goods-chip { gap: 8px; white-space: normal; }
/* New order heads the book, above the per-good folds, so the exchange's
   primary action is never below the tickets. */
body.glass-bridge #panel-ops #tab-orders > .table-foot.ops-orders-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px;
  margin: 0 0 12px; padding: 0 0 10px; border: 0; border-bottom: 1px solid var(--line-soft);
  font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted);
}
body.glass-bridge #panel-ops #tab-orders > .table-foot > span:first-child { flex: 1 1 18ch; }
body.glass-bridge #panel-ops .ops-post-reason { color: var(--ink-muted); }
body.glass-bridge #panel-ops .ops-post-reason:empty { display: none; }
body.glass-bridge #panel-ops #ops-post-order { margin: 0; }

/* ── Observed prices: one row per good, price and a log₂ base-price ruler ── */
body.glass-bridge #panel-ops #ops-prices { min-width: 0; }
body.glass-bridge #panel-ops .ops-price-board { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 0 16px; }
body.glass-bridge #panel-ops .ops-price-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; align-items: center; min-width: 0;
  margin: 0; padding: 8px 0; border: 0; border-bottom: 1px solid var(--line-soft); background: none; color: var(--ink);
}
body.glass-bridge #panel-ops .ops-price-row[data-price-extra="desktop"] { display: none; }
body.glass-bridge #panel-ops .ops-prices-expanded .ops-price-row[data-price-extra] { display: grid; }
body.glass-bridge #panel-ops .ops-price-row > h4 { min-width: 0; margin: 0; font: 600 15px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge #panel-ops .ops-price-row .goods-chip { gap: 10px; white-space: normal; }
body.glass-bridge #panel-ops .ops-price-figure { display: flex; align-items: baseline; gap: 6px; margin: 0; }
body.glass-bridge #panel-ops .ops-price-figure > strong { font: 400 16px/1.2 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink); }
body.glass-bridge #panel-ops .ops-price-figure > small { font: 400 11px/1 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge :is(#panel-ops, #order-modal) .ops-price-ratio { grid-column: 1 / -1; min-width: 0; font: 400 11px/1.4 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge :is(#panel-ops, #order-modal) .ops-price-scale {
  position: relative; height: 6px; margin: 4px 0 2px; background: var(--ring-track);
  background-image: linear-gradient(90deg, transparent calc(50% - .5px), var(--line) calc(50% - .5px), var(--line) calc(50% + .5px), transparent calc(50% + .5px));
}
body.glass-bridge :is(#panel-ops, #order-modal) .ops-price-pointer {
  position: absolute; top: -3px; width: 2px; height: 12px; margin-left: -1px; background: var(--accent); box-shadow: 0 0 6px var(--accent-40);
}
body.glass-bridge :is(#panel-ops, #order-modal) .ops-scale-labels { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 8px; padding: 0; font-size: 10px; letter-spacing: .04em; }
body.glass-bridge :is(#panel-ops, #order-modal) .ops-scale-labels > :last-child { text-align: right; }
body.glass-bridge :is(#panel-ops, #order-modal) .ops-price-ratio > p { margin: 2px 0 0; font: inherit; color: inherit; }
body.glass-bridge #panel-ops .ops-more-prices { display: none; margin-top: 10px; }
body.glass-bridge #panel-ops .ops-more-prices.desktop-more { display: inline-flex; }
body.glass-bridge #panel-ops .ops-price-note { margin: 10px 0 0; padding: 0; background: none; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }
@media (max-width: 760px), (max-height: 500px) and (max-width: 1279px) {
  body.glass-bridge #panel-ops .ops-price-row[data-price-extra="phone"] { display: none; }
  body.glass-bridge #panel-ops .ops-prices-expanded .ops-price-row[data-price-extra] { display: grid; }
  body.glass-bridge #panel-ops .ops-more-prices { display: inline-flex; }
}

/* ── Paperwork: receipts container, my orders, holdings ──────────────────── */
body.glass-bridge #panel-ops #ops-receipts { color: var(--ink); }
body.glass-bridge #panel-ops #dockside-receipt { margin: 0; font: 400 13px/1.45 var(--font-ui); color: var(--ink); }
body.glass-bridge #panel-ops #dockside-receipt:empty { display: none; }
/* The whole ledger row is the toggle: the summary carries the pane padding,
   so the tap target is the row the captain sees (28 px desktop, 44 px touch). */
body.glass-bridge #panel-ops details.ops-own-ledger { padding: 0; }
body.glass-bridge #panel-ops .ops-own-ledger > summary { box-sizing: border-box; justify-content: flex-start; align-items: center; min-height: 36px; padding: 10px 12px; margin: 0; }
body.glass-bridge #panel-ops .ops-own-ledger > summary > .gl-title { flex: 1; }
body.glass-bridge #panel-ops .ops-own-ledger > summary::after { margin-left: 12px; }
body.glass-bridge #panel-ops .ops-own-ledger[open] > summary { margin-bottom: 0; }
body.glass-bridge #panel-ops .ops-own-ledger > #ops-my-orders { padding: 0 12px 12px; }
body.glass-bridge #panel-ops .ops-ledger-pages { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 10px; }
body.glass-bridge #panel-ops .ops-ledger-pages > p { margin: 0 auto 0 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge #panel-ops #ops-cargo { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 12px 16px; min-width: 0; }
body.glass-bridge #panel-ops #ops-cargo .stock-lot { min-width: 0; margin: 0; padding: 0; border: 0; background: none; color: var(--ink); }
body.glass-bridge #panel-ops #ops-cargo .stock-lot > h4 { margin: 0 0 2px; padding: 0 0 6px; border-bottom: 1px solid var(--accent-60); font: 600 15px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge #panel-ops #ops-cargo .stock-lot > .ops-reference { margin: 4px 0; }
body.glass-bridge #panel-ops #ops-cargo .ops-holdings-here { margin: 4px 0 8px; font: 400 13px/1.45 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge #panel-ops #ops-cargo .stock-entry { min-width: 0; padding: var(--row-pad) 0; border-bottom: 1px solid var(--line-soft); }
body.glass-bridge #panel-ops #ops-cargo .stock-entry .line { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; padding: 0; border: 0; }
body.glass-bridge #panel-ops #ops-cargo .stock-entry .k { flex: 1 1 12ch; min-width: 0; color: var(--ink); }
body.glass-bridge #panel-ops #ops-cargo .stock-entry :is(.goods-chip, .goods-chip > span:last-child) { gap: 8px; font: 400 13px/1.4 var(--font-ui); white-space: normal; color: var(--ink); }
body.glass-bridge #panel-ops #ops-cargo .stock-entry .v { font: 400 13px/1.4 var(--font-mono); color: var(--ink); }
body.glass-bridge #panel-ops #ops-cargo .stock-availability { margin: 2px 0 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }

/* ── Cargo agreements board and dockets ──────────────────────────────────── */
body.glass-bridge #panel-ops #cargo-agreements { display: flex; flex-direction: column; gap: 10px; margin: 0; color: var(--ink); }
body.glass-bridge #panel-ops #cargo-agreements > .gl-head { margin: 0; }
body.glass-bridge #panel-ops #cargo-agreements > .dockside-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
body.glass-bridge #panel-ops #cargo-agreements > details { margin: 0; padding: 0; border-top: 1px solid var(--line-soft); }
body.glass-bridge #panel-ops #cargo-agreements > details > summary { min-height: 36px; padding: 8px 0; }
body.glass-bridge #panel-ops #cargo-agreements > details > summary .gl-meta { margin-left: auto; }
body.glass-bridge #panel-ops .agreement-dockets { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr)); gap: 10px; padding: 4px 0 10px; }
body.glass-bridge #panel-ops .agreement-docket { min-width: 0; margin: 0; padding: 10px 12px; border: 1px solid var(--line); background: var(--field); color: var(--ink); }
body.glass-bridge #panel-ops .agreement-docket:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* A docket focused after an agreement scrolls in with its focus ring whole. */
body.glass-bridge #panel-ops .agreement-docket { scroll-margin: 12px; }
body.glass-bridge #panel-ops .agreement-docket header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
body.glass-bridge #panel-ops .agreement-docket h4 { flex: 1 1 12ch; min-width: 0; margin: 4px 0; font: 600 15px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge #panel-ops .agreement-docket .goods-chip { gap: 8px; white-space: normal; }
body.glass-bridge #panel-ops .agreement-docket p { margin: 4px 0; font: 400 13px/1.45 var(--font-ui); color: var(--ink-muted); }
/* References, figures and the deadline scale are mono, as everywhere else in
   the room; the docket's paragraph rule above would otherwise set them in UI. */
body.glass-bridge #panel-ops .agreement-docket p:is(.ops-reference, .agreement-deadline-scale) { font: 400 11px/1.4 var(--font-mono); letter-spacing: .04em; }
body.glass-bridge #panel-ops .agreement-docket strong { font-weight: 500; color: var(--ink); }
body.glass-bridge #panel-ops .agreement-verdict {
  display: inline-block; padding: 3px 6px; border: 1px solid var(--accent-60); transform: none;
  font: 400 10px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
}
body.glass-bridge #panel-ops .agreement-verdict::before { content: none; }
body.glass-bridge #panel-ops .agreement-docket:is([data-status="expired"], [data-status="failed"], [data-status="cancelled"]) .agreement-verdict { border-color: var(--muted-40); color: var(--ink-muted); }
body.glass-bridge #panel-ops .agreement-docket p.agreement-figures { font: 400 12px/1.4 var(--font-mono); }
body.glass-bridge #panel-ops .agreement-route { padding: 4px 0; border-block: 1px solid var(--line-soft); }
body.glass-bridge #panel-ops .agreement-fill { display: flex; width: 100%; height: 6px; margin: 6px 0 2px; border: 0; background: var(--ring-track); }
body.glass-bridge #panel-ops .agreement-fill span { display: block; height: 100%; }
body.glass-bridge #panel-ops .agreement-delivered { background: var(--accent); }
body.glass-bridge #panel-ops .agreement-committed { background: repeating-linear-gradient(90deg, var(--accent-60) 0 3px, transparent 3px 6px); }
/* Deadline: ticks left on the 48-tick scale, then the scale's name. The gap
   below keeps the scale's name with its bar, apart from the next measure. */
body.glass-bridge #panel-ops .agreement-deadline { margin: 0 0 10px; }
body.glass-bridge #panel-ops .agreement-deadline-bar { display: flex; width: 100%; height: 6px; margin: 6px 0 2px; background: var(--ring-track); }
body.glass-bridge #panel-ops .agreement-deadline-bar > span { display: block; height: 100%; background: var(--accent); }
body.glass-bridge #panel-ops .agreement-docket p.agreement-deadline-scale { margin: 0 0 4px; }
body.glass-bridge #panel-ops .agreement-reputation { margin: 6px 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge #panel-ops .agreement-reputation-segments { display: flex; gap: 3px; height: 6px; margin-bottom: 4px; }
body.glass-bridge #panel-ops .agreement-reputation-segments > span { flex: 1; background: var(--ring-track); border: 0; }
body.glass-bridge #panel-ops .agreement-reputation-segments i { display: block; height: 100%; background: var(--accent); }
body.glass-bridge #panel-ops .agreement-docket .dockside-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
body.glass-bridge #panel-ops .agreement-docket .dockside-actions:empty { display: none; }
body.glass-bridge #panel-ops #cargo-agreements .dockside-actions:empty { display: none; }
body.glass-bridge #panel-ops .agreement-rules > p { margin: 0 0 8px; }
body.glass-bridge #panel-ops #agreement-receipt { margin: 0; color: var(--ink); }
body.glass-bridge #panel-ops #agreement-receipt[hidden] { display: none; }
body.glass-bridge #panel-ops #cargo-agreements .gl-notice { margin: 0; }

/* ── Dialogs: the exchange ticket and the agreement sheet ────────────────── */
body.glass-bridge #order-modal .modal.ops-order-pad,
body.glass-bridge #agreement-modal .modal.agreement-sheet {
  position: relative; width: min(720px, 100%); max-width: 100%; max-height: 100%; margin: auto; overflow: auto;
  padding: 16px 18px 18px; border: 1px solid var(--line); border-image: none; border-radius: 0;
  background: var(--glass); -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
  box-shadow: var(--hairline-top); color: var(--ink); color-scheme: dark; font: 400 14px/1.45 var(--font-ui);
}
body.glass-bridge #order-modal .modal.ops-order-pad::before { content: none; }
/* Head, error line and foot stay put; only the body between them scrolls, so
   Cancel and Post (or Close and Review) are on screen from the moment the
   dialog opens. Rows inside the body keep their height. */
body.glass-bridge #order-modal .modal.ops-order-pad,
body.glass-bridge #agreement-modal .modal.agreement-sheet { display: flex; flex-direction: column; overflow: hidden; }
body.glass-bridge #order-modal .modal.ops-order-pad > *,
body.glass-bridge #agreement-modal .modal.agreement-sheet > * { flex-shrink: 0; }
body.glass-bridge #order-modal .modal.ops-order-pad > .ops-order-body,
body.glass-bridge #agreement-modal .modal.agreement-sheet > .agreement-sheet-paper {
  flex: 0 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain;
  /* Room for focus rings at the scroll edges. */
  margin: -4px -6px 0; padding: 4px 6px 6px;
}
body.glass-bridge :is(#order-modal, #agreement-modal) .gl-modal-head { margin: 0 0 10px; }
body.glass-bridge :is(#order-modal, #agreement-modal) .gl-modal-head .gl-title { margin: 0; }
body.glass-bridge :is(#order-modal, #agreement-modal) h2.gl-modal-title { margin: 8px 0 0; font: 600 22px/1.1 var(--font-head); letter-spacing: 0; text-transform: none; color: var(--ink); }
body.glass-bridge #order-modal #order-modal-where { margin: 6px 0 0; font: 400 11px/1.4 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge :is(#order-modal, #agreement-modal) :is(label, .gl-label, legend) {
  display: block; margin: 12px 0 6px; padding: 0; font: 500 11px/1.2 var(--font-ui); letter-spacing: .18em; text-transform: uppercase; color: var(--ink-muted);
}
body.glass-bridge #order-modal .side-toggle { display: flex; gap: 8px; margin: 0 0 6px; }
body.glass-bridge #order-modal .side-toggle > .gl-btn { flex: 1 1 0; min-width: 8ch; }
body.glass-bridge #order-modal #order-specimens {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 112px), 1fr)); gap: 6px;
  min-width: 0; min-inline-size: 0; margin: 6px 0 0; padding: 0; border: 0;
}
body.glass-bridge #order-modal #order-specimens > legend { grid-column: 1 / -1; float: left; width: 100%; margin: 6px 0; }
body.glass-bridge #order-modal .ops-specimen-choice {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; min-height: 0; margin: 0;
  padding: 10px 6px 8px; border: 1px solid var(--line); background: var(--field); color: var(--ink); text-align: center; cursor: pointer;
  font: 400 12px/1.3 var(--font-ui); letter-spacing: 0; text-transform: none;
}
body.glass-bridge #order-modal .ops-specimen-choice:hover { border-color: var(--accent-60); }
body.glass-bridge #order-modal .ops-specimen-choice:has(:checked) { border-color: var(--accent); background: var(--accent-12); }
body.glass-bridge #order-modal .ops-specimen-choice:has(:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
body.glass-bridge #order-modal .ops-specimen-choice > input { position: absolute; top: 4px; left: 4px; width: 14px; height: 14px; margin: 0; accent-color: var(--accent); }
body.glass-bridge #order-modal .ops-specimen-choice > input:focus-visible { outline: 0; }
body.glass-bridge #order-modal .ops-specimen-name { min-width: 0; max-width: 100%; overflow-wrap: normal; color: var(--ink); }
body.glass-bridge #order-modal .ops-specimen-choice > small { font: 400 11px/1.3 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge #order-modal .ops-specimen-wide { grid-column: 1 / -1; }
body.glass-bridge #order-modal .ops-specimen-fold { margin: 12px 0 0; border-top: 1px solid var(--line-soft); }
body.glass-bridge #order-modal .ops-specimen-fold > summary { padding: 8px 0; }
body.glass-bridge #order-modal .ops-specimen-fold > summary > .gl-meta { margin-left: auto; letter-spacing: 0; text-transform: none; }
body.glass-bridge #order-modal .ops-specimen-fold > #order-specimens { margin: 0 0 4px; }
body.glass-bridge #order-modal .ops-specimen-fold > #order-specimens > legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; margin: 0; }
body.glass-bridge :is(#order-modal, #agreement-modal) .gl-select { width: auto; }
body.glass-bridge :is(#order-modal, #agreement-modal) .gl-select > select { height: calc(100% + 2px); width: calc(100% + 2px); padding-top: 0; padding-bottom: 0; border: 0; background: transparent; color: var(--ink); }
/* Until a good is chosen the ticket's field shows its placeholder in the
   muted field colour, as the Port trade select does; a chosen good is ink. */
body.glass-bridge #order-modal .gl-select > select:has(> option[value=""]:checked) { color: var(--ink-muted); }
body.glass-bridge #order-modal .order-good { margin: 8px 0 0; font: 600 15px/1.2 var(--font-head); color: var(--ink); }
body.glass-bridge #order-modal .order-good .goods-chip { gap: 10px; white-space: normal; }
body.glass-bridge #order-modal .row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; }
body.glass-bridge #order-modal .row > div { min-width: 0; }
body.glass-bridge #order-modal .gl-input { width: 100%; }
body.glass-bridge #order-modal #order-total { margin: 12px 0 0; padding: 10px 0 0; border-top: 1px solid var(--line-soft); font: 400 13px/1.45 var(--font-mono); color: var(--ink); }
body.glass-bridge #order-modal #order-escrow:empty { display: none; }
body.glass-bridge #order-modal #order-price-context { margin-top: 8px; }
body.glass-bridge #order-modal #order-price-context:empty { display: none; }
body.glass-bridge #order-modal #order-price-context p { margin: 6px 0; font: 400 12px/1.45 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge :is(#order-modal, #agreement-modal) .err { margin: 8px 0 0; min-height: 0; font: 400 13px/1.4 var(--font-ui); color: var(--bad); }
body.glass-bridge :is(#order-modal, #agreement-modal) .err:empty { display: none; }
body.glass-bridge :is(#order-modal, #agreement-modal) .foot.gl-modal-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line-soft); }
body.glass-bridge :is(#order-modal, #agreement-modal) .foot.gl-modal-foot > .gl-btn { margin: 0; max-width: none; flex: 0 0 auto; }

/* One column: the fields, then the cargo plan and the reviewed summary. */
body.glass-bridge #agreement-modal .agreement-sheet-paper { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; background: none; }
body.glass-bridge #agreement-modal #agreement-fields { min-width: 0; }
body.glass-bridge #agreement-modal #agreement-fields[hidden] { display: none; }
body.glass-bridge #agreement-modal #agreement-cargo-preview { min-width: 0; color: var(--ink); }
body.glass-bridge #agreement-modal :is(#agreement-summary, #agreement-cargo-preview):empty { display: none; }
body.glass-bridge #agreement-modal :is(#agreement-fields, #agreement-cargo-preview, #agreement-summary) :is(p, .hint) { font: 400 13px/1.45 var(--font-ui); color: var(--ink-muted); }
body.glass-bridge #agreement-modal #agreement-summary p { color: var(--ink); }
body.glass-bridge #agreement-modal .agreement-stepper { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
body.glass-bridge #agreement-modal .agreement-stepper > .gl-input { flex: 2 1 8ch; width: 8ch; min-width: 8ch; }
body.glass-bridge #agreement-modal .agreement-stepper > .gl-btn { flex: 1 0 auto; }
body.glass-bridge #agreement-modal .agreement-search { display: flex; gap: 8px; align-items: center; }
body.glass-bridge #agreement-modal .agreement-search > .gl-input { flex: 1; }
body.glass-bridge #agreement-modal input[type="range"] { width: 100%; min-height: 28px; accent-color: var(--accent); }
body.glass-bridge #agreement-modal #agreement-all,
body.glass-bridge #agreement-modal #agreement-starter-load { margin-top: 8px; }
body.glass-bridge #agreement-modal .dockside-warning { color: var(--bad); }
body.glass-bridge #agreement-modal .agreement-capacity-mark { margin: 10px 0; font: 400 12px/1.4 var(--font-mono); color: var(--ink-muted); }
body.glass-bridge #agreement-modal .agreement-capacity-mark meter { display: block; width: 100%; height: 8px; accent-color: var(--accent); }

/* ── Small screens and touch ─────────────────────────────────────────────── */
@media (max-width: 640px) {
  body.glass-bridge #panel-ops :is(.ops-switch, .ops-paperwork-rail) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px), (pointer: coarse) {
  body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab { min-height: 44px; }
  body.glass-bridge #panel-ops #ops-order-rail .ops-ticket-group > summary.ops-group-head { min-height: 44px; }
  body.glass-bridge :is(#ops-exchange-zone, .ops-private-ledgers, #cargo-agreements, #order-modal, #agreement-modal) details > summary { min-height: 44px; }
  body.glass-bridge #panel-ops .ops-own-ledger > summary,
  body.glass-bridge #panel-ops #cargo-agreements > details > summary { min-height: 44px; }
  body.glass-bridge #order-modal .ops-specimen-choice > input { width: 18px; height: 18px; }
}
@media (max-width: 640px) {
  body.glass-bridge #order-modal .modal.ops-order-pad,
  body.glass-bridge #agreement-modal .modal.agreement-sheet { width: 100%; max-height: 92dvh; margin: auto 0 0; border-bottom: 0; padding-bottom: max(18px, env(safe-area-inset-bottom)); }
  body.glass-bridge #order-modal .row { grid-template-columns: minmax(0, 1fr); }
  body.glass-bridge :is(#order-modal, #agreement-modal) .foot.gl-modal-foot > .gl-btn { flex: 1 1 0; }
  body.glass-bridge #order-modal #order-specimens { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Phone landscape: the ticket is a full-height sheet with a one-line head,
   and the terms (quantity, price, order value) stand beside the side and the
   good, so everything Post Order commits is on screen when the ticket opens.
   DOM order stays side, good, terms, so focus and reading order match. */
@media (max-height: 500px) {
  body.glass-bridge #order-modal { align-items: stretch; padding: 0; }
  body.glass-bridge #order-modal .modal.ops-order-pad {
    width: 100%; max-width: none; height: 100%; max-height: none; margin: 0; border-width: 0;
    padding: 10px max(16px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  }
  body.glass-bridge #order-modal .gl-modal-head { margin: 0 0 2px; }
  body.glass-bridge #order-modal .gl-modal-head > div { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; }
  body.glass-bridge #order-modal h2.gl-modal-title { margin: 0; }
  body.glass-bridge #order-modal #order-modal-where { display: none; }
  body.glass-bridge #order-modal .ops-order-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 20px; align-items: start; }
  body.glass-bridge #order-modal .ops-order-body > .ops-specimen-fold { grid-column: 1 / -1; }
  body.glass-bridge #order-modal :is(label, .gl-label) { margin: 8px 0 4px; }
  body.glass-bridge #order-modal .order-good { margin-top: 6px; }
  body.glass-bridge #order-modal #order-total { margin-top: 8px; padding-top: 8px; }
  body.glass-bridge #order-modal .foot.gl-modal-foot { margin-top: 8px; padding-top: 8px; }
}

/* ── Forced colours and high contrast ────────────────────────────────────── */
@media (forced-colors: active) {
  body.glass-bridge #panel-ops :is(.ops-order-tally, .stock-reservation, .agreement-fill, .agreement-deadline-bar, .ops-price-scale) { border: 1px solid CanvasText; background: Canvas; }
  body.glass-bridge #panel-ops :is(.ops-order-tally > span, .stock-reservation > i, .agreement-delivered, .agreement-deadline-bar > span, .agreement-reputation-segments i),
  body.glass-bridge :is(#panel-ops, #order-modal) .ops-price-pointer { background: CanvasText; forced-color-adjust: none; }
  body.glass-bridge :is(#order-modal, #agreement-modal) .modal { background: Canvas; color: CanvasText; border-color: CanvasText; }
  /* The terminal pane and the exchange tabs are styled at ID weight above;
     give them the system colours the primitives use. */
  body.glass-bridge #panel-ops #dockside-terminal.gl-pane { background: Canvas; color: CanvasText; border-color: CanvasText; -webkit-backdrop-filter: none; backdrop-filter: none; }
  body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab { background: ButtonFace; color: ButtonText; border-color: ButtonText; }
  body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab:is(.active, [aria-pressed="true"]) { background: ButtonText; color: ButtonFace; border-color: ButtonText; }
  body.glass-bridge #panel-ops #ops-exchange-zone .tabs .tab:hover { background: Highlight; color: HighlightText; border-color: Highlight; }
  body.glass-bridge #order-modal .ops-specimen-choice { border-color: CanvasText; }
  body.glass-bridge #order-modal .ops-specimen-choice:has(:checked) { outline: 2px solid Highlight; }
  body.glass-bridge #panel-ops .agreement-docket { border-color: CanvasText; background: Canvas; }
}
