/* The room itself.
   tokens.css says what things are made of; this file says what the room looks
   like with the lamp on. Loaded last, so it layers over base/components/screens
   without any of those files needing to know it exists.

   Three ideas run through everything below:
   1. Light comes from above and slightly left. Every raised surface gets a
      hairline highlight on its top edge and a warm shadow underneath.
   2. Paper and brass are warm; instruments are cool. The contrast is what stops
      a dark interface reading as a terminal.
   3. Motion is arrival, not decoration. Things settle into place once. */

:root {
  /* Film grain, generated in the browser: no network request, no binary asset.
     One decoded tile, reused by every layer that references the token. */
  --tex-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- Desk: grain and ambient light ---------------------------------------
   Two fixed overlays on <body> rather than a background per panel. The grain
   sits above unpositioned content so it reads as a single sheet of atmosphere
   across the whole room instead of stopping at every panel edge; at 3.5% it is
   texture, not noise. Both are inert to the pointer. */

body::before,
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

body::before {
  background-image: var(--tex-noise);
  background-size: 180px 180px;
  opacity: 0.035;
}

body::after {
  background-image:
    radial-gradient(1100px 620px at 20% -12%, rgba(255, 196, 128, 0.075), transparent 62%),
    radial-gradient(900px 700px at 102% -4%, rgba(126, 166, 255, 0.035), transparent 58%),
    radial-gradient(150% 125% at 50% 42%, transparent 44%, rgba(8, 5, 2, 0.58) 100%);
}

/* ---- Chrome: the fittings around the room --------------------------------
   The rail, topbar and action bar are physical objects with an edge, not areas
   of flat colour. A one-pixel dark line under each one does most of the work. */

.brand,
.rail {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 260px);
}

.brand {
  box-shadow: var(--shadow-inset);
}

.brand-mark {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--text-hi);
}

.topbar {
  gap: var(--sp-2);
  padding: 0 var(--sp-3);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  box-shadow: var(--shadow-inset), 0 1px 0 rgba(0, 0, 0, 0.55);
  scrollbar-width: none;
}

/* The instrument row scrolls when it must, but a visible scrollbar under the
   pills makes the bar look like a web page again. */
.topbar::-webkit-scrollbar { height: 0; }

.actionbar {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 238, 214, 0.05);
}

.main {
  background-image: radial-gradient(120% 70% at 50% 0%, rgba(255, 200, 140, 0.035), transparent 60%);
}

.rail .nav-item {
  position: relative;
  transition:
    background var(--dur-1) var(--ease-out),
    color var(--dur-1) var(--ease-out);
}

.rail .nav-item[aria-current="page"] {
  background-image: linear-gradient(90deg, rgba(255, 236, 210, 0.07), rgba(255, 236, 210, 0) 62%);
  border-left-color: var(--nation-1);
  box-shadow: inset 3px 0 14px -7px var(--nation-1);
}

/* The active rail item gets a lit edge rather than a brighter fill: the eye
   finds the glow before it reads the label. */
.rail .nav-item[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: -2px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--nation-1);
  box-shadow: 0 0 10px 0 var(--nation-1);
}

/* ---- Ticker: a physical wire ---------------------------------------------- */

.ticker {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  box-shadow: inset 0 1px 0 rgba(255, 238, 214, 0.04);
}

.ticker-label {
  position: relative;
  padding-left: 15px;
  color: var(--text-mid);
  border-right-color: var(--line-strong);
}

.ticker-label::before {
  content: "";
  position: absolute;
  left: 1px;
  top: 50%;
  margin-top: -3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--neg);
  box-shadow: 0 0 7px var(--neg);
  animation: livePip 2.2s ease-in-out infinite;
}

/* ---- Panels and cards ----------------------------------------------------- */

.panel {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 62px);
  box-shadow: var(--shadow-1), var(--shadow-inset);
  border-radius: 5px;
}

.panel-head {
  background: rgba(255, 238, 214, 0.018);
  border-bottom-color: var(--line);
  color: var(--text-mid);
}

.card {
  position: relative;
  padding: var(--sp-4);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 60%);
  background-color: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: var(--shadow-1), var(--shadow-inset);
  min-width: 0;
}

/* A card that wraps its own header or artwork owns no padding — the children
   already carry it, and a padded frame around a full-bleed illustration is the
   single most dashboard-looking mistake available. */
.card:has(> .panel-head),
.card:has(> .scene-frame),
.card:has(> .hero),
.panel.card {
  padding: 0;
}

.card.lift {
  transition:
    transform var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out);
}

/* Lifts answer a cursor. A tap leaves :hover stuck on, so on a touch screen
   the card would stay raised after the finger has gone. */
@media (hover: hover) {
  .card.lift:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2), var(--shadow-inset);
    border-color: var(--line-strong);
  }
}

.card.lift:active {
  transform: translateY(0);
  box-shadow: var(--shadow-1), var(--shadow-inset);
}

/* ---- Hero band ------------------------------------------------------------
   A masthead for a screen: the landmark sits behind the words, faded out of
   the way, and the type does the talking. */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 150px;
  display: flex;
  align-items: flex-end;
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: 6px;
  background-color: var(--bg-1);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 72%);
  box-shadow: var(--shadow-1), var(--shadow-inset);
}

.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 34%, #000 100%);
  mask-image: linear-gradient(90deg, transparent, #000 34%, #000 100%);
}

.hero-media svg {
  display: block;
  width: 100%;
  height: auto;
  min-height: 100%;
}

.hero-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 72ch;
}

.hero-title {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: 700;
  line-height: 1.03;
  letter-spacing: -0.012em;
  color: var(--text-hi);
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.55);
  text-wrap: balance;
}

