/* Thruact dashboard
   Design language: near-white canvas, hairline borders, monochrome first with
   semantic colour used only where it carries meaning. Density stays low so the
   numbers that matter are the loudest thing on the page. */

:root {
  --bg:            #fbfbfa;
  --surface:       #ffffff;
  --surface-sunk:  #f6f6f5;
  --border:        #ebebe9;
  --border-strong: #dedddb;
  --selected:      #edecea;

  --text:          #1a1a1a;
  --text-2:        #6b6b6b;
  --text-3:        #9b9b9b;

  --accent:        #317cff;
  --accent-soft:   rgba(49, 124, 255, .10);
  --green:         #16a34a;
  --red:           #dc2626;
  --amber:         #ea8c00;
  --purple:        #7c5cff;

  --radius:   12px;
  --radius-sm: 8px;

  /* Two measurements, deliberately separate:
       --rail  is how wide the panel is drawn right now (rail + its buttons).
       the shell's margin is how much space the panel *reserves*.
     They agree when pinned and diverge while peeking — which is precisely how
     an overlay differs from a push. */
  --rail-collapsed: 64px;
  --rail-open:      228px;
  --rail:           var(--rail-collapsed);

  /* Decelerating curve — the panel arrives rather than stopping dead. */
  --ease:  cubic-bezier(.32, .72, 0, 1);
  --speed: 260ms;

  --shadow-card: 0 1px 2px rgba(16, 16, 16, .04);
  color-scheme: light;
  --shadow-pop:  0 8px 28px rgba(16, 16, 16, .10);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter",
               "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

button, input, select { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

.ico { width: 19px; height: 19px; fill: none; stroke: currentColor;
       stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* `hidden` must beat the rail's display:flex. */
[hidden] { display: none !important; }

kbd {
  font: inherit; font-size: 11.5px;
  padding: 1px 5px; margin-left: 4px; border-radius: 4px;
  background: rgba(255, 255, 255, .16); color: inherit;
}

/* ---------------------------------------------------------------- icon rail */

/* Two independent states, and the difference matters:
     peek   — hovering. The panel floats *over* the page, so crossing the rail
              with the mouse never reflows what you were reading.
     pinned — a deliberate click. The panel reserves space and pushes content.
   Only pinning changes the layout; peeking is purely an overlay. */
.rail {
  position: fixed; inset: 0 auto 0 0;
  width: var(--rail);
  display: flex; flex-direction: column;
  gap: 3px; padding: 14px 0 14px;
  background: var(--bg);
  border-right: 1px solid var(--border);
  z-index: 40;
  overflow: visible; /* so collapsed tooltips can escape the rail */
  transition: width var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
/* Widening the variable carries the nav buttons with it, so labels are never
   clipped by a button still sized for the collapsed rail. */
body.rail-wide { --rail: var(--rail-open); }

/* Only the floating state casts a shadow — that is what says "above", and it is
   the cue that the page underneath has not moved. */
body.rail-wide:not(.rail-pinned) .rail {
  box-shadow: 4px 0 24px rgba(16, 16, 16, .07);
}

/* Header: the logo mark never moves between states — only the wordmark and the
   pin appear — so opening reads as revealing, not relayout. */
.rail-head {
  display: flex; align-items: center;
  height: 38px; margin-bottom: 12px; padding: 0 10px 0 15px;
  white-space: nowrap;
}
.rail-logo {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; margin-left: -7px;
  border-radius: 9px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border);
}
.rail-word {
  flex: 1; margin-left: 11px; overflow: hidden;
  font-size: 15.5px; font-weight: 600; letter-spacing: -.012em;
  opacity: 0; transform: translateX(-6px);
  transition: opacity .15s ease, transform var(--speed) var(--ease);
}
body.rail-wide .rail-word { opacity: 1; transform: none; }

/* The pin sits beside the logo and only exists once there is room for it. It is
   inert while collapsed so it can never be tabbed to or clicked invisibly. */
.rail-pin {
  position: relative; flex: none;
  display: grid; place-items: center;
  width: 30px; height: 30px; margin-right: -4px;
  border: 0; border-radius: 8px;
  background: transparent; color: var(--text-3);
  cursor: pointer;
  opacity: 0; pointer-events: none;
  transition: opacity .15s ease, background .13s ease, color .13s ease;
}
body.rail-wide .rail-pin { opacity: 1; pointer-events: auto; }
.rail-pin:hover { background: var(--surface-sunk); color: var(--text); }
.rail-pin:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; opacity: 1; }
/* Filled left column = pinned. Same icon, one bit of state. */
.rail-pin .pin-fill { fill: currentColor; opacity: 0; transition: opacity .15s ease; }
body.rail-pinned .rail-pin { color: var(--text); }
body.rail-pinned .rail-pin .pin-fill { opacity: .16; }

.rail-nav { display: flex; flex-direction: column; gap: 3px; }
.rail-foot { margin-top: auto; display: flex; flex-direction: column; gap: 3px; }

/* ---- workspace switcher ---- */
/* Only shown once the rail is wide — collapsed to icons there is no room for a
   name, same reasoning as the nav labels. Position:relative anchors the menu. */
.rail-org-wrap { position: relative; display: none; margin: 0 8px 8px; }
body.rail-wide .rail-org-wrap { display: block; }

.rail-org {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); color: var(--text); cursor: pointer; text-align: left;
  transition: border-color .13s ease, background .13s ease;
}
.rail-org:hover { border-color: var(--border-strong); background: var(--surface-sunk); }
.rail-org-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.rail-org-name { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-org-role { font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--amber); }
.rail-org-caret { flex: none; display: inline-flex; color: var(--text-3); transform: rotate(90deg); }
.rail-org-caret .ico { width: 15px; height: 15px; }
body.org-menu-open .rail-org-caret { transform: rotate(-90deg); }

.rail-org-menu {
  display: none; position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 60;
  padding: 6px; border: 1px solid var(--border); border-radius: 11px;
  background: var(--surface); box-shadow: var(--shadow-pop);
}
.rail-org-menu.is-open { display: block; }
.rail-org-menu-label { padding: 6px 8px 4px; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); }
.rail-org-list { display: flex; flex-direction: column; gap: 1px; max-height: 240px; overflow-y: auto; }

.rail-org-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 9px; border: 0; border-radius: 7px;
  background: transparent; color: var(--text); cursor: pointer; text-align: left;
  transition: background .12s ease;
}
.rail-org-item:hover { background: var(--surface-sunk); }
.rail-org-item.is-active { background: var(--selected); }
.rail-org-item-name { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-org-item-role { flex: none; font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); }
.rail-org-item-tick { flex: none; display: inline-flex; color: var(--green); }
.rail-org-item-tick .ico { width: 15px; height: 15px; }

.rail-org-sep { height: 1px; margin: 6px 4px; background: var(--border); }

.rail-org-add {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 9px; border: 0; border-radius: 7px;
  background: transparent; color: var(--text-2); cursor: pointer; text-align: left;
  font-size: 13.5px; font-weight: 500;
  transition: background .12s ease, color .12s ease;
}
.rail-org-add:hover { background: var(--surface-sunk); color: var(--text); }
.rail-org-add-ico { display: inline-flex; color: var(--text-3); }
.rail-org-add-ico .ico { width: 15px; height: 15px; }
.rail-org-expand { padding: 4px 6px 6px; }
.rail-org-inputrow { display: flex; align-items: center; gap: 6px; }
.rail-org-input { flex: 1; min-width: 0; padding: 8px 10px; font-size: 13.5px; }
.rail-org-go {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px;
  border: 1px solid var(--border-strong); border-radius: 8px;
  background: var(--text); color: var(--bg); cursor: pointer;
  transition: opacity .13s ease;
}
.rail-org-go:hover { opacity: .86; }
.rail-org-go:disabled { opacity: .45; cursor: default; }
.rail-org-go .ico { width: 16px; height: 16px; }
.rail-org-err { margin: 6px 2px 0; font-size: 12px; color: var(--red); }

/* ---- product switcher ---- */
/* Sits in the rail, directly above the workspace switcher, and follows the same
   rule: only shown once the rail is wide, because collapsed to icons there is no
   room for a product name. */
.prod-wrap { position: relative; }

.prod-rail { display: none; margin: 0 8px 6px; }
body.rail-wide .prod-rail { display: block; }
.prod-rail .prod-trigger { width: 100%; }
/* Wider than the rail on purpose: the rail is 228px and a name plus its blurb
   does not fit in it, so the menu overhangs into the page rather than truncating
   every product to an ellipsis. */
.prod-rail .prod-menu { left: 0; width: 330px; }

