/* Hallmark · macrostructure: Workbench · genre: atmospheric · tone: technical
 * theme: Vespryx (brand-locked, preserved at pre-flight) · anchor hue: cool-blue
 * pre-emit critique: P5 H5 E5 S5 R4 V4
 *
 * Every colour and font here is a token from ../ui/tokens.css. No inline hex, no
 * bare font-family: the palette is the same one the walls are drawn in, and a
 * settings page that drifts to a different amber teaches the wrong colour for a
 * line the regime panel is about to name out loud.
 *
 * THE LAYOUT IS A TWO-COLUMN WORKBENCH, and that is the v2 redesign's one
 * structural claim. This page was a single 400-line scroll of nine cards, which
 * is the shape that hides the thing you came for: the expiry picker and the
 * strength floor both sat below three cards of prose, so both were reported as
 * missing. Six sections behind a sticky rail means every control is at most one
 * click and no scroll away, and the rail can state what each section is DOING.
 */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  overflow-x: clip;          /* clip, never hidden: hidden kills position:sticky */
}

body {
  /* Two gradients, one job: lift the top of the page off the flat navy so the
   * hero reads as a lit surface rather than a border. */
  background:
    radial-gradient(1100px 620px at 50% -8%, rgba(var(--tdx-slate-rgb), 0.07), transparent 62%),
    radial-gradient(120% 80% at 78% -10%, rgba(var(--tdx-accent-rgb), 0.08), transparent 60%),
    var(--tdx-navy);
  color: var(--tdx-white);
  font: var(--tdx-text-base)/1.55 var(--tdx-font);
  /* A flex column so the sticky footer lands on the viewport floor when the
   * visible section is short. Sections now differ hugely in height -- Keep dressed
   * is a third of On your chart -- and a footer floating mid-page with dead space
   * under it reads as a page that failed to finish loading. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.shell { flex: 1; }

code {
  font-family: var(--tdx-mono);
  font-size: 0.92em;
  background: rgba(var(--tdx-slate-rgb),  0.13);
  padding: 1px 5px;
  border-radius: 4px;
}

.a { color: var(--tdx-accent); text-decoration: none; }
.a:hover { color: var(--vx-glow); text-decoration: underline; }
.a:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 2px; border-radius: 3px; }

/* ============================================================ hero */
.hero {
  position: relative;
  overflow: hidden;
  /* The kit's own black, one step under navy, so the wordmark sits on the
   * background it was drawn against. */
  background:
    radial-gradient(660px 250px at 15% -55%, rgba(var(--tdx-accent-rgb), 0.20), transparent 70%),
    var(--vx-black);
}
/* A gradient rule, not a border: it fades from accent at the wordmark to plain
 * line by the right edge, so the header ends without drawing a hard box. */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(var(--tdx-accent-rgb), 0.5),
    rgba(var(--tdx-accent-rgb), 0.07) 44%,
    var(--tdx-line) 76%);
}
.hero__inner {
  max-width: 1000px;
  margin: 0 auto;
  padding: var(--tdx-space-32) var(--tdx-space-24) var(--tdx-space-24);
  display: flex;
  align-items: flex-end;
  gap: var(--tdx-space-24);
  flex-wrap: wrap;
}
.hero__id { flex: 1; min-width: 300px; display: grid; gap: var(--tdx-space-12); justify-items: start; }

/* The supplied lockup. Sized by half its intrinsic width so it stays crisp on a
 * 2x display, and it already carries the tagline, so the byline does not repeat it. */
.brand__logo { display: block; width: 306px; max-width: 100%; height: auto; }

.hero__by { margin: 0; color: var(--tdx-slate); font-size: var(--tdx-text-base); max-width: 48ch; }
.hero__src { display: block; margin-top: var(--tdx-space-4); font-size: var(--tdx-text-sm); }

/* Connection chip. State lives in data-state so JS sets one attribute, not
 * three class names it might forget to clear. */
