:root {
  --paper:#F2F3F0; --card:#FFFFFF; --ink:#16191C; --ink-2:#4A5054; --muted:#6E7377;
  --rule:#DDE0DA; --accent:#35566B; --accent-ink:#FFFFFF;
  --ok:#4A6B4F; --ok-bg:#E4EBE1; --warn:#A65729; --warn-bg:#F4E6DA; --bad:#8C3A2B;
  --radius:10px;
  --sans:"IBM Plex Sans KR",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
@media (prefers-color-scheme: dark) {
  :root {
    --paper:#15181A; --card:#1D2124; --ink:#E7E9E4; --ink-2:#B4BAB8; --muted:#8A9094;
    --rule:#333A3E; --accent:#8FB4CA; --accent-ink:#12181C;
    --ok:#8FB394; --ok-bg:#1E2A20; --warn:#D08B54; --warn-bg:#33251A; --bad:#D08376;
  }
}
*{box-sizing:border-box}
html{
  /* Without this the browser paints native scrollbars, date pickers and
     select popups in the light theme on a dark page. */
  color-scheme: light dark;
}
html,body{margin:0}
body{
  background:var(--paper); color:var(--ink); font-family:var(--sans);
  /* Removes the 300ms double-tap delay without disabling zoom. */
  touch-action:manipulation;
  -webkit-tap-highlight-color:rgba(53,86,107,.12);
  font-size:16px; line-height:1.6; -webkit-font-smoothing:antialiased;
  word-break:keep-all;
  /* Room for the home indicator, and never less than the old value. */
  padding-bottom:calc(48px + env(safe-area-inset-bottom));
  overscroll-behavior-y:contain;
}
.wrap{
  max-width:640px; margin:0 auto; padding-block:16px 0;
  padding-inline:max(16px, env(safe-area-inset-left)) max(16px, env(safe-area-inset-right));
}

header.bar{
  border-bottom:1px solid var(--rule); position:sticky; top:0;
  background:var(--paper); z-index:5;
}
.barinner{
  max-width:1120px; margin:0 auto; display:flex; align-items:center; gap:18px;
  padding:12px max(16px, env(safe-area-inset-right))
         12px max(16px, env(safe-area-inset-left));
}
header.bar .brand{
  font-weight:600; letter-spacing:-.01em; text-decoration:none; color:var(--ink);
  flex:none; display:inline-flex; align-items:center; min-height:44px;
}
@media (min-width: 900px){ header.bar .brand{min-height:36px} }
/* Navigation belongs where people look for it, not at the bottom of the page. */
.nav{display:flex; gap:4px; overflow-x:auto; flex:1; scrollbar-width:none}
.nav::-webkit-scrollbar{display:none}
.nav a{
  text-decoration:none; color:var(--muted); font-size:14px; font-weight:500;
  padding:8px 12px; border-radius:8px; white-space:nowrap; min-height:38px;
  display:inline-flex; align-items:center;
}
.nav a:hover{color:var(--ink); background:var(--card)}
.nav a.on{color:var(--accent); background:var(--card)}
header.bar .who{font-family:var(--mono); font-size:12px; color:var(--muted); flex:none}
header.bar .who a{color:var(--muted)}
.backlink{
  display:inline-block; color:var(--accent); text-decoration:none;
  font-size:14px; margin:4px 0 -4px;
}
@media (max-width: 620px){
  .barinner{gap:10px; flex-wrap:wrap}
  header.bar .who{order:2; margin-left:auto}
  .nav{order:3; width:100%; flex:none}
}

h1,h2,h3{font-weight:600}
h1{font-size:1.3rem; margin:20px 0 4px; letter-spacing:-.01em}
h2{font-size:1.02rem; margin:26px 0 10px; letter-spacing:-.005em}
p.sub{color:var(--muted); margin:0 0 18px; font-size:14px}
em{font-style:normal; font-weight:500; color:var(--ink)}
a{color:var(--accent)}
a:focus-visible,button:focus-visible,select:focus-visible,input:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px
}

.card{
  background:var(--card); border:1px solid var(--rule); border-radius:var(--radius);
  padding:16px;
}
/* A plain stack of cards gets its gap from the sibling margin. Inside a grid
   the container provides it, so the margin has to be cancelled or the second
   item is pushed down and the row stops lining up. */
.card + .card, .card + .panelcard, .panelcard + .card{margin-top:12px}
.card{margin-bottom:12px}
/* The grid supplies the gap, so its cards carry no margin of their own. It
   has to be a grid at every width for that to hold: written for wide screens
   only, the margin was cancelled on a phone where nothing replaced it and
   the cards ran together into one block. */
.cardgrid{display:grid; grid-template-columns:minmax(0, 1fr); gap:12px}
.cardgrid .card{margin:0}
.card.link{display:block; text-decoration:none; color:inherit}
.card .title{font-weight:600; display:flex; justify-content:space-between; gap:10px; align-items:baseline}
/* The title is how one model is told from another, so on a narrow screen it
   gets two lines rather than one line and an ellipsis. Wide screens keep the
   single line, where the grid depends on the cards being the same height. */
.card .title > span:first-child{
  min-width:0; overflow:hidden;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
  line-height:1.4; word-break:keep-all; overflow-wrap:anywhere;
}
@media (min-width: 900px){
  .card .title > span:first-child{
    display:block; white-space:nowrap; text-overflow:ellipsis;
  }
}
/* The badge must not shrink. Written as :last-child it also matched a card
   that has no badge, because there the single span is both first and last,
   and flex:none then stopped the title from shrinking to the screen. */
.card .title > span:first-child + span{
  flex:none; font-family:var(--mono); font-variant-numeric:tabular-nums;
}
.card .meta{font-family:var(--mono); font-size:12px; color:var(--muted); margin-top:4px}

/* ===== buttons ===========================================================
   One definition, three variants, two sizes. Every earlier rule for these
   lived somewhere different and quietly overrode the last one; the visible
   symptom was two buttons side by side at different heights, because a
   stacked-layout margin was still being applied in a row. */

.btn{
  --btn-h: 48px;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  box-sizing:border-box; min-height:var(--btn-h); padding:0 20px;
  border:1px solid transparent; border-radius:var(--radius);
  background:var(--accent); color:var(--accent-ink);
  font:600 15px/1 var(--sans); text-decoration:none; cursor:pointer;
  text-align:center; white-space:nowrap;
}
.btn.ghost{background:transparent; color:var(--accent); border-color:var(--rule)}
.btn.danger{background:transparent; color:var(--bad); border-color:var(--rule)}
.btn.small{--btn-h: 44px; font-size:14px; padding:0 14px}
@media (min-width: 900px){ .btn.small{--btn-h: 36px} }

.btn:hover{filter:brightness(1.06)}
.btn.ghost:hover, .btn.danger:hover{border-color:currentColor; filter:none}
.btn:disabled, .btn[aria-disabled=true]{
  opacity:.45; cursor:not-allowed; filter:none;
}

