.who[hidden],
.who-menu[hidden],
body.signed-in .sign-in,
body.signed-out .corner-tools,
body.signed-out .side-toggle,
body.signed-out .side,
body.signed-out nav.lessons,
body.signed-out .paint-sheet,
body.signed-out .avatar-card {
  display: none;
}

@keyframes launch-title {
  0% { opacity: 0; transform: translateY(18px); }
  22% { opacity: 1; transform: translateY(0); }
  58% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-48px); }
}

@media (prefers-reduced-motion: reduce) {
  body.signed-out.launch .launch-title {
    animation: launch-title-still 2.4s ease forwards;
  }
}

@keyframes launch-title-still {
  0% { opacity: 0; }
  20% { opacity: 1; }
  70% { opacity: 1; }
  100% { opacity: 0; }
}

nav.lessons > button.drawer-head,
aside.side > button.side-head {
  position: absolute;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 1.7rem;
  height: 1.7rem;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: #161616;
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

nav.lessons > button.drawer-head {
  top: 0.55rem;
  left: 0.55rem;
}

nav.lessons > button.drawer-head:hover,
aside.side > button.side-head:hover {
  background: #f3f3f3;
}

nav.lessons.rolled > button.drawer-head,
aside.side.rolled > button.side-head {
  top: 0;
  width: max-content;
  height: auto;
  padding: 0.55rem 1.05rem;
  line-height: 1.4;
  background: #fff;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
}

nav.lessons.rolled > button.drawer-head {
  left: 100%;
  transform: translate(0.9rem, 0.9rem);
}

nav.lessons.rolled > button.drawer-head:hover,
aside.side.rolled > button.side-head:hover {
  background: #f6f6f6;
}

aside.side,
aside.avatar-card {
  position: fixed;
  z-index: 3;
  display: flex;
  flex-direction: column;
  width: min(20rem, 92vw);
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  background: #fff;
  box-shadow: -8px 0 28px rgba(0, 0, 0, 0.08);
}

aside.avatar-card {
  z-index: 12;
  top: 50%;
  left: 50%;
  width: min(28rem, calc(100vw - 2.4rem));
  max-height: calc(100vh - 2.4rem);
  padding: 1.35rem 1.45rem 1.55rem;
  border-radius: 1.5rem;
  box-shadow: 0 28px 70px rgba(24, 40, 32, 0.2);
  transform: translate(-50%, -50%);
}

aside.side[hidden],
aside.avatar-card[hidden] {
  display: none;
}

aside.avatar-card .side-hide {
  position: absolute;
  top: 0.85rem;
  right: 0.85rem;
  z-index: 1;
}

.avatar-stage {
  height: 280px;
  margin: 0 0 0.35rem;
  overflow: hidden;
  border-radius: 1.15rem;
  background: #e7f2ea;
  touch-action: none;
  cursor: grab;
}

.avatar-stage.dragging {
  cursor: grabbing;
}

.avatar-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.colour-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.45rem;
  padding: 0.4rem 0.1rem 0;
}

.colour-row span {
  flex: none;
  width: 4.5rem;
  margin: 0;
  color: #5c6560;
  font-size: 0.68rem;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.swatches input[type="color"] {
  width: 2.4rem;
  height: 1.6rem;
  padding: 0;
  border: 0;
  border-radius: 0.35rem;
  background: transparent;
  cursor: pointer;
}

.gh-field {
  display: flex;
  align-items: center;
  margin-top: 0.45rem;
  border: 1px solid #ddd;
  border-radius: 0.7rem;
  background: #fff;
  overflow: hidden;
}

.gh-field:focus-within {
  border-color: #161616;
}

.gh-prefix {
  flex: 0 0 auto;
  padding: 0 0.1rem 0 0.7rem;
  color: #777;
  font-size: 0.9rem;
  white-space: nowrap;
  user-select: none;
}

#github {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0.55rem 0.7rem 0.55rem 0.1rem;
  border: 0;
  background: transparent;
  font: inherit;
  box-sizing: border-box;
}

#github:focus {
  outline: none;
}

.gh-link {
  display: block;
  margin: 0.45rem 0.15rem 0;
  color: #2f6f62;
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}

.gh-link[hidden] {
  display: none;
}

.learner-detail .gh-link {
  margin: 0;
}

aside.house-paint {
  width: min(22rem, calc(100vw - 2rem));
}

aside.piece-paint,
aside.piece-remove,
aside.lesson-prompt {
  width: min(20rem, calc(100vw - 2rem));
}

.paint-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0.65rem 0;
}