.hero-sub {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  font-size: var(--fs-small);
  color: var(--text-mid);
}

/* The nation stripe: three accents, hairline, along the bottom of the band. */
.hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  z-index: 2;
  background: linear-gradient(
    90deg,
    var(--nation-1) 0 33.3%,
    var(--nation-2) 33.3% 66.6%,
    var(--nation-3) 66.6% 100%
  );
  opacity: 0.85;
}

@media (max-width: 720px) {
  .hero { min-height: 118px; padding: var(--sp-4); }
  .hero-title { font-size: 28px; }
}

/* ---- Portraits ------------------------------------------------------------ */

.portrait {
  position: relative;
  display: block;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-3);
  border: 1px solid var(--line-strong);
}

.portrait svg,
.portrait img {
  display: block;
  width: 100%;
  height: 100%;
}

/* Sits the face down into the frame instead of pasting it on top. */
.portrait::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow:
    inset 0 2px 7px rgba(0, 0, 0, 0.45),
    inset 0 0 0 1px rgba(255, 238, 214, 0.06);
  pointer-events: none;
}

.portrait.sm { width: 28px; height: 28px; }
.portrait.lg { width: 96px; height: 96px; }
.portrait.lg::after { box-shadow: inset 0 4px 14px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(255, 238, 214, 0.06); }

/* A real photograph sits over the drawn face it replaces. The drawing stays
   underneath on purpose: it is the placeholder while the JPEG loads and the
   fallback if it never does (ui/art/portrait.js removes a failed layer). */
.portrait img.ph {
  position: absolute;
  inset: 0;
  object-fit: cover;
  object-position: 50% 32%;
  border-radius: inherit;
  /* Commons photos are lit for daylight; the room is lit by lamps. A touch of
     warmth lets them sit beside the drawn cast. */
  filter: saturate(0.9) contrast(1.04) sepia(0.06);
}

/* The avatar draws its own rim; a photo needs one drawn over it. */
.portrait img.ph.ring {
  outline: 2px solid var(--ph-ring, currentColor);
  outline-offset: -2px;
}

/* Two people sharing one leadership: overlapping frames. */
.portrait-pair { display: inline-flex; align-items: center; flex: none; }
.portrait-pair > .portrait + .portrait { margin-left: -14px; box-shadow: -2px 0 0 var(--bg-1); }
.portrait-pair > .portrait.sm + .portrait.sm { margin-left: -9px; }
.portrait-pair > .portrait.lg + .portrait.lg { margin-left: -24px; }

/* ---- Event footage -------------------------------------------------------- */

/* The drawn scene stays in flow and sets the slot's aspect; a clip or its
   poster covers it edge to edge. */
.scene-frame .em-layer {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: transparent;
}

.scene-frame video.em-video { animation: fadeIn var(--dur-3) var(--ease-out) both; }
.scene-frame .em-poster-fallback { width: 100%; height: 100%; object-fit: cover; }

/* Footage grades softly into the card below it, so a photographic band and a
   flat card body read as one object. */
.scene-frame .em-fade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 38%,
    color-mix(in srgb, var(--bg-2) 55%, transparent) 78%,
    color-mix(in srgb, var(--bg-2) 92%, transparent) 100%);
}

/* ---- Instrument pill ------------------------------------------------------ */

.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background-color: var(--bg-1);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  box-shadow: var(--shadow-inset);
  white-space: nowrap;
  color: inherit;
  transition: border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}

.pill:hover { border-color: var(--line-strong); }

.pill .icon { color: var(--text-low); }

.pill-label {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-low);
}

.pill-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-data);
  line-height: 1.1;
  color: var(--text-hi);
}

.pill-value.pos { color: var(--pos); }
.pill-value.neg { color: var(--neg); }
.pill-value.warn { color: var(--warn); }

/* ---- Rubber stamp --------------------------------------------------------- */

.stamp {
  display: inline-block;
  padding: 3px 11px 4px;
  border: 2px solid currentColor;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: var(--fs-body);
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-mid);
  opacity: 0.82;
  transform: rotate(-4deg);
  transform-origin: center;
  /* Ink soaks unevenly into paper; a faint inner shadow fakes that without an
     image. */
  box-shadow: inset 0 0 8px -4px currentColor;
  text-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}

.stamp.pos { color: var(--pos); }
.stamp.neg { color: var(--neg); }
.stamp.warn { color: var(--warn); }

/* ---- Buttons: things you press -------------------------------------------- */

.btn {
  border-radius: 5px;
  background-color: var(--bg-3);
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-2));
  box-shadow: var(--shadow-inset), 0 1px 2px rgba(0, 0, 0, 0.35);
  transition:
    background-color var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

.btn:hover:not(:disabled) {
  background-color: var(--bg-hover);
  border-color: var(--line-strong);
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.4);
}

.btn.ghost { background-image: none; box-shadow: none; }
.btn.ghost:hover:not(:disabled) { background-image: none; box-shadow: none; }

/* Brass. Reserved for commitment: take office, sign, advance the clock. */
.btn.primary {
  background-color: var(--accent-warm);
  background-image: linear-gradient(180deg, var(--accent-warm-hi), var(--accent-warm) 58%, #c2762c);
  border-color: var(--accent-warm-line);
  color: var(--ink);
  font-weight: 600;
  text-shadow: 0 1px 0 rgba(255, 240, 214, 0.25);
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 244, 224, 0.4);
}

