/* Rack & Ruin.
   The look is a night-shift control room: warm charcoal, bone type, amber for
   anything that wants your attention, and cold cyan reserved for the cold side
   of the plant. Rules and spacing separate things; borders are the exception,
   not the rule. */

:root {
  /* Whether the inspector is a band that is always there or a sheet that
     covers the floor. Declared here so the breakpoint lives in one place:
     the script reads this rather than repeating the media queries, which
     is how the two drift apart. */
  --inspector: band;

  --bg: #0e0c0a;
  --panel: #15120f;
  --panel2: #1b1713;
  --raise: #241f19;
  --line: #292319;
  --line2: #3b3225;
  --fg: #ede6da;
  --dim: #a2978a;
  --dimmer: #6e6458;
  --acc: #f2a83c;          /* amber — the primary voice */
  --acc-dim: #7a5620;
  --cold: #6fc8d8;         /* only for the cold side: cooling, water */
  --good: #93cc6d;
  --warn: #f2c14e;
  --bad: #e5614f;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;
  --r: 5px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  margin: 0; height: 100%; overflow: hidden;
  background: var(--bg); color: var(--fg);
  font-family: var(--sans); font-size: 13.5px; line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
button { font: inherit; color: inherit; cursor: pointer; background: none; border: 0; }
h1, h2, h3, h4 { margin: 0; font-weight: 620; }
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb { background: #332c22; border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: #473d2e; }
::-webkit-scrollbar-track { background: transparent; }

.eyebrow, .sec > h3, .todohead, .sparklabel, .vital .lbl, .mini .mk, .meter .mk,
.speedlbl, table.grid th, .sheet h4, .sheet .gh, #objective .k, #tutorial .tk {
  font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--dimmer); font-weight: 600;
}

/* ------------------------------------------------------------------ boot */

#boot {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background:
    radial-gradient(900px 520px at 50% 0%, #241c12 0%, transparent 60%),
    linear-gradient(#14110d, #0a0908);
}
#bootsky { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.bootcard { position: relative; width: min(620px, 92vw); text-align: center; padding: 30px;
  animation: bootin .7s cubic-bezier(.2,.7,.3,1) both; }
@keyframes bootin { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .bootcard { animation: none; } }
.bootcard h1 { font-size: 58px; letter-spacing: -2px; font-weight: 700; }
.bootcard h1 { text-shadow: 0 2px 30px rgba(0,0,0,.85); }
.bootcard h1 span { color: var(--acc); text-shadow: 0 0 26px rgba(242,168,60,.45); }
/* The game's own name sits under the product name, smaller. */
.bootcard .sub {
  font-family: var(--mono); font-size: 13px; letter-spacing: .34em; text-transform: uppercase;
  color: var(--dim); margin: 8px 0 0; text-indent: .34em;
}
.bootcard .tag { color: var(--dim); margin: 14px 0 32px; font-size: 15px; }
#bootbody { display: grid; gap: 14px; }
#bootbody .row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
#bootbody .note { color: var(--dimmer); font-size: 12px; }
/* Small enough to ignore, there when you need to know what is deployed. */
.bootcard .build { color: var(--dimmer); font-size: 10.5px; font-family: var(--mono);
  margin-top: 22px; letter-spacing: .06em; }

/* ------------------------------------------------------------------- app */

#app { display: grid; grid-template-rows: auto 1fr auto; height: 100%; }

/* --------------------------------------------------------------- top bar */

#topbar {
  display: flex; align-items: stretch; gap: 20px; flex-wrap: nowrap;
  background: linear-gradient(180deg, #191510, #120f0c);
  border-bottom: 1px solid var(--line); padding: 8px 16px 7px;
  /* Fixed height for the same reason as the footer: a number growing a digit
     must never reflow the bar and resize the floor underneath it. */
  height: 74px; overflow: hidden;
}
.vital { display: flex; flex-direction: column; justify-content: center;
  width: 128px; flex: none; }
