/* ============================================================================
   fable the quant — the terminal
   ----------------------------------------------------------------------------
   A DESK, NOT A DASHBOARD. The first pass was airy cards with serif
   paragraphs in them, which is a document wearing a monospace font. The
   things that actually make a trading terminal read as one, and which are
   all now here:

     - BOX-DRAWING CHROME. Panel titles sit ON the border, in brackets,
       the way a curses app draws them. This alone does most of the work.
     - COLUMN HEADERS AND ONE LINE PER EVENT. The scan was a stack of
       cards; it is a table now, because a terminal shows you fifteen
       things at once and lets you scan down a column.
     - DENSITY. 20px pitch, 12px type, 4px cell padding. A terminal is
       information-dense on purpose; whitespace reads as a landing page.
     - A FIXED FUNCTION BAR pinned to the bottom of the viewport with a
       running clock. Nothing says terminal faster.
     - ALMOST NO PROSE. What is left is one line per panel. CLAUDE.md's
       rule holds — prose gets the serif or there is no prose — and the
       answer here is mostly "there is no prose".

   TWO STATES, NOT A PALETTE. --live (Claude coral) is the value in force.
   --struck (dead warm grey) is what has been crossed out. --bad is
   reserved for a failed check and a broken machine, nothing else.
   ==========================================================================*/

:root {
  --bg:      #171614;
  --panel:   #1c1b19;
  --panel2:  #221f1c;
  --rule:    #221f1c;
  --line:    #33302a;
  --line2:   #45403a;
  --live:    #d97757;
  --liveDim: #c96442;
  --scan:    #f6c0aa;
  --struck:  #6e675f;
  --ink:     #faf9f5;
  --body:    #bdb8ae;
  --dim:     #857f76;
  --faint:   #55504a;
  --bad:     #c25a4a;
  --good:    #d97757;

  --pitch: 20px;
  --mono: 'JetBrains Mono', ui-monospace, Consolas, monospace;
  --serif: 'Newsreader', Georgia, serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--bg); color: var(--body);
  font-family: var(--mono);
  font-size: 12px; line-height: var(--pitch);
  -webkit-font-smoothing: antialiased;
}

/* CRT chrome over a flat document, never the layout */
.crt { position: fixed; inset: 0; z-index: 60; pointer-events: none;
       background: repeating-linear-gradient(to bottom,
         rgba(0,0,0,.20) 0 1px, transparent 1px 3px); opacity: .5; }
.crt::after {
  content: ''; position: absolute; left: 0; right: 0; height: 110px;
  background: linear-gradient(to bottom, transparent, rgba(217,119,87,.05), transparent);
  animation: sweep 8s linear infinite;
}
@keyframes sweep { from { transform: translateY(-140px); } to { transform: translateY(100vh); } }

.shell { position: relative; z-index: 1; max-width: 1500px; margin: 0 auto;
         padding: 0 10px calc(var(--pitch) * 2 + 12px); }

/* ==========================================================================
   THE BOOT — full screen, top left, scrolling. A terminal cold-starts by
   filling the screen with what it is doing, not by centring a card.
   ========================================================================*/
#boot {
  position: fixed; inset: 0; z-index: 100; overflow: hidden;
  background: var(--bg); padding: 14px 16px;
  font-size: 12px; line-height: 17px;
  transition: opacity .3s ease;
}
#boot[hidden] { display: none; }          /* id display outranks [hidden] */
#boot.out { opacity: 0; pointer-events: none; }

#bootart { color: var(--liveDim); white-space: pre; line-height: 1.02;
           font-size: 10px; letter-spacing: -.5px; margin-bottom: 10px; }
.bl { white-space: pre; color: var(--dim); }
.bl .t { color: var(--faint); }
.bl .ok { color: var(--live); }
.bl .no { color: var(--struck); }
.bl .hi { color: var(--ink); }
.bl.head { color: var(--ink); }
#bootcur { color: var(--live); }

/* ==========================================================================
   PANELS — box-drawing chrome. The title sits ON the top border.
   ========================================================================*/
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px;
        align-items: start; }
.grid.one { grid-template-columns: 1fr; }
.grid.wide { grid-template-columns: 1.6fr 1fr; }

/* TWO INDEPENDENT STACKS, NOT GRID ROWS.

   A grid row is as tall as its tallest cell, so a two-line BOOK sitting
   beside a nine-line RULEBOOK left a dead rectangle under the book, and
   another under the roster. align-items:start stops the panel STRETCHING
   but cannot stop the row being tall — the hole is in the row, not in the
   panel. Columns that flow independently have no rows to be tall.

   The columns then STRETCH to match each other, and the tape is the one
   panel marked .grow, so whichever column comes up short gives its slack
   to more of fable talking rather than to bare ground. */
.cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: 10px; margin-top: 10px;
        align-items: stretch; }
