/* QUIPU
 *
 * WHAT THIS IS   A research instrument for forming a view on one company,
 *                well enough to take an options position on it.
 * WHO FOR        One person, no position yet, ten to thirty minutes per
 *                ticker, who will act on what they read.
 *
 * THE RULE FOR EVERY MARK ON THE SCREEN
 *
 * Monochrome. Colour was carrying no information here — it was decoration,
 * and decoration in an instrument reads as noise. Everything below has one
 * job, stated beside it. If a rule, weight or space cannot name its job, it
 * is deleted.
 *
 * WHAT CARRIES MEANING NOW
 *
 *   line weight    evidence class. The more solid and heavy the rule above a
 *                  panel, the more you can lean on what is inside it:
 *                  FILED solid heavy, PRICED solid light, DERIVED dashed
 *                  (computed, not observed), CLAIMED dotted (hearsay).
 *
 *   typeface       one face per job, three in total.
 *                  Bodoni Moda — news headlines and the masthead, nothing
 *                    else. A Didone is what a newspaper title is set in; it
 *                    says "reportage" before you have read a word.
 *                  IBM Plex Mono — every number, everywhere. Tabular figures
 *                    align down a column; that is the whole point of them.
 *                  Inter — labels, prose, interface. Legible at 10px and
 *                    otherwise gets out of the way.
 *
 *   direction      filled triangle up, hollow triangle down — the old
 *                  newspaper stock-table convention. Same ink, same weight,
 *                  so it survives colour blindness and monochrome print.
 *                  Colour never encodes direction, because there is none.
 *
 *   the 1px gap    the grid itself. Panels sit flush in one ruled table
 *                  rather than floating as cards, because they are one
 *                  document about one company, not 25 widgets.
 *
 * WHAT IS GONE, AND WHY
 *   Rounded corners, drop shadows, glows, gradients, hover lift, four accent
 *   hues. None of them told the reader anything.
 */

@import url("https://fonts.googleapis.com/css2?family=Bodoni+Moda:opsz,wght@6..96,600;6..96,700;6..96,900&family=GFS+Didot&family=IBM+Plex+Mono:wght@400;500;600&family=Inter:wght@400;500;600;700&display=swap");

:root {
  --black:  #0A0A0B;   /* app ground, and the rules between panels */
  --panel:  #121214;   /* the default panel */
  --sunk:   #0D0D0F;   /* recessed — the least trustworthy class */
  --raised: #17171A;   /* raised — the class you can lean on */

  --text:   #F2F2F0;   /* 16.8:1 on panel */
  --text2:  #A3A3A0;   /* 7.4:1 — secondary */
  --faint:  #6E6E6C;   /* 3.6:1 — labels only, never data */
  --rule:   #262629;
  --rule2:  #3A3A3E;
  --up:     #F2F2F0;   /* used inline where a claim is corroborated */

  /* THE ONE PLACE COLOUR IS ALLOWED
   *
   * Everything else here is monochrome on purpose: colour that carries
   * no information is noise in an instrument. These three carry
   * information -- they say WHICH LINE IS WHICH, and nothing else.
   *
   * Three dashed grey lines over a candle chart are three dashed grey
   * lines. The dash patterns were meant to tell them apart and do not,
   * at 1px over a busy price series, which is why the 200-day looked
   * missing when it was simply indistinguishable.
   *
   * Muted and close in luminance so none of them shouts over the price,
   * and each is keyed to a dot on its own button so the mapping is
   * readable rather than remembered. They appear only when the line is
   * switched on, so the default chart stays black and white. Colour
   * never encodes direction or sentiment anywhere in this app. */
  --ma20:   #C08A4E;   /* sand */
  --ma50:   #5C9EAD;   /* teal */
  --ma200:  #9C87C4;   /* mauve */

  /* Profit and loss. The one other place a hue carries a fact rather
   * than a mood: money gained and money lost are opposite things and
   * every trader already reads them this way. Heavily desaturated --
   * a full green on black is a traffic light, and a page of them
   * stops meaning anything. Direction of PRICE is still filled and
   * hollow triangles, not colour: a stock being down is not bad news,
   * and a red tick would say it was. */
  --pos:    #6E9E78;
  --neg:    #B5706B;

  /* A deadline, which is neither good news nor bad. Desaturated to
     sit with the pair above -- an expiry two sessions out is a fact
     that wants noticing, not an alarm. */
  --warn:   #B59A54;

  /* The four evidence classes. Barely there on purpose -- the class is
   * already named in words on every panel and drawn in the weight of
   * its top rule, so this is a third quiet echo of a fact you can
   * already read, not a new code to learn. */
  --c-filed:   #7E93B8;
  --c-priced:  #6E9E78;
  --c-derived: #9C87C4;
  --c-claimed: #A8845E;

  /* Worth a second look. Not good, not bad -- unusual. Volume against
     open interest, a burst of filings, an implied volatility a long way
     from what the stock has actually been doing. Amber because that is
     what amber has always meant, and because neither green nor red is
     honest about something whose direction is unknown. */
  --attn:   #C79A52;

  /* The source lights under a search. Lit, not muted: an LED says
     on or off at a glance, and that is the only thing it is for. */
  --led-on:  #3FD06B;
  --led-off: #F0473C;


  /* THE FOUR ROOMS

   *

   * The same argument the moving averages make: this hue says WHICH

   * ROOM a tab is, and nothing else. It is not a mood and not a

   * judgement -- a workshop tab is not warmer or better than a search

   * tab, it is a different kind of place.

   *

   * Kept away from the hues that already mean something. Green and red

   * are money, amber is attention, and the sand/teal/mauve trio belongs

   * to the moving averages. These four are quieter than all of them,

   * because a tab strip is furniture and should not be the brightest

   * thing on screen.

   *

   * Every room is also named in words, on the tab and on the button

   * that opens it, so the colour is a second way of reading something

   * already legible rather than the only way. */

  --room-search:   #8FA3B8;   /* slate  -- one company            */

  --room-finder:   #7FA88C;   /* sage   -- the whole market       */

  --room-position: #C0946B;   /* tan    -- building something     */

  --room-log:      #A98BB5;   /* lilac  -- what you already hold  */
  --room-world:    #B5847E;   /* clay   -- everything at once   */


  --mast:   "Bodoni Moda", Georgia, serif;
  /* GFS Didot, from the Greek Font Society -- a Greek Didone that also cuts
     Latin. Used for the name alone, nowhere else. */
  --greek:  "GFS Didot", "Bodoni Moda", Georgia, serif;
  --mono:   "IBM Plex Mono", Consolas, monospace;
  --ui:     Inter, "Segoe UI", system-ui, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--black);
  color: var(--text);
  font: 13px/1.5 var(--ui);
  height: 100vh; overflow: hidden;
  display: flex; flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

/* ================= chrome ================= */

.tabstrip {
  display: flex; align-items: stretch; gap: 1px;
  background: var(--rule); border-bottom: 1px solid var(--rule);
  flex: 0 0 auto; -webkit-app-region: drag;
}
.tab {
  border-radius: 13px 13px 0 0;
  -webkit-app-region: no-drag;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 14px; background: var(--black); color: var(--text2);
  cursor: pointer; max-width: 300px; min-width: 150px;
  font-size: 12.5px; user-select: none;
}
.tab.active { background: var(--panel); color: var(--text); }
.tab:hover:not(.active) { color: var(--text); }
.tab .sym { font-weight: 600; margin-right: auto; }
.tab .px { font-family: var(--mono); font-size: 12px; color: var(--text); }
.tab .chg { font-family: var(--mono); font-size: 11.5px; }
.tab .x { font-size: 15px; line-height: 1; color: var(--faint); }
.tab .x:hover { color: var(--text); }
.newtab {
  -webkit-app-region: no-drag; background: var(--black); border: none;
  color: var(--rule2); font-size: 18px; cursor: pointer; padding: 0 16px;
  transition: color .12s ease;
}
.newtab:hover { color: var(--text); }

.viewport { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; background: var(--black); }

/* ================= launcher =================
 * Three things on the page: the name, the field, and six tickers. Nothing
 * here is outlined -- the field is a shape in the ground rather than a box
 * drawn on it, which is the same reason the panels below have no borders
 * either. */

.launcher {
  height: 100%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 34px;
}
/* Set in GFS Didot, a Greek Didone. Wide tracking because display type at
   this size closes up, and the letterforms are the only ornament here. */
.launcher h1 {
  font-family: var(--greek); font-weight: 400;
  font-size: clamp(52px, 8vw, 104px); letter-spacing: .3em;
  text-indent: .3em;                    /* recover the trailing track */
  color: var(--text); line-height: 1;
}
.searchwrap { position: relative; width: min(600px, 80vw); }
.searchbox {
  display: flex; border: none;
  background: var(--panel); border-radius: 999px; overflow: hidden;
  transition: background .15s ease;
}
.searchbox:focus-within { background: var(--raised); }
.searchbox input {
  flex: 1; background: none; color: var(--text); border: none;
  padding: 17px 28px; font-family: var(--ui); font-size: 16px; outline: none;
}
.searchbox input::placeholder { color: var(--faint); }
.searchbox button {
  background: none; border: none; color: var(--text2);
  font-family: var(--ui); font-weight: 600; font-size: 11px;
  letter-spacing: .18em; padding: 0 30px; cursor: pointer; text-transform: uppercase;
  transition: color .12s ease;
}
.searchbox button:hover { color: var(--text); }

.suggest {
  position: absolute; top: calc(100% + 7px); left: 0; right: 0; z-index: 30;
  background: var(--raised); border: none;
  border-radius: 20px; overflow: hidden;
  max-height: 300px; overflow-y: auto;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .55);
}
.suggest div {
  padding: 9px 16px; cursor: pointer; display: flex; align-items: baseline; gap: 12px;
  border-bottom: 1px solid var(--rule);
}
.suggest div:hover, .suggest div.on { background: var(--raised); }
.suggest .s { font-family: var(--mono); font-weight: 600; font-size: 13px; min-width: 70px; }
.suggest .n { flex: 1; font-size: 13px; color: var(--text2); }
.suggest .e { font-size: 10.5px; color: var(--faint); text-transform: uppercase; }

.quick { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; }
.quick span {
  padding: 7px 18px; border: none; border-radius: 999px;
  font-family: var(--mono); font-size: 12px; color: var(--faint);
  cursor: pointer; transition: background .12s ease, color .12s ease;
}
.quick span:hover { background: var(--panel); color: var(--text); }

/* ================= positions =================
   The board, not a form. Calls left, puts right, strikes down the middle
   and the share price drawn straight through the ladder where it actually
   falls -- which is the layout a trader already has in their head, and the
   one every options screen flattens into a spreadsheet.

   Behind each price is a bar for open interest. It is the only encoding
   here that is not a number, and it earns that: the difference between a
   strike with forty contracts open and one with forty thousand decides
   whether the trade is possible at all, and reading it out of a column of
   integers takes ten seconds that a bar takes none. */

.launchlinks { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }

.pospick {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--rule);
}
.pospick .searchwrap { position: relative; }
.pospick .searchbox { background: var(--panel); }
.pospick .searchbox input { padding: 10px 18px; font-size: 14px; }
.pospick button {
  background: none; border: none; color: var(--faint); cursor: pointer;
  font-family: var(--ui); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; padding: 7px 14px; border-radius: 999px;
  transition: background .12s ease, color .12s ease;
}
.pospick button:hover { background: var(--panel); color: var(--text); }

/* ---- the legs you hold, as chips ---- */
.chips {
  display: flex; flex-wrap: wrap; gap: 7px;
  padding: 11px 16px; border-bottom: 1px solid var(--rule); min-height: 44px;
}
.empty-chips {
  color: var(--faint); font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  align-items: center;
}
.chip {
  display: flex; align-items: baseline; gap: 6px;
  background: var(--sunk); border-radius: 999px; padding: 5px 6px 5px 12px;
  font-family: var(--mono); font-size: 12px; color: var(--text);
}
/* Long and short are the one thing that must never be misread, so they get
   a weight difference rather than a colour: bought is solid, sold hollow. */
.chip.long { box-shadow: inset 0 0 0 1px var(--text); }
.chip.short { box-shadow: inset 0 0 0 1px var(--rule2); }
.chip .cs {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.chip.long .cs { color: var(--text); }
.chip .ck { font-weight: 600; }
.chip .cx, .chip .at { color: var(--faint); font-size: 11px; }
.chip input {
  background: none; border: none; border-bottom: 1px dashed var(--rule2);
  color: var(--text); font-family: var(--mono); font-size: 12px;
  width: 44px; text-align: center; padding: 0 2px; outline: none;
}
.chip input:focus { border-bottom-color: var(--text); }
.chip button {
  background: none; border: none; color: var(--rule2); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 5px;
}
.chip button:hover { color: var(--text); }

/* ---- the chain ----
   Built to the convention rather than around it. Seven headed columns a
   side, the same order on both, strikes down the middle, in-the-money
   rows shaded. Anyone who has opened a broker's chain can read this
   without being told, which is the entire argument for it -- the previous
   version invented a layout and then had to explain itself in a footnote. */
.chainwrap { max-width: 1320px; margin: 0 auto; padding: 0 112px 18px 16px; }

.expbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 0 10px;
}
.explab, .exphint {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.exphint { margin-left: auto; }
.exphint b { color: var(--text); }
.expiries { flex-wrap: wrap; }

.chain { border-top: 1px solid var(--rule); }

.crow {
  display: grid; grid-template-columns: 1fr 96px 1fr;
  border-bottom: 1px solid var(--hline);
}
.cside {
  display: grid; grid-template-columns: repeat(8, 1fr);
  align-items: stretch;
}

/* The two header rows: what side, then what column. */
.chead2 { border-bottom: none; }
.chead2 .hd {
  grid-column: 1 / -1; padding: 8px 10px 2px;
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--text);
}
.chead2 .puts .hd { text-align: right; }
.chead .q, .chead b {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  padding: 4px 6px 7px;
}
.chead { border-bottom: 1px solid var(--rule); }

.q {
  font-family: var(--mono); font-size: 12px; color: var(--text2);
  padding: 5px 6px; text-align: right; align-self: center;
  white-space: nowrap; overflow: hidden;
}
.cside.calls .q { text-align: right; }
.cside.puts .q { text-align: left; }
.cside.puts .chead .q { text-align: left; }

/* ---- the three zones ----

   A chain is read by where the money is, and this board had only one of
   the three marked -- with a four-percent wash that was invisible on
   anything but a good monitor. The strike nearest the share price, which
   is the row every other strike is compared against, had no mark at all.

   The shading runs down one side of the board and up the other, because
   a call is in the money BELOW the share price and a put above it. That
   inversion is the thing people get wrong, so each side says which way
   it runs rather than leaving the shading to imply it. */

.cside.itm {
  background: rgba(242, 242, 240, .075);
  box-shadow: inset 0 0 0 1px rgba(242, 242, 240, .035);
}
.cside.itm .q { color: var(--text); }
.cside.otm .q.oi { color: var(--rule2); }

/* At the money: ruled above and below so it reads as a landmark rather
   than as another shaded row. */
.crow.atm {
  background: rgba(242, 242, 240, .03);
  border-top: 1px solid var(--rule2);
  border-bottom: 1px solid var(--rule2);
}
/* Ringed rather than labelled. A word here has nowhere to go: the
   strike column is 96px and an absolutely positioned "atm" spilled
   straight into the put side's bid. The ring costs no horizontal room,
   and the key underneath says what it means. */
.crow.atm .cstrike b {
  color: var(--text); font-weight: 700;
  box-shadow: inset 0 0 0 1px var(--rule2);
  border-radius: 3px; padding: 3px 10px;
}

/* Which direction each side runs, stated on the side it applies to. */
.mny-dir {
  font-family: var(--ui); font-size: 8.5px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  font-style: normal; margin-left: 9px;
}
.cside.puts .hd .mny-dir { margin: 0 9px 0 0; }

/* The key. Shading is not a language anyone is born knowing. */
.mnykey { display: inline-flex; align-items: center; gap: 12px; }
.mnykey b {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  display: inline-flex; align-items: center; gap: 5px;
}
.mnykey b::before {
  content: ""; width: 11px; height: 11px; border-radius: 2px;
  border: 1px solid var(--rule);
}
.mnykey .k-itm::before { background: rgba(242, 242, 240, .12); }
/* Matches the ring drawn around the at-the-money strike itself. */
.mnykey .k-atm::before {
  background: transparent; border-color: var(--rule2); border-radius: 3px;
}
.mnykey .k-otm::before { background: transparent; }

.q.oi { color: var(--faint); }

/* Bid and ask are the controls. They are boxed so they read as pressable
   before the cursor reaches them, and each one says what it will do. */
button.q.px {
  border: none; cursor: pointer; border-radius: 3px;
  font-family: var(--mono); font-size: 12.5px; font-weight: 500;
  color: var(--text); background: var(--sunk);
  margin: 2px 3px; padding: 4px 6px; transition: background .1s ease, color .1s ease;
}
button.q.px:hover { background: var(--text); color: var(--black); }
button.q.px.sell:hover::after { content: " sell"; font-size: 8px; letter-spacing: .1em; }
button.q.px.buy:hover::after { content: " buy"; font-size: 8px; letter-spacing: .1em; }
span.q.px { color: var(--rule2); }

.q.edge.dear { color: var(--text); }
.q.edge.cheap { color: var(--text2); }
.q.edge.flat { color: var(--rule2); }

.cstrike {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  border-left: 1px solid var(--rule); border-right: 1px solid var(--rule);
}
.cstrike b {
  font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--text);
  padding: 5px 0;
}
.crow.mine .cstrike { background: var(--raised); }
.crow:hover { background: rgba(242, 242, 240, .025); }

/* How many of that exact contract you hold, on the strike it belongs to. */
.pos {
  font-family: var(--mono); font-style: normal; font-size: 9.5px; font-weight: 700;
  padding: 1px 5px; border-radius: 999px;
}
.pos.l { background: var(--text); color: var(--black); }
.pos.s { box-shadow: inset 0 0 0 1px var(--text); color: var(--text); }

/* Where the stock is, across the board.
   The line stays -- which rungs are above and below the money is the one
   thing you read a chain for. The label moved out into the right margin,
   because centred it sat directly on top of the strike column and you had
   to look past the price to read the strike it was marking. */
.spotrow {
  position: relative; height: 0; border-top: 1px dashed var(--text);
}
.spotrow span {
  position: absolute; right: -104px; top: -9px; white-space: nowrap;
  font-family: var(--mono); font-size: 11px; color: var(--text);
  display: flex; align-items: center; gap: 6px;
}
.spotrow span::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--text);
}

/* ---- ready-made setups ----
   Cards rather than a list, because you scan these comparing one against
   another: the odds sit in the same place on every card so the eye can run
   down them, and the payoff sentence sits underneath so the trade-off --
   likely and small against unlikely and large -- shows up as a pattern
   across the row instead of something you have to work out per card. */
