/* ============================================================================
   LEXUN WORKSPACE SHELL  —  the workspace stylesheet, loaded only by /platform
   ----------------------------------------------------------------------------
   WHAT WAS WRONG WITH THE OLD SHELL

   1. Six flat sidebar items with no grouping, followed by ~55% of the sidebar
      height as dead space, followed by a paragraph of small grey text with nine
      links run together on one line separated by middots. The most important
      navigation on the site was formatted as a footnote.
   2. Nothing in the workspace reached the engines, the evidence pages or the
      account pages except that middot list — so from inside the product you
      could not get to the product's own explanations.
   3. No top bar. No indication of which view you were in beyond a faint
      background tint in the sidebar, no search, no state, and no hint that a
      command palette existed at all — /platform was the one screen where the
      palette had no visible trigger.
   4. A "KEY" chip repeated on five of six items. A badge that appears on almost
      everything communicates nothing; it is just noise with a border.

   THE SHAPE NOW

   Sidebar: brand, one search control, then four labelled groups —
   Decide / Engines / Evidence / Account — then the site rail. Every destination
   on the site is reachable from the workspace without going back to the
   marketing header, which is what "a dashboard with access to the whole
   webpage" has to mean.

   Top bar: sticky, holds the current view's name (so the answer to "where am I"
   is a word, not a tint), the key state, and the palette trigger.

   This file loads only on /platform, so none of it costs the other 34 pages a
   byte. It also lives outside the document because platform.html is 147 KB
   against a hard 150 KB budget enforced by audit/tech.py:244 — inline was not
   an option even if it had been the better one.
   ==========================================================================*/

:root{
  --side-w:256px;
  --top-h:60px;
}

/* ============================ SHELL ====================================== */

.shell{display:flex;min-height:100vh;align-items:flex-start}

/* ============================ SIDEBAR ==================================== */

/* --surface is deliberately translucent (css/hud.css) so panels read as sitting
   on the page rather than on top of it. Navigation cannot afford that: as a
   fixed drawer over live content the page bled straight through it. Compositing
   the same translucent surface over --bg gives a colour identical to what the
   docked column already rendered, but opaque — and it stays correct in the
   paper theme without hard-coding a hex anywhere. */
nav.side{
  --side-bg:var(--surface);
  width:var(--side-w);flex:0 0 var(--side-w);
  border-right:1px solid var(--line);
  background-color:var(--bg);
  background-image:linear-gradient(var(--side-bg),var(--side-bg));
  padding:0;
  display:flex;flex-direction:column;gap:0;
  position:sticky;top:0;height:100vh;
  overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;
}
nav.side::-webkit-scrollbar{width:8px}
nav.side::-webkit-scrollbar-thumb{background:var(--line2);border-radius:4px}

/* No gap on the flex container: an anonymous text run is a flex item, so
   `gap` was inserting 8px between "LEX" and "UN" and the wordmark rendered as
   two words. The gap belongs to the one place it was ever meant for. */
nav.side .brand{
  display:flex;align-items:baseline;gap:0;
  padding:18px 16px 14px;margin:0;
  font-size:19px;font-weight:400;letter-spacing:.01em;
  color:var(--ink);text-decoration:none;
  border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:2;
  background-color:var(--bg);
  background-image:linear-gradient(var(--side-bg),var(--side-bg));
}
nav.side .brand .u{color:var(--acc)}
nav.side .brand .bsub{
  margin-left:9px;
  font-family:var(--sans);font-size:10.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dim);
}

/* --- the search control --------------------------------------------------
   Full width, at the top, shaped like a search field rather than a button,
   because that is the shape people already know how to read. It opens the
   command palette, which is the only search the workspace has — so the control
   that looks like search IS search, rather than being a decoy next to a
   keyboard shortcut nobody was told about. */
.sidesearch{
  display:flex;align-items:center;gap:8px;
  margin:12px 12px 4px;padding:0 10px;
  min-height:38px;width:calc(100% - 24px);
  border:1px solid var(--line);border-radius:4px;
  background:rgba(255,255,255,.03);
  color:var(--dim);font-size:13.5px;font-weight:400;text-align:left;
  cursor:pointer;
  transition:border-color .16s ease,color .16s ease,background .16s ease;
}
@media (hover:hover){.sidesearch:hover{border-color:var(--line2);color:var(--mut);background:rgba(255,255,255,.05)}}
.sidesearch kbd{
  margin-left:auto;font:inherit;font-size:11.5px;font-family:var(--mono);
  color:var(--dim);border:1px solid var(--line);border-radius:3px;
  padding:2px 5px;line-height:1;white-space:nowrap;
}

