/* Lobby design system: see DESIGN.md before changing tokens. */
@font-face { font-family: "Atkinson Hyperlegible"; font-weight: 400; font-style: normal; font-display: swap; src: url(/fonts/AtkinsonHyperlegible-400.woff2) format("woff2"); }
@font-face { font-family: "Atkinson Hyperlegible"; font-weight: 400; font-style: italic; font-display: swap; src: url(/fonts/AtkinsonHyperlegible-400i.woff2) format("woff2"); }
@font-face { font-family: "Atkinson Hyperlegible"; font-weight: 700; font-style: normal; font-display: swap; src: url(/fonts/AtkinsonHyperlegible-700.woff2) format("woff2"); }
@font-face { font-family: "Libre Franklin"; font-weight: 800; font-style: normal; font-display: swap; src: url(/fonts/LibreFranklin-800.woff2) format("woff2"); }
@font-face { font-family: "Barlow Condensed"; font-weight: 600; font-style: normal; font-display: swap; src: url(/fonts/BarlowCondensed-600.woff2) format("woff2"); }

:root {
  color-scheme: light;
  /* palette: 🅱️chat's red and white, always light */
  --wall: #fbf4f4;       /* page background: white with a breath of red */
  --wall-2: #fffafa;     /* raised surfaces: sheets, inputs */
  --paper: #ffffff;      /* inputs, lists, the docks' chrome */
  --ink: #2e0b0f;        /* text: a red so deep it reads as black */
  --ink-2: #7d4a4f;      /* secondary text */
  --ink-3: #a98689;      /* tertiary text, hints */
  --rule: #ecd2d4;       /* separators, input borders */
  --felt: #b8111b;       /* the letterboard: red felt */
  --felt-groove: #9c0d16;
  --letter: #ffffff;     /* letterboard letters */
  --red: #d3121c;        /* your own bubbles, primary buttons, links, focus */
  --red-ink: #ffffff;
  --bubble: #ffffff;     /* everyone else's bubbles, with a 1px edge */
  --bubble-edge: #ebcfd1;
  --signal: #ffffff;     /* change requests + "in progress": white on the red board */
  --signal-ink: #b8111b;
  --focus: #d3121c;
  --note: #ffe6e6;       /* replies from Lobby: pale red paper */
  --note-ink: #4a0d12;
  --danger: #b42318;
  --ok: #1f7a4d;
  /* type */
  --font: "Atkinson Hyperlegible", system-ui, -apple-system, "Segoe UI", sans-serif;
  --board: "Barlow Condensed", "Arial Narrow", sans-serif;
  --bar-font: "Libre Franklin", "Helvetica Neue", Arial, sans-serif; /* the section bar's heavy tracked caps */
  --app-h: 100dvh;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; height: 100%; touch-action: manipulation; background: var(--wall); color: var(--ink); font: 17px/1.45 var(--font); overscroll-behavior: none; }