.presets { padding: 4px 0 16px; }
.pregrid {
  display: grid; gap: 1px; background: var(--rule);
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.pcard {
  display: flex; flex-direction: column; gap: 5px; text-align: left;
  background: var(--panel); border: none; cursor: pointer;
  padding: 13px 15px 12px; font-family: var(--ui); color: var(--text2);
  transition: background .12s ease;
}
.pcard:hover { background: var(--raised); }

/* The odds, in the same spot on every card. */
.pcard .odds { display: flex; align-items: baseline; gap: 6px; }
.pcard .odds b {
  font-family: var(--mono); font-size: 21px; font-weight: 500;
  color: var(--text); line-height: 1;
}
.pcard .odds i {
  font-style: normal; font-size: 9px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--faint);
}

.pcard .pname { font-size: 12.5px; font-weight: 600; color: var(--text); }
.pcard .pview { font-size: 11.5px; line-height: 1.45; color: var(--text2); }
.pcard .psum { font-size: 10.5px; line-height: 1.55; color: var(--faint); }
.pcard .psum b { color: var(--text2); font-weight: 500; font-family: var(--mono); }
.pcard .plegs {
  font-family: var(--mono); font-size: 10px; color: var(--rule2);
  margin-top: auto; padding-top: 6px;
}
.pcard .puse {
  font-size: 9px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); opacity: 0; transition: opacity .12s ease;
}
.pcard:hover .puse { opacity: 1; color: var(--text); }

.plink {
  background: none; border: none; cursor: pointer; padding: 0;
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--text2);
}
.plink:hover { color: var(--text); }

.cfoot {
  padding: 12px 2px 0; max-width: 92ch;
  font-size: 11px; line-height: 1.6; color: var(--faint);
}
.cfoot b { color: var(--text2); }

@media (max-width: 1200px) {
  .chainwrap { padding-right: 16px; }
  .spotrow span {
    right: 0; top: -8px; background: var(--black); padding-left: 8px;
  }
  .cside { grid-template-columns: repeat(8, 1fr); }
  .q { font-size: 11px; padding: 4px 3px; }
  .chead .q { font-size: 7.5px; letter-spacing: .04em; }
}

/* ---- the read-out below ---- */
.posbody { padding: 16px 16px 30px; }
.phead { margin-bottom: 14px; }
.phead h2 {
  font-family: var(--mast); font-weight: 700; font-size: 28px;
  display: inline-block; margin-right: 12px;
}
.phead .fam {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--faint);
}
.phead p { font-size: 13px; color: var(--text2); margin-top: 5px; max-width: 70ch; }

/* The position written out. Set at reading size and given the width of a
   column of prose, because that is what it is -- the grid underneath is
   the abbreviation, not the other way round. */
.plain { margin-bottom: 18px; max-width: 78ch; }
.plain p {
  font-family: var(--ui); font-size: 14.5px; line-height: 1.68;
  color: var(--text2); margin-bottom: 9px;
}
.plain p b { color: var(--text); font-weight: 600; }

.pstats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; background: var(--rule); border: 1px solid var(--rule);
  margin-bottom: 16px;
}
.pstats .pstat { background: var(--panel); padding: 10px 13px; }
.pstats .pstat span {
  display: block; font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 4px;
}
.pstats .pstat b {
  font-family: var(--mono); font-size: 19px; font-weight: 500; color: var(--text);
}

.plegs { margin-bottom: 8px; }
.pleg {
  display: grid; gap: 10px; align-items: baseline; padding: 6px 0;
  grid-template-columns: minmax(150px, 1.4fr) 110px 78px 78px 78px 78px 96px;
  border-bottom: 1px solid var(--hline);
  font-family: var(--mono); font-size: 12px; color: var(--text2);
}
.pleg span:last-child { text-align: right; }
.pleg b { color: var(--text); font-weight: 600; }
.plhead {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  border-bottom: 1px solid var(--rule);
}
.poschart { border: 1px solid var(--rule); margin-bottom: 16px; }
.tab-position .sym { letter-spacing: .06em; }

@media (max-width: 1100px) {
  .lhead { grid-template-columns: 1fr; gap: 8px; }
  .lhead > span { display: none; }
  .pleg { grid-template-columns: minmax(120px,1.3fr) 92px 62px 62px 62px 62px 80px; gap: 7px; }
}

/* ================= the finder =================
   A table, because that is what a ranked list of two thousand things is.
   The reasons column is the point: a score of 94.4 is not an argument, and
   "+422% over the year to last month / 0.93 trend fit" is. */

.findlink {
  background: none; border: none; cursor: pointer;
  color: var(--faint); font-family: var(--ui); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 6px 14px; border-radius: 999px;
  transition: color .12s ease, background .12s ease;
}
.findlink:hover { color: var(--text); background: var(--panel); }

/* One button per ranking, each carrying its own one-line purpose. A bare
   label would make these seven synonyms for "sort"; the sentence is what
   tells you which one answers your question. */
.fpick {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1px; background: var(--rule); border-bottom: 1px solid var(--rule);
}
.fpick button {
  background: var(--panel); border: none; cursor: pointer;
  text-align: left; padding: 11px 14px 12px;
  display: flex; flex-direction: column; gap: 3px;
  transition: background .12s ease;
}
.fpick button:hover { background: var(--raised); }
.fpick button.on { background: var(--text); }
.fpick .l {
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text);
}
.fpick .n { font-size: 11px; line-height: 1.4; color: var(--text2); }
/* What the ranking actually did, from the walk-forward. Set smaller and
   quieter than the purpose above it: the claim comes first, the evidence
   second, and the evidence should not shout. */
.fpick .v {
  font-family: var(--mono); font-size: 9.5px; line-height: 1.45;
  color: var(--faint); margin-top: 4px;
  padding-top: 5px; border-top: 1px solid var(--rule);
}
.fpick button.on .v { color: var(--black); opacity: .72; border-top-color: rgba(0,0,0,.2); }
.fstudy { padding: 16px 16px 0; max-width: 88ch; font-size: 11.5px; }
.fpick button.on .l, .fpick button.on .n { color: var(--black); }

.finder { padding: 0 0 4px; }
.frow {
  display: grid;
  grid-template-columns: 34px 175px minmax(230px, 1fr) repeat(5, 92px);
  gap: 12px; align-items: baseline;
  padding: 9px 16px; border-bottom: 1px solid var(--hline);
  cursor: pointer; transition: background .1s ease;
}
.frow:hover { background: var(--raised); }
.fhead {
  cursor: default; background: none; border-bottom: 1px solid var(--rule);
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.fhead:hover { background: none; }
.frow .fn { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.frow .fsym b {
  font-family: var(--mono); font-size: 14px; font-weight: 600;
  color: var(--text); display: block;
}
.frow .fsym i {
  font-style: normal; font-size: 10.5px; color: var(--faint);
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.frow .fwhy { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.frow .fwhy em {
  font-style: normal; font-size: 11px; color: var(--text2);
}
/* The strongest reason first, and it reads as the strongest. */
.frow .fwhy em:first-child { color: var(--text); }
.frow .fv {
  font-family: var(--mono); font-size: 12.5px; color: var(--text);
  text-align: right;
}
.fhead .fv { font-family: var(--ui); text-align: right; }


.tab-finder .sym { letter-spacing: .1em; }

@media (max-width: 1100px) {
  .frow { grid-template-columns: 26px 130px minmax(140px, 1fr) repeat(5, 70px); gap: 7px; }
}

/* ================= the grid =================
 * 1px gaps over a rule-coloured ground: the gap IS the rule. Panels sit
 * flush in one ruled table instead of floating as separate cards. */

.grid {
  --tile-min: 232px;
  --grid-gap: 0px;
  --vline: #43434A;   /* columns: the structure you read across */
  --hline: #1D1D20;   /* rows: quieter, because there are far more of them */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-min), 1fr));
  grid-auto-rows: 128px;
  grid-auto-flow: row dense;
  gap: var(--grid-gap);
  background: var(--black);
  position: relative;
  /* A gutter for the region rail. It floats with no ground of its own, so
     the page has to leave it room rather than let it sit over the panels.
     packGrid() reads this padding when it works out the column count. */
  padding-right: 112px;
}
/* ---- spans ---- */
.w2 { grid-column: span 2; } .w3 { grid-column: span 3; } .w4 { grid-column: span 4; } .w5 { grid-column: span 5; }
.h2 { grid-row: span 2; } .h3 { grid-row: span 3; } .h4 { grid-row: span 4; } .h5 { grid-row: span 5; }

/* ---- the panel ----
   No border and no card. Panels sit flush in one ruled table, so the only
   separators are the two rules each panel draws inside its own right and
   bottom edge. The vertical rule is the brighter of the two: columns are the
   structure you read across, rows are merely how many there happen to be. */

.tile {
  background: var(--panel);
  box-shadow: inset -1px 0 0 var(--vline), inset 0 -1px 0 var(--hline);
  padding: 11px 13px 12px;
  display: flex; flex-direction: column; overflow: hidden;
  cursor: zoom-in; position: relative; min-width: 0;
}
.tile:hover { background: var(--raised); }

/* Evidence class as line weight on the panel's top rule. Heavier and more
   solid means you can lean on it harder: FILED is a regulator's own words,
   CLAIMED is an interested party talking. */
.tile::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0;
  border-top: 1px solid var(--rule2);
}
/* The top rule carries the class, in weight and now faintly in hue.
   The word is printed in the masthead of every panel and the line
   weight already says it, so this is a third quiet echo of something
   readable two other ways -- which is the only reason colour is safe
   on a page this dense. */
.e-filed::before   { border-top: 2px solid var(--c-filed); }
.e-priced::before  { border-top: 1px solid var(--c-priced); }
.e-derived::before { border-top: 1px dashed var(--c-derived); }
.e-claimed::before { border-top: 1px dotted var(--c-claimed); }
.tile.e-filed   > h3 .cls { color: var(--c-filed); }
.tile.e-priced  > h3 .cls { color: var(--c-priced); }
.tile.e-derived > h3 .cls { color: var(--c-derived); }
.tile.e-claimed > h3 .cls { color: var(--c-claimed); }
.e-filed   { background: var(--raised); }
.e-claimed { background: var(--sunk); }

.tile > h3 {
  display: flex; align-items: baseline; gap: 9px;
  font-family: var(--ui); font-size: 9.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text);
  margin-bottom: 7px; flex: 0 0 auto;
}
.tile > h3 > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The class word and the badge are labels ABOUT the panel, not content in
   it, so they sit at label weight and never compete with the numbers. */
.tile > h3 .cls {
  margin-left: auto; font-size: 8px; letter-spacing: .14em;
  color: var(--faint); cursor: help; flex: 0 0 auto;
}
.tile > h3 .badge {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0;
  color: var(--text2); text-transform: none; flex: 0 0 auto;
}
.tile > .body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.tile > .body::-webkit-scrollbar { width: 6px; }
.tile > .body::-webkit-scrollbar-thumb { background: var(--rule); }

/* A chart needs a definite height to size against, and .body is a block --
   so a body that holds a chart becomes a flex column. Without this the SVG
   falls back to its own viewBox aspect ratio, that height is measured on the
   next draw, and the chart ratchets taller until it overflows the tile. */
.tile > .body:has(> .qchart-host) { display: flex; flex-direction: column; }

/* Where the panel's numbers came from. Stated on every panel, quietly. */
.source {
  font-size: 8.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 7px;
}

/* Typographic register. A panel carrying one number sets it large; a panel
   carrying a table sets everything small so the columns stay alignable. */
.t-hero .figure { font-size: 40px; }
.t-mid .figure { font-size: 30px; }
.t-small .kv, .t-small .row { font-size: 11.5px; }
.m-heavy .body { font-variant-numeric: tabular-nums; }
.m-side .claim { border-left-width: 2px; }

/* ---- content primitives ---- */

.kv {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 3.5px 0; border-bottom: 1px solid var(--hline); font-size: 12px;
}
.kv > span:first-child { color: var(--text2); }
.kv > span:last-child { font-family: var(--mono); color: var(--text); text-align: right; }

.row {
  display: grid; align-items: baseline; gap: 8px;
  padding: 3px 0; border-bottom: 1px solid var(--hline);
  font-family: var(--mono); font-size: 11.5px; color: var(--text2);
}
.row.head {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  border-bottom: 1px solid var(--rule);
}
.row > span:first-child { color: var(--text); }

.figure {
  font-family: var(--mono); font-size: 34px; font-weight: 500;
  line-height: 1.05; color: var(--text); letter-spacing: -.01em;
}
.unitline {
  font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); margin: 3px 0 9px;
}
.prose { font-size: 12px; line-height: 1.6; color: var(--text2); }
.prose b { color: var(--text); font-weight: 600; }
.dim { color: var(--faint); }
.warn { color: var(--attn); }

/* Direction, the old newspaper stock-table way: filled triangle up,
   hollow down. The triangles stay and stay load-bearing -- they are why
   this survives being printed, or read by someone who cannot separate
   the two hues. The colour is a second, quieter copy of the same fact,
   for scanning a page of numbers rather than reading one.

   Deliberately washed out. A full green on black is a traffic light and
   a page of traffic lights stops meaning anything; more to the point, a
   stock being down is not bad news, and a warning red would say it was. */
.up::before { content: "\25B2"; font-size: .72em; margin-right: .35em; }
.down::before { content: "\25BD"; font-size: .72em; margin-right: .35em; }
.up { color: var(--pos); }
.down { color: var(--neg); }

/* ---- the quote panel ---- */
.coname { font-family: var(--mast); font-weight: 700; font-size: 21px; line-height: 1.1; }
.exch { font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); margin: 2px 0 8px; }
.price { font-family: var(--mono); font-size: 34px; font-weight: 500; line-height: 1.05; }
.pricechg { font-family: var(--mono); font-size: 13px; margin: 1px 0 9px; }
.pricechg .unit { color: var(--text2); margin-left: 7px; }

/* ---- tables ---- */
.chain { grid-template-columns: 52px 46px 40px 48px 52px 46px; cursor: pointer; }
.chain:hover { background: var(--raised); }
.chain.on { background: var(--text); }
.chain.on, .chain.on > span { color: var(--black); }
.fin { grid-template-columns: 44px 1fr 54px 48px 48px; }
.scen { grid-template-columns: 60px 66px 1fr 64px; }

.filing {
  display: grid; grid-template-columns: 56px 1fr 48px; gap: 10px;
  padding: 4px 0; font-size: 11.5px; align-items: baseline;
  border-bottom: 1px solid var(--hline);
}
.filing .form {
  font-family: var(--mono); font-size: 10.5px; color: var(--text2);
  border: 1px solid var(--rule2); text-align: center; padding: 1px 0;
}
.filing .form.hot { background: var(--text); color: var(--black); border-color: var(--text); }
.filing .means { color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- the greeks, in plain english ---- */
.gk-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-bottom: 10px; }
.gk-pick label { font-size: 9px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.gk-pick select, .gk-pick input {
  background: var(--sunk); border: none; border-radius: 999px;
  color: var(--text); font-family: var(--mono); font-size: 11px;
  padding: 4px 10px; outline: none;
}
.gk-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding-bottom: 8px; border-bottom: 1px solid var(--rule); margin-bottom: 4px;
}
.gk-head .pos { font-weight: 700; font-size: 16px; }
.gk-head .pos::before { content: none; }
.gk-head .cost { font-family: var(--mono); font-size: 11.5px; color: var(--text2); }
.gk { padding: 9px 0; display: grid; grid-template-columns: 92px 1fr; gap: 14px; border-bottom: 1px solid var(--hline); }
.gk .name { display: block; font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.gk .val { display: block; font-family: var(--mono); font-size: 17px; color: var(--text); }
.gk .say { font-size: 12px; line-height: 1.55; color: var(--text2); }
.gk .say b, .verdict b { color: var(--text); font-weight: 600; }
.verdict {
  margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--rule);
  font-size: 12.5px; line-height: 1.6; color: var(--text2);
}

/* ---- implied against realised ---- */
.volbar { margin-bottom: 9px; }
.volbar .track { height: 9px; background: var(--sunk); position: relative; }
.volbar .fill { position: absolute; inset: 0 auto 0 0; background: var(--text); }
.volbar .lab { display: flex; justify-content: space-between; font-size: 10px; color: var(--text2); margin-top: 3px; }
.volbar .lab span:last-child { font-family: var(--mono); color: var(--text); }

/* ---- news ----
   Headlines are the one thing on this page meant to be read across the room:
   big, bold, and set in the face a newspaper puts its own title in. */
.article { padding: 9px 0; border-bottom: 1px solid var(--hline); }
.article .hl {
  font-family: var(--mast); font-weight: 700; font-size: 17px; line-height: 1.2;
  color: var(--text); text-decoration: none; display: block;
}
.article .hl:hover { text-decoration: underline; text-underline-offset: 3px; }
.article .meta { font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--faint); margin: 4px 0; }
.article .meta .dot { margin: 0 6px; }
.article .stand { font-size: 12px; line-height: 1.55; color: var(--text2); }
.nofull { color: var(--faint); font-style: italic; }
.cols2 .body { column-count: 2; column-gap: 18px; column-rule: 1px solid var(--rule); }

.claim {
  border-left: 1px solid var(--rule2); padding: 7px 0 7px 11px; margin-bottom: 7px;
  font-size: 12px; line-height: 1.5; color: var(--text2);
}
.claim .src { font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); margin-right: 8px; }
.claim .sc { font-family: var(--mono); font-size: 9.5px; color: var(--faint); }


/* ---- charts ---- */
.qchart-host { position: relative; flex: 1 1 auto; min-height: 90px; }
svg.qchart { width: 100%; height: 100%; display: block; }
.qchart text.qc-axis { font-family: var(--mono); font-size: 8.5px; fill: var(--faint); }
/* the price the crosshair pins to the axis */
.qchart text.qc-tag { font-family: var(--mono); font-size: 9px; font-weight: 600; fill: var(--black); }

.qchart-readout {
  position: absolute; top: 0;
  background: var(--text); color: var(--black);
  font-family: var(--mono); font-size: 10px; line-height: 1.4;
  padding: 3px 7px; pointer-events: none; white-space: nowrap; z-index: 3;
}
.qchart-readout b { font-size: 11.5px; display: block; }
.qchart-readout span { display: block; opacity: .7; }
.qchart-hint { font-size: 8.5px; letter-spacing: .06em; color: var(--faint); text-align: right; padding-top: 3px; opacity: 0; }
.tile:hover .qchart-hint, .zoom .qchart-hint { opacity: 1; }

/* Chart controls. The segments share one recessed ground instead of a drawn
   frame, so the group reads as one control without a line around it. */
.cbar { display: flex; align-items: center; gap: 10px; padding-bottom: 7px; }
.cbar .grow { flex: 1; }
.cseg { display: flex; background: var(--sunk); border-radius: 999px; padding: 1px; }
.cseg button {
  background: none; border: none; border-radius: 999px;
  color: var(--faint); cursor: pointer;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .08em;
  text-transform: uppercase; padding: 3px 10px;
  transition: color .12s ease, background .12s ease;
}
.cseg button:hover { color: var(--text); }
.cseg button.on { background: var(--text); color: var(--black); }

