:root {
  color-scheme: dark;
  --ink: #080d1b;
  --ink-soft: #10182b;
  --panel: #131d34;
  --panel-2: #192642;
  --line: #2c3a5d;
  --line-soft: rgba(151, 163, 191, .19);
  /* Form-control boundaries need 3:1 against the ground to pass 1.4.11; --line is
     1.73:1 on --ink, so fields get their own, darker-but-visible step (3.22:1). */
  --line-strong: #50628f;
  --text: #f7f8fb;
  --muted: #9ca9c3;
  --acid: #c8f36b;
  --acid-soft: #e8fcae;
  --violet: #988bff;
  --violet-soft: #cac5ff;
  --orange: #ffb15b;
  --red: #ff7b88;
  --cyan: #71d8ff;
  --shadow: 0 24px 70px rgba(0, 0, 0, .28);
}
#auctionClock {position:sticky;bottom:12px;z-index:4;background:var(--acid);color:var(--ink);padding:14px;text-align:center;border-radius:14px;font-weight:900;font-size:1.2rem;margin:12px 0;box-shadow:0 4px 24px #0006;}
#connectionStatus {font-size:14px;color:var(--muted);margin:10px 0;}
#connectionStatus:empty {margin:0;}
.bid-button {min-height:48px;min-width:48px;font-size:14px;}

* { box-sizing: border-box; }
html { min-width: 320px; background: var(--ink); }
body { margin: 0; min-height: 100vh; color: var(--text); background: radial-gradient(circle at 86% 8%, rgba(126, 107, 255, .2), transparent 29rem), radial-gradient(circle at 10% 72%, rgba(199, 243, 107, .07), transparent 25rem), linear-gradient(rgba(255,255,255,.025) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.025) 1px, transparent 1px), var(--ink); background-size: auto, auto, 34px 34px, 34px 34px, auto; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 16px; overflow-x: hidden; }
button, input, select, textarea { font: inherit; }
/* Safari zooms focused controls below 16px. Keep user pinch zoom enabled. */
input, select, textarea { font-size: 16px; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .38; }
h1, h2, h3, p { margin: 0; }
h1 { font-size: clamp(1.45rem, 2vw, 1.8rem); letter-spacing: -.05em; line-height: 1; }
h2 { font-size: clamp(1.3rem, 2vw, 1.7rem); letter-spacing: -.05em; line-height: 1.04; }
h3 { font-size: 1.05rem; letter-spacing: -.025em; }
code { color: var(--acid-soft); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .86em; }
[hidden] { display: none !important; }

/* The two fixed .ambient glow blobs that used to live here are gone: DESIGN.md forbids
   floating decoration twice ("nothing floats decoratively", "don't float objects that do
   not exist"), and the body already carries the two documented washes below. */
.app-frame { width: min(1560px, 100%); margin: 0 auto; padding: 28px 32px 48px; position: relative; z-index: 1; }
.brand-lockup, .topbar-actions, .room-strip, .room-strip-actions, .squads-header, .panel-heading, .bid-strip, .stage-actions, .modal-head, .modal-actions, .tab-bar { display: flex; align-items: center; }
/* Grid instead of flex so the logo sits on the true horizontal center of the page -- flex's
   space-between only pushes the first/last items to the edges, it doesn't balance a middle
   item against unequal-width siblings the way two equal 1fr side columns do. */
.topbar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px; margin-bottom: 28px; }
.topbar .hub-back { justify-self: start; }
.topbar .brand-lockup { justify-self: center; }
.topbar .topbar-actions { justify-self: end; }
.brand-lockup { gap: 14px; text-decoration: none; color: inherit; cursor: pointer; transition: opacity .15s ease; }
.brand-lockup:hover, .brand-lockup:focus-visible { opacity: .85; }
.brand-mark { width: 37px; height: 37px; display: grid; place-items: center; position: relative; border: 1px solid rgba(200,243,107,.55); border-radius: 10px; transform: rotate(-6deg); background: rgba(200,243,107,.08); animation: logo-bob 4s ease-in-out 1; }
.brand-mark span:first-child { width: 17px; height: 4px; background: var(--acid); position: absolute; top: 10px; left: 9px; box-shadow: 0 7px 0 var(--acid); }
.brand-mark span:last-child { width: 4px; height: 14px; background: var(--violet); position: absolute; right: 9px; bottom: 7px; }
.eyebrow, .meta-label { color: var(--muted); font-size: .69rem; font-weight: 850; letter-spacing: .15em; line-height: 1.2; text-transform: uppercase; }
.eyebrow { margin-bottom: 7px; }
.topbar-actions { gap: 10px; }
.mini-status i { width: 7px; height: 7px; border-radius: 50%; background: var(--acid); box-shadow: 0 0 0 4px rgba(200,243,107,.1), 0 0 15px var(--acid); display: inline-block; }
.ghost-button, .icon-button, .text-button, .close-button { border: 0; color: var(--muted); background: transparent; }
.ghost-button { display: inline-flex; align-items: center; gap: 8px; font-size: .86rem; font-weight: 750; padding: 10px; }
.ghost-button:hover, .text-button:hover { color: var(--text); }
.rules-button { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.rules-button .button-icon { color: var(--ink); border-color: var(--ink); }
.button-icon { width: 21px; height: 21px; display: inline-grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; color: var(--violet-soft); font-size: .75rem; }
.icon-button { width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 10px; color: var(--acid); font-size: 1.2rem; }
.icon-button:hover { background: var(--panel); border-color: var(--violet); }
.panel { background: linear-gradient(145deg, rgba(24,35,60,.96), rgba(14,22,40,.96)); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); }