.paint-row input[type="color"] {
  width: 2.6rem;
  height: 1.7rem;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

body.viewing-house .side-toggle,
body.viewing-house .side,
body.viewing-house .avatar-card {
  display: none;
}

nav.lessons::-webkit-scrollbar,
aside.settings-card::-webkit-scrollbar,
aside.side::-webkit-scrollbar,
aside.avatar-card::-webkit-scrollbar,
aside.admin-card::-webkit-scrollbar,
article.sheet .sheet-body::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

/* ---- room scene: the house, the yard and the shop -------------------- */

html,
body {
  height: 100%;
}

body.room {
  margin: 0;
  overflow: hidden;
  background: #e7e1d8;
  color: #161616;
  font: 1rem/1.4 "Segoe UI", sans-serif;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.account-bar {
  position: fixed;
  z-index: 8;
  top: 0.9rem;
  left: 50%;
  transform: translateX(-50%);
}

.privacy-link {
  position: fixed;
  z-index: 8;
  right: 0.9rem;
  bottom: 0.7rem;
  color: #333;
  font-size: 0.68rem;
  text-decoration: none;
}

.privacy-link:hover,
.privacy-link:focus {
  text-decoration: none;
}

.account-bar .sign-in,
.who-button {
  display: inline-block;
  max-width: min(22rem, calc(100vw - 11rem));
  padding: 0.55rem 1.05rem;
  overflow: hidden;
  border: 0;
  border-radius: 999px;
  background: #161616;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
  color: #fff;
  font: inherit;
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.who {
  position: relative;
}

.who-button {
  background: #fff;
  color: #161616;
}

.who-menu {
  position: absolute;
  top: calc(100% + 0.45rem);
  left: 50%;
  min-width: 9.5rem;
  margin: 0;
  padding: 0.35rem;
  border-radius: 1rem;
  background: #fff;
  box-shadow: 0 16px 40px rgba(24, 40, 32, 0.18);
  transform: translateX(-50%);
}

.who-menu button {
  display: block;
  width: 100%;
  padding: 0.55rem 0.75rem;
  border: 0;
  border-radius: 0.7rem;
  background: transparent;
  color: #161616;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.who-menu button:hover {
  background: #f6f6f6;
}

.who-menu button[hidden] {
  display: none !important;
}

.who[hidden],
.who-menu[hidden],
.sign-in[hidden],
body.signed-in .sign-in,
body.signed-out .corner-tools,
body.signed-out .side-toggle,
body.signed-out .side,
body.signed-out nav.lessons,
body.signed-out .paint-sheet {
  display: none !important;
}

.launch-title {
  display: none;
}

body.signed-out.launch .launch-title {
  position: fixed;
  z-index: 30;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  background: rgba(22, 28, 24, 0.35);
  color: #fff;
  font-size: clamp(3.2rem, 11vw, 7.5rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  pointer-events: none;
  animation: launch-title 5.2s ease forwards;
}

.corner-tools {
  position: fixed;
  z-index: 6;
  top: 0.9rem;
  left: 0.9rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.45rem;
}

.corner-tools[hidden] {
  display: none;
}

.corner-tools button {
  padding: 0.55rem 0.95rem;
  border: 0;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.corner-tools button[aria-expanded="true"] {
  box-shadow: 0 0 0 2px #161616;
}

button.closer,
button.side-hide {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: #f3f3f3;
  color: #161616;
  line-height: 0;
  cursor: pointer;
}

button.closer svg,
button.side-hide svg {
  display: block;
  width: 0.8rem;
  height: 0.8rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}

nav.lessons,
aside.settings-card {
  position: fixed;
  z-index: 12;
  box-sizing: border-box;
  margin: 0;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  border-radius: 1.25rem;
  background: #fff;
  box-shadow: 0 24px 70px rgba(24, 40, 32, 0.22);
}

nav.lessons {
  top: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  width: min(20rem, calc(100vw - 2.4rem));
  max-height: none;
  padding: 2.6rem 0.9rem 1rem;
  overflow: visible;
  border-radius: 0;
  box-shadow: 8px 0 28px rgba(0, 0, 0, 0.08);
  transition: transform 0.28s ease;
}

nav.lessons.rolled {
  transform: translateX(-100%);
}

body.lesson-open #lessons-roll,
body.lesson-open #shop-roll {
  visibility: hidden;
  pointer-events: none;
}

aside.settings-card {
  top: 4.4rem;
  left: 50%;
  width: min(22rem, calc(100vw - 1.8rem));
  max-height: min(70vh, 36rem);
  padding: 0.75rem 0.95rem 1.15rem;
  transform: translateX(-50%);
}

nav.lessons[hidden],
aside.settings-card[hidden] {
  display: none;
}

.drawer-head {
  display: flex;
  align-items: center;
  gap: 0.28rem;
  min-height: 2.75rem;
  margin-bottom: 0.35rem;
}

.drawer-title {
  flex: 1;
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
}

.drawer-head .drawer-title {
  margin: 0;
}

nav.lessons p {
  margin: 0 0 0.8rem;
  color: #444;
  font-size: 0.92rem;
}

nav.lessons .rows a,
nav.lessons .rows button {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0.9rem 0.1rem;
  border: 0;
  border-top: 1px solid #eee;
  background: transparent;
  color: #161616;
  font: inherit;
  font-size: 1.05rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

nav.lessons .rows a:hover,
nav.lessons .rows button:hover {
  background: #fafafa;
}

nav.lessons ol {
  margin: 0;
  padding: 0;
  overflow: auto;
  flex: 1;
  min-height: 0;
  list-style: none;
  scrollbar-width: none;
}

nav.lessons li {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  border-top: 1px solid #eee;
}

nav.lessons a {
  display: block;
  flex: 1;
  padding: 0.9rem 0.2rem;
  color: #161616;
  font-size: 1.08rem;
  text-decoration: none;
}

.badges {
  display: flex;
  flex: none;
  gap: 0.35rem;
  align-items: center;
  padding-right: 0.15rem;
}

/* A lesson achievement is the same coin as a price. The disc, the turn and
   the gleam are shared with .gem further down; this block only says what a
   lesson coin adds, which is a tier. An unearned tier is an empty ring in
   its own metal. An earned one is filled and wears the darker rim the
   currency coin wears, so its edge reads instead of dissolving into the
   fill - the same rim test that once made these look borderless. */
.badge {
  width: 0.72rem;
  height: 0.72rem;
  background: transparent;
  border: 1px solid transparent;
  vertical-align: middle;
}

.badge.bronze { border-color: #b87333; }

.badge.silver { border-color: #c0c0c0; }

.badge.gold { border-color: #d4af37; }

.badge.on.bronze { background: #b87333; border-color: #7d4a1e; }

.badge.on.silver { background: #c0c0c0; border-color: #8a8a8a; }

.badge.on.gold { background: #d4af37; border-color: #b08b21; }

.float-tip,
.overlay-tip {
  position: fixed;
  z-index: 20;
  max-width: 16rem;
  margin: 0;
  padding: 0.55rem 0.75rem;
  border-radius: 0.8rem;
  background: #161616;
  color: #fff;
  font-size: 0.85rem;
  line-height: 1.35;
  pointer-events: none;
}

.float-tip {
  transform: translate(-50%, calc(-100% - 0.45rem));
}

.overlay-tip[hidden],
.float-tip[hidden] {
  display: none;
}

nav.lessons a:hover {
  background: #fafafa;
}

nav.lessons small {
  display: block;
  margin-top: 0.1rem;
  color: #666;
  font-size: 0.85rem;
}

aside.settings-card .slider,
nav.lessons .slider {
  display: block;
  margin: 1.1rem 0.15rem 0;
  color: #161616;
  font-size: 0.95rem;
}

aside.settings-card .slider input,
nav.lessons .slider input {
  display: block;
  width: 100%;
  margin-top: 0.45rem;
  accent-color: #161616;
}

.account {
  margin: 1.2rem 0.15rem 0.2rem;
  padding-top: 0.9rem;
  border-top: 1px solid #eee;
}

.account p {
  margin: 0 0 0.7rem;
  color: #444;
  font-size: 0.92rem;
}

.account a,
.account button {
  display: inline-block;
  margin: 0 0.4rem 0.4rem 0;
  padding: 0.45rem 0.75rem;
  border: 0;
  border-radius: 999px;
  background: #161616;
  color: #fff;
  font: inherit;
  font-size: 0.92rem;
  text-decoration: none;
  cursor: pointer;
}

.account button {
  background: #f3f3f3;
  color: #161616;
}

.account ul {
  margin: 0.8rem 0 0;
  padding: 0;
  list-style: none;
}

.account li {
  margin: 0;
  padding: 0.55rem 0;
  border-top: 1px solid #eee;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

.account small {
  display: block;
  color: #666;
}

button.side-toggle {
  position: fixed;
  z-index: 4;
  top: 0.9rem;
  right: 0.9rem;
  padding: 0.55rem 0.95rem;
  border: 0;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
  color: #161616;
  font: inherit;
  cursor: pointer;
}

aside.side > button.side-head {
  position: absolute;
  z-index: 2;
  top: 0.55rem;
  right: 0.55rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 1.7rem;
  height: 1.7rem;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: #161616;
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

select.shop-kind {
  position: absolute;
  z-index: 2;
  top: 0.55rem;
  left: 0.75rem;
  height: 1.7rem;
  max-width: calc(100% - 3rem);
  margin: 0;
  padding: 0 0.2rem;
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.lesson-kind-label {
  margin: 0.35rem 0.75rem 0.15rem;
  font: 700 0.85rem/1.2 "Source Sans 3", system-ui, sans-serif;
  color: #5a6575;
  letter-spacing: 0.02em;
}
select.lesson-kind {
  position: absolute;
  z-index: 2;
  top: 0.55rem;
  left: 2.55rem;
  height: 1.7rem;
  max-width: calc(100% - 3.2rem);
  margin: 0;
  padding: 0 0.2rem;
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.roll-label {
  display: none;
}

.roll-arrow {
  display: block;
  width: 0.7rem;
  height: 0.7rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Rolled, both drawers hang their pill outside the viewport edge, so the
   Lessons pill and the Shop pill sit on one line across the top of the room.
   The drawer itself starts at the top of the window, so `top: 0` plus the
   0.9rem slide puts each pill's top gap on exactly the same 0.9rem as the
   account bar in the middle. */
aside.side.rolled > button.side-head {
  top: 0;
  width: max-content;
  height: auto;
  padding: 0.55rem 1.05rem;
  line-height: 1.4;
  background: #fff;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
  right: 100%;
  transform: translate(-0.9rem, 0.9rem);
}

nav.lessons.rolled .roll-label,
aside.side.rolled .roll-label {
  display: inline;
}

nav.lessons.rolled .roll-arrow,
aside.side.rolled .roll-arrow {
  display: none;
}

aside.side {
  position: fixed;
  z-index: 12;
  display: flex;
  flex-direction: column;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(20rem, calc(100vw - 2.4rem));
  padding-top: 2.6rem;
  overflow: visible;
  scrollbar-width: none;
  -ms-overflow-style: none;
  background: #fff;
  box-shadow: -8px 0 28px rgba(0, 0, 0, 0.08);
  transition: transform 0.28s ease;
}

aside.side.rolled {
  transform: translateX(100%);
}

aside.side[hidden] {
  display: none;
}

.side-head {
  display: flex;
  align-items: center;
}

.tabs {
  display: flex;
  flex: none;
  border-bottom: 1px solid #eee;
}

.tabs button {
  flex: 1;
  margin: 0;
  padding: 0.9rem 0.4rem;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: #444;
  font: inherit;
  cursor: pointer;
}

.tabs button[aria-selected="true"] {
  border-bottom-color: #161616;
  color: #161616;
  font-weight: 650;
}

.tabs.sub button {
  font-size: 0.9rem;
}

.catalog[hidden],
.place-hint[hidden] {
  display: none;
}

.catalog {
  display: grid;
  flex: 1;
  min-height: 0;
  overflow: auto;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0.45rem 0.15rem;
  padding: 0.35rem 0.45rem 0.7rem;
  scrollbar-width: none;
}

.catalog .card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.05rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  font-size: 0.72rem;
  cursor: pointer;
}

.catalog .card[aria-pressed="true"] span {
  font-weight: 650;
}

.catalog .price {
  color: #666;
  font-size: 0.68rem;
}

/* The rooftop card that is standing on the house right now. Tapping it a
   second time is the purchase, and this word is the invitation. */
.catalog .card .buy-tag {
  position: absolute;
  top: 0.2rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.08rem 0.45rem;
  border-radius: 999px;
  background: #161616;
  color: #fff;
  font-size: 0.62rem;
  font-weight: 650;
  line-height: 1.5;
  pointer-events: none;
}

.catalog .card .buy-tag[hidden] {
  display: none;
}

.catalog .card.previewing img {
  border-radius: 0.5rem;
  box-shadow: 0 0 0 2px #161616;
}

/* ---- the coin ---------------------------------------------------------
   One coin, one definition. The currency mark (.gem: account bar, shop
   price, job budget, toast) and the lesson achievement (.badge.on) are the
   same disc - same geometry, same turn, same gleam - so a price and a prize
   read as the same money. Only the size and the fill differ, and those are
   the two short rules below.

   The markup still carries the coin glyph inside the .gem span (every file
   that names a price says so in plain text). text-indent pushes that glyph out
   of the disc and overflow clips it, so the coin you see is the rule alone.
   Sizing is in em, so the coin follows the text around it.

   A badge has no glyph, so it needs none of that; it keeps a fixed 0.72rem
   in .badge because the lesson list sets its own text size. */
.gem,
.badge {
  position: relative;
  display: inline-block;
  box-sizing: border-box;
  overflow: hidden;
  border-radius: 50%;
}

/* Only a filled coin turns. An unearned tier is an empty ring, and a ring
   spinning about its axis is invisible work. */
.gem,
.badge.on {
  animation: coin-turn var(--coin-turn, 3.2s) linear infinite;
  animation-delay: var(--coin-delay, 0s);
}

.gem {
  width: 0.78em;
  height: 0.78em;
  margin: 0 0.1em 0 0.14em;
  border: 1px solid #b08b21;
  background: #d4af37;
  vertical-align: -0.1em;
  text-indent: -2em;
  white-space: nowrap;
}

/* The turn. perspective() sits on the coin itself, so it turns in three
   dimensions wherever it appears, without a parent having to set up a
   stage for it. A coin seen edge-on is a line for an instant, which is what
   makes it read as turning rather than squashing. */
@keyframes coin-turn {
  from { transform: perspective(90px) rotateY(0deg); }
  to { transform: perspective(90px) rotateY(360deg); }
}

/* The gleam: a band of white that crosses the face once, then stops. It is
   put on by account.js at random, so the coins on a page sparkle one at a
   time rather than in a chorus. */
.gem.shine::after,
.badge.shine::after {
  content: "";
  position: absolute;
  top: -30%;
  bottom: -30%;
  left: 0;
  width: 62%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.95), transparent);
  animation: coin-gleam 0.5s ease;
  text-indent: 0;
}

@keyframes coin-gleam {
  from { transform: translateX(-140%); }
  to { transform: translateX(320%); }
}

@media (prefers-reduced-motion: reduce) {
  .gem, .badge.on { animation: none; }
  .gem.shine::after, .badge.shine::after { animation: none; opacity: 0; }
}

#username {
  display: block;
  width: 100%;
  margin-top: 0.45rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid #ddd;
  border-radius: 0.7rem;
  font: inherit;
  box-sizing: border-box;
}

button.save-name {
  margin: 0.9rem 0.15rem 0.2rem;
  padding: 0.45rem 0.8rem;
  border: 0;
  border-radius: 999px;
  background: #161616;
  color: #fff;
  font: inherit;
  cursor: pointer;
}

button.save-name:disabled.gig-state {
  background: transparent;
  color: #161616;
  cursor: default;
}

aside.admin-card {
  position: fixed;
  z-index: 12;
  top: 50%;
  left: 50%;
  box-sizing: border-box;
  width: min(40rem, calc(100vw - 2rem));
  max-height: min(82vh, 46rem);
  margin: 0;
  padding: 1rem 1.15rem 1.2rem;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  border-radius: 1.25rem;
  background: #fff;
  box-shadow: 0 24px 70px rgba(24, 40, 32, 0.22);
  transform: translate(-50%, -50%);
}

aside.admin-card[hidden] {
  display: none;
}

/* The admin view is a reading room, not a card: it takes nearly the whole
   screen, because a review is a letter of several paragraphs and a
   half-width column makes it a chore. The header stays put and only the pane
   below it scrolls, so the tab you are on never leaves the screen. */
aside.admin-card.admin-wide {
  display: flex;
  flex-direction: column;
  /* Above the shop drawer (z-index 12). The panel is inset from the edge by
     the same amount as the shop's rolled pill, so an equal z-index let the
     pill paint over the reviews. */
  z-index: 16;
  width: min(86rem, calc(100vw - 2.4rem));
  height: min(56rem, calc(100vh - 2.4rem));
  max-height: calc(100vh - 2.4rem);
  padding: 0;
  overflow: hidden;
  border-radius: 1.1rem;
}

/* The shop's pill hangs outside the shop's own right edge, and the admin
   panel leaves a small margin at the viewport edge. Rather than let the pill
   sit in that margin over the reviews, the shop is taken off the page while
   the panel is open; closing it brings the shop back as it was. */
body.admin-open .side,
body.admin-open .side-toggle,
body.admin-open .overlay-tip {
  display: none;
}

aside.admin-card.admin-wide[hidden] {
  display: none;
}

.admin-top {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex: none;
  padding: 0.8rem 1rem 0.8rem 1.25rem;
  border-bottom: 1px solid #eee;
}

.admin-tabs {
  display: flex;
  gap: 0.35rem;
  flex: 1;
  min-width: 0;
}

.admin-tab {
  padding: 0.45rem 1rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: #444;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}

.admin-tab[aria-selected="true"] {
  background: #161616;
  color: #fff;
}

.admin-close {
  flex: none;
  padding: 0.4rem 0.8rem;
  border: 1px solid #e2e2e2;
  border-radius: 999px;
  background: #fff;
  color: #333;
  font: inherit;
  cursor: pointer;
}

.admin-pane {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding: 1.1rem 1.35rem 1.8rem;
}

.admin-pane[hidden] {
  display: none;
}

/* Class progress lives in one matrix: learners down, lessons across. */
.learners {
  margin: 0;
  padding: 0;
}

.progress-scroll {
  width: 100%;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

.progress-table {
  width: max-content;
  min-width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.88rem;
}

.progress-table th,
.progress-table td {
  padding: 0.45rem 0.4rem;
  border-bottom: 1px solid #eee;
  text-align: center;
  vertical-align: middle;
}

.progress-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #fff;
  font-weight: 650;
  color: #333;
}

.progress-table .progress-name {
  position: sticky;
  left: 0;
  z-index: 3;
  text-align: left;
  min-width: 9.5rem;
  max-width: 14rem;
  padding-left: 0.15rem;
  padding-right: 0.7rem;
  background: #fff;
}

.progress-table thead .progress-name {
  z-index: 4;
}

.progress-table .progress-coins {
  min-width: 4.2rem;
  white-space: nowrap;
}

.progress-table .progress-lesson {
  width: 2.4rem;
  min-width: 2.4rem;
  max-width: 2.6rem;
  padding-top: 0.55rem;
  padding-bottom: 0.55rem;
  vertical-align: bottom;
}

.progress-table .progress-lesson span {
  display: inline-block;
  max-height: 7.5rem;
  overflow: hidden;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.1;
}

.progress-cell {
  width: 2.4rem;
}

.progress-cell .badge {
  width: 0.85rem;
  height: 0.85rem;
}

.progress-none {
  color: #d0d0d0;
  font-size: 0.75rem;
}

.job-mark {
  display: inline-block;
  min-width: 1rem;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1;
}

.job-mark.pass { color: #2f7a45; }
.job-mark.wait { color: #8a6a18; }
.job-mark.reject { color: #a0452e; }

.progress-row:hover > * {
  background: #fafaf7;
}

.progress-give-row td {
  padding: 0.55rem 0.35rem 0.85rem;
  text-align: left;
  background: #fafaf7;
}

.learner-give .house-button {
  margin-top: 0.55rem;
}

/* Reviews are letters, so they get a wider column and a fixed order: newest
   at the top, each block self-contained. */
#job-reviews {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30rem, 1fr));
  gap: 0 2rem;
  align-items: start;
}

#job-reviews > .job-lead,
#job-reviews > .job-status {
  grid-column: 1 / -1;
}

.review-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 0.9rem;
}

.review-filters button {
  padding: 0.4rem 0.85rem;
  border: 1px solid #e2e2e2;
  border-radius: 999px;
  background: #fff;
  color: #333;
  font: inherit;
  cursor: pointer;
}

.review-filters button[aria-pressed="true"] {
  border-color: #161616;
  background: #161616;
  color: #fff;
}

.review-choice {
  padding: 0.45rem 0.9rem;
  border: 1px solid #ddd;
  border-radius: 999px;
  background: #fff;
  color: #161616;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}

.review-choice[aria-pressed="true"] {
  border-color: #161616;
  background: #161616;
  color: #fff;
}

.review-pay {
  font-weight: 650;
}

.review-who {
  color: #333;
}

.review-letter-sent {
  color: #555;
}

/* Every send behind the current one, folded away. The summary is the count,
   so the reviewer can tell a resubmitted gig from a first attempt without
   opening anything. */
.review-history {
  margin: 0.5rem 0 0.9rem;
  padding: 0.45rem 0.75rem;
  border: 1px solid #ececec;
  border-radius: 0.7rem;
  background: #fafafa;
  overflow-wrap: anywhere;
}

.review-history > summary {
  color: #333;
  font-weight: 650;
  cursor: pointer;
}

.review-attempt {
  margin: 0.55rem 0 0.2rem;
  padding-top: 0.55rem;
  border-top: 1px solid #e7e7e7;
}

.review-attempt p {
  margin: 0.2rem 0;
}

.review-attempt-head {
  color: #666;
  font-size: 0.86rem;
}

@media (max-width: 44rem) {
  aside.admin-card.admin-wide {
    width: calc(100vw - 0.8rem);
    height: calc(100vh - 1.4rem);
    max-height: calc(100vh - 1.4rem);
    border-radius: 0.9rem;
  }
  .admin-top {
    gap: 0.4rem;
    padding: 0.6rem 0.6rem 0.6rem 0.8rem;
  }
  .admin-tab {
    padding: 0.4rem 0.65rem;
  }
  .admin-close {
    padding: 0.35rem 0.6rem;
  }
  .admin-pane {
    padding: 0.8rem 0.85rem 1.4rem;
  }
  #job-reviews {
    grid-template-columns: 1fr;
  }
  .progress-table .progress-name {
    min-width: 7.5rem;
    max-width: 10rem;
  }
}

/* One shared colour panel for the avatar, house items and the house itself.
   Nothing but the swatches: no card, no title, no border. The row floats on the
   bottom of the room, centred, so the colours are the only thing on screen and
   a learner sees exactly what they are changing above it. Tapping the empty
   strip or anywhere else closes it and asks about unsaved colours. */
.paint-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  box-sizing: border-box;
  width: 100%;
  max-height: 58vh;
  overflow: auto;
  scrollbar-width: none;
  padding: 0.5rem 0.8rem calc(0.85rem + env(safe-area-inset-bottom, 0px));
  background: none;
  box-shadow: none;
}

.paint-sheet::-webkit-scrollbar {
  display: none;
}

.paint-sheet[hidden] {
  display: none;
}

/* The confirm popup: a small centred card on a veil, asked once when the
   panel closes with colours that cost gems still unsaved. */
.paint-ask-veil {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(24, 40, 32, 0.26);
}

.paint-ask-veil[hidden] {
  display: none;
}

aside.paint-ask {
  z-index: 41;
  width: min(19rem, calc(100vw - 2rem));
  text-align: center;
}

.paint-ask p {
  margin: 0.1rem 0;
}

/* Cancel is a real button here, not quiet text: this is the one decision in
   the flow and it must be as easy to hit as Confirm. */
.paint-ask #paint-ask-no {
  background: #f1f1f1;
}

.paint-ask .job-actions {
  margin-top: 0.9rem;
}

/* The swatches are the whole content: one centred row of round chips, sized
   to a thumb and wrapped only when the widest screen is not wide enough. */
.paint-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
}

.paint-swatch {
  flex: 0 0 auto;
  box-sizing: border-box;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  filter: drop-shadow(0 2px 5px rgba(24, 40, 32, 0.28));
  transition: transform 0.14s ease;
}

.paint-swatch:active {
  transform: scale(0.94);
}

.paint-swatch::-webkit-color-swatch-wrapper {
  padding: 0;
}

.paint-swatch::-webkit-color-swatch {
  border: 2px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
}

.paint-swatch::-moz-color-swatch {
  border: 2px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
}

aside.piece-menu {
  position: fixed;
  z-index: 14;
  top: 0;
  left: 0;
  width: max-content;
  max-width: min(14rem, calc(100vw - 1rem));
  margin: 0;
  padding: 0.22rem;
  border-radius: 0.75rem;
  background: #fff;
  box-shadow: 0 12px 36px rgba(24, 40, 32, 0.18);
}

aside.piece-menu[hidden] {
  display: none;
}

.piece-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.05rem;
  margin: 0;
}

.piece-actions button {
  margin: 0;
  padding: 0.32rem 0.7rem;
  border: 0;
  border-radius: 0.55rem;
  background: transparent;
  color: #161616;
  font: inherit;
  line-height: 1.25;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}

.piece-actions button[aria-pressed="true"] {
  background: #161616;
  color: #fff;
}

.piece-actions button[aria-expanded="true"] {
  background: #161616;
  color: #fff;
}

.piece-use-menu[hidden] {
  display: none;
}

aside.piece-remove,
aside.lesson-prompt {
  width: min(20rem, calc(100vw - 2rem));
}

aside.lesson-prompt {
  z-index: 13;
  width: min(28rem, calc(100vw - 2rem));
}

aside.lesson-prompt p {
  margin: 0.2rem 0 0.3rem;
}

#piece-ask-text {
  margin: 0.2rem 0 0.3rem;
}

aside.job-pitch {
  z-index: 13;
}

.admin-note {
  margin: 0 0 0.6rem;
  color: #444;
}

.learner-name,
.house-button,
.give-button {
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.learner-name {
  max-width: 100%;
  padding: 0.15rem 0;
  overflow: hidden;
  font-weight: 650;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.learner-name:hover,
.learner-name:focus-visible {
  text-decoration: underline;
}

.learner-gems {
  color: #333;
  white-space: nowrap;
}

.house-button,
.give-button {
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  background: #161616;
  color: #fff;
}

.learner-detail {
  max-width: 28rem;
}

.learner-detail p {
  margin: 0.2rem 0;
}

.learner-give-who {
  margin: 0 0 0.45rem;
  color: #555;
  font-size: 0.86rem;
  overflow-wrap: anywhere;
}

.learner-detail .muted {
  color: #666;
  font-size: 0.82rem;
}

.give {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.35rem;
}

.give input {
  width: 6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid #ddd;
  border-radius: 0.7rem;
  font: inherit;
}

.visit-bar {
  position: fixed;
  z-index: 8;
  top: 4.3rem;
  left: 50%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  padding: 0.4rem 0.45rem 0.4rem 0.95rem;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 10px rgba(0, 0, 0, 0.12);
  transform: translateX(-50%);
}

.visit-bar[hidden] {
  display: none;
}

.visit-bar button {
  padding: 0.4rem 0.75rem;
  border: 0;
  border-radius: 999px;
  background: #161616;
  color: #fff;
  font: inherit;
  cursor: pointer;
}

body.viewing-house .side-toggle,
body.viewing-house .side,
body.viewing-house .paint-sheet {
  display: none;
}

button.linkish {
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}

button.linkish[aria-pressed="true"] {
  text-decoration: underline;
}

.job-lead,
.job-brief,
.job-status,
.review-block p {
  margin: 0.35rem 0;
}

.job-lead,
.job-status,
.review-block .muted {
  color: #444;
}

.job-title {
  margin: 0 0 0.35rem;
  font-weight: 650;
}

.job-stage {
  /* Portrait crop: a wide stage left empty glass on both sides of the NPC,
     which read as a wasted left gutter once the letter sat beside it. */
  flex: none;
  width: 7.25rem;
  height: 9.25rem;
  touch-action: none;
  cursor: grab;
}

.job-stage.dragging {
  cursor: grabbing;
}

.job-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.job-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.55rem;
  margin-top: 1rem;
}

/* The gig board is a reading room, not a card. Two panes side by side: the
   posts down the left, the letter on the right. It needs the width because a
   list of nine titles and a letter of several paragraphs are two different
   shapes, and stacked they turn browsing into a scroll. */
aside.admin-card#jobs {
  /* Above the shop drawer (z-index 12), for the same reason the admin panel
     is: the rolled shop pill hangs in the margin this room now reaches into. */
  z-index: 16;
  width: min(74rem, calc(100vw - 2.4rem));
  height: min(52rem, calc(100vh - 2.4rem));
  max-height: calc(100vh - 2.4rem);
  padding: 0;
  overflow: hidden;
  border-radius: 1.1rem;
}

aside.admin-card#jobs:not([hidden]) {
  display: flex;
  flex-direction: column;
}

.job-room-top {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex: none;
  padding: 0.7rem 0.8rem 0.7rem 1.2rem;
  border-bottom: 1px solid #eee;
}

.job-room-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
}

.job-room-body {
  display: grid;
  /* Titles wrap to two lines; give the index enough width that they do not
     feel crushed beside the letter. */
  grid-template-columns: minmax(16rem, 22rem) minmax(0, 1fr);
  flex: 1 1 auto;
  min-height: 0;
}

/* The index. Each post is a button, because picking one is the only thing the
   list does; the current one is filled in so the letter on the right always
   has a visible source. */
.job-list {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-height: 0;
  padding: 0.6rem 0.55rem 1rem;
  overflow: auto;
  border-right: 1px solid #eee;
  background: #fbfbf9;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.job-list::-webkit-scrollbar {
  display: none;
}

.job-post {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 0.55rem 0.65rem;
  border: 0;
  border-radius: 0.7rem;
  background: transparent;
  color: #161616;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.job-post:hover {
  background: #f0f0ec;
}

.job-post[aria-current="true"] {
  background: #161616;
  color: #fff;
}

/* Finished work stays listed and clickable, but greyed so the board reads as
   "done" at a glance. Current still fills in, quieter than an open post. */
.job-post.done {
  color: #8a8a8a;
  opacity: 0.72;
}

.job-post.done:hover {
  background: #f3f3f0;
  color: #6f6f6f;
}

.job-post.done[aria-current="true"] {
  background: #7a7a7a;
  color: #f2f2f2;
  opacity: 0.9;
}

.job-post.done[aria-current="true"] .job-post-meta {
  color: #d8d8d8;
}

.job-submission {
  margin: 0.85rem 0 0;
  padding: 0.7rem 0.85rem;
  border: 1px solid #e8e8e8;
  border-radius: 0.8rem;
  background: #fafaf8;
}

.job-submission.locked {
  border-style: dashed;
  background: #f3f3f1;
  color: #555;
}

.job-submission-lead {
  margin: 0 0 0.35rem;
  font-size: 0.82rem;
  font-weight: 650;
  color: #666;
}

.job-submission-url {
  margin: 0.2rem 0;
  overflow-wrap: anywhere;
}

.job-submission-note {
  margin: 0.45rem 0 0;
  color: #444;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Two lines of title, then an ellipsis: a post's title is the way in, and a
   list where every row is five lines tall is not a list any more. The title is
   set smaller than the letter's own heading because it is an index entry, not
   the thing being read: nine of them have to fit beside the letter. */
.job-post-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 0.84rem;
  font-weight: 600;
  line-height: 1.32;
  overflow-wrap: anywhere;
}

.job-post-meta {
  display: block;
  margin-top: 0.22rem;
  color: #777;
  font-size: 0.74rem;
}

.job-post[aria-current="true"] .job-post-meta {
  color: #cfcfcf;
}

/* The reading pane. Positioned so the review note covers the letter only. */
.job-read {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

#jobs #job-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 1rem 1.15rem 1.35rem;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

#jobs #job-body::-webkit-scrollbar {
  display: none;
}

/* The reading pane is the letter's room: use its width. A capped centred
   column left a dead gutter beside the NPC and starved the brief of space
   the pane already had. */
#jobs .job-client {
  width: 100%;
  max-width: none;
  margin: 0;
  gap: 0.7rem;
}

#jobs .job-copy {
  flex: 1 1 auto;
  min-width: 0;
}

#jobs #job-body > .job-said,
#jobs #job-body > .job-actions {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* Mailbox letter: one post at a time. The left index is the laptop's way to
   jump around; from the box you only have Next letter, so the list stays off. */
aside.admin-card#jobs.job-mail {
  width: min(42rem, calc(100vw - 2.4rem));
  height: min(46rem, calc(100vh - 2.4rem));
}

aside.admin-card#jobs.job-mail .job-list {
  display: none;
}

aside.admin-card#jobs.job-mail .job-room-body {
  grid-template-columns: minmax(0, 1fr);
}

aside.admin-card#jobs.job-mail .job-note {
  border-radius: 0 0 1.1rem 1.1rem;
}