.prod-trigger {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 9px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--surface); color: var(--text); cursor: pointer; text-align: left;
  font-size: 13px; font-weight: 600; font-family: inherit;
  transition: border-color .13s ease, background .13s ease;
}
.prod-trigger:hover { border-color: var(--border-strong); background: var(--surface-sunk); }
.prod-trigger-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prod-trigger-caret { flex: none; display: inline-flex; color: var(--text-3); transform: rotate(90deg); transition: transform .13s ease; }
.prod-trigger-caret .ico { width: 14px; height: 14px; }
.prod-wrap.is-open .prod-trigger-caret { transform: rotate(-90deg); }

.prod-menu {
  display: none; position: absolute; top: calc(100% + 6px); z-index: 60;
  max-width: calc(100vw - 32px);
  padding: 6px; border: 1px solid var(--border); border-radius: 11px;
  background: var(--surface); box-shadow: var(--shadow-pop);
}
.prod-wrap.is-open .prod-menu { display: block; }
.prod-menu-label { padding: 6px 8px 4px; font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-3); }

.prod-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 9px; border: 0; border-radius: 7px;
  background: transparent; color: var(--text); text-align: left;
  font-family: inherit; font-size: 13.5px;
  transition: background .12s ease;
}
button.prod-item { cursor: pointer; }
button.prod-item:hover { background: var(--surface-sunk); }
.prod-item.is-active { background: var(--selected); }
/* Not built yet: legible, but visibly not a destination. */
.prod-item.is-soon { cursor: default; }
.prod-item.is-soon .prod-item-name, .prod-item.is-soon .prod-item-blurb { color: var(--text-3); }

.prod-item-num { flex: none; align-self: flex-start; padding-top: 2px; font-size: 11px; font-weight: 600; letter-spacing: .04em; color: var(--text-3); font-variant-numeric: tabular-nums; }
/* Name over blurb rather than beside it. "artificial routing intelligence" does
   not fit on one line next to a COMING SOON badge at any width the rail can
   overhang, and an ellipsis on the only sentence describing a product is worse
   than a second line. */
.prod-item-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.prod-item-name { font-weight: 600; }
.prod-item-blurb { color: var(--text-2); font-size: 12px; line-height: 1.35; }
.prod-item .tag { flex: none; align-self: flex-start; font-size: 10.5px; padding: 2px 7px; letter-spacing: .03em; text-transform: uppercase; }

.rail-btn {
  position: relative;
  display: flex; align-items: center; gap: 12px;
  width: calc(var(--rail) - 16px); height: 38px;
  margin: 0 8px; padding: 0 0 0 14px;
  border: 0; border-radius: 9px;
  background: transparent; color: var(--text-3);
  cursor: pointer; text-align: left; overflow: hidden; white-space: nowrap;
  transition: background .13s ease, color .13s ease, width var(--speed) var(--ease);
}
.rail-btn .ico { flex: none; }
.rail-btn:hover { background: var(--surface-sunk); color: var(--text); }
.rail-btn.is-active { background: var(--selected); color: var(--text); }
.rail-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.rail-label {
  font-size: 14.5px; font-weight: 500;
  opacity: 0; transform: translateX(-6px);
  transition: opacity .15s ease, transform var(--speed) var(--ease);
}
body.rail-wide .rail-label { opacity: 1; transform: none; }

/* Collapsed-only tooltip, replacing the browser's native title box. */
.rail-tip {
  position: absolute; left: calc(100% + 10px); top: 50%;
  transform: translateY(-50%) translateX(-4px);
  padding: 6px 10px; border-radius: 7px;
  background: var(--text); color: #fff;
  font-size: 13px; font-weight: 500; line-height: 1;
  box-shadow: var(--shadow-pop);
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity .12s ease, transform .12s ease;
}
.rail-btn:hover .rail-tip, .rail-btn:focus-visible .rail-tip,
.rail-pin:hover .rail-tip, .rail-pin:focus-visible .rail-tip {
  opacity: 1; transform: translateY(-50%);
}
.rail-btn { overflow: visible; }
.rail-btn > .rail-label { overflow: hidden; }

/* Nav tooltips are only useful while collapsed — once wide, the label is on
   screen and a tooltip would just be noise. */
body:not(.rail-wide) .rail-btn:hover .rail-tip,
body:not(.rail-wide) .rail-btn:focus-visible .rail-tip { visibility: visible; }

/* The pin only exists while wide, so its tooltip always applies. It opens to the
   left because the button sits at the panel's right edge. */
.rail-pin .rail-tip { visibility: hidden; }
.rail-pin:hover .rail-tip, .rail-pin:focus-visible .rail-tip { visibility: visible; }
.rail-tip-left {
  left: auto; right: calc(100% + 10px);
  transform: translateY(-50%) translateX(4px);
}

@media (prefers-reduced-motion: reduce) {
  .rail, .shell, .rail-btn, .rail-label, .rail-word, .rail-pin, .rail-tip {
    transition-duration: 1ms !important;
  }
}

/* No hover means no peek, so the pin has to be reachable at rest. Give the header
   a second row for it rather than leaving the panel with no way to open. */
@media (hover: none) {
  .rail-head { flex-wrap: wrap; height: auto; row-gap: 6px; }
  .rail-pin { opacity: 1; pointer-events: auto; margin-left: auto; }
}

/* ------------------------------------------------------------------- layout */

/* Shares the rail's variable and timing, so the content is pushed by the panel
   rather than chasing it. */
/* Only a pin moves the page. Reads the fixed collapsed width, never --rail, so
   a peek cannot reflow what you are looking at. */
.shell {
  margin-left: var(--rail-collapsed); padding: 44px 56px 96px;
  transition: margin-left var(--speed) var(--ease);
}
body.rail-pinned .shell { margin-left: var(--rail-open); }
body.no-rail .shell { margin-left: 0; }
.page  { max-width: 1240px; margin: 0 auto; }

.loading { padding: 80px 56px; color: var(--text-3); }

.page-head {
  display: flex; align-items: flex-start;
  justify-content: space-between; gap: 24px; margin-bottom: 38px;
}
h1 {
  margin: 0; font-size: 30px; font-weight: 600;
  letter-spacing: -.022em; line-height: 1.2;
}
.page-sub { margin: 7px 0 0; color: var(--text-2); font-size: 15px; }

h2 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.012em; }

/* -------------------------------------------------------------------- stats */

.stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px; margin-bottom: 44px;
}
.stat-label {
  display: flex; align-items: center; gap: 7px;
  font-size: 14px; color: var(--text-2); margin-bottom: 9px;
}
.stat-label .ico { width: 16px; height: 16px; }
.stat-value {
  display: flex; align-items: baseline; gap: 9px;
  font-size: 27px; font-weight: 600; letter-spacing: -.02em;
}
.stat-pct { font-size: 14px; font-weight: 400; color: var(--text-3); letter-spacing: 0; }

.t-green  { color: var(--green); }
.t-red    { color: var(--red); }
.t-amber  { color: var(--amber); }
.t-purple { color: var(--purple); }
.t-blue   { color: var(--accent); }
.t-muted  { color: var(--text-3); }

/* -------------------------------------------------------------------- chart */

.chart-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 18px;
}
.chart-title { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 600; }
.chart-total { color: var(--accent); font-weight: 600; }
.chart-wrap { position: relative; }
.chart { display: block; width: 100%; height: 250px; overflow: visible; }
.chart-x {
  display: flex; justify-content: space-between;
  margin: 12px 0 0 46px; font-size: 13px; color: var(--text-3);
}

.chart-tip {
  position: absolute; pointer-events: none; opacity: 0;
  transform: translate(-50%, -100%);
  background: var(--text); color: #fff;
  padding: 7px 11px; border-radius: 8px; font-size: 13px;
  white-space: nowrap; box-shadow: var(--shadow-pop);
  transition: opacity .12s ease;
}
.chart-tip strong { font-weight: 600; }

/* ---------------------------------------------------------- tabs + toolbar */

.toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin: 52px 0 4px;
}
.tabs { display: flex; align-items: center; gap: 6px; }
.tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 15px; border-radius: 999px;
  border: 1px solid transparent; background: transparent;
  color: var(--text-2); font-size: 15px; cursor: pointer;
  transition: background .13s ease, border-color .13s ease, color .13s ease;
}
.tab:hover { color: var(--text); }
.tab.is-active {
  background: var(--surface); border-color: var(--border-strong);
  color: var(--text); font-weight: 500;
}
.tab-count { color: var(--text-3); font-weight: 400; }
.tab.is-active .tab-count { color: var(--text-3); }

.toolbar-actions { display: flex; align-items: center; gap: 10px; }