.btn.primary:hover:not(:disabled) {
  background-color: var(--accent-warm-hi);
  background-image: linear-gradient(180deg, #f7bc70, var(--accent-warm-hi) 58%, #cf8330);
  border-color: #c98436;
}

.btn.danger {
  background-image: linear-gradient(180deg, var(--neg-dim), rgba(61, 34, 32, 0.4));
}

.btn-turn {
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: 0.12em;
  padding: 11px 22px;
  border-radius: 6px;
}

/* ---- KPI tiles ------------------------------------------------------------ */

.tile {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-radius: 5px;
  box-shadow: var(--shadow-1), var(--shadow-inset);
  transition:
    border-color var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

@media (hover: hover) {
  .tile:hover {
    background-image: linear-gradient(180deg, var(--bg-3), var(--bg-2));
    border-color: var(--line-strong);
    transform: translateY(-2px);
    box-shadow: var(--shadow-2), var(--shadow-inset);
  }
}

.tile-value { font-family: var(--font-mono); letter-spacing: -0.01em; }

/* ---- Scene illustration frame --------------------------------------------- */

.scene-frame {
  position: relative;
  overflow: hidden;
  line-height: 0;
  border: 1px solid var(--line);
  border-radius: 5px;
  background-color: var(--bg-2);
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-1));
}

.scene-frame svg {
  display: block;
  width: 100%;
  height: auto;
}

/* Grades the bottom of the illustration into whatever sits below it, so the
   art belongs to the card rather than being pasted into it. */
.scene-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 52%, rgba(12, 9, 7, 0.55) 100%);
}

/* ---- Advisors ------------------------------------------------------------- */

.advisor {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  min-width: 0;
}

.advisor-say {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  color: var(--text-mid);
  font-size: var(--fs-small);
  line-height: 1.55;
}

/* The pointer is a rotated square with two borders, so it inherits the speech
   line's edge exactly and needs no second colour to maintain. */
.advisor-say::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 13px;
  width: 8px;
  height: 8px;
  background: var(--bg-2);
  border-left: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  transform: rotate(45deg);
}

.advisor-say strong,
.advisor-say .advisor-name { color: var(--text-hi); font-weight: 600; }
.advisor-say .advisor-role {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-low);
}

/* ---- Diplomatic board ------------------------------------------------------
   Nodes are placed by the screen with inline left/top percentages; the SVG
   layer underneath draws the relations between them. */

.board {
  position: relative;
  width: 100%;
  min-height: 280px;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 6px;
  background-color: var(--bg-1);
  /* A graticule under the lamp: the grid is what turns a dark rectangle into a
     map table. Two hairline gradients, no image. */
  background-image:
    repeating-linear-gradient(90deg, rgba(255, 232, 200, 0.032) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(0deg, rgba(255, 232, 200, 0.032) 0 1px, transparent 1px 44px),
    radial-gradient(120% 100% at 50% 38%, var(--bg-3), var(--bg-1) 74%);
  box-shadow: var(--shadow-inset), inset 0 0 70px rgba(0, 0, 0, 0.45);
}

.board-svg {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}

.board-node {
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  color: var(--text-hi);
  font: inherit;
  font-size: var(--fs-caption);
  text-align: center;
  cursor: pointer;
  transform: translate(-50%, -50%);
  transition: transform var(--dur-1) var(--ease-out), filter var(--dur-1) var(--ease-out);
}

.board-node:focus-visible {
  transform: translate(-50%, -50%) scale(1.07);
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.55));
}
@media (hover: hover) {
  .board-node:hover {
    transform: translate(-50%, -50%) scale(1.07);
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.55));
  }
}

.board-node[aria-pressed="true"] .portrait,
.board-node.selected .portrait,
.board-node[aria-pressed="true"] .flag,
.board-node.selected .flag { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-dim); }

.board-center {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 2;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-1));
  box-shadow: var(--shadow-2), var(--shadow-inset), 0 0 40px -12px var(--nation-1);
  text-align: center;
  white-space: nowrap;
}

@media (max-width: 720px) {
  .board { aspect-ratio: 4 / 5; }
}

/* ---- Small art: icons, emblems, flags, moods, dials ----------------------- */

.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  vertical-align: -0.16em;
  color: inherit;
}

.icon > svg,
svg.icon { display: block; }

.emblem {
  display: inline-flex;
  flex: none;
  vertical-align: -0.2em;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}

.emblem > svg { display: block; }

.flag {
  display: inline-flex;
  flex: none;
  vertical-align: -0.2em;
  border-radius: 2px;
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, 0.45);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.flag > svg,
svg.flag { display: block; }

/* Sized for either an SVG face or a glyph, so a mood can be swapped for the
   other without the row height moving. */
.mood {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 20px;
  height: 20px;
  font-size: 15px;
  line-height: 1;
  vertical-align: -0.28em;
}

.mood.sm { width: 16px; height: 16px; font-size: var(--fs-small); }
.mood.lg { width: 28px; height: 28px; font-size: 21px; }

.mood > svg,
svg.mood { display: block; width: 100%; height: 100%; }

.dial {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background-image: radial-gradient(circle at 50% 32%, var(--bg-3), var(--bg-1) 72%);
  box-shadow: var(--shadow-inset), var(--shadow-1), inset 0 -6px 12px rgba(0, 0, 0, 0.35);
}

.dial > svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.dial-value {
  position: relative;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-data);
  color: var(--text-hi);
}

/* ---- Folder: bills, save slots -------------------------------------------- */

.folder {
  position: relative;
  margin-top: 12px;
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 2px 8px 5px 5px;
  background-color: var(--bg-2);
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-1) 70%);
  box-shadow: var(--shadow-1), var(--shadow-inset);
}

/* The tab overlaps the card's top border by a pixel so the two read as one cut
   piece of card rather than a rectangle with a flag on it. */