/* --- groups --------------------------------------------------------------
   The heading is the thing that turns six undifferentiated rows into four
   short lists. Four lists of two to five items are scannable; one list of
   fifteen is not, and fifteen is where this sidebar was always heading once it
   held the whole site. */
.navgrp{padding:10px 12px 2px}
.navgrp + .navgrp{border-top:1px solid var(--line);margin-top:8px;padding-top:12px}
.navhd{
  margin:0 0 4px;padding:0 10px;
  font-family:var(--sans);font-size:10.5px;font-weight:500;
  letter-spacing:.18em;text-transform:uppercase;color:var(--dim);
}

.navlink{
  display:flex;align-items:center;gap:8px;
  position:relative;
  padding:9px 10px;min-height:38px;
  border-radius:4px;border:0;background:none;
  color:var(--mut);font-family:inherit;font-size:14px;font-weight:450;
  text-align:left;width:100%;text-decoration:none;cursor:pointer;
  transition:background .14s ease,color .14s ease;
}
@media (hover:hover){.navlink:hover{background:var(--surface2);color:var(--ink)}}
.navlink:active{background:var(--surface2)}
.navlink[aria-current="page"]{background:var(--surface2);color:var(--ink);font-weight:500}
/* A 2px rail rather than only a tint: the tint alone was a ~4% luminance step,
   which is under the threshold at which many screens and most bright rooms can
   show a difference at all. The rail survives both. */
.navlink[aria-current="page"]::before{
  content:"";position:absolute;left:-12px;top:6px;bottom:6px;width:2px;
  background:var(--acc);border-radius:0 2px 2px 0;
}
/* Off-workspace links get a quiet outbound mark, so a row that leaves the
   workspace is distinguishable from a row that switches view inside it.
   Two glyphs, not an icon file — the site ships no icons. */
.navlink.out::after{
  content:"↗";margin-left:auto;font-size:12px;color:var(--dim);
  opacity:0;transition:opacity .14s ease;
}
@media (hover:hover){.navlink.out:hover::after{opacity:1}}
.navlink .vtag{
  margin-left:auto;font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;
  color:var(--dim);border:1px solid var(--line);border-radius:3px;padding:1px 4px;
}

.side .grow{flex:1;min-height:12px}

.sidefoot{
  border-top:1px solid var(--line);
  margin-top:8px;padding:14px 22px 20px;
  font-size:12.5px;color:var(--dim);line-height:1.6;
}
.sidefoot a{color:var(--dim);text-decoration:none}
@media (hover:hover){.sidefoot a:hover{color:var(--mut);text-decoration:underline}}
.sidefoot .loopline{display:block;margin-bottom:8px;color:var(--mut)}

/* ============================ MAIN + TOP BAR ============================= */

main{flex:1;min-width:0;padding:0 0 90px}

/* THE TWO DOORS IN THE WORKSPACE BAR.
   Ghost weight, because the primary action here is still a simulation and not
   an account question — they are a way back in, not a gate in front. They
   collapse to one where the bar starts to crowd, then to none, and the record
   state pill carries the rest. */
