/*
 * Rooftop - the interface.
 *
 * Everything here sits over a night scene, so it is built from smoked glass and
 * one warm accent: the colour of a lit cigarette. Nothing is a solid panel; a
 * heavy opaque HUD over a view is the fastest way to make a beautiful place
 * feel like a menu.
 */
:root {
  --ember: #ff7a3d;
  --ember-soft: #ffb27a;
  --ink: #e9e7e2;
  --dim: #a09a92;
  --glass: rgba(16, 16, 20, 0.42);
  --edge: rgba(255, 255, 255, 0.10);
  --font: ui-sans-serif, -apple-system, "Segoe UI", Inter, system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; height: 100%; overflow: hidden; background: #05070c;
  color: var(--ink); font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

#view { display: block; position: fixed; inset: 0; width: 100%; height: 100%; }

#hud {
  position: fixed; inset: 0; pointer-events: none;
  font-size: 13px; letter-spacing: 0.01em;
  opacity: 0; transition: opacity .9s ease .3s;
}
body.playing #hud { opacity: 1; }

/* ------------------------------------------------------------ top left */
/* The bar, and the microphone beside it. Three buttons in one pill, hairlines
   between them, so the corner reads as one thing rather than as four things
   that happen to be near each other. */
#topleft { position: absolute; top: 18px; left: 20px; height: 38px; display: flex; align-items: center; gap: 10px; }

#topbar {
  display: flex; align-items: stretch; height: 38px; pointer-events: auto;
  background: rgba(30, 20, 14, .6); border: 1px solid rgba(255, 140, 80, .5); border-radius: 999px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 6px 26px rgba(0, 0, 0, .45), 0 0 24px rgba(255, 122, 61, .15);
}
#topbar > .mwrap { position: relative; display: flex; }
#topbar button {
  appearance: none; cursor: pointer; font: inherit; font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink);
  background: transparent; border: 0; border-radius: 999px;
  padding: 0 14px; display: flex; align-items: center; gap: 8px;
  transition: color .18s, background .18s;
}
#topbar button[hidden] { display: none; }
#topbar button svg { flex: none; color: var(--ember-soft); transition: color .18s; }
#topbar button:hover { color: #fff; background: rgba(255, 140, 80, .13); }
#topbar button:hover svg { color: var(--ember); }
/* The hairlines: one before every part of the bar that has a showing part
   before it, so a roof with no shop has no line hanging off its end. */
#topbar > *:not([hidden]) ~ *:not([hidden]) { position: relative; }
#topbar > *:not([hidden]) ~ *:not([hidden])::before {
  content: ''; position: absolute; left: 0; top: 9px; bottom: 9px; width: 1px;
  background: rgba(255, 140, 80, .28); pointer-events: none;
}
/* The middle button, while its list is down, and either of the two items that
   have a panel of their own open. */
#menuBtn.on, body.settings #settingsBtn, body.room #roomBtn { color: #fff; background: rgba(255, 140, 80, .18); }
#menuBtn.on svg, body.settings #settingsBtn svg, body.room #roomBtn svg { color: var(--ember); }

/* What is behind Menu: Home first, then the link, the room's controls,
   the settings. */
#topMenu {
  position: absolute; left: 0; top: calc(100% + 8px); z-index: 6; min-width: 208px;
  display: flex; flex-direction: column; padding: 6px; pointer-events: auto;
  background: rgba(14, 14, 18, .82); border: 1px solid var(--edge); border-radius: 14px;
  backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .6);
}
#topMenu[hidden] { display: none; }
#topMenu button {
  display: flex; align-items: center; gap: 11px; text-align: left; white-space: nowrap;
  padding: 10px 12px; border-radius: 9px;
  font-size: 12.5px; letter-spacing: .02em; text-transform: none; color: var(--ink);
}
#topMenu button:hover { background: rgba(255, 255, 255, .08); }
#topMenu #inviteBtn.done, #topMenu #inviteBtn.done svg { color: var(--ember-soft); }
/* Home is the way off the roof, not one of the room's own things: a
   hairline under it says so without a second heading. */
#topMenu #homeBtn { margin-bottom: 5px; padding-bottom: 12px; border-bottom: 1px solid var(--edge); border-radius: 9px 9px 0 0; }

/* The shop, at the end of the bar: amber as the wallet runs down, red when
   it is out (tokens.js). Hidden where nothing is charged for. */
#shopBtn.low, #shopBtn.low svg { color: var(--ember-soft); }
#shopBtn.out, #shopBtn.out svg { color: #e2685a; }
#shopBtn.out:hover { background: rgba(226, 104, 90, .16); }
/* Narrow: the bar keeps its shapes and drops its words. The list behind
   Menu is where the words are, and it keeps them. */
@media (max-width: 620px) {
  #topbar > button > span, #topbar > .mwrap > button > span { display: none; }
  #topbar button { padding: 0 12px; }
}

/* ----------------------------------------------------------- top right */
/* Who is up here, under the connection dot, names flush to the edge. */
#topright { position: absolute; top: 44px; right: 18px; }
/* The names take the mouse (the rest of the HUD does not): a click on one
   opens their card. The pill a row lights up as hangs off both edges, so
   the names themselves stay flush against the right of the screen, and the
   scrollbar, when there is one, sits in the padding rather than pushing
   them in. A roof of twenty-odd runs off the bottom otherwise, so the list
   scrolls where it has to; the count over it (#roomWho) does not move. */
#roster {
  display: flex; flex-direction: column; gap: 3px; align-items: flex-end;
  pointer-events: auto;
  max-height: calc(100vh - 200px); overflow-y: auto; overscroll-behavior: contain;
  margin-right: -6px; padding: 2px 6px;
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .16) transparent;
}
#roster::-webkit-scrollbar { width: 6px; }
#roster::-webkit-scrollbar-track { background: transparent; }
#roster::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: 3px; }
#roster::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .3); }
/* ------------------------------------------------------- the account bar */
/* Yours, not the room's: what is left in the wallet, and the account it
   hangs on. Two pills the same size and glass as the bar top left - the
   same height, type and ember edge, so the two corners answer each other -
   at the very top of this column, straight under the build stamp, and over
   the roof's own line so the corner reads down from you to the room to the
   people in it. Both take the mouse; the rest of this corner, apart from
   the names, does not. */
#account {
  position: relative;
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  margin-bottom: 9px; pointer-events: auto;
}
#account button {
  appearance: none; cursor: pointer; font: inherit; font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink);
  background: rgba(30, 20, 14, .6); border: 1px solid rgba(255, 140, 80, .5); border-radius: 999px;
  padding: 0 14px; height: 38px; display: flex; align-items: center; gap: 8px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 6px 26px rgba(0, 0, 0, .45), 0 0 24px rgba(255, 122, 61, .15);
  transition: color .18s, background .18s, border-color .18s;
}
#account[hidden], #account button[hidden] { display: none; }
#account button:hover { color: #fff; background: rgba(255, 140, 80, .16); border-color: rgba(255, 140, 80, .8); }

/* The balance. The number is the only part that is not small grey type,
   and it is tabular so a counter running from 3,600 to 3,540 does not
   shuffle the word beside it left and right while it runs. */
#walletChip { position: relative; }
#walletNum { color: var(--ink); font-size: 13px; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
#walletChip .lb { font-size: 10px; letter-spacing: .16em; color: rgba(160, 154, 146, .8); }
#walletChip.low #walletNum { color: var(--ember-soft); }
#walletChip.out #walletNum { color: #e2685a; }
/* What just changed, floating off the top of the number and fading as it
   goes. It is out of the flow: the pill must not change width because a
   turn was paid for. */
#walletDelta {
  position: absolute; right: 10px; bottom: 100%; margin-bottom: 1px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 1px;
  pointer-events: none;
}
#walletDelta b {
  font-weight: 600; font-size: 11px; letter-spacing: .06em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .85);
  animation: walletFloat 1.5s ease-out forwards;
}
#walletDelta b.up, #goldDelta b.up { color: #7ee787; }
#walletDelta b.down, #goldDelta b.down { color: #e2685a; }
/* Gold: the same pill, the same counter, one colour apart. It never goes
   amber or red - gold running low is not a thing that stops working the
   way an empty credit balance is - so it has no `.low` and no `.out`. */
#goldChip { position: relative; }
#goldNum { color: #e8c67a; font-size: 13px; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
#goldChip .lb { font-size: 10px; letter-spacing: .16em; color: rgba(232, 198, 122, .55); }
#goldDelta {
  position: absolute; right: 10px; bottom: 100%; margin-bottom: 1px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 1px;
  pointer-events: none;
}
#goldDelta b {
  font-weight: 600; font-size: 11px; letter-spacing: .06em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .85);
  animation: walletFloat 1.5s ease-out forwards;
}
@keyframes walletFloat {
  0% { opacity: 0; transform: translateY(6px); }
  18% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-14px); }
}
/* Somebody who has asked for less movement still gets the number: it sits
   still for a moment and fades, over the same second and a half, because
   the line is swept up when that is over. */
@media (prefers-reduced-motion: reduce) {
  @keyframes walletFloat { 0%, 70% { opacity: 1; transform: none; } 100% { opacity: 0; transform: none; } }
}

/* The account. Signed in, it is the handle and the little picture that
   comes with it; signed out, it is the one word that does anything. A
   handle is a name and is written the way its owner writes it: the small
   capitals the rest of the bar is set in would turn @bboym0dE into a
   shout. */
/* Your account, under your own name: the list behind Menu in glass, hung
   off the right edge because that is the edge the badge sits on. It is
   inside #account, so the pill rules above reach it - each item says so
   again, the way #topMenu's do over the top bar's buttons. */
#accountMenu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 6; min-width: 176px;
  display: flex; flex-direction: column; padding: 6px;
  background: rgba(14, 14, 18, .82); border: 1px solid var(--edge); border-radius: 14px;
  backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .6);
}
#accountMenu[hidden] { display: none; }
#account #accountMenu button {
  display: block; width: 100%; height: auto; text-align: left; white-space: nowrap;
  padding: 9px 12px; border: 0; border-radius: 9px; background: none;
  font-size: 12.5px; letter-spacing: .02em; text-transform: none; color: var(--ink);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
#account #accountMenu button:hover { background: rgba(255, 255, 255, .08); border-color: transparent; }
/* The way out of the account, not one of the things you do inside it. */
#account #accountMenu #accOutBtn {
  margin-top: 5px; padding-top: 11px;
  border-top: 1px solid var(--edge); border-radius: 0 0 9px 9px; color: var(--dim);
}
#account #accountMenu #accOutBtn:hover { color: #e2685a; background: rgba(226, 104, 90, .14); }

#account #loginChip { text-transform: none; letter-spacing: .02em; font-size: 13px; }
#loginChip img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; margin-left: -5px; }
#loginChip.in { color: var(--ink); }
#loginChip.out { color: var(--ember-soft); border-color: rgba(255, 140, 80, .45); }

/* The roof itself, over the roster: what it is called, and the frame rate. */
#roominfo {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px; margin-bottom: 8px;
  color: var(--dim); font-size: 11.5px; text-shadow: 0 1px 8px rgba(0, 0, 0, .85);
}
#roomTitle { color: var(--ink); font-size: 13px; letter-spacing: .04em; max-width: 220px; text-align: right; }
#roomTitle[hidden] { display: none; }
#roominfo, #roominfo > div { line-height: 1.25; }
/* The hour running out on a meeting: an ember-coloured line that only
   shows near the end (hud.js), and turns red for the last minute. */
#roomEnds { font-size: 11px; letter-spacing: .04em; color: var(--ember-soft); font-variant-numeric: tabular-nums; }
#roomEnds[hidden] { display: none; }
#roomEnds.soon { color: #e2685a; }
#roomFps { font-size: 10.5px; letter-spacing: .12em; font-variant-numeric: tabular-nums; color: rgba(160, 154, 146, .7); }
/* Which build you are looking at, after the rate. Dim, but there: "it looks
   the same to me" and "you have not reloaded yet" look alike otherwise. */
#buildStamp { color: rgba(160, 154, 146, .45); letter-spacing: .08em; text-transform: uppercase; }
#fpsLine:not(:empty) + #buildStamp:not(:empty)::before { content: '\00b7'; margin: 0 .45em; }
/* How many people are up here, heading the names. */
#roomWho { margin-top: 4px; font-size: 11px; letter-spacing: .06em; color: rgba(160, 154, 146, .85); }
.who {
  display: flex; align-items: center; gap: 7px;
  color: var(--dim); font-size: 12.5px;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .85);
  padding: 1px 6px; margin: 0 -6px; border-radius: 5px; cursor: pointer;
}
.who:hover { background: rgba(255, 255, 255, .09); color: var(--ink); }
.who.me { color: var(--ink); }
.who i { width: 6px; height: 6px; border-radius: 50%; display: block; }
.who em { font-style: normal; color: rgba(255, 178, 122, .65); font-size: 11px; }
.who.muted { opacity: .5; }
.who.muted em { color: rgba(160, 154, 146, .7); text-decoration: line-through; }
.who.away { opacity: .45; }
.who.away em { color: rgba(160, 154, 146, .7); }

/* ---------------------------------------------------------------- feed */
#feed {
  position: absolute; top: 18px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.ev {
  font-size: 12.5px; color: rgba(255, 210, 180, .9);
  text-shadow: 0 1px 10px rgba(0, 0, 0, .9);
  transition: opacity .4s linear;
}

/* ------------------------------------------------------------- reticle */
#reticle {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 46px; height: 46px; display: grid; place-items: center;
  opacity: 0; transition: opacity .25s ease;
}
body.aiming #reticle,
body.beinglit #reticle { opacity: 1; }
#reticle::after {
  content: ''; width: 3px; height: 3px; border-radius: 50%;
  background: var(--ember-soft); box-shadow: 0 0 8px var(--ember);
}
#aimRing {
  --p: 0;
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--ember) calc(var(--p) * 360deg), rgba(255, 255, 255, .13) 0);
  -webkit-mask: radial-gradient(circle, transparent 61%, #000 63%);
  mask: radial-gradient(circle, transparent 61%, #000 63%);
  transition: none;
}
#aimLabel {
  position: absolute; top: 52px; white-space: nowrap; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--ember-soft);
  text-shadow: 0 1px 8px #000;
}