/* Laptop freelance board: same dark glass as chat, list still beside the letter. */
aside.admin-card#jobs.job-digital {
  border: 1px solid #23323d;
  border-radius: 0;
  background: #0d141a;
  color: #cfe6f2;
  box-shadow: 0 0 0 1px #0a1015, 0 30px 80px rgba(4, 12, 18, 0.62),
    0 0 42px rgba(42, 168, 224, 0.16);
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  background-image:
    linear-gradient(rgba(42, 168, 224, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(42, 168, 224, 0.045) 1px, transparent 1px);
  background-size: 26px 26px;
}

aside.admin-card#jobs.job-digital .job-room-top {
  border-bottom-color: #23323d;
  background: #111b22;
}

aside.admin-card#jobs.job-digital .job-room-title {
  color: #dff3ff;
  font-size: 0.95rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: 0 0 12px rgba(42, 168, 224, 0.55);
}

aside.admin-card#jobs.job-digital .job-list {
  border-right-color: #23323d;
  background: #0a1116;
}

aside.admin-card#jobs.job-digital .job-post {
  color: #cfe6f2;
  border-radius: 0;
}

aside.admin-card#jobs.job-digital .job-post:hover {
  background: #152029;
}

aside.admin-card#jobs.job-digital .job-post[aria-current="true"] {
  background: #1a3344;
  color: #e8f7ff;
  box-shadow: inset 2px 0 0 #2aa8e0;
}