.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 17px; border-radius: 9px; border: 1px solid transparent;
  background: var(--text); color: #fff;
  font-size: 14.5px; font-weight: 500; cursor: pointer;
  transition: opacity .13s ease;
}
.btn:hover { opacity: .86; }
.btn:disabled { opacity: .45; cursor: default; }
.btn-ghost {
  background: transparent; color: var(--text-2);
  border-color: transparent; padding: 8px;
}
.btn-ghost:hover { background: var(--surface-sunk); color: var(--text); opacity: 1; }
/* A complete button on its own, not a modifier on .btn — adding .btn would drag
   in the dark-mode `.btn { color: var(--bg) }` override and paint the label the
   same near-black as the surface. So it carries its own box: display, padding,
   radius and a visible border (the base .btn declares border-color but no width,
   which is why these rendered as bare text). */
.btn-outline {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 17px; border-radius: 9px;
  border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text);
  font-size: 14.5px; font-weight: 500; line-height: 1.2; cursor: pointer;
  transition: background .13s ease, border-color .13s ease, opacity .13s ease;
}
.btn-outline:hover { background: var(--surface-sunk); border-color: var(--text-3); }
.btn-outline:disabled { opacity: .45; cursor: default; }

/* -------------------------------------------------------------------- table */

.table { width: 100%; border-collapse: collapse; }
.table thead th {
  padding: 14px 12px; font-size: 13.5px; font-weight: 400;
  color: var(--text-3); text-align: right; white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.table thead th:first-child { text-align: left; padding-left: 0; }
.table tbody td {
  padding: 15px 12px; text-align: right;
  border-bottom: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
}
.table tbody td:first-child { text-align: left; padding-left: 0; }
.table tbody tr:hover { background: rgba(0, 0, 0, .015); }
.table .group-label {
  padding: 26px 0 10px; font-size: 14px; color: var(--text-2); font-weight: 500;
}

.row-name { display: flex; align-items: center; gap: 11px; }
.row-title { font-weight: 500; letter-spacing: -.006em; }
.row-sub { font-size: 13.5px; color: var(--text-3); margin-top: 2px; }

.pill-ok, .pill-fail {
  display: inline-grid; place-items: center;
  width: 19px; height: 19px; border-radius: 50%; flex: none;
}
.pill-ok   { color: var(--green); }
.pill-fail { color: var(--red); }

.chips { display: inline-flex; align-items: center; gap: 13px; justify-content: flex-end; }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 14px; font-variant-numeric: tabular-nums;
}
.chip .ico { width: 15px; height: 15px; }

/* --------------------------------------------------------------- catalogue */

.search {
  display: flex; align-items: center; gap: 11px;
  width: 100%; padding: 13px 17px; margin-bottom: 34px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 11px; color: var(--text-3);
  transition: border-color .13s ease, box-shadow .13s ease;
}
.search:focus-within {
  border-color: var(--border-strong);
  box-shadow: 0 0 0 4px rgba(0, 0, 0, .03);
}
.search input {
  flex: 1; border: 0; outline: 0; background: transparent;
  color: var(--text); font-size: 15px;
}
.search input::placeholder { color: var(--text-3); }
/* Advertises the shortcut without competing with the placeholder for attention,
   and steps aside the moment the field is in use. */
.search-kbd {
  flex: none; display: grid; place-items: center;
  min-width: 21px; height: 21px; padding: 0 6px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface-sunk); color: var(--text-3);
  font-size: 12px; line-height: 1;
  transition: opacity .13s ease;
}
.search:focus-within .search-kbd { opacity: 0; }

/* The catalogue is a two-level thing — a capability, and the providers that can
   satisfy it — so it is drawn that way. A card per tool duplicated the
   capability's description once per provider and buried the only fact that
   matters: whether this capability can fail over today.

   `align-items: start` is what stops the results column from being stretched to
   the height of an 18-item facet rail. Both children of a single-row grid
   inherit `stretch` otherwise, and the card row inside then stretches with it. */
.catalog {
  display: grid; grid-template-columns: 236px minmax(0, 1fr);
  align-items: start; gap: 40px;
}

/* Long enough to need its own scroll, so it gets one and stays put while the
   results move. Ends one line short of the viewport so it never looks clipped. */
.facets {
  display: flex; flex-direction: column; gap: 1px;
  position: sticky; top: 24px;
  max-height: calc(100vh - 48px);
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: 4px; margin-right: -4px;
  scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent;
}
.facets::-webkit-scrollbar { width: 6px; }
.facets::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; }
.facets::-webkit-scrollbar-track { background: transparent; }

.facet-group {
  padding: 18px 12px 7px; font-size: 12px; font-weight: 500;
  letter-spacing: .05em; text-transform: uppercase; color: var(--text-3);
}
.facet-group:first-child { padding-top: 4px; }

.facet {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 12px; border: 0; border-radius: 9px;
  background: transparent; color: var(--text-2);
  font-size: 14.5px; cursor: pointer; text-align: left;
  transition: background .13s ease, color .13s ease;
}
.facet:hover { background: var(--surface-sunk); color: var(--text); }
.facet.is-active { background: var(--selected); color: var(--text); font-weight: 500; }
.facet:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.facet-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.facet-count { color: var(--text-3); font-size: 13.5px; font-variant-numeric: tabular-nums; }
/* A zero is worth drawing rather than hiding — it says "this filter exists and
   nothing here matches", which a missing row cannot. */
.facet-count.is-zero { opacity: .45; }

/* -------------------------------------------------- catalogue results header */

.cat-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 18px; min-height: 32px;
}
.cat-count { font-size: 14px; color: var(--text-2); }
.cat-count strong { color: var(--text); font-weight: 600; }

/* The dense list can be wider than its column at intermediate widths, so it
   scrolls inside its own box at every size. Without this the page itself scrolls
   sideways between the mobile breakpoint and full desktop. */
.cat-table-wrap { overflow-x: auto; }

/* Shelf sections — the two-level taxonomy made visible. Cards sit under a group
   heading in the same order the facet rail lists the shelves, so scrolling the
   page and scanning the rail describe one structure rather than two. */
.shelved { display: flex; flex-direction: column; gap: 30px; }
.shelf-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 13px; padding-bottom: 9px; border-bottom: 1px solid var(--border);
}
.shelf-mark {
  flex: none; display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 7px; background: var(--surface-sunk); border: 1px solid var(--border);
  color: var(--text-2);
}
.shelf-mark .ico { width: 15px; height: 15px; }
.shelf-title {
  font-size: 15px; font-weight: 600; color: var(--text);
  text-transform: capitalize; margin: 0;
}
.shelf-count { font-size: 13px; color: var(--text-3); }

/* A category button under its shelf header: indented, quieter, so the hierarchy
   reads at a glance without a disclosure triangle to click. */
/* A shelf's chevron: right when closed, down when open. The whole shelf row is
   the toggle, so the caret only signals state rather than being its own control. */
.facet-caret {
  flex: none; width: 15px; height: 15px; margin: 0 -4px; color: var(--text-3);
  display: inline-flex; transition: transform .14s ease;
}
.facet-caret .ico { width: 15px; height: 15px; }
.facet-shelf.is-open .facet-caret { transform: rotate(90deg); }
.facet-shelf .facet-name { text-transform: capitalize; }
/* A single-category shelf has no caret, so it borrows the caret's width to keep
   every shelf name on one left edge. */
.facet-flat { padding-left: 23px; }

/* Categories indent past the shelf name, so the tree reads as a tree. Capitalized
   to match the shelf headers above them. */
.facet-sub {
  padding-left: 38px; font-size: 13.5px; color: var(--text-2);
}
.facet-sub .facet-name { text-transform: capitalize; }

/* An app's mark carries the vendor initials the way a provider row does, one
   size up because here it is the card's identity rather than a list bullet. */
.app-mark { width: 26px; height: 26px; font-size: 11.5px; border-radius: 7px; }

/* Segmented control. Same hairline vocabulary as the tabs, but the selection is
   a filled slab rather than an outline so the two never read as the same
   control at a glance. */
.seg {
  display: inline-flex; align-items: center; gap: 2px; flex: none;
  padding: 2px; border-radius: 9px;
  background: var(--surface-sunk); border: 1px solid var(--border);
}
.seg-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px; border: 0; border-radius: 7px;
  background: transparent; color: var(--text-3);
  font-size: 13.5px; font-weight: 500; cursor: pointer;
  transition: background .13s ease, color .13s ease, box-shadow .13s ease;
}
.seg-btn .ico { width: 15px; height: 15px; }
.seg-btn:hover { color: var(--text); }
.seg-btn.is-active {
  background: var(--surface); color: var(--text);
  box-shadow: var(--shadow-card);
}
.seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ------------------------------------------------------------ capability grid */

