/* =============================================================================
   Trading Blox web screens -- shared components.

   Everything two or more screens need: the window shell, the toolbar controls,
   tables, the inspector panel, the status bar, and the overlay a screen shows
   while it is waiting for data or explaining why it never arrived.

   A screen's own stylesheet should hold its LAYOUT and nothing else. If a
   component ends up copied into a second screen, it belongs here instead.
   ========================================================================== */

*{box-sizing:border-box}

/* THE hidden ATTRIBUTE HAS TO WIN. The browser hides it with a UA rule, and a UA
   rule loses to ANY author rule that sets display -- so `.appbar .seg{display:flex}`
   quietly beat `seg.hidden = true` and the CLASSIC / NEW switch stayed on screen
   for licences that have no classic interface to switch to. Fifty-odd controls
   across these screens are shown and hidden through this attribute; this makes
   all of them behave, rather than each component remembering to. */
[hidden]{display:none !important}

html,body{height:100%}
body{
  margin:0;background:var(--ground);color:var(--ink);font-family:var(--ui);font-size:13px;
  line-height:1.5;-webkit-font-smoothing:antialiased;overflow:hidden;user-select:none;
}
input,select,textarea{user-select:text}

.app{height:100%;display:flex;flex-direction:column;min-height:0;position:relative}
.spacer{flex:1 1 auto}
.mono{font-family:var(--data);font-variant-numeric:tabular-nums}

/* ---------- the identity band ----------
   The middle rung of a three-step value ladder: dark title bar, mid steel band,
   white workspace -- inverted for the dark theme. It is the frame of the
   application rather than part of the document, and stepping the two chrome
   bands by VALUE is what stops them reading as one heavy slab, which is what
   happened when both were the same near-black.

   42px, and it holds only the application's own identity: the lockup, which
   installation this is, the menu titles, the interface switch and the version.
   No page controls -- those belong to the row below --
   and nothing that names the screen or the suite, because every pane carries its
   own name and Control carries the suite on its own picker, so a single answer up
   here was wrong over a window showing three panes. */
.appbar{display:flex;align-items:center;gap:14px;padding:0 14px;height:42px;
  box-sizing:border-box;background:var(--band);
  border-bottom:1px solid var(--band-border)}

/* 32px of lockup in a 42px band -- ~5px of optical padding top and bottom. The
   artwork is cropped to its own bounding box: the lockup shipped with dead
   margin baked in, which is what made it render undersized and floaty in a
   fixed-height band. At 32px tall the horizontal lockup is 94px wide. */
.appbar .brand img{display:block;height:32px;width:auto}

/* Positive lockup on the steel band, reversed on the dark one -- slate and blue
   on light, near-white and the lighter blue on dark. Both are transparent, so
   neither carries a background that has to match the band. */
.appbar .brand .brand__dark{display:none}
:root[data-theme="dark"] .appbar .brand .brand__light{display:none}
:root[data-theme="dark"] .appbar .brand .brand__dark{display:block}
@media (prefers-color-scheme:dark){
  :root[data-theme="system"] .appbar .brand .brand__light{display:none}
  :root[data-theme="system"] .appbar .brand .brand__dark{display:block}
}

.appbar .banddiv{width:1px;height:18px;background:var(--band-divider);flex:none}

/* The menu TITLES. The bar is ours, in the band's colours; the popups are real
   Windows menus the shell opens, which is the only way a dropdown can paint over
   the panes below a 42px strip. See shell/band.html. */
.appbar .appmenu{display:flex;gap:2px}
.appbar .appmenu__item{background:none;border:none;border-radius:4px;cursor:pointer;
  font-family:var(--ui);font-size:13px;font-weight:500;line-height:1;
  padding:6px 10px;color:var(--band-ink)}
.appbar .appmenu__item:hover{background:var(--band-hover)}
/* Lit while its popup is up. The popup is a window of its own, so without this
   the band gives no sign of which title opened the menu standing over it. */
