/* The Lobby (Bii Plaza, from WiiYapp) + the Bii editor, in 🅱️chat's red and white: one white look (no theme picker), red
   for "you" and selection, M PLUS Rounded type. See DESIGN.md. */
@font-face { font-family: "M PLUS Rounded 1c"; font-weight: 500; font-style: normal; font-display: swap; src: url(/fonts/MPLUSRounded1c-500.woff2) format("woff2"); }
@font-face { font-family: "M PLUS Rounded 1c"; font-weight: 800; font-style: normal; font-display: swap; src: url(/fonts/MPLUSRounded1c-800.woff2) format("woff2"); }

/* .pz-vars carries the plaza tokens outside the plaza too (the game screens in games.css). */
.plaza, .pz-vars {
  --pz-world: var(--wall);  /* the void past the floor's edge */
  --pz-sky: var(--wall);
  --pz-floor: var(--wall-2);
  --pz-chrome: var(--paper);
  --pz-ink: var(--ink);
  --pz-ink-2: var(--ink-2);
  --pz-line: var(--rule);
  --pz-blue: var(--red);    /* your marker, selection rings (red, despite the name) */
  --pz-bar: #c3121b;        /* pressed buttons, the main button, open dock cells (white text reads on it) */
  --pz-icon: var(--red);    /* the dock's pixel icons */
  --pz-rounded: "M PLUS Rounded 1c", var(--font); /* the Wii's voice: rounded type in the Lobby, editor and challenges */
}
.plaza {
  position: fixed; left: 0; right: 0; top: var(--app-top, 0px); height: var(--app-h); z-index: 25;
  display: flex; flex-direction: column; max-width: 1100px; margin: 0 auto;
  background: var(--pz-floor); color: var(--pz-ink); font-family: var(--pz-rounded); font-weight: 500;
  opacity: 0; transform: scale(.985); transition: opacity .2s, transform .2s;
}
.plaza.in { opacity: 1; transform: none; }
body.in-plaza { background: var(--paper); }
@media (min-width: 1101px) { .plaza { box-shadow: 0 0 0 1px var(--rule); } }

