/* neout/agents dashboard — design tokens inherited from index.html
   (the marketing landing) so the brand is consistent across both
   screens. Navy + emerald, JetBrains for code, Plus Jakarta for body. */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }

:root {
  /* ── Vercel-harvested design tokens 2026-06-08 ──────────────────
     Captured live via getComputedStyle on vercel.com dashboard
     (signed-in dark theme). Two-tone canvas, single muted text
     color, 6px radius everywhere, borders implemented as inset
     box-shadows. See vercel-design-tokens.md for the full harvest. */
  --vercel-bg:           #000000;  /* page canvas */
  --vercel-surface:      #0a0a0a;  /* cards, inputs, sidebar bg */
  --vercel-elevated:     #1a1a1a;  /* popover, inline-code bg */
  --vercel-hover:        #1f1f1f;  /* nav hover, sidebar active */
  --vercel-pressed:      #292929;  /* dividers, deeper hover */
  --vercel-text:         #ededed;  /* primary text/headings */
  --vercel-muted:        #a1a1a1;  /* one muted tone — Vercel uses ONE */
  --vercel-disabled:     #7d7d7d;
  --vercel-border:       #1f1f1f;  /* default hairline */
  --vercel-border-strong:#2e2e2e;  /* button outlines */
  --vercel-focus: 0 0 0 1px #ffffff82, 0 0 0 4px #ffffff3d;
  --vercel-shadow-border: 0 0 0 1px #ffffff25, 0 1px 1px #00000005, 0 4px 8px #0000000a;

  /* ── Brand identity layer ──────────────────────────────────────
     We adopt Vercel's discipline (canvas + spacing + radius) but
     keep neout's emerald as the brand accent so the primary CTA
     and active states still read as "neout/agents", not "Vercel". */
  --emerald: #10b981;
  --emerald-2: #34d399;
  --emerald-hover: #0d9668;
  --emerald-glow: rgba(16,185,129,0.15);

  /* ── Map existing --navy-* tokens to the Vercel scale so all
        existing rules (cards, sidebars, inputs, modals, tables,
        webhooks, playground, account, …) adopt the new palette
        in one shot. Touching the tokens here means every selector
        that referenced --navy-700 etc. now reads Vercel-grade dark
        without the audit-flagged blue cast. */
  --navy-900: var(--vercel-bg);        /* page canvas → #000 */
  --navy-800: var(--vercel-surface);   /* cards/inputs → #0a0a0a */
  --navy-700: var(--vercel-elevated);  /* hover/secondary → #1a1a1a */
  --navy-600: var(--vercel-hover);     /* selected row → #1f1f1f */
  --navy-500: var(--vercel-pressed);   /* dividers → #292929 */
  --navy-400: var(--vercel-border-strong);

  --text:       var(--vercel-text);
  --text-muted: var(--vercel-muted);
  /* --text-dim collapsed onto the same muted tone — Vercel uses ONE
     muted tone everywhere and lets weight/size carry the hierarchy
     instead of three shades of gray (design audit 2026-06-08). */
  --text-dim:   var(--vercel-muted);

  --border:       var(--vercel-border);
  --border-light: var(--vercel-border-strong);

  --red: #ef4444;
  --amber: #f59e0b;
  --max-w: 1200px;

  /* Unified radius scale — Vercel uses 6px everywhere; 4px for
     inline code; full-pill for status dots. Audit-recommended
     collapse from our 4/8/10/12/14 mess. */
  --radius-sm: 4px;
  --radius:    6px;
  --radius-lg: 8px;
}

/* Global :focus-visible — keyboard-only focus ring. The pre-existing
   `outline:none` on inputs (plus an emerald glow only on text inputs)
   left buttons, links, nav items, model selectors, and template chips
   with NO visible focus state at all. Without this, keyboard users
   cannot see where focus is — WCAG 2.4.7 violation.
   Audit: 2026-06-08 a11y review. */
*:focus { outline: none; }
/* Vercel's double-layered focus ring (1px white-50% + 4px white-24%)
   — reads on both dark surfaces and bright CTAs without recoloring,
   and removes one source of emerald-overuse the audit flagged. */
*:focus-visible {
  outline: none;
  box-shadow: var(--vercel-focus);
  border-radius: inherit;
}

/* Visually-hidden but available to screen readers. Used where we
   want to keep a heading semantically but the visual layout already
   communicates the same thing (e.g. dash-header h1 + card h2 with
   identical text reads as duplicated to sighted users). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip-link — bypass nav for keyboard users (WCAG 2.4.1). Hidden until
   focused; jumps the user past the sidebar's 11 nav items straight to
   the dashboard heading. */
.skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  background: var(--emerald);
  color: #fff;
  padding: 8px 12px;
  text-decoration: none;
  font-weight: 600;
  border-radius: 6px;
  z-index: 9999;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 8px; }

html { scroll-behavior: smooth; }

/* Font-family vars — Geist is Vercel's open-source UI font. Mono pairs
   with Geist Mono. Loaded from Google Fonts in <head>. All UI text
   below resolves through these vars; never re-declare 'Geist' inline. */
:root {
  --font-sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, SFMono-Regular,
               Menlo, Monaco, Consolas, "Liberation Mono", monospace;
}

body {
  /* Vercel baseline: 14px / 1.5 / -0.01em — measured live on their
     dashboard <main>. Geist + tight tracking is what makes the UI
     feel like a developer tool, not a marketing page. */
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -0.01em;
  font-weight: 400;
  background: var(--vercel-bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
code, .mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-feature-settings: "ss01", "cv11";
}

/* ============ NAV ============ */
.app-nav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
/* Auth-screen mode: hide the full marketing nav (Vercel pattern — the
   sign-in page should not be cluttered with Home / Sign in / Get
   started chrome). A small "Browsa" word-mark anchored top-left is
   injected by renderAuth() as .auth-corner-logo so the user still has
   one click back to the marketing site. */
body.is-auth > .app-nav { display: none !important; }
.auth-corner-logo {
  position: fixed;
  top: 24px;
  left: 32px;
  z-index: 60;
  color: var(--vercel-text);
  font-weight: 600;
  font-size: 18px;
  text-decoration: none;
  letter-spacing: -0.01em;
}
.auth-corner-logo:hover { opacity: 0.8; }
@media (max-width: 640px) { .auth-corner-logo { top: 16px; left: 16px; font-size: 16px; } }
.nav-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 16px 24px;
  display: flex; align-items: center; justify-content: space-between;
}
.logo {
  font-weight: 700; font-size: 17px;
  color: var(--text); text-decoration: none;
  display: flex; align-items: center;
}
.logo .slash { color: var(--text-dim); font-weight: 400; }
.logo .accent { color: var(--text); font-weight: 600; }  /* Vercel-style: brand color stays out of the logo */
.nav-right { display: flex; align-items: center; gap: 12px; }
.nav-link {
  color: var(--text-muted); text-decoration: none; font-size: 14px;
  font-weight: 500;
}
.nav-link:hover { color: var(--text); }
.nav-user {
  color: var(--text-muted);
  font-size: 13px;
  padding: 4px 8px;
  background: var(--navy-700);
  border-radius: 6px;
  border: 1px solid var(--border);
}

/* ============ BUTTONS — Vercel pattern ============
   Primary: white-on-black, 40px tall, 6px radius, weight 500.
            This is THE move — replaces the emerald CTA with the
            highest-contrast button in the industry. Brand emerald
            still lives in the logo + active-state highlights.
   Secondary: outlined via inset shadow, transparent bg.
   Ghost: same as secondary but no outline until hover.
   All buttons use Vercel's box-shadow-as-border so the outline
   can animate on hover without layout shift. */
.btn-primary, .btn-ghost, .btn-secondary, .btn-icon {
  font-family: inherit;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: -0.01em;
  border-radius: var(--radius);
  border: none;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, box-shadow 150ms ease, filter 150ms ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-decoration: none;
  white-space: nowrap;
  height: 40px;
  padding: 0 12px;
  line-height: 1;
}
.btn-primary {
  background: var(--vercel-text);  /* #ededed — Vercel's signature white */
  color: var(--vercel-bg);
}
.btn-primary:hover { filter: brightness(0.94); }
.btn-primary:disabled {
  background: var(--vercel-elevated);
  color: var(--vercel-disabled);
  cursor: not-allowed;
}

.btn-ghost {
  background: transparent;
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
}
.btn-ghost:hover {
  background: var(--vercel-elevated);
  color: var(--vercel-text);
}

.btn-secondary {
  background: var(--vercel-surface);
  color: var(--vercel-text);
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
}
.btn-secondary:hover { background: var(--vercel-elevated); }

.btn-full { width: 100%; padding: 12px 14px; font-size: 15px; }
.btn-danger {
  background: transparent;
  color: var(--red);
  padding: 4px 8px;
  border: 1px solid transparent;
}
.btn-danger:hover { background: rgba(239, 68, 68, 0.1); border-color: rgba(239, 68, 68, 0.3); }
.icon-btn {
  padding: 6px 10px;
  font-size: 16px;
  line-height: 1;
}