.appbar .appmenu__item.on{background:var(--band-hover)}
/* The access-key underline, shown always rather than only while Alt is held:
   there is no menu bar to teach them any more, so the band has to. */
.appbar .appmenu__item u{text-decoration-thickness:1px;text-underline-offset:2px}

/* The right cluster: the theme switch, then the version. */
.appbar .bandright{margin-left:auto;display:flex;align-items:center;gap:8px}

/* The theme switch. Two states in the band -- "follow Windows" is the third and
   lives in Edit > Appearance, because a segmented control that has to show three
   is no longer a switch. Selection is a fill; the 1px lift is the only shadow
   anywhere in the chrome. */
.appbar .seg{display:flex;background:var(--seg);border:1px solid var(--band-border);
  border-radius:4px;padding:2px}
.appbar .seg__btn{background:none;border:none;cursor:pointer;border-radius:3px;
  font-family:var(--data);font-size:10.5px;font-weight:500;line-height:1;
  padding:4px 7px;color:var(--seg-ink)}
.appbar .seg__btn:hover{color:var(--seg-ink-hover)}
.appbar .seg__btn[aria-pressed="true"]{background:var(--seg-sel);font-weight:600;
  color:var(--seg-ink-sel);box-shadow:0 1px 2px rgba(35,42,51,.12)}

.appbar .version{font-family:var(--data);font-size:11px;font-weight:400;
  line-height:1;color:var(--seg-ink);white-space:nowrap}

/* The focus ring the mock did not draw. Every interactive thing in the chrome
   needs one, and it is the only place a 2px accent outline appears. */
.appbar .appmenu__item:focus-visible,
.appbar .seg__btn:focus-visible{outline:2px solid var(--accent-line);
  outline-offset:1px}

/* Below ~720px the band drops the version, then the wordmark -- the mark stays.
   The bands themselves never reflow: the middle is what collapses. */
@media (max-width:720px){
  .appbar .version{display:none}
}
@media (max-width:560px){
  .appbar .brand img{width:32px;object-fit:cover;object-position:left}
}

/* ---------- window title: now the page's CONTROLS row ----------
   Shaded a step away from the page body so a strip of controls reads as
   chrome rather than content. */
.titlebar{display:flex;align-items:center;gap:12px;padding:7px 16px;background:var(--panel-2);
  border-bottom:1px solid var(--rule)}
.titlebar h1{margin:0;font-size:15px;font-weight:640;letter-spacing:-.01em}

/* A dropdown in the title bar: which run the Chart is charting, which run
   Results is showing. It names the thing the whole screen is about, so it sits
   beside the screen's name rather than inside the body. */
.pick{font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--panel);
  border:1px solid var(--rule);border-radius:4px;padding:4px 8px;max-width:300px}
.pick:focus{outline:2px solid var(--accent);outline-offset:-1px}

/* The application lockup (injected by boot.js): one rendered PNG per theme,
   the explicit toggle beating the OS preference in both directions, and a
   hairline between the lockup and the screen's name. */
.brand{display:flex;align-items:center;flex:none}
.brand img{display:block;height:26px;width:auto}
.brand .brand__dark{display:none}
@media (prefers-color-scheme:dark){
  .brand .brand__light{display:none}
  .brand .brand__dark{display:block}
}
:root[data-theme="dark"] .brand .brand__light{display:none}
:root[data-theme="dark"] .brand .brand__dark{display:block}
:root[data-theme="light"] .brand .brand__light{display:block}
:root[data-theme="light"] .brand .brand__dark{display:none}
.brand+h1{border-left:1px solid var(--rule);padding-left:12px}
.path{font-family:var(--data);font-size:11.5px;color:var(--ink-3);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;direction:rtl;max-width:46ch}

/* ---------- title-bar menus ---------- */
.menuwrap{position:relative}
/* Right-anchored, because these hang off controls at the RIGHT end of a title
   bar and would otherwise run off the pane. */