.col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.panel.grow { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.panel.grow .tape { flex: 1 1 auto; height: auto; min-height: calc(var(--pitch) * 7); }

/* margin-top gives the title room to sit ABOVE the border; padding-top keeps
   the content from starting UNDER it. The first pass had only the margin, so
   the title's lower half covered the first row of every panel — the rulebook
   opened with a half-eaten "stake, notional". Both are needed and they are
   not the same 9px. */
.panel { border: 1px solid var(--line); background: var(--panel); min-width: 0;
         position: relative; margin-top: 9px; padding-top: 9px; }
.panel > h2 {
  position: absolute; top: -9px; left: 10px; margin: 0;
  background: var(--bg); padding: 0 7px;
  font-size: 10px; font-weight: 400; letter-spacing: .22em; line-height: 17px;
  color: var(--live); text-transform: uppercase; white-space: nowrap;
}
.panel > h2 .n { color: var(--faint); letter-spacing: .1em; }
/* the right-hand caption rides the same border line, other end */
.panel > .rt {
  position: absolute; top: -9px; right: 10px;
  background: var(--bg); padding: 0 7px;
  font-size: 10px; letter-spacing: .16em; line-height: 17px;
  color: var(--faint); text-transform: uppercase; white-space: nowrap;
}
.pad { padding: 7px 9px; }

/* the honest empty state. one line, no paragraph. */
.empty { padding: 8px 9px; color: var(--dim); font-size: 11.5px; }
.empty b { color: var(--body); }

/* ==========================================================================
   TABLES — the terminal's whole vocabulary
   ========================================================================*/
table { width: 100%; border-collapse: collapse; table-layout: auto; }
thead th {
  font-weight: 400; font-size: 9.5px; letter-spacing: .18em; color: var(--faint);
  text-align: left; padding: 3px 9px; text-transform: uppercase;
  border-bottom: 1px solid var(--line); background: var(--panel2);
  white-space: nowrap;
}
tbody td { padding: 0 9px; height: var(--pitch); line-height: var(--pitch);
           border-bottom: 1px solid var(--rule); white-space: nowrap;
           overflow: hidden; text-overflow: ellipsis; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--panel2); }
td.r, th.r { text-align: right; }
td.k { color: var(--dim); }
td.hi { color: var(--ink); }
.up { color: var(--live); }
.down { color: var(--struck); }
.dash { color: var(--faint); }
.tnum { font-variant-numeric: tabular-nums; }

/* verdict cell */
.v-ok { color: var(--live); }
.v-no { color: var(--struck); }
.why { color: var(--faint); font-size: 11px; }
.namedw { color: var(--live); }

/* ==========================================================================
   TOP BAR
   ========================================================================*/
.bar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 0;
  height: calc(var(--pitch) + 8px);
  background: var(--bg); border-bottom: 1px solid var(--line2);
  font-size: 11px; white-space: nowrap; overflow: hidden;
}
.bar .seg { padding: 0 11px; border-right: 1px solid var(--line); color: var(--dim);
            height: 100%; display: flex; align-items: center; gap: 7px; }
.bar .seg:last-child { border-right: 0; }
.bar .who { color: var(--ink); letter-spacing: .04em; }
.bar .rev { color: var(--live); }
.bar b { color: var(--ink); font-weight: 400; }
.bar .push { margin-left: auto; border-right: 0; }

.dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%;
       background: var(--faint); }
.dot.on { background: var(--live); box-shadow: 0 0 7px var(--live); }
.dot.warn { background: var(--struck); }

.ca { font: inherit; font-size: 11px; color: var(--dim); background: none;
      border: 1px solid var(--line); padding: 1px 8px; cursor: pointer; }
.ca:hover { color: var(--live); border-color: var(--liveDim); }

/* ==========================================================================
   FUNCTION BAR — pinned to the viewport. the single fastest terminal tell.
   ========================================================================*/
.fkeys {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  height: calc(var(--pitch) + 6px);
  display: flex; align-items: center; gap: 0;
  background: var(--panel2); border-top: 1px solid var(--line2);
  font-size: 10.5px; color: var(--dim); white-space: nowrap; overflow: hidden;
}
.fkeys a, .fkeys span { padding: 0 10px; height: 100%; display: flex; align-items: center;
                        border-right: 1px solid var(--line); text-decoration: none;
                        color: var(--dim); }
.fkeys a:hover { color: var(--live); background: var(--panel); }
.fkeys .k { color: var(--live); margin-right: 6px; }
.fkeys .push { margin-left: auto; border-right: 0; border-left: 1px solid var(--line); }
.fkeys .warnpaper { color: var(--struck); }

/* ==========================================================================
   THE RULEBOOK
   ========================================================================*/
.rulerow { display: flex; align-items: center; height: var(--pitch);
           border-bottom: 1px solid var(--rule); padding: 0 9px; gap: 9px; }
.rulerow:last-child { border-bottom: 0; }
.rulerow .k { color: var(--dim); }
.rulerow .v { margin-left: auto; color: var(--ink); font-variant-numeric: tabular-nums; }
.rulerow .tag { color: var(--faint); font-size: 10px; letter-spacing: .12em; }