/* the visible window, in numbers, directly under the axis it describes */
.cstats {
  display: flex; flex-wrap: wrap; gap: 0 14px; padding-top: 5px;
  border-top: 1px solid var(--hline);
  font-family: var(--mono); font-size: 9.5px; color: var(--text2);
}
.cstats .k { color: var(--text); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }

/* ================= the numbered options story =================
   Numbers do the ordering, so the steps need no rules between them; the
   figure sits between heading and prose because it is the answer, and the
   prose is only there to say what the answer means. */

.story-steps { display: flex; flex-direction: column; }
.sstep { display: grid; grid-template-columns: 22px 1fr; gap: 10px; padding: 9px 0; border-top: 1px solid var(--hline); }
.sstep:first-child { border-top: none; padding-top: 2px; }
.sn {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  color: var(--black); background: var(--text);
  width: 19px; height: 19px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
}
.sbody h5 {
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--text2);
  margin: 3px 0 0;
}
.sfig { font-family: var(--mono); font-size: 19px; line-height: 1.15; color: var(--text); margin: 2px 0 3px; }
.sbody p { font-family: var(--ui); font-size: 11.5px; line-height: 1.55; color: var(--text2); margin: 0; }
.sbody p b { color: var(--text); font-weight: 600; }
.story-steps.full .sstep { padding: 14px 0; grid-template-columns: 26px 1fr; gap: 14px; }
.story-steps.full .sn { width: 23px; height: 23px; font-size: 12px; }
.story-steps.full .sfig { font-size: 26px; }
.story-steps.full .sbody p { font-size: 13px; line-height: 1.68; }

/* the touch-versus-finish ladder */
.lad, .lad-head { display: grid; grid-template-columns: 70px 80px 1fr 1fr; gap: 10px; font-family: var(--mono); font-size: 11.5px; padding: 3px 0; }
.lad-head {
  font-family: var(--ui); font-size: 9px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); border-bottom: 1px solid var(--rule); padding-bottom: 5px; margin-top: 6px;
}
.lad { border-bottom: 1px solid var(--hline); color: var(--text2); }
.lad span:nth-child(3) { color: var(--text); }

/* ================= glossary =================
   A dotted underline is this page's mark for "claimed, not proven", so a
   defined term gets dashes instead -- present enough to find, quiet enough
   that a paragraph with six of them still reads as prose. */

.term {
  border-bottom: 1px dashed var(--rule2);
  cursor: help;
  transition: border-color .12s ease, color .12s ease;
}
.term:hover { border-bottom-color: var(--text); color: var(--text); }

.termtip {
  /* Above the zoom overlay, which sits at 90. At 60 the definitions
     were behind it: hovering a term inside an opened panel showed
     nothing at all, which reads as the glossary being broken rather
     than as a stacking mistake. */
  position: fixed; left: 0; top: 0; z-index: 200;
  width: 320px; max-width: calc(100vw - 20px);
  background: var(--panel); border: 1px solid var(--text);
  padding: 12px 14px 13px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .65);
  /* Deliberately no animation and no transition on this element. A running
     animation or transition overrides the element's own inline style for
     every property it touches -- and the tip is positioned by an inline
     transform. Under a throttled compositor the keyframe never advances, so
     it froze at its start value and pinned the tip to the corner of the
     screen. Appearing instantly is no worse, and cannot fail that way. */
}
.termtip h6 {
  font-family: var(--ui); font-size: 9.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text);
  margin: 0 0 7px; padding-bottom: 6px; border-bottom: 1px solid var(--rule);
}
.termtip p { font-family: var(--ui); font-size: 12.5px; line-height: 1.55; color: var(--text); margin: 0; }
/* The formula is the one place monospace is not decoration: the alignment
   of the symbols is the meaning. */
.termtip pre {
  font-family: var(--mono); font-size: 11.5px; line-height: 1.5;
  color: var(--text); background: var(--sunk);
  border-left: 2px solid var(--rule2);
  margin: 9px 0 0; padding: 7px 9px;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.termtip p.note {
  margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--hline);
  font-size: 11.5px; color: var(--text2);
}

/* ================= story overlay ================= */

.storylayer { position: absolute; inset: 0; pointer-events: none; z-index: 5; overflow: visible; }
.storyline {
  fill: none; stroke: var(--text); stroke-width: 1.5; opacity: .45;
  stroke-dasharray: 1400; stroke-dashoffset: 1400;
  animation: drawIn .5s var(--delay, 0ms) ease forwards;
}
.storystep circle { fill: var(--text); stroke: var(--black); stroke-width: 2; }
.storystep text { font-family: var(--mono); font-size: 11px; font-weight: 600; fill: var(--black); }

/* ================= the region rail =================
   Four words at the right edge, no container and no outline -- it floats
   over the page rather than sitting in a box. The region you are in is the
   only one at full strength; everything else is a label waiting to be used.
   The digit is the keyboard shortcut, not decoration. */

/* The dot field behind the rail. Sits under the labels, takes no pointer
   events -- the ripple is driven from window pointermove, so the field
   reacts as the cursor approaches rather than only once it is over it. */
#railfield {
  position: fixed; right: 0; top: 0; pointer-events: none;
  /* Under the live bar (20), not over it -- the canvas runs the full height
     of the window and would otherwise scatter dots across the bar's own
     buttons. The bar's ground is opaque, so it simply covers the field. */
  z-index: 10;
}
@media (max-width: 900px) { #railfield { display: none; } }

.rail {
  position: fixed; right: 0; top: 50%; transform: translateY(-50%);
  z-index: 40; width: 112px; padding: 10px 16px 10px 0;
  display: flex; flex-direction: column; gap: 3px;
}
.rail button {
  background: none; border: none; cursor: pointer;
  display: flex; align-items: baseline; justify-content: flex-end; gap: 8px;
  padding: 5px 0; position: relative; width: 100%;
  color: var(--faint); font-family: var(--ui);
  font-size: 9.5px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  transition: color .14s ease;
}
/* The rule is the only mark: it grows in from the edge rather than
   appearing, so the eye follows it to the word it belongs to. */
.rail button::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: 0; height: 1px; background: var(--text);
  transition: width .18s ease;
}
.rail button:hover { color: var(--text2); }
.rail button:hover::before { width: 8px; }
.rail button.on { color: var(--text); }
.rail button.on::before { width: 16px; }
.rail .k {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0;
  color: var(--rule2);
}
.rail button.on .k { color: var(--text2); }

@media (max-width: 900px) {
  /* Too narrow to spend 112px on an index. */
  .rail { display: none; }
  .grid { padding-right: 0; }
}


/* ================= source lights ================= */

/* Last thing on the search page, stuck to the bottom of the view: one
   light per data source, green answered, red not. Wraps onto a second
   row in a narrow window rather than hiding the last few off the edge --
   a light nobody can see is the same as no light. */
.wirebar {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px 11px;
  background: var(--black); color: var(--text2);
  border-top: 1px solid var(--rule);
  padding: 7px 13px; font-family: var(--ui); font-size: 9.5px;
  letter-spacing: .05em; text-transform: uppercase; white-space: nowrap;
}
.wirebar .wb-head {
  color: var(--faint); font-weight: 600; letter-spacing: .14em;
  padding-right: 11px; border-right: 1px solid var(--rule);
}
.wirebar .wb-head b { font-family: var(--mono); color: var(--text); letter-spacing: 0; font-weight: 500; }
.wirebar .wb-wait { color: var(--faint); }
/* Names in their own case: capitals would make the row half as wide
   again, and all twenty-two need to fit across one screen. */
.wb-src {
  display: inline-flex; align-items: center; gap: 6px; cursor: default;
  font-size: 10px; text-transform: none; letter-spacing: 0;
}
.wb-src .led { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.wb-src.ok .led { background: var(--led-on); box-shadow: 0 0 6px var(--led-on); }
.wb-src.bad .led { background: var(--led-off); box-shadow: 0 0 6px var(--led-off); }
.wb-src.bad { color: var(--text); }

/* ================= autopilot ================= */

/* Bots that trade by rules. The builder is a form read like sentences --
   "price moves up 0.6% within 5 min" -- so each condition row is its type
   and then the sentence with the numbers left open. */
.ap { max-width: 1500px; margin: 0 auto; padding: 14px 16px 60px; font-family: var(--ui); }
.ap-head { margin-bottom: 14px; }
.ap-headrow { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px;
  padding: 12px 16px; background: var(--panel); border-radius: 4px; }
.ap-title h2 { margin: 0; font-family: var(--mast); font-size: 22px; color: var(--text); }
.ap-title span { display: block; font-size: 12px; color: var(--text2); margin-top: 2px; }
.ap-acct { font-size: 12.5px; color: var(--text2); }
.ap-acct b { color: var(--text); font-family: var(--mono); font-weight: 500; }
.ap-market { font-size: 11px; color: var(--text2); display: inline-flex; align-items: center; gap: 6px; }
.ap-head .led, .ap-cres .led { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex: none; }
.ap-market .led.on, .ap-cres.ok .led { background: var(--led-on); box-shadow: 0 0 5px var(--led-on); }
.ap-market .led.off, .ap-cres.no .led { background: var(--led-off); box-shadow: 0 0 5px var(--led-off); }
.ap-live { display: flex; align-items: center; gap: 8px; font-size: 11px; }
.ap-livebadge { background: var(--neg); color: var(--black); font-weight: 700; font-size: 10px;
  letter-spacing: .12em; padding: 3px 8px; border-radius: 3px; }
.ap button { font-family: var(--ui); font-size: 11.5px; background: var(--raised); color: var(--text);
  border: 1px solid var(--rule2); border-radius: 3px; padding: 5px 11px; cursor: pointer; }
.ap button:hover { border-color: var(--text2); }
.ap button.primary { background: var(--text); color: var(--black); border-color: var(--text); font-weight: 600; }
.ap-kill { margin-left: auto; background: transparent !important; border-color: var(--neg) !important; color: var(--neg) !important; }
.ap-kill:hover { background: var(--neg) !important; color: var(--black) !important; }
.ap-err { color: var(--neg); font-size: 12px; margin-top: 6px; }
.ap-ext { color: var(--text); text-decoration: underline; text-decoration-color: var(--rule2); text-underline-offset: 2px; }
.ap-ext:hover { text-decoration-color: var(--text); }
.ap-cols { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(320px, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1100px) { .ap-cols { grid-template-columns: 1fr; } }
.ap-build, .ap-side { background: var(--panel); border-radius: 4px; padding: 14px 16px; }
.ap-side h3 { margin: 0 0 10px; font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--text2); }
.ap-tpl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 12px; }
.ap-tpl > span { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); margin-right: 4px; }
.ap-top { display: grid; grid-template-columns: 1.4fr .8fr 1fr; gap: 10px; margin-bottom: 10px; }
.ap-f { display: flex; flex-direction: column; gap: 3px; font-size: 10.5px; color: var(--text2); }
.ap-f > span { letter-spacing: .06em; }
.ap-f i, .ap-cbody i { font-style: normal; color: var(--faint); font-size: 10px; }
.ap input, .ap select { background: var(--black); color: var(--text); border: 1px solid var(--rule2);
  border-radius: 3px; padding: 5px 7px; font-family: var(--mono); font-size: 12px; }
.ap input[type="checkbox"] { width: auto; padding: 0; }
.ap fieldset { border: 1px solid var(--rule); border-radius: 4px; padding: 10px 12px 12px; margin: 0 0 10px; }
.ap legend { padding: 0 6px; font-size: 11px; color: var(--text); display: flex; align-items: center; gap: 10px; }
.ap legend label { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.ap-rules.off > :not(legend) { opacity: .45; }
.ap-cond { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--rule); }
.ap-ctype { flex: none; width: 118px; font-size: 10px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--attn); }
.ap-cbody { flex: 1; font-size: 12.5px; color: var(--text2); line-height: 2; }
.ap-cbody input, .ap-cbody select { padding: 2px 5px; margin: 0 2px; }
.ap-cond button { flex: none; padding: 2px 8px; }
.ap-addc { margin-top: 8px; }
.ap-none { font-size: 12px; padding: 6px 0; line-height: 1.5; }
.ap-sets { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 1400px) { .ap-sets { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ap-sets fieldset { display: flex; flex-direction: column; gap: 7px; }
.ap-chk { flex-direction: row; align-items: center; gap: 7px; }
.ap-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; }
.ap-msg { font-size: 12px; color: var(--attn); }
.ap-check { margin-top: 12px; border-top: 1px solid var(--rule); padding-top: 10px; }
.ap-chead { font-size: 12px; color: var(--text2); margin-bottom: 8px; }
.ap-cside { padding: 8px 10px; border-radius: 3px; background: var(--sunk); margin-bottom: 8px; font-size: 12px; }
.ap-cside.met { box-shadow: inset 2px 0 0 var(--led-on); }
.ap-cside b { display: block; margin-bottom: 4px; color: var(--text); }
.ap-cres { display: flex; align-items: center; gap: 7px; color: var(--text2); line-height: 1.7; }
.ap-bot { border: 1px solid var(--rule); border-radius: 4px; padding: 10px 12px; margin-bottom: 10px; font-size: 12px; }
.ap-bot.st-active { border-color: var(--led-on); box-shadow: inset 3px 0 0 var(--led-on); }
.ap-bot.st-run { box-shadow: inset 3px 0 0 var(--attn); }
.ap-bot.st-stop { opacity: .8; }
.ap-bhead { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.ap-bhead b { color: var(--text); font-size: 13px; }
.ap-mode { font-size: 9.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 2px; background: var(--raised); color: var(--text2); }
.ap-mode.m-paper { color: var(--c-filed); }
.ap-mode.m-live { background: var(--neg); color: var(--black); }
.ap-status { margin-left: auto; font-size: 11px; color: var(--text2); }
.st-active .ap-status { color: var(--led-on); font-weight: 600; }
.ap-bnums, .ap-pos, .ap-wait { color: var(--text2); line-height: 1.6; }
.ap-bnums b, .ap-pos b { font-family: var(--mono); font-weight: 500; }
.ap-pos { margin: 6px 0; padding: 6px 8px; background: var(--sunk); border-radius: 3px; color: var(--text); }
.ap-wait { font-size: 11.5px; color: var(--faint); }
/* What the bot's conditions read on its last look, a light each. */
.ap-sees { margin: 6px 0; font-size: 11px; }
.ap-sees > div { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 12px; }
.ap-sees b { font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); width: 38px; }
.ap-sees .ap-cres { line-height: 1.6; }
.ap-events { margin: 6px 0; font-size: 11px; color: var(--faint); line-height: 1.55; }
.ap-events span { font-family: var(--mono); margin-right: 8px; }
.ap-bbtns { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ap-cash { margin-left: auto; display: inline-flex; gap: 4px; }
.ap-cash input { width: 70px; }
.ap-th { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--text2); margin: 14px 0 6px; }
.ap-trade { display: grid; grid-template-columns: 70px 1fr 1.2fr 70px 1.3fr; gap: 8px; font-size: 11.5px;
  padding: 4px 0; border-bottom: 1px solid var(--rule); color: var(--text2); }
.ap-trade span:first-child { font-family: var(--mono); }
.ap-flag { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 2px; margin-right: 6px; background: var(--raised); color: var(--text2); }
.ap-flag.f-active { background: var(--led-on); color: var(--black); }
.ap-flag.f-run { color: var(--attn); }
.ap-lrow.done { opacity: .75; }
.ap-lognone { max-width: 1100px; margin: 6px auto 0; padding: 0 20px; font-size: 12px; color: var(--faint); }

/* ================= instant ================= */

/* What lands first. A list read top-down by time, newest first; the kind
   and the source lead each row because they say how far to trust it
   before the headline says anything. */
.in-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding-bottom: 7px; margin-bottom: 4px; border-bottom: 1px solid var(--rule);
}
.in-feeds { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.in-feed {
  display: inline-flex; align-items: center; gap: 5px; cursor: default;
  font-family: var(--ui); font-size: 10px; color: var(--text2);
}
.in-feed .led { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.in-feed.ok .led { background: var(--led-on); box-shadow: 0 0 5px var(--led-on); }
.in-feed.bad .led { background: var(--led-off); box-shadow: 0 0 5px var(--led-off); }
.in-alert {
  flex: none; background: none; border: 1px solid var(--rule2); color: var(--text2);
  font-family: var(--ui); font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 4px 10px; border-radius: 999px; cursor: pointer;
}
.in-alert:hover { color: var(--text); border-color: var(--text2); }
.in-alert.on { background: var(--attn); border-color: var(--attn); color: var(--black); }
.in-row { padding: 7px 0 8px; border-bottom: 1px solid var(--rule); }
.in-row:last-child { border-bottom: none; }
.in-meta {
  display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px;
  font-family: var(--ui); font-size: 9.5px; letter-spacing: .06em; color: var(--faint);
}
.in-kind { text-transform: uppercase; letter-spacing: .12em; color: var(--text2); font-weight: 600; }
.in-src { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.in-when { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
.in-lag { color: var(--attn); margin-left: 6px; }
.in-title { display: block; color: var(--text); font-size: 13px; line-height: 1.35; text-decoration: none; }
a.in-title:hover { text-decoration: underline; }
.in-sum { color: var(--text2); font-size: 12px; line-height: 1.45; margin-top: 4px; }
.in-also { color: var(--faint); font-size: 10.5px; margin-top: 3px; }
/* Worth a second look: an 8-K that matters, a stake filing, a tripwire. */
.in-row.hot { box-shadow: inset 2px 0 0 var(--attn); padding-left: 10px; }
.in-row.k-move .in-kind { color: var(--attn); }
.in-row.fresh .in-title { font-weight: 600; }
.in-empty { padding: 10px 0; }
.in-sub {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; padding: 8px 0 4px; border-top: 1px solid var(--rule2);
  font-family: var(--ui); font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text2); font-weight: 600;
}
.in-sub span { font-family: var(--mono); color: var(--text); letter-spacing: 0; }
.in-sub em { font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--faint); font-size: 10.5px; }
/* Still readable, a step quieter than what is about the company. */
.in-mentions .in-title { color: var(--text2); font-size: 12.5px; }
.in-legend { display: grid; gap: 6px; margin: 12px 0 14px; }
.in-legend > div {
  display: grid; grid-template-columns: 110px 90px 1fr; gap: 12px; align-items: baseline;
  font-size: 12px; color: var(--text2); line-height: 1.4;
}
.in-legend b { color: var(--text); font-weight: 600; }
.in-legend .in-speed { font-family: var(--mono); font-size: 11px; color: var(--attn); }
/* Something new landed: the panel flashes once. */
.tile.ping { animation: inPing 1.6s ease-out 1; }
@keyframes inPing {
  0% { box-shadow: inset 0 0 0 2px var(--attn); }
  100% { box-shadow: inset 0 0 0 2px transparent; }
}

/* ================= live bar ================= */

.livebar {
  display: flex; align-items: center; gap: 16px;
  background: var(--black); color: var(--text2);
  border-bottom: 1px solid var(--rule);
  padding: 7px 13px; font-size: 10.5px;
  letter-spacing: .08em; text-transform: uppercase;
  position: sticky; top: 0; z-index: 20;
}
.livebar .grow { flex: 1; }
/* The ticker and price lead the bar and are the only things in it set at
   reading size -- everything else there is status, not information. The
   vertical rule after them is the page's own separator convention. */
.livebar .lbsym {
  font-family: var(--ui); font-size: 12px; font-weight: 700;
  letter-spacing: .16em; color: var(--text);
}
.livebar .lbprice {
  display: flex; align-items: baseline; gap: 9px;
  padding-right: 16px; margin-right: 2px;
  border-right: 1px solid var(--vline);
}
.livebar .lbprice b {
  font-family: var(--mono); font-size: 17px; font-weight: 500;
  color: var(--text); text-transform: none; letter-spacing: 0;
}
.livebar .lbprice > span {
  font-family: var(--mono); font-size: 11.5px; text-transform: none; letter-spacing: 0;
}
.livebar b { font-family: var(--mono); color: var(--text); text-transform: none; letter-spacing: 0; }
/* No outline on any of these. A border draws a box the eye has to read
   before the word inside it; the word is the control, and the pill only
   needs to appear under the cursor to say so. */
.livebar button {
  background: none; border: none; color: var(--faint);
  font-family: var(--ui); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 13px; cursor: pointer; border-radius: 999px;
  transition: background .12s ease, color .12s ease;
}
.livebar button:hover { background: var(--panel); color: var(--text); }
.livebar button.on { background: var(--text); color: var(--black); }
.livedot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--text); margin-right: 7px; vertical-align: middle; }
.livedot.off { background: var(--faint); }
.stale { color: var(--text); text-decoration: underline; }