.authpair{display:inline-flex;gap:8px;align-items:center}
.authpair .btn{white-space:nowrap}
@media(max-width:56.99rem){.authpair #btnKeyNew{display:none}}
@media(max-width:43.99rem){.authpair{display:none}}
.topbar{
  position:sticky;top:0;z-index:40;
  display:flex;align-items:center;gap:14px;
  min-height:var(--top-h);
  padding:0 clamp(16px,4vw,44px);
  background:color-mix(in srgb,var(--bg) 88%,transparent);
  -webkit-backdrop-filter:saturate(140%) blur(12px);
  backdrop-filter:saturate(140%) blur(12px);
  border-bottom:1px solid var(--line);
}
/* color-mix is not universal; the fallback is a flat solid rather than a
   transparent bar, because a transparent bar with no blur support would let
   content print straight through it. */
@supports not (background:color-mix(in srgb,#000 50%,transparent)){
  .topbar{background:var(--bg)}
}
.topbar .where{
  display:flex;align-items:baseline;gap:9px;min-width:0;
}
.topbar .where .wk{
  font-family:var(--sans);font-size:10.5px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dim);white-space:nowrap;
}
.topbar .where .wv{
  font-size:15px;font-weight:500;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.topbar .tspacer{flex:1;min-width:8px}
.topbar .tstate{
  display:inline-flex;align-items:center;gap:7px;
  font-family:var(--sans);font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--dim);border:1px solid var(--line);border-radius:999px;
  padding:5px 11px;white-space:nowrap;background:none;cursor:pointer;
}
.topbar .tstate:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.topbar .tstate .dot{width:6px;height:6px;border-radius:50%;background:var(--dim)}
.topbar .tstate[data-state="unlocked"]{color:var(--good);border-color:rgba(86,195,149,.34)}
.topbar .tstate[data-state="unlocked"] .dot{background:var(--good)}
.topbar .tstate[data-state="locked"] .dot{background:var(--dim)}

.viewpad{padding:24px clamp(16px,4vw,44px) 0}

/* ============================ MOBILE ===================================== */

nav.tabbar{display:none}

@media(max-width:56.99rem){
  nav.side{
    position:fixed;inset:0 auto 0 0;z-index:120;
    transform:translateX(-100%);
    transition:transform .22s cubic-bezier(.22,.61,.36,1);
    box-shadow:0 0 0 100vmax rgba(0,0,0,0);
    display:flex;
  }
  html[data-side="open"] nav.side{transform:none;box-shadow:0 0 0 100vmax rgba(0,0,0,.55)}
  main{padding-bottom:96px}
  .topbar{padding-left:14px;padding-right:14px;gap:10px}
  .viewpad{padding:18px 16px 0}

  .sidetoggle{
    display:inline-flex;align-items:center;justify-content:center;
    min-width:44px;height:38px;margin-left:-6px;
    border:1px solid var(--line);border-radius:4px;background:none;
    color:var(--ink);font-family:var(--sans);font-size:11px;letter-spacing:.12em;
    text-transform:uppercase;cursor:pointer;
  }

  nav.tabbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:110;
    background:var(--surface);border-top:1px solid var(--line);
    padding:4px 6px calc(4px + env(safe-area-inset-bottom));
  }
  .tabbar button,.tabbar a{
    flex:1;min-height:52px;border:0;background:none;color:var(--dim);
    font-family:inherit;font-size:12.5px;font-weight:500;text-decoration:none;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    border-radius:4px;cursor:pointer;
  }
  .tabbar button[aria-current="page"],.tabbar a[aria-current="page"]{color:var(--ink)}
  /* The bar the row is under, not a colour change alone — same reason as the
     sidebar rail. */
  .tabbar button[aria-current="page"]::before,.tabbar a[aria-current="page"]::before{
    content:"";width:16px;height:2px;background:var(--acc);border-radius:1px;
  }
  .grid2,.grid3{grid-template-columns:1fr}
}
@media(min-width:57rem){.sidetoggle{display:none}}

@media (prefers-reduced-motion:reduce){
  nav.side{transition:none}
  .navlink,.sidesearch{transition:none}
}


/* ===========================================================================
   THE ENGINE  —  how a decision is entered and how a result is presented
   ---------------------------------------------------------------------------
   Everything below overrides css/hud.css, which is loaded before this file.
   hud.css sets one chip treatment for .chip, .badge, .stage, .clsbtn and
   [role="tab"] together — mono, uppercase, letterspaced, fully rounded, and
   lifting 2px on hover. That is a reasonable look for a filter chip. It is the
   wrong look for four different things that happen to share a shape, and on
   the New decision screen it put the progress bar, the evidence classifiers
   and the run metadata at exactly the same visual weight as each other, which
   is a hierarchy of one. They do different jobs and now they look it.
   =========================================================================== */

/* ---- the seven stages ----------------------------------------------------
   Seven uppercase pills across the top of the screen were the loudest object
   on it, and the only one there you could not act on: inert decoration
   outranking the inputs underneath. It is a rail now — one quiet line that
   says where you are and how far there is left — and every stage you have
   already reached is a real control that takes you to its card. */
.stages{
  display:flex;flex-wrap:wrap;gap:0;
  margin:0 0 22px;padding:0;
  border-bottom:1px solid var(--line);
}
.stage{
  position:relative;
  display:inline-flex;align-items:center;gap:7px;
  min-height:38px;padding:9px 14px;
  border:0;border-radius:0;background:none;
  font-family:inherit;font-size:13px;font-weight:500;
  text-transform:none;letter-spacing:-.005em;line-height:1.2;
  color:var(--dim);cursor:default;
  transition:color var(--ctl-dur,170ms) var(--ctl-ease,ease);
}
.stage .n{
  font-family:var(--mono);font-size:12px;letter-spacing:.06em;
  color:var(--dim);
  transition:color var(--ctl-dur,170ms) var(--ctl-ease,ease);
}
/* The state marker is a 2px rule sitting on the container's own border, so the
   rail reads as one line with a segment lit rather than as seven boxes. */