/* --------------------------------------------------------------- lungs */
/* A drag, made visible: the lobes fill from the bottom while the button is
   held and empty again when it is let go. Bottom centre, above the hands,
   and faded away entirely unless a breath is actually going in or out. */
#lungs {
  /* Above the hand squares, not on them: the tallest square - a shape, its
     caption and two lines under it - reaches about 165px up from the
     bottom edge with the hints under it, so this clears it by a margin. */
  position: absolute; left: 50%; bottom: 204px; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  opacity: 0; transition: opacity .35s ease; pointer-events: none;
}
#lungs.on { opacity: 1; }
#lungs svg { overflow: visible; filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .8)); }
#lungBody { transform-origin: 60px 42px; transform: scale(var(--breath, 1)); }
#lungs .outline .lobe { fill: rgba(16, 16, 20, .38); stroke: rgba(233, 231, 226, .55); stroke-width: 1.6; }
#lungs .air .lobe { fill: var(--ember-soft); fill-opacity: .82; stroke: none; }
#lungs.full .air .lobe { fill: var(--ember); }
#lungs.cough #lungBody { animation: cough .32s ease-in-out 2; }
#lungLabel {
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ember-soft); text-shadow: 0 1px 8px #000; white-space: nowrap; min-height: 14px;
}
#lungs.cough #lungLabel { color: var(--ember); }
@keyframes cough {
  0%, 100% { transform: scale(var(--breath, 1)); }
  50% { transform: scale(calc(var(--breath, 1) * .93)) translateY(2px); }
}

/* ----------------------------------------------------------- crosshair */
/* Always there, barely: a dot in the middle of the view. It brightens on a
   person or a seat and says what E does about them. Below the flame reticle
   in weight, and hidden while that one is doing its job. */
#xhair {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 0; height: 0; display: grid; place-items: center;
  opacity: .8; transition: opacity .2s;
}
#xhair i {
  position: absolute; width: 4px; height: 4px; border-radius: 50%;
  background: rgba(233, 231, 226, .55); box-shadow: 0 0 6px rgba(0, 0, 0, .8);
  transition: transform .15s, background .15s, box-shadow .15s;
}
/* ?flat=1 (boot.js): no frosted glass anywhere, for measuring what it costs */
body.flat * { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
#xhair.on i { background: var(--ember-soft); box-shadow: 0 0 10px var(--ember), 0 0 2px #000; transform: scale(1.4); }
#xhair.seat i { background: rgba(233, 231, 226, .95); box-shadow: 0 0 10px rgba(255, 255, 255, .5), 0 0 2px #000; }
#xhairLabel {
  position: absolute; top: 16px; white-space: nowrap; appearance: none; border: none;
  font: inherit; font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink); text-shadow: 0 1px 8px #000; background: none; padding: 0;
  opacity: 0; transition: opacity .15s; pointer-events: none; cursor: default;
}
#xhair.on #xhairLabel { opacity: 1; }
#xhairLabel b { color: var(--ember); font-weight: 600; margin-right: 6px;
  border: 1px solid rgba(255, 122, 61, .45); border-radius: 5px; padding: 1px 5px; font-size: 10px; }
body.aiming #xhair, body.beinglit #xhair, body.profile #xhair, body.settings #xhair, body.help #xhair, body.chatting #xhair { opacity: 0; }
/* On a phone the label is the button. Big enough for a thumb, and only
   while there is something under it, so a tap on empty sky still looks. */
body.touch #xhair.on #xhairLabel {
  pointer-events: auto; cursor: pointer; top: 18px;
  padding: 9px 14px; border-radius: 999px; background: var(--glass); border: 1px solid rgba(255, 140, 80, .5);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); font-size: 12px;
}
body.touch #xhair.on #xhairLabel:active { transform: translateY(1px); }

/* ------------------------------------------------------------- notices */
/* Somebody you asked about came out. A line with their picture, under the
   feed, gone in a few seconds; the feed keeps the words. */
#notices {
  position: absolute; top: 56px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.notice {
  display: flex; align-items: center; gap: 9px; padding: 7px 14px 7px 8px;
  background: rgba(30, 20, 14, .6); border: 1px solid rgba(255, 140, 80, .5); border-radius: 999px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  color: var(--ink); font-size: 12.5px; white-space: nowrap;
  box-shadow: 0 6px 26px rgba(0, 0, 0, .45), 0 0 24px rgba(255, 122, 61, .15);
  transition: opacity .3s linear;
}
.notice img, .notice i { width: 22px; height: 22px; border-radius: 50%; display: block; object-fit: cover; }
.notice i { background: var(--ember); box-shadow: 0 0 10px var(--ember); }

/* ------------------------------------------------------------- profile */
/* Somebody's card. One sheet of glass in the middle, over a dimmed roof. */
#profile, #banner, #mintbox, #pool, #wallet {
  position: fixed; inset: 0; display: grid; place-items: center; padding: 20px;
  background: rgba(3, 4, 8, .45); pointer-events: none; opacity: 0;
  transition: opacity .18s ease; z-index: 6;
}
#profile.open, #banner.open, #mintbox.open, #pool.open, #wallet.open { opacity: 1; pointer-events: auto; }
/* The wallet's card is the one of these that opens over the FRONT page as
   well as over the roof: Customize under the figure opens its wardrobe
   (js/gatefigure.js), and the gate is z-index 10. In a room it goes back
   to sitting with the others, under the microphone card. */
body:not(.playing) #wallet { z-index: 13; }
.pcard {
  position: relative; width: min(360px, 100%); padding: 18px 20px 16px;
  background: rgba(14, 14, 18, .8); border: 1px solid var(--edge); border-radius: 18px;
  backdrop-filter: blur(24px) saturate(1.3); -webkit-backdrop-filter: blur(24px) saturate(1.3);
  box-shadow: 0 24px 80px rgba(0, 0, 0, .6);
  transform: translateY(6px) scale(.98); transition: transform .18s ease;
  font-size: 13px; color: var(--ink);
}
#profile.open .pcard, #banner.open .pcard, #mintbox.open .pcard, #pool.open .pcard, #wallet.open .pcard { transform: none; }
/* The pool table's card: the guests, one row each with a button. */
#pool .pactions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 6px; }
#pool .pguests { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--edge); }
#pool .pguests h3 { margin: 0 0 6px; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--dim); font-weight: 600; }
#pool .pguests .row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 3px 0; }
#pool .pguests .who { font-size: 13px; }
#pool .pguests .btn { padding: 5px 10px; font-size: 12px; }
/* The blackjack table has no card. It is played by looking at the felt
   (blackjack.js), and this is the one strip that tells a seated player the
   two numbers they cannot read off two centimetres of card: what the
   dealer is showing, and what they are holding. It sits over the hands,
   out of the way of the table itself. */
#bjbar {
  display: flex; align-items: center; gap: 18px; margin: 0 auto 10px; padding: 7px 16px;
  background: rgba(28, 12, 16, .62); border: 1px solid rgba(233, 220, 196, .22); border-radius: 999px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 8px 30px rgba(0, 0, 0, .5);
  font-size: 12.5px; color: var(--ink); white-space: nowrap; pointer-events: none;
}
/* The `display` above outranks the browser's own `[hidden] { display: none }`,
   so without this the empty strip is drawn over the hands at every moment
   nobody is sitting at the table - a small blank pill above the right hand. */
#bjbar[hidden] { display: none; }
#bjbar .ph { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--dim); }
#bjbar .ph b { color: rgba(255, 178, 122, .95); letter-spacing: 0; font-size: 12.5px; }
#bjbar .v { display: flex; align-items: baseline; gap: 6px; font-weight: 600; }
#bjbar .v i { font-style: normal; font-weight: 400; font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dim); }
#bjbar .v.me { color: rgba(255, 178, 122, .95); }
#xhair.pool i { background: transparent; border: 1.5px solid #6fd39a; width: 9px; height: 9px; border-radius: 2px; box-shadow: 0 0 8px rgba(111, 211, 154, .6); }
body.pool #xhair { opacity: 0; }
/* The mint card: a wallet's icon or initial on its button, and the quantity. */
.pcard .btn img, .pcard .btn .wi { width: 24px; height: 24px; border-radius: 6px; flex: none; }
.pcard .btn .wi { display: grid; place-items: center; font-style: normal; font-size: 12px; font-weight: 600; color: var(--ember-soft); background: rgba(255, 178, 122, .16); }
/* The list of spaces still for sale, when the card is opened without one. */
.mlist {
  display: flex; flex-direction: column; gap: 4px; max-height: min(40vh, 320px); overflow: auto;
  margin: 0 0 8px; padding-right: 4px; overscroll-behavior: contain;
}
.mlist button {
  appearance: none; font: inherit; text-align: left; cursor: pointer; color: var(--ink);
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: 9px;
  background: rgba(255, 255, 255, .04); border: 1px solid transparent;
}
.mlist button:hover { border-color: rgba(255, 140, 80, .5); background: rgba(255, 140, 80, .08); }
.mlist button b { font-weight: 600; font-size: 13px; }
.mlist button span { font-size: 11.5px; color: var(--dim); }
.pcounts .lnk { margin-left: auto; }
.mtiers { display: flex; flex-wrap: wrap; gap: 5px; margin: 0 0 8px; }
.mtiers button {
  appearance: none; font: inherit; cursor: pointer; color: var(--dim); font-size: 11px; letter-spacing: .06em;
  padding: 4px 9px; border-radius: 999px; background: rgba(255, 255, 255, .05); border: 1px solid transparent;
}
.mtiers button span { color: rgba(255, 178, 122, .8); }
.mtiers button:hover { border-color: rgba(255, 140, 80, .4); }
.mtiers button.on { color: var(--ink); border-color: rgba(255, 140, 80, .7); background: rgba(255, 140, 80, .12); }
/* An advert's card: the same glass, a teal mark instead of a face, and the
   picture that is up on it if there is one. */
.phead i.ad { border-radius: 8px; background: linear-gradient(160deg, #1ee8d2, #0a6a60); }
.bpic { margin: 0 0 12px; border-radius: 10px; overflow: hidden; border: 1px solid var(--edge); background: #000; }
.bpic img { display: block; width: 100%; max-height: 180px; object-fit: contain; }
#xhair.banner i { background: #1ee8d2; box-shadow: 0 0 10px rgba(30, 232, 210, .7), 0 0 2px #000; }
/* An object within reach: a ring rather than a dot, the shape of a hand about to close. */
#xhair.prop i { background: transparent; border: 1.5px solid var(--ember-soft); width: 9px; height: 9px;
  box-shadow: 0 0 8px rgba(255, 122, 61, .6), 0 0 2px #000; }
.pcard .x {
  position: absolute; top: 10px; right: 12px; appearance: none; background: none; border: none;
  color: var(--dim); cursor: pointer; font: inherit; font-size: 22px; line-height: 1; padding: 4px 6px;
}
.pcard .x:hover { color: var(--ink); }
.phead { display: flex; align-items: center; gap: 13px; margin-bottom: 8px; padding-right: 28px; }
.phead img, .phead i {
  width: 48px; height: 48px; border-radius: 50%; display: block; object-fit: cover; flex: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .1), 0 6px 20px rgba(0, 0, 0, .5);
}
.phead div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.phead b { font-size: 17px; font-weight: 600; letter-spacing: .01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.phead span { font-size: 12px; color: rgba(255, 178, 122, .85); }
/* The name row: the name, and for somebody from X the mark that opens them there. */
.phead .pname { flex-direction: row; align-items: center; gap: 8px; }
.phead .pname b { min-width: 0; }
.phead .xgo {
  display: grid; place-items: center; flex: none; width: 24px; height: 24px; border-radius: 50%;
  color: var(--ink); background: rgba(255, 255, 255, .08); border: 1px solid rgba(255, 255, 255, .12);
  text-decoration: none;
}
.phead .xgo:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .3); }
.phead span.dim { color: var(--dim); }
.pstate { font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--dim); margin-bottom: 12px; }
.pcounts { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; font-size: 12.5px; color: var(--dim); margin-bottom: 12px; }
.pcounts b { color: var(--ink); font-weight: 600; }
.pcounts em {
  font-style: normal; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ember-soft); border: 1px solid rgba(255, 140, 80, .4); border-radius: 999px; padding: 2px 8px;
}
.pcounts em.friend { background: rgba(60, 34, 20, .6); border-color: rgba(255, 140, 80, .7); }
.pactions { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 8px; }
.pcard .btn {
  appearance: none; cursor: pointer; font: inherit; font-size: 13px; color: var(--ink);
  background: rgba(255, 255, 255, .06); border: 1px solid var(--edge); border-radius: 10px;
  padding: 10px 14px; text-align: left; transition: border-color .18s, background .18s;
  display: flex; align-items: center; gap: 10px;
}
.pcard .btn:hover { border-color: rgba(255, 140, 80, .5); }
.pcard .btn:disabled { opacity: .5; cursor: default; }
.pcard .btn.on {
  background: linear-gradient(180deg, rgba(70, 40, 24, .8), rgba(44, 24, 14, .8));
  border-color: rgba(255, 140, 80, .8); color: var(--ember-soft);
}
.pcard .btn.tog i {
  width: 28px; height: 16px; border-radius: 999px; background: rgba(255, 255, 255, .12); position: relative; flex: none;
  transition: background .18s;
}
.pcard .btn.tog i::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--dim); transition: transform .18s, background .18s;
}
.pcard .btn.tog.on i { background: rgba(255, 122, 61, .5); }
.pcard .btn.tog.on i::after { transform: translateX(12px); background: var(--ember-soft); box-shadow: 0 0 8px var(--ember); }
.pcard .fine { color: rgba(160, 154, 146, .75); font-size: 11.5px; line-height: 1.5; margin: 6px 0 0; }
.pcard .fine.warn { color: rgba(255, 178, 122, .85); }
.pcard .pmute, .pcard .phost { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--edge); }
.pcard .lnk {
  appearance: none; background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; font-size: inherit; color: rgba(255, 178, 122, .85); text-decoration: underline dotted;
}
body.profile { cursor: default; }
body.touch .pcard { padding: 16px 16px 14px; }