.folder::before {
  content: "";
  position: absolute;
  left: -1px;
  top: -12px;
  width: 96px;
  height: 13px;
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: 4px 10px 0 0;
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-3));
  box-shadow: inset 0 1px 0 rgba(255, 238, 214, 0.05);
}

.folder.selected,
.folder[aria-current="true"] { border-color: var(--accent); }
.folder.selected::before,
.folder[aria-current="true"]::before { border-color: var(--accent); }

/* ---- Newspaper -------------------------------------------------------------
   The one lit object in the room. Inside .paper the surface tokens are flipped
   to their paper values, so any shared component dropped onto the sheet — a
   meter, a table, a chip — comes out in ink rather than in screen colours. */

.paper {
  --text-hi: var(--paper-ink);
  --text-mid: #4c433a;
  --text-low: #7d7266;
  --line: var(--paper-line);
  --line-strong: #b3a189;
  --bg-1: #efe6d8;
  --bg-2: #ebe1d2;
  --bg-3: #e3d8c6;
  --bg-hover: #e0d4c0;

  position: relative;
  width: min(880px, 100%);
  margin: 0 auto;
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
  background-color: var(--paper-bg);
  background-image: linear-gradient(184deg, #f8f1e7, var(--paper-bg) 40%, #ece1d1);
  color: var(--paper-ink);
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  line-height: 1.55;
  border-radius: 2px;
  box-shadow: var(--shadow-2);
  transform: rotate(-0.35deg);
}

/* A sheet of newsprint is never perfectly flat on a desk. */
.paper::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(90deg, rgba(90, 66, 40, 0.06), transparent 8%, transparent 92%, rgba(90, 66, 40, 0.06));
}

/* The masthead carries its own rules, so it is right whether or not the markup
   supplies .np-rule around it — and a rule that turns up immediately beside it
   steps aside rather than doubling up. */
.np-mast {
  font-family: var(--font-display);
  font-size: clamp(30px, 5.2vw, 46px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.015em;
  text-align: center;
  color: var(--paper-ink);
  padding: var(--sp-3) 0;
  border-top: 1px solid rgba(27, 23, 20, 0.55);
  border-bottom: 3px solid rgba(27, 23, 20, 0.55);
}

.np-mast + .np-rule,
.np-rule:has(+ .np-mast) { display: none; }

.np-dateline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: #6a5f52;
  padding: 4px 0;
}

.np-rule {
  height: 0;
  border: 0;
  border-top: 1px solid rgba(27, 23, 20, 0.55);
  margin: 6px 0;
}

.np-rule + .np-rule { margin-top: -3px; border-top-width: 3px; }

.np-lead {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.9vw, 35px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-align: center;
  margin: var(--sp-3) 0 var(--sp-2);
  text-wrap: balance;
}

.np-deck {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 18px;
  line-height: 1.45;
  text-align: center;
  color: #4c433a;
  margin-bottom: var(--sp-4);
  text-wrap: balance;
}

/* The lead photograph: a still of the matching footage, printed in ink. */
.np-photo {
  margin: 0 0 var(--sp-3);
  break-inside: avoid;
}
.np-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 12 / 5;
  object-fit: cover;
  filter: grayscale(1) contrast(1.12) sepia(0.18);
  border: 1px solid rgba(27, 23, 20, 0.35);
}
.np-photo figcaption {
  margin-top: 5px;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--fs-caption);
  line-height: 1.4;
  color: #4c433a;
}
.np-photo-credit {
  font-family: var(--font-mono);
  font-style: normal;
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #6a5f52;
}

.np-cols {
  column-count: 3;
  column-gap: var(--sp-5);
  column-rule: 1px solid rgba(27, 23, 20, 0.18);
  text-align: justify;
  hyphens: auto;
}

.np-col { margin: 0 0 var(--sp-3); }
.np-col p { margin: 0 0 0.7em; }

.np-col h3,
.np-head {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.2;
  text-align: left;
  margin: 0 0 4px;
}

p.np-drop::first-letter,
span.np-drop {
  float: left;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 3.1em;
  line-height: 0.82;
  padding: 0.04em 0.07em 0 0;
  color: var(--paper-ink);
}

.np-box {
  break-inside: avoid;
  border: 1px solid rgba(27, 23, 20, 0.45);
  background: rgba(27, 23, 20, 0.035);
  padding: var(--sp-3);
  margin: 0 0 var(--sp-3);
  text-align: left;
}

.np-box h3,
.np-box .np-head {
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  font-family: var(--font-ui);
  font-weight: 700;
}