.stage::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;
  background:transparent;
  transition:background var(--ctl-dur,170ms) var(--ctl-ease,ease);
}
.stage.done{color:var(--mut);cursor:pointer}
.stage.done .n{color:var(--good)}
/* hud.css fills .stage.now with var(--acc) — pure white — and pairs it with
   var(--ink-on-acc) for the text. That is the right pairing for a selected tab,
   and it was inherited here because .stage was bundled into the same selector.
   The colour was overridden below to var(--ink) without the background being
   overridden with it, which left #f3f3f3 text on a #ffffff block: a contrast
   ratio of about 1.04:1, so the stage you are actually on was the one stage you
   could not read. The rail marks state with the 2px rule underneath, not with a
   filled block, so the fill is removed rather than re-paired. */
.stage.now{background:none}
.stage.now,.stage.now .n{color:var(--ink)}
.stage.now::after{background:var(--acc)}
/* hud.css lifts every chip 2px on hover. A progress rail that jumps when the
   pointer crosses it is exactly the cheap motion this design language removed
   from the buttons; the hover here is a state change, not a trick. */
@media (hover:hover){
  .stage:hover{transform:none;border-color:transparent;background:none}
  .stage.done:hover{color:var(--ink)}
  .stage.done:hover::after{background:var(--line2,rgba(255,255,255,.28))}
  .stage:not(.done):not(.now):hover{color:var(--dim)}
}

/* ---- evidence classifiers ------------------------------------------------
   These are not decoration: choosing "fact" rather than "assumption" is what
   tightens or widens the published band, so they are the most consequential
   controls on the screen. They are set in the control system's own type,
   like every other control, instead of in the chip font. */
.clsbtn{
  font-family:inherit;text-transform:none;
  font-size:13px;font-weight:500;letter-spacing:-.005em;
  border-radius:var(--ctl-r,4px);
  min-height:var(--ctl-h-sm,36px);padding:0 12px;
  display:inline-flex;align-items:center;
  background:var(--ctl-face,rgba(255,255,255,.05));
  transition:color var(--ctl-dur,170ms) var(--ctl-ease,ease),
             border-color var(--ctl-dur,170ms) var(--ctl-ease,ease),
             background var(--ctl-dur,170ms) var(--ctl-ease,ease);
}
@media (hover:hover){
  .clsbtn:hover{transform:none;color:var(--ink);border-color:var(--line2,rgba(255,255,255,.28))}
}
.clsbtn[aria-pressed="true"]{
  border-color:var(--acc);color:var(--acc);
  background:color-mix(in srgb,var(--acc) 12%,transparent);
}
@media (hover:hover){
  .clsbtn[aria-pressed="true"]:hover{color:var(--acc);border-color:var(--acc)}
}

/* ---- run provenance ------------------------------------------------------
   "5,000 paths · seed 564 · model 1.0.0" is the receipt for the run: it is the
   reason the result can be reproduced, and it belongs beside the button. As a
   bordered pill at button height it read as a second button that did nothing
   when clicked. It is metadata, so it is set as metadata. */
#simMeta{
  border:0;background:none;padding:0;
  font-family:var(--mono);font-size:12.5px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--dim);
  align-self:center;
}

/* ---- the verdict ---------------------------------------------------------
   The plain-English verdict is the single sentence the whole product exists to
   produce, and it was the third-largest piece of type in its own card.

   css/lexun.css caps every h2 at 26ch, which is right for a section heading at
   its display size. .verdict h2 overrode the size down to 20px but not the cap,
   and because the cap is in ch it shrank with the font — a 95-character
   sentence broke into three 30-character lines inside a 1096px card. The cap is
   restated here at a measure suited to a statement rather than a label. */
.verdict h2{
  font-size:clamp(21px,1.9vw,27px);
  line-height:1.24;letter-spacing:-.015em;
  max-width:46ch;margin:10px 0 12px;
}
/* The band is the verdict's classification and sat above it in 13px regular,
   reading as a caption. It is the answer's category — small, but deliberate. */
.verdict .band{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.14em;
  text-transform:uppercase;
}