.conn {
  display: inline-flex;
  align-items: center;
  gap: var(--tdx-space-8);
  padding: var(--tdx-space-6) var(--tdx-space-12);
  border: var(--tdx-rule);
  border-radius: var(--tdx-radius-pill);
  background: rgba(var(--tdx-navy-rgb),  0.6);
  font-size: var(--tdx-text-sm);
  color: var(--tdx-slate);
}
.conn__dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--tdx-slate);
  transition: background var(--tdx-dur) var(--tdx-ease-out);
}
.conn[data-state="ok"] { color: var(--tdx-green-text); border-color: rgba(var(--tdx-green-rgb),  0.4); }
.conn[data-state="ok"] .conn__dot { background: var(--tdx-green); box-shadow: 0 0 0 3px rgba(var(--tdx-green-rgb), 0.16); }
.conn[data-state="out"] { color: var(--tdx-amber); border-color: rgba(var(--tdx-amber-rgb),  0.4); }
.conn[data-state="out"] .conn__dot { background: var(--tdx-amber); box-shadow: 0 0 0 3px rgba(var(--tdx-amber-rgb), 0.16); }
.conn[data-state="err"] { color: var(--tdx-red-text); border-color: rgba(var(--tdx-red-rgb),  0.4); }
.conn[data-state="err"] .conn__dot { background: var(--tdx-red); }
/* The pulse says the chip is a live reading rather than a label printed once. */
.conn[data-state="ok"] .conn__dot,
.conn[data-state="out"] .conn__dot { animation: tdx-pulse 2.8s ease-in-out infinite; }
@keyframes tdx-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
@media (prefers-reduced-motion: reduce) { .conn__dot { animation: none !important; } }

/* ------------------------------------------------------------- master switch
 * Opposite the wordmark, alone on its side of the header. In a card at the top of
 * the body it read as the first of nine settings; the one control that turns the
 * whole product off should not be in the same list as the one that renames a label. */
.hero__master { display: grid; gap: var(--tdx-space-8); justify-items: end; }
.master {
  display: flex;
  align-items: center;
  gap: var(--tdx-space-12);
  padding: var(--tdx-space-8) var(--tdx-space-12);
  border: var(--tdx-rule);
  border-radius: var(--tdx-radius);
  background: rgba(var(--tdx-panel-rgb), 0.8);
  cursor: pointer;
  transition: border-color var(--tdx-dur) var(--tdx-ease-out);
}
.master:hover { border-color: rgba(var(--tdx-slate-rgb), 0.45); }
.master__label { display: grid; gap: 2px; text-align: right; }
.master__title { font-size: var(--tdx-text-md); font-weight: 600; }
.master__state {
  font: 600 var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.12em;
  color: var(--tdx-green-text);
}
.master__fine {
  margin: 0;
  max-width: 30ch;
  text-align: right;
  color: var(--tdx-slate-dim);
  font-size: var(--tdx-text-xs);
  line-height: 1.5;
}
/* The green track: this switch is not one of the accent-blue feature toggles. */
.master .sw:checked ~ .sw__track { background: var(--tdx-green); border-color: var(--tdx-green); }
/* Off reads as a warning, not as a neutral setting: the product is doing nothing. */
.hero__master:has(.sw:not(:checked)) .master { border-color: rgba(var(--tdx-amber-rgb), 0.5); }
.hero__master:has(.sw:not(:checked)) .master__state { color: var(--tdx-amber); }

/* ============================================================ shell + nav */
.shell {
  /* width: 100% because body is a column flex container, and an auto cross-axis
   * margin there cancels `align-self: stretch` -- the shell would shrink to fit
   * its content instead of filling to max-width. */
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  padding: var(--tdx-space-24);
  display: grid;
  grid-template-columns: 196px minmax(0, 1fr);
  gap: var(--tdx-space-24);
  align-items: start;
}

.nav { position: sticky; top: var(--tdx-space-16); display: grid; gap: 3px; }
.nav__eyebrow {
  padding: 2px var(--tdx-space-12) var(--tdx-space-8);
  font: 600 var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.18em;
  color: var(--vx-chrome-lo);
}
.nav__item {
  position: relative;
  display: grid;
  gap: 2px;
  justify-items: start;
  text-align: left;
  padding: var(--tdx-space-8) var(--tdx-space-12);
  border: 1px solid transparent;
  border-radius: var(--tdx-radius-sm);
  background: transparent;
  color: var(--tdx-white-dim);
  font: inherit;
  cursor: pointer;
  transition:
    background var(--tdx-dur-fast) var(--tdx-ease-out),
    border-color var(--tdx-dur-fast) var(--tdx-ease-out);
}
/* The active bar is a child rather than a border-left, so switching sections does
 * not shift the label by a pixel. */
