/* hub.css — THE PLAYER HUB (the utility panel on the website).
   =========================================================================
   A PAGE SHEET LAYS OUT ITS PAGE; IT DOES NOT DESCRIBE A SURFACE. Every
   record on this page (.hub-plate, .hub-tile, .hub-gauge, .hub-slot,
   .hub-item, .hub-stat, ...) is named in terminal.css section 6b, THE
   SURFACE REGISTER, and takes the house grammar from there. Chips are the
   house .pill, small buttons the house .btn-sm, the hero name the house
   .page-h1, interior headings the --tm-h-* steps, radii the --r tokens. A
   site theme (hatch) re-rounds these names in its own sheet.

   THE SHAPE (owner, 2026-08-23: "reads like a paragraph"): a DASHBOARD.
   The hero is the animal in its well beside four gauges; the doors are icon
   tiles with one word and a price; below, two columns of compact plates.
   Numbers are big, words are labels, sentences live only in the confirm
   sheet.
   ========================================================================= */

.hub-head { margin-bottom: 18px; }

/* ---- the hero ------------------------------------------------------------- */
.hub-hero { padding: 0; }
.hub-hero.lvc { gap: 22px; align-items: stretch; }
/* ★★★★★ THE WELL ALIGNS TO THE START, AND THAT ONE WORD IS LOAD-BEARING
   (measured 2026-08-29, Everfall, in a real browser at 1440).

   `align-items: stretch` above is needed by the OTHER column: `.hub-gauges`
   uses `margin-top: auto` to sit on the bottom of the card, which does nothing
   unless `.hub-hero-main` is stretched to the row's height. But `stretch`
   applies to EVERY item, so it also gave the well a DEFINITE block size - the
   row height, which column two's own content decides - and `aspect-ratio: 1/1`
   then transferred that height into the INLINE axis. The well came out
   459x459 inside a 320px track: 139px of a square dinosaur painted straight
   over the species name and the health gauge, on every load, at desktop width.

   Measured before the fix, signed in, viewport 1416:
     #hub-hero            grid, cols "320px 810px", align-items stretch, h 459
     .lvc-specimen        x 132  w 459  h 459   <- 139px past its own track
     .hub-hero-main       x 474                 <- 117px of it was covered
   and after: .lvc-specimen w 320 h 320, .hub-hero-main x 474, no overlap.

   `align-self: start` restores exactly what livecard.css's own `.lvc` sets
   (`align-items: start`) for this one child, so the height goes back to being
   derived FROM the width through the aspect ratio - a 320 square - while the
   main column keeps the stretch it actually needs. It is scoped to the hub's
   hero, so no other surface that mounts a specimen well can be moved by it.

   ★ THE PHONE LAYOUT IS UNTOUCHED. Below 860px `.lvc` collapses to one column
   (livecard.css) and §"phone" below re-shapes this well to 4/3 with no
   min-height; a single-column row has no second child to take a height from,
   so `start` and `stretch` compute the same box there. */
.hub-hero .lvc-specimen { aspect-ratio: 1 / 1; min-height: 300px; align-self: start; }
.hub-hero-main { display: flex; flex-direction: column; gap: 14px; min-width: 0; padding: 22px; }
.hub-hero-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hub-hero-when { margin-left: auto; color: var(--fg-mute); font-size: var(--tm-h-micro); letter-spacing: .08em; text-transform: uppercase; }
.hub-hero-name { margin: 0; line-height: 1; }
.hub-hero-gate { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 8px 0; }
.hub-hero-gate .gate-ico { margin: 0; }