/* Three separate things, and all three are needed:
     align-content: start  — keeps a single row of cards at its content height
                             instead of spreading it down the whole column.
     grid-auto-rows        — sizes each row track to its content.
     align-items: start    — stops a card stretching to match the tallest card
                             beside it, which is what lets a 4-provider card and
                             a 1-provider card share a row honestly. The ragged
                             bottom edge is the point: it is the provider count
                             made visible before you read a word. */
/* min(300px, 100%) rather than a bare 300px: once the container is narrower than
   the track minimum, a plain minmax() keeps demanding 300px and the page grows a
   horizontal scrollbar instead of the card getting smaller. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  align-content: start; gap: 14px;
}
.card {
  display: flex; flex-direction: column; min-height: 176px;
  padding: 17px 17px 13px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  transition: border-color .14s ease, box-shadow .14s ease;
}
.card:hover {
  border-color: var(--border-strong);
  box-shadow: 0 4px 14px rgba(16, 16, 16, .05);
}
/* Agent setup reuses the card's surface for code samples rather than for a
   capability, so it has no provider list to space itself against and asks for a
   plain stacking gap instead of the capability card's tuned margins. */
.card-stack { gap: 10px; padding-bottom: 17px; }

/* A standalone explanatory banner. Deliberately not a .card: those are grid
   tiles with a 176px min-height, which leaves two lines of prose stranded in the
   middle of a mostly empty box. */
.notice {
  display: flex; flex-direction: column; gap: 4px;
  padding: 13px 15px; margin-bottom: 15px;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--green); border-radius: var(--radius-sm);
}
.notice-title { font-size: 14px; font-weight: 600; }
.notice-body { font-size: 13px; line-height: 1.5; color: var(--text-2); }

.card-head { display: flex; align-items: flex-start; gap: 11px; margin-bottom: 3px; }
.card-stack .card-head { margin-bottom: 0; }
.card-stack .card-foot { margin-top: 0; }
.card-title {
  flex: 1; min-width: 0; font-size: 15.5px; font-weight: 600; letter-spacing: -.008em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-id {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 12.5px; color: var(--text-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-desc {
  color: var(--text-2); font-size: 13.8px; line-height: 1.45; margin: 8px 0 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* The providers are the point of the card, so they are drawn as real rows on a
   sunk panel rather than as a sentence saying how many there are. */
.provs {
  display: flex; flex-direction: column;
  margin: 13px 0 0; padding: 3px; gap: 1px;
  background: var(--surface-sunk); border-radius: var(--radius-sm);
}
.prov {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 8px; border-radius: 6px; min-width: 0;
  transition: background .12s ease;
}
.prov:hover { background: var(--surface); }
.prov-mark {
  display: grid; place-items: center; flex: none;
  width: 22px; height: 22px; border-radius: 6px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: 10.5px; font-weight: 600; color: var(--text-2); letter-spacing: .01em;
}
.prov-name {
  flex: 1; min-width: 0; font-size: 13.5px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.prov-name .prov-sub { color: var(--text-3); }
.prov-price {
  flex: none; font-size: 13px; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
/* A gated provider is dimmed rather than hidden: knowing it exists and needs a
   key is useful, and it is exactly what the failover badge is counting. */
.prov.is-gated .prov-mark,
.prov.is-gated .prov-name,
.prov.is-gated .prov-price { color: var(--text-3); }
.prov-state { display: grid; place-items: center; flex: none; width: 16px; }
.prov-state .ico { width: 14px; height: 14px; }

/* The bottom block pins to the foot of the card via margin-top:auto, so a short
   description and a long one still leave the marks and footer on one baseline —
   which is what makes every card in a shelf the same height. */
.card-bottom { margin-top: auto; padding-top: 13px; }

/* A constant-height row of provider marks — the multi-provider reality at a
   glance, without the variable height a full list would bring. */
.card-marks { display: flex; align-items: center; gap: 6px; margin-bottom: 11px; }
.card-mark {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 7px;
  background: var(--surface-sunk); border: 1px solid var(--border);
  font-size: 10.5px; font-weight: 600; color: var(--text-2); letter-spacing: .01em;
}
.card-mark.is-gated { opacity: .5; }
.card-mark-more { background: transparent; border-style: dashed; color: var(--text-3); }

.card-foot {
  display: flex; align-items: center; gap: 8px;
  margin-top: 0; font-size: 13px; color: var(--text-3);
  white-space: nowrap; overflow: hidden;
}
.card-foot > span:not(.tag):not(.dot) { overflow: hidden; text-overflow: ellipsis; }
.dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: .5; flex: none; }

/* ------------------------------------------------------------ capability list */

/* The dense alternative. Same data, one line per provider, and room for the
   numbers a card has no space for — price, latency, measured success. */
.cat-table .cap-row td {
  padding: 22px 12px 9px; border-bottom: 1px solid var(--border);
  color: var(--text-2);
}
.cat-table .cap-row:first-child td { padding-top: 6px; }
.cat-table .cap-row td:first-child { padding-left: 0; }
.cap-row-name { display: flex; align-items: baseline; gap: 10px; }
.cap-row-name strong { color: var(--text); font-size: 14.5px; font-weight: 600; letter-spacing: -.006em; }
.cap-row-name span { font-size: 12.5px; color: var(--text-3); }
.cat-table .prov-row td { padding: 10px 12px; }
.cat-table .prov-row td:first-child { padding-left: 0; }
.cat-table .prov-row:hover { background: rgba(0, 0, 0, .015); }
.prov-row-name { display: flex; align-items: center; gap: 10px; padding-left: 2px; }
.prov-row.is-gated .prov-row-name .prov-name { color: var(--text-3); }

.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: 999px;
  font-size: 12.5px; font-weight: 500; white-space: nowrap; flex: none;
  background: var(--surface-sunk); border: 1px solid var(--border); color: var(--text-2);
}
/* A shelf is navigation, not status, so it stays monochrome — semantic colour is
   reserved for things that carry meaning about whether a call will work. */
.tag-shelf { font-size: 11.5px; letter-spacing: .02em; text-transform: lowercase; }

.tag-live  { color: var(--green); background: rgba(22, 163, 74, .07); border-color: rgba(22, 163, 74, .16); }
.tag-gated { color: var(--amber); background: rgba(234, 140, 0, .07); border-color: rgba(234, 140, 0, .18); }

/* --------------------------------------------------------------- empty/pane */

.empty {
  padding: 60px 24px; text-align: center; color: var(--text-3);
  border: 1px dashed var(--border-strong); border-radius: var(--radius);
}
.empty strong { display: block; color: var(--text); font-weight: 600; margin-bottom: 6px; }
.empty p { margin: 0 0 6px; font-size: 14.5px; }
.empty p:last-child { margin-bottom: 0; }
/* Matches the chart's footprint so the page does not jump once data arrives. */
.empty-chart {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; height: 286px;
}
.empty-hint { color: var(--text-3); font-size: 13.5px; }
.empty-cmd {
  padding: 2px 6px; border-radius: 5px;
  background: var(--surface-sunk); border: 1px solid var(--border); color: var(--text-2);
}

.meter { width: 92px; height: 5px; border-radius: 999px; background: var(--surface-sunk); overflow: hidden; }
.meter span { display: block; height: 100%; border-radius: 999px; background: var(--green); }

.attempts { display: flex; flex-direction: column; gap: 5px; padding: 4px 0 14px; }
.attempt {
  display: flex; align-items: center; gap: 9px;
  font-size: 13.5px; color: var(--text-2);
}
.attempt code { font-size: 12.5px; color: var(--text-3); }
.mono { font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace; font-size: 13px; }

/* --------------------------------------------------------------- connect */

.connect {
  max-width: 430px; margin: 12vh auto 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 30px; box-shadow: var(--shadow-card);
}
.connect h1 { font-size: 22px; margin-bottom: 8px; }
.connect p { color: var(--text-2); font-size: 14.5px; margin: 0 0 22px; }
.field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 15px; }
.field label { font-size: 13.5px; color: var(--text-2); }
.field input {
  padding: 11px 13px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--surface); outline: 0;
}
.field input:focus { border-color: var(--border-strong); box-shadow: 0 0 0 4px rgba(0,0,0,.03); }
.connect .btn { width: 100%; justify-content: center; margin-top: 6px; }
.connect-note { margin-top: 18px; font-size: 13px; color: var(--text-3); line-height: 1.5; }

@media (max-width: 1080px) {
  .shell { padding: 32px 24px 72px; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 8px; }

  /* Below this the rail cannot stay a column without eating the results, so it
     becomes a horizontal band of chips: same buttons, laid out sideways, and no
     longer sticky because a band that follows you down the page is just a
     shrinking viewport.

     Capped, because 18 capability chips unrolled is about a screen and a half of
     filters before the first result — which puts the answer below the fold on
     the device least able to spare it. The band scrolls instead. */
  /* minmax(0,…) rather than 1fr: a grid track's automatic minimum is the item's
     min-content, and the chip band's is wide enough to push the column past the
     viewport and give the whole page a horizontal scrollbar. */
  .catalog { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .facets {
    position: static; min-width: 0;
    flex-direction: row; flex-wrap: wrap; gap: 6px;
    max-height: 172px; overflow-y: auto;
    margin-right: 0; padding-right: 0;
  }
  .facet { padding: 7px 13px; border: 1px solid var(--border); background: var(--surface); }
  .facet-group {
    width: 100%; padding: 6px 0 0;
  }
  .facet-group:first-child { padding-top: 0; }
}

@media (max-width: 640px) {
  .cards { grid-template-columns: minmax(0, 1fr); }
  .cat-bar { flex-wrap: wrap; gap: 10px; }

  /* One chip per row down here, so the 172px budget is spent before the
     capability list starts. Enough height to prove there is more below. */
  .facets { max-height: 244px; }

  /* Three facts in ~260px truncate to "2 provid… · from fr… · p50 368…", which
     is three pieces of nothing. Let the line wrap instead. */
  .card-foot { flex-wrap: wrap; white-space: normal; }
  .card-foot > span:not(.tag):not(.dot) { overflow: visible; text-overflow: clip; }
  /* The dense view carries five numeric columns; below this it stops fitting, so
     it scrolls inside its own box rather than dragging the page sideways. */
  .cat-table-wrap { overflow-x: auto; }
  .cat-table { min-width: 560px; }
}

/* ------------------------------------------------------------------ billing */

/* Reuses the connect-form input treatment rather than inventing a second one —
   two subtly different text fields in one product is worse than either. */
.input {
  padding: 10px 12px; border-radius: 9px; min-width: 0; width: 100%;
  border: 1px solid var(--border); background: var(--surface); outline: 0;
}
.input:focus { border-color: var(--border-strong); box-shadow: 0 0 0 4px rgba(0,0,0,.03); }

.field-row {
  display: flex; align-items: center; gap: 10px;
  font-size: 14px; color: var(--text-2);
}
/* Fixed label column so the four auto-topup fields line up as a form rather
   than a ragged stack. */
.field-label { flex: 0 0 92px; }
.field-row .input { flex: 1 1 auto; }
.field-row .btn { flex: 0 0 auto; white-space: nowrap; }
.check { width: 16px; height: 16px; accent-color: var(--accent); flex: 0 0 auto; }

/* The two-line clamp exists so catalogue cards stay a uniform height. On a
   billing card the text *is* the content, and a truncated explanation of why a
   daily cap is mandatory is worse than no explanation. */
.card-stack .card-desc {
  display: block; -webkit-line-clamp: none; overflow: visible;
}

/* A full-width ghost button reads as a centred banner rather than a link, so
   it sits at its natural width. The primary action keeps the full width. */
.card-stack .btn-ghost { align-self: flex-start; padding-left: 0; }

/* The shared .chips row is right-aligned and non-wrapping because it lives in a
   table cell. Here it is a row of buttons in a card, so it wraps and starts at
   the left — without the wrap the first preset is clipped on a phone. */
.card-stack .chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  justify-content: flex-start; margin-bottom: 2px;
}
.card-stack .chip {
  cursor: pointer; padding: 5px 11px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface-sunk);
}
.card-stack .chip:hover { border-color: var(--border-strong); }

/* The payments table follows a grid of cards, and without this the section
   heading sits on the shortest card's bottom edge. */
.cards + .chart-head { margin-top: 26px; }

@media (max-width: 520px) {
  /* Below this the label column crowds the field out; stack instead. */
  .field-row { flex-wrap: wrap; }
  .field-label { flex-basis: 100%; }
}

/* ------------------------------------------------------------- sign-in form */

/* A text button that reads as a link. Swapping between sign-in and sign-up is
   not a primary action and must not compete with the one below it. */
.btn-link {
  display: block; width: 100%; margin-top: 12px; padding: 4px;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; color: var(--accent);
}
.btn-link:hover { text-decoration: underline; }

.connect .btn-outline { width: 100%; justify-content: center; margin-top: 4px; }

/* The token route is real but rare, so it is folded away rather than given
   equal weight to the form most people want. */
.connect-note.is-error { color: var(--red); }

.connect-alt { margin-top: 20px; border-top: 1px solid var(--border); padding-top: 14px; }
.connect-alt summary {
  cursor: pointer; font-size: 13.5px; color: var(--text-2); list-style: none;
}
.connect-alt summary::-webkit-details-marker { display: none; }
.connect-alt summary::before { content: "› "; color: var(--text-3); }
.connect-alt[open] summary::before { content: "⌄ "; }
.connect-alt summary:hover { color: var(--text); }
.connect-alt .field { margin-top: 14px; }
.connect-hint { margin: 9px 0 14px; font-size: 12.5px; color: var(--text-3); line-height: 1.55; }
.connect-hint code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px;
  padding: 1px 5px; border-radius: 5px; background: var(--surface-sunk); color: var(--text-2);
}