aside.admin-card#jobs.job-digital .job-post.done {
  color: #5d7b8c;
  opacity: 1;
}

aside.admin-card#jobs.job-digital .job-post.done:hover {
  background: #121a20;
  color: #7a9aab;
}

aside.admin-card#jobs.job-digital .job-post.done[aria-current="true"] {
  background: #24323c;
  color: #a8c4d4;
}

aside.admin-card#jobs.job-digital .job-post-meta {
  color: #5d7b8c;
}

aside.admin-card#jobs.job-digital .job-post[aria-current="true"] .job-post-meta {
  color: #7eb6cf;
}

aside.admin-card#jobs.job-digital .job-title,
aside.admin-card#jobs.job-digital .job-brief,
aside.admin-card#jobs.job-digital .job-said {
  color: #cfe6f2;
}

aside.admin-card#jobs.job-digital .job-submission {
  border-color: #26404f;
  background: #111b22;
  color: #b7d4e4;
}

aside.admin-card#jobs.job-digital .job-submission.locked {
  background: #0a1116;
  color: #7a9aab;
}

aside.admin-card#jobs.job-digital .job-submission-lead {
  color: #5d7b8c;
}

aside.admin-card#jobs.job-digital .job-note {
  border-radius: 0;
  background: rgba(8, 14, 18, 0.78);
}