/* The wallet's card (tokens.js): the balance and the till across the top,
   then a grid of what is for sale behind the bar. What somebody already
   owns is not on it - a shop is not an inventory - and nothing is bought
   without the sheet over the card asking first. */
#wallet .pcard { width: min(460px, 100%); }
/* The shelf and the wardrobe are long - fifty things and a hundred and
   ten - so the card is given a ceiling and scrolls inside it rather than
   running off the top and bottom of the screen. The head and the tabs
   scroll with it: what is wanted is a sheet of paper you can run your eye
   down, not a pane with a list bolted into the middle of it. */
/* ONE size for every page behind the tabs. The shop was 560 and the
   character pages 880, and the card changed size under the pointer on
   every tab, which is the sort of thing people notice first. */
#wallet[data-mode="wallet"] .pcard, #wallet[data-mode="shop"] .pcard, #wallet[data-mode="wear"] .pcard,
#wallet[data-mode="kind"] .pcard, #wallet[data-mode="awards"] .pcard {
  width: min(880px, 100%); height: min(88vh, 740px); overflow-y: auto;
  overscroll-behavior: contain;
}
/* The confirmation covers the card it was asked from, and a card that
   scrolls would otherwise leave it pinned to the top of a long page. */
#wallet[data-mode="shop"] .pcard:has(.tconf),
#wallet[data-mode="wear"] .pcard:has(.tconf) { overflow: hidden; }
/* The sign-in stack. A <button> shrinks to its own words even as a flex
   box, so without a width these come out three different lengths under a
   card that is left-aligned everywhere else; with one, the icons make a
   column and so do the labels. */
#wallet .pcard .btn { width: 100%; margin-top: 8px; }
#wallet .pcard .btn.buy { border-color: rgba(255, 140, 80, .55); color: var(--ember-soft); }
.thead { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 2px; }
/* The balance is two lines and one left edge. The number and the word
   `tokens` share a baseline; what the balance is worth in time goes under
   both of them and starts where the number starts - hung off the end of
   the word instead, it moves with every digit the balance gains or loses
   and the head of the card reads as a staircase. */
.thead .tbal { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.thead .tnum { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
/* The second balance. Smaller than the first, because credits are what
   runs out while you are standing there and gold is what you have; and
   gold-coloured, which is the one place on the card that colour means
   "this is the other currency" rather than "this is a price". */
.thead .tnum.gold { margin-top: -2px; }
.thead .tnum.gold .tk { font-size: 19px; color: #e8c67a; }
.thead .tnum.gold .lb { color: rgba(232, 198, 122, .6); }
.thead .tk {
  font-size: 30px; font-weight: 600; line-height: 1; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.thead .lb { font-size: 11px; line-height: 1; letter-spacing: .18em; text-transform: uppercase; color: var(--dim); }
.thead .tsub { font-size: 10.5px; line-height: 1.35; letter-spacing: .02em; color: rgba(160, 154, 146, .7); }
/* The till, top right: the one thing on this card that costs money rather
   than tokens, so it is the only thing on it wearing the ember. */
.thead .tbuy {
  appearance: none; cursor: pointer; font: inherit; flex: none; margin-top: 1px;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 6px 12px; border-radius: 10px; font-size: 12px; color: var(--ink);
  background: rgba(255, 255, 255, .06); border: 1px solid var(--edge);
  transition: border-color .18s, background .18s;
}
.thead .tbuy small { font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: rgba(160, 154, 146, .7); }
.thead .tbuy.on { border-color: rgba(255, 140, 80, .55); color: var(--ember-soft); }
.thead .tbuy.on small { color: rgba(255, 178, 122, .8); }
.thead .tbuy.on:hover { background: rgba(255, 140, 80, .12); border-color: rgba(255, 140, 80, .8); }
.thead .tbuy:disabled { opacity: .45; cursor: default; }
#wallet .thead .x { position: static; flex: none; margin: -2px -4px 0 0; }
/* The login and shop cards open on a title where the tokens card opens on
   the balance: the same head, the same left edge, a word instead of a
   number. Data-mode is which card this is (tokens.js), for the tools. */
.thead .ttl { margin: 0; font-size: 17px; font-weight: 600; line-height: 1.2; letter-spacing: -.01em; color: var(--ink); }
#wallet[data-mode="login"] .pcard { width: min(360px, 100%); }
/* The ways in (money.js waysIn): the two accounts from elsewhere as a
   pair of buttons across the top, their marks and their words centred so
   the two read as one row; then "or"; then the account kept here as a
   form, whose one lit button is the Sign in. The same column the gate
   draws (#stepWho), on a card in front of the room instead of a page. */
.tways { display: flex; gap: 6px; margin-top: 8px; }
#wallet .tways .btn { flex: 1; margin-top: 0; justify-content: center; padding: 7px 10px; font-size: 12px; white-space: nowrap; }
.tways .mk { width: 14px; height: 14px; flex: none; }
.pcard .or {
  display: flex; align-items: center; gap: 10px; margin: 8px 0 6px;
  font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase; color: rgba(160, 154, 146, .5);
}
.pcard .or::before, .pcard .or::after { content: ''; flex: 1; height: 1px; background: var(--edge); }
/* Small on purpose: the whole column, marks to links, has to fit under
   the thing that was clicked without pushing the room out of the frame.
   The field names are the placeholders; the label's own words are kept
   off-screen (the usual one-pixel clip, which every reader still speaks)
   for the screen reader and the password manager. */
.tpw { display: flex; flex-direction: column; gap: 6px; margin: 0; text-align: left; }
.tpw label { display: flex; flex-direction: column; position: relative; }
.tpw label .sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.tpw input {
  font: inherit; font-size: 12.5px; letter-spacing: 0; text-transform: none; width: 100%; box-sizing: border-box;
  color: var(--ink); background: rgba(255, 255, 255, .045);
  border: 1px solid var(--edge); border-radius: 8px; padding: 7px 10px; outline: none;
  transition: border-color .2s;
}
.tpw input:focus { border-color: rgba(255, 140, 80, .55); }
.tpw input::placeholder { color: rgba(160, 154, 146, .5); }
#wallet .tpw .btn.go {
  margin-top: 2px; justify-content: center; padding: 8px 12px; font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
  color: #140d08; background: linear-gradient(180deg, var(--ember-soft), var(--ember)); border-color: transparent;
  box-shadow: 0 6px 24px rgba(255, 122, 61, .2);
}
#wallet .tpw .btn.go:hover { box-shadow: 0 8px 30px rgba(255, 122, 61, .32); }
#wallet .tpw .btn.go:disabled { box-shadow: none; }
.tpw .fine { margin: 0; font-size: 11px; }
.tpw .trow { display: flex; justify-content: space-between; gap: 12px; margin-top: 0; font-size: 11px; }
.tpw .trow .lnk { color: rgba(160, 154, 146, .8); text-decoration: none; }
.tpw .trow .lnk:hover { color: var(--ember-soft); }
/* The same column on the sheet over the shop (waySheet): a form the width
   of the whole shop is a form nobody can read, so it keeps to a narrow
   card in the middle of the sheet - narrower than the login card, since
   here it sits over a shelf the player was in the middle of reading. */
.tconf .cbox:has(.tpw) { max-width: 280px; }
.tconf .cbox:has(.tpw) p { margin-bottom: 8px; font-size: 13px; }
.tconf .cbox:has(.tpw) .fine { font-size: 11px; line-height: 1.4; }
.tconf .tpw + .crow { margin-top: 8px; justify-content: center; }
#wallet .tconf .tpw + .crow .btn {
  flex: none; width: auto; padding: 4px 10px; font-size: 11.5px;
  background: none; border-color: transparent; color: rgba(160, 154, 146, .8);
}
#wallet .tconf .tpw + .crow .btn:hover { color: var(--ember-soft); }
.tshop { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--edge); }
.tshop h3 {
  margin: 0 0 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ember-soft);
}
/* The shelf: one tile a thing, two across, and the whole tile is the button. */
.tgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.tgrid .titem {
  appearance: none; cursor: pointer; font: inherit; text-align: left; color: var(--ink);
  display: flex; flex-direction: column; gap: 2px; padding: 10px 12px 9px;
  border-radius: 12px; background: rgba(255, 255, 255, .04); border: 1px solid var(--edge);
  transition: border-color .18s, background .18s;
}
.tgrid .titem:hover:not(:disabled) { border-color: rgba(255, 140, 80, .6); background: rgba(255, 140, 80, .08); }
.tgrid .titem b { font-size: 13px; font-weight: 600; }
.tgrid .titem small { font-size: 10.5px; color: rgba(160, 154, 146, .7); }
/* The bottom line of a tile: a price, or the word for a thing that is
   already yours. `margin-top: auto` puts it on the floor of the tile and
   the tiles in a row are one height, so the row has one bottom line; and
   both are drawn on the strut of a 15px line rather than on their own
   text, so `OWNED` beside `250 TOKENS` sits on that same line and not a
   pixel or two above it. */
.tgrid .titem .p {
  margin-top: auto; padding-top: 6px; font-size: 15px; line-height: 18px;
  font-weight: 600; color: var(--ember-soft); font-variant-numeric: tabular-nums;
}
.tgrid .titem .p em {
  font-style: normal; font-size: 9.5px; font-weight: 500; letter-spacing: .14em;
  text-transform: uppercase; color: var(--dim); margin-left: 5px;
}
.tgrid .titem .p.own em { font-size: 11px; margin-left: 0; }
.tgrid .titem:disabled { cursor: default; }
.tgrid .titem.mine { opacity: .5; }
.tgrid .titem.poor .p { color: var(--dim); }
/* The confirmation, over the card it was asked from. */
/* Over everything the page drew, the shop's own pictures included: they
   are a canvas laid over the card (slots.js) and the card is what this
   covers. */
.tconf {
  position: absolute; inset: 0; z-index: 3; display: grid; place-items: center; padding: 18px;
  background: rgba(8, 8, 12, .86); border-radius: 18px;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.tconf .cbox { width: 100%; text-align: center; }
.tconf p { margin: 0 0 14px; font-size: 14px; line-height: 1.45; color: var(--ink); }
.tconf p b { font-weight: 600; color: var(--ember-soft); }
.tconf .crow { display: flex; gap: 8px; }
#wallet .tconf .crow .btn { flex: 1; width: auto; margin-top: 0; justify-content: center; }

/* ------------------------------------------------ the shop card's pages
   Wallet and Shop - the pages about buying, and only those. A card that
   is one of several has to say which several, or the other is a thing you
   have to already know is there. (Character is a card of its own since
   the shop came off it, and Achievements another, off Menu; neither wears
   a tab.) The row sits under the head and over everything the page
   draws, and it is the LOUD row: a lit pill, one per page. The shop's own
   row of shelves under it is deliberately none of those things. */
.ttabs { display: flex; gap: 4px; margin: 10px 0 2px; }
.ttabs .ttab {
  appearance: none; cursor: pointer; font: inherit; flex: 1;
  padding: 6px 10px; border-radius: 9px; font-size: 11.5px; letter-spacing: .04em;
  color: var(--dim); background: transparent; border: 1px solid transparent;
  transition: color .18s, background .18s, border-color .18s;
}
.ttabs .ttab:hover { color: var(--ink); background: rgba(255, 255, 255, .05); }
.ttabs .ttab.on {
  color: var(--ember-soft); background: rgba(255, 140, 80, .1);
  border-color: rgba(255, 140, 80, .45);
}

/* ------------------------------------------------------ the shop's shelves
   Which counter you are standing at: smokes, lighters, toys, the bar, the
   beach shop. This is the second row of tabs on the card and it must not
   read as a rival to the first, so it is quieter in every way one row can
   be quieter than another - smaller, spaced out, no box around a tab, and
   marked by an underline in the accent rather than by a lit pill. It
   scrolls sideways rather than wrapping, so a narrow card keeps one line
   of shelves and not three. */
.tshelves {
  display: flex; gap: 2px; margin: 12px 0 0; padding: 0 2px;
  overflow-x: auto; scrollbar-width: none; border-bottom: 1px solid var(--edge);
}
.tshelves::-webkit-scrollbar { display: none; }
/* ...except where the card is as wide as the screen, and one line of
   shelves would leave the last of them off the edge of a phone with
   nothing to say it was there: they wrap instead. */
@media (max-width: 560px) { .tshelves { flex-wrap: wrap; overflow-x: visible; } }
.tshelves .tsh {
  appearance: none; cursor: pointer; font: inherit; flex: none; white-space: nowrap;
  padding: 7px 9px 6px; margin-bottom: -1px; background: none; border: none;
  border-bottom: 2px solid transparent;
  font-size: 10.5px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--dim); transition: color .18s, border-color .18s;
}
.tshelves .tsh:hover { color: var(--ink); }
.tshelves .tsh.on { color: var(--ember-soft); border-bottom-color: rgba(255, 140, 80, .75); }
/* The shelf under it. Positioned, because slots.js lays its canvas over
   this box and over nothing else on the card; the canvas is the whole of
   the grid, with a scissor per tile. */
.tshelf { position: relative; margin-top: 12px; }
.tshelf .sview {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  pointer-events: none; z-index: 2;
}
/* The picture box, at the top of a tile: empty markup that slots.js draws
   the OBJECT into - the same meshes the world builds, turning slowly on a
   stage of their own. What is here is only the room it stands in: a pool
   of warm light under it, so a dark thing on dark glass has a floor. A
   thing the world makes no object for gets no box at all and keeps the
   plain tile it always had. */