/* ------------------------------------------------------------ admin pages */

.rail-rule {
  height: 1px; background: var(--border); margin: 8px 10px;
}

/* A page is a stack of panels. Grouping by concern beats one long table,
   because "budgets" and "deny rules" answer different questions. */
.panel {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 20px 22px; margin-bottom: 18px;
}
.panel-head { margin-bottom: 14px; }
.panel h2 { font-size: 16px; margin: 0; }
.panel-note { color: var(--text-3); font-size: 13px; margin: 6px 0 0; line-height: 1.5; }
.panel-note.is-error { color: var(--red); }
/* A table with four columns does not fit a phone, and shrinking the type to
   make it fit makes it unreadable. It scrolls inside the panel instead, so the
   page itself never scrolls sideways. */
.panel .table { margin-top: 0; }

/* A generated input form inside a panel. `.field` was written for the sign-in
   card, which is 380px wide and centred; in a full-width panel its controls
   would stretch to the whole screen and read as a search bar rather than a
   field, so they are bounded and the button is given room of its own. */
.panel .field { max-width: 520px; }
.panel .field input, .panel .field select { width: 100%; }
.panel .field + .toolbar-actions { margin-top: 4px; }

/* Two lines, then an ellipsis. A comparison is read by scanning down a column,
   and one provider that returns a screen of markdown would otherwise make its
   row taller than the whole rest of the table. The full text is on the receipt
   and in the tooltip. */
.cell-clamp {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; max-width: 46ch; word-break: break-word;
}
.table-scroll { overflow-x: auto; }
.table-scroll .table { min-width: 480px; }
/* Inside a panel the scroller runs to the padding edge, so a row that is cut
   off looks cut off rather than looking like it ends there. */
.panel .table-scroll { margin: 0 -22px; padding: 0 22px; }
.panel .field-row { margin-top: 14px; }
/* Two short password fields have no business spanning a 760px panel — capped so
   the form reads as a form, not a pair of runway-length inputs. */
.pw-form { max-width: 460px; }

/* Destructive actions are quiet until you are near them: a red button repeated
   down every row turns the page into a warning nobody reads. */
.btn-danger {
  background: none; border: 1px solid transparent; border-radius: 8px;
  padding: 5px 10px; font: inherit; font-size: 13px;
  color: var(--text-3); cursor: pointer;
}
.btn-danger:hover { color: var(--red); border-color: var(--red); }

.facts { display: grid; grid-template-columns: 140px 1fr; gap: 8px 16px; margin: 0; }
.facts dt { color: var(--text-3); font-size: 13.5px; }
.facts dd { margin: 0; font-size: 13.5px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }

/* A budget is a fraction, and a bar says that faster than two numbers do. */
.meter {
  height: 6px; border-radius: 3px; background: var(--surface-sunk);
  overflow: hidden; min-width: 120px;
}
.meter-fill { height: 100%; background: var(--accent); border-radius: 3px; }
.meter-fill.is-hot { background: var(--red); }

.is-dim { opacity: .5; }

select.input { cursor: pointer; }

/* An invite code appears exactly once, so it is given the weight of something
   you must act on now rather than a line in a table. */