.setup-view { display: grid; gap: 16px; max-width: 1080px; margin: 8vh auto 0; animation: rise-in .6s ease both; }
.setup-hero { max-width: 700px; margin: 0 auto; text-align: center; }
.setup-kicker { color: var(--acid); font-size: .69rem; font-weight: 900; letter-spacing: .15em; }
.setup-hero h2 { font-size: clamp(1.9rem, 4vw, 2.6rem); line-height: 1.05; letter-spacing: -.03em; margin: 14px 0 14px; }
.setup-hero p { max-width: 560px; margin: 0 auto; color: var(--muted); font-size: 1rem; line-height: 1.55; }
.setup-fork { display: grid; grid-template-columns: 1.35fr 1fr; gap: 24px; align-items: stretch; }
.tab-card { display: flex; flex-direction: column; overflow: hidden; }
.tab-bar { padding: 8px; gap: 6px; background: rgba(6,10,22,.4); border-bottom: 1px solid var(--line); }
.tab-button { flex: 1; border: none; border-radius: 10px; padding: 12px; font-size: .86rem; font-weight: 850; cursor: pointer; background: transparent; color: var(--muted); font-family: inherit; }
.tab-button[data-tab="create"].active { background: var(--acid); color: var(--ink); }
.tab-button[data-tab="join"].active { background: var(--violet); color: var(--ink); }
.tab-body { padding: 28px; flex: 1; min-height: 320px; }
.tab-pane { display: grid; align-content: start; gap: 16px; }
.tab-pane-lede { margin: 0; min-height: 3em; color: var(--muted); font-size: .82rem; line-height: 1.5; }
.pane-error { color: #ffadad; font-size: .75rem; line-height: 1.48; min-height: 1em; }
.setup-poster { position: relative; border-radius: 18px; overflow: hidden; border: 1px solid rgba(255,255,255,.2); box-shadow: var(--shadow); min-height: 280px; }
.setup-poster img { width: 100%; height: 100%; object-fit: cover; display: block; position: absolute; inset: 0; }
.setup-poster-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,13,27,.15), rgba(8,13,27,.85)); }
.setup-poster-stamp { position: absolute; bottom: 20px; left: 20px; right: 20px; z-index: 1; margin: 0; color: var(--text); font-size: 1rem; font-weight: 900; line-height: 1.25; letter-spacing: -.01em; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; }
.form-grid.single-field { grid-template-columns: 1fr; }
.form-grid label { display: grid; gap: 7px; color: var(--muted); font-size: .75rem; font-weight: 750; }
.form-grid input, .form-grid select { width: 100%; border: 1px solid var(--line-strong); border-radius: 10px; outline: none; color: var(--text); background: rgba(6,10,22,.56); padding: 11px 12px; }
.form-grid input, .form-grid select { font-size:16px; min-height:48px; min-width:0; }
.form-grid input:focus, .form-grid select:focus { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(152,139,255,.12); }
.primary-button, .secondary-button, .violet-button, .outline-button { border-radius: 10px; padding: 11px 16px; font-size: .82rem; font-weight: 850; transition: transform .18s ease, background .18s ease, border-color .18s ease, box-shadow .18s ease; }
.primary-button { color: var(--ink); border: 1px solid var(--acid); background: var(--acid); box-shadow: 0 7px 20px rgba(200,243,107,.14); }
.primary-button:hover { background: var(--acid-soft); transform: translateY(-2px); box-shadow: 0 10px 26px rgba(200,243,107,.22); }
.secondary-button { color: var(--text); border: 1px solid var(--line); background: rgba(255,255,255,.04); }
.secondary-button:hover { border-color: var(--violet); background: rgba(152,139,255,.12); transform: translateY(-1px); }
.violet-button { color: var(--ink); border: 1px solid var(--violet); background: var(--violet); box-shadow: 0 7px 20px rgba(152,139,255,.18); }
.violet-button:hover { background: var(--violet-soft); transform: translateY(-2px); box-shadow: 0 10px 26px rgba(152,139,255,.26); }
.outline-button { display: flex; justify-content: space-between; align-items: center; color: var(--acid); border: 1px solid rgba(200,243,107,.35); background: transparent; }
.outline-button:hover { background: rgba(200,243,107,.09); }
.full-button { width: 100%; }
.setup-lower { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.setup-tip { display: flex; gap: 13px; align-items: flex-start; padding: 18px; box-shadow: none; }
.tip-icon { color: var(--acid); font-size: .69rem; font-weight: 900; letter-spacing: .1em; }
.setup-tip strong { display: block; font-size: .86rem; }
.setup-tip p { color: var(--muted); font-size: .75rem; line-height: 1.44; margin-top: 5px; }

.lobby-hero { padding: 20px; border-color: rgba(200,243,107,.4); background: linear-gradient(100deg, rgba(200,243,107,.1), rgba(152,139,255,.11)); animation: lobby-pulse 3s ease-in-out infinite; }
.lobby-status { font-size: .95rem; line-height: 1.5; margin-bottom: 14px; }
.lobby-status strong { color: var(--acid); }
.ready-toggle { display: flex; border: 1px solid var(--line); border-radius: 12px; padding: 4px; background: rgba(6,10,22,.5); margin-bottom: 12px; }
.ready-toggle-option { flex: 1; text-align: center; padding: 11px 10px; border-radius: 9px; font-size: .82rem; font-weight: 800; color: var(--muted); border: 0; background: transparent; font-family: inherit; }
.ready-toggle-option { cursor: pointer; }
.ready-toggle-option.selected { font-weight: 850; color: var(--text); }
.ready-toggle-notready.selected { background: rgba(255,255,255,.08); }
.ready-toggle-yes.selected { color: var(--ink); background: var(--acid); box-shadow: 0 4px 14px rgba(200,243,107,.3); }
.ready-toggle-option:not(.selected) { opacity: .55; }
.lobby-start-divider { border-top: 1px dashed rgba(151,163,191,.3); margin-top: 4px; padding-top: 14px; }
.lobby-start-divider .field-label { display: block; margin-bottom: 8px; text-align: center; }
/* Roster redesign per feedback: replaces the old .player-chips wrapped-pill row. Each row
   uses the same --player-accent identity treatment as .bidder-card/.squad-card (colored avatar,
   accent border) so a player reads as the same "entity" in the lobby as they will once bidding
   starts, instead of the lobby using a different, unrelated visual language. */
.lobby-roster-card { padding: 20px; }
.lobby-roster-header { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 12px; }
.lobby-roster-header h2 { font-size: 1.15rem; margin-top: 4px; }
.roster-seat-chip { border: 1px solid var(--line); color: var(--muted); background: rgba(255,255,255,.035); padding: 7px 9px; font-size: .66rem; font-weight: 850; border-radius: 999px; white-space: nowrap; }
.lobby-roster { display: grid; gap: 8px; margin: 0; }
.roster-row { display: flex; align-items: center; gap: 11px; padding: 11px 12px; border: 1px solid var(--line); border-left: 3px solid var(--player-accent); border-radius: 12px; background: rgba(19,27,48,.6); }
.roster-row.is-host { background: color-mix(in srgb, var(--player-accent) 7%, rgba(19,27,48,.6)); }
.roster-avatar { width: 32px; height: 32px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 50%; background: var(--player-accent); color: var(--ink); font-size: .74rem; font-weight: 900; }
.roster-name { flex: 1; min-width: 0; }
.roster-name strong { font-size: .86rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-you { color: var(--acid-soft); font-weight: 750; }
.roster-host-badge { display: block; color: var(--player-accent); font-size: .63rem; font-weight: 850; letter-spacing: .06em; margin-top: 2px; }
.roster-ready { flex: 0 0 auto; color: var(--muted); font-size: .72rem; font-weight: 750; white-space: nowrap; }
.roster-ready.is-ready { color: var(--acid); font-weight: 850; }
.roster-row.roster-open { border-style: dashed; border-left-style: dashed; border-color: rgba(151,163,191,.35); background: transparent; }
.roster-avatar-empty { background: rgba(255,255,255,.06); color: var(--muted); font-size: .68rem; }
.roster-open-label { color: var(--muted); font-size: .8rem; }

/* Inline lobby settings -- Theme/Scenario browsing fields (row 1) plus Budget/Timer/Picks
   (row 2), shown only while state.status === 'lobby'. Replaces the old "Room settings" modal
   for that status; see settingsButton.hidden in app.js, which now also hides during lobby. */
.lobby-settings { display: grid; gap: 14px; padding: 24px; }
.lobby-settings-heading h2 { font-size: 1.35rem; letter-spacing: -.03em; margin-top: 6px; }
.lobby-settings-heading p { color: var(--muted); font-size: .85rem; line-height: 1.4; margin-top: 6px; }
.lobby-settings-row { display: grid; gap: 14px; }
.lobby-settings-fields { grid-template-columns: 1fr 1fr; }
.lobby-settings-numbers { grid-template-columns: 1fr 1fr 1fr; }
.field-group { position: relative; display: grid; gap: 7px; min-width: 0; }
.field-label { color: var(--muted); font-size: .75rem; font-weight: 750; }
.field-trigger { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; border: 1px solid var(--line-strong); border-radius: 10px; outline: none; background: rgba(6,10,22,.56); padding: 9px 12px; color: var(--text); font-size: 16px; font-family: inherit; text-align: left; min-height: 48px; }
.field-trigger:focus-visible { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(152,139,255,.12); }
.field-trigger[aria-expanded="true"] { border-color: var(--acid); box-shadow: 0 0 0 3px rgba(200,243,107,.15); }
.field-trigger-value { display: flex; align-items: center; gap: 9px; min-width: 0; overflow: hidden; }
.field-trigger-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.field-swatch { width: 24px; height: 24px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 7px; font-size: .8rem; line-height: 1; color: var(--swatch-accent, var(--acid)); background: color-mix(in srgb, var(--swatch-accent, var(--acid)) 14%, transparent); border: 1px solid color-mix(in srgb, var(--swatch-accent, var(--acid)) 40%, transparent); }
.field-swatch svg { display: block; }
.chevron { flex: 0 0 auto; transition: transform .18s ease; }
.field-trigger:hover .chevron, .field-trigger:focus-visible .chevron { transform: translateY(2px); }
@media (prefers-reduced-motion: reduce) { .chevron { transition: none; } }
.field-popover { position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 30; max-height: 320px; overflow-y: auto; border: 1px solid var(--line); border-radius: 14px; background: var(--panel); box-shadow: var(--shadow); }
.field-option { width: 100%; display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 0; border-top: 1px solid var(--line-soft); background: transparent; color: var(--text); text-align: left; font-family: inherit; font-size: 14px; }
.field-option:first-child { border-top: 0; }
.field-option:hover, .field-option:focus-visible { background: rgba(255,255,255,.05); }
.field-option.selected { background: color-mix(in srgb, var(--swatch-accent, var(--acid)) 10%, transparent); border-left: 3px solid var(--swatch-accent, var(--acid)); padding-left: 11px; }
.field-option-copy { flex: 1; min-width: 0; }
.field-option-copy strong { display: flex; align-items: center; gap: 8px; font-size: .92rem; }
.field-option-copy small { color: var(--acid); font-size: .69rem; font-weight: 850; text-transform: uppercase; letter-spacing: .04em; }
.field-option-copy span { display: block; margin-top: 2px; color: var(--muted); font-size: .76rem; line-height: 1.35; }
.stepper-field { display: grid; gap: 7px; min-width: 0; }
.stepper { display: flex; align-items: stretch; border: 1px solid var(--line-strong); border-radius: 10px; background: rgba(6,10,22,.56); overflow: hidden; min-height: 48px; }
.stepper:has(.stepper-btn:disabled) { opacity: .38; }
.stepper-btn { width: 34px; min-height: 38px; flex: 0 0 auto; border: 0; background: transparent; color: var(--acid); font-size: 16px; font-weight: 900; font-family: inherit; }
.stepper-btn:disabled { display: none; }
.field-trigger:disabled .chevron, .field-trigger:disabled .ui-arrow { display: none; }
.stepper-btn:first-child { border-right: 1px solid var(--line); }
.stepper-btn:last-child { border-left: 1px solid var(--line); }
.stepper-btn:hover:not(:disabled) { background: rgba(200,243,107,.09); }
.stepper-value { flex: 1; display: grid; place-items: center; color: var(--text); font-size: 14px; font-weight: 800; }
.lobby-settings select { width: 100%; border: 1px solid var(--line-strong); border-radius: 10px; outline: none; color: var(--text); background: rgba(6,10,22,.56); padding: 11px 12px; min-height: 48px; font-size: 16px; }
.lobby-settings select:focus { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(152,139,255,.12); }
.room-strip { justify-content: space-between; gap: 16px; min-height: 57px; padding: 0 4px 16px; }
.room-strip > div:first-child { display: flex; align-items: baseline; gap: 10px; }
.room-strip strong { color: var(--acid); font-size: 1.25rem; letter-spacing: .1em; }
.room-subtext { color: var(--muted); font-size: .75rem; }
.room-strip-actions { gap: 10px; min-width: 0; }
.room-strip-actions .compact-button { min-height: 44px; }
.room-strip-actions [data-action="copy"] { color: var(--text); border-color: var(--line); background: rgba(255,255,255,.04); }
.icon-button.danger-button, .outline-button.danger-button, .secondary-button.danger-button { color: var(--red); border-color: rgba(255,123,136,.35); background: rgba(255,123,136,.08); }
.outline-button.danger-button { font-size: .75rem; }
.icon-button.danger-button:hover, .outline-button.danger-button:hover, .secondary-button.danger-button:hover { background: rgba(255,123,136,.16); border-color: var(--red); }
/* Solid fill, not an outline tint: ending the game affects every player in the room, not just
   the one clicking, so it reads as more consequential than the outline-style Leave Room. */
.primary-button.danger-button { color: var(--ink); border-color: var(--red); background: var(--red); box-shadow: 0 7px 20px rgba(255,123,136,.22); }
.primary-button.danger-button:hover { background: #ffa3ad; box-shadow: 0 10px 26px rgba(255,123,136,.3); }
/* Share uses the Web Share sheet, which only makes sense on a touch device -- keep it out of
   the room strip above the phone breakpoint even on desktop browsers that technically support
   the API (feature-detection alone isn't a reliable "is this a phone" signal). */
#shareRoomButton { display: none; }
@media (max-width: 570px) { #shareRoomButton { display: flex; } }
/* #shareRoomButton only ever renders at mobile widths (the rule above) -- no separate media
   query needed to swap its label for a share icon, common in many apps' compact toolbars. */
#shareRoomButton .share-room-label { display: none; }
#shareRoomButton .share-room-icon { display: inline-flex; align-items: center; }
/* Local/demo mode isn't a room anyone else could join -- room code, invite link and share
   promise something a solo sandbox can't deliver, so all three drop out entirely there. */
.local-game #roomCodeDisplay, .local-game [data-action="copy"], .local-game #shareRoomButton { display: none; }
.compact-button { width: auto; padding: 8px 10px; font-size: .69rem; gap: 12px; }

.game-layout { display: grid; grid-template-columns: minmax(470px, 1fr) 345px; gap: 22px; align-items: start; }
/* Lobby two-column layout. Reuses .game-layout's exact grid values verbatim (the approved
   design canvas uses the same minmax(470px,1fr) 345px / gap:22px proportions) for visual
   consistency with the rest of the app. */
.lobby-layout { display: grid; grid-template-columns: minmax(470px, 1fr) 345px; gap: 22px; align-items: start; margin-bottom: 16px; }
.lobby-col-main, .lobby-col-side { min-width: 0; display: grid; gap: 16px; align-content: start; }

.auction-column { min-width: 0; }
.section-intro { display: flex; align-items: end; justify-content: space-between; gap: 20px; padding: 3px 4px 17px; }
.item-stage { padding: 22px 24px 19px; overflow: hidden; position: relative; }
.pill { border-radius: 999px; padding: 6px 9px; font-size: .69rem; font-weight: 900; letter-spacing: .12em; }
.purple-pill { color: var(--violet-soft); border: 1px solid rgba(152,139,255,.35); background: rgba(152,139,255,.13); }
/* Absolutely positioned so it costs no layout height of its own -- matches the design
   canvas's treatment, which moved this out of flow for the same reason. */
.pick-badge { position: absolute; top: 20px; right: 20px; z-index: 2; display: inline-flex; align-items: baseline; gap: 5px; border-radius: 999px; padding: 5px 14px; font-size: .66rem; font-weight: 900; letter-spacing: .1em; color: var(--violet-soft); border: 1px solid rgba(152,139,255,.35); background: rgba(152,139,255,.13); font-variant-numeric: tabular-nums; }
.pick-badge .pick-num { color: var(--text); font-size: .92rem; font-weight: 900; }
.pick-badge .pick-max.final { color: var(--acid); }
.card-facts{margin-top:8px}.card-facts summary{cursor:pointer;min-height:44px;display:flex;align-items:center;font-size:14px;color:var(--violet-soft);font-weight:700}.card-facts summary::before{content:'+';margin-right:8px}.card-facts[open] summary::before{content:'−'}.item-description:has(.card-facts){display:block;-webkit-line-clamp:unset;overflow:visible}
.item-copy { display: flex; align-items: center; gap: 18px; padding: 18px 4px 29px; position: relative; z-index: 1; }
.item-art { width: 111px; height: 111px; display: grid; place-items: center; flex: 0 0 auto; position: relative; overflow: hidden; border: 1px solid rgba(255,255,255,.22); border-radius: 18px; background-position: center; background-size: cover; box-shadow: 11px 11px 0 rgba(152,139,255,.23); transform: rotate(-4deg); }
.item-art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(155deg, rgba(200,243,107,.18), transparent 45%, rgba(7,10,19,.56)); pointer-events: none; }
.item-art-label { position: absolute; top: 9px; left: 10px; z-index: 1; color: rgba(255,255,255,.8); font-size: .69rem; font-weight: 900; letter-spacing: .06em; }
.item-symbol { width: 51px; height: 51px; display: grid; place-items: center; position: relative; z-index: 1; border: 1px solid var(--acid); border-radius: 5px; background: var(--acid); color: var(--ink); font-family: monospace; font-size: 1rem; font-weight: 700; letter-spacing: -.04em; box-shadow: none; }
.item-copy h3 { color: var(--text); font-size: clamp(2rem, 4vw, 3.3rem); letter-spacing: -.075em; line-height: .96; }
.item-description { color: var(--muted); font-size: .94rem; line-height: 1.45; margin-top: 11px; max-width: 590px; }
.lane-meta-grid { display: grid; grid-template-columns: .78fr 1.22fr; gap: 11px; position: relative; z-index: 1; }
.lane-meta { display: flex; align-items: flex-start; gap: 10px; min-width: 0; border: 1px solid var(--line-soft); border-radius: 10px; padding: 11px 12px; background: rgba(255,255,255,.035); }
.lane-meta-icon { width: 25px; height: 25px; display: grid; place-items: center; flex: 0 0 auto; color: var(--acid); border: 1px solid rgba(200,243,107,.3); border-radius: 8px; background: rgba(200,243,107,.08); font-size: .82rem; }
.lane-meta strong { display: block; margin-top: 5px; color: var(--text); font-size: .75rem; line-height: 1.3; }
.bid-strip { justify-content: space-between; gap: 18px; border-top: 1px solid var(--line-soft); margin-top: 14px; padding-top: 18px; position: relative; z-index: 1; }
/* The bid is the auction's heartbeat. Every other object on this screen already speaks in
   the display scale and the printed hard-offset; the price was the one element opting out
   of the system's strongest moves, so it read as one more field among equals. It is now a
   printed price slab at display scale, and the labels around it were quieted so nothing
   competes with the number. */
.bid-price { padding: 9px 15px 11px; border: 1px solid var(--lead-accent, var(--acid)); border-radius: 12px; background: rgba(200,243,107,.07); box-shadow: 7px 7px 0 rgba(152,139,255,.23); transition: border-color .35s ease; }
/* Whose bid is it: the price wears the leader's seat accent, the same ownership device the
   bidder and squad cards use as their 2px top border, and gives one beat when it changes
   hands. The room can see who just raised without reading a name. */
.bid-price.lead-changed { animation: lead-flash .7s ease; }
@keyframes lead-flash {
  0% { box-shadow: 7px 7px 0 rgba(152,139,255,.23); }
  40% { box-shadow: 0 0 0 6px var(--lead-accent, rgba(200,243,107,.18)), 7px 7px 0 rgba(152,139,255,.23); }
  100% { box-shadow: 7px 7px 0 rgba(152,139,255,.23); }
}
.current-bid { display: flex; align-items: baseline; gap: 3px; color: var(--acid); margin-top: 2px; }
.current-bid span { font-size: 1.35rem; font-weight: 800; }
.current-bid strong { font-size: clamp(2.4rem, 4vw, 3.2rem); letter-spacing: -.055em; line-height: .9; font-variant-numeric: tabular-nums; }
.bid-strip .meta-label { font-weight: 700; letter-spacing: .12em; opacity: .78; }
.bid-leader { padding-left: 19px; border-left: 1px solid var(--line-soft); margin-right: auto; }
.bid-leader .meta-label { font-size: .74rem; }
.bid-leader strong { display: block; color: var(--violet-soft); font-size: 1.05rem; margin-top: 6px; letter-spacing: .04em; }
.stage-actions { gap: 8px; }
.stage-helper { color: var(--muted); font-size: .75rem; padding-top: 16px; position: relative; z-index: 1; }

.luna-panel { display: flex; align-items: flex-start; gap: 14px; min-height: 112px; padding: 17px; margin-top: 13px; position: relative; overflow: hidden; border-color: rgba(152,139,255,.46); background: linear-gradient(110deg, rgba(152,139,255,.19), rgba(200,243,107,.07) 60%, rgba(19,27,48,.92)); }
.luna-panel::after { content: ""; position: absolute; width: 260px; height: 1px; right: -22px; bottom: 17px; background: linear-gradient(90deg, transparent, rgba(200,243,107,.48), transparent); transform: rotate(-17deg); animation: scanline 4s linear infinite; }
.luna-orb { width: 40px; height: 40px; display: grid; place-items: center; flex: 0 0 auto; position: relative; border: 1px solid var(--acid); border-radius: 50%; color: var(--ink); background: var(--acid); }
/* The ring lives on a pseudo-element and pulses with transform/opacity, which the
   compositor can carry. Animating box-shadow directly repainted the shadow every
   frame, forever, on the phones that play this game. */
.luna-orb::after { content: ""; position: absolute; inset: -7px; border-radius: 50%; pointer-events: none; box-shadow: 0 0 0 7px rgba(200,243,107,.08), 0 0 27px rgba(200,243,107,.23); animation: orb-pulse 2.8s ease-in-out infinite; }
.luna-orb span { font-size: .69rem; font-weight: 950; }
.luna-body { min-width: 0; flex: 1; }
.luna-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.luna-heading h3 { font-size: 1.08rem; }
.luna-meta { display: grid; gap: 3px; color: var(--muted); text-align: right; font-size: .69rem; }
.luna-reaction { max-width: 850px; margin-top: 11px; color: var(--acid-soft); font-size: .94rem; line-height: 1.5; }
.luna-reaction strong { font-weight: 850; }
.luna-spark { color: var(--acid); font-size: 1.4rem; animation: spark-spin 4s linear 2; }
.bidder-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 13px 0 0; }
.online-game #bidderGrid, .online-game #opponentList { display: none; }
.bidder-card { padding: 16px; border: 1px solid var(--line); border-top: 2px solid var(--player-accent); border-radius: 16px; background: rgba(19,27,48,.8); transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease; animation: card-in .45s ease both; }
.bidder-card:hover { transform: translateY(-2px); }
.bidder-card.leading { border-color: color-mix(in srgb, var(--player-accent) 70%, white 8%); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--player-accent) 18%, transparent); }
.bidder-card.is-me { box-shadow: 0 0 0 2px rgba(200,243,107,.11), inset 0 0 0 1px rgba(200,243,107,.12); }
.bidder-card-header { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; }
.player-id { color: var(--muted); font-size: .69rem; font-weight: 900; letter-spacing: .13em; }
.player-name { margin-top: 4px; font-size: 1.15rem; letter-spacing: -.05em; }
.bidder-status { color: var(--player-accent); font-size: .69rem; font-weight: 850; text-transform: uppercase; letter-spacing: .08em; white-space: nowrap; }
.bidder-stats { display: flex; justify-content: space-between; align-items: end; gap: 10px; border-top: 1px solid var(--line-soft); margin-top: 16px; padding-top: 12px; }
.budget-number { color: var(--acid); font-size: 1.33rem; font-weight: 850; letter-spacing: -.06em; }
.budget-label { color: var(--muted); font-size: .69rem; }
.quick-bids { display: flex; flex-wrap: wrap; justify-content: end; gap: 5px; }
.opponent-list { display: grid; gap: 6px; padding-top: 8px; }
.opponent-row { display: flex; justify-content: space-between; align-items: center; padding: 9px 13px; border: 1px solid var(--line); border-radius: 10px; background: rgba(19,27,48,.5); }
.opponent-row.leading { border-color: var(--acid); }
.opponent-name { font-size: .86rem; }
.opponent-leading { color: var(--acid); font-weight: 850; text-transform: uppercase; font-size: .69rem; letter-spacing: .06em; }
.opponent-stats { color: var(--muted); font-size: .75rem; white-space: nowrap; }
.bid-button { min-width: 43px; border: 1px solid color-mix(in srgb, var(--player-accent) 42%, var(--line)); border-radius: 8px; color: var(--violet-soft); background: rgba(152,139,255,.1); padding: 8px 8px; font-size: .75rem; font-weight: 850; transition: .15s ease; }
.bid-button:hover:not(:disabled) { color: var(--ink); border-color: var(--acid); background: var(--acid); transform: translateY(-2px) rotate(-2deg); }
.auction-footer { display: grid; grid-template-columns: 1fr; margin-top: 13px; }
.activity-log { min-height: 187px; padding: 17px; }
.log-heading { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; }
.log-heading h3 { font-size: .94rem; }
.tape-light { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: .69rem; font-weight: 900; letter-spacing: .1em; }
.tape-light span { width: 6px; height: 6px; border-radius: 50%; background: var(--red); box-shadow: 0 0 8px var(--red); animation: live-blink 1.3s ease-in-out infinite; }
.log-list { display: grid; gap: 7px; max-height: 115px; overflow: auto; }
@media (min-width: 821px) { .activity-log { min-height: 260px; } .log-list { max-height: 190px; } }
.log-entry { display: flex; gap: 10px; align-items: baseline; color: var(--muted); font-size: .75rem; line-height: 1.3; }
.log-time { flex: 0 0 auto; color: var(--violet-soft); font-size: .69rem; font-weight: 800; letter-spacing: .06em; }
.empty-log { color: var(--muted); font-size: .82rem; padding: 14px 0; }
.text-button { align-self: flex-start; padding: 5px 6px; font-size: .75rem; font-weight: 750; }