aside.admin-card#jobs.job-digital .job-note-card {
  border: 1px solid #26404f;
  border-radius: 0;
  background: #111b22;
  color: #cfe6f2;
}

aside.admin-card#jobs.job-digital button.job-next {
  color: #9ec9de;
  border-radius: 0;
}

aside.admin-card#jobs.job-digital button.job-next:hover {
  background: #152029;
  color: #dff3ff;
}

aside.admin-card#jobs.job-digital .save-name {
  border-radius: 0;
  border: 1px solid #2aa8e0;
  background: #123246;
  color: #dff3ff;
}

aside.admin-card#jobs.job-digital .save-name:hover {
  background: #1a4560;
}

aside.admin-card#jobs.job-digital .save-name:disabled,
aside.admin-card#jobs.job-digital .save-name.gig-state:disabled {
  border-color: #26404f;
  background: #152029;
  color: #5d7b8c;
}

/* A phone cannot hold two panes side by side: the list goes above the letter
   and is capped, so the letter below it still gets most of the screen. This
   block sits after the room's own rules on purpose - the two-pane grid above is
   what it is overriding, and an earlier copy of this query lost the fight. */
@media (max-width: 56rem) {
  aside.admin-card#jobs {
    width: calc(100vw - 0.8rem);
    height: calc(100vh - 1.4rem);
    max-height: calc(100vh - 1.4rem);
    border-radius: 0.9rem;
  }
  aside.admin-card#jobs.job-digital {
    border-radius: 0;
  }
  aside.admin-card#jobs.job-mail {
    width: calc(100vw - 0.8rem);
    height: calc(100vh - 1.4rem);
  }
  aside.admin-card#jobs.job-mail .job-room-body {
    grid-template-rows: minmax(0, 1fr);
  }
  .job-room-top {
    padding: 0.55rem 0.6rem 0.55rem 0.8rem;
  }
  .job-room-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 34vh) minmax(0, 1fr);
  }
  aside.admin-card#jobs.job-mail .job-room-body {
    grid-template-rows: minmax(0, 1fr);
  }
  .job-list {
    border-right: 0;
    border-bottom: 1px solid #eee;
  }
  aside.admin-card#jobs.job-digital .job-list {
    border-bottom-color: #23323d;
  }
  .job-note {
    border-radius: 0 0 0.9rem 0.9rem;
  }
  #jobs #job-body {
    padding: 0.9rem 0.85rem 1.4rem;
  }
}