/* ================= zoom ================= */

.overlay {
  position: fixed; inset: 0; z-index: 90; background: rgba(6, 6, 7, .9);
  display: flex; align-items: center; justify-content: center; padding: 24px;
  animation: fadeIn .14s ease both;
}
.zoom {
  background: var(--panel); border: 1px solid var(--rule2);
  border-radius: 18px; overflow: hidden;
  width: min(1240px, 94vw); height: min(92vh, 1000px);
  display: flex; flex-direction: column; cursor: auto;
}
.zoom > header {
  display: flex; align-items: baseline; gap: 16px;
  background: var(--black); border-bottom: 1px solid var(--rule2); padding: 13px 20px;
}
.zoom > header h2 { font-family: var(--mast); font-weight: 700; font-size: 21px; text-transform: none; letter-spacing: 0; }
.zoom > header .sub { font-size: 11px; color: var(--text2); text-transform: uppercase; letter-spacing: .1em; }
.zoom > header .grow { flex: 1; }
/* the price, carried into every close-up -- see zoomPrice() */
.zoom > header .zprice { display: flex; align-items: baseline; gap: 9px; margin-right: 16px; }
.zoom > header .zprice b { font-family: var(--mono); font-size: 19px; font-weight: 500; color: var(--text); }
.zoom > header .zprice > span { font-family: var(--mono); font-size: 12px; }
.zoom > header .zprice i {
  font-family: var(--ui); font-style: normal; font-size: 9.5px; font-weight: 700;
  letter-spacing: .14em; color: var(--faint);
  border-left: 1px solid var(--rule2); padding-left: 9px;
}
.zoom > header button {
  background: none; border: none; color: var(--faint);
  font-family: var(--ui); font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  padding: 7px 16px; cursor: pointer; border-radius: 999px;
  transition: background .12s ease, color .12s ease;
}
.zoom > header button:hover { background: var(--raised); color: var(--text); }
.zoom > .inner { flex: 1 1 auto; overflow-y: auto; padding: 20px 24px 26px; font-size: 14px; }
.zoom > .inner::-webkit-scrollbar { width: 8px; }
.zoom > .inner::-webkit-scrollbar-thumb { background: var(--rule2); }

.zoom .kv, .zoom .kv > span { font-size: 13.5px; }
.zoom .row { font-size: 12.5px; }
.zoom .figure { font-size: 50px; }
.zoom .prose { font-size: 15px; line-height: 1.7; }
.zoom .gk .say, .zoom .verdict { font-size: 14.5px; line-height: 1.68; }
.zoom .article .hl { font-size: 21px; }
.zoom .article .stand { font-size: 13.5px; }
.zoom .claim { font-size: 14px; }
.zoom .colset { column-count: 2; column-gap: 26px; column-rule: 1px solid var(--rule); }
.zoom h4 {
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--text);
  border-bottom: 1px solid var(--rule2); padding-bottom: 6px; margin: 22px 0 12px;
}
.zoom h4:first-child { margin-top: 0; }

.dstats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); margin-bottom: 14px; }
.dstats > div { background: var(--panel); padding: 10px 13px; }
.dstats span { display: block; font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); margin-bottom: 3px; }
.dstats b { font-family: var(--mono); font-size: 20px; font-weight: 500; color: var(--text); }

.dbar { display: grid; grid-template-columns: 190px 1fr 150px; gap: 12px; align-items: center; padding: 3px 0; }
.dbar-l { font-size: 12px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dbar-t { height: 11px; border: 1px solid var(--rule2); position: relative; }
.dbar-t i { position: absolute; inset: 0 auto 0 0; background: var(--text2); display: block; }
.dbar-t i.pos { background: var(--text); }
.dbar-t i.neg { background: var(--text); opacity: .45; }
.dbar-v { font-family: var(--mono); font-size: 11px; color: var(--text2); }

.rbar { margin: 12px 0 16px; }
.rbar-head, .rbar-foot { display: flex; justify-content: space-between; font-size: 10px; color: var(--faint); }
.rbar-head { text-transform: uppercase; letter-spacing: .1em; margin-bottom: 5px; }
.rbar-foot { font-family: var(--mono); margin-top: 4px; }
.rbar-t { height: 6px; border: 1px solid var(--rule2); position: relative; }
.rbar-t i { position: absolute; top: -5px; width: 2px; height: 14px; background: var(--text); transform: translateX(-50%); }

.dexp { padding: 9px 0; }
.dexp + .dexp { border-top: 1px solid var(--rule); }
.dexp-h { display: flex; justify-content: space-between; align-items: baseline; }
.dexp-h span { font-weight: 600; font-size: 12.5px; color: var(--text); }
.dexp-h b { font-family: var(--mono); font-size: 15px; }
.dexp-w { font-size: 12.5px; color: var(--text2); line-height: 1.55; }

.dstory { border-left: 1px solid var(--rule2); padding: 9px 0 9px 13px; margin-bottom: 12px; }
.dstory-h { display: flex; align-items: center; gap: 9px; margin-bottom: 5px; }
.dstory .hl { font-family: var(--mast); font-weight: 700; font-size: 17px; line-height: 1.25; }
.dstory .stand { font-size: 12.5px; color: var(--text2); }

.dmsg { padding: 9px 0; font-size: 13px; color: var(--text2); }
.dmsg + .dmsg { border-top: 1px solid var(--rule); }

.zoomchart { border: 1px solid var(--rule); margin-bottom: 4px; }

/* ================= misc ================= */

a { color: inherit; text-decoration: none; }
.link { color: var(--text); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--rule2); }
.link:hover { text-decoration-color: var(--text); }

.pill {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 9px;
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--rule2); color: var(--text2); margin-right: 6px;
}
.pill.good { background: var(--c-priced); color: var(--black); border-color: var(--c-priced); }
.pill.hot  { background: var(--attn); color: var(--black); border-color: var(--attn); }

.loading, .empty { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 72%; gap: 16px; color: var(--text2); }
.loading b { font-family: var(--mast); font-weight: 700; color: var(--text); }
.spinner { width: 22px; height: 22px; border: 1px solid var(--rule2); border-top-color: var(--text); border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.stage { font-size: 11px; color: var(--faint); text-transform: uppercase; letter-spacing: .1em; }

/* ================= motion =================
 * Only where it reports something: a panel opening, the story arrows drawing
 * their path, a value that just changed. Nothing decorative, nothing looping. */

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes drawIn { to { stroke-dashoffset: 0; } }
@keyframes flash { 0% { background: var(--rule2); } 100% { background: transparent; } }
.tile.flash { animation: flash 1s ease-out; }
.suggest div, .tile, .livebar button { transition: background .12s ease, color .12s ease, border-color .12s ease; }

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

/* ================= model tabs =================
 * Two ways to price the same contract, side by side. Two models agreeing is
 * information; two models disagreeing is more information -- it usually means
 * early exercise is worth something, which only the tree can see. */

.mtabs { display: flex; gap: 0; margin-bottom: 10px; border-bottom: 1px solid var(--rule); }
.mtabs button {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--faint); cursor: pointer;
  font-family: var(--ui); font-size: 10.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; padding: 7px 14px;
  transition: color .12s ease, border-color .12s ease;
}
.mtabs button:hover { color: var(--text2); }
.mtabs button.on { color: var(--text); border-bottom-color: var(--text); }
.mtabs .spacer { flex: 1; }
.mtabs .note { align-self: center; font-family: var(--mono); font-size: 10px; color: var(--faint); padding-right: 2px; }


/* ---- what is coming ----
   A date list that is read top to bottom once, so everything is on a
   fixed four-part grid: when, what, how far off, and why it matters.
   Estimated dates are drawn dashed, which is the same thing the top rule
   of a panel does elsewhere -- line weight is how this app says "lean on
   this less", and a calendar entry is no different. */
.evhead {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  padding: 13px 0 5px; border-bottom: 1px solid var(--rule); margin-bottom: 3px;
}
.evrow {
  display: grid; grid-template-columns: 76px 1fr auto;
  gap: 4px 10px; padding: 6px 0; align-items: baseline;
  border-bottom: 1px solid var(--hline);
}
.evd {
  font-family: var(--mono); font-size: 11.5px; color: var(--text);
  white-space: nowrap;
}
.evn { font-size: 12px; color: var(--text); }
.evx {
  font-family: var(--mono); font-size: 10.5px; color: var(--faint);
  white-space: nowrap; text-align: right;
}
/* The reason sits under the name, in the name's column, so the date
   column stays a clean edge to run an eye down. */
.evy {
  grid-column: 2 / -1; font-size: 10.5px; line-height: 1.5; color: var(--faint);
}

/* Not confirmed: the date is the estimate, so the date is what goes
   dashed, and the row says which kind of estimate it is in words. */
.evrow.est .evd {
  border-bottom: 1px dashed var(--rule2); color: var(--text2);
}
.evn em {
  font-style: normal; font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  margin-left: 7px; border-bottom: 1px dashed var(--rule2); cursor: help;
}
/* A company date outranks a market-wide one for a single stock. */
.evrow.company .evd, .evrow.company .evn { color: var(--text); font-weight: 600; }

.evflag {
  margin-top: 9px; padding: 9px 11px; background: var(--sunk);
  border-left: 2px solid var(--text);
  font-size: 11.5px; line-height: 1.55; color: var(--text2);
}
.evflag b { color: var(--text); font-weight: 600; }

.evfoot {
  padding-top: 11px; font-size: 10px; line-height: 1.5; color: var(--faint);
}


/* ---- one setup, opened up ----
   The card is a menu entry; this is the thing itself. Laid out in the
   order the questions arrive: what is it, what are the odds, what does it
   cost and pay, what am I actually buying, and what is it worth if the
   stock ends up somewhere. Nothing is revealed on hover -- a reader
   deciding whether to put money on something should not have to go
   looking for the terms. */
.pdhead {
  display: flex; align-items: flex-start; gap: 28px; flex-wrap: wrap;
  padding: 6px 0 18px; border-bottom: 1px solid var(--rule);
}
.pdname { flex: 1 1 320px; }
.pdname h4 {
  font-family: var(--ui); font-size: 19px; font-weight: 600;
  color: var(--text); letter-spacing: -.01em;
}
.pdview {
  margin-top: 6px; max-width: 62ch;
  font-size: 12.5px; line-height: 1.6; color: var(--text2);
}

/* The odds, said once, properly. The number was the confusing part of the
   card -- "40 in 100" is a percentage wearing a hat -- so it is a
   percentage here with the sentence that defines it sitting underneath
   rather than hidden in a tooltip. */
.pdodds { flex: 0 0 auto; max-width: 260px; text-align: right; }
.pdodds b {
  display: block; font-family: var(--mono); font-size: 40px; font-weight: 400;
  line-height: 1; color: var(--text);
}
.pdodds span {
  display: block; margin-top: 5px;
  font-family: var(--ui); font-size: 9.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.pdodds em {
  display: block; margin-top: 8px; font-style: normal;
  font-size: 10.5px; line-height: 1.5; color: var(--faint);
}

.pdgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; background: var(--rule); margin: 1px 0 0;
}
.pdbox { background: var(--panel); padding: 13px 15px; }
.pdlab {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.pdnum {
  margin-top: 5px; font-family: var(--mono); font-size: 16px; color: var(--text);
}

.pdsec {
  padding: 20px 0 8px;
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}

/* Each leg on its own, with the reason that strike was picked. The
   reason is the part a ready-made setup normally hides, and it is the
   only part that teaches you anything. */
.pdleg {
  display: grid; grid-template-columns: 1fr auto; gap: 3px 16px;
  padding: 10px 0; border-bottom: 1px solid var(--hline);
}
.pdlt { font-size: 13px; color: var(--text); }
.pdlc { font-family: var(--mono); font-size: 13px; color: var(--text); text-align: right; }
.pdlw {
  grid-column: 1 / -1; max-width: 76ch;
  font-size: 11px; line-height: 1.55; color: var(--faint);
}

.pdcurve {
  display: block; width: 100%; height: 110px; margin-top: 4px;
  background: var(--sunk);
}
.pdline { fill: none; stroke: var(--text); stroke-width: 1.6; }
.pdzero { stroke: var(--rule2); stroke-width: 1; }
.pdbe { stroke: var(--rule2); stroke-width: 1; stroke-dasharray: 2 3; }
.pdaxis {
  display: flex; justify-content: space-between; padding: 5px 1px 0;
  font-family: var(--mono); font-size: 9.5px; color: var(--faint);
}

/* The same curve as arithmetic, for people who do not read charts -- and
   as a check for people who do that they read it the right way round. */
.pdscen {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px; background: var(--rule); margin-top: 14px;
}
.pdsrow {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--panel); padding: 9px 10px;
}
.pdsrow.win { background: var(--raised); }
.pdsm {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .1em; color: var(--faint);
}
.pdsp { font-family: var(--mono); font-size: 11px; color: var(--text2); }
.pdsv { font-family: var(--mono); font-size: 13px; color: var(--text); }
.pdsrow:not(.win) .pdsv { color: var(--text2); }

.pduse {
  margin-top: 20px; width: 100%; cursor: pointer; border: none;
  background: var(--text); color: var(--black);
  font-family: var(--ui); font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 14px 18px; border-radius: 3px;
  transition: opacity .12s ease;
}
.pduse:hover { opacity: .86; }

.prenote {
  padding: 12px 1px 0; max-width: 82ch;
  font-size: 10.5px; line-height: 1.6; color: var(--faint);
}
.prenote b { color: var(--text2); }


/* ---- citations ----
   The source sits under every row rather than once at the bottom,
   because the rows do not all come from the same place and the
   difference matters: "the Fed published this" and "projected from four
   previous payments" are not the same claim and should not look it. */
.evrow { grid-template-columns: 76px 1fr auto; }
.evc {
  grid-column: 2 / -1; padding-top: 2px;
  font-family: var(--ui); font-size: 9px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--rule2);
}
.evc a { color: var(--faint); text-decoration: none; border-bottom: 1px solid var(--rule); }
.evc a:hover { color: var(--text); border-bottom-color: var(--text); }

.evsrc { margin-top: 6px; }
.evsrow {
  display: flex; gap: 10px; align-items: baseline;
  padding: 5px 0; border-bottom: 1px solid var(--hline);
  font-size: 11px; color: var(--faint);
}
.evsrow a {
  flex: 0 0 auto; min-width: 158px;
  color: var(--text2); text-decoration: none; font-weight: 500;
}
.evsrow a:hover { color: var(--text); }


/* ---- the money ----
   The first thing on the page and deliberately the loudest. Three
   columns in the order the cash actually moves: out (or in) today, then
   the two ends of where it can finish. The worst case is given the same
   size as the best one -- shrinking it would be a lie told by layout. */
.mny { margin: 4px 0 22px; }

.mnyneed {
  display: flex; align-items: baseline; gap: 12px;
  padding: 0 0 14px;
}
.mnyarrow {
  font-family: var(--mono); font-size: 22px; line-height: 1; color: var(--text);
}
.mnytext { font-size: 16px; line-height: 1.45; color: var(--text2); }
.mnytext b { color: var(--text); font-weight: 600; }
.mnytext i { font-style: normal; color: var(--faint); }

.mnygrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1px; background: var(--rule);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.mnycol { background: var(--panel); padding: 16px 18px 18px; }
.mnycol.today { background: var(--raised); }