.np-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-5);
  padding: var(--sp-2) 0;
  margin: var(--sp-3) 0;
  border-top: 1px solid rgba(27, 23, 20, 0.55);
  border-bottom: 1px solid rgba(27, 23, 20, 0.55);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.np-strip .np-strip-label { color: #6a5f52; margin-right: 6px; }
.np-strip .pos { color: #1d6b45; }
.np-strip .neg { color: #a32b23; }

@media (max-width: 860px) {
  .np-cols { column-count: 2; }
}

@media (max-width: 620px) {
  .np-cols { column-count: 1; }
  .paper { padding: var(--sp-4); transform: none; }
}

/* ---- Modals and the briefing memo ----------------------------------------- */

.modal-backdrop {
  background: rgba(10, 6, 3, 0.62);
  animation: fadeIn var(--dur-2) var(--ease-out) both;
}

/* Blurring the desk is the difference between a dialogue in the room and a
   rectangle on a web page. Guarded: without support the flat scrim stands. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .modal-backdrop {
    background: rgba(10, 6, 3, 0.5);
    -webkit-backdrop-filter: blur(7px) saturate(0.85);
    backdrop-filter: blur(7px) saturate(0.85);
  }
}

.decision-memo {
  border-radius: 7px;
  background-color: var(--bg-1);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 220px);
  box-shadow: var(--shadow-2), var(--shadow-inset);
  animation: popIn var(--dur-2) var(--ease-out) both;
}

/* Media slot: an illustration above the band runs the full width of the memo,
   corners squared off against the memo's own rounding. Either the shared frame
   or a bare .memo-media wrapper works. */
.decision-memo > .scene-frame:first-child,
.decision-memo > .memo-media {
  position: relative;
  overflow: hidden;
  line-height: 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 7px 7px 0 0;
}

.decision-memo > .scene-frame:first-child svg,
.decision-memo > .memo-media svg { display: block; width: 100%; height: auto; }

.memo-band {
  background-image: linear-gradient(180deg, rgba(212, 167, 44, 0.14), rgba(212, 167, 44, 0.06));
  text-transform: uppercase;
}

.memo-title { font-family: var(--font-display); font-size: var(--fs-title); line-height: 1.15; }

/* A card that comes back from an earlier answer names it (engine/consequences.js). */
.memo-echo {
  margin: 0;
  padding-left: var(--sp-2);
  border-left: 2px solid var(--accent-warm-line);
  color: var(--text-mid);
  font-size: var(--fs-small);
  font-style: italic;
}

.decision-option {
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-2));
  border-radius: 5px;
  box-shadow: var(--shadow-inset);
  transition:
    border-color var(--dur-1) var(--ease-out),
    transform var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

/* A lift under the cursor only: on a touch screen :hover sticks after the
   tap and leaves the answer just given floating a pixel up. */
@media (hover: hover) {
  .decision-option:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-1), var(--shadow-inset);
    border-color: var(--accent);
  }
}

/* A phone gets the memo as the whole screen: no desk showing round it, so no
   blur to pay for on a slow handset, the band pinned under the notch while
   the brief scrolls, and answers a thumb can hit. */
@media (max-width: 639.98px), (max-height: 520px) and (min-width: 640px) {
  .modal-backdrop {
    padding: var(--safe-t) 0 0;
    background: var(--bg-0);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  /* An opaque strip under the status bar, so the brief scrolls away beneath
     the clock rather than through it; the band pins just below it. */
  .modal-backdrop::before {
    content: "";
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--safe-t);
    z-index: 3;
    background: var(--bg-1);
  }
  .decision-memo {
    width: 100%;
    min-height: 100%;
    border: 0;
    border-radius: 0;
    overflow: clip;
  }
  .decision-memo > .scene-frame:first-child,
  .decision-memo > .memo-media { border-radius: 0; }
  .memo-band {
    position: sticky;
    top: var(--safe-t);
    z-index: 2;
    padding-left: max(var(--sp-4), var(--safe-l));
    padding-right: max(var(--sp-4), var(--safe-r));
    background-color: var(--bg-1);
  }
  .memo-body {
    padding-left: max(var(--sp-4), var(--safe-l));
    padding-right: max(var(--sp-4), var(--safe-r));
    padding-bottom: calc(var(--sp-4) + var(--safe-b));
  }
  .decision-option { min-height: 56px; justify-content: center; }
}

/* ---- Title and questionnaire screens --------------------------------------
   Both carried a cool blue wash; the room is warm now, so the light is too. */

.start-screen {
  background-image: radial-gradient(1200px 520px at 50% -120px, rgba(217, 139, 58, 0.11), transparent 62%);
}

.q-screen {
  background-image: radial-gradient(900px 420px at 50% -90px, rgba(217, 139, 58, 0.09), transparent 62%);
}

/* Every full-screen view (the title, the identity, the questionnaires, the
   night, the studio, the ceremony) stays clear of the notch and the home
   indicator, fills a phone's real height rather than the toolbar-less one,
   and does not hand an overscroll to the browser to reload with. */
.start-screen,
.q-screen {
  padding: var(--safe-t) var(--safe-r) var(--safe-b) var(--safe-l);
  overscroll-behavior-y: contain;
}
.q-screen { min-height: 100dvh; }

.start-title {
  font-family: var(--font-display);
  font-size: clamp(34px, 7vw, 52px);
  font-weight: 700;
}

/* Ten tracked capitals need ~350px at the 34px floor; a phone has less. */
@media (max-width: 520px) {
  .start-title {
    font-size: clamp(20px, 7.4vw, 34px);
    letter-spacing: 0.16em;
    margin-right: -0.16em;
  }
}

.q-title { font-family: var(--font-display); font-size: 29px; line-height: 1.2; }

.country-card {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-radius: 6px;
  box-shadow: var(--shadow-1), var(--shadow-inset);
  transition:
    transform var(--dur-1) var(--ease-out),
    border-color var(--dur-1) var(--ease-out),
    box-shadow var(--dur-1) var(--ease-out);
}

@media (hover: hover) {
  .country-card:hover:not(.disabled) {
    transform: translateY(-3px);
    box-shadow: var(--shadow-2), var(--shadow-inset);
    border-color: var(--line-strong);
  }
}

.country-card.selected {
  border-color: var(--nation-1);
  box-shadow: var(--shadow-2), var(--shadow-inset), 0 0 0 1px var(--nation-1);
}

.verdict-card {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-radius: 8px;
  box-shadow: var(--shadow-2), var(--shadow-inset);
}

.minister-card,
.actor-card {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-radius: 5px;
  box-shadow: var(--shadow-inset);
}

.policy-row {
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 60%);
  border-radius: 5px;
  box-shadow: var(--shadow-inset);
}