.nav__item::before {
  content: "";
  position: absolute;
  left: 0; top: var(--tdx-space-12); bottom: var(--tdx-space-12);
  width: 2px;
  border-radius: 0 2px 2px 0;
  background: transparent;
  transition: background var(--tdx-dur-fast) var(--tdx-ease-out);
}
.nav__item:hover { background: var(--tdx-raise); }
.nav__item:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 2px; }
.nav__item[aria-current="true"] { background: var(--tdx-raise); border-color: var(--tdx-line); color: var(--tdx-white); }
.nav__item[aria-current="true"]::before { background: var(--tdx-accent); }
.nav__label { font-size: var(--tdx-text-base); font-weight: 600; }
.nav__note {
  font: var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.03em;
  color: var(--tdx-slate-dim);
}
.nav__item[aria-current="true"] .nav__note { color: var(--tdx-slate); }

/* ============================================================ layout */
.wrap { display: grid; gap: var(--tdx-space-16); min-width: 0; }
.sec { display: grid; gap: var(--tdx-space-16); min-width: 0; }
/* A section, like a tabpanel, needs the reset: [hidden] loses to any author
 * `display` rule, and `display:grid` here is exactly such a rule. This is the
 * bug popup.css found once and fixed for one element; it is a page-level rule now. */
[hidden] { display: none !important; }

/* The card gained a gradient, a shadow and 14px corners. Flat panel-on-navy at
 * 12px read as a form; the lift is what makes six of them read as a stack of
 * instrument panels. */
.card {
  /* --tdx-line-soft, not --tdx-line: the mockup reserves the heavier edge for the
   * panel chrome and gives cards the softer one. */
  border: 1px solid var(--tdx-line-soft);
  border-radius: 14px;
  background: linear-gradient(var(--tdx-panel-hi), var(--tdx-panel-lo));
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.34);
  overflow: hidden;
}
.card--accent {
  border-color: rgba(var(--tdx-accent-rgb),  0.24);
  background:
    radial-gradient(420px 200px at 0% 0%, rgba(var(--tdx-accent-rgb), 0.09), transparent 70%),
    linear-gradient(var(--tdx-panel-hi), var(--tdx-panel-lo));
}

.card__head { padding: var(--tdx-space-16) var(--tdx-space-20) var(--tdx-space-12); }
.card__head--row { display: flex; align-items: center; gap: var(--tdx-space-12); }
.card__headtext { flex: 1; display: grid; gap: 3px; min-width: 0; }
.card__head h2 {
  margin: 0;
  font-size: var(--tdx-text-md);
  font-weight: 650;
  letter-spacing: -0.01em;
}
.card__head p { margin: var(--tdx-space-4) 0 0; max-width: 70ch; color: var(--tdx-slate); font-size: var(--tdx-text-sm); line-height: 1.55; }
.card__headtext p { margin: 0; }
.card__head p + p { margin-top: var(--tdx-space-8); }

/* The count of what is live, in the head. It is the one number that answers "is
 * this section doing anything", which is otherwise six toggles to read. */
.tally {
  flex: none;
  padding: 3px var(--tdx-space-8);
  border: 1px solid rgba(var(--tdx-accent-rgb), 0.26);
  border-radius: var(--tdx-radius-pill);
  background: rgba(var(--tdx-accent-rgb), 0.11);
  font: 600 var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.06em;
  color: var(--vx-glow);
  white-space: nowrap;
}

/* The foot is a tinted band, so buttons and fine print read as the card's
 * apparatus rather than as two more rows. */
.card__foot {
  padding: var(--tdx-space-16) var(--tdx-space-20);
  border-top: 1px solid var(--tdx-raise);
  background: rgba(var(--tdx-navy-rgb), 0.5);
}
.card__foot--bare { border-top: none; background: transparent; padding-top: 0; }

