/* ══════════════════════════════════════════════════════════════════════════
   src/styles/hunt.css — the hunt screen's panels (HUNT_SCREEN_SPEC §1.4):
   the top bar, the party board, the analyzer, the hearth-emblem bottom bar,
   the hunt settings editor, the chat window's Combat tab and Settings.
   Charcoal & Gold, tokens only (ART_DIRECTION §9): HUD panels sit in the
   2-art-px iron frame (radius 0), no glow, no gradient on controls. One text
   style (§10): --f-label headings, --f-ui body, never under --t-micro.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── The shared panel frame and controls ── */
/* FORGED STEEL for the HUD (2026-10-24): a read-only panel over the World is the quiet member of the family:
   the THIN steel frame (assets/ui/steel-frame-thin.png, 3 art px = 6 px), the HUD plate as its floor at the
   player's Window opacity (--hud-fill), no grain, its name in Cinzel over a dim gold rule. */
.hh-panel {
  display: flex; flex-direction: column;
  background: var(--hud-fill);
  border: 6px solid transparent;
  border-image: url('../../assets/ui/steel-frame-thin.png') 3 / 6px stretch;
  image-rendering: pixelated;
  font-size: var(--t-micro); color: var(--ink);
}
/* Over a busy ground at a low Window opacity the words keep a hard 1 px shadow under them (as the chat's lines do;
   never a blur). */
.hh-panel, .ht-bar, .hs-tally, .hw-alert, .hs-online { text-shadow: 0 1px 0 var(--world-shadow); }
.hh-panel-head { display: flex; align-items: center; gap: 6px; min-height: 32px; padding: 2px 6px; border-bottom: 2px solid var(--steel-rule); }
.hh-panel-title { flex: 1; margin: 0; font-family: var(--f-display); font-weight: 700; font-size: var(--t-micro); letter-spacing: .14em; color: var(--gold-2); }
.hh-panel-body { padding: 6px 8px 8px; }
/* Controls carry no box of their own (containment is earned, §9):
   · .hh-tool is a text command. Quiet ink, a panel wash on hover, and when it
     is a toggle the pressed one is gold with a 2 px gold underline, the same
     mark the launcher row and the character strip use for "this one".
   · .hh-seg is a choice sunk into a well: the well is the group (.hh-segs,
     .hh-step) or, for a lone toggle like Chase, the button itself. The pressed
     choice is lifted one rung (--bg-3) and underlined gold.
   · Inputs keep the one hairline: a field has to read as a place to type. */
.hh-tool, .hh-seg {
  min-height: 30px; padding: 0 10px;
  border: 0; border-bottom: 2px solid transparent; border-radius: 0;
  background: none; color: var(--ink-2);
  font-family: var(--f-ui); font-weight: 700; font-size: var(--t-micro);
  font-variant-numeric: lining-nums;
  cursor: pointer;
}
.hh-tool:hover:not(:disabled), .hh-seg:hover:not(:disabled) { color: var(--ink); background: var(--surf-panel); }
.hh-tool:focus-visible, .hh-seg:focus-visible, .hh-select:focus-visible, .hh-num:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: 1px; }
.hh-tool[aria-pressed="true"], .hh-seg[aria-pressed="true"] { color: var(--gold-2); border-bottom-color: var(--gold); }
.hh-tool:disabled, .hh-seg:disabled, .hh-select:disabled, .hh-num:disabled { opacity: .5; cursor: default; }
.hh-tool .hs-glyph { width: 18px; height: 18px; }
.hh-tool { white-space: nowrap; }
.hh-tool:has(.hs-glyph) { display: inline-grid; place-items: center; min-width: 32px; padding: 0 6px; color: var(--ink-3); }
.hh-select, .hh-num {
  min-height: 30px; padding: 0 6px;
  border: 1px solid var(--line-soft); border-radius: var(--r-sm);
  background: var(--bg-0); color: var(--ink);
  font-family: var(--f-ui); font-size: var(--t-micro); font-variant-numeric: lining-nums;
}
.hh-num { width: 64px; }
.hh-segs, .hh-step, .hh-seg { background: var(--bg-1); box-shadow: var(--steel-well); }
.hh-segs .hh-seg, .hh-step .hh-seg { background: none; box-shadow: none; }
.hh-segs .hh-seg[aria-pressed="true"], .hh-seg[aria-pressed="true"], .hh-seg[aria-pressed="true"]:hover:not(:disabled) { background: var(--bg-3); }
.hh-segs { display: inline-flex; }
.hh-step { display: inline-flex; align-items: center; }
.hh-step .hh-seg { min-width: 30px; padding: 0; }
.hh-step-val { min-width: 24px; text-align: center; font-weight: 700; font-variant-numeric: lining-nums tabular-nums; }
.hh-intent-msg { margin: 0; min-height: 0; font-size: var(--t-micro); color: var(--ink-3); }
.hh-intent-msg:empty { display: none; }
.is-pending .hh-intent-msg { color: var(--ink-2); }
.hh-empty { display: none; margin: 0; color: var(--ink-3); }
.hh-icon { width: 32px; height: 32px; image-rendering: pixelated; display: inline-grid; place-items: center; flex: none; }
.hh-icon.is-glyph .hs-glyph { width: 20px; height: 20px; color: var(--ink-3); }

/* ── Gauges: a sunk bar with its number on it ── */
/* The track is the same well as a bar slot, so an empty stretch still reads as a bar. */
.hh-gauge { position: relative; display: block; height: 18px; background: var(--bg-0); box-shadow: var(--steel-well); overflow: hidden; }
.hh-gauge-fill { position: absolute; top: 0; left: 0; bottom: 0; width: 0; background: var(--ink-3); }
.hh-gauge.is-hp .hh-gauge-fill { background: var(--hud-fill-hp); }
.hh-gauge.is-mana .hh-gauge-fill { background: var(--gem); }
.hh-gauge.is-stamina .hh-gauge-fill { background: var(--hud-fill-stamina); }
.hh-gauge.is-xp .hh-gauge-fill { background: var(--gold-3); }
.hh-gauge-text { position: relative; display: block; padding: 0 6px; font-style: normal; font-size: var(--t-micro); line-height: 18px; font-weight: 700; color: var(--ink); paint-order: stroke fill; -webkit-text-stroke: 3px var(--bg-0); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; }

/* ── Top bar ── */
.ht-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 2px 4px 2px 8px; background: var(--hud-fill); border: 6px solid transparent; border-image: url('../../assets/ui/steel-frame-thin.png') 3 / 6px stretch; image-rendering: pixelated; }
/* The ground is named as a place is (ART_DIRECTION §10): Cinzel in gold. */
.ht-ground { font-family: var(--f-display); font-weight: 700; font-size: var(--t-small); letter-spacing: .08em; color: var(--gold-2); white-space: nowrap; }
.ht-clock { font-variant-numeric: lining-nums tabular-nums; color: var(--ink-2); font-size: var(--t-micro); white-space: nowrap; padding-right: 6px; margin-right: 2px; border-right: 2px solid var(--steel-sep); }
.ht-bar .hh-intent-msg { max-width: none; flex-basis: 100%; }
/* The pending leave's countdown beside Leave hunt: gold label text (the bar's own ground-name ink), tabular seconds. */
.ht-leaving { font-family: var(--f-label); font-weight: 700; font-size: var(--t-small); color: var(--gold-2); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; }