.vital .big {
  font-family: var(--mono); font-size: 23px; font-weight: 600; line-height: 1.1;
  letter-spacing: -.8px; font-variant-numeric: tabular-nums;
}
.vital .big, .vital .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vital .sub { font-size: 11px; color: var(--dim); font-family: var(--mono); }
.vital.good .big { color: var(--good); }
.vital.bad  .big { color: var(--bad); }
.vital.warn .sub { color: var(--warn); }
.vital.jump { cursor: pointer; border-radius: var(--r); margin: -3px -8px; padding: 3px 8px; }
.vital.jump:hover { background: #1e1913; }
.vital.jump .sub::after { content: ' \2192'; }

.meters { display: grid; grid-template-columns: repeat(2, auto);
  gap: 5px 18px; align-content: center; flex: none; }
.meter { display: grid; grid-template-columns: auto 46px auto; align-items: center; gap: 9px; }
.meter .mk, .meter .mv { white-space: nowrap; }
.meter .mbar { height: 6px; background: #0c0a08; box-shadow: inset 0 0 0 1px #2a2419; overflow: hidden; }
.meter .mbar > i { display: block; height: 100%; background: var(--cold); transition: width .25s; }
.meter .mv { font-family: var(--mono); font-size: 10.5px; color: var(--dim); text-align: right;
  font-variant-numeric: tabular-nums; }
/* State is not carried by colour alone.
   Rendering a real frame through a deuteranopia filter, all four top-bar
   meters came out the same yellow-green: a player could not see that cooling
   and network were over capacity, which is the most important read on the
   screen. The bar also clamps at 100%, so an over-capacity meter looked
   identical to a merely full one and the colour was doing all the work.
   Stripes carry it instead, and they survive any colour vision. */
.meter.warn .mbar > i { background: var(--warn); }
.meter.bad .mbar > i {
  background:
    repeating-linear-gradient(115deg,
      var(--bad) 0 4px, #7d2b22 4px 8px);
}
.meter.bad .mv { color: var(--bad); }
.meter.bad .mv::before { content: '! '; font-weight: 700; }
/* The town drivers need room for a word and a real number, unlike the top-bar
   meters they borrow their shape from. */
.townmeter { grid-template-columns: 54px 1fr 92px; margin: 5px 0; }
.townmeter .mk { white-space: nowrap; }
.townmeter .mv { font-size: 11px; }

.minis { display: grid; grid-template-columns: repeat(3, auto); gap: 4px 18px;
  grid-auto-flow: column; grid-template-rows: repeat(2, auto);
  align-content: center; flex: none; }
.mini { display: flex; gap: 8px; align-items: baseline; }
.mini .mk { white-space: nowrap; }
.mini .mv { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums;
  margin-left: auto; white-space: nowrap; }
.mini.warn .mv { color: var(--warn); }
.mini.bad .mv { color: var(--bad); }
.mini.acc .mv { color: var(--acc); }

.divider { width: 1px; background: var(--line); margin: 5px 0; }
.spacer { flex: 1; }

.topright { display: flex; align-items: center; gap: 10px; flex: none; margin-left: auto; }

/* How many people are playing, next to the speed control.
   The number is fixed-width on purpose: the top bar re-measures itself when
   its width changes, and a count going 9 -> 10 must not be able to trigger
   that. Hidden entirely until the server has actually answered. */
.livecount { display: flex; align-items: center; gap: 6px; flex: none;
  padding: 4px 9px 4px 8px; border: 1px solid var(--line2); border-radius: 100px;
  background: var(--panel2); font-size: 12px; color: var(--dim); cursor: default; }
.livecount[hidden] { display: none; }
.livecount i { width: 7px; height: 7px; border-radius: 50%; background: var(--good);
  box-shadow: 0 0 0 0 rgba(147, 204, 109, .55); animation: pulse 2.8s ease-out infinite; }
.livecount b { font: 600 12px var(--mono); color: var(--fg);
  min-width: 2ch; text-align: right; }
.livecount.alone i { background: var(--dimmer); animation: none; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(147, 204, 109, .5); }
  70%  { box-shadow: 0 0 0 7px rgba(147, 204, 109, 0); }
  100% { box-shadow: 0 0 0 0 rgba(147, 204, 109, 0); }
}
.speeds {
  display: flex; align-items: center; gap: 3px; align-self: center;
  background: #0d0b09; border: 1px solid var(--line2); border-radius: var(--r); padding: 3px 5px 3px 9px;
}
.speedlbl { margin-right: 4px; }
.sp {
  min-width: 40px; padding: 6px 9px; border-radius: 3px; font-size: 12.5px; font-weight: 600;
  font-family: var(--mono); color: var(--dim); letter-spacing: .02em;
}
.sp:hover { color: var(--fg); background: #241e16; }
.sp.on { background: var(--acc); color: #17120a; }
.sp.on.paused { background: #4a3410; color: var(--warn); box-shadow: inset 0 0 0 1px var(--warn); }

.topbtn {
  align-self: center; background: #1c1712; border: 1px solid var(--line2); border-radius: var(--r);
  padding: 7px 13px; font-size: 12px; color: var(--dim);
}
.topbtn:hover { background: #262019; color: var(--fg); }
.topbtn.icon { display: grid; place-items: center; padding: 6px 10px; }
.topbtn.icon svg { display: block; width: 20px; height: 16px; fill: none;
  stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.topbtn.icon svg path:first-child { fill: currentColor; stroke-width: 1.2; }
.topbtn.icon svg .w1, .topbtn.icon svg .w2 { opacity: .85; }
.topbtn.icon svg .x { stroke: var(--bad); }
.topbtn.icon.off { color: var(--dimmer); }
/* the outer wave breathes while sound is on, so the button reads as live */
.topbtn.icon:not(.off) svg .w2 { animation: wave 2.6s ease-in-out infinite; }
@keyframes wave { 0%, 100% { opacity: .3; } 50% { opacity: .95; } }
@media (prefers-reduced-motion: reduce) {
  .topbtn.icon:not(.off) svg .w2 { animation: none; opacity: .85; }
}

/* ----------------------------------------------------------------- main */

#main { display: grid; grid-template-columns: 1fr 412px; min-height: 0; min-width: 0; }

#floor { display: grid; grid-template-rows: auto 1fr auto; min-width: 0; min-height: 0;
  overflow: hidden; }
#panel { min-width: 0; }
#floorhead {
  display: flex; align-items: center; gap: 12px; padding: 7px 16px;
  border-bottom: 1px solid var(--line); background: #120f0c;
  /* min-width lets the chips shrink; the clipping lives on #events itself.
     overflow:hidden here would make this a scroll container, and an auto grid
     row measures one of those as zero — the whole row collapsed to its
     padding and the buttons were sliced off. */
  min-width: 0;
}
#facilityname { font-weight: 600; font-size: 13px; }
/* The tools never wrap to a second line: the row above the floor has a fixed
   height, and a second line of buttons pushes the floor down. */
#floortools { margin-left: auto; display: flex; gap: 3px; flex-wrap: nowrap; flex: none; }
.tool { border-radius: 3px; padding: 5px 11px; font-size: 11.5px; color: var(--dim); }
.tool:hover { background: #201a14; color: var(--fg); }
.tool.on { background: var(--acc-dim); color: #ffdca0; box-shadow: inset 0 0 0 1px #8a6224; }
/* Only on screen while a machine is held. Just the cross: which machine you
   are holding is already on the row that is marked "selected", so the button
   only has to be findable, not explanatory. */
.dropbtn {
  position: absolute; right: 10px; top: 10px; z-index: 21;
  display: grid; place-items: center; width: 30px; height: 30px; padding: 0;
  background: #1d1710e8; color: var(--acc);
  border: 1px solid #6b4d1e; border-radius: 50%;
  font-size: 13px; line-height: 1; box-shadow: 0 4px 14px #0008;
}
.dropbtn:hover { background: var(--acc); color: #17120a; border-color: var(--acc); }
.dropbtn:active { background: #e09428; color: #17120a; }

#canvaswrap { position: relative; overflow: hidden; min-height: 220px;
  background: radial-gradient(900px 640px at 46% 14%, #191510, #0b0908 74%); }
#view { display: block; width: 100%; height: 100%; cursor: crosshair; touch-action: none; }

/* No page zoom on a touch screen.
   iOS Safari has ignored user-scalable=no since iOS 10, so the viewport tag
   alone does not stop a double tap from zooming the whole interface. Declaring
   what each area accepts does: nothing zooms, panels still scroll up and down,
   the tool row still scrolls sideways, and the floor keeps its own pinch,
   which is handled from pointer events in render.js and is the one zoom that
   should work. */
html, body { touch-action: none; }
#panel, #tabbody, #inspector, #logfeed, #modal, .sheet { touch-action: pan-y; }
#floorhead { touch-action: pan-x; }

#ghost {
  position: absolute; left: 14px; bottom: 14px; pointer-events: none;
  background: #120f0cdd; border: 1px solid var(--line2); border-radius: 3px;
  padding: 5px 12px; font-size: 11.5px; color: var(--dim); max-width: 360px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--mono);
}

#events { display: flex; gap: 5px; flex-wrap: nowrap; min-width: 0; flex: 1 1 auto;
  overflow: hidden; mask-image: linear-gradient(90deg, #000 calc(100% - 24px), transparent); }
.ev.more { color: var(--dimmer); border-left-color: var(--line2); cursor: help; }
.ev {
  display: inline-flex; align-items: baseline; gap: 8px; padding: 3px 10px;
  flex: none; white-space: nowrap;
  border-radius: 3px; font-size: 11px; border-left: 2px solid var(--line2);
  background: #1a1611; color: var(--dim); cursor: help;
}
.ev b { color: var(--fg); font-weight: 600; }
.ev .t { font-family: var(--mono); font-size: 10px; color: var(--dimmer); }
.ev.good { border-left-color: var(--good); }
.ev.good b { color: var(--good); }
.ev.bad { border-left-color: var(--bad); }
.ev.bad b { color: var(--bad); }

/* ------------------------------------------------------------- inspector */

#inspector {
  border-top: 1px solid var(--line); background: #120f0c;
  padding: 9px 16px; height: 19vh; min-height: 118px; max-height: 190px; overflow: auto;
}
#inspector .empty { color: var(--dimmer); font-size: 12px; }
#inspector .title { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.inspclose { display: none; }
#inspector .kv { max-width: 440px; }
#inspector table.grid { max-width: 660px; }

.todohead { margin-bottom: 8px; }
.todo {
  display: flex; align-items: center; gap: 11px; width: 100%; max-width: 800px;
  padding: 7px 12px; margin-bottom: 2px; font-size: 12.5px; text-align: left; color: var(--fg);
  border-left: 2px solid #3a3128; background: #17130f;
}
.todo:hover { background: #201a14; }
.todo .dot { display: none; }
.todo .txt { flex: 1; }
.todo .go { color: var(--dimmer); font-size: 11px; opacity: 0; white-space: nowrap; }
.todo:hover .go { color: var(--acc); opacity: 1; }
.todo.bad { border-left-color: var(--bad); }
.todo.warn { border-left-color: var(--warn); }
.todo.good { border-left-color: var(--good); }
.todo.info { border-left-color: var(--cold); }

/* ----------------------------------------------------------------- panel */

#panel { display: grid; grid-template-rows: auto 1fr; border-left: 1px solid var(--line);
  background: var(--panel); min-height: 0; }
#tabs { display: flex; flex-wrap: wrap; gap: 0; padding: 0 6px; background: #120f0c;
  border-bottom: 1px solid var(--line); }
.tab {
  padding: 10px 7px 9px; font-size: 11.5px; letter-spacing: -.1px; color: var(--dim); white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab:hover { color: var(--fg); background: #ffffff06; }
/* The tab you are on gets a lit underline rather than a plain one — it is the
   one piece of state on screen you look for without meaning to. */
.tab.on {
  color: var(--acc); border-bottom-color: var(--acc);
  box-shadow: 0 6px 14px -8px var(--acc);
}
#tabbody { overflow: auto; padding: 14px 14px 28px; }

.sec { margin-bottom: 22px; }
.sec > h3 { margin-bottom: 9px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.hint { color: var(--dim); font-size: 12px; margin-bottom: 11px; line-height: 1.55; }

/* Rows: the default for anything list-shaped. */
/* Each thing you can buy is a card with its own surface.
   A hairline between rows made the list read as one undifferentiated wall of
   text; a card gives each item an edge, and gives hover something to lift. */
.row {
  display: grid; grid-template-columns: 34px 1fr; gap: 12px;
  padding: 11px 12px; width: 100%; text-align: left;
  background: linear-gradient(180deg, #1a1611, #161310);
  border: 1px solid var(--line);
  border-radius: 7px;
  margin-bottom: 7px;
}
.row.click {
  cursor: pointer;
  transition: transform .13s ease, border-color .13s ease,
              box-shadow .13s ease, background .13s ease;
}
.row.click:hover {
  background: linear-gradient(180deg, #211c15, #1a1611);
  border-color: var(--acc-dim);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px #0007, inset 0 1px 0 #ffffff0a;
}
.row.click:active { transform: none; background: #241d14; }
.row.click:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
.row.owned {
  background: linear-gradient(180deg, #1b1d13, #17190f);
  border-color: #33401f;
  box-shadow: inset 2px 0 0 var(--good);
}

/* Locked items are the majority of a long list and they were the loudest
   thing in it: four of them each carrying a paragraph of flavour, a wrapped
   requirement and a button pushed the one thing you could actually buy off
   the bottom of the screen. They keep the requirement, which is the only part
   that matters while they are locked, and lose the rest. */
.row.locked {
  opacity: .62;
  padding: 8px 12px;
  background: none;
  border-color: #211c16;
}
.row.locked:hover { opacity: .82; }
.row.locked .desc { display: none; }
.row.locked .meta { display: none; }
.row.locked .head b { font-weight: 550; }
.row.locked .note {
  opacity: 1; color: var(--acc); font-size: 11.5px; margin-top: 2px;
}
/* Short note, small button, one line between them. */
.row.locked .body { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.row.locked .head { flex: 1 1 100%; }
.row.locked .btnrow { margin-top: 0; }
.row.locked .btn {
  opacity: 1; padding: 3px 9px; font-size: 11px;
  background: none; border-color: var(--acc-dim); color: var(--acc);
}
.row.locked .btn:hover { background: #241b0e; }
/* Rung when you follow "Go to research" so the right node is obvious. */
@keyframes flashrow {
  0%, 100% { box-shadow: inset 0 0 0 0 transparent; }
  50% { box-shadow: inset 0 0 0 2px var(--acc); background: #241d13; }
}
.row.flash { animation: flashrow .8s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) {
  .row.flash { animation: none; box-shadow: inset 0 0 0 2px var(--acc); }
}
.row.cant .price { color: var(--warn); }
.row .ico { width: 34px; height: 34px; border-radius: 3px; background: #100d0a center/22px no-repeat;
  border: 1px solid var(--line2); }
.row .body { min-width: 0; }
.row .head { display: flex; align-items: baseline; gap: 8px; }
.row .head b { font-weight: 650; font-size: 13.5px; }
.row .price { margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--dim);
  font-variant-numeric: tabular-nums; }
.row .price.ok { color: var(--good); }
.row .desc { color: var(--dim); font-size: 12px; margin-top: 3px; }
.row .meta { display: flex; flex-wrap: wrap; gap: 3px 14px; margin-top: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--dimmer); }
.row .meta b { color: var(--dim); font-weight: 500; }
.row .note { color: var(--dimmer); font-size: 11.5px; margin-top: 5px; }

/* Cards: for discrete things you act on. */
.card { background: var(--panel2); border-radius: var(--r); padding: 12px 13px; margin-bottom: 9px;
  box-shadow: inset 0 0 0 1px var(--line); }
.card.click { cursor: pointer; }
.card.click:hover { background: var(--raise); }
.card.owned { box-shadow: inset 0 0 0 1px #4a5a2c, inset 3px 0 0 var(--good); background: #191a11; }
.card.cant { opacity: .66; }
.card .title { display: flex; align-items: baseline; gap: 8px; }
.card .title b { font-weight: 650; }
.card .title .price { margin-left: auto; font-family: var(--mono); font-size: 12px; color: var(--warn); }
.card .title .price.ok { color: var(--good); }
.card .desc { color: var(--dim); font-size: 12px; margin-top: 5px; }
.card .meta { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 7px;
  font-family: var(--mono); font-size: 10.5px; color: var(--dimmer); }
.card .meta b { color: var(--fg); font-weight: 500; }

.pill { display: inline-block; padding: 1px 7px; border-radius: 2px; font-size: 10px;
  background: #241e16; color: var(--dim); letter-spacing: .04em; }
.pill.acc { color: var(--good); background: #1d2314; }
.pill.bad { color: var(--bad); background: #2a1614; }
.pill.warn { color: var(--warn); background: #2a2214; }
.pill.new { color: #17120a; background: var(--acc); font-weight: 700; }

/* Buttons get a little material: a gradient down the face and a one-pixel
   highlight along the top, which is what separates a control you want to press
   from a rectangle with a word in it. */
.btn {
  background: linear-gradient(180deg, #2a231b, #201a14);
  border: 1px solid var(--line2); border-radius: 5px;
  padding: 6px 12px; font-size: 12px;
  box-shadow: inset 0 1px 0 #ffffff0d;
  transition: background .12s ease, border-color .12s ease, transform .1s ease;
}
.btn:hover:not(:disabled) {
  background: linear-gradient(180deg, #3a3126, #2b241c);
  border-color: #4b3f2d;
}
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .35; cursor: not-allowed; }
.btn.primary {
  background: linear-gradient(180deg, #ffc061, var(--acc));
  border-color: #c98a2c; color: #1a1206; font-weight: 650;
  box-shadow: inset 0 1px 0 #fff6, 0 2px 10px #f2a83c33;
}
.btn.primary:hover:not(:disabled) {
  background: linear-gradient(180deg, #ffd083, #ffb542);
  border-color: #e0a03c;
}
.btn.danger {
  background: linear-gradient(180deg, #3d1e18, #2c1611);
  border-color: #6b3026; color: #f0a89e;
}
.btn.danger:hover:not(:disabled) { background: linear-gradient(180deg, #4c261e, #351a14); }
.btn.small { padding: 4px 10px; font-size: 11px; }
.btnrow { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 9px; }

/* The line that opens the locked half of a build list. It is a door, not an
   offer, so it reads quieter than anything you can actually buy. */
.btn.small.lockfold {
  display: block; width: 100%; margin-top: 8px;
  background: none; border: 1px dashed var(--line2);
  color: var(--dim); font-size: 11px; letter-spacing: .02em;
}
.btn.small.lockfold:hover:not(:disabled) { background: rgba(255, 255, 255, .03); color: var(--fg); }

.bar { height: 7px; background: #0b0e12; overflow: hidden; margin-top: 8px;
  border-radius: 4px; box-shadow: inset 0 0 0 1px #262a31, inset 0 1px 2px #0008; }
.bar > i {
  display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(180deg, #a8dd85, var(--good));
  box-shadow: 0 0 8px -1px currentColor; transition: width .25s;
}
.bar.warn > i { background: var(--warn); }
.bar.bad > i {
  background: repeating-linear-gradient(115deg, var(--bad) 0 5px, #7d2b22 5px 10px);
}

.kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; font-family: var(--mono);
  font-size: 11.5px; font-variant-numeric: tabular-nums; }
.kv .k { color: var(--dimmer); }
/* Overdrawn: the one state the player must not be able to miss. */

.desc.acc { color: var(--acc); }
.overdrawn { box-shadow: inset 0 0 0 1px var(--bad), 0 0 24px #e8615f22; background: #1d1210; }
.overdrawn .odbig { font-family: var(--mono); font-size: 26px; font-weight: 700;
  color: var(--bad); letter-spacing: -1px; font-variant-numeric: tabular-nums; margin: 2px 0 6px; }
.kv .v { text-align: right; }
/* A figure in a key/value block that is not the number you would expect —
   the compute rate once the site is large enough to price itself down. */
.kv .v.warn { color: var(--warn); }

table.grid { width: 100%; border-collapse: collapse; font-size: 12px; }
table.grid th { text-align: left; padding: 4px 5px; }
table.grid td { padding: 6px 5px; border-top: 1px solid var(--line); font-family: var(--mono);
  font-variant-numeric: tabular-nums; }

input[type=range] { width: 100%; accent-color: var(--acc); }
input[type=text], textarea {
  width: 100%; background: #0c0a08; border: 1px solid var(--line2);
  color: var(--fg); border-radius: 3px; padding: 8px 10px; font-family: var(--mono); font-size: 12px;
}

/* -------------------------------------------------------- compute & plots */

.bignum { font-family: var(--mono); font-size: 30px; font-weight: 600; letter-spacing: -1.2px;
  line-height: 1.05; margin-bottom: 10px; font-variant-numeric: tabular-nums; }
.stack { display: flex; height: 12px; overflow: hidden; background: #0c0a08;
  box-shadow: inset 0 0 0 1px #2a2419; }
.stack .seg { height: 100%; transition: width .3s; }
.stack .seg.sold { background: var(--good); }
.stack .seg.free { background: #4a3f31; }
.stack .seg.rnd { background: var(--cold); }
.stacklegend { display: flex; flex-wrap: wrap; gap: 5px 18px; margin-top: 9px; font-size: 11.5px; }
.sl { display: flex; align-items: center; gap: 7px; }
.sl i { width: 9px; height: 9px; }
.sl i.sold { background: var(--good); }
.sl i.free { background: #4a3f31; }
.sl i.rnd { background: var(--cold); }
.sl .k { color: var(--dim); }
.sl .v { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.spark { margin: 3px 0 14px; }
.spark svg { width: 100%; height: 48px; display: block; }
.sparkempty { color: var(--dimmer); font-size: 11.5px; padding: 14px 0; }
.sparkends { display: flex; justify-content: space-between; font-family: var(--mono);
  font-size: 10px; color: var(--dimmer); margin-top: 3px; }
.sparklabel { margin-bottom: 3px; }
.keeps { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0 4px; }
.keep .kh { font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; font-weight: 600;
  margin-bottom: 5px; }
.keep.good .kh { color: var(--good); }
.keep.bad .kh { color: var(--bad); }
.keep .ki { font-size: 12px; color: var(--dim); padding-left: 11px; position: relative; }
.keep .ki::before { content: ''; position: absolute; left: 0; top: 7px; width: 4px; height: 4px;
  background: currentColor; opacity: .5; }
.lvlbar { display: flex; gap: 2px; margin-top: 7px; }
.lvlbar i { flex: 1; height: 3px; background: #2f281e; }
.lvlbar i.on { background: var(--acc); }

.townstage { font-size: 15px; font-weight: 650; margin: 12px 0 3px; }

#paused { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
  background: #0e0c0a55; z-index: 18; }
#paused span {
  font-size: 12px; letter-spacing: .22em; text-transform: uppercase; color: var(--warn);
  background: #17120bee; border: 1px solid #6b5730; border-radius: 3px; padding: 7px 20px;
  font-weight: 600;
}

/* ------------------------------------------------------------- guided start */

#tutorial {
  position: absolute; left: 16px; top: 16px; width: min(340px, 62%); z-index: 22;
  background: linear-gradient(#221a11, #171208); border: 1px solid #6b4d1e;
  border-left: 3px solid var(--acc); border-radius: var(--r); padding: 13px 15px 12px;
  box-shadow: 0 18px 48px #000b;
}
#tutorial .tt { font-size: 16px; font-weight: 700; margin: 4px 0 6px; }
#tutorial .tb { font-size: 12.5px; color: #ded2c0; line-height: 1.55; }
#tutorial .tn { font-size: 11.5px; color: var(--dim); margin-top: 7px; font-style: italic; }
#tutorial .tfoot { display: flex; align-items: center; gap: 10px; margin-top: 11px; }
#tutorial .tdots { display: flex; gap: 4px; margin-right: auto; }
#tutorial .tdots i { width: 18px; height: 3px; background: #3d3325; }
#tutorial .tdots i.on { background: var(--acc); }
#tutorial .tdots i.now { background: #fff0d0; }
#tutorial .tskip { color: var(--dimmer); font-size: 11px; text-decoration: underline; padding: 2px 4px; }
#tutorial .tskip:hover { color: var(--fg); }

.tut-target { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 3px;
  animation: aim 1.5s ease-in-out infinite; }
@keyframes aim {
  0%, 100% { box-shadow: 0 0 0 0 #f2a83c66; }
  50%      { box-shadow: 0 0 0 8px #f2a83c00; }
}
#canvaswrap.tut-target { outline-offset: -3px; border-radius: 0; }

/* ------------------------------------------------------------------- log */

#logbar { display: grid; grid-template-columns: 340px 1fr; gap: 16px; align-items: center;
  border-top: 1px solid var(--line); background: #120f0c; padding: 6px 16px;
  /* Fixed, not min-: a taller footer used to shrink the floor and shunt the
     whole board up and down as the objective text changed length. */
  height: 62px; overflow: hidden; }
#objective { font-size: 12px; line-height: 1.32; height: 48px; overflow: hidden; }
/* Each of the three lines keeps its own row, so wrapping can never add one. */
#objective .k, #objective .n, #objective .h {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#objective .n { color: var(--acc); font-weight: 650; }
#objective .h { color: var(--dim); }
#logfeed { display: flex; gap: 18px; overflow: hidden; font-size: 12px; white-space: nowrap; }
#logfeed .e { color: var(--dim); }
#logfeed .e.good { color: var(--good); }
#logfeed .e.bad { color: var(--bad); }

/* ------------------------------------------------------- tooltip & modals */

#tip {
  position: fixed; z-index: 70; pointer-events: none; max-width: 310px;
  background: #16120d; border: 1px solid var(--line2); border-left: 2px solid var(--acc);
  border-radius: 3px; padding: 10px 13px; box-shadow: 0 16px 40px #000c;
  animation: tipin .12s ease-out;
}
#tip .tiph { font-size: 11.5px; font-weight: 700; color: var(--acc); margin-bottom: 4px;
  letter-spacing: .02em; }
#tip .tipb { font-size: 12px; color: #ded2c0; line-height: 1.5; }
#tip .tipb + .tipb { margin-top: 6px; }
@keyframes tipin { from { opacity: 0; transform: translateY(3px); } }

/* A plain scrim, not a blur.
   backdrop-filter over a full screen was costing 24fps on a finished site —
   measured at 36 down to 12 — and it did it for every dialogue in the game:
   the Menu, an event decision, the bank's offer. The compositor re-filters the
   whole page every frame regardless of whether the canvas underneath changed,
   so there is no way to keep it cheaply. A darker scrim separates the sheet
   just as well and costs nothing. */
#modal { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center;
  background: #060504d9; padding: 20px; }
.sheet { width: min(600px, 96vw); max-height: 86vh; overflow: auto; background: var(--panel);
  border: 1px solid var(--line2); border-top: 3px solid var(--acc); border-radius: var(--r);
  padding: 22px 24px; box-shadow: 0 30px 90px #000d; }
.sheet h2 { font-size: 22px; margin-bottom: 5px; letter-spacing: -.4px; }
.sheet .sub { color: var(--dim); font-size: 12.5px; margin-bottom: 18px; }
.sheet p { color: var(--fg); }
.sheet h4, .sheet .gh { margin: 18px 0 8px; }
.gintro p { margin: 0 0 10px; color: #ded2c0; font-size: 13px; }
.gsec .kv { grid-template-columns: 104px 1fr; gap: 6px 14px; }
.gsec .kv .v { text-align: left; color: #cec2b2; font-family: var(--sans); font-size: 12.5px; }
.gsec .kv .k { color: var(--acc); font-family: var(--sans); font-size: 12.5px; font-weight: 600; }
.glegend { display: grid; gap: 7px; }
.grow { display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
.gsw { width: 12px; height: 12px; flex: none; }
.grow b { font-weight: 650; }
.gnote { color: var(--dim); }

/* A moment for the handful of things that only happen once a run. */
#banner {
  position: absolute; inset: 0; z-index: 24; display: grid; place-items: center;
  pointer-events: none; text-align: center;
}
#banner .inner {
  padding: 26px 44px; border-radius: 8px;
  background: radial-gradient(420px 200px at 50% 50%, #1d1710f2, #12100cd8);
  box-shadow: 0 0 0 1px #3a2f22, 0 24px 60px #000b;
  animation: banner 3.2s cubic-bezier(.2,.8,.25,1) both;
}
#banner .kicker { font-family: var(--mono); font-size: 11px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--acc); }
#banner .title { font-size: 34px; font-weight: 700; letter-spacing: -.5px; margin: 6px 0 4px; }
#banner .note { color: var(--dim); font-size: 13px; max-width: 42ch; margin: 0 auto; }
#banner .rule { height: 1px; margin: 14px auto 0; width: 60px; background: var(--acc); opacity: .55; }
@keyframes banner {
  0%   { opacity: 0; transform: scale(.94) translateY(10px); }
  12%  { opacity: 1; transform: none; }
  78%  { opacity: 1; transform: none; }
  100% { opacity: 0; transform: scale(1.02); }
}
@media (prefers-reduced-motion: reduce) { #banner .inner { animation: none; } }

#toasts { position: absolute; right: 12px; bottom: 12px; z-index: 20; display: grid; gap: 4px;
  justify-items: end; pointer-events: none; max-width: min(250px, 52%); }
.toast {
  display: flex; align-items: center; gap: 7px;
  background: linear-gradient(90deg, #1b160fe0, #14110ce8);
  border: 1px solid #2e2620; border-left: 2px solid var(--acc); border-radius: 4px;
  padding: 5px 10px 5px 9px; font-size: 10.5px; line-height: 1.35; color: #cec2b2;
  box-shadow: 0 8px 20px #0009, inset 0 1px 0 #ffffff08;
  backdrop-filter: blur(3px);
  animation: toastin .34s cubic-bezier(.2,.8,.25,1) both;
}
/* A dot in the accent of the tone, so the kind of news reads before the text. */
.toast::before {
  content: ''; flex: none; width: 4px; height: 4px; border-radius: 50%;
  background: var(--acc); box-shadow: 0 0 8px currentColor;
}
.toast.bad { color: #f2bcb5; border-left-color: var(--bad); }
.toast.bad::before { background: var(--bad); }
.toast.warn { color: #f2dfb2; border-left-color: var(--warn); }
.toast.warn::before { background: var(--warn); }
.toast.good { color: #cfe6bb; border-left-color: var(--good); }
.toast.good::before { background: var(--good); }
@keyframes toastin {
  from { opacity: 0; transform: translateX(18px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* --------------------------------------------------------- accessibility */

:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 2px; }
button:focus:not(:focus-visible) { outline: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ------------------------------------------------------------ responsive */

/* Which readouts survive a narrow window is decided by measuring the bar on
   the viewer's own machine (see fitTopBar) rather than by pixel breakpoints,
   because the widths depend on their fonts. These two classes are what that
   measurement toggles. */
#topbar.hide-minis .minis,
#topbar.hide-meters .meters { display: none; }

/* The last resort, reached only when hiding the readouts was not enough — a
   narrow phone with a wide cash figure. Everything here is a squeeze, not a
   removal, except the speaker, which moves into the Menu rather than going
   away. Measured, not guessed: see fitTopBar in src/ui.js. */
#topbar.tight { gap: 6px; padding-left: 6px; padding-right: 6px; }
#topbar.tight .vital { width: 94px; }
#topbar.tight .topright { gap: 6px; }
#topbar.tight .sp { min-width: 20px; padding: 6px 2px; font-size: 10px; }
#topbar.tight .topbtn.icon { display: none; }
#topbar.tight .livecount { padding: 3px 6px; gap: 4px; }
#topbar.tight .livecount i { width: 6px; height: 6px; }
#topbar.tight .livecount b { min-width: 1ch; font-size: 11px; }

/* The counter is the point of the whole exercise, so it is never dropped —
   it just loses its label and keeps the dot and the number, which costs
   about 40px and still reads at a glance on a phone. */
#topbar.hide-minis .livecount span { display: none; }
#topbar.hide-minis .livecount { padding: 4px 8px; }

@media (max-width: 1560px) {
  #topbar { gap: 15px; }
}
@media (max-width: 1180px) {
  #main { grid-template-columns: 1fr 356px; }
}
/* Phone and small-tablet widths: everything still reachable, just tighter.
   Guide and Menu keep their first letters as labels rather than disappearing,
   because they are the only way into the rules and the save. */
@media (max-width: 900px) {
  #topbar { height: 66px; gap: 11px; padding: 7px 10px 6px; }
  .speedlbl { display: none; }
  .divider { display: none; }
  .vital { width: 116px; }
  .vital .big { font-size: 20px; }
  .sp { min-width: 32px; padding: 6px 6px; font-size: 11.5px; }
  .topbtn { padding: 7px 9px; font-size: 11.5px; }
  .topbtn.icon { padding: 6px 7px; }
  .speed { gap: 2px; }
}
@media (max-width: 620px) {
  #topbar {
    gap: 8px;
    /* Last resort on a phone: rather than clip a control off the edge, let the
       bar scroll sideways. Nothing is ever unreachable. */
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  }
  #topbar::-webkit-scrollbar { display: none; }
  /* Compute has its own big readout at the top of the Deals tab, one tap away,
     so on a phone the bar keeps cash and gives the room to the controls. */
  #v_compute { display: none; }
  .vital { width: 92px; }
  .vital .big { font-size: 18px; }
  .vital .sub { font-size: 10px; }
  .sp { min-width: 27px; padding: 6px 4px; font-size: 11px; }
  .topbtn { padding: 7px 7px; font-size: 11px; }
}
@media (max-width: 900px) {
  #main { grid-template-columns: 1fr; grid-template-rows: minmax(280px, 1fr) 44vh; }
  #panel { border-left: 0; border-top: 1px solid var(--line); }
  #inspector { height: 21vh; min-height: 118px; }
  #logbar { grid-template-columns: 1fr; }
  #logfeed { display: none; }
  .divider { display: none; }
}

/* ------------------------------------------------------------------ phone

   A phone has no room for the desktop's four stacked bands. The floor is what
   the game is, so it gets the space: the inspector goes (everything in it is
   in the panels a tap away), the footer goes (the objective moves into the
   bar), and the panel becomes a sheet under the floor with its tabs pinned.  */
@media (max-width: 700px) {
  :root { --inspector: sheet; }
  #app { grid-template-rows: auto 1fr; }
  #logbar { display: none; }
  /* The inspector used to be switched off entirely here, which meant tapping a
     rack on a phone selected it and then showed you nothing — so there was no
     way to find out why something was warning at you. It is now a sheet over
     the floor, and only in tile mode: tapping bare floor or the cross closes
     it, and it never takes space when there is nothing to say. */
  #floor { position: relative; }
  #inspector { display: none; }
  #inspector[data-mode="tile"] {
    display: block;
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 25;
    height: auto; min-height: 0; max-height: 52%;
    padding: 12px 14px 16px;
    border-top: 1px solid var(--line2);
    background: #14110e;
    box-shadow: 0 -16px 34px rgba(0, 0, 0, .6);
    overscroll-behavior: contain;
  }
  #inspector[data-mode="tile"] .kv { max-width: none; }
  .inspclose {
    display: grid; place-items: center;
    margin-left: auto; flex: none;
    width: 32px; height: 32px; padding: 0;
    border: 1px solid var(--line2); border-radius: 50%;
    background: var(--raise); color: var(--fg); font-size: 14px; line-height: 1;
  }

  #main { grid-template-rows: minmax(38vh, 1fr) 44vh; }
  #floor { grid-template-rows: auto 1fr; }

  #topbar { height: 54px; gap: 8px; padding: 5px 8px; }
  .vital { width: 104px; }
  .vital .lbl { display: none; }
  .vital .big { font-size: 17px; letter-spacing: -.4px; }
  .vital .sub { font-size: 9.5px; }
  #v_compute { display: none; }
  .sp { min-width: 25px; padding: 6px 4px; font-size: 10.5px; }
  /* This said .speed for a long time, which is not a class that exists, so the
     gap never tightened on a phone. */
  .speeds { gap: 1px; }
  /* Guide and Menu become their glyphs rather than disappearing: they are the
     only way into the rules and the save. */
  .topbtn { padding: 7px 9px; font-size: 10.5px; }
  .topbtn[data-short] { font-size: 0; min-width: 30px; }
  .topbtn[data-short]::after { content: attr(data-short); font-size: 15px; line-height: 1; }

  /* The overlay row scrolls sideways instead of wrapping into two lines. */
  #floorhead { padding: 5px 8px; gap: 8px; overflow-x: auto; scrollbar-width: none; }
  #floorhead::-webkit-scrollbar { display: none; }
  #floortools { flex: none; }
  #facilityname { display: none; }

  #tabs { position: sticky; top: 0; z-index: 5; flex-wrap: nowrap; overflow-x: auto;
    scrollbar-width: none; }
  #tabs::-webkit-scrollbar { display: none; }
  .tab { padding: 11px 9px 10px; font-size: 12px; }
  #tabbody { padding: 10px 10px 26px; }

  /* The guide card is 62% wide on desktop, which on a phone is a narrow
     column that turns four lines of text into twelve and swallows the floor.
     Here it is a wide, short bar across the top instead. */
  #tutorial {
    left: 8px; right: 8px; top: 8px; width: auto;
    padding: 9px 11px 8px; border-left-width: 3px; border-radius: 6px;
  }
  #tutorial .tk { font-size: 9.5px; letter-spacing: .1em; }
  #tutorial .tt { font-size: 14px; margin: 2px 0 3px; }
  #tutorial .tb { font-size: 12px; line-height: 1.4; }
  #tutorial .tn { font-size: 11px; margin-top: 4px; }
  #tutorial .tfoot { margin-top: 7px; gap: 8px; }
  #tutorial .tdots i { width: 11px; height: 2px; }
  #tutorial .tskip { white-space: nowrap; font-size: 11px; }

  /* Touch targets, and rows that do not try to be three columns wide. */
  .row { padding: 11px 4px; }
  .btn.small { padding: 9px 11px; }
  .sheet { width: min(94vw, 460px); padding: 20px 18px; }
  /* The guide card spans the top of a phone screen, so the button goes to the
     bottom corner instead, with the toasts stacked above it. A shade bigger
     than on a desktop, because it is hit with a thumb. */
  .dropbtn { right: 8px; top: auto; bottom: 8px; width: 36px; height: 36px; font-size: 15px; }
  #toasts { max-width: 74%; right: 8px; bottom: 52px; }
  #ghost { display: none; }
}

/* Landscape phone: height is the scarce thing, so go back to side by side. */
@media (max-height: 500px) and (orientation: landscape) {
  :root { --inspector: sheet; }
  #app { grid-template-rows: auto 1fr; }
  #logbar { display: none; }
  /* Same reasoning as portrait: hidden until you tap something, then a sheet.
     Shallower here, because height is the scarce thing in landscape. */
  #floor { position: relative; }
  #inspector { display: none; }
  #inspector[data-mode="tile"] {
    display: block;
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 25;
    height: auto; min-height: 0; max-height: 62%;
    padding: 12px 14px 14px;
    border-top: 1px solid var(--line2); background: #14110e;
    box-shadow: 0 -16px 34px rgba(0, 0, 0, .6);
    overscroll-behavior: contain;
  }
  .inspclose {
    display: grid; place-items: center;
    margin-left: auto; flex: none;
    width: 30px; height: 30px; padding: 0;
    border: 1px solid var(--line2); border-radius: 50%;
    background: var(--raise); color: var(--fg); font-size: 13px; line-height: 1;
  }
  #main { grid-template-columns: 1fr minmax(240px, 34%); grid-template-rows: 1fr; }
  #panel { border-left: 1px solid var(--line); border-top: 0; }
  #topbar { height: 48px; }
  .vital .lbl { display: none; }
  .vital .big { font-size: 16px; }
  #floorhead { padding: 4px 8px; }
}

/* ------------------------------------------------------------- the register */

/* Every address in Ashbrook and what happened to it. Deliberately plain: a
   ledger, not a feed. The ones still standing are dimmed rather than hidden,
   so the length of what is left to take is visible at a glance. */
.register { display: flex; flex-direction: column; gap: 0; }

.reglatest {
  background: #1a1310; border: 1px solid #3a2a20; border-left: 3px solid var(--bad);
  border-radius: var(--r); padding: 11px 13px; margin-bottom: 12px;
}
.reglatest .regk {
  font: 600 10px var(--mono); letter-spacing: .8px; text-transform: uppercase;
  color: var(--dimmer); margin-bottom: 5px;
}
.reglatest .regaddr { font-size: 15px; font-weight: 600; color: var(--fg); }
.reglatest .regwho { font-size: 12px; color: var(--dim); margin-top: 1px; }
.reglatest .regline { font-size: 12.5px; line-height: 1.5; color: var(--dim); margin-top: 7px; }

.register .kv { margin-bottom: 14px; }

.regrow {
  display: grid; grid-template-columns: 38px 1fr; gap: 10px;
  padding: 9px 0; border-top: 1px solid #1e1a15;
}
.regrow:first-of-type { border-top: 0; }
.regat {
  font: 600 10px var(--mono); color: var(--bad); padding-top: 2px; text-align: right;
}
.reghead { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.reghead b { font-size: 13px; color: var(--fg); }
.regwho { font-size: 11.5px; color: var(--dim); }
.regn {
  font: 600 10px var(--mono); color: var(--dimmer); margin-left: auto;
  border: 1px solid var(--line2); border-radius: 100px; padding: 1px 6px;
}
.regline { font-size: 12px; line-height: 1.5; color: var(--dim); margin-top: 3px; }

.regrow.standing { opacity: .42; }
.regrow.standing .regat { color: var(--dimmer); }
.regrow.standing .reghead b { color: var(--dim); font-weight: 500; }

/* -------------------------------------------------------- closing statement */

/* The one ending the game has. Quieter and wider than every other dialogue:
   no amber, no buttons shouting, just a set of figures and the last thing
   anybody in Ashbrook said. */
.sheet.closing { max-width: 560px; }
.sheet.closing h2 {
  font-size: 30px; letter-spacing: -.5px; margin-bottom: 2px;
}
.sheet.closing .sub {
  font: 600 11px var(--mono); letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--dimmer); margin-bottom: 20px;
}
.ledger {
  display: grid; grid-template-columns: 1fr auto; gap: 9px 18px;
  align-items: baseline; margin-bottom: 20px;
}
.ledger .lk { font-size: 13px; color: var(--dim); }
.ledger .lv { font: 600 14px var(--mono); color: var(--fg); text-align: right; }
.ledger .lv.bad { color: var(--bad); }
.ledger .lrule { border-top: 1px solid var(--line); height: 0; margin: 3px 0; }

.closinglast {
  border-left: 2px solid var(--bad); padding: 2px 0 2px 14px;
}
.closinglast .ck {
  font: 600 10px var(--mono); letter-spacing: .9px; text-transform: uppercase;
  color: var(--dimmer); margin-bottom: 5px;
}
.closinglast .caddr { font-size: 15px; font-weight: 600; color: var(--fg); }
.closinglast .cline {
  font-size: 13px; line-height: 1.6; color: var(--dim); margin-top: 6px;
}

@media (max-width: 700px) {
  .sheet.closing h2 { font-size: 24px; }
  .ledger { gap: 7px 12px; }
  .ledger .lk { font-size: 12px; }
  .ledger .lv { font-size: 13px; }
}

/* -------------------------------------------------- the auto-sign uptime cap */

.caprow { margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--line); }
.caplbl { font-size: 12.5px; color: var(--dim); margin-bottom: 7px; }
.caplbl b { color: var(--fg); font-family: var(--mono); font-weight: 600; }
.caprow input[type="range"] { width: 100%; accent-color: var(--acc); margin: 0; }
.caphint { font-size: 11px; color: var(--dimmer); margin-top: 6px; }

/* ------------------------------------------ why a contract is not delivering */

.whybtn {
  display: inline-grid; place-items: center; vertical-align: middle;
  width: 15px; height: 15px; margin-left: 5px; padding: 0;
  border: 1px solid var(--line2); border-radius: 50%;
  background: var(--raise); color: var(--dim);
  font: 600 10px var(--sans); line-height: 1; cursor: help;
}
.whybtn:hover { color: var(--acc); border-color: var(--acc-dim); background: #241b0e; }

.sheet.why { max-width: 520px; }
.whyrow {
  display: grid; grid-template-columns: 52px 1fr; gap: 12px;
  padding: 10px 0; border-top: 1px solid var(--line);
}
.whyrow:first-of-type { border-top: 0; }
.whycost { font: 600 13px var(--mono); color: var(--bad); text-align: right; }
.whytext { font-size: 13px; line-height: 1.55; color: var(--dim); }
.whytext b { color: var(--fg); font-weight: 600; }

/* A tab with something waiting behind it.
   "It should always feel like you can upgrade something" — and the counts a
   player needs for that were spread across four panels, so knowing whether
   there was anything to do meant opening all of them. The dot carries the
   number of new things affordable behind that tab: a machine better than the
   best one you own, a building you have never placed, a research node you can
   pay for, a deal that fits. Shape as well as colour, so it reads without
   relying on the accent being visible. */
/* Absolutely positioned, because it must not cost the row any width. The tab
   row has a check on it that it never wraps — seven tabs at 1500px have very
   little slack, and an inline badge put it onto two lines immediately. */
.tab { position: relative; }
.tab .badge {
  position: absolute; top: 1px; right: 0; padding: 0 3px; min-width: 12px;
  font-size: 9px; font-weight: 700; line-height: 12px; text-align: center;
  border-radius: 6px; background: var(--acc); color: #17120c;
  pointer-events: none;
}
.tab.on .badge { background: var(--fg); }