.squad-rail { min-width: 0; }
.squads-header { justify-content: space-between; gap: 10px; padding: 3px 3px 17px; }
.squad-card { padding: 13px 14px; border: 1px solid var(--line); border-left: 3px solid var(--player-accent); border-radius: 16px; background: linear-gradient(145deg, rgba(24,35,60,.93), rgba(16,24,43,.93)); margin-bottom: 10px; animation: card-in .45s ease both; }
/* Row 1: name (who) | status (how they stand on this lot). Row 2: picks (what they have) |
   money (what they can spend). Team list flows into an implicit row 3, full width. */
.squad-grid { display: grid; grid-template-columns: minmax(0,1fr) auto; column-gap: 10px; row-gap: 9px; align-items: center; }
.squad-name-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.squad-name-row h3 { font-size: 1.25rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex-shrink: 1; }
.you-tag { flex-shrink: 0; color: var(--player-accent); font-size: .7rem; font-weight: 800; letter-spacing: .05em; white-space: nowrap; }
.host-tag { flex-shrink: 0; display: inline-flex; align-items: center; gap: 2px; color: var(--player-accent); font-size: .625rem; font-weight: 850; letter-spacing: .04em; white-space: nowrap; }
.squad-status { display: flex; align-items: center; gap: 5px; white-space: nowrap; font-size: .6rem; font-weight: 850; letter-spacing: .05em; text-transform: uppercase; }
.squad-status-icon { display: flex; }
.squad-status.tone-leading { color: var(--acid); }
.squad-status.tone-out { color: var(--muted); font-weight: 800; }
.squad-status.tone-pending { color: var(--text); }
/* Row 2's two cells run very different font sizes (the $ figure is nearly double the picks
   text), so centering them by box height left the small text visually floating relative to
   the big one -- aligning both to the row's shared text baseline instead reads as one line. */
