
:root{
  /* The wordmark only. Coinbase Sans is custom and not licensable; Plus
     Jakarta Sans is the closest widely available face - geometric, low
     contrast, open apertures, slightly wide. */
  --brandfont:'Plus Jakarta Sans','Inter var','Inter',-apple-system,sans-serif;
  --font:'Inter var','Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',
        Helvetica,Arial,sans-serif;
  --mono:ui-monospace,'SF Mono',SFMono-Regular,Menlo,monospace;
  /* Money and metrics are not code. SF Mono and Menlo both slash their
     zeros, which is right in a terminal and wrong in a table - it reads as
     a struck-through value or an error state. The sans face with tabular
     figures aligns columns just as well and looks like a number. */
  --num:var(--font);
  --bg:#ffffff; --raise:#f6f7f9; --line:#e6e8ec; --line2:#d3d7dd;
  /* var(--ink3) on white is ~3.5:1 - below the 4.5:1 body-text threshold, and
     it reads as disabled rather than secondary. ink3 is now for structural
     hints only (table headers, placeholders); prose uses ink2. */
  /* Grey is not used for prose. Twice it read as disabled rather than
     secondary, and the fix is not another notch darker - it is that
     secondary text is still text. ink2 is near-black and carries all copy;
     ink3 exists only for input placeholders and table column headers, where
     lightness means "not content yet" rather than "less important". */
  --ink:#14161a; --ink2:#5b6270; --ink3:#8b9098;
  /* ACCENT. This was var(--ink) — the token existed and pointed at the same
     black as everything else, used once, so the product was monochrome by
     omission rather than by decision. That is most of why it read as
     unfinished: nothing on the page was ever the colour of "do this".

     One token. Change this line and every primary action, link, focus ring
     and active tab moves with it. */
  --accent:#3b5bdb; --accent-ink:var(--bg); --accent-soft:#e8ecfd;
  /* Selected, without colour: used where an accent would be too loud
     for a thing you merely picked. Referenced with a literal
     fallback in a dozen places and never actually defined. */
  --sel:#eef1f6;
  --accent-hover:#2f49b8;
  --ok:#16794a; --warn:#a45c07; --bad:#b42318;
  --ok-soft:#e7f6ee; --warn-soft:#fdf3e2; --bad-soft:#fdeceb;

  /* TYPE SCALE. There were fourteen font sizes in this file — 13.5, 12.5,
     11.5, 14.5 — because every surface decided locally and none of them
     agreed. Five, named for their job. */
  --t-display:26px;   /* page title */
  --t-head:17px;      /* section heading */
  --t-body:14px;      /* everything you read */
  --t-small:13px;     /* secondary, table cells */
  --t-meta:11.5px;    /* labels, units, timestamps */

  /* SPACE. Forty distinct paddings became six steps. A layout with no
     rhythm reads as floating, which is the complaint this answers. */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:36px;

  /* Corners: three, named for the thing. Twelve distinct radii were in
     play — 2, 7, 8, 10, 12, 14, 20, 22 — so a card, a button and an
     input all rounded differently. */
  /* Tokens the components need, named for their job rather than their
     value — which is what makes a second theme possible at all. Before
     this there were forty-seven hardcoded colours in the stylesheet, and
     any theme would have reached about half the product. */
  --ok-line:#cfe7db; --warn-line:#f0e2c6; --bad-line:#f5dad7;
  --term-bg:#0e1013; --term-ink:#e8eaed; --term-dim:#8b929c; --term-bad:#f87171;
  --series-1:#3b41a8; --series-1-soft:#dcdff5;
  --series-2:#12724a; --series-3:#8a5416;

  --r-sm:6px;    /* inputs, chips, small controls */
  --r:10px;      /* cards, panels, the editor */
  --r-lg:14px;   /* nothing yet; reserved for a modal */
  --r-pill:99px;
  /* A hairline plus a barely-there shadow, rather than a heavier border.
     Borders everywhere is what makes a page look like a form. */
  --shadow:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
  --shadow-lift:0 4px 16px rgba(16,24,40,.10);
  --shadow-accent:0 3px 12px rgba(59,91,219,.28);
}

/* ---- dark ----
   Follows the system by default and can be forced with data-theme, because
   a developer tool that is white at 1am is a tool people complain about.
   Every value here is a token that already exists: the work was not the
   palette, it was getting the forty-seven literals out of the components
   first. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]){
    --bg:#0c0d0f; --raise:#141619; --line:#22252a; --line2:#2e3238;
    --ink:#f2f3f5; --ink2:#c8cbd1; --ink3:#8b9098;
    --sel:#1c1f24;
    --accent:#7c8cf8; --accent-ink:#0c0d0f; --accent-soft:#1c2140;
    --accent-hover:#93a0fa;
    --ok:#4ade80; --ok-soft:#12241a; --ok-line:#1f4030;
    --warn:#fbbf24; --warn-soft:#241d0e; --warn-line:#453516;
    --bad:#f87171; --bad-soft:#2a1414; --bad-line:#4a2020;
    --term-bg:#08090b; --term-ink:#e8eaed; --term-dim:#8b929c; --term-bad:#f87171; --term-bad:#f87171;
    --series-1:#818cf8; --series-1-soft:#232748;
    --series-2:#4ade80; --series-3:#fbbf24;
    --shadow:0 1px 2px rgba(0,0,0,.4),0 1px 3px rgba(0,0,0,.3);
    --shadow-lift:0 4px 16px rgba(0,0,0,.5);
    --shadow-accent:0 3px 12px rgba(124,140,248,.3);
  }
}
[data-theme=dark]{
  --bg:#0c0d0f; --raise:#141619; --line:#22252a; --line2:#2e3238;
  --ink:#f2f3f5; --ink2:#c8cbd1; --ink3:#8b9098;
  --sel:#1c1f24;
  --accent:#7c8cf8; --accent-ink:#0c0d0f; --accent-soft:#1c2140;
  --accent-hover:#93a0fa;
  --ok:#4ade80; --ok-soft:#12241a; --ok-line:#1f4030;
  --warn:#fbbf24; --warn-soft:#241d0e; --warn-line:#453516;
  --bad:#f87171; --bad-soft:#2a1414; --bad-line:#4a2020;
  --term-bg:#08090b; --term-ink:#e8eaed; --term-dim:#8b929c; --term-bad:#f87171;
  --series-1:#818cf8; --series-1-soft:#232748;
  --series-2:#4ade80; --series-3:#fbbf24;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 1px 3px rgba(0,0,0,.3);
  --shadow-lift:0 4px 16px rgba(0,0,0,.5);
  --shadow-accent:0 3px 12px rgba(124,140,248,.3);
}
:root{
  color-scheme:light dark;
  --ring:0 0 0 3px var(--accent-soft);
}
*{box-sizing:border-box}
/* Safari keeps native control styling unless appearance is cleared, so every
   custom button rendered as a blue system button there. It was visible on the
   survey pills and quietly wrong on the choice and amount cards too. */
button,input:not([type=checkbox]):not([type=radio]),select,textarea{
  -webkit-appearance:none;appearance:none;font-family:inherit}
/* Checkboxes keep their native box: clearing appearance leaves nothing to
   click, which is how the terms checkbox became invisible. */
input[type=checkbox],input[type=radio]{accent-color:var(--ink);cursor:pointer}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--ink);font-family:var(--font);
  font-size:var(--t-body);line-height:1.55;-webkit-font-smoothing:antialiased;
  letter-spacing:-0.011em}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline;text-underline-offset:2px;opacity:1}
/* Structural links — nav, cards, table rows — are not prose links and
   must not all turn blue. */
/* Containers do not turn blue; LINKS do. `.rall` is "all runs" — a real
   link that this list once flattened into grey text beside grey text, which
   is the whole reason nobody could tell it was clickable. */
a.plain,a.tab,a.rcard,a.trow,.brand,.tabs a,.sso a,.menu a,
.rowlist > a,.btn,.card > a{color:inherit}
a.plain:hover,a.tab:hover,a.rcard:hover,a.trow:hover,
.brand:hover,.tabs a:hover,.sso a:hover,.menu a:hover,
.rowlist > a:hover{text-decoration:none}
/* The wordmark is ink, always. It is the one element on the page that must
   not move when --accent does. */
.brand,.brand:hover{color:var(--ink)}
/* The brand above a chromeless page. Sign-in, sign-up, OAuth and every
   welcome step rendered with top="", so the first screens anyone sees
   carried no mark at all. */
.authtop{display:flex;justify-content:center;padding:var(--s5) 0 0}
.authtop .brand{font-size:var(--t-head);gap:9px}
/* Tight to the card beneath it. .authtop's own padding used to stack on top
   of .wizard's 60px margin, putting the mark a hundred and twenty pixels
   above the thing it belongs to — which reads as a stray element rather
   than a lockup. */
/* EVERY chromeless container, not just .wizard. The sign-in and sign-up
   pages use .auth, which kept its own 76px margin on top of the mark's
   padding — so the logo floated a quarter of the screen above the card it
   belongs to. Naming one container and assuming the rest matched is how
   this survived being "fixed". */
.authtop + .wizard,.authtop + .auth,.authtop + .card,
.authtop ~ .wizard,.authtop ~ .auth{margin-top:var(--s5)}
code,.mono{font-family:var(--mono);font-size:var(--t-small)}
/* Turn off the slashed zero. It exists so 0 and O are distinguishable in
   source code; in a money column there are no letters to confuse it with, and
   it reads as a rendering fault. */
.num,.cost,.mono,code,.ins b,.stat div b,.metric b,.kv b,.amount b{
  font-feature-settings:"zero" 0,"ss01" 0;font-variant-numeric:tabular-nums}

/* Two different jobs, two different widths.
   
   1040px everywhere meant a wide monitor showed a narrow column floating in
   the middle, and the top bar inherited it - so the logo started somewhere in
   the middle of nowhere rather than at the edge of the window, which is where
   every application puts it.
   
   Chrome spans the window. Content stays readable: a line of prose past ~75
   characters is harder to read, not easier, so the cap on text is deliberate.
   Tables and grids get more room because they have columns to fill. */
.shell{max-width:1320px;margin:0 auto;padding:0 var(--s6)}
/* 840px was wrong. The reasoning — "a page you fill in wants a column" — is
   true of a signup card and false of an application: on a wide monitor it
   put the whole product into a third of the window with dead space either
   side, which no dashboard does. The app fills the frame; the READING
   MEASURE belongs on prose, not on the layout. */
main > .shell{max-width:1280px}
main > .shell.wide{max-width:1440px}
main .sub,main .shint,main .hint2{max-width:76ch}
.topbar .shell{max-width:none;padding:0 24px}

/* Prose keeps a comfortable measure even when the page is wide. */
h1 + .sub,h2 + .sub,.sub{max-width:70ch}
.topbar{border-bottom:1px solid var(--line);background:var(--bg);
  position:sticky;top:0;z-index:10}
.topbar .shell{display:flex;align-items:center;gap:28px;height:60px;
  max-width:none;padding:0 24px}
.brand{font-family:var(--brandfont);display:flex;align-items:center;gap:9px;font-weight:600;
  letter-spacing:-0.02em;font-size:16px}
/* ---- the sidebar ----
   Every product in this category — E2B, Daytona, Modal — puts navigation on
   the left. Four tabs across the top is a marketing-site shape wearing an
   application's clothes: it caps the nav at what fits on one line, and it
   spends the widest axis of the screen on five words. */
.side{position:fixed;left:0;top:0;bottom:0;width:224px;z-index:20;
  border-right:1px solid var(--line);background:var(--raise);
  overflow-y:auto}
.sidein{display:flex;flex-direction:column;height:100%;
  padding:var(--s4) var(--s3);gap:var(--s2)}
.side .brand{padding:var(--s2) var(--s3) var(--s4);font-size:var(--t-head)}
.nav{display:flex;flex-direction:column;gap:1px}
.nav a{display:flex;align-items:center;gap:10px;padding:7px var(--s3);
  border-radius:var(--r-sm);font-size:var(--t-small);color:var(--ink2);
  white-space:nowrap}