.tgrid .titem .pic {
  flex: none; display: block; height: 72px; margin: -2px -4px 5px;
  border-radius: 10px;
  background: radial-gradient(58% 62% at 50% 64%, rgba(255, 178, 122, .11), rgba(255, 178, 122, 0) 72%);
}
.tgrid .titem:hover:not(:disabled) .pic {
  background: radial-gradient(58% 62% at 50% 64%, rgba(255, 178, 122, .18), rgba(255, 178, 122, 0) 72%);
}
/* A thing already owned is drawn at half strength with the rest of its
   tile, and the canvas is not part of the tile - so the dimming is done
   to the light it stands in instead. */
.tgrid .titem.mine .pic { background: none; }

/* ---------------------------------------------------------- the awards
   How many boxes are waiting, and the list that pays them. The strip at
   the top is the only thing on the page that does anything, so it is the
   only thing on it wearing the ember - and it wears it only when there is
   actually a box to open. */
.tboxes {
  display: flex; align-items: center; gap: 12px; margin-top: 12px;
  padding: 11px 14px; border-radius: 14px;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--edge);
}
.tboxes.some { background: rgba(255, 140, 80, .08); border-color: rgba(255, 140, 80, .45); }
.tboxes .bn {
  font-size: 28px; font-weight: 600; line-height: 1; color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.tboxes.some .bn { color: var(--ember-soft); }
.tboxes .bl {
  flex: 1; min-width: 0; font-size: 10.5px; line-height: 1.3; letter-spacing: .18em;
  text-transform: uppercase; color: var(--dim);
}
#wallet .tboxes .btn { width: auto; flex: none; margin-top: 0; padding: 8px 16px; }
/* One shelf of the list. The heading is the shop's, because it is the same
   card and the same kind of heading. */
.tawards { margin-top: 14px; }
.tawards h3 {
  margin: 0 0 2px; font-size: 10.5px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ember-soft);
}
.tawards ul { margin: 0; padding: 0; list-style: none; }
/* A line of it: the tick, what it is and what there is to do, and what it
   pays. The right-hand column answers one question, and which question
   depends on the tick - what do I get for this, or when did I get it. */
.awd {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 7px 0; border-top: 1px solid rgba(255, 255, 255, .05);
}
.awd .tk {
  flex: none; width: 17px; height: 17px; margin-top: 1px; border-radius: 50%;
  display: grid; place-items: center; font-size: 11px; line-height: 1;
  color: transparent; background: transparent; border: 1px solid rgba(255, 255, 255, .14);
}
.awd.got .tk { color: #14100c; background: var(--ember-soft); border-color: transparent; }
.awd .wt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.awd .wt b { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.awd .wt small { font-size: 10.5px; line-height: 1.4; color: rgba(160, 154, 146, .7); }
.awd .pay {
  flex: none; padding-top: 1px; font-size: 10.5px; letter-spacing: .04em;
  color: rgba(160, 154, 146, .55); text-align: right; white-space: nowrap;
}
.awd .pay.due { font-size: 14px; font-weight: 600; color: var(--ember-soft); font-variant-numeric: tabular-nums; }
.awd .pay.due em {
  font-style: normal; font-size: 9px; font-weight: 500; letter-spacing: .14em;
  text-transform: uppercase; color: var(--dim); margin-left: 4px;
}
/* Earned is the quiet state, not the loud one: the list is a list of
   things to go and do, and the ones that are done are behind you. */
.awd.got .wt b { color: rgba(230, 226, 220, .6); }
.awd.got .wt small { color: rgba(160, 154, 146, .45); }

/* A price says which coin it is in. Credits wear the ember the card has
   always used; gold wears gold. Two currencies on one tile that looked
   the same would be the single worst thing this card could do. */
.tgrid .titem .p.gold { color: #e8c67a; }
.tgrid .titem .p.gold em { color: rgba(232, 198, 122, .6); }
.tgrid .titem .p.money { font-size: 14px; color: var(--ember-soft); }
.tgrid.tpacks { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }

/* Rarity, as the left edge of a tile and nothing more: a stripe, not a
   background. A grid of fifty tiles each in its own colour is a fruit
   machine, and the thing being chosen is a coat. */
.tgrid .titem { border-left-width: 3px; }
.tgrid .titem.r-common { border-left-color: var(--edge); }
.tgrid .titem.r-uncommon { border-left-color: #5fae7e; }
.tgrid .titem.r-rare { border-left-color: #5b8fd6; }
.tgrid .titem.r-epic { border-left-color: #a274d8; }
.tgrid .titem.r-legendary { border-left-color: #e8c67a; }

/* -------------------------------------------------------- the melt
   Gold down into credits, and one way. The slider is the amount and the
   line under it is what comes out, written before anything is agreed to. */
.tmelt { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--edge); }
.tmelt h3 {
  margin: 0 0 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: #e8c67a;
}
.tmelt input[type="range"] { width: 100%; accent-color: #e8c67a; margin: 2px 0 4px; }
#wallet .tmelt .btn { width: auto; padding-inline: 18px; margin-top: 6px; }

/* ------------------------------------------------------- the wardrobe
   Nine slots, each a shelf of its own. The tiles are smaller than the
   shop's because there are a hundred of them and every one is two words. */
.wslot .tgrid { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 6px; }
.wslot .tgrid .titem { padding: 8px 10px 7px; }
.wslot .tgrid .titem b { font-size: 12px; }
.wslot .tgrid .titem .p { font-size: 12.5px; line-height: 15px; padding-top: 4px; }
.wslot .tgrid .titem.on {
  opacity: 1; border-color: rgba(255, 140, 80, .7); background: rgba(255, 140, 80, .12);
}
.wslot .tgrid .titem.mine:not(.on) { opacity: 1; }
.wslot .tgrid .titem.mine:not(.on) .p.own em { color: rgba(160, 154, 146, .55); }
/* The colour beside a slot, which is free and is therefore a row of
   swatches rather than a row of tiles with nothing written on them. */
.wtint { display: flex; flex-wrap: wrap; gap: 5px; margin: -2px 0 8px; }
.wtint .wsw {
  appearance: none; cursor: pointer; padding: 2px; line-height: 0;
  border-radius: 7px; background: transparent; border: 1px solid var(--edge);
}
.wtint .wsw.on { border-color: rgba(255, 140, 80, .8); }
.wtint .wsw .sw { display: block; width: 16px; height: 16px; border-radius: 5px; background: var(--sw, #6b6b72); }

/* ----------------------------------------------------- the loot box
   It arrives while somebody is standing in a room with people in it, so
   it takes the middle of the screen for a moment and gives it straight
   back: never modal, never in the way of walking, and it never takes the
   pointer. */
#loot {
  position: absolute; left: 50%; top: 38%; transform: translate(-50%, -50%);
  z-index: 40; pointer-events: auto; cursor: pointer;
  opacity: 0; transition: opacity .28s ease-out;
}
#loot.in { opacity: 1; }
#loot .lbox {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  min-width: 210px; padding: 16px 26px 15px; border-radius: 16px;
  background: rgba(8, 8, 12, .82); border: 1px solid var(--edge);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .55);
  animation: lootIn .5s cubic-bezier(.2, .9, .3, 1.2) both;
}
#loot .lcap {
  font-size: 9.5px; letter-spacing: .24em; text-transform: uppercase;
  color: var(--dim);
}
#loot .lbig {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 27px; font-weight: 600; line-height: 1.15; color: var(--ink);
  text-align: center; font-variant-numeric: tabular-nums;
}
#loot .lbig em {
  font-style: normal; font-size: 11px; font-weight: 500; letter-spacing: .16em;
  text-transform: uppercase; color: var(--dim);
}
#loot .lsub { font-size: 11px; color: rgba(160, 154, 146, .75); }
#loot.k-gold .lbig { color: #e8c67a; }
#loot.k-gold .lbig em { color: rgba(232, 198, 122, .6); }
#loot.r-uncommon .lbox { border-color: rgba(95, 174, 126, .6); }
#loot.r-uncommon .lcap { color: #5fae7e; }
#loot.r-rare .lbox { border-color: rgba(91, 143, 214, .6); }
#loot.r-rare .lcap { color: #5b8fd6; }
#loot.r-epic .lbox { border-color: rgba(162, 116, 216, .7); }
#loot.r-epic .lcap { color: #a274d8; }
#loot.r-legendary .lbox {
  border-color: rgba(232, 198, 122, .8);
  box-shadow: 0 10px 40px rgba(0, 0, 0, .55), 0 0 32px rgba(232, 198, 122, .22);
}
#loot.r-legendary .lcap { color: #e8c67a; }
@keyframes lootIn {
  0% { opacity: 0; transform: scale(.86) translateY(10px); }
  100% { opacity: 1; transform: none; }
}
body.touch .pcard .btn { padding: 12px 14px; }

/* The people section of the settings. */
#settings .row.people .fine, #room .row.people .fine { margin: 0; text-align: right; line-height: 1.3; }
#settings section.off .seg, #settings section.off .row.people, #settings section.off .fader, #room section.off .seg, #room section.off .row.people, #room section.off .fader { opacity: .35; pointer-events: none; }
#settings .btn:disabled, #room .btn:disabled { opacity: .5; cursor: default; }
/* The lend section: the one-time token, as the command that uses it. */
#settings #setLend a { color: var(--ember-soft); }
#settings pre.tok {
  margin: 6px 0 0; padding: 8px 10px; border-radius: 6px; background: rgba(0, 0, 0, .35);
  border: 1px solid rgba(255, 255, 255, .08); color: rgba(230, 226, 220, .85);
  font: 10.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; word-break: break-all; user-select: all;
}
#settings .fine.warn { color: rgba(255, 178, 122, .85); }

/* -------------------------------------------------------------- bottom */
#bottom {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 0 20px 18px; display: flex; flex-direction: column;
  align-items: center; gap: 10px;
  background: linear-gradient(to top, rgba(4, 5, 9, .72), transparent);
  padding-top: 70px;
}

#actions { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; pointer-events: auto; }

/* The secondary actions - offer one, tap the ash, sit down. Deliberately
   lighter than the hand squares: these are things you can do, not things you
   are holding, and the bar should not compete with the two squares below it. */
.act {
  appearance: none; cursor: pointer; font: inherit; color: var(--ink);
  background: var(--glass); border: 1px solid var(--edge);
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border-radius: 10px; padding: 6px 12px 6px 9px;
  display: flex; align-items: baseline; gap: 8px;
  transition: border-color .18s, background .18s, transform .12s;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .4);
}
.act:hover { border-color: rgba(255, 140, 80, .5); background: rgba(38, 26, 20, .5); }
.act:active { transform: translateY(1px); }
.act .k {
  font-size: 10px; line-height: 1.35; color: var(--ember);
  border: 1px solid rgba(255, 122, 61, .45); border-radius: 5px; padding: 1px 5px;
}
.act .l { font-size: 12.5px; }
.act .s { font-size: 10.5px; color: var(--dim); }

/* The one word along the very bottom where the key hints were. Present,
   never loud: the same grey as the hints it replaced. */
#helpBtn {
  appearance: none; cursor: pointer; font: inherit; pointer-events: auto;
  color: rgba(160, 154, 146, .6); font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  background: none; border: 1px solid rgba(160, 154, 146, .25); border-radius: 999px;
  padding: 4px 12px; transition: color .18s, border-color .18s;
}
#helpBtn:hover, body.help #helpBtn { color: var(--ember-soft); border-color: rgba(255, 140, 80, .5); }

/* The instructions: the profile's sheet of glass, with the keys on it. */
#help {
  position: fixed; inset: 0; display: grid; place-items: center; padding: 20px;
  background: rgba(3, 4, 8, .45); pointer-events: none; opacity: 0;
  transition: opacity .18s ease; z-index: 6;
}
#help.open { opacity: 1; pointer-events: auto; }
#help .pcard { width: min(420px, 100%); max-height: calc(100vh - 40px); overflow: auto; }
#help.open .pcard { transform: none; }
#help h2 { margin: 0 0 6px; font-size: 16px; font-weight: 600; padding-right: 28px; }
#help .tag { margin: 0 0 12px; color: var(--dim); font-size: 12.5px; line-height: 1.4; }
#help .keys { margin: 0 0 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px; }
#help .keys > div { display: flex; align-items: baseline; gap: 9px; }
#help .keys > div[hidden] { display: none; }
#help .keys dt {
  flex: none; min-width: 42px; text-align: center; font-size: 10.5px; line-height: 1.35; color: var(--ember);
  border: 1px solid rgba(255, 122, 61, .45); border-radius: 5px; padding: 1px 6px;
}
#help .keys dd { margin: 0; font-size: 12.5px; }
#help .fine { margin: 0; color: var(--dim); font-size: 11.5px; line-height: 1.4; }
@media (max-width: 520px) { #help .keys { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- the hands */
/* Two squares: your left hand and your right, and the one the mouse speaks
   to. The whole control scheme is "the button is the active hand", so which
   hand that is, and what is in it, have to be unmistakable. */

#handbar { display: flex; align-items: flex-end; gap: 12px; pointer-events: auto; }
#items { position: relative; }
#slots { display: flex; gap: 12px; justify-content: center; pointer-events: auto; }
/* The objects themselves, drawn by slots.js into one transparent canvas laid
   over the two squares. Above the buttons so it is not behind their glass,
   and letting every click through to them. */
#itemsView {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  pointer-events: none; z-index: 2;
}

/* The squares are the things they stand for. Each is a shape of glass -
   an open palm for a hand, the left one facing you and the right its
   mirror, a briefcase for the pocket - and nothing else: no box round it.
   The object a hand holds is drawn by slots.js into the palm (the .pic
   box), and the words sit under the shape: the number and which hand, then
   what is in it. A hand with nothing in it is a dashed outline, and the
   active one glows the colour of an ember. The shapes are <use>s of the
   two paths defined once in index.html. */
