/* Mii Plaza + Mii editor. A change of voice from the chat in type (rounded, white pill buttons) but not in colour: it wears
   Chatteau's own palette (member request: one look, no theme picker), indigo for "you" and selection. 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-grid: var(--wall);
  --pz-chrome: var(--paper);
  --pz-ink: var(--ink);
  --pz-ink-2: var(--ink-2);
  --pz-line: var(--rule);
  --pz-blue: var(--indigo); /* your marker, selection rings */
  --pz-bar: var(--indigo);  /* pressed buttons and the main button (white text reads on it) */
  --pz-lift: 100%;          /* how much of a member's colour to keep in names; dark mode mixes the rest toward white */
  --pz-rounded: "M PLUS Rounded 1c", "Hiragino Maru Gothic ProN", var(--font);
  --mw: 62px;
}
.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; }
/* typing in the Lobby (member request): the keyboard slides over the floor instead of shrinking it (app.js fitViewport) */
html.kb-over .plaza { height: var(--app-full, var(--app-h)); }
html.kb-over body.tabs-on .plaza { height: calc(var(--app-full, var(--app-h)) - var(--tabs-y, 0px)); }
@media (prefers-color-scheme: dark) {
  .plaza, .pz-vars { --pz-chrome: var(--wall-2); --pz-lift: 55%; }
  .plaza .mface.cutout img { filter: invert(1); } /* drawn faces go white-on-dark, like their lineart on the 3D floor */
}
body.in-plaza { background: var(--felt); }
@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); }
@media (prefers-color-scheme: dark) { .pz-top .pz-btn { border-color: #ffffff40; } .pz-top .pz-btn.blue { background: #fff; color: #a10f18; } }
.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 (member requests, Ethan): a strip across the Lobby's head, right under the Chat / Change / Lobby bar, over the
   floor. #pzCam is the row in it: back to chat, Change, then the places (arcade, the palette for paint and blocks:
   plaza.js PLACES); their menus and trays drop down from it over the floor.
   Cells share the width on a phone and stop growing at 60px on a wide screen; the frame colour shows through the 2px
   gaps as the dividers, the same between every pair of cells (member request, Ethan). */
.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 { 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-ink);
  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:active { transform: translateY(1px); }
/* Pixel icons (member request, Ethan): 12 x 12 one-bit sprites at 2px a pixel. */
.pz-cam-b svg.px { width: 24px; height: 24px; shape-rendering: crispEdges; }
/* Group cells (member request, Ethan): the arcade (arcade + high scores). Open, it goes header red and its rows drop
   down under it. */
.pz-cam-b.group[aria-pressed="true"] { background: var(--pz-bar); color: #fff; }
.pz-group { transform-origin: 30px 0; }
.pz-group .pz-act { width: auto; min-width: 118px; }
.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: name tag at the feet,
   "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, one solid red block in the section bar's style (member request, Ethan:
   "cleaner, solid red like the top bar"): the bar's #d3121c, white Libre Franklin caps, square corners, no icons. The
   name leads in those caps behind a small hard square in the member's colour; a status line in white under it; then
   the buttons as the bar's cells, split by its faint white hairlines. Gary's card stays Geek Squad black, the hot
   dog's keeps its poem paper. */
.pm-challenge { --pm-red: #d3121c; 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); background: var(--pm-red); color: #fff; white-space: nowrap;
  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: -6px; width: 12px; height: 12px;
  margin-left: -6px; background: var(--pm-red); transform: rotate(45deg); }
.pm-challenge.below { bottom: auto; top: 12px; }
.pm-challenge.below::after { bottom: auto; top: -6px; }
.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; background: none; color: #fff; cursor: pointer; -webkit-tap-highlight-color: transparent;
  font: 800 13px/1 "Libre Franklin", "Helvetica Neue", Arial, sans-serif; letter-spacing: .1em; text-transform: uppercase; text-rendering: geometricPrecision; }