/* ---- Motion ----------------------------------------------------------------
   Every animation ends in the element's default state, so the global
   reduced-motion kill-switch in base.css collapses them to nothing visible
   rather than leaving anything stranded mid-flight. */

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes riseIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

@keyframes popIn {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: none; }
}

@keyframes pulseSoft {
  0% { box-shadow: 0 0 0 0 rgba(240, 171, 85, 0.38); }
  70%, 100% { box-shadow: 0 0 0 11px rgba(240, 171, 85, 0); }
}

@keyframes livePip {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

@keyframes confettiFall {
  from { transform: translate3d(0, -24px, 0) rotate(0deg); opacity: 1; }
  to { transform: translate3d(var(--dx, 0px), 105vh, 0) rotate(var(--spin, 720deg)); opacity: 0; }
}

.fade-in { animation: fadeIn var(--dur-2) var(--ease-out) both; }
.rise-in { animation: riseIn var(--dur-2) var(--ease-out) both; }
.pop-in { animation: popIn var(--dur-2) var(--ease-spring) both; }

/* The end-turn control breathes only while it is the only thing left to do.
   The glow lives on a ring pseudo-element rather than on the host's box-shadow,
   so it can be added to anything without overwriting that element's own
   elevation — and it ends fully transparent, which is what reduced motion
   collapses it to. */
.pulse-soft { position: relative; }

.pulse-soft::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: 0 0 0 11px rgba(240, 171, 85, 0);
  animation: pulseSoft 2.4s var(--ease-out) infinite;
}

/* Longhands, not the shorthand: a child that also carries .fade-in keeps its
   own animation-name from the override below while still picking up the delay. */
.stagger > * {
  animation-name: riseIn;
  animation-duration: var(--dur-2);
  animation-timing-function: var(--ease-out);
  animation-fill-mode: both;
  animation-delay: calc(var(--i, 0) * 40ms);
}

.stagger > .fade-in { animation-name: fadeIn; }
.stagger > .pop-in { animation-name: popIn; }

.confetti {
  position: absolute;
  top: 0;
  width: 7px;
  height: 11px;
  border-radius: 1px;
  pointer-events: none;
  will-change: transform;
  animation: confettiFall var(--fall, 2600ms) linear var(--delay, 0ms) forwards;
}

/* base.css kills durations, which is enough for entrances but would leave
   confetti as a row of frozen dots and the stagger as a stack of delayed
   invisible blocks. Both are handled explicitly. */
@media (prefers-reduced-motion: reduce) {
  .stagger > * { animation-delay: 0s !important; }
  .confetti { display: none; }
  .card.lift:hover,
  .tile:hover,
  .country-card:hover:not(.disabled),
  .decision-option:hover,
  .board-node:hover { transform: none; }
}

/* ---- Media, identity and credits ------------------------------------------ */

/* Your own photo: a file input dressed as a button, still reachable by Tab. */
.id-photo-row { gap: var(--sp-2); align-items: center; flex-wrap: wrap; margin-top: var(--sp-3); }
.id-photo-btn { position: relative; cursor: pointer; }
.id-photo-btn:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.id-photo-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.id-photo-note { font-size: var(--fs-caption); }

/* Credits tables run wide; on a phone they scroll inside their own box. */
.hb-credits { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.hb-credits .table td,
.hb-credits .table th { font-size: var(--fs-caption); vertical-align: top; }
.hb-credits a { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .scene-frame video.em-video { animation: none; }
}

/* ---- The room at every size ------------------------------------------------
   The same fittings, rearranged for the screen they are on (the grid itself
   is in base.css). A laptop between 1024 and 1600 is the room as designed;
   everything below is a tablet folding the rail, a phone moving it under the
   thumb, or a wide screen giving the wire its own column. */

/* Rail signs: icon and name on a row; the short name waits for a tablet. */
.nav-sign { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.nav-label-s { display: none; }

/* Readouts: the phone's short forms and the tablet's gauge stay out of the
   desktop's way. The dots wrapper dissolves so the dots sit in the row
   exactly as they always did. */
.pill-label-s, .pill-value-s, .pill .pc-bar { display: none; }
.pill .pc-dots { display: contents; }
.pill-text { min-width: 0; }

/* The face in the top bar: the frame clips, so the tap area is its wrapper's. */
.tb-face { display: inline-flex; border-radius: 50%; }

.pc-bar {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 3px;
  border-radius: 2px;
  background: var(--bg-3);
  overflow: hidden;
  vertical-align: middle;
}
.pc-bar > span { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 2px; }
.delta-glyph { font-size: max(var(--fs-micro), 0.8em); margin-left: 2px; }

/* The wire runs sideways now rather than clipping. */
.ticker-items {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  border-radius: 2px;
}
.ticker-items::-webkit-scrollbar { display: none; }
.ticker-item { scroll-snap-align: start; }
.ticker-items:focus-visible { outline-offset: -2px; }

/* The action bar's short names wait for a screen that needs them, and the
   count of waiting decisions for the phone, where it replaces the turn. */
.ab-status { display: inline-flex; align-items: center; gap: var(--sp-2); }
.ab-wait, .ab-short { display: none; }

/* A laptop narrower than the readouts: tighter pills, the second line of the
   budget and election readouts in their tips, the face without the name. */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  .pill { padding: 4px 8px; }
  .pill .pc-dots { display: inline-flex; gap: 3px; }
  .pill-sub, .tb-name { display: none; }
}

/* ---- Wide: the wire as a column ------------------------------------------- */

.side {
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-3);
  overflow-y: auto;
  overscroll-behavior-y: contain;
  border-left: 1px solid var(--line);
  background-color: var(--bg-1);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1) 260px);
  box-shadow: var(--shadow-inset);
}