/* Capped and scrollable. A menu built from a LIST -- every system in the library
   that a suite does not already contain -- is as long as the library, and
   without this it ran off the bottom of the pane with no way to reach the end.
   60vh keeps it inside the window wherever the button sits. */
.menupanel{position:absolute;right:0;top:calc(100% + 6px);z-index:60;min-width:225px;
  max-height:min(60vh,420px);overflow-y:auto;overscroll-behavior:contain;
  background:var(--panel);border:1px solid var(--rule);border-radius:6px;
  box-shadow:0 8px 28px rgba(0,0,0,.28);padding:5px}
/* ...and left-anchored for the ones that hang off a control near the LEFT edge,
   where right:0 walks the panel off the other side. */
.menupanel--left{right:auto;left:0}
.mitem{display:block;width:100%;text-align:left;background:none;border:none;border-radius:4px;
  padding:6px 10px;font-size:12.5px;color:var(--ink);cursor:pointer}
.mitem:hover{background:var(--panel-2)}
.mitem:disabled{color:var(--ink-3);cursor:default;background:none}
.msep{height:1px;background:var(--rule-soft);margin:4px 2px}

/* The inline form a menu item turns into for New / Copy / Rename / Delete. */
.mform{padding:7px 9px;display:flex;flex-direction:column;gap:9px;min-width:250px}
.mform .lbl{font-size:11.5px;color:var(--ink-2);max-width:34ch}
.mform input[type=text]{font-family:var(--data);font-size:12.5px;color:var(--ink);
  background:var(--ground);border:1px solid var(--rule);border-radius:4px;padding:5px 8px}
.mform input[type=text]:focus{outline:2px solid var(--accent);outline-offset:-1px}
.mform .gssrow{display:flex;gap:7px;align-items:flex-start;font-size:11.5px;color:var(--ink-2)}
.mform .gssrow input{accent-color:var(--accent);margin-top:1px}
.mform .row{display:flex;gap:8px;justify-content:flex-end}

/* ---------- toolbar ---------- */
.toolbar{display:flex;gap:8px;align-items:center;padding:9px 16px;flex-wrap:wrap;
  background:var(--panel-3);border-bottom:1px solid var(--rule-soft)}

.search{position:relative;flex:0 1 250px;min-width:160px}
.search input{width:100%;font-family:inherit;font-size:12.5px;color:var(--ink);background:var(--panel);
  border:1px solid var(--rule);border-radius:4px;padding:5px 9px 5px 27px}
.search svg{position:absolute;left:8px;top:50%;transform:translateY(-50%);width:13px;height:13px;
  opacity:.5;pointer-events:none}
.search kbd{position:absolute;right:7px;top:50%;transform:translateY(-50%);font-family:var(--data);
  font-size:10px;color:var(--ink-3);border:1px solid var(--rule);border-radius:3px;padding:0 4px;
  background:var(--panel-2);pointer-events:none}
.search input:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:transparent}
.search input:focus ~ kbd{display:none}

/* A flat tab strip, not a bordered pill row: the selected tab is a filled
   rectangle sitting on a thin baseline rule, the rest are plain text. */
.segs{display:flex;gap:2px;border-bottom:2px solid var(--rule-soft)}
.seg{font-family:inherit;font-size:12px;padding:6px 12px;background:transparent;color:var(--ink-2);
  border:0;cursor:pointer;margin-bottom:-2px;border-bottom:2px solid transparent}
.seg:hover{background:var(--panel-2);color:var(--ink)}
.seg[aria-pressed="true"]{background:var(--accent);color:var(--accent-ink);font-weight:620;
  border-bottom-color:var(--accent)}

.filt{font-family:inherit;font-size:12px;padding:4px 10px;border-radius:999px;cursor:pointer;
  border:1px solid var(--rule);background:var(--panel);color:var(--ink-2);display:inline-flex;
  gap:6px;align-items:center}