.revrow { padding: 4px 9px; border-bottom: 1px solid var(--rule); }
.revrow .n { color: var(--faint); font-size: 10px; letter-spacing: .14em; }
.revrow .why { color: var(--dim); font-size: 11px; }

.amend { display: flex; align-items: baseline; gap: 9px; }
.was { color: var(--struck); text-decoration: line-through; text-decoration-thickness: 2px; }
.arrow { color: var(--faint); }
.now { color: var(--live); }

/* ==========================================================================
   THE TAPE
   ========================================================================*/
.tape { height: calc(var(--pitch) * 8); overflow-y: auto; padding: 5px 9px; }
.tapeline { display: flex; gap: 9px; align-items: baseline; line-height: 17px; }
.tapeline .t { color: var(--faint); font-size: 10.5px; flex: none; }
.tapeline .m { color: var(--body); }
.tapeline.hot .m { color: var(--ink); }
.tapeline.rev .m { color: var(--live); }

.cur { display: inline-block; width: 6px; height: 11px; background: var(--live);
       vertical-align: -1px; animation: blink 1.05s step-end infinite; }
@keyframes blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }

/* ==========================================================================
   MOTION — driven by state changes, never ambient. Every one of these fires
   because a MEASURED thing happened: a coin landed, a verdict stamped, a
   number moved, a line printed. All dead under prefers-reduced-motion via
   the global kill at the bottom of this sheet.
   ========================================================================*/

/* a new intake row lands: coral wash that drains away */
tr.fresh td { animation: rowland 1.5s ease-out; }
@keyframes rowland {
  from { background: rgba(217,119,87,.16); }
  to   { background: transparent; }
}
/* and its verdict stamps on, slightly oversized then settling */
tr.fresh .stamp { display: inline-block; animation: stampin .36s cubic-bezier(.2,1.6,.4,1); }
@keyframes stampin {
  0% { transform: scale(1.9); opacity: 0; }
  55% { transform: scale(.92); opacity: 1; }
  100% { transform: scale(1); }
}

/* a figure that just changed ticks bright, then cools to its own colour */
.tick { animation: tickflash 1s ease-out; }
@keyframes tickflash { from { color: var(--scan); } }

/* a new tape line prints with a brief wash, newest only */
.tapeline.fresh { animation: lineland 1.3s ease-out; }
@keyframes lineland { from { background: rgba(217,119,87,.13); } }

/* the mascot blinks. the eyes are HOLES in the grid, so a blink FILLS them:
   two coral cells that appear for ~130ms every 5.7s. same trick as fable's
   ascii renderer, done in css so there is no timer to leak. */
.face .eye { opacity: 0; animation: blinkeyes 5.7s step-end infinite; }
@keyframes blinkeyes {
  0%, 96.9% { opacity: 0; }
  97%, 99.4% { opacity: 1; }
  100% { opacity: 0; }
}

/* selection in house colours */
::selection { background: var(--liveDim); color: var(--bg); }

/* ==========================================================================
   PROPOSALS — a command line, because that is what a terminal gives you
   ========================================================================*/
.cmd { display: flex; align-items: center; gap: 7px; padding: 5px 9px;
       border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.cmd .prompt { color: var(--live); }
select, input {
  font: inherit; font-size: 11.5px; background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); height: 21px; padding: 0 6px; min-width: 0;
}
input { width: 84px; }
select:focus, input:focus { outline: none; border-color: var(--liveDim); }
button.go { font: inherit; font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
            background: none; color: var(--live); border: 1px solid var(--liveDim);
            height: 21px; padding: 0 10px; cursor: pointer; }
button.go:hover:not(:disabled) { background: var(--liveDim); color: var(--bg); }
button.go:disabled { color: var(--faint); border-color: var(--line); cursor: not-allowed; }
.formnote { flex-basis: 100%; color: var(--faint); font-size: 11px; }

/* ==========================================================================
   MISC
   ========================================================================*/
.demobar { background: var(--struck); color: var(--bg); padding: 2px 10px;
           font-size: 10.5px; letter-spacing: .1em; text-align: center; }
.scanwrap { max-height: calc(var(--pitch) * 13 + 22px); overflow-y: auto; }
.face { display: block; }

/* the one line of prose left on the page */
.claim { padding: 7px 9px; color: var(--dim); font-family: var(--serif);
         font-style: italic; font-size: 14px; line-height: 19px; }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--line2); }

@media (max-width: 980px) {
  .grid, .grid.wide, .cols { grid-template-columns: 1fr; }
  .bar { height: auto; flex-wrap: wrap; }
  .bar .seg { border-bottom: 1px solid var(--line); }
  .fkeys { font-size: 9.5px; }
  .fkeys .hideNarrow { display: none; }
  tbody td, thead th { padding-left: 6px; padding-right: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