/* ============ AUTH SCREEN ============ */
main {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.auth-screen {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 96px 24px 48px;  /* room for the top-left corner logo */
  gap: 48px;
}
/* Vercel-style auth: no card chrome. The form sits directly on the
   canvas with a large heading on top. Was a navy card with rounded
   corners before — restyled 2026-06-10 to match the dashboard's
   Vercel-grade language across the whole signed-out journey. */
.auth-card {
  width: 100%;
  max-width: 420px;
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  flex-shrink: 0;
}

/* Inline form hints (e.g. password rules under the password field).
   Smaller, dimmer than the label — feels like a tooltip baked into
   the form rather than a separate paragraph. */
.field-hint {
  font-size: 11.5px;
  color: var(--text-dim);
  margin-top: 2px;
}
.field-hint[hidden] { display: none !important; }

/* Legal consent line below the submit button on signup. Stripe/Linear
   pattern — no checkbox, accepting the form constitutes consent. */
.auth-legal {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-dim);
  text-align: center;
  margin-top: 4px;
}
.auth-legal[hidden] { display: none !important; }
.auth-legal a {
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.auth-legal a:hover { color: var(--text); }

/* Value-prop sidebar — appears next to the auth card in signup mode
   so the page feels less like a lonely form on a giant black canvas. */
.auth-sidebar {
  width: 320px;
  flex-shrink: 0;
  padding: 28px 28px 24px;
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.auth-sidebar[hidden] { display: none !important; }
@media (max-width: 880px) {
  .auth-screen { flex-direction: column-reverse; }
  .auth-sidebar { width: 100%; max-width: 420px; border-left: 0; border-top: 1px solid var(--border); padding: 24px 0 0; }
}
.auth-sidebar-head {
  display: flex; flex-direction: column; gap: 8px;
}
.auth-sidebar-tag {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--emerald-2);
  background: rgba(16,185,129,0.10);
  padding: 3px 8px;
  border-radius: 999px;
  align-self: flex-start;
}
.auth-sidebar h3 {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  margin: 0;
}
.auth-sidebar-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Bullet uses text-indent so the body text wraps as a single block
   (the previous flex layout broke <b> off into its own column when
   the inline-bold ran long). */
.auth-sidebar-list li {
  position: relative;
  padding-left: 22px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}
.auth-sidebar-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--emerald);
  font-weight: 700;
}
.auth-sidebar-list b { color: var(--text); font-weight: 600; }
.auth-sidebar-foot {
  font-size: 12px;
  color: var(--text-dim);
  margin: 0;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
  line-height: 1.5;
}
.auth-title {
  /* Vercel-grade — large headline on the canvas, no card chrome. */
  font-size: 36px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.1;
  margin-bottom: 10px;
  color: var(--vercel-text);
}
.auth-subtitle {
  color: var(--text-muted);
  font-size: 15px;
  margin-bottom: 32px;
}
@media (max-width: 640px) { .auth-title { font-size: 28px; } }
.auth-form { display: flex; flex-direction: column; gap: 16px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field[hidden] { display: none !important; }
.field > span {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
}
.field input {
  font-family: inherit;
  background: var(--navy-800);
  border: 1px solid var(--border-light);
  color: var(--text);
  border-radius: 8px;
  padding: 11px 14px;
  font-size: 15px;
  transition: border-color 150ms;
}
.field input:focus {
  /* Vercel input focus — white border + double-layered white halo. */
  outline: none;
  border-color: var(--vercel-text);
  box-shadow: var(--vercel-focus);
}
.form-error {
  color: var(--red);
  font-size: 13px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.2);
  padding: 10px 12px;
  border-radius: 8px;
}
.form-success {
  color: var(--emerald-2);
  font-size: 13px;
  background: var(--emerald-glow);
  border: 1px solid rgba(16,185,129,0.35);
  padding: 10px 12px;
  border-radius: 8px;
  line-height: 1.5;
}
.auth-email {
  color: var(--emerald-2);
  font-weight: 600;
}
.auth-forgot {
  text-align: center;
  margin-top: 10px;
  font-size: 13px;
}
.auth-forgot a {
  color: var(--text-muted); text-decoration: none;
}
.auth-forgot a:hover { color: var(--text); text-decoration: underline; }
.auth-foot {
  margin-top: 18px;
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
}
.auth-foot a {
  /* Vercel link pattern: text inherits foreground, underline appears
     on hover — accent stays reserved for primary CTA. */
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
  margin-left: 4px;
}
.auth-foot a:hover { text-decoration: underline; }

/* ============ DASHBOARD LAYOUT (Hyperbrowser pattern) ============ */
/* The dashboard switches off the global top nav and replaces it with
   a persistent left sidebar + scrollable main area. The body gets
   .has-sidebar class via JS while the dashboard route is active. */
body.has-sidebar > .app-nav { display: none; }
body.has-sidebar { background: var(--navy-900); }

/* Sidebar — Vercel's exact dimensions measured live:
   256px column, 36px-tall items, 6px radius, no left-accent-bar.
   Active state is just bg #1f1f1f — cleaner than the trendy
   left-rule-marker. */
.dash-layout {
  display: grid;
  grid-template-columns: 256px 1fr;
  min-height: 100vh;
}
@media (max-width: 880px) {
  .dash-layout { grid-template-columns: 1fr; }
  .dash-sidebar { display: none; }
  body.has-sidebar > .app-nav { display: block; }
}