.mnylab {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.mnybig {
  margin-top: 8px; font-family: var(--mono); font-size: 30px; font-weight: 400;
  line-height: 1; color: var(--text); letter-spacing: -.01em;
}
.mnywhy {
  margin-top: 10px; font-size: 11px; line-height: 1.55; color: var(--faint);
  max-width: 40ch;
}

.mnyratio {
  padding: 11px 1px 0; font-size: 12px; color: var(--text2);
}
.mnyratio b { color: var(--text); font-family: var(--mono); }


/* ---- the accounts ----
   A financial statement is a table and has been for five hundred years.
   Label on the left, one column per period, figures right-aligned in
   tabular figures so the magnitudes line up and a missing digit is
   visible as a gap rather than as a slightly shorter number. */
.ftab { display: table; width: 100%; border-collapse: collapse; }
.fr {
  display: grid; align-items: baseline;
  grid-template-columns: minmax(130px, 1.6fr) repeat(auto-fit, minmax(58px, 1fr));
  border-bottom: 1px solid var(--hline);
}
.fr.fhead { border-bottom: 1px solid var(--rule); }
.fr.fgap { height: 9px; border: none; }

.fl {
  font-size: 11.5px; color: var(--text2); padding: 6px 8px 6px 0;
}
.fhead .fl, .fhead .fv {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  padding-bottom: 6px;
}
.fv {
  font-family: var(--mono); font-size: 11.5px; color: var(--text);
  text-align: right; padding: 6px 0; font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fhead .fv { color: var(--text2); }

.fsub {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  padding: 16px 0 6px;
}

/* The link back to the document. The point of the whole panel. */
.fcite { display: flex; flex-wrap: wrap; gap: 6px 14px; padding: 11px 0 0; }
.fcite a {
  font-family: var(--ui); font-size: 9px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  text-decoration: none; border-bottom: 1px solid var(--rule);
}
.fcite a:hover { color: var(--text); border-bottom-color: var(--text); }

.fnote {
  padding-top: 9px; max-width: 76ch;
  font-size: 10.5px; line-height: 1.55; color: var(--faint);
}
.fnote b { color: var(--text2); font-family: var(--mono); font-size: 10px; }

/* A figure the app worked out because the filer did not tag it. Marked
   in the label rather than the number, so the column of figures stays a
   clean column of figures. */
.fdrv {
  font-style: normal; font-family: var(--ui); font-size: 8px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
  margin-left: 7px; border-bottom: 1px dashed var(--rule2); cursor: help;
}

/* ---- the fork ----
   Two jobs that were sharing one screen. Building a spread leg by leg
   and picking one off a menu want opposite things, so they are asked
   for once, up front, and then you are in one of them.

   The animation is doing a job rather than decorating: the card you
   did not pick collapses and the one you did slides to the middle and
   opens into what it was describing, so the grid that appears is
   visibly the same object you clicked rather than a new screen. */
.routewrap {
  min-height: 62vh; display: flex; align-items: center; justify-content: center;
  padding: 24px 20px;
}
.routes {
  display: grid; grid-template-columns: 1fr 1fr; gap: 18px;
  width: min(880px, 100%);
  transition: grid-template-columns .42s cubic-bezier(.4, 0, .2, 1),
              gap .42s cubic-bezier(.4, 0, .2, 1),
              width .42s cubic-bezier(.4, 0, .2, 1);
}
.route {
  display: flex; flex-direction: column; gap: 9px; text-align: left;
  background: var(--panel); border: none; cursor: pointer;
  border-radius: 4px; padding: 26px 26px 22px;
  font-family: var(--ui); color: var(--text2);
  transition: background .16s ease, opacity .34s ease,
              transform .42s cubic-bezier(.4, 0, .2, 1);
}
.route:hover { background: var(--raised); }
.rk { font-size: 17px; font-weight: 600; color: var(--text); }
.rd { font-size: 12.5px; line-height: 1.6; max-width: 42ch; }
.rg {
  margin-top: 4px; font-size: 9px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint);
}

/* Chosen: the other one folds away, this one takes the middle. The
   collapsing card keeps `visibility` until the end so it fades rather
   than vanishing on the first frame. */
.routes.picked { grid-template-columns: 1fr; width: min(560px, 100%); gap: 0; }
.routes.picked .route { pointer-events: none; }
.routes.to-custom .route[data-route="ready"],
.routes.to-ready .route[data-route="custom"] {
  opacity: 0; transform: scale(.96); grid-row: 1; grid-column: 1;
}
.routes.to-custom .route[data-route="custom"],
.routes.to-ready .route[data-route="ready"] {
  grid-row: 1; grid-column: 1; background: var(--raised);
}

/* The other two routes fold away the same way when one of them is picked. */
.routes.to-target .route:not([data-route="target"]),
.routes.to-auto .route:not([data-route="auto"]) {
  opacity: 0; transform: scale(.96); grid-row: 1; grid-column: 1;
}
.routes.to-target .route[data-route="target"],
.routes.to-auto .route[data-route="auto"] {
  grid-row: 1; grid-column: 1; background: var(--raised);
}

/* Where you are, and the one word back to the other side. */
.routebar {
  display: flex; align-items: baseline; gap: 14px;
  max-width: 1320px; margin: 0 auto; padding: 14px 16px 0;
}
.rbnow {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text2);
}

/* The setups arriving. Same easing as the card that opened into them,
   so it reads as one movement. */
.readywrap .pregrid, .readywrap .expbar { animation: routein .34s ease both; }
.readywrap .pregrid { animation-delay: .04s; }
@keyframes routein {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

@media (max-width: 760px) {
  .routes { grid-template-columns: 1fr; }
}

/* ---- the calendar's two sides ----
   One panel switched between rather than two panels stacked: the packer
   could otherwise land them on opposite sides of the page, and comparing
   "earnings on the 29th" with "Fed on the 28th" then meant holding one
   in your head while you went and found the other. */
.calseg {
  display: flex; gap: 2px; margin-bottom: 4px;
  border-bottom: 1px solid var(--rule);
}
.calseg button {
  background: none; border: none; cursor: pointer;
  padding: 7px 13px 8px; margin-bottom: -1px;
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  border-bottom: 1px solid transparent; transition: color .12s ease;
}
.calseg button:hover { color: var(--text2); }
.calseg button.on { color: var(--text); border-bottom-color: var(--text); }

/* A filing that has already happened. Dimmer than a date still ahead --
   it is context for the forward dates, not one of them. */
.evrow.filed .evd { color: var(--text2); }
.evrow.filed .evn { color: var(--text2); }
.evrow.filed.w3 .evn { color: var(--text); }
.evform {
  font-family: var(--mono); font-size: 10px; font-weight: 600;
  color: var(--faint); margin-right: 6px;
}
.evrow.filed.w3 .evform { color: var(--text); }
.evitem {
  font-style: normal; font-family: var(--mono); font-size: 9.5px;
  color: var(--rule2); margin-right: 2px;
}

/* ---- what the indicator reads ----
   A line crossing 70 means nothing unless you know what 70 is, and the
   argument of this whole app is that a number should arrive with its
   interpretation attached rather than assume the reader brings one. */
.indnote {
  padding: 7px 2px 0; max-width: 92ch;
  font-size: 11.5px; line-height: 1.6; color: var(--text2);
}
.indnote:empty { display: none; }
.indnote b { color: var(--text); font-family: var(--mono); }
.indname {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
  margin-right: 8px;
}
.inddef { display: block; margin-top: 3px; font-size: 10.5px; color: var(--faint); }

/* A second reading under the first, ruled off so they do not read as
   one run-on sentence about two different things. */
.indsplit {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--hline);
}


/* A dot on the button in the line's own colour, so the mapping between
   the control and the mark on the chart is visible rather than learned. */
.cseg button .swatch {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  margin-right: 5px; vertical-align: 1px;
}
.cseg button.off-range { opacity: .45; }


/* ---- the trade log ----
   Where both routes end. A table because a log is a table: ticker,
   what it is, what it is doing, how long is left. Sorted by nothing
   clever -- newest first, which is the order they were opened in. */
.bookbar {
  display: flex; align-items: baseline; gap: 14px;
  max-width: 1100px; margin: 0 auto; padding: 22px 16px 12px;
}
.bookbar h2 {
  font-family: var(--ui); font-size: 19px; font-weight: 600; color: var(--text);
}
.bookn {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.bookadd {
  background: var(--text); color: var(--black); border: none; cursor: pointer;
  border-radius: 3px; padding: 9px 16px;
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  transition: opacity .12s ease;
}

.booklist {
  max-width: 1100px; margin: 0 auto; padding: 0 16px;
  border-top: 1px solid var(--rule);
}
.bookrow {
  display: grid; width: 100%; text-align: left; align-items: baseline;
  grid-template-columns: 76px 1fr 110px 74px 96px;
  gap: 12px; padding: 13px 4px;
  background: none; border: none; border-bottom: 1px solid var(--hline);
  cursor: pointer; font-family: var(--ui); color: var(--text2);
  transition: background .12s ease;
}
.bookrow:hover { background: var(--panel); }
.bookrow.bhead {
  cursor: default; padding: 7px 4px; border-bottom: 1px solid var(--rule);
  font-size: 8.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint);
}
.bookrow.bhead:hover { background: none; }
.bookrow.shut { opacity: .5; }

.bsym {
  font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--text);
}
.bname { font-size: 13px; color: var(--text); }
.bname i {
  display: block; margin-top: 3px; font-style: normal;
  font-size: 10.5px; color: var(--faint);
}
.bpl, .bpct, .bdays {
  font-family: var(--mono); font-size: 13.5px; text-align: right;
  font-variant-numeric: tabular-nums;
}
.bpct { font-size: 12px; }
.bpl.up, .bpct.up { color: var(--pos); }
.bpl.down, .bpct.down { color: var(--neg); }

/* Two totals side by side, because they are two different facts: one
   moves every time the market does, the other never will again. A
   single combined figure hides which is which, so the sum only shows
   next to the pair it is made from. */
.booktots {
  max-width: 1100px; margin: 0 auto; padding: 16px 20px 4px;
  display: grid; gap: 1px; background: var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.btot { background: var(--panel); padding: 12px 16px 14px; }
.btl {
  display: block; font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.btot b {
  display: block; margin-top: 6px;
  font-family: var(--mono); font-size: 22px; font-weight: 400; color: var(--text);
}
.btot.up b { color: var(--pos); }
.btot.down b { color: var(--neg); }
.btot.up b::before, .btot.down b::before { content: none; margin: 0; }
.btn2 { display: block; margin-top: 5px; font-size: 10.5px; color: var(--faint); }

.bookhead {
  max-width: 1100px; margin: 0 auto; padding: 26px 20px 6px;
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}

/* The end of both routes. */
.commitbar {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin-top: 22px; padding: 16px 0 0; border-top: 1px solid var(--rule);
}
.cmsg { flex: 1 1 320px; font-size: 11px; line-height: 1.55; color: var(--faint); }
.bookclose {
  background: none; border: none; cursor: pointer; padding: 9px 14px;
  font-family: var(--ui); font-size: 10px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  box-shadow: inset 0 0 0 1px var(--rule); border-radius: 3px;
}
.bookclose:hover { color: var(--text); box-shadow: inset 0 0 0 1px var(--rule2); }


/* ---- the rest of the hints ----
   Each one names a fact that is already stated in words somewhere
   nearby. None of them is the only way to read anything. */

/* The two ends of a trade. Best and worst are opposite outcomes and the
   panel exists to make that obvious -- but only the rule is tinted, not
   the figure, so the column of numbers stays one colour to read down. */
.mnycol.best  { box-shadow: inset 0 2px 0 var(--pos); }
.mnycol.worst { box-shadow: inset 0 2px 0 var(--neg); }

/* A scheduled event that can move the whole market, against one that
   cannot. The weight is in the panel text either way. */
.evrow.company .evd { color: var(--c-filed); }
.evrow.est .evd { color: var(--c-derived); }
.evrow.filed.w3 .evform { color: var(--c-claimed); }

/* Cheap or dear against the reference, on the option board. The sign is
   already printed in front of the number. */
.q.edge.dear  { color: var(--neg); }
.q.edge.cheap { color: var(--pos); }

/* A leg you hold, on the board and in the chips. */
.pos.l { background: var(--pos); color: var(--black); }
.pos.s { box-shadow: inset 0 0 0 1px var(--neg); color: var(--neg); }

/* The odds on a ready-made setup: the number is right there, this is
   only so a row of eleven cards can be scanned rather than read. */
.pcard .odds b { color: var(--text); }
.pdodds b { color: var(--text); }

/* Profit and loss wherever it is stated as a figure. */
.pstat b.up { color: var(--pos); }
.pstat b.down { color: var(--neg); }
.pleg span.up { color: var(--pos); }
.pleg span.down { color: var(--neg); }
.pdsrow.win .pdsv { color: var(--pos); }
.pdsrow:not(.win) .pdsv { color: var(--neg); }

/* The payoff curve's break-even line, and the profitable side of it. */
.pdline { stroke: var(--text); }
.pdzero { stroke: var(--rule2); }

/* ---- the three other rooms ----
   The front page was a search field and two sentences, and the
   sentences were doing too much: "I am already in a trade" is a mood,
   not a destination. Naming the places is shorter and says where each
   one goes.

   Kept at label size and unoutlined, like everything else on this
   page, because the search field is still the point of it. The log
   carries a count only when there is something in it -- the one thing
   a door can usefully tell you before you walk through. */
.doors {
  display: flex; gap: 6px; flex-wrap: wrap; justify-content: center;
  margin-top: 4px;
}
.door {
  display: flex; flex-direction: column; gap: 3px; align-items: center;
  background: none; border: none; cursor: pointer;
  padding: 11px 22px; border-radius: 10px;
  transition: background .14s ease;
}
.door:hover { background: var(--panel); }
.dn {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--ui); font-size: 12.5px; font-weight: 600; color: var(--text2);
  transition: color .14s ease;
}
.door:hover .dn { color: var(--text); }
.dw {
  font-family: var(--ui); font-size: 10px; color: var(--faint);
  letter-spacing: .02em;
}
.dcount {
  font-style: normal; font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  background: var(--c-priced); color: var(--black);
  padding: 0 5px; border-radius: 999px; line-height: 15px;
}

/* ---- back and forward ----
   One pair, acting on whichever tab is in front. The trail belongs to
   the tab, so switching tabs switches history with it. */
.navpair {
  display: flex; align-items: stretch; gap: 1px;
  background: var(--black); -webkit-app-region: no-drag;
}
.navb {
  background: none; border: none; cursor: pointer;
  padding: 0 9px; font-size: 17px; line-height: 1; color: var(--rule2);
  transition: color .12s ease;
}
.navb:hover:not(:disabled) { color: var(--text); }
.navb:disabled { color: var(--rule); cursor: default; }


/* ---- the rest of the site ----
   Same rule throughout: a hue only where it names something the page
   already states in words, so nothing here is the only way to read
   anything. Everything stays desaturated -- the point is a page that
   can be scanned, not a page that shouts. */

/* THE LIVE BAR. The price and its move, pinned to the top of every
   panel-grid, which is the one number always on screen. */
.livebar .lbprice > span.up { color: var(--pos); }
.livebar .lbprice > span.down { color: var(--neg); }

/* THE REGION RAIL. Where you are in the document, which is a place and
   not a judgement -- so the marker takes the FILED blue, the same hue
   the app uses for "this is on the record", rather than a verdict hue. */
.rail button.on { color: var(--text); }
.rail button.on::before { background: var(--c-filed); }

/* THE FINDER. A ranked table is read down one column, so only the
   number that decides the ranking is tinted, and only by direction. */
.frow .fv.up { color: var(--pos); }
.frow .fv.down { color: var(--neg); }
.frow .fwhy em:first-child { color: var(--text); }

/* THE OPTION BOARD. In-the-money shading stays a wash rather than a
   hue: it covers half the board, and half a board of colour is a
   background, not a signal. The spot marker gets the line, because it
   is the one thing on the board that moves. */
/* The share price across the board. Blue, not green: this line is
   where the stock IS, which is a fact and not a gain -- in green it
   read as profit, which is the page editorialising about a number
   that has no opinion in it. */
.spotrow { border-top-color: var(--c-filed); }
.spotrow span { color: var(--c-filed); }
.spotrow span::before { background: var(--c-filed); }

/* THE CALENDAR. An event that can move the whole market against one
   that cannot -- said in the panel text either way. */
.evrow.w3 .evd, .evrow .evn em { color: var(--attn); }

/* THE VOLATILITY PANEL and anywhere else stating rich or cheap. */
.rich, .expensive { color: var(--neg); }
.cheap, .inexpensive { color: var(--pos); }

/* THE SETUP CARDS. The odds are the number being compared across
   eleven cards, so the eye needs somewhere to land -- but the reading
   is a probability, not a verdict, and colouring 70% green would be
   the app calling it the better trade when it is only the likelier
   one. Left alone deliberately. */

/* THE GLOSSARY. A term you can hover is a different kind of word from
   the ones around it. */
.term { border-bottom-color: var(--c-derived); }

/* LOADING. The one moving thing on the page. */
.spinner { border-top-color: var(--c-filed); }

/* THE COMMIT BAR, which is the end of both routes. */
.bookadd { background: var(--c-priced); color: var(--black); }
.bookadd:hover { opacity: .88; }

/* THE POSITION CHART. Profit above the line, loss below it. */
.poschart .qc-pos { fill: var(--pos); }
.poschart .qc-neg { fill: var(--neg); }

/* The triangle is the primary carrier of direction and the colour is the
   echo -- but several of these numbers already print their own + or -,
   and a row reading "▲ +12%" says it three times. Where the sign is in
   the text, the glyph steps aside and the hue does the echoing. */
.fv.up::before, .fv.down::before,
.bpl.up::before, .bpl.down::before,
.bpct.up::before, .bpct.down::before,
.pstat b.up::before, .pstat b.down::before,
.pleg span.up::before, .pleg span.down::before,
.pdsv.up::before, .pdsv.down::before,
.booktot.up b::before, .booktot.down b::before { content: none; margin: 0; }

/* .warn sits inside a key-value row, and `.kv > span:last-child` is the
   more specific selector, so the plain class never landed. */
.kv > span.warn, span.warn { color: var(--attn); }

/* The actionable half of a definition. Ruled off and led with a label,
   because "what it means" and "what to do with it" are different
   questions and running them together makes both easier to skim past. */
.termtip .use {
  margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--rule);
  font-size: 11.5px; line-height: 1.55; color: var(--text2);
}
.termtip .use b {
  display: block; margin-bottom: 3px;
  font-size: 8.5px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--c-priced);
}

/* A row and the action belonging to it. Quiet until the row is under
   the cursor: a button saying "close" sitting bright on every line
   invites exactly the accident it names. */
.bookitem { position: relative; }
.brow-act {
  position: absolute; right: 8px; top: 24px; transform: translateY(-50%);
  background: var(--panel); border: none; cursor: pointer;
  padding: 5px 11px; border-radius: 3px;
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
  opacity: 0; transition: opacity .12s ease, color .12s ease;
  box-shadow: inset 0 0 0 1px var(--rule);
}
.bookitem:hover .brow-act { opacity: 1; }
.brow-act:hover { color: var(--text); box-shadow: inset 0 0 0 1px var(--rule2); }
.bookitem.closing .brow-act { display: none; }