.nav a:hover{background:var(--bg);color:var(--ink)}
.nav a.on{background:var(--accent-soft);color:var(--accent);font-weight:600}
.nav a .ico{flex:0 0 auto}
/* The account group sits at the bottom, separated, because it is where you
   go once a day rather than every minute. */
.navlow{border-top:1px solid var(--line);padding-top:var(--s2);
  margin-top:var(--s2)}
.navlow a{font-size:var(--t-meta);color:var(--ink3)}

main.app{margin-left:224px}
@media (max-width:900px){
  .side{position:static;width:auto;height:auto;border-right:0;
    border-bottom:1px solid var(--line)}
  .sidein{flex-direction:row;align-items:center;flex-wrap:wrap;
    padding:var(--s2) var(--s4)}
  .side .brand{padding:0 var(--s4) 0 0}
  .nav{flex-direction:row}
  .navlow{border-top:0;padding-top:0;margin-top:0}
  main.app{margin-left:0}
}
/* Account things live behind the avatar, where every product puts them.
   Eight top-level tabs is a menu nobody scans; four is a menu you read. */
.acct{position:relative}
.avatar{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s2) var(--s3);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--bg);
  cursor:pointer;font:inherit;font-size:var(--t-small);color:var(--ink)}
.avatar:hover{background:var(--raise)}
.avatar i{display:flex;width:26px;height:26px;border-radius:50%;
  background:var(--ink);color:var(--bg);align-items:center;justify-content:center;
  font-size:var(--t-meta);font-weight:600;font-style:normal}
.menu{position:absolute;left:0;bottom:calc(100% + var(--s2));min-width:212px;
  background:var(--bg);border:1px solid var(--line2);border-radius:var(--r);
  box-shadow:var(--shadow-lift);padding:6px;z-index:40;display:none}
.acct[open] .menu,.menu.on{display:block}
.menu .who{padding:10px 12px 12px;border-bottom:1px solid var(--line);
  margin-bottom:6px}
.menu .who b{display:block;font-size:var(--t-small);font-weight:600}
.menu .who span{font-size:var(--t-meta);color:var(--ink2);word-break:break-all}
.menu a{display:flex;align-items:center;gap:10px;padding:9px 12px;
  border-radius:var(--r-sm);font-size:var(--t-small);color:var(--ink)}
.menu a:hover{background:var(--raise);opacity:1}
.menu a svg{color:var(--ink2)}
.menu .sep{height:1px;background:var(--line);margin:6px 0}
.tabs a{padding:7px 12px;border-radius:var(--r-sm);color:var(--ink2);font-size:var(--t-body);
  font-weight:500;display:flex;align-items:center;gap:7px}
.tabs a:hover{background:var(--raise);color:var(--ink2);opacity:1}
.tabs a.on{background:var(--accent-soft);color:var(--accent);
  font-weight:600}
.spacer{flex:1}

main{padding:var(--s6) 0 80px}
/* Rhythm, on the space scale. Section headings were the SAME SIZE as body
   text, so nothing on the page announced a new idea — which is most of what
   "it just floats" describes. */
h1{font-size:var(--t-display);font-weight:600;letter-spacing:-0.025em;
  margin:0 0 var(--s1)}
h2{font-size:var(--t-head);font-weight:600;letter-spacing:-0.015em;
  margin:var(--s6) 0 var(--s3)}
h2:first-of-type{margin-top:var(--s5)}
.sub{color:var(--ink2);font-size:var(--t-body);margin:0 0 var(--s5);
  line-height:1.55}

/* A card that is a LINK responds; a card that is a container does not.
   `.node` and `.rcard` had hovers; `.card` used as a link had none, so half
   the clickable surfaces on the product were inert. */
a.card:hover,.card > a:hover{border-color:var(--ink3)}
.card{background:var(--bg);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;box-shadow:var(--shadow)}
.card-p{padding:var(--s5)}
.card+.card{margin-top:var(--s4)}

/* DENSITY. Rows were 13px/18px with 14px text, which is comfortable for
   twelve rows and wasteful at two hundred: a table you have to scroll to
   read four values is a table that shows you less. Tighter rows, smaller
   cells, headers that stop shouting. */
table{width:100%;border-collapse:collapse}
th{text-align:left;font-size:var(--t-meta);font-weight:500;color:var(--ink3);
  padding:var(--s2) var(--s4);background:transparent;
  border-bottom:1px solid var(--line);letter-spacing:.02em;
  text-transform:none}
td{padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);
  font-size:var(--t-small);line-height:1.45}
tr:last-child td{border-bottom:none}
tbody tr:hover{background:var(--raise)}

/* ONE STATUS COMPONENT.
   There were five — dot, rdot, tpill, pill, stg — each styled where it was
   first needed, which is how `.tpill.live` came to inherit the run page's
   black cost bar and render green-on-black. A status is a dot and a word,
   the same everywhere, and its colour means the same thing on every page. */
   The canonical one is `.st`, defined below with the
   status colours and the pulse. */

/* A tag is NOT a status: no colour, no dot, just a bounded label. Mixing the
   two is why "not saved" and "1 running" looked like the same kind of
   thing. */
.tag{display:inline-flex;align-items:center;font-size:var(--t-meta);
  padding:1px 7px;border-radius:var(--r-pill);border:1px solid var(--line2);
  color:var(--ink3);white-space:nowrap}
.tag.accent{border-color:var(--accent);color:var(--accent);
  background:var(--accent-soft)}

/* One row. The task list, the runs list and anything else that is a list of
   things you click. */
.rowlist{border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);overflow:hidden;background:var(--bg)}
.rowlist > a,.rowlist > div{display:grid;gap:var(--s3);align-items:center;
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);
  color:inherit;text-decoration:none}
.rowlist > a:last-child,.rowlist > div:last-child{border-bottom:0}
.rowlist > a:hover{background:var(--raise)}
.num{text-align:right;font-variant-numeric:tabular-nums;font-family:var(--num);
  font-size:var(--t-small)}
.dim{color:var(--ink2)}
.strong{font-weight:600}

/* Label row is a flex row so "Optional" sits at the right edge rather than
   trailing the name like an afterthought. Same treatment OpenRouter uses, and
   it reads as a property of the field rather than a comment on it. */
label{display:flex;align-items:baseline;justify-content:space-between;
  font-size:var(--t-small);font-weight:500;margin:0 0 var(--s2);
  color:var(--ink)}
/* A label that WRAPS its control is associated with it without needing an
   id on each one — no ids to invent, none to collide, nothing to keep in
   sync. Sixteen inputs across eight pages had visible label text that was
   not attached to anything, so a screen reader announced "edit text, blank"
   on the password field of the sign-in form. The wrapper is a column so the
   text still sits above the control. */
label.lbl{display:block;margin:0}
label.lbl > span{display:flex;align-items:baseline;
  justify-content:space-between;margin:0 0 var(--s2)}
label.lbl > input,label.lbl > select,label.lbl > textarea{margin:0}
/* Shown only when the field is invalid - a permanent "at least 10
   characters" is noise 90% of the time and invisible when it matters. */
.hint{font-size:var(--t-meta);color:var(--bad);font-weight:400;display:none;
  margin-top:6px}
/* Differentiated by weight, not by fading. */
.opt{font-size:var(--t-small);color:var(--ink2);font-weight:400}
.pwwrap:has(input:not(:placeholder-shown):invalid) + .hintwrap .hint{display:block}
/* An empty state is a place someone has arrived at and cannot leave.
   Twelve of these were written by hand and several were a sentence with
   nowhere to go — "No files yet" on a page whose only purpose is files. A
   heading, a line of why, and the one thing to do next. */
.empty{padding:var(--s6) var(--s5);text-align:center;color:var(--ink2);
  font-size:var(--t-small)}
.empty b{display:block;font-size:var(--t-body);color:var(--ink);
  margin-bottom:var(--s1)}
.empty p{margin:0 auto var(--s4);max-width:44ch;line-height:1.55}
.empty .btn{margin-top:var(--s3)}
/* The mark, faint, above it. An empty page with nothing on it at all is the
   one screen where the product has no chance to say what it is. */
.empty .mk{display:block;width:26px;height:26px;margin:0 auto var(--s3);
  opacity:.16}
input,select{width:100%;padding:10px 13px;border:1px solid var(--line2);
  border-radius:var(--r-sm);font:inherit;font-size:var(--t-body);background:var(--bg);
  color:var(--ink);transition:border-color .12s,box-shadow .12s}
input:focus,select:focus{outline:0;border-color:var(--accent);
  box-shadow:var(--ring)}
input::placeholder{color:var(--ink3)}
.field{margin-bottom:18px}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  background:var(--accent);color:var(--bg);border:1px solid var(--accent);
  padding:11px 20px;border-radius:var(--r-sm);font:inherit;font-size:var(--t-body);
  font-weight:500;cursor:pointer;
  transition:background .08s,box-shadow .08s,transform .06s}
/* Hover was var(--ink2) — near-black, hardcoded back when the button WAS black.
   So the accent applied at rest and vanished the moment anyone touched the
   button, which is why it "turns from blue to black". A hover state that
   changes the hue is not a hover state, it is a different button. */
.btn:hover{background:var(--accent-hover);border-color:var(--accent-hover);
  box-shadow:var(--shadow-accent)}
.btn:active{transform:translateY(1px);box-shadow:none}
/* Disabled is WAITING, not broken. opacity:.4 on a solid black button is a
   large grey slab the size of the primary action, which reads as a dead
   control rather than as one that needs input first. */
.btn:disabled{background:var(--accent);border-color:var(--accent);
  color:var(--accent-ink);opacity:.32;cursor:not-allowed;box-shadow:none}
.btn:disabled:hover{background:var(--accent);box-shadow:none}
/* The page's one action. Bigger than everything around it on purpose —
   nine blocks of equal weight is why nothing led anywhere. */
.btn.go{font-size:var(--t-head);padding:14px 34px;border-radius:var(--r);
  font-weight:600}
.btn.ghost:hover{background:var(--raise);box-shadow:none}
.btn.wide{width:100%}
.btn.ghost{background:var(--bg);color:var(--ink);border-color:var(--line2)}

.btn.quiet{background:none;border:none;color:var(--ink2);font-weight:400;
  padding:11px 4px}
.btn.quiet:hover{color:var(--ink);opacity:1}

.sso{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:22px}
.sso a{display:flex;align-items:center;justify-content:center;gap:9px;
  padding:11px;border:1px solid var(--line2);border-radius:var(--r-sm);
  font-size:var(--t-body);font-weight:500;background:var(--bg);transition:background .12s}
.sso a:hover{background:var(--raise);opacity:1}
.sso a.off{opacity:.45}
.or{display:flex;align-items:center;gap:14px;color:var(--ink2);font-size:var(--t-small);
  margin:22px 0}
.or:before,.or:after{content:"";height:1px;background:var(--line);flex:1}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
/* The consent line needs air. Pressed against the button it reads as part of
   the button, and a checkbox you skim past is a checkbox you did not agree to. */
.terms{display:flex;gap:11px;align-items:flex-start;font-size:var(--t-small);
  color:var(--ink);margin:24px 0 28px;line-height:1.5}
.terms input{width:16px;height:16px;margin:2px 0 0;flex:0 0 auto;accent-color:var(--ink)}
.terms a{text-decoration:underline;text-underline-offset:2px}
.pwwrap{position:relative}
.pweye{position:absolute;right:10px;top:50%;transform:translateY(-50%);
  background:none;border:0;cursor:pointer;color:var(--ink3);padding:4px;
  display:flex}
.pweye:hover{color:var(--ink)}

.auth{max-width:400px;margin:var(--s6) auto}
.auth .card-p{padding:32px 30px}
.auth h1{font-size:var(--t-display);text-align:center}
.auth .sub{text-align:center;margin-bottom:28px}
.foot{text-align:center;color:var(--ink);font-size:var(--t-small);margin-top:22px}
.foot a:not(.skip){text-decoration:underline;text-underline-offset:3px}
/* A bare link under a card reads as an afterthought someone forgot to
   finish. It is a real choice, so it gets a real target. */