body.in-chat { background: #fff linear-gradient(var(--felt), var(--felt)) top / 100% 50% no-repeat; } /* felt behind the status bar, white below */
button { font: inherit; color: inherit; cursor: pointer; }
input, textarea { font: inherit; font-size: 17px; color: var(--ink); }
a { color: var(--red); }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.boot { height: var(--app-h); background: var(--felt); }

/* ---------- the letterboard ---------- */
.board {
  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: .14em;
  text-shadow: 0 1px 0 #000a;
}
.board .row1 { font-size: 26px; line-height: 1; }
.board .row2 { font-size: 15px; line-height: 1.2; letter-spacing: .12em; opacity: .82; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- auth ---------- */
.auth { min-height: var(--app-h); display: flex; flex-direction: column; }
.auth .board { padding: calc(56px + env(safe-area-inset-top)) 24px 40px; }
.auth .board .row1 { font-size: 64px; letter-spacing: .18em; }
.auth .board .row2 { font-size: 20px; margin-top: 14px; white-space: normal; }
.auth-body { flex: 1; padding: 28px 24px calc(28px + env(safe-area-inset-bottom)); max-width: 420px; width: 100%; }
.auth-body p { margin: 0 0 20px; color: var(--ink-2); }
.auth form { display: grid; gap: 12px; }
.field { width: 100%; padding: 12px 14px; background: var(--paper); border: 1.5px solid var(--rule); border-radius: 10px; outline: none; }
.field:focus { border-color: var(--red); }
.btn { border: 0; border-radius: 10px; padding: 13px 18px; font-weight: 700; background: var(--red); color: var(--red-ink); }
.btn:disabled { opacity: .5; }
.btn.quiet { background: transparent; border: 1.5px solid var(--rule); color: var(--ink); }
.btn.small { padding: 7px 12px; font-size: 15px; }
.btn.signal { background: var(--red); color: var(--red-ink); }
.err { color: var(--danger); min-height: 1.3em; font-size: 15px; }
.hint { color: var(--ink-2); font-size: 15px; margin-top: 22px; }

/* ---------- chat layout ---------- */
.chat { position: fixed; top: var(--app-top, 0px); left: 0; right: 0; height: var(--app-h); display: flex; flex-direction: column; max-width: 760px; margin: 0 auto; background: #fff; --wall: #fff; }
@keyframes spin { to { transform: rotate(360deg); } }

.banner { display: flex; align-items: center; gap: 12px; padding: 10px 14px 10px 18px; background: var(--note); color: var(--note-ink); font-size: 15px; }
.banner .txt { flex: 1; }
.banner .x { background: none; border: 0; color: inherit; opacity: .6; font-size: 15px; padding: 4px 6px; text-decoration: underline; }

.messages { flex: 1; overflow-y: auto; padding: 8px 14px 6px; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.older { text-align: center; color: var(--ink-3); font-size: 14px; padding: 10px 0; min-height: 1px; }
.day { margin: 18px 4px 6px; font-size: 14px; font-weight: 700; color: var(--ink-2); }

.msg { display: flex; flex-direction: column; align-items: flex-start; margin-top: 3px; }
.msg.first { margin-top: 14px; }
.msg .who { font-size: 14px; font-weight: 700; margin: 0 0 3px 2px; color: var(--c, var(--ink-2)); }
/* hidden names (member request): the alias crossfades in over the name while it's touched (app.js whoLabel) */
.msg .who.has-alias { display: grid; justify-items: start; }
.who.has-alias > span { grid-area: 1 / 1; transition: opacity .18s, transform .22s cubic-bezier(.2, .8, .2, 1); }
.who.has-alias .who-a { opacity: 0; transform: translateY(5px); }
.who.has-alias.alias-on .who-n { opacity: 0; transform: translateY(-5px); }
.who.has-alias.alias-on .who-a { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .who.has-alias > span { transition: none; transform: none !important; } }
.msg .bubble { max-width: min(80%, 540px); padding: 8px 13px 9px; border-radius: 16px; background: var(--bubble); white-space: pre-wrap; overflow-wrap: anywhere; box-shadow: 0 0 0 1px var(--bubble-edge); }
.msg:not(.own).last .bubble { border-bottom-left-radius: 5px; }
.msg .bubble a { color: inherit; }
.msg .time { font-size: 12.5px; color: var(--ink-3); margin: 3px 4px 0; }
.msg.own { align-items: flex-end; }
.msg.own .bubble { background: var(--red); color: var(--red-ink); box-shadow: none; }
.msg.own.last .bubble { border-bottom-right-radius: 5px; }
.msg.pending .bubble { opacity: .55; }
.msg.failed .bubble { outline: 2px solid var(--danger); }
.msg.failed .time { color: var(--danger); }
.msg .bubble.big { font-size: 44px; line-height: 1.1; background: none; box-shadow: none; padding: 0 2px; }

.sys { margin: 12px 4px; font-size: 14.5px; color: var(--ink-2); overflow-wrap: anywhere; }
.sys q { font-style: italic; color: var(--ink); quotes: "“" "”"; }

/* replies from Lobby: a note from the front desk */
.note { margin: 14px 0; max-width: min(88%, 560px); background: var(--note); color: var(--note-ink); border-radius: 4px; padding: 10px 14px 11px; box-shadow: 0 0 0 1px #d3121c26; }
.note .tag { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; }
.note .tag b { font: 600 14px/1 var(--board); letter-spacing: .14em; text-transform: uppercase; background: var(--felt); color: var(--letter); padding: 3px 6px 2px; border-radius: 2px; }
.note .tag span { font-size: 13.5px; opacity: .75; }
.note .body { white-space: pre-wrap; overflow-wrap: anywhere; }
.note.failed { background: transparent; border: 1.5px dashed var(--rule); color: var(--ink); box-shadow: none; }

.jump { position: absolute; right: 14px; bottom: calc(80px + env(safe-area-inset-bottom)); border: 0; background: var(--ink); color: var(--wall); border-radius: 99px; padding: 8px 14px; font-size: 14px; font-weight: 700; z-index: 4; }
.typing { height: 20px; padding: 0 18px; font-size: 13.5px; color: var(--ink-3); font-style: italic; }

.composer { display: flex; align-items: flex-end; gap: 8px; padding: 8px 12px calc(10px + env(safe-area-inset-bottom)); background: var(--wall); }
.composer textarea { flex: 1; resize: none; max-height: 150px; min-height: 44px; padding: 10px 15px; border-radius: 22px; border: 1.5px solid var(--rule); background: var(--paper); outline: none; line-height: 1.35; }
.composer textarea:focus { border-color: var(--red); }
.send { flex: none; width: 44px; height: 44px; border-radius: 50%; border: 0; background: var(--red); color: var(--red-ink); display: grid; place-items: center; }
.send svg { width: 20px; height: 20px; }

/* ---------- sheets ---------- */
.scrim { position: fixed; inset: 0; background: #0b0d1a80; z-index: 20; opacity: 0; transition: opacity .2s; }
.scrim.open { opacity: 1; }
.sheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 21; max-width: 760px; margin: 0 auto; max-height: calc(var(--app-h) - 28px - env(safe-area-inset-top)); overflow-y: auto; background: var(--wall-2); border-radius: 20px 20px 0 0; padding: 18px 18px calc(24px + env(safe-area-inset-bottom)); transform: translateY(100%); transition: transform .26s cubic-bezier(.2, .8, .2, 1); }
.sheet.open { transform: none; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sheet h2 { margin: 0; font-size: 22px; line-height: 1.2; }
.sheet h3 { margin: 26px 0 8px; font-size: 16px; }
.sheet .credit { color: var(--ink-2); font-size: 13px; margin: 18px 0 0; }
.sheet .credit a { color: inherit; }
.sheet .lede { color: var(--ink-2); margin: 6px 0 16px; max-width: 60ch; }
.close { flex: none; background: none; border: 0; color: var(--ink-2); font-size: 15px; font-weight: 700; padding: 6px 2px; text-decoration: underline; }
.muted { color: var(--ink-3); font-size: 15px; }

.ask textarea { width: 100%; min-height: 110px; resize: vertical; padding: 12px 14px; border-radius: 10px; border: 1.5px solid var(--rule); background: var(--paper); outline: none; }
.ask textarea:focus { border-color: var(--red); }
.ask .row { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: 10px; }
.ask .row .muted { font-size: 14px; }

.jobs { list-style: none; margin: 0; padding: 0; }
.job { padding: 12px 0; border-top: 1px solid var(--rule); }
.job:first-child { border-top: 0; }
.job .head { display: flex; align-items: baseline; gap: 8px; font-size: 15px; }
.job .head b { font-weight: 700; }
.job .head .status { color: var(--ink-2); }
.job .head .sp { flex: 1; }
.job .prompt { margin-top: 3px; white-space: pre-wrap; overflow-wrap: anywhere; }
.job .act { margin-top: 5px; font-size: 14.5px; color: var(--ink-2); font-style: italic; }
.job .reply { margin-top: 8px; padding: 7px 11px; background: var(--note); color: var(--note-ink); border-radius: 4px; font-size: 15.5px; }
.job.running .status { color: var(--ink); font-weight: 700; }
.job.running .status::before { content: ""; display: inline-block; width: 12px; height: 12px; margin-right: 6px; vertical-align: -1px; border-radius: 50%; border: 2px solid var(--rule); border-top-color: var(--ink); animation: spin .9s linear infinite; }
.job.failed .status { color: var(--danger); }

.working { display: flex; gap: 16px; align-items: center; padding: 18px 16px; margin-top: 4px; background: var(--felt); color: var(--letter); border-radius: 12px; }
.working .spinner { flex: none; width: 44px; height: 44px; border-radius: 50%; border: 4px solid #ffffff22; border-top-color: var(--signal); border-right-color: var(--signal); animation: spin 1s linear infinite; }
.working .t1 { font-weight: 700; font-size: 18px; }
.working .t2 { font-size: 15px; opacity: .8; margin-top: 2px; }
.working .t3 { font-size: 14.5px; opacity: .7; margin-top: 4px; font-style: italic; min-height: 1.3em; }
.working .actions { display: flex; gap: 14px; margin-top: 10px; }
.working .actions button { background: none; border: 0; color: var(--letter); padding: 0; font-size: 15px; text-decoration: underline; opacity: .85; }

.reply-card { margin-top: 4px; background: var(--note); color: var(--note-ink); border-radius: 4px; padding: 16px 18px 18px; }
.reply-card .t1 { font-weight: 700; font-size: 18px; margin-bottom: 6px; }
.reply-card .body { white-space: pre-wrap; margin-bottom: 14px; }
.reply-card.failed { background: var(--paper); color: var(--ink); border: 1.5px dashed var(--rule); }

.group { background: var(--paper); border-radius: 12px; overflow: hidden; }
.item { display: flex; align-items: center; gap: 12px; width: 100%; padding: 13px 16px; border: 0; border-top: 1px solid var(--rule); background: none; text-align: left; text-decoration: none; color: var(--ink); }
.item:first-child { border-top: 0; }
.item .sub2 { color: var(--ink-2); font-size: 14.5px; }
.item .grow { flex: 1; min-width: 0; }
.people { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.person { display: flex; align-items: center; gap: 7px; font-weight: 700; color: var(--c, var(--ink)); }
.person .d { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--ink-3); }
.person .d.on { background: var(--ok); border-color: var(--ok); }
.invite-box { display: flex; gap: 8px; padding: 0 16px 14px; }
.invite-box input { flex: 1; min-width: 0; padding: 9px 11px; border-radius: 8px; border: 1.5px solid var(--rule); background: var(--wall-2); font-size: 15px; }

.toast { position: fixed; left: 50%; top: calc(14px + env(safe-area-inset-top)); transform: translate(-50%, -160%); background: var(--ink); color: var(--wall); padding: 10px 16px; border-radius: 10px; z-index: 40; transition: transform .3s; max-width: calc(100% - 32px); font-size: 15px; font-weight: 700; }
.toast.show { transform: translate(-50%, 0); }

/* ---------- the shell (🅱️chat's layout) ----------
   Top to bottom: the felt safe area (.top), the section bar (#tabbar: Chat, Change, Lobby), then the chat, the Change
   page (docked under the bar) or the Lobby and its Arcade (under the bar at the chat's width). The menu is the left
   drawer, pulled out by the grip on the chat's left edge (#menuBtn) or a swipe in from that edge. */
.chat > .top, .chat > .tabbar, .chat > .banner, .chat > .messages, .chat > .typing, .chat > .composer { position: relative; z-index: 1; }
.chat > .top { flex: none; display: block; padding: env(safe-area-inset-top) 0 0; background: var(--felt); }
.chat > .top + .tabbar { border-top: 0; }

/* the section bar: equal cells edge to edge, heavy tracked Libre Franklin caps. Closed = white with a red label, split
   by a faint red hairline, over a 2px red rule; the open one is solid red with a white label led by the room's G tile. */
.tabbar { --c: #d3121c; --n: 3; --i: 0; position: relative; flex: none; display: flex; background: #fff; border-top: 2px solid #fff; border-bottom: 2px solid var(--c);
  user-select: none; -webkit-user-select: none; }
.tabbar .tab { position: relative; flex: 1 1 0; min-width: 0; height: 44px; margin: 0; padding: 0 6px;
  display: flex; align-items: center; justify-content: center; gap: 6px; border: 0; background: #fff; color: var(--c);
  font: 800 15px/1 var(--bar-font); letter-spacing: .1em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; cursor: pointer; -webkit-tap-highlight-color: transparent; text-rendering: geometricPrecision; }
/* no colour fade on a label (iPhone could stall it and leave a label the colour of its cell): the real cells always stay
   white with red labels; the open look lives only in the lens below */
.tabbar .tab::before { content: ""; position: absolute; inset: 0; border: 6px solid #fff; pointer-events: none; }
.tabbar .tab + .tab::after { content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 1px; background: rgba(211, 18, 28, .35); pointer-events: none; }
.tabbar > .tab[aria-selected="true"]::after, .tabbar > .tab[aria-selected="true"] + .tab::after { display: none; }
.tabbar .tab > span { padding-left: .1em; overflow: hidden; text-overflow: clip; }
/* the sliding lens: app.js mountLens lays one red window (.tab-lens, a cell wide) over the bar and glides it to cell
   --i; inside, a copy of every cell in the open look slides the other way, so the labels hold still and turn white as
   the red crosses them. It runs up through the safe area to the top of the screen. */
.tabbar > .tab-lens { position: absolute; left: 0; top: 0; bottom: 0; z-index: 1; width: calc(100% / var(--n)); overflow: hidden;
  pointer-events: none; transform: translate3d(calc(var(--i) * 100%), 0, 0); transition: transform .38s cubic-bezier(.3, .9, .2, 1); }
.chat > .top + .tabbar > .tab-lens { top: calc(-1 * env(safe-area-inset-top, 0px)); }
.tab-lens-row { display: flex; height: 100%; width: calc(100% * var(--n)); transform: translate3d(calc(var(--i) * -100% / var(--n)), 0, 0); transition: inherit; }
.tabbar > .tab-lens.still, .tabbar > .tab-lens.still .tab-lens-row { transition: none; }
@media (prefers-reduced-motion: reduce) { .tabbar > .tab-lens, .tab-lens-row { transition: none; } }
.tab-lens .tab { height: 100%; background: var(--c); color: #fff; }
.chat > .top + .tabbar .tab-lens .tab { padding-top: env(safe-area-inset-top, 0px); }
.tab-lens .tab::before, .tab-lens .tab::after { display: none; }
#tabbar .tab-lens .tab { outline-color: transparent !important; }
.tabbar:has(> .tab[aria-selected="true"]:active) > .tab-lens { filter: brightness(.94); }
.tabbar:has(> .tab[aria-selected="true"]:focus-visible) > .tab-lens::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 2px #fff; }
/* the open label is led by the room's mark: a white G tile with a red letter (🅱️chat's has its 🅱️ there) */
.tab-lens .tab > span { display: flex; align-items: center; padding-block: .3em; }
.tab-lens .tab > span::before { content: "G"; flex: none; display: grid; place-items: center; width: 1.3em; height: 1.3em; margin-right: .32em; border-radius: 3px;
  background: #fff; color: var(--c); font: 800 1.02em/1 var(--bar-font); letter-spacing: 0; padding-left: .02em; }
.tabbar .tab:active { filter: brightness(.94); }
#tabbar > .tab[aria-selected="true"]:not(:active, [data-hit], :focus-visible) { outline-color: transparent !important; }
.tabbar .tab-n { display: inline-grid; place-items: center; min-width: 19px; height: 19px; padding: 0 4px; background: var(--c); color: #fff;
  font: 800 11px/1 var(--bar-font); letter-spacing: 0; font-style: normal; }
.tab-lens .tab .tab-n { background: #fff; color: var(--c); }
@media (max-width: 600px) {
  #askBtn, .tab-lens [data-id="askBtn"] { gap: 7px; }
  .tabbar .tab { font-size: 13px; letter-spacing: .07em; padding: 0 4px; gap: 4px; }
  .tabbar .tab::before { border-width: 5px; }
  .tab-lens .tab { letter-spacing: .04em; gap: 3px; }
}
@media (max-width: 350px) { .tabbar .tab { font-size: 11.5px; letter-spacing: .04em; } #askBtn, .tab-lens [data-id="askBtn"] { gap: 5px; padding: 0 2px; } }
/* the menu's pull tab: a faint 3px grip sliver on the chat's left edge, halfway down, with a wide invisible hit area */
.chat > .menu-pull { position: absolute; left: 0; top: 50%; z-index: 4; width: 3px; height: 44px; margin: -22px 0 0; padding: 0; border: 0;
  border-radius: 0; background: var(--ink-3); opacity: .45; touch-action: none; -webkit-tap-highlight-color: transparent; }
.chat > .menu-pull::before { content: ""; position: absolute; inset: -20px -22px -20px 0; }
.chat > .menu-pull[aria-expanded="true"] { visibility: hidden; }

/* the Lobby, the Arcade, the high scores, the tower and the skateboard open under the bar, at the chat's width; sheets still come up over them */
body.tabs-on .plaza, body.tabs-on .arc, body.tabs-on .hsp, body.tabs-on .twr, body.tabs-on .skt { top: calc(var(--app-top, 0px) + var(--tabs-y, 0px)); height: calc(var(--app-h) - var(--tabs-y, 0px)); max-width: 760px; margin: 0 auto; }
body.tabs-on .arc-top { padding-top: 8px; }
body.tabs-on:is(.in-plaza, .in-arcade, .in-scores, .in-tower, .in-skate) .scrim { z-index: 31; }
body.tabs-on:is(.in-plaza, .in-arcade, .in-scores, .in-tower, .in-skate) .sheet { z-index: 32; }
/* landscape on a phone or tablet: every page drops the 760px column and runs edge to edge, clear of the side safe areas */
@media (orientation: landscape) and (pointer: coarse) {
  .chat, body.tabs-on .plaza, body.tabs-on .arc, body.tabs-on .hsp, body.tabs-on .twr, body.tabs-on .skt, .plaza { max-width: none; }
  .chat > .messages { padding-left: max(14px, env(safe-area-inset-left)); padding-right: max(14px, env(safe-area-inset-right)); }
  .chat > .composer { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
  body .chat > .sheet.docked { padding-left: max(14px, env(safe-area-inset-left)); padding-right: max(14px, env(safe-area-inset-right)); }
}
/* Change is a section: the sheet docks under the bar inside .chat on plain white, square, no scrim, slide or Close
   (app.js openSheet adds .docked + body.ask-on), a layer above the chat so nothing slides over the bar */
.chat > .sheet.docked { position: absolute; top: var(--tabs-y, 0px); bottom: 0; left: 0; right: 0; height: auto; max-height: none; max-width: none; margin: 0;
  z-index: 2; border-radius: 0; background: #fff; transform: none; transition: none; padding: 16px 14px calc(24px + var(--sab)); }
body.ask-on .chat > .top, body.ask-on .chat > .tabbar { z-index: 3; }
.kb-open .sheet.docked { border-radius: 0; padding-bottom: 16px; }
.sheet.docked .close { display: none; }
body.ask-on #jump { display: none; }
/* on Change the who's-here row stays out under it and shows the queue: one head per change in running order, each with
   its place in line on a felt tile (app.js queueRow); the docked sheet stops at its top (--chat-here-h, app.js) */
body.ask-on .chat > .here { z-index: 3; }
html:not(.kb-open) body.ask-on .chat > .sheet.docked { bottom: var(--chat-here-h, 0px); padding-bottom: 24px; }
.here.queue .here-face { position: relative; }
.q-n { position: absolute; top: 0; left: 2px; min-width: 18px; height: 20px; padding: 0 4px; display: grid; place-items: center; background: var(--felt);
  color: #fff; font: 600 15px/1 var(--board); border-radius: 2px; box-shadow: 0 0 0 2px #fff; }
.here.queue .now .q-n { background: #fff; color: var(--felt); box-shadow: inset 0 0 0 2px var(--felt); }

/* the menu drawer: full height from the left edge, square with a hard edge, the felt letterboard with the room's name
   across its top (the board holds the safe area) */
.sheet.drawer { top: var(--app-top, 0px); bottom: auto; right: auto; height: var(--app-h); max-height: none; width: min(88vw, 380px); max-width: none;
  margin: 0; border-radius: 0; padding: 0 16px calc(24px + var(--sab)); box-shadow: 1px 0 0 var(--rule); transform: translateX(-100%); }
.sheet.drawer.open { transform: none; }
.kb-open .sheet.drawer { border-radius: 0; }
.drawer-board { position: sticky; top: 0; z-index: 1; margin: 0 -16px 14px; padding: calc(10px + env(safe-area-inset-top)) 14px 10px 16px; background: var(--felt); color: var(--letter); }
.sheet .drawer-board h2 { font: 600 30px/1 var(--board); letter-spacing: .12em; text-transform: uppercase; }
.drawer-board .close { color: var(--letter); }
.drawer-board :focus-visible { outline-color: var(--letter); }
@media (prefers-reduced-motion: reduce) { .sheet.drawer { transition: none; } }

/* keyboard open (iOS): the sheet rides above the keyboard, and home-bar padding goes away */
.sheet { bottom: var(--kb, 0px); overscroll-behavior: contain; }
.kb-open .composer { padding-bottom: 8px; }
.kb-open .sheet { padding-bottom: 16px; border-radius: 20px; }

@media (min-width: 761px) { .chat { box-shadow: 0 0 0 1px var(--rule); } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0s !important; animation-iteration-count: 1 !important; transition-duration: 0s !important; }
}
.confetti { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 50; }

/* ---------- the Lobby (public/plaza.css has the rest) ---------- */
:root { --sab: env(safe-area-inset-bottom, 0px); } /* the bottom safe area, as 🅱️chat's Lobby code reads it */
:root { --here-h: 80px; } /* the glass who's-here bar's height, less the bottom safe area it also holds (plaza.css .pz-here) */
/* Who's here (member request, from 🅱️chat): the row of Bii heads along the bottom of the chat and the Lobby, you first, each over its member's name in their colour (app.js renderHere).
   The chat's row is .here (style.css "the shell"), the Lobby's .pz-here (plaza.css). */
/* the member whose change is being made: their head loops the loop with spiral eyes for as long as it runs */
.here-p.changing .here-face .mface.cutout { position: relative; }
.dz-loop { display: block; width: 100%; height: 100%; animation: dz-loop 1.5s linear infinite; }
@keyframes dz-loop {
  from { transform: rotate(0turn) translateY(-3px) rotate(0turn); }
  to { transform: rotate(1turn) translateY(-3px) rotate(1turn); }
}
.dz-over { position: absolute; inset: 0; }
.dz-spin { transform-box: fill-box; transform-origin: center; animation: spin .7s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .dz-loop { animation-duration: 1.6s !important; animation-iteration-count: infinite !important; }
  .dz-spin { animation-duration: .9s !important; animation-iteration-count: infinite !important; }
}
/* members who aren't online doze (member request, Ethan): shut eyes, a snot bubble that swells and shrinks with each
   breath (mii.js 'sleepy'), a dimmer head and name, and three Z's that fade in and float up off the top right, one after
   another. Both keep moving under Reduce Motion (member request), like the dizzy head above. */
.here-p.asleep .here-face { position: relative; opacity: .8; }
.here-p.asleep .here-n { opacity: .6; }
.here-p.asleep .mface.cutout { position: relative; }
.zz-bub { transform-box: fill-box; transform-origin: 0% 50%; animation: zz-bub 2.4s ease-in-out infinite; }
@keyframes zz-bub {
  0%, 100% { transform: scale(.35); }
  55% { transform: scale(1.12); }
  70% { transform: scale(1); }
}
.zz { position: absolute; right: -8px; top: 2px; width: 20px; height: 24px; pointer-events: none; }
.zz i { position: absolute; left: 0; bottom: 0; font: italic 900 9px/1 var(--font); color: var(--red); opacity: 0;
  text-shadow: 0 0 2px #fff, 0 0 2px #fff; animation: zz 3s linear infinite; }
.zz i:nth-child(2) { font-size: 11px; animation-delay: 1s; }
.zz i:nth-child(3) { font-size: 13px; animation-delay: 2s; }
@keyframes zz {
  0% { transform: translate(0, 6px) rotate(-12deg) scale(.6); opacity: 0; }
  30% { opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translate(10px, -20px) rotate(12deg) scale(1.1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .here-p .zz-bub { animation-duration: 2.4s !important; animation-iteration-count: infinite !important; }
  .here-p .zz i { animation-duration: 3s !important; animation-iteration-count: infinite !important; }
}
.here-p { flex: none; width: 64px; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0 0 2px; border: 0;
  background: none; color: var(--c, var(--ink)); font: 700 12px/1.2 var(--font); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.here-face { width: 50px; height: 50px; display: grid; place-items: center; }
.here-face .mface, .here-face img, .here-face svg { display: block; width: 100%; height: 100%; }
.here-face .mface.flat svg { padding: 4px; }
.here-n { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.here-p:active .here-face { scale: .92; }
.here-note { margin: 0; min-height: 66px; display: flex; align-items: center; padding: 0 8px; color: var(--ink-3); font-size: 14px; }
/* a finished change's reply pops up over the Lobby too */
body.in-plaza .scrim { z-index: 31; }
body.in-plaza .sheet { z-index: 32; }

/* ---------- @mentions (member request, from 🅱️chat) ----------
   A member's name in a bubble is bold in their name colour; your own name (or @everyone) is a small red tab, and a
   bubble that names you gets a red rim. "@" in the composer opens a row of members above it (#mentionBar). */
.msg .bubble .mention { font-weight: 700; color: var(--mc, inherit); white-space: nowrap; }
.msg .bubble .mention.me { color: var(--red-ink); background: var(--red); border-radius: 4px; padding: 0 .22em; margin: 0 -.05em; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.msg.own .bubble .mention { color: inherit; text-decoration: underline 2px; text-underline-offset: .18em; }
.msg.own .bubble .mention.me { color: var(--red); background: var(--red-ink); text-decoration: none; }
.msg.at-me:not(.own) .bubble:not(.big) { box-shadow: 0 0 0 2px var(--red); }
.composer { position: relative; }
.mention-bar { position: absolute; left: 0; right: 0; bottom: 100%; z-index: 3; display: flex; gap: 6px; padding: 6px 12px; background: var(--wall); overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.mention-bar::-webkit-scrollbar { display: none; }
.mpick { flex: none; display: flex; align-items: center; gap: 7px; min-height: 44px; padding: 3px 14px 3px 4px; border: 1.5px solid var(--rule); border-radius: 22px; background: var(--paper); color: var(--c, var(--ink)); font: inherit; font-size: 16px; font-weight: 700; -webkit-tap-highlight-color: transparent; }
.mpick:first-child { border-color: var(--red); }
.mpick .mp-face { width: 34px; height: 34px; display: grid; place-items: center; }
.mpick .mp-face .mface, .mpick .mp-face svg { display: block; width: 100%; height: 100%; }
.mpick.all { color: var(--ink); }
.mpick.all .mp-face { font-size: 22px; line-height: 1; color: var(--red); }
.mpick:not(.here):not(.all) .mp-face { opacity: .55; } /* away */

/* ---------- replies (member request, from 🅱️chat) ----------
   Swipe a message right: it follows the finger and a round reply button slides in from the edge, pale while you pull,
   red once letting go would start the reply. A reply carries the quote as a slip tinted with the original author's
   colour, tucked behind the top of its bubble: their Bii head, name and one line of their words. The composer shows
   the same slip above the field while you write, with an x to drop it. */
.messages { overflow-x: hidden; }
/* the chat's who's-here row (🅱️chat's): a quiet row under the composer on the chat's white, a hairline above; it holds
   the bottom safe area while the keyboard is down and is gone while it's up, so the composer sits on the keys */
.chat > .here { position: relative; z-index: 1; flex: none; display: flex; gap: 4px; padding: 6px 10px calc(4px + var(--sab)); overflow-x: auto;
  overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; border-top: 1px solid var(--rule); background: #fff; }
.chat > .here::-webkit-scrollbar { display: none; }
.chat > .composer:has(+ .here) { padding-bottom: 8px; }
.kb-open .chat > .here { display: none; }
.chat > .jump { bottom: calc(80px + var(--chat-here-h, 0px)); }
.kb-open .chat > .jump { bottom: 80px; }
#list .msg[data-id] { touch-action: pan-y; }
.msg.swiping, .msg.swipe-back { position: relative; transform: translateX(var(--sx, 0px)); }
.msg.swipe-back { transition: transform .24s cubic-bezier(.25, 1.2, .4, 1); }
.swipe-arrow {
  position: absolute; left: -46px; top: 50%; width: 34px; height: 34px; margin-top: -17px; display: grid; place-items: center;
  border-radius: 50%; background: var(--paper); color: var(--red); opacity: var(--sk, 0); transform: scale(calc(.5 + .5 * var(--sk, 0)));
  transition: background-color .12s, color .12s; pointer-events: none;
}
.swipe-arrow svg { width: 19px; height: 19px; }
.swipe-arrow.armed { background: var(--red); color: var(--red-ink); }

.msg.has-rq { margin-top: 12px; }
.msg .bubble { position: relative; z-index: 1; }
.rq, .rb-q {
  position: relative; display: flex; align-items: center; gap: 7px; min-width: 0; border: 0; text-align: left; cursor: pointer;
  background: color-mix(in oklab, var(--rc, var(--ink-3)) 13%, var(--paper)); color: var(--ink-2); font: 14px/1.3 var(--font);
  -webkit-tap-highlight-color: transparent; overflow: hidden;
}
.rq::before, .rb-q::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--rc, var(--ink-3)); }
.msg .rq { max-width: min(76%, 440px); margin: 0 0 -8px; padding: 5px 12px 13px 10px; border-radius: 10px 10px 0 0; }
.msg .rq::before { bottom: 8px; }
.msg.own .rq { margin-right: 6px; }
.msg:not(.own) .rq { margin-left: 6px; }
.rq-face { flex: none; width: 24px; height: 24px; }
.rq-face .mface { display: block; width: 100%; height: 100%; margin: 0; }
.rq-face .mface svg { display: block; width: 100%; height: 100%; }
.rq-txt { display: flex; flex-direction: column; min-width: 0; }
.rq-txt b { font-size: 13px; font-weight: 700; color: color-mix(in oklab, var(--rc, var(--ink-2)) 70%, var(--ink)); }
.rq-txt > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg.rq-ring .bubble { animation: rq-ring 1.7s ease both; }
@keyframes rq-ring { 0%, 55% { outline: 3px solid var(--red); outline-offset: 3px; } 100% { outline: 3px solid transparent; outline-offset: 3px; } }

.composer.replying { flex-wrap: wrap; row-gap: 6px; }
.reply-bar { order: -1; flex: 0 0 100%; display: flex; min-width: 0; border-radius: 10px; overflow: hidden; }
.rb-q { flex: 1; padding: 6px 10px 6px 13px; min-height: 44px; }
.rb-q .rq-face { width: 30px; height: 30px; }
.rb-to { font-size: 13px; }
.rb-to b { color: color-mix(in oklab, var(--rc, var(--ink-2)) 70%, var(--ink)); }
.rb-x { flex: none; width: 44px; border: 0; display: grid; place-items: center; background: color-mix(in oklab, var(--rc, var(--ink-3)) 13%, var(--paper)); color: var(--ink-2); cursor: pointer; }
.rb-x svg { width: 18px; height: 18px; }