.side-h {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  font-size: var(--fs-caption);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-mid);
}
.side-h .ticker-label { border-right: 0; padding-right: 0; }

.wire-list { display: flex; flex-direction: column; gap: var(--sp-2); }
.wire-item {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr);
  gap: var(--sp-2);
  align-items: baseline;
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--text-mid);
}
.wire-item .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--text-low); transform: translateY(-1px); }
.wire-item.good .dot { background: var(--pos); }
.wire-item.bad .dot { background: var(--neg); }
.wire-item.warn .dot { background: var(--warn); }

.side-desk { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.side-desk > div { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3); font-size: var(--fs-small); }
.side-desk dt { color: var(--text-low); }
.side-desk dd { margin: 0; color: var(--text-hi); text-align: right; }

@media (min-width: 1600px) {
  .decision-memo { width: min(640px, 100%); }
}

/* ---- Tablet: a compact rail and a top bar that fits ------------------------ */

@media (min-width: 640px) and (max-width: 1023.98px) {
  .brand { align-items: center; padding: 0; }
  .brand-mark, .brand-country { display: none; }

  .rail { padding-top: var(--sp-2); }
  .rail .nav-item {
    position: relative;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-height: 58px;
    padding: 6px 4px;
    text-align: center;
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--fs-micro);
    line-height: 1.2;
  }
  .rail .nav-sign { flex-direction: column; gap: 4px; }
  .rail .nav-sign > .icon { width: 20px; height: 20px; }
  .rail .nav-label { display: none; }
  .rail .nav-label-s { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rail .nav-badge { position: absolute; top: 4px; left: calc(50% + 6px); }
  /* The compact rail is a phone tab on its side: a word is a dot here too. */
  .rail .nav-badge.word {
    top: 7px;
    left: calc(50% + 9px);
    width: 8px;
    min-width: 0;
    height: 8px;
    padding: 0;
    box-shadow: 0 0 0 2px var(--bg-1);
  }
  .rail .nav-badge.word > .nav-badge-text { display: none; }
  .rail .nav-badge.word.quiet { background: var(--text-low); }

  .topbar {
    gap: 6px;
    padding: 6px var(--sp-2);
    overflow: visible;
  }
  .topbar .pill { flex: 1 1 0; min-width: 0; padding: 4px 8px; gap: 6px; }
  .topbar .pill > .icon { display: none; }
  .topbar .pill-label { display: none; }
  .topbar .pill-label-s {
    display: block;
    font-size: var(--fs-micro);
    text-transform: uppercase;
    letter-spacing: var(--ls-caps);
    color: var(--text-low);
  }
  .topbar .pill-label-s,
  .topbar .pill-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar .pill-value { font-size: 15px; }
  .pill-sub, .tb-name { display: none; }
  .pill .pc-dots { display: none; }
  .pill .pc-bar { display: inline-block; }
  .topbar .fill { display: none; }
  .tb-who { flex: none; }

  .actionbar { gap: var(--sp-3); padding: 0 var(--sp-3); }
  .actionbar .btn { white-space: nowrap; }
  .btn-turn { padding: 10px 16px; }
  .ab-long { display: none; }
  .ab-short { display: inline; }
}

/* A small tablet held upright: the readouts take the phone's short figures,
   and the two settings keep only their icons (their names stay in the
   accessible name and the tip). */
@media (min-width: 640px) and (max-width: 739.98px) {
  .topbar .pill-value { display: none; }
  .topbar .pill-value-s {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 15px;
    line-height: 1.2;
    color: var(--text-hi);
  }
  .topbar .pill-value-s .pc-bar { display: block; width: 100%; margin-top: 3px; }
  .ab-tools .btn[data-shell="paper"] .ab-short,
  .ab-tools .btn[data-shell="video"] .ab-short {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
}

/* A tablet wide enough gives the readouts their icons back. */
@media (min-width: 900px) and (max-width: 1023.98px) {
  .topbar .pill > .icon { display: inline-flex; }
}

/* ---- Phone: tab bar, compact readouts, the turn under the thumb ------------ */

.tabbar {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: stretch;
  padding: 0 var(--safe-r) var(--safe-b) var(--safe-l);
  background-color: var(--bg-1);
  background-image: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border-top: 1px solid var(--line);
  box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.55);
}

.tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  min-height: var(--tabbar-h);
  padding: 6px 2px 4px;
  border: 0;
  background: none;
  color: var(--text-low);
  font-size: var(--fs-micro);
  line-height: 1.1;
  cursor: pointer;
}
.tab:active { background: var(--bg-2); }
.tab-icon { display: inline-flex; }
.tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Placed against the tab, not the icon, so they sit inside its box. */
.tab .nav-badge { position: absolute; top: 3px; left: calc(50% + 4px); font-size: var(--fs-micro); line-height: 16px; }
.tab-dot {
  position: absolute;
  top: 6px;
  left: calc(50% + 9px);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--neg);
  box-shadow: 0 0 0 2px var(--bg-1);
}
/* A badge that is a word ("open", "3 mo") is wider than the room right of
   the icon in a fifth of a phone: it becomes the same dot. The tab's name
   still says the word to a screen reader (nav.js). */
.tab .nav-badge.word {
  top: 6px;
  left: calc(50% + 9px);
  width: 8px;
  min-width: 0;
  height: 8px;
  padding: 0;
  box-shadow: 0 0 0 2px var(--bg-1);
}
.tab .nav-badge.word > .nav-badge-text { display: none; }
.tab .nav-badge.word.quiet { background: var(--text-low); }