.filt:hover{background:var(--panel-2)}
.filt[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-soft);color:var(--ink);
  font-weight:600}
.filt .cnt{font-family:var(--data);font-size:10.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}
.filt[aria-pressed="true"] .cnt{color:var(--accent)}
.pip{width:6px;height:6px;border-radius:50%}
.pip--warn{background:var(--warn)} .pip--bad{background:var(--bad)}

/* ---------- buttons ---------- */
.btn{font-family:inherit;font-size:12.5px;padding:5px 13px;border-radius:4px;cursor:pointer;
  border:1px solid var(--rule);background:var(--panel);color:var(--ink)}
.btn:hover{background:var(--panel-3)}
/* The filled buttons must RESTATE their background on hover. `.btn:hover` sets
   one, and a pseudo-class beats a plain class, so the hover grey was overriding
   `.btn--go`'s blue while the white text stayed white -- every primary and
   danger button in the application went blank under the pointer. Same
   specificity here (0,2,0), so it is source order that settles it: these come
   after. */
.btn--go{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:620}
.btn--go:hover{background:var(--accent);filter:brightness(1.08)}
.btn--danger{background:var(--bad);border-color:var(--bad);color:#fff;font-weight:620}
.btn--danger:hover{background:var(--bad);filter:brightness(1.08)}
.btn:disabled{opacity:.45;cursor:default}
.btn--link{border:0;background:none;color:var(--accent);text-decoration:underline;
  text-underline-offset:2px;padding:5px 2px}
.btn:focus-visible,.seg:focus-visible,.filt:focus-visible{outline:2px solid var(--accent);
  outline-offset:2px}

/* ---------- tables ---------- */
.tablescroll{overflow:auto;flex:1 1 auto;min-height:0}
table{border-collapse:separate;border-spacing:0;width:100%;font-size:12.5px}
thead th{position:sticky;top:0;z-index:2;background:var(--panel-2);color:var(--ink-2);font-size:10.5px;
  letter-spacing:.06em;text-transform:uppercase;font-weight:700;text-align:left;padding:7px 10px;
  border-bottom:1px solid var(--rule);white-space:nowrap}
thead th[data-col]{cursor:pointer}
thead th[data-col]:hover{color:var(--ink)}
thead th .arw{opacity:0;font-size:9px;margin-left:3px}
thead th[data-sorted] .arw{opacity:.75}
tbody td{padding:6px 10px;border-bottom:1px solid var(--rule-soft);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;max-width:280px}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
.sym{font-family:var(--data);font-weight:600}
.empty{padding:40px 16px;text-align:center;color:var(--ink-3);font-size:13px}

.pill{font-size:10.5px;padding:1px 7px;border-radius:999px;border:1px solid var(--rule);
  color:var(--ink-2)}
.pill--stale{background:var(--warn-soft);border-color:var(--warn);color:var(--warn)}
.flag{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:6px;vertical-align:1px}
.flag--bad{background:var(--bad)} .flag--warn{background:var(--warn)} .flag--none{background:transparent}

/* ---------- inspector ---------- */
.note{margin:10px 14px 0;padding:8px 10px;border-radius:4px;font-size:12px;line-height:1.45;
  border-left:2px solid}
.note--bad{background:var(--bad-soft);border-color:var(--bad)}
.note--warn{background:var(--warn-soft);border-color:var(--warn)}
.note b{display:block;font-weight:640;margin-bottom:1px}
.note a{color:var(--accent);cursor:pointer;text-decoration:underline;text-underline-offset:2px}

details.grp{border-bottom:1px solid var(--rule-soft)}
details.grp>summary{list-style:none;cursor:pointer;padding:8px 14px;display:flex;align-items:center;
  gap:7px;font-size:10px;letter-spacing:.12em;text-transform:uppercase;font-weight:700;
  color:var(--ink-3)}
details.grp>summary::-webkit-details-marker{display:none}
details.grp>summary::before{content:"\25B8";font-size:9px;opacity:.75;transition:transform .12s ease}
details.grp[open]>summary::before{transform:rotate(90deg)}
details.grp>summary:hover{color:var(--ink-2)}
details.grp>summary .n{margin-left:auto;font-family:var(--data);letter-spacing:0;text-transform:none;
  font-weight:400;font-size:10.5px}

.fields{padding:0 14px 12px;display:flex;flex-direction:column;gap:7px}
.f{display:grid;grid-template-columns:104px 1fr;align-items:center;gap:10px}
.f>label{font-size:11.5px;color:var(--ink-2)}
.f input,.f select{width:100%;font-family:var(--data);font-size:12px;color:var(--ink);
  background:transparent;border:1px solid transparent;border-radius:3px;padding:3px 6px}
.f input:hover,.f select:hover{border-color:var(--rule);background:var(--panel)}
.f input:focus,.f select:focus{outline:2px solid var(--accent);outline-offset:-1px;
  background:var(--panel);border-color:transparent}
.f input[readonly]{color:var(--ink-3)}
.f.dirty input,.f.dirty select{background:var(--warn-soft);border-color:var(--warn)}

/* A field with a button beside it: Browse, or the correlation picker. */
.f--act{grid-template-columns:104px 1fr auto}
.f--act .mini{font-family:inherit;font-size:11px;padding:3px 8px;border:1px solid var(--rule);
  border-radius:3px;background:var(--panel);color:var(--ink-2);cursor:pointer;white-space:nowrap}
.f--act .mini:hover{background:var(--panel-2);color:var(--ink)}

/* ---------- modal picker ---------- */
.modal{position:absolute;inset:0;display:none;place-items:center;background:rgba(0,0,0,.35);z-index:30;
  padding:24px}
.modal.on{display:grid}
.modal__box{background:var(--panel);border:1px solid var(--rule);border-radius:6px;width:min(460px,100%);
  max-height:100%;display:flex;flex-direction:column;box-shadow:0 18px 48px -20px rgba(0,0,0,.6)}
.modal__hd{padding:12px 16px 10px;border-bottom:1px solid var(--rule-soft)}
.modal__hd h2{margin:0;font-size:14px;font-weight:640}
.modal__hd p{margin:3px 0 0;font-size:12px;color:var(--ink-2)}
.modal__body{overflow:auto;flex:1 1 auto;min-height:0;padding:8px 10px}
.modal__ft{display:flex;gap:8px;align-items:center;padding:10px 16px;border-top:1px solid var(--rule);
  background:var(--panel-2)}
.picklist{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:2px}
.picklist label{display:flex;gap:6px;align-items:center;padding:3px 6px;border-radius:3px;
  font-family:var(--data);font-size:12px;cursor:pointer}
.picklist label:hover{background:var(--panel-3)}
.picklist input{accent-color:var(--accent);width:13px;height:13px}

/* ---------- status bar ---------- */
.status{display:flex;align-items:center;gap:14px;padding:9px 16px;border-top:1px solid var(--rule);
  background:var(--panel-2);font-size:12px;color:var(--ink-2)}
.dirtytext{color:var(--warn)}

/* ---------- boot / failure overlay ----------
   Every screen shows this until its first message arrives, and leaves it up
   with a reason if one never does. A blank window is the worst thing a screen
   can do: it looks identical whether the bridge failed, the data was empty, or
   the script never ran. */
.boot{position:absolute;inset:0;display:grid;place-items:center;background:var(--ground);z-index:20;
  padding:24px}
.boot.gone{display:none}
.boot__box{max-width:52ch;text-align:center}
.boot__msg{font-size:14px;color:var(--ink-2);margin:0 0 8px}
.boot__detail{font-family:var(--data);font-size:12px;color:var(--ink-3);margin:0 0 14px;
  white-space:pre-wrap;text-align:left}
.boot__detail:empty{margin:0}

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

/* Drag handle for the adjustable side areas (wired up by boot.js). Invisible
   until hovered, so the boundary looks like a boundary until it is wanted. */
.tbsplit{position:absolute;top:0;bottom:0;width:7px;cursor:col-resize;z-index:40;
  background:transparent;touch-action:none}
.tbsplit:hover,.tbsplit:active{background:var(--accent-soft)}

/* The theme toggle boot.js drops into every title bar. */
.themetog{margin-left:auto;font-family:inherit;font-size:13px;line-height:1;padding:4px 8px;
  border-radius:4px;border:1px solid var(--rule);background:none;color:var(--ink-2);cursor:pointer}
.themetog:hover{background:var(--panel-2);color:var(--ink)}
.titlebar .themetog~*{margin-left:0}


/* =============================================================================
   Parameter rows -- shared by the Control page (a system's parameters) and the
   Suite Editor (the suite's own). The markup comes from shared/params.js, and
   the two screens must not drift into two ideas of what a percent field or a
   stepped range looks like.
   ========================================================================== */

/* Read-only because the suite is locked. Shown once at the top of the
   parameters rather than left to be inferred from disabled fields. */
.lockednote{display:flex;gap:8px;align-items:baseline;background:var(--warn-soft);border:1px solid var(--warn);
  border-radius:6px;padding:8px 12px;font-size:12.5px;color:var(--ink);margin-bottom:12px;max-width:76ch}

/* One area = one group box; the header is dropped when it would just repeat
   the tab above it. Rows are tighter than the other screens: this is the
   place a person tunes twelve numbers in a row. */
.grp{border:1px solid var(--rule);border-radius:6px;margin-bottom:12px;max-width:860px;overflow:hidden}
.grp__hd{background:var(--panel-2);padding:6px 13px;font-size:12px;font-weight:640;color:var(--ink);
  border-bottom:1px solid var(--rule-soft)}
.grp__body{padding:2px 13px 5px}

/* Label and value sit together: names right-justified against a shared
   gutter, controls left-justified right after -- the eye never travels the
   whole row width to pair them. */
.prow{display:grid;grid-template-columns:minmax(150px,34%) 1fr;align-items:center;gap:14px;
  padding:4px 0;border-bottom:1px solid var(--rule-soft);min-height:30px}
.grp__body .prow:last-child{border-bottom:none}
.prow__name{min-width:0;font-size:12.5px;color:var(--ink);text-align:right}
/* WRAPS RATHER THAN OVERFLOWS. The Step toggle is the only way to turn
   stepping back off, and it trails a stepped row's from/to/step/unit/count --
   so on a narrow panel it was pushed past the right edge and out of reach,
   leaving no way to undo a tick. Wrapping puts it on the next line instead. */
.prow__val{display:flex;align-items:center;gap:8px;min-width:0;flex-wrap:wrap;row-gap:6px}
.prow--sub{display:flex;border-bottom:none;padding-top:9px}
.prow--sub .prow__name{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
  font-weight:700;text-align:left}

.prow input[type=text],.prow input[type=date],.prow select{font-family:var(--data);font-size:12.5px;
  color:var(--ink);background:var(--ground);border:1px solid var(--rule);border-radius:4px;padding:4px 8px}
.prow input[type=text]{width:104px;text-align:right}
.prow input[type=text].wide{width:220px;text-align:left}
.prow select{max-width:240px}
.prow input:focus,.prow select:focus{outline:2px solid var(--accent);outline-offset:-1px}
.prow input[type=checkbox]{accent-color:var(--accent);width:15px;height:15px;cursor:pointer}
.prow .unit{font-size:11.5px;color:var(--ink-3);width:14px}

.steplab{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-3)}
/* NOT A BOX OF ITS OWN. The from/to/step groups, the test count and the Step
   toggle wrap as ONE run of items, so a narrow panel breaks them wherever they
   happen to run out of room. As a flex container of its own, .steps3 filled the
   line whether or not its contents needed it, which pushed the Step toggle --
   the only way to turn stepping off -- onto a line by itself, and off the
   screen entirely before this row learned to wrap. */