/* top bar */
.pz-top { flex: none; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 10px;
  padding: calc(10px + env(safe-area-inset-top)) 12px 10px; background: var(--pz-bar); color: #fff; }
.pz-top > :first-child { justify-self: start; }
.pz-top > :last-child { justify-self: end; }
.pz-title { margin: 0; font: 800 21px/1.1 var(--pz-rounded); letter-spacing: .01em; white-space: nowrap; }
.pz-spacer { width: 1px; }

.pz-btn { min-height: 44px; padding: 9px 17px; border-radius: 99px; border: 2px solid var(--pz-line); background: var(--pz-chrome); color: var(--pz-ink);
  font: 800 15px/1 var(--pz-rounded); box-shadow: inset 0 -3px 0 #0000000f; white-space: nowrap; }
.pz-btn:active { transform: translateY(1px); box-shadow: inset 0 -1px 0 #0000000f; }
.pz-btn:disabled { opacity: .55; }
.pz-top .pz-btn { border-color: #ffffff; }
.pz-btn.blue { background: var(--pz-bar); border-color: var(--pz-bar); color: #fff; }
.pz-top .pz-btn.blue { background: #fff; color: var(--pz-bar); }
.pz-btn.small { min-height: 40px; padding: 7px 14px; font-size: 14.5px; }
.pz-link { background: none; border: 0; padding: 8px 4px; min-height: 40px; color: var(--pz-blue); font: 800 14px/1.2 var(--pz-rounded); text-decoration: underline; text-underline-offset: 3px; }
.pz-link.danger { color: var(--danger); }
.plaza :focus-visible { outline: 3px solid var(--pz-blue); outline-offset: 2px; }

/* the floor */
.pz-floor { position: relative; flex: 1; overflow: hidden; touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none;
  background: var(--pz-world);
}
/* bug fix (Ethan): the floor is its own layer, so nothing drawn on it (bubbles, placards, markers) climbs over the text bar */
.pz-floor { isolation: isolate; }
/* The dock (from 🅱️chat): a row of cells right under the section bar, white with the line colour showing through 2px
   gaps as the dividers, one-bit pixel icons (plaza.js PIX, 12 x 12 at 2px a pixel). #pzCam holds My Bii, the arcade
   (a group: Arcade, High scores, Racetrack), Paint and Blocks (plaza.js PLACES); trays drop down from it over the
   floor. Cells share the width on a phone and stop growing at 62px on a wide screen. Open or pressed = header red. */
.pz-dock { flex: none; position: relative; z-index: 3500; background: var(--pz-chrome); border-bottom: 2px solid var(--pz-line); cursor: default; }
.pz-cam { position: relative; display: flex; gap: 2px; max-width: calc(11 * 62px); margin: 0 auto; background: var(--pz-line); }
.pz-cam-b { position: relative; flex: 1 1 0; min-width: 0; height: 48px; padding: 0; margin: 0; display: grid; place-items: center;
  background: var(--pz-chrome); color: var(--pz-icon); border: 0; border-radius: 0; -webkit-tap-highlight-color: transparent; cursor: pointer; }
.pz-cam-b svg { width: 22px; height: 22px; fill: currentColor; }
.pz-cam-b svg.px { width: 24px; height: 24px; shape-rendering: crispEdges; }
.pz-cam-b:active { transform: translateY(1px); }
.pz-cam .pz-cam-b:is([aria-pressed="true"]) { background: var(--pz-bar); color: #fff; }

/* The arcade's sheet (plaza.js openGroup): one big row per page, its pixel icon in red. */
.pz-rows { display: grid; gap: 8px; margin-top: 16px; --c: var(--red); }
.pz-row { display: flex; align-items: center; gap: 14px; width: 100%; min-height: 58px; margin: 0; padding: 0 16px; border: 0; border-radius: 0;
  background: var(--paper); color: var(--ink); font: 700 18px/1.2 var(--font); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  box-shadow: inset 0 0 0 1.5px var(--rule); }
.pz-row .pz-ico { width: 24px; height: 24px; color: var(--c); fill: currentColor; shape-rendering: crispEdges; }
.pz-row:active { background: color-mix(in srgb, var(--c) 12%, var(--paper)); }
.pz-row:focus-visible { outline: 3px solid var(--c); outline-offset: 2px; }
.pz-ripple { position: absolute; width: 34px; height: 14px; margin: -7px 0 0 -17px; border-radius: 50%; border: 2.5px solid var(--pz-blue); pointer-events: none; animation: pz-ripple .55s ease-out forwards; z-index: 1; }
@keyframes pz-ripple { from { transform: scale(.3); opacity: 1; } to { transform: scale(1.5); opacity: 0; } }

/* the 3D floor (mii3d.js draws it) and the overlays that ride on each Mii: the
   "you" marker, "!" and speech bubble above the head. --hh is the head height in px. */
.pz-canvas { position: absolute; inset: 0; display: block; }
.pm { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; will-change: transform; --hh: 120px; }
.pm-me { position: absolute; left: -8px; bottom: calc(var(--hh) + 6px); width: 0; height: 0; pointer-events: none;
  border: 8px solid transparent; border-top: 11px solid var(--pz-blue); border-bottom: 0; animation: pz-marker 1.2s ease-in-out infinite alternate; }
@keyframes pz-marker { to { transform: translateY(-5px); } }
.pm.talking { z-index: 4000 !important; }
.pm.offering { z-index: 4500 !important; }
.pm.offering .pm-bubble { display: none; }
/* Tap a Bii: its card pops up over its head dressed like the Biis' speech bubbles (member request, Ethan): paper chrome,
   a 2px line border, 14px corners and the same bordered tail, Atkinson in ink, sentence case. The name leads (bold, with
   the here/away dot), a status line under it, then the buttons as one row of cells split by the bubble's line colour. */
.pm-challenge { position: absolute; left: 0; bottom: calc(var(--hh) + 12px); transform: translateX(-50%); pointer-events: auto;
  display: grid; grid-template-columns: repeat(var(--n, 1), minmax(max-content, 1fr)); width: max-content; max-width: calc(100vw - 24px); margin-left: var(--dx, 0px);
  border-radius: 14px; background: var(--pz-chrome); color: var(--pz-ink); border: 2px solid var(--pz-line); white-space: nowrap;
  font: 500 14px/1.3 var(--pz-rounded); animation: pz-pop .22s cubic-bezier(.3, 1.6, .5, 1); }
.pm-challenge::after { content: ""; position: absolute; left: clamp(18px, calc(50% - var(--dx, 0px)), calc(100% - 18px)); bottom: -8px; width: 12px; height: 12px;
  margin-left: -6px; background: inherit; border: solid var(--pz-line); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.pm-challenge.below { bottom: auto; top: 12px; }
.pm-challenge.below::after { bottom: auto; top: -8px; border-width: 2px 0 0 2px; }
.pm-challenge > :not(button) { grid-column: 1 / -1; min-width: 0; }
.pm-challenge button { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; margin: 0; padding: 0 16px; border: 0; border-top: 2px solid var(--pz-line); background: none; color: var(--pz-blue); cursor: pointer;
  -webkit-tap-highlight-color: transparent; font: 700 15px/1 var(--pz-rounded); }
.pm-challenge button + button { border-left: 2px solid var(--pz-line); }
.pm-challenge button:first-of-type { border-bottom-left-radius: 12px; }
.pm-challenge button:last-of-type { border-bottom-right-radius: 12px; }
.pm-challenge button:active { background: var(--pz-blue); color: #fff; }
.pm-challenge button:focus-visible { outline: 3px solid var(--pz-blue); outline-offset: -5px; }
/* (steaks) "Feed steaks": seared brown, with a little steak */
.pm-challenge .pm-ch-steak { color: #a8401c; }
.pm-challenge .pm-ch-steak svg { width: 20px; height: 20px; fill: #c65a32; stroke: #5a200c; stroke-width: 1.6; }
.pm-challenge .pm-ch-steak svg circle { fill: #f3e6cc; stroke-width: 1.2; }
.pm-challenge .pm-ch-steak:active { background: #a8401c; color: #fff; }
/* (burritos) "Feed Mona Ayala House Burritos": its own row along the bottom, salsa red, a half-foiled burrito */
.pm-challenge .pm-ch-steak.burrito { grid-column: 1 / -1; border-left: 0; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; white-space: normal; line-height: 1.15; text-align: center; color: #b3321c; }
.pm-challenge .pm-ch-steak.burrito svg { flex: none; width: 22px; height: 22px; stroke: #5a3414; stroke-width: 1.3; stroke-linejoin: round; }
.pm-challenge .pm-ch-steak.burrito .bt { fill: #f0d29a; }
.pm-challenge .pm-ch-steak.burrito .bf { fill: #c9ced5; stroke: #6f7680; }
.pm-challenge .pm-ch-steak.burrito .bc { stroke: #f4f6f8; }
.pm-challenge .pm-ch-steak.burrito circle { fill: #c8321f; stroke: none; }
.pm-challenge .pm-ch-steak.burrito:active { background: #b3321c; color: #fff; }
.pm-challenge:has(.burrito) button:not(.burrito) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* the card's top: name and status */
.pm-who { display: grid; gap: 3px; padding: 9px 14px 10px; text-align: left; }
.pm-who-n { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; font: 700 16px/1.2 var(--pz-rounded); color: var(--pz-ink); }
/* the dot by the name: green when they're here, red when they're away (member request, Ethan) */
.pm-who-n::before { content: ""; display: inline-block; width: 9px; height: 9px; margin: 0 7px 0 1px; vertical-align: .08em; border-radius: 50%; background: #e5484d; }
.pm-who-n.on::before { background: #2bb65f; }
.pm-who-s { display: flex; align-items: center; font: 500 13px/1.25 var(--pz-rounded); color: var(--pz-ink-2); }
.pm.offering .pm-me { display: none; }
.pm.talking .pm-me { display: none; }
.pm-bubble { position: absolute; left: 0; bottom: calc(var(--hh) + 10px); transform: translateX(-50%); width: max-content; max-width: 168px; pointer-events: none;
  padding: 7px 11px 8px; border-radius: 14px; background: var(--pz-chrome); color: var(--pz-ink); border: 2px solid var(--pz-line);
  font: 500 14px/1.3 var(--pz-rounded); overflow-wrap: anywhere; animation: pz-pop .22s cubic-bezier(.3, 1.6, .5, 1); }
.pm-bubble::after { content: ""; position: absolute; left: 50%; bottom: -8px; width: 12px; height: 12px; margin-left: -6px; background: inherit;
  border: solid var(--pz-line); border-width: 0 2px 2px 0; transform: rotate(45deg); }
@keyframes pz-pop { from { transform: translateX(-50%) scale(.6); opacity: 0; } }
.pm-bang { position: absolute; left: 14px; bottom: calc(var(--hh) - 4px); font: 800 28px/1 var(--pz-rounded); color: #f0532d; opacity: 0; pointer-events: none; }
.pm.emo-poked .pm-bang { animation: pz-bang 1.1s ease-out; }
@keyframes pz-bang { 0% { opacity: 0; transform: translateY(6px) scale(.5); } 15% { opacity: 1; transform: none; } 75% { opacity: 1; } 100% { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) {
  .pm-me { animation: none; }
}


/* bottom bar (Fire): the Lobby's foot now the dock is up top, so it holds the bottom safe area */
.pz-bottom { flex: none; grid-template-columns: minmax(0, 1fr); background: var(--pz-chrome); border-top: 2px solid var(--pz-line); padding: 8px 12px calc(10px + var(--sab)); display: grid; gap: 8px; }
.pz-emotes { display: flex; gap: 8px; }
/* with nothing to show (no Fire), the bar goes and the floor runs down to the screen's bottom edge */
.plaza > .pz-bottom { padding-bottom: calc(8px + var(--here-h) + var(--sab)); } /* its buttons stay above the glass bar laid over it */
.kb-open .pz-bottom { padding-bottom: 10px; }
.plaza:not(:has(> .pz-bottom > :not(.pz-emotes):not([hidden]), > .pz-bottom > .pz-emotes > :not([hidden]))) > .pz-bottom { display: none; }
/* who's here (member requests, Ethan: "add the active bii bar back", then "Liquid Glass", then "the bottom of the screen"):
   the row of flat 2D Bii heads (style.css .here-*) along the very bottom of the chat (app.js #here, given .pz-vars, under
   the composer) and of the Lobby (#pzHere, last in .plaza). It's a strip of iOS-style Liquid Glass running edge to edge
   (no side gap, member request) and holding the bottom safe area: fixed height (--here-h, plus --sab) and, in the Lobby,
   a negative top margin so the floor runs on under it to the screen's edge, blurred and brightened through the glass,
   with lit top/bottom rims (inset shadows) and a sheen fixed to the strip while the heads scroll; the side safe areas
   are its padding. Names keep the member's colour. Gone while the keyboard is up, so the messages keep the room. */
.pz-here { position: relative; z-index: 5; flex: none; display: flex; gap: 4px; box-sizing: border-box;
  height: calc(var(--here-h) + var(--sab)); margin: calc(-1 * var(--here-h) - var(--sab)) 0 0;
  padding: 6px max(12px, env(safe-area-inset-right)) calc(6px + var(--sab)) max(12px, env(safe-area-inset-left)); border-radius: 0;
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  background: linear-gradient(135deg, rgba(255,255,255,.5), rgba(255,255,255,.08) 38%, rgba(255,255,255,0) 62%, rgba(255,255,255,.22)), rgba(255,255,255,.32);
  -webkit-backdrop-filter: blur(11px) saturate(1.9) brightness(1.1); backdrop-filter: blur(11px) saturate(1.9) brightness(1.1);
  box-shadow: inset 0 1px rgba(255,255,255,.95), inset 0 -1px rgba(255,255,255,.7),
    inset 0 0 16px rgba(255,255,255,.35), 0 -.5px rgba(18,28,60,.14), 0 -10px 26px -10px rgba(18,28,60,.3); }
.pz-here::-webkit-scrollbar { display: none; }
.kb-open .pz-here { display: none; }
.pz-here .here-p { color: var(--c, var(--pz-ink)); font: 800 12px/1.2 var(--pz-rounded); }
.pz-here .here-n { text-shadow: 0 0 3px #fff, 0 0 6px rgba(255,255,255,.8); } /* names stay legible over whatever is under the glass */
.pz-here .here-note { color: var(--pz-ink-2); font-family: var(--pz-rounded); }

/* Talking (member request, Ethan: no say bar; a speech bubble button, and the text box is the bubble over your Bii).
   #pzDraft is the pz-bubble you're writing: your red "you" line while the keyboard is up, dashed and faded once you tap
   away with it unsent, the plain bubble line the moment it's sent (then the real bubble takes over). The red square
   holds a one-bit up arrow, like the column. plaza.js placeDraft sets its spot and --tail. */
.pz-draft { position: absolute; left: 0; top: 0; z-index: 4800; display: flex; align-items: flex-end; gap: 6px; width: max-content;
  max-width: min(272px, calc(100% - 16px)); padding: 4px 4px 4px 12px; border-radius: 14px; background: var(--pz-chrome);
  border: 2px solid var(--pz-blue); color: var(--pz-ink); pointer-events: auto; cursor: text; touch-action: manipulation;
  animation: pz-draft .2s cubic-bezier(.3, 1.6, .5, 1); transform-origin: var(--tail, 50%) 100%; }
.pz-draft[hidden] { display: none; }
.pz-draft::after { content: ""; position: absolute; left: var(--tail, 50%); bottom: -8px; width: 12px; height: 12px; margin-left: -6px;
  background: inherit; border: inherit; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.pz-draft.untailed::after { display: none; }
@keyframes pz-draft { from { opacity: 0; scale: .7; } }
.pz-draft-in { display: grid; flex: 1; min-width: 7.5em; padding: 6px 0 5px; }
.pz-draft-in::after { content: attr(data-v) " "; visibility: hidden; white-space: pre-wrap; overflow-wrap: anywhere; }
.pz-draft-in::after, .pz-draft textarea { grid-area: 1 / 1; max-height: 6.5em; overflow: hidden; font: 500 17px/1.3 var(--pz-rounded); } /* five lines, then it scrolls */
.pz-draft textarea { width: 0; min-width: 100%; margin: 0; padding: 0; border: 0; border-radius: 0; background: none; color: inherit;
  resize: none; overflow-y: auto; outline: none; caret-color: var(--pz-blue); overflow-wrap: anywhere; -webkit-appearance: none; appearance: none; }
.pz-draft textarea:focus-visible { outline: none; } /* the bubble's red line is the focus */
.pz-draft textarea::placeholder { color: var(--pz-ink-2); opacity: 1; }
.pz-draft-go { flex: none; width: 36px; height: 36px; margin: 0; padding: 0; display: grid; place-items: center; border: 0;
  background: var(--pz-bar); color: #fff; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pz-draft-go svg { width: 22px; height: 22px; }
.pz-draft.idle { border-style: dashed; color: var(--pz-ink-2); }
.pz-draft.idle .pz-draft-go { display: none; }
.pz-draft.idle { padding-right: 12px; }
.pz-draft.sending { border-color: var(--pz-line); }
.pz-draft.sending .pz-draft-go { visibility: hidden; }
.plaza.talk .pm-me, .plaza.talk .pz-floor > .pm:has(.pm-me) .pm-bubble { display: none; }
@media (prefers-reduced-motion: reduce) { .pz-draft { animation: none; } }

/* panels (My Miis, editor) slide over the floor */
.pz-panel { position: absolute; inset: 0; z-index: 5000; display: flex; flex-direction: column; background: var(--pz-floor);
  opacity: 0; transform: translateY(14px); transition: opacity .2s, transform .22s cubic-bezier(.2, .8, .2, 1); }
.pz-panel.in { opacity: 1; transform: none; }
.pz-scroll { flex: 1; overflow-y: auto; padding: 16px 14px calc(24px + var(--sab)); overscroll-behavior: contain; }
.pz-lede { margin: 0 0 16px; color: var(--pz-ink-2); font-size: 15.5px; line-height: 1.45; max-width: 52ch; }

.mc-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px; }
.mc { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.mc-pick { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 8px 10px; border-radius: 18px;
  border: 2px solid var(--pz-line); background: var(--pz-chrome); color: var(--pz-ink); font-family: var(--pz-rounded); }
.mc-pick .mc-fig { width: 76px; height: 129px; opacity: 0; transition: opacity .15s; }
.mc-pick .mc-fig.in { opacity: 1; }
.mc-pick .mc-cutout { object-fit: contain; }
.mc.main .mc-pick { border-color: var(--pz-blue); box-shadow: inset 0 0 0 1.5px var(--pz-blue); }
.mc-name { font-weight: 800; font-size: 15px; }
.mc-flag { min-height: 40px; display: grid; place-items: center; font-weight: 800; font-size: 14px; color: var(--pz-blue); }

/* editor */
.ed-stage { position: relative; flex: none; height: clamp(190px, 34vh, 340px); padding: 0; background: var(--pz-sky); border-bottom: 2px solid var(--pz-line); display: flex; justify-content: center; overflow: hidden; }
.ed-mii { width: 100%; height: 100%; }
.ed-canvas { display: block; width: 100%; height: 100%; touch-action: none; cursor: grab; }
.ed-mii > .mii { display: block; height: 100%; width: auto; margin: 0 auto; aspect-ratio: 100 / 170; overflow: visible; }
.ed-shuffle { position: absolute; right: 12px; bottom: 12px; }
.ed-name { flex: none; display: flex; align-items: center; gap: 10px; padding: 10px 14px; background: var(--pz-chrome); border-bottom: 2px solid var(--pz-line); font-weight: 800; font-size: 15px; }
.ed-name input { flex: 1; min-width: 0; min-height: 42px; padding: 8px 14px; border-radius: 12px; border: 2px solid var(--pz-line); background: var(--pz-floor); color: var(--pz-ink); font: 800 17px/1.2 var(--pz-rounded); outline: none; }
.ed-name input:focus { border-color: var(--pz-blue); }
.ed-tabs { flex: none; display: flex; gap: 6px; overflow-x: auto; padding: 10px 12px; scrollbar-width: none; background: var(--pz-chrome); border-bottom: 2px solid var(--pz-line); }
.ed-tabs::-webkit-scrollbar { display: none; }
.ed-tabs button { flex: none; min-height: 40px; padding: 7px 14px; border-radius: 99px; border: 2px solid var(--pz-line); background: var(--pz-floor); color: var(--pz-ink-2); font: 800 14.5px/1 var(--pz-rounded); }
.ed-tabs button[aria-selected="true"] { border-color: var(--pz-blue); background: var(--pz-chrome); color: var(--pz-ink); box-shadow: inset 0 0 0 1.5px var(--pz-blue); }
.ed-pane { flex: 1; overflow-y: auto; padding: 14px 12px calc(20px + var(--sab)); overscroll-behavior: contain; }
.ed-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(74px, 1fr)); gap: 8px; }
.opt { aspect-ratio: 1; padding: 4px; border-radius: 16px; border: 2px solid var(--pz-line); background: var(--pz-chrome); display: grid; place-items: center; }
.opt .mii-face, .opt img { width: 100%; height: 100%; display: block; }
.opt img { opacity: 0; transition: opacity .15s; }
.opt img.in { opacity: 1; }
.opt.on { border-color: var(--pz-blue); box-shadow: inset 0 0 0 2px var(--pz-blue); background: var(--pz-sky); }
/* Body types (member request): taller tiles, the whole Bii over its animal's name. */
.ed-bodies { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); margin-bottom: 8px; }
.ed-bodies .opt { aspect-ratio: auto; grid-template-rows: 112px auto; gap: 2px; padding: 4px 4px 8px; color: var(--pz-ink-2); font: 700 13.5px/1.15 var(--pz-rounded); }
.ed-bodies .opt img { object-fit: contain; min-height: 0; }
.ed-bodies .opt.on { color: var(--pz-ink); }
.ed-swatches { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.sw { width: 42px; height: 42px; border-radius: 50%; background: var(--sw); border: 2px solid #00000024; }
.sw.on { box-shadow: 0 0 0 3px var(--pz-floor), 0 0 0 6px var(--pz-blue); }
.ed-sub { margin: 20px 0 0; font-weight: 800; font-size: 15px; }
.ed-slider { display: grid; grid-template-columns: 64px 1fr; align-items: center; gap: 12px; min-height: 48px; font-weight: 800; font-size: 15px; }
.ed-slider input { width: 100%; accent-color: var(--pz-bar); height: 32px; }
.ed-del { display: block; margin: 22px auto 0; }
.ed-pet-pick { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 16px; }
.ed-pet-opt { aspect-ratio: auto; min-height: 56px; color: var(--pz-ink); font: 800 16px/1.2 var(--pz-rounded); }
/* Drawn face, mix and match (member request, Ethan): each part Drawn or Ready-made. The Face tab's grid shows them all;
   a part's own tab has the two big choices (.ed-keep-pick) over its list. */
.ed-keep { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; margin: 4px 0 16px; }
.ed-keep-b { display: grid; gap: 3px; min-height: 52px; padding: 7px 10px; border-radius: 14px; border: 2px dashed color-mix(in srgb, var(--pz-ink-2) 55%, transparent); background: var(--pz-floor);
  color: var(--pz-ink); text-align: left; font: 800 15px/1.15 var(--pz-rounded); }
.ed-keep-b span { font-weight: 700; font-size: 12.5px; color: var(--pz-ink-2); }
.ed-keep-b.on { border-style: solid; border-color: var(--pz-blue); background: var(--pz-sky); box-shadow: inset 0 0 0 1.5px var(--pz-blue); }
.ed-keep-b.on span { color: var(--pz-blue); }
.ed-keep-pick { margin: 0 0 12px; }


/* The mech and henry's centipede: the owner's red "Fire"/"Bite" pill, the "!" when a laser or bite hits, and the floor shaking on impact. */
.pz-btn.fire { margin-left: auto; background: var(--pz-bar); border-color: var(--pz-bar); color: #fff; }
.pz-btn[hidden] { display: none; }
/* The dragon's "Breathe fire" (member request, Ethan): the dock's red, a flame drawn in the line icons' hand. */
.pz-btn.breath { display: inline-flex; align-items: center; gap: 6px; background: #c90000; border-color: #c90000; }
.pz-btn.breath svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
.pz-btn.breath:active { background: #9c0000; border-color: #9c0000; }
/* The Land Cruiser's "Car mode"/"Robot mode" (member request, Jack): the car's own dark green, a line-drawn car or robot head. */
.pz-btn.cruise { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; background: #1d4632; border-color: #1d4632; color: #fff; }
.pz-btn.cruise svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linejoin: round; stroke-linecap: round; }
.pz-btn.cruise:active { background: #10291d; border-color: #10291d; }
/* Passengers (member request, Gabe): riding in the Land Cruiser, the bar says how to fire, next to a paintball in your
   own colour (a glossy ball), and "Get out" sits right as a plain pill. */
.pz-pb { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; color: var(--pz-ink); font: 700 14.5px/1.1 var(--pz-rounded); }
.pz-pb[hidden] { display: none; }
.pz-pb-ball { flex: none; width: 22px; height: 22px; border-radius: 50%; background: radial-gradient(circle at 34% 30%, #fff 0 14%, transparent 16%), var(--c, #5b6079);
  box-shadow: inset -3px -4px 0 #00000033, 0 0 0 2px var(--pz-ink); }
.pz-btn.getout { margin-left: auto; }
/* Driving (member request, Jack): over the floor's foot while your Land Cruiser is a car. A steering stick on the left
   (paper base with a grey well, the car's green knob that springs back), the pedals on the right as a car has them: a
   wide Brake left of a tall Gas, ink rubber with ribs under a cap in the dock's red and green; pressed, a pedal tips away. */
.pz-drive { position: absolute; left: 0; right: 0; bottom: 0; z-index: 4700; display: flex; justify-content: space-between; align-items: flex-end;
  padding: 0 max(14px, env(safe-area-inset-right)) 14px max(14px, env(safe-area-inset-left)); pointer-events: none; }
.pz-drive[hidden], .kb-open .pz-drive { display: none; }
.pz-drive > * { pointer-events: auto; touch-action: none; -webkit-touch-callout: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.drv-stick { position: relative; flex: none; width: 124px; height: 124px; border-radius: 50%; background: var(--pz-chrome);
  border: 2px solid var(--pz-ink); box-shadow: inset 0 0 0 12px #eceef2; cursor: grab; }
.drv-ways { position: absolute; inset: 0; width: 100%; height: 100%; fill: none; stroke: var(--pz-ink); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; opacity: .5; }
.drv-knob { position: absolute; left: 50%; top: 50%; width: 58px; height: 58px; margin: -29px 0 0 -29px; border-radius: 50%;
  background: #1d4632; border: 2px solid #10291d; box-shadow: inset 0 0 0 6px #2a5c43, inset 0 0 0 8px #10291d;
  transition: transform .22s cubic-bezier(.3, 1.6, .5, 1); }
.drv-stick.on { cursor: grabbing; }
.drv-stick.on .drv-knob { transition: none; background: #10291d; }
.drv-pedals { display: flex; align-items: flex-end; gap: 12px; }
.drv-pedal { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 7px; padding: 10px 9px 9px; border: 0;
  border-top: 6px solid var(--cap); border-radius: 12px 12px 9px 9px; background: var(--pz-ink); color: #fff;
  font: 700 14px/1 var(--font); transform-origin: 50% 100%; transition: transform .08s ease-out, background .08s; cursor: pointer; }
.drv-pedal.brake { --cap: #c90000; width: 80px; height: 86px; }
.drv-pedal.gas { --cap: #00a83f; width: 58px; height: 120px; }
.drv-ribs { flex: 1; width: 100%; fill: #3b4170; }
.drv-pedal.on { transform: perspective(260px) rotateX(26deg); background: #0f1229; }
/* Race cars and jumps (member request, Gabe): Jump sits over the pedals, a round paper button with an ink rim and a
   double chevron that presses in; the stick's knob also leans forward and back (a dodge's way). The lap clock is a
   little felt letterboard under the dock (Barlow, the letterboard's rule): this lap big, your best and the record under it.
   A parked race car's card is a Bii card (.pm-challenge) pointing at the car. */
.drv-right { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.drv-jump { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; width: 74px; height: 74px; margin-right: 6px; padding: 0;
  border-radius: 50%; border: 2px solid var(--pz-ink); background: var(--pz-chrome); color: var(--pz-ink); box-shadow: inset 0 -6px 0 #dfe2e8;
  font: 700 13px/1 var(--font); cursor: pointer; transition: transform .06s ease-out, box-shadow .06s; }
.drv-jump svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.drv-jump.on { transform: translateY(3px); box-shadow: inset 0 -2px 0 #dfe2e8; background: #eceef2; }
.pz-lap { position: absolute; top: 10px; left: 50%; z-index: 4600; transform: translateX(-50%); display: grid; justify-items: center; gap: 2px;
  min-width: 168px; padding: 7px 16px 8px; border: 4px solid var(--ann-frame, #b9bec9); border-radius: 4px; pointer-events: none;
  background-color: var(--felt); background-image: repeating-linear-gradient(to bottom, transparent 0 7px, var(--felt-groove) 7px 9px);
  color: var(--letter); font-family: var(--board); font-weight: 600; text-transform: uppercase; letter-spacing: .1em; text-shadow: 0 1px 0 #000a; }
.pz-lap[hidden] { display: none; }
.lap-now { font-size: 30px; line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: .06em; }
.lap-best, .lap-rec { font-size: 14px; line-height: 1.1; opacity: .8; }
.lap-rec:empty { display: none; }
.pm-kart { z-index: 4500; }
.pm-kart .pm-who-n::before { content: none; }
@media (prefers-reduced-motion: reduce) { .drv-knob, .drv-pedal, .drv-jump { transition: none; } }
.pm.emo-zapped .pm-bang { animation: pz-bang 1.3s ease-out; }
.pz-floor.shake { animation: pz-shake .34s linear; }
@keyframes pz-shake { 0%, 100% { transform: none; } 20% { transform: translate(-5px, 2px); } 40% { transform: translate(4px, -3px); } 60% { transform: translate(-3px, 1px); } 80% { transform: translate(2px, -1px); } }
@media (prefers-reduced-motion: reduce) { .pz-floor.shake { animation: none; } }


/* Drop-down trays (.pz-tama: the Blocks and Paint trays), lined up under the dock. */
.pz-tama { position: absolute; left: 0; top: calc(100% + 10px); display: flex; flex-direction: column;
  border: 2px solid var(--pz-line); background: var(--pz-line); transform-origin: 22px 0; animation: pz-tama .16s ease-out; }
.pz-tama[hidden] { display: none; }
@keyframes pz-tama { from { opacity: 0; transform: translateY(-10px) scale(.96); } }
.pz-tama > :not(:first-child) { border-top: 2px solid var(--pz-line); }
.pz-ico { flex: none; display: block; width: 22px; height: 22px; }
@media (prefers-reduced-motion: reduce) { .pz-tama { animation: none; } }
.pz-emotes:not(:has(> :not([hidden]))) { display: none; }
@media (max-width: 380px) { .pz-emotes .pz-btn.small { padding-left: 11px; padding-right: 11px; } }


/* Blocks + Paint trays (member request, Ethan; plaza.js "blocks", "paint").
   The palette cell darkens while its tray is up; the tray hangs from the dock's bottom edge across its
   full width (edge to edge, no side frame): cells in the dock's chrome with 2px frame-colour dividers, like the moves
   menu. Each colour fills its whole cell (Blocks' Minecraft looks: their side's pixel art, crisp, tiled to the cell's height), seven to a row (fourteen on a wide screen); the picked one wears an indigo frame
   with a white line inside (::before). Tools are moves-menu rows (one-bit icon + bold
   rounded label); on = red with white, like the open cell. Paint's tools line up under the colour columns: three
   brush-size squares in the picked colour (hollow for the eraser, which rubs square), Eraser and Undo two columns
   each. The hint is the last row in ink-2. Remove fades the swatches (they don't apply). The floor takes a crosshair
   while painting. */
.pz-tama.pz-blocks { --cols: 7; --pdab: 14px; left: 0; right: 0; top: calc(100% + 2px); gap: 0; border: 0; border-bottom: 2px solid var(--pz-line);
  transform-origin: 50% 0; }
.pz-tama.pz-blocks:not(.pz-paint) { --cols: 8; } /* 16 block kinds: two rows of 8, one row of 16 when wide */
@media (min-width: 700px) { .pz-tama.pz-blocks { --cols: 14; } .pz-tama.pz-blocks:not(.pz-paint) { --cols: 16; } }
.pz-tama.pz-blocks > :not(:first-child) { border-top: 0; }
.pz-sws, .pz-ptools { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: 2px; }
.pz-sw { position: relative; height: 46px; min-width: 0; margin: 0; padding: 0; border: 0; display: grid; place-items: center;
  background: var(--pz-chrome); color: var(--pz-ink); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pz-sws .pz-sw { color: var(--pz-bar); }
.pz-sws .pz-sw > i { position: absolute; inset: 0; background: var(--c); }
.pz-sws .pz-sw > i.tex, .pz-blocks:not(.pz-paint) .pz-pdab::before { image-rendering: pixelated; image-rendering: crisp-edges; image-rendering: pixelated; }
.pz-sws .pz-sw:active > i { filter: brightness(.88); }
/* water and lava swatches run down like the blocks do (a tile is the cell's height) */
.pz-sws .pz-sw > i.flow { animation: pz-flow 2.4s linear infinite; }
.pz-sws .pz-sw[data-kind="15"] > i.flow { animation-duration: 7s; }
@keyframes pz-flow { from { background-position-y: 0; } to { background-position-y: 46px; } }
.pz-sws .pz-sw[aria-pressed="true"]::before { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border: 3px solid var(--pz-bar); box-shadow: inset 0 0 0 2px #fff; }
.pz-blocks.erase .pz-sws .pz-sw > i { opacity: .35; }
.pz-btools { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
/* The 2D | 3D switch (member request, Ethan; plaza.js "paint or blocks"): two tabs over the tools, the live one in ink
   with a red underline, the other in ink-2. Swapping trays doesn't replay the drop-in (.swap). */
.pz-mode { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; }
.pz-mode .pz-bt { height: 42px; color: var(--pz-ink-2); }
.pz-mode .pz-bt[aria-pressed="true"] { background: var(--pz-chrome); color: var(--pz-ink); box-shadow: inset 0 -4px 0 var(--pz-bar); cursor: default; }
.pz-tama.pz-blocks.swap { animation: none; }
.pz-bt { display: flex; align-items: center; justify-content: center; gap: 8px; height: 46px; min-width: 0; margin: 0; padding: 0 8px;
  border: 0; background: var(--pz-chrome); color: var(--pz-ink); font: 800 15.5px/1 var(--pz-rounded); white-space: nowrap;
  -webkit-tap-highlight-color: transparent; cursor: pointer; }
.pz-bt:active > * { transform: translateY(1px); }
.pz-bt[aria-pressed="true"] { background: var(--pz-bar); color: #fff; }
.pz-bhint { margin: 0; padding: 10px 12px 11px; background: var(--pz-chrome); color: var(--pz-ink-2); font: 600 13.5px/1.35 var(--pz-rounded); }
.pz-ptools .pz-bt { grid-column: span 2; }
@media (min-width: 700px) { .pz-ptools .pz-bt { grid-column: span 4; } .pz-ptools .pz-size { grid-column: span 2; } }
@media (max-width: 370px) { .pz-ptools .pz-bt { gap: 5px; padding: 0 4px; font-size: 14px; } }
.pz-size > i { display: block; width: var(--d); height: var(--d); background: var(--dab, var(--pz-ink)); }
.pz-sw.pz-size:active > i { transform: translateY(1px); }
.pz-sw.pz-size[aria-pressed="true"] { background: var(--pz-bar); color: #fff; }
.pz-sw.pz-size[aria-pressed="true"] > i { box-shadow: 0 0 0 2px #fff; }
.pz-paint.erase .pz-size > i { background: transparent; box-shadow: inset 0 0 0 2px currentColor; }
/* Folding (member requests): once its picks are made (Blocks: a colour or Remove; Paint: a colour and a size) or it's
   used on the floor, the Blocks or Paint tray slides up into one strip so the floor is free: a square of what you'll do
   (the block colour / the brush size in the colour; hollow for Remove and the eraser), its name, a chevron, then
   the quick tools (Blocks: Build and Remove icons; Paint: Undo). Tapping the strip slides the
   full tray back down. */
.pz-pfold { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .22s cubic-bezier(.3, .7, .2, 1); }
.pz-pfull { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow: hidden; }
.pz-blocks.folded .pz-pfold { grid-template-rows: 0fr; }
.pz-pstrip { display: none; gap: 2px; animation: pz-tama .16s ease-out; }
.pz-blocks.folded .pz-pstrip { display: flex; }
.pz-pstrip .pz-bt { flex: 0 0 auto; height: 42px; padding: 0 14px; }
.pz-pshow { flex: 1 1 auto; display: flex; align-items: center; gap: 10px; min-width: 0; height: 42px; margin: 0; padding: 0 12px;
  border: 0; background: var(--pz-chrome); color: var(--pz-ink); font: 800 15.5px/1 var(--pz-rounded); text-align: left;
  white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pz-pshow > span { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.pz-pshow:active > * { transform: translateY(1px); }
.pz-pdab { flex: none; display: grid; place-items: center; width: 22px; height: 22px; }
.pz-pdab::before { content: ""; width: var(--pdab, 10px); height: var(--pdab, 10px); background: var(--dab, var(--pz-ink));
  box-shadow: 0 0 0 1.5px var(--pz-line); }
.pz-blocks.erase .pz-pdab::before { background: transparent; box-shadow: inset 0 0 0 2px currentColor; }
.pz-pchev { width: 18px; height: 18px; margin-left: -2px; }
@media (prefers-reduced-motion: reduce) { .pz-pfold { transition: none; } .pz-pstrip { animation: none; } }
.plaza.painting .pz-floor { cursor: crosshair; }

/* Landscape (member request, Ethan): held sideways on a phone or tablet, the dock stands up as a column on the right
   edge, the floor fills the rest with the who's-here row along its bottom, and the side safe area (notch, home bar) is the dock's own chrome. The square
   cells stack edge to edge and stop growing at 64px tall; the block and paint trays hang from the dock's left edge, seven colours to a row. */
@media (orientation: landscape) and (pointer: coarse) {
  .plaza { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: minmax(0, 1fr) auto auto; }
  .plaza > .pz-floor { grid-column: 1; grid-row: 1; }
  .plaza > .pz-bottom { grid-column: 1; grid-row: 2; padding-left: max(12px, env(safe-area-inset-left)); }
  .plaza > .pz-here { grid-column: 1; grid-row: 3; }
  .plaza > .pz-dock { grid-column: 2; grid-row: 1 / -1; min-height: 0; border-bottom: 0; border-left: 2px solid var(--pz-line);
    padding: 0 env(safe-area-inset-right) var(--sab) 0; }
  .plaza .pz-cam { flex-direction: column; width: 58px; max-width: none; max-height: 100%; margin: 0; }
  .plaza .pz-cam-b { flex: 0 1 64px; width: 100%; height: auto; min-height: 0; padding-top: 0; }
  .plaza .pz-tama { left: auto; right: calc(100% + 12px); top: 0; bottom: auto; transform-origin: 100% 22px; }
  @keyframes pz-tama-side { from { opacity: 0; transform: translateX(10px) scale(.96); } }
  .plaza .pz-tama { animation-name: pz-tama-side; }
  .pz-tama.pz-blocks:not(.pz-paint) { --cols: 8; }
  .pz-tama.pz-blocks { --cols: 7; left: auto; right: 100%; top: 0; bottom: auto; width: min(378px, calc(100vw - 120px)); max-height: 100%; overflow-y: auto;
    overscroll-behavior: contain; border-left: 2px solid var(--pz-line); transform-origin: 100% 0; }
  .pz-ptools .pz-bt { grid-column: span 2; }
  .pz-ptools .pz-size { grid-column: auto; }
}

/* Weather (plaza.js "weather"): a lightning strike whites the floor out for a blink, twice, like a real flash. */
.pz-flash { position: absolute; inset: 0; z-index: 3000; pointer-events: none; background: #fff; opacity: 0; }
.pz-flash.on { animation: pz-flash .5s linear; }
@keyframes pz-flash { 0% { opacity: 0; } 8% { opacity: .7; } 22% { opacity: .05; } 34% { opacity: .45; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .pz-flash.on { animation: none; } }
.pz-ico:not(.line) { shape-rendering: crispEdges; }