/* ---- result markup that used to be inline style attributes ---------------
   renderResult() built its markup with nine hard-coded style="" attributes.
   Each one was a decision about type or spacing made in JavaScript, invisible
   to every stylesheet, unthemeable, and unfixable without editing the
   application — the same problem as the seven competing .btn definitions this
   pass started with, one layer down. They are classes now.

   .pstat .v is a figure at 20px. Two of the three figures in that row are
   numbers; the third is the word "moderate", and a word set at a number's size
   claims a precision it does not have. .word is that exception, named for what
   it is rather than for the pixel value it happens to use. */
.pstat .v.word{font-size:16px;letter-spacing:0}
/* Three of the four .mod tiles hold a short label; two hold a full sentence.
   A sentence at label size overflows its tile, so it steps down and gains the
   line-height a sentence needs. */
.mod .mv.sent{font-size:13px;font-weight:400;line-height:1.5}
.bul{margin:6px 0 0 18px}
.mb10{margin-bottom:10px}
.acc2{color:var(--acc2)}
/* Inline links inside a validation message: the message already carries the
   warning colour, and a second colour on the link inside it would be two
   signals for one fact. It underlines instead. */
.ilink{color:inherit;font-weight:500}


/* ---- the sample-data flag ------------------------------------------------
   "SAMPLE DATA — NOT YOUR NUMBERS" is the most important honest signal on the
   New decision screen: it is what stops a visitor mistaking a demonstration for
   their own forecast. hud.css gives every .badge the chip treatment, so it sat
   between "Try it with example numbers" and "Replace with my numbers" as a
   bordered pill at exactly the two buttons' 44px height — a warning wearing a
   button's clothes, in a row of buttons. Visitors click warnings that look
   clickable, find nothing happens, and stop reading them.

   It keeps the mono type and the warn colour, because those are what make it
   read as a caution rather than as a label. It loses the border, the fill and
   the button height, and gains a rule down its left edge: the vocabulary of an
   annotation, which is what it is. */
#exampleFlag{
  border:0;border-left:2px solid var(--warn);
  border-radius:0;background:none;
  padding:2px 0 2px 10px;min-height:0;
  align-self:center;
  font-size:12.5px;letter-spacing:.1em;
}

/* The two doors in the top bar. Familiar words for a local passcode: "Sign in"
   opens the unlock tab, "Get started" the create tab. They sit together so the
   pair reads as one choice, and they disappear once the record is open. */
.topbar .authpair{display:inline-flex;gap:8px;align-items:center;margin-left:10px}
.topbar .authpair[hidden]{display:none}
@media(max-width:43.99rem){
  /* A narrow top bar cannot hold two doors, the menu, the location, the state
     pill AND search. Something has to go, and the first attempt cut the wrong
     thing: it hid Sign in, so a returning person on a phone was offered only
     "Get started" — the door for someone who has never been here. A person
     with a record could not see the way back into it.
     Search goes instead. It is a convenience, it is still on Ctrl+K, and it is
     still in the menu. A way back into your own record is not a convenience.
     The long halves of the labels go too ("Unlock my record" → "Unlock",
     "New simulation" → "New", "Not saved yet" → "Not saved"); the accessible
     names keep the full wording. Measured: below 44rem the bar was clipping
     the primary button to "New / imulatio" and the pill to "NOT". */
  .topbar .authpair{margin-left:6px;gap:6px}
  .topbar .authpair .btn{padding-left:10px;padding-right:10px;white-space:nowrap}
  .topbar > [data-lxcmd]{display:none}
  .topbar .tb-full{display:none}
  .topbar .btn.sm{flex:0 0 auto;overflow:visible}
  .topbar .where{min-width:0;overflow:hidden;text-overflow:ellipsis}
  /* the ellipsis has to sit on the text span: text-overflow does nothing on a
     flex container, which is why the pill was cut mid-letter */
  .topbar .tstate{flex:0 1 auto;min-width:0;max-width:11em}
  .topbar .tstate #keystatetxt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
@media(max-width:34.99rem){
  /* The location line is the one thing here the page already says: the view
     heading directly beneath the bar carries the same words. And the state
     pill keeps its dot and its accessible name but not its words: a 320-pixel
     phone cannot hold Menu, the pill's text, the returning door and the
     primary action without clipping one of them, and the site's breakpoint
     ladder (rightly) has no rung below this one to special-case 320. The
     dot's colour still says saved-or-not; the record is one tap away in the
     Menu; the words are read out by a screen reader. */
  .topbar .where{display:none}
  .topbar .tstate{min-width:24px;min-height:24px;justify-content:center;padding:5px 8px}
  .topbar .tstate .dot{width:10px;height:10px}
  .topbar .tstate #keystatetxt{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
}
