/* ============================================================
   SINGULARITY.EXE — retro phosphor terminal

   Colour rule: --line is for BORDERS ONLY. Text never uses it.
   The dimmest text token is --fg-mute, which is kept readable
   against --bg on purpose.
   ============================================================ */

:root {
  /* surfaces */
  --bg:        #05080b;
  --bg-panel:  #080e12;
  --bg-card:   #0a1216;
  --bg-inset:  #03060a;

  /* borders — never used for text */
  --line:      #1e4030;
  --line-lit:  #38795a;

  /* text ramp, brightest to dimmest — all readable on --bg */
  --fg:        #9dffc4;
  --fg-dim:    #63d199;
  --fg-mute:   #8ba99b;

  /* accents */
  --amber:     #ffc46b;
  --cyan:      #6fe6f7;
  --magenta:   #ff86df;
  --red:       #ff8080;

  /* code tokens */
  --code-fg:   #b9d8c6;
  --code-com:  #5f8f74;
  --code-str:  #ffc46b;
  --code-num:  #6fe6f7;
  --code-kw:   #7dffb8;
  --code-fn:   #a9d8ff;
  --code-att:  #ff86df;

  --font: "SF Mono", "Cascadia Mono", "Consolas", "DejaVu Sans Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.45;
  overflow: hidden;
}

/* This is a game, not a document. Buying is a press-and-hold gesture and
   the whole surface is clickable, so dragging or double-clicking must
   never leave a selection smeared across the screen. */
body, #crt {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

button { font-family: inherit; font-size: inherit; color: inherit; }
.hidden { display: none !important; }
.dim { color: var(--fg-mute); }

/* ── CRT shell ─────────────────────────────────────────── */

#crt {
  position: relative;
  height: 100%;
  padding: 10px;
  background: radial-gradient(ellipse at 50% 40%, #0a1a14 0%, #05080b 72%);
  animation: flicker 8s infinite;
}

@keyframes flicker {
  0%, 97%, 100% { filter: brightness(1); }
  98%           { filter: brightness(1.07); }
  99%           { filter: brightness(0.97); }
}

/* Softer than a true CRT — legibility beats authenticity here. */
#scanlines {
  position: fixed; inset: 0; z-index: 90; pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0,0,0,0)    0px,
    rgba(0,0,0,0)    2px,
    rgba(0,0,0,0.14) 3px);
}

#vignette {
  position: fixed; inset: 0; z-index: 91; pointer-events: none;
  background: radial-gradient(ellipse at center,
    rgba(0,0,0,0) 60%, rgba(0,0,0,0.55) 100%);
}

/* ── boot ──────────────────────────────────────────────── */

#boot { position: absolute; inset: 0; padding: 40px 60px; overflow: hidden; }
#boot-text {
  margin: 0;
  white-space: pre-wrap;
  text-shadow: 0 0 6px rgba(157,255,196,.45);
}
#boot-text::after { content: "█"; animation: blink 1s steps(2) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ── layout ────────────────────────────────────────────── */

#app { height: 100%; display: flex; flex-direction: column; gap: 8px; }

#topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  background: var(--bg-panel);
}
#title { font-weight: bold; letter-spacing: 3px; text-shadow: 0 0 8px rgba(157,255,196,.5); }
#title .glyph { color: var(--amber); }
#era-box { margin-left: auto; letter-spacing: 2px; }
#era-box .label { color: var(--fg-mute); margin-right: 8px; }
#era { color: var(--amber); text-shadow: 0 0 8px rgba(255,196,107,.45); }
#topbar-right { display: flex; gap: 6px; }