.skip{display:inline-flex;align-items:center;gap:7px;padding:9px 16px;
  border:1px solid var(--line);border-radius:var(--r-sm);color:var(--ink2);
  font-size:var(--t-small);transition:border-color .12s,color .12s,background .12s}
.skip:hover{border-color:var(--line2);background:var(--raise);
  color:var(--ink);opacity:1}
.steps2{counter-reset:s;margin:26px 0 22px}
.step2{position:relative;padding:0 0 20px 40px;counter-increment:s}
.step2:before{content:counter(s);position:absolute;left:0;top:-1px;width:26px;
  height:26px;border-radius:50%;background:var(--ink);color:var(--bg);
  display:flex;align-items:center;justify-content:center;font-size:var(--t-small);
  font-weight:600}
.step2:not(:last-child):after{content:"";position:absolute;left:12.5px;top:30px;
  bottom:2px;width:1px;background:var(--line)}
.step2 h3{margin:2px 0 4px;font-size:var(--t-body);font-weight:600;
  letter-spacing:-0.01em}
.step2 p{margin:0 0 9px;font-size:var(--t-small);color:var(--ink2);line-height:1.5}
.cmd{background:var(--term-bg);color:var(--term-ink);border-radius:var(--r-sm);padding:11px 14px;
  font-family:var(--mono);font-size:var(--t-meta);overflow-x:auto;white-space:nowrap}
.cmd .c{color:var(--ok)}

/* The runner. The point of this product is that an agent runs somewhere and
   you can see what it cost; a first-run experience that hands over a key and
   two shell commands demonstrates none of that. */
.tpick{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:22px 0}
@media (max-width:700px){.tpick{grid-template-columns:1fr}}
.tp{text-align:left;border:1px solid var(--line2);border-radius:var(--r);
  padding:16px;background:var(--bg);color:var(--ink);font:inherit;
  cursor:pointer;transition:border-color .13s,box-shadow .13s}
.tp:hover{border-color:var(--ink);box-shadow:var(--shadow-lift)}
/* The hit areas own the pointer; the bars ignore it. Both being hoverable
   meant crossing from one to the other fired leave-then-enter repeatedly,
   which was the flicker.
   Only the day under the pointer changes. Dimming every other bar to
   highlight one is a lot of movement to answer "what is this column" — and
   it made the whole chart flicker as the pointer crossed it. */
.hit2{cursor:crosshair}
.bar2{pointer-events:none;transition:fill .1s}
.chart .bar2[data-on]{fill:var(--accent)}
/* NOT `.live` — that is the run page's dark cost bar (background var(--term-bg)),
   so adding it here painted the readout black and my colour rule put dark
   text on top of it. Identical to the `.tpill.live` collision, in the second
   place I had used the word and did not fix. */
#chartval.reading{color:var(--ink);font-weight:600}
/* At the cursor, because that is where the eye is. A readout in the corner
   makes you look away from the thing you are pointing at. */
.charttip{position:absolute;pointer-events:none;z-index:30;
  background:var(--ink);color:var(--bg);border-radius:var(--r-sm);
  padding:6px var(--s2);font-size:var(--t-meta);white-space:nowrap;
  font-variant-numeric:tabular-nums;opacity:0;transition:opacity .1s;
  transform:translate(-50%,-140%)}
.charttip.on{opacity:1}
.chartwrap{position:relative}
.tp.on{border-color:var(--ink);background:var(--sel,var(--sel));
  box-shadow:inset 0 0 0 1px var(--ink)}
.tp.on b{color:var(--ink)}
.tp b{display:block;font-size:var(--t-body);font-weight:600;margin-bottom:4px}
.tp span{font-size:var(--t-meta);line-height:1.45;color:var(--ink2)}
.runner{display:grid;grid-template-columns:1fr;gap:0;border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;margin:20px 0}
.rtabs{display:flex;gap:2px;padding:8px;background:var(--raise);
  border-bottom:1px solid var(--line);overflow-x:auto}
.rtab{white-space:nowrap;padding:8px 14px;border-radius:var(--r-sm);border:0;
  background:none;font:inherit;font-size:var(--t-small);color:var(--ink2);
  cursor:pointer}
.rtab:hover{background:var(--bg);color:var(--ink)}
.rtab.on{background:var(--accent);color:var(--accent-ink)}
/* Light, in the end.
   Dark was defended twice as "a code editor is dark everywhere", and that is
   true of editors and not of a single input on an otherwise white page: it
   read as a slab dropped into the layout rather than a field belonging to
   it. The thing that makes an input read as code is the typeface and the
   frame, not the darkness. */
.editor{border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  background:var(--bg);transition:border-color .13s,box-shadow .13s}
.editor:focus-within{border-color:var(--accent);
  box-shadow:var(--ring)}
/* One row. The five starter chips that used to live here are behind an
   Examples control now — a filename competing with five buttons is not a
   filename. */
.edbar{display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s4);border-bottom:1px solid var(--line);
  background:var(--raise);font-size:var(--t-meta);color:var(--ink3);
  flex-wrap:nowrap;overflow-x:auto}
.edbar b{flex:0 0 auto}
.edbar b{font-family:var(--mono);font-size:var(--t-meta);font-weight:500;
  color:var(--ink)}
.edbar .grow{flex:1}
.code{width:100%;border:0;padding:var(--s4) var(--s5);
  font-family:var(--mono);font-size:var(--t-small);
  line-height:1.75;background:transparent;color:var(--ink);resize:vertical;
  /* The page IS the editor now, so it gets the height to look like one. */
  min-height:300px;display:block;tab-size:4}
.code:focus{outline:0}
.code::placeholder{color:var(--ink2);opacity:.75}
.code:focus{outline:0}
/* A placeholder greys out and vanishes on the first keystroke, which is the
   universal signal for "type here". Pre-filled comments are not. */
/* What this run will do, before it does it. The page used to hide every
   decision behind a button; someone choosing between "cheapest" and "highest
   performance" cannot judge that without seeing what each resolves to. */
/* The run page as a SEQUENCE, not a form.

   It was a pile of boxes with equal weight: a tab bar, a black editor, two
   dropdowns, a strip and an output pane, all visible at once and none
   obviously first. Nobody could tell what order to do things in because
   there was no order.

   Three steps. Each is either DONE - collapsed to its answer, changeable -
   or CURRENT, open with one decision in it. The answer stays visible; the
   controls do not. */
/* Removed: a second .steps rule that overrode the onboarding
   progress bar and stacked it into an invisible column. The
   step-card component is .steps3 and has its own rules. */
.step{border:1px solid var(--line2);border-radius:var(--r-lg);background:var(--bg);
  overflow:hidden;transition:border-color .15s}
.step.now{border-color:var(--ink);box-shadow:var(--shadow-lift)}
.step.done{background:var(--raise)}
.step > .head{display:flex;align-items:center;gap:14px;padding:16px 20px;
  cursor:pointer}
/* Hexagons, not circles. The mark is ten hexagons; a numbered circle beside
   it is a shape from a different product. Same clip-path as a single cell of
   the tetractys, so the step markers and the logo share one geometry. */
.step .n{flex:0 0 auto;width:28px;height:31px;display:flex;
  align-items:center;justify-content:center;font-size:var(--t-meta);font-weight:600;
  background:var(--line);color:var(--ink2);
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
.step.now .n{background:var(--accent);color:var(--accent-ink)}
.step.done .n{background:var(--ok);color:var(--bg)}
.step .head .t{flex:1;min-width:0}
.step .head .t b{display:block;font-size:var(--t-body);font-weight:600;
  letter-spacing:-0.01em}
.step .head .t span{display:block;font-size:var(--t-small);color:var(--ink2);
  margin-top:2px;word-break:break-word}
.step .head .edit{font-size:var(--t-meta);color:var(--ink2);text-decoration:underline;
  text-underline-offset:2px;flex:0 0 auto}
.step .body{padding:18px 20px 20px;border-top:1px solid var(--line)}
.step:not(.now) .body{display:none}

.seg2{display:inline-flex;border:1px solid var(--line2);border-radius:var(--r-sm);
  overflow:hidden;margin-bottom:16px}
.seg2 button{padding:8px 16px;border:0;background:var(--bg);font:inherit;
  font-size:var(--t-small);cursor:pointer;color:var(--ink2)}
.seg2 button.on{background:var(--accent);color:var(--accent-ink)}
.seg2 button:not(.on):hover{background:var(--raise);color:var(--ink)}

/* The model picker. Cursor's own users say theirs is overloaded: too much at
   once, hard to pick quickly. Three intents, each showing the ONE model it
   resolves to, its price and its context window. That last column is what
   every competitor omits and their users ask for, because context binds more
   often than price does. */
.pick2{position:relative;display:block}
.pick2 summary{display:flex;align-items:center;gap:10px;padding:12px 14px;
  border:1px solid var(--line2);border-radius:var(--r);background:var(--bg);
  cursor:pointer;font-size:var(--t-small);list-style:none}
.pick2 summary::-webkit-details-marker{display:none}
.pick2 summary:hover{border-color:var(--ink)}
.pick2 summary .g{flex:1;min-width:0}
.pick2 summary b{display:block;font-weight:600}
.pick2 summary em{display:block;font-style:normal;color:var(--ink2);
  font-size:var(--t-meta);margin-top:1px}
.pick2 summary:after{content:"change";font-size:var(--t-meta);color:var(--ink2);
  text-decoration:underline;text-underline-offset:2px}
.pick2 .pop{margin-top:8px;background:var(--bg);border:1px solid var(--line2);
  border-radius:var(--r);padding:6px;display:none}
.pick2[open] .pop{display:block}
.opt2{display:flex;align-items:flex-start;gap:11px;width:100%;padding:12px;
  border:0;border-radius:var(--r-sm);background:none;text-align:left;font:inherit;
  cursor:pointer;color:var(--ink)}
.opt2:hover{background:var(--raise)}
.opt2.on{background:var(--raise)}
.opt2 .tick2{width:15px;flex:0 0 auto;color:var(--ok);padding-top:2px}
.opt2 .mid{flex:1;min-width:0}
.opt2 .mid b{display:block;font-size:var(--t-small);font-weight:600}
.opt2 .mid span{display:block;font-size:var(--t-meta);color:var(--ink2);margin-top:1px}
.opt2 .mid code{display:block;font-size:var(--t-meta);color:var(--ink2);margin-top:4px;
  word-break:break-all}
.opt2 .rt2{flex:0 0 auto;text-align:right;font-family:var(--num);font-size:var(--t-meta);
  color:var(--ink2);line-height:1.5}
.opt2 .rt2 b{display:block;color:var(--ink);font-weight:600;font-size:var(--t-meta)}
.pop .sep2{height:1px;background:var(--line);margin:6px 4px}
.pop .own{display:flex;gap:8px;padding:4px 8px 8px}
.pop .own input{flex:1;font-size:var(--t-small);padding:8px 10px}

.runrow{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.runrow .est{font-size:var(--t-small);color:var(--ink2)}
.runrow .est b{color:var(--ink);font-family:var(--num)}

/* A run you can watch. Every competitor shows logs after the fact; the point
   here is seeing the stages complete and the money move while it happens. */
.stages{display:flex;gap:0;border-top:1px solid var(--line);flex-wrap:wrap}
.stg{flex:1;min-width:130px;padding:12px 16px;border-right:1px solid var(--line);
  display:flex;align-items:center;gap:9px;font-size:var(--t-small);color:var(--ink2)}
.stg:last-child{border-right:0}
.stg .bul{width:9px;height:9px;border-radius:50%;background:var(--line2);
  flex:0 0 auto}
.stg.go .bul{background:var(--ok);animation:pulse 1.3s ease-in-out infinite}
.stg.ok .bul{background:var(--ok)}
.stg.ok{color:var(--ink)}
.stg.go{color:var(--ink)}
.stg b{font-weight:600}
/* The cost line sits WITH the result, not as a black slab across the page.
   Full-bleed black in a light interface reads as an error state whatever
   it says, and at $0.000000 it was shouting a number that means nothing
   yet. Inset, rounded to the same scale as the cards above it, and the
   figure sized as a fact rather than a headline. */
.live{display:flex;align-items:baseline;gap:10px;padding:10px 14px;
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--raise);color:var(--ink);
  margin:var(--s2) 0;font-family:var(--num);font-size:var(--t-small)}
.live .big{font-size:var(--t-body);font-weight:600;letter-spacing:-0.01em;
  font-variant-numeric:tabular-nums;color:var(--ink)}
/* Live spend is the one number worth colouring: it is the thing the
   product exists to show, and it moves while you watch. */
.live.running .big{color:var(--accent)}
.live .sm{color:var(--ink2);font-size:var(--t-meta)}
.live .grow{flex:1}

.plan{display:flex;align-items:center;gap:0;padding:0;
  border-top:1px solid var(--line);background:var(--raise);flex-wrap:wrap}
.plan .cell{flex:1;min-width:170px;padding:14px 18px;
  border-right:1px solid var(--line)}
.plan .cell:last-child{border-right:0}
.plan .cell span{display:block;font-size:var(--t-meta);color:var(--ink2);
  margin-bottom:3px;letter-spacing:.01em}
.plan .cell b{display:block;font-size:var(--t-small);font-weight:600;
  letter-spacing:-0.01em;word-break:break-word}
.plan .cell i{display:block;font-style:normal;font-size:var(--t-meta);
  color:var(--ink2);margin-top:2px;font-family:var(--num)}
.plan .cell a{font-size:var(--t-meta);color:var(--ink2);text-decoration:underline;
  text-underline-offset:2px}
.plan .cell a:hover{color:var(--ink);opacity:1}

.rbar{display:flex;align-items:center;gap:14px;padding:12px 16px;
  background:var(--raise);border-top:1px solid var(--line)}
.rbar .grow{flex:1}
.out{border-top:1px solid var(--line);background:var(--bg)}
.outh{display:flex;align-items:center;gap:10px;padding:11px 16px;
  font-size:var(--t-meta);color:var(--ink2);border-bottom:1px solid var(--line)}
.outb{padding:16px;font-family:var(--mono);font-size:var(--t-meta);line-height:1.6;
  white-space:pre-wrap;word-break:break-word;max-height:280px;overflow:auto}
.metrics{display:flex;gap:0;border-top:1px solid var(--line)}
.metric{flex:1;padding:14px 16px;border-right:1px solid var(--line)}
.metric:last-child{border-right:0}
.metric b{display:block;font-family:var(--num);font-size:var(--t-head);font-weight:600;
  letter-spacing:-0.01em}
.metric span{font-size:var(--t-meta);color:var(--ink2)}
.spin{width:13px;height:13px;border:2px solid var(--line2);
  border-top-color:var(--ink);border-radius:50%;animation:sp .7s linear infinite;
  display:inline-block}
@keyframes sp{to{transform:rotate(360deg)}}
.keyline{display:flex;align-items:center;gap:12px;justify-content:space-between;
  padding:13px 16px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--raise);font-size:var(--t-small);margin-top:6px}