/* ============================================================ switch rows */
.row {
  display: grid;
  /* minmax(0, 1fr), never a bare 1fr. A 1fr track's floor is its content's
   * min-content width, and .row__ep is `white-space: nowrap` -- so the longest
   * endpoint string ("needs /ticker/:symbol/tactical-grid (401, beginner tier)",
   * ~330px) becomes a hard minimum for the whole card. That is invisible on a wide
   * monitor and breaks the ~600px pane Chrome renders this page in from
   * chrome://extensions, where `overflow-x: clip` would hide the scrollbar and
   * leave truncation as the only symptom. The `min-width: 0` on .row__label does
   * not help: it bounds the item, not the track. */
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--tdx-space-16);
  padding: var(--tdx-space-12) var(--tdx-space-20);
  border-top: 1px solid var(--tdx-raise);
  cursor: pointer;
  transition: background var(--tdx-dur-fast) var(--tdx-ease-out);
}
.row:hover { background: var(--tdx-raise); }
/* A segmented row is centred: its control is a single-line tray, so top-aligning
 * it against a four-line note leaves the chips floating at the ceiling. */
.row--seg { align-items: center; }

.row__label { display: grid; gap: 3px; min-width: 0; justify-items: start; }
.row__title { font-weight: 600; font-size: var(--tdx-text-base); }
.row__note { color: var(--tdx-white-2); font-size: var(--tdx-text-sm); line-height: 1.5; }
.row__hint { color: var(--tdx-slate-dim); }

/* The endpoint, in a chip. It is the strongest honesty signal on the page --
 * "this layer is one call against your session" is a claim you can check -- and
 * left as bare mono text it read as a stray comment. */
.row__ep {
  margin-top: 2px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 2px var(--tdx-space-6);
  border: var(--tdx-rule);
  border-radius: 5px;
  background: rgba(var(--tdx-slate-rgb), 0.06);
  font: var(--tdx-text-xs) var(--tdx-mono);
  color: var(--tdx-slate-dim);
}

/* A small inline qualifier beside a title ("reload the page"). */
.tag {
  margin-left: var(--tdx-space-6);
  padding: 1.5px var(--tdx-space-6);
  border: var(--tdx-rule);
  border-radius: 5px;
  background: rgba(var(--tdx-slate-rgb), 0.07);
  font: var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.04em;
  font-weight: 400;
  color: var(--tdx-slate-dim);
  white-space: nowrap;
}

/* A layer with no endpoint behind it. Dimmed and labelled, never dropped: the
 * design promises six layers and silently shipping three leaves no trace of why. */
.row[data-ready="false"] { cursor: default; opacity: 0.55; }
.row[data-ready="false"]:hover { background: transparent; }
.row__soon {
  flex: none;
  align-self: center;
  padding: 3px var(--tdx-space-8);
  border: 1px solid rgba(var(--tdx-amber-rgb), 0.3);
  border-radius: 5px;
  background: rgba(var(--tdx-amber-rgb), 0.1);
  font: 600 var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.08em;
  color: var(--tdx-amber);
  white-space: nowrap;
}

/* ------------------------------------------------------------------- marks
 * A 28px tile per layer, drawn in that layer's own colour AND its own line
 * style. The table teaches the chart's vocabulary while you switch it on: a
 * dotted purple tile here and a dotted purple line on the chart are the same
 * claim, which is the whole reason the palette is a token file.
 *
 * Drawn in CSS rather than shipped as six icons so it cannot drift off the
 * tokens the walls are actually painted with. */
.row--layer { grid-template-columns: auto minmax(0, 1fr) auto; }
.mark {
  flex: none;
  width: 28px; height: 28px;
  margin-top: 1px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(var(--tdx-slate-rgb), 0.16);
  border-radius: 8px;
  background: rgba(var(--tdx-slate-rgb), 0.07);
  transition: background var(--tdx-dur) var(--tdx-ease-out), border-color var(--tdx-dur) var(--tdx-ease-out);
}
.mark__ink { display: block; width: 12px; }
/* Off is dim. The tile tints up only when the layer is actually drawing, so the
 * table's left edge is a glanceable read of what is on. */
.row:has(.sw:not(:checked)) .mark { opacity: 0.4; }