.squad-picks-row { align-self: baseline; justify-self: start; display: flex; align-items: baseline; gap: 7px; color: var(--muted); font-size: .64rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.squad-picks-row strong { color: var(--text); font-size: .78rem; font-weight: 900; }
.picks-dots { display: flex; gap: 4px; align-self: center; }
.picks-dot { width: 7px; height: 7px; border-radius: 50%; border: 1px solid rgba(156,169,195,.4); }
.picks-dot.filled { border-color: var(--player-accent); background: var(--player-accent); }
.squad-total { align-self: baseline; text-align: right; white-space: nowrap; }
.squad-total strong { color: var(--player-accent); font-size: 1.2rem; letter-spacing: -.05em; }
.squad-total span { color: var(--muted); font-size: .69rem; }
.team-list { grid-column: 1 / -1; display: grid; gap: 6px; }
.team-item, .team-empty { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 8px; background: rgba(255,255,255,.035); }
.team-item-name { font-size: .75rem; font-weight: 720; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.team-item-price { color: var(--muted); font-size: .69rem; font-weight: 800; }
.team-empty { color: var(--muted); font-size: .75rem; border: 1px dashed rgba(151,163,191,.28); background: transparent; }
.reset-button { margin-top: 8px; }

.toast { position: fixed; left: 50%; bottom: 24px; z-index: 20; opacity: 0; pointer-events: none; transform: translate(-50%, 10px); color: var(--ink); background: var(--acid); border-radius: 10px; padding: 11px 15px; font-size: .82rem; font-weight: 800; box-shadow: var(--shadow); transition: .2s ease; }
.toast[data-tone="error"] { color: var(--text); background: var(--red); }
.toast.show { opacity: 1; transform: translate(-50%, 0); }

.modal { width: min(560px, calc(100% - 30px)); border: 1px solid var(--line); border-radius: 18px; padding: 0; color: var(--text); background: var(--panel); box-shadow: var(--shadow); }
.modal::backdrop { background: rgba(3,5,12,.78); backdrop-filter: blur(5px); }
.modal-inner { padding: 25px; }
.modal-head { align-items: flex-start; justify-content: space-between; gap: 16px; }
.modal-head h2 { max-width: 420px; }
.close-button { width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 8px; color: var(--muted); font-size: 1.35rem; line-height: 1; }
.close-button:hover { color: var(--text); border-color: var(--violet); }
.modal-lede { color: var(--muted); font-size: .86rem; line-height: 1.48; margin: 12px 0 22px; }
.rules-list { display: grid; gap: 10px; }
.rule-row { display: grid; grid-template-columns: 31px 1fr; gap: 12px; padding: 13px; border-radius: 10px; background: rgba(255,255,255,.035); }
.rule-row > span { color: var(--acid); font-size: .75rem; font-weight: 900; }
.rule-row strong { font-size: .86rem; }
.rule-row p { color: var(--muted); font-size: .75rem; line-height: 1.4; margin-top: 4px; }
.modal-callout { display: flex; gap: 10px; align-items: center; border: 1px solid rgba(200,243,107,.25); border-radius: 10px; color: var(--acid-soft); background: rgba(200,243,107,.07); padding: 13px; margin: 15px 0; }
.modal-callout p { font-size: .75rem; line-height: 1.4; }
.modal-callout strong { color: var(--acid); }
.modal-actions { justify-content: flex-end; gap: 8px; margin-top: 22px; }
#confirmActionModal { width: min(440px, calc(100% - 30px)); }
#confirmActionModal .modal-actions button { flex: 1; }
/* Verdict room reading order, top to bottom: the story, then what the brief wanted, then the
   squad cards, then the automatic judgment -- one linear flow at every width, no side column
   splitting the squad cards away from the brief that explains them. */
/* .modal-inner's padding:25px (dist/styles.css:353) is meant for a floating dialog card --
   left in place here it indents the whole results screen inward, out of line with
   .room-strip/"Room code" above it. Zeroed so this screen's content sits flush at the same
   left edge as the rest of the page. */
.results-layout .modal-inner { display: flex; flex-direction: column; gap: 14px; padding: 0; }
.results-layout .verdict-side { display: contents; }
.results-layout #missionWants { order: 1; }
.results-layout #compareGrid { order: 2; }
.results-layout #judgeCard { order: 3; }
.results-layout .modal-actions { order: 4; flex-wrap: wrap; }
.results-layout #resultsLobbyNote { order: 5; }
/* Two side-by-side buttons at narrow widths get too little room for an icon plus a longer
   label ("Return to lobby") without the icon wrapping onto its own line, inflating that one
   button's height against its sibling. Keeping each button's own content on one line lets the
   row wrap the whole button to a new line instead, which reads cleanly at any width. */
.results-layout .modal-actions button { white-space: nowrap; }
/* A fixed max track (not 1fr) keeps cards a sane width once the verdict screen lost its own
   width cap and started flowing full-width like the lobby/auction screens: with only 2-3
   players, 1fr let each card stretch past 700px on a wide monitor around a small, fixed-size
   radar chart -- mostly empty card. */
.compare-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.compare-card { border: 1px solid var(--line); border-top: 2px solid var(--line); border-radius: 12px; padding: 15px; background: rgba(255,255,255,.035); }
.compare-card.winner-card { border-color: rgba(200,243,107,.55); border-top-color: var(--acid); background: linear-gradient(145deg, rgba(200,243,107,.11), rgba(255,255,255,.035)); }
.compare-rank { color: var(--acid); font-size: .69rem; font-weight: 900; letter-spacing: .1em; }
.compare-card h3 { font-size: 1.25rem; margin: 7px 0 3px; }
.compare-card p { color: var(--muted); font-size: .75rem; }
.compare-card ul { display: grid; gap: 5px; padding: 13px 0 0; margin: 13px 0 0; border-top: 1px solid var(--line-soft); list-style: none; }
.compare-card li { display: flex; justify-content: space-between; gap: 8px; color: var(--text); font-size: .75rem; }
.compare-card li span { color: var(--muted); }
.vote-button { width: 100%; margin-top: 15px; border: 1px solid var(--line); border-radius: 8px; color: var(--text); background: transparent; padding: 9px; font-size: .75rem; font-weight: 800; }
.vote-button:hover, .vote-button.selected { color: var(--ink); border-color: var(--acid); background: var(--acid); }
.judge-card { display: grid; gap: 10px; border: 1px solid rgba(152,139,255,.36); border-radius: 12px; padding: 14px; background: linear-gradient(100deg, rgba(152,139,255,.13), rgba(200,243,107,.06)); }
.judge-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.judge-card-head strong { color: var(--acid); font-size: .75rem; letter-spacing: .06em; text-transform: uppercase; }
.judge-card-head span { color: var(--muted); font-size: .69rem; }
.judge-call { font-size: .86rem; line-height: 1.4; }
.judge-metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.judge-metric { display: flex; justify-content: space-between; align-items: center; gap: 9px; border-top: 1px solid var(--line-soft); padding-top: 8px; color: var(--muted); font-size: .69rem; }
.judge-metric b { color: var(--text); font-size: .75rem; }
.judge-note { color: var(--muted); font-size: .69rem; line-height: 1.4; }

.item-entrance { animation: item-entrance .65s cubic-bezier(.2,.85,.3,1) both; }
.bid-flash { animation: bid-flash .7s ease both; }
.sold-flash { animation: sold-flash .8s ease both; }
.number-pop { animation: number-pop .45s ease both; }

#auctionClock.urgent { background: var(--orange); animation: gavel-beat .7s ease infinite alternate; }
#joinError { color: #ffadad; line-height: 1.5; }
#phoneBids { display:none; }
.real-card-image { width:100%; height:100%; object-fit:contain; position:absolute; inset:0; background:#0b1020; }
.item-art:has(.real-card-image) { width:160px; height:190px; transform:none; box-shadow:none; border-radius:18px; }
.item-art:has(.real-card-image)::after { display:none; }
.image-status { padding:14px; text-align:center; font-size:13px; color:var(--muted); line-height:1.5; }
.card-identity, .scout-line, .card-joke { display:block; margin-bottom:10px; }
.scout-line b { color:var(--text); }
.card-joke { color:var(--acid-soft); }
.card-credits { font-size:12px; line-height:1.5; overflow-wrap:anywhere; }
.card-credits a { color:var(--violet-soft); text-decoration:underline; }
.card-credits small { display:block; color:var(--muted); margin-top:4px; }
.luna-heading h3, .brand-lockup .eyebrow { overflow-wrap:anywhere; }
@media(max-width:570px) {
  .item-copy:has(.real-card-image) { display:grid; grid-template-columns:minmax(0,1fr); padding-top:16px; }
  .item-art:has(.real-card-image) { width:100%; height:132px; }
  .item-description { font-size:16px!important; }
  .luna-heading .eyebrow { font-size:12px; line-height:1.45; letter-spacing:.02em; }
  .brand-lockup { max-width:100%; }
}
.verdict-story { padding:18px; border:1px solid var(--violet); border-radius:12px; background:linear-gradient(120deg,#252242,#142137); }
.story-copy { font-size:16px; line-height:1.65; margin-top:10px; overflow-wrap:anywhere; }
.story-parts { margin-top:10px; }
.story-part { font-size:16px; line-height:1.65; margin:0 0 10px; overflow-wrap:anywhere; }
/* Each part fades in as its round arrives. Every part is in the DOM from the first frame -
   nothing is withheld - so the panel only holds back what has not been reached yet WHILE a
   reveal is running (.is-telling, set by startReplay), and a verdict opened without a replay
   shows the whole recap at once. The newest part keeps the acid bar; the others are plain
   text, not dimmed script. */
.verdict-story.is-telling .story-part { opacity:0; transform:translateY(6px); }
.verdict-story.is-telling .story-part.is-shown { opacity:1; transform:none; }
.story-parts .story-part.is-current { border-left:2px solid var(--acid); padding-left:10px; }
/* The trade-off is the closing frame of the brief, so it arrives with the verdict part. */
.verdict-story.is-telling .story-complication { opacity:0; transform:translateY(6px); }
.verdict-story.is-complete .story-complication { opacity:1; transform:none; }
@media (prefers-reduced-motion: no-preference) {
  .story-part, .story-complication { transition:opacity .5s ease, transform .5s ease; }
}
.briefing-modal { width:min(640px,calc(100% - 24px)); max-height:90dvh; overflow-y:auto; }
.briefing-modal h2 { line-height:1.2; }
.briefing-modal .mission-brief { margin-top:20px; }
.story-complication, .story-hook { margin-top:14px; font-size:15px; line-height:1.55; }
.story-hook { color:var(--acid-soft); }
.story-complication .meta-label, .story-hook .meta-label { display:block; font-size:11px; letter-spacing:.12em; color:var(--violet); margin-bottom:4px; }
#phoneBids .scenario-shortcut { position:absolute; right:12px; top:8px; min-height:32px; padding:5px 9px; font-size:12px; }
#phoneBids:has(.scenario-shortcut) > strong { padding-right:90px; }
.mission-brief { padding:20px; margin:0 0 18px; border:1px solid var(--line); border-left:4px solid var(--acid); border-radius:12px; background:linear-gradient(125deg,#1e2941,#10182b); }
.mission-brief-header { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:12px; }
.mission-brief-header .eyebrow { margin-bottom:0; }
.mission-mode { display:inline-block; color:var(--ink); background:var(--acid); border-radius:999px; padding:4px 11px; font-size:.68rem; letter-spacing:.1em; font-weight:900; }
.mission-brief h2 { font-size:24px; line-height:1.15; margin-bottom:12px; }
.mission-brief p { font-size:16px; line-height:1.5; margin-bottom:12px; }
.mission-goal-box { display:flex; align-items:center; gap:10px; border:1px solid var(--line-soft); border-radius:11px; padding:12px 13px; background:rgba(255,255,255,.035); margin-bottom:12px; }
.mission-goal-icon { width:25px; height:25px; flex:0 0 auto; display:grid; place-items:center; color:var(--acid); border:1px solid rgba(200,243,107,.3); border-radius:8px; background:rgba(200,243,107,.08); font-size:.8rem; }
.mission-goal-box .mission-goal { margin:0; font-size:.85rem; line-height:1.4; color:var(--text); }
.mission-goal-label { color:var(--muted); font-weight:850; letter-spacing:.1em; text-transform:uppercase; font-size:.69rem; }
.mission-brief .mission-rules, .brief-note, .results-lobby-note { font-size:14px; line-height:1.5; color:var(--muted); }
.brief-note { margin:12px 0; }
/* The AI-story note starts empty (no upfront disclaimer) and only gets text once there's
   something to report (pending/error/attribution) -- collapses out of the layout until then. */
.brief-note:empty { display: none; }
.results-lobby-note { margin: 10px 0 0; text-align: right; }
#setupBrief { margin-top:16px; }
.scene-details { margin-top:16px; padding-top:12px; border-top:1px solid var(--line); }
.scene-details summary { cursor:pointer; color:var(--acid); font-size:14px; padding:8px 0; }
.scene-details p { font-size:15px; line-height:1.5; margin:12px 0; }
.item-copy > div, .room-strip > div { min-width:0; }
@media (max-width:820px) {
  #lobbyHero .primary-button { min-height:48px; }
  #lobbySettings .lobby-settings-fields, #lobbySettings .lobby-settings-numbers { grid-template-columns: 1fr; }
}
@media (max-width:570px) {
  .topbar { grid-template-columns: 1fr; gap:14px; }
  .brand-lockup { min-width:0; }
  /* Centering the logo only reads right when it's balanced against something on either side;
     stacked alone above a left-aligned button row, a truly centered logo just looks adrift.
     Left-aligned keeps the whole header on one consistent edge. Matches ".topbar .brand-lockup"
     (styles.css:52) in specificity so this actually wins instead of losing the cascade to it. */
  .topbar .brand-lockup { justify-self: start; }
  /* flex-wrap left 4 buttons as 3-then-1, orphaning the last one alone on its own row. A 2-column
     grid wraps them in even, full-width pairs instead -- also matching ".topbar .topbar-actions"
     (styles.css:53) in specificity so "stretch" actually overrides its "end". */
  .topbar-actions { display: grid; grid-template-columns: repeat(2, 1fr); }
  .topbar .topbar-actions { justify-self: stretch; }
  .room-strip > div:first-child { flex-wrap:wrap; }
  .item-copy h3, .player-name, .squad-card h3 { overflow-wrap:anywhere; }
}
@media (max-width:700px) {
  /* The tray owns the bottom of the screen under 700px, which is what DESIGN.md
     promises: between 571 and 700px the old 570px gate left a remote player with
     no above-the-fold bid control at all. */
  body:has(#phoneBids) { padding-bottom: calc(var(--dock-h, 183px) + 24px); }
  .online-game #auctionClock { bottom: calc(var(--dock-h, 183px) + 8px); font-size:1rem; padding:10px; }
  #phoneBids { display:block; position:fixed; bottom:0; left:0; right:0; padding:12px 16px max(12px,env(safe-area-inset-bottom)); z-index:8; background:#131d34f7; border-top:2px solid var(--acid); box-shadow:0 -10px 30px #0008; }
  #phoneBids .phone-bid-top { display:flex; align-items:center; gap:8px; }
  #phoneBids strong { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #phoneBids .dock-pick-badge { position:static; flex:0 0 auto; padding:5px 12px; font-size:.75rem; }
  #phoneBids .dock-pick-badge .pick-num { font-size:1.05rem; }
  #phoneBids small { display:block; color:var(--acid); font-size: .69rem; margin:5px 0 8px; }
  #phoneBids > div { display:grid; grid-template-columns:repeat(3,1fr); gap:8px; }
  #phoneBids .bid-button { min-height:48px; width:100%; font-size:16px; }
}
.bidder-card.is-me { order: -1; }
@keyframes gavel-beat { to { box-shadow: 0 0 0 5px rgba(255,177,91,.22); } }
@keyframes rise-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }
@keyframes card-in { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: translateY(0); } }
@keyframes item-entrance { 0% { opacity: .45; transform: translateY(9px) scale(.985); } 65% { transform: translateY(-2px) scale(1.008); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes bid-flash { 0%, 100% { box-shadow: var(--shadow); } 35% { box-shadow: 0 0 0 3px rgba(200,243,107,.45), 0 0 38px rgba(200,243,107,.18), var(--shadow); } }
@keyframes sold-flash { 0% { transform: scale(1); } 35% { transform: scale(1.015) rotate(.3deg); border-color: var(--acid); } 100% { transform: scale(1); } }
@keyframes number-pop { 0% { transform: scale(1); } 50% { transform: scale(1.16); } 100% { transform: scale(1); } }
@keyframes ambient-drift { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(-20px,24px,0) scale(1.08); } }
@keyframes logo-bob { 0%, 100% { transform: rotate(-6deg) translateY(0); } 50% { transform: rotate(-2deg) translateY(-3px); } }
@keyframes orb-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .78; transform: scale(1.18); } }
@keyframes spark-spin { to { transform: rotate(360deg); } }
@keyframes scanline { from { transform: translateX(15px) rotate(-17deg); } to { transform: translateX(-280px) rotate(-17deg); } }
@keyframes lobby-pulse { 0%, 100% { box-shadow: var(--shadow); } 50% { box-shadow: 0 0 0 2px rgba(200,243,107,.06), 0 24px 70px rgba(0,0,0,.28); } }
@keyframes live-blink { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: .01ms !important; } }
@media (max-width: 1220px) { .squad-rail { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; align-items: start; } .squads-header { grid-column: 1 / -1; padding-bottom: 0; } .reset-button { margin-top: 0; } .lobby-layout { grid-template-columns: 1fr; } }
@media (max-width: 820px) { .app-frame { padding: 20px 16px 34px; } .setup-fork { grid-template-columns: 1fr; gap: 24px; } /* wild-card-chaos.jpg is a square (800x800) image; a short fixed min-height (200px) on a
     full-width mobile box forced object-fit:cover to crop off its top and bottom -- matching
     the image's own aspect-ratio instead shows all of it, no cropping. */ .setup-poster { min-height: 0; aspect-ratio: 1; } .setup-lower { grid-template-columns: 1fr; } .room-strip { align-items: flex-start; flex-direction: column; gap: 11px; padding-bottom: 15px; } .room-strip-actions { width: 100%; flex-wrap: wrap; } .invite-text { max-width: 100%; flex: 1; } .game-layout { display: flex; flex-direction: column; gap: 16px; } .auction-column, .squad-rail { width: 100%; } .squad-rail { display: grid; grid-template-columns: 1fr 1fr; } .squads-header { grid-column: 1 / -1; } .reset-button { grid-column: 1 / -1; } }
@media (max-width: 570px) { .hero-line-break { display: none; } .leave-room-suffix, .copy-link-icon { display: none; } .topbar { align-items: flex-start; margin-bottom: 12px; } .topbar-actions { gap: 3px; } .ghost-button { font-size: 0; padding: 8px 5px; } .ghost-button .button-icon { font-size: .69rem; } .setup-hero h2 { font-size: clamp(1.7rem, 9vw, 2.3rem); } .tab-body { padding: 20px; } .form-grid { grid-template-columns: 1fr; } .item-stage { padding: 12px; } .item-copy { flex-direction: column; align-items: flex-start; padding: 14px 1px 12px; gap: 10px; } .item-art { width: 84px; height: 84px; border-radius: 18px; box-shadow: 7px 7px 0 rgba(152,139,255,.23); } .item-symbol { width: 42px; height: 42px; border-radius: 12px; font-size: 1.2rem; } .item-art-label { display: none; } .item-copy h3 { font-size: 2.15rem; } .item-description { font-size: .82rem; } .lane-meta-grid { grid-template-columns: 1fr; } .bid-strip { flex-wrap: wrap; } .bid-leader { margin-right: 0; } .stage-actions { width: 100%; } .stage-actions button { flex: 1; } .luna-heading { display: grid; } .luna-meta { text-align: left; } .bidder-grid, .squad-rail { grid-template-columns: 1fr; } .squad-rail { display: grid; } .squads-header { grid-column: auto; } .reset-button { grid-column: auto; } .compare-grid, .judge-metrics { grid-template-columns: 1fr; } .modal-inner { padding: 20px; }
  /* Phone chrome budget. Measured at 390x844 on a live seat: the chrome above the lot was
     393px (topbar 131 + room strip 187 + section intro 75) and the lot name landed at y=722,
     fully behind the fixed bid tray that starts at 659. Compressing the chrome clears the
     tray without shrinking the poster, which is the surface's identity. */
  .room-strip { padding: 8px 0 10px; gap: 6px; }
  .room-strip-actions { gap: 6px; }
  .room-strip-actions .outline-button { padding: 8px 10px; font-size: .69rem; }
  .section-intro { display: none; }
  /* The item-art image sits right where this badge's top-right position lands on mobile.
     Remote play's #phoneBids dock carries its own dock-pick-badge instead; local/demo mode
     has no dock to move it into, so it simply goes unshown there. */
  #itemsRemaining { display: none; }
}
/* Keep the two live-game shortcuts on one row above the phone safe area. */
#phoneBids .scenario-shortcut, #phoneBids .phone-pass { position:static; display:inline-flex; align-items:center; justify-content:center; width:calc(50% - 5px); min-height:44px; margin-top:6px; font-size:14px; }
#phoneBids .phone-pass { margin-left:6px; }
.bid-limit-note { margin:12px 0 0; font-size:14px; line-height:1.45; color:var(--muted); }
.quick-bids .bid-button { min-width:0; padding:6px 4px; font-size:13px; }
/* The player's own controls live in the bid strip on a wide screen (above the fold)
   and in the phone dock on a narrow one; never in both places at once. */
.stage-bids { display:flex; align-items:center; gap:6px; }
.stage-bids .bid-button { min-width:43px; min-height:41px; padding:11px 10px; border:1px solid var(--line); }
@media (min-width:701px) { .bidder-card.is-me .quick-bids { display:none; } }
@media (max-width:700px) { #stageBids { display:none; } }
/* Legal/credit chrome belongs in the lot, not shouting in it. */
.credit-details { margin-top: 8px; }
.credit-details summary { color: var(--muted); font-size: .69rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.credit-details a { display: block; margin-top: 6px; color: var(--violet-soft); font-size: .69rem; }
.credit-details small { display: block; margin-top: 4px; color: var(--muted); font-size: .69rem; line-height: 1.4; }
/* The verdict's rubric, one tap away instead of above the winner. */
.verdict-rubric { margin-top: 10px; }
.verdict-rubric summary { display: block; padding: 12px 0; color: var(--muted); font-size: .69rem; font-weight: 850; letter-spacing: .1em; text-transform: uppercase; cursor: pointer; }
.verdict-rubric .radar-legend, .verdict-rubric .want-note { margin-top: 8px; }
/* Disabled controls must look disabled, selects included. */
select:disabled, input:disabled, button:disabled { cursor: not-allowed; }
select:disabled, input:disabled { opacity: .45; }
.hub-back { color:var(--acid);font-size:14px;font-weight:800;letter-spacing:1px;text-decoration:none; }
.lane-meta-icon { font-family: monospace; font-size: .69rem; font-weight: 600; border-radius: 4px; }
.mission-brief>.outline-button { margin:6px 8px 0 0; }
@media(max-width:700px) and (min-width:571px){.topbar>.hub-back{width:100%;font-size:12px;display:flex;align-items:center;min-height:36px}.topbar{flex-wrap:wrap}}
/* Delight thesis: the gavel landing is the one moment this game has earned, and the joke of
   an auction is that everything gets documented — so a won lot stamps itself onto the
   buyer's receipt. Transient by construction: the class is only present on the render where
   the squad actually grew, and the stamp fades itself out. Nothing is gated behind it; the
   sale is already announced in the tape, the toast and the price. */
.squad-card { position: relative; }
.squad-card.just-won::after {
  content: "SOLD · $" attr(data-won-price);
  position: absolute; top: 12px; right: 12px; z-index: 2;
  padding: 5px 10px; border: 1px solid var(--acid); border-radius: 8px;
  background: var(--acid); color: var(--ink);
  font-size: .69rem; font-weight: 900; letter-spacing: .08em;
  box-shadow: 5px 5px 0 rgba(11,16,32,.55);
  animation: stamp-in 1.7s ease both;
}
@keyframes stamp-in {
  0% { opacity: 0; transform: rotate(-9deg) scale(1.3); }
  16% { opacity: 1; transform: rotate(-4deg) scale(1); }
  72% { opacity: 1; transform: rotate(-4deg) scale(1); }
  100% { opacity: 0; transform: rotate(-4deg) scale(1); }
}
/* Screen-reader-only: announcements that must not add visible chrome. */
/* Entrance belongs to a card that is actually new: both grids are rebuilt on every render,
   so .card-in used to replay on every bid and every poll (measured: four cards re-animating
   after each action). The container carries the verdict; the animation no longer does. */
#bidderGrid.settled .bidder-card, #squadList.settled .squad-card { animation: none; }
/* The receipts tape acknowledges the line it just wrote. */
.log-entry.log-new { animation: log-in .18s ease both; }
@keyframes log-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* The hub has always had a skip link; the game, which is the longer page, did not. */
.skip { position: absolute; left: 10px; top: -100px; z-index: 20; padding: 10px 14px; border-radius: 8px; background: var(--acid); color: var(--ink); font-weight: 850; text-decoration: none; }
.skip:focus { top: 10px; }
/* Laptops are the short viewports, not the wide ones: 1366x768 (and a 1512x700 window) leave
   the price at y~670 with a 110px strip whose bid row falls at the fold. The wide layout was
   designed against ~900px of viewport. On a short window the stage gives up the same things
   the phone gives up — a smaller display name, a two-line description, a shorter photo — so
   the price and the bid controls stay reachable without scrolling. */
@media (min-width:701px) and (max-height:860px) {
  .item-copy { padding: 18px 4px 14px; }
  .item-copy h3 { font-size: clamp(1.7rem, 2.6vw, 2.4rem); }
  .item-description { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .item-art:has(.real-card-image) { height: 120px; }
  .lane-meta-grid { margin-top: 4px; }
}
/* The skip link only has a destination once the game is on screen. */
body:has(#setupView:not([hidden])) .skip { display: none; }
[aria-invalid="true"] { border-color: var(--red); }
/* The fold is a height budget, not a width one: the tray is a fixed 187px, so a shorter
   phone has a smaller band and the banner is what gives way. Measured band above the tray:
   657px at 390x844, 553px at 360x740, 480px at 375x667. */
@media (max-width:570px) and (max-height:780px) {
  .item-art:has(.real-card-image) { height: 100px; }
  .room-strip { padding: 5px 0 7px; }
  .topbar { margin-bottom: 8px; }
  .section-intro { padding: 4px 0; }
}
/* Narrow *and* short: no band left for context art (the tray names the lot anyway). */
@media (max-width:400px) and (max-height:780px) {
  .item-art:has(.real-card-image) { display: none; }
  .item-copy:has(.real-card-image) { padding-top: 8px; padding-bottom: 8px; }
}
@media (max-width:570px) and (max-height:700px) {
  /* No budget for context art: the tray names the lot, the name is the content. */
  .item-art:has(.real-card-image) { display: none; }
  .item-copy:has(.real-card-image) { padding-top: 8px; padding-bottom: 8px; }
}

/* --- Squad scouting: radar + readiness bar (playful sim flourish) --- */
.attr-block { margin:12px 0; display:flex; flex-direction:column; align-items:center; gap:10px; }
.attr-block.empty-attr { color:var(--muted); font-size:13px; padding:14px 0; text-align:center; }
.radar-svg { width:168px; height:168px; max-width:100%; overflow:visible; }
.radar-grid path { fill:none; stroke:var(--line-soft); stroke-width:1; }
.radar-grid line { stroke:var(--line-soft); stroke-width:1; }
.radar-demand { fill:rgba(152,139,255,.16); stroke:var(--violet); stroke-width:1.5; stroke-dasharray:4 3; }
.radar-ghost { fill:none; stroke:var(--muted); stroke-width:1.2; stroke-dasharray:3 3; opacity:0; transition:opacity .18s ease; }
.radar-ghost.is-on { opacity:.85; }
.radar-squad { fill:rgba(200,243,107,.22); stroke:var(--acid); stroke-width:2; }

/* Axis ticks: wanted axes wear the mission colour, and the tick the last pick
   moved flashes so the shape change has a name next to it. */
.radar-labels text { fill:var(--muted); font-size: .69rem; font-weight:800; letter-spacing:.06em; transition:fill .2s ease; }
.radar-labels text.axis-wanted { fill:var(--violet-soft); }
.radar-labels text.axis-flash { animation:axis-pulse .56s ease both; }
@keyframes axis-pulse {
  0% { fill:var(--acid); }
  35% { fill:var(--acid-soft); }
  100% { fill:var(--violet-soft); }
}
.thresh-wrap { width:100%; }
.thresh-track { position:relative; height:10px; border-radius:999px; background:var(--panel-2); overflow:hidden; }
.thresh-line { position:absolute; top:-3px; bottom:-3px; width:2px; background:var(--text); opacity:.5; transform:translateX(-1px); z-index:2; }
.thresh-fill { position:absolute; left:0; top:0; bottom:0; border-radius:999px; transition:width .9s cubic-bezier(.22,1,.36,1); }
.thresh-caption { display:flex; justify-content:space-between; align-items:baseline; gap:8px; margin-top:6px; font-size:12px; }
.thresh-caption b { font-weight:800; letter-spacing:.02em; }
.thresh-caption span { color:var(--muted); }
.mission-wants { padding:8px 14px; border:1px solid var(--line); border-radius:12px; background:var(--panel-2); }
.mission-wants .meta-label { display:block; margin-bottom:8px; }
.want-chips { display:flex; flex-wrap:wrap; gap:6px; }
.want-chip { padding:4px 10px; border-radius:999px; font-size:12px; font-weight:800; letter-spacing:.04em; color:var(--ink); background:var(--violet-soft); }
.want-note { margin:8px 0 0; font-size: .69rem; line-height:1.4; color:var(--muted); }

/* Reveal sting */
.reveal-sting { animation:sting-in .5s cubic-bezier(.22,1,.36,1) both; }
.want-headline { margin:6px 0 10px; font-size:19px; font-weight:800; letter-spacing:.01em; color:var(--text); }
.want-allalong { color:var(--violet-soft); font-style:italic; font-weight:700; }
@keyframes sting-in { from { opacity:0; transform:translateY(8px) scale(.98); } to { opacity:1; transform:none; } }

/* Dispatch-style ball */
.radar-ball { fill:var(--violet-soft); stroke:#fff; stroke-width:1.5; filter:drop-shadow(0 0 6px rgba(202,197,255,.7)); transition:fill .25s, filter .25s; }
.radar-ball.hit { fill:var(--acid); filter:drop-shadow(0 0 9px rgba(200,243,107,.9)); }
.radar-ball.miss { fill:var(--red); filter:drop-shadow(0 0 9px rgba(255,123,136,.85)); }
.radar-impact { fill:none; stroke:var(--acid); stroke-width:2; }
.radar-impact.miss { stroke:var(--red); }

/* Per-card contribution reveal (MVP / dead weight). Rows are also the control
   that inspects a single pick, so they carry hover/focus/active states. */
.contrib-list { list-style:none; margin:12px 0 0; padding:0; width:100%; }
.contrib-row { display:flex; justify-content:space-between; align-items:center; gap:8px; padding:5px 6px; border-top:1px solid var(--line-soft); border-radius:8px; font-size:13px; opacity:0; transform:translateX(-6px); transition:opacity .34s ease, transform .34s ease, background .18s ease; cursor:pointer; }
.contrib-row.is-shown { opacity:1; transform:none; }
.contrib-row.is-dim { opacity:.28; }
.contrib-row.is-active { background:rgba(152,139,255,.16); box-shadow:inset 0 0 0 1px rgba(152,139,255,.35); }
.contrib-row:hover { background:rgba(255,255,255,.05); }
.contrib-row:focus-visible { outline:2px solid var(--violet); outline-offset:1px; }
/* .compare-card li span (styles.css:397) sets a muted default for the OLDER simple stat rows
   in a .compare-card <ul> -- it out-specifies a bare .contrib-name rule (equal class count, but
   more type selectors), so the pick's own name was rendering muted instead of white. Scoped to
   .contrib-row to win cleanly instead of reaching for !important. */
.contrib-row .contrib-name { color:var(--text); display:flex; align-items:center; gap:6px; }
.contrib-price { color:var(--muted); font-weight:400; }
.contrib-push { font-weight:800; font-variant-numeric:tabular-nums; }
.contrib-push.up { color:var(--acid); }
.contrib-push.down { color:var(--red); }
.contrib-badge { font-size: .69rem; font-weight:900; letter-spacing:.06em; padding:2px 6px; border-radius:999px; }
.contrib-badge.mvp { color:var(--ink); background:var(--acid); }
.contrib-badge.goat { color:var(--ink); background:var(--red); }

/* Replay narration: one steady line per card telling you which pick you are
   watching, and the chip row explaining what the hovered pick moved. */
.radar-step { min-height:15px; margin:2px 0 0; font-size: .69rem; letter-spacing:.02em; color:var(--muted); text-align:center; }
.radar-step b { color:var(--acid); }
.radar-delta { display:flex; flex-wrap:wrap; justify-content:center; gap:5px; margin:0; font-size: .69rem; }
.radar-delta .dl-note { color:var(--muted); align-self:center; letter-spacing:.04em; text-transform:uppercase; font-weight:800; }
.radar-delta .dl { padding:2px 7px; border-radius:999px; background:var(--panel-2); font-weight:850; font-variant-numeric:tabular-nums; }
.radar-delta .dl.up { color:var(--acid); }
.radar-delta .dl.down { color:var(--red); }
.radar-legend { display:flex; flex-wrap:wrap; align-items:center; gap:6px 14px; margin:10px 0 0; font-size: .69rem; letter-spacing:.03em; color:var(--muted); text-transform:uppercase; font-weight:800; }
.radar-legend .lg { display:inline-block; width:14px; height:10px; margin-right:5px; border-radius:3px; vertical-align:middle; }
.radar-legend .lg.demand { border:1.5px dashed var(--violet); background:rgba(152,139,255,.16); }
.radar-legend .lg.squad { border:1.5px solid var(--acid); background:rgba(200,243,107,.22); }
.radar-legend .lg.ghost { border:1.2px dashed var(--muted); }
.radar-legend .lg.ball { width:11px; height:11px; border-radius:50%; border:1.5px solid var(--acid); background:var(--acid); }

/* The squad being revealed owns the room; the others wait their turn. */
.compare-card { transition:opacity .3s ease, transform .3s ease, border-color .3s ease, box-shadow .3s ease; }
.compare-card.is-off { opacity:.45; }
.compare-card.is-showing { border-color:rgba(200,243,107,.45); box-shadow:0 0 0 1px rgba(200,243,107,.16), 0 18px 44px rgba(0,0,0,.3); transform:translateY(-2px); }
.skip-replay { display:inline-flex; align-items:center; gap:6px; margin-right:6px; font-size: .69rem; letter-spacing:.06em; text-transform:uppercase; font-weight:850; }

/* Axis receipts: the printed reason under each chart. Every rule is scoped
   through .attr-block because the compare card's own `ul` / `li` / `li span`
   rules reach inside the attribute block and would otherwise restyle the rows
   as part of the card's summary list. */
.receipt-list { width:100%; }
.attr-block .receipt-list .meta-label { display:block; margin-bottom:7px; }
.attr-block .receipt-list .receipt-rows { display:flex; flex-direction:column; gap:4px; margin:0; padding:0; border:0; list-style:none; }
.attr-block .receipt-list .receipt-row { display:block; padding:4px 7px; border:1px solid transparent; border-radius:7px; background:rgba(255,255,255,.04); font-size:12px; letter-spacing:.02em; }
/* The row is a disclosure, so the head is a real button: it carries the tap, the
   keyboard and the accessible name (axis + figures) while the panel below it
   stays ordinary readable content. Phones get the 44px target mobile.css gives
   every button, which is the point — a phone has no hover to fall back on. */
.attr-block .receipt-list .receipt-head { display:flex; justify-content:space-between; align-items:center; gap:8px; width:100%; min-width:0; padding:0; border:0; background:none; color:inherit; font:inherit; letter-spacing:inherit; text-align:left; cursor:pointer; }
.attr-block .receipt-list .receipt-head:hover .receipt-axis { color:var(--violet-soft); }
.attr-block .receipt-list .receipt-head:focus-visible { outline:2px solid var(--violet); outline-offset:2px; border-radius:5px; }
.attr-block .receipt-list .receipt-caret { flex:0 0 auto; width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent; border-top:5px solid var(--muted); }
.attr-block .receipt-list .receipt-row.is-open .receipt-caret { border-top-color:var(--violet-soft); transform:rotate(180deg); }
.attr-block .receipt-list .receipt-row .receipt-axis { min-width:0; overflow-wrap:anywhere; color:var(--text); font-weight:800; }
.attr-block .receipt-list .receipt-row .receipt-figure { flex:0 0 auto; color:var(--muted); font-variant-numeric:tabular-nums; }
.attr-block .receipt-list .receipt-row .receipt-figure b { font-weight:850; }
/* The tone comes from the row's own met flag, so a covered axis can never wear
   the miss colour: acid is the cleared family, orange the miss family. */
.attr-block .receipt-row[data-tone="acid"] { border-color:rgba(200,243,107,.35); background:rgba(200,243,107,.08); }
.attr-block .receipt-row[data-tone="acid"] .receipt-figure b { color:var(--acid); }
.attr-block .receipt-row[data-tone="cyan"] { border-color:rgba(113,216,255,.35); background:rgba(113,216,255,.08); }
.attr-block .receipt-row[data-tone="cyan"] .receipt-figure b { color:var(--cyan); }
.attr-block .receipt-row[data-tone="orange"] { border-color:rgba(255,177,91,.35); background:rgba(255,177,91,.08); }
.attr-block .receipt-row[data-tone="orange"] .receipt-figure b { color:var(--orange); }
.attr-block .receipt-row[data-tone="red"] { border-color:rgba(255,123,136,.35); background:rgba(255,123,136,.08); }
.attr-block .receipt-row[data-tone="red"] .receipt-figure b { color:var(--red); }
.attr-block .receipt-list .receipt-note { margin:7px 0 0; font-size:11px; line-height:1.4; color:var(--muted); text-align:left; }
.attr-block .receipt-list .receipt-call { margin:6px 0 0; font-size:12.5px; line-height:1.45; color:var(--text); text-align:left; }
/* The drill-down: which pick carried the axis and which dragged it. Shown by a
   class, not by an entrance of any kind — a tap, a click, an Enter key and a
   reduced-motion session all read the same numbers, and a rebuild of the compare
   grid shows nothing replaying. Nothing here is required to read the panel. */
.attr-block .receipt-list .receipt-break { display:none; margin-top:5px; padding-top:5px; border-top:1px dashed var(--line-soft); }
.attr-block .receipt-list .receipt-row.is-open .receipt-break { display:block; }
.attr-block .receipt-list .rb-note { margin:0 0 4px; font-size:11px; line-height:1.4; color:var(--muted); text-align:left; }
.attr-block .receipt-list .rb-list { display:flex; flex-direction:column; gap:3px; margin:0; padding:0; border:0; list-style:none; }
.attr-block .receipt-list .rb-row { display:flex; justify-content:space-between; align-items:center; gap:8px; margin:0; color:var(--text); font-size:11.5px; }
.attr-block .receipt-list .rb-name { display:flex; align-items:center; gap:6px; min-width:0; overflow-wrap:anywhere; color:var(--text); }
.attr-block .receipt-list .rb-delta { flex:0 0 auto; font-weight:850; font-variant-numeric:tabular-nums; }
.attr-block .receipt-list .rb-delta.up { color:var(--acid); }
.attr-block .receipt-list .rb-delta.down { color:var(--red); }
.attr-block .receipt-list .rb-delta.flat { color:var(--muted); font-weight:750; }

/* The endgame beat: the replay's last frame settles the chart one step larger
   and keeps a firmer rim on the ball, so the eye lands where the ball stopped.
   Transform only — the chart's geometry and the ball's arena maths are untouched,
   and the SVG scales about its own view-box centre rather than its corner. */
/* The landing zoom is a camera, not a scale: app.js tweens this chart's viewBox so it keeps
   its size and its place in the layout and cannot grow over anything beside it. A CSS scale
   here would enlarge the element too, and would double up with the camera. */
.attr-block .radar-svg { transform-box:view-box; transform-origin:center; }
.attr-block .radar-ball { transition:fill .25s, filter .25s, stroke-width .55s cubic-bezier(.22,1,.36,1); }
.attr-block.is-final .radar-ball { stroke-width:2.6; }
/* Reduced motion still gets the final size — it just arrives without travelling,
   which is what the app signals by adding .is-instant when wantsMotion() is false. */
.attr-block.is-instant .radar-svg, .attr-block.is-instant .radar-ball { transition:none; }

/* Honour the OS setting: no build-up, no ball, no drifting decoration. The
   charts and numbers still land in their final state either way. */
@media (prefers-reduced-motion: reduce) {
  .reveal-sting, .radar-labels text.axis-flash, .contrib-row, .compare-card, .thresh-fill, .radar-ghost, .radar-ball { animation:none !important; transition:none !important; }
  .contrib-row { opacity:1; transform:none; }
  .brand-mark { animation:none !important; }
  .compare-card.is-showing { transform:none; }
  .brand-lockup:hover { transform:none; }
}
