/*
 * 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 of the same smoked glass as the bar top left, sat
   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: 6px;
  margin-bottom: 7px; pointer-events: auto;
}
#account button {
  appearance: none; cursor: pointer; font: inherit; font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
  background: rgba(30, 20, 14, .5); border: 1px solid var(--edge); border-radius: 999px;
  padding: 0 10px; height: 24px; display: flex; align-items: center; gap: 6px;
  backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
  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, .45); }

/* 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: 12px; letter-spacing: .04em; font-variant-numeric: tabular-nums; }
#walletChip .lb { font-size: 9.5px; 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 { color: #7ee787; }
#walletDelta b.down { color: #e2685a; }
@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: 11.5px; }
#loginChip img { width: 15px; height: 15px; border-radius: 50%; object-fit: cover; margin-left: -3px; }
#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); }
/* 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; }

/* ---------------------------------------------------------------- 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, #tokens {
  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, #tokens.open { opacity: 1; pointer-events: auto; }
.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, #tokens.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. */
#tokens .pcard { width: min(420px, 100%); }
/* 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. */
#tokens .pcard .btn { width: 100%; margin-top: 8px; }
#tokens .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; }
.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; }
#tokens .thead .x { position: static; flex: none; margin: -2px -4px 0 0; }
.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. */
.tconf {
  position: absolute; inset: 0; 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; }
#tokens .tconf .crow .btn { flex: 1; width: auto; margin-top: 0; justify-content: center; }
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);
}
/* 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, and the build, with
   no gap left where the words used to be. */
#connText:empty { display: none; }
/* Which build you are looking at. Dim, but there. */
#buildStamp { color: rgba(160, 154, 146, .45); letter-spacing: .08em; }
#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. */
#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: 11; 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); }

/* ---------------------------------------------------------- green room */
/* The last step before walking in: the microphone, its meter, and the way
   back. It sits over the gate the way the age notice does. */
#ready {
  position: fixed; inset: 0; z-index: 12; display: grid; place-items: safe center; overflow-y: auto;
  background: radial-gradient(120% 90% at 50% 20%, #101726 0%, #05070c 70%);
  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 0; }
#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; }

#gate .card { width: min(420px, 88vw); text-align: center; }
#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; }

/* New: the button that starts one now, the one that opens the rest, and
   the menu it drops. */
#gate .newwrap { position: relative; }
#gate .split { display: grid; grid-template-columns: 1fr auto; gap: 6px; }
#gate #gateNewMore {
  display: flex; align-items: center; justify-content: center; padding: 15px 17px;
  color: #140d08; background: linear-gradient(180deg, var(--ember-soft), var(--ember));
  box-shadow: 0 10px 40px rgba(255, 122, 61, .28);
}
#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, .5); background: rgba(255, 255, 255, .05);
  border: 1px solid var(--edge); box-shadow: none;
}
#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; right: 0; top: calc(100% + 6px); 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 front page's one big button, with a plus on it. */
#gate #gateNew, #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. */
#gate form.code { display: grid; grid-template-columns: 1fr auto; gap: 8px; margin-top: 6px; }
#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. */
#gate fieldset.maps { border: 0; margin: 0 0 4px; padding: 0; }
#gate fieldset.maps legend {
  padding: 0; margin-bottom: 8px; font-size: 10.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--dim);
}
#gate .mpick { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
#gate .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;
}
#gate .mpick label:hover { background: rgba(255, 255, 255, .06); }
#gate .mpick input { position: absolute; opacity: 0; width: 0; height: 0; }
#gate .mpick img {
  display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
  background: #0e141d; border-bottom: 1px solid var(--edge);
}
#gate .mpick b { display: block; padding: 7px 10px 2px; font-size: 13px; font-weight: 500; }
#gate .mpick span {
  display: block; padding: 0 10px 9px; font-size: 11px; line-height: 1.35;
  color: rgba(160, 154, 146, .8);
}
#gate .mpick label.on { border-color: var(--ember); background: rgba(255, 122, 61, .12); }
#gate .mpick label.on b { color: var(--ember-soft); }
@media (max-width: 520px) { #gate .mpick { grid-template-columns: 1fr; } }
/* The same picker on the front page, over the New meeting button: the
   pictures stay, the paragraph under each goes. The front page is a card
   somebody reads in one glance, and two blurbs there push the button that
   is the whole point of it below the fold on a laptop. */
#gate #gateHomeMap { margin-bottom: 12px; }
#gate #gateHomeMap .mpick span { display: none; }
#gate #gateHomeMap .mpick img { aspect-ratio: 16 / 9; }
#gate #gateHomeMap .mpick b { padding: 6px 9px 7px; font-size: 12.5px; }
/* And two abreast even on a phone, where the host form's stack: two small
   pictures are still two pictures, and stacking them here would push New
   meeting off a phone screen. */
@media (max-width: 520px) {
  #gate #gateHomeMap .mpick { grid-template-columns: 1fr 1fr; gap: 8px; }
  #gate #gateHomeMap .mpick b { padding: 5px 7px 6px; font-size: 11.5px; }
}
#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; }
#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; }
.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; }
}