.mark--walls { background: rgba(var(--tdx-green-rgb), 0.13); border-color: rgba(var(--tdx-green-rgb), 0.3); }
.mark--walls .mark__ink { border-top: 2px solid var(--tdx-green); }

.mark--prints { background: rgba(var(--tdx-green-rgb), 0.13); border-color: rgba(var(--tdx-green-rgb), 0.3); }
.mark--prints .mark__ink { width: 7px; height: 7px; border-radius: 50%; background: var(--tdx-green-text); }

.mark--panel { background: rgba(var(--tdx-slate-rgb), 0.13); border-color: rgba(var(--tdx-slate-rgb), 0.3); }
.mark--panel .mark__ink { height: 9px; border-radius: 2px; background: rgba(211, 216, 222, 0.45); }

.mark--cone { background: rgba(var(--tdx-accent-rgb), 0.13); border-color: rgba(var(--tdx-accent-rgb), 0.3); }
.mark--cone .mark__ink { height: 7px; border-radius: 1px; border-top: 1px dashed var(--tdx-accent); background: rgba(var(--tdx-accent-rgb), 0.2); }

.mark--oi { background: rgba(168, 85, 247, 0.13); border-color: rgba(168, 85, 247, 0.3); }
.mark--oi .mark__ink { border-top: 2px dotted var(--tdx-purple); }

.mark--ghosts .mark__ink { border-top: 2px dashed var(--tdx-slate); }

/* The real input stays in the DOM for a11y and for label/for; it is visually
 * replaced by .sw__track. Not display:none, which removes it from the a11y tree
 * and from keyboard focus order. */
.sw {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
  margin: 0;
}
.sw__track {
  position: relative;
  flex: none;
  width: 38px; height: 22px;
  margin-top: 1px;
  border-radius: var(--tdx-radius-pill);
  background: rgba(var(--tdx-slate-rgb),  0.22);
  border: 1px solid rgba(var(--tdx-slate-rgb),  0.25);
  transition:
    background var(--tdx-dur) var(--tdx-ease-out),
    border-color var(--tdx-dur) var(--tdx-ease-out);
}
.sw__thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--tdx-white);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  transition: transform var(--tdx-dur) var(--tdx-ease-out);
}
/* The hero's switch is bigger, because it is the only one on that side of the
 * header and it governs the other eight. */
.sw__track--lg { width: 44px; height: 24px; margin-top: 0; }
.sw__track--lg .sw__thumb { top: 3px; left: 3px; }
.sw:checked ~ .sw__track--lg .sw__thumb { transform: translateX(20px); }

/* checked */
.sw:checked ~ .sw__track { background: var(--tdx-accent); border-color: var(--tdx-accent); }
.sw:checked ~ .sw__track .sw__thumb { transform: translateX(16px); }

/* focus-visible. Shows instantly: an animated focus ring is a focus ring that
 * arrives after the user has already moved on. */
.sw:focus-visible ~ .sw__track {
  outline: 2px solid var(--tdx-accent);
  outline-offset: 3px;
}
/* active */
.sw:active ~ .sw__track .sw__thumb { width: 19px; }
/* disabled */
.sw:disabled ~ .sw__track { opacity: 0.45; }
.row:has(.sw:disabled) { cursor: not-allowed; }
.row:has(.sw:disabled):hover { background: transparent; }

/* ============================================================ segmented
 * The chip tray, mirroring a real <select> that stays authoritative. See
 * ../ui/segmented.mjs for why the select is kept rather than replaced. */
.seg {
  flex: none;
  display: flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--tdx-line-soft);
  border-radius: var(--tdx-radius-sm);
  background: var(--tdx-navy);
}
.seg__chip {
  min-width: 30px;
  padding: 5px var(--tdx-space-8);
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--tdx-slate);
  font: 600 var(--tdx-text-sm) var(--tdx-mono);
  text-align: center;
  cursor: pointer;
  transition:
    background var(--tdx-dur-fast) var(--tdx-ease-out),
    color var(--tdx-dur-fast) var(--tdx-ease-out);
}
.seg__chip:hover { color: var(--tdx-white-dim); background: rgba(var(--tdx-slate-rgb), 0.08); }
.seg__chip:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 1px; }
.seg__chip[aria-pressed="true"] { background: var(--tdx-line); color: var(--tdx-white); }