.invite-code {
  background: var(--accent-soft); border: 1px solid var(--accent);
  border-radius: 12px; padding: 16px 18px; margin-bottom: 18px;
}
.invite-code p { color: var(--text-2); font-size: 13.5px; margin: 6px 0 12px; }
.invite-code code {
  display: block; flex: 1 1 auto; padding: 9px 11px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 8px; user-select: all; word-break: break-all;
}

/* -------------------------------------------------------------- dark theme */

/* Only the tokens change. Every rule in this file already reads through them,
   so a second stylesheet would be a second thing to keep in step.

   Three states, not two. An explicit choice stamps data-theme on the root; the
   default stamps nothing and follows the system. The media query is guarded
   against data-theme="light" so choosing light beats a dark system setting. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:            #131313;
    --surface:       #1a1a1a;
    --surface-sunk:  #222222;
    --border:        #2a2a2a;
    --border-strong: #383838;
    --selected:      #2e2e2e;

    --text:          #f2f2f0;
    --text-2:        #a8a8a4;
    --text-3:        #767672;

    /* Lifted, because the light-mode blue reads muddy on a dark ground. */
    --accent:        #5b9bff;
    --accent-soft:   rgba(91, 155, 255, .14);
    --green:         #34d17c;
    --red:           #ff6b5e;
    --amber:         #ffb340;
    --purple:        #9d85ff;

    --shadow-card:   0 1px 2px rgba(0, 0, 0, .35);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg:            #131313;
  --surface:       #1a1a1a;
  --surface-sunk:  #222222;
  --border:        #2a2a2a;
  --border-strong: #383838;
  --selected:      #2e2e2e;

  --text:          #f2f2f0;
  --text-2:        #a8a8a4;
  --text-3:        #767672;

  --accent:        #5b9bff;
  --accent-soft:   rgba(91, 155, 255, .14);
  --green:         #34d17c;
  --red:           #ff6b5e;
  --amber:         #ffb340;
  --purple:        #9d85ff;

  --shadow-card:   0 1px 2px rgba(0, 0, 0, .35);
  color-scheme: dark;
}

/* The primary button is the one place a hard-coded colour survived: it paints
   text white on --text, which is nearly black in light mode and nearly white in
   dark. */
:root[data-theme="dark"] .btn,
:root:not([data-theme="light"]) .btn {
  color: var(--bg);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .btn { color: #fff; }
}

.theme-toggle {
  background: none; border: 0; cursor: pointer; padding: 0;
  color: inherit; font: inherit;
}

/* ------------------------------------------------------------ run drawer */

.drawer-backdrop {
  position: fixed; inset: 0; background: rgba(16, 16, 16, .28);
  z-index: 40; animation: fade var(--speed) var(--ease);
}
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 100%);
  background: var(--bg); border-left: 1px solid var(--border);
  z-index: 41; overflow-y: auto; padding: 24px 26px 40px;
  animation: slide-in var(--speed) var(--ease);
}
@keyframes fade { from { opacity: 0 } }
@keyframes slide-in { from { transform: translateX(16px); opacity: 0 } }

.drawer-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.drawer-head h2 { font-size: 18px; margin: 0; }
/* Three blocks in a 560px panel, not four across a page. Inheriting the
   overview's grid squashed them until the sub-label collided with the next
   column's value. */
.drawer-stats {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px; margin: 22px 0 8px;
}
.drawer-stats .stat-value { font-size: 22px; }
/* The sub-label goes under the number here rather than beside it: there is not
   room for both on one line at this width. */
.drawer-stats .stat-pct { display: block; margin: 4px 0 0; }
.drawer-title { font-size: 13px; text-transform: uppercase; letter-spacing: .06em;
                color: var(--text-3); margin: 26px 0 10px; }

.attempts { display: flex; flex-direction: column; gap: 8px; }
.attempt {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 11px 13px;
}
/* The winning attempt is the one you look for first, so it is the one with
   colour on it. */
.attempt.is-ok  { border-color: var(--green); }
.attempt.is-fail .attempt-n { color: var(--red); }
.attempt-n {
  font-variant-numeric: tabular-nums; color: var(--text-3);
  font-size: 12.5px; min-width: 14px;
}

.code {
  background: var(--surface-sunk); border: 1px solid var(--border);
  border-radius: 10px; padding: 12px 14px; margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px; line-height: 1.55; overflow-x: auto;
  white-space: pre-wrap; word-break: break-word;
}

tr.is-clickable { cursor: pointer; }
tr.is-clickable:hover { background: var(--surface-sunk); }
tr.is-clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* A four-column table does not fit a phone, and shrinking the type until it
   does makes it unreadable. So the table itself becomes the scroll container
   below the breakpoint, while thead and tbody stay real tables — that is what
   keeps the columns lined up with each other while the whole thing slides.

   Done in CSS rather than by wrapping every table in markup: several pages
   build their tables inline, and a wrapper is a change to each of them. */
@media (max-width: 720px) {
  /* The toolbar is a row of tabs and a button, side by side. On a phone the
     pair is wider than the screen and neither half is optional, so it wraps
     rather than pushing the page sideways. */
  .toolbar { flex-wrap: wrap; }
  .toolbar-actions { flex-wrap: wrap; }

  /* Agent setup is mostly config blocks — a JSON snippet and an MCP URL — and
     a long unbroken line in one pushed the page sideways. The block scrolls
     inside itself instead. */
  .card-stack pre, pre.mono { overflow-x: auto; max-width: 100%; }

  .table { display: block; overflow-x: auto; }
  .table thead, .table tbody { display: table; width: 100%; min-width: 460px; }
  .panel .table { margin-inline: -22px; padding-inline: 22px; }
}

/* ---------------------------------------------------------- capability detail */

.back-link { display: inline-flex; align-items: center; gap: 4px; margin-bottom: 18px; }
.back-caret { display: inline-flex; width: 16px; height: 16px; transform: rotate(180deg); }
.back-caret .ico { width: 16px; height: 16px; }

.cap-detail-head { display: flex; align-items: center; gap: 14px; }
.cap-detail-mark {
  flex: none; display: grid; place-items: center; width: 42px; height: 42px;
  border-radius: 11px; background: var(--surface-sunk); border: 1px solid var(--border);
  color: var(--text-2);
}
.cap-detail-mark .ico { width: 20px; height: 20px; }
.cap-detail-title { font-size: 24px; margin: 0; line-height: 1.15; }
.cap-detail-id { font-size: 13px; color: var(--text-3); margin-top: 2px; }
.cap-detail-desc { color: var(--text-2); font-size: 15px; margin: 14px 0 10px; max-width: 70ch; }
.cap-detail-tags { display: flex; gap: 7px; margin-bottom: 26px; }
.cap-detail-actions { margin-top: 16px; }

/* Input / output schema as a three-column grid: field, type, description. */
.schema-block { margin-bottom: 18px; }
.schema-label {
  font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-3); margin-bottom: 9px;
}
.schema-grid {
  display: grid; grid-template-columns: minmax(120px, auto) minmax(60px, auto) 1fr;
  gap: 8px 18px; align-items: baseline;
}
.schema-field { font-size: 13.5px; color: var(--text); }
.schema-type { font-size: 12.5px; }
.schema-desc { font-size: 13.5px; line-height: 1.45; }

/* Call snippets — CLI / MCP / HTTP tabs over one copyable block. */
.snippet { border: 1px solid var(--border); border-radius: 11px; overflow: hidden; margin-top: 18px; }
.snippet-head {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface-sunk); border-bottom: 1px solid var(--border); padding: 0 8px;
}
.snippet-tabs { display: flex; }
.snippet-tab {
  border: 0; background: transparent; color: var(--text-3); cursor: pointer;
  padding: 10px 13px; font-size: 12.5px; font-weight: 500; letter-spacing: .02em;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.snippet-tab:hover { color: var(--text); }
.snippet-tab.is-active { color: var(--text); border-bottom-color: var(--accent); }
.snippet-copy {
  border: 0; background: transparent; color: var(--text-3); cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px; padding: 6px 8px; font-size: 12px;
}
.snippet-copy:hover { color: var(--text); }
.snippet-copy .ico { width: 15px; height: 15px; }
.snippet-body { border: 0; border-radius: 0; margin: 0; background: var(--surface); }

/* Provider lines — one interchangeable implementation per row, with the measured
   numbers Treg's static price list cannot show. */
.prov-list { display: flex; flex-direction: column; gap: 8px; }
.prov-line {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 11px;
  background: var(--surface);
}
.prov-line.is-gated { opacity: .72; }
.prov-line.is-clickable { cursor: pointer; width: 100%; text-align: left; }
.prov-line.is-clickable:hover { border-color: var(--border-strong); background: var(--surface-sunk); }
.prov-line-main { flex: 1; min-width: 0; }
.prov-line-name { font-size: 14.5px; color: var(--text); }
.prov-line-name .prov-sub { color: var(--text-3); }
.prov-line-meta { margin-top: 5px; }
.prov-line-stats { display: flex; gap: 22px; flex: none; }
.prov-stat { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: 13.5px; }
.prov-stat-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-3);
}