/* The lit tab: the rail's glow, turned on its side. */
.tab[aria-current="page"] { color: var(--text-hi); }
.tab[aria-current="page"] .tab-icon { color: var(--nation-1); }
.tab[aria-current="page"]::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 22%;
  right: 22%;
  height: 2px;
  border-radius: 0 0 2px 2px;
  background: var(--nation-1);
  box-shadow: 0 0 10px 0 var(--nation-1);
}
.tab-more[aria-expanded="true"] { color: var(--text-hi); background: var(--bg-2); }

/* The More sheet's contents. */
.more-who {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-small);
}
.more-name { font-family: var(--font-display); font-size: 22px; line-height: 1.1; color: var(--text-hi); }
.more-h {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-caption);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--text-low);
}
.more-rooms { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--tap-gap); }
.more-room, .more-toggle, .more-exit {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 56px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: 6px;
  background-color: var(--bg-2);
  background-image: linear-gradient(180deg, var(--bg-3), var(--bg-2));
  box-shadow: var(--shadow-inset);
  color: var(--text-mid);
  font-size: var(--fs-small);
  text-align: left;
  cursor: pointer;
}
.more-room .icon { color: var(--text-low); }
.more-room-label { flex: 1 1 auto; min-width: 0; }
.more-room[aria-current="page"] { color: var(--text-hi); border-color: var(--nation-1); }
.more-room[aria-current="page"] .icon { color: var(--nation-1); }
.more-settings { display: flex; flex-direction: column; gap: var(--tap-gap); }
.more-toggle { min-height: 48px; }
.more-state { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-low); }
.more-toggle > svg { width: 18px; height: 18px; flex: none; }
.more-toggle[aria-pressed="true"] { color: var(--text-hi); }
.more-toggle[aria-pressed="true"] .more-state { color: var(--pos); }
.more-exit {
  justify-content: center;
  margin-top: var(--sp-3);
  border-color: var(--line-strong);
  color: var(--text-hi);
}

@media (max-width: 639.98px) {
  /* The top bar: five readouts in five equal cells, each a short word over
     the one number that matters, under the notch. */
  .topbar {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 3px;
    padding: calc(4px + var(--safe-t)) max(6px, var(--safe-r)) 4px max(6px, var(--safe-l));
    overflow: visible;
  }
  .topbar .pill {
    min-width: 0;
    min-height: 44px;
    padding: 3px 5px;
    gap: 0;
    border-radius: 6px;
  }
  .topbar .pill > .icon,
  .topbar .pill-label,
  .topbar .pill-value,
  .topbar .fill,
  .tb-who { display: none; }
  .topbar .pill-label-s,
  .topbar .pill-value-s {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .topbar .pill-label-s { font-size: var(--fs-micro); line-height: 1.3; color: var(--text-low); }
  .topbar .pill-value-s {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 14px;
    line-height: 1.25;
    letter-spacing: -0.02em;
    color: var(--text-hi);
  }
  .topbar .pill-value-s .pc-bar { display: block; width: 100%; margin-top: 2px; }
  /* Words are narrower in the text face than in the figures' one. */
  .topbar .pill-month { font-family: var(--font-ui); letter-spacing: 0; }

  .ticker {
    min-height: var(--ticker-h);
    padding: 0 max(var(--sp-3), var(--safe-r)) 0 max(var(--sp-3), var(--safe-l));
    font-size: var(--fs-body);
  }

  .actionbar {
    min-height: var(--actionbar-h);
    gap: var(--sp-3);
    padding: var(--sp-2) max(var(--sp-3), var(--safe-r)) var(--sp-2) max(var(--sp-3), var(--safe-l));
  }
  .ab-left { flex: 0 1 auto; min-width: 0; }
  .ab-tools { display: none; }
  .ab-wait { display: inline; font-size: var(--fs-small); font-weight: 600; line-height: 1.25; }
  .ab-turn:has(+ .ab-wait) { display: none; }
  /* The month's key: as wide as the bar can spare, never wrapped. */
  .ab-end { flex: 1 0 auto; max-width: 64%; justify-content: flex-end; }
  .ab-end > .btn-turn { width: 100%; min-height: 48px; padding: 10px 12px; letter-spacing: 0.08em; white-space: nowrap; }
}

/* ---- Short landscape: a phone on its side ---------------------------------
   Width puts it with the tablets; height cannot afford their chrome. */
@media (max-height: 520px) and (min-width: 640px) {
  :root { --ticker-h: 24px; --actionbar-h: 48px; }
  .rail .nav-item { min-height: 44px; padding: 4px; }
  .topbar { padding-block: 2px; }
  .topbar .pill { padding-block: 2px; }
  .sticky-actions { position: static; }
  /* Twelve rooms do not fit in some 300px of rail. The rooms below the fold
     fade out at its foot, which says the rail scrolls; the fade is the last
     thing in the rail, held to the foot while there is more to come, and
     drops into the empty space after the last room once it is in view. */
  .rail::after {
    content: "";
    position: sticky;
    bottom: 0;
    display: block;
    height: 32px;
    background: linear-gradient(rgba(0, 0, 0, 0), var(--bg-1) 85%);
    pointer-events: none;
  }
}
/* The compact rail on its side: each room keeps its short name under its
   icon, packed into the finger's 44px instead of growing to the tablet's 58,
   so a room is never only a glyph. */
@media (max-height: 520px) and (min-width: 640px) and (max-width: 1023.98px) {
  .rail .nav-item { padding: 3px 4px; gap: 0; }
  .rail .nav-sign { gap: 2px; }
  .rail .nav-label-s { line-height: 1.15; }
}