/* The select is still focusable and still in the a11y tree; it is only taken out
 * of the visual flow while its tray is standing in for it. Not display:none and
 * not visibility:hidden, both of which drop it from the tab order. */
.seg__native {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* The one select that keeps its native form: 35 expiries are not chips. */
.seg__native:focus-visible ~ .seg .seg__chip[aria-pressed="true"] {
  outline: 2px solid var(--tdx-accent);
  outline-offset: 1px;
}

/* ============================================================ fields */
.grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--tdx-space-16);
  padding: var(--tdx-space-16) var(--tdx-space-20);
  border-top: 1px solid var(--tdx-raise);
}
.field { display: grid; gap: var(--tdx-space-6); min-width: 0; }
.field--narrow { max-width: 180px; }
.field__label { font-size: var(--tdx-text-sm); font-weight: 600; color: var(--tdx-white-dim); }
.field__hint { color: var(--tdx-slate-dim); font-size: var(--tdx-text-xs); }

.field input {
  width: 100%;
  padding: 9px var(--tdx-space-12);
  border: var(--tdx-rule);
  border-radius: var(--tdx-radius-sm);
  background: var(--tdx-navy);
  color: var(--tdx-white);
  font: var(--tdx-text-base) var(--tdx-mono);
  letter-spacing: 0.04em;
  transition:
    border-color var(--tdx-dur-fast) var(--tdx-ease-out),
    box-shadow var(--tdx-dur-fast) var(--tdx-ease-out);
}
.field input::placeholder { color: rgba(var(--tdx-slate-rgb),  0.55); }
.field input:hover { border-color: rgba(var(--tdx-slate-rgb),  0.45); }
.field input:focus-visible {
  outline: none;
  border-color: var(--tdx-accent);
  box-shadow: 0 0 0 3px rgba(var(--tdx-accent-rgb), 0.14);
}
.field input:disabled { opacity: 0.5; cursor: not-allowed; }

/* ============================================================ callout
 * A tinted block that states one live fact. It is not a row: it has no control,
 * and styling it as one would promise something to click. */
.callout {
  display: grid;
  gap: var(--tdx-space-4);
  margin: 0 var(--tdx-space-20) var(--tdx-space-16);
  padding: var(--tdx-space-12);
  border: 1px solid rgba(var(--tdx-accent-rgb), 0.22);
  border-radius: 11px;
  background: rgba(var(--tdx-accent-rgb), 0.06);
}
.callout__k {
  font: var(--tdx-text-xs) var(--tdx-mono);
  letter-spacing: 0.14em;
  color: var(--vx-glow);
}
.callout__v { font: var(--tdx-text-base) var(--tdx-mono); letter-spacing: 0.05em; color: var(--tdx-white); }
.callout__d { color: var(--tdx-slate); font-size: var(--tdx-text-xs); line-height: 1.5; }

/* The session block. A pulse and a colour, because "rides your session, never an
 * API key" is the product's central promise and a paragraph states it weakly. */
.rides {
  display: flex;
  align-items: center;
  gap: var(--tdx-space-12);
  margin: 0 var(--tdx-space-20) var(--tdx-space-16);
  padding: var(--tdx-space-12);
  border: 1px solid rgba(var(--tdx-green-rgb), 0.22);
  border-radius: 11px;
  background:
    radial-gradient(340px 140px at 0% 0%, rgba(var(--tdx-green-rgb), 0.09), transparent 70%),
    var(--tdx-panel-lo);
}
.rides__badge {
  flex: none;
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(var(--tdx-green-rgb), 0.3);
  border-radius: 10px;
  background: rgba(var(--tdx-green-rgb), 0.1);
}
.rides__pulse {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--tdx-green-text);
  box-shadow: 0 0 0 4px rgba(var(--tdx-green-rgb), 0.16);
  animation: tdx-pulse 2.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .rides__pulse { animation: none; } }