/* The one question the app cannot answer for itself. */
.closeform {
  background: var(--sunk); padding: 14px 18px 16px;
  border-bottom: 1px solid var(--hline);
}
.cfq { font-size: 12.5px; color: var(--text); margin-bottom: 11px; }
.cfrow {
  display: grid; grid-template-columns: 130px 150px 1fr;
  gap: 12px; align-items: center; margin-bottom: 8px;
}
.cfl {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.closeform input {
  background: var(--panel); border: none; border-radius: 3px;
  color: var(--text); font-family: var(--mono); font-size: 14px;
  padding: 8px 11px; width: 100%; outline: none;
}
.closeform input:focus { box-shadow: inset 0 0 0 1px var(--c-priced); }
.cfv { font-family: var(--mono); font-size: 13px; color: var(--text2); }
.cfhint { font-size: 10.5px; color: var(--faint); }
.cfact { margin-top: 12px; margin-bottom: 0; }
.cfact .bookadd, .cfact .bookclose { justify-self: start; }

/* ---- what is inside a fund ----
   A list you read down and click into. Ticker on a fixed left edge so
   the eye can run the column; weight right-aligned in tabular figures
   so the big positions stand out by shape before you read a number. */
.hsect { padding: 4px 0 12px; }
.hsrow {
  display: grid; grid-template-columns: 132px 1fr 46px;
  gap: 10px; align-items: center; padding: 3px 0;
}
.hsn { font-size: 11px; color: var(--text2); text-transform: capitalize; }
.hsbar { height: 4px; background: var(--sunk); border-radius: 2px; overflow: hidden; }
.hsbar i { display: block; height: 100%; background: var(--c-filed); }
.hsv {
  font-family: var(--mono); font-size: 10.5px; color: var(--faint); text-align: right;
}

.hlist { border-top: 1px solid var(--rule); }
.hrow {
  display: grid; width: 100%; text-align: left;
  grid-template-columns: 62px 1fr 60px; gap: 10px; align-items: baseline;
  background: none; border: none; border-bottom: 1px solid var(--hline);
  padding: 6px 2px; cursor: pointer; font-family: var(--ui);
  transition: background .1s ease;
}
.hrow:hover { background: var(--raised); }
.hrow .hsym {
  font-family: var(--mono); font-size: 11.5px; font-weight: 600; color: var(--text);
}
.hrow .hname {
  font-size: 11px; color: var(--text2); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.hrow .hw {
  font-family: var(--mono); font-size: 11px; color: var(--text2);
  text-align: right; font-variant-numeric: tabular-nums;
}
.hrow:hover .hname, .hrow:hover .hw { color: var(--text); }
.hmore {
  padding: 8px 2px 0; font-size: 10.5px; color: var(--faint);
}

/* ---- a number with a derivation behind it ----
   Marked, not shouted. A dotted underline in the DERIVED colour, the
   same hue the evidence classes already use for "this was computed",
   so the mark means the same thing wherever it appears. Only numbers
   this app worked out are marked -- a quoted price has no arithmetic
   and marking it would promise something and then waste the hover. */
.calc {
  border-bottom: 1px dotted var(--c-derived);
  cursor: help;
}
.calc:hover { color: var(--text); border-bottom-style: solid; }

.calctip {
  position: fixed; left: 0; top: 0; z-index: 200;
  width: 420px; max-width: calc(100vw - 20px);
  background: var(--panel); border: 1px solid var(--c-derived);
  padding: 12px 14px 13px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .65);
  /* No animation and no transition, for the same reason the glossary
     tip has none: a running one overrides the inline transform this is
     positioned by, and under a throttled compositor it never advances. */
}
.calctip h6 {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  margin: 0 0 9px; padding-bottom: 7px; border-bottom: 1px solid var(--rule);
}

/* The sum. One row per line, sign in its own narrow column so the
   operators stack and it reads down as arithmetic rather than across
   as prose. */
.wrow {
  display: grid; grid-template-columns: 16px 1fr auto;
  gap: 8px; align-items: baseline; padding: 3px 0;
}
.wsign {
  font-family: var(--mono); font-size: 13px; color: var(--text2); text-align: center;
}
.wterms { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; }
.wt { display: inline-flex; align-items: baseline; gap: 5px; }
.wt i {
  font-style: normal; font-size: 11px; color: var(--text2);
}
.wt b {
  font-family: var(--mono); font-size: 12.5px; font-weight: 500; color: var(--text);
}
.wop { font-family: var(--mono); font-size: 11px; color: var(--faint); }
.wgives {
  font-family: var(--mono); font-size: 11.5px; color: var(--faint);
  text-align: right; white-space: nowrap;
}
.wrow.wtotal {
  margin-top: 5px; padding-top: 7px; border-top: 1px solid var(--rule);
}
.wrow.wtotal .wterms {
  font-family: var(--mono); font-size: 15px; color: var(--text);
}
.wrow.wx100 .wgives { color: var(--text); font-size: 13px; }
.wrow.wfloor .wterms i { color: var(--faint); }

.wnote {
  margin-top: 7px; font-size: 10.5px; line-height: 1.5; color: var(--faint);
}
.wnote b { color: var(--text2); font-weight: 500; }
.wfoot {
  margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--hline);
  font-size: 10.5px; line-height: 1.5; color: var(--faint);
}


/* Implied against realised, per strike. Same washed-out pair the rest
   of the board uses for dear and cheap, and the sign is printed in
   front of the number so the colour is never the only cue. */
.q.ivhv.dear  { color: var(--neg); }
.q.ivhv.cheap { color: var(--pos); }
.q.ivhv.flat  { color: var(--rule2); }


/* ---- size, and the sums written out ----
   The position workspace states what a trade costs and what it can do.
   Two things were missing from it: any way to say how much of it you
   want, and the arithmetic behind the three figures it puts in the
   largest type on the page. */

.mnysize {
  display: flex; align-items: center; gap: 8px;
  padding: 0 0 14px;
}
.mszlab {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}
.mszbtn {
  width: 26px; height: 26px; padding: 0;
  background: var(--raised); color: var(--text2);
  border: 1px solid var(--rule); border-radius: 2px;
  font-family: var(--mono); font-size: 14px; line-height: 1; cursor: pointer;
}
.mszbtn:hover { background: var(--panel); color: var(--text); border-color: var(--rule2); }
.mszin {
  width: 58px; height: 26px; text-align: center;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--rule2); border-radius: 2px;
  font-family: var(--mono); font-size: 14px;
}
.mszin:focus { outline: none; border-color: var(--text2); }
.mszhint { font-size: 11px; color: var(--faint); }
.mszhint b { color: var(--text2); font-family: var(--mono); }

/* What is actually being bought, in the words an order would use. */
.mnywhat { padding: 0 0 12px; }
.mnylegs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.mnyleg {
  font-family: var(--mono); font-size: 13px; color: var(--text2);
  background: var(--raised); border: 1px solid var(--rule);
  border-radius: 2px; padding: 4px 9px;
}
.mnyleg b { color: var(--text); font-weight: 600; }
.mnyleg i { font-style: normal; color: var(--faint); font-size: 11px; }
.mnyleg.long  { border-left: 2px solid var(--pos); }
.mnyleg.short { border-left: 2px solid var(--neg); }

/* Four columns is one too many to wrap gracefully at the old minimum. */
.mnygrid.four { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

.mnymath { margin-top: 14px; }
.mnymath > summary {
  cursor: pointer; list-style: none;
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  padding: 4px 0;
}
.mnymath > summary::-webkit-details-marker { display: none; }
.mnymath > summary::before { content: "− "; font-family: var(--mono); }
.mnymath:not([open]) > summary::before { content: "+ "; }
.mnymath > summary:hover { color: var(--text2); }
.mnymathgrid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px; background: var(--rule);
  border: 1px solid var(--rule); margin-top: 6px;
}
.mnymathpane { background: var(--panel); padding: 12px 14px 14px; }
.mnymathpane h6 {
  margin: 0 0 8px; font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
/* Inside a pane the sum is the content, not a tooltip, so it gets room. */
.mnymathpane .wcalc { font-size: 12px; }

/* The sum behind a step's headline figure, folded away by default:
   the steps are a narrative, and three open sums between each
   paragraph would break the thread they are there to carry. */
.sworking { margin-top: 9px; }
.sworking > summary {
  cursor: pointer; list-style: none;
  font-size: 10.5px; color: var(--faint); padding: 2px 0;
}
.sworking > summary::-webkit-details-marker { display: none; }
.sworking > summary::before { content: "+ "; font-family: var(--mono); }
.sworking[open] > summary::before { content: "− "; }
.sworking > summary:hover { color: var(--text2); }


/* ---- which way a position leans ----
   Read off the payoff by the engine rather than off the name of the
   structure. The word alone is not enough: "bullish" covers a long call
   that needs a six percent rise and a cash-secured put that needs the
   price not to fall four, so the chip says whether it NEEDS the move or
   merely HOLDS a level. Colour is never the only carrier -- there is an
   arrow and a word in every one of these. */

.bias {
  display: inline-flex; align-items: baseline; gap: 5px; margin-left: 8px;
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--rule); color: var(--faint);
  white-space: nowrap; vertical-align: middle;
}
.bias i { font-style: normal; font-family: var(--mono); font-size: 11px; }
.bias em { font-style: normal; opacity: .6; letter-spacing: .08em; }
.bias.b-bullish { color: var(--pos); border-color: color-mix(in srgb, var(--pos) 35%, transparent); }
.bias.b-bearish { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 35%, transparent); }
.bias.b-neutral { color: var(--text2); border-color: var(--rule2); }
.bias.b-either  { color: var(--text2); border-color: var(--rule2); }
.bias.big { font-size: 9.5px; padding: 3px 9px; }

/* The card edge repeats it, so the grid sorts itself by eye. */
.pcard.lean-bullish { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--pos) 55%, transparent); }
.pcard.lean-bearish { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--neg) 55%, transparent); }
.pcard.lean-neutral,
.pcard.lean-either  { box-shadow: inset 2px 0 0 var(--rule2); }

/* ---- what you want to happen, and how far ---- */
.mnyhope { padding: 0 0 16px; }
.mnyhead { display: flex; align-items: center; gap: 10px; }
.mnywant { font-size: 17px; line-height: 1.35; color: var(--text2); }
.mnywant b { color: var(--text); font-weight: 600; }
.mnyhope .mnyarrow { font-size: 20px; line-height: 1; }
.mnyhope.lean-bullish .mnyarrow { color: var(--pos); }
.mnyhope.lean-bearish .mnyarrow { color: var(--neg); }
.mnyhope.lean-neutral .mnyarrow,
.mnyhope.lean-either  .mnyarrow { color: var(--text2); }
.mnyfrom { margin-top: 3px; font-size: 11.5px; color: var(--faint); }
.mnyfrom b { color: var(--text2); font-family: var(--mono); }

.mnysteps { list-style: none; margin: 11px 0 0; padding: 0; }
.mnysteps li {
  display: grid; grid-template-columns: 132px 92px 62px 1fr;
  align-items: baseline; gap: 8px;
  padding: 5px 0; border-top: 1px solid var(--hline);
}
.mslab {
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--faint);
}
.msval { font-family: var(--mono); font-size: 14px; color: var(--text); }
.mspct { font-family: var(--mono); font-size: 11.5px; color: var(--faint); }
.mspct.up { color: var(--pos); }
.mspct.down { color: var(--neg); }
.msnote { font-size: 11px; color: var(--faint); }

@media (max-width: 760px) {
  .mnysteps li { grid-template-columns: 1fr auto; }
  .mnysteps .msnote { grid-column: 1 / -1; }
}

/* ---- a deadline in the trade log ----
   An option that expires this week is the one thing in a log that has a
   clock on it: miss it and the position settles itself at whatever the
   price happens to be. It used to print "2 sessions" in the same grey as
   everything else on the row. */
.bookitem { position: relative; }
.bookitem.exp-soon  { box-shadow: inset 3px 0 0 var(--warn); }
.bookitem.exp-today { box-shadow: inset 3px 0 0 var(--neg); }
.bookitem.exp-gone  { box-shadow: inset 3px 0 0 var(--neg); }
.bookitem.exp-gone .bookrow { opacity: .75; }

.bdays {
  font-family: var(--ui); font-size: 10px; color: var(--faint);
  text-align: right;
}
.bookitem.exp-soon  .bdays { color: var(--warn); }
.bookitem.exp-today .bdays,
.bookitem.exp-gone  .bdays { color: var(--neg); font-weight: 700; }

/* A dot, so urgency survives a colourblind reader and a grey printout. */
.expdot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; margin-right: 6px; vertical-align: middle;
}
.bookitem.urgent .expdot { animation: expPulse 2.4s ease-in-out infinite; }
@keyframes expPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .bookitem.urgent .expdot { animation: none; }
}


/* ---- the four rooms, in the strip and in the nav ----
   A tab carries its room as a top edge; the button that opens that room
   carries the same hue as a dot. Shown twice so the mapping is read
   rather than remembered, and named in words in both places so the
   colour is never doing the work alone. */

.tab { position: relative; }
.tab::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: var(--room); opacity: .34;
}
.tab.active::before { opacity: 1; }
.t-search   { --room: var(--room-search); }
.t-finder   { --room: var(--room-finder); }
.t-position { --room: var(--room-position); }
.t-log      { --room: var(--room-log); }

/* ---- going somewhere else, from anywhere ----
   The ring. Four buttons in every room, so no room is a dead end you
   have to reverse out of. */
.rooms { display: inline-flex; align-items: center; gap: 2px; margin-left: 10px; }
.room {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; cursor: pointer;
  padding: 4px 9px; border-radius: 3px;
  font-family: var(--ui); font-size: 9px; font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--faint);
}
.room::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--room); opacity: .55;
}
.room.r-search   { --room: var(--room-search); }
.room.r-finder   { --room: var(--room-finder); }
.room.r-position { --room: var(--room-position); }
.room.r-log      { --room: var(--room-log); }
.room:hover { color: var(--text); background: var(--raised); }
.room:hover::before { opacity: 1; }

/* Where you already are is not a destination. */
.room.here {
  color: var(--text); cursor: default;
  box-shadow: inset 0 0 0 1px var(--rule);
}
.room.here::before { opacity: 1; }
.room.here:hover { background: none; }

@media (max-width: 900px) {
  .room { padding: 4px 6px; font-size: 0; gap: 0; }   /* dots only */
  .room::before { width: 8px; height: 8px; }
}

/* The ticker in a log row is a way into the company. */
.bsym[data-stock] { cursor: pointer; }
.bsym[data-stock]:hover { color: var(--text); text-decoration: underline dotted; }

/* The doors on the front page are the same three rooms as the nav. */
.door { position: relative; }
.door::before {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  top: -7px; width: 5px; height: 5px; border-radius: 50%;
  background: var(--room); opacity: .6;
}
.door:hover::before { opacity: 1; }
.door.d-finder   { --room: var(--room-finder); }
.door.d-position { --room: var(--room-position); }
.door.d-log      { --room: var(--room-log); }

/* The odds, opened up. A bare percentage next to a trade reads like a
   forecast; this one is a restatement of today's option prices. */
.oddswork { margin-top: 8px; text-align: left; }
.oddswork > summary {
  cursor: pointer; list-style: none;
  font-size: 10.5px; color: var(--faint); padding: 2px 0;
}
.oddswork > summary::-webkit-details-marker { display: none; }
.oddswork > summary::before { content: "+ "; font-family: var(--mono); }
.oddswork[open] > summary::before { content: "\2212 "; }
.oddswork > summary:hover { color: var(--text2); }

/* The expiry deadline, which is a day and a clock time rather than a
   count of sessions. New York first, because that is the market's
   clock and the one the deadline is actually set in; the reader's own
   underneath when it differs. */
.bdays b { font-weight: 600; display: block; }
.blocal {
  display: block; font-style: normal; font-size: 9px;
  color: var(--faint); letter-spacing: .04em; margin-top: 1px;
}
.bookitem.exp-today .blocal,
.bookitem.exp-gone  .blocal { color: var(--neg); }

/* ---- what closing comes to ----
   The form asked for a number and printed a result, with the step
   between them left to the reader -- and that step is not obvious for
   anything sold, where "what you paid to open" is a negative number
   and both figures look like income. */
/* The row is a three-column grid and this one has two children, so
   the sum was landing in the 150px middle column and wrapping one
   word to a line. It spans the two value columns instead. */
.cfrow.cfwork { align-items: start; }
.cfrow.cfwork .cfsum { grid-column: 2 / -1; min-width: 0; }
.cfsum .wcalc { font-size: 12px; }
.cfnone { font-size: 11.5px; color: var(--faint); }
/* What the box actually wants. "Value received" is the accounting term
   and it does not say whose cash, in which direction, or across how
   many legs. */
.cfrow.cfsay { margin-top: -4px; }
.cfrow.cfsay .cfhelp {
  grid-column: 2 / -1;
  font-size: 11px; line-height: 1.55; color: var(--faint); max-width: 62ch;
}
.cfrow.cfsay .cfhelp b { color: var(--text2); font-weight: 600; }
.cfres {
  margin-top: 7px; font-family: var(--mono); font-size: 13px; color: var(--text2);
}
.cfres b { font-size: 16px; font-weight: 500; }
.cfres.up b { color: var(--pos); }
.cfres.down b { color: var(--neg); }


/* ---- two setups, side by side ----
   A character select, for option structures. The held one sits top
   right and stays there; hovering any card in the grid fills the
   second column and marks, row by row, which of the two wins that row.

   No overall winner is drawn, on purpose. These trade off against each
   other by construction -- the best odds belong to the setups that make
   the least -- so declaring a victor would invent a preference the
   reader has not stated. Each row says which way it goes and stops. */

/* Two columns rather than a float beside a grid.
   A float does not push grid items aside, so reserving the space with
   padding as well was doing it twice: the cards were squeezed into a
   third of the row with a gap where the panel already was. The whole
   section is one grid, the bar and the footnote span it, and the panel
   is simply the second column. */
.presets.haspin {
  display: grid; grid-template-columns: minmax(0, 1fr) 352px;
  gap: 0 22px; align-items: start;
}
.presets.haspin > .expbar,
.presets.haspin > .prenote { grid-column: 1 / -1; }
.presets.haspin > .pregrid { grid-column: 1; grid-row: 2; }
.presets.haspin > .vs { grid-column: 2; grid-row: 2; }

.vs {
  background: var(--panel); border: 1px solid var(--rule);
  border-top: 2px solid var(--room-position);
  padding: 14px 16px 12px;
  /* Follows the grid down: the point is comparing against a card
     further along the list than the one you are holding. */
  position: sticky; top: 12px;
}