.hub-gauges { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-top: auto; }
.hub-gauge { display: grid; justify-items: center; gap: 6px; padding: 12px 6px 10px; background: var(--surface-2); text-align: center; --g: var(--accent); }
.hub-gauge-ring { position: relative; width: 62px; height: 62px; }
.hub-gauge-ring svg { width: 62px; height: 62px; transform: rotate(-90deg); }
.hub-gauge-ring circle { fill: none; stroke-width: 6; }
.hub-gauge-ring .track { stroke: var(--surface-sink); }
.hub-gauge-ring .fill { stroke: var(--g); stroke-linecap: round; transition: stroke-dasharray .5s ease; }
.hub-gauge-ring svg.ico { position: absolute; inset: 0; width: 62px; height: 62px; transform: none; padding: 19px; color: var(--g); }
.hub-gauge b { font-family: var(--font-display); font-weight: 700; color: var(--fg); }
.hub-gauge span { font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.hub-gauge.is-low { --g: var(--bad); }
.hub-gauge.is-low b { color: var(--bad); }
.hub-gauge.is-unknown b { color: var(--fg-mute); }

.hub-growth { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; }
.hub-growth span { font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.hub-growth i { display: block; height: 6px; border-radius: var(--r-pill); background: var(--surface-sink); overflow: hidden; }
.hub-growth i::after { content: ""; display: block; height: 100%; width: var(--w, 0%); background: var(--accent); border-radius: var(--r-pill); transition: width .5s ease; }
.hub-growth b { font-family: var(--font-display); font-weight: 700; color: var(--fg); }

/* THE WELL WITH NO MODEL. The engine leaves an empty frame when a species has
   no bake on this box (every Legacy species today - the client pak key is not
   recovered). An empty black box reads as broken, so the frame says the
   species' name and what is coming. */
.hub-hero .lvc-specimen-mount[data-empty]::before {
  content: attr(data-species);
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 90%; text-align: center; font-family: var(--font-display); font-weight: 700;
  font-size: clamp(20px, 2.6vw, 30px); letter-spacing: .06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--fg) 26%, transparent);
}
.hub-hero .lvc-specimen-mount[data-empty]::after {
  content: "3D preview coming";
  position: absolute; left: 0; right: 0; bottom: 14px; text-align: center;
  font-size: var(--tm-h-micro); font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--fg-mute);
}
/* the engine's own poster disc is noise under our own placeholder */
.hub-hero .lvc-specimen-mount[data-empty] .shopview[data-view]::after { content: none; }

/* ---- plates --------------------------------------------------------------- */
.hub-plate { padding: 18px 20px 18px; }
.hub-plate-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.hub-plate-head h2 { font-size: var(--tm-h-sec); margin: 0; }
.hub-chips { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.hub-chip b { font-family: var(--font-display); font-weight: 700; }
.hub-chip-accent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.hub-chip-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.hub-chip-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 45%, transparent); }
.hub-chip-ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); }
.hub-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; align-items: start; }
.hub-col { min-width: 0; }