.slot, #invBtn {
  position: relative; appearance: none; cursor: pointer; font: inherit; color: var(--ink);
  width: 90px; padding: 0; background: none; border: none;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  touch-action: none; transition: transform .12s;
}
.slot:active, #invBtn:active { transform: translateY(1px); }
.slot .shape, #invBtn .shape {
  display: block; width: 90px; height: 85px; overflow: visible;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .5));
}
.slot[data-hand="2"] .shape { transform: scaleX(-1); }
.slot .shape use, #invBtn .shape use {
  fill: rgba(16, 16, 20, .62); stroke: rgba(255, 255, 255, .16); stroke-width: 1.6;
  transition: fill .18s, stroke .18s;
}
.slot:hover .shape use, #invBtn:hover .shape use { stroke: rgba(255, 140, 80, .5); }
/* Where the object is drawn: most of the hand, not just the palm, so a
   thing in it is big enough to read and spills over the outline a little,
   the way a held thing does. Sized against the shape at the width above
   (the 90 by 85 shape: the same box scaled down from 104 by 98). */
.slot .pic { position: absolute; left: 5px; top: 10px; width: 80px; height: 73px; pointer-events: none; }
.slot .cap, #invBtn .cap {
  font-size: 8.5px; line-height: 1; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(160, 154, 146, .6); display: flex; align-items: baseline; gap: 6px;
}
.slot .cap b, #invBtn .cap b { font-size: 10px; font-weight: 600; color: rgba(255, 178, 122, .8); letter-spacing: 0; }
.slot .l { font-size: 11px; letter-spacing: .01em; text-align: center; padding: 0 6px;
  text-shadow: 0 1px 6px rgba(0, 0, 0, .8); }
.slot .s, #invBtn .n { font-size: 10px; color: var(--dim); }

/* Held: warm, lit, unmistakable at a glance. */
.slot.on .shape use {
  fill: rgba(60, 34, 20, .82); stroke: rgba(255, 140, 80, .85);
}
.slot.on .shape { filter: drop-shadow(0 6px 18px rgba(255, 122, 61, .3)); }
.slot.on .cap b { color: var(--ember); }
.slot.on .cap { color: rgba(255, 178, 122, .7); }

/* Empty: an outline of a hand, plainly, and still a button - an empty hand
   can be made the active one, which is how you pick things up. */
.slot.empty .shape use { fill: rgba(12, 12, 16, .4); stroke-dasharray: 3 3; }
.slot.empty .shape { filter: none; }
.slot.empty .l { font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase; color: rgba(160, 154, 146, .5); }
.slot.empty.on .shape use { fill: rgba(44, 24, 14, .5); stroke: rgba(255, 140, 80, .6); }
.slot.empty.on .l { color: rgba(255, 178, 122, .7); }

body.inventory #invBtn .shape use { fill: rgba(44, 24, 14, .7); stroke: rgba(255, 140, 80, .8); }
body.inventory #invBtn .cap { color: rgba(255, 178, 122, .7); }

/* Where a drag can land: a hand, the briefcase, the sheet's put-away
   zone. Lit only while what is being dragged could go there. */
.slot.over .shape use, #invBtn.over .shape use {
  stroke: var(--ember); stroke-dasharray: none; fill: rgba(70, 40, 24, .85);
}
.slot.over .shape, #invBtn.over .shape { filter: drop-shadow(0 0 10px rgba(255, 122, 61, .5)); }
/* The thing under the pointer while it is being dragged: a chip with its
   name, warm once it is over somewhere it can go. Above everything and
   invisible to hit testing, so the drop target under it is still found. */
#dragGhost {
  position: fixed; left: 0; top: 0; z-index: 30; pointer-events: none;
  padding: 6px 11px; border-radius: 999px; font-size: 12px; color: var(--ink);
  background: rgba(14, 14, 18, .82); border: 1px solid var(--edge);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .55); white-space: nowrap;
  opacity: 0; transition: opacity .1s, border-color .1s, color .1s;
}
#dragGhost.on { opacity: 1; }
#dragGhost.ok { border-color: rgba(255, 140, 80, .8); color: var(--ember-soft); }
body.dragging { cursor: grabbing; }
body.dragging .slot, body.dragging #invBtn, body.dragging #invList .tile { cursor: grabbing; }

/* ----------------------------------------------------------- inventory */
/* The pocket. A sheet of the settings panel's glass down the right of the
   screen, big enough to see what you own: a grid of squares, each showing
   its object and nothing else, the way the hand squares do, with the name
   of the one under the pointer in a caption under the grid. Tiles are
   buttons and drag sources; the whole sheet is where a hand square is
   dropped to put its thing away. The grid is what scrolls, not the sheet,
   so the canvas laid over the sheet (#invView) stays put and the stow zone
   stays a drop target. */
#inventory {
  position: absolute; right: 18px; top: 66px; bottom: 150px;
  width: min(460px, calc(100vw - 36px)); transform: translateX(10px);
  display: flex; flex-direction: column; overflow: hidden;
  background: rgba(14, 14, 18, .74); border: 1px solid var(--edge); border-radius: 18px;
  backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
  padding: 16px 18px 12px; pointer-events: none; opacity: 0;
  transition: opacity .2s ease, transform .2s ease; z-index: 4;
}
body.inventory #inventory { opacity: 1; transform: none; pointer-events: auto; }
#inventory > * { flex: 0 0 auto; }
/* The objects on the tiles, drawn by slots.js into one transparent canvas
   laid over the panel: above the tiles so it is not behind their glass,
   letting every click and drag through to them, and inside the sheet so it
   fades with it. */
#invView {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  pointer-events: none; z-index: 2;
}
#inventory .sh {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase; color: var(--dim);
  margin-bottom: 8px;
}
#inventory .x {
  appearance: none; background: none; border: none; color: var(--dim); cursor: pointer;
  font: inherit; font-size: 20px; line-height: 1; padding: 0 2px;
}
#inventory .x:hover { color: var(--ink); }
#invList {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 12px;
  align-content: start; flex: 1 1 auto; min-height: 0; overflow: auto; padding: 2px;
}
/* A square, the hand squares' glass, holding nothing but its count: the
   object is drawn over it. */
#invList .tile {
  position: relative; appearance: none; cursor: grab; font: inherit; color: var(--ink);
  aspect-ratio: 1; width: 100%; padding: 0;
  background: var(--glass); border: 1px solid var(--edge); border-radius: 14px;
  touch-action: none; transition: border-color .15s, background .15s, transform .12s;
  box-shadow: 0 6px 26px rgba(0, 0, 0, .35);
}
#invList .tile:hover { border-color: rgba(255, 140, 80, .5); background: rgba(38, 26, 20, .5); }
/* The tile a click picked out, until the next click or the next rewrite. */
#invList .tile.sel { border-color: var(--ember); background: rgba(70, 40, 24, .55); }
#invList .tile:active { cursor: grabbing; transform: translateY(1px); }
#invList .ct {
  position: absolute; top: 8px; right: 10px; font-size: 12px; color: var(--ember-soft);
  text-shadow: 0 1px 6px rgba(0, 0, 0, .8);
}
/* A bound thing of yours that is not in your pocket - a toy in somebody
   else's fist, a duck under a sofa (docs/money.md). The dashed edge is the
   put-away zone's, for the same reason: what it outlines is not here. The
   line sits at the foot of the square, clear of the object slots.js draws
   over the middle of it, and takes no pointer events so it cannot swallow
   the press that begins a drag. */
#invList .tile.away { border-style: dashed; }
#invList .tile .wh {
  position: absolute; left: 5px; right: 5px; bottom: 7px;
  font-size: 10px; line-height: 1.2; color: var(--ember-soft);
  text-shadow: 0 1px 6px rgba(0, 0, 0, .9);
  pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* What the tile under the pointer is. Kept a line tall while empty so the
   grid does not jump. */
#invInfo {
  min-height: 20px; margin-top: 10px; font-size: 13px; color: var(--ink);
  opacity: 0; transition: opacity .12s;
}
#invInfo.on { opacity: 1; }
#invList .none { margin: 4px 0 6px; font-size: 12px; color: var(--dim); }
#invStow {
  margin-top: 10px; padding: 9px; border: 1px dashed rgba(255, 255, 255, .14); border-radius: 10px;
  text-align: center; font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: rgba(160, 154, 146, .6);
  display: flex; flex-direction: column; gap: 2px; transition: border-color .15s, background .15s, color .15s;
}
#invStow small { font-size: 10px; letter-spacing: .04em; text-transform: none; color: rgba(160, 154, 146, .5); }
#invStow.over { border-color: var(--ember); border-style: solid; background: rgba(70, 40, 24, .6); color: var(--ember-soft); }
#inventory .fine { color: rgba(160, 154, 146, .6); font-size: 11px; margin: 8px 0 0; line-height: 1.5; }
#inventory .fine b { color: rgba(230, 226, 220, .8); font-weight: 600; }
body.inventory #xhair { opacity: 0; }

/* ---------------------------------------------------------------- chat */
#chat {
  position: absolute; left: 20px; bottom: 128px; width: min(360px, 34vw);
  display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
#chatLog {
  max-height: 30vh; overflow: hidden; display: flex; flex-direction: column;
  justify-content: flex-end; gap: 3px;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%);
  mask-image: linear-gradient(to bottom, transparent, #000 22%);
}
.msg { font-size: 13px; color: rgba(233, 231, 226, .88); text-shadow: 0 1px 9px rgba(0, 0, 0, .95); }
.msg b { font-weight: 600; margin-right: 5px; }
/* A link in the chat is the one thing in the log the mouse may touch. It
   needs the mouse free (Esc), since a captured pointer belongs to the roof. */
.msg a {
  color: #9fd0ff; text-decoration: underline; text-underline-offset: 2px;
  pointer-events: auto; cursor: pointer; overflow-wrap: anywhere;
}
.msg a:hover { color: #cfe7ff; }
body.locked .msg a { pointer-events: none; }
/* A player's name is the other thing the mouse may touch: it opens their
   card, the same as their row in the list top right. Same rule as a link -
   a pointer the roof has captured has no cursor to click with. */
.msg b.nm { pointer-events: auto; cursor: pointer; }
.msg b.nm:hover { text-decoration: underline; text-underline-offset: 2px; }
body.locked .msg b.nm { pointer-events: none; }

#chatForm { opacity: 0; pointer-events: none; transition: opacity .2s; display: flex; align-items: center; gap: 7px; }
body.chatting #chatForm { opacity: 1; pointer-events: auto; }
/* Who the line is for, in conversation: her red, beside the box, and it
   stays there when the placeholder has been typed over. */
#chatTo {
  flex: none; font-size: 12px; letter-spacing: .04em; color: #e8899a;
  padding: 6px 9px; border-radius: 8px; background: rgba(232, 137, 154, .12);
  border: 1px solid rgba(232, 137, 154, .38); white-space: nowrap;
  text-shadow: 0 1px 9px rgba(0, 0, 0, .95);
}
#chatTo:empty { display: none; }
#chatInput {
  width: 100%; font: inherit; color: var(--ink); padding: 9px 13px;
  background: var(--glass); border: 1px solid rgba(255, 140, 80, .4);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-radius: 10px; outline: none;
}
#chatInput::placeholder { color: rgba(160, 154, 146, .6); }

/* The bartender in the log: her name in her sash's red, the English of a
   Japanese line under it in the feed's grey; a line said to her says so. */
.msg.her b { color: #e8899a; }
.msg .en, .msg .to { font-size: 11px; color: rgba(200, 196, 190, .7); margin-left: 5px; }
#chatHint {
  font-size: 12px; color: rgba(233, 231, 226, .72); min-height: 0;
  text-shadow: 0 1px 9px rgba(0, 0, 0, .95);
}
#chatHint:empty { display: none; }
body.barchat #chatInput { border-color: rgba(232, 137, 154, .55); }
#xhair.keep i { background: #e8899a; box-shadow: 0 0 10px rgba(232, 137, 154, .7), 0 0 2px #000; }

/* ---------------------------------------------------------- connection */
#conn {
  position: fixed; right: 18px; top: 22px; display: flex; align-items: center; gap: 7px;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
  opacity: 0; transition: opacity .6s; text-shadow: 0 1px 8px #000;
}
body.playing #conn { opacity: 1; }
#conn .dot { width: 6px; height: 6px; border-radius: 50%; background: #6b6b6b; }
/* Connected and nothing to say about the room: the dot alone, with no gap
   left where the words used to be. */
#connText:empty { display: none; }
#conn.ok .dot { background: #7ee787; box-shadow: 0 0 10px rgba(126, 231, 135, .8); }
#conn.bad .dot { background: #e2725b; box-shadow: 0 0 10px rgba(226, 114, 91, .8); }
/* While there is no connection, say so where the eye already is: the
   middle of a black screen. Gone the moment the roof comes back. */
#connBig {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 12px; pointer-events: none;
  font-size: 15px; letter-spacing: .22em; text-transform: uppercase; color: var(--ink);
  text-shadow: 0 1px 12px #000; opacity: 0; transition: opacity .4s; z-index: 5;
}
body.playing #connBig.on { opacity: 1; }
#connBig .dot {
  width: 9px; height: 9px; border-radius: 50%; background: #e2725b;
  box-shadow: 0 0 14px rgba(226, 114, 91, .9); animation: connPulse 1.2s ease-in-out infinite;
}
@keyframes connPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ------------------------------------------------------------ age gate */
/* The adults-only notice. It shares the gate's look but sits over it, and
   nothing underneath is reachable until it goes: a date of birth, a ticked
   affirmation, and only then the roof. #ageStatic is the same wall for a
   browser with scripts off, where there is nothing to pass. It sits over
   everything, the wardrobe opened from the gate included. */