.rides__body { flex: 1; display: grid; gap: 3px; min-width: 0; }
.rides__k { font-size: var(--tdx-text-base); font-weight: 600; }
.rides__d { color: var(--tdx-slate); font-size: var(--tdx-text-sm); line-height: 1.5; }
/* Signed out is amber, matching the connection chip. Not red: the walls draw
 * signed out, so this is "there is more available", not "this is broken". */
.rides[data-state="out"] { border-color: rgba(var(--tdx-amber-rgb), 0.28); background: var(--tdx-panel-lo); }
.rides[data-state="out"] .rides__badge { border-color: rgba(var(--tdx-amber-rgb), 0.3); background: rgba(var(--tdx-amber-rgb), 0.1); }
.rides[data-state="out"] .rides__pulse { background: var(--tdx-amber); box-shadow: 0 0 0 4px rgba(var(--tdx-amber-rgb), 0.16); }

/* ============================================================ buttons */
.btn {
  appearance: none;
  border: 1px solid var(--tdx-line-hi);
  border-radius: var(--tdx-radius-sm);
  background: transparent;
  color: var(--tdx-white-dim);
  font: 600 var(--tdx-text-base) var(--tdx-font);
  padding: 8px var(--tdx-space-16);
  cursor: pointer;
  transition:
    background var(--tdx-dur-fast) var(--tdx-ease-out),
    border-color var(--tdx-dur-fast) var(--tdx-ease-out),
    color var(--tdx-dur-fast) var(--tdx-ease-out),
    box-shadow var(--tdx-dur-fast) var(--tdx-ease-out),
    transform var(--tdx-dur-fast) var(--tdx-ease-out);
}
.btn:hover { border-color: var(--tdx-line-hi); color: var(--tdx-white); background: rgba(var(--tdx-slate-rgb), 0.06); }
.btn:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 2px; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn[data-state="loading"] { opacity: 0.7; cursor: progress; }

.btn--primary {
  background: var(--vx-deep);
  border-color: transparent;
  color: var(--tdx-white);
  font-weight: 650;
}
.btn--primary:hover {
  background: var(--tdx-accent-deep);
  border-color: transparent;
  color: var(--tdx-white);
  box-shadow: 0 6px 18px rgba(var(--tdx-accent-rgb), 0.28);
}
.btn--ghost { background: transparent; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--tdx-space-8); }

/* Select, styled to match the inputs rather than left as the platform control,
 * which renders white-on-white on a dark page in some Chrome builds. Applies to
 * the expiry picker, the one select that stays native. */
.sel {
  flex: none;
  max-width: 220px;
  padding: 7px var(--tdx-space-8);
  border: var(--tdx-rule);
  border-radius: var(--tdx-radius-sm);
  background: var(--tdx-navy);
  color: var(--tdx-white);
  font: var(--tdx-text-sm) var(--tdx-mono);
  cursor: pointer;
}
.sel:hover { border-color: rgba(var(--tdx-slate-rgb),  0.45); }
.sel:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 1px; }

/* ============================================================ links */
.links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--tdx-space-12);
  padding: 0 var(--tdx-space-20) var(--tdx-space-20);
}
.linkcard {
  position: relative;
  display: grid;
  gap: var(--tdx-space-6);
  padding: var(--tdx-space-16);
  border: 1px solid var(--tdx-raise);
  border-radius: 12px;
  background: rgba(var(--tdx-navy-rgb), 0.55);
  color: inherit;
  text-decoration: none;
  transition:
    border-color var(--tdx-dur) var(--tdx-ease-out),
    background var(--tdx-dur) var(--tdx-ease-out);
}
.linkcard:hover { border-color: rgba(var(--tdx-accent-rgb), 0.45); background: var(--tdx-raise); }
.linkcard:focus-visible { outline: 2px solid var(--tdx-accent); outline-offset: 2px; }
.linkcard--discord:hover { border-color: rgba(168, 85, 247, 0.5); }
.linkcard__k { font-weight: 600; font-size: var(--tdx-text-base); padding-right: var(--tdx-space-20); }
.linkcard__d { color: var(--tdx-slate); font-size: var(--tdx-text-sm); line-height: 1.55; }
.linkcard__go {
  position: absolute;
  top: var(--tdx-space-16); right: var(--tdx-space-16);
  color: var(--vx-glow);
  transition: transform var(--tdx-dur) var(--tdx-ease-out);
}
.linkcard:hover .linkcard__go { transform: translateX(3px); }
.linkcard[aria-disabled="true"] { opacity: 0.55; pointer-events: none; }