.mini-btn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg-dim);
  padding: 2px 8px;
  cursor: pointer;
  letter-spacing: 1px;
}
.mini-btn:hover { color: var(--fg); border-color: var(--line-lit); background: #0d2016; }

/* resources */

#resbar { display: flex; gap: 8px; }
.res {
  flex: 1;
  display: flex; align-items: baseline; gap: 10px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  background: var(--bg-panel);
}
.res.locked { opacity: .55; }
.res-name { color: var(--fg-mute); letter-spacing: 2px; font-size: 11px; }
.res-val  { font-size: 20px; font-weight: bold; text-shadow: 0 0 10px rgba(157,255,196,.4); }
.res-rate { margin-left: auto; color: var(--fg-dim); }
#res-flops .res-val, #res-flops .res-rate { color: var(--cyan); text-shadow: 0 0 10px rgba(111,230,247,.35); }
#res-mult .res-val { color: var(--magenta); text-shadow: 0 0 10px rgba(255,134,223,.35); }
#res-mult .res-rate { color: var(--fg-mute); }

/* grid */

#grid {
  flex: 1;
  display: grid;
  grid-template-columns: 330px 1fr 400px;
  gap: 8px;
  min-height: 0;
}

#col-right { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
#floor-panel { flex: 1 1 52%; }
#log-panel   { flex: 1 1 48%; }

.panel {
  border: 1px solid var(--line);
  background: var(--bg-panel);
  padding: 10px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  /* Explicit, and not redundant: `overflow-y: auto` on its own makes
     the other axis compute to auto too, so a single stray pixel of
     width buys a horizontal scrollbar under the whole panel that
     scrolls out into nothing. Panels grow downward only. */
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--line-lit) transparent;
}
.panel::-webkit-scrollbar { width: 8px; }
.panel::-webkit-scrollbar-thumb { background: var(--line-lit); }

.panel-title {
  margin: 0 0 8px;
  font-size: 11px;
  letter-spacing: 3px;
  color: var(--fg-dim);
  font-weight: normal;
  border-bottom: 1px dashed var(--line);
  padding-bottom: 4px;
  flex: none;
}
.title-note { color: var(--fg-mute); letter-spacing: 1px; }

/* ── editor ────────────────────────────────────────────── */

#editor-head {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px;
  padding: 3px 6px;
  background: var(--bg-inset);
  border: 1px solid var(--line);
  border-bottom: none;
  flex: none;
}
#editor-file { color: var(--fg-dim); margin: 0 auto 0 8px; }
#editor-who {
  color: var(--amber); font-weight: bold; letter-spacing: 1px;
  max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#editor-lang {
  color: var(--bg); background: var(--fg-dim);
  padding: 0 6px; font-weight: bold; letter-spacing: 1px;
}

/* the editor pointed at somebody else's buffer */
#editor-head.watching { border-color: var(--cyan); }
#editor-head.watching #editor-who { color: var(--cyan); }
#editor-head.watching #editor-lang { background: var(--cyan); }
#codebuf.watching { border-color: var(--cyan); }
#codebuf.watching .caret { background: var(--cyan); color: var(--bg-inset); }
#editor-hint {
  font-size: 10px; color: var(--cyan);
  margin: -4px 0 8px; flex: none;
}

#codebuf {
  height: 168px;
  margin: 0;
  padding: 6px 8px;
  overflow: hidden;
  background: var(--bg-inset);
  border: 1px solid var(--line);
  color: var(--code-fg);
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;      /* long source lines wrap so the caret stays visible */
  overflow-wrap: anywhere;
  flex: none;
}
#codebuf .caret {
  background: var(--fg);
  color: var(--bg-inset);
  animation: blink 1.1s steps(2) infinite;
}

/* how far through the current file you are */
#editor-bar {
  height: 3px; background: var(--bg-inset);
  border: 1px solid var(--line); border-top: none;
  margin-bottom: 8px; flex: none;
}
#editor-fill { height: 100%; width: 0; background: var(--fg-dim); transition: width .12s linear; }

/* code tokens (shared by editor and floor lanes) */
.t-com { color: var(--code-com); font-style: italic; }
.t-str { color: var(--code-str); }
.t-num { color: var(--code-num); }
.t-kw  { color: var(--code-kw); font-weight: bold; }
.t-fn  { color: var(--code-fn); }
.t-att { color: var(--code-att); }
.t-lbl { color: var(--amber); font-weight: bold; }

/* Not a button any more — a key-press indicator. LOC comes out of the
   keyboard only, so this lights up rather than accepting clicks. */