.keyline code{color:var(--ink2)}

/* Sessions as objects you can see and click, not rows in a table.
   Railway's lesson: infrastructure becomes understandable when it has a
   shape. A list of ids tells you that things exist; it does not tell you
   which one is running, which one is costing money, or which one is stuck. */
/* Filter bar. Sticky because scrolling past your own filters and forgetting
   what you set is the standard way a long list becomes confusing. */
.filters{display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  padding:12px 14px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--raise);margin:18px 0}
.filters input[type=search]{flex:1;min-width:190px}
.filters select{width:auto;min-width:118px}
.chip{display:inline-flex;align-items:center;gap:6px;padding:5px 11px;
  border:1px solid var(--line2);border-radius:var(--r-pill);background:var(--bg);
  font-size:var(--t-meta);color:var(--ink2)}
.chip b{color:var(--ink);font-weight:600}
.chip a{color:var(--ink3);font-weight:600;margin-left:2px}
.chip a:hover{color:var(--ink);opacity:1}
.sched{display:flex;align-items:center;gap:16px;padding:16px 18px;
  border-bottom:1px solid var(--line)}
.sched:last-child{border-bottom:0}
.sched .who{flex:1;min-width:0}
.sched .who b{display:block;font-size:var(--t-body);font-weight:600;
  letter-spacing:-0.01em}
.sched .who span{font-size:var(--t-meta);color:var(--ink2)}
.sched .num{text-align:right;font-family:var(--num);font-size:var(--t-small);
  min-width:78px}
.sched .num span{display:block;font-family:var(--font);font-size:var(--t-meta);
  color:var(--ink2)}
.mini{padding:6px 12px;font-size:var(--t-small);border-radius:var(--r-sm)}
.ceiling{font-size:var(--t-meta);color:var(--ink2);margin-top:7px}
.ceiling b{color:var(--ink);font-weight:600}
.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:18px;font-size:var(--t-small);color:var(--ink2)}
.pager a{padding:8px 14px;border:1px solid var(--line2);border-radius:var(--r-sm);
  color:var(--ink)}
.pager a:hover{background:var(--raise);opacity:1}
.pager .off{opacity:.35;pointer-events:none}
.insight{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:20px 0}
@media (max-width:760px){.insight{grid-template-columns:1fr}}
.ins{border:1px solid var(--line);border-radius:var(--r);padding:18px}
.ins span{display:block;font-size:var(--t-meta);color:var(--ink2);margin-bottom:6px}
.ins b{display:block;font-family:var(--num);font-size:var(--t-head);font-weight:600;
  letter-spacing:-0.02em}
.ins i{display:block;font-style:normal;font-size:var(--t-meta);color:var(--ink2);
  margin-top:5px}
.chart{width:100%;height:150px;display:block}
.chart .bar2{fill:var(--ink);opacity:.82}
.chart .bar2:hover{opacity:1}
.chart .grid2{stroke:var(--line);stroke-width:1}
.chart text{font-size:10.5px;fill:var(--ink3);font-family:var(--font)}
.charthead{display:flex;justify-content:space-between;align-items:baseline;
  gap:14px;margin-bottom:6px}

.setgrid{display:grid;grid-template-columns:190px 1fr;gap:28px;
  align-items:start;margin-top:22px}
@media (max-width:760px){.setgrid{grid-template-columns:1fr}}
.setnav{position:sticky;top:78px;display:flex;flex-direction:column;gap:2px}
.setnav a{padding:8px 12px;border-radius:var(--r-sm);font-size:var(--t-small);color:var(--ink2)}
.setnav a:hover{background:var(--raise);color:var(--ink);opacity:1}
.setnav a.on{background:var(--raise);color:var(--ink);font-weight:500}
.sec{scroll-margin-top:86px}
.sec h2{margin-top:0}
.sec+.sec{margin-top:34px}
.danger{border-color:var(--bad-line)}
.danger h2{color:var(--bad)}
.btn.bad{background:var(--bad);border-color:var(--bad)}
.btn.bad:hover{background:var(--bad)}
.hint2{font-size:var(--t-meta);color:var(--ink2);margin:6px 0 0;line-height:1.5}

.steps3{counter-reset:q;margin:8px 0 0}
.q{position:relative;padding:0 0 16px 34px;counter-increment:q}
.q:before{content:counter(q);position:absolute;left:0;top:0;width:22px;
  height:22px;border-radius:50%;background:var(--ink);color:var(--bg);display:flex;
  align-items:center;justify-content:center;font-size:var(--t-meta);font-weight:600}
.q p{margin:0 0 7px;font-size:var(--t-small);color:var(--ink2);line-height:1.5}

/* DENSITY. Cards were 258px wide with 18px padding and a legend repeated
   inside every one of them: twenty-four cards meant seventy-two labels
   explaining a bar that is identical on all of them. The legend moved above
   the grid; the cards got tighter and narrower, so more fit on a screen. */
.gridhead{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--s4);margin:var(--s5) 0 var(--s2);font-size:var(--t-meta)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(212px,1fr));
  gap:var(--s3);margin:0 0 var(--s5)}
/* The card is one big link, so the checkbox sits beside it rather than
   inside. Only shown on hover or when checked: a grid of checkboxes reads
   as a form, and this is a list you mostly just read. */
.nodewrap{position:relative}
.nodewrap .pick{position:absolute;top:10px;left:10px;z-index:2;margin:0;
  opacity:0;transition:opacity .12s;cursor:pointer}
.nodewrap:hover .pick,.nodewrap .pick:checked,
.nodewrap .pick:focus-visible{opacity:1}
.nodewrap:has(.pick:checked) .node{border-color:var(--accent);
  box-shadow:var(--shadow-accent)}

.bulk{position:sticky;top:8px;z-index:5;display:flex;align-items:center;
  gap:10px;margin:0 0 12px;padding:8px 12px;border-radius:var(--r);
  background:var(--bg);border:1px solid var(--accent);
  box-shadow:var(--shadow-lift)}

.node{position:relative;display:block;border:1px solid var(--line);
  border-radius:var(--r);padding:var(--s3) var(--s4);background:var(--bg);
  color:var(--ink);box-shadow:var(--shadow);
  transition:border-color .14s,box-shadow .14s;overflow:hidden}
.node:hover{border-color:var(--ink3);
  box-shadow:var(--shadow-lift);opacity:1}
.node .top{display:flex;align-items:flex-start;justify-content:space-between;
  gap:var(--s2);margin-bottom:var(--s2)}
.node .name{font-weight:600;font-size:var(--t-body);letter-spacing:-0.01em;
  word-break:break-word;line-height:1.35}
.node .rt{font-size:var(--t-meta);color:var(--ink2);margin-top:3px}
.node .cost{font-family:var(--num);font-size:var(--t-head);font-weight:600;
  letter-spacing:-0.02em}
.node .sub2{font-size:var(--t-meta);color:var(--ink2);margin-top:2px}
.node .bar{display:flex;height:4px;border-radius:2px;overflow:hidden;
  background:var(--line);margin:var(--s3) 0 0}
.node .bar i{display:block}
.node .bar .cpu{background:var(--series-1)}
.node .bar .tok{background:var(--ok)}
.node .bar .tul{background:var(--warn)}
.legend{display:flex;gap:14px;font-size:var(--t-meta);color:var(--ink2)}
.legend b{font-weight:500;display:inline-flex;align-items:center;gap:5px}
.legend b:before{content:"";width:8px;height:8px;border-radius:2px}
.legend .l1:before{background:var(--series-1)}
.legend .l2:before{background:var(--ok)}
.legend .l3:before{background:var(--warn)}

/* ---- the run page ----
   These forty-four rules lived in a <style> block inside the page itself,
   which is why this one screen kept drifting from every other: it was the
   only page substantially built OUTSIDE the design system, so its spacing,
   its type and its colours were forty-four more local decisions rather
   than the shared ones. */
.foot1{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  font-size:var(--t-meta);color:var(--ink3);line-height:1.6;margin:var(--s5) 0 0;
  padding-top:var(--s4);border-top:1px solid var(--line)}
.footsep{flex:1}
.cfgline{background:var(--raise);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:var(--s3) 15px;font:var(--t-meta)/1.7 var(--mono);
  white-space:pre-wrap;margin:0;overflow-x:auto}
/* The heading and the recent runs share one line. A heading, a subhead and
   a labelled strip stacked above the editor pushed the thing people came
   for below the fold. */
.runtop{display:flex;align-items:baseline;gap:var(--s5);
  margin-bottom:var(--s4);min-width:0}
.runtop h1{flex:0 0 auto}
.runtop .recent{flex:1;min-width:0}
.runtop h1{margin:0}
.recent{margin:0;min-width:0}
.rhead{display:none}
/* WRAPS, rather than scrolling off the edge. A row you have to scroll to
   read hides the thing it exists to show, and the fade I put there to
   soften the clipping just made it look deliberate. Four fit on a line at
   this width; the rest go under. */