/* A clickable capability card lifts on hover to say it drills in. */
.card.is-clickable { cursor: pointer; }
.card.is-clickable:hover { border-color: var(--border-strong); box-shadow: var(--shadow-card); transform: translateY(-1px); }
.cap-row.is-clickable { cursor: pointer; }

@media (max-width: 720px) {
  .prov-line { flex-wrap: wrap; }
  .prov-line-stats { gap: 16px; }
  .schema-grid { grid-template-columns: 1fr; gap: 3px 0; }
  .schema-desc { margin-bottom: 8px; }
}

/* ---------------------------------------------------------------- app ledger */

/* A vendor logo sits over its monogram, filling the mark; if it fails to load
   (air-gap, no favicon) the img removes itself and the monogram shows through. */
.vmark { position: relative; overflow: hidden; }
.vmark-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; padding: 2px; background: var(--surface);
  border-radius: inherit;
}

.app-card-shelf { font-family: inherit; text-transform: capitalize; color: var(--text-3); }
.app-detail-mark { background: var(--text); color: var(--surface); border-color: var(--text); font-weight: 700; }

/* The vendor's calls, filed by capability. A subject header per capability, then
   one row per endpoint — Treg's "one ledger, filed by subject". */
.app-ledger { display: flex; flex-direction: column; gap: 2px; }
.app-ledger-subject {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: transparent; border: 0; cursor: pointer;
  padding: 16px 4px 8px; margin-top: 6px; border-bottom: 1px solid var(--border);
}
.app-ledger-subject:first-child { margin-top: 0; }
.app-ledger-subject:hover .app-ledger-cap { color: var(--accent); }
.app-ledger-cap { font-size: 14.5px; font-weight: 600; color: var(--text); }
.app-ledger-capid { font-size: 12.5px; color: var(--text-3); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.app-ledger-row {
  display: grid; align-items: center; gap: 14px;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) auto auto auto;
  padding: 11px 4px; border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
.app-ledger-row.is-gated { opacity: .68; }
.app-ledger-what { min-width: 0; }
.app-ledger-what .mono { font-size: 13px; color: var(--text); }
.app-ledger-desc {
  display: block; font-size: 12.5px; margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.app-ledger-call { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-ledger-price { font-variant-numeric: tabular-nums; text-align: right; }
.app-ledger-state { display: flex; justify-content: flex-end; }
.app-ledger-iq { font-size: 12.5px; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

@media (max-width: 760px) {
  .app-ledger-row { grid-template-columns: 1fr auto; gap: 6px 12px; }
  .app-ledger-call, .app-ledger-iq { display: none; }
}

/* ------------------------------------------------------------------- try it */

.tryit-fields {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px 16px; margin: 18px 0 4px;
}
.tryit-fields .field { margin-bottom: 0; }
.tryit-actions { display: flex; gap: 10px; margin-top: 14px; }

/* The run outcome — the moat made visible: what answered, the failover chips,
   what it cost. */
.runres { margin-top: 18px; border: 1px solid var(--border); border-radius: 12px; padding: 16px; }
.runres-head { display: flex; align-items: center; gap: 12px; }
.runres-headmain { flex: 1; min-width: 0; }
.runres-title { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 9px; }
.runres-note { font-size: 12.5px; font-weight: 400; color: var(--text-3); }
.runres-meta { display: flex; align-items: center; gap: 8px; margin-top: 3px; font-size: 13px; color: var(--text-2); }
.runres-chips { margin-top: 13px; }
.runres-steps { display: flex; flex-direction: column; gap: 5px; margin-top: 13px; }
.runres-step { display: flex; align-items: center; gap: 9px; font-size: 13px; }
.runres-step.is-fail { color: var(--red); }
.runres-step-n {
  display: grid; place-items: center; width: 18px; height: 18px; flex: none;
  border-radius: 5px; background: var(--surface-sunk); font-size: 11px; color: var(--text-3);
}
.runres .code { margin-top: 13px; }
.runres-receipt { margin-top: 11px; font-size: 12px; }

/* The agent-facing snippets, tucked behind a disclosure — reference, not the
   first thing a person here wants. */
.snippet-details { margin-top: 20px; }
.snippet-details > summary {
  cursor: pointer; font-size: 13.5px; color: var(--text-2); padding: 6px 0;
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
}
.snippet-details > summary::-webkit-details-marker { display: none; }
.snippet-details > summary::before { content: "›"; transition: transform .14s ease; display: inline-block; }
.snippet-details[open] > summary::before { transform: rotate(90deg); }

/* ------------------------------------------------------------- start / bench */

.start-panel { max-width: 760px; margin-bottom: 18px; }
.start-code { position: relative; margin-top: 4px; }
.start-code .snippet-copy { position: absolute; top: 8px; right: 8px; }
.start-hint { font-size: 13px; margin: 10px 0 0; }

/* Numbered step header: a filled counter, the "Set up your" lead-in, and — for
   step 1 — the client picker inline so the sentence completes itself. */
.start-step-head { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; margin-bottom: 16px; }
.start-step-head h2 { flex: none; }
.start-step-num {
  display: grid; place-items: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--text); color: var(--bg);
  font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.start-picker { width: auto; min-width: 190px; padding: 8px 12px; font-weight: 500; }

/* A code block with a copy chip pinned to its top-right. Config blocks scroll
   sideways rather than wrap — a wrapped closing brace on its own line reads as
   broken JSON, and the token line is long enough to trip the default pre-wrap. */
.start-block { position: relative; }
.start-block .code { padding-right: 84px; white-space: pre; overflow-x: auto; }
.start-copy {
  position: absolute; top: 9px; right: 9px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 9px; border-radius: 7px;
  border: 1px solid var(--border-strong); background: var(--surface);
  color: var(--text-2); font-size: 12px; font-weight: 500; cursor: pointer;
  transition: color .13s ease, border-color .13s ease, background .13s ease;
}
.start-copy:hover { color: var(--text); border-color: var(--text-3); }
.start-copy.is-done { color: var(--green); border-color: var(--green); }
.start-copy-ico { display: inline-flex; }
.start-copy-ico .ico { width: 13px; height: 13px; }

/* API key — masked by default, its own box so a client that asks for the token
   on a separate screen has somewhere to copy it from. */
.start-keybox { margin-top: 16px; padding: 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-sunk); }
.start-keybox.is-empty { background: transparent; border-style: dashed; }
.start-key-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.start-key-label { font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-3); }
.start-key-row { display: flex; align-items: center; gap: 10px; }
.start-key-value {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; color: var(--text);
}
.start-keybox .start-copy { position: static; flex: none; }
.start-key-reveal { width: auto; margin: 0; flex: none; font-size: 13px; }

/* Try-it-out prompt cards, two up. */
.start-examples { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.start-example { padding: 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.start-example-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.start-example-ico { display: inline-flex; color: var(--text-3); }
.start-example-ico .ico { width: 16px; height: 16px; }
.start-example-title { flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-3); }
.start-example-head .start-copy { position: static; }
.start-example-text { margin: 0; font-size: 14.5px; color: var(--text); line-height: 1.45; }

.start-advanced summary {
  cursor: pointer; font-size: 14.5px; font-weight: 500; color: var(--text-2); list-style: none;
}
.start-advanced summary::-webkit-details-marker { display: none; }
.start-advanced summary::before { content: "› "; color: var(--text-3); }
.start-advanced[open] summary::before { content: "⌄ "; }
.start-advanced summary:hover { color: var(--text); }

/* ------------------------------------------------------------- directory */

.dir-bar { align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
.cat-search { flex: 1; min-width: 240px; }
.dir-authbar { flex: none; flex-wrap: wrap; }

/* Tab bar for the merged pages (Providers, Settings, Policy). */
.page-tabs { margin: 0 0 22px; flex-wrap: wrap; }
.tab-body > .panel:first-child { margin-top: 0; }

.dir-cards { grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); align-content: start; }
.dir-card { display: flex; flex-direction: column; gap: 13px; }
.dir-card-head { display: flex; align-items: center; gap: 11px; min-width: 0; }
.dir-mark {
  width: 34px; height: 34px; border-radius: 9px; flex: none;
  display: grid; place-items: center; overflow: hidden; position: relative;
  background: var(--surface-sunk); border: 1px solid var(--border);
  font-size: 12px; font-weight: 600; color: var(--text-2);
}
.dir-mark .vmark-img { background: #fff; padding: 2px; }
.dir-card-id { min-width: 0; flex: 1; }
.dir-card-name { font-size: 14.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dir-card-cats { font-size: 12px; color: var(--text-3); text-transform: capitalize; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dir-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; }
.dir-auth { font-size: 11.5px; }
.dir-auth-oauth { color: var(--green); }
.dir-connect { padding: 5px 13px; font-size: 13px; }
.dir-connect-note { font-size: 12.5px; }
.dir-more-wrap { display: flex; justify-content: center; margin-top: 22px; }
.dir-more { min-width: 220px; justify-content: center; }
.dir-loading { padding: 48px; text-align: center; grid-column: 1 / -1; }
.dir-connect { padding: 5px 12px; font-size: 13px; gap: 5px; }
.dir-connect.is-connected { color: var(--green); border-color: var(--green); }
.dir-connect.is-connected svg { width: 14px; height: 14px; }

/* Vendor connect / try drawer (reuses the run drawer's shell). */
.vendor-body { margin-top: 20px; }
.vendor-body .field { margin-bottom: 12px; }
.vendor-connected {
  display: flex; align-items: center; gap: 9px; margin-bottom: 22px;
  padding: 11px 13px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-sunk);
  font-size: 13.5px;
}
.vendor-connected .pill-ok { flex: none; }
.vendor-connected .btn-danger { margin-left: auto; }
.vendor-req { display: flex; gap: 8px; margin-bottom: 12px; }
.vendor-req .input:not(select) { flex: 1; }
.vendor-req .btn { flex: none; }
.vendor-status { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }

@media (max-width: 640px) {
  .start-examples { grid-template-columns: minmax(0, 1fr); }
  .start-step-head { gap: 9px; }
  .start-picker { min-width: 0; flex: 1; }
}

/* ------------------------------------------------------------- oauth sign-in */

.connect-oauth { display: flex; flex-direction: column; gap: 9px; margin-bottom: 4px; }
.connect-provider { width: 100%; justify-content: center; gap: 9px; }
.connect-provider-mark { width: 18px; height: 18px; border-radius: 5px; }
/* Provider favicons are drawn for a white background — GitHub's octocat is
   near-black and vanishes on the dark button. So the loaded logo sits on its own
   white chip. Only the img is repainted, not the span: if the favicon fails to
   load (air-gap) the img removes itself and the light monogram shows straight on
   the button, which stays legible where a white chip would not. */
.connect-provider-mark .vmark-img { background: #fff; padding: 2.5px; }
.connect-divider {
  display: flex; align-items: center; text-align: center; color: var(--text-3);
  font-size: 12.5px; margin: 14px 0 4px;
}
.connect-divider::before, .connect-divider::after {
  content: ""; flex: 1; border-bottom: 1px solid var(--border);
}
.connect-divider span { padding: 0 12px; }

/* ---------------------------------------------------------------- landing */

/* The landing lives inside the app shell but reads as its own page: a contained
   column with generous rhythm, contrast bands, and its own top bar. Contained
   (not full-bleed) so it needs no fragile negative-margin break-out. */
.landing { max-width: 1120px; margin: 0 auto; }

.lp-top { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 2px 0 10px; margin-bottom: 36px; }
.lp-brand { display: inline-flex; align-items: center; gap: 10px; font-size: 17px; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
.lp-logo { display: inline-grid; place-items: center; color: var(--text); }
.lp-topnav { display: flex; align-items: center; gap: 22px; }
.lp-topnav > a { color: var(--text-2); font-size: 14.5px; }
.lp-topnav > a:hover { color: var(--text); }
.lp-signin { width: auto; margin: 0; padding: 0; color: var(--text-2); font-size: 14.5px; }
.lp-signin:hover { color: var(--text); text-decoration: none; }
.lp-cta { padding: 9px 18px; }

.lp-hero { display: grid; grid-template-columns: 1.05fr .95fr; gap: 48px; align-items: center; padding: 20px 0 56px; }
.lp-eyebrow { font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--accent); margin-bottom: 16px; }
.lp-hero h1 { font-size: 52px; line-height: 1.04; letter-spacing: -.03em; margin: 0 0 20px; font-weight: 700; }
.lp-accent { color: var(--text-3); }
.lp-sub { font-size: 18px; line-height: 1.55; color: var(--text-2); margin: 0 0 28px; max-width: 32em; }
.lp-hero-cta { display: flex; gap: 12px; flex-wrap: wrap; }
.lp-hero-cta .btn, .lp-hero-cta .btn-outline { padding: 11px 20px; font-size: 15px; }

.lp-hero-code { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); box-shadow: var(--shadow-card); }
.lp-code-head { display: flex; align-items: center; gap: 7px; padding: 11px 14px; border-bottom: 1px solid var(--border); background: var(--surface-sunk); }
.lp-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); }
.lp-code-title { margin-left: 8px; font-size: 12.5px; color: var(--text-3); }
.lp-hero-code .code { border: 0; border-radius: 0; background: var(--surface); font-size: 12.5px; }

.lp-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; padding: 30px; margin: 4px 0 64px; border: 1px solid var(--border); border-radius: 16px; background: var(--surface-sunk); }
.lp-stat { text-align: center; }
.lp-stat-n { font-size: 34px; font-weight: 700; letter-spacing: -.02em; }
.lp-stat-l { font-size: 13px; color: var(--text-3); margin-top: 4px; }

.lp-section { padding: 32px 0 64px; }
.lp-section-head { max-width: 40em; margin: 0 auto 36px; text-align: center; }
.lp-section-head h2, .lp-band h2, .lp-final h2 { font-size: 32px; letter-spacing: -.02em; margin: 0 0 12px; font-weight: 700; }
.lp-section-sub { font-size: 16.5px; color: var(--text-2); line-height: 1.55; margin: 0; }
.lp-feats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.lp-feat { padding: 22px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); }
.lp-feat h3 { font-size: 16.5px; margin: 0 0 8px; font-weight: 600; }
.lp-feat p { font-size: 14px; color: var(--text-2); line-height: 1.55; margin: 0; }