/* What the client said about a gig that has been looked at. It covers the gig
   underneath, and the cover is also the lock: every tap lands on the note, so
   nothing behind it can be pressed while the message is up. A tap anywhere
   closes it, which is why the veil itself is the button. */
.job-note {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 1.1rem;
  /* The reading pane's own corners: square against the list, round against the
     card's right edge. */
  border-radius: 0 1.1rem 1.1rem 0;
  background: rgba(255, 255, 255, 0.74);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  cursor: pointer;
  animation: job-note-in 0.22s ease-out both;
}

.job-note[hidden] {
  display: none;
}

.job-note-card {
  width: min(26rem, 100%);
  max-height: 100%;
  overflow: auto;
  box-sizing: border-box;
  padding: 1.2rem 1.3rem 1.1rem;
  border-radius: 1rem;
  background: #fff;
  box-shadow: 0 18px 44px rgba(24, 40, 32, 0.18);
  cursor: auto;
  text-align: center;
}

.job-note-lead {
  margin: 0 0 0.4rem;
  font-weight: 650;
}

/* The client's own words. They are shown as written, line breaks and all, and
   never as markup: nothing a reviewer types can become part of the page. */
.job-note-text {
  margin: 0;
  color: #444;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.job-note .save-name {
  margin-top: 1rem;
}

/* The same words, kept on the gig after the note is closed, so a learner
   fixing a rejected job still has the reason in front of them. */
.job-said {
  margin: 0.6rem 0 0;
  padding: 0.5rem 0.8rem;
  border-left: 2px solid #ddd;
  color: #444;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

@keyframes job-note-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .job-note { animation: none; }
}

.job-actions .save-name {
  margin: 0;
}

button.job-next {
  margin: 0;
  padding: 0.45rem 0.8rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.job-client {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
}

.job-back {
  margin: 0 0 0.6rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: #161616;
  font: inherit;
  cursor: pointer;
}

.job-form input,
.job-form textarea,
.review-block textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 0.35rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid #ddd;
  border-radius: 0.7rem;
  font: inherit;
}

.job-form textarea,
.review-block textarea {
  min-height: 7rem;
  resize: vertical;
}

#offer-form textarea {
  min-height: 4.5rem;
}

#offer-form input[type="range"] {
  padding: 0.4rem 0;
  border: 0;
  background: transparent;
  accent-color: #161616;
}

/* Laptop brief + pitch: same dark glass as chat. Mailbox keep the paper card. */
aside.admin-card#job-offer.offer-digital,
aside.admin-card#job-pitch.pitch-digital {
  border: 1px solid #23323d;
  border-radius: 0;
  background: #0d141a;
  color: #cfe6f2;
  box-shadow: 0 0 0 1px #0a1015, 0 30px 80px rgba(4, 12, 18, 0.62),
    0 0 42px rgba(42, 168, 224, 0.16);
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  background-image:
    linear-gradient(rgba(42, 168, 224, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(42, 168, 224, 0.045) 1px, transparent 1px);
  background-size: 26px 26px;
}

aside.admin-card#job-offer.offer-digital .job-brief,
aside.admin-card#job-offer.offer-digital .job-letter,
aside.admin-card#job-offer.offer-digital .job-status,
aside.admin-card#job-pitch.pitch-digital .job-brief,
aside.admin-card#job-pitch.pitch-digital .job-letter,
aside.admin-card#job-pitch.pitch-digital .job-status {
  color: #cfe6f2;
}

aside.admin-card#job-offer.offer-digital .job-form input,
aside.admin-card#job-offer.offer-digital .job-form textarea,
aside.admin-card#job-pitch.pitch-digital .job-form input,
aside.admin-card#job-pitch.pitch-digital .job-form textarea {
  border: 1px solid #26404f;
  border-radius: 0;
  background: #0a1116;
  color: #dff3ff;
}

aside.admin-card#job-offer.offer-digital .job-form input:focus,
aside.admin-card#job-offer.offer-digital .job-form textarea:focus,
aside.admin-card#job-pitch.pitch-digital .job-form input:focus,
aside.admin-card#job-pitch.pitch-digital .job-form textarea:focus {
  outline: 1px solid #2aa8e0;
  outline-offset: 1px;
}

aside.admin-card#job-offer.offer-digital #offer-budget {
  accent-color: #2aa8e0;
}

aside.admin-card#job-offer.offer-digital button.job-next,
aside.admin-card#job-pitch.pitch-digital button.job-next {
  color: #9ec9de;
  border-radius: 0;
}

aside.admin-card#job-offer.offer-digital .save-name,
aside.admin-card#job-pitch.pitch-digital .save-name {
  border-radius: 0;
  border: 1px solid #2aa8e0;
  background: #123246;
  color: #dff3ff;
}

aside.admin-card#job-offer.offer-digital .save-name:hover,
aside.admin-card#job-pitch.pitch-digital .save-name:hover {
  background: #1a4560;
}