.vshead { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vscol { min-width: 0; }
.vslab {
  display: block; font-family: var(--ui); font-size: 8px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
  margin-bottom: 3px;
}
.vscol b { font-size: 13px; color: var(--text); font-weight: 600; display: block; }
.vscol .bias { margin: 4px 0 0; }
.vsempty i { font-style: normal; font-size: 11.5px; color: var(--rule2); }

.vsrows { margin-top: 12px; border-top: 1px solid var(--rule); }
.vsrow {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px 10px;
  padding: 7px 0; border-bottom: 1px solid var(--hline);
}
.vsname {
  grid-column: 1 / -1;
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.vsv { font-family: var(--mono); font-size: 12.5px; color: var(--text); }
.vsv2 { color: var(--text2); }
.vsverdict { grid-column: 1 / -1; }
.vsw {
  font-size: 10px; color: var(--faint);
  display: inline-flex; align-items: baseline; gap: 5px;
}
.vsw::before { content: "\25B8"; font-size: .9em; }
.vsw.vsa { color: var(--room-position); }
.vsw.vsb { color: var(--room-log); }

.vsfoot {
  margin-top: 10px; font-size: 10.5px; line-height: 1.5; color: var(--faint);
}
.vsact { display: flex; gap: 8px; margin-top: 12px; }
.vsact .bookadd { flex: 1; }

/* The card you are holding. */
.pcard.pinned {
  box-shadow: inset 0 0 0 1px var(--room-position),
              inset 2px 0 0 var(--room-position);
}
.pcard.pinned .puse { color: var(--room-position); }

@media (max-width: 1150px) {
  /* No room beside the grid, so the panel goes above it and stops
     following. A 352px column next to a card grid on a narrow window
     leaves neither of them readable. */
  .presets.haspin { grid-template-columns: minmax(0, 1fr); }
  .presets.haspin > .vs { grid-column: 1; grid-row: 2; position: static; margin-bottom: 14px; }
  .presets.haspin > .pregrid { grid-row: 3; }
}

/* The two columns of the comparison, keyed to the colours the verdict
   lines use. Without this the panel names a winner in a hue that
   appears nowhere else on it, which is a code with no key. */
.vscol.vspin b { box-shadow: inset 0 -2px 0 var(--room-position); }
.vscol.vshov b { box-shadow: inset 0 -2px 0 var(--room-log); }

/* What it costs to place, which a bare "commissions are not included"
   never let anybody weigh against anything. */
.mnyfee {
  padding: 8px 1px 0; font-size: 11.5px; line-height: 1.5; color: var(--faint);
}
.mnyfee b { color: var(--text2); font-family: var(--mono); }

/* Start the banked total again. A line, not a delete: the closed
   trades stay listed and simply stop being added up, because the
   record of what you actually did is the part that cannot be
   reconstructed. */
.btreset {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; color: var(--faint);
  text-decoration: underline dotted; text-underline-offset: 2px;
}
.btreset:hover { color: var(--text2); }

/* A story that arrived while the page was open. The list is sorted by
   time, so without a mark a new arrival is indistinguishable from one
   that was there when you loaded it. */
.article.fresh { box-shadow: inset 2px 0 0 var(--attn); padding-left: 10px; }
.newflag {
  font-style: normal; font-family: var(--ui); font-size: 8px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--attn);
  border: 1px solid color-mix(in srgb, var(--attn) 45%, transparent);
  border-radius: 2px; padding: 1px 4px; margin-right: 7px; vertical-align: 1px;
}

/* ---- the world ----
   Where the market is, what happened, and what is coming -- in the
   order somebody would ask. */
.t-world { --room: var(--room-world); }
.room.r-world { --room: var(--room-world); }
.door.d-world { --room: var(--room-world); }

/* The World page is the company page's grid, without the region rail. */
.grid.world { padding-right: 0; }
/* Margins stay inside what fill.js measures, so a filled square does not
   overshoot by a few pixels and grow a scrollbar. */
.grid.world .fill { display: flow-root; }
/* Only the headline lists are longer than their square; the rest are
   filled to the edge, and the pixel a fractional zoom rounds up by is
   not worth a scrollbar. */
.grid.world .tile:not(.elastic) > .body { overflow: hidden; }

/* The barometer. "The market" as a set of numbers rather than a word. */
.wxbig {
  display: block; margin-top: 2px;
  font-family: var(--mono); font-size: 21px; font-weight: 400; color: var(--text);
}
.wxpx { font-family: var(--mono); font-size: 11.5px; color: var(--text2); }
.wxwhat {
  display: block; margin-top: 6px; font-size: 10.5px; line-height: 1.5;
  color: var(--faint); max-width: 34ch;
}

/* The headlines. */
.wnews { border-top: 1px solid var(--rule); }
.wnrow { padding: 11px 2px 12px; border-bottom: 1px solid var(--hline); }
.wnrow.loud { box-shadow: inset 3px 0 0 var(--attn); padding-left: 12px; }
.wnhl {
  font-size: 14px; line-height: 1.4; color: var(--text); text-decoration: none;
}
.wnhl:hover { text-decoration: underline; }
.wnmeta {
  margin-top: 4px; font-size: 10.5px; color: var(--faint);
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
}
.wnmeta b { color: var(--text2); font-family: var(--mono); }
.wnsrc { color: var(--text2); }
.wnloud {
  font-family: var(--ui); font-size: 8px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--attn);
  border: 1px solid color-mix(in srgb, var(--attn) 40%, transparent);
  border-radius: 2px; padding: 1px 5px;
}
.wnsum {
  margin-top: 5px; font-size: 11.5px; line-height: 1.55; color: var(--faint);
  max-width: 96ch;
}

/* The story at the top. */
.wnlead {
  display: block; font-size: 19px; line-height: 1.35; color: var(--text);
  text-decoration: none;
}
.wnlead:hover { text-decoration: underline; }
.wnrow .t-bullish { color: var(--pos); } .wnrow .t-bearish { color: var(--neg); }

/* What is coming. */
.wcd { font-family: var(--mono); font-size: 12px; color: var(--text2); }
.wct { font-size: 13px; color: var(--text); margin-top: 3px; }
.wcw { font-size: 11px; color: var(--faint); line-height: 1.5; margin-top: 4px; }
.wcz .wct { font-size: 18px; margin: 8px 0 4px; font-weight: 400; }
.wcdet { font-size: 12px; color: var(--text2); }
.wcz .wcw { font-size: 13px; max-width: 70ch; margin: 10px 0; }

/* The handful most likely to have moved the price.
   Sixty articles is a good haul and a bad list: chronological order
   puts a syndicated opinion piece above an earnings miss, and leaves
   the reader doing the ranking the app should have done. */
.movers {
  background: var(--sunk); border-left: 2px solid var(--attn);
  padding: 11px 14px 12px; margin: 0 0 14px;
}
.mvhead {
  font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--attn);
  margin-bottom: 8px;
}
.mvrow {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 12px;
  padding: 5px 0; border-top: 1px solid var(--hline);
}
.mvrow:first-of-type { border-top: none; }
.mvhl { font-size: 12.5px; line-height: 1.4; color: var(--text); text-decoration: none; }
.mvhl:hover { text-decoration: underline; }
.mvage { font-family: var(--mono); font-size: 10px; color: var(--faint); }
.mvwhy {
  grid-column: 1 / -1; font-size: 10px; color: var(--faint);
  font-family: var(--ui); letter-spacing: .04em;
}
.mvnote {
  margin-top: 9px; font-size: 10px; line-height: 1.5; color: var(--faint);
}
/* And the same story, still in its place in the list below. */
.article.mover { box-shadow: inset 2px 0 0 var(--attn); padding-left: 10px; }

/* ---- structures built around a price you name ----
   The catalogue picks strikes by delta, which is right when the view
   is about direction. When it is about a number, the strikes come
   from the number -- and then the comparison is interesting rather
   than obvious, because a capped structure usually wins at a
   specific target. Refusing to buy the part above your own number is
   what makes it cheaper. */
.tgbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 2px; border-bottom: 1px solid var(--rule);
}
.tginput { display: flex; align-items: center; gap: 2px; }
.tgcur { font-family: var(--mono); font-size: 15px; color: var(--faint); }
.tginput input {
  width: 120px; background: var(--panel); border: 1px solid var(--rule2);
  border-radius: 3px; color: var(--text); font-family: var(--mono);
  font-size: 15px; padding: 7px 10px; outline: none;
}
.tginput input:focus { border-color: var(--c-priced); }

.tghead {
  padding: 16px 2px 12px; font-size: 15px; color: var(--text2); line-height: 1.5;
}
.tghead b { color: var(--text); font-family: var(--mono); }

.tgrows { border-top: 1px solid var(--rule); }
.tgrow { padding: 14px 2px 15px; border-bottom: 1px solid var(--hline); }
.tgrow.best { box-shadow: inset 3px 0 0 var(--c-priced); padding-left: 12px; }
.tgname { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.tgname b { font-size: 14px; color: var(--text); font-weight: 600; }
.tgcap {
  font-family: var(--ui); font-size: 8px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; padding: 2px 6px; border-radius: 2px;
  border: 1px solid var(--rule2); color: var(--faint);
}
.tgcap.uncapped { color: var(--attn); border-color: color-mix(in srgb, var(--attn) 40%, transparent); }

.tgnums {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  gap: 10px 14px; margin-top: 10px;
}
.tgn { display: flex; flex-direction: column; gap: 2px; }
.tgn i {
  font-style: normal; font-family: var(--ui); font-size: 8.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.tgn b { font-family: var(--mono); font-size: 14px; font-weight: 400; color: var(--text); }
.tgn.big b { font-size: 19px; }

.tgwhy {
  margin-top: 9px; font-size: 11.5px; line-height: 1.55; color: var(--faint);
  max-width: 88ch;
}
.tglegs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 9px; }

/* ---- the payoff, drawn as a payoff ----
   Profit against the price it finishes at. The winning region is
   tinted apart from the losing one, every strike is marked with the
   leg that put it there, and both extremes are labelled where they
   happen -- because "I am down on an iron condor and I do not know
   why" is answered by seeing the price has walked off the flat top
   and onto a slope, and a bare line never says that. */
.poschart { position: relative; }
.pfsvg { width: 100%; height: 100%; display: block; overflow: visible; }
.pfempty { padding: 10px 2px; font-size: 11.5px; color: var(--faint); }

/* Money made and money lost: the one place a hue carries a fact. */
.pfband.win  { fill: color-mix(in srgb, var(--pos) 16%, transparent); }
.pfband.lose { fill: color-mix(in srgb, var(--neg) 16%, transparent); }

.pfline { fill: none; stroke: var(--text); stroke-width: 1.6; }
.pfzero { stroke: var(--text2); stroke-width: 1; }

/* Where each leg sits. */
.pfstrike line { stroke: var(--rule2); stroke-width: 1; stroke-dasharray: 2 4; }
.pfstrike text {
  font-family: var(--mono); font-size: 9.5px; fill: var(--text2);
}
.pfstrike text.pfleg {
  font-family: var(--ui); font-size: 8px; letter-spacing: .06em; fill: var(--faint);
}

/* The two figures the reader came for. */
.pfext line { stroke-width: 1; stroke-dasharray: 3 5; }
.pfext text { font-family: var(--ui); font-size: 9.5px; letter-spacing: .04em; }
.pfext.best line   { stroke: color-mix(in srgb, var(--pos) 55%, transparent); }
.pfext.best circle { fill: var(--pos); }
.pfext.best text   { fill: var(--pos); }
.pfext.worst line   { stroke: color-mix(in srgb, var(--neg) 55%, transparent); }
.pfext.worst circle { fill: var(--neg); }
.pfext.worst text   { fill: var(--neg); }

/* Where it stops losing, and where it trades now. */
.pfbe line { stroke: var(--text2); stroke-width: 1.4; }
.pfbe text { font-family: var(--mono); font-size: 9px; fill: var(--faint); }
.pfspot line { stroke: var(--attn); stroke-width: 1; stroke-dasharray: 4 3; }
.pfspot text {
  font-family: var(--mono); font-size: 9.5px; fill: var(--attn);
}

.pfytick text { font-family: var(--mono); font-size: 9.5px; fill: var(--faint); }
.pfytick.zero text { fill: var(--text2); }

/* Open interest, marked by what it means for getting out.
   The number alone cannot say: 1,240 is a deep strike on one board and
   a backwater on another. Only the two extremes are marked -- flagging
   the ordinary middle would be colour carrying no information, and
   both carry the reading in the tooltip. */
.q.oi.none { color: var(--neg); }
.q.oi.thin { color: var(--warn); }
.q.oi.deep { color: var(--text); }
.q.oi.none::after { content: "\00a0!"; font-size: .85em; }

/* ==== the step-by-step guide (course.js) ================================
 *
 * The curriculum at the top of a search. Every number is drawn the same
 * way -- label, big figure, which way it points, score x weight, then the
 * table it is read against with its row lit -- so the shape is learned
 * once. Direction colour is the app's own pos/neg and nothing else; the
 * lit table row is the attention hue, because it answers "which rule
 * applied" rather than "good or bad".
 */
.guide { display: flex; flex-direction: column; gap: 14px; padding: 14px 112px 22px 18px;  /* clear of the fixed rail, as the grid is */
  border-bottom: 1px solid var(--rule2); }
.cg-block { background: var(--panel); border: 1px solid var(--rule); padding: 18px 20px; }
.cg-wait { font-family: var(--ui); color: var(--text2); font-size: 13px; padding: 10px 0; }
.cg-head { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 12px; scroll-margin-top: 12px; }
.cg-head h3 { margin: 0; font-family: var(--ui); font-size: 17px; letter-spacing: .02em; color: var(--text); }
.cg-head p { margin: 3px 0 0; color: var(--text2); font-size: 13px; }
.cg-n { font-family: var(--mono); font-size: 22px; font-weight: 700; color: var(--black);
  background: var(--text); min-width: 34px; height: 34px; display: grid; place-items: center; }
.cg-section { margin: 14px 0 6px; }
.cg-section > h5, .cg-card > h5, .cg-news > h5 { font-family: var(--ui); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text2); margin: 0 0 8px; font-weight: 700; }
.cg-lesson { font-family: var(--mono); font-size: 10.5px; color: var(--faint); border: 1px solid var(--rule2);
  padding: 1px 5px; margin-right: 6px; letter-spacing: 0; text-transform: none; }
.cg-context { color: var(--faint); font-size: 12px; margin: 4px 0 8px; }