/* ONE row that scrolls, not a wrapping grid. Six cards wrapped left the
   sixth stranded on a second line beside "all runs →", which reads as a
   layout fault rather than as history. A horizontal strip also says the
   right thing: this is a timeline, and it continues off the edge. */
.rrow{display:flex;gap:var(--s2);align-items:stretch;overflow-x:auto;
  scrollbar-width:thin;padding-bottom:4px;
  -webkit-overflow-scrolling:touch}
.rrow::-webkit-scrollbar{height:6px}
.rrow::-webkit-scrollbar-thumb{background:var(--line2);border-radius:var(--r-pill)}
.rall{align-self:center;font-size:var(--t-meta);white-space:nowrap;
  padding-left:var(--s2);position:sticky;right:0;background:var(--bg);
  flex:0 0 auto}
/* State is a bar on the left edge, not a coloured pip in front of the text.
   It reads at a glance, costs no horizontal space, and does not look like a
   decoration bolted onto every row. */
.rcard{flex:0 0 auto;border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s2) var(--s3);text-decoration:none;color:inherit;
  display:grid;gap:1px;white-space:nowrap;background:var(--bg);
  border-left:2px solid var(--line2);min-width:154px}
.rcard b{font-size:var(--t-small);font-weight:600}
.rcard .rcost{font-size:var(--t-meta);font-variant-numeric:tabular-nums;
  color:var(--ink)}
.rcard .rwhen{font-size:var(--t-meta);color:var(--ink3)}
.rcard.running{border-left-color:var(--ok)}
.rcard.suspended{border-left-color:var(--warn)}
.rcard:hover{border-color:var(--ink)}


.biginput{width:100%;font-size:var(--t-body);padding:var(--s3) var(--s4)}
.underbox{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  margin-top:var(--s2)}
.underbox input{width:220px;font-size:var(--t-small);padding:var(--s2) var(--s3)}
.exlead{font-size:var(--t-meta);color:var(--ink3)}
/* Examples as a row of small chips, not five cards taking a third of the
   screen before anyone has typed anything. */
.tpick{display:flex;gap:var(--s2);flex-wrap:wrap}
.tpick .tp{padding:var(--s1) var(--s3);border-radius:var(--r-pill);font-size:var(--t-meta);
  border:1px solid var(--line);background:var(--bg)}
.tpick .tp b{display:inline;font-size:var(--t-meta);font-weight:500;margin:0}
.tpick .tp span{display:none}
.tpick .tp.on{border-color:var(--ink);box-shadow:none;
  background:var(--sel)}

.pline{font-size:var(--t-small);line-height:1.5;display:block}
.runmeta{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
/* The starters, inside the editor bar. Small, quiet, and next to the
   filename they change. */
.edbar .tpick{display:flex;gap:var(--s1);margin-left:var(--s3)}
.edbar .tp{padding:3px var(--s2);font-size:var(--t-meta);border-radius:var(--r-pill);
  border:1px solid transparent;background:transparent;color:var(--ink3)}
.edbar .tp:hover{color:var(--ink);background:var(--bg);
  border-color:var(--line)}
.edbar .tp.on{color:var(--accent);background:var(--accent-soft);
  border-color:transparent;box-shadow:none}
.edfoot{display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s4);border-top:1px solid var(--line);
  background:var(--raise);font-size:var(--t-meta)}
.edfoot input{width:210px;padding:var(--s1) var(--s2);font-size:var(--t-meta);
  background:var(--bg)}
.chg{font-size:var(--t-meta);color:var(--ink3);cursor:pointer;
  text-decoration:underline;text-underline-offset:2px}
.chg:hover{color:var(--ink)}
/* Genuinely hidden until asked for. Model, machine, cap, task id and every
   stored credential were in the DOM on load — announced to a screen reader,
   found by ctrl-F, and part of the page's weight — for a panel nobody had
   opened. `display:none` on the container is not enough when the intent is
   "this does not exist yet". */
.changer{display:none;border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s4);margin:var(--s3) 0 0;background:var(--raise)}
.changer.open{display:block}
.changer[hidden]{display:none}
.cgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s3)}
.cgrid label{display:block;font-size:var(--t-meta);font-weight:600;margin-bottom:var(--s1)}
.cgrid select,.cgrid input{width:100%}
.changer .cbxs{display:flex;gap:var(--s3);flex-wrap:wrap;margin-top:var(--s2)}
.cbx{display:flex;align-items:center;gap:var(--s2);font-size:var(--t-small);cursor:pointer}
.cbx input[type=checkbox]{width:14px;height:14px;margin:0;flex:0 0 auto}
.cbx em{color:var(--ink3);font-size:var(--t-meta);font-style:normal}
.shint{font-size:var(--t-meta);color:var(--ink3);margin:var(--s2) 0 0}

/* The action bar sits on the editor rather than floating under it, so the
   button and the terms it commits to read as one object. */
.runbar{display:flex;align-items:center;gap:var(--s4);
  margin:var(--s4) 0 0;padding:var(--s4) var(--s5);
  border:1px solid var(--line);border-radius:var(--r);
  background:var(--bg);box-shadow:var(--shadow);
  font-size:var(--t-meta)}
.runbar .btn.go{flex:0 0 auto}

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


/* Spacing between two facts on one line. `&nbsp;` was reached for six
   separate times today and rendered as literal text every time, because
   these strings are read as text somewhere downstream. An element cannot
   be mis-escaped. */
span.sep{display:inline-block;width:var(--s3)}

/* The sign-out button, styled as the menu item it replaced. It was an <a>,
   so a GET signed people out; a form keeps the appearance and moves the
   action to POST. */
.menu .signout{margin:0}
.menu .signout button{display:flex;align-items:center;gap:10px;width:100%;
  background:none;border:0;padding:var(--s2) var(--s3);font:inherit;
  font-size:var(--t-small);color:var(--ink);cursor:pointer;text-align:left;
  border-radius:var(--r-sm)}
.menu .signout button:hover{background:var(--raise)}

/* Click any code span to copy it. The affordance has to be visible or
   nobody discovers it, and the confirmation has to be on the element itself
   or you cannot tell WHICH of six ids you just took. */
code{cursor:copy;border-radius:var(--r-sm);padding:1px 4px;
  background:var(--raise);transition:background .1s,color .1s}
code:hover{background:var(--sel);color:var(--ink)}
code[data-copied]{background:var(--ok-soft);color:var(--ok)}
code[data-copied]::after{content:" copied";font-size:.85em;opacity:.8}
code[data-nocopy]{cursor:inherit;background:none;padding:0}

/* The theme control, styled as the menu row it sits in. */
.menu .themebtn{display:flex;align-items:center;gap:10px;width:100%;
  background:none;border:0;padding:var(--s2) var(--s3);font:inherit;
  font-size:var(--t-small);color:var(--ink);cursor:pointer;text-align:left;
  border-radius:var(--r-sm)}
.menu .themebtn:hover{background:var(--raise)}
.menu .themebtn #themeico::before{content:"◐";font-size:14px;
  color:var(--ink3)}

/* A count of what is in flight, on the nav item that leads to it. Visible
   from every page, because "is anything running" is the question people
   have while doing something else. */
.livecount{margin-left:auto;font-size:var(--t-meta);font-weight:600;
  min-width:18px;padding:0 5px;border-radius:var(--r-pill);
  background:var(--ok-soft);color:var(--ok);text-align:center}
.livecount.bad{background:var(--bad-soft);color:var(--bad)}
.livecount[hidden]{display:none}
/* A value that just changed, marked briefly. Without it a number updating
   under your eyes reads as a rendering glitch rather than news. */
@keyframes ticked{from{background:var(--accent-soft)}to{background:none}}
[data-live-cost].ticked{animation:ticked .9s ease-out}

/* ---- the file browser ----
   E2B and Daytona both ship one, and it is the thing that turns "a machine
   ran" into "a machine I can look inside". Built on the exec every backend
   already has, so it works on E2B, Modal and local alike. */
.fbrowse{padding:0;overflow:hidden}
.fbbar{display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s4);border-bottom:1px solid var(--line);
  background:var(--raise);font-size:var(--t-meta)}
.fblist{max-height:320px;overflow-y:auto}
.fbrow{display:flex;align-items:center;gap:var(--s3);width:100%;
  padding:6px var(--s4);border:0;background:none;font:inherit;
  font-size:var(--t-small);color:var(--ink);cursor:pointer;text-align:left}
.fbrow:hover{background:var(--raise)}
.fbrow .fbname{flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);
  font-size:var(--t-meta)}
.fbrow.dir .fbname{font-weight:600}
.fbrow.dir .fbname::after{content:"/";color:var(--ink3)}
.fbsize{font-size:var(--t-meta);color:var(--ink3);
  font-variant-numeric:tabular-nums}
.fbwait{padding:var(--s4);color:var(--ink3);font-size:var(--t-small)}
.fbview{margin:0;border-top:1px solid var(--line);background:var(--term-bg);
  color:var(--term-ink);padding:var(--s4);max-height:340px;overflow:auto;
  font-family:var(--mono);font-size:var(--t-meta);line-height:1.6;
  white-space:pre-wrap;word-break:break-word}
.fbview[hidden]{display:none}

/* ---- machine state ----
   Answers a question the cost table cannot: an agent that has spent four
   minutes and $0.30 might be working hard, or might be stuck on a socket. */
.machrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));
  gap:var(--s5)}
.machcell{min-width:0}
.machlbl{font-size:var(--t-meta);color:var(--ink3)}
.machval{font-size:var(--t-small);font-weight:600;
  font-variant-numeric:tabular-nums;margin:2px 0 var(--s2)}
.machtrack{height:4px;border-radius:2px;background:var(--line);
  overflow:hidden}
.machtrack i{display:block;height:100%;background:var(--accent);
  transition:width .3s}
.machtrack i.hot{background:var(--warn)}

/* ---- the console ----
   One command at a time, not a PTY. The output pane is the only dark
   surface in the product on purpose: a terminal that is white does not read
   as a terminal. */
.term{padding:0;overflow:hidden}
.termout{margin:0;padding:var(--s4);background:var(--term-bg);
  color:var(--term-ink);font-family:var(--mono);font-size:var(--t-meta);
  line-height:1.65;max-height:300px;overflow:auto;white-space:pre-wrap;
  word-break:break-word}
.termout .termcmd{color:var(--term-dim);margin-top:var(--s2)}
.termout .termerr{color:var(--term-bad)}
.termout .termdim{color:var(--term-dim)}
.termbar{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s2) var(--s4);border-top:1px solid var(--line);
  background:var(--raise)}
.termps{font-family:var(--mono);color:var(--ink3);font-size:var(--t-meta)}
.termbar input{border:0;background:none;padding:4px 0;
  font-family:var(--mono);font-size:var(--t-meta)}
.termbar input:focus{box-shadow:none}

/* ---- the detail sheet ----
   Clicking a run slides this over rather than navigating away, so you keep
   your place in a list you may have scrolled and filtered to reach. Daytona
   calls the same thing a sheet; the pattern is the category convention. */
.sheet{position:fixed;inset:0;z-index:90;background:rgba(0,0,0,.3);
  display:flex;justify-content:flex-end}
.sheet[hidden]{display:none}
.sheetbox{position:relative;width:min(760px,94vw);height:100%;
  background:var(--bg);border-left:1px solid var(--line2);
  box-shadow:var(--shadow-lift);overflow-y:auto;
  padding:var(--s6) var(--s6) 80px;
  animation:sheetin .16s ease-out}
@keyframes sheetin{from{transform:translateX(24px);opacity:.4}
                   to{transform:none;opacity:1}}
.sheetx{position:absolute;top:var(--s4);right:var(--s4);
  display:flex;align-items:center;justify-content:center;
  width:30px;height:30px;border:1px solid var(--line);
  border-radius:var(--r-sm);background:var(--bg);color:var(--ink2);
  cursor:pointer}
.sheetx:hover{background:var(--raise);color:var(--ink)}
.sheetwait{color:var(--ink3);font-size:var(--t-small);padding:var(--s5) 0}
/* The sheet is narrower than the page, so anything inside that assumed the
   full width has to reflow rather than overflow. */