/* A lone button fills the width on a phone; a row of them shares it. */
.btn{width:100%}
/* Buttons sitting together share the line and grow to fill it. Giving each
   one width:100% made every button claim a row of its own, so two buttons
   became two full-width bars stacked down a phone screen. A single button
   still fills the row, because flex-grow does that on its own. */
.row{display:flex; gap:10px; flex-wrap:wrap; align-items:stretch}
.row > *{flex:1 1 auto; min-width:0}
.row .btn, .row form{width:auto}
.row form{display:flex}
.row form > .btn{width:100%}

@media (min-width: 900px){
  .btn{--btn-h: 40px; width:auto; max-width:340px}
  .row > *{flex:0 0 auto}
  .row .btn{width:auto}
  /* Inside a side panel the buttons stack, so they fill it. */
  .panelcard .btn{width:100%; max-width:none}
}


select:disabled{opacity:.6; cursor:not-allowed}
option:disabled{color:var(--muted)}
label{display:block; font-size:13px; color:var(--muted); margin:16px 0 8px}
select,input[type=text],input[type=number],input[type=date]{
  width:100%; padding:12px; min-height:48px; font:400 15px var(--sans);
  background-color:var(--card); color:var(--ink); border:1px solid var(--rule);
  border-radius:var(--radius);
}
select option{background-color:var(--card); color:var(--ink)}
input[type=range]{width:100%; min-height:44px}
.hint{font-size:12px; color:var(--muted); margin-top:6px}

.rule{border:1px solid var(--rule); border-radius:var(--radius); padding:12px; margin-bottom:10px; background:var(--card)}
.rule .head{display:flex; justify-content:space-between; align-items:center; gap:8px}
.rule .idx{font-family:var(--mono); font-size:12px; color:var(--accent); font-weight:600}
.rule .grid{display:grid; grid-template-columns:1fr; gap:8px; margin-top:8px}
.rule .move{display:flex; gap:6px}
.rule .move button{
  background:transparent; border:1px solid var(--rule); border-radius:8px;
  color:var(--ink-2); min-width:40px; min-height:40px; font-size:15px; cursor:pointer;
}