/* ── Party board ── */
/* It ends above the action bar and scrolls inside (--hs-room, hud-room.js; the phone's own cap is below). */
.hp-party { width: 250px; max-height: var(--hs-room, none); }
.hp-party .hs-wfold { display: none; }
.hp-party .hh-panel-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.hp-party.is-empty .hh-empty { display: block; }
.hp-members { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.hp-m { display: flex; gap: 8px; align-items: flex-start; }
.hp-portrait { width: 36px; height: 36px; flex: none; display: grid; place-items: center; border-radius: 50%; background: var(--bg-1); border: 2px solid var(--line); color: var(--ink-2); }
.hp-m.is-self .hp-portrait { border-color: var(--gold); color: var(--gold-2); }
.hp-portrait .hs-glyph { width: 20px; height: 20px; }
.hp-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.hp-line { display: flex; align-items: baseline; gap: 6px; }
.hp-name { flex: 0 1 auto; min-width: 4em; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-role, .hp-state { overflow: hidden; text-overflow: ellipsis; }
.hp-role, .hp-lv, .hp-state { font-size: var(--t-micro); color: var(--ink-3); white-space: nowrap; }
.hp-lv { margin-left: auto; }
.hp-state:empty { display: none; }
.hp-line.is-sub { gap: 8px; margin-top: -2px; }
.hp-state { color: var(--gold-2); }
.hp-lead { display: none; color: var(--gold); }
.hp-lead.is-on { display: inline-flex; }
.hp-lead .hs-glyph { width: 14px; height: 14px; }
.hp-stats { display: none; grid-template-columns: auto 1fr auto 1fr; gap: 0 6px; margin: 2px 0 0; font-size: var(--t-micro); }
.hp-party.is-expanded .hp-stats { display: grid; }
.hp-stats dt { color: var(--ink-3); }
.hp-stats dd { margin: 0; font-weight: 700; font-variant-numeric: lining-nums tabular-nums; }
/* The tank's turn at holding the pack (bug #59): its own line under the role; the holder's in the state gold. */
.hp-turn { margin: 0; font-size: var(--t-micro); color: var(--ink-3); }
.hp-turn.is-holding { color: var(--gold-2); }
.hp-turn:empty { display: none; }
.hp-tanks { margin: 8px 0 0; font-size: var(--t-micro); color: var(--ink-2); line-height: 1.4; }
.hp-tanks:empty { display: none; }
/* Who holds the pack (party-hold.js): the leader's switch and its tanks; the others see it read-only, at full ink. */
.hp-hold { margin: 8px 0 0; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.hp-hold[hidden], .hp-hold-tanks[hidden] { display: none; }
.hp-hold-label { margin: 0; font-size: var(--t-micro); color: var(--ink-3); }
.hp-hold-tanks { flex-wrap: wrap; max-width: 100%; }
.hp-hold-narrow { display: none; }
.hp-hold.is-read .hh-seg:disabled { opacity: 1; }
.hp-hold-warn { margin: 4px 0 0; font-size: var(--t-micro); color: var(--red); }
.hp-hold-warn:empty { display: none; }
/* "Leave if anyone leaves the hunt or dies" (party-leave.js): the viewer's own row only, under its gauges; it wraps in the phone's 200 px board. */
.hp-together { display: flex; align-items: flex-start; gap: 6px; margin-top: 3px; font-size: var(--t-micro); line-height: 1.3; color: var(--ink-2); cursor: pointer; }
.hp-together[hidden] { display: none; }
.hp-together input { flex: none; margin: 2px 0 0; accent-color: var(--gold); }
.hp-together input:disabled { cursor: default; }
.hp-together input:disabled + .hp-together-text { color: var(--ink-3); }
.hp-foot { margin: 8px 0 0; padding-top: 6px; border-top: 2px solid var(--steel-sep); font-size: var(--t-micro); color: var(--ink-3); }
.hp-party.is-empty .hp-foot { display: none; }
.hp-acts { display: flex; gap: 6px; margin-top: 8px; }
.hp-acts.is-off { display: none; }
.hp-kick { margin-left: auto; }
.hp-m.is-away { opacity: .7; }
.hp-msg:empty { display: none; }

/* ── Analyzer ── */
/* --hs-room (shell.js roomForStack): the height that leaves the Tally stacked under it clear of the action bar. */
.ha-analyzer { width: 290px; max-height: min(560px, calc(100vh - 200px), var(--hs-room, 100vh)); }
/* Its close is the phone's (no HUD panel carries one on a desktop, where Hunt details and HUD layout hide it). */
.ha-close { display: none; }
/* Folded (widget-move.js): the title row alone, its fold a plus; the stacked Tally rises under it. */
.is-folded > .ha-analyzer > .hh-panel-body { display: none; }
.is-folded > .ha-analyzer > .hh-panel-head { border-bottom: 0; }
.ha-analyzer .hh-panel-body { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.ha-scope { display: inline-flex; gap: 2px; }
.ha-main > .ha-scope { align-self: center; margin-bottom: 6px; }
.ha-scope .hh-tool { padding: 0 6px; }
.ha-analyzer:not(.has-party) .ha-scope { display: none; }
.ha-wait, .ha-ended { display: none; margin: 0 0 6px; color: var(--ink-2); line-height: 1.35; }
.ha-analyzer.is-waiting .ha-wait { display: block; }
.ha-analyzer.is-waiting .ha-main { display: none; }
.ha-analyzer.is-ended .ha-ended { display: block; color: var(--gold-2); }
.ha-main { display: flex; flex-direction: column; min-height: 0; }
.ha-clocks { display: flex; justify-content: space-around; margin-bottom: 6px; text-align: center; }
.ha-clocks small { display: block; font-family: var(--f-label); font-size: var(--t-micro); color: var(--ink-3); letter-spacing: .04em; }
.ha-clocks b { font-variant-numeric: lining-nums tabular-nums; }
.ha-tabs, .hc-tabs { display: flex; gap: 2px; margin-bottom: 6px; border-bottom: 1px solid var(--line-soft); }
/* The analyzer's tabs and sections part on the steel separator (2 px, one art px). */
.ha-tabs { border-bottom: 2px solid var(--steel-sep); }
.ha-tabs .ha-tab { margin-bottom: -2px; padding: 0 4px; }
.ha-tab { flex: 1; min-height: 30px; margin-bottom: -1px; padding: 0 10px; border: 0; border-bottom: 2px solid transparent; background: none; color: var(--ink-3); font-family: var(--f-label); font-weight: 700; font-size: var(--t-micro); letter-spacing: .04em; cursor: pointer; }
.hc-tabs .ha-tab { flex: none; }
.ha-tab:hover { color: var(--ink); }
.ha-tab:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: -2px; }
.ha-tab[aria-selected="true"] { color: var(--gold-2); border-bottom-color: var(--gold); }
.ha-scroll { overflow: auto; min-height: 0; }
.ha-sec { border-top: 2px solid var(--steel-sep); }
.ha-sec-head { margin: 0; }
.ha-fold { width: 100%; min-height: 30px; padding: 0; border: 0; background: none; text-align: left; color: var(--ink-3); font-family: var(--f-label); font-weight: 700; font-size: var(--t-micro); letter-spacing: .04em; cursor: pointer; }
.ha-fold::after { content: '\25BE'; float: right; }
.ha-sec.is-folded .ha-fold::after { content: '\25B8'; }
.ha-sec.is-folded .ha-sec-body { display: none; }
.ha-analyzer:not([data-tab]) .ha-sec:not([data-tab="session"]),
.ha-analyzer[data-tab="session"] .ha-sec:not([data-tab="session"]),
.ha-analyzer[data-tab="training"] .ha-sec:not([data-tab="training"]),
.ha-analyzer[data-tab="taken"] .ha-sec:not([data-tab="taken"]),
.ha-analyzer[data-tab="dealt"] .ha-sec:not([data-tab="dealt"]) { display: none; }
.ha-stats { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; margin: 0 0 6px; }
.ha-stats[hidden] { display: none; }
.ha-stats dt { color: var(--ink-2); }
.ha-stats dd { margin: 0; font-weight: 700; text-align: right; font-variant-numeric: lining-nums tabular-nums; }
.ha-stats dd.is-loss { color: var(--red); }
.ha-list { margin: 0 0 6px; padding: 0; list-style: none; }
.ha-line { display: flex; align-items: center; gap: 6px; min-height: 32px; }
.ha-ico:empty, .ha-eta:empty { display: none; }
.ha-name { flex: 1; min-width: 0; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ha-count, .ha-eta { color: var(--ink-3); font-variant-numeric: lining-nums tabular-nums; }
.ha-val { font-weight: 700; font-variant-numeric: lining-nums tabular-nums; }
.ha-none { display: none; margin: 0 0 6px; color: var(--ink-3); }
.ha-none.is-on { display: block; }

/* ── The action bar: vitals, 2 x 10 priority slots, the set's plaque ── */
/* AN OPEN TOOLTIP, DROP MENU OR PANEL SHEET IS ON TOP (v0.2.23 gate: the alert stack drew over the slot's name
   and why). The bar's widget rises over its sibling widgets' own cards (the hunt bar's pointer is z 5), and the
   world HUD over the screen layer (.hs-screen, z 6: the alerts and the launcher row) while one is open and no
   window is: an open window (Configure action above all) stays over the bar. */
.hs-widget:has(.hb-tip.is-on, .hb-drop.is-on, .hb-plaque.is-open, .hb-buy.is-on) { z-index: 6; }
.hs-shell:not(:has(.hs-win:not(.is-leaving))) > .hs-hud:has(.hb-tip.is-on, .hb-drop.is-on, .hb-plaque.is-open, .hb-buy.is-on) { z-index: 7; }
/* THE BAR IS ONE FORGED OBJECT (Tyler 10-22: "dorky, no art to it"; 10-25: keep the layout, a smooth ring, the fight
   controls back on the right, more gold, bigger icons). A 6-art-px iron plate (bar-plate.png, tools/make-hud-bar-art.mjs)
   with a gold rule along its top edge (--steel-rule, a window heading's rule); the slots are wells sunk into it
   (--steel-well, one art px deep). The plate is opaque so the world never reads through the wells.
   A DESKTOP NEVER GIVES WAY TO THE PHONE (Tyler 10-25): the phone has its own arrangement under the phone query. */
.hb-bar { position: relative; display: flex; align-items: center; gap: 6px; padding: 2px 4px; background: var(--bg-0); border: 12px solid transparent; border-image: url('../../assets/ui/bar-plate.png') 6 / 12px stretch; image-rendering: pixelated; box-shadow: inset 0 2px 0 var(--steel-rule); }
/* Slots | hub | slots | fight panel: the markup puts the hub first (the phone's order), the desktop orders it between. */
.hb-grid { display: contents; }
.hb-grid > .hb-slots:first-child { order: 1; }
.hb-hub { order: 2; }
.hb-grid > .hb-slots:last-child { order: 3; }
.hb-plaque { order: 4; }
/* THE SLOT SIZE (Tyler 10-25: "making the icons a bit bigger so people can see what they are"): a 32 px pixel icon at
   x2 (64 px, whole-number scale, ART_DIRECTION §3) in a 68 px well, so the bar spends its width on the art. The size
   follows the screen between a 40 px well (a narrow desktop) and 68 px, reaching 44 px at 1024 so the bar fits the World in any font (friends' panel): twelve wells wide (ten slots, Food,
   Charm) plus 464 px of everything else, so it fits from 1280 px (a Steam Deck) up with 68 px wells, and the icon
   inside always snaps to a whole scale of its 32 art px (round(down, ..., 32px)): x2 in a 68 well, x1 below it. */
.hb-slots { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(5, clamp(40px, calc(9.375vw - 52px), 68px)); grid-auto-rows: clamp(40px, calc(9.375vw - 52px), 68px); gap: 4px; }
.hb-slot { position: relative; display: grid; place-items: center; cursor: pointer; background: var(--bg-2); box-shadow: var(--steel-well); }
.hb-slot:hover { background: var(--bg-3); }
.hb-slot:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: 1px; }
.hb-slot.is-drop { outline: 2px solid var(--gold); outline-offset: -2px; }
.hb-slot-ico { width: 100%; height: 100%; display: grid; place-items: center; }
.hb-slot .hh-icon, .hb-socket-ico .hh-icon { width: round(down, 100% - 4px, 32px); height: round(down, 100% - 4px, 32px); }
.hb-slot .hh-icon.is-glyph .hs-glyph { width: 50%; height: 50%; color: var(--ink-2); }
.hb-slot small { position: absolute; font-size: var(--t-micro); font-weight: 700; line-height: 1; font-variant-numeric: lining-nums tabular-nums; paint-order: stroke; -webkit-text-stroke: 3px var(--bg-0); }
/* Gold where it earns its place: the slot's number is brass (it is the priority order); the count stays white (data). */
.hb-slot .hb-n { top: 3px; left: 4px; color: var(--gold-3); }
.hb-count { bottom: 3px; right: 4px; color: var(--ink); font-size: var(--t-small); }
.hb-warn { display: none; position: absolute; top: 3px; right: 5px; font-size: var(--t-small); line-height: 1; color: var(--gold-2); paint-order: stroke; -webkit-text-stroke: 3px var(--bg-0); }
.hb-slot.is-blocked .hb-warn { display: block; }
/* An empty well is a dark hole with a gold "+": a pixel cross (2 px strokes, the x2 grid), brighter under the pointer. */
.hb-plus { display: none; position: relative; width: 18px; height: 18px; }
.hb-plus::before, .hb-plus::after { content: ''; position: absolute; background: var(--gold-3); }
.hb-plus::before { left: 8px; top: 0; width: 2px; height: 18px; }
.hb-plus::after { left: 0; top: 8px; width: 18px; height: 2px; }
.hb-slot.is-empty { background: var(--bg-1); }
.hb-slot.is-empty .hb-plus { display: block; }
.hb-slot.is-empty .hb-n { opacity: .6; }
.hb-slot.is-empty:hover { background: var(--bg-2); }
.hb-slot.is-empty:hover .hb-plus::before, .hb-slot.is-empty:hover .hb-plus::after, .hb-slot.is-empty:focus-visible .hb-plus::before, .hb-slot.is-empty:focus-visible .hb-plus::after { background: var(--gold-2); }
.hb-slot.is-off .hb-slot-ico { opacity: .35; }
.hb-slot.is-off::after { content: ''; position: absolute; left: 8%; right: 8%; top: calc(50% - 2px); height: 4px; background: var(--red); transform: rotate(-45deg); }
/* THE FIGHT PANEL at the far right (Tyler 10-19, 10-25): the setup, its target, stance, chase and distance, each in
   view; the sliders fold out what does not fit (the gold to keep) above the bar's end. A groove cut down the plate
   (bar-socket.png's shadowed wall) parts it from the slots. */
.hb-plaque { position: relative; align-self: stretch; width: 232px; display: flex; flex-direction: column; justify-content: center; gap: 4px; padding-left: 10px; border-left: 4px solid transparent; border-image: url('../../assets/ui/bar-socket.png') 2 / 0 0 0 4px stretch; image-rendering: pixelated; }
.hb-pl-row { display: flex; align-items: center; gap: 6px; min-height: 30px; }
.hb-pl-more { display: contents; }
.hb-pl-fold { position: absolute; right: -16px; bottom: calc(100% + 20px); width: 284px; display: flex; flex-direction: column; gap: 6px; padding: 6px 10px 10px; z-index: 3;
  background: var(--modal-bg); border: 8px solid transparent; border-image: url('../../assets/ui/frame-iron.png') 4 / 8px stretch; image-rendering: pixelated;
  transform: translateY(8px); visibility: hidden; transition: transform 120ms ease-out, visibility 0s linear 120ms; }
.hb-plaque.is-open .hb-pl-fold { transform: none; visibility: visible; transition: transform 120ms ease-out; }
.hb-plaque .hb-more { display: inline-grid; }
.hb-plaque.is-open .hb-more { color: var(--gold-2); }
.hb-pl-head { display: flex; align-items: center; justify-content: space-between; min-height: 30px; font-family: var(--f-label); font-size: var(--t-micro); letter-spacing: .04em; color: var(--ink-3); }
.hb-label { flex: none; font-family: var(--f-label); font-size: var(--t-micro); color: var(--ink-3); letter-spacing: .04em; }
.hb-pl-note { margin: 0; font-size: var(--t-micro); color: var(--ink-2); }
/* The setup in use is the panel's title: its name in gold, set as a heading (Forged Steel's Cinzel). */
.hb-set { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--gold-2); font-family: var(--f-display); font-weight: 700; letter-spacing: .04em; }
.hb-pl-row .hh-select { flex: 1; min-width: 0; }
.hb-stance { display: flex; width: 100%; }
/* each its own width: three equal thirds cut "Offensive" and "Defensive" to an ellipsis at 216 px (first-hour play 2026-10-31) */
.hb-stance .hh-seg { flex: 1 1 auto; min-width: 0; padding: 0 1px; font-size: var(--t-micro); font-size-adjust: var(--f-ui-aspect); letter-spacing: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hb-dist { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.hb-pl-row .hb-gold { flex: 1; min-width: 0; text-align: right; font-variant-numeric: lining-nums tabular-nums; }
/* The status line floats above the panel: a message coming or going never shifts a control under the pointer. */
.hb-plaque .hh-intent-msg { position: absolute; left: 0; right: 0; bottom: calc(100% + 20px); margin: 0; padding: 2px 6px; font-size: var(--t-micro); background: var(--world-hud-bg); pointer-events: none; }
.hb-plaque .hh-intent-msg:empty { display: none; }
/* Why a slot cannot fire: a small glyph on the slot, its words first in the tooltip (action-facts.js reasonOf). */
/* Above the struck slot's red line (.hb-slot.is-off::after). */
.hb-why { position: absolute; z-index: 1; left: 3px; bottom: 3px; width: 22px; height: 22px; display: grid; place-items: center; pointer-events: none; }
.hb-why:not(:empty) { background: var(--bg-0); border-radius: 50%; box-shadow: inset 0 0 0 1px var(--steel); }
.hb-why .hs-glyph { width: 16px; height: 16px; color: var(--gold-2); }
.hb-slot.is-wait .hb-slot-ico { opacity: .6; }
/* A cooling slot (the sim's ember): a veil, an ember rising from the bottom as the cooldown runs out, the seconds left. */
.hb-cd { display: none; position: absolute; inset: 2px; background: var(--hud-cool-veil); pointer-events: none; }
.hb-slot.is-cooling .hb-cd { display: block; }
.hb-cd-ember { position: absolute; left: 0; right: 0; bottom: 0; height: 0; background: var(--hud-ember); box-shadow: inset 0 1px 0 var(--hud-ember-edge); }
.hb-cd-s { position: absolute; inset: 0; display: grid; place-items: center; font-size: var(--t-lead); font-weight: 800; color: var(--hud-ember-ink); paint-order: stroke; -webkit-text-stroke: 3px var(--bg-0); font-variant-numeric: lining-nums tabular-nums; }
/* The drop menu: onto an action, swap or insert; Escape or a press elsewhere cancels. */
.hb-drop { display: none; position: absolute; bottom: calc(100% + 6px); width: 240px; padding: 8px; flex-direction: column; gap: 4px; background: var(--modal-bg); border: 4px solid transparent; border-image: url('../../assets/ui/frame-iron-thin.png') 2 / 4px stretch; image-rendering: pixelated; z-index: 3; }
.hb-drop.is-on { display: flex; }
.hb-drop-t { color: var(--ink); font-size: var(--t-small); }
.hb-drop .hh-tool { justify-content: flex-start; text-align: left; min-height: 34px; }
.hb-tip { display: none; position: absolute; bottom: calc(100% + 6px); width: 260px; padding: 8px 10px; background: var(--modal-bg); border: 4px solid transparent; border-image: url('../../assets/ui/frame-iron-thin.png') 2 / 4px stretch; image-rendering: pixelated; pointer-events: none; z-index: 2; }
.hb-tip.is-on { display: block; }
.hb-tip b { color: var(--ink); }
.hb-tip-n { float: right; font-size: var(--t-micro); color: var(--ink-3); }
.hb-tip p { margin: 3px 0 0; font-size: var(--t-micro); color: var(--ink-2); line-height: 1.4; }
.hb-tip hr { margin: 6px 0 0; border: 0; border-top: 1px solid var(--line-soft); }
.hb-tip .is-setup { color: var(--ink-3); }
.hb-tip .is-warn { color: var(--gold-2); }

/* ── The vitals hub (vitals-hub.js): HP and Food | the ring over stamina | MP and Charm ── */
.hb-hub { display: grid; grid-template-columns: auto 120px auto; grid-template-rows: auto 1fr auto; grid-template-areas: "hp medal mp" "food medal charm" "food stam charm"; column-gap: 4px; row-gap: 2px; align-self: stretch; justify-items: center; }
/* THE RING (Tyler 10-25: "the circle just needs to be smoothed out"; his call overrides the pixel-only rule for it):
   one smooth vector ring on its own 120-unit grid (vitals-hub.js), flat token colours, no ticks, no glow, no gradient.
   Steel bezel, a dark gauge channel with HP filling red up its left and mana blue up its right, the XP ring filling
   gold from the top, and the inner disc the words sit in. */
.hb-medal { grid-area: medal; align-self: start; position: relative; width: 120px; height: 120px; }
.hb-arcs { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.hb-ring-bezel { fill: var(--bg-2); stroke: var(--steel-btn); stroke-width: 2; }
.hb-ring-channel { fill: none; stroke: var(--bg-0); stroke-width: 10; }
.hb-arc-track { fill: none; stroke: var(--steel-sep); stroke-width: 8; }
.hb-arc { fill: none; stroke-width: 8; stroke-linecap: butt; }
.hb-arc.is-hp { stroke: var(--hud-fill-hp); }
.hb-arc.is-mana { stroke: var(--hud-mana-ink); }
.hb-ring-xp { fill: none; stroke: var(--steel-sep); stroke-width: 5; }
.hb-arc.is-xp { stroke: var(--gold-2); stroke-width: 5; }
.hb-ring-disc { fill: var(--bg-0); }
/* The words fit the disc for the widest they get ("XP 99%" under a 3-digit Level) in the widest fallback face, not only
   the one on screen: the wide XP line sits low where the disc is narrow, so the stack rides 4 px above centre (the short
   "Lv" above has the room) and the Level number's line box hugs its lining digits (PH-8, HS-27: v0.2.57 red when the
   10-25 curve put a 2-digit percent on the fixture). */
.hb-medal-in { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; line-height: 1; padding-bottom: 8px; pointer-events: none; }
.hb-lv-k, .hb-xp { font-size: var(--t-micro); font-weight: 700; color: var(--ink-2); font-variant-numeric: lining-nums tabular-nums; }
.hb-xp-k { font-style: normal; }
.hb-lv { font-family: var(--f-display); font-weight: 700; font-size: var(--t-num); line-height: .8; color: var(--gold-2); font-variant-numeric: lining-nums tabular-nums; }
/* "HP" over its number over its regen, beside the ring's upper half and toward it. */
.hb-read { display: flex; flex-direction: column; line-height: 1.15; font-variant-numeric: lining-nums tabular-nums; align-self: start; }
.hb-read.is-hp { grid-area: hp; align-items: flex-end; justify-self: end; }
.hb-read.is-mana { grid-area: mp; align-items: flex-start; justify-self: start; }
.hb-read-k { font-size: var(--t-micro); font-weight: 700; color: var(--ink-3); }
.hb-read-v { font-size: var(--t-small); font-weight: 700; }
.hb-read.is-hp .hb-read-v { color: var(--hud-hp-ink); }
.hb-read.is-mana .hb-read-v { color: var(--hud-mana-ink); }
.hb-read-r { font-size: var(--t-micro); color: var(--ink-3); }
.hb-stam { grid-area: stam; align-self: end; display: flex; align-items: center; gap: 4px; font-size: var(--t-micro); color: var(--ink-2); font-variant-numeric: lining-nums tabular-nums; }
.hb-stam .hs-glyph { width: 14px; height: 14px; color: var(--ink-3); }
/* THE STAMINA "+" (Tyler 10-25, stamina-buy.js): a small sunk well with a gold pixel cross after the timer (the bar's "+"
   language: press it to add). Its press target is 36 px; the -8 px margin keeps the line at the well's 20 px. */
.hb-stam-buy { position: relative; width: 36px; height: 36px; margin: -8px -8px -8px -4px; padding: 0; border: 0; background: none; cursor: pointer; display: grid; place-items: center; }
.hb-stam-buy > i { position: relative; width: 20px; height: 20px; background: var(--bg-1); box-shadow: var(--steel-well); }
.hb-stam-buy > i::before, .hb-stam-buy > i::after { content: ''; position: absolute; background: var(--gold); }
.hb-stam-buy > i::before { left: 9px; top: 5px; width: 2px; height: 10px; }
.hb-stam-buy > i::after { left: 5px; top: 9px; width: 10px; height: 2px; }
.hb-stam-buy:hover > i, .hb-stam-buy[aria-expanded="true"] > i { background: var(--bg-3); }
.hb-stam-buy:hover > i::before, .hb-stam-buy:hover > i::after, .hb-stam-buy[aria-expanded="true"] > i::before, .hb-stam-buy[aria-expanded="true"] > i::after { background: var(--gold-2); }
.hb-stam-buy:focus-visible { outline: none; }
.hb-stam-buy:focus-visible > i { outline: 2px solid var(--aqua-2); outline-offset: 1px; }
/* Its panel, from the bar over the stamina line: what one refill gives and its price (the server's quote), why it cannot
   be bought, the premium note for a hero without premium, Buy (the gold plate), the status line. */
.hb-buy { display: none; position: absolute; bottom: calc(100% + 6px); width: 280px; padding: 8px 10px 10px; flex-direction: column; gap: 4px; background: var(--modal-bg); border: 4px solid transparent; border-image: url('../../assets/ui/frame-iron-thin.png') 2 / 4px stretch; image-rendering: pixelated; z-index: 3; }
.hb-buy.is-on { display: flex; }
.hb-buy-do { display: flex; gap: 6px; }
.hb-buy-do > .hb-buy-go { flex: 1; }
.hb-buy-head { display: flex; align-items: center; gap: 8px; min-height: 30px; }
.hb-buy-head b { font-family: var(--f-display); font-size: var(--t-micro); letter-spacing: .1em; color: var(--gold-2); }
.hb-buy-now { flex: 1; font-size: var(--t-micro); color: var(--ink-2); font-variant-numeric: lining-nums tabular-nums; }
.hb-buy p { margin: 0; font-size: var(--t-micro); line-height: 1.35; color: var(--ink-2); }
.hb-buy p:empty { display: none; }
.hb-buy .hb-buy-quote { color: var(--ink); }
.hb-buy .hb-buy-why { color: var(--gold-2); }
.hb-buy .hb-buy-premium { display: none; color: var(--ink-3); }
.hb-buy .hb-buy-premium.is-on { display: block; }
.hb-buy-go { align-self: stretch; margin-top: 4px; min-height: 34px; }
.hb-socket { display: flex; flex-direction: column; align-items: center; gap: 2px; align-self: end; }
.hb-socket.is-food { grid-area: food; }
.hb-socket.is-charm { grid-area: charm; }
.hb-socket-ico { width: clamp(40px, calc((100vw - 464px) / 12), 68px); height: clamp(40px, calc((100vw - 464px) / 12), 68px); display: grid; place-items: center; background: var(--bg-1); box-shadow: var(--steel-well); }
.hb-socket-ico .hh-icon.is-glyph .hs-glyph, .hb-socket-ico > .hs-glyph { width: 40%; height: 40%; color: var(--ink-3); }
.hb-socket-k { font-size: var(--t-micro); color: var(--ink-2); white-space: nowrap; }

/* ── Configure action: ONE slot as one sentence, its items as a sorted table (art direction 2026-10-21) ──
   One gold accent per state (the picked row, Save); warnings gold-2 text; refusals red text and outline;
   one hairline between regions and one sunken well for the list. No cards, pills, glow or gradient. */
.ca .ca-loading { display: none; margin: 0; font-size: var(--t-small); color: var(--ink-3); }
.ca.is-empty .ca-loading { display: block; }
.ca.is-empty .ca-form { display: none; }
.ca-form { display: flex; flex-direction: column; gap: 10px; }
/* The sentence and the list: no box of their own on a desktop; the phone sheet's one scroller (below). */
.ca-mid { display: contents; }
.ca-top { display: flex; align-items: center; gap: 12px; min-height: 40px; border-bottom: 1px solid var(--line-soft); }
.ca-rank { font-size: var(--t-small); color: var(--ink-3); white-space: nowrap; }
.ca-tabs { display: flex; flex: 1; justify-content: center; }
.ca-tab { min-height: 40px; padding: 0 16px; background: none; border: 0; border-bottom: 2px solid transparent; color: var(--ink-3); font: inherit; font-family: var(--f-label); font-weight: 700; font-size: var(--t-small); cursor: pointer; }
.ca-tab:hover:not(:disabled) { color: var(--ink); }
.ca-tab:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: -2px; }
.ca-tab[aria-selected="true"] { color: var(--gold-2); border-bottom-color: var(--gold); }
.ca-move { display: flex; gap: 4px; }
.ca-close, .ca-move-phone { display: none; }
/* The sentence is the editor: words in ink-2, the editable tokens gold-2 on a hairline. */
.ca-sentence { display: flex; flex-direction: column; gap: 4px; padding-bottom: 10px; border-bottom: 1px solid var(--line-soft); font-size: var(--t-lead); color: var(--ink-2); }
.ca-lead { margin: 0; line-height: 1.6; }
.ca-lead.is-blank .ca-verb { color: var(--ink-2); }
.ca-verb { color: var(--ink); }
.ca-item { padding: 0 2px; border: 0; border-bottom: 1px solid var(--line-soft); background: none; color: var(--gold-2); font: inherit; font-weight: 700; cursor: pointer; }
.ca-item:hover:not(:disabled) { border-bottom-color: var(--gold); }
.ca-item:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: 2px; }
.ca-item:empty { display: none; }
.ca-note { font-size: var(--t-small); color: var(--ink-3); }
.ca-conds { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 2px; }
.ca-cond { display: none; flex-wrap: wrap; align-items: center; gap: 4px; min-height: 40px; }
.ca-cond.is-on { display: flex; }
.ca-cond.is-error { outline: 1px solid var(--red); outline-offset: 2px; }
.ca-glue { color: var(--ink-2); }
.ca-token { min-height: 32px; padding: 0 2px; border: 0; border-bottom: 1px solid var(--line-soft); border-radius: 0; background: none; color: var(--gold-2); font: inherit; font-weight: 700; cursor: pointer; }
.ca-token:hover:not(:disabled) { border-bottom-color: var(--gold); }
.ca-token:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: 2px; }
.ca-token option { background: var(--bg-1); color: var(--ink); font-weight: 400; }
.ca-cond [data-f="subject"], .ca-cond [data-f="effect"], .ca-num { display: none; }
.ca-cond [data-f="subject"].is-on, .ca-cond [data-f="effect"].is-on { display: inline-block; }
.ca-num.is-on { display: inline-flex; align-items: center; gap: 2px; }
.ca-val { width: 48px; text-align: center; cursor: text; -moz-appearance: textfield; }
.ca-unit { color: var(--ink-2); }
.ca-step { min-width: 32px; padding: 0 6px; }
.ca-drop { margin-left: auto; }
.ca-add { align-self: flex-start; font-size: var(--t-small); }
.ca-warn { margin: 0; font-size: var(--t-small); color: var(--gold-2); line-height: 1.45; }
.ca-weapon, .ca-carry { margin: 0; font-size: var(--t-small); color: var(--gold-2); line-height: 1.45; }
.ca-warn:empty, .ca-note:empty, .ca-weapon:empty, .ca-d-warn { display: none; }
.ca-d-warn { color: var(--gold-2); }
/* The table beside the detail: one sunken well, only the list scrolls. */
.ca-pick { display: grid; grid-template-columns: 480px minmax(0, 1fr); gap: 16px; min-height: 0; }
.ca-well { position: relative; max-height: 380px; overflow-y: auto; overscroll-behavior: contain; background: var(--surf-sunken); }
.ca-run-label { margin: 0; padding: 8px 8px 2px; font-family: var(--f-label); font-size: var(--t-h3); font-variant: small-caps; letter-spacing: .04em; color: var(--ink-2); }
.ca-head, .ca-row { display: grid; grid-template-columns: 32px minmax(0, 1fr) 56px 56px 60px 60px; align-items: center; column-gap: 12px; padding: 0 8px; }
.ca-head { position: sticky; top: 0; z-index: 1; min-height: 28px; background: var(--surf-sunken); font-family: var(--f-label); font-size: var(--t-micro); color: var(--ink-3); }
.ca-head .ca-c { text-align: right; line-height: 1.1; }
.ca-row { width: 100%; min-height: 40px; border: 0; border-bottom: 1px solid var(--line-soft); background: none; color: var(--ink); font: inherit; font-size: var(--t-small); text-align: left; cursor: pointer; }
.ca-row:hover:not(:disabled), .ca-row:focus-visible { background: var(--surf-panel); outline: none; }
.ca-row.is-on { background: var(--bg-3); }
.ca-row.is-on .ca-name { color: var(--gold-2); }
.ca-row.is-on .ca-name::before { content: ''; display: inline-block; width: 6px; height: 6px; margin-right: 6px; border-radius: 50%; background: var(--gold); vertical-align: middle; }
.ca-row.is-none { color: var(--ink-3); }
.ca-row:disabled { cursor: default; }
.ca-ico, .ca-ico .hh-icon { width: 32px; height: 32px; }
.ca-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-body); font-family: var(--f-ui); }
.ca-namebox { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ca-lock { display: none; flex: none; width: 14px; height: 14px; color: var(--ink-3); }
.ca-lock svg { width: 14px; height: 14px; }
.ca-row.is-locked .ca-lock { display: inline-flex; }
.ca-row.is-locked .ca-name { color: var(--ink-3); }
.ca-c { text-align: right; font-variant-numeric: lining-nums tabular-nums; color: var(--ink-2); }
.ca-row .ca-c[data-c="0"] { color: var(--hud-hp-ink); }
.ca-row.is-mana .ca-c[data-c="0"] { color: var(--hud-mana-ink); }
.ca-row .ca-sort { color: var(--ink); font-weight: 700; }
.ca-row.is-store .ca-c[data-c="3"], .ca-row.is-none .ca-c { color: var(--ink-3); }
.ca-pinned { display: none; position: sticky; top: 0; z-index: 2; }
.ca-pinned.is-on { display: block; border-bottom: 1px solid var(--line-soft); }
.ca-pinned .ca-row { min-height: 32px; }
.ca-empty { margin: 0; padding: 12px 8px; font-size: var(--t-small); color: var(--ink-3); }
.ca-empty:empty { display: none; }
/* The detail: the hovered row against the pick, one fact a line; no boxes. */
.ca-detail { min-width: 0; display: flex; flex-direction: column; gap: 4px; font-size: var(--t-small); color: var(--ink-2); line-height: 1.45; }
.ca-detail p { margin: 0; }
.ca-d-head { display: flex; align-items: center; gap: 8px; }
.ca-d-icon:empty { display: none; }
.ca-d-name { font-size: var(--t-lead); color: var(--ink); }
.ca-vs { font-size: var(--t-micro); color: var(--ink-3); }
.ca-cmp { margin: 0; padding: 0; list-style: none; color: var(--ink); font-variant-numeric: lining-nums tabular-nums; }
.ca-cmp li:last-child { font-weight: 700; }
.ca-waste { color: var(--gold-2); }
.ca-src { padding-top: 6px; border-top: 1px solid var(--line-soft); }
.ca-eff, .ca-req { font-size: var(--t-micro); color: var(--ink-3); }
.ca-vs:empty, .ca-cmp:empty, .ca-waste:empty, .ca-src:empty, .ca-eff:empty, .ca-req:empty { display: none; }
.ca-runestore { display: none; padding-top: 6px; border-top: 1px solid var(--line-soft); }
.ca-runestore.is-on { display: block; }
.ca-rs-q { margin: 0 0 2px; color: var(--ink-2); }
.ca-rs-list { margin: 0; padding: 0; list-style: none; }
.ca-rs { width: 100%; min-height: 40px; padding: 0 8px; border: 0; border-bottom: 1px solid var(--line-soft); background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer; font-variant-numeric: lining-nums tabular-nums; }
.ca-rs:hover:not(:disabled) { background: var(--surf-panel); }
.ca-rs.is-on { background: var(--bg-3); color: var(--gold-2); }
.ca-msg { margin: 0; font-size: var(--t-small); color: var(--ink-2); }
.ca-msg:empty { display: none; }
.ca-msg.is-error { color: var(--red); }
/* The footer stays in reach while the body scrolls (the 922 x 423 sheet is short). */
.hc-foot { position: sticky; bottom: -12px; display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin: 0 -12px -12px; padding: 6px 12px 8px; border-top: 1px solid var(--line-soft); background: var(--bg-1); }
/* The gold plate of the one primary is shell.css's (Forged Steel). */

/* ── Chat: the Combat tab ── */
.hc-chat { display: flex; flex-direction: column; min-height: 260px; }
/* The lines come first (chat-combat.js): one row of filters, the type boxes opening over the log, no input below it. */
.hc-filters { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.hc-more summary { display: flex; align-items: center; list-style: none; }
.hc-more[open] summary { color: var(--gold-2); }
.hc-more .hc-types { position: absolute; z-index: 1; top: 100%; left: 0; right: 0; padding: 6px 4px; background: var(--bg-1); border-bottom: 2px solid var(--steel-sep); }
.hc-pane.is-combat.is-on ~ .hc-input, .hc-pane.is-combat.is-on ~ .hc-msg:empty { display: none; }
.hc-types { display: flex; flex-wrap: wrap; gap: 2px 10px; }
.hc-type { font-size: var(--t-micro); color: var(--ink-2); }
.hc-type input { accent-color: var(--gold); }
.hc-log { margin: 0; padding: 0; list-style: none; max-height: 340px; overflow: auto; border-top: 2px solid var(--steel-sep); }
.hc-line { padding: 3px 0; font-size: var(--t-micro); color: var(--ink-2); border-bottom: 1px solid var(--line-soft); }
.hc-line.is-taken, .hc-line.is-death { color: var(--red); }
.hc-line.is-heal { color: var(--green); }
.hc-line.is-loot, .hc-line.is-xp { color: var(--gold-2); }
/* A blow that did nothing is not a cost: half a fresh hero's blows taken miss, and red for them would hide the ones that hurt. */
.hc-line.is-quiet { color: var(--ink-3); }
.hc-none { margin-top: 8px; }
.hc-none.is-on { display: block; }

/* ── Chat: the channels, whispers and the input (src/shell/windows/chat.js) ── */
/* Tyler 2026-10-22: the chat sits over the World, so the World shows through it (--chat-bg); its lines keep a
   1 px shadow so they stay readable over a bright tile. Sized (desktop), the log takes the height the player gave it. */
.hs-win[data-hs-win="chat"] { background: var(--chat-bg); }
/* The chat keeps its own see-through plate (Tyler 10-22), not the window floor or the opacity setting. */
.hs-win[data-hs-win="chat"]::before { display: none; }
.hs-win[data-hs-win="chat"] .hc-log.is-talk .hc-line { text-shadow: 0 1px 0 var(--world-shadow); }
.hs-win.is-sized .hc-chat { flex: 1; min-height: 0; }
.hs-win.is-sized .hc-pane.is-on { min-height: 0; }
.hs-win.is-sized .hc-logs { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.hs-win.is-sized .hc-log { flex: 1; min-height: 0; max-height: none; }
/* The channel tabs sit on the windows' 2 px steel line (windows.css .hw-tabs), the shown one underlined gold. */
.hc-tabs { flex-wrap: wrap; border-bottom: 2px solid var(--steel-sep); }
.hc-tab { display: inline-flex; align-items: center; }
.hc-tab .ha-tab { position: relative; margin-bottom: -2px; padding: 0 9px; }
.hc-tab.is-whisper .ha-tab { font-style: italic; }
.hc-dot { display: none; position: absolute; top: 5px; right: 2px; width: 6px; height: 6px; border-radius: 50%; background: var(--gold-2); }
.ha-tab.is-unread .hc-dot { display: block; }
.ha-tab.is-unread { color: var(--ink); }
.hc-x { min-width: 22px; min-height: 26px; padding: 0; border: 0; background: none; color: var(--ink-3); font-size: var(--t-small); cursor: pointer; }
.hc-x:hover { color: var(--ink); }
.hc-pane { display: none; position: relative; flex: 1; min-height: 0; }
.hc-pane.is-on { display: flex; flex-direction: column; }
.hc-log.is-talk { display: none; flex: 1; min-height: 180px; border-top: 0; }
.hc-log.is-talk.is-on { display: block; }
.hc-log.is-talk .hc-line { padding: 2px 2px; border-bottom: 0; line-height: 1.4; color: var(--ink); overflow-wrap: anywhere; }
.hc-line.is-system { color: var(--gold-2); }
.hc-time { margin-right: 2px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.hc-name { padding: 0; border: 0; background: none; font: inherit; font-weight: 700; color: var(--ink-2); cursor: pointer; }
.hc-name:hover, .hc-name:focus-visible { text-decoration: underline; outline: none; }
.hc-name.is-tank { color: var(--chat-role-tank); }
.hc-name.is-melee_dps { color: var(--chat-role-melee); }
.hc-name.is-ranger { color: var(--chat-role-ranger); }
.hc-name.is-mage { color: var(--chat-role-mage); }
.hc-name.is-healer { color: var(--chat-role-healer); }
.hc-title { color: var(--ink-3); }
/* THE TOWN CRIER: a paid line stands apart at a glance, on a band of its own with the Crier's mark at its head. The band is solid, so its words read over any floor. */
.hc-log.is-talk .hc-line.is-crier { margin: 3px 0; padding: 4px 6px; border-left: 4px solid var(--gold); background: var(--chat-crier-band); color: var(--gold-2); font-weight: 700; }
.hc-line.is-crier .hc-time, .hc-line.is-crier .hc-tag, .hc-line.is-crier .hc-title { color: var(--ink-2); }
.hc-line.is-crier .hc-name { color: var(--gold-2); font-weight: 800; }
.hc-crier-mark { display: inline-block; margin-right: 2px; padding: 0 5px; background: var(--gold); color: var(--bg-0); font-family: var(--f-label); font-weight: 800; letter-spacing: .04em; text-shadow: none; }
.hc-crier-open { flex: none; }
.hc-crier-open[aria-expanded="true"] { color: var(--gold-2); }
.hc-crier-open[hidden], .hc-again[hidden] { display: none; }
.hc-crier { display: none; flex: none; padding-top: 4px; }
.hc-crier.is-on { display: block; }
.hc-crier-msg { margin: 0; font-size: var(--t-micro); color: var(--ink-2); }
/* the bar never takes the whole log: a few lines stay on screen, and the chat's own red line gives way while it's open */
.hc-chat.is-crying .hc-msg:empty { display: none; }
.hs-win.is-sized .hc-chat.is-crying .hc-pane.is-on { min-height: 52px; }
.hc-crier-do { display: flex; gap: 6px; margin-bottom: 2px; }
.hc-cry { flex: none; min-height: 32px; }
.hc-again { flex: 1; min-width: 0; min-height: 32px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.hc-tag { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.hc-role { display: inline-block; width: 11px; height: 11px; margin-left: 2px; vertical-align: -1px; }
.hc-role .hs-glyph { width: 100%; height: 100%; fill: currentColor; }
.hc-link { padding: 0; border: 0; background: none; font: inherit; color: var(--rar-common); cursor: help; }
.hc-link[class*="rar-"] { color: var(--pocket-rar); }
.hc-link:hover { text-decoration: underline; }
/* New messages: a square steel button floating over the log's foot. */
.hc-pill { position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%); min-height: 28px; padding: 0 12px; border: 2px solid var(--steel-btn); border-radius: 0; background: var(--bg-2); color: var(--gold-2); font-family: var(--f-label); font-weight: 700; font-size: var(--t-micro); cursor: pointer; box-shadow: 0 4px 10px color-mix(in srgb, var(--world-shadow) 50%, transparent); }
.hc-pill:hover { background: var(--bg-3); }
.hc-pill[hidden] { display: none; }
.hc-input { display: flex; gap: 6px; margin-top: 6px; }
.hc-field { flex: 1; min-width: 0; min-height: 32px; padding: 0 8px; color: var(--ink); font-family: var(--f-ui); font-size: var(--t-small); }
.hc-field:focus { outline: 2px solid var(--gold); outline-offset: -1px; }
.hc-field:disabled { color: var(--ink-3); }
.hc-field::placeholder { color: var(--ink-3); }
.hc-msg { min-height: 1em; margin: 3px 0 0; font-size: var(--t-micro); color: var(--red); }
.hw-menu-say { margin: 0; padding: 6px 8px 4px; max-width: 260px; font-size: var(--t-micro); color: var(--ink-2); line-height: 1.35; border-top: 1px solid var(--line-soft); }

/* ── Friends and Inspect ── */
.hf-add { display: flex; gap: 6px; }
.hf-name { flex: 1; min-width: 0; min-height: 30px; padding: 0 8px; color: var(--ink); font-family: var(--f-ui); font-size: var(--t-small); }
.hf-msg { min-height: 1em; margin: 4px 0 0; font-size: var(--t-micro); color: var(--ink-2); }
.hf-head { display: none; }
.hf-head.is-on { display: block; }
.hf-list { margin: 0; padding: 0; list-style: none; }
.hf-row { display: grid; grid-template-columns: 10px 1fr auto; grid-template-rows: auto auto; align-items: center; column-gap: 8px; padding: 5px 2px; }
.hf-row > .hf-who { grid-column: 2; }
.hf-list.is-in .hf-row, .hf-list.is-out .hf-row { grid-template-columns: 1fr auto; }
.hf-list.is-in .hf-who, .hf-list.is-out .hf-who { grid-column: 1; }
.hf-dot { grid-row: 1 / 3; width: 8px; height: 8px; border-radius: 50%; background: var(--ink-3); }
.hf-row.is-online .hf-dot { background: var(--green); }
.hf-who { color: var(--ink); }
.hf-doing { grid-column: 2; font-size: var(--t-micro); color: var(--ink-3); }
.hf-row.is-online .hf-doing { color: var(--ink-2); }
.hf-acts { grid-column: 3; grid-row: 1 / 3; display: flex; gap: 4px; }
.hf-list.is-in .hf-acts, .hf-list.is-out .hf-acts { grid-column: 2; }
.hi-line { margin: 0 0 6px; font-size: var(--t-micro); color: var(--ink-2); }
.hi-gear { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; }
.hi-item { display: grid; grid-template-columns: 36px 1fr; grid-template-rows: auto auto; column-gap: 6px; align-items: center; cursor: help; }
.hi-item .hh-icon { grid-row: 1 / 3; width: 32px; height: 32px; image-rendering: pixelated; }
.hi-slot { font-size: var(--t-micro); color: var(--ink-3); }
.hi-name { font-size: var(--t-small); font-weight: 400; color: var(--ink); }
.hs-blocks { margin: 0; padding: 0; list-style: none; }
.hs-block { display: flex; align-items: center; justify-content: space-between; padding: 3px 2px; color: var(--ink); }

/* ── Settings ── */
.hs-sub { margin: 12px 0 4px; }
.hs-sub:first-child { margin-top: 0; }
.st-find { margin-bottom: 8px; }
.st-search { width: 100%; box-sizing: border-box; min-height: 36px; padding: 0 10px; color: var(--ink); font: inherit; font-size: var(--t-small); }
.st-search:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: 1px; }
.st-body { display: flex; gap: 12px; align-items: flex-start; }
.st-tabs { flex: none; width: 124px; display: flex; flex-direction: column; border-right: 2px solid var(--steel-sep); }
.st-tab { min-height: 36px; padding: 0 10px; border: 0; border-left: 2px solid transparent; background: none; text-align: left; color: var(--ink-2); font-family: var(--f-label); font-weight: 700; font-size: var(--t-small); cursor: pointer; }
.st-tab:hover { color: var(--ink); }
/* The page shown: lifted, its gold bar at the left (the Forged Steel picked row). */
.st-tab.is-on { color: var(--gold-2); border-left: 4px solid var(--gold); background: var(--fill-3); }
.st-tab:focus-visible { outline: 2px solid var(--aqua-2); outline-offset: -2px; }
.st-pages { flex: 1; min-width: 0; }
.st-back { display: none; }
.st-row { padding: 6px 0; border-top: 1px solid var(--line-soft); }
.st-line { display: flex; align-items: center; gap: 10px; min-height: 28px; }
label.st-line { cursor: pointer; }
.st-label { flex: 1; font-size: var(--t-small); color: var(--ink-2); }
/* Help's notes (how the game works) are read, not set: the heading and its text always show. */
.st-row.is-note .st-label { display: block; margin: 0; font-family: var(--f-label); font-weight: 700; color: var(--ink); }
.st-row.is-note .st-help { display: block; color: var(--ink-2); }
.st-row input[type="checkbox"], .st-row input[type="range"] { accent-color: var(--gold); }
.st-select { min-height: 32px; color: var(--ink); }
.st-help { display: none; margin: 2px 0 0; font-size: var(--t-micro); color: var(--ink-3); line-height: 1.4; }
.st-row:hover .st-help, .st-row:focus-within .st-help { display: block; }

.hb-page, .ca-why { display: none; }
/* ── Phone, landscape: compact bar, one swipeable slot row, plaque to the editor ── */
@keyframes ca-sheet { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (max-width: 540px), (max-height: 540px) and (max-width: 1024px) {
  /* The phone keeps its sheet as it was: opaque, so nothing of the bar under it reads through (see-through is desktop only). */
  .hs-win[data-hs-win="chat"] { background: var(--bg-1); }
  /* THE MESSAGE BOX STAYS ON THE SHEET (phone playtest 2026-10-31: at 667 px it started below the screen): the log gives
     way, its minimum heights are a desktop's, and the input stands thumb-sized at the sheet's foot. */
  .hs-win[data-hs-win="chat"] .hs-win-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
  .hs-win[data-hs-win="chat"] .hc-chat { flex: 1; min-height: 0; }
  .hs-win[data-hs-win="chat"] .hc-pane.is-on { min-height: 0; overflow: hidden; }
  .hs-win[data-hs-win="chat"] .hc-logs { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .hs-win[data-hs-win="chat"] .hc-log { flex: 1; min-height: 0; max-height: none; }
  .hc-input { flex: none; }
  .hc-field, .hc-send, .hc-crier-open { min-height: 40px; }
  .hc-msg:empty { display: none; }
  /* Why this slot will not fire, first thing on its sheet: a phone has no tooltip to read it in (configure-action.js). */
  .ca-why:not(:empty) { display: block; flex: none; margin: 4px 0 0; padding: 2px 8px; font-size: var(--t-micro); color: var(--gold-2); box-shadow: inset 4px 0 0 var(--gold); }
  /* SETTINGS BY TOUCH (QA 10-24: a press on the words did nothing, the boxes were 13 px, the slider 14 px tall):
     each control's line is its label (settings.js), 44 px tall; the boxes are 20 px; the slider's own target is
     44 px tall, its sunk 14 px track (shell.css's slider) and a larger plate drawn inside it. */
  .st-line { min-height: var(--tap); }
  .st-row input[type="checkbox"] { width: 20px; height: 20px; margin: 0; }
  .st-row input[type="range"] { height: var(--tap); background: none; box-shadow: none; }
  .st-row input[type="range"]::-webkit-slider-runnable-track { height: 14px; background: var(--bg-0); box-shadow: var(--steel-well); }
  .st-row input[type="range"]::-moz-range-track { height: 14px; background: var(--bg-0); box-shadow: var(--steel-well); }
  .st-row input[type="range"]::-webkit-slider-thumb { width: 16px; height: 22px; margin-top: -4px; }
  .st-row input[type="range"]::-moz-range-thumb { width: 16px; height: 22px; }
  .hp-party { width: 200px; }
  /* SOLO, THE PANEL STARTS FOLDED (phone panel v0.2.83: board, hunt bar and card covered 60% of a 245 px World, and a party of
     one says nothing the bar does not): its name and its plus, the width of those; hud-widgets.js says when. */
  .hp-party .hs-wfold { display: grid; margin: -2px -6px; }
  .is-folded > .hp-party { width: max-content; }
  .is-folded > .hp-party > .hh-panel-body, .is-folded > .hp-party [data-hs-act="expand"] { display: none; }
  .is-folded > .hp-party > .hh-panel-head { border-bottom: 0; }
  /* A party of two with the hold switch is 245 px tall: past the action bar's top at 390 px, so the bar pushed the
     board below the screen. It ends above the bar (at most 100 px tall, 2 px up) and scrolls inside. */
  .hp-party { max-height: calc(100vh - 160px); }
  .hp-portrait { width: 28px; height: 28px; }
  .hp-role { display: none; }
  /* The hold switch on one line in the phone's 200 px board: the short labels (party-hold.js holdHtml). */
  .hp-hold-wide { display: none; }
  .hp-hold-narrow { display: inline; }
  .hp-hold .hh-seg { white-space: nowrap; }
  /* THE PHONE'S OWN BAR (Tyler 10-25: "if it doesn't work for mobile then mobile needs its own bar"): one band at most
     96 px tall (the alerts dock above it, HS-22): the hub at its left (the ring, then HP, MP, stamina and food as four
     lines), the twenty slots as ONE block of two rows (1-10 over 11-20, the 32 px icons at x1 in 36 px wells) that a
     thumb swipes sideways when the screen is narrower than all ten columns, and the fight panel at its right in two
     rows: stance, then the setup, Chase and distance. The sliders slide out a sheet with the target and the gold. */
  /* The phone's plate is the window frame (frame-iron.png, 4 art px = 8 px): the desktop's 12 px plate costs height a
     375 px screen does not have. */
  .hb-bar { gap: 3px; padding: 0 2px; max-width: calc(100vw - 8px); border-width: 8px; border-image: url('../../assets/ui/frame-iron.png') 4 / 8px stretch; }
  .hb-hub, .hb-grid > .hb-slots:first-child, .hb-grid > .hb-slots:last-child { order: 0; }
  .hb-grid { order: 1; display: flex; gap: 2px; min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none; }
  .hb-grid::-webkit-scrollbar { display: none; }
  /* The slots' page press (action-bar.js): only where ten columns do not fit; a gold chevron, the bar's "+" gold. */
  .hb-page:not([hidden]) { order: 1; flex: none; display: grid; place-items: center; align-self: center; width: 36px; height: 74px; padding: 0; border: 0; background: var(--bg-1); color: var(--gold-2); font-family: var(--f-ui); font-size: var(--t-lead); font-weight: 700; line-height: 1; cursor: pointer; }
  .hb-page::before { content: '\203A'; }
  .hb-page.is-back::before { content: '\2039'; }
  .hb-plaque { order: 2; }
  /* The hub never gives way; the setup name truncates first (the plaque shrinks a hundred times faster), then the slots swipe. */
  .hb-hub { flex: none; }
  .hb-plaque { flex-shrink: 100; }
  .hb-slots { grid-template-columns: repeat(5, 36px); grid-auto-rows: 36px; gap: 2px; flex: none; }
  .hb-slot { scroll-snap-align: start; }
  .hb-slot .hb-n { top: 1px; left: 2px; font-size: var(--t-micro); }
  .hb-count { bottom: 1px; right: 2px; font-size: var(--t-micro); }
  .hb-warn { top: 1px; right: 3px; font-size: var(--t-micro); }
  .hb-plus { width: 10px; height: 10px; }
  .hb-plus::before { left: 4px; height: 10px; }
  .hb-plus::after { top: 4px; width: 10px; }
  .hb-why { left: 1px; bottom: 1px; width: 18px; height: 18px; }
  .hb-why .hs-glyph { width: 14px; height: 14px; }
  .hb-slot.is-off::after { top: calc(50% - 1px); height: 2px; }
  .hb-cd-s { font-size: var(--t-small); }
  /* The hub: the ring, and beside it four lines (HP, MP, stamina, food). The Charm socket (empty until charms exist)
     and the regen lines stay on the desktop; the ring carries the level and the XP % (its words are its title). */
  .hb-hub { grid-template-columns: 72px auto; grid-template-rows: repeat(4, auto); grid-template-areas: "medal hp" "medal mp" "medal stam" "medal food"; column-gap: 4px; row-gap: 0; align-content: center; align-self: center; justify-items: start; }
  .hb-medal { width: 72px; height: 72px; align-self: center; }
  .hb-lv-k, .hb-xp-k { display: none; }
  /* no "Lv" over the number here, so nothing to ride up for: the stack sits on centre */
  .hb-medal-in { padding-bottom: 0; }
  .hb-lv { font-size: var(--t-lead); }
  .hb-xp { font-size-adjust: var(--f-ui-aspect); }
  .hb-read { flex-direction: row; align-items: baseline; gap: 4px; line-height: 1.15; }
  .hb-read.is-hp, .hb-read.is-mana { align-items: baseline; justify-self: start; align-self: auto; }
  .hb-read-v { font-size: var(--t-micro); }
  .hb-read-r { display: none; }
  .hb-stam { align-self: auto; justify-self: start; line-height: 1.15; }
  .hb-buy-go, .hb-buy .hh-tool { min-height: 40px; }
  .hb-socket.is-charm { display: none; }
  .hb-socket.is-food { flex-direction: row; align-self: auto; line-height: 1.15; }
  .hb-socket.is-food .hb-socket-ico { display: none; }
  /* The fight panel in two rows of thumb-sized controls: stance and Chase; the setup corner (its name, the saved
     setups, the sliders) and distance. */
  .hb-plaque { width: auto; align-self: center; display: grid; grid-template-columns: minmax(clamp(46px, calc((100vw - 667px) * .5), 64px), auto) auto auto auto auto; grid-template-rows: 36px 36px; gap: 3px 2px; grid-template-areas: "stance stance stance stance chase" "set ok more dist dist"; padding-left: 4px; }
  .hb-pl-row.is-set, .hb-pl-row.is-move { display: contents; }
  .hb-pl-row.is-set > .hb-label { display: none; }
  /* The setup's name is a press the height of its row (phone panel v0.2.83: 21 px tall, reading "Pre..."): one line where the
     screen has the width for it, two short ones at 667 px. */
  .hb-set { grid-area: set; align-self: stretch; font-family: var(--f-ui); font-size: var(--t-micro); letter-spacing: 0; line-height: 1.1; white-space: normal; }
  .hb-set .hs-name { width: 100%; height: 100%; }
  .hb-set .hs-name-t { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; white-space: normal; overflow-wrap: anywhere; }
  .hb-ok { grid-area: ok; }
  .hb-plaque .hb-more { grid-area: more; }
  .hb-pl-row.is-stance { grid-area: stance; min-height: 0; }
  .hb-chase { grid-area: chase; }
  .hb-dist { grid-area: dist; gap: 2px; margin-left: 0; }
  .hb-plaque .hh-tool, .hb-plaque .hh-seg { min-height: 36px; }
  .hb-stance .hh-seg { flex: 1 0 auto; padding: 0 clamp(2px, calc((100vw - 667px) / 30), 6px); }
  .hb-dist .hb-label { letter-spacing: 0; }
  .hb-dist .hh-step .hh-seg { min-width: 30px; }
  .hb-pl-more { position: fixed; top: 0; right: 0; bottom: 0; width: 280px; display: flex; flex-direction: column; justify-content: center; gap: 8px; padding: 12px; z-index: auto;
    background: var(--modal-bg); border: 0 solid transparent; border-left-width: 4px; border-image: url('../../assets/ui/frame-iron-thin.png') 2 / 4px stretch; image-rendering: pixelated;
    transform: translateX(100%); visibility: hidden; transition: transform 160ms ease-out, visibility 0s linear 160ms; }
  .hb-plaque.is-open .hb-pl-more { transform: none; visibility: visible; transition: transform 160ms ease-out; }
  .hb-pl-fold { display: contents; }
  .hb-pl-head { order: -1; color: var(--ink); font-family: var(--f-ui); font-size: var(--t-small); letter-spacing: 0; }
  .hb-pl-more .hb-pl-row, .hb-pl-more .hh-seg, .hb-pl-more .hh-select { min-height: 40px; }
  /* A full-screen window (Configure action): the alert stack (a screen widget, over the windows' layer) waits. */
  :root:has(.hs-win.is-modal:not(.is-leaving)) .hs-widget.is-alerts { visibility: hidden; }
  /* ...except that a side sheet leaves the World's half free, and an invite must reach a player reading one (panel
     2026-11-01: no toast, only a red 1): the stack stands beside the sheet instead. */
  :root:has(.hs-win:not(.is-modal):not(.is-leaving)) .hs-widget.is-alerts { transform: translateX(calc(-1 * min(400px, 48vw) - 8px)); }
  /* A short screen: the tooltip runs wide instead of tall, so it never climbs into the top strip. */
  .hb-tip { width: 440px; }
  /* CONFIGURE ACTION ON A PHONE: the whole screen under the icon row, in three bands. The top row (the slot, the
     tabs, the close) and the foot (Empty slot, Cancel, Save) never move; between them ONE scroller holds the sentence
     and the list, so the list has the band's whole height once the sentence has scrolled by (QA 10-24: at 922 x 423
     4 of 16 spells and 2 of 46 foods could be reached; at 667 x 375 Save and the close were off screen). The detail
     pane rides beside the list (sticky): the pick and its whole heal warning stay in view (HS-23). */
  /* width = min = max = 100%: the window manager writes an inline width (800 px) a plain width never beats, and
     with no max the sheet ran 133 px off a 667 px screen, Save and the close with it. */
  .hs-win[data-hs-win="configure-action"].is-modal { top: 0; left: 0; right: 0; bottom: 0; transform: none; width: 100%; min-width: 100%; max-width: 100%; height: 100%; max-height: none; border-width: 0; animation: ca-sheet 160ms ease-out both; }
  .hs-win[data-hs-win="configure-action"] .hs-win-head { display: none; }
  .hs-win[data-hs-win="configure-action"] .hs-win-body { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 0 8px; overflow: hidden; }
  .ca { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .ca-form { flex: 1; min-height: 0; gap: 4px; }
  .hs-win[data-hs-win="configure-action"] .ca-mid { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; overscroll-behavior: contain; }
  .ca-top { flex: none; gap: 6px; }
  .ca-tabs { justify-content: flex-start; }
  .ca-move { display: none; }
  .ca-close { display: grid; flex: none; margin-left: auto; width: var(--tap); height: var(--tap); }
  .ca-move-phone { display: flex; gap: 4px; margin-top: auto; padding-top: 6px; }
  /* The sentence spends one line less: "+ Add a condition" stands at the end of its first line. */
  .ca-sentence { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 8px; padding-bottom: 4px; }
  .ca-sentence > * { grid-column: 1 / -1; }
  .ca-sentence > .ca-lead { grid-column: 1; }
  .ca-sentence > .ca-add { grid-area: 1 / 2; align-self: center; }
  .ca-lead, .ca-cond { min-height: 40px; }
  .ca-warn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .ca-d-warn:not(:empty) { display: block; }
  .ca-pick { flex: none; align-items: start; grid-template-columns: minmax(0, 1fr) clamp(200px, 32%, 300px); gap: 10px; }
  /* The well is no scroller here (its head sticks to the sheet's), and the pick is the sentence's: no pinned copy. */
  .ca-well { max-height: none; overflow: visible; }
  .ca-pinned.is-on { display: none; }
  .ca-detail { position: sticky; top: 0; max-height: calc(100vh - 160px); overflow-y: auto; overscroll-behavior: contain; }
  .ca-head, .ca-row { grid-template-columns: 32px minmax(0, 1fr) 52px 56px 56px; column-gap: 8px; }
  /* The heads stick to the sheet's scroller while their run scrolls under them: solid, so no row reads through. */
  .ca-head { min-height: 24px; background: var(--bg-0); }
  .ca-head .ca-c[data-c="1"], .ca-row .ca-c[data-c="1"] { display: none; }
  .ca-ico, .ca-ico .hh-icon { width: 32px; height: 32px; } /* whole pixels: 28 drew 16-px art at 0.875x */
  .ca-token, .ca-step, .ca-cfg .hh-tool, .ca-form .hh-tool { min-height: 40px; }
  .ca-foot { flex: none; position: static; min-height: 48px; margin: 0 -8px; align-items: center; }
  /* a phone's press on a slot opens this, and a player may have meant to use it (QA 2026-11-04): the bar is idle by ruling, so the foot says so */
  .ca-self { flex: 1 1 0; min-width: 0; margin: 0; font-size: var(--t-micro); color: var(--ink-2); }
  .ht-bar { gap: 6px; padding: 2px 4px; }
  /* The side sheet halves the stage: the top bar (anchored right) would run
     under the party board, so it drops the ground's name and keeps the clock
     and its two commands. The sheet's own world is the name. */
  .app:has(.hs-win:not(.is-leaving)) .ht-ground { display: none; }
  .ht-bar .hh-tool { padding: 0 8px; }
  /* THE HUNT BAR ON A PHONE: one line, never over the Party panel (QA 10-24: "Leaving in 32s" ran 88 px over it).
     It keeps the World's width less the panel's column (200 px, its 4 px inset, 20 px clear); the ground's name
     gives way first (an ellipsis), and while a leave pends its countdown stands where Leave hunt was (the button
     is off until the hunt ends, hunt-topbar.js). */
  .hs-widget.is-hunt-topbar { max-width: calc(100% - 224px); }
  /* width auto, not fit-content: a fit-content bar is never narrower than the ground's whole name, so it ran out of
     its box instead of letting the name give way. The words sit at the bar's right end, under the icon row. */
  .ht-bar { flex-wrap: nowrap; width: auto; justify-content: flex-end; }
  .ht-wide { display: none; }
  .ht-bar .hh-tool { text-transform: capitalize; }
  .ht-bar:has(.hh-intent-msg:not(:empty)) { flex-wrap: wrap; }
  .ht-ground { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .ht-bar:has(.ht-leaving:not([hidden])) .is-leave { display: none; }
  /* Thumb-sized: the bar's buttons, the analyzer's tabs and its close (QA 10-24: 30 px). */
  .ha-tab, .ht-bar .hh-tool { min-height: 40px; }
  /* THE ANALYZER ON A PHONE: stacked under the hunt bar (hud-widgets.js `below`, its top the bar's foot, about
     111 px down), it ends above the action bar (at most 100 px tall, 2 px up, HS-22): 150 to 200 px of screen. So
     it spends none on a title band: the tabs are its top row with the close beside them, Next level in (premium)
     and the hero / party switch share the second, and the numbers scroll under them. The head, the body and the
     main box lend their children to the panel's own grid (display: contents); the desktop panel is unchanged. */
  .ha-analyzer { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-rows: auto auto auto minmax(0, 1fr) auto;
    align-items: center; column-gap: 2px; width: min(376px, calc(100vw - 232px)); max-height: min(calc(100vh - 219px), var(--hs-room, 100vh)); padding: 0 6px 4px; }
  .ha-analyzer .hh-panel-head, .ha-analyzer .hh-panel-body, .ha-analyzer .ha-main { display: contents; }
  .ha-analyzer .hh-panel-title { display: none; }
  /* The tabs share row 1 with the fold and the close: all four fit (phone panel v0.2.83: Taken cut, Dealt behind the buttons),
     a wide fallback font too, brought down to Alegreya's size. Past that the strip pans under the thumb and still never runs under the fold. */
  .ha-analyzer .ha-tabs { grid-area: 1 / 1 / 2 / 2; min-width: 0; margin-bottom: 0; overflow-x: auto; scrollbar-width: none; }
  .ha-analyzer .ha-tabs .ha-tab { flex: none; }
  .ha-analyzer .ha-tabs .ha-tab { font-size-adjust: var(--f-ui-aspect); }
  .ha-analyzer .hs-wfold { grid-area: 1 / 2; }
  /* Folded, the phone panel is its name, its plus and its close: one 44 px row under the hunt bar. */
  .is-folded > .ha-analyzer .hh-panel-title { display: block; grid-area: 1 / 1; align-self: center; }
  .is-folded > .ha-analyzer > .hh-panel-body { display: none; }
  .ha-analyzer .ha-tab { padding: 0 4px; }
  .ha-close { display: grid; grid-area: 1 / 3; width: var(--tap); height: var(--tap); }
  .ha-clocks { grid-area: 2 / 1 / 3 / 2; justify-content: flex-start; margin: 0; }
  /* The whole row, its words at the right end: spanning the fold's and the close's columns alone, its 125 px widened both and took it out of the tabs. */
  .ha-analyzer .ha-scope { grid-area: 2 / 1 / 3 / -1; justify-self: end; margin-bottom: 0; }
  /* A hero with no party: no row for the switch, and the Session tab's first head does not say Session again. The numbers get both. */
  .ha-analyzer.is-alone .ha-scope { display: none; }
  .ha-sec[data-sec="totals"] { border-top: 0; }
  .ha-sec[data-sec="totals"] > .ha-sec-head { display: none; }
  .ha-analyzer .ha-wait, .ha-analyzer .ha-ended { grid-area: 3 / 1 / 4 / -1; }
  .ha-scroll { grid-area: 4 / 1 / 5 / -1; align-self: stretch; }
  .ha-more { grid-area: 5 / 1 / 6 / -1; margin: 4px 0 0; }
  /* The session clock is the hunt bar's own; a premium hero keeps Next level in, on one line. */
  .ha-clocks > span:first-child { display: none; }
  .ha-clocks:not(:has([data-premium]:not([hidden]))) { display: none; }
  .ha-clocks small { display: inline; margin-right: 6px; }
  /* The analyzer is the player's ask: while it shows, the coach card under the hunt bar waits (it would lie over
     the analyzer's head and its close); it comes back when the analyzer closes. */
  .app:has(.hs-widget.is-analyzer) .hs-widget.is-hunt-topbar > .hs-pointer { display: none; }
  /* Summary and Leave are not one thumb apart (panel 2026-11-01: 7 px, "I wanted Summary"). */
  .ht-bar [data-hs-act="leave"] { margin-left: 10px; }
}