/* ============================================================ status + fine */
.fine {
  margin: var(--tdx-space-12) 0 0;
  color: var(--tdx-slate-dim);
  font-size: var(--tdx-text-sm);
  line-height: 1.6;
  max-width: 74ch;
}
.fine:first-child { margin-top: 0; }
.status {
  margin: var(--tdx-space-8) 0 0;
  font-size: var(--tdx-text-sm);
  min-height: 1.2em;
  color: var(--tdx-slate);
}
.status[data-state="ok"] { color: var(--tdx-green-text); }
.status[data-state="err"] { color: var(--tdx-red-text); }

/* The footer confirmation. It takes the byline's slot rather than sitting beside
 * it: the byline is decoration and the confirmation is the answer to what you just
 * pressed, so on a narrow footer the decoration is what gives way. */
.status--foot { flex: 1; min-width: 0; margin: 0; }
.foot__inner:has(.status--foot:not(:empty)) .foot__by { display: none; }
/* Motion is the point. A message that swaps in silently next to a button you just
 * clicked reads as text that was always there. */
.status--foot:not(:empty) { animation: tdx-status-in 220ms ease-out; }
@keyframes tdx-status-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .status--foot:not(:empty) { animation: none; }
}

/* ============================================================ footer */
.foot {
  position: sticky;
  bottom: 0;
  border-top: var(--tdx-rule);
  background: rgba(var(--tdx-navy-rgb),  0.92);
  backdrop-filter: blur(12px);
}
.foot__inner {
  max-width: 1000px;
  margin: 0 auto;
  padding: var(--tdx-space-12) var(--tdx-space-24);
  display: flex;
  align-items: center;
  gap: var(--tdx-space-12);
}
.foot__mark { display: block; flex: none; width: 22px; height: 22px; border-radius: 5px; }
.foot__by { color: var(--tdx-slate); font-size: var(--tdx-text-sm); flex: 1; min-width: 0; }
.foot .btn { flex: none; }

/* ============================================================ narrow
 * The options page opens in a real tab, but Chrome also renders it inside a
 * ~600px embedded pane from chrome://extensions. Both are in scope. */
@media (max-width: 900px) {
  /* The rail becomes a horizontal scroller. It stops being sticky first: a
   * pinned two-line strip across the top of a 700px viewport costs more than it
   * saves. */
  .shell { grid-template-columns: minmax(0, 1fr); }
  .nav {
    position: static;
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    gap: var(--tdx-space-4);
    overflow-x: auto;
    padding-bottom: var(--tdx-space-4);
  }
  .nav__eyebrow { display: none; }
  .nav__item { padding-left: var(--tdx-space-12); }
  .nav__item::before { top: auto; bottom: 0; left: var(--tdx-space-8); right: var(--tdx-space-8); width: auto; height: 2px; border-radius: 2px 2px 0 0; }
  .hero__inner { flex-direction: column; align-items: flex-start; }
  .hero__master { justify-items: start; }
  .master__label, .master__fine { text-align: left; }
}
@media (max-width: 620px) {
  .grid, .links { grid-template-columns: minmax(0, 1fr); }
  .field--narrow { max-width: none; }
  .foot__inner { flex-wrap: wrap; }
  .foot__by { flex-basis: 100%; order: 3; }
  /* The tray wraps under the label rather than squeezing the note to two words. */
  .row--seg { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .row--seg .seg { justify-self: start; flex-wrap: wrap; }
}
@media (max-width: 420px) {
  .hero__inner, .shell, .foot__inner { padding-left: var(--tdx-space-16); padding-right: var(--tdx-space-16); }
  .row { padding-left: var(--tdx-space-16); padding-right: var(--tdx-space-16); }
  .card__head, .grid { padding-left: var(--tdx-space-16); padding-right: var(--tdx-space-16); }
  .callout, .rides { margin-left: var(--tdx-space-16); margin-right: var(--tdx-space-16); }
  .brand__logo { width: 240px; }
}