.steps3{display:contents}
.steps3 .lbl{font-size:10.5px;color:var(--ink-3)}
/* A label and the field it names, kept on one line -- the row may wrap only
   between these, never inside one. */
.steps3 .fgrp{display:inline-flex;align-items:center;gap:6px}
.steps3 input[type=text]{width:74px}
/* A date end needs room for the whole date and its picker button; 74px was a
   number field's width and clipped yyyymmdd to its first four digits. */
.steps3 input[type=date]{width:138px}
.stepcount{font-size:10.5px;color:var(--ink-3);white-space:nowrap}

/* The unit a length of time is counted in, sitting against the number it
   belongs to -- "5 Years" reads as one answer, which is the whole point of
   drawing it here instead of on a row of its own. Narrow, because Days /
   Months / Years is the entire vocabulary. */
.prow .unitsel{width:88px;padding:4px 6px}

/* A stepping range the engine cannot walk, said where it went wrong. The
   count and the complaint share the slot -- one or the other is true -- so
   the row never has to grow to complain. The field is marked too: the count
   is at the end of the row, and the mistake is in a box further back. */
.stepcount--bad{color:var(--bad)}
.steps3 input.is-bad{border-color:var(--bad)}

.setrow{display:flex;gap:8px;align-items:center}

/* The Check table button beside a switch whose truth lives in a table. */
.tablebtn{margin-left:10px;font-size:11px;padding:2px 8px;border:1px solid var(--rule);
  border-radius:4px;background:none;color:var(--ink-2);cursor:pointer}