.sheetbody .detail{grid-template-columns:1fr}
.sheetbody h1{font-size:var(--t-head)}

/* ---- the command palette ----
   Two keystrokes to anywhere. Every developer tool in this category has
   one, and without it the only way to reach a task is to remember which
   list it is on. */
.palcue{display:flex;align-items:center;gap:10px;width:100%;
  padding:7px var(--s3);margin-bottom:var(--s2);
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--bg);color:var(--ink3);font:inherit;
  font-size:var(--t-small);cursor:pointer;text-align:left}
.palcue:hover{border-color:var(--ink3);color:var(--ink)}
.palcue kbd{margin-left:auto}
kbd{font:inherit;font-size:var(--t-meta);font-family:var(--mono);
  color:var(--ink3);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:1px 5px;background:var(--raise)}

.pal{position:fixed;inset:0;z-index:100;background:rgba(0,0,0,.28);
  display:flex;align-items:flex-start;justify-content:center;
  padding-top:12vh}
.pal[hidden]{display:none}
.palbox{width:min(560px,92vw);background:var(--bg);
  border:1px solid var(--line2);border-radius:var(--r);
  box-shadow:var(--shadow-lift);overflow:hidden}
.palbox > input{border:0;border-bottom:1px solid var(--line);
  border-radius:0;padding:var(--s4) var(--s5);font-size:var(--t-head)}
.palbox > input:focus{box-shadow:none;border-color:var(--line)}
.palout{max-height:46vh;overflow-y:auto;padding:var(--s1)}
.palrow{display:flex;align-items:baseline;gap:var(--s3);
  padding:var(--s2) var(--s3);border-radius:var(--r-sm);color:inherit}
.palrow.on{background:var(--accent-soft)}
.palrow.on .pallabel{color:var(--accent)}
.palkind{font-size:var(--t-meta);color:var(--ink3);width:44px;
  flex:0 0 auto}
.pallabel{font-size:var(--t-small);font-weight:600;flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.palmeta{font-size:var(--t-meta);color:var(--ink3);white-space:nowrap}
.palnone{padding:var(--s4) var(--s5);color:var(--ink3);
  font-size:var(--t-small)}
.palfoot{display:flex;align-items:center;gap:6px;
  padding:var(--s2) var(--s5);border-top:1px solid var(--line);
  background:var(--raise);font-size:var(--t-meta);color:var(--ink3)}
.palfoot kbd{margin-left:var(--s3)}
.palfoot kbd:first-child{margin-left:0}

/* Examples, behind one control. */
.exmenu{position:relative;flex:0 0 auto}
.exmenu > summary{list-style:none;cursor:pointer;padding:3px var(--s2);
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--bg);color:var(--ink2);font-size:var(--t-meta)}
.exmenu > summary::-webkit-details-marker{display:none}
.exmenu > summary:hover{border-color:var(--ink3);color:var(--ink)}
.exmenu[open] > summary{border-color:var(--accent);color:var(--accent)}
.expop{position:absolute;right:0;top:calc(100% + var(--s1));z-index:30;
  display:flex;flex-direction:column;gap:2px;min-width:200px;
  background:var(--bg);border:1px solid var(--line2);
  border-radius:var(--r-sm);box-shadow:var(--shadow-lift);padding:var(--s1)}
.expop .tp{text-align:left;border:0;background:none;padding:6px var(--s2);
  border-radius:var(--r-sm);font-size:var(--t-small);color:var(--ink)}
.expop .tp:hover{background:var(--raise)}
.expop .tp.on{background:var(--accent-soft);color:var(--accent)}

/* One row. The five starter chips that used to live here are behind an
   Examples control now — a filename competing with five buttons is not a
   filename. */
.tfilter{display:flex;gap:var(--s3);align-items:center;margin:0 0 var(--s4)}
.tfilter input{flex:1;max-width:340px}
/* Grid on the shared row, not a second row implementation. */
/* A header row, so five bare numbers stop needing a caption each. */
.tlist .trow,.tlist .thead{grid-template-columns:minmax(0,1fr)
  repeat(5,78px)}
.tlist .thead{font-size:var(--t-meta);color:var(--ink3);
  background:var(--raise)}
.tlist .thead span{text-align:right}
.tlist .thead span:first-child{text-align:left}
.tname{display:flex;align-items:center;gap:var(--s2);min-width:0}
.tname b{font-size:var(--t-body);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.tnum{text-align:right;font-size:var(--t-small);
  font-variant-numeric:tabular-nums}
.tnum em{display:block;font-size:var(--t-meta);color:var(--ink3);
  font-style:normal;margin-top:1px}
@media (max-width:820px){.trow{grid-template-columns:1fr auto auto}
  .trow .tnum:nth-child(n+4){display:none}}

.thead{display:flex;justify-content:space-between;align-items:flex-start;
  gap:var(--s5)}
.thead h1{margin-bottom:2px}
.srow{display:flex;gap:var(--s3);align-items:center}
.srow select{max-width:260px}
.kv{display:flex;justify-content:space-between;gap:var(--s4);padding:var(--s2) 0;
  font-size:var(--t-small);border-bottom:1px solid var(--line)}
.kv:last-child{border-bottom:0}
.kv span{color:var(--ink3)}


/* THE status component. One name, and the state words are the ones the model
   already uses — `running`, `suspended`, `stuck` — so a status from the
   store maps onto a class without a lookup table per page. That lookup table
   is where the five variants came from. */
.st{display:inline-flex;align-items:center;gap:6px;font-size:var(--t-meta);
  font-weight:500;padding:3px 9px;border-radius:var(--r-pill);
  border:1px solid var(--line);white-space:nowrap;color:var(--ink2);
  background:var(--raise)}
.st:before{content:"";width:6px;height:6px;border-radius:50%;
  background:currentColor;flex:0 0 auto}
.st.run,.st.running,.st.ok{color:var(--ok);border-color:var(--ok-line);
  background:var(--ok-soft)}
.st.run:before,.st.running:before{animation:pulse 1.6s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}
                 50%{opacity:.35;transform:scale(.8)}}
.st.sus,.st.suspended{color:var(--warn);border-color:var(--warn-line);background:var(--warn-soft)}
.st.end,.st.terminated{color:var(--ink2);background:var(--raise)}
.st.bad,.st.stuck,.st.failed{color:var(--bad);border-color:var(--bad-line);
  background:var(--bad-soft)}
/* Bare — no chrome — for use inline in a dense row. */
.st.bare{border:0;background:none;padding:0}

.detail{display:grid;grid-template-columns:1fr 300px;gap:18px;margin-top:20px}
@media (max-width:820px){.detail{grid-template-columns:1fr}}
.tl{display:flex;height:26px;border-radius:var(--r-sm);overflow:hidden;
  background:var(--line);margin:6px 0 10px}
.tl i{display:block;height:100%}
.tl .on2{background:var(--ok)}
.tl .off2{background:var(--line)}
/* A heading with an action beside it. Floating the button inside the card
   put it on top of the right-aligned value it was meant to sit above. */
.h2row{display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;margin:34px 0 0}
.h2row h2{margin:0}


.kv:last-child{border-bottom:0}
.kv span{color:var(--ink2)}
.kv b{font-family:var(--num);font-weight:600}

.perks{display:grid;gap:14px;margin:24px 0 8px}
.perk{display:flex;gap:11px;align-items:flex-start;font-size:var(--t-small);
  color:var(--ink2);line-height:1.5}
.perk svg{flex:0 0 auto;color:var(--ok);margin-top:1px}
.perk b{color:var(--ink);font-weight:600}

/* Onboarding moves between full page loads, so the smoothness has to come
   from how each step ARRIVES rather than from animating between them. The
   content rises a few pixels as it fades; the progress bar fills rather
   than jumping, which is the one element continuous across steps and the
   only place a real transition is possible. */
.wizard{max-width:520px;margin:var(--s6) auto;
  animation:stepin .34s cubic-bezier(.16,.84,.44,1) both}
/* The models step asks for `wide` and there was no rule for it, so three
   tiers were squeezed into a 520px column and stacked — which is why a
   three-way comparison became a scroll. */
.wizard.wide{max-width:960px}
/* A step whose content is one centred column — the top-up form — reads
   badly at 960px: prose stretches, cards float. `.narrow` caps the
   content without reverting the wrapper, which the tier comparison needs
   at full width. */
.wizard.wide.narrow{max-width:620px}
/* And less dead air above the heading. --s6 top margin on a page that is
   already vertically centred pushed the first line far down a tall
   viewport, so the choices fell below the fold. */
.wizard.wide{margin-top:var(--s3)}
.wizard.wide h1{margin-top:0}
/* The wallet is a 132px box because the coin animation needs room to
   fall. On this step that is most of the space above the fold, and
   the amount cards are what people came for. */
.wizard.narrow .wallet{height:96px}
.wizard.narrow .steps{margin-bottom:24px}
@keyframes stepin{from{opacity:0;transform:translateY(10px)}
  to{opacity:1;transform:none}}
.steps{display:flex;gap:6px;margin-bottom:36px}
.steps i{height:3px;flex:1;background:var(--line);border-radius:2px;
  position:relative;overflow:hidden}
.steps i.done::after{content:"";position:absolute;inset:0;
  background:var(--accent);transform-origin:left;
  animation:stepfill .42s cubic-bezier(.16,.84,.44,1) both}