.dash-sidebar {
  background: var(--vercel-bg);
  border-right: 1px solid var(--vercel-border);
  padding: 18px 12px 12px;
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.dash-logo {
  font-weight: 600; font-size: 15px;
  letter-spacing: -0.02em;
  color: var(--text); text-decoration: none;
  padding: 4px 12px 16px;
  display: inline-block;
}
.dash-logo .slash { color: var(--text-muted); font-weight: 400; }
.dash-logo .accent { color: var(--text); }  /* was emerald — Vercel keeps brand color out of the logo lockup */

.dash-nav {
  display: flex; flex-direction: column; gap: 1px;
  margin-bottom: auto;
}
.dash-nav-item {
  display: flex; align-items: center; gap: 10px;
  height: 36px;            /* Vercel spec exact */
  padding: 0 12px;
  color: var(--text-muted); font-size: 14px; font-weight: 500;
  letter-spacing: -0.01em;
  text-decoration: none; border-radius: var(--radius);
  transition: background-color 120ms ease, color 120ms ease;
  white-space: nowrap;
}
.dash-nav-item:hover { background: var(--vercel-hover); color: var(--text); }
.dash-nav-item.active {
  background: var(--vercel-hover);
  color: var(--text);
}
/* No ::before left-bar — Vercel uses pure bg shift for active state. */
.dash-nav-item.ghost { color: var(--text-dim); font-size: 13px; }
.dash-nav-item.ghost:hover { color: var(--text-muted); }
.dash-nav-ico {
  display: inline-flex; align-items: center; justify-content: center;
  /* Sized to match Vercel/Linear sidebar icons (16px box, 1.5 stroke).
     Was 18px with mono-font glyph chars; replaced with inline SVG on
     2026-06-10 — chars rendered inconsistently across fonts and read
     as decoration instead of nav affordances. */
  width: 16px; height: 16px;
  color: var(--text-dim); flex-shrink: 0;
  transition: color 120ms ease;
}
svg.dash-nav-ico { stroke-width: 1.6; }
.dash-nav-item:hover .dash-nav-ico { color: var(--text); }
.dash-nav-item.active .dash-nav-ico { color: var(--text); }
.dash-nav-item .ext { margin-left: auto; font-size: 11px; color: var(--text-dim); }

.dash-sidebar-footer {
  margin-top: 24px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 2px;
}

/* Persistent credit-balance pill in the sidebar — competitor-audit
   2026-06-09 (persona A): browser-use cloud's '9 free tasks' counter
   is a clean activation nudge that's always visible. We mirror the
   pattern but use real credit balance instead of free-task count. */
.dash-credits-pill {
  display: flex; align-items: center; gap: 8px;
  margin-top: 16px; padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
  color: var(--text);
  background: var(--vercel-card, rgba(255,255,255,0.02));
  transition: border-color 120ms, background 120ms;
  font-size: 13px;
}
.dash-credits-pill:hover {
  border-color: var(--emerald, #10b981);
  background: rgba(16,185,129,0.05);
}
.dash-credits-num {
  font-size: 16px; font-weight: 700;
  color: var(--emerald, #10b981);
  font-variant-numeric: tabular-nums;
}
.dash-credits-label {
  color: var(--text-dim, #94a3b8);
  font-size: 12px;
  letter-spacing: 0.04em;
}
/* Low / empty states — softened from full amber/red border to a tiny
   leading dot indicator. The previous bright amber clashed with the
   monochrome Vercel canvas (audit 2026-06-10 flagged it as an off-
   brand accent). The dot keeps the warning signal where it belongs
   (next to the number) without dyeing the whole pill chrome. */
.dash-credits-pill.low { border-color: var(--vercel-border-strong); }
.dash-credits-pill.low .dash-credits-num { color: var(--vercel-text); }
.dash-credits-pill.low .dash-credits-num::before {
  content: ""; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  background: #fbbf24;
  margin-right: 8px; vertical-align: 1px;
}
.dash-credits-pill.empty { border-color: var(--vercel-border-strong); }
.dash-credits-pill.empty .dash-credits-num { color: var(--vercel-text); }
.dash-credits-pill.empty .dash-credits-num::before {
  content: ""; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  background: #f87171;
  margin-right: 8px; vertical-align: 1px;
}

.dash-user {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 10px 4px;
  margin-top: 6px;
  border-top: 1px solid var(--border);
}
.dash-user-avatar {
  /* Vercel-style neutral avatar — emerald-fill was loudest non-CTA
     element on screen. Now: surface bg + hairline border + foreground
     letter, matching the team-row avatars in Vercel Settings. */
  width: 32px; height: 32px; border-radius: var(--radius);
  background: var(--vercel-elevated);
  color: var(--vercel-text);
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  display: flex; align-items: center; justify-content: center;
  font-weight: 500; font-size: 13px;
  text-transform: uppercase; flex-shrink: 0;
}
.dash-user-meta {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
}
.dash-user-name {
  color: var(--text); font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dash-user-email {
  color: var(--text-dim); font-size: 11px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dash-user-signout {
  background: transparent; border: 1px solid var(--border-light);
  color: var(--text-muted); cursor: pointer;
  width: 26px; height: 26px; border-radius: 6px;
  font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
}
.dash-user-signout:hover { color: var(--red); border-color: rgba(239,68,68,0.4); }

.dash-main {
  padding: 28px 36px 64px;
  max-width: 1240px;
  width: 100%;
}
@media (max-width: 880px) {
  .dash-main { padding: 20px 16px 48px; }
}

/* Mobile-only horizontal nav. Replaces the hidden sidebar on
   narrow viewports so users still have a way to switch dashboard
   views. Scrolls horizontally when the 7 pills don't fit. */
.dash-mobile-nav { display: none; }
@media (max-width: 880px) {
  .dash-mobile-nav {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    margin: -4px -16px 16px;
    padding: 4px 16px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    border-bottom: 1px solid var(--border);
  }
  .dash-mobile-nav::-webkit-scrollbar { display: none; }
}
.dmn-item {
  flex: 0 0 auto;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  background: var(--navy-700);
  white-space: nowrap;
  transition: background 120ms, color 120ms, border-color 120ms;
}
.dmn-item:hover { color: var(--text); }
.dmn-item.active {
  /* Mobile nav active pill — inverted, matches sidebar active pattern. */
  background: var(--vercel-text);
  color: var(--vercel-bg);
  border-color: var(--vercel-text);
  font-weight: 500;
}

.dash-shell {
  /* Legacy outer wrapper, retained for compatibility with the old
     single-column layout if .dash-layout is ever absent. */
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 32px 24px 64px;
  width: 100%;
}
.dash-header {
  margin-bottom: 24px;
}
.dash-header-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.dash-header h1 {
  /* Vercel/Linear tight-tracking ramp — 600 weight + negative tracking
     does the hierarchical work that 700+ used to do, but reads as
     calmer and more deliberate. Design audit 2026-06-08. */
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin-bottom: 6px;
}
.dash-header p {
  color: var(--text-muted);
  font-size: 13.5px;
  line-height: 1.5;
  max-width: 640px;
}
.dash-actions {
  display: flex; gap: 8px; align-items: center;
}
.dash-actions .btn-ghost {
  font-size: 13px; padding: 6px 12px;
}

/* Onboarding banner — fresh-user 3-step guide.
   Design audit 2026-06-08: previously a gradient hero card that
   consumed ~25% of viewport above the fold and crowded out KPIs.
   Shrunk to a compact strip — same content, half the visual weight,
   no gradient. Emerald accent narrowed to the left-edge rule + step
   numbers, not the whole card. */
.onboarding {
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-left: 2px solid var(--vercel-border-strong);
  border-radius: 8px;
  padding: 14px 18px;
  margin-bottom: 20px;
  position: relative;
}
.onboarding-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 10px;
}
.onboarding-head h2 {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 1px;
  color: var(--text);
}
.onboarding-head p {
  font-size: 12.5px;
  color: var(--text-muted);
}
.onboarding-dismiss {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 20px;
  cursor: pointer;
  line-height: 1;
  padding: 0 6px;
  font-family: inherit;
}
.onboarding-dismiss:hover { color: var(--text); }
/* Steps row — compact inline strip, not 3 full sub-cards.
   Visual QA 2026-06-08 found my previous outer-container shrink
   didn't actually slim the banner because the 3 child cards still
   each had padding+borders+circular numbers. This converts them to
   a single horizontal row of pill-like badges with no per-step
   border/bg — the rule on the parent banner does the visual work. */
.onboarding-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
}
@media (max-width: 720px) {
  .onboarding-steps { gap: 10px; }
}
.onboarding-step {
  display: flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  text-decoration: none;
  color: var(--text);
  transition: opacity 120ms;
}
.onboarding-step:hover { opacity: 0.85; }
.onboarding-num {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--vercel-elevated);
  color: var(--text-muted);
  border: 1px solid var(--border);
  font-weight: 600; font-size: 11px;
  flex-shrink: 0;
}
.onboarding-step-label {
  font-size: 12.5px; font-weight: 500; color: var(--text);
  letter-spacing: -0.01em;
}
/* Sub-line dropped on the compact strip — the label alone communicates
   the step. Re-enable later if we re-introduce a verbose variant. */
.onboarding-step-sub { display: none; }
/* Done state: step 2/3 turn into checkmark + strikethrough so the user
   can see "one more to go". Wired by setupOnboarding (.done class
   toggled on each .onboarding-step). QA 2026-06-08. */
.onboarding-step.done .onboarding-num {
  /* Done-state uses Vercel's "ready" cyan (#50e3c2) — matches the
     Deployment Ready status pill on Vercel's dashboard. Keeps the
     emerald brand color from leaking into a sub-success indicator. */
  background: #50e3c2;
  color: transparent;
  border-color: #50e3c2;
  position: relative;
}
.onboarding-step.done .onboarding-num::after {
  content: '✓';
  color: #0a0a0a;
  font-size: 11px;
  font-weight: 700;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.onboarding-step.done .onboarding-step-label {
  text-decoration: line-through;
  color: var(--text-muted);
}

/* Metrics row */
.metrics-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  margin-bottom: 24px;
}
@media (max-width: 1100px) {
  .metrics-row { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 680px) {
  .metrics-row { grid-template-columns: repeat(2, 1fr); }
}
/* Cards lift one step above page canvas (#000 → #0a0a0a body
   → #1a1a1a card). Audit 2026-06-10 flagged dashboard cards as
   "floaty/undefined" because they sat at #0a0a0a (same as body on
   most pages) with only a 1px hairline. Bumping the surface to
   --vercel-elevated gives proper visual depth and matches the
   landing-page card pattern. */
.metric {
  background: var(--vercel-elevated);
  border: none;
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  border-radius: var(--radius);
  padding: 14px 16px;
  min-height: 92px;
  display: flex; flex-direction: column; justify-content: space-between;
  transition: box-shadow 150ms ease, transform 150ms ease;
}
.metric:hover { box-shadow: inset 0 0 0 1px var(--vercel-border-strong); transform: translateY(-1px); }
.metric-head {
  display: flex; align-items: center; gap: 8px;
  color: var(--text-dim); font-size: 11px;
}
.metric-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px;
  font-family: var(--font-mono); font-size: 11px;
  /* Icons recede — design audit said per-stat colored icons fight the
     numbers for attention. Single mono color across the row. */
  color: var(--text-dim);
}
.metric-label {
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 10.5px;
}
.metric-num {
  font-size: 32px; font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.1;
  margin-top: 8px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* Vercel discipline: metric numbers stay white. Color is reserved
   for warning/error states ONLY. The previous `.metric.good →
   emerald` rule was tinting Credits emerald just because it had
   a positive balance — which made the most-prominent number on
   the dashboard the wrong color. */
.metric.warn .metric-num { color: var(--amber); }
.metric.bad  .metric-num { color: var(--red); }
.metric.good .metric-num { color: var(--text); }
.metric-sub {
  color: var(--text-dim); font-size: 11.5px;
  margin-top: 4px;
}

/* Cards */
/* Card chrome — Vercel pattern: elevated surface (one step above page
   canvas) + inset 1px shadow as "border" (animates without layout shift
   on hover), 6px radius. Was using --vercel-surface (#0a0a0a) which is
   identical to the body bg → cards looked floaty against the canvas.
   Lifting to --vercel-elevated (#1a1a1a) restores depth (audit 2026-06-10). */
.card {
  background: var(--vercel-elevated);
  border: none;
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  border-radius: var(--radius);
  margin-bottom: 20px;
  overflow: hidden;
  transition: box-shadow 150ms ease;
}
.card:hover {
  /* Outline brightens on hover — Vercel's signature card interaction.
     No transform, no scale, no shadow lift — just a hairline glow. */
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
}
.card-head {
  padding: 16px 16px 6px;
}
.card-head.row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}
.card-head h2 {
  /* Vercel section-heading ramp: 14px / 500 / -0.28px tracking.
     The tight letter-spacing at small sizes is the optical move that
     makes the UI read as deliberate. */
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
  color: var(--text);
}
.card-head p {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}
.card-body { padding: 12px 16px 16px; }

/* Generic helpers */
.muted { color: var(--text-muted); }
.dim { color: var(--text-dim); }
.small { font-size: 12px; }
code {
  background: var(--vercel-elevated);
  border: none;
  padding: 1px 5px;
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.92em;
}

/* ============ PLAYGROUND ============ */
.playground .card-head.row { align-items: center; }
.pg-status {
  font-size: 11px; font-weight: 600;
  padding: 4px 10px; border-radius: 999px;
  text-transform: uppercase; letter-spacing: 0.5px;
  background: var(--navy-800); color: var(--text-muted);
  border: 1px solid var(--border);
  display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap;
}
.pg-status.idle { color: var(--text-muted); }
.pg-status.queued { background: rgba(99,102,241,0.15); color: #a5b4fc; border-color: rgba(99,102,241,0.3); }
.pg-status.running {
  background: rgba(245,158,11,0.15); color: #fbbf24; border-color: rgba(245,158,11,0.3);
}
.pg-status.running::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: #fbbf24; animation: pulse 1.5s ease-in-out infinite;
}
.pg-status.completed { background: rgba(80,227,194,0.08); color: #50e3c2; border-color: rgba(80,227,194,0.24); }
.pg-status.failed { background: rgba(239,68,68,0.15); color: #fca5a5; border-color: rgba(239,68,68,0.35); }

.pg-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: 18px;
  margin-top: 10px;
}
@media (max-width: 1100px) { .pg-grid { grid-template-columns: 1fr; } }

.pg-form { display: flex; flex-direction: column; gap: 14px; }
.pg-field { display: flex; flex-direction: column; gap: 6px; }
.pg-field > span {
  font-size: 12.5px; font-weight: 500; color: var(--text-muted);
  display: flex; align-items: baseline; gap: 8px;
}
.pg-hint { color: var(--text-dim); font-size: 11px; font-weight: 400; }
.pg-field input,
.pg-field select,
.pg-field textarea {
  font-family: inherit;
  background: var(--navy-800);
  border: 1px solid var(--border-light);
  color: var(--text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14px;
  resize: vertical;
  transition: border-color 120ms;
}
.pg-field textarea { font-family: inherit; line-height: 1.45; }
.pg-field input:focus,
.pg-field select:focus,
.pg-field textarea:focus {
  outline: none; border-color: var(--vercel-text);
  box-shadow: var(--vercel-focus);
}
.pg-field select {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='%2394a3b8'><path d='M3 4l3 3 3-3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
  padding-right: 32px;
}
.pg-row-2 { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; }

/* Collapsible "Browser fingerprint" block — OS type + Country
   pickers, our anti-detect knobs. Hidden by default so the form
   stays calm for the 90%-case; one click opens the advanced view. */
.pg-advanced {
  margin: 4px 0 4px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(255,255,255,0.015);
}
.pg-advanced > summary {
  list-style: none;
  cursor: pointer;
  padding: 10px 14px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  user-select: none;
  border-radius: 8px;
}
.pg-advanced > summary::-webkit-details-marker { display: none; }
.pg-advanced > summary::before {
  content: "▸";
  color: var(--text-dim);
  font-size: 10px;
  transition: transform 120ms;
  width: 12px;
}
.pg-advanced[open] > summary::before {
  transform: rotate(90deg);
}
.pg-advanced > summary:hover { background: rgba(255,255,255,0.025); }
.pg-advanced > .pg-row-2 {
  padding: 4px 14px 14px;
  grid-template-columns: 1fr 1fr;
}
.pg-advanced > .pg-advanced-body {
  padding: 8px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.pg-advanced-help {
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-muted);
  background: rgba(16,185,129,0.05);
  border: 1px solid rgba(16,185,129,0.15);
  border-radius: 6px;
  padding: 8px 10px;
}
.pg-advanced-help strong { color: var(--text); font-weight: 600; }

/* When the custom-provider section has a saved value (auto-opened
   on page load via JS), give it a faint emerald tint so the user
   sees it's active. */
.pg-llm-custom[open] > summary {
  background: rgba(16,185,129,0.05);
  border-radius: 8px 8px 0 0;
}
.pg-llm-custom[open] {
  border-color: rgba(16,185,129,0.25);
}

/* Inline link in the model selector hint — jumps to the custom
   provider disclosure when the user wants to point at a proxy. */
/* Vercel link pattern — text inherits foreground, underline on hover. */
.pg-link-inline {
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
}
.pg-link-inline:hover {
  color: var(--text);
  text-decoration: underline;
}

/* Inline geo-mismatch warning — appears when the task text strongly
   implies a country that doesn't match the Egress region selector.
   Stops users from running OpenTable/Amazon tasks through Hetzner DE. */
.pg-geo-warn {
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.55;
  color: #fbbf24;
  background: rgba(245,158,11,0.08);
  border: 1px solid rgba(245,158,11,0.3);
  border-radius: 6px;
  padding: 8px 10px;
}
.pg-geo-warn a {
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
  margin-left: 6px;
}
.pg-geo-warn a:hover { text-decoration: underline; color: var(--text); }

/* Inline action button rows (Playground: agt_live + Generate, etc.) */
.pg-input-row {
  display: flex; gap: 8px; align-items: stretch;
}
.pg-input-row input { flex: 1; }
.pg-inline-action {
  white-space: nowrap;
  font-size: 13px;
  padding: 0 14px;
}

/* Task templates */
.pg-templates {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 4px 0 8px;
}
.pg-tpl {
  font-family: inherit;
  background: var(--navy-800);
  color: var(--text-muted);
  border: 1px solid var(--border);
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 120ms;
  white-space: nowrap;
}
.pg-tpl:hover {
  color: var(--text);
  border-color: var(--vercel-border-strong);
  background: var(--vercel-elevated);
}

/* Team invite form — email field grows, button stays compact. */
.team-invite-form {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
}
.team-invite-form .pg-field { margin-bottom: 0; }

/* Flagship template — the cross-retailer price-compare. Marketed
   above the rest because it's the demo that no competitor can run
   end-to-end (5 distinct bot walls in one task). Distinction is
   carried by ⚡ icon + emerald border + bold weight; no background
   fill so it can't be confused with the .active "selected" state.
   QA re-verify 2026-06-08 — previously a gradient background made
   the flagship LOOK selected even when another chip was active. */
/* Flagship base — neutral chip with a slight foreground lift; the ⚡
   icon does the "this is special" work, not the color. Active state
   below adopts Vercel's white-on-black inversion. */
.pg-tpl.flagship {
  background: var(--vercel-surface);
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
  border-color: transparent;
  color: var(--text);
  font-weight: 500;
}
.pg-tpl.flagship:hover {
  background: var(--vercel-elevated);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
}

/* Active chip — inverted (white-on-black) so it reads as the selected
   one without burning the brand emerald. Matches the primary-CTA
   color discipline. */
.pg-tpl.active,
.pg-tpl.flagship.active {
  background: var(--vercel-text);    /* #ededed */
  color: var(--vercel-bg);           /* #000 */
  border-color: var(--vercel-text);
  box-shadow: none;
  font-weight: 500;
}

/* Hide step counter when idle to reduce visual noise. */
.playground:has(.pg-status.idle) .pg-step { display: none; }

/* Running-state summary (Hyperbrowser pattern) — replaces the form
   when a task is queued/running/completed/failed so the user sees a
   stable, read-only view of the config their agent is operating on. */
.pg-summary {
  display: flex; flex-direction: column; gap: 18px;
}
.pg-summary-row { display: flex; flex-direction: column; gap: 6px; }
.pg-summary-label {
  font-size: 11.5px; font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em;
}
.pg-summary-task {
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
  white-space: pre-wrap; word-break: break-word;
}
.pg-summary-id {
  display: flex; align-items: center; gap: 8px;
}
.pg-summary-id code {
  font-family: var(--font-mono);
  font-size: 13px; color: var(--text);
  background: var(--navy-800); border: 1px solid var(--border);
  padding: 6px 10px; border-radius: 6px;
  flex: 1; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.pg-copy-btn {
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--navy-800);
  border: 1px solid var(--border);
  color: var(--text-muted);
  border-radius: 6px; cursor: pointer;
  font-size: 13px; font-family: inherit;
  text-decoration: none;
  transition: color 120ms, border-color 120ms;
}
.pg-copy-btn:hover { color: var(--text); border-color: var(--vercel-border-strong); }

.pg-summary-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
}
.pg-summary-value {
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13.5px;
  color: var(--text);
  font-family: var(--font-mono);
}
.pg-summary-actions {
  display: flex; gap: 10px; margin-top: 4px;
}

/* Anti-detect fingerprint panel — visible during a task run after
   the burner is provisioned. Reuses .pg-summary-value styling for
   the cells so it looks like a sibling of the existing summary
   grid, but has its own emerald-tinted header to call out that
   THIS is the platform's real differentiator. */
.pg-fingerprint {
  margin-top: 10px;
  border: 1px solid rgba(16, 185, 129, 0.25);
  background: linear-gradient(180deg, rgba(16,185,129,0.04), transparent 70%);
  border-radius: 10px;
  padding: 12px 14px;
}
.pg-fp-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 600;
  color: var(--text);
  letter-spacing: 0.02em;
  margin-bottom: 10px;
}
.pg-fp-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  font-family: var(--font-mono); font-size: 12px;
  color: var(--emerald);
}
.pg-fp-link {
  margin-left: auto;
  font-size: 12px;
  color: var(--emerald-2);
  text-decoration: none;
  padding: 2px 8px;
  border: 1px solid rgba(16, 185, 129, 0.25);
  border-radius: 999px;
  transition: background 120ms;
}
.pg-fp-link:hover {
  background: rgba(16, 185, 129, 0.12);
  color: var(--emerald);
}
.pg-fp-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
}
@media (max-width: 880px) {
  .pg-fp-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Trust-score color bands. Thresholds match server-side
   trust_score.go: ≥850 OK, ≥700 suspicious, <700 flagged. */
.pg-fp-trust {
  font-weight: 700;
  font-size: 18px;
  font-family: var(--font-mono);
  line-height: 1.2;
}
.pg-fp-trust.ok   { color: var(--emerald-2); }
.pg-fp-trust.warn { color: #fbbf24; }
.pg-fp-trust.bad  { color: #f87171; }
.pg-fp-trust-label {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 11px;
  color: var(--text-dim);
  /* Render on its own line so it doesn't wrap mid-cell */
  display: block;
  margin-top: 1px;
}
.pg-fp-id code {
  font-size: 11.5px;
  color: var(--text-muted);
  background: transparent;
  padding: 0;
}

/* Stronger Stop button — red when actually running, calmer otherwise. */
.btn-danger {
  background: #ef4444;
  color: white;
  border: 1px solid #ef4444;
  font-family: inherit; font-weight: 600; font-size: 14px;
  padding: 10px 18px;
  border-radius: 8px; cursor: pointer;
  transition: background 120ms, transform 120ms;
}
.btn-danger:hover { background: #dc2626; transform: translateY(-1px); }
.btn-danger:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.pg-actions { display: flex; gap: 10px; align-items: center; margin-top: 4px; }
.pg-link {
  color: var(--text-muted); font-size: 12.5px; text-decoration: none;
  padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border);
}
.pg-link:hover { color: var(--text); border-color: var(--vercel-border-strong); }
.pg-error {
  background: rgba(239,68,68,0.08);
  border: 1px solid rgba(239,68,68,0.3);
  color: #fca5a5;
  padding: 10px 12px; border-radius: 8px;
  font-size: 13px;
}

.pg-preview {
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 12px;
  display: flex; flex-direction: column;
  overflow: hidden;
  min-height: 360px;
}
.pg-preview-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 12px; color: var(--text-muted); font-weight: 500;
}
.pg-step { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-dim); }
.pg-preview-body {
  flex: 1; min-height: 320px;
  position: relative;
  background: var(--navy-900);
}
.pg-preview-body iframe {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; background: white;
}
.pg-preview-empty {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 12px;
  color: var(--text-dim); font-size: 13px;
  padding: 32px 24px;
  text-align: center;
}
.pg-preview-icon {
  font-size: 28px; opacity: 0.55;
  font-family: var(--font-mono);
  color: var(--emerald);
  width: 48px; height: 48px;
  border-radius: 50%;
  background: var(--emerald-glow);
  display: flex; align-items: center; justify-content: center;
}
.pg-preview-empty-title {
  font-size: 15px; font-weight: 600; color: var(--text);
  margin-bottom: 4px;
}
.pg-preview-bullets {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 6px;
  text-align: left;
  font-size: 12.5px;
  color: var(--text-muted);
  max-width: 360px;
}
.pg-preview-bullets li {
  display: flex; gap: 8px;
  line-height: 1.45;
}
.pg-preview-bullets li::before {
  content: "✓";
  color: var(--emerald);
  font-weight: 700;
  flex-shrink: 0;
}
.pg-result {
  padding: 14px 16px;
  border-top: 1px solid var(--border);
  background: var(--navy-900);
  max-height: 320px; overflow: auto;
  position: relative;
}
.pg-result::before {
  content: "RESULT";
  display: block;
  font-size: 10.5px; font-weight: 700;
  color: var(--emerald);
  letter-spacing: 0.08em;
  margin-bottom: 8px;
}
.pg-result pre {
  font-family: var(--font-mono); font-size: 12px;
  line-height: 1.55; white-space: pre-wrap; word-break: break-word;
  color: var(--text);
}

/* Loading shimmer */
.skel {
  background: linear-gradient(90deg, var(--navy-600) 0%, var(--navy-500) 50%, var(--navy-600) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.5s linear infinite;
  border-radius: 6px;
  height: 16px;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Key list */
.key-list { display: flex; flex-direction: column; gap: 10px; }
.key-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 14px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.key-meta { flex: 1; min-width: 0; }
.key-name { font-weight: 600; font-size: 14px; }
.key-prefix { font-family: var(--font-mono); font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.key-dates { font-size: 12px; color: var(--text-dim); white-space: nowrap; }

/* Revoked-keys history. Collapsible <details> below the active
   key list — the row visually de-emphasizes (faded) and shows a
   "revoked" pill where the active row had a Revoke button. */
.revoked-keys {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
}
.revoked-keys > summary {
  list-style: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 4px 0 10px;
  user-select: none;
  display: flex; align-items: center; gap: 8px;
}
.revoked-keys > summary::-webkit-details-marker { display: none; }
.revoked-keys > summary::before {
  content: "▸";
  color: var(--text-dim);
  font-size: 10px;
  transition: transform 120ms;
  width: 12px;
}
.revoked-keys[open] > summary::before { transform: rotate(90deg); }
.revoked-keys > summary:hover { color: var(--text); }
.key-row.revoked {
  opacity: 0.6;
  background: transparent;
  border-style: dashed;
}
.key-row.revoked .key-name,
.key-row.revoked .key-prefix {
  text-decoration: line-through;
  text-decoration-color: var(--text-dim);
  text-decoration-thickness: 1px;
}
.key-row .pill.bad {
  background: rgba(248, 113, 113, 0.12);
  color: #f87171;
  border: 1px solid rgba(248, 113, 113, 0.25);
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Minted-key banner */
.minted {
  background: var(--emerald-glow);
  border: 1px solid rgba(16, 185, 129, 0.35);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.minted-label {
  display: flex; align-items: center; gap: 6px;
  color: var(--emerald-2);
  font-weight: 600;
  font-size: 14px;
}
.minted-key {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
}
.minted-key code {
  flex: 1;
  font-size: 13px;
  background: transparent;
  border: none;
  padding: 0;
  word-break: break-all;
}
.minted-actions { display: flex; gap: 8px; }

/* Mint form */
.mint-form {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  align-items: stretch;
}
.mint-form input {
  flex: 1;
  font-family: inherit;
  background: var(--navy-800);
  border: 1px solid var(--border-light);
  color: var(--text);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14px;
}
.mint-form input:focus {
  outline: none;
  border-color: var(--vercel-text);
  box-shadow: var(--vercel-focus);
}

/* Quick actions row */
.quick-links {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.quick-links a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: 6px;
}
.quick-links a:hover { color: var(--text); background: var(--vercel-elevated); }

/* Balance */
.balance {
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
}
.balance .unit {
  color: var(--text-muted);
  font-weight: 500;
  font-size: 13px;
  margin-left: 4px;
}

/* Credit ledger ("Recent activity") */
.ledger {
  margin-top: 20px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
}
.ledger > summary {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  list-style: none;
  padding: 4px 0;
}
.ledger > summary::-webkit-details-marker { display: none; }
.ledger > summary::before {
  content: "+ ";
  color: var(--text-dim);
  font-weight: 400;
}
.ledger[open] > summary::before { content: "− "; }
.ledger-table {
  margin-top: 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.ledger-head, .ledger-row {
  display: grid;
  grid-template-columns: 140px 1fr 80px 90px;
  gap: 12px;
  padding: 8px 12px;
  font-size: 12.5px;
}
.ledger-head {
  background: var(--navy-900);
  color: var(--text-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-size: 11px;
  border-bottom: 1px solid var(--border);
}
.ledger-row + .ledger-row { border-top: 1px solid var(--border); }
.ledger-row { color: var(--text); }
.ledger-row .right { text-align: right; }
.ledger-row .dim { color: var(--text-dim); }
.ledger-row .pos { color: #50e3c2; font-weight: 600; }  /* Vercel ready-cyan, not brand emerald */
.ledger-row .neg { color: var(--red); font-weight: 600; }
.ledger-sub {
  font-size: 11px; color: var(--text-dim);
  font-family: var(--font-mono);
  margin-top: 2px;
}
@media (max-width: 720px) {
  .ledger-head, .ledger-row {
    grid-template-columns: 100px 1fr 60px 70px;
    font-size: 11.5px;
    padding: 8px;
  }
}

/* Pack grid */
.pack-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
}
.pack {
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
}
.pack-label { font-weight: 600; font-size: 14px; }
.pack-meta { color: var(--text-muted); font-size: 13px; margin: 4px 0 12px; }

/* Signing-secret block */
.secret-block {
  margin-top: 16px;
  padding: 14px 16px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.secret-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
}
.secret-label {
  display: flex; flex-direction: column; gap: 2px;
  min-width: 180px;
}
.secret-label > span:first-child {
  font-size: 13px; font-weight: 600; color: var(--text);
}
.secret-label .hint {
  font-size: 11.5px; color: var(--text-dim);
}
.secret-label code {
  background: transparent; border: 0; padding: 0; color: inherit;
  font-family: var(--font-mono); font-size: 11px;
}
.secret-value {
  display: flex; align-items: center; gap: 6px; flex: 1; min-width: 280px;
}
.secret-input {
  flex: 1;
  font-family: var(--font-mono); font-size: 12px;
  background: var(--navy-900);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 7px 10px;
  width: 100%;
}
.secret-snippet { margin-top: 12px; }
.secret-snippet summary {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  cursor: pointer; list-style: none;
  padding: 4px 0;
}
.secret-snippet summary::-webkit-details-marker { display: none; }
.secret-snippet summary::before {
  content: "+ "; color: var(--text-dim);
}
.secret-snippet[open] summary::before { content: "− "; }
.secret-snippet pre {
  margin-top: 8px;
  background: var(--navy-900);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text);
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Account section */
.acct-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 24px;
  align-items: start;
  margin-bottom: 20px;
}
@media (max-width: 880px) {
  .acct-grid { grid-template-columns: 1fr; }
}
.acct-info { display: flex; flex-direction: column; gap: 10px; }
.acct-row {
  display: grid; grid-template-columns: 130px 1fr; gap: 10px; align-items: center;
}
.acct-label {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.acct-value {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; color: var(--text);
}
.acct-value.mono code {
  font-family: var(--font-mono); font-size: 12.5px;
  background: var(--navy-800); border: 1px solid var(--border);
  padding: 4px 8px; border-radius: 6px;
}
.acct-actions {
  display: flex; flex-direction: column; gap: 8px; min-width: 200px;
}
.acct-actions .btn-secondary { text-align: center; text-decoration: none; }
.acct-pw {
  border-top: 1px solid var(--border);
  padding-top: 16px;
  margin-top: 8px;
}
.acct-pw > summary {
  font-size: 14px; font-weight: 600; color: var(--text);
  cursor: pointer; list-style: none; padding: 6px 0;
}
.acct-pw > summary::-webkit-details-marker { display: none; }
.acct-pw > summary::before {
  content: "+ "; color: var(--text-dim); font-weight: 400;
}
.acct-pw[open] > summary::before { content: "− "; }
.acct-pw-form {
  display: flex; flex-direction: column; gap: 12px;
  margin-top: 12px;
  max-width: 420px;
}
/* Legacy .pill.ok rule REMOVED — was emerald glow. New Vercel-aligned
   rules live at the bottom of the file with the Geist palette
   (cyan #50e3c2 for ready) and supersede this. */

/* Webhook list */
.webhook-list { display: flex; flex-direction: column; gap: 10px; }
.webhook-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.webhook-meta { flex: 1; min-width: 0; }
.webhook-url {
  font-weight: 600;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.webhook-events { display: flex; gap: 5px; margin-top: 4px; flex-wrap: wrap; }
.chip {
  background: var(--navy-700);
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
}
.webhook-status { font-size: 12px; color: var(--text-dim); }

/* Jobs table */
.jobs-table {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.thead, .trow {
  display: grid;
  grid-template-columns: 120px 90px 110px 90px 80px 70px 1fr 150px;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
}
.col-trust { font-size: 12px; }
.trow .col-trust .trow-trust {
  font-family: var(--font-mono);
  color: var(--text-dim);
}

/* Identities view filter pills — same shape as the mobile-nav pill
   bar but inline in the card head. */
.ident-filter {
  display: flex; gap: 6px; align-items: center;
}
.ident-pill {
  background: var(--navy-700);
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 6px 12px;
  border-radius: 999px;
  font-family: inherit;
  font-size: 12.5px; font-weight: 500;
  cursor: pointer;
  transition: background 120ms, color 120ms, border-color 120ms;
}
.ident-pill:hover { color: var(--text); }
.ident-pill.active {
  /* Vercel segmented-control active state — inverted (white-on-black). */
  background: var(--vercel-text);
  color: var(--vercel-bg);
  border-color: var(--vercel-text);
  font-weight: 500;
}
.thead {
  background: var(--navy-800);
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  font-weight: 600;
}
.trow + .trow { border-top: 1px solid var(--border); }
.trow { cursor: pointer; }
.trow:hover { background: var(--navy-800); }
.trow.active { background: var(--navy-800); border-left: 3px solid var(--emerald); padding-left: 11px; }
.trow .mono { font-family: var(--font-mono); font-size: 12px; }
.trow .actions { display: flex; gap: 4px; justify-content: flex-end; }

/* Job drawer: opens below the table when a row is clicked. */
.card-drawer {
  margin: 0 22px 20px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.card-drawer-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.card-drawer-head > div {
  display: flex; align-items: center; gap: 10px;
}
.card-drawer-head .mono { font-size: 12px; color: var(--text-muted); }
.card-drawer-body { padding: 14px; }
.card-drawer-body .kv {
  display: grid; grid-template-columns: 110px 1fr; gap: 6px 14px;
  font-size: 13px;
  margin-bottom: 12px;
}
.card-drawer-body .kv .k { color: var(--text-muted); }
.card-drawer-body .kv .v { color: var(--text); word-break: break-word; }
.card-drawer-body .kv .v.dim { color: var(--text-muted); }
.card-drawer-body pre {
  font-family: var(--font-mono); font-size: 11.5px; line-height: 1.5;
  background: var(--navy-900);
  padding: 12px; border-radius: 8px;
  max-height: 360px; overflow: auto;
  white-space: pre-wrap; word-break: break-word;
}
.card-drawer-body .drawer-section {
  margin-top: 12px;
}
.card-drawer-body .drawer-section h4 {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em;
  margin-bottom: 6px;
}
.trow .actions button {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  padding: 3px 8px;
  border-radius: 5px;
  font-size: 11px;
  cursor: pointer;
  font-family: inherit;
}
.trow .actions button:hover { color: var(--text); border-color: var(--vercel-border-strong); }
.trow .actions a {
  color: var(--emerald);
  text-decoration: none;
  font-size: 11px;
  border: 1px solid var(--border);
  padding: 3px 8px;
  border-radius: 5px;
}

/* Status pill base — the comprehensive .pill.* color variants live
   near the bottom of the file (Vercel-aligned Geist palette: cyan
   ready, amber building, red error, muted idle). Only base shape
   declared here. The legacy emerald `.pill.completed` rule has
   been removed; .completed now resolves through the cyan "ready"
   variant via the bottom-of-file rule. */
.pill {
  /* shape only — colors come from .pill.ok/.warn/.bad/.idle at EOF */
}
/* Map run-state class names onto the canonical Vercel-aligned set
   so the existing JS that emits class="pill running" etc. keeps
   working without code changes. */
.pill.running   { color: #f5a623; background: rgba(245, 166, 35, 0.08); border: 1px solid rgba(245, 166, 35, 0.24); }
.pill.completed { color: #50e3c2; background: rgba(80, 227, 194, 0.08); border: 1px solid rgba(80, 227, 194, 0.24); }
.pill.queued    { color: var(--text-muted); background: var(--vercel-elevated); border: 1px solid var(--vercel-border-strong); }

/* Empty state — Vercel pattern. Lifted surface (#1a1a1a) matches
   the card hierarchy, solid hairline replaces the prior dashed
   border (dashed read as "construction zone" not as a friendly
   empty), generous vertical padding gives the content room to
   breathe. Icon block accepts either an inline SVG (preferred,
   styles below) or the legacy unicode glyph. */
.empty {
  text-align: center;
  padding: 56px 24px;
  color: var(--text-muted);
  background: var(--vercel-elevated);
  border: none;
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  border-radius: var(--radius);
}
.empty-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  margin: 0 auto 14px;
  border-radius: 10px;
  background: var(--vercel-hover);
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  color: var(--text-muted);
  font-size: 22px;
}
.empty-icon svg { width: 22px; height: 22px; stroke-width: 1.5; }
.empty h3 {
  font-size: 15px; font-weight: 600;
  color: var(--vercel-text);
  margin: 0 0 6px;
  letter-spacing: -0.005em;
}
.empty p {
  font-size: 13.5px; line-height: 1.6;
  max-width: 360px;
  margin: 0 auto 18px;
  color: var(--text-muted);
}
.empty pre {
  text-align: left;
  background: var(--navy-900);
  color: var(--text);
  padding: 12px 14px;
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  margin-top: 14px;
  overflow-x: auto;
}
/* Empty-state docs link — was inheriting browser-default dark blue
   which sat under the WCAG AA threshold against navy-700/800.
   Use emerald-2 (already meets contrast) so the call-to-docs is
   readable. QA 2026-06-08 (Identities view). */
.empty a,
.empty p a {
  /* Vercel link pattern in empty-states: foreground text + underline. */
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.empty a:hover { color: var(--text); }

/* Dashboard footer */
.dash-footer {
  margin-top: 32px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}
.dash-footer a {
  color: var(--text-muted);
  text-decoration: none;
}
.dash-footer a:hover { color: var(--text); }

/* Toasts */
.toasts {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.toast {
  background: var(--navy-700);
  border: 1px solid var(--border-light);
  color: var(--text);
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 14px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  animation: toast-in 200ms ease-out;
}
.toast.ok { border-left: 3px solid var(--emerald); }
.toast.err { border-left: 3px solid var(--red); }
@keyframes toast-in {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

/* Responsive */
/* Intermediate breakpoint — the dashboard sidebar steals ~220px of
   horizontal real estate, so the 8-column jobs grid overflows from
   ~1100px down until the existing 720px override fires. Without this
   middle step the table introduced horizontal scroll on every common
   laptop width. UX audit 2026-06-08. Drops the lower-priority columns
   (credits + trust) early; the higher-info columns (job id, status,
   age, actions) keep their full layout. */
@media (max-width: 1100px) and (min-width: 721px) {
  .thead, .trow {
    grid-template-columns: 110px 80px 100px 80px 1fr 140px;
  }
  .thead .col-credits, .trow .col-credits { display: none; }
  .thead .col-trust,   .trow .col-trust   { display: none; }
}

@media (max-width: 720px) {
  .thead, .trow {
    grid-template-columns: 90px 70px 90px 70px 1fr 110px;
    gap: 8px;
    font-size: 12px;
    padding: 8px 10px;
  }
  .thead .col-credits, .trow .col-credits { display: none; }
  .thead .col-trust,   .trow .col-trust   { display: none; }
  .mint-form { flex-direction: column; }
  .auth-card { padding: 24px; }
}

/* Small-mobile header + playground summary tweaks. Pre-fix h1 sat at
   26px on a 16px-padded viewport — on 320px screens that's ~80% of
   the available row width and the subtitle wrapped to 4 lines.
   Playground summary grid stayed 3-column on phones, cramming LLM /
   Max steps / Steps taken into <120px each. UX audit 2026-06-08. */
@media (max-width: 560px) {
  .dash-header h1 { font-size: 20px; }
  .dash-header p  { font-size: 12.5px; }
  .pg-summary-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 380px) {
  .pg-summary-grid { grid-template-columns: 1fr; }
}

/* ---------- Multi-view dashboard (sub-routes) ----------
   Each .dash-view is a "page" shown when its data-view matches the
   active sidebar item. The global [hidden] rule already takes care
   of suppressing the non-active ones; this block adds the Overview
   quick-actions grid so the landing view has real content instead
   of just the metrics row. */
.dash-view { display: block; }

.quick-actions {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 24px;
}
@media (max-width: 1100px) {
  .quick-actions { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .quick-actions { grid-template-columns: 1fr; }
}
.qa-card {
  background: var(--vercel-elevated);
  border: none;
  box-shadow: inset 0 0 0 1px var(--vercel-border);
  border-radius: var(--radius);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s ease, background 0.15s ease, transform 0.15s ease;
}
.qa-card:hover {
  box-shadow: inset 0 0 0 1px var(--vercel-border-strong);
  background: var(--vercel-elevated);
  transform: translateY(-1px);
}
.qa-ico {
  /* Vercel quick-action icon — neutral tinted tile, not emerald wash.
     Icon glyph picks up muted-foreground so the title carries the
     hierarchical weight, not the icon color. */
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--vercel-elevated);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 14px;
}
.qa-title {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
}
.qa-sub {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.4;
}
.qa-sub code {
  font-size: 12px;
  background: rgba(255,255,255,0.04);
  padding: 1px 5px;
  border-radius: 4px;
}

/* Playground toolbar — replaces the redundant card-head title.
   The page-level header (h1 + subtitle from VIEW_META) already names
   the view; the card just needs the status pill and nothing else. */
.pg-toolbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 14px 22px 0;
}

/* ============ PLAYGROUND IMPROVEMENTS ============ */

/* Visual model selector — replaces the boring LLM <select>.
   Horizontally scrollable so all 5 buttons fit on narrow viewports. */
.pg-model-selector {
  display: flex;
  gap: 7px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.pg-model-selector::-webkit-scrollbar { display: none; }
.pg-model-btn {
  flex: 0 0 auto;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 13px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: border-color 120ms, background 120ms;
  min-width: 100px;
}
.pg-model-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.pg-model-sub {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 2px;
  white-space: nowrap;
}
.pg-model-btn:hover {
  border-color: var(--vercel-border-strong);
  background: var(--vercel-elevated);
}
.pg-model-btn.active {
  /* Vercel inversion — selected model reads as the inverted CTA color
     so it can't be confused with brand emerald. Same pattern as
     .pg-tpl.active and .ident-pill.active. */
  border-color: var(--vercel-text);
  background: var(--vercel-text);
}
.pg-model-btn.active .pg-model-name { color: var(--vercel-bg); }
.pg-model-btn.active .pg-model-sub { color: rgba(0,0,0,0.7); opacity: 1; }

/* Visual separator between task/model section and credentials. */
.pg-divider {
  height: 1px;
  background: var(--border);
  margin: 2px 0;
}

/* ─── Redesigned Playground (2026-06-10) ──────────────────────────────
   Goals:
   - Task is the hero, not a label squeezed between a chip-grid and a
     model picker. Bigger, framed, more breathing room.
   - Secondary knobs (steps / egress / OS) live on ONE horizontal row.
   - Credentials in their own paired row — same density.
   - Cost estimate next to Run so customers see what they're about to
     spend.
   - Tighter overall vertical rhythm — fits on a 13" laptop without
     scrolling, used to spill below the fold.
*/

/* Templates strip — one horizontal scroll line, quieter than the
   wrapping grid which used to fight the textarea for attention. */
.pg-templates-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
}
.pg-templates-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  position: relative;
}
.pg-templates-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .07em;
}

/* Recent tasks menu — appears next to the templates label once the
   user has run at least one task. Stores the last 6 prompts in
   localStorage so reload-and-tweak is one click. */
.pg-recent-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  transition: border-color 120ms, color 120ms;
}
.pg-recent-btn:hover {
  border-color: var(--vercel-border-strong);
  color: var(--text);
}
.pg-recent-count {
  background: var(--navy-700);
  color: var(--text);
  padding: 0 6px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 600;
  min-width: 16px;
  text-align: center;
}
.pg-recent-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  background: var(--navy-800);
  border: 1px solid var(--border-light);
  border-radius: 10px;
  padding: 6px;
  min-width: 320px;
  max-width: 480px;
  z-index: 60;
  box-shadow: 0 12px 32px rgba(0,0,0,0.45);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.pg-recent-item {
  background: transparent;
  border: 0;
  border-radius: 6px;
  padding: 8px 10px;
  text-align: left;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  transition: background 120ms;
}
.pg-recent-item:hover { background: var(--vercel-elevated); }
.pg-recent-item .pg-recent-time {
  font-size: 10.5px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.pg-recent-item .pg-recent-preview {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pg-recent-empty {
  padding: 12px;
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
}

/* Keyboard hint inside the Run task button — small subtle chip on
   the right of the label. Visible at all times so the shortcut is
   discoverable without hovering. */
.pg-kbd-hint {
  display: inline-block;
  margin-left: 10px;
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 500;
  padding: 1.5px 6px;
  border-radius: 4px;
  background: rgba(0,0,0,0.15);
  color: rgba(0,0,0,0.5);
  letter-spacing: .04em;
}
.btn-primary:hover .pg-kbd-hint { color: rgba(0,0,0,0.7); }
.btn-primary:disabled .pg-kbd-hint { opacity: 0.6; }
.pg-templates {
  /* Override the old wrap behavior — keep it one row, scroll
     horizontally when the chips overflow. Hide the scrollbar
     because the user navigates by clicking, not scrolling.   */
  flex-wrap: nowrap !important;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
  margin: 0;
  /* Fade the right edge so a partially-clipped chip clearly
     reads as "scroll for more" instead of a layout bug. The
     CSS audit 2026-06-10 flagged "X Tw…" as looking broken. */
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
  mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
}
.pg-templates::-webkit-scrollbar { display: none; }

/* Task hero — frames the textarea so it's visually unmissable. The
   textarea itself keeps the existing .pg-field input styling for
   focus state. */
.pg-hero {
  background: var(--navy-800);
  border: 1px solid var(--border-light);
  border-radius: 10px;
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 8px;
  transition: border-color 120ms;
}
.pg-hero:focus-within {
  border-color: var(--vercel-border-strong);
}
.pg-hero-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .07em;
}
.pg-hero textarea {
  background: transparent !important;
  border: 0 !important;
  padding: 0 !important;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
  resize: vertical;
  min-height: 110px;
  outline: none;
}
.pg-hero textarea::placeholder {
  color: var(--text-dim);
  opacity: 1;
}

/* Flat field — no big gap, smaller label. Used everywhere except the
   task hero. */
.pg-field-flat { gap: 4px; }
.pg-mini-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .07em;
  display: flex; align-items: center; gap: 8px;
}
.pg-mini-label .pg-hint {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}
.pg-tag-mini {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 4px;
  background: rgba(16,185,129,0.10);
  color: var(--emerald-2);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
}
.pg-mini-link {
  margin-left: auto;
  background: transparent;
  border: 0;
  padding: 0;
  color: var(--emerald-2);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
  font-size: 11px;
  cursor: pointer;
  font-family: inherit;
}
.pg-mini-link:hover { color: var(--text); }

/* Compact horizontal config row — Egress / Max steps / OS fingerprint
   on one line. Collapses to stacked at narrow widths. */
.pg-config-strip {
  display: grid;
  grid-template-columns: minmax(0, 2.2fr) minmax(0, 1fr) minmax(0, 1.3fr);
  gap: 12px;
}
@media (max-width: 720px) {
  .pg-config-strip { grid-template-columns: 1fr; }
}

/* Credentials pair — LLM key + Agents key side-by-side. Two columns
   that collapse to one on narrow widths. */
.pg-creds {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 720px) {
  .pg-creds { grid-template-columns: 1fr; }
}

/* Run area — cost estimate sits next to the primary CTA. */
.pg-run-area {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 4px;
  padding: 10px 14px;
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 10px;
}
@media (max-width: 720px) {
  .pg-run-area { flex-direction: column; align-items: stretch; }
}
.pg-cost-estimate {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.pg-cost-line {
  display: flex; gap: 8px; align-items: baseline;
  font-size: 12px;
}
.pg-cost-label {
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: 10.5px;
  font-weight: 600;
  min-width: 96px;
}
.pg-cost-val { color: var(--text); font-weight: 500; }

/* Run area button alignment override — keep the primary CTA right-
   aligned and at a comfortable size against the cost estimate. */
.pg-run-area .pg-actions {
  margin-top: 0;
  flex-shrink: 0;
}
.pg-run-area .btn-primary {
  padding: 0 22px;
  height: 38px;
  font-size: 14px;
}

/* Extra empty-state copy below the bullets. */
.pg-preview-empty-sub {
  font-size: 12.5px;
  color: var(--text-dim);
  max-width: 360px;
  margin-bottom: 8px;
}
.pg-preview-tips {
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
  max-width: 360px;
  width: 100%;
}
.pg-preview-tips-head {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--text-muted);
  margin-bottom: 8px;
  text-align: left;
}
.pg-preview-tips-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 6px;
  text-align: left;
  font-size: 12px;
  color: var(--text-dim);
}
.pg-preview-tips-list li {
  display: flex; gap: 8px;
  line-height: 1.45;
}
.pg-preview-tips-list li::before {
  content: "·";
  color: var(--text-muted);
  font-weight: 700;
  flex-shrink: 0;
}

/* Browser chrome bar above the live preview iframe.
   Traffic-light dots + pill address bar make the preview look like
   a real desktop browser — reinforces that this is a real Chromium
   session, not a headless API call. */
.pg-preview-chrome {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--navy-900);
  flex-shrink: 0;
}
.pg-chrome-dots {
  display: flex;
  gap: 5px;
  flex-shrink: 0;
}
.pg-chrome-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.pg-chrome-dot:nth-child(1) { background: #ff5f57; opacity: 0.65; }
.pg-chrome-dot:nth-child(2) { background: #ffbd2e; opacity: 0.65; }
.pg-chrome-dot:nth-child(3) { background: #28c940; opacity: 0.65; }
.pg-chrome-bar {
  flex: 1;
  background: var(--navy-700);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 4px 14px;
  font-size: 11.5px;
  font-family: var(--font-mono);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  transition: color 200ms, background 200ms;
}
.pg-chrome-bar.live {
  color: var(--emerald-2);
  background: rgba(16,185,129,0.05);
  border-color: rgba(16,185,129,0.3);
}
.pg-chrome-bar.done { color: var(--emerald-2); }
.pg-chrome-bar.err  { color: #fca5a5; }

/* Live-session iframe overlay — sits on top of the embedded stream
   iframe and fades out once the iframe finishes its first load.
   Avoids the ~1s blank-white-flash while the Angular SPA boots
   inside the frame. */
.pg-live-overlay {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 14px;
  background: var(--navy-900);
  transition: opacity 350ms ease-out;
  pointer-events: none;
}
.pg-live-pulse {
  width: 52px; height: 52px;
  border-radius: 50%;
  background: rgba(16,185,129,0.1);
  border: 2px solid var(--emerald);
  animation: live-pulse 2s ease-in-out infinite;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.pg-live-pulse::after {
  content: '';
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--emerald);
}
@keyframes live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(16,185,129,0.35); }
  50%       { box-shadow: 0 0 0 14px rgba(16,185,129,0); }
}
.pg-live-label {
  font-size: 14px; font-weight: 600; color: var(--text);
}

/* Terminal-state icon shown in the preview after a task completes
   or fails. Replaces the live noVNC pulse with a static, color-coded
   check / X so the iframe area doesn't sit on "Failed to connect"
   from the dead noVNC client. */
.pg-done-icon {
  width: 56px; height: 56px;
  border-radius: 50%;
  font-size: 28px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.pg-done-icon.ok  { background: rgba(16,185,129,0.15); color: var(--emerald-2);
                    border: 2px solid rgba(16,185,129,0.4); }
.pg-done-icon.err { background: rgba(239,68,68,0.12);  color: #fca5a5;
                    border: 2px solid rgba(239,68,68,0.4); }

/* Pop-out button — floats top-right of the iframe so power users
   can pop the live view into a full tab without scrolling. */
.pg-live-popout {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(15,23,41,0.75);
  border: 1px solid var(--border-light);
  color: var(--text);
  border-radius: 6px;
  text-decoration: none;
  font-size: 14px; font-weight: 700;
  backdrop-filter: blur(8px);
  transition: background 120ms, color 120ms, border-color 120ms;
}
.pg-live-popout:hover {
  background: var(--emerald);
  color: var(--navy-900);
  border-color: var(--emerald);
}

/* Step counter moves into the chrome bar row */
.pg-preview-chrome .pg-step {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  white-space: nowrap;
}

/* ─── Design overhaul 2026-06-08 ────────────────────────────────────
   Bottom-of-file shipped together by the design pass. Includes:
     (a) Status pill component (Vercel-style capsule + dot)
     (b) Monospace ID pill (Linear-style)
     (c) Row + button micro-transitions
     (d) Shimmer keyframe for skeleton loaders
   All ADDITIONS — no existing rules touched, so this layers on top
   without breaking the current visual tree. */

/* ── Status pills — capsule with leading colored dot.
   Reuse for run states (queued/running/succeeded/failed) and any
   semantic state we surface (active/disabled/expired). Border + bg
   are tinted with the accent's own hue so the pill carries meaning
   without screaming. */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 10px;
  border-radius: 9999px;
  font: 600 11px/1 var(--font-sans), system-ui, sans-serif;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
.pill::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex-shrink: 0;
}
/* Pill palette discipline (Vercel pattern):
   • .ready / .success / .completed — cyan #50e3c2 (Geist "Ready")
   • .ok (generic "this is fine" badge for static labels like a plan
     tier, role, or account-status) — NEUTRAL muted gray. Vercel uses
     gray badges for non-runtime labels; cyan is reserved for live
     deployment states. Using cyan on "Pay-as-you-go" / "OWNER" was
     making static labels read as runtime status indicators. */
.pill.ready,
.pill.success {
  color: #50e3c2;
  background: rgba(80, 227, 194, 0.08);
  border-color: rgba(80, 227, 194, 0.24);
}
.pill.ok {
  color: var(--text-muted);
  background: var(--vercel-elevated);
  border-color: var(--vercel-border-strong);
}
.pill.warn,
.pill.queued,
.pill.pending {
  color: #f5a623;
  background: rgba(245, 166, 35, 0.08);
  border-color: rgba(245, 166, 35, 0.24);
}
.pill.bad,
.pill.error,
.pill.failed {
  color: #ff4d4f;
  background: rgba(255, 77, 79, 0.08);
  border-color: rgba(255, 77, 79, 0.20);
}
.pill.idle,
.pill.neutral {
  color: var(--text-muted);
  background: var(--vercel-elevated);
  border-color: var(--vercel-border-strong);
}

/* ── Monospace ID pill — render UUIDs, job IDs, key prefixes, and
   webhook IDs in this style. Linear ships this for every `ENG-2703`
   reference; it's what makes a developer platform feel like one. */
.mono-pill,
code.mono-pill,
.id-pill {
  font-family: var(--font-mono), ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text-muted);
  background: var(--navy-800);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 2px 6px;
  white-space: nowrap;
  vertical-align: baseline;
}
.mono-pill:hover, .id-pill:hover { color: var(--text); border-color: var(--border-light); }

/* ── Micro-transitions baseline — buttons, links, table rows, and
   nav items pick up a 120ms ease on color/background so the app
   stops feeling static. No transform, no scale — just calm fades. */
.btn-primary, .btn-secondary, .btn-ghost, .btn-danger,
a.dash-nav-item, .dmn-item, .pg-tpl, .ident-pill,
button[data-test-hook], button[data-del-hook] {
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
/* Table-row hover bg lift — replaces the static-feeling default. */
.trow { transition: background-color 120ms ease; }
.trow:hover { background: var(--navy-700); }

/* ── Shimmer keyframe for skeleton loaders.
   Audit: current skeletons are flat gray bars — page visibly reflows
   when data arrives. This adds a 1.5s gradient sweep so loading
   reads as progress instead of broken. Apply via the .skel class
   that the JS skeleton helper already emits. */
@keyframes neoa-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}
.skel, .skeleton {
  position: relative;
  background: linear-gradient(
    90deg,
    var(--navy-800) 0%,
    var(--navy-700) 50%,
    var(--navy-800) 100%
  );
  background-size: 200% 100%;
  animation: neoa-shimmer 1.5s ease-in-out infinite;
  border-radius: 4px;
}

/* ─── Cmd-K command palette ────────────────────────────────────────────
   The stretch move from design audit 2026-06-08: "what makes a developer
   platform feel like a developer platform" — Linear's cmd-K plus monospace
   id treatment. Opens on ⌘K / Ctrl-K from any dashboard view; closes on
   esc / click-outside / command-select. Surfaces:
     • Jump-to-view  (Overview / Playground / Identities / Keys / …)
     • Quick actions (Mint a key, Register webhook, Buy credits)
     • UUID detection (paste a job id → "View job <id>")
     • Recent jobs (last 10, mono-pill styled) */
.cmdk-overlay {
  position: fixed; inset: 0;
  z-index: 10000;
  background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 14vh;
  animation: cmdk-fade-in 100ms ease-out;
}
@keyframes cmdk-fade-in { from { opacity: 0; } to { opacity: 1; } }
.cmdk-modal {
  width: min(640px, calc(100vw - 32px));
  background: var(--vercel-surface);
  box-shadow:
    inset 0 0 0 1px var(--vercel-border-strong),
    0 32px 64px rgba(0, 0, 0, 0.65);
  border-radius: 10px;
  overflow: hidden;
  display: flex; flex-direction: column;
  max-height: 70vh;
}
.cmdk-input-row {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--vercel-border);
}
.cmdk-prompt {
  font: 500 11px var(--font-mono);
  color: var(--text-muted);
  padding: 3px 6px;
  background: var(--vercel-elevated);
  border-radius: 4px;
  letter-spacing: 0.04em;
}
#cmdk-input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text);
  font: 400 15px/1.4 var(--font-sans);
  letter-spacing: -0.01em;
}
#cmdk-input::placeholder { color: var(--text-muted); }
.cmdk-list {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0;
}
.cmdk-section {
  font: 500 10.5px var(--font-sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 8px 16px 4px;
}
.cmdk-item {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 16px;
  cursor: pointer;
  color: var(--text);
  font: 400 14px/1.3 var(--font-sans);
  letter-spacing: -0.01em;
  user-select: none;
  border-left: 2px solid transparent;
}
.cmdk-item.active,
.cmdk-item:hover {
  background: var(--vercel-elevated);
  border-left-color: var(--text);
}
.cmdk-item-glyph {
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.cmdk-item-label { flex: 1; }
.cmdk-item-sub {
  color: var(--text-muted);
  font-size: 12.5px;
  font-family: var(--font-mono);
}
.cmdk-empty {
  padding: 16px;
  color: var(--text-muted);
  font-size: 13px;
  text-align: center;
}
.cmdk-footer {
  display: flex; gap: 14px;
  padding: 8px 16px;
  border-top: 1px solid var(--vercel-border);
  color: var(--text-muted);
  font-size: 11.5px;
}
.cmdk-footer kbd {
  font: 500 10px var(--font-mono);
  background: var(--vercel-elevated);
  border: 1px solid var(--vercel-border-strong);
  border-radius: 3px;
  padding: 1px 5px;
  margin-right: 4px;
  color: var(--text);
}

/* Mono ID pill helper for inline rendering of UUIDs / key prefixes /
   job ids anywhere in the dashboard. Linear ships this pattern for
   `ENG-2703` — we apply it to every UUID + agent_id + key prefix. */
.id-pill {
  display: inline-flex; align-items: center;
  font: 500 11.5px/1 var(--font-mono);
  background: var(--vercel-elevated);
  color: var(--text);
  padding: 3px 6px;
  border-radius: 4px;
  letter-spacing: -0.01em;
  vertical-align: baseline;
  cursor: copy;
  transition: background 120ms;
}
.id-pill:hover { background: var(--vercel-hover); }
.id-pill.copied { background: rgba(80, 227, 194, 0.15); color: #50e3c2; }