#age, #ageStatic {
  position: fixed; inset: 0; display: grid; place-items: center; overflow: auto;
  background: radial-gradient(120% 90% at 50% 20%, #101726 0%, #05070c 70%);
  z-index: 14; transition: opacity .6s ease, visibility .6s;
}
#age.gone { opacity: 0; visibility: hidden; }
#age [hidden] { display: none; }
#age .card, #ageStatic .card { width: min(440px, 90vw); text-align: center; padding: 28px 0; }
#age .badge {
  display: inline-block; margin: 0 0 14px; padding: 6px 12px; border-radius: 8px;
  font-size: 13px; font-weight: 700; letter-spacing: .18em;
  color: #140d08; background: linear-gradient(180deg, var(--ember-soft), var(--ember));
  box-shadow: 0 8px 30px rgba(255, 122, 61, .3);
}
#age h1, #ageStatic h1 {
  margin: 0 0 12px; font-size: 30px; font-weight: 300; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink);
  text-shadow: 0 0 60px rgba(255, 122, 61, .25);
}
#age .tag, #ageStatic .tag { margin: 0 0 22px; color: var(--dim); font-size: 14px; line-height: 1.6; }
#age .tag b { color: var(--ink); font-weight: 600; }
#age form { display: flex; flex-direction: column; gap: 12px; text-align: left; }
#age fieldset { margin: 0; padding: 0; border: none; min-width: 0; }
#age legend {
  padding: 0; margin: 0 0 6px; font-size: 10.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--dim);
}
#age .dob { display: grid; grid-template-columns: 1fr 1.5fr 1.2fr; gap: 8px; }
#age .dob label { display: flex; flex-direction: column; gap: 4px; }
#age .dob label span { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: rgba(160, 154, 146, .7); }
#age .dob select {
  width: 100%; min-width: 0; box-sizing: border-box; font: inherit; font-size: 16px; text-align: center;
  color: var(--ink); background: rgba(255, 255, 255, .045);
  border: 1px solid var(--edge); border-radius: 10px; padding: 11px 8px; outline: none;
  transition: border-color .2s;
}
#age .dob select {
  appearance: none; -webkit-appearance: none; cursor: pointer; text-align: left; padding-right: 26px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23a09a92' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 11px;
}
#age .dob select:invalid, #age .dob select.empty { color: rgba(160, 154, 146, .6); }
/* The open list is the browser's own. color-scheme lets it draw that list
   dark, so it belongs to the page instead of landing as a white column;
   the option rules cover the engines that paint from CSS instead. */
#age .dob select { color-scheme: dark; }
#age .dob select option { color: var(--ink); background: #15181d; font-size: 15px; padding: 6px 8px; }
#age .dob select option:checked { color: #fff; background: rgba(255, 122, 61, .35); }
#age .dob select option[value=""] { color: rgba(160, 154, 146, .6); }
#age .dob select:focus { border-color: rgba(255, 140, 80, .55); }
#age .dob select.bad { border-color: rgba(226, 114, 91, .8); }
#age .err { margin: 0; font-size: 12.5px; line-height: 1.5; color: #e2725b; }
#age button {
  margin-top: 4px; font: inherit; font-size: 14px; letter-spacing: .16em;
  text-transform: uppercase; cursor: pointer; color: #140d08;
  background: linear-gradient(180deg, var(--ember-soft), var(--ember));
  border: none; border-radius: 10px; padding: 13px;
  box-shadow: 0 10px 40px rgba(255, 122, 61, .28);
  transition: transform .12s, box-shadow .2s;
}
#age button:hover { box-shadow: 0 12px 50px rgba(255, 122, 61, .42); }
#age button:active { transform: translateY(1px); }
#age button.leave {
  margin: 0; color: var(--dim); background: transparent; border: 1px solid var(--edge);
  box-shadow: none; letter-spacing: .12em; text-transform: none; font-size: 13px;
}
#age button.leave:hover { color: var(--ink); background: rgba(255, 255, 255, .06); box-shadow: none; }
#age .fine { margin-top: 22px; color: rgba(160, 154, 146, .55); font-size: 11.5px; line-height: 1.55; }
#age form .fine { margin: -4px 0 0; text-align: center; }
#age .legal { margin-top: 26px; font-size: 11px; }
#age #ageRetry { width: 100%; margin-top: 18px; text-transform: none; letter-spacing: .06em; }
#gate .fine.age { margin-top: 12px; }
#gate .fine.age b { color: var(--ember-soft); font-weight: 600; letter-spacing: .08em; }
#gate .fine.age a { color: rgba(160, 154, 146, .8); }

/* --------------------------------------------------- microphone check */
/* The first thing in the room: the microphone and its meter, on a card
   over the world, which goes on being drawn behind it - they are in, and
   muted, and this is the question of whether to stop being. */
#ready {
  position: fixed; inset: 0; z-index: 12; display: grid; place-items: safe center; overflow-y: auto;
  background: rgba(4, 6, 10, .55);
  backdrop-filter: blur(10px) saturate(1.1); -webkit-backdrop-filter: blur(10px) saturate(1.1);
  transition: opacity .35s ease, visibility .35s;
}
#ready.gone { opacity: 0; visibility: hidden; }
#ready [hidden] { display: none !important; }
#ready .card {
  width: min(420px, 88vw); text-align: center; padding: 28px 26px; box-sizing: border-box;
  background: rgba(12, 15, 22, .82); border: 1px solid var(--edge); border-radius: 18px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, .55);
}
#ready .lead {
  margin: 0; font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase; color: var(--dim);
}
#ready h2 {
  margin: 8px 0 4px; font-size: 26px; font-weight: 400; letter-spacing: .14em; color: var(--ink);
}
/* Which of the worlds is on the other side of Join now. The code names
   the room; this names the place, which is the half of it a person can
   picture. */
#ready .where {
  margin: 0 0 3px; font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ember-soft);
}
#ready .fine { margin: 0; color: rgba(160, 154, 146, .6); font-size: 12px; }
#ready .fine.keys { margin-top: 22px; }
#ready .fine.keys b { color: var(--ember-soft); font-weight: 600; }
#ready .hint { margin: 10px 0 0; min-height: 1.4em; font-size: 12px; color: rgba(160, 154, 146, .6); }
#ready .hint.warn { color: rgba(255, 178, 122, .85); }

/* The mic button and its meter, side by side. */
#ready .mic { display: flex; align-items: center; gap: 12px; margin: 26px 0 12px; }
#ready #readyMic {
  flex: none; display: flex; align-items: center; gap: 9px; cursor: pointer;
  font: inherit; font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--dim); background: rgba(255, 255, 255, .06); border: 1px solid var(--edge);
  border-radius: 999px; padding: 11px 16px; transition: color .18s, border-color .18s, background .18s;
}
#ready #readyMic:hover { color: var(--ink); background: rgba(255, 255, 255, .1); }
#ready #readyMic.on { color: var(--ember-soft); border-color: rgba(255, 140, 80, .5); background: rgba(60, 34, 20, .5); }
#ready #readyMic.on #readyMicSlash { display: none; }
/* Twelve bars: what the microphone is actually hearing, right now. */
#readyMeter { flex: 1; display: flex; gap: 3px; align-items: center; height: 18px; }
#readyMeter i {
  flex: 1; height: 100%; border-radius: 2px; background: rgba(255, 255, 255, .07);
  transition: background .08s linear;
}
#readyMeter i.lit { background: var(--ember-soft); }
#readyMeter i.hot { background: #e2725b; }

#ready label.dev {
  display: flex; flex-direction: column; gap: 6px; text-align: left;
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim);
}
#ready label.dev select {
  font: inherit; font-size: 14px; letter-spacing: 0; text-transform: none;
  color: var(--ink); background: rgba(255, 255, 255, .045);
  border: 1px solid var(--edge); border-radius: 10px; padding: 10px 12px; outline: none;
}
#ready label.dev select option { background: #15181d; color: var(--ink); }
#ready #readyGo {
  width: 100%; margin-top: 22px; font: inherit; font-size: 14px; letter-spacing: .16em;
  text-transform: uppercase; cursor: pointer; color: #140d08;
  background: linear-gradient(180deg, var(--ember-soft), var(--ember));
  border: none; border-radius: 10px; padding: 14px;
  box-shadow: 0 10px 40px rgba(255, 122, 61, .28);
  transition: transform .12s, box-shadow .2s;
}
#ready #readyGo:hover { box-shadow: 0 12px 50px rgba(255, 122, 61, .42); }
#ready #readyGo:active { transform: translateY(1px); }
#ready .back {
  width: 100%; margin-top: 8px; padding: 8px; cursor: pointer;
  font: inherit; font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--dim); background: transparent; border: none;
}
#ready .back:hover { color: var(--ink); }

/* ---------------------------------------------------------------- gate */
#gate {
  position: fixed; inset: 0; display: grid; place-items: safe center; overflow-y: auto;
  background: radial-gradient(120% 90% at 50% 20%, #101726 0%, #05070c 70%);
  z-index: 10; transition: opacity .8s ease, visibility .8s;
}
#gate.gone { opacity: 0; visibility: hidden; }

/* The gate is a card in the middle of the screen, and now a figure
   beside it. Two columns on anything wide enough, and one on a phone -
   where the figure goes ABOVE the card rather than beside it, because the
   thing somebody came to the page to do is start a meeting and that must
   not be pushed under the fold by a mannequin. */
#gate {
  grid-auto-flow: column; gap: clamp(20px, 4vw, 56px);
  align-items: center; justify-content: safe center;
}
#gate .card { width: min(420px, 88vw); text-align: center; }

/* You, on the front page (js/gatefigure.js). The plinth keeps its size
   whether or not there is anybody standing on it, and it is in the page
   from the first paint, so the card never jumps sideways - not when the
   script binds and not when the model finishes loading. */
#gateMe {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  width: min(240px, 30vw);
}
/* `display: flex` beats the `hidden` attribute, and the plinth is hidden
   where nothing can ever stand on it (tools/hiddencheck.js). */
#gateMe[hidden] { display: none; }
#gateMeView {
  width: 100%; aspect-ratio: 3 / 4.4; position: relative;
  border-radius: 18px; cursor: grab;
  background: radial-gradient(78% 62% at 50% 38%, rgba(255, 140, 80, .10) 0%, rgba(255, 140, 80, 0) 70%);
  touch-action: none;
}
#gateMeView:active { cursor: grabbing; }
#gateMeView .gfCanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#gateMe .hint { margin: 0; font-size: 11px; color: rgba(160, 154, 146, .7); }
#gateDress {
  appearance: none; cursor: pointer; font: inherit; font-size: 12.5px;
  letter-spacing: .06em; color: var(--ink);
  padding: 9px 20px; border-radius: 11px;
  background: rgba(255, 255, 255, .05); border: 1px solid var(--edge);
  transition: border-color .18s, background .18s, color .18s;
}
#gateDress:hover {
  color: var(--ember-soft); background: rgba(255, 140, 80, .10);
  border-color: rgba(255, 140, 80, .55);
}
/* Under about a tablet the two stack, and the figure gets out of the way:
   short, and above the card, so the table is still near the top of the
   screen. */
@media (max-width: 760px) {
  #gate { grid-auto-flow: row; gap: 14px; }
  #gateMe { width: min(150px, 42vw); }
  #gateMeView { aspect-ratio: 3 / 3.2; }
}
#gate h1 {
  margin: 0 0 6px; font-size: 44px; font-weight: 300; letter-spacing: .22em;
  text-transform: uppercase; color: var(--ink);
  text-shadow: 0 0 60px rgba(255, 122, 61, .25);
}
#gate .tag { margin: 0 0 32px; color: var(--dim); font-size: 14px; line-height: 1.6; }
#gate .step { display: flex; flex-direction: column; gap: 12px; text-align: left; }
#gate .step[hidden], #gate button[hidden], #gate p[hidden],
#gate label[hidden], #gate form[hidden], #gatePw[hidden] { display: none !important; }
/* The account this site keeps itself: the same column as the step it is in. */
#gatePw { display: flex; flex-direction: column; gap: 12px; }
/* "or", with the line through it: the two ways in are one choice. */
#gate .or {
  display: flex; align-items: center; gap: 12px; margin: 4px 0 0;
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: rgba(160, 154, 146, .5);
}
#gate .or::before, #gate .or::after { content: ''; flex: 1; height: 1px; background: var(--edge); }
#gate label {
  display: flex; flex-direction: column; gap: 6px;
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim);
}
#gate input, #gate select {
  font: inherit; font-size: 15px; letter-spacing: 0; text-transform: none;
  color: var(--ink); background: rgba(255, 255, 255, .045);
  border: 1px solid var(--edge); border-radius: 10px; padding: 11px 13px; outline: none;
  transition: border-color .2s;
}
#gate input:focus, #gate select:focus { border-color: rgba(255, 140, 80, .55); }
#gate select option { background: #1a1410; color: var(--ink); }
#gate label.opt {
  flex-direction: row; align-items: center; gap: 10px; cursor: pointer;
  font-size: 12.5px; letter-spacing: 0; text-transform: none; color: var(--ink);
}
#gate label.opt input { width: 16px; height: 16px; padding: 0; margin: 0; accent-color: var(--ember); flex: none; }
#gate label.opt.off { opacity: .45; cursor: default; }
#gate .hint.note { margin: -20px 0 24px; color: rgba(255, 178, 122, .85); text-align: center; min-height: 0; }
#gate button {
  margin: 0; font: inherit; font-size: 14px; letter-spacing: .16em;
  text-transform: uppercase; cursor: pointer; color: #140d08;
  background: linear-gradient(180deg, var(--ember-soft), var(--ember));
  border: none; border-radius: 10px; padding: 13px;
  box-shadow: 0 10px 40px rgba(255, 122, 61, .28);
  transition: transform .12s, box-shadow .2s;
}
#gate button:hover { box-shadow: 0 12px 50px rgba(255, 122, 61, .42); }
#gate button:active { transform: translateY(1px); }
#gate button:disabled { opacity: .45; cursor: default; box-shadow: none; transform: none; }
/* The quiet buttons: the second way in, a step back, hosting. */
#gate button.ghost, #gate button.x {
  color: var(--ink); background: rgba(255, 255, 255, .06); border: 1px solid var(--edge);
  box-shadow: none; letter-spacing: .12em;
}
#gate button.ghost:hover, #gate button.x:hover { background: rgba(255, 255, 255, .1); box-shadow: none; }
#gate button.x { display: flex; align-items: center; justify-content: center; gap: 9px; }
#gate button.back {
  padding: 8px; color: var(--dim); background: transparent; border: none; box-shadow: none;
  font-size: 12px; letter-spacing: .12em;
}
#gate button.back:hover { color: var(--ink); box-shadow: none; }
#gate .row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 2px; }
/* Hosting: a name for the roof, and what it will be called once cleaned. */
#gate .hint { margin: -4px 0 0; color: rgba(160, 154, 146, .6); font-size: 12px; min-height: 1.4em; }
#gate .hint b { color: var(--ember-soft); font-weight: 600; letter-spacing: .06em; }
#gate .hint.warn { color: rgba(255, 178, 122, .85); }
#gate .fine { margin-top: 22px; color: rgba(160, 154, 146, .55); font-size: 12px; }