@keyframes stepfill{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* The choices stagger in behind the heading — four things appearing at
   once reads as a page load; four arriving in sequence reads as a step. */
.wizard .choice,.wizard .popmodel{
  animation:stepin .32s cubic-bezier(.16,.84,.44,1) both}
.wizard .choice:nth-child(1){animation-delay:.05s}
.wizard .choice:nth-child(2){animation-delay:.10s}
.wizard .choice:nth-child(3){animation-delay:.15s}
.wizard .popmodel:nth-child(1){animation-delay:.18s}
.wizard .popmodel:nth-child(2){animation-delay:.21s}
.wizard .popmodel:nth-child(3){animation-delay:.24s}
.wizard .popmodel:nth-child(4){animation-delay:.27s}
.wizard .popmodel:nth-child(5){animation-delay:.30s}

/* Somebody who has asked not to be moved is not asked twice. */
@media (prefers-reduced-motion:reduce){
  .wizard,.wizard .choice,.wizard .popmodel,.steps i.done::after{
    animation:none}
}
.summary{padding:16px 22px;cursor:pointer;font-weight:500;font-size:var(--t-body);
  list-style:none;display:flex;align-items:center;justify-content:space-between}
.summary::-webkit-details-marker{display:none}
.summary:after{content:"+";color:var(--ink2);font-size:var(--t-head)}
details[open] .summary:after{content:"\2212"}
.summary:hover{background:var(--raise)}
/* Two choices, side by side, each a full clickable target. A radio you have
   to find and then a button you have to press is two decisions where there is
   only one. */
.choices{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:26px 0;
  align-items:stretch}
/* THREE tiers, side by side. They were forced into one column, which turned
   a three-way comparison into a scroll — you cannot compare what you cannot
   see at once, and comparing is the entire job of this step. */
.choices.tiers{grid-template-columns:repeat(3,1fr)}
@media (max-width:860px){.choices.tiers{grid-template-columns:1fr}}
/* The tier cards carry the accent, not grey. A page whose only colour is
   the "Recommended" pill reads as unfinished. */
.choices.tiers .choice .tiericon{color:var(--accent)}
.choices.tiers .choice[aria-pressed=true],
.choices.tiers .choice.on{border-color:var(--accent);
  background:var(--accent-soft);box-shadow:var(--ring)}
.choices.tiers .choice small{color:var(--ink2);font-variant-numeric:tabular-nums}
/* In a 3-across card the absolutely-positioned pill lands on top of the
   icon — there is no longer horizontal room between them. Give it its own
   row and let the icon follow. */
.choices.tiers .choice{padding-top:16px}
.choices.tiers .choice::before{content:"";display:block;height:22px;
  margin-bottom:12px}
.choices.tiers .choice .tag{position:absolute;top:16px;left:20px;
  display:inline-flex}
.choices.tiers .choice .tiericon{margin-top:0}
/* position:relative so the tag can leave the flow. In flow it pushed the
   left card's title down by its own height and the two headings no longer
   lined up - the kind of thing that reads as "broken" without being
   nameable. */
.choice{position:relative;display:block;text-align:left;width:100%;
  background:var(--bg);border:1px solid var(--line2);border-radius:var(--r);
  padding:22px 20px;cursor:pointer;font:inherit;color:var(--ink);
  transition:border-color .14s,box-shadow .14s,transform .14s}
.choice:hover{border-color:var(--ink);box-shadow:var(--shadow-lift);
  transform:translateY(-1px)}
.choice:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---- focus, once, for everything ---- */
a:focus-visible,button:focus-visible,summary:focus-visible,
[tabindex]:focus-visible,input:focus-visible,select:focus-visible,
textarea:focus-visible{outline:2px solid var(--accent);outline-offset:2px;
  border-radius:var(--r-sm)}
/* The editor is its own frame, so the ring goes on the frame rather than
   inside it where it would sit under the text. */
.code:focus-visible{outline:0}
.editor:focus-within{border-color:var(--accent);box-shadow:var(--ring)}
/* Rows and cards are large; an outline hugging the whole shape reads better
   than a rectangle around the text inside it. */
.rowlist > a:focus-visible,.node:focus-visible,.rcard:focus-visible{
  outline:2px solid var(--accent);outline-offset:-1px;
  border-radius:var(--r)}
/* Nothing moves for someone who asked for less motion. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms !important;
    animation-duration:.01ms !important;animation-iteration-count:1 !important}
}
/* Tinted tiles. Flat grey icons are what makes a product look generated;
   a little colour, used consistently per concept, is most of what separates
   a drawn icon set from a downloaded one. */
.choice .cico{display:flex;width:42px;height:42px;align-items:center;
  justify-content:center;border-radius:var(--r);margin-bottom:16px}
.cico.credit{background:var(--ok-soft);color:var(--ok);border:1px solid var(--ok-line)}
.cico.byok{background:var(--series-1-soft);color:var(--series-1);border:1px solid var(--series-1-soft)}
.cico.amount{background:var(--warn-soft);color:var(--warn);border:1px solid var(--warn-line)}
.choice b{display:block;font-size:15.5px;font-weight:600;margin-bottom:5px;
  letter-spacing:-0.01em}
.choice p{margin:0;font-size:var(--t-small);line-height:1.5;color:var(--ink2)}
/* Was ink3 — around 3.5:1 on white, below the 4.5:1 body threshold, and it
   reads as disabled rather than secondary. A price nobody can read is the
   one line on this card that decides the choice. */
.choice .rate{color:var(--ink2)}
/* Titles line up because the icon tile and its margin are identical on both
   cards and nothing above the title varies in height. */
.choice b{min-height:0}
.choice .tag{position:absolute;top:18px;right:18px;font-size:var(--t-meta);
  font-weight:600;padding:3px 10px;border-radius:var(--r-pill);background:var(--ink);
  color:var(--bg);letter-spacing:.01em}
.choice.disabled{opacity:.5;cursor:not-allowed}
.choice.disabled:hover{border-color:var(--line2);box-shadow:none;
  transform:none}
.choice .why{display:block;margin-top:12px;font-size:var(--t-meta);color:var(--ink2)}
@media (max-width:620px){.choices{grid-template-columns:1fr}}
.wizard.wide{max-width:620px}
/* A wallet, and a coin that moves WHEN SOMETHING HAPPENS.
   The previous version looped forever, which is decoration rather than
   feedback - an animation that never resolves is telling you nothing. This
   one fires on submit and lands green on success. */
.wallet{position:relative;height:132px;margin:4px 0 8px;display:flex;
  align-items:center;justify-content:center}
.wallet svg{overflow:visible}
.wbody{transition:stroke .4s,fill .4s}
.coin{transform-origin:center;opacity:0}
.wallet.drop .coin{animation:tocard .85s cubic-bezier(.45,.05,.5,1) forwards}
@keyframes tocard{
  0%   {transform:translateY(-42px) scale(.7) rotate(-16deg);opacity:0}
  22%  {opacity:1}
  72%  {transform:translateY(6px) scale(1) rotate(6deg);opacity:1}
  100% {transform:translateY(14px) scale(.35) rotate(10deg);opacity:0}
}
.tick{opacity:0;transform:scale(.6);transform-origin:center}
.wallet.ok .tick{animation:pop .45s .55s cubic-bezier(.2,1.4,.4,1) forwards}
@keyframes pop{to{opacity:1;transform:scale(1)}}
.wallet.ok .wbody{stroke:var(--ok)}
@media (prefers-reduced-motion:reduce){
  /* Someone who asked the system to stop moving things meant exactly this. */
  .wallet.drop .coin,.wallet.ok .tick{animation:none}
  .wallet.ok .tick{opacity:1;transform:none}
}

/* Amounts SELECT rather than submit. Tapping $5 and being thrown to the next
   screen gives no chance to change your mind and no confirmation of what you
   chose. */
.amount.on{border-color:var(--accent);background:var(--accent);color:var(--accent-ink);
  box-shadow:var(--shadow-lift)}
.amount.on span{color:rgba(255,255,255,.75)}

/* Tiles, not pills. Seven word-shaped targets in a row is a wall of text to
   read; a mark plus a short label is scannable, and a bigger target is easier
   to hit. */
.tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:26px 0 6px}
@media (max-width:620px){.tiles{grid-template-columns:repeat(2,1fr)}}
.tile{display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:10px;padding:22px 10px;border:1px solid var(--line2);
  border-radius:var(--r);background:var(--bg);color:var(--ink);font:inherit;
  font-size:var(--t-small);font-weight:500;cursor:pointer;text-align:center;
  min-height:100px;transition:border-color .13s,box-shadow .13s,transform .13s}
.tile:hover{border-color:var(--ink);box-shadow:var(--shadow-lift);
  transform:translateY(-1px)}
.tile:active{transform:none;box-shadow:none}
.tile svg{color:var(--ink2)}
.tile:hover svg{color:var(--ink)}

/* The card fields and the wallet share one page. Paying used to navigate to
   a success screen, which breaks the connection between the coin dropping
   and the money arriving - the animation is feedback for an action, and
   feedback on a different page is just a picture. */
.paybox{border:1px solid var(--line2);border-radius:var(--r);padding:18px;
  margin-top:18px}
.paybox.hide{display:none}
#card{padding:4px 0}
.payrow{display:flex;align-items:center;gap:12px;margin-top:16px}
.payrow .grow{flex:1}
.payerr{color:var(--bad);font-size:var(--t-small);margin-top:10px;min-height:18px}
.secure{display:flex;align-items:center;gap:7px;font-size:var(--t-meta);
  color:var(--ink2);margin-top:14px}
.secure svg{color:var(--ok)}
.amounts{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;
  margin:24px 0 8px}
.amount{border:1px solid var(--line2);border-radius:var(--r);padding:20px 14px;
  text-align:center;cursor:pointer;background:var(--bg);font:inherit;
  color:var(--ink);transition:border-color .14s,box-shadow .14s}
.amount:hover{border-color:var(--ink);box-shadow:var(--shadow-lift)}
.amount b{display:block;font-family:var(--num);font-size:var(--t-display);font-weight:600;letter-spacing:-0.02em}
.amount span{font-size:var(--t-meta);color:var(--ink2)}
.custom{display:flex;gap:10px;align-items:center;margin-top:16px}
.custom input{flex:1}

.pick{display:flex;gap:14px;align-items:flex-start;padding:18px;
  border:1px solid var(--line2);border-radius:var(--r);cursor:pointer;
  margin-bottom:12px;transition:border-color .12s,background .12s;
  background:var(--bg);width:100%;text-align:left;font:inherit}
.pick:hover{border-color:var(--ink);background:var(--raise)}
.pick .ico{flex:0 0 auto;margin-top:2px;color:var(--ink2)}
.pick b{display:block;font-size:var(--t-body);font-weight:600;margin-bottom:2px}
.pick span{font-size:var(--t-small);color:var(--ink2);line-height:1.45}

.keybox{background:var(--ink);color:var(--raise);border-radius:var(--r);padding:16px 18px;
  font-family:var(--mono);font-size:var(--t-small);word-break:break-all;line-height:1.7;
  display:flex;align-items:flex-start;gap:14px}
.keybox span{flex:1}
.copy{background:rgba(255,255,255,.1);border:0;color:var(--raise);border-radius:var(--r-sm);
  padding:6px 10px;cursor:pointer;font:inherit;font-size:var(--t-meta);flex:0 0 auto}
.copy:hover{background:rgba(255,255,255,.18)}

/* No left rule. A 2px bar down the side of a grey box is the house style of
   every generated admin panel; the colour belongs on the icon, where it says
   something, rather than on a stripe that says only "notice". */
/* The icon used to be a flex sibling of the text, which made a bold lead-in
   its own narrow column beside the body - the "lines not aligning" effect.
   Floating it lets the sentence flow as one paragraph and wrap normally. */
.callout{border:1px solid var(--warn-line);border-radius:var(--r);padding:15px 17px;
  font-size:var(--t-small);color:var(--ink);margin:18px 0;background:var(--warn-soft);
  line-height:1.6}
.callout svg{float:left;margin:1px 11px 0 0;color:var(--warn)}
.callout b{font-weight:600}
.callout:after{content:"";display:block;clear:both}
.callout.info{border-color:var(--series-1-soft);background:var(--series-1-soft)}
.callout.info svg{color:var(--series-1)}
/* Green for a good state. Amber says "careful"; money successfully on your
   account is not a warning. */
.callout.ok{border-color:var(--ok-line);background:var(--ok-soft)}
.callout.ok svg{color:var(--ok)}
.err{color:var(--bad);background:var(--bad-soft);border-color:var(--bad-line)}
.err svg{color:var(--bad)}
/* The landing page. Restrained on purpose: the copy rules say plain words
   and no hype, and a hero that shouts undercuts a product whose pitch is
   "you will know what this cost". */
.hero{padding:var(--s6) 0 var(--s4);max-width:62ch}
.hero h1{font-size:2.6rem;line-height:1.1;letter-spacing:-.02em;
  margin:0 0 var(--s3)}