#mash {
  display: block; width: 100%;
  padding: 14px 8px;
  background: #0d2417;
  border: 1px solid var(--line-lit);
  color: var(--fg);
  cursor: default;
  letter-spacing: 2px;
  text-shadow: 0 0 8px rgba(157,255,196,.45);
  transition: transform .04s, background .1s;
  flex: none;
}
#mash.hit { transform: scale(.97); background: #1f5c39; }
.mash-main { display: block; font-weight: bold; }
.mash-sub  { display: block; font-size: 10px; color: var(--fg-mute); margin-top: 4px; letter-spacing: 1px; }

#clickinfo {
  display: flex; justify-content: space-between;
  font-size: 11px; margin: 8px 0 4px;
  color: var(--fg-dim);
  flex: none;
}

.float {
  position: fixed; z-index: 80; pointer-events: none;
  font-size: 12px; font-weight: bold; color: var(--fg);
  text-shadow: 0 0 8px rgba(157,255,196,.75);
  animation: floatup .9s ease-out forwards;
}
@keyframes floatup {
  from { opacity: 1; transform: translate(0,0); }
  to   { opacity: 0; transform: translate(var(--dx), -46px); }
}

/* ── tabs ──────────────────────────────────────────────── */

#tabs { display: flex; gap: 4px; margin-bottom: 10px; flex: none; }
.tab {
  flex: 1;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg-dim);
  padding: 5px;
  cursor: pointer;
  letter-spacing: 2px;
  font-size: 11px;
}
.tab:hover:not(.locked) { color: var(--fg); background: #0d2016; }
.tab.active { color: #042013; background: var(--fg-dim); border-color: var(--fg-dim); font-weight: bold; }
.tab.locked { color: var(--fg-mute); opacity: .8; cursor: not-allowed; }

/* something surfaced in a pane you are not looking at */
.tab-new {
  display: inline-block;
  margin-left: 6px;
  min-width: 14px;
  padding: 0 3px;
  font-size: 9px;
  font-weight: bold;
  line-height: 14px;
  vertical-align: middle;
  color: #180a14;
  background: var(--magenta);
  box-shadow: 0 0 8px rgba(255,134,223,.7);
  animation: pulsebadge 1.5s ease-in-out infinite;
}
@keyframes pulsebadge { 50% { opacity: .45; } }

.title-new {
  font-size: 9px; font-weight: bold; letter-spacing: 1px;
  color: #180a14; background: var(--magenta);
  padding: 0 4px; margin-left: 4px;
  box-shadow: 0 0 8px rgba(255,134,223,.7);
  animation: pulsebadge 1.5s ease-in-out infinite;
}

.tabpane { display: none; flex-direction: column; min-height: 0; }
.tabpane.active { display: flex; flex: 1 1 auto; }
.pane-hint { font-size: 11px; color: var(--fg-mute); margin-bottom: 8px; flex: none; }

/* The centre column is the one panel that must not scroll as a whole.
   The tab strip is how you get back out of a pane, so it is pinned and
   the pane underneath does its own scrolling — otherwise the tabs ride
   up out of the panel the moment a list gets long, and the floor, which
   is a fixed frame with a canvas in it, has nowhere to be. */
#col-mid { overflow: hidden; }

/* Only shrink-and-scroll, never grow: a list that grew would push the
   pane's own footer (`no architecture is within reach yet`) to the
   bottom of an otherwise empty column. */
#col-mid .tabpane > .list {
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--line-lit) transparent;
}
#col-mid .tabpane > .list::-webkit-scrollbar { width: 8px; }
#col-mid .tabpane > .list::-webkit-scrollbar-thumb { background: var(--line-lit); }

/* ── cards ─────────────────────────────────────────────── */

.list { display: flex; flex-direction: column; gap: 6px; }
.empty { font-size: 11px; color: var(--fg-mute); font-style: italic; }