/* The quiet row under the table: a meeting of your own, and a code.
   Small, outlined, no glow - the table above is the page, and these are
   the two things it is not. They sit side by side and wrap on a narrow
   card. */
#gate .ways { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 2px; }
#gate .ways button.quiet, #gate .ways #gateNew, #gate .ways #gateNewMore {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 14px; font-size: 11.5px; letter-spacing: .14em;
  color: var(--dim); background: transparent; border: 1px solid var(--edge); box-shadow: none;
}
#gate .ways button.quiet:hover, #gate .ways #gateNew:hover, #gate .ways #gateNewMore:hover,
#gate .ways button.quiet[aria-expanded="true"] {
  color: var(--ink); background: rgba(255, 255, 255, .06); box-shadow: none;
}
#gate .ways button.quiet svg { flex: none; color: var(--ember-soft); }
/* New: the button that starts one now, the one that opens the rest, and
   the menu it drops - upward, since this row is the bottom of the card. */
#gate .newwrap { position: relative; }
#gate .split { display: flex; }
#gate .ways #gateNew { border-radius: 10px 0 0 10px; }
#gate .ways #gateNewMore { padding: 9px 10px; margin-left: -1px; border-radius: 0 10px 10px 0; }
#gate #gateNewMore[aria-expanded="true"] svg { transform: rotate(180deg); }
#gate #gateNewMore svg { transition: transform .18s; }
/* Hosting, to a guest: there, and plainly not theirs to press. The caret
   still opens, since seeing what is behind it is the point. */
#gate .newwrap.locked #gateNew, #gate .newwrap.locked #gateNewMore {
  color: rgba(160, 154, 146, .45); background: transparent; box-shadow: none;
}
#gate .newwrap.locked #gateNew svg { color: rgba(160, 154, 146, .35); }
#gate .newwrap.locked #gateNew { cursor: default; }
#gate .newwrap.locked #gateNew:hover, #gate .newwrap.locked #gateNewMore:hover { box-shadow: none; }
#gate #newMenu button.locked, #gate #newMenu button.locked:hover {
  color: rgba(160, 154, 146, .4); background: transparent; cursor: default;
}
#gate #newMenu button.locked svg { color: rgba(160, 154, 146, .3); }
#gate .hint.flash { animation: hintflash 1.4s ease; }
@keyframes hintflash {
  0% { color: rgba(160, 154, 146, .6); } 12% { color: var(--ember-soft); } 100% { color: rgba(160, 154, 146, .6); }
}
#gate .hint a { color: var(--ember-soft); }
#gate #newMenu {
  position: absolute; left: 0; bottom: calc(100% + 6px); min-width: 240px; z-index: 3;
  display: flex; flex-direction: column; padding: 6px;
  background: #10151f; border: 1px solid var(--edge); border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .65);
}
#gate #newMenu[hidden] { display: none; }
#gate #newMenu button {
  display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 12px 13px; margin: 0; border-radius: 8px;
  font-size: 13.5px; letter-spacing: .02em; text-transform: none;
  color: var(--ink); background: transparent; border: none; box-shadow: none;
}
#gate #newMenu button:hover { background: rgba(255, 255, 255, .07); box-shadow: none; }
#gate #newMenu button svg { flex: none; color: var(--ember-soft); }

/* A meeting made for later: its link, big enough to read out loud. */
#gate .linkbox {
  margin: 6px 0 4px; padding: 16px 12px; text-align: center;
  border: 1px solid var(--edge); border-radius: 12px; background: rgba(255, 255, 255, .03);
}
#gate .linkbox b {
  display: block; font-size: 22px; font-weight: 400; letter-spacing: .14em; color: var(--ink);
}
#gate .linkbox span {
  display: block; margin-top: 6px; font-size: 12px; color: rgba(160, 154, 146, .7);
  word-break: break-all;
}
#gate #laterCopy.done { color: #140d08; }

/* The one big button on a step, with a plus on it. */
#gate #gateLinkGo, #gate #laterCopy {
  display: flex; align-items: center; justify-content: center; gap: 10px; padding: 15px; font-size: 15px;
}
#gate .hint.center { margin: -6px 0 0; text-align: center; }
#gate .hint.center.warn { color: rgba(255, 178, 122, .85); }
#gate .lead { margin: 0 0 4px; text-align: center; font-size: 14px; color: var(--ink); }
/* A code or a link, typed or pasted, and Join beside it: folded away
   under the row until "Join with a code" opens it. */
#gate form.code { display: grid; grid-template-columns: 1fr auto; gap: 8px; margin-top: 0; }
#gate form.code input { min-width: 0; letter-spacing: .06em; }
#gate form.code button { padding: 11px 18px; }
#gate .or {
  margin: 8px 0 -2px; display: flex; align-items: center; gap: 12px;
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim); white-space: nowrap;
}
#gate .or::before, #gate .or::after { content: ''; flex: 1; height: 1px; background: var(--edge); }
/* A link somebody sent: the roof, big, and who is there. */
#gate .invite { margin: 0 0 6px; text-align: center; font-size: 13px; color: var(--dim); line-height: 1.5; }
#gate .invite b {
  display: block; margin: 4px 0; font-size: 24px; font-weight: 400; letter-spacing: .14em; color: var(--ink);
}
#gate .invite span { display: block; }
/* Top right: the account, with the way out; or the way in. */
#gateCorner {
  position: fixed; top: 16px; right: 20px; z-index: 1;
  display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--dim);
}
#gateCorner .who { display: flex; align-items: center; gap: 8px; }
#gateCorner .who[hidden], #gateCorner a[hidden] { display: none; }
#gateCorner .who img { width: 24px; height: 24px; border-radius: 50%; }
#gateCorner .who span { color: var(--ink); }
#gateCorner a { color: rgba(160, 154, 146, .8); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; text-decoration: none; }
#gateCorner a:hover { color: var(--ink); }
#gateCorner #gateSignInLink { color: var(--ember-soft); }

/* The roofs, in a table: pick a row, then Enter. */
#gate .rooms {
  max-height: min(44vh, 320px); overflow-y: auto;
  border: 1px solid var(--edge); border-radius: 10px; background: rgba(255, 255, 255, .03);
}
#roomTable { width: 100%; border-collapse: collapse; font-size: 14px; }
#roomTable th {
  position: sticky; top: 0; padding: 9px 13px; text-align: left; font-weight: 400;
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase; color: var(--dim);
  background: #0c111a; border-bottom: 1px solid var(--edge);
}
#roomTable td { padding: 10px 13px; border-top: 1px solid rgba(255, 255, 255, .05); }
#roomTable .n { text-align: right; white-space: nowrap; }
#roomTable td.n { font-size: 12px; letter-spacing: .08em; color: var(--dim); }
#roomTable td.code { font-weight: 500; letter-spacing: .14em; }
/* What the room is called, under the code it is spelled as. */
#roomTable td.code small {
  display: block; margin-top: 3px; font-size: 11.5px; font-weight: 400;
  letter-spacing: .02em; color: rgba(160, 154, 146, .75); text-transform: none;
}
#roomTable .go { width: 1px; padding-right: 8px; }
/* A picture of the place, beside its code. Small: it is a reminder of
   which world this room is, not a photograph to study - the same shot the
   host picked it by (#gateMapPick), at a sixth of the size. */
#roomTable td.code { display: flex; align-items: center; gap: 10px; }
#roomTable td.code .rshot {
  flex: 0 0 auto; width: 54px; height: 34px; border-radius: 5px; object-fit: cover;
  background: #0e141d; border: 1px solid var(--edge);
}
#roomTable td.code .rshot[hidden] { display: none; }
#roomTable td.code .what { min-width: 0; }
/* Which world it is, when it is not the roof. */
#roomTable td.code em {
  display: block; margin-top: 2px; font-size: 10px; font-style: normal;
  letter-spacing: .16em; text-transform: uppercase; color: rgba(255, 122, 61, .75);
}

/* Picking a world when you open a room: two cards, each with its picture.
   Used on the host form, on the schedule screen and in the green room,
   so it is not scoped to the gate. */
fieldset.maps { border: 0; margin: 0 0 4px; padding: 0; }
fieldset.maps legend {
  padding: 0; margin-bottom: 8px; font-size: 10.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--dim);
}
.mpick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.mpick label {
  display: block; margin: 0; cursor: pointer; border: 1px solid var(--edge);
  border-radius: 10px; overflow: hidden; background: rgba(255, 255, 255, .03);
  transition: border-color .15s, background .15s;
}
.mpick label:hover { background: rgba(255, 255, 255, .06); }
.mpick input { position: absolute; opacity: 0; width: 0; height: 0; }
.mpick img {
  display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
  background: #0e141d; border-bottom: 1px solid var(--edge);
}
.mpick b { display: block; padding: 7px 10px 2px; font-size: 13px; font-weight: 500; }
.mpick span {
  display: block; padding: 0 10px 9px; font-size: 11px; line-height: 1.35;
  color: rgba(160, 154, 146, .8);
}
.mpick label.on { border-color: var(--ember); background: rgba(255, 122, 61, .12); }
.mpick label.on b { color: var(--ember-soft); }
@media (max-width: 520px) { .mpick { grid-template-columns: 1fr; } }
/* Small: the picker as a step in a flow rather than a field on a form -
   the schedule screen, and the space step a new meeting goes through on
   the way in. The pictures stay, since they are
   the whole reason this is not a dropdown; the paragraph under each goes,
   and the two stay abreast at every width. */
.mpick.small { gap: 8px; }
.mpick.small span { display: none; }
.mpick.small img { aspect-ratio: 16 / 9; }
.mpick.small b { padding: 5px 8px 6px; font-size: 11.5px; letter-spacing: .02em; }
@media (max-width: 520px) { .mpick.small { grid-template-columns: 1fr 1fr; } }
/* On the schedule screen it sits under the link it changes; on the space
   step it is the step. */
#stepLater fieldset.maps, #stepSpace fieldset.maps { margin: 2px 0 12px; }
#roomTable tbody tr { cursor: pointer; transition: background .15s; }
#roomTable tbody tr:hover { background: rgba(255, 255, 255, .06); }
#roomTable tbody tr.selected { background: rgba(255, 122, 61, .14); box-shadow: inset 3px 0 0 var(--ember); }
#roomTable tbody tr.selected td.n { color: var(--ember-soft); }
#roomTable tr.none td { padding: 12px 13px; font-size: 12.5px; color: rgba(160, 154, 146, .55); cursor: default; }
/* Join, on each row: small, and the one thing on the row that is a button. */
#gate #roomTable button.join {
  padding: 6px 12px; font-size: 11px; letter-spacing: .12em; border-radius: 8px; box-shadow: none;
}
#gate #roomTable button.join:hover { box-shadow: 0 6px 24px rgba(255, 122, 61, .35); }

body.locked { cursor: none; }

/* ------------------------------------------------------------ settings */
/* Over the chat, which comes later in the HUD and would otherwise paint
   through the glass; under the cards and the gate. Both panels hang from the
   bar that opens them, so they sit in the same place - and each one puts the
   other away (settings.js, room.js) rather than stacking on it. */
#settings {
  position: absolute; left: 20px; top: 66px; width: min(340px, calc(100vw - 36px));
  max-height: calc(100vh - 110px); overflow: auto; z-index: 5;
  background: rgba(14, 14, 18, .72); border: 1px solid var(--edge); border-radius: 16px;
  backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
  padding: 14px 16px 10px; pointer-events: none;
  opacity: 0; transform: translateY(-6px) scale(.98);
  transition: opacity .2s ease, transform .2s ease;
}
body.settings #settings { opacity: 1; transform: none; pointer-events: auto; }
/* The room controls (room.js): the same panel, under the same corner. */
#room {
  position: absolute; left: 20px; top: 66px; width: min(340px, calc(100vw - 36px));
  max-height: calc(100vh - 110px); overflow: auto; z-index: 5;
  background: rgba(14, 14, 18, .72); border: 1px solid var(--edge); border-radius: 16px;
  backdrop-filter: blur(22px) saturate(1.3); -webkit-backdrop-filter: blur(22px) saturate(1.3);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
  padding: 14px 16px 10px; pointer-events: none;
  opacity: 0; transform: translateY(-6px) scale(.98);
  transition: opacity .2s ease, transform .2s ease;
}
body.room #room { opacity: 1; transform: none; pointer-events: auto; }
#room input[type=text], #room select {
  flex: 1; min-width: 0; font: inherit; font-size: 12.5px; color: var(--ink);
  background: rgba(255, 255, 255, .06); border: 1px solid var(--edge); border-radius: 9px; padding: 7px 10px;
}
#room input[type=text]:focus, #room select:focus { outline: none; border-color: rgba(255, 140, 80, .6); }
#room select:disabled { opacity: .5; }
#room .row.people small { color: rgba(160, 154, 146, .6); }

#settings .sh, #room .sh {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase; color: var(--dim);
  margin-bottom: 6px;
}
#settings .x, #room .x {
  appearance: none; background: none; border: none; color: var(--dim); cursor: pointer;
  font: inherit; font-size: 20px; line-height: 1; padding: 0 2px;
}
#settings .x:hover, #room .x:hover { color: var(--ink); }
#settings section, #room section { padding: 10px 0 8px; border-top: 1px solid rgba(255, 255, 255, .06); }
#settings h3, #room h3 {
  margin: 0 0 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ember-soft);
}
#settings .fine, #room .fine { color: rgba(160, 154, 146, .7); font-size: 11.5px; margin: 6px 0 0; }
#settings .fine b, #room .fine b { color: rgba(230, 226, 220, .8); font-weight: 600; }