.pm-gb { --n: 2; }
.pm-challenge button + button::before { content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 1px; background: rgba(255, 255, 255, .45); }
.pm-challenge button:active { filter: brightness(.94); }
.pm-challenge button:focus-visible { outline: 3px solid #fff; outline-offset: -5px; }
/* the card's top: name, status, what they're up to (stars live on the profile, member request); a faint white hairline (inset like the bar's) over the buttons */
.pm-who { position: relative; display: grid; gap: 4px; padding: 11px 16px 11px; text-align: left; color: #fff; }
.pm-challenge:not(.bare) .pm-who::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: 0; height: 1px; background: rgba(255, 255, 255, .45); }
.pm-who-n { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; font: 800 16px/1.1 "Libre Franklin", "Helvetica Neue", Arial, sans-serif;
  letter-spacing: .1em; text-transform: uppercase; color: #fff; text-rendering: geometricPrecision; }
/* 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: 10px; height: 10px; margin: 0 9px 0 2px; vertical-align: .05em; border-radius: 50%; background: #ff5a62; box-shadow: 0 0 0 1.5px #fff; }
.pm-who-n.on::before { background: #2fd16c; }
.pm-who-s { display: flex; align-items: center; font: 700 13px/1.2 var(--pz-rounded); color: rgba(255, 255, 255, .82); }
/* what they're up to (member request, Ethan): a live white dot, then the line in white */
.pm-doing { display: flex; align-items: baseline; gap: 7px; width: max-content; max-width: min(260px, calc(100vw - 72px)); margin-top: 1px; white-space: normal; font: 700 14px/1.25 var(--pz-rounded); color: #fff; }
.pm-doing::before { content: ''; flex: none; width: 8px; height: 8px; transform: translateY(-1px); background: #fff; box-shadow: 0 0 0 0 rgba(255, 255, 255, .6); animation: pm-doing 1.8s ease-out infinite; }
@keyframes pm-doing { 0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, .6); } 100% { box-shadow: 0 0 0 7px rgba(255, 255, 255, 0); } }
@media (prefers-reduced-motion: reduce) { .pm-doing::before { animation: none; } }
/* Agent Gary's card: one black "Show me how" bar with a Geek Squad orange underline */
.pm-gs .pm-gs-go { padding: 9px 18px 10px; background: #000; box-shadow: inset 0 -3px 0 #ff6c0c; }
.pm-gs .pm-gs-go::before { display: none; }
.pm-gs .pm-gs-go svg { width: 19px; height: 19px; flex: none; color: #ff6c0c; }
.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); }
.pm-bubble .blood { font-style: normal; }
.pm-bubble .grawlix { font-family: "Comic Sans MS", "Comic Neue", "Chalkboard SE", "Comic Sans", cursive; font-weight: 700; font-style: normal; white-space: nowrap; }
@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); } }
/* sleepers lie on the floor: z's drift up off the head (which lies toward --side * -1) */
.pm-zzz { display: none; position: absolute; left: calc(var(--side, 1) * var(--hh) * -.55); bottom: calc(var(--hh) - 6px); width: 0; height: 0; pointer-events: none; }
.pm.sleeping .pm-zzz { display: block; }
.pm-zzz i { position: absolute; left: 0; bottom: 0; font: 800 15px/1 var(--pz-rounded); font-style: normal; color: var(--pz-ink-2); opacity: 0;
  animation: pz-zzz-r 3.6s ease-out infinite; will-change: transform, opacity; }
.pm-zzz.flip i { animation-name: pz-zzz-l; }
.pm-zzz i:nth-child(2) { font-size: 19px; animation-delay: 1.2s; }
.pm-zzz i:nth-child(3) { font-size: 24px; animation-delay: 2.4s; }
/* Bug fix (Ethan: the z's didn't move): iOS Safari doesn't animate var() inside @keyframes, so each side gets its own
   keyframes (plaza.js mkEl adds .flip for side -1), and they keep drifting under Reduce Motion (a slow, small float). */
@keyframes pz-zzz-r {
  0% { opacity: 0; transform: translate(0, 0) rotate(-8deg) scale(.6); }
  15% { opacity: .9; }
  45% { transform: translate(-8px, -20px) rotate(4deg) scale(.82); }
  70% { opacity: .7; }
  100% { opacity: 0; transform: translate(-26px, -46px) rotate(8deg) scale(1); }
}
@keyframes pz-zzz-l {
  0% { opacity: 0; transform: translate(0, 0) rotate(8deg) scale(.6); }
  15% { opacity: .9; }
  45% { transform: translate(8px, -20px) rotate(-4deg) scale(.82); }
  70% { opacity: .7; }
  100% { opacity: 0; transform: translate(26px, -46px) rotate(-8deg) scale(1); }
}
.pm.sleeping .pm-bang { left: calc(var(--side, 1) * var(--hh) * -.55); }
@media (prefers-reduced-motion: reduce) {
  .pm-me { animation: none; }
  .pm-zzz i { animation-duration: 4.8s !important; animation-iteration-count: infinite !important; }
  .pm-zzz i:nth-child(2) { animation-delay: 1.6s; }
  .pm-zzz i:nth-child(3) { animation-delay: 3.2s; }
}


/* 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 */
.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 request, Ethan: "add the active bii bar back"): the chat's row of flat 2D Bii heads (style.css .here-*)
   at the Lobby's foot, in the chrome. It holds the bottom safe area, so the bar above drops its own; names keep
   the member's colour, lifted toward white in dark mode (--pz-lift). Gone while the keyboard is up, like the chat's. */
.pz-here { flex: none; display: flex; gap: 4px; padding: 6px 10px calc(4px + var(--sab)); overflow-x: auto; background: var(--pz-chrome);
  overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; border-top: 2px solid var(--pz-line); }