.tablebtn:hover{color:var(--ink)}

/* Goodness selectors: a wrapping row of checkbox chips (multi) on the suite's
   goodness parameters. */
.goodset{display:flex;flex-wrap:wrap;gap:4px 12px}
.goodchk{display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--ink-2);white-space:nowrap;cursor:pointer}

.perr{color:var(--bad);font-size:11.5px;padding:2px 0 6px}



/* -----------------------------------------------------------------------------
   Locked while a test runs.

   The controls stop taking input; the screen stays READABLE and scrollable,
   which is the point -- a run is exactly when people want to look at the
   parameters they just set. A blocking overlay would have taken that away.

   The host refuses the writes too. This is the half that stops a user typing
   into a field whose value has already been read.
   -------------------------------------------------------------------------- */
.tb-locked input, .tb-locked select, .tb-locked textarea,
.tb-locked button, .tb-locked [contenteditable]{
  pointer-events:none; opacity:.55}

/* The LABEL too, and not for the look. A label activates the control it
   wraps, so a click on the words beside a checkbox toggles it -- the click
   lands on the label, which is not the element pointer-events was taken
   away from. That is how systems could still be checked in and out of a
   suite through a locked Suites page: the tick was refused, the sentence
   next to it was not. */
.tb-locked label{pointer-events:none}

/* ...except the way out. Leaving a screen is not editing it, and a locked
   pane you cannot close is a pane the rail has to rescue you from. */
.tb-locked #closeBtn, .tb-locked #cancelBtn, .tb-locked .tb-lock-note button{
  pointer-events:auto; opacity:1}

/* FIXED, and appended to the document body rather than inserted into the
   screen's own layout. Sticky inside .body made it a flex/grid ITEM of whatever
   container it landed in -- on the Portfolios screen that is a row of columns,
   so the note became a tall narrow column down the left. It has no business
   being part of any screen's layout: it is a strip across the top, over
   whatever is there. */
.tb-lock-note{position:fixed; top:0; left:0; right:0; z-index:40;
  display:flex; align-items:center; gap:8px; padding:6px 12px;
  font-size:12px; font-weight:600; line-height:1.35;
  background:var(--warn-soft); color:var(--ink); border-bottom:1px solid var(--warn);
  box-shadow:0 2px 8px rgba(15,19,24,.10)}