.lp-band { display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap; padding: 36px 40px; margin: 4px 0 64px; border-radius: 18px; background: var(--text); }
.lp-band h2, .lp-band p { color: var(--bg); }
.lp-band p { font-size: 15.5px; opacity: .82; margin: 0; max-width: 44em; }
/* Selector carries three classes so it out-specifies the global theme rule
   `:root:not([data-theme="dark"]) .btn { color:#fff }` — without it the band's
   light button gets white text on its own white face and vanishes. */
.landing .lp-band .btn { background: var(--bg); color: var(--text); flex: none; }
.landing .lp-band .btn:hover { opacity: .88; }

.lp-ways { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.lp-way { padding: 22px; border: 1px solid var(--border); border-radius: 14px; }
.lp-way-k { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; font-weight: 600; color: var(--accent); margin-bottom: 10px; }
.lp-way p { font-size: 14px; color: var(--text-2); line-height: 1.55; margin: 0; }
.lp-ways-cta { display: flex; justify-content: center; margin-top: 28px; }

.lp-final { text-align: center; padding: 60px 24px; margin: 4px 0 40px; border: 1px solid var(--border); border-radius: 20px; background: var(--surface-sunk); }
.lp-final p { font-size: 16.5px; color: var(--text-2); margin: 10px 0 26px; }
.lp-cta-lg { padding: 13px 26px; font-size: 16px; }

.lp-footer { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; padding: 28px 0; border-top: 1px solid var(--border); }
.lp-foot-brand { display: flex; gap: 12px; align-items: baseline; font-weight: 600; }
.lp-foot-links { display: flex; gap: 22px; align-items: center; }
.lp-foot-links a, .lp-foot-links button { color: var(--text-2); font-size: 14px; width: auto; margin: 0; padding: 0; }
.lp-foot-links a:hover, .lp-foot-links button:hover { color: var(--text); text-decoration: none; }

@media (max-width: 860px) {
  .lp-hero { grid-template-columns: 1fr; gap: 30px; padding-bottom: 40px; }
  .lp-hero h1 { font-size: 38px; }
  .lp-sub { font-size: 16.5px; }
  .lp-stats { grid-template-columns: repeat(2, 1fr); gap: 22px 12px; }
  .lp-feats, .lp-ways { grid-template-columns: 1fr; }
  .lp-topnav > a { display: none; }
  .lp-band { padding: 28px; }
  .lp-section-head h2, .lp-band h2, .lp-final h2 { font-size: 26px; }
}