.hero .lede{font-size:1.12rem;line-height:1.5;color:var(--ink2);margin:0}
.heroact{display:flex;gap:10px;margin:var(--s4) 0 var(--s5);flex-wrap:wrap}
.three{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:var(--s4);margin:0 0 var(--s5);padding:var(--s4) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.three b{display:block;margin:0 0 6px}
.three p{margin:0;color:var(--ink2);font-size:var(--t-meta);line-height:1.55}
ul.plain{margin:0 0 var(--s4);padding-left:1.1em;color:var(--ink2);
  line-height:1.7;max-width:70ch}

/* Failures that belong to the customer, on the page they open when
   something looks wrong. Uses the warning tokens rather than a new colour:
   this is "something needs your attention", not an error state. */
/* The tier icons. Same hexagon as the mark, at a size where the count is
   the message — three of these side by side must read as "less / more"
   before anybody reads the labels. */
/* Switching tiers. The wallet's rule applies: it fires on the action and
   RESOLVES — a spinner that loops forever says only "something is
   happening", and the thing happening here is that hexagons light up.
   Which is the same visual language as the icons themselves, so the
   animation is the mark moving rather than a borrowed spinner. */
.switcher{position:relative;height:120px;display:flex;align-items:center;
  justify-content:center;margin:2px 0 6px}
.switcher .tiericon{width:82px;height:82px}
.switcher polygon{transition:opacity .28s ease,fill .28s ease}
/* Each hexagon lights in turn rather than all at once: the count IS the
   difference between tiers, so counting them out is the message. */
.switcher.go polygon:nth-child(1){animation:lite .3s .00s both}
.switcher.go polygon:nth-child(2){animation:lite .3s .07s both}
.switcher.go polygon:nth-child(3){animation:lite .3s .14s both}
.switcher.go polygon:nth-child(4){animation:lite .3s .21s both}
.switcher.go polygon:nth-child(5){animation:lite .3s .28s both}
.switcher.go polygon:nth-child(6){animation:lite .3s .35s both}
@keyframes lite{
  0%   {opacity:.2;transform:scale(.86)}
  60%  {opacity:1;transform:scale(1.12)}
  100% {opacity:1;transform:scale(1)}
}
.switcher polygon{transform-origin:center;transform-box:fill-box}
.switcher .stick{opacity:0;transform:scale(.6);transform-origin:center}
.switcher.ok .stick{animation:pop .4s .1s cubic-bezier(.2,1.4,.4,1) forwards}
@media (prefers-reduced-motion:reduce){
  .switcher.go polygon,.switcher.ok .stick{animation:none}
  .switcher.ok .stick{opacity:1;transform:none}
}

/* The strip: what you are on, what it costs, and a way to change it that
   does not leave the page. */
/* Projections. A bar per model, sorted cheapest first, so the shape of the
   answer is visible before any number is read — that is the whole job of a
   row of bars and it is why this is not a table. */
.projections{display:flex;flex-direction:column;gap:2px}
.prow{display:grid;grid-template-columns:minmax(140px,1.1fr) 3fr auto;
  align-items:center;gap:14px;padding:9px 2px;
  border-bottom:1px solid var(--line)}
.prow:last-child{border-bottom:0}
.prow .pm{display:flex;flex-direction:column;min-width:0}
.prow .pm b{font-size:var(--t-meta);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.prow .pm small{color:var(--ink2);font-size:.72rem}
.prow .pbar{height:8px;background:var(--line);
  border-radius:var(--r-pill);overflow:hidden}
.prow .pbar i{display:block;height:100%;background:var(--ink3);
  border-radius:var(--r-pill);
  transition:width .5s cubic-bezier(.16,.84,.44,1)}
/* The row you are ON is the reference point, so it carries the accent and
   everything else is measured against it. */
.prow.now .pbar i{background:var(--accent)}
.prow.now .pm b::after{content:" · now";color:var(--accent);font-weight:600}
.prow .pv{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums}
.prow .pv b{display:block}
.prow .pv small{font-size:.72rem}
.prow .pv small.down{color:var(--ok)}
.prow .pv small.up{color:var(--ink2)}
.prow:hover .pbar i{filter:brightness(1.15)}

/* Same row grammar as the projections — name, bar, number — because they
   answer neighbouring questions and two different table styles stacked on
   one page reads as two pages. */
.mrow{display:grid;grid-template-columns:minmax(150px,1.1fr) 3fr auto auto;
  align-items:center;gap:14px;padding:9px 2px;
  border-bottom:1px solid var(--line);cursor:default}
.mrow:last-child{border-bottom:0}
.mrow .mm{display:flex;flex-direction:column;min-width:0}
.mrow .mm b{font-size:var(--t-meta)}
.mrow .mm small,.mrow .mv small{color:var(--ink2);font-size:.72rem}
.mrow .mv{text-align:right;white-space:nowrap;
  font-variant-numeric:tabular-nums}
.mrow .mv b{display:block}
.mrow .pbar{height:8px;background:var(--line);
  border-radius:var(--r-pill);overflow:hidden}
.mrow .pbar i{display:block;height:100%;background:var(--accent);
  border-radius:var(--r-pill);opacity:.85;
  transition:width .5s cubic-bezier(.16,.84,.44,1),opacity .14s}
.mrow:hover .pbar i{opacity:1}

/* The stack. Model is the accent because it is almost always the bulk and
   the thing a customer can change; machine and tools are quieter shades of
   the same hue rather than three unrelated colours — a chart is not a
   parade. */
.chart .bar2.seg-tokens{fill:var(--accent)}
.chart .bar2.seg-compute{fill:var(--ink3)}
.chart .bar2.seg-tools{fill:var(--accent-soft)}
.chart .bar2.seg-tools{stroke:var(--line2);stroke-width:.5}
.ttk{width:8px;height:8px;border-radius:2px;display:inline-block;flex:0 0 auto}
.ttk.seg-tokens{background:var(--accent)}
.ttk.seg-compute{background:var(--ink3)}
.ttk.seg-tools{background:var(--accent-soft)}
[data-theme=light] .ttk.seg-tools{background:var(--accent-soft)}
.charttip .tth{font-weight:600;margin-bottom:4px}
.charttip .ttr{display:flex;align-items:center;gap:7px;
  font-size:.72rem;color:var(--ink2);line-height:1.6}
.charttip .ttr b{margin-left:auto;color:var(--ink);
  font-variant-numeric:tabular-nums}

/* The key, so the stack is readable without hovering. */
.chartkey{display:flex;gap:14px;align-items:center;
  font-size:.72rem;color:var(--ink2);margin-top:8px}
.chartkey span{display:inline-flex;align-items:center;gap:6px}

/* Burn. Three numbers across the top, because they answer in sequence:
   what am I spending, what does that annualise to, and when do I run out.
   The third is the one that gets acted on, so it is the one that can go
   red. */
.burn{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:1px;background:var(--line);border:1px solid var(--line);
  border-radius:var(--r);overflow:hidden;margin:0 0 var(--s4)}
.bstat{background:var(--bg);padding:14px 16px}
.bstat b{display:block;font-size:1.45rem;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums}
.bstat span{color:var(--ink2);font-size:var(--t-meta);line-height:1.45}
.bstat.warn b{color:var(--warn)}

/* The drill-down. A <details> so it works before the script runs and is
   keyboard navigable without any code. */
.mdet summary{list-style:none;cursor:pointer}
.mdet summary::-webkit-details-marker{display:none}
.mdet summary::after{content:"";width:6px;height:6px;flex:0 0 auto;
  border-right:1.5px solid var(--ink3);border-bottom:1.5px solid var(--ink3);
  transform:rotate(-45deg);margin-left:2px;transition:transform .16s}
.mdet[open] summary::after{transform:rotate(45deg)}
.mdet summary:hover::after{border-color:var(--ink2)}
.msub{padding:2px 0 10px 0}
.taskrow{display:grid;grid-template-columns:1fr auto auto;gap:14px;
  align-items:center;padding:7px 10px;border-radius:var(--r-sm);
  color:var(--ink2);font-size:var(--t-meta);text-decoration:none}
.taskrow:hover{background:var(--raise);color:var(--ink)}
.taskrow b{font-variant-numeric:tabular-nums;color:var(--ink)}

/* Swapping the group table in place rather than reloading the page. See
   the script in web.py — this class is the hook it looks for. */
#groupwrap.swapping{opacity:.55;transition:opacity .12s}

/* Range. A row of links rather than a select: four options, all visible,
   one click each — a dropdown hides three of them behind an interaction to
   save no space. */
.ranges{display:flex;gap:4px;margin:0 0 var(--s3)}
.range{padding:5px 11px;border-radius:var(--r-pill);color:var(--ink2);
  font-size:var(--t-meta);text-decoration:none;border:1px solid transparent;
  transition:color .14s,border-color .14s,background .14s}
.range:hover{color:var(--ink);background:var(--raise)}
.range.on{color:var(--ink);border-color:var(--line2);background:var(--raise)}

.planbar{display:flex;align-items:center;gap:14px;padding:12px 14px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--bg);
  margin:0 0 var(--s4)}
.planbar .tiericon{width:34px;height:34px;flex:0 0 auto}
.planbar .pb-mid{flex:1;min-width:0}
.planbar .pb-mid b{display:block}
.planbar .pb-mid span{color:var(--ink2);font-size:var(--t-meta)}

/* The sheet. Centred rather than a side panel: this is a decision with
   three options, not a browsing surface. */
.tsheet{position:fixed;inset:0;z-index:60;display:none;
  align-items:center;justify-content:center;padding:20px;
  background:rgba(0,0,0,.5)}
.tsheet.open{display:flex;animation:fadein .18s both}
@keyframes fadein{from{opacity:0}to{opacity:1}}
.tsheet .inner{background:var(--bg);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-lift);
  max-width:560px;width:100%;padding:var(--s5);
  animation:sheetin .26s cubic-bezier(.16,.84,.44,1) both}
@keyframes sheetin{from{opacity:0;transform:translateY(14px) scale(.98)}
  to{opacity:1;transform:none}}
.tierpick{display:grid;gap:8px;margin:var(--s3) 0}
.tierpick button{display:flex;align-items:center;gap:12px;text-align:left;
  padding:11px 13px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--bg);color:var(--ink);cursor:pointer;
  transition:border-color .14s,transform .14s}
.tierpick button:hover{border-color:var(--ink3);transform:translateY(-1px)}
.tierpick button.on{border-color:var(--accent);
  box-shadow:var(--shadow-accent)}
.tierpick .tiericon{width:34px;height:34px;flex:0 0 auto}
.tierpick .tp-mid{flex:1;min-width:0}
.tierpick .tp-mid b{display:block}
.tierpick .tp-mid span{color:var(--ink2);font-size:var(--t-meta)}
.tdone{text-align:center}
.tdone .bal{color:var(--ink2);font-size:var(--t-meta);margin:6px 0 14px}

.tiericon{width:44px;height:44px;display:block}
/* Inside the run page's popover the icon sits in a row, so it is smaller
   than the onboarding card version — same drawing, different size. */
.optico{flex:0 0 auto;display:block}
.optico .tiericon{width:28px;height:28px}
.opt2.on .optico{color:var(--accent)}
.pmark{width:20px;height:20px;display:block;flex:0 0 auto}

/* The second row: named models, secondary to the three tiers above it. A
   quieter treatment on purpose — most people should take a tier. */
.popmodels{display:flex;flex-wrap:wrap;gap:8px;margin:var(--s3) 0 0}
.popmodel{display:inline-flex;align-items:center;gap:8px;padding:8px 12px;
  border:1px solid var(--line);border-radius:var(--r-pill);background:var(--bg);
  color:var(--ink);font-size:var(--t-meta);cursor:pointer;
  transition:border-color .14s,transform .14s}
.popmodel:hover{border-color:var(--ink3);transform:translateY(-1px)}
.popmodel.on{border-color:var(--accent);box-shadow:var(--shadow-accent)}
.popmodel small{color:var(--ink2)}
.tiericon .tf-off{opacity:.2}
.opt2.on .tiericon,.tierpick .on .tiericon{color:var(--accent)}

.alerts{display:flex;flex-direction:column;gap:6px;margin:0 0 18px}
.alert{display:flex;justify-content:space-between;align-items:baseline;
  gap:12px;padding:9px 12px;border-radius:var(--r);
  background:var(--warn-soft);border:1px solid var(--warn-line);
  font-size:var(--t-meta)}
.alert .dim{white-space:nowrap;opacity:.75}

.pill{display:inline-flex;align-items:center;gap:5px;font-size:var(--t-meta);
  padding:2.5px 8px;border-radius:var(--r-pill);background:var(--raise);
  border:1px solid var(--line);color:var(--ink2);font-weight:500}
.pill.ok{color:var(--ok);border-color:var(--ok-line);background:var(--ok-soft)}
.pill.warn{color:var(--warn);border-color:var(--warn-line);background:var(--warn-soft)}
.pill.bad{color:var(--bad);border-color:var(--bad-line);background:var(--bad-soft)}
.empty b{display:block;color:var(--ink);font-weight:500;margin-bottom:4px;
  font-size:var(--t-body)}
.seg{display:inline-flex;border:1px solid var(--line2);border-radius:var(--r-sm);
  overflow:hidden;margin-bottom:16px}
.seg a{padding:7px 14px;font-size:var(--t-small);color:var(--ink2);
  border-right:1px solid var(--line2)}
.seg a:last-child{border-right:0}
.seg a.on{background:var(--accent);color:var(--accent-ink)}
.stat{display:flex;gap:34px;padding:20px 22px;border-bottom:1px solid var(--line)}
.stat div b{display:block;font-size:var(--t-display);font-weight:600;letter-spacing:-0.02em;
  font-family:var(--num)}
.stat div span{font-size:var(--t-meta);color:var(--ink2)}