.stat{
  display:flex; justify-content:space-between; align-items:baseline; gap:12px;
  padding:9px 0; border-bottom:1px solid var(--rule); font-size:14px;
}
.stat:last-child{border-bottom:0}
.stat .k{color:var(--muted); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.stat .v{
  font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-size:16px; font-weight:500; white-space:nowrap;
}

/* The result grid is read by comparing figures, so they carry the emphasis. */
.statgrid .stat{padding:11px 0}
.statgrid .stat .v{font-size:17.5px}
@media (min-width: 900px) {
  .statgrid .stat .v{font-size:19px}
}
.v.pos{color:var(--ok)} .v.neg{color:var(--bad)}

.warn{background:var(--warn-bg); border-left:3px solid var(--warn); border-radius:6px;
  padding:12px 16px; margin-bottom:10px; font-size:13.5px; color:var(--ink)}
.good{background:var(--ok-bg); border-left:3px solid var(--ok); border-radius:6px;
  padding:12px 16px; margin-bottom:10px; font-size:13.5px}

.pill{
  display:inline-block; font-family:var(--mono); font-size:11px; padding:3px 8px;
  border-radius:20px; border:1px solid var(--rule); color:var(--muted);
  white-space:nowrap;
}
/* Reserved for something the reader should act on. */
.pill.ok{color:var(--ok); border-color:var(--ok); background:var(--ok-bg)}
.pill.bad{color:var(--warn); border-color:var(--warn); background:var(--warn-bg)}
/* A count is information, not a problem. */
.pill.count{color:var(--muted); border-color:var(--rule); background:transparent}

.empty{text-align:center; color:var(--muted); padding:40px 16px; font-size:14px}
/* A table with more columns than the screen has room for is the one thing
   allowed to scroll sideways, and only inside its own box. Without this the
   page itself scrolls and every other column goes with it. */
.tablewrap{overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%}
.tablewrap table{min-width:520px}
table{width:100%; border-collapse:collapse; font-family:var(--mono); font-size:13px}
td,th{padding:8px 0; border-bottom:1px solid var(--rule); text-align:right}
th:first-child,td:first-child{text-align:left; font-family:var(--sans)}
th{color:var(--muted); font-weight:500; font-size:12px}

/* ===== rule builder ====================================================== */

:root { --buy:#4A6B4F; --buy-bg:#E4EBE1; --sell:#96543A; --sell-bg:#F3E5DC; }
@media (prefers-color-scheme: dark) {
  :root { --buy:#8FB394; --buy-bg:#1E2A20; --sell:#C98A6A; --sell-bg:#2E211A; }
}

/* The rail is the point: judgement runs top to bottom and stops at the first
   rule that matches, so precedence has to be visible, not implied. */
.stack{position:relative; margin:8px 0 4px}
.stack::before{
  content:""; position:absolute; left:13px; top:14px; bottom:14px; width:2px;
  background:linear-gradient(var(--accent), transparent); opacity:.35;
}
.step{position:relative; padding-left:38px; margin-bottom:10px}
.step > .no{
  position:absolute; left:0; top:12px; width:28px; height:28px; border-radius:50%;
  display:grid; place-items:center; background:var(--paper); color:var(--accent);
  border:2px solid var(--accent); font:600 12px/1 var(--mono);
}
.step.off > .no{border-color:var(--rule); color:var(--muted)}

.rulecard{
  background:var(--card); border:1px solid var(--rule); border-radius:12px;
  padding:12px 12px 10px; border-left:3px solid var(--rule);
}
.rulecard.buy{border-left-color:var(--buy)}
.rulecard.sell{border-left-color:var(--sell)}
.rulecard.off{opacity:.5}

/* The sentence is the control surface: read it and tap the part to change. */
.sent{font-size:15.5px; line-height:2.15; margin:0 0 8px}
.chip{
  display:inline-block; border:1px dashed var(--rule); background:var(--paper);
  color:var(--ink); border-radius:8px; padding:0 11px; margin:0 1px;
  font:500 14.5px/1 var(--sans); cursor:pointer; min-height:44px;
  line-height:42px; vertical-align:middle;
}
@media (min-width: 900px){ .chip{min-height:36px; line-height:34px} }
.chip:active{transform:translateY(1px)}
.chip.num{font-family:var(--mono); font-variant-numeric:tabular-nums; border-style:solid}
.chip.act{border-style:solid; font-weight:600}
.chip.act[data-action=buy]{color:var(--buy); border-color:var(--buy); background:var(--buy-bg)}
.chip.act[data-action=sell]{color:var(--sell); border-color:var(--sell); background:var(--sell-bg)}
.sent .lit{color:var(--muted); font-weight:300}

.rulebar{display:flex; gap:6px; justify-content:flex-end; border-top:1px solid var(--rule); padding-top:8px}
.rulebar button{
  background:transparent; border:1px solid var(--rule); border-radius:9px;
  min-width:44px; min-height:44px; color:var(--ink-2); font-size:15px; cursor:pointer;
}
@media (min-width: 900px){ .rulebar button{min-height:36px} }
.rulebar button:hover:not(:disabled){border-color:var(--accent); color:var(--accent)}
.rulebar button:disabled{opacity:.3; cursor:default}
.card.link:hover{border-color:var(--accent)}
.chip:hover{border-color:var(--accent)}
.rulebar .spacer{flex:1}

/* Bottom sheet — a phone-sized picker rather than a native select. */
.sheet{
  position:fixed; inset:0; z-index:50; display:none;
  background:rgba(0,0,0,.42);
}
.sheet[open]{display:block}
.sheet .panel{
  position:absolute; left:0; right:0; bottom:0; max-height:82dvh; overflow:auto;
  overscroll-behavior:contain;
  background:var(--card); border-radius:16px 16px 0 0; padding:8px 16px 24px;
  border-top:1px solid var(--rule);
}
.sheet .grab{width:38px; height:4px; border-radius:2px; background:var(--rule); margin:8px auto 12px}
.sheet h3{margin:0 0 4px; font-size:1.05rem}
.sheet .note{color:var(--muted); font-size:13px; margin:0 0 14px}
.sheet .group{color:var(--muted); font-size:12px; margin:16px 0 6px; font-weight:500}
.opt{
  display:flex; justify-content:space-between; align-items:center; gap:12px; width:100%;
  background:transparent; border:0; border-bottom:1px solid var(--rule);
  padding:14px 2px; min-height:52px; text-align:left; cursor:pointer;
  color:var(--ink); font:400 15px var(--sans);
}
.opt .u{font-family:var(--mono); font-size:12px; color:var(--muted)}
.opt[aria-selected=true]{color:var(--accent); font-weight:600}

.stepper{display:flex; align-items:center; gap:10px; margin:6px 0 2px}
.stepper button{
  width:52px; height:52px; border-radius:12px; border:1px solid var(--rule);
  background:var(--paper); color:var(--ink); font-size:22px; cursor:pointer;
}
.stepper input{
  flex:1; text-align:center; font:600 22px/1 var(--mono); font-variant-numeric:tabular-nums;
  min-height:52px; border-radius:12px;
}
.presets{display:flex; flex-wrap:wrap; gap:8px; margin-top:12px}
.presets button{
  border:1px solid var(--rule); background:var(--paper); color:var(--ink-2);
  border-radius:20px; padding:0 15px; font:500 13px var(--mono);
  cursor:pointer; min-height:44px;
}
@media (min-width: 900px){ .presets button{min-height:38px} }

/* ===== wider screens ======================================================
   The reading measure stays narrow; the extra width goes only to things that
   are genuinely better side by side. Stretching prose to fill a monitor makes
   it harder to read, not easier. */

@media (min-width: 900px) {
  /* A full-width button on a monitor is a stripe of colour, not a control. */
  .rulebar button{min-width:38px; min-height:36px}
  .opt{min-height:44px}

  .wrap{max-width:1120px; padding-inline:32px; padding-block:24px 0}
  header.bar{padding:0}
  .barinner{padding:12px 32px}
  h1{font-size:1.75rem; margin-top:8px}
  h2{font-size:1.12rem; margin-top:34px}
  body{font-size:16.5px}

  /* Prose keeps its own measure regardless of the container. */
  p.sub, .hint, .warn p, .good p{max-width:70ch}

  /* Two columns: work on the left, what-you-need-to-know pinned on the right. */
  .split{display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:32px; align-items:start}
  .split > .aside{position:sticky; top:calc(var(--barh, 64px) + 24px)}

  .panelcard{
    background:var(--card); border:1px solid var(--rule); border-radius:12px; padding:16px;
  }
  .panelcard h3{margin:0 0 10px; font-size:.95rem}

  /* Cards in a list read better as a grid once there is room for two. */
  .cardgrid{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* A dozen figures in a column is a list to scroll; in a grid it is a table
     you can compare across. */
  .statgrid{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:0 24px}
  .statgrid .stat{border-bottom:1px solid var(--rule)}


  /* The sheet becomes a centred dialog: at this width, sliding up from the
     bottom edge is a long way from where the pointer already is. */
  .sheet .panel{
    left:50%; top:50%; right:auto; bottom:auto; transform:translate(-50%,-50%);
    width:min(520px, 92vw); max-height:80vh; border-radius:14px;
    border:1px solid var(--rule); padding:20px 24px 24px;
    box-shadow:0 24px 60px rgba(0,0,0,.28);
  }
  .sheet .grab{display:none}
  .opt{min-height:46px; padding:11px 2px}
  .stepper button{width:48px; height:48px}

  /* The rule sentence can breathe. */
  .sent{font-size:16.5px; line-height:2.1}
  .chip{font-size:15px}
  .rulecard{padding:14px 16px 12px}

  .row }

@media (min-width: 1280px) {
  .wrap{max-width:1200px}
  .barinner{max-width:1200px}
  .statgrid{grid-template-columns:repeat(4,minmax(0,1fr))}
}

/* Choices carry a line of explanation, so the list is taller and the label
   has to stay the thing you read first. */
.opt.tall{align-items:flex-start; padding:13px 2px}
.opt .txt{display:flex; flex-direction:column; gap:3px; min-width:0}
.opt .txt .l{font-weight:500}
.opt .txt .h{font-size:12.5px; line-height:1.5; color:var(--muted); font-weight:400}
.opt[aria-selected=true] .txt .h{color:var(--muted)}
.group .gn{display:block; font-weight:400; color:var(--muted); font-size:11.5px; margin-top:2px}

/* ===== result chart ====================================================== */

.chartcard{padding:14px 12px 10px}
.chartlegend{display:flex; gap:16px; margin:0 4px 8px; font-size:12.5px; color:var(--muted)}
.chartlegend .lg{display:inline-flex; align-items:center; gap:6px}
.chartlegend .lg::before{content:""; width:14px; height:2.5px; border-radius:2px}
.chartlegend .mine::before{background:var(--accent)}
.chartlegend .hold::before{background:var(--muted)}

.chartbox{position:relative; touch-action:pan-y}
#chart{display:block; width:100%; height:240px}
#chart text{dominant-baseline:auto}
#chart .axis{font:400 10.5px var(--mono); fill:var(--muted)}
#chart .l-mine{stroke:var(--accent)}
#chart .l-hold{stroke:var(--muted); stroke-dasharray:5 4; opacity:.75}
#chart .d-mine{fill:var(--accent)}
#chart .d-hold{fill:var(--muted)}

/* The readout sits over the plot so the eye does not travel to read it. */
.readout{
  position:absolute; top:0; left:0; background:var(--card);
  border:1px solid var(--rule); border-radius:9px; padding:9px 11px;
  pointer-events:none; white-space:nowrap;
  box-shadow:0 6px 20px rgba(0,0,0,.14);
}
.readout .when{font:500 11.5px var(--mono); color:var(--muted); margin-bottom:5px}
.readout .line{display:flex; align-items:center; gap:7px; font:500 13px var(--mono);
  font-variant-numeric:tabular-nums; color:var(--ink); padding:1px 0}
.readout .sw{width:11px; height:2.5px; border-radius:2px; flex:none}
.readout .sw.mine{background:var(--accent)}
.readout .sw.hold{background:var(--muted)}

@media (min-width: 900px) {
  #chart{height:300px}
  .chartcard{padding:16px 16px 12px}
}

/* ===== jobs =============================================================== */

.card.job.failed{border-left:3px solid var(--warn)}
.card.job.done{border-left:3px solid var(--ok)}
.card.job.running{border-left:3px solid var(--accent)}
.card.job .bar{
  height:6px; background:var(--paper-2, var(--rule)); border-radius:3px;
  overflow:hidden; margin-top:10px;
}
.card.job .bar span{display:block; height:100%; background:var(--accent); transition:width .4s}


/* Rule 2: long explanations fold away so the figures stay near the top.
   Warnings never fold -- an unread warning is the same as no warning. */
details.more{margin:10px 0}
details.more > summary{
  cursor:pointer; color:var(--accent); font-size:13.5px; list-style:none;
  padding:6px 0; min-height:44px; display:flex; align-items:center; gap:6px;
}
details.more > summary::-webkit-details-marker{display:none}
details.more > summary::before{content:"▸"; font-size:11px; transition:transform .15s}
details.more[open] > summary::before{transform:rotate(90deg)}
details.more .body{font-size:13.5px; line-height:1.7; color:var(--ink-2); max-width:70ch}
@media (prefers-reduced-motion: reduce){
  details.more > summary::before{transition:none}
}

/* A numbered list of sentences, not a table of figures. The stat row is for
   figures and clips long text; rules need to wrap. */
.rulelist{counter-reset:rl; margin:0}
.rulelist li{
  counter-increment:rl; list-style:none; display:grid;
  grid-template-columns:22px 1fr; gap:10px; align-items:baseline;
  padding:10px 0; border-bottom:1px solid var(--rule); line-height:1.6;
}
.rulelist li:last-child{border-bottom:0}
.rulelist li::before{
  content:counter(rl); font:600 12px/1.9 var(--mono); color:var(--accent);
}
.rulelist li.off{opacity:.5; text-decoration:line-through}

/* Small actions inside a card: sized to their label, still finger-sized. */
.chipbtn{
  background:transparent; border:1px solid var(--rule); border-radius:9px;
  color:var(--ink-2); font:500 13px/1 var(--sans); cursor:pointer;
  padding:0 14px; min-height:44px;
}
/* min-height does nothing to an inline element, so a link wearing this class
   comes out the height of the text around it. Every one of them is a target
   people are meant to hit. */
a.chipbtn{
  display:inline-flex; align-items:center; text-decoration:none;
  vertical-align:middle;
}
.chipbtn:hover{border-color:var(--accent); color:var(--accent)}
.chipbtn.danger:hover{border-color:var(--warn); color:var(--warn)}
.inlineform{display:inline}
.notetext{font-family:var(--sans); font-size:13px; color:var(--muted); line-height:1.6}
@media (min-width: 900px) { .chipbtn{min-height:36px} }


/* A model runs on several symbols and the results differ wildly. One number
   from whichever ran last is not a summary; the range is. */
.spread{
  display:flex; justify-content:space-between; gap:12px; margin-top:8px;
  font-family:var(--mono); font-size:13px; font-variant-numeric:tabular-nums;
  color:var(--muted);
}
.spread b{font-weight:600}
.spread .pos{color:var(--ok)} .spread .neg{color:var(--bad)}

/* ===== preset plans ====================================================== */

.planrun{margin-top:12px}
.planrun label{margin-top:0}
.checks{display:flex; flex-wrap:wrap; gap:8px; margin-top:6px}
.check{
  display:inline-flex; align-items:center; gap:7px; margin:0;
  border:1px solid var(--rule); border-radius:20px; padding:0 14px;
  min-height:44px; cursor:pointer; font-size:13.5px; color:var(--ink);
}
@media (min-width: 900px){ .check{min-height:38px} }
.check input{width:auto; min-height:auto; margin:0}
.check:has(input:checked){border-color:var(--accent); color:var(--accent)}
.check:has(input:disabled){opacity:.5; cursor:not-allowed}
/* 전체 selects the others rather than being one of them, so it is set apart
   by weight and a divider instead of sitting in the same row as a peer. */
.check.all{font-weight:600; margin-right:6px}
.check.all::after{
  content:""; position:absolute; margin-left:calc(100% + 6px);
  width:1px; height:20px; background:var(--rule);
}
.check.all{position:relative}

/* The grid is the point of a plan: one weak column or row should jump out. */
table.matrix{min-width:auto}
table.matrix td, table.matrix th{padding:10px 12px; text-align:right}
table.matrix td.name, table.matrix th:first-child{text-align:left; font-family:var(--sans); font-weight:500}
table.matrix td{font-size:14.5px; font-weight:500}
table.matrix td.pos{color:var(--ok)}
table.matrix td.neg{color:var(--bad)}
table.matrix td.none{color:var(--muted)}
table.matrix .star{color:var(--accent); margin-left:2px}

/* Page heading and its action sit on one line once there is room. */
.head{display:flex; justify-content:space-between; align-items:flex-end; gap:16px; flex-wrap:wrap}
.head h1{margin-bottom:2px}
.lab{font-weight:400; color:var(--muted); font-size:12px; margin-left:4px}

/* A run list is scanned down a column of numbers, so it is rows not cards. */
.runlist{border-top:1px solid var(--rule)}
/* The row is a link plus a hide button. The link cannot wrap the button,
   so the row is the container and the link fills whatever the button
   leaves. */
.runrow{
  display:flex; align-items:stretch; gap:8px;
  border-bottom:1px solid var(--rule);
}
.runmain{
  flex:1; min-width:0;
  display:grid; grid-template-columns:1fr auto; gap:2px 16px; align-items:center;
  padding:12px 4px; text-decoration:none; color:inherit;
}
.runrow:hover{background:var(--card)}
.runrow .inlineform{display:flex; align-items:center; flex:none}
.runrow .rt{font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.runrow .rm{grid-column:1; font-size:12.5px; color:var(--muted); font-family:var(--mono)}
/* The headline number and what it counts, stacked on the right so the
   title on the left keeps the whole first column. */
.runrow .rs{
  grid-column:2; grid-row:1 / span 2; text-align:right;
  display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-size:20px; color:var(--muted);
}
.runrow .rs .of{font-size:11px; white-space:nowrap}
.restorerow{display:flex; align-items:center; gap:10px; flex-wrap:wrap}
.runrow .rs b{color:var(--ink); font-weight:600}
.runrow .rs b.pos{color:var(--ok)}
.runrow .rs .of{font-size:14px}

.savedrow{
  display:grid; grid-template-columns:1fr auto; gap:2px 10px; align-items:center;
  padding:9px 0; border-top:1px solid var(--rule);
}
.savedrow .st{font-size:14px; font-weight:500}
.savedrow .sm{grid-column:1; font-size:11.5px; color:var(--muted); font-family:var(--mono)}
.savedrow form{grid-column:2; grid-row:1 / span 2}

/* Cells are links now. */
table.matrix td a{color:inherit; text-decoration:none; display:block; padding:2px 0}
table.matrix td a:hover{text-decoration:underline}
table.matrix td.flat{color:var(--muted)}

.nav .dot{
  display:inline-block; width:6px; height:6px; border-radius:50%;
  background:var(--accent); vertical-align:middle;
}

/* Buttons stacked in a panel need the gap the row gives horizontally. */
.stack-btns{display:flex; flex-direction:column; gap:8px}
.dangerzone{margin-top:20px; padding-top:16px; border-top:1px solid var(--rule)}
.panelcard form > .btn{margin-top:16px}

/* Money reads better with separators and a visible unit. */
.moneyfield{position:relative}
.moneyfield input{
  font-family:var(--mono); font-size:17px; font-variant-numeric:tabular-nums;
  text-align:right; padding-right:34px;
}
.moneyfield .unit{
  position:absolute; right:12px; top:50%; transform:translateY(-50%);
  color:var(--muted); font-size:14px; pointer-events:none;
}

.savedrow .sact{grid-column:2; grid-row:1 / span 2; display:flex; gap:6px}

/* ===== result heat strip =================================================
   Thirty-six windows in a table gives three-line headers and a row that runs
   off the screen. As blocks whose colour carries the sign and whose depth
   carries the size, the same data reads in one look. */

.heat{margin:8px 0 4px; overflow-x:auto; padding-bottom:4px}
.heatrow{display:flex; align-items:stretch; gap:10px; margin-bottom:4px; min-width:min-content}
.heatrow .rowname{
  flex:none; width:52px; align-self:center; font:600 13px var(--sans);
  position:sticky; left:0; background:var(--paper); z-index:1;
}
.heatrow .cells{display:grid; grid-template-columns:repeat(var(--cols), minmax(26px, 1fr)); gap:3px; flex:1}

.cell{
  position:relative; display:flex; align-items:center; justify-content:center;
  min-height:44px; border-radius:5px; text-decoration:none;
  font:600 11px/1 var(--mono); font-variant-numeric:tabular-nums;
  color:var(--ink); background:var(--rule);
}
.cell.up   { background:color-mix(in oklab, var(--ok)   calc(var(--mag) * 100%), transparent); }
.cell.down { background:color-mix(in oklab, var(--bad)  calc(var(--mag) * 100%), transparent); }
.cell.zero { background:var(--rule); color:var(--muted) }
.cell.na   { background:transparent; border:1px dashed var(--rule) }
.cell:hover{outline:2px solid var(--accent); outline-offset:1px}
/* Beating the do-nothing baseline is a second fact, so it gets a second mark
   rather than another colour. */
.cell.star::after{
  content:""; position:absolute; top:3px; right:3px; width:4px; height:4px;
  border-radius:50%; background:var(--accent);
}
.cell .v{opacity:.92}

.heatrow.axis{margin-top:2px}
.heatrow.axis .cells{gap:3px}
.tick{font:500 11px var(--mono); color:var(--muted); text-align:center}

.legend{
  display:flex; flex-wrap:wrap; gap:6px 18px; align-items:center;
  font-size:12.5px; color:var(--muted); margin:10px 0 22px;
}
.legend .sw{
  display:inline-block; width:12px; height:12px; border-radius:3px;
  vertical-align:-2px; margin-right:5px;
}
.legend .sw.up{background:var(--ok)} .legend .sw.down{background:var(--bad)}
.legend .sw.zero{background:var(--rule)}
.legend .sw.star{background:var(--rule); position:relative}
.legend .sw.star::after{
  content:""; position:absolute; top:1px; right:1px; width:4px; height:4px;
  border-radius:50%; background:var(--accent);
}
.legend .tip{flex-basis:100%; color:var(--muted)}

.fig .of{font-size:.62em; color:var(--muted); font-weight:400}
.runrow .rs .of{font-size:15px}
.fig .of{font-size:max(11px, .62em)}

@media (min-width: 900px){
  .heatrow .cells{grid-template-columns:repeat(var(--cols), minmax(30px, 1fr))}
  .cell{min-height:44px; font-size:12px}
}

/* ===== money summary =====================================================
   The grid counts how often the rule won. The first question is how much. */

.money{
  border:1px solid var(--rule); border-radius:12px; background:var(--card);
  padding:16px 18px; margin:6px 0 12px;
}
.money .net{display:flex; flex-direction:column; gap:4px}
.money .net .l{font-size:13px; color:var(--muted)}
.money .net .n{
  font:600 clamp(1.7rem, 6vw, 2.4rem)/1.1 var(--mono);
  font-variant-numeric:tabular-nums; letter-spacing:-.02em;
}
.money .net.pos .n{color:var(--ok)} .money .net.neg .n{color:var(--bad)}
.money .parts{
  display:flex; flex-wrap:wrap; gap:6px 22px; margin-top:12px;
  padding-top:12px; border-top:1px solid var(--rule);
  font-size:13px; color:var(--muted);
}
.money .parts b{font-family:var(--mono); font-variant-numeric:tabular-nums; font-weight:600}
.money .won b{color:var(--ok)} .money .lost b{color:var(--bad)}

.bysym{margin:0 0 20px}
.symrow{
  display:grid; grid-template-columns:60px 1fr auto; gap:12px; align-items:baseline;
  padding:9px 2px; border-bottom:1px solid var(--rule); font-size:13.5px;
}
.symrow .s{font-weight:600}
.symrow .w{color:var(--muted); font-size:12.5px}
.symrow .m{font-family:var(--mono); font-variant-numeric:tabular-nums; font-weight:600}
.symrow .m.pos{color:var(--ok)} .symrow .m.neg{color:var(--bad)}

/* ===== number tiles =======================================================
   A row of headline figures. The grid supplies the gap and every tile takes
   a full track, so the tiles stay the same width and their labels sit on one
   baseline however long the wording is. */
.figs{
  display:grid; gap:12px; margin:0 0 12px;
  grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
}
.fig{
  background:var(--card); border:1px solid var(--rule); border-radius:var(--radius);
  padding:14px; margin:0;
  display:flex; flex-direction:column; justify-content:space-between; gap:6px;
}
.fig .n, .fig .v{
  font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-size:28px; font-weight:600; line-height:1.1; letter-spacing:-.01em;
}
.fig .l, .fig .k{color:var(--muted); font-size:13px; line-height:1.35}
.fig .s{color:var(--muted); font-family:var(--mono); font-size:12px}
/* The label comes first when the tile leads with it, so the number still
   sits at the bottom edge of every tile in the row. */
.fig .k{order:-1}
.fig .pos, .fig .n.good{color:var(--ok)}
.fig .neg, .fig .n.bad{color:var(--bad)}
@media (min-width: 900px){
  .fig .n, .fig .v{font-size:32px}
}


/* ===== pager =============================================================
   Ends of the range stay in place as dimmed text rather than disappearing,
   so the row does not shift under the finger on the first and last page. */
.pager{display:flex; align-items:center; gap:10px; margin:14px 0}
/* Above a list it needs the gap on the other side. */
.cardgrid + .pager{margin-top:14px}
.pager + .cardgrid{margin-top:12px}
.pager .where{
  font-family:var(--mono); font-size:13px; color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.pager .chipbtn{text-decoration:none; display:inline-flex; align-items:center}
.pager .chipbtn.off{opacity:.4; cursor:default}


/* ===== choice sheet: compact list ========================================
   Every entry is one line so the whole set is visible at once, and the
   explanation for the entry under the pointer is shown in a fixed place at
   the bottom instead of once per row. */
/* The box stays put while the list scrolls under it, so narrowing the list
   never means scrolling back up first. */
.sheetsearch{
  position:sticky; top:0; z-index:1;
  width:100%; margin:0 0 12px; min-height:44px; padding:0 12px;
  border:1px solid var(--rule); border-radius:8px;
  background:var(--paper); color:var(--ink); font-size:15px;
}
.sheetsearch:focus-visible{outline:2px solid var(--accent); outline-offset:1px}
.optgrid{display:grid; gap:0 18px; grid-template-columns:1fr}
@media (min-width: 640px){ .optgrid{grid-template-columns:1fr 1fr} }
/* A wide list of choices needs the room; the small sheets stay narrow. */
@media (min-width: 900px){
  .sheet .panel:has(.optgrid){width:min(760px, 92vw)}
  .optgrid{grid-template-columns:1fr 1fr 1fr}
}
.optgrid .opt{min-height:44px}
/* With a pointer there is no finger to fit, so the rows close up and the
   whole set fits a short laptop window without scrolling. */
@media (min-width: 900px){
  .optgrid .opt{min-height:38px; padding:6px 2px}
  .sheet .group{margin:12px 0 2px}
  .sheet .panel:has(.optgrid){padding-top:14px}
  .sheetwhy{margin-top:10px; padding-top:10px}
}
.sheetwhy{
  position:sticky; bottom:0; background:var(--card);
  margin:14px 0 0; padding-top:12px; border-top:1px solid var(--rule);
  color:var(--muted); font-size:13px; line-height:1.55;
  box-sizing:content-box; overflow:hidden;
}
.sheetwhy:not(.on){color:transparent}
.sheet .empty{padding:20px 2px; color:var(--muted); font-size:14px}


/* ===== symbol list =======================================================
   A management list is scanned, not read: one line each, with the ticker and
   the state first because those are what the eye is looking for. */
.symlist{border-top:1px solid var(--rule); margin-bottom:12px}
.symrow2{
  display:grid; align-items:center; gap:4px 10px;
  grid-template-columns:auto auto 1fr;
  padding:10px 4px; border-bottom:1px solid var(--rule);
}
.symrow2 .t{font-family:var(--mono); font-weight:600; font-size:15px}
.symrow2 .b{
  font-family:var(--mono); font-size:12px; color:var(--muted);
  font-variant-numeric:tabular-nums; text-align:right;
}
.symrow2 .n{
  grid-column:1 / -1; color:var(--muted); font-size:12.5px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.symrow2 .a{grid-column:1 / -1; display:flex; gap:6px; flex-wrap:wrap}
@media (min-width: 900px){
  .symrow2{grid-template-columns:78px auto 84px 1fr auto}
  .symrow2 .n{grid-column:auto; min-width:0}
  .symrow2 .a{grid-column:auto; flex-wrap:nowrap}
}


/* A running job shows its progress where the buttons sit on the other rows,
   so the column keeps one width and the rows stay aligned. */
.symrow2 .a .bar{
  display:block; width:120px; height:6px; border-radius:3px;
  background:var(--rule); overflow:hidden;
}
.symrow2 .a .bar > span{display:block; height:100%; background:var(--accent)}
.symrow2.failed .t{color:var(--bad)}


/* A link buried in a sentence is the size of the sentence. When a notice
   offers somewhere to go, the link becomes a target you can hit. */
.warn.withaction, .good.withaction{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  justify-content:space-between;
}
.warn.withaction .chipbtn, .good.withaction .chipbtn{
  text-decoration:none; flex:none;
}


/* The trade log is read down a column, so the times and the money line up. */
table .when{font-family:var(--mono); font-size:12.5px; color:var(--muted); white-space:nowrap}
table .sub2{color:var(--muted); font-size:12px}

/* A hint that has turned into a warning still reads as a hint unless it
   says so in something other than words. */
.hint.bad{color:var(--bad)}


/* The grid is read across, and the pairs have to be read down. A label row
   between groups is what makes the second reading possible. */
.heatrow.grouphead{margin-top:10px}
.heatrow.grouphead:first-child{margin-top:0}
.heatrow.grouphead .rowname{
  color:var(--ink-2); font-family:var(--sans); font-weight:600; font-size:12px;
}
.heatrow.grouphead .cells{display:flex; align-items:center}
.heatrow .alone{color:var(--warn); font-size:11.5px; white-space:nowrap}


/* The money list groups the same way the grid does, so the pair can be read
   against each other here too. */
.symgroup{
  color:var(--ink-2); font-size:12px; font-weight:600;
  margin:14px 0 2px; padding-top:8px; border-top:1px solid var(--rule);
}
.symgroup:first-child{margin-top:0; padding-top:0; border-top:0}


/* The conditions of a run, read down as label and value. */
.factlist{display:grid; gap:10px}
.fact{display:grid; grid-template-columns:100px 1fr; gap:12px; align-items:baseline}
.fact .k{color:var(--muted); font-size:13px}
.fact .v{font-size:14.5px; min-width:0}
.fact .v .sub2{display:block; color:var(--muted); font-size:12.5px; margin-top:2px}
@media (min-width: 900px){
  .factlist{gap:8px}
  .fact .v .sub2{display:inline; margin-left:8px}
}


/* ===== printing ==========================================================
   Print is a second layout, not a screenshot. Everything that only exists to
   be clicked comes out, the palette flips to ink on paper because a dark
   page prints as a solid block, and the grid is allowed to break across
   pages at a row boundary rather than mid-row. */
.printonly{display:none}

@media print {
  :root{
    --paper:#fff; --card:#fff; --ink:#111; --ink-2:#333; --muted:#555;
    --rule:#bbb; --accent:#245; --ok:#1a5c2a; --bad:#8c2b1c;
  }
  html, body{background:#fff !important; color:#111 !important}
  /* Keep the meaning of the heat cells; browsers drop backgrounds by
     default and the grid becomes unreadable. */
  *{-webkit-print-color-adjust:exact !important; print-color-adjust:exact !important}

  header.bar, .nav, .backlink, .row, .legend .tip,
  .sheet, .dangerzone, form{display:none !important}
  .printonly{
    display:block; font:600 12px var(--mono); color:#555;
    letter-spacing:.08em; margin-bottom:6px;
  }
  .wrap{max-width:none; padding:0}
  h1{font-size:22px}
  h2{page-break-after:avoid; margin-top:18px}
  .card, .money, .factlist{page-break-inside:avoid}
  .heatrow{page-break-inside:avoid}
  .symrow, .symgroup{page-break-inside:avoid}
  a{color:inherit; text-decoration:none}
  .tablewrap{overflow:visible}
  @page{margin:14mm}
}


/* Import screen: a big plain box for text that is read by a machine. */
textarea{
  width:100%; min-height:220px; padding:12px; border-radius:10px;
  border:1px solid var(--rule); background:var(--card); color:var(--ink);
  font:13px/1.6 var(--mono); resize:vertical;
}
pre.code{
  margin:0; padding:12px; border-radius:8px; background:var(--paper);
  border:1px solid var(--rule); font:12.5px/1.6 var(--mono);
  color:var(--ink-2); overflow-x:auto;
}
code{font-family:var(--mono); font-size:.92em}
.filepick{display:inline-flex; align-items:center; cursor:pointer; margin:0}


/* ===== API docs ==========================================================
   Two renderings of one document: Swagger for trying a call, and a plain
   list for reading on paper. Only one is visible at a time. */
.swaggerbox{margin-top:16px}
.swaggerbox .topbar, .swaggerbox .information-container{display:none}
.swaggerbox .swagger-ui{font-family:var(--sans)}
.apiplain{display:none}
.apiop{
  border-top:1px solid var(--rule); padding:12px 0;
  page-break-inside:avoid; break-inside:avoid;
}
.apihead{display:flex; gap:10px; align-items:baseline; flex-wrap:wrap}
.apihead code{font-size:14px; font-weight:600}
.apihead .m{
  font:600 11px var(--mono); letter-spacing:.06em; padding:2px 7px;
  border-radius:5px; border:1px solid var(--rule); color:var(--muted);
}
.apihead .m.get{color:var(--accent)}
.apihead .m.post{color:var(--ok)}
.apisum{margin-top:5px; font-size:14px}
.apidesc{margin-top:4px; color:var(--muted); font-size:13px; line-height:1.6;
  max-width:70ch; white-space:pre-wrap}
.apirow{display:grid; grid-template-columns:82px 1fr; gap:10px; margin-top:6px}
.apirow .k{color:var(--muted); font-size:12.5px}
.apirow .v{font-size:13px; min-width:0}
.apirow .v i{color:var(--muted); font-style:normal; font-size:12px}
.apinote{color:var(--muted); font-size:13.5px; line-height:1.7;
  max-width:70ch; white-space:pre-wrap}

@media print {
  .swaggerbox{display:none !important}
  .apiplain{display:block !important}
}


/* Notes on a model: what was being tried, and why. */
.notelist{display:grid; gap:10px; margin-bottom:12px}
.notecard{
  display:grid; grid-template-columns:1fr auto; gap:4px 10px;
  background:var(--card); border:1px solid var(--rule);
  border-radius:var(--radius); padding:12px 14px;
}
.notecard .when{
  grid-column:1; font-family:var(--mono); font-size:12px; color:var(--muted);
}
.notecard .body{grid-column:1; white-space:pre-wrap; line-height:1.65; max-width:70ch}
.notecard .inlineform{grid-column:2; grid-row:1 / span 2}


/* ===== pull to refresh ====================================================
   Sits above the top edge and is dragged into view. Nothing about it exists
   until a finger moves, so a mouse never sees it. */
.pull{
  position:fixed; top:0; left:0; right:0; z-index:60;
  display:flex; align-items:center; justify-content:center;
  height:56px; margin-top:-56px; pointer-events:none;
  color:var(--muted); font-size:13px; opacity:0;
  transition:opacity .12s linear;
}
.pull.on{opacity:1}
.pull .pulltext{
  padding:7px 14px; border-radius:999px;
  background:var(--card); border:1px solid var(--rule);
  box-shadow:0 6px 18px rgba(0,0,0,.16);
}
.pull.ready .pulltext{color:var(--accent); border-color:var(--accent)}
.pull.busy .pulltext{color:var(--accent)}


/* The one number that lets two models be compared, so it is the largest
   thing on the card after the name. The pair below it is the spread across
   symbols, which is a different question and stays small. */
.card .yearly{
  margin-top:8px; font-family:var(--mono); font-variant-numeric:tabular-nums;
  font-size:26px; font-weight:600; line-height:1.1; letter-spacing:-.01em;
}
.card .yearly .u{
  font-family:var(--sans); font-size:12px; font-weight:400;
  color:var(--muted); margin-left:7px; letter-spacing:0;
}
.card .yearly.pos{color:var(--ok)}
.card .yearly.neg{color:var(--bad)}


/* Finding one model among a hundred. The box takes the room; the order and
   the buttons take what they need. */
.findbar{
  display:flex; gap:8px; flex-wrap:wrap; align-items:stretch; margin-bottom:12px;
}
.findbar input[type=search]{
  flex:1 1 160px; min-width:0; min-height:44px; padding:0 12px;
  border:1px solid var(--rule); border-radius:10px;
  background:var(--card); color:var(--ink); font-size:15px;
}
.findbar select{flex:0 1 auto; min-height:44px; width:auto; padding-block:0}
.findbar .chipbtn{flex:none; text-decoration:none;
  display:inline-flex; align-items:center}
@media (min-width: 900px){
  .findbar input[type=search], .findbar select{min-height:38px}
}


/* A control that is working. Not greyed out: it is still the thing that was
   pressed, it just cannot be pressed again. */
.btn.busy, .chipbtn.busy{opacity:.72; cursor:progress}


/* ===== the model list on a phone =========================================
   A screenshot of 165 models showed two and a half cards: a third of the
   screen went on a heading, a sentence, three buttons and a search row
   before the first card. The list is the page; everything above it is
   getting to the list. */
.widescreen{display:none}
@media (min-width: 620px){ .widescreen{display:inline-flex} }

@media (max-width: 619px){
  /* The heading already says what the page is. */
  .head p.sub{display:none}
  .head{align-items:center; gap:10px; margin-bottom:10px}
  .head h1{margin-bottom:0}
  /* Searching is what you do after scrolling a while, so it comes with you
     rather than waiting at the top. */
  .findbar{
    /* Below the bar, which is sticky too. At top:0 it spent the whole
       scroll hidden behind it. */
    position:sticky; top:var(--barh, 0px); z-index:3; margin-bottom:10px;
    padding:8px 0; background:var(--paper);
    box-shadow:0 1px 0 var(--rule);
  }
  /* All three on one row. The submit had been wrapping onto a line of its
     own, spending a whole row on one small button. */
  .findbar input[type=search]{flex:1 1 90px; min-height:40px}
  .findbar select{min-height:40px; max-width:46%}
  .findbar .chipbtn{padding:0 12px}
  .cardgrid{gap:10px}
  .cardgrid .card{padding:12px}
  .card .yearly{font-size:24px; margin-top:6px}
}

/* Which of the two is the low one. Small, because the number is the point
   and the word is only there to stop it being read the wrong way round. */
.spread i{
  font-style:normal; font-family:var(--sans); font-size:11px;
  color:var(--muted); margin-right:3px;
}
.card .meta b{font-weight:600; color:var(--ink)}
.card .meta b.allpos{color:var(--ok)}


/* ===== a menu inside the bar ==============================================
   Two reports, with more to come. A row of links along a bar that already
   scrolls sideways on a phone would push the rest off the edge. */
/* Not called `.sheet`: that name already belongs to the dialog the rule
   picker opens, whose rules gave this box a fourteen-pixel height and no
   visible panel at all. */
/* Deliberately not `relative`. The navigation scrolls sideways on a phone,
   and an overflow container clips anything whose containing block is inside
   it — the menu opened and nothing appeared. Left static, the sheet anchors
   to the bar instead, which clips nothing. */
.nav details.menu{position:static}
.nav details.menu > summary{
  list-style:none; cursor:pointer;
  color:var(--muted); font-size:14px; font-weight:500;
  padding:8px 12px; border-radius:8px; white-space:nowrap; min-height:38px;
  display:inline-flex; align-items:center; gap:6px;
}
.nav details.menu > summary::-webkit-details-marker{display:none}
.nav details.menu > summary::after{
  content:""; width:5px; height:5px; margin-top:-3px;
  border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor;
  transform:rotate(45deg); opacity:.7;
}
.nav details.menu > summary:hover{color:var(--ink); background:var(--card)}
.nav details.menu[open] > summary{color:var(--accent); background:var(--card)}
.nav details.menu .reportmenu{
  position:absolute; top:calc(100% + 4px); z-index:20;
  left:max(16px, env(safe-area-inset-left));
  min-width:190px; padding:6px;
  background:var(--card); border:1px solid var(--rule); border-radius:10px;
  box-shadow:0 8px 24px rgba(0,0,0,.14);
  display:flex; flex-direction:column; gap:2px;
}
.nav details.menu .reportmenu a{width:100%}


/* ===== choosing the years =================================================
   Fifteen years of daily bars is several market regimes. Picking the years
   is how a stretch is held back rather than quietly averaged in, so the
   control has to be as easy to reach as the bar length above it. */
.years{margin-top:6px}
.yearbtns{display:flex; gap:6px; margin-bottom:8px}
.yearlist{display:flex; flex-wrap:wrap; gap:6px}
.yearlist .check{
  font-family:var(--mono); font-variant-numeric:tabular-nums; padding:0 10px;
}
.yearlist .check.off{opacity:.35}
.yearlist .check.off input{cursor:not-allowed}


/* ===== the fold: what a model learned from, what will judge it ==========
   One row, read left to right like the sentence it is: learned on these
   years, judged on that one, and whether the answer has been looked at. */
.fold .foldrow{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  font-family:var(--mono); font-variant-numeric:tabular-nums;
}
.fold .foldrow .k{color:var(--muted); font-size:12px; font-family:var(--sans)}
.fold .foldrow .arrow{color:var(--muted)}
.fold .foldrow b{font-weight:600}
.fold.sealed{border-left:3px solid var(--warn)}
.fold.open{border-left:3px solid var(--ok)}
.fold.binned{border-left:3px solid var(--rule); opacity:.8}
.fold .row{margin-top:10px}
.pill.warn{background:var(--warn-bg); color:var(--warn)}


/* ===== the demo: one cycle, pressable ====================================
   A row of numbered steps that reads as a sentence, and one pane open at a
   time. The parts inside the panes are the real screens' parts. */
.steps{
  display:flex; flex-wrap:wrap; gap:6px; list-style:none; padding:0;
  margin:0 0 14px; font-size:13px;
}
.steps li{
  display:inline-flex; align-items:center; gap:6px; padding:6px 10px;
  border:1px solid var(--rule); border-radius:999px; color:var(--muted);
}
.steps li b{
  font-family:var(--mono); font-weight:600; font-size:11px;
  width:18px; height:18px; border-radius:50%; display:inline-grid;
  place-items:center; border:1px solid currentColor;
}
.steps li.on{color:var(--accent); border-color:var(--accent); background:var(--card)}
.steps li.done{color:var(--ok); border-color:var(--ok)}
.demo .card + .card{margin-top:12px}
.demo textarea{
  width:100%; min-height:56px; padding:10px 12px; border:1px solid var(--rule);
  border-radius:10px; background:var(--card); color:var(--ink);
  font:inherit; font-size:14px; resize:vertical;
}
.rulelist li.changed{background:var(--ok-bg); border-radius:6px; padding:2px 6px; margin-left:-6px}
.rulelist li .of, .yearlist .of{font-size:11px; color:var(--muted); margin-left:4px}
.hint.warntext{color:var(--warn)}

/* A line of text beside a chip: centred on each other, not on the baseline,
   or the chip sits six pixels below the words. */
.demofoot{display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin-top:14px}
.demofoot .hint{margin:0}

/* Two month pickers side by side; one under the other on a phone. */
.months{display:flex; gap:12px; flex-wrap:wrap; margin-top:10px}
.months label{flex:1 1 160px; margin-top:0}
.months input[type=month]{
  display:block; width:100%; min-height:44px; padding:0 12px; margin-top:4px;
  border:1px solid var(--rule); border-radius:10px; background:var(--card);
  color:var(--ink); font-size:15px;
}

/* The scope chip at its default reads as part of the sentence, not a
   setting: dimmed until it says something other than "언제나". */
.chip.dim{opacity:.55}

/* The "add a condition" button sits under the sentence, small, because a
   second condition is the exception and the sentence is the thing. */
.condadd{margin-top:8px}