/* ---- the doors: icon tiles ------------------------------------------------ */
.hub-tiles { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 8px; }
.hub-tile {
  display: grid; justify-items: center; gap: 6px; padding: 12px 6px 10px;
  background: var(--surface-2); color: var(--fg); cursor: pointer; font: inherit; text-align: center;
  transition: border-color .15s ease, transform .15s ease;
}
.hub-tile:hover:not([disabled]) { border-color: color-mix(in srgb, var(--accent) 55%, transparent); transform: translateY(-1px); }
.hub-tile[disabled] { opacity: .42; cursor: not-allowed; }
.hub-tile-ico { width: 38px; height: 38px; border-radius: var(--r-round); display: grid; place-items: center; background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent); }
.hub-tile-ico svg { width: 19px; height: 19px; }
.hub-tile-bad .hub-tile-ico { background: color-mix(in srgb, var(--bad) 14%, var(--surface)); color: var(--bad); }
.hub-tile b { font-family: var(--font-display); font-weight: 600; line-height: 1.15; }
.hub-tile-price { font-size: var(--tm-h-micro); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.hub-tile-price.is-free { color: var(--fg-mute); font-weight: 600; }

/* ---- an inline answer under a plate --------------------------------------- */
.hub-say { margin: 10px 0 0; padding: 9px 12px; line-height: 1.35; background: var(--surface-2); color: var(--fg); }
.hub-say.is-ok { border-color: color-mix(in srgb, var(--ok) 50%, transparent); }
.hub-say.is-bad { border-color: color-mix(in srgb, var(--bad) 50%, transparent); }
.hub-say.is-busy { color: var(--fg-dim); }

/* ---- the vault slots ------------------------------------------------------ */
.hub-slots { display: grid; gap: 8px; }
.hub-slot { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px 12px; align-items: center; padding: 10px 12px; background: var(--surface-2); }
.hub-ring { position: relative; width: 46px; height: 46px; flex: none; }
.hub-ring svg { width: 46px; height: 46px; transform: rotate(-90deg); }
.hub-ring circle { fill: none; stroke-width: 5; }
.hub-ring .track { stroke: var(--surface-sink); }
.hub-ring .fill { stroke: var(--accent); stroke-linecap: round; }
.hub-ring b { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; color: var(--fg); }
.hub-slot-name { min-width: 0; }
.hub-slot-name b { display: block; font-size: var(--tm-h-item); font-family: var(--font-display); font-weight: 700; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-slot-name span { display: block; font-size: var(--tm-h-micro); letter-spacing: .06em; text-transform: uppercase; color: var(--fg-mute); margin-top: 3px; }
.hub-slot-perks { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 5px; }
.hub-slot-act { grid-column: 1 / -1; display: flex; gap: 6px; flex-wrap: wrap; }
.hub-slot.is-busy { opacity: .7; }
.hub-slot-state { position: absolute; top: 8px; right: 8px; }
.hub-empty { display: grid; justify-items: center; gap: 6px; padding: 22px 10px; text-align: center; background: var(--surface-2); color: var(--fg-dim); }
.hub-empty svg { width: 26px; height: 26px; color: var(--fg-mute); }
.hub-empty b { font-family: var(--font-display); color: var(--fg); }

/* ---- the shop ------------------------------------------------------------- */
.hub-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.hub-tab { cursor: pointer; }
.hub-tab[aria-selected="true"] { color: var(--fg); border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.hub-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 6px; }
.hub-item {
  display: grid; gap: 4px; padding: 9px 10px; text-align: left; font: inherit; color: var(--fg);
  background: var(--surface-2); cursor: pointer;
  transition: border-color .15s ease, transform .15s ease;
}
.hub-item:hover { border-color: color-mix(in srgb, var(--accent) 55%, transparent); transform: translateY(-1px); }
.hub-item b { font-family: var(--font-display); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-item span { font-size: var(--tm-h-micro); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.hub-item.is-short { opacity: .5; }
.hub-item.is-short span { color: var(--fg-mute); }

/* ---- the wallet ----------------------------------------------------------- */
.hub-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.hub-stat { display: grid; gap: 4px; padding: 12px 14px; background: var(--surface-2); }
.hub-stat span { font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.hub-stat b { font-family: var(--font-display); font-weight: 700; font-size: clamp(24px, 3vw, 32px); line-height: 1; color: var(--fg); letter-spacing: -.01em; }
.hub-lanes { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.hub-lane code { font-family: var(--font-display); font-weight: 700; }
.hub-ledger { display: grid; gap: 4px; margin-top: 10px; }
.hub-ledger-row { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 6px 10px; background: var(--surface-2); }
.hub-ledger-row b { font-family: var(--font-display); font-weight: 700; }
.hub-ledger-row b.is-up { color: var(--ok); }
.hub-ledger-row b.is-down { color: var(--bad); }
.hub-ledger-row span { color: var(--fg-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-ledger-row time { color: var(--fg-mute); font-size: var(--tm-h-micro); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }

/* ---- skins ---------------------------------------------------------------- */
.hub-designs { display: grid; gap: 6px; }
.hub-design { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 8px 10px; background: var(--surface-2); }
.hub-design b { display: block; font-family: var(--font-display); font-weight: 700; }
.hub-design span { display: block; font-size: var(--tm-h-micro); letter-spacing: .06em; text-transform: uppercase; color: var(--fg-mute); margin-top: 2px; }
.hub-swatches { display: inline-flex; gap: 3px; margin-left: 8px; vertical-align: middle; }
.hub-swatches i { width: 10px; height: 10px; border-radius: var(--r); display: inline-block; }

/* ---- forms inside sheets -------------------------------------------------- */
.hub-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.hub-form input, .hub-form select { flex: 1 1 160px; min-width: 0; }
.hub-code { font-family: var(--font-display); font-weight: 700; font-size: clamp(22px, 4vw, 30px); line-height: 1.1; letter-spacing: .12em; color: var(--accent); }

/* ---- the confirm sheet ---------------------------------------------------- */
.hub-sheet { border: 0; padding: 0; background: transparent; max-width: min(92vw, 460px); width: 100%; }
.hub-sheet::backdrop { background: color-mix(in srgb, var(--bg-deep) 70%, transparent); backdrop-filter: blur(4px); }
.hub-sheet-in { padding: 22px; display: grid; gap: 10px; color: var(--fg); }
.hub-sheet-in h3 { margin: 0; font-size: var(--tm-h-item); }
.hub-sheet-body { display: grid; gap: 8px; }
.hub-sheet-row { display: flex; justify-content: space-between; gap: 12px; padding: 8px 10px; background: var(--surface-2); }
.hub-sheet-row b { font-family: var(--font-display); }
.hub-sheet-note { margin: 0; }
.hub-sheet-act { display: flex; gap: 8px; justify-content: flex-end; margin-top: 6px; }
.hub-picks { display: grid; gap: 6px; }
.hub-pick { display: flex; align-items: flex-start; gap: 10px; padding: 8px 10px; background: var(--surface-2); cursor: pointer; }
.hub-pick input { margin-top: 3px; }
.hub-pick b { display: block; font-family: var(--font-display); font-weight: 600; }
.hub-pick span { display: block; color: var(--fg-dim); }
.hub-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.hub-choice .btn[aria-pressed="true"] { border-color: color-mix(in srgb, var(--accent) 70%, transparent); background-color: color-mix(in srgb, var(--accent) 16%, var(--surface-2)); }

/* =========================================================================
   THE EVRIMA CARE DECK + THE MONEY DECK (2026-08-24)
   -------------------------------------------------------------------------
   Same grammar as everything above: a record states its GROUND and nothing
   else. The hairline, the radius and the absence of a shadow all arrive from
   terminal.css section 6b, where every class below is named. A `border:` in
   this file would be this sheet answering "what does a box look like" for the
   sixth time, which is the exact drift the register exists to stop.
   ========================================================================= */

/* ---- the island picker (only ever drawn on a two-island owner) ------------ */
.hub-islands { display: inline-flex; gap: 4px; }
.hub-island { cursor: pointer; }
.hub-island[aria-pressed="true"] { color: var(--fg); border-color: color-mix(in srgb, var(--accent) 55%, transparent); }

/* ---- reverse grow -------------------------------------------------------- */
.hub-ungrow { display: grid; gap: 10px; padding: 12px 14px; background: var(--surface-2); margin-bottom: 10px; }
.hub-ungrow-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.hub-ungrow-head b { font-family: var(--font-display); font-weight: 700; font-size: var(--tm-h-item); }
/* THE PREVIEW IS THE POINT OF THE CONTROL: two readings and an arrow, so the
   player sees the trade before they can press it. The target is accented and
   the current value is not - the eye should land on the number that CHANGES. */
.hub-ungrow-read { display: flex; align-items: center; justify-content: center; gap: 14px; }
.hub-ungrow-cell { display: grid; justify-items: center; gap: 2px; min-width: 74px; }
.hub-ungrow-cell i { font-style: normal; font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.hub-ungrow-cell b { font-family: var(--font-display); font-weight: 700; font-size: clamp(22px, 3.4vw, 30px); line-height: 1; color: var(--fg-dim); }
.hub-ungrow-cell.is-to b { color: var(--accent); }
.hub-ungrow-arrow { color: var(--fg-mute); font-size: var(--tm-h-item); }
.hub-ungrow-slider { width: 100%; margin: 0; accent-color: var(--accent); }
.hub-ungrow-slider[disabled] { opacity: .42; cursor: not-allowed; }
.hub-ungrow-act { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.hub-ungrow-num { width: 78px; min-width: 0; text-align: center; font-family: var(--font-display); font-weight: 700; }
.hub-ungrow-act .btn-primary { margin-left: auto; }

/* A wider door row: the care tiles carry a CURRENCY NAME in their price, and
   at eight-across ("5 NADDERS") the word wraps under the number on a laptop.
   ★ AUTO-FIT, NOT A FIXED COUNT. How many doors this row holds is the
   catalog's answer, not this sheet's - an island with one diet letter draws
   four tiles and one with three draws six, and a fixed five-column grid
   orphans the sixth on a row of its own. */
.hub-tiles-wide { grid-template-columns: repeat(auto-fit, minmax(124px, 1fr)); }

/* ---- the money deck ------------------------------------------------------ */
.hub-money { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 12px; align-items: start; }
.hub-card { display: grid; gap: 10px; padding: 14px 16px; background: var(--surface-2); }
.hub-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.hub-card-head b { font-family: var(--font-display); font-weight: 700; font-size: var(--tm-h-item); }

/* THE WORK PRESS IS THE WHOLE TARGET. A small button inside a large card is a
   target a thumb misses, and this is the one door a player presses every
   hour. The ring is the cooldown's own gauge, drawn from the server's clock. */
.hub-work { justify-items: center; text-align: center; }
/* Its GROUND and its hairline are spoken in terminal.css section 6b, where
   "this surface is deliberately not a plate" belongs - the register is the
   one list of what a surface IS, and an exception buried in a page sheet is
   how the eleven surfaces drifted apart in the first place. */
.hub-work-press { display: grid; place-items: center; padding: 0; cursor: pointer; font: inherit; color: var(--fg); }
.hub-work-press[disabled] { cursor: not-allowed; }
.hub-work-ring { position: relative; display: grid; place-items: center; width: 132px; height: 132px; }
.hub-work-ring svg { position: absolute; inset: 0; width: 132px; height: 132px; transform: rotate(-90deg); }
.hub-work-ring circle { fill: none; stroke-width: 7; }
.hub-work-ring .track { stroke: var(--surface-sink); }
.hub-work-ring .fill { stroke: var(--accent); stroke-linecap: round; transition: stroke-dasharray 1s linear; }
.hub-work-ring.is-cooling .fill { stroke: var(--fg-mute); }
.hub-work-face { display: grid; justify-items: center; gap: 4px; }
.hub-work-ico { display: grid; place-items: center; width: 34px; height: 34px; color: var(--accent); }
.hub-work-ico svg { width: 26px; height: 26px; }
.hub-work-ring.is-cooling .hub-work-ico { color: var(--fg-mute); }
.hub-work-face b { font-family: var(--font-display); font-weight: 700; font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; }
.hub-work-press:hover:not([disabled]) .hub-work-ring .fill { stroke: var(--ok); }
/* THE REVEAL. It animates ONCE, on the frame the receipt lands - a payout a
   player never sees arrive is a payout they think did not happen. Held to a
   transform and an opacity so a reduced-motion reader loses the movement and
   keeps the number. */
.hub-work-got { min-height: 1.4em; margin: 0; font-family: var(--font-display); font-weight: 700; font-size: clamp(20px, 3vw, 28px); line-height: 1.2; color: var(--ok); opacity: 0; }
.hub-work-got.is-in { animation: hub-got .6s ease-out forwards; }
@keyframes hub-got {
  from { opacity: 0; transform: translateY(8px) scale(.94); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hub-work-got.is-in { animation: none; opacity: 1; }
  .hub-work-ring .fill { transition: none; }
}
.hub-work-rate { margin: 0; font-size: var(--tm-h-micro); letter-spacing: .08em; text-transform: uppercase; }

/* ---- transfer ------------------------------------------------------------ */
.hub-xfer-form { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto; gap: 8px; align-items: end; position: relative; }
.hub-xfer-field { display: grid; gap: 4px; min-width: 0; }
.hub-xfer-field i { font-style: normal; font-size: var(--tm-h-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.hub-xfer-field input { width: 100%; min-width: 0; }
/* THE DROP-DOWN IS THE REGISTER'S FLOATING KIND: it sits over page content,
   so it keeps an opaque ground and the panel lift - both spoken in the house
   look beside the Bans tab's list, which is the same shape. */
.hub-xfer-list { position: absolute; z-index: 2; top: 100%; left: 0; width: min(100%, 320px); margin-top: 4px; padding: 4px; list-style: none; max-height: 216px; overflow-y: auto; background: var(--surface); }
.hub-xfer-list li { display: block; }
.hub-xfer-list button { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 10px; background: none; border: 0; cursor: pointer; font: inherit; color: var(--fg); text-align: left; }
.hub-xfer-list button:hover, .hub-xfer-list button:focus-visible { background: var(--surface-2); }
.hub-xfer-list b { font-family: var(--font-display); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The name the player SEARCHED by, when the value being inserted is a
   different one the bot can resolve. It must read as secondary to the pick and
   must never push the ambiguity pill off the row, so it is the flex item that
   gives way. */
.hub-xfer-alias { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: right; font-size: var(--tm-h-micro); }
/* The honest empty state sits where the list would have been, so the answer to
   "did it look?" appears in the same place either way. */
.hub-xfer-empty { position: absolute; z-index: 2; top: 100%; left: 0; width: min(100%, 320px); margin-top: 4px; padding: 7px 10px; background: var(--surface); font-size: var(--tm-h-micro); }

@media (max-width: 900px) {
  .hub-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .hub-cols { grid-template-columns: minmax(0, 1fr); }
  .hub-money { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .hub-hero .lvc-specimen { min-height: 0; aspect-ratio: 4 / 3; }
  .hub-hero-main { padding: 14px; }
  .hub-gauges { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hub-plate { padding: 14px 12px 12px; }
  .hub-ledger-row { grid-template-columns: 60px minmax(0, 1fr); }
  .hub-ledger-row time { display: none; }
  .hub-tiles-wide { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hub-ungrow-act .btn-primary { margin-left: 0; width: 100%; }
  /* The send button drops to its own full-width row rather than being
     squeezed to an ellipsis beside two fields. */
  .hub-xfer-form { grid-template-columns: minmax(0, 1fr); }
  .hub-xfer-form .btn { width: 100%; }
  .hub-ungrow-cell { min-width: 60px; }
}