.fader { display: grid; grid-template-columns: 96px 1fr 38px; align-items: center; gap: 10px; padding: 5px 0; }
.fader .n { font-size: 12.5px; color: var(--ink); display: flex; flex-direction: column; line-height: 1.2; }
.fader .n small { font-size: 10px; color: rgba(160, 154, 146, .7); letter-spacing: .02em; }
.fader .v { font-size: 11px; color: var(--dim); text-align: right; font-variant-numeric: tabular-nums; }
.fader.off { opacity: .35; pointer-events: none; }

#settings input[type=range] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 22px; background: none; margin: 0;
  cursor: pointer;
}
#settings input[type=range]::-webkit-slider-runnable-track {
  height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .14);
}
#settings input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; margin-top: -5.5px;
  background: var(--ember-soft); box-shadow: 0 0 10px rgba(255, 122, 61, .5);
  border: 1px solid rgba(0, 0, 0, .4);
}
#settings input[type=range]::-moz-range-track { height: 3px; border-radius: 2px; background: rgba(255, 255, 255, .14); }
#settings input[type=range]::-moz-range-thumb {
  width: 13px; height: 13px; border-radius: 50%; background: var(--ember-soft);
  border: 1px solid rgba(0, 0, 0, .4); box-shadow: 0 0 10px rgba(255, 122, 61, .5);
}
#settings input[type=range]:focus { outline: none; }
#settings input[type=range]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba(255, 178, 122, .35); }

#settings .row, #room .row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 4px; }
/* `hidden` has to win over the flex above, or a row told to go stays: the
   wardrobe's row under Your look was shown for a body that has no wardrobe. */
#settings .row[hidden], #room .row[hidden] { display: none; }
#inventory .lnk, #settings .lnk {
  appearance: none; background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 11.5px; color: rgba(255, 178, 122, .8); text-decoration: underline dotted;
}
#inventory .lnk:hover, #settings .lnk:hover { color: var(--ember-soft); }

#settings .btn, #room .btn {
  appearance: none; cursor: pointer; font: inherit; font-size: 12.5px; color: var(--ink);
  background: rgba(255, 255, 255, .06); border: 1px solid var(--edge); border-radius: 9px;
  padding: 7px 12px; white-space: nowrap; transition: border-color .18s, background .18s;
}
#settings .btn:hover, #room .btn:hover { border-color: rgba(255, 140, 80, .5); }
#settings .btn.on, #room .btn.on {
  background: linear-gradient(180deg, rgba(70, 40, 24, .8), rgba(44, 24, 14, .8));
  border-color: rgba(255, 140, 80, .8); color: var(--ember-soft);
}
#settings .row.mic .fine { margin: 0; text-align: right; line-height: 1.3; }

/* The microphone dropdown: a fader row whose control is a select. The open
   list is the browser's own; color-scheme keeps it dark like the age gate. */
.fader.sel { grid-template-columns: 96px 1fr; }
#settings select, #room select {
  width: 100%; min-width: 0; box-sizing: border-box; font: inherit; font-size: 12px; color: var(--ink);
  background: rgba(255, 255, 255, .045); border: 1px solid var(--edge); border-radius: 9px;
  padding: 7px 26px 7px 10px; outline: none; cursor: pointer; color-scheme: dark;
  appearance: none; -webkit-appearance: none; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
  transition: border-color .18s;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23a09a92' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 11px;
}
#settings select:hover, #room select:hover { border-color: rgba(255, 140, 80, .4); }
#settings select:focus, #room select:focus { border-color: rgba(255, 140, 80, .55); }
#settings select option, #room select option { color: var(--ink); background: #15181d; font-size: 13px; padding: 6px 8px; }
#settings select option:checked, #room select option:checked { color: #fff; background: rgba(255, 122, 61, .35); }

/* The mic meter: a thin bar that fills with what the mic hears, and turns
   ember while it is actually being sent. */
#settings .meter {
  height: 4px; border-radius: 2px; background: rgba(255, 255, 255, .08);
  margin: 10px 0 10px; overflow: hidden;
}
#settings .meter i {
  display: block; height: 100%; width: 0; border-radius: 2px;
  background: rgba(160, 154, 146, .55); transition: width .06s linear, background .15s;
}
#settings .meter i.hot { background: var(--ember); box-shadow: 0 0 10px rgba(255, 122, 61, .8); }
#settings:not(.micon) .meter { opacity: .3; }

.seg { display: flex; gap: 6px; margin: 6px 0; }
/* `display: flex` above would otherwise beat the browser's own [hidden]. */
.seg[hidden] { display: none; }
.seg button {
  flex: 1; appearance: none; cursor: pointer; font: inherit; font-size: 12px; color: var(--dim);
  background: rgba(255, 255, 255, .04); border: 1px solid var(--edge); border-radius: 9px;
  padding: 7px 8px; transition: border-color .18s, background .18s, color .18s;
}
.seg button b { color: var(--ink); font-weight: 600; }
.seg button:hover { border-color: rgba(255, 140, 80, .4); }
.seg button.on {
  color: var(--ember-soft); background: rgba(60, 34, 20, .6); border-color: rgba(255, 140, 80, .7);
}
.seg button.on b { color: var(--ember-soft); }

/* ----------------------------------------------------------------- voice */
/* The mic pill, bottom right. Off is quiet; on is a dot; talking glows. */
/* Mute, top left beside the bar. Muted is the loud state - a
   slashed mic in warning red - because being muted without knowing it is
   the thing that costs somebody a sentence. */
#mic {
  display: flex; align-items: center; gap: 8px; flex: none;
  font: inherit; font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--dim); text-shadow: 0 1px 8px #000; pointer-events: auto; cursor: pointer;
  /* The same height as the bar beside it: two pills on one line. */
  height: 38px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--edge);
  background: rgba(14, 14, 18, .55);
  transition: border-color .2s, background .2s, color .2s;
}
#mic:hover { border-color: rgba(255, 140, 80, .5); background: rgba(60, 34, 20, .55); color: var(--ink); }
#mic svg { flex: none; }
#mic.on { color: var(--ink); }
#mic.on .slash { display: none; }
#mic.hot { color: var(--ember-soft); border-color: rgba(255, 140, 80, .6); background: rgba(60, 34, 20, .6); }
#mic.hot svg { animation: micpulse 1s ease-in-out infinite; }
#mic.off { color: #e2725b; border-color: rgba(226, 114, 91, .45); background: rgba(48, 18, 14, .5); }
#mic.off:hover { color: #f08c76; border-color: rgba(226, 114, 91, .7); background: rgba(64, 24, 18, .6); }
#mic.none { display: none; }
@keyframes micpulse {
  0%, 100% { transform: scale(1); } 50% { transform: scale(1.35); }
}

/* Somebody talking in the roster. */
.who.talk { color: var(--ink); }
.who.talk i { box-shadow: 0 0 10px currentColor; animation: micpulse .9s ease-in-out infinite; }
.who.talk em { color: var(--ember-soft); }

/* ------------------------------------------------------------------ touch */
/* A phone. body.touch is set by touch.js when the primary pointer is a
   finger. The scheme is the same - hold a thing, use it - but the mouse is a
   button bottom right, the legs are a stick under the left thumb, and the
   interface makes room for both. Everything else here is the same glass. */
body.touch { overscroll-behavior: none; -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; }
body.touch #view { touch-action: none; }
body.touch #hud { touch-action: none; }
body.touch #helpBtn { display: none; }
body.touch #notices { top: 48px; }
body.touch .notice { font-size: 12px; }
#gate .turn { display: none; }
body.touch #gate .turn { display: block; margin-top: 10px; }
@media (orientation: landscape) { body.touch #gate .turn { display: none; } }
/* 16px, so iOS does not zoom the page when a field is focused. */
body.touch #gate input, body.touch #chatInput { font-size: 16px; }
body.touch #age .card { padding: 18px 0; }
body.touch #age h1 { font-size: 24px; }
body.touch #age .tag { margin-bottom: 14px; }
body.touch #gate h1 { font-size: 34px; }
body.touch #gate .tag { margin-bottom: 20px; }
@media (max-height: 460px) {
  body.touch #gate .card { display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; align-items: center; text-align: left; width: min(640px, 92vw); }
  body.touch #gate .tag { margin-bottom: 0; }
  body.touch #gate .fine { grid-column: 1 / -1; margin-top: 12px; text-align: center; }
  body.touch #gate .rooms { max-height: 34vh; }
}

/* The bottom bar shrinks and stays clear of the thumbs: the stick's home is
   bottom left and the buttons are bottom right, so the centred column gets
   side padding to stay between them. */
body.touch #bottom {
  padding: 40px 150px calc(12px + env(safe-area-inset-bottom)); gap: 6px;
}
body.touch .slot, body.touch #invBtn { width: 76px; }
body.touch .slot .shape, body.touch #invBtn .shape { width: 76px; height: 72px; }
body.touch .slot .pic { left: 4px; top: 9px; width: 68px; height: 62px; }
body.touch .slot .l { font-size: 10px; }
body.touch .slot.empty .l { font-size: 8.5px; }
body.touch .slot .s, body.touch #invBtn .n { display: none; }
body.touch #slots { gap: 9px; }
body.touch #handbar { gap: 9px; }
body.touch #invBtn { width: 62px; height: 62px; border-radius: 12px; padding-bottom: 7px; }
body.touch #invBtn .n { font-size: 11px; }
body.touch #inventory { top: 56px; bottom: calc(96px + env(safe-area-inset-bottom)); width: min(400px, calc(100vw - 180px)); padding: 12px 14px 8px; }
body.touch #invList { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
body.touch #inventory .fine { display: none; }
body.touch .act { padding: 7px 11px 7px 9px; }
body.touch .act .k { display: none; }
body.touch .act:hover { border-color: var(--edge); background: var(--glass); }

/* Chat lives top left under the settings button on a phone. The bottom is
   thumbs, and the keyboard covers the bottom half of the screen while you type. */
body.touch #chat {
  left: 16px; top: 66px; bottom: auto; width: min(320px, 46vw);
}
body.touch #chatLog { max-height: 18vh; }
body.touch #chatInput { padding: 8px 12px; }
body.touch #topleft { top: 14px; left: 16px; }
body.touch #topright { top: 40px; right: 14px; }
body.touch #conn { right: 14px; top: 18px; }
/* Both panels hang from the bar now, so they pull to the same edge on a
   phone as well: leaving the room's old `right` beside the base rule's
   `left` pinned both sides and stretched it across the screen. */
body.touch #settings, body.touch #room { left: 16px; right: auto; top: 62px; }
body.touch #lungs { bottom: calc(96px + env(safe-area-inset-bottom)); }

#touch { display: none; }
body.touch #touch { display: block; }

/* The stick. At rest it sits faintly where the thumb would be, so the left
   side reads as "walk" before anybody has tried it; touched, it moves under
   the finger and follows it. */
#stickBase {
  position: absolute; left: 96px; bottom: 96px; width: 104px; height: 104px;
  margin-left: -52px; margin-top: -52px; border-radius: 50%;
  border: 1px dashed rgba(255, 255, 255, .16); background: rgba(16, 16, 20, .18);
  display: grid; place-items: center; pointer-events: none;
  transition: opacity .2s;
  opacity: .55;
}
#stickBase.live { bottom: auto; opacity: 1; border-style: solid; border-color: rgba(255, 178, 122, .45);
  background: rgba(16, 16, 20, .3); }
#stickKnob {
  display: block; width: 40px; height: 40px; border-radius: 50%;
  background: rgba(233, 231, 226, .18); border: 1px solid rgba(255, 255, 255, .22);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .4);
}
#stickBase.live #stickKnob { background: rgba(255, 178, 122, .35); border-color: rgba(255, 178, 122, .7);
  box-shadow: 0 0 14px rgba(255, 122, 61, .35); }

/* The buttons, bottom right, above the mic pill. USE is the left mouse
   button and is the big one; DROP is the right; jump and squat are the legs
   and are smaller. */
#touchBtns {
  position: absolute; right: 14px; bottom: calc(50px + env(safe-area-inset-bottom));
  display: flex; align-items: flex-end; gap: 10px; pointer-events: none;
}
#touchSide {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 10px; pointer-events: none;
}
.tb {
  pointer-events: auto; touch-action: none; appearance: none; cursor: pointer;
  font: inherit; font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink); width: 56px; height: 56px; border-radius: 50%; padding: 0;
  background: var(--glass); border: 1px solid var(--edge);
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .45);
  transition: border-color .12s, background .12s, transform .08s, color .12s;
}
.tb.big { width: 82px; height: 82px; font-size: 13px; font-weight: 600; color: var(--ember-soft);
  border-color: rgba(255, 140, 80, .45); }
.tb.down, .tb.on {
  background: linear-gradient(180deg, rgba(70, 40, 24, .85), rgba(44, 24, 14, .85));
  border-color: rgba(255, 140, 80, .85); color: var(--ember-soft);
  box-shadow: 0 8px 30px rgba(255, 122, 61, .24), inset 0 1px 0 rgba(255, 190, 140, .2);
}
.tb.down { transform: scale(.96); }
#touchSide .tb { width: 48px; height: 48px; font-size: 10px; border-radius: 12px; }
#touchSide .tb[hidden] { display: none; }
body.chatting #tChat { border-color: rgba(255, 140, 80, .85); color: var(--ember-soft); }

/* A short phone, on its side: pull everything in. */
@media (max-height: 420px) {
  body.touch #bottom { padding-top: 26px; gap: 4px; }
  body.touch #inventory { top: 48px; }
  body.touch #chat { top: 58px; }
  body.touch #chatLog { max-height: 14vh; }
  body.touch #topleft { top: 10px; }
  body.touch #conn { top: 56px; }
  body.touch #settings, body.touch #room { top: 58px; }
  body.touch #topright { top: 80px; }
  #stickBase { left: 84px; bottom: 84px; }
  .tb.big { width: 72px; height: 72px; }
  .tb { width: 50px; height: 50px; }
}