.pz-here::-webkit-scrollbar { display: none; }
.plaza > .pz-bottom:has(+ .pz-here) { padding-bottom: 8px; }
.kb-open .pz-here { display: none; }
.kb-open .plaza > .pz-bottom:has(+ .pz-here) { padding-bottom: 10px; }
.pz-here .here-p { color: color-mix(in srgb, var(--c, var(--pz-ink)) var(--pz-lift), #fff); font: 800 12px/1.2 var(--pz-rounded); }
.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.px { width: 24px; height: 24px; fill: currentColor; shape-rendering: crispEdges; }
.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); }
.mc-new { justify-content: center; min-height: 185px; border-style: dashed; }
.mc-new .plus { font: 800 44px/1 var(--pz-rounded); 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); }
.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; }
/* Pokémon tab (member request, Ethan: hide your follower): a Poké Ball that pops open while it's out, two big choices. */
.ed-pet-ball { flex: none; position: relative; width: 64px; height: 64px; border-radius: 50%; border: 3px solid var(--pz-ink);
  background: linear-gradient(var(--pz-bar) 0 calc(50% - 2px), var(--pz-ink) 0 calc(50% + 2px), #fff 0); transition: transform .25s; }
.ed-pet-ball::after { content: ""; position: absolute; left: 50%; top: 50%; width: 16px; height: 16px; margin: -11px 0 0 -11px; border-radius: 50%; border: 3px solid var(--pz-ink); background: #fff; }
.ed-pet-ball.out { transform: rotate(-18deg); background: linear-gradient(var(--pz-bar) 0 calc(42% - 2px), var(--pz-ink) 0 calc(42% + 2px), #fff 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); }
@media (prefers-reduced-motion: reduce) { .ed-pet-ball { transition: none; } }
/* 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 chat header's door to the plaza: your own Mii's face */

/* 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; }
.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 menus and trays (.pz-tama: the Blocks and Paint trays, group menus), 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-act { display: flex; align-items: center; gap: 10px; width: 118px; height: 44px; margin: 0; padding: 0 12px 0 10px; border: 0;
  background: var(--pz-chrome); color: var(--pz-ink); font: 800 15.5px/1 var(--pz-rounded); text-align: left; white-space: nowrap;
  -webkit-tap-highlight-color: transparent; cursor: pointer; }
.pz-tama > :not(:first-child) { border-top: 2px solid var(--pz-line); }
.pz-act:active { transform: translateY(1px); }
.pz-act:disabled { opacity: .45; cursor: default; }
.pz-ico { flex: none; display: block; width: 24px; height: 24px; fill: currentColor; shape-rendering: crispEdges; }
.pz-ico .f2 { opacity: 0; }
@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; } }

.pm-challenge.pm-gs, .pm-challenge.pm-gs::after { border-color: #000; background: #000; }

/* Blocks + Paint trays (member request, Ethan; plaza.js "blocks", "paint").
   The palette cell goes header red 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, seven to a row (fourteen on a wide screen); the picked one wears an indigo frame
   with a white line inside (::before, buttons.css drops button shadows). Tools are moves-menu rows (one-bit icon + bold
   rounded label); on = indigo with white, like the open cell; waiting =
   dimmed with the time left. 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-cam-b.place[aria-pressed="true"] { background: var(--pz-bar); color: #fff; }
.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; }
@media (min-width: 700px) { .pz-tama.pz-blocks { --cols: 14; } }
.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:active > i { filter: brightness(.88); }
.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 an indigo 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 pixel chevron, then
   the quick tools (Blocks: Build and Remove icons with their countdowns; 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, and the side safe area (notch, home bar) is the dock's own chrome. Cells keep the
   2px frame-colour dividers and stop growing at 64px tall. Menus open leftward beside their button (plaza.js setGroup
   lines the arcade's up with it); 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; }
  .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 { grid-template-rows: minmax(0, 1fr) auto auto; }
  .plaza > .pz-here { grid-column: 1; grid-row: 3; padding-left: max(10px, env(safe-area-inset-left)); }
  .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; }
  .pz-cam { flex-direction: column; width: 58px; max-width: none; max-height: 100%; margin: 0; }
  .pz-cam-b { flex: 0 1 64px; width: 100%; height: auto; min-height: 0; }
  .pz-tama { left: auto; right: calc(100% + 12px); top: 0; transform-origin: 100% 22px; }
  @keyframes pz-tama-side { from { opacity: 0; transform: translateX(10px) scale(.96); } }
  .pz-tama { animation-name: pz-tama-side; }
  .pz-group { left: auto !important; }
  .pz-tama.pz-blocks { --cols: 7; left: auto; right: 100%; top: 0; 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; } }