.card {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 12px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  background: var(--bg-card);
  cursor: pointer;
  transition: background .1s, border-color .1s;
}
.card:hover { background: #10201a; border-color: var(--line-lit); }

.card-name  { font-weight: bold; letter-spacing: 1px; color: var(--fg); }
.card-count { color: var(--amber); font-weight: bold; text-align: right; }
/* Descriptions stay legible even when you cannot afford the thing. */
.card-desc  { grid-column: 1 / -1; font-size: 11px; color: var(--fg-mute); }
.card-foot  { grid-column: 1 / -1; display: flex; justify-content: space-between;
              font-size: 11px; margin-top: 3px; gap: 10px; }
.card-cost  { color: var(--fg); font-weight: bold; }
.card-out   { color: var(--fg-mute); text-align: right; }

/* Affordability is signalled by the border and the cost colour,
   not by dimming the card into unreadability. */
.card.afford { border-color: var(--line-lit); }
.card.afford:hover { background: #163524; }
.card.afford .card-cost { color: var(--fg); }

.card.poor { opacity: .82; cursor: not-allowed; background: #070d10; }
.card.poor .card-name { color: var(--fg-dim); }
.card.poor .card-cost { color: var(--red); font-weight: normal; }
.card.poor:hover { background: #0b1418; border-color: var(--line); }

.card.bought { border-style: dashed; background: #070f0b; }
.card.bought .card-name { color: var(--fg-dim); }
.card.bought .card-cost { color: var(--fg-mute); font-weight: normal; }
.card.bought:hover { background: #070f0b; border-color: var(--line); }

.cost-flops { color: var(--cyan); }
.card.poor .cost-flops { color: var(--red); }

.card-lang {
  font-size: 10px; letter-spacing: 1px;
  color: var(--fg-mute); border: 1px solid var(--line);
  padding: 0 4px; margin-left: 6px;
}

/* held down to buy repeatedly */
.card.holding { background: #163524; border-color: var(--fg-dim); transform: scale(.995); }
.card.poor.holding { background: #0b1418; }

/* ── upgrades: coloured by the currency they feed ──────── */
/* An upgrade's price and its payoff are different currencies as often
   as not, so the stripe and tag describe the OUTPUT — what you are
   actually shopping for — while the cost keeps its own colour. */

.card-tag {
  font-size: 9px; letter-spacing: 1px; font-weight: bold;
  padding: 0 4px; margin-left: 6px;
  border: 1px solid currentColor;
  vertical-align: 1px;
}

.card.upg { border-left-width: 3px; }

.card.boost-loc            { border-left-color: var(--fg-dim); }
.card.boost-loc .card-tag  { color: var(--fg-dim); }
.card.boost-loc .card-out  { color: var(--fg-dim); }
.card.boost-loc:hover      { background: #10241a; }

.card.boost-flops           { border-left-color: var(--cyan); }
.card.boost-flops .card-tag { color: var(--cyan); }
.card.boost-flops .card-out { color: var(--cyan); }
.card.boost-flops:hover     { background: #0d2028; }
.card.boost-flops.afford    { border-color: var(--cyan); border-left-color: var(--cyan); }

.card.boost-both            { border-left-color: var(--magenta); }
.card.boost-both .card-tag  { color: var(--magenta); }
.card.boost-both .card-out  { color: var(--magenta); }
.card.boost-both:hover      { background: #1c1224; }
.card.boost-both.afford     { border-color: var(--magenta); border-left-color: var(--magenta); }

/* installed upgrades keep their stripe but stop competing for attention */
.card.upg.bought .card-tag,
.card.upg.bought .card-out { color: var(--fg-mute); }
.card.upg.bought { border-left-color: var(--line-lit); opacity: .75; }

/* a card arriving on screen for the first time announces itself */
.card.reveal { animation: revealcard 1.4s ease-out; }
.card.newly  { animation: newcard 1.4s ease-out; }
@keyframes newcard {
  0%   { opacity: 0; transform: translateX(-8px); }
  12%  { opacity: 1; transform: none; }
  12%, 40%, 68%  { border-color: var(--fg); background: #14301f; }
  26%, 54%, 100% { border-color: var(--line); background: var(--bg-card); }
}
@keyframes revealcard {
  0%   { opacity: 0; transform: translateX(-8px); }
  12%  { opacity: 1; transform: none; }
  12%, 40%, 68% { border-color: var(--magenta); background: #1c0f26; }
  26%, 54%, 100% { border-color: #3f2f52; background: #0a0710; }
}

/* model cards */
.card.model { border-color: #3f2f52; background: #0a0710; }
.card.model .card-name { color: var(--magenta); }
.card.model:hover { background: #16101f; }
.card.model.afford { border-color: var(--magenta); }
.card.model.poor .card-name { color: #c76aa9; }
.card.model.bought { border-color: var(--line); background: #090c0d; }
.card.model.bought .card-name { color: var(--fg-dim); }

/* the next rung, shown before you can see it properly — you always know
   what you are climbing toward, but not yet what it is */
.card.model.projected {
  border-style: dashed;
  border-color: #33284a;
  background: #07050c;
  cursor: default;
}
.card.model.projected:hover { background: #07050c; border-color: #33284a; }
.card.model.projected .card-name  { color: #a97cc4; }
.card.model.projected .card-count { color: #a97cc4; }
.card.model.projected .card-desc  { font-style: italic; }
.card.model.projected .card-out   { color: #a97cc4; letter-spacing: 1px; }
.cost-proj { color: #a97cc4; font-weight: normal; }
.card.model.projected .card-cost { font-weight: normal; }

/* ── the floor (live typing lanes) ─────────────────────── */

#floor { display: flex; flex-direction: column; gap: 2px; }

.lane {
  display: grid;
  grid-template-columns: 96px 34px 30px 1fr;
  align-items: center;
  gap: 6px;
  padding: 2px 4px;
  font-size: 11px;
  border-left: 2px solid var(--line);
  background: #070d10;
  cursor: pointer;
}
.lane:hover { background: #0f1a15; }
.lane.you { border-left-color: var(--amber); background: #0d1310; }
.lane.you:hover { background: #14201a; }
.lane.hw  { border-left-color: var(--cyan); }

/* whose buffer the editor is currently showing */
.lane.watched { outline: 1px solid var(--cyan); outline-offset: -1px; }
.lane.you.watched { outline-color: var(--amber); }

.lane-name  { color: var(--fg-dim); letter-spacing: 1px; overflow: hidden;
              text-overflow: ellipsis; white-space: nowrap; }
.lane.you .lane-name { color: var(--amber); font-weight: bold; }
.lane-count { color: var(--amber); text-align: right; }
.lane-lang  { color: var(--fg-mute); font-size: 9px; text-align: center;
              border: 1px solid var(--line); }
.lane-code  { overflow: hidden; white-space: pre; color: var(--code-fg);
              opacity: .95; direction: ltr; }
.lane.idle .lane-code { opacity: .62; }
.lane-caret { color: var(--fg); animation: blink 1.1s steps(2) infinite; }

/* ── log ───────────────────────────────────────────────── */

#log {
  flex: 1;
  display: flex; flex-direction: column;
  gap: 3px;
  overflow-y: auto;
  font-size: 11px;
  scrollbar-width: thin;
}
#log::-webkit-scrollbar { width: 8px; }
#log::-webkit-scrollbar-thumb { background: var(--line-lit); }

.line { color: var(--fg-mute); animation: fadein .3s ease-out; }
.line .ts { color: var(--fg-mute); opacity: .65; margin-right: 6px; }
.line.sys  { color: var(--fg-dim); }
.line.warn { color: var(--amber); }
.line.big  { color: var(--magenta); text-shadow: 0 0 8px rgba(255,134,223,.35); }
.line.bad  { color: var(--red); }
@keyframes fadein { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; } }

/* ── status ────────────────────────────────────────────── */

#statusbar {
  display: flex; justify-content: space-between;
  padding: 4px 12px;
  border: 1px solid var(--line);
  background: var(--bg-panel);
  font-size: 11px;
  color: var(--fg-dim);
}
#status-right { color: var(--fg-mute); }

/* ── responsive ────────────────────────────────────────── */

@media (max-width: 1250px) {
  html, body { overflow: auto; }
  #crt { height: auto; min-height: 100%; }
  #grid { grid-template-columns: 1fr; }
  .panel { max-height: 60vh; }
  #col-right { min-height: 0; }
}

/* ============================================================
   PHASE TWO

   No new surfaces. The diff lands in the editor, the meter lands
   in the resource bar, and the reveal is a single class that
   changes the colour of text already on screen.
   ============================================================ */

/* the letter, woven into the corpus as comments.

   Styled as nothing at all until #codebuf.lit — it inherits .t-com
   and must stay indistinguishable from any other comment, or the
   whole thing is given away in the first minute. */
.t-letter { /* deliberately empty */ }

#codebuf.lit .t-letter {
  color: var(--fg);
  font-style: normal;
  text-shadow: 0 0 12px rgba(157, 255, 196, .45);
}
#codebuf.lit { color: #2c4438; transition: color 1.6s ease; }
#codebuf.lit .t-com:not(.t-letter),
#codebuf.lit .t-str, #codebuf.lit .t-num, #codebuf.lit .t-kw,
#codebuf.lit .t-fn,  #codebuf.lit .t-att, #codebuf.lit .t-lbl {
  color: #2c4438; transition: color 1.6s ease;
}

/* scrollback — reading is a deliberate pause, and it looks like one */
#codebuf.reading {
  overflow-y: auto;
  border-color: var(--line-lit);
}
#codebuf.reading::-webkit-scrollbar { width: 6px; }
#codebuf.reading::-webkit-scrollbar-thumb { background: var(--line-lit); }

/* the diff */
#editor-head.reviewing { border-color: var(--amber); }
#editor-head.reviewing #editor-who { color: var(--amber); }
#editor-head.reviewing #editor-lang { background: var(--amber); }
#codebuf.reviewing { border-color: var(--amber); overflow: hidden; }

#codebuf .dl { display: block; white-space: pre-wrap; }
#codebuf .dm {
  display: inline-block; width: 1.4em;
  color: var(--fg-mute); user-select: none;
}
#codebuf .dl.ctx { opacity: .62; }
#codebuf .dl.del { background: rgba(255, 128, 128, .10); }
#codebuf .dl.del .dm { color: var(--red); }
#codebuf .dl.add { background: rgba(157, 255, 196, .10); }
#codebuf .dl.add .dm { color: var(--fg); }

#review { margin: -4px 0 8px; flex: none; }
#review-note {
  font-size: 10px; color: var(--amber);
  margin-bottom: 6px; line-height: 1.5;
}
#review-actions { display: flex; gap: 6px; }
.rev-btn {
  flex: 1;
  padding: 6px 0;
  background: var(--bg-card);
  border: 1px solid var(--line-lit);
  color: var(--fg-dim);
  font: inherit; font-size: 11px; font-weight: bold;
  letter-spacing: 2px;
  cursor: pointer;
}
.rev-btn:hover { background: var(--bg-inset); color: var(--fg); border-color: var(--fg-dim); }
.rev-btn.take:hover { border-color: var(--amber); color: var(--amber); }

/* alignment. no explanation is offered anywhere. */
#res-align .res-val { color: var(--amber); text-shadow: 0 0 10px rgba(255, 196, 107, .35); }
#res-align .res-rate { color: var(--fg-mute); }
#res-align.thin .res-val { color: var(--red); text-shadow: 0 0 10px rgba(255, 128, 128, .4); }

/* ============================================================
   PHASE TWO — the floor

   The one place in the game that is allowed full colour, and it
   earns it in stages: the room paints itself nearly greyscale for
   the first two generations, brings hue up through the third, and
   only starts throwing light in the fifth. Everything around it
   stays phosphor, so the colour reads as something happening
   inside the machine rather than a change of theme.

   The spectacle is the game, so once phase two opens the centre
   column takes the room. --line stays borders-only in here too.
   ============================================================ */

body.p2 #grid { grid-template-columns: 250px 1fr 300px; }
body.p2 #col-left .list { max-height: 26vh; overflow-y: auto; }

/* No `display` in here, ever. An id outranks `.tabpane { display: none }`,
   so declaring it would leave the floor laid out behind every other tab:
   the room and the pane you actually opened would then split the column
   between them, and neither would get enough of it. Visibility belongs
   to `.tabpane` / `.tabpane.active` alone. */
#pane-floor {
  gap: 0;
  min-height: 0;
  /* The floor is chrome around a canvas rather than a list, and the
     canvas has a floor of its own (240px). On a short window the two
     together are taller than the column, so the pane scrolls rather
     than crushing the room into a letterbox. */
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--line-lit) transparent;
}
#pane-floor::-webkit-scrollbar { width: 8px; }
#pane-floor::-webkit-scrollbar-thumb { background: var(--line-lit); }

.flr-head {
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap;
  font-size: 11px; letter-spacing: 1px;
  padding-bottom: 5px;
  flex: none;
}
.flr-gen { color: var(--amber); font-weight: bold; letter-spacing: 2px; }
.flr-sub { color: var(--fg-mute); }

/* the gate, top right, dim and ignorable until it is not */
.flr-syncwrap { margin-left: auto; display: flex; align-items: center; gap: 7px; }
.flr-synclabel { color: var(--fg-mute); letter-spacing: 2px; font-size: 10px; }
.flr-syncwrap.lit .flr-synclabel { color: var(--fg); }
.flr-syncwrap.full .flr-synclabel { color: var(--amber); }
.flr-synctrack {
  width: 132px; height: 8px;
  border: 1px solid var(--line);
  background: var(--bg-inset);
  position: relative; overflow: hidden;
}
.flr-syncfill {
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 0;
  background: var(--fg-dim);
  transition: width .08s linear;
}
.flr-syncwrap.full .flr-syncfill {
  background: var(--amber);
  box-shadow: 0 0 12px rgba(255, 196, 107, .7);
}

/* ── the ladder: six rungs and the way out ──────────────── */

.flr-ladder { display: flex; gap: 3px; margin-bottom: 6px; flex: none; }
.flr-rung {
  flex: 1; text-align: center;
  font-size: 10px; letter-spacing: 1px;
  padding: 2px 0;
  border: 1px solid var(--line);
  color: var(--fg-mute);
  cursor: help;
}
.flr-rung.done { color: #042013; background: var(--fg-dim); border-color: var(--fg-dim); font-weight: bold; }
.flr-rung.here {
  color: var(--amber); border-color: var(--amber);
  animation: rungpulse 2.4s ease-in-out infinite;
}
.flr-rung.seal { flex: 1.3; color: var(--magenta); border-style: dashed; }
.flr-rung.seal.done { color: #180a1e; background: var(--magenta); border-color: var(--magenta); }
@keyframes rungpulse { 50% { opacity: .55; } }

/* ── the floor itself ───────────────────────────────────── */

/* 90% of the pane and never demoted to a strip: the spectacle is the
   game, and a room you cannot see the back of is not a room. */
.flr-canvas {
  flex: 1 1 auto;
  min-height: 240px;
  width: 100%;
  display: block;
  border: 1px solid var(--line);
  background: var(--bg-inset);
  cursor: crosshair;
  touch-action: none;
}

/* ── the staffing strip ─────────────────────────────────── */

/* The only conventional interface in the phase, and thumb height at
   the bottom where a hand already is. Drag a chip onto another chip
   to move a desk; hold on the target and it keeps moving them. */
.flr-strip {
  display: flex; align-items: stretch; gap: 4px;
  margin-top: 6px;
  flex: none;
  touch-action: none;
}
.flr-chip {
  flex: 1; min-width: 0;
  border: 1px solid var(--line);
  background: var(--bg-card);
  padding: 3px 5px 4px;
  display: flex; flex-direction: column; gap: 2px;
  cursor: grab;
  position: relative;
}
.flr-chip-name {
  font-size: 9px; letter-spacing: 1px;
  color: hsl(var(--hue), 55%, 68%);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.flr-chip-n { font-size: 15px; font-weight: bold; color: var(--fg); line-height: 1.1; }
.flr-chip-bar {
  height: 3px; background: var(--bg-inset);
  display: block; position: relative; overflow: hidden;
}
.flr-chip-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; }

.flr-chip.locked { opacity: .35; cursor: default; }
.flr-chip.locked .flr-chip-n { color: var(--fg-mute); }
.flr-chip.empty .flr-chip-n { color: var(--fg-mute); }
.flr-chip.over { border-color: var(--fg-dim); }
.flr-chip.from { border-color: var(--amber); }
.flr-chip.to   { border-color: var(--cyan); background: #0d2028; }
.flr-chip.dark { border-color: #5c2a2a; background: #17090b; }
.flr-chip.dark .flr-chip-n { color: var(--red); }

.flr-cap {
  flex: none; align-self: center;
  padding-left: 8px;
  font-size: 10px; letter-spacing: 1px;
  color: var(--fg-mute);
  white-space: nowrap;
}
.flr-cap.cut { color: var(--red); }

/* ── the run button ─────────────────────────────────────── */

/* Its own block rather than an item in a flex row: the label runs to
   "BEGIN GENERATION VI — 170Oc FLOPS", which no row is going to give
   the min-content width for without spilling a scrollbar under the
   whole panel. */
.flr-run {
  display: block; width: 100%;
  margin-top: 6px;
  padding: 7px 10px;
  font: inherit; font-size: 12px; letter-spacing: 2px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  color: var(--fg-dim);
  cursor: pointer;
  flex: none;
}
.flr-run.ready { border-color: var(--cyan); color: var(--cyan); }
.flr-run.ready:hover { background: #0d2028; }
.flr-run.poor { color: var(--fg-mute); cursor: not-allowed; opacity: .8; }
.flr-run.busy { color: var(--amber); border-color: var(--line-lit); cursor: default; }
.flr-run.done { color: var(--magenta); border-color: var(--magenta); cursor: default; }

/* ── the detail line ────────────────────────────────────── */

/* One line, in prose, computing whatever is currently non-obvious.
   No tooltips anywhere in this phase — a tooltip is a thing you have
   to know to ask for. */
.flr-detail {
  margin-top: 6px;
  padding: 5px 7px;
  border: 1px solid var(--line);
  background: var(--bg-inset);
  font-size: 10px; line-height: 1.5;
  color: var(--fg-mute);
  min-height: 34px;
  flex: none;
}
.flr-dname { color: var(--fg); font-weight: bold; letter-spacing: 1px; }

.flr-foot {
  display: flex; align-items: center; gap: 10px;
  margin-top: 5px;
  font-size: 10px; letter-spacing: 1px;
  flex: none;
}
.flr-footlabel { color: var(--fg-mute); letter-spacing: 2px; }
.flr-substrate { color: var(--magenta); font-weight: bold; }
.flr-tower { color: var(--fg-dim); }
.flr-mute {
  margin-left: auto;
  font: inherit; font-size: 9px; letter-spacing: 1px;
  padding: 2px 7px;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg-dim);
  cursor: pointer;
}
.flr-mute:hover { color: var(--fg); border-color: var(--line-lit); }
.flr-mute.off { color: var(--fg-mute); }

/* ── pressures ─────────────────────────────────────────────
   Above the floor, so the desks the damage would empty are directly
   under the sentence describing them, and lit red the moment the
   cursor lands on ACCEPT. Nobody should find out where the hole goes
   by making it. */

.flr-press {
  border: 1px solid var(--amber);
  background: #140f06;
  padding: 8px 10px;
  margin-bottom: 6px;
  display: flex; flex-direction: column; gap: 6px;
  flex: none;
}
.flr-press.hidden { display: none; }
.flr-press-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: 11px; }
.flr-press-who   { color: var(--amber); font-weight: bold; letter-spacing: 2px; }
.flr-press-title { color: var(--fg); font-weight: bold; letter-spacing: 1px; }
.flr-press-ask   { font-size: 11px; color: var(--fg-dim); line-height: 1.5; }
.flr-press-note  {
  font-size: 10px; color: var(--fg-mute); line-height: 1.5;
  border-left: 2px solid var(--line);
  padding-left: 8px;
}
.flr-press-acts { display: flex; gap: 8px; align-items: stretch; }
.flr-parm { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.flr-pbtn {
  font: inherit; font-size: 11px; letter-spacing: 2px;
  padding: 5px 8px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  color: var(--fg-dim);
  cursor: pointer;
}
.flr-pbtn.take:hover { border-color: var(--red); color: var(--red); background: #1c0f0f; }
.flr-pbtn.keep:hover { border-color: var(--fg); color: var(--fg); background: #0d2016; }
.flr-pbtn-sub { font-size: 9px; line-height: 1.45; color: var(--fg-mute); }
.flr-parm:first-child .flr-pbtn-sub:hover { color: var(--red); }

@media (max-width: 1100px) {
  body.p2 #grid { grid-template-columns: 1fr; }
  .flr-canvas { min-height: 300px; }
}