aside.admin-card#job-offer.offer-digital .save-name:disabled,
aside.admin-card#job-pitch.pitch-digital .save-name:disabled {
  border-color: #26404f;
  background: #152029;
  color: #5d7b8c;
}

.job-letter input {
  display: inline-block;
  width: min(18rem, 100%);
  margin: 0.35rem 0.2rem 0;
  vertical-align: middle;
}

.job-letter input.job-prompt {
  display: block;
  width: 100%;
  margin: 0.35rem 0 0;
}

.job-count {
  margin: 0.25rem 0 0;
  color: #666;
  font-size: 0.82rem;
}

.review-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.7rem;
}

.review-block {
  margin: 0;
  padding: 0.9rem 0;
  border-top: 1px solid #eee;
  overflow-wrap: anywhere;
}

.review-block a {
  color: #161616;
}

nav.lessons::-webkit-scrollbar,
aside.settings-card::-webkit-scrollbar,
aside.side::-webkit-scrollbar,
aside.admin-card::-webkit-scrollbar,
article.sheet .sheet-body::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

.catalog img {
  width: 100%;
  height: auto;
  background: transparent;
}

.place-hint {
  margin: 0 0.9rem 0.7rem;
  color: #444;
  font-size: 0.82rem;
}
@keyframes launch-title {
  0% { opacity: 0; transform: translateY(18px); }
  22% { opacity: 1; transform: translateY(0); }
  58% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-48px); }
}

@media (prefers-reduced-motion: reduce) {
  body.signed-out.launch .launch-title {
    animation: launch-title-still 2.4s ease forwards;
  }
}

@keyframes launch-title-still {
  0% { opacity: 0; }
  20% { opacity: 1; }
  70% { opacity: 1; }
  100% { opacity: 0; }
}

/* ---------------- the laptop's chat ----------------
   The panel is the laptop's own screen: dark glass, a cyan line, square
   corners, mono type. That is not decoration for its own sake - it is the one
   panel in the room that is a device rather than a card, so it is drawn the
   way the device is drawn in the scene (#1b2733 with a #2aa8e0 glow).

   Layout is unchanged from the card version: an index down the left, the
   thread on the right, and the box you type in never leaves the screen. */

aside.admin-card#chat {
  /* Above the shop drawer, for the same reason the other rooms are: the rolled
     shop pill hangs in the margin this panel reaches into. */
  z-index: 16;
  width: min(74rem, calc(100vw - 2.4rem));
  height: min(52rem, calc(100vh - 2.4rem));
  max-height: calc(100vh - 2.4rem);
  padding: 0;
  overflow: hidden;
  border: 1px solid #23323d;
  border-radius: 0;
  background: #0d141a;
  color: #cfe6f2;
  box-shadow: 0 0 0 1px #0a1015, 0 30px 80px rgba(4, 12, 18, 0.62),
    0 0 42px rgba(42, 168, 224, 0.16);
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  /* The faint grid is the screen's own texture: two hairlines, no gradient,
     so it reads as a display rather than as a tinted card. */
  background-image:
    linear-gradient(rgba(42, 168, 224, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(42, 168, 224, 0.045) 1px, transparent 1px);
  background-size: 26px 26px;
}

aside.admin-card#chat:not([hidden]) {
  display: flex;
  flex-direction: column;
}

.chat-top {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex: none;
  padding: 0.6rem 0.7rem 0.6rem 1.1rem;
  border-bottom: 1px solid #23323d;
  background: #111b22;
}

/* The title wears the screen's glow, the way a lit display reads in a dim room. */
.chat-title {
  margin: 0;
  color: #dff3ff;
  font-size: 0.95rem;
  font-weight: 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: 0 0 12px rgba(42, 168, 224, 0.55);
}

/* How many questions are left. Empty when a deployment has no cap, so the
   header never says "0 left" to somebody who can ask all day. */
.chat-left {
  flex: 1;
  min-width: 0;
  color: #5d7b8c;
  font-size: 0.72rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-model-label {
  color: #5d7b8c;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.chat-model {
  flex: none;
  max-width: 15rem;
  padding: 0.34rem 0.5rem;
  border: 1px solid #26404f;
  border-radius: 0;
  background: #0a1116;
  color: #bfe8fa;
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}

.chat-model:focus {
  outline: 1px solid #2aa8e0;
  outline-offset: 1px;
}

/* The dropdown list is drawn by the OS, so it gets the same glass rather than
   the white sheet a light theme would hand it. */
.chat-model option {
  background: #0a1116;
  color: #bfe8fa;
}

.chat-new {
  flex: none;
  padding: 0.38rem 0.8rem;
  border: 1px solid #2aa8e0;
  border-radius: 0;
  background: rgba(42, 168, 224, 0.14);
  color: #9fe0ff;
  font: inherit;
  font-size: 0.76rem;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.chat-new:hover {
  background: rgba(42, 168, 224, 0.26);
  color: #e6f8ff;
}

.chat-room-body {
  display: grid;
  grid-template-columns: minmax(12rem, 17rem) minmax(0, 1fr);
  flex: 1 1 auto;
  min-height: 0;
}

.chat-list {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-height: 0;
  padding: 0.6rem 0.5rem 1rem;
  overflow: auto;
  border-right: 1px solid #23323d;
  background: #0a1116;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.chat-list::-webkit-scrollbar {
  display: none;
}

.chat-list-empty {
  margin: 0.4rem 0.6rem;
  color: #5d7b8c;
  font-size: 0.76rem;
}

.chat-row {
  display: flex;
  align-items: stretch;
  gap: 0.1rem;
}

.chat-pick {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-left: 2px solid transparent;
  border-radius: 0;
  background: transparent;
  color: #b7d4e2;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.chat-pick:hover {
  background: #121d25;
  color: #e6f6ff;
}

.chat-pick[aria-current="true"] {
  border-left-color: #2aa8e0;
  background: #16242e;
  color: #eaf9ff;
}

.chat-pick-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.32;
  overflow-wrap: anywhere;
}

.chat-pick-meta {
  display: block;
  margin-top: 0.2rem;
  color: #587382;
  font-size: 0.68rem;
}

.chat-pick[aria-current="true"] .chat-pick-meta {
  color: #7fa7bb;
}

.chat-del {
  flex: none;
  align-self: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #4b6675;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.chat-del:hover {
  background: #1b2a34;
  color: #ff8f7a;
}

.chat-thread {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.chat-log {
  flex: 1 1 auto;
  min-height: 0;
  padding: 1.1rem 1.4rem 1rem;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.chat-log::-webkit-scrollbar {
  display: none;
}

.chat-intro {
  max-width: 40rem;
  margin: 0.2rem auto 0.9rem;
  color: #7b99a8;
  font-size: 0.84rem;
}

.chat-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  max-width: 40rem;
  margin: 0 auto;
}

.chat-chips button {
  padding: 0.4rem 0.85rem;
  border: 1px solid #26404f;
  border-radius: 0;
  background: #0f1a21;
  color: #a8ccdd;
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}

.chat-chips button:hover {
  border-color: #2aa8e0;
  background: #14232c;
  color: #e6f8ff;
}

/* A bubble is plain text with its line breaks kept: that is what makes a
   pasted function come back readable, and it is the whole reason the panel
   does not try to render markdown. Square bodies with a coloured edge read as
   a terminal, not as a messenger. */
.chat-msg {
  display: flex;
  margin: 0 0 0.7rem;
}

.chat-msg.user {
  justify-content: flex-end;
}

.chat-said {
  max-width: min(44rem, 86%);
  padding: 0.6rem 0.85rem;
  border: 1px solid #22333e;
  border-left: 2px solid #2aa8e0;
  border-radius: 0;
  background: #101a21;
  color: #cfe6f2;
  font-size: 0.84rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.chat-msg.user .chat-said {
  border-color: #2aa8e0;
  border-left-color: #2aa8e0;
  background: rgba(42, 168, 224, 0.16);
  color: #eaf9ff;
}

.chat-msg.err .chat-said {
  border-color: #6b2a22;
  border-left-color: #ff6f52;
  background: #24120f;
  color: #ffb4a2;
}

.chat-msg.thinking .chat-said {
  color: #6d8b9a;
  font-style: italic;
}

.chat-form {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  flex: none;
  padding: 0.7rem 1rem 0.9rem;
  border-top: 1px solid #23323d;
  background: #111b22;
}

#chat-input {
  flex: 1 1 auto;
  min-height: 2.4rem;
  max-height: 9rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid #26404f;
  border-radius: 0;
  background: #0a1116;
  color: #dff3ff;
  font: inherit;
  font-size: 0.84rem;
  line-height: 1.4;
  resize: none;
  caret-color: #2aa8e0;
}

#chat-input::placeholder {
  color: #4f6b7a;
}

#chat-input:focus {
  outline: 1px solid #2aa8e0;
  outline-offset: 0;
  border-color: #2aa8e0;
}

