/* LOT BOSS — flat, dark, orange-accent. Wordmark family matches the app:
   near-white #f4f2ee, flat orange #FF6A00. */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: #101216; color: #f4f2ee;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
button { font: inherit; cursor: pointer; border: 0; border-radius: 10px;
  background: #23262e; color: #f4f2ee; padding: 8px 12px; }
button:hover { background: #2e323c; }
button.on { background: #FF6A00; color: #14161c; font-weight: 700; }
.hidden { display: none !important; }
.amp { color: #FF6A00; }

/* ---------- HUD ---------- */
#hud { display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 8px 14px; background: #14161c; border-bottom: 2px solid #FF6A00; }
#hud .brand { font-weight: 900; font-size: 22px; letter-spacing: 0.5px; }
.hudstat { font-size: 15px; color: #d8d4cc; }
.hudstat.phase { margin-left: auto; font-weight: 800; color: #f2b21c; letter-spacing: 1px; }
#speedBtns { display: flex; gap: 6px; }
#speedBtns button { padding: 6px 12px; font-size: 15px; }

/* ---------- Stage ---------- */
#stage { display: flex; gap: 12px; padding: 12px; align-items: flex-start; }
#lotWrap { position: relative; flex: 1 1 auto; min-width: 0; }
#lot { width: 100%; height: auto; display: block; border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.5); background: #79a84c; touch-action: manipulation; }

/* ---------- Palette ---------- */
#palette { width: 252px; flex: 0 0 252px; background: #14161c; border-radius: 12px; padding: 14px; }
#palette h2 { margin: 0 0 6px; font-size: 18px; }
#palette .hint { color: #a8a49c; font-size: 13px; line-height: 1.45; margin: 4px 0 10px; }
#palette .hint.small { font-size: 12px; }
.palItem { display: flex; justify-content: space-between; align-items: center; width: 100%;
  text-align: left; margin: 0 0 7px; padding: 9px 11px; }
.palItem small { display: block; color: #a8a49c; font-weight: 400; font-size: 11.5px; }
.palItem .cost { color: #f2b21c; font-weight: 700; white-space: nowrap; margin-left: 8px; }
.palItem.on { background: #FF6A00; color: #14161c; }
.palItem.on small { color: #3a2410; }
.palItem.on .cost { color: #14161c; }
.palItem:disabled { opacity: 0.4; cursor: not-allowed; }
.paletteRow { display: flex; gap: 7px; margin: 10px 0; }
.paletteRow button { flex: 1; font-size: 13px; padding: 8px 6px; }
#buildMsg { min-height: 20px; font-size: 13px; color: #f2b21c; margin: 6px 0; }
#openGates { width: 100%; background: #57a047; color: #fff; font-weight: 800;
  font-size: 16px; padding: 12px; letter-spacing: 0.4px; }
#openGates:hover { background: #65b657; }

/* ---------- Rev ---------- */
/* LB-11 pager bar, v0.3 (Addition M): the pager lives in the page
   flow UNDER the stage — it never covers the lot again. ~6 s after
   a message lands it collapses to a slim one-line strip; tap Rev's
   face or the strip to expand, tap again to fold. Expanded history
   is height-capped + scrolls. The last message is always visible
   (the strip counts) and the log is one tap away — LB-11 holds. */
/* v0.3.1: the strip — Rev lives UNDER the HUD, in flow, on every
   screen: face + his current line (one line folded, a few
   expanded). He scrolls with the page and pushes content down;
   he never floats over a list again. The dismiss ✕ is the last
   thing in the strip — its top-right, always visible.
   v0.3.3: the face shrinks to 28px everywhere, and on MENU
   screens (title/picker/city, .menuStrip) the strip is a strict
   one-liner: bubble truncated to a single line, history never
   rendered — the full pager lives on the lot only. */
#revPanel { position: relative; display: flex; gap: 9px; align-items: center;
  margin: 0; padding: 6px 12px; background: #14161c;
  border-bottom: 1px solid rgba(255,106,0,0.45); cursor: pointer; }
#revFace { background: #1d2733; border-radius: 50%; border: 2.5px solid #FF6A00; flex: 0 0 auto;
  width: 28px; height: 28px; cursor: pointer; }
#revPanel.menuStrip #revBubble { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
#revPanel.menuStrip #revBubble::after { content: none; }
#revPanel.menuStrip #revHistory { display: none; }
/* v0.3.5: Rev's plain-text line — desktop never shows it (the
   pager lives there); the narrow stylesheet swaps it in for the
   face/bubble/history on menu + build screens. */
#revLine { display: none; }
#revBar { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1 1 auto; }
#revBubble { background: #f4f2ee; color: #26221f; border-radius: 11px; padding: 6px 11px;
  font-size: 13.5px; line-height: 1.35; }
#revPanel.collapsed #revBubble { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; padding: 5px 11px; font-size: 13px; }
#revPanel.collapsed #revBubble::after { content: ' ▸'; color: #FF6A00; font-weight: 900; }
#revHistory { background: rgba(20,22,28,0.85); color: #a8a49c; border-radius: 10px;
  padding: 6px 11px; font-size: 11.5px; line-height: 1.45;
  max-height: 84px; overflow-y: auto; }
#revPanel.collapsed #revHistory { display: none; }
#revHistory:empty { display: none; }
#revHistory div + div { border-top: 1px solid rgba(244,242,238,0.10); margin-top: 3px; padding-top: 3px; }
#revDot { position: absolute; top: 0; left: 32px; color: #FF6A00; font-size: 13px;
  text-shadow: 0 1px 4px rgba(0,0,0,0.7); }
/* v0.3.3: the ✕ is a real thumb target now (≥44px both ways) — on
   menu screens it's Rev's EJECT (he leaves, the tab below takes
   his place); on the lot it folds the pager. */
#revClose { flex: 0 0 auto; align-self: center; min-width: 44px; min-height: 44px;
  padding: 6px 10px; font-size: 16px;
  background: #23262e; color: #d8d4cc; border-radius: 8px; }
/* v0.3.3: the 🧢 Rev tab — the strip's dock with Rev dismissed.
   Same spot in the flow, same bottom edge, so the page doesn't
   jump when he leaves or returns. */
#revTab { display: flex; align-items: center; width: 100%; min-height: 44px;
  margin: 0; padding: 6px 12px; text-align: left; font-weight: 700;
  background: #14161c; color: #d8d4cc; border-radius: 0;
  border-bottom: 1px solid rgba(255,106,0,0.45); }

/* ---------- v0.3.1: save chip (the version pill that shared
   this section retired at v1.92 — see UNDER THE LETTERING at
   the foot of this file) ---------- */
#saveChip { color: #8fd18a; font-size: 13px; white-space: nowrap; }
#saveLine { color: #8fd18a; }
#saveWarn { color: #ff9a8a; font-weight: 700; max-width: 420px; }

/* ---------- Awards ---------- */
#awardsBanner { position: absolute; top: 16px; left: 50%; transform: translateX(-50%);
  background: rgba(20,22,28,0.94); border: 2px solid #f2b21c; border-radius: 14px;
  padding: 14px 22px; text-align: center; min-width: 300px; }
#awardsBanner h2 { margin: 0 0 8px; color: #f2b21c; letter-spacing: 1px; }
#winnersList { font-size: 15px; line-height: 1.6; margin-bottom: 10px; }
#toReceipts { background: #FF6A00; color: #14161c; font-weight: 800; }

/* ---------- v1.18: REV'S CHOICE presentation ----------
   Rev presents his own pick inside the awards banner: his comic
   host art beside a paper speech bubble in his voice. LARGE text
   on purpose (phone-lane standard — it must read at arm's length):
   the speech line at 20px, the winner line at 17px, both clear of
   the 15px results list around them. */
#revsChoiceBlock { display: flex; align-items: center; gap: 12px; text-align: left;
  margin: 4px auto 12px; max-width: 460px; }
#revsChoiceBlock.hidden { display: none; }
#revsChoiceFace { width: 72px; height: 72px; object-fit: cover; flex: 0 0 72px;
  border: 2.5px solid #14161c; border-radius: 12px 4px 12px 4px;
  box-shadow: 0 0 0 2px #f2b21c; transform: rotate(-2deg); background: #f4f2ee; }
.revsChoiceBubble { position: relative; background: #f4f2ee; color: #26221f;
  border: 2.5px solid #14161c; border-radius: 14px 5px 14px 5px;
  padding: 10px 14px; flex: 1 1 auto; }
.revsChoiceBubble::before { content: ''; position: absolute; left: -11px; top: 50%;
  margin-top: -7px; border: 7px solid transparent; border-right-color: #14161c; border-left: 0; }
#revsChoiceSpeech { font-size: 20px; font-weight: 800; line-height: 1.3; }
#revsChoiceWinner { font-size: 17px; line-height: 1.4; margin-top: 3px; color: #4a443c; }
#revsChoiceWinner b { color: #14161c; letter-spacing: 0.4px; }

/* ---------- Title ---------- */
/* v1.38: THE TITLE SCREEN SCROLLS — Gary's live find (Oct 26):
   the v1.35 account block made the menu stack taller than short
   viewports, and the ONLY overflow-y:auto for this surface lived
   inside the max-width:900px phone pass — so a desktop window
   (any height) or a wide phone held sideways got a fixed,
   centered, NON-scrolling column whose overflow clipped at BOTH
   ends: the Log in button sat below the fold, unreachable.
   Now the base rule scrolls at EVERY width: flex-start +
   overflow-y auto, children never shrink, and the stack still
   CENTERS when it fits — #titleArt's margin-top:auto and the
   last child's margin-bottom:auto split the spare space, and
   auto margins collapse to 0 the moment the stack overflows,
   so scrolling starts flush at the top with nothing clipped. */
#titleScreen { position: fixed; inset: 0; background: #101216; z-index: 30;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 4px; padding: 20px;
  overflow-y: auto; overscroll-behavior: contain; }
#titleScreen > * { flex-shrink: 0; }
#titleArt { margin-top: auto; }
#titleScreen > :last-child { margin-bottom: auto; }
#titleArt { border-radius: 14px; box-shadow: 0 10px 40px rgba(0,0,0,0.6); max-width: 92vw; height: auto; }
#titleScreen h1 { font-size: 64px; font-weight: 900; margin: 14px 0 0; letter-spacing: 1px; }
#titleScreen .byline { font-size: 21px; color: #d8d4cc; margin: 2px 0 0; letter-spacing: 0.4px; }
#titleScreen .byline b { color: #f4f2ee; font-weight: 800; }
#titleScreen .tagline { font-size: 22px; color: #d8d4cc; margin: 2px 0 16px; font-style: italic; }
#startBtn { background: #FF6A00; color: #14161c; font-weight: 900; font-size: 20px; padding: 14px 34px; }
#startBtn:hover { background: #ff7d22; }
.tiny { color: #6e6a62; font-size: 12px; margin-top: 14px; }

/* ---------- Receipts ---------- */
#receipts { position: fixed; inset: 0; background: rgba(8,9,12,0.82); z-index: 40;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.receiptCard { position: relative; background: #14161c; border: 2px solid #FF6A00; border-radius: 16px;
  padding: 26px 30px; max-width: 560px; width: 100%; text-align: center;
  max-height: calc(100dvh - 30px); overflow-y: auto; }
.receiptCard h1 { margin: 0; font-size: 30px; }
.receiptCard .sub { color: #a8a49c; margin: 6px 0 18px; }
.receiptCard .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; text-align: left; }
.receiptCard .cell { background: #1d2027; border-radius: 10px; padding: 10px 14px; }
.receiptCard .cell b { display: block; font-size: 22px; color: #f2b21c; }
.receiptCard .cell span { color: #a8a49c; font-size: 13px; }
.receiptCard .cell.net b { color: #57a047; }
.receiptCard .cell.net.neg b { color: #c9332b; }
.receiptBtns { display: flex; gap: 10px; justify-content: center; margin-top: 20px; }
#posterBtn { background: #FF6A00; color: #14161c; font-weight: 800; }
#againBtn { font-weight: 700; }
.receiptCard .tiny { margin-top: 16px; }
.receiptCard .tiny b { color: #f4f2ee; }

/* ---------- v0.2: HUD buttons, city panel, picker, notes ---------- */
.hudbtn { padding: 6px 11px; font-size: 13.5px; }
/* v0.2.1: day ended while you were out in the city — the My Show
   button turns into a pulsing 🏆 See results so it can't be missed. */
.hudbtn.pulse { background: #f2b21c; color: #14161c; font-weight: 800;
  animation: hudPulse 0.9s ease-in-out infinite; }
@keyframes hudPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(242,185,28,0.55); }
  50% { box-shadow: 0 0 0 7px rgba(242,185,28,0); }
}
.wideBtn { width: 100%; margin-top: 12px; font-weight: 700; }
#notesBtnTitle { margin-top: 12px; font-weight: 700; padding: 10px 20px; }

#cityPanel { width: 252px; flex: 0 0 252px; background: #14161c; border-radius: 12px; padding: 14px;
  max-height: calc(100vh - 90px); overflow-y: auto; }
#cityPanel h2 { margin: 0 0 6px; font-size: 19px; }
#cityPanel h3 { margin: 14px 0 7px; font-size: 14.5px; color: #f2b21c; }
#cityPanel .hint { color: #a8a49c; font-size: 13px; line-height: 1.45; margin: 4px 0 10px; }
#cityPanel .hint.small { font-size: 12px; }
.venueItem, .showItem { display: flex; justify-content: space-between; align-items: center; width: 100%;
  text-align: left; margin: 0 0 6px; padding: 8px 10px; font-size: 13.5px;
  flex-wrap: wrap; row-gap: 2px; column-gap: 6px; }
/* v0.3.4: venue rows are DIVS now — a real 🎪 HOST button lives on
   each row, and a button can't nest inside a button — so the row
   carries its own button chrome. Tapping the row still peeks;
   HOST starts hosting directly (Gary's phone shot: the card's
   Host button sat below the fold — effectively missing). */
.venueItem { background: #23262e; border-radius: 10px; cursor: pointer; }
.venueItem:hover { background: #2e323c; }
.hostRowBtn { flex: 0 0 auto; min-height: 44px; min-width: 78px; padding: 8px 12px;
  background: #57a047; color: #fff; font-weight: 800; font-size: 13.5px; }
.hostRowBtn:hover { background: #65b657; }
.venueItem small, .showItem small { display: block; color: #a8a49c; font-size: 11.5px; }
.venueItem.on, .showItem.on { background: #FF6A00; color: #14161c; }
.venueItem.on small, .showItem.on small { color: #3a2410; }
.venueItem .meta, .showItem .meta { color: #f2b21c; font-weight: 700; white-space: nowrap; margin-left: auto; font-size: 12.5px; }
.venueItem.on .meta, .showItem.on .meta { color: #14161c; }
/* v0.3.1: roster rows read "BigSal · Sal's Mega Lot · 5/92 🚗" —
   named parts with separators, wrapping instead of crushing. */
.showItem .who { font-weight: 700; }
.showItem .sep { color: #a8a49c; }
.showItem .where { color: #d8d4cc; }
.showItem.on .sep, .showItem.on .where { color: #3a2410; }
.avatarDot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px;
  border: 1.5px solid rgba(244,242,238,0.7); vertical-align: -1px; }
#venueCard, #showCard { position: relative; background: #1d2027; border: 1.5px solid #FF6A00; border-radius: 10px;
  padding: 10px 12px; font-size: 13px; line-height: 1.5; margin: 6px 0 4px; }
/* v0.3.1: card anatomy — name line, description line, price chip;
   the ✕ rides the card's top-right corner. */
.cardName { font-weight: 800; color: #f2b21c; font-size: 15px; padding-right: 28px; }
.cardDesc { color: #e6e2da; margin: 2px 0 6px; }
.cardRow { display: flex; justify-content: space-between; align-items: center; margin: 3px 0; gap: 10px; }
.priceChip { background: #f2b21c; color: #14161c; font-weight: 800; border-radius: 7px;
  padding: 2px 10px; white-space: nowrap; }
.cardClose { position: absolute; top: 6px; right: 6px; padding: 1px 8px; font-size: 12px;
  background: #23262e; color: #d8d4cc; border-radius: 8px; z-index: 2; }
#venueCard b, #showCard b { color: #f2b21c; }
#venueCard .ssLine, #showCard .ssLine { color: #a8a49c; font-size: 12px; }
#hostBtn { width: 100%; margin-top: 8px; background: #57a047; color: #fff; font-weight: 800; padding: 10px; }
#hostBtn:hover { background: #65b657; }

/* ---------- v0.4: THE BIG ONE finale card ---------- */
#finaleCard { position: relative; background: #241a08; border: 2px solid #f2b21c; border-radius: 10px;
  padding: 12px 26px 12px 12px; margin: 0 0 12px; }
#finaleCard .cardName { color: #f2b21c; font-weight: 900; font-size: 17px; margin-bottom: 4px; }
#finaleCard .cardDesc { color: #e8e0cc; font-size: 13px; line-height: 1.45; }
#finaleBtn { width: 100%; margin-top: 10px; background: #f2b21c; color: #26221f; font-weight: 900; padding: 12px; }
#finaleBtn:hover { background: #ffc94d; }
#tourStatus { min-height: 18px; }
#cityPanel .paletteRow button:disabled { opacity: 0.4; cursor: not-allowed; }

/* ---------- v0.5: YOUR GARAGE card ----------
   A standing card on the city screen (like the finale card, it
   is never stacked with a peek card — venue/show peeks open
   above it and close back to it). Rows wrap; nothing is
   fixed-height; the care buttons are full thumb targets. */
#garageCard { position: relative; background: #1d2027; border: 1.5px solid #3f7fbf; border-radius: 10px;
  padding: 10px 12px; font-size: 13px; line-height: 1.5; margin: 10px 0 4px; }
#garageCard .cardName { color: #7db3e8; }
#garageCard b { color: #f2b21c; }
.garageRow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 6px 0; }
.garageRow label { font-weight: 700; color: #a8a49c; }
.garageRow input[type="text"], .garageRow select { flex: 1 1 130px; min-width: 0; min-height: 40px;
  background: #14161c; color: #f4f2ee; border: 1px solid rgba(244,242,238,0.25); border-radius: 8px;
  padding: 6px 10px; font-size: 16px; }
.shineBar { flex: 1 1 120px; min-width: 80px; height: 12px; background: #14161c; border-radius: 6px;
  border: 1px solid rgba(244,242,238,0.2); overflow: hidden; }
#shineFill { height: 100%; background: linear-gradient(90deg, #b97d10, #f2b21c); transition: width 0.3s; }
.garageCare { display: flex; gap: 8px; flex-wrap: wrap; margin: 8px 0 4px; }
.garageCare button { flex: 1 1 140px; padding: 10px; font-weight: 700; }
.garageCare button small { display: block; font-weight: 400; color: #a8a49c; margin-top: 2px; }
.garageCare button:disabled { opacity: 0.4; cursor: not-allowed; }
#garageGlory { color: #f2b21c; font-weight: 700; }

#cityPicker { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 35;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.pickerCard { background: #14161c; border: 2px solid #FF6A00; border-radius: 16px;
  padding: 26px 30px; max-width: 520px; width: 100%; text-align: center;
  max-height: calc(100dvh - 30px); overflow-y: auto; }
.pickerCard h1 { margin: 0; font-size: 28px; }
.pickerCard .sub { color: #a8a49c; margin: 6px 0 16px; }
.cityPick { display: block; width: 100%; text-align: left; padding: 13px 15px; margin: 0 0 9px; font-size: 16px; }
.cityPick small { display: block; color: #a8a49c; font-size: 12.5px; margin-top: 2px; }
.cityPick:disabled { opacity: 0.45; cursor: not-allowed; }
.cityPick .lock { float: right; }
#pickerBack { margin-top: 6px; }

#notesPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 45;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.notesCard { background: #14161c; border: 2px solid #FF6A00; border-radius: 16px;
  padding: 22px 26px; max-width: 620px; width: 100%; max-height: 86vh; display: flex; flex-direction: column; }
.notesHead { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.notesHead h1 { margin: 0; font-size: 24px; }
#notesBody { overflow-y: auto; text-align: left; padding-right: 6px; }
.noteVer { border-top: 1px solid rgba(244,242,238,0.14); padding: 12px 0 6px; }
.noteVer:first-child { border-top: 0; }
.noteVer h2 { margin: 0 0 2px; font-size: 18px; color: #f2b21c; }
.noteVer h2 span { color: #a8a49c; font-size: 12.5px; font-weight: 500; margin-left: 8px; }
.noteVer ul { margin: 6px 0 8px; padding-left: 20px; }
.noteVer li { font-size: 13.5px; line-height: 1.5; margin-bottom: 5px; color: #e6e2da; }

/* ---------- v0.3: prep panel, choices, season ---------- */
#palette { max-height: calc(100vh - 90px); overflow-y: auto; }
.prepH { margin: 14px 0 7px; font-size: 14.5px; color: #f2b21c; }
#forecastCard { background: #1d2027; border: 1.5px solid #3f7fbf; border-radius: 10px;
  padding: 9px 12px; font-size: 13px; line-height: 1.5; margin-bottom: 10px; }
#forecastCard b { color: #9cc3ee; }
#forecastCard.storm { border-color: #c9332b; }
#forecastCard.storm b { color: #ff9a8a; }
.prepBtns { display: flex; flex-direction: column; gap: 6px; }
.prepBtns button { text-align: left; font-size: 13.5px; padding: 8px 10px; }
.prepBtns button small { display: block; color: #a8a49c; font-size: 11.5px; }
.prepBtns button.on { background: #FF6A00; color: #14161c; font-weight: 700; }
.prepBtns button.on small { color: #3a2410; }
.prepBtns button:disabled { opacity: 0.4; cursor: not-allowed; }
.prepRow { display: flex; justify-content: space-between; align-items: center;
  font-size: 13.5px; padding: 5px 0; }
.prepRow .stepper { display: flex; gap: 5px; align-items: center; }
.prepRow .stepper button { padding: 4px 9px; font-size: 13px; }
.prepRow .stepper b { min-width: 34px; text-align: center; color: #f2b21c; }
#orderSwagBtn { width: 100%; margin-top: 8px; background: #3f7fbf; color: #fff; font-weight: 800; padding: 10px; }
#orderSwagBtn:disabled { background: #23262e; color: #a8a49c; font-weight: 600; }
#promoChip { margin-top: 12px; }
#promoChip button { width: 100%; font-size: 13.5px; }
#promoChip button.on { background: #f2b21c; color: #14161c; font-weight: 800; }
#presetRack { display: flex; flex-direction: column; gap: 6px; }
#presetRack button { text-align: left; font-size: 13.5px; padding: 8px 10px; }
#presetRack button small { display: block; color: #a8a49c; font-size: 11.5px; }
#presetRack button .cost { float: right; color: #f2b21c; font-weight: 700; }
#presetRack button:disabled { opacity: 0.45; cursor: not-allowed; }

#choiceBar { position: absolute; left: 12px; bottom: 14px; z-index: 12;
  background: rgba(20,22,28,0.96); border: 2px solid #f2b21c; border-radius: 12px;
  padding: 11px 13px; max-width: 430px; box-shadow: 0 8px 26px rgba(0,0,0,0.55); }
#choiceText { font-size: 14px; line-height: 1.45; margin-bottom: 9px; }
.choiceRow { display: flex; gap: 8px; }
.choiceRow button { flex: 1; font-weight: 700; padding: 9px 8px; font-size: 13.5px; }
#choiceA { background: #57a047; color: #fff; }
#choiceB { background: #3f7fbf; color: #fff; }

#receiptLog { text-align: left; font-size: 13.5px; line-height: 1.65; color: #e6e2da;
  background: #1d2027; border-radius: 10px; padding: 10px 14px; margin-top: 12px; }
#receiptLog:empty { display: none; }
#nextWeekBtn { background: #FF6A00; color: #14161c; font-weight: 800; }
#seasonPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.86); z-index: 42;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#seasonBody { text-align: left; font-size: 15px; line-height: 1.8; }
#seasonBody b { color: #f2b21c; }
#newSeasonBtn { background: #57a047; color: #fff; font-weight: 800; }

/* ---------- v0.3.4: one path to show day ---------- */
/* The step marker: slim, in flow under Rev's dock, always naming
   where you are on the path. */
#crumbBar { padding: 5px 12px; font-size: 12.5px; font-weight: 800;
  letter-spacing: 1.2px; color: #f2b21c; background: #0c0e11;
  border-bottom: 1px solid rgba(244,242,238,0.08); }
/* The gates dock: fixed to the screen's bottom edge, safe-area
   padded; body.dockOn reserves the same height in flow so the
   dock never covers content. The button tells the truth — in
   .needs state it names the missing piece instead of opening. */
#gatesDock { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(16,18,22,0.97); border-top: 2px solid #FF6A00; }
#gatesDockBtn { width: 100%; min-height: 52px; font-size: 17px; font-weight: 800;
  background: #57a047; color: #fff; letter-spacing: 0.4px; }
#gatesDockBtn.needs { background: #23262e; color: #f2b21c; }
body.dockOn { padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px)); }
/* The missing-piece tap pulses the tool it just armed. */
.palItem.pulse { animation: hudPulse 0.9s ease-in-out infinite; }

@media (max-width: 900px) {
  #stage { flex-direction: column; }
  /* v1.32: NO palette reordering at phone width anymore — the
     DOM itself leads with the ⚡ Fastest start layouts (the
     preset heading, rack and build message sit directly above
     the pieces grid in index.html), so desktop and phone render
     the same top-to-bottom order with no flex-order rules.
     (The v0.3.4/v0.3.5 phone-only order block that used to live
     here was removed with this wave; it also left #buildSpendLine
     unordered at the top of the flex column — plain DOM order
     has no such trap.) */
  /* v0.3.1 fold audit (360px wide, large font): the side panels
     cap their height and scroll INSIDE themselves, so no control
     is ever a full page-scroll away from the stage. */
  #palette { width: 100%; flex: none; max-height: 68dvh; }
  #cityPanel { width: 100%; flex: none; max-height: 68dvh; }
  #titleScreen h1 { font-size: 44px; }
  #revBubble { font-size: 12.5px; }
  #revHistory { font-size: 11px; max-height: 72px; }
  #choiceBar { max-width: calc(100% - 24px); }
}

/* ---------- v0.3 Addition J: taps stay in the game ----------
   No text selection, no long-press callout ("Tap to see search
   results"), no double-tap zoom delay — anywhere in the game UI. */
body, body * { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
button, canvas, .palItem, .venueItem, .showItem, .cityPick, #revPanel {
  touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
#howToBtn { margin-top: 12px; font-weight: 700; padding: 10px 20px; }

/* ---------- v0.3 Addition L: the guided tour ---------- */
#guideRing { position: absolute; z-index: 60; pointer-events: none;
  border: 3px solid #FF6A00; border-radius: 12px;
  box-shadow: 0 0 0 4px rgba(255,106,0,0.25), 0 0 22px rgba(255,106,0,0.45);
  animation: guidePulse 1.1s ease-in-out infinite; }
@keyframes guidePulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(255,106,0,0.30), 0 0 16px rgba(255,106,0,0.35); }
  50% { box-shadow: 0 0 0 8px rgba(255,106,0,0.12), 0 0 28px rgba(255,106,0,0.55); }
}
/* ---------- v0.3.2: THE tour card — one card, big buttons ----------
   The ONLY tour surface. In flow directly under the HUD (above
   Rev's strip), sticky to the top of the screen: it scrolls into
   place and stays reachable, it never floats over a list, and
   advancing a step REPLACES the line inside it — tour text can
   never stack again (v0.3 spoke through the pager bubble + pager
   history + a floating tag at once, and the 12px Skip buried at
   the end of Rev's strip row clipped off Gary's phone). */
#guideCard { position: sticky; top: 0; z-index: 65;
  background: #1d2027; border-bottom: 2px solid #FF6A00;
  padding: 10px 14px 12px; box-shadow: 0 8px 22px rgba(0,0,0,0.4); }
#guideCard .guideHead { display: flex; justify-content: space-between;
  align-items: center; gap: 10px; }
#guideStepLabel { font-weight: 800; color: #f2b21c; font-size: 13px;
  letter-spacing: 0.6px; white-space: nowrap; }
.guideBtns { display: flex; gap: 8px; flex: 0 0 auto; }
#guideNext, #guideSkipBtn { min-height: 44px; padding: 8px 16px;
  font-size: 14px; font-weight: 800; border-radius: 10px; }
#guideNext { background: #FF6A00; color: #14161c; }
#guideSkipBtn { background: #23262e; color: #f4f2ee;
  border: 1.5px solid #FF6A00; }
#guideLine { font-size: 14.5px; line-height: 1.45; margin-top: 7px; }

/* ---------- v0.3.1: nothing clipped at the bottom ----------
   Page bottom carries the phone's safe area so the last row of
   buttons clears the gesture/nav bar at large font sizes; the
   big fixed panels pad the same way. */
body { padding-bottom: env(safe-area-inset-bottom, 0px); }
#stage { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
#titleScreen, #receipts, #cityPicker, #notesPanel, #seasonPanel {
  padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
/* The build screen's primary action rides the palette's bottom
   edge instead of living a long scroll away. */
#openGates { position: sticky; bottom: 0; box-shadow: 0 -8px 18px rgba(0,0,0,0.45); }

/* ---------- v0.3.5: PHONE PASS ----------
   Narrow-viewport only; the desktop presentation is untouched.
   Three jobs: (1) Rev off the lot is ONE plain-text line — no
   face, no bubble card, no white box; (2) each screen's first
   content under its header is the path's next action; (3)
   large-font survival — tap targets ≥48px, no fixed heights
   that can trap content, no horizontal scroll at 360px.
   Fixed-height audit behind these rules: the side panels keep
   an internal scroll cap (74dvh) but lead with their action;
   the title screen (a fixed, centered column) now scrolls and
   starts at the top so 200% text can't clip its own head; the
   awards banner and choice bar were absolutely positioned with
   a 300px min-width / fixed offsets and are now inset-bound
   with internal scroll; the gates dock's reserved in-flow
   space grows to match a two-line button at big fonts; modal
   cards cap at 100dvh-20px and scroll internally. */
@media (max-width: 900px) {
  html, body { max-width: 100%; overflow-x: clip; }
  #hud { gap: 8px; padding: 8px 10px; }
  #hud > * { min-width: 0; }
  #hud .brand { font-size: 1.35rem; overflow-wrap: anywhere; }
  .hudstat { overflow-wrap: anywhere; }
  .hudstat.phase { flex: 1 1 100%; margin-left: 0; }
  button, .venueItem { min-height: 48px; }
  #speedBtns button, .hudbtn { min-width: 48px; min-height: 48px; }
  .cardClose { min-width: 48px; min-height: 48px; padding: 8px; }
  .cardName { padding-right: 58px; }
  #revTab, #revClose, .hostRowBtn, #guideNext, #guideSkipBtn { min-height: 48px; }
  #stage { padding: 8px; gap: 8px; }
  #palette, #cityPanel { max-height: 74dvh; overscroll-behavior: contain; }

  /* (1) Rev = text only off the lot (menus + build). v0.5: the
     bubble and history are named explicitly (not just their
     #revBar wrapper) — belt and braces beside game.js's inline
     enforcement, so no stylesheet path can resurrect them. */
  #revPanel.textOnly { background: transparent; border-bottom: 0;
    padding: 8px 12px; cursor: default; }
  #revPanel.textOnly #revFace,
  #revPanel.textOnly #revBar,
  #revPanel.textOnly #revBubble,
  #revPanel.textOnly #revHistory,
  #revPanel.textOnly #revDot { display: none !important; }
  #revPanel.textOnly #revLine { display: block; flex: 1 1 auto; min-width: 0;
    color: #d8d4cc; background: transparent; font-size: 1rem; line-height: 1.35;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  #revPanel.textOnly #revClose { margin-left: 8px; }

  /* (2) Phone-first ordering — city: HOST rows lead the panel. */
  #cityPanel { display: flex; flex-direction: column; }
  #cityName { order: 0; }
  #seasonLine { order: 1; }
  #hostHeading { order: 2; }
  #venueList { order: 3; }
  #venueCard { order: 4; }
  #cityIntro { order: 5; }
  #liveHeading { order: 6; }
  #showList { order: 7; }
  #showCard { order: 8; }
  #garageCard { order: 9; }
  #tourHeading { order: 10; }
  #tourIntro { order: 11; }
  #tourButtons { order: 12; }
  #tourStatus { order: 13; }
  #notesBtnCity { order: 14; }
  #changeCityBtn { order: 15; }

  /* v0.5 narrow pass — the garage card (standing rule: every new
     surface gets this pass; Gary's LARGE accessibility font is
     the spec, so rows wrap, targets are ≥48px, no fixed heights,
     and the card never shares the screen with a peek card's
     content — it sits below them in the one column). */
  #garageCard { overflow-wrap: anywhere; }
  .garageRow input[type="text"], .garageRow select { min-height: 48px; flex-basis: 150px; }
  .garageCare button { min-height: 48px; flex-basis: 150px; }
  .shineBar { flex-basis: 100px; }

  /* v0.8 narrow pass — the showroom (same standing rule): the
     open button is a full thumb target, the overlay card caps
     at the viewport and scrolls inside, the canvas keeps a
     sane slice of a short screen, care stays ≥48px (it rides
     the .garageCare rule above). */
  #garage3dBtn { min-height: 48px; }
  #garage3dWrap { padding: 10px; }
  .garage3dCard { max-height: calc(100dvh - 20px); padding: 14px; }
  #glGarage { height: 44dvh; }

  /* (3) Large-font survival. */
  #titleScreen { justify-content: flex-start; overflow-y: auto;
    padding-top: max(18px, env(safe-area-inset-top, 0px)); }
  #titleScreen > * { flex-shrink: 0; }
  #titleScreen h1 { font-size: 2.5rem; line-height: 1.05; text-align: center;
    overflow-wrap: anywhere; }
  #cityPicker, #receipts, #notesPanel, #seasonPanel { padding: 10px; overflow-y: auto; }
  .pickerCard, .receiptCard, .notesCard { max-height: calc(100dvh - 20px); padding: 18px; }
  .notesCard { height: auto; }
  #notesBody { min-height: 0; }
  .receiptCard .grid { grid-template-columns: 1fr; }
  .receiptBtns { flex-wrap: wrap; }
  .receiptBtns button { flex: 1 1 150px; }
  #guideCard { max-height: 46dvh; overflow-y: auto; }
  #guideCard .guideHead { flex-wrap: wrap; }
  #guideStepLabel { white-space: normal; overflow-wrap: anywhere; }
  .guideBtns { flex-wrap: wrap; }
  #guideLine { overflow-wrap: anywhere; }
  #awardsBanner { left: 12px; right: 12px; transform: none; min-width: 0;
    max-height: calc(100% - 24px); overflow-y: auto; }
  #choiceBar { left: 8px; right: 8px; bottom: 8px; max-width: none; }
  .choiceRow { flex-wrap: wrap; }
  .choiceRow button { flex: 1 1 140px; }
  .venueItem { align-items: stretch; }
  .venueItem > span:first-child { flex: 1 1 150px; min-width: 0; overflow-wrap: anywhere; }
  .venueItem .meta { white-space: normal; overflow-wrap: anywhere; }
  .hostRowBtn { align-self: center; }
  .showItem, #venueCard, #showCard { overflow-wrap: anywhere; }
  .cardRow { flex-wrap: wrap; }
  .prepRow { flex-wrap: wrap; gap: 8px; }
  .prepRow .stepper button { min-width: 48px; min-height: 48px; }
  #gatesDock { padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); }
  #gatesDockBtn { min-height: 56px; white-space: normal; line-height: 1.25; }
  body.dockOn { padding-bottom: calc(112px + env(safe-area-inset-bottom, 0px)); }
  #openGates { min-height: 56px; }
  #lotWrap { flex: 1 1 100%; width: 100%; min-width: 0; }
}

/* ---------- v0.7: FIRST DIMENSION (the 3D viewer) ----------
   The WebGL canvas overlays #lot exactly (same box, same
   rounded corners) and sits below the lot's own overlays
   (awards banner, choice bar). The control bar rides the
   lot's top-right; the caption names a tapped car bottom-left.
   touch-action: none — drags orbit, they don't scroll. */
#gl3d { position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  border-radius: 12px; z-index: 2; touch-action: none; background: #79a84c; }
/* v1.113: the lot stage's OWN fullscreen (the #branfordWrap
   precedent). Fullscreen is requested on #lotWrap itself, so
   the browser presents the stage alone — the canvas (absolute
   inset 0) fills it, and the bar / caption / eye overlays ride
   as the wrap's own children. v1.111 fullscreened the whole
   page instead: menus on top, the lot in its in-flow box —
   "half menu, half screen" on a real phone. */
#lotWrap:fullscreen { width: 100%; height: 100%; background: #101216; }
#lotWrap:fullscreen #gl3d { border-radius: 0; }
#lotWrap:-webkit-full-screen { width: 100%; height: 100%; background: #101216; }
#lotWrap:-webkit-full-screen #gl3d { border-radius: 0; }
#awardsBanner { z-index: 9; }
#bar3d { position: absolute; top: 10px; right: 10px; z-index: 8; display: flex; gap: 8px; }
#bar3d button { min-height: 48px; padding: 10px 14px; font-weight: 700;
  background: rgba(20,22,28,0.92); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 10px; }
#cap3d { position: absolute; left: 12px; bottom: 12px; z-index: 8; max-width: calc(100% - 24px);
  background: rgba(20,22,28,0.94); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 10px;
  padding: 9px 13px; font-size: 15px; font-weight: 700; }
#note3d { position: absolute; left: 12px; right: 12px; top: 12px; z-index: 8;
  background: rgba(20,22,28,0.96); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 10px;
  padding: 11px 13px; font-size: 14px; line-height: 1.45; }

/* ---------- v0.8: BUILD IN 3D — auto-fit + the showroom ----------
   Desktop auto-fit is JS-driven (game.js applyFit): the wrap
   only becomes a fixed, hidden-overflow stage when body.fitted
   is set, and that only happens above 900px. Unfitted (JS off,
   or a narrow window) the wrap is a plain block and every rule
   below stays out of the way — the phone pass is untouched.
   v1.84: the fitted stage is the whole window again — the
   v1.83 room (board rail + header line) is retired, and with
   it the stage box that stopped at its edges. Stats live on
   their own page, behind their buttons. */
#fitScale { transform-origin: 0 0; }
@media (min-width: 901px) {
  body.fitted { overflow: hidden; }
  body.fitted #fitWrap { position: fixed; inset: 0; overflow: hidden; background: #101216; }
  /* In fitted mode the side panels stop dictating the column
     height: they cap at the lot's height and scroll inside,
     like the city panel always did. */
  body.fitted #palette, body.fitted #cityPanel { max-height: 792px; overflow-y: auto; }
}
/* The showroom: a fixed overlay in the family of the other
   panels (receipts/notes), gold-bordered, one surface at a
   time. The canvas is a void — #101116, the adapter paints
   the dark backdrop into the scene itself. */
#garage3dBtn { border: 2px solid #f2b21c; font-weight: 800; }
#noteGarage3d { background: rgba(20,22,28,0.96); color: #f4f2ee; border: 2px solid #f2b21c;
  border-radius: 10px; padding: 11px 13px; font-size: 14px; line-height: 1.45; margin: 8px 0 4px; }
#garage3dWrap { position: fixed; inset: 0; z-index: 45; background: rgba(8,9,12,0.88);
  display: flex; align-items: center; justify-content: center; padding: 14px; }
.garage3dCard { background: #14161c; border: 2px solid #f2b21c; border-radius: 16px;
  padding: 16px; width: min(94vw, 880px); max-height: calc(100dvh - 24px); overflow-y: auto; }
.garage3dHead { display: flex; justify-content: space-between; align-items: center;
  gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
#garage3dLabel { font-weight: 800; font-size: 17px; color: #f4f2ee; overflow-wrap: anywhere; min-width: 0; }
#garage3dExit { min-height: 48px; font-weight: 700; flex: 0 0 auto; }
#glGarage { width: 100%; height: min(52dvh, 460px); display: block; border-radius: 12px;
  background: #101116; touch-action: none; }
.g3care { margin-top: 10px; }
#garage3dMsg { min-height: 18px; }

/* ---------- v1.2: THE LIVING MAP ---------- */
#city3dBtn { border: 2px solid #f2b21c; font-weight: 800; min-height: 48px; }
/* v1.20: the Harbor grey-box entry — plain grey frame, no neon:
   the button dresses like the district (cardboard, not polish). */
#harbor3dBtn { border: 2px solid #8b8e93; font-weight: 800; min-height: 48px; }
#noteCity3d, #noteHarbor3d { background: rgba(20,22,28,0.96); color: #f4f2ee; border: 2px solid #f2b21c;
  border-radius: 10px; padding: 11px 13px; font-size: 14px; line-height: 1.45; margin: 8px 0 4px; }
#noteHarbor3d { border-color: #8b8e93; }
#city3dWrap, #harbor3dWrap { position: fixed; inset: 0; z-index: 46; background: linear-gradient(180deg, rgba(42,33,64,0.94), rgba(10,9,16,0.94)); /* v1.13: neon-dusk frame for the Living Map */
  display: flex; align-items: center; justify-content: center; padding: 14px; }
#harbor3dWrap { background: rgba(24,25,28,0.94); /* v1.20: the grey-box keeps a plain grey frame */ }
.city3dCard { background: #14161c; border: 2px solid #f2b21c; border-radius: 16px;
  padding: 16px; width: min(96vw, 1080px); max-height: calc(100dvh - 24px); overflow-y: auto; }
.city3dHead { display: flex; justify-content: space-between; align-items: center;
  gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
#city3dLabel, #harbor3dLabel { font-weight: 800; font-size: 17px; color: #f4f2ee; overflow-wrap: anywhere; min-width: 0; }
.city3dBtns { display: flex; gap: 8px; flex-wrap: wrap; }
.city3dBtns button { min-height: 48px; font-weight: 700; }
#glCity, #glHarbor { width: 100%; height: min(62dvh, 640px); display: block; border-radius: 12px;
  background: #79a84c; touch-action: none; }
#glHarbor { background: #7e8287; /* v1.20: grey-box canvas ground tone */ }
@media (max-width: 760px) {
  #city3dWrap, #harbor3dWrap { padding: 10px; }
  .city3dCard { max-height: calc(100dvh - 20px); padding: 14px; }
  #glCity, #glHarbor { height: 52dvh; }
  .city3dBtns { width: 100%; }
  .city3dBtns button { flex: 1 1 140px; }
}

/* ---------- v1.27: EYE VIEW — drive HUD + spectator bars ----------
   Large text is the spec (Gary's accessibility size): guide and
   labels ≥19px, every driving/walking control ≥56px tall. The
   drive HUD lives in-flow under the Living Map canvas; the
   spectator bars ride the lot board like #cap3d does. */
#eyeCruiseBtn { border: 2px solid #f2b21c; font-weight: 800; min-height: 48px; }
#noteEyeDrive { background: rgba(20,22,28,0.96); color: #f4f2ee; border: 2px solid #f2b21c;
  border-radius: 10px; padding: 11px 13px; font-size: 14px; line-height: 1.45; margin: 8px 0 4px; }
#eyeHud { margin-top: 10px; background: rgba(20,22,28,0.97); border: 2px solid #f2b21c;
  border-radius: 12px; padding: 12px; color: #f4f2ee; }
#eyeGuide { font-size: 21px; font-weight: 800; line-height: 1.35; margin-bottom: 10px; overflow-wrap: anywhere; }
.eyeRow { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0; }
.eyeRow button { min-height: 52px; font-weight: 700; font-size: 17px; flex: 1 1 150px; }
.eyeSchemeLabel { font-size: 17px; font-weight: 700; }
.eyeScheme.on { background: #f2b21c; color: #14161c; }
.eyeControls { margin-top: 8px; }
.eyeBig { min-height: 60px; min-width: 64px; font-size: 19px; font-weight: 800; touch-action: none; }
#eyeTouchControls { display: flex; gap: 8px; }
#eyeTouchControls .eyeBig { flex: 1 1 0; }
.eyeDpad { display: grid; grid-template-columns: repeat(3, 76px); grid-template-rows: repeat(2, 60px);
  gap: 8px; justify-content: center; margin: 6px 0; }
.eyeDpad .eyeBig { width: 76px; height: 60px; }
#eyePadUp, #eyeWalkUp { grid-column: 2; grid-row: 1; }
#eyePadLeft, #eyeWalkLeft { grid-column: 1; grid-row: 2; }
#eyePadDown, #eyeWalkDown { grid-column: 2; grid-row: 2; }
#eyePadRight, #eyeWalkRight { grid-column: 3; grid-row: 2; }
#eyeTiltControls .eyeBig { width: 100%; margin: 4px 0; }
#eyeTiltControls .eyeRow .eyeBig { flex: 1 1 0; width: auto; }
#eyeBar { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 9;
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  background: rgba(20,22,28,0.97); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 12px; padding: 10px 12px; }
#eyeBarLabel { font-size: 20px; font-weight: 800; flex: 1 1 180px; }
#eyeStepInBtn { min-height: 56px; font-size: 19px; font-weight: 800; flex: 1 1 220px; }
#eyeBarClose { min-height: 56px; min-width: 56px; font-size: 19px; }
/* v1.39 HOP IN: the Get-in bar rides the lot board exactly like
   the ride-offer bar — same large text, same 56px actions. */
#eyeCarBar { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 9;
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  background: rgba(20,22,28,0.97); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 12px; padding: 10px 12px; }
#eyeCarLabel { font-size: 20px; font-weight: 800; flex: 1 1 180px; }
#eyeGetInBtn { min-height: 56px; font-size: 19px; font-weight: 800; flex: 1 1 220px; }
#eyeCarBarClose { min-height: 56px; min-width: 56px; font-size: 19px; }
#eyeCarBar.hidden { display: none; }
#eyeRideHud { position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 9;
  background: rgba(20,22,28,0.97); color: #f4f2ee; border: 2px solid #f2b21c; border-radius: 12px; padding: 10px 12px; }
#eyeRideLabel { font-size: 20px; font-weight: 800; margin-bottom: 6px; }
#eyeRideHud .eyeRow button { min-height: 56px; font-size: 18px; font-weight: 800; }
#eyeRideHud.hidden, #eyeBar.hidden, #eyeHud.hidden { display: none; }

/* ================================================================
   v1.11: COMIC MENUS + '80s LOADING STORY — the game's FACE.
   A SKIN, not a re-layout: every control keeps its id, its place
   in the mental map, and its size or better. The square boxy
   panels are gone — angled/rounded comic panels with ink-line
   borders and sunset-neon trim. The black void around the play
   column is now the comic urban city (assets/city-surround.jpg),
   painted on the BODY so the fitted wrap and the phone column
   both sit inside the same page of the comic; side panels go
   translucent at the edges so the skyline breathes through,
   while anything carrying a number (the garage card, the HUD
   stats' own ground) stays effectively opaque — readability
   outranks style every time. The play surface stays brightest.
   ================================================================ */
html, body { background: linear-gradient(rgba(7,8,14,0.55), rgba(7,8,14,0.80)), url('assets/frontpage-combo-bg.jpg?v=1.4') center 22% / cover fixed no-repeat #0b0d16; }
/* v1.12: the combo IS the front-page background (Gary: 'use that in this') — the dark gradient above keeps HUD/menu text legible over the art; panels keep their translucency. */
/* v1.15.1: LOADING STATE ONLY — while <body> carries .loading
   (set in the static HTML, removed by the loading story when it
   finishes) the smoked-glass wash above is OFF: the combo city
   art shows at FULL strength around the torn comic page, so the
   page visibly floats on the bright city. The wash returns the
   moment loading finishes — the rest of the front page is
   unchanged. Loader legibility stays element-local (v1.13.1:
   caption card, skip button, bar backing, music-note pill). */
body.loading { background: url('assets/frontpage-combo-bg.jpg?v=1.4') center 22% / cover fixed no-repeat #0b0d16; }
body.fitted #fitWrap { background: linear-gradient(180deg, rgba(9,7,18,0.42), rgba(9,7,18,0.66)); }

/* ---------- the graffiti wordmark (title, loading, header) ----------
   '80s urban bubble lettering by CSS: sunset-neon gradient fill,
   hard ink stroke, hard drop shadow. Deliberately simple letter
   shapes — it must read at a glance at phone size, so the flavor
   lives in the fill and the outline, never in wildstyle mush. */
.graffitiWord { font-weight: 900; letter-spacing: 1.5px; line-height: 1.02;
  background: linear-gradient(180deg, #ffe259 0%, #ffa751 38%, #ff5e8a 68%, #b04dff 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  -webkit-text-stroke: 2px #160510;
  filter: drop-shadow(4px 4px 0 #160510) drop-shadow(0 0 16px rgba(255,94,138,0.35));
  transform: rotate(-2deg); }
.graffitiWord .amp { color: transparent; }
#hud .brand.graffitiMini { font-size: 24px;
  background: linear-gradient(180deg, #ffe259 0%, #ffa751 45%, #ff5e8a 80%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  -webkit-text-stroke: 1px #160510;
  filter: drop-shadow(2px 2px 0 #160510); transform: rotate(-1.5deg); }
#hud .brand.graffitiMini .amp { color: transparent; }

/* ---------- header: the square shit is gone ---------- */
#hud { background: linear-gradient(100deg, rgba(28,17,48,0.97), rgba(44,20,58,0.95) 55%, rgba(18,20,40,0.97));
  border-bottom: 3px solid #0b0b0e; box-shadow: 0 3px 0 #FF6A00, 0 10px 24px rgba(0,0,0,0.45);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 5px), 0 100%); padding-bottom: 13px; }
#hud .hudbtn, #speedBtns button { border: 2px solid #0b0b0e; border-radius: 12px 4px 12px 4px;
  box-shadow: 2px 2px 0 rgba(0,0,0,0.5); }
#hud .hudstat { background: rgba(10,10,18,0.55); border-radius: 9px 3px 9px 3px; padding: 2px 8px; }
#revPanel { background: linear-gradient(90deg, rgba(24,16,44,0.96), rgba(16,18,34,0.94));
  border-bottom: 2px solid #0b0b0e; box-shadow: 0 2px 0 rgba(255,106,0,0.65); }
#crumbBar { background: rgba(10,8,20,0.88); }
#guideCard { border-bottom: 3px solid #0b0b0e; box-shadow: 0 3px 0 #FF6A00, 0 8px 22px rgba(0,0,0,0.4); }

/* ---------- side menus: comic panels that blend into the city ---------- */
#palette, #cityPanel { background: linear-gradient(165deg, rgba(32,21,56,0.93), rgba(17,19,34,0.90));
  border: 2.5px solid #0b0b0e; border-radius: 16px 5px 18px 6px;
  box-shadow: 5px 5px 0 rgba(0,0,0,0.5), inset 0 0 0 2px rgba(255,167,81,0.16); }
#palette button, #cityPanel button { border: 2px solid rgba(6,6,10,0.85); border-radius: 11px 4px 11px 4px; }
#garageCard { background: #1d2027; }  /* numbers live here — stays solid, per the readability rule */
#venueCard, #showCard, #forecastCard, #finaleCard { border-radius: 12px 4px 12px 4px; border-width: 2px; }
.receiptCard, .pickerCard, .notesCard, .garage3dCard, .city3dCard {
  background: linear-gradient(170deg, rgba(30,20,52,0.98), rgba(18,20,34,0.98));
  border: 2.5px solid #0b0b0e; border-radius: 16px 5px 18px 6px;
  box-shadow: 6px 6px 0 rgba(0,0,0,0.55), 0 0 0 3px #FF6A00; }
#gatesDock { background: linear-gradient(180deg, rgba(24,16,44,0.97), rgba(14,14,26,0.98));
  border-top: 3px solid #0b0b0e; box-shadow: 0 -3px 0 #FF6A00; }
#awardsBanner, #choiceBar { border-radius: 14px 5px 14px 5px; border-width: 2.5px; }

/* ---------- menu art: the cast frames the UI, never covers it ---------- */
.menuArtWide { display: block; width: 100%; height: 88px; object-fit: cover; object-position: center 26%; }
/* v1.83: the Build palette's banner is the stats-purple panel
   (the same collage + veils as the title backdrop) — the
   portrait retired from the door, consistently. */
.menuArtPurple { background-color: #0a0714;
  background-image: linear-gradient(0deg, rgba(10,7,20,.82), rgba(10,7,20,.30) 55%, rgba(10,7,20,.55)),
    url('assets/gtcustomz-collage-background.jpg?v=1.83');
  background-size: cover; background-position: center 30%;
  border: 2.5px solid #0b0b0e; border-radius: 12px 4px 12px 4px; margin: 2px 0 10px;
  box-shadow: 3px 3px 0 rgba(0,0,0,0.5); pointer-events: none; }
.castAccent { float: right; width: 58px; height: 78px; object-fit: cover; object-position: center 18%;
  border: 2.5px solid #0b0b0e; border-radius: 10px 3px 10px 3px; margin: 0 0 8px 10px;
  box-shadow: 3px 3px 0 rgba(0,0,0,0.5); transform: rotate(2deg); pointer-events: none; }
.castAccent.big { width: 72px; height: 96px; }

/* ---------- title screen: Boss + Rev flank the graffiti title ---------- */
#titleScreen { background: linear-gradient(180deg, rgba(10,7,20,0.66), rgba(10,7,20,0.86)); }
#titleScreen h1.graffitiWord { font-size: 68px; margin: 16px 0 0; }
.titleHeroes { display: flex; align-items: flex-end; justify-content: center; gap: 16px; margin: 10px 0 14px; }
.titleHeroes img { height: 172px; border: 3px solid #0b0b0e; border-radius: 14px 5px 14px 5px;
  box-shadow: 5px 5px 0 rgba(0,0,0,0.55); pointer-events: none; }
#titleHero { width: 150px; object-fit: cover; object-position: center 20%; transform: rotate(-2deg); }
#titleRev { width: 118px; object-fit: contain; background: #f4f2ee; transform: rotate(2deg); }

/* ---------- v1.110: the title tiles are doors — CLICKABLE WHEN RAISED ----------
   Gary (Nov 3): "utilize them into links" — "clickable when
   raised" — "the rev one see yellow outline" — "match that
   to other tile". The yellow outline IS the armed mark:
   Rev's tile already wore it at rest (the #titleRev rule
   beside the governor toast, further down); the comic tile
   wore nothing, and both tiles were pointer-events:none —
   pictures, not doors. Now ONE shared armed style covers
   both tiles identically: the gold edge says "this is a
   door", and the RAISE — hover or keyboard focus on a
   desktop, the press itself on a phone — lifts the tile
   on its own tilt, deepens its shadow and steps the gold
   edge out; the click that lands on the raised tile fires
   its door (game.js delegates each tile to the very button
   its door has always used). No tile is second-class:
   same outline, same lift, same terms. */
.titleHeroes img.tileLink { pointer-events: auto; cursor: pointer;
  outline: 2px solid #f2b21c; outline-offset: 0;
  transition: transform .16s ease, box-shadow .16s ease, outline-offset .16s ease; }
#titleHero.tileLink:hover, #titleHero.tileLink:focus-visible, #titleHero.tileLink:active {
  transform: rotate(-2deg) translateY(-7px) scale(1.045);
  box-shadow: 9px 12px 0 rgba(0,0,0,0.55); outline-offset: 3px; }
#titleRev.tileLink:hover, #titleRev.tileLink:focus-visible, #titleRev.tileLink:active {
  transform: rotate(2deg) translateY(-7px) scale(1.045);
  box-shadow: 9px 12px 0 rgba(0,0,0,0.55); outline-offset: 3px; }

/* ---------- governor toast: Rev's face on the announcement ---------- */
#govToast { position: fixed; right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); z-index: 70;
  display: flex; align-items: center; gap: 10px; max-width: min(430px, calc(100vw - 28px));
  background: #f4f2ee; color: #26221f; border: 3px solid #0b0b0e; border-radius: 14px 5px 14px 5px;
  box-shadow: 5px 5px 0 rgba(0,0,0,0.55); padding: 9px 13px 9px 9px;
  font-size: 14px; line-height: 1.4; font-weight: 600; }
#govToastFace { width: 54px; height: 54px; flex: 0 0 auto; object-fit: cover; object-position: center 22%;
  background: #fff; border: 2.5px solid #0b0b0e; border-radius: 50%; transform: rotate(-3deg); }

/* ---------- loading screen: just video (v1.107) ----------
   Gary's ruling (Tue Nov 3, 2026): the boot is the film
   alone. The '80s comic card system that served this
   screen from v1.11 through v1.106 (the paper card, the
   spotlight window, the caption row with Rev's bust, the
   torn edge) is retired — the story it told lives on as
   Comic Book page 3, "Back to Rev", permanently. What
   stands here now: the film's poster frame (the film
   itself layers over it when live — the movie block
   below), the LOT BOSS wordmark, the progress bar and
   the skip. The bare loader (no film) is this same face
   standing over the poster still. #loadScreen stays
   transparent over the lot: the title screen's bright
   city shows through the whole boot, as it has since
   v1.15 (body.loading in game.js drops the smoked wash
   until the handoff). */
#loadScreen { position: fixed; inset: 0; z-index: 200; overflow-y: auto; display: flex; align-items: flex-end; justify-content: center;
  background: transparent; padding: 0 14px calc(18px + env(safe-area-inset-bottom)); }
#loadPoster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.loadCard { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: 100%; max-width: min(92vw, 430px); }
.loadWord { font-size: clamp(44px, 13vw, 68px); font-weight: 900; letter-spacing: 3px; line-height: 1; text-align: center;
  background: linear-gradient(180deg, #ffd23e 5%, #FF6A00 55%, #FF2E88 105%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 3px 0 rgba(10,10,14,.85)) drop-shadow(0 10px 22px rgba(0,0,0,.45)); }
.loadBar { width: 100%; height: 14px; background: #101018; border: 2px solid #f7f3e8; border-radius: 8px; overflow: hidden; }
#loadFill { height: 100%; width: 4%; background: repeating-linear-gradient(45deg, #FF6A00 0 14px, #ffd23e 14px 28px); transition: width .3s ease; }
#loadSkip { background: #FF6A00; color: #14100a; border: 3px solid #14161c; border-radius: 12px;
  min-height: 52px; padding: 12px 30px; font-size: 17px; font-weight: 900; letter-spacing: 1px; cursor: pointer; box-shadow: 0 4px 0 #14161c; }
#loadScreen.done { opacity: 0; pointer-events: none; transition: opacity 0.35s ease; }


/* v1.104: THE BOOT MOVIE — the film is the loading screen's
   hero visual (assets/boot-intro.mp4: harbour fly-in, the
   main-street cruise, Rev's welcome, the CarShowMafia
   coin). It layers over the lot exactly like the bright
   boot's city surround, under the loader card — and since
   v1.107 the card is just the wordmark, the bar and the
   skip, which stay up over the film as its status line
   (the v1.104–v1.106 run hid the card while the film
   played; there is no comic half left to hide). Without
   .movieOn — video blocked, errored, or reduced motion —
   the poster frame stands in the film's place (the bare
   loader) and the boot hands off on the load.
   #loadScreen.done (above) still owns the exit fade.
   A player who has seen the film through once gets the
   taller skip from the first frame of every later boot
   (the .bootSeen rule, set by game.js from the
   localStorage flag the film earns at its end). */
#loadMovie { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; display: none; background: #06070c; }
#loadScreen.movieOn { background: #06070c; }
#loadScreen.movieOn #loadMovie { display: block; }
#loadScreen.movieOn #loadPoster { display: none; }
#loadScreen.bootSeen #loadSkip { font-size: 19px; min-height: 58px; padding: 14px 38px; }


@media (max-width: 900px) {
  #titleScreen h1.graffitiWord { font-size: 2.9rem; }
  .titleHeroes img { height: 128px; }
  #titleHero { width: 112px; }
  #titleRev { width: 88px; }
  #govToast { left: 14px; right: 14px; max-width: none; }
  .castAccent { width: 50px; height: 68px; }
}
@media (prefers-reduced-motion: reduce) {
  #loadFill { transition: none; }
}

/* ---------- v1.12 WORLD LIFE ---------- */
#titleRev, #govToastFace { background: #0b0d16 url('assets/city-surround-urban.jpg?v=1.4') center / cover no-repeat; border: 3px solid #14161c; outline: 2px solid #f2b21c; }
#adsCard { background: rgba(20,22,28,0.92); border: 2px solid #f2b21c; border-radius: 12px; padding: 12px; margin: 14px 0; }
#adsCard .cardName { font-weight: 900; font-size: 17px; margin-bottom: 6px; }
#adBtns { display: flex; flex-direction: column; gap: 7px; margin: 8px 0; }
#adBtns button { font-size: 16px; padding: 12px; text-align: left; }
#adBtns button:disabled { opacity: 0.55; }
#shiftBtn { font-size: 16px; padding: 12px; margin-top: 8px; }
#ssCard { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-start; justify-content: center; overflow-y: auto; background: rgba(5,6,10,0.72); padding: 18px 10px; }
#ssCard.hidden { display: none !important; }

/* ---------- v1.15: EXIT PROMPT (root back-press) ----------
   The game's own exit door: a fixed overlay in the family of
   the other panels, with LARGE plain text and two ≥52px
   buttons — it has to read at Gary's accessibility size on a
   phone, mid-show, one-handed. The HUD is untouched. */
#exitPrompt { position: fixed; inset: 0; z-index: 80; background: rgba(8,9,12,0.88);
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.exitCard { background: #14161c; border: 3px solid #FF6A00; border-radius: 16px;
  padding: 26px 28px; max-width: 560px; width: 100%; text-align: center;
  max-height: calc(100dvh - 30px); overflow-y: auto; }
.exitCard h1 { margin: 0 0 10px; font-size: 32px; }
.exitBody { font-size: 20px; line-height: 1.5; color: #f4f2ee; margin: 8px 0; }
.exitBtns { display: flex; gap: 12px; justify-content: center; margin-top: 20px; flex-wrap: wrap; }
.exitBtns button { flex: 1 1 200px; min-height: 56px; font-size: 19px; font-weight: 800; padding: 14px; }
#exitKeepBtn { background: #57a047; color: #fff; }
#exitLeaveBtn { background: #23262e; color: #f4f2ee; border: 2px solid #c9332b; }

/* ---------- v1.25: SAVE BACKUP panel ----------
   A menu-surface overlay in the notes family (never the HUD).
   The confirm reuses the exit prompt's big plain language —
   it has to read at large text on a phone, one-handed. */
#backupPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 46;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#backupPanel.hidden, #backupConfirm.hidden { display: none; }
.backupBody { overflow-y: auto; text-align: left; padding-right: 6px; }
.backupNote { font-size: 16px; line-height: 1.55; color: #f4f2ee; }
.backupText { width: 100%; box-sizing: border-box; margin-top: 10px; background: #0d0f13;
  color: #e6e2da; border: 1.5px solid #3a3e47; border-radius: 10px; padding: 10px;
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; line-height: 1.45; }
#backupFile { margin: 10px 0 2px; font-size: 15px; color: #f4f2ee; max-width: 100%; }
.backupMsg { font-size: 16px; font-weight: 700; line-height: 1.5; min-height: 24px; color: #9be29b; }
.backupMsg.err { color: #ff9d94; }
#backupConfirm { position: fixed; inset: 0; z-index: 82; background: rgba(8,9,12,0.9);
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#backupConfirmBtn { background: #57a047; color: #fff; }
#backupCancelBtn { background: #23262e; color: #f4f2ee; border: 2px solid #c9332b; }

/* ---------- v1.29: REPORT A BUG panel ----------
   A menu-surface overlay in the notes/backup family (never the
   HUD). One big box, big buttons — Easy-Mode spirit: it has to
   read and tap clean at large text on a phone, one-handed. */
#bugPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 47;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#bugPanel.hidden { display: none; }
.bugBody { overflow-y: auto; text-align: left; padding-right: 6px; }
.bugNote { font-size: 16px; line-height: 1.55; color: #f4f2ee; }
.bugLabel { display: block; font-size: 18px; font-weight: 800; color: #f2b21c; margin: 10px 0 6px; }
.bugText { width: 100%; box-sizing: border-box; background: #0d0f13;
  color: #e6e2da; border: 1.5px solid #3a3e47; border-radius: 10px; padding: 12px;
  font-size: 17px; line-height: 1.5; min-height: 120px; resize: vertical; }
.bugBtns { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.bugBtns button { min-height: 52px; font-size: 17px; font-weight: 800; padding: 12px 20px; flex: 1 1 180px; }
#bugSend { background: #57a047; color: #fff; }
#bugCancel { background: #23262e; color: #f4f2ee; }
.bugMsg { font-size: 17px; font-weight: 700; line-height: 1.5; min-height: 26px; color: #9be29b; }
.bugMsg.err { color: #ff9d94; }

/* ---------- v1.31: STATS BOARD panel ----------
   Same menu-surface family as the bug/backup panels (never the
   HUD). One field (your board name), one big Post button — it has
   to read and tap clean at large text on a phone, one-handed. */
#statsPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 47;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#statsPanel.hidden { display: none; }
.statsBody { overflow-y: auto; text-align: left; padding-right: 6px; }
.statsNote { font-size: 16px; line-height: 1.55; color: #f4f2ee; }
.statsLabel { display: block; font-size: 18px; font-weight: 800; color: #f2b21c; margin: 10px 0 6px; }
.statsText { width: 100%; box-sizing: border-box; background: #0d0f13;
  color: #e6e2da; border: 1.5px solid #3a3e47; border-radius: 10px; padding: 12px;
  font-size: 17px; line-height: 1.5; }
.statsBtns { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.statsBtns button { min-height: 52px; font-size: 17px; font-weight: 800; padding: 12px 20px; flex: 1 1 180px; }
#statsPost { background: #57a047; color: #fff; }
/* v1.83: the panel's lead Post button — full width, 56px, the same
   green: the control Gary couldn't find, where he looks for it. */
#statsPostTop { display: block; width: 100%; min-height: 56px; margin: 0 0 12px;
  font-size: 19px; font-weight: 900; background: #57a047; color: #fff; border-radius: 12px; }
#statsCancel { background: #23262e; color: #f4f2ee; }
.statsMsg { font-size: 17px; font-weight: 700; line-height: 1.5; min-height: 26px; color: #9be29b; }
.statsMsg.err { color: #ff9d94; }

/* ---------- v1.35: THE ACCOUNT BLOCK (stats-only login) ----------
   Lives on the MENU surfaces (title + city) only — never the HUD.
   Big targets, large text: the login records stats under the
   member's Show & Shine account name; guests see the doors plus
   one quiet line, members see their name + claim + log out. */
.acctBlock { margin: 10px 0; padding: 12px; background: rgba(13,15,19,0.72);
  border: 1.5px solid #3a3e47; border-radius: 12px; text-align: left; }
.acctTitle { font-size: 19px; font-weight: 800; color: #f2b21c; }
.acctLine { font-size: 16px; line-height: 1.5; color: #f4f2ee; margin: 6px 0; }
.acctMsg { font-size: 16px; font-weight: 700; line-height: 1.5; color: #9be29b; margin: 6px 0 0; }
.acctRow { display: flex; gap: 8px; flex-wrap: wrap; margin: 8px 0; }
.acctBlock input { flex: 1 1 180px; box-sizing: border-box; background: #0d0f13;
  color: #e6e2da; border: 1.5px solid #3a3e47; border-radius: 10px; padding: 12px;
  font-size: 17px; line-height: 1.5; min-height: 48px; }
.acctBlock button { min-height: 52px; font-size: 17px; font-weight: 800; }
.acctBlock .acctDoor { display: block; margin-top: 8px; text-decoration: none; }
#garageStatsToggle, #statsToggleBtn { min-height: 52px; font-size: 17px; font-weight: 800; }

/* ---------- v1.40: THE SWIPE WHEEL (base geometry, all lanes) —
   a see-through 120px wheel; the ROT layer turns with the drag
   (game.js sets its transform), the gold marker at the top of
   the rim reads the angle at a glance. Phone strip dressing
   lives in the v1.40 phone block below. ---------- */
#eyeWheel { width: 120px; height: 120px; border-radius: 50%; flex: 0 0 auto;
  border: 6px solid #101216;
  background: radial-gradient(circle at 50% 42%, #2b2f36 0 34%, #1d2026 55%, #262a31 72%, #121418 100%);
  box-shadow: inset 0 3px 7px rgba(255,255,255,0.28), inset 0 -8px 12px rgba(0,0,0,0.6), 0 4px 14px rgba(0,0,0,0.35);
  position: relative; touch-action: none; }
#eyeWheelRot { position: absolute; inset: 0; border-radius: 50%; }
/* v1.47 REAL LOOK: a moulded grip ring rides the rotating layer —
   segmented shading that turns WITH the wheel, like knurling on
   a real rim; an inner ring seats the spokes like a real wheel's
   dish. Same 120px visual, same ghost language — only the face. */
#eyeWheelRot::before { content: ''; position: absolute; inset: 2px; border-radius: 50%;
  background: repeating-conic-gradient(rgba(255,255,255,0.07) 0deg 6deg, transparent 6deg 18deg); }
.eyeWheelRing { position: absolute; inset: 9px; border-radius: 50%;
  border: 2px solid rgba(244,242,238,0.28); box-shadow: inset 0 1px 3px rgba(0,0,0,0.5); }
.eyeWheelMarker { position: absolute; left: 50%; top: 3px; width: 12px; height: 12px;
  margin-left: -6px; border-radius: 50%; background: #f2b21c;
  box-shadow: 0 0 0 2px rgba(15,17,20,0.55); }
.eyeWheelSpoke { position: absolute; left: 50%; top: 50%; width: 12px; height: 46px;
  margin-left: -6px; border-radius: 6px;
  background: linear-gradient(90deg, #565b64, #c9ccd2 45%, #565b64);
  box-shadow: 0 1px 3px rgba(0,0,0,0.55);
  transform-origin: 50% 0; }
.eyeWheelSpokeA { transform: rotate(90deg); }
.eyeWheelSpokeB { transform: rotate(210deg); }
.eyeWheelSpokeC { transform: rotate(330deg); }
.eyeWheelHub { position: absolute; left: 50%; top: 50%; width: 40px; height: 40px;
  margin: -20px 0 0 -20px; border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #6a6f78, #2c2f36 62%, #17191d);
  border: 3px solid #0f1114; box-shadow: 0 2px 5px rgba(0,0,0,0.55), inset 0 1px 2px rgba(255,255,255,0.35); }
.eyeWheelHub::after { content: ''; position: absolute; left: 50%; top: 50%; width: 10px; height: 10px;
  margin: -5px 0 0 -5px; border-radius: 50%; background: #f2b21c;
  box-shadow: 0 0 0 2px rgba(15,17,20,0.65); }
#eyeWheelZone { touch-action: none; }
.eyePedalsSlim .eyeBig { min-width: 58px; }

/* ---------- v1.34: PHONE EYE MODE — full screen, see-through
   controls at the bottom (Gary's phone pass, Oct 25).
   PHONE LANE ONLY (max-width: 900px): desktop drive + walk keep
   the v1.27/v1.28 layout byte-for-byte in feel. Resting opacity
   0.5 — the road shows through the pedals and the round pad;
   a pressed control goes 0.92, near-solid, so the press reads.
   The control layer is anchored to the BOTTOM edge (safe-area
   padded) and re-anchors on rotation: the portrait rules and
   the landscape rules below carry the same bottom anchor, and
   nothing here depends on orientation except spacing.
   v1.40: resting opacity tuned 0.55 → 0.5 (the bottom strip). ------- */
.eyeSummon { min-width: 56px; min-height: 56px; font-size: 22px; font-weight: 800; border-radius: 999px; }
@media (max-width: 900px) {
  /* — the scene goes full screen, edge to edge, in eyes — */
  body.eye-drive-on #city3dWrap { padding: 0; }
  body.eye-drive-on .city3dCard { width: 100vw; height: 100dvh; max-height: 100dvh; border: none; border-radius: 0; padding: 0; overflow: hidden; }
  body.eye-drive-on #glCity { width: 100vw; height: 100dvh; border-radius: 0; }
  body.eye-ride-on #gl3d { position: fixed; inset: 0; width: 100vw; height: 100dvh; border-radius: 0; z-index: 40; }
  /* — the drive layer floats see-through over the scene,
       anchored to the bottom, always — */
  body.eye-drive-on #eyeHud { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 60;
    margin: 0; background: transparent; border: none; border-radius: 0;
    /* v1.46: floor clearance = max(safe-area, 10px) + 4px; 20px side
       padding keeps every drag-start out of the Back-gesture band */
    padding: 8px 20px calc(max(env(safe-area-inset-bottom, 0px), 10px) + 4px); }
  body.eye-drive-on #eyeGuide { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 8px); left: 50%;
    transform: translateX(-50%); width: max-content; max-width: 92vw; text-align: center; z-index: 62;
    background: rgba(20,22,28,0.5); border-radius: 999px; padding: 8px 14px; margin: 0; }
  #eyeHud.panel-hidden .eyeSettingsBlock { display: none; }
  body.eye-drive-on #eyeSettingsSummon { position: fixed; top: calc(10px + env(safe-area-inset-top)); right: 10px; z-index: 61;
    background: rgba(20,22,28,0.5); color: #f4f2ee; border: 2px solid #f2b21c; }
  .eyeDriveLayer { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; }
  .eyeDriveLayer.hidden { display: none; }
  .eyePedals { display: flex; gap: 11px; order: 0; }
  .eyeSteerZones { display: flex; gap: 8px; order: 1; }
  .eyePedals .eyeBig, .eyeSteerZones .eyeBig { min-width: 76px; min-height: 84px; background: rgba(20,22,28,0.5); color: #f4f2ee; }
  /* — the round pad: circular, see-through, steering side — */
  .eyeRoundPad { width: 136px; height: 136px; border-radius: 50%; order: 1;
    background: rgba(20,22,28,0.5); border: 2px solid rgba(242,178,28,0.75);
    grid-template-columns: repeat(3, 42px); grid-template-rows: repeat(3, 42px); gap: 4px;
    justify-content: center; align-content: center; }
  .eyeRoundPad .eyeBig { width: 42px; height: 42px; min-width: 42px; min-height: 42px; border-radius: 50%;
    background: rgba(20,22,28,0.5); color: #f4f2ee; }
  #eyePadDown, #eyeWalkDown { grid-row: 3; }
  #eyePadLeft, #eyeWalkLeft, #eyePadRight, #eyeWalkRight { grid-row: 2; }
  .eyeBig.eyePressed { background: rgba(20,22,28,0.92); }
  .eyeRoundPad .eyeBig.eyePressed { background: rgba(20,22,28,0.92); }
  /* — swapped (left-handed): pedals right, steering left — */
  #eyeHud.eyeSwapped .eyePedals { order: 1; }
  #eyeHud.eyeSwapped .eyeSteerZones, #eyeHud.eyeSwapped .eyeRoundPad { order: 0; }
  /* — ride / walk: HUD floats, chrome compacts — */
  body.eye-ride-on #eyeRideHud { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 50;
    background: transparent; border: none; border-radius: 0;
    padding: 8px 10px calc(10px + env(safe-area-inset-bottom)); }
  #eyeRideHud.chrome-hidden .eyeRideChrome { display: none; }
  body.eye-ride-on #eyeRideSummon { position: fixed; top: calc(10px + env(safe-area-inset-top)); right: 10px; z-index: 51;
    background: rgba(20,22,28,0.5); color: #f4f2ee; border: 2px solid #f2b21c; }
  body.eye-ride-on #eyeRideExitBtn { min-height: 56px; background: rgba(20,22,28,0.5); color: #f4f2ee; }
  body.eye-ride-on #eyeWalkPad .eyeRoundPad { margin-left: auto; }
  body.eye-ride-on #eyeRideHud.eyeSwapped #eyeWalkPad .eyeRoundPad { margin-left: 0; margin-right: auto; }
  #eyeRideHud.eyeSwapped #eyeWalkPad .eyeRoundPad { order: 0; }
  /* — v1.40: TRUE FULL SCREEN, EVERY DRIVE (Gary's free-cruise
       screenshot is the failing case): v1.34 made the Living Map
       CARD full-viewport but never hid the town 3D header inside
       it, so "Hickory Hills in 3D" + Poster / Reset / Back walled
       off the top of the screen while driving, and the lot-side
       get-in drive never got a full-viewport scene at all. Now:
       while eye-drive-on, the town header and the card's trailing
       words are GONE, the lot scene (#gl3d) goes fixed full-
       viewport too, and the lot's own 3D bar/caption stand down.
       Exiting drive removes the class and restores everything. — */
  body.eye-drive-on #city3dWrap .city3dHead { display: none; }
  body.eye-drive-on .city3dCard > .hint { display: none; }
  body.eye-drive-on #gl3d { position: fixed; inset: 0; width: 100vw; height: 100dvh; border-radius: 0; z-index: 40; }
  body.eye-drive-on #bar3d, body.eye-drive-on #cap3d,
  body.eye-ride-on #bar3d, body.eye-ride-on #cap3d { display: none; }
  /* — v1.40: THE BOTTOM STRIP (the GRID video's shape): every
       drive scheme's controls live in ONE low translucent strip
       along the bottom edge — nothing climbs the sides. Resting
       0.5, pressed 0.92 (the .eyePressed rule above). — */
  /* v1.46: NO PANEL — the bordered strip is deleted; wheel, pedals
     and pad float as individual ghost elements directly on the scene */
  .eyeDriveLayer { background: transparent; border: none; border-radius: 0; padding: 0; align-items: flex-end; }
  /* slim pedals on the pedals side of the strip */
  .eyePedalsSlim { flex-direction: row; }
  .eyePedalsSlim .eyeBig { min-width: 72px; width: 72px; min-height: 84px; height: 84px; font-size: 15px; padding: 6px 4px; }
  /* the wheel sits on the steering side of the strip */
  #eyeWheelZone { display: flex; align-items: center; gap: 10px; order: 1; position: relative; margin-right: 2px; }
  #eyeSteerHint { position: absolute; right: 0; bottom: calc(100% + 6px); white-space: nowrap; margin: 0; }
  #eyeHud.eyeSwapped #eyeWheelZone { order: 0; }
  #eyeWheelZone.eyePressed #eyeWheel { border-color: #f2b21c; background: rgba(20,22,28,0.92); }
  /* — v1.40: walk mode wears the same bottom-strip ghost — */
  body.eye-ride-on #eyeWalkPad { background: transparent; border: none; border-radius: 0; padding: 0; margin-top: 8px; }
}
@media (max-width: 900px) and (orientation: landscape) {
  /* rotation re-anchors: same bottom edge, same handedness */
  body.eye-drive-on #eyeHud { bottom: 0; top: auto; padding-bottom: calc(max(env(safe-area-inset-bottom, 0px), 10px) + 4px); }
  #eyeWheel { width: 110px; height: 110px; }
  body.eye-ride-on #eyeRideHud { bottom: 0; top: auto; padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
  body.eye-drive-on #glCity { height: 100dvh; }
  body.eye-ride-on #gl3d { height: 100dvh; }
  .eyeRoundPad { width: 108px; height: 108px; grid-template-columns: repeat(3, 34px); grid-template-rows: repeat(3, 34px); gap: 2px; }
  .eyeRoundPad .eyeBig { width: 34px; height: 34px; min-width: 34px; min-height: 34px; }
}
@media (max-width: 900px) {
  #eyeTiltControls { flex-wrap: wrap; }
  #eyeTiltControls #eyeTiltCal, #eyeTiltControls #eyeTiltPerm { flex: 1 1 100%; }
  #eyeDpadControls { flex-wrap: wrap; }
  #eyeDpadControls .hint { flex: 1 1 100%; order: 2; }
}

/* ---------- v1.44: THE MENU GRID (title screen) ----------
   Gary (Oct 26, from his title screenshot): the six secondary
   menu buttons stacked one to a row, tall enough to push the
   Account block toward/below the fold. Now they ride in a grid
   under the full-width Pick-a-city hero: 2 across by default,
   3 across where a wide desktop honestly fits them, 1 across
   only on truly narrow screens. Equal heights per row (grid
   stretch + height:100%); labels wrap centred, never truncate.
   The grid, hero and account block share one column width so
   the account block sits directly under the menu — and the
   v1.38 scroll rule still owns the title screen, so nothing
   can be clipped at short heights. Layout only. */
#startBtn { width: min(680px, 100%); }
.menuGrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  width: min(680px, 100%); margin-top: 12px; align-items: stretch; }
.menuGrid > button, .menuGrid > a { margin: 0; }
.menuGrid > a { display: flex; text-decoration: none; }
.menuGrid button { width: 100%; height: 100%; margin: 0; min-height: 52px;
  padding: 10px 12px; font-weight: 700; font-size: 16px; line-height: 1.25;
  text-align: center; white-space: normal; overflow-wrap: anywhere;
  display: flex; align-items: center; justify-content: center; }
.menuGrid > a > button { flex: 1 1 auto; }
/* the pre-grid ID rules for these two carried margin-top:12px +
   wider padding — inside the grid they must sit flush with
   their row-mates (ID-pair specificity beats those old rules). */
#titleMenuGrid #notesBtnTitle, #titleMenuGrid #howToBtn { margin: 0; padding: 10px 12px; }
#titleScreen .acctBlock { width: min(680px, 100%); }
@media (min-width: 1100px) {
  .menuGrid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 340px) {
  .menuGrid { grid-template-columns: 1fr; }
}

/* ---------- v1.45: DRIVE FEEL — the burnout button ----------
   One honest button under every scheme's drive controls,
   centred in the bottom control zone: pedals and steering
   swap sides with handedness, the centre never moves, so it
   collides with nothing in either handedness. See-through at
   rest (0.5, the strip's own language), firms on press. */
#eyeBurnoutRow { display: flex; justify-content: center; margin-top: 8px; }
#eyeBurnout { min-width: 168px; min-height: 60px; font-size: 20px; font-weight: 900; letter-spacing: 0.5px;
  background: rgba(20,22,28,0.5); color: #f4f2ee; border: 2px solid rgba(242,178,28,0.75);
  border-radius: 14px; touch-action: none; }
#eyeBurnout.eyePressed { background: rgba(20,22,28,0.92); border-color: #f2b21c; }
@media (max-width: 900px) {
  #eyeBurnout { min-height: 56px; }
}

/* v1.45.1 hotfix (2026-10-27 evening): the Branford skeleton canvas never
   got the #glCity/#glHarbor sizing rule — it rendered into a sliver, so
   Gary's click on the skeleton button "did nothing." Same dimensions as
   its sibling canvases; background matches the skeleton sky tone. */
#glBranford { width: 100%; height: min(62dvh, 640px); display: block; border-radius: 12px;
  background: #a3a6a8; touch-action: none; }
@media (max-width: 760px) {
  #glBranford { height: 52dvh; }
}

/* v1.45.1 hotfix part 2 (2026-10-27 evening): #branfordWrap also missed the
   overlay frame rule its siblings #city3dWrap/#harbor3dWrap carry — without
   it the skeleton card rendered in page flow at the margin (Gary saw its
   buttons and blurb peeking from behind the game). Grey frame, matching
   the harbor grey-box. Label styling matches its siblings too. */
#branfordWrap { position: fixed; inset: 0; z-index: 46; background: rgba(24,25,28,0.94);
  display: flex; align-items: center; justify-content: center; padding: 14px; }
#branfordLabel { font-weight: 800; font-size: 17px; color: #f4f2ee; overflow-wrap: anywhere; min-width: 0; }
@media (max-width: 760px) {
  #branfordWrap { padding: 10px; }
}

/* ---------- v1.46: PHONE CONTROLS v2.1 — toast, one-time hint,
   desktop-help gate, bottom-centre burnout ----------
   The entry toast: a pill that lives ~2.5s (game.js owns the
   timer). Base lane centres it in the HUD flow; the phone lane
   pins it top-center under the HUD. The steering hint is a
   small ghost pill that shows once per wheel-scheme entry. */
#eyeToast { width: fit-content; max-width: 92%; margin: 0 auto 8px; text-align: center;
  background: rgba(20,22,28,0.82); color: #f4f2ee; border: 2px solid rgba(242,178,28,0.85);
  border-radius: 999px; padding: 8px 16px; font-size: 19px; font-weight: 800; }
.eyeSteerHint { background: rgba(20,22,28,0.5); color: #f4f2ee; border: 1.5px solid rgba(242,178,28,0.6);
  border-radius: 999px; padding: 6px 12px; font-size: 16px; font-weight: 800; }
/* the desktop help paragraph is input-gated: coarse pointers
   never see it, whatever the width (the game gates it too) */
@media (pointer: coarse) {
  #eyeDesktopHelp { display: none !important; }
}
@media (max-width: 900px) {
  #eyeDesktopHelp { display: none !important; }
  .eyePhoneOff { display: none !important; }
  body.eye-drive-on #eyeToast { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 64px);
    left: 50%; transform: translateX(-50%); z-index: 63; margin: 0; white-space: nowrap; max-width: 92vw; }
  /* the v1.45 burnout button compacts into the same bottom zone,
     bottom-centre, bottom-aligned with the wheel + pedals */
  #eyeBurnoutRow { position: absolute; left: 50%; transform: translateX(-50%);
    bottom: calc(max(env(safe-area-inset-bottom, 0px), 10px) + 4px); margin: 0; }
  #eyeBurnout { min-width: 0; min-height: 44px; height: 44px; font-size: 15px; padding: 6px 10px; }
}

/* ---------- v1.47: BURNOUT CLEAR OF GAS (portrait) + BRANFORD
   FULL SCREEN ----------
   Portrait phones are narrow: at bottom-centre the compacted
   burnout pill still reached into the GAS pedal's column (Gary's
   screenshots: the pill overlapping GAS, label half-hidden). In
   portrait it now rides one pedal-height ABOVE the pedal row,
   still bottom-centre, still inside the bottom zone (floor 14 +
   lift 92 + pill 44 = 150px <= 18% of an 844px screen). Landscape
   keeps the v1.46 bottom-centre seat — the width is honest
   there and nothing overlaps. */
@media (max-width: 900px) and (orientation: portrait) {
  #eyeBurnoutRow { bottom: calc(max(env(safe-area-inset-bottom, 0px), 10px) + 4px + 92px); }
}
/* the skeleton, full screen: the wrap's card + canvas stretch
   edge to edge (frameTick re-sizes from client size each frame,
   so the render follows on its own). */
#branfordWrap:fullscreen { padding: 0; }
#branfordWrap:fullscreen .city3dCard { width: 100%; height: 100%; max-height: none;
  border: none; border-radius: 0; display: flex; flex-direction: column; }
#branfordWrap:fullscreen #glBranford { flex: 1 1 auto; height: auto; min-height: 0; }
#branfordWrap:-webkit-full-screen { padding: 0; }
#branfordWrap:-webkit-full-screen .city3dCard { width: 100%; height: 100%; max-height: none;
  border: none; border-radius: 0; display: flex; flex-direction: column; }
#branfordWrap:-webkit-full-screen #glBranford { flex: 1 1 auto; height: auto; min-height: 0; }

/* v1.62 STREET EYE VIEW — the touch pad under the Branford
   canvas: big hold-to-walk buttons (Gary's large-text,
   thumb-first rule: nothing under 52px tall). */
#branfordStreetPad { margin-top: 8px; text-align: center; }
#branfordStreetPad .streetHint { margin: 4px 0 8px; }
#branfordStreetPad .streetPadBtns { display: flex; gap: 10px; justify-content: center; }
#branfordStreetPad .streetPadBtns button { min-width: 64px; min-height: 52px; font-size: 22px; border-radius: 12px; touch-action: none; }

/* ================= v1.80: THE FRONT DOOR =================
   The wall's CSS backstop: in the player face (body.playerFace,
   set by game.js applyDevWall) dev surfaces and office-relocated
   support buttons do not exist visually — the !important beats
   every surface's own display rule, including surfaces created
   after boot (the peek cards' Eye View buttons). With the dev
   flag on, none of these rules apply and the game is exactly
   the game Gary has been testing. */
body.playerFace .devOut,
body.playerFace .movedSupport { display: none !important; }

/* v1.83 (Gary's ruling, 2026-10-31): POP THE GAME IN STATS —
   the title drops the portrait backdrop altogether (at the
   shipped crop Gary read it as his back, and stretched) and
   wears the STATS BOARD'S background instead: the GT
   Customz collage under the board's own deep-violet veils
   over #0a0714 — the stats page's body recipe, stops
   sampled from stats/index.html (its vertical veil's
   bottom runs .88 here for the title's control stack).
   Cover only, focal center top: the art is cropped, never
   stretched. Gary's portrait stays on the stats board,
   where it belongs; no people art stands on the door, so
   no likeness can drift here again. */
#titleCastBg { position: absolute; inset: 0; pointer-events: none; background-color: #0a0714;
  background: linear-gradient(0deg, rgba(10,7,20,.88), rgba(10,7,20,0) 45%, rgba(10,7,20,.36)),
    linear-gradient(90deg, rgba(10,7,20,.73), rgba(10,7,20,.48) 50%, rgba(10,7,20,.73)),
    url('assets/gtcustomz-collage-background.jpg?v=1.83') center top / cover no-repeat; }
#titleScreen > *:not(#titleCastBg) { position: relative; z-index: 1; }

/* The hero: one loud answer to "what do I do now?" */
#startBtn { font-size: 24px; padding: 18px 42px; min-height: 64px; }
.menuGrid .doorBtn { font-weight: 800; }

/* The Boss's Office + the World poster: same shell family as
   the Version Notes panel (fixed, centered, dimmed ground). */
#officePanel, #worldPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 45;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
#officePanel .acctBlock { margin: 10px 0; }
#officeStatsSlot .garageRow { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
#officeStatsSlot .wideBtn { margin-top: 8px; }


/* v1.81: THE COMIC VIEWER — same shell family as the Boss's
   Office and the World poster (fixed, centered, dimmed
   ground); Gary's page rides large, its caption under it. */
#comicPanel { position: fixed; inset: 0; background: rgba(8,9,12,0.88); z-index: 45;
  display: flex; align-items: center; justify-content: center; padding: 18px; }
.comicPageImg { display: block; max-width: 100%; max-height: 44vh; margin: 10px auto; border-radius: 10px; }
.comicPageCap { text-align: center; font-weight: 700; margin: 6px 0 10px; }

/* ================================================================
   v1.84: THE ROOM IS RETIRED — Gary's ruling (2026-10-31):
   "lets keep stats seperate" / "go back to simple." The v1.83
   room section stood here (the board-format header line, the
   board nest at the right, the desktop collage ground). All of
   it is gone: the game screen is the game again, and the board
   is its own page behind its 📊 buttons. The title backdrop's
   stats-purple (its own v1.83 ruling, a different surface)
   stays exactly as it was. ================================================================ */

/* ================================================================
   v1.83: SHOW DAY BREATHES (phones) — Gary's screenshot (Oct 31,
   01:36): "Playing area small — cell phone only." The 3D view's
   height was the 2D canvas's aspect box (~250px at phone width),
   so Show Day played in the bottom ~40% under the HUD and Rev's
   stack. On phone widths, with the 3D view on, the lot's stage
   is 68dvh tall — two-thirds of the screen is the game — and
   the stack above trims: Rev's history caps at two lines (it
   still scrolls inside; the fold/expand tap works as ever) and
   his current line clamps to three. Nothing moves, nothing
   hides: the 2D / Reset view buttons ride the lot's corner as
   always, the transport (pause / play / fast) stays in the HUD.
   Desktop composition untouched. ================================================================ */
@media (max-width: 900px) {
  #lotWrap:has(> #gl3d:not(.hidden)) { min-height: 68dvh; }
  #lotWrap:has(> #gl3d:not(.hidden)) #lot { height: 100%; }
  #hud .hudstat { padding: 4px 8px; }
  #speedBtns button { min-height: 44px; padding: 6px 12px; }
  #revHistory { max-height: 40px; overflow-y: auto; }
  #revPanel:not(.collapsed):not(.menuStrip) #revBubble { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
}

/* v1.84: the title and city picker are full-viewport again —
   the v1.83 stage box they borrowed for the room is retired
   with it. */

/* v1.85: THE TOP BAR — Gary's two calls in one bar (Oct 31).
   THE MOVE: the four destination doors (Friend Shows, Stats
   board, The Comic Book, Boss's Office) ride in the HUD in
   #destBar — one nowrap row that never splits across the
   HUD's wrap; the board door's anchor is a flex child like
   its sibling buttons. THE PIN: #verPill can never be flexed
   or shrunk — the build number reads whole or not at all.
   On phone widths the doors' words fold away and the icons
   carry them (names stay in the buttons' titles; the phone
   pass already guarantees .hudbtn a 48px tap), so bar +
   pin hold one row at large text without pushing anything
   off the screen. Nothing else about the HUD changes.
   v1.92: THE PIN THIS PARAGRAPH PROTECTS HAS RETIRED — Gary
   moved the version under the lettering ("same way show n
   shine is"), so the #verPill flex rule that stood here is
   gone with the pill. See UNDER THE LETTERING at the foot
   of this file. */
#destBar { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
#destBar a { display: flex; text-decoration: none; }
.destBtn { white-space: nowrap; }
@media (max-width: 900px) {
  .destBtn .destLbl { display: none; }
  .destBtn { padding: 6px 8px; }
}

/* v1.87: BREATHING ROOM — Gary's phone catch (Oct 31, from his
   own screenshot of the v1.86 top bar: "tops cluttered"). On the
   phone the v1.85 bar stacked FOUR rows of chrome over the game
   — the save row, the doors row, the phase strip, the transport.
   The doors keep their top-bar home (his v1.85 call stands), but
   at phone widths they fold into ONE chip (#destChip, markup in
   index.html, wiring in game.js): the chip opens #destBar as a
   drop-down sheet under the bar, the doors listed with their
   FULL names on full-size rows; picking a door — or tapping
   anywhere outside — tucks it away. One whole row goes back to
   the game. Past 900px nothing changes: the chip never renders
   and the bar stays the row v1.85 shipped. The phase strip
   (#phaseLabel) keeps its own phone row ON PURPOSE — it is the
   game's phase readout (TITLE / BUILD — venue / SHOW DAY /
   AWARDS / RECEIPTS), real state, not chrome. #hud gains
   position:relative purely so the sheet can anchor under the
   bar; it moves nothing else (no HUD child is anchored to it). */
#hud { position: relative; }
#destChip { display: none; }
@media (max-width: 900px) {
  #destChip { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
  #destBar { display: none; }
  #destBar.open { display: flex; flex-direction: column; align-items: stretch; gap: 6px;
    position: absolute; top: calc(100% + 6px); left: 8px; width: 300px; max-width: calc(100% - 16px);
    background: #14161c; border: 2px solid #FF6A00; border-radius: 12px; padding: 10px;
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55); z-index: 65; }
  /* The HUD wears a decorative clip-path (the slanted bottom edge) —
     and a clip-path clips EVERYTHING inside the bar, so a sheet
     hanging below the bar would be clipped out of existence: no
     paint, no taps (found the hard way in QA: perfect rects, zero
     pixels). While the sheet is open the slant rests; the sheet
     covers that corner anyway. Closed, the bar is byte-identical. */
  #hud:has(#destBar.open) { clip-path: none; }
  #destBar.open a { display: flex; width: 100%; }
  #destBar.open a .destBtn { flex: 1 1 auto; }
  #destBar.open .destBtn { width: 100%; justify-content: flex-start; text-align: left;
    padding: 10px 12px; font-size: 15px; }
  #destBar.open .destBtn .destLbl { display: inline; }
}
/* v1.87 rider (Gary's desktop dedup): Version Notes had TWO homes
   at desktop widths — the 📓 chip in the top bar (#notesBtnHud)
   and a full button in the city sidebar (#notesBtnCity). The
   sidebar copy retires at desktop widths; the chip is its one
   home. The button, its id, and its openNotes wiring are NOT
   deleted — and at phone widths the sidebar keeps it, unchanged.
   Post my stats is a different job (posting your numbers, not
   reading the board) and stays, as do Backup / Report a bug. */
@media (min-width: 901px) {
  #notesBtnCity { display: none; }
}

/* v1.88: MORE ROOM — Gary's second pass at the phone top (Oct 31,
   his screenshot of v1.87: "needs more room"). Three folds, phone
   widths only; past 900px nothing in this block exists. (1) The
   save chip's detail span folds away: the chips above the pill
   already show Week / purse / Buzz, so on the phone the pill
   just says 💾 Saved — the numbers live exactly once. (2) The
   transport (⏸ ▶ ⏩) rests while the phase readout says TITLE
   (#hud wears .onTitle, mirrored from #phaseLabel in game.js's
   HUD tick): nothing is playing yet; the moment a show is on,
   the readout changes and the transport stands again. (3) The
   Version Notes button in the top bar shrinks to a chip beside
   the 🧭 Doors chip: its "Version " folds (the .notesLbl span,
   the destLbl pattern), leaving 📓 Notes — same button, same
   openNotes wiring, still a ≥48px tap at phone widths. The
   v1.87 doors fold and the desktop rider stand untouched. */
@media (max-width: 900px) {
  #saveChip .saveDetail { display: none; }
  #hud.onTitle #speedBtns { display: none; }
  #notesBtnHud { white-space: nowrap; }
  #notesBtnHud .notesLbl { display: none; }
}

/* ================================================================
   v1.89: ONE SCROLL — Gary's catch (Oct 31, 23:38, his phone):
   "why is there 2 scroll areas." He was right, and the bisect
   (staging-scrollfix, SHIP189.md) names the anatomy: on a phone
   the DOCUMENT scrolled (header and all) while #cityPanel /
   #palette ALSO scrolled inside their 74dvh cap (the v0.3.1
   fold-audit box, overscroll-behavior: contain) — two scrollers
   on one screen, and a drag's owner depended on where your
   thumb landed. The v1.85 top-bar move fed the fight: it moved
   the doors into the HUD (the header grew a row; measured HUD
   height on the picker 265px -> 329px), pushing the page
   further past the viewport so the outer scroller became a
   constant presence on the picker instead of an occasional
   one. (The v1.83 ROOM is exonerated: every room rule was
   min-width:901px-gated, phones never rendered it, and v1.84
   removed it whole.)
   THE FIX (phone widths only; desktop untouched): the page
   stops scrolling. #fitWrap/#fitScale become a full-viewport
   column — HUD, Rev's strip, the step marker park at the top
   (flex 0 0 auto) — and #stage is the ONE scroller under them.
   The side panels lose their cap and their inner scroll: their
   content flows at natural height inside the stage's scroll,
   so the panel and the town map below it ride the same single
   scrollbar, and every venue card is reachable with one drag
   that always behaves the same. Body's old safe-area/dock
   padding moves into the scroller (body itself no longer
   carries it — an unscrollable body with padding would clip
   the column's foot). Modal overlays (notes, receipts, the
   city picker) are position:fixed with their own scroll, as
   before — each is the only scroller while it stands.
   ================================================================ */
@media (max-width: 900px) {
  html, body { height: 100%; overflow: hidden; }
  body { padding-bottom: 0; }
  #fitWrap { height: 100vh; height: 100dvh; }
  #fitScale { height: 100%; display: flex; flex-direction: column; }
  #hud, #guideCard, #revPanel, #revTab, #crumbBar { flex: 0 0 auto; }
  #stage { flex: 1 1 auto; min-height: 0; overflow-y: auto;
    overscroll-behavior: contain; }
  #palette, #cityPanel { max-height: none; overflow-y: visible; }
  body.dockOn { padding-bottom: 0; }
  body.dockOn #stage { padding-bottom: calc(112px + env(safe-area-inset-bottom, 0px)); }
}

/* ================================================================
   v1.90: NOTES LEAVES THE TOP BAR (phone) — Gary's call (Nov 1,
   from his phone, right after the one-scroll pass): "NOTES IN
   TOP BAR CAN GO — we have it at bottom." He is right: on the
   phone the notes already keep a bottom door — the full
   📓 Version Notes button near the foot of the town panel
   (#notesBtnCity, order 14 down there), plus the title screen's
   own #notesBtnTitle — so the top-bar chip is a third copy the
   phone doesn't need. At phone widths #notesBtnHud retires:
   the button, its id, its .notesLbl fold and its openNotes
   wiring are NOT deleted (the desktop needs all of it) — it is
   simply not rendered on the phone, and the button row up top
   (My Show, the 🧭 Doors chip) reflows into the space.
   Desktop does NOT move: past 900px the chip is the notes' ONE
   home (v1.87 retired the panel copy at desktop widths), so
   this block lives at max-width:900px only — the mirror image
   of that rider. The v1.88 fold inside this width stands
   untouched above; it simply has nothing left to fold. */
@media (max-width: 900px) {
  #notesBtnHud { display: none; }
}

/* ================================================================
   v1.92: UNDER THE LETTERING — Gary's call (Nov 1, from the
   desktop and the phone alike): "under lotboss lettering can
   we do version there and remove pill — same way show n shine
   is." So the yellow pill is retired WHOLE: the three elements
   (#verPill in the HUD, #verPillTitle and #verPillPicker in
   the overlay corners), the two .verpill style rules and the
   #verPill flex rule, and the 'LOT BOSS ' prefix in the boot
   stamp — everything that existed only to serve the badge.
   In its seat, the version rides as one small quiet line
   directly under the wordmark, the Show & Shine .brand-stack
   treatment: in the HUD the brand becomes a stack (graffiti
   wordmark over version), and the title and city-picker
   screens carry the same small line under their lettering.
   Nothing about the v0.3.1 promise changes — the build number
   stands on every screen in both faces, still stamped at boot
   from the one LB.VERSION (game.js), so a screenshot still
   tells both sides exactly what's being played. It just
   stopped wearing a badge. The stack is sized to the title
   row the pill used to share (37px): the wordmark's line box
   tightens to its glyphs (line-height: 1 — "LOT BOSS" is all
   caps, no descenders to clip) and the line rides 2px under
   it, so the stack stands exactly as tall as the seat it took
   and no surface grows a row for this move. The pill's whole
   width goes back to the row instead. */
#hud .brandStack { display: flex; flex-direction: column; align-items: flex-start; }
#hud .brandStack .brand { line-height: 1; }
.verline { font-size: 11px; font-weight: 700; letter-spacing: 0.8px;
  line-height: 1; white-space: nowrap; color: #b9b3e0; opacity: 0.78; }
#hud .verline { margin-top: 2px; }
.verline.screen { font-size: 12px; text-align: center; margin-top: 8px; }
#cityPicker .verline { margin-top: 2px; }

/* ================================================================
   v1.94: ONE ROW — Gary's header campaign, piece 2: his sketch
   (settled Nov 1) and his order from the phone after v1.92
   landed ("shrink the doors my show and speaker into new
   icons and look").
   The two wrappers (#statsBar around the ten chips, #topBtns
   around the buttons) are display:contents on the DESKTOP:
   the desktop header is the v1.92 header, byte-for-byte in
   flow — the new Stats button never renders past 900px.
   At phone widths the wrappers become the two pieces of the
   one top row: #topBtns is the segmented family bar (Stats,
   My Show, Doors, the speaker — fresh buttons, one height,
   icons carrying them, labels folded like the doors' fold
   before them), and #statsBar is the slim dropdown band
   under it, open while a show is on, closed otherwise. The
   clock tenant is the time itself — its emoji folds at
   phone widths (the fit probe measured the row ~24px over
   with it once the bounce segment joins; the desktop chip
   keeps its 🕖).
   ================================================================ */
#statsBtn { display: none; }
#statsBar, #topBtns { display: contents; }
@media (max-width: 900px) {
  #hud { gap: 6px; }
  /* the row's tenants, in sketch order (flex order only; the
     DOM order is unchanged, so the desktop flow never moves) */
  #hud .brandStack { order: 0; }
  #topBtns { order: 1; display: flex; align-items: stretch;
    background: rgba(10, 10, 18, 0.55); border: 2px solid #0b0b0e;
    border-radius: 12px 4px; box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
    overflow: hidden; }
  #hud .clockStat { order: 2; background: transparent; box-shadow: none;
    padding: 2px 1px; font-weight: 700; }
  /* the clock's emoji folds at phone widths — the TIME is the
     tenant of Gary's row; the desktop chip keeps its 🕖 */
  #hud .clockStat .clockIco { display: none; }
  #statsBar { order: 3; }
  #destBar { order: 4; }
  #hud .phase { order: 5; }
  #speedBtns { order: 6; }
  /* the family — fresh buttons, one height, joined segments */
  #topBtns .segBtn { min-width: 0; min-height: 40px; height: 40px;
    display: inline-flex; align-items: center; justify-content: center;
    gap: 5px; background: transparent; border: 0; border-radius: 0;
    box-shadow: none; padding: 0 7px; font-size: 14px; line-height: 1;
    white-space: nowrap; border-left: 1px solid rgba(216, 212, 204, 0.16); }
  #statsBtn { display: inline-flex; order: 0; border-left: 0; font-weight: 700; }
  #showBtn, #cityBtn { order: 1; }
  #destChip { order: 2; }
  #musicBtn { order: 3; }
  #notesBtnHud { order: 4; }
  #topBtns .segBtn .btnLbl { display: none; }
  #statsBtn .btnChev, #destChip .btnChev { font-size: 10px; }
  #statsBtn .btnChev { transition: transform 0.15s ease; }
  #statsBtn[aria-expanded="true"] .btnChev { transform: rotate(180deg); }
  #topBtns .segBtn:active { background: rgba(255, 106, 0, 0.25); }
  /* the results state keeps its gold inside the bar (the
     family strip would otherwise flatten .hudbtn.pulse) */
  #topBtns .segBtn.pulse { background: #f2b21c; color: #14161c; }
  /* the dropdown: a slim in-flow band under the row, never a
     popover over the lot */
  #statsBar { display: none; flex: 1 1 100%; }
  #statsBar.open { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    padding: 7px 6px 3px; background: rgba(10, 8, 20, 0.45);
    border-top: 1px solid rgba(255, 106, 0, 0.35); border-radius: 0 0 10px 4px; }
  #statsBar .hudstat { font-size: 14px; }
}

/* ---------- v1.111: THE VIEW ROW + VIEW CHIP MENU ----------
   Launch: one compact row on the title screen — the headline
   door (3D FULLSCREEN) wears the START orange; the two
   alternatives wear the house chip face (dark + gold edge).
   In-session: the view menu drops from the existing 3D bar —
   same cluster, no new rows, the phone top untouched. */
#viewRow { display: flex; flex-wrap: nowrap; gap: 8px; justify-content: center;
  width: min(680px, 100%); margin: 5px auto 0; }
.viewDoor { flex: 1 1 0; min-width: 0; min-height: 40px; padding: 5px 5px; border-radius: 12px;
  background: rgba(20,22,28,0.92); color: #f4f2ee; border: 2px solid #f2b21c;
  font-weight: 800; font-size: 13px; line-height: 1.15; cursor: pointer; }
.viewDoor small { display: block; font-weight: 600; font-size: 10.5px; opacity: 0.85; margin-top: 0; }
.viewDoor:hover { background: rgba(38,42,52,0.95); }
.viewDoorMain { background: #FF6A00; color: #14161c; border-color: #FF6A00; font-size: 15px; }
.viewDoorMain:hover { background: #ff7d22; }
#viewNote { color: #ffd98a; text-align: center; margin: 6px auto 0; width: min(680px, 100%); }
#viewMenu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 9;
  display: flex; flex-direction: column; gap: 6px; min-width: 210px; }
#viewMenu.hidden { display: none; }
#viewMenu button { text-align: left; white-space: nowrap; }