.cg-metric { border-top: 1px solid var(--rule); padding: 12px 0 10px; }
.cg-metric.off { opacity: .62; }
.cg-top { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.cg-top .grow { flex: 1; }
.cg-label { font-family: var(--ui); font-size: 14px; color: var(--text); font-weight: 600; }
.cg-big { font-family: var(--mono); font-size: 24px; font-weight: 700; color: var(--text); }
.m-bullish .cg-big { color: var(--pos); }
.m-bearish .cg-big { color: var(--neg); }
.cg-reads, .cg-stance, .cg-score, .cg-mixed { font-family: var(--ui); font-size: 10.5px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; padding: 3px 7px; border: 1px solid var(--rule2); color: var(--text2); }
.cg-reads.r-bullish { color: var(--pos); border-color: var(--pos); }
.cg-reads.r-bearish { color: var(--neg); border-color: var(--neg); }
.cg-stance.s-buy, .cg-stance.s-pass { color: var(--pos); border-color: var(--pos); }
.cg-stance.s-sell, .cg-stance.s-credit, .cg-stance.s-fail { color: var(--neg); border-color: var(--neg); }
.cg-stance.s-debit { color: var(--attn); border-color: var(--attn); }
.cg-score { font-family: var(--mono); text-transform: none; letter-spacing: 0; }
.cg-score.pos b { color: var(--pos); } .cg-score.neg b { color: var(--neg); }
.cg-means { color: var(--text2); font-size: 13.5px; line-height: 1.5; margin: 6px 0 8px; max-width: 980px; }
.cg-means.down, .cg-wait.down { color: var(--neg); }
.cg-against { display: grid; grid-template-columns: minmax(260px, 1fr) minmax(260px, 1.2fr); gap: 8px 22px; }
@media (max-width: 900px) { .cg-against { grid-template-columns: 1fr; } }
.cg-foot { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 6px; }
.cg-formula { font-family: var(--mono); font-size: 11.5px; color: var(--faint); }
.cg-src { font-size: 11px; color: var(--faint); font-style: italic; }

.cg-table { border-collapse: collapse; width: 100%; font-size: 12.5px; }
.cg-table td { padding: 4px 8px; border-bottom: 1px solid var(--rule); color: var(--text2); vertical-align: top; }
.cg-table .cg-when { font-family: var(--mono); white-space: nowrap; color: var(--faint); }
.cg-table tr.hit td { color: var(--text); background: rgba(199, 154, 82, .12); }
.cg-table tr.hit .cg-when { color: var(--attn); }
.cg-table tr.th td { font-family: var(--ui); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.cg-table tr.total td { border-top: 1px solid var(--rule2); color: var(--text); }
.cg-table tr.off td { opacity: .55; }
.cg-table tr.t-bullish td b { color: var(--pos); } .cg-table tr.t-bearish td b { color: var(--neg); }

.cg-cmp { margin: 0; display: flex; flex-direction: column; }
.cg-cmp > div { display: flex; justify-content: space-between; gap: 14px; padding: 4px 0; border-bottom: 1px dotted var(--rule); }
.cg-cmp dt { color: var(--faint); font-size: 12.5px; }
.cg-cmp dd { margin: 0; font-family: var(--mono); font-size: 12.5px; color: var(--text); text-align: right; }
.cg-cmp .t-bullish dd, .cg-cmp .t-bullish .cg-arrow { color: var(--pos); }
.cg-cmp .t-bearish dd, .cg-cmp .t-bearish .cg-arrow { color: var(--neg); }
.cg-arrow { font-style: normal; margin-right: 6px; }
.cg-eq dd i { color: var(--faint); font-style: normal; }

.cg-output { margin-top: 14px; padding: 12px 14px; border-left: 3px solid var(--attn); background: var(--raised);
  font-size: 13.5px; line-height: 1.5; color: var(--text); }
.cg-output .cg-context { display: block; margin: 6px 0 0; }
.cg-card { margin-top: 16px; }

/* the verdict */
.cg-verdict { border-width: 1px 1px 1px 4px; }
.cg-verdict.v-bullish { border-left-color: var(--pos); }
.cg-verdict.v-bearish { border-left-color: var(--neg); }
.cg-verdict.v-neutral { border-left-color: var(--text2); }
.cg-steps { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 14px; }
.cg-steps a { font-family: var(--ui); font-size: 12px; color: var(--text2); text-decoration: none;
  padding: 5px 10px; border: 1px solid var(--rule2); }
.cg-steps a b { font-family: var(--mono); color: var(--text); margin-right: 4px; }
.cg-steps a:hover { color: var(--text); border-color: var(--text2); }
.cg-steps .grow { flex: 1; }
.cg-iv { font-size: 11.5px; color: var(--faint); margin-right: 8px; }
.cg-toggle, .cg-open { font-family: var(--ui); font-size: 11px; font-weight: 700; letter-spacing: .06em;
  background: transparent; color: var(--text2); border: 1px solid var(--rule2); padding: 5px 10px; cursor: pointer; }
.cg-open { color: var(--black); background: var(--text); border-color: var(--text); padding: 9px 14px; font-size: 12px; }
.cg-open:hover { background: var(--attn); border-color: var(--attn); }
.cg-call { display: grid; grid-template-columns: auto minmax(220px, 1fr) minmax(280px, 1.3fr) auto;
  gap: 18px 26px; align-items: center; }
@media (max-width: 1100px) { .cg-call { grid-template-columns: 1fr 1fr; } }
.cg-dir { display: flex; gap: 12px; align-items: center; }
.cg-dir-arrow { font-size: 44px; line-height: 1; font-weight: 700; color: var(--text2); }
.v-bullish .cg-dir-arrow, .v-bullish .cg-dir b { color: var(--pos); }
.v-bearish .cg-dir-arrow, .v-bearish .cg-dir b { color: var(--neg); }
.cg-dir b { display: block; font-family: var(--ui); font-size: 26px; text-transform: capitalize; }
.cg-dir span { font-size: 12.5px; color: var(--text2); }
.cg-meter-bar { position: relative; height: 8px; background: linear-gradient(90deg, var(--neg), var(--rule2) 50%, var(--pos)); }
.cg-meter-bar i { position: absolute; top: -5px; width: 3px; height: 18px; background: var(--text); transform: translateX(-1px); }
.cg-meter-lab { display: flex; justify-content: space-between; font-size: 11px; color: var(--faint); margin-top: 6px; }
.cg-meter-lab b { font-family: var(--mono); font-size: 15px; color: var(--text); }
.cg-kv { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px; }
.cg-kv dt { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.cg-kv dd { margin: 1px 0 0; font-family: var(--mono); font-size: 13.5px; color: var(--text); }
.cg-thesis { margin: 16px 0 4px; font-size: 15px; line-height: 1.55; color: var(--text); max-width: 1100px; }
.cg-temper { margin: 10px 0 0; font-size: 12.5px; color: var(--attn); }
.cg-disclaimer { margin: 6px 0 0; font-size: 11px; color: var(--faint); }

/* the numbers that matter most on a trade, big */
.cg-big3 { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0; }
.cg-big3 > div { background: var(--raised); border: 1px solid var(--rule); padding: 10px 14px; min-width: 150px; }
.cg-big3 span { display: block; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.cg-big3 b { font-family: var(--mono); font-size: 22px; color: var(--text); }
.cg-big3 .pos b { color: var(--pos); } .cg-big3 .neg b { color: var(--neg); }
.cg-payoff { margin-top: 8px; }
.cg-matrix td.col { background: rgba(255, 255, 255, .03); }
.cg-matrix tr.row td:first-child { color: var(--text); }
.cg-matrix td.hit { color: var(--black) !important; background: var(--attn) !important; font-weight: 700; }
.cg-why { margin: 8px 0 0 18px; padding: 0; color: var(--text2); font-size: 13px; line-height: 1.55; }
.cg-legs tr.t-bullish td:first-child b { color: var(--pos); }
.cg-legs tr.t-bearish td:first-child b { color: var(--neg); }

.cg-inputs { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; margin: 4px 0 10px; }
.cg-inputs label { font-size: 12px; color: var(--text2); display: flex; gap: 8px; align-items: center; }
.cg-inputs input { font-family: var(--mono); font-size: 14px; background: var(--black); color: var(--text);
  border: 1px solid var(--rule2); padding: 6px 8px; width: 120px; }
.cg-exits { list-style: none; margin: 0; padding: 0; }
.cg-exits li { padding: 8px 0; border-bottom: 1px solid var(--rule); font-size: 13.5px; color: var(--text); }
.cg-exits li b:first-child { display: inline-block; min-width: 118px; font-family: var(--ui); font-size: 10.5px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.cg-exits li span { display: block; margin: 3px 0 0 122px; color: var(--faint); font-size: 12px; }
.cg-exits .x-price b:first-child, .cg-exits .x-premium b:first-child { color: var(--neg); }
.cg-exits .x-target b:first-child { color: var(--pos); }

/* the news, beside the scorecard */
.cg-art { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; padding: 8px 0; border-bottom: 1px solid var(--rule); }
.cg-art a { color: var(--text); text-decoration: none; font-size: 13.5px; }
.cg-art a:hover { text-decoration: underline; }
.cg-art .cg-words, .cg-art .cg-src { grid-column: 2; font-size: 11.5px; color: var(--faint); }
.cg-art .cg-words { font-family: var(--mono); }
.cg-art.t-bullish .cg-words { color: var(--pos); } .cg-art.t-bearish .cg-words { color: var(--neg); }
.cg-mixed { grid-column: 1; }
.cg-means .t-bullish { color: var(--pos); } .cg-means .t-bearish { color: var(--neg); }

/* ==== the curriculum as squares (course.js) =============================
 *
 * The steps live in the same packed grid as the rest of the page, below a
 * thin bar. A square's face is the figure, its lean, and the rule that
 * applied; everything else is inside it. The path is deliberately quiet:
 * a hairline and a small number in each corner, tinted by the lean, so the
 * grid still reads as a grid until you follow it.
 */
.stepbar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  height: auto; min-height: 38px; padding: 5px 112px 5px 14px;
  background: var(--black); border-top: 1px solid var(--rule2); border-bottom: 1px solid var(--rule2);
  position: sticky; top: 0; z-index: 30; }
.stepbar .grow { flex: 1; }
.sb-title { font-family: var(--ui); font-size: 9.5px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--faint); margin-right: 6px; }
.stepbar button { font-family: var(--ui); font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  background: transparent; color: var(--text2); border: 1px solid var(--rule2); padding: 4px 10px; cursor: pointer; }
.stepbar button:hover { color: var(--text); border-color: var(--text2); }
.stepbar .sb-path { color: var(--text); border-color: var(--text2); }
.stepbar .sb-path.on { color: var(--black); background: var(--attn); border-color: var(--attn); }
.stepbar .sb-open { color: var(--black); background: var(--text); border-color: var(--text); }
.sb-verdict { font-family: var(--mono); font-size: 11.5px; color: var(--text2); }
.sb-verdict b { text-transform: capitalize; }
.sb-verdict.v-bullish b { color: var(--pos); } .sb-verdict.v-bearish b { color: var(--neg); }

.grid.steps { border-top: 0; }
.tile.ct > h3 .ct-step { font-family: var(--mono); color: var(--faint); letter-spacing: 0; margin-right: 4px; }
.ct-face { display: flex; flex-direction: column; gap: 5px; min-height: 0; }
.ct-big { font-family: var(--mono); font-size: 26px; font-weight: 700; color: var(--text); line-height: 1.1; }
.ct-face.m-bullish .ct-big { color: var(--pos); }
.ct-face.m-bearish .ct-big { color: var(--neg); }
.ct-face.off .ct-big { color: var(--faint); }
.ct-unit { font-size: 12px; font-style: normal; font-weight: 400; color: var(--faint); }
.ct-split { display: flex; gap: 14px; font-size: 20px; }
.ct-split .t-bullish { color: var(--pos); } .ct-split .t-bearish { color: var(--neg); }
.ct-chips { display: flex; gap: 5px; flex-wrap: wrap; }
.ct-chips .cg-reads, .ct-chips .cg-stance, .ct-chips .cg-score { font-size: 9px; padding: 2px 5px; }
.ct-hit { font-family: var(--mono); font-size: 11px; color: var(--attn); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ct-means { margin: 0; font-size: 12px; line-height: 1.45; color: var(--text2);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.h3 .ct-means { -webkit-line-clamp: 6; }
.ct-line { font-family: var(--mono); font-size: 11.5px; color: var(--text2); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.ct-line.t-bullish, .ct-line.t-bullish b { color: var(--pos); } .ct-line.t-bearish, .ct-line.t-bearish b { color: var(--neg); }
.ct-line i { color: var(--faint); font-style: normal; }
.ct-thesis { margin: 0 0 8px; font-size: 13.5px; line-height: 1.5; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden; }
.ct-exits { list-style: none; margin: 0; padding: 0; font-size: 12px; line-height: 1.4; }
.ct-exits li { padding: 4px 0; border-bottom: 1px solid var(--rule); color: var(--text2); }
.ct-exits b { font-family: var(--ui); font-size: 9px; letter-spacing: .12em; text-transform: uppercase; margin-right: 6px; }
.ct-exits .x-price b, .ct-exits .x-premium b { color: var(--neg); } .ct-exits .x-target b { color: var(--pos); }
.ct-payoff { flex: 1; min-height: 150px; }
.ct-payoff svg { width: 100%; height: 100%; }
.ct .cg-big3 { margin: 2px 0; gap: 6px; }
.ct .cg-big3 > div { padding: 5px 9px; min-width: 0; }
.ct .cg-big3 b { font-size: 17px; }
.ct .cg-kv dd { font-size: 12px; }
.cg-matrix.small { font-size: 10.5px; }
.cg-matrix.small td { padding: 2px 5px; }
.ct .cg-meter { margin: 2px 0 4px; }

/* inside an opened square */
.cg-zoom { max-width: 1100px; }
.cg-zoom .cg-metric { border-top: 0; padding-top: 0; }
.cg-zoom .cg-big { font-size: 34px; }
.cg-sumhead { font-family: var(--ui); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); margin: 14px 0 6px; }
.cg-zoom .cg-payoff svg { width: 100%; height: auto; }

/* the path */
.pathlayer { position: absolute; inset: 0; pointer-events: none; z-index: 4; overflow: visible; }
.pathline { fill: none; stroke: var(--text2); stroke-width: 1; stroke-dasharray: 3 4; opacity: .38; }
.pathhead { fill: var(--text2); opacity: .5; }
.ct-order { position: absolute; left: 6px; top: 6px; z-index: 5; width: 22px; height: 22px;
  display: grid; place-items: center; font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  color: var(--text); background: var(--black); border: 1px solid var(--rule2); border-radius: 50%;
  pointer-events: none; }
.ct-order.o-bullish { border-color: var(--pos); color: var(--pos); }
.ct-order.o-bearish { border-color: var(--neg); color: var(--neg); }
.grid.steps.pathing .tile > h3 { padding-left: 24px; }

/* ==== filled squares ======================================================
 *
 * Every size on a square's face is in em, off one scale the fit sets per
 * square (--s), so a square can grow its type as a whole until it is full.
 * These rules come after the earlier .ct-* ones and replace their pixel
 * sizes.
 */
.tile.ct > .body { overflow: hidden; }
.ct-face { font-size: calc(var(--s, 1) * 12px); gap: .42em; }
.ct-face .ct-b[hidden] { display: none; }
.ct-face .ct-big { font-size: 2.2em; line-height: 1.05; white-space: nowrap; }
.ct-face .ct-split { font-size: 1.7em; gap: .8em; }
.ct-face .ct-chips { gap: .4em; }
.ct-face .ct-chips .cg-reads, .ct-face .ct-chips .cg-stance, .ct-face .ct-chips .cg-score {
  font-size: .72em; padding: .22em .5em; }
.ct-face .ct-hit { font-size: .92em; -webkit-line-clamp: unset; display: block; }
.ct-face .ct-means { font-size: 1em; -webkit-line-clamp: unset; display: block; line-height: 1.45; }
.ct-face .ct-line { font-size: .95em; white-space: normal; }
.ct-face .ct-line i { display: block; font-size: .85em; }
.ct-face .ct-thesis { font-size: 1.2em; -webkit-line-clamp: unset; display: block; }
.ct-face .ct-why { margin: 0; font-size: .9em; line-height: 1.4; color: var(--faint); }
.ct-face .ct-why b, .ct-face .ct-formula { font-family: var(--mono); }
.ct-face .ct-why b { display: block; font-size: .78em; letter-spacing: .12em; text-transform: uppercase; }
.ct-face .ct-formula { font-size: .82em; color: var(--faint); }
.ct-face .ct-rows { font-size: .85em; color: var(--faint); line-height: 1.4; }
.ct-face .ct-rows .t-bullish b { color: var(--pos); } .ct-face .ct-rows .t-bearish b { color: var(--neg); }
.ct-face .ct-rows b { float: right; font-family: var(--mono); }
.ct-cmp { margin: 0; font-size: .9em; }
.ct-cmp > div { display: flex; justify-content: space-between; gap: .8em; padding: .12em 0; border-bottom: 1px dotted var(--rule); }
.ct-cmp dt { color: var(--faint); }
.ct-cmp dd { margin: 0; font-family: var(--mono); color: var(--text); text-align: right; }
.ct-cmp .t-bullish dd { color: var(--pos); } .ct-cmp .t-bearish dd { color: var(--neg); }
.ct-leg { font-family: var(--mono); font-size: 1.15em; color: var(--text); }
.ct-leg.t-bullish b { color: var(--pos); } .ct-leg.t-bearish b { color: var(--neg); }
.ct-leg span { color: var(--text2); } .ct-leg i { display: block; font-size: .72em; color: var(--faint); font-style: normal; }
.ct-exit { font-size: 1em; line-height: 1.35; padding: .25em 0; border-bottom: 1px solid var(--rule); color: var(--text2); }
.ct-exit b { font-family: var(--ui); font-size: .72em; letter-spacing: .12em; text-transform: uppercase; margin-right: .5em; }
.ct-exit.x-price b, .ct-exit.x-premium b { color: var(--neg); } .ct-exit.x-target b { color: var(--pos); }
.ct-face .cg-matrix.small { font-size: .88em; }
.ct-face .cg-table.cg-greeks { font-size: .85em; }
.ct-face .cg-kv dd { font-size: 1em; } .ct-face .cg-kv dt { font-size: .75em; }
.ct-face .cg-meter-lab { font-size: .8em; }
.ct-face .cg-open { font-size: .95em; align-self: flex-start; }
.ct-fixed { display: flex; flex-direction: column; height: 100%; }

/* ==== an opened square, using all of the box ============================ */
.cg-zoom { max-width: none; font-size: 15px; }
.cz-cols { display: grid; grid-template-columns: minmax(300px, 0.9fr) minmax(360px, 1.1fr); gap: 28px 40px; margin-top: 8px; }
@media (max-width: 1000px) { .cz-cols { grid-template-columns: 1fr; } }
.cz-top { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.cz-big { font-family: var(--mono); font-size: 58px; font-weight: 700; line-height: 1.05; color: var(--text); margin: 10px 0 8px; }
.cz-big.m-bullish { color: var(--pos); } .cz-big.m-bearish { color: var(--neg); }
.cz-big .ct-unit { font-size: 18px; }
.cz-big.ct-split { display: flex; gap: 28px; font-size: 44px; }
.cz-big .t-bullish { color: var(--pos); } .cz-big .t-bearish { color: var(--neg); }
.cz-means { font-size: 16px; line-height: 1.55; color: var(--text2); margin: 6px 0 12px; }
.cz-means.down { color: var(--neg); }
.cz-formula { font-family: var(--mono); font-size: 13px; color: var(--text2); padding: 10px 12px;
  border: 1px solid var(--rule2); background: var(--black); margin: 10px 0; }
.cz-guide { margin-top: 18px; display: flex; flex-direction: column; gap: 10px; }
.cz-guide > div { font-size: 14px; line-height: 1.5; color: var(--text2); padding-left: 12px; border-left: 2px solid var(--rule2); }
.cz-guide span { display: block; font-family: var(--ui); font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 2px; }
.cg-zoom .cg-table { font-size: 14px; }
.cg-zoom .cg-table td { padding: 7px 10px; }
.cg-zoom .cg-cmp dt, .cg-zoom .cg-cmp dd { font-size: 14px; }
.cg-zoom .cg-cmp > div { padding: 7px 0; }
.cg-zoom .cg-art a { font-size: 15px; }
.cz-sibs { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.cz-sib { text-align: left; background: var(--raised); border: 1px solid var(--rule); padding: 10px 12px; cursor: pointer;
  display: flex; flex-direction: column; gap: 3px; color: var(--text2); font-family: var(--ui); }
.cz-sib:hover { border-color: var(--text2); }
.cz-sib span { font-size: 11px; letter-spacing: .06em; }
.cz-sib b { font-family: var(--mono); font-size: 20px; color: var(--text); }
.cz-sib i { font-style: normal; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; }
.cz-sib.t-bullish b, .cz-sib.t-bullish i { color: var(--pos); }
.cz-sib.t-bearish b, .cz-sib.t-bearish i { color: var(--neg); }
.cg-zoom .cg-output { margin-top: 22px; font-size: 15px; }

/* The fit measures a square while it sets its type, so nothing inside a
 * face may animate: a transition on font-size -- which a global rule gives
 * everything -- means the measurement reads the old size mid-flight, and
 * the square is fitted to a size it no longer has. */
.ct-face, .ct-face * { transition: none !important; }

/* Each square is laid out on its own: what happens inside a face cannot
 * move anything outside it, so the fit can measure a square without the
 * whole page being laid out again for every guess. */
.tile.ct > .body { contain: strict; }

/* An opened curriculum square is as tall as what it holds, up to the
 * screen, rather than a fixed box with the bottom third empty. */
.zoom:has(.cg-zoom) { height: auto; max-height: min(92vh, 1000px); }
.zoom:has(.cg-zoom) > .inner { overflow: auto; }

/* Filled squares (fill.js): the zoom is measured as it is set, so nothing
 * inside may animate its size. */
.fill, .fill * { transition: none !important; }
.pcard > .fill { display: flex; flex-direction: column; gap: 5px; }

/* ================= a phone =================
 * QUIPU is a desktop instrument, and wearechintu.com's Start button opens
 * it on a phone as well. Everything here is for that width and nothing is
 * taken away: the same panels, stacked in one column instead of packed into
 * a table; the bars that stick to the screen kept to one line each, which
 * scrolls sideways; and the wide tables scroll inside themselves instead of
 * pushing the page off the right edge. */
@media (max-width: 760px) {
  /* The screen a phone actually shows: 100vh counts the browser's own bars
     and put the bottom of the page under them. */
  body { height: 100dvh; }

  /* Tabs: one row that scrolls. A tab never shrinks below its own words. */
  .tabstrip { overflow-x: auto; scrollbar-width: none; }
  .tabstrip::-webkit-scrollbar { display: none; }
  .tab { flex: none; min-width: 0; max-width: 72vw; padding: 8px 11px; gap: 7px; }

  /* One column. Below two columns the packer steps aside and leaves the
     stacking to CSS (packOne), and a panel's "two columns wide" would then
     make CSS invent columns off the right edge, which is what squeezed the
     quote into three-quarters of the screen and the next panel into 90px. */
  .grid { grid-template-columns: minmax(0, 1fr); }
  .grid > .tile.w2, .grid > .tile.w3, .grid > .tile.w4, .grid > .tile.w5 { grid-column: auto; }

  /* The three bars that stick: one line each. Wrapped, they were 110, 154
     and 130px tall, half the screen, with the panels in the gap between. */
  .livebar, .stepbar, .wirebar {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .livebar::-webkit-scrollbar, .stepbar::-webkit-scrollbar, .wirebar::-webkit-scrollbar { display: none; }
  .livebar > *, .stepbar > *, .wirebar > * { flex: none; white-space: nowrap; }
  .livebar { gap: 12px; }
  .livebar .grow, .stepbar .grow { display: none; }
  .stepbar { padding-right: 14px; }       /* no rail to leave room for */

  /* Tables whose columns are fixed widths scroll inside their own box. */
  .finder, .plegs, .chain { overflow-x: auto; }
  .frow { min-width: 700px; }
  .pleg { min-width: 600px; }
  /* The option board: eight columns a side squeezed to 15px each, the
     numbers printed over one another. At its own width it scrolls, calls,
     strikes and puts still in one row. */
  .chain > .crow, .chain > .spotrow { min-width: 760px; }

  /* The trade log's rows reflow instead: its five columns squeezed the
     trade's own description to 69px. Three columns, and the last two wrap
     under them in the same order, so the header still labels them. */
  .bookrow { grid-template-columns: 64px minmax(0, 1fr) auto; row-gap: 4px; }
  .cfrow { grid-template-columns: minmax(0, 1fr); gap: 4px; }

  /* A waiting or empty page's line of small capitals ran to the glass. */
  .loading { padding-inline: 16px; text-align: center; }
  .dbar { grid-template-columns: 110px 1fr 90px; gap: 8px; }
  .presets.haspin { grid-template-columns: minmax(0, 1fr); }
}