#chat-send {
  flex: none;
}

/* The send button is a shop-style pill everywhere else; on a laptop screen it
   is a key. */
#chat #chat-send {
  border: 1px solid #2aa8e0;
  border-radius: 0;
  background: rgba(42, 168, 224, 0.18);
  color: #9fe0ff;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

#chat #chat-send:hover {
  background: rgba(42, 168, 224, 0.3);
  color: #eaf9ff;
}

#chat #chat-send:disabled {
  border-color: #2b3d47;
  background: #14202a;
  color: #4f6b7a;
}

.chat-note {
  flex: none;
  margin: 0;
  padding: 0 1rem 0.8rem;
  background: #111b22;
  color: #7b99a8;
  font-size: 0.76rem;
}

.chat-note.warn {
  color: #ff9d85;
}

/* A phone cannot hold two panes: the list goes above the thread and is capped,
   so the conversation below still gets most of the screen. This query sits
   after the chat's own rules on purpose - an earlier copy of the job room's
   query lost exactly this fight. */
@media (max-width: 56rem) {
  aside.admin-card#chat {
    width: calc(100vw - 0.8rem);
    height: calc(100vh - 1.4rem);
    max-height: calc(100vh - 1.4rem);
    border-radius: 0;
  }
  .chat-top {
    flex-wrap: wrap;
    padding: 0.5rem 0.55rem 0.5rem 0.75rem;
  }
  .chat-left {
    display: none;
  }
  .chat-model {
    flex: 1;
    max-width: none;
  }
  .chat-model-label {
    display: none;
  }
  .chat-room-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 28vh) minmax(0, 1fr);
  }
  .chat-list {
    border-right: 0;
    border-bottom: 1px solid #23323d;
  }
  .chat-log {
    padding: 0.8rem 0.75rem;
  }
  .chat-said {
    max-width: 92%;
  }
  .chat-form {
    padding: 0.55rem 0.6rem 0.7rem;
  }
}

/* ---------------- the inbox ----------------
   One list of what a teacher decided while the learner was away: a post
   accepted, a post sent back, coins with a note. The card is narrow on
   purpose - a message is a signpost, and the thing it points at is a whole
   post - so the list is the only thing that scrolls. */

aside.admin-card#inbox,
aside.admin-card#visit {
  z-index: 16;
  width: min(34rem, calc(100vw - 2rem));
  max-height: min(38rem, calc(100vh - 4rem));
  padding: 0;
  overflow: hidden;
  border-radius: 1.1rem;
}

aside.admin-card#inbox:not([hidden]),
aside.admin-card#visit:not([hidden]) {
  display: flex;
  flex-direction: column;
}

.inbox-top {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex: none;
  padding: 0.6rem 0.7rem 0.6rem 1.2rem;
  border-bottom: 1px solid #eee;
}

.inbox-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
}

.inbox-count {
  flex: 1;
  min-width: 0;
  color: #888;
  font-size: 0.76rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.inbox-all {
  flex: none;
  padding: 0.34rem 0.7rem;
  border: 1px solid #ddd;
  border-radius: 999px;
  background: #fff;
  color: #333;
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}

.inbox-all[hidden] {
  display: none;
}

.inbox-note {
  margin: 0;
  padding: 0.75rem 1.2rem 0.1rem;
  color: #666;
  font-size: 0.86rem;
}

.inbox-list,
.visit-list {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 0.55rem 0.7rem 0.8rem;
}

.inbox-empty {
  margin: 0.6rem 0.5rem;
  color: #666;
}

.inbox-row {
  display: block;
  width: 100%;
  margin: 0 0 0.45rem;
  padding: 0.65rem 0.8rem 0.7rem;
  border: 1px solid #ececec;
  border-radius: 0.9rem;
  background: #fff;
  color: #161616;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.inbox-row:hover {
  background: #fafafa;
}

.inbox-row.unread {
  border-color: #dcdcdc;
}

.inbox-row-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* The kind is written and coloured, so the list can be skimmed for the one
   decision that is still waiting to be read. */
.inbox-kind {
  font-size: 0.68rem;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #666;
}

.inbox-kind.approved {
  color: #1f7a4d;
}

.inbox-kind.rejected {
  color: #a33a2a;
}

.inbox-kind.coins {
  color: #8a6100;
}

.inbox-when {
  margin-left: auto;
  color: #999;
  font-size: 0.72rem;
}

.inbox-row-title {
  display: block;
  margin-top: 0.18rem;
  font-weight: 650;
}

.inbox-row.unread .inbox-row-title::after {
  content: "";
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  margin-left: 0.45rem;
  border-radius: 50%;
  background: #d94a32;
  vertical-align: middle;
}

.inbox-row-body {
  display: block;
  margin-top: 0.2rem;
  color: #555;
  font-size: 0.88rem;
}

/* ---------------- visiting a classmate ---------------- */

.visit-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  margin: 0 0 0.4rem;
  padding: 0.62rem 0.85rem;
  border: 1px solid #ececec;
  border-radius: 0.9rem;
  background: #fff;
  color: #161616;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.visit-row:hover {
  background: #fafafa;
}

.visit-row.busy {
  opacity: 0.6;
  cursor: default;
}

.visit-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.visit-go {
  flex: none;
  color: #666;
  font-size: 0.82rem;
}

/* The veil between two gardens. A visit swaps the whole scene in one frame;
   the fade is what turns that into a walk. It sits above every card, because
   it is a moment between rooms rather than part of either. */
.house-fade {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: #fff;
  opacity: 0;
  transition: opacity 0.24s ease;
  pointer-events: none;
}

.house-fade[hidden] {
  display: none;
}

.house-fade.on {
  opacity: 1;
}

/* The unread count lives on the menu item that opens the inbox, and a dot on
   the account button says there is something in it without opening anything. */
.who-badge {
  display: inline-block;
  min-width: 1.15rem;
  margin-left: 0.4rem;
  padding: 0.05rem 0.32rem;
  border-radius: 999px;
  background: #d94a32;
  color: #fff;
  font-size: 0.68rem;
  line-height: 1.35;
  text-align: center;
  vertical-align: middle;
}

.who-badge[hidden] {
  display: none;
}

.who-menu button.unread {
  font-weight: 650;
}

.who-button.has-mail::after {
  content: "";
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  margin-left: 0.45rem;
  border-radius: 50%;
  background: #d94a32;
  vertical-align: middle;
}

/* ---------------- the admin's coin gift ---------------- */

.give-note {
  display: block;
  box-sizing: border-box;
  width: 100%;
  max-width: 28rem;
  margin-top: 0.5rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid #ddd;
  border-radius: 0.7rem;
  font: inherit;
  font-size: 0.88rem;
}

/* micro:bit 101 fullscreen explorers */
iframe.mb-frame {
  position: fixed;
  inset: 0;
  z-index: 40;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  background: #eef0f3;
}

iframe.mb-frame[hidden] {
  display: none;
}

body.mb-open > .account-bar,
body.mb-open > .privacy-link,
body.mb-open > .launch-title,
body.mb-open > nav.lessons,
body.mb-open > aside.side,
body.mb-open > aside.settings-card,
body.mb-open > aside.admin-card,
body.mb-open > #house-fade {
  visibility: hidden;
  pointer-events: none;
}
