/* ---------- themes ----------
   Dark is the default and lives on :root, so a page that never loads js/theme.js
   still renders. The other three only override the colours that differ; the
   radii, widths and fonts below are shared. --topbar-bg is separate from --bg
   because the bar is translucent and needs an alpha the flat colour cannot give.

   --accent is the filled-button colour and pairs with --bg as its text colour,
   so it inverts between the dark and light themes. */

:root {
  color-scheme: dark;

  --bg: #0a000a;
  --card: rgba(60, 60, 67, 0.92);
  --bg-soft: #4a4a52;
  --bg-raised: #55555e;
  --line: #575760;
  --text: #f2f2f5;
  --muted: #d8d8e0;
  --accent: #d3d6dc;
  --accent-color: #7b93bf;
  --accent-hover: #c2d3f0;
  --accent-subtle: #8798b8;

  --line-soft: rgba(87, 87, 96, 0.55);
  --line-faint: rgba(87, 87, 96, 0.28);
  --panel: rgba(60, 60, 67, 0.42);
  --dim: #8e8e99;

  --topbar-bg: rgba(10, 0, 10, 0.82);
  --danger: #d9706f;
  --danger-text: #f0bcbb;
  --success: #6fa87c;
  --success-text: #c3e2c9;
  --warning-text: #e5cf9b;
  --checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23d3d6dc' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5'/%3E%3C/svg%3E");

  --radius-sm: 6px;
  --radius: 9px;

  --maxw: 1060px;
  --font: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

html[data-theme='light'] {
  color-scheme: light;

  --bg: #f7f7f9;
  --card: #ffffff;
  --bg-soft: #ececf0;
  --bg-raised: #e2e2e8;
  --line: #d2d2db;
  --text: #17171c;
  --muted: #4c4c58;
  --accent: #1c1c22;
  --accent-color: #3f5b8c;
  --accent-hover: #000000;
  --accent-subtle: #6f83a3;

  --line-soft: rgba(23, 23, 28, 0.14);
  --line-faint: rgba(23, 23, 28, 0.08);
  --panel: #ffffff;
  --dim: #6f6f7c;

  --topbar-bg: rgba(247, 247, 249, 0.85);
  --danger: #c0565a;
  --danger-text: #8f2f34;
  --success: #3f7d4f;
  --success-text: #2b5c38;
  --warning-text: #7a5a12;
  --checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2317171c' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5'/%3E%3C/svg%3E");
}

html[data-theme='midnight'] {
  color-scheme: dark;

  --bg: #06080f;
  --card: rgba(26, 33, 51, 0.92);
  --bg-soft: #1a2133;
  --bg-raised: #232c42;
  --line: #2e3950;
  --text: #eef2fb;
  --muted: #c2cbdd;
  --accent: #d7e5ff;
  --accent-color: #5b8def;
  --accent-hover: #ffffff;
  --accent-subtle: #6f92d8;

  --line-soft: rgba(94, 116, 160, 0.4);
  --line-faint: rgba(94, 116, 160, 0.2);
  --panel: rgba(26, 33, 51, 0.5);
  --dim: #7b879e;

  --topbar-bg: rgba(6, 8, 15, 0.82);
  --checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23d7e5ff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5'/%3E%3C/svg%3E");
}

html[data-theme='ember'] {
  color-scheme: dark;

  --bg: #120806;
  --card: rgba(74, 42, 34, 0.92);
  --bg-soft: #3a211b;
  --bg-raised: #4a2a22;
  --line: #5c382e;
  --text: #fbeee9;
  --muted: #e2c6bc;
  --accent: #ffd9c9;
  --accent-color: #e08256;
  --accent-hover: #fff3ee;
  --accent-subtle: #c07a5c;

  --line-soft: rgba(146, 92, 74, 0.42);
  --line-faint: rgba(146, 92, 74, 0.22);
  --panel: rgba(74, 42, 34, 0.42);
  --dim: #a08279;

  --topbar-bg: rgba(18, 8, 6, 0.82);
  --checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23ffd9c9' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5 6.5 11.5 12.5 4.5'/%3E%3C/svg%3E");
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
  html { scroll-behavior: auto; }
}

a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; }
button { font: inherit; color: inherit; }
code { font-family: var(--mono); font-size: 0.94em; }

/* ---------- primitives ---------- */

.shell {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 12px 16px;
  background: var(--bg-raised);
  border-radius: var(--radius);
  z-index: 60;
}
.skip:focus { left: 16px; top: 16px; }

.section { padding: 88px 0; }

/* ---------- browser key portal ---------- */

.key-main {
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: 72px 24px 96px;
}

.key-card {
  padding: 34px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
}

.key-card h1 {
  margin: 4px 0 0;
  font-size: clamp(1.8rem, 5vw, 2.5rem);
  line-height: 1.2;
  letter-spacing: -0.035em;
}

/* ---------- key page tabs ---------- */

.key-tabs {
  display: flex;
  gap: 4px;
  margin: 18px 0 0;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line-soft);
}

.key-tab {
  padding: 8px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--muted);
  font-size: 14px;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
}
.key-tab:hover { background: var(--bg-soft); color: var(--text); }
.key-tab[aria-selected='true'] {
  background: var(--bg-raised);
  color: var(--text);
  font-weight: 500;
}
.key-tab:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
}

.key-tabs + [role='tabpanel'] > h1 {
  margin-top: 22px;
}

.key-list {
  display: grid;
  gap: 10px;
  margin-top: 22px;
}

.key-row {
  display: grid;
  gap: 6px;
  padding: 14px 16px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.key-row-name {
  margin: 0;
  font-weight: 600;
}

.key-row-meta {
  margin: 0;
  color: var(--dim);
  font-size: 12px;
  line-height: 1.5;
}

.key-row-value {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.key-row-value code {
  overflow-wrap: anywhere;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.key-list + .btn {
  margin-top: 20px;
}

.eyebrow {
  margin: 0;
  color: var(--accent-subtle);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.key-lede,
.key-instructions {
  max-width: 56ch;
  color: var(--muted);
}

.key-start-form,
.token-form {
  display: grid;
  gap: 10px;
  margin-top: 26px;
}

.key-start-form label,
.token-form label {
  font-size: 13px;
  font-weight: 600;
}

.key-start-row {
  display: flex;
  gap: 10px;
}

.key-start-row input,
.key-start-form > input,
.token-form input {
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
}

.key-start-row input,
.key-start-form > input {
  font-family: var(--mono);
  font-size: 13px;
}

.key-hint,
.key-foot {
  margin: 4px 0 0;
  color: var(--dim);
  font-size: 12px;
  line-height: 1.55;
}

.key-flow {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid var(--line-soft);
}

.key-progress {
  color: var(--accent-subtle);
  font-size: 12px;
  font-weight: 600;
}

.key-flow h2 {
  margin: 7px 0 0;
  font-size: 1.3rem;
}

.key-flow .btn {
  margin-top: 12px;
}

.key-result {
  display: grid;
  justify-items: start;
  gap: 10px;
  margin-top: 24px;
  padding: 18px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.key-result p {
  margin: 0;
}

.key-result code {
  overflow-wrap: anywhere;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.key-foot {
  margin: 16px auto 0;
  text-align: center;
}

.key-page [hidden] {
  display: none;
}

@media (max-width: 560px) {
  .key-main { padding: 38px 16px 64px; }
  .key-card { padding: 22px 18px; }
  .key-start-row { flex-direction: column; }
  .key-start-row .btn { width: 100%; }
}

.section h2 {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  max-width: 34ch;
}

.section .lede {
  margin: 12px 0 0;
  max-width: 54ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--muted);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 9px 20px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}

.btn-primary {
  background: var(--accent);
  color: var(--bg);
}
.btn-primary:hover { background: #ffffff; }

.btn-ghost {
  border-color: var(--line);
  color: var(--text);
}
.btn-ghost:hover { background: var(--bg-soft); }

/* pointer-events stops the hover styles above from firing on a busy button,
   e.g. while an auth request is in flight. */
.btn:disabled {
  opacity: 0.6;
  cursor: default;
  pointer-events: none;
}

.notice {
  margin: 20px 0 0;
  font-size: 13px;
  color: var(--dim);
}

.handle {
  font-family: var(--mono);
  font-size: 0.94em;
  color: var(--accent);
  white-space: nowrap;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- header ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 16px 24px;
  border-bottom: 1px solid var(--line-faint);
  background: var(--topbar-bg);
  backdrop-filter: blur(10px);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 600;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  color: var(--muted);
}

.nav-links a {
  padding: 8px 11px;
  border-radius: var(--radius-sm);
  transition: color 0.15s, background-color 0.15s;
}
.nav-links a:hover { color: var(--text); background: var(--bg-soft); }

.nav-actions { display: flex; align-items: center; gap: 8px; }
.nav-actions .btn { min-height: 38px; padding: 6px 16px; font-size: 13.5px; }

.nav-login {
  padding: 8px 6px;
  font-size: 13.5px;
  color: var(--muted);
}
.nav-login:hover { color: var(--text); }

/* The signed in name, filled in by js/session-nav.js. js/supabase.js already
   shortens a long email, so this width is only a backstop for a long username;
   it is set wide enough that the shortening is not then cut again. */
.nav-account {
  max-width: 26ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13.5px;
  color: var(--muted);
}

.nav-toggle {
  display: none;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
}

@media (max-width: 860px) {
  .nav-toggle { display: grid; place-items: center; }
  .nav-links, .nav-actions { display: none; }
  .topbar.is-open .nav {
    flex-wrap: wrap;
    row-gap: 4px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--bg-soft);
  }
  .topbar.is-open .nav > .brand { order: 1; padding: 0 4px; }
  .topbar.is-open .nav-toggle { order: 2; }
  .topbar.is-open .nav-links {
    order: 3;
    display: flex;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding-top: 12px;
  }
  .topbar.is-open .nav-links a { padding: 10px 12px; }
  .topbar.is-open .nav-actions {
    order: 4;
    display: flex;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    margin-top: 10px;
    padding-top: 14px;
    border-top: 1px solid var(--line-faint);
  }
  .topbar.is-open .nav-actions .btn { width: 100%; }
  .topbar.is-open .nav-login { text-align: center; }
  .topbar.is-open .nav-account { text-align: center; }
}

/* ---------- hero ---------- */

.hero { padding: 84px 0 32px; text-align: center; }

.hero h1 {
  margin: 0 auto;
  max-width: 20ch;
  font-size: clamp(2.1rem, 5vw, 3rem);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.hero .lede {
  margin: 20px auto 0;
  max-width: 62ch;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--muted);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 30px;
}

@media (max-width: 720px) {
  .section { padding: 64px 0; }
  .hero { padding: 64px 0 44px; }
}

/* ---------- pricing ---------- */

.price-panel {
  margin-top: 36px;
  padding: 30px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
}

.price-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
}

.price-head b {
  font-size: 2.6rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.04em;
}

.price-head span { font-size: 14px; color: var(--muted); }

.check-list {
  margin: 26px 0 0;
  padding: 24px 0 0;
  border-top: 1px solid var(--line-faint);
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(252px, 1fr));
  gap: 22px 34px;
}

.check-list li {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  gap: 10px;
}

.check-list li::before {
  content: "";
  width: 14px;
  height: 14px;
  margin-top: 4px;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--checkmark-icon) center / 10px 10px no-repeat;
}

.check-list b {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}

.check-list p {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--dim);
}

.check-list li.limit::before { border-color: var(--accent); }

.price-panel .btn { margin-top: 26px; }

.price-foot {
  margin: 22px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--line-faint);
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--dim);
}

.price-foot a { color: var(--accent); }
.price-foot a:hover { text-decoration: underline; }

/* ---------- faq ---------- */

.faq-list { margin-top: 34px; border-top: 1px solid var(--line-soft); }

.faq-list details { border-bottom: 1px solid var(--line-soft); }

.faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 20px 0;
  list-style: none;
  cursor: pointer;
  font-size: 15.5px;
  font-weight: 500;
}

.faq-list summary::-webkit-details-marker { display: none; }

.faq-list summary::after {
  content: "+";
  flex: none;
  width: 20px;
  text-align: center;
  font-size: 17px;
  line-height: 1;
  color: var(--dim);
  transition: transform 0.2s, color 0.2s;
}

.faq-list details[open] summary::after {
  transform: rotate(45deg);
  color: var(--text);
}

.faq-list .answer {
  margin: 0;
  padding: 0 0 22px;
  max-width: 68ch;
  font-size: 14.2px;
  line-height: 1.75;
  color: var(--muted);
}

/* ---------- closing ---------- */

.closer {
  padding: 38px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
}

.closer h2 {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.closer p {
  margin: 12px 0 0;
  max-width: 52ch;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--muted);
}

.closer-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }

@media (max-width: 620px) {
  .closer { padding: 26px 22px; }
}

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--line-soft);
  padding: 46px 0 34px;
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(2, minmax(0, 0.75fr));
  gap: 36px;
}

.footer-brand { display: flex; align-items: center; gap: 10px; }

.footer-blurb {
  margin: 14px 0 0;
  max-width: 36ch;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--muted);
}

.footer-col h4 {
  margin: 0 0 12px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dim);
}

.footer-col ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 9px;
  font-size: 13.5px;
  color: var(--muted);
}

.footer-col a:hover { color: var(--text); }

.footer-base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 38px;
  padding-top: 20px;
  border-top: 1px solid var(--line-faint);
  font-size: 12.5px;
  color: var(--dim);
}

.footer-base a { color: var(--muted); }
.footer-base a:hover { color: var(--text); }

@media (max-width: 780px) {
  .footer-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .footer-grid > :first-child { grid-column: span 2; }
}

/* ---------- auth pages ---------- */

.page-narrow { display: flex; flex-direction: column; min-height: 100vh; }

.auth-main {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 56px 24px;
}

/* A plain column on the page rather than a card, so the provider buttons and the
   form sit on the same surface. */
.auth-panel {
  width: 100%;
  max-width: 400px;
}

.auth-panel h1 {
  margin: 0 0 8px;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.auth-lede {
  margin: 0 0 26px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--muted);
}

.field { display: grid; gap: 6px; margin-bottom: 15px; }

.field label { font-size: 12.5px; color: var(--dim); }

.field input,
.field select {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 14px;
}

.field input:focus,
.field select:focus { outline: none; border-color: var(--accent); }

/* A select keeps the native arrow, so it needs room on the right for it. */
.field select {
  padding-right: 34px;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.field select option { background: var(--bg-soft); color: var(--text); }

.auth-panel form .btn { width: 100%; margin-top: 9px; }

/* Auth feedback (idle while hidden, then error or success).
   The base rule needs `.auth-panel >` so it beats the plain paragraph defaults
   on margin and colour. The state rules below repeat that context so they in
   turn beat the base rule rather than losing to it on specificity. */
.auth-panel > p.auth-status {
  margin: 16px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent-color);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

.auth-panel > p.auth-status[hidden] { display: none; }

.auth-panel > p.auth-status.is-error {
  border-left-color: var(--danger);
  color: var(--danger-text);
}

.auth-panel > p.auth-status.is-success {
  border-left-color: var(--success);
  color: var(--success-text);
}

/* ---------- third party sign in ---------- */

.oauth { display: grid; gap: 10px; }

/* The word sits in the middle with a rule either side, drawn as flex lines so
   the two halves always match. */
.oauth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0;
  font-size: 12.5px;
  color: var(--dim);
}

.oauth-divider::before,
.oauth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line-faint);
}

.btn-oauth {
  border-color: var(--line);
  background: transparent;
  color: var(--text);
}

.btn-oauth:hover {
  border-color: var(--accent-subtle);
  background: var(--bg-soft);
}

.oauth-logo {
  width: 18px;
  height: 18px;
  flex: none;
}

/* The provider marks come from simpleicons in white, which disappears on a
   light background. They are single colour, so inverting them is enough. */
html[data-theme='light'] .oauth-logo { filter: invert(1); }

/* ---------- docs stub ---------- */

.stub-main { padding: 64px 0 84px; }

.legal-main {
  max-width: 820px;
  padding-top: 44px;
  padding-bottom: 84px;
}

.legal-main > h1 {
  margin: 24px 0 6px;
  font-size: clamp(32px, 5vw, 46px);
  letter-spacing: -0.045em;
}

.legal-updated { margin: 0 0 26px; font-size: 13px; color: var(--dim); }

.legal-notice {
  margin: 24px 0 36px;
  padding: 14px 16px;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.7;
}

.legal-notice strong { color: var(--danger-text); }

.legal-main section { margin: 30px 0; }

.legal-main section h2 {
  margin: 0 0 10px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.legal-main section p,
.legal-main section li {
  font-size: 14px;
  line-height: 1.8;
  color: var(--muted);
}

.legal-main section p { margin: 9px 0; }
.legal-main section ul { padding-left: 22px; }
.legal-main section li + li { margin-top: 8px; }
.legal-main a { color: var(--accent); text-underline-offset: 3px; }
.legal-main a:hover { color: var(--text); }

@media (max-width: 600px) {
  .legal-main { padding-top: 28px; }
}

.stub-main h1 {
  margin: 0;
  max-width: 26ch;
  font-size: clamp(1.9rem, 4vw, 2.4rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.12;
}

.stub-list {
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 14px;
}

.stub-list li {
  padding: 20px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
}

.stub-list h3 { margin: 0; font-size: 15px; font-weight: 500; }

.stub-list p {
  margin: 7px 0 0;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--muted);
}

.stub-list code { color: var(--accent); }

.stub-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 34px; }

/* ---------- shared small pieces ---------- */

.btn-sm { min-height: 32px; padding: 5px 12px; font-size: 13px; }

.btn-danger {
  border-color: var(--danger);
  background: transparent;
  color: var(--danger-text);
}
.btn-danger:hover { background: var(--danger); color: var(--bg); }

.icon-btn {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.icon-btn:hover:not(:disabled) { border-color: var(--line); color: var(--text); }
.icon-btn:disabled { opacity: 0.4; cursor: default; }
.icon-btn svg { width: 15px; height: 15px; }

.status { font-size: 12.5px; color: var(--dim); }
.status.is-error { color: var(--danger-text); }
.status.is-success { color: var(--success-text); }
.status.is-warning { color: var(--warning-text); }
.status[hidden] { display: none; }

.notification-toast {
  position: fixed;
  z-index: 1000;
  bottom: 20px;
  right: 20px;
  max-width: min(420px, calc(100vw - 40px));
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--text);
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.28);
  font-size: 13px;
}
.notification-toast.is-success { border-color: var(--success); }
.notification-toast.is-error { border-color: var(--danger); color: var(--danger-text); }
.notification-toast[hidden] { display: none; }

.empty { margin: 0; font-size: 13px; line-height: 1.6; color: var(--dim); }
.empty[hidden] { display: none; }

/* ---------- dashboard shell ---------- */

.dash { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }

.dash-top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 22px;
  border-bottom: 1px solid var(--line-faint);
  background: var(--topbar-bg);
  backdrop-filter: blur(10px);
}

.dash-top .brand { margin-right: auto; }

.dash-usage {
  flex: none;
  padding: 5px 11px;
  border: 1px solid var(--line-faint);
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--dim);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dash-user-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.dash-user-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 5px 10px 5px 6px;
  border: 1px solid var(--line-faint);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}

.dash-user-button:hover {
  border-color: var(--line);
  background: var(--bg-raised);
}

.dash-user-button svg {
  width: 15px;
  height: 15px;
  flex: none;
  color: var(--dim);
}

.dash-user-avatar,
.profile-avatar {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-color), var(--accent-subtle));
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  overflow: hidden;
  background-size: cover;
  background-position: center;
  text-transform: uppercase;
}

.profile-avatar {
  width: 44px;
  height: 44px;
  font-size: 15px;
}

.dash-user-name {
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  color: var(--muted);
}

.profile-popover {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 30;
  width: min(290px, calc(100vw - 32px));
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-soft);
  box-shadow: 0 18px 28px rgb(0 0 0 / 0.2);
}

.profile-popover[hidden] { display: none; }

.profile-card {
  display: grid;
  gap: 14px;
  padding: 12px;
  border-radius: calc(var(--radius) - 2px);
  background: var(--panel);
}

.profile-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.profile-meta {
  min-width: 0;
  display: grid;
  gap: 2px;
}

.profile-meta strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
  font-weight: 600;
}

.profile-meta span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  color: var(--dim);
}

.profile-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.profile-stat {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--line-faint);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}

.profile-stat span {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dim);
}

.profile-stat strong {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.dash-top .btn { min-height: 36px; padding: 6px 14px; font-size: 13.5px; }

.dash-body {
  flex: 1;
  display: flex;
  align-items: stretch;
  min-height: 0;
}

.dash-side {
  flex: none;
  width: 214px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 12px;
  border-right: 1px solid var(--line-faint);
}

.dash-tabs { display: flex; flex-direction: column; gap: 2px; }

.dash-tab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--muted);
  transition: background-color 0.15s, color 0.15s;
}
.dash-tab svg { width: 16px; height: 16px; flex: none; }
.dash-tab:hover { background: var(--bg-soft); color: var(--text); }
.dash-tab.is-active { background: var(--bg-raised); color: var(--text); font-weight: 500; }

.dash-side-foot {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: auto;
  padding: 14px 12px 4px;
  border-top: 1px solid var(--line-faint);
  font-size: 13px;
  color: var(--dim);
}
.dash-side-foot a { padding: 5px 0; }
.dash-side-foot a:hover { color: var(--text); }

.dash-main {
  flex: 1;
  min-width: 0;
  padding: 20px 22px 26px;
  overflow: auto;
}

.dash-panel[hidden] { display: none; }

/* ---------- obfuscation studio ---------- */

#panel-obfuscation:not([hidden]) {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 100%;
}

.studio-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

/* The feedback line sits between the controls and the button. Its auto margin is
   what pushes the button to the right edge, so it is never hidden - only ever
   empty. The margin reset is for the default one a paragraph carries, which
   would otherwise make the bar taller than its buttons. */
.studio-bar .status {
  margin: 0;
  margin-left: auto;
  text-align: right;
}

.studio-context {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 5px 6px 5px 12px;
  border: 1px solid var(--line-faint);
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--dim);
}
.studio-context[hidden] { display: none; }
.studio-context-name {
  max-width: 26ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
}

.dropdown { position: relative; }

.dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 30;
  width: 270px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-soft);
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.34);
}
.dropdown-menu[hidden] { display: none; }

.dropdown-title {
  margin: 6px 8px 8px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--dim);
}

.switch {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  cursor: pointer;
}
.switch:hover { background: var(--bg-raised); }
.switch input {
  width: 15px;
  height: 15px;
  flex: none;
  margin: 0;
  accent-color: var(--accent-color);
  cursor: inherit;
}
.switch em {
  margin-left: auto;
  font-style: normal;
  font-size: 11.5px;
  color: var(--dim);
}
.switch input:disabled,
.switch input:disabled + span { color: var(--dim); }

.studio-grid {
  flex: 1;
  min-height: 520px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line-faint);
}

.panel-head h2 { margin: 0; font-size: 13px; font-weight: 500; }

.panel-meta {
  margin-left: auto;
  font-size: 12px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.panel-meta.is-over { color: var(--danger-text); }

.panel-tools { display: flex; align-items: center; gap: 4px; margin-left: auto; }

.panel-bar {
  padding: 7px 12px;
  border-bottom: 1px solid var(--line-faint);
  font-size: 12px;
  color: var(--dim);
}

.editor {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
  background: var(--bg);
}

.editor .CodeMirror {
  flex: 1;
  width: 0;
  height: auto;
  color: var(--text);
  background: transparent;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
}

.CodeMirror-gutters {
  border-right: 1px solid var(--line-faint);
  background: var(--bg);
}

.CodeMirror-linenumber { color: var(--dim); }
.CodeMirror-cursor { border-left-color: var(--text); }
.CodeMirror-selected { background: rgba(158, 92, 255, 0.24) !important; }
.cm-keyword, .cm-operator, .cm-meta { color: #c792ea; }
.cm-number, .cm-atom { color: #f78c6c; }
.cm-string { color: #c3e88d; }
.cm-comment { color: #788497; }
.cm-def, .cm-builtin { color: #82aaff; }
.cm-variable-2, .cm-property { color: #89ddff; }
.cm-variable { color: var(--text); }

.editor-text {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 12px;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
  white-space: pre;
  overflow: auto;
  resize: none;
  tab-size: 4;
}
.editor-text::placeholder { color: var(--dim); }
.editor-text[readonly] { color: var(--muted); }

/* ---------- page headers ----------
   Projects and Settings open with the same heading block: a title and a line of
   explanation on the left, the page's main action on the right. */

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 22px;
}

.page-head h1 {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.15;
}

.page-lede {
  margin: 8px 0 0;
  max-width: 64ch;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--muted);
}

.page-head-actions { display: flex; flex-wrap: wrap; gap: 8px; }

.page-head .btn { min-height: 40px; padding: 8px 16px; font-size: 13.5px; }

/* Every icon inside a button is sized here rather than with a style attribute,
   which the CSP in _headers blocks. */
.btn svg { width: 15px; height: 15px; flex: none; }

.empty-state {
  padding: 26px 22px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--panel);
}
.empty-state[hidden] { display: none; }
.empty-state h2 { margin: 0; font-size: 15px; font-weight: 600; }
.empty-state p {
  margin: 8px 0 0;
  max-width: 56ch;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--muted);
}

/* The load and failure line above the project cards. */
#projectsStatus:not([hidden]) { margin: 0 0 16px; }

/* ---------- projects ---------- */

.project-index[hidden],
.project-view[hidden] { display: none; }

.project-cards {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(296px, 1fr));
  gap: 14px;
}

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
  transition: border-color 0.15s, background-color 0.15s;
}
.project-card:hover { border-color: var(--line); background: var(--bg-soft); }
.project-card:focus-within { border-color: var(--accent-color); }

/* The whole card opens the project, so the target is the card rather than the
   title. The copy button lifts itself above this. */
.project-card-hit {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: var(--radius);
}

.project-card-top { display: flex; align-items: center; gap: 12px; }
.project-card-details { position: relative; z-index: 1; margin-left: auto; }

.project-card-top h2 {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 15px;
  font-weight: 600;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  margin-left: auto;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 11.5px;
  color: var(--dim);
  white-space: nowrap;
}
.pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.pill.is-active { border-color: var(--success); color: var(--success-text); }

/* A script with nothing stored. Not an error, but the one thing a card cannot show
   by itself, and the one a publisher would otherwise not notice until a user said the
   script they redeemed was empty. */
.pill.is-empty { border-color: var(--danger); color: var(--danger-text); }

.project-card-link {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  min-width: 0;
  font-size: 12.5px;
  color: var(--dim);
}
.project-card-link span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-card-link svg { width: 13px; height: 13px; flex: none; }

.project-card-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--line-faint);
}
.project-card-stats div { min-width: 0; }

.project-card-stats dt {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
}
.project-card-stats dt svg { width: 12px; height: 12px; flex: none; }

.project-card-stats dd {
  margin: 7px 0 0;
  font-size: 1.45rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.project-card-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--line-faint);
  font-size: 12px;
  color: var(--dim);
}

.project-card-id {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  position: relative;
  z-index: 1;
  margin-left: auto;
  padding: 3px 8px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 11.5px;
  cursor: pointer;
}
.project-card-id:hover { background: var(--bg-raised); color: var(--text); }
.project-card-id svg { width: 13px; height: 13px; flex: none; }

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 16px;
  font-size: 13px;
  color: var(--dim);
}
.back-link:hover { color: var(--text); }
.back-link svg { width: 14px; height: 14px; flex: none; }

.detail-blocks { display: grid; gap: 16px; max-width: 1180px; }

.detail-block {
  padding: 18px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
}

.detail-block h2 { margin: 0; font-size: 15px; font-weight: 600; }

.block-lede {
  margin: 6px 0 16px;
  max-width: 78ch;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--muted);
}
.block-lede:empty { display: none; }

.block-head { display: flex; align-items: flex-start; gap: 16px; }
.block-head > .btn { margin-left: auto; flex: none; }

/* ---------- checkpoints ---------- */

.field-block { margin-bottom: 16px; }

.new-script-form {
  display: grid;
  gap: 8px;
  margin: 16px 0;
  padding: 14px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}
.new-script-form[hidden] { display: none; }
.new-script-form h3 { margin: 0; font-size: 14px; font-weight: 600; }
.new-script-form label { font-size: 13px; font-weight: 600; }
.new-script-editor .CodeMirror {
  height: 220px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: 12.5px/1.6 var(--mono);
}
.new-script-editor .CodeMirror-focused { border-color: var(--accent); }
.new-script-form .block-lede { margin: 0; }

/* ---------- webhooks ---------- */

.webhooks-page { display: grid; gap: 20px; }
.webhooks-page > .detail-block { min-width: 0; }
.webhooks-page .field-block { max-width: 440px; }

.webhook-action-tabs {
  display: flex;
  gap: 4px;
  margin: 8px 0 18px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-faint);
}

.webhook-action-tab {
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
}

.webhook-action-tab:hover,
.webhook-action-tab.is-active {
  border-color: var(--line-soft);
  background: var(--bg-raised);
  color: var(--text);
}

.webhook-action-panel form {
  display: grid;
  gap: 16px;
  max-width: 760px;
}

.webhook-enabled {
  width: fit-content;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--line-faint);
  border-radius: var(--radius-sm);
}

.webhook-action-panel .field { margin: 0; }
.webhook-action-panel .field .block-lede { margin: 5px 0 0; }
.webhook-action-panel .field textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  resize: vertical;
}

.webhook-fieldset {
  margin: 0;
  padding: 14px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
}

.webhook-fieldset legend {
  padding: 0 6px;
  font-size: 13px;
  font-weight: 600;
}

.webhook-fieldset .block-lede { margin: 0 0 12px; }

.webhook-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px 18px;
}

.webhook-fields label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
}

.webhook-fields input { accent-color: var(--accent-color); }

.webhook-customize {
  border-top: 1px solid var(--line-faint);
  padding-top: 14px;
}

.webhook-customize summary {
  width: fit-content;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
}

.webhook-custom-fields {
  display: grid;
  gap: 14px;
  margin-top: 16px;
}

.webhook-custom-fields .field { margin: 0; }
.webhook-action-panel .row-actions { align-items: center; }
.webhook-action-panel .row-actions .status { margin: 0; }
.webhook-help .block-lede { margin-bottom: 0; }
.webhook-empty { padding-top: 10px; }
.webhook-empty[hidden] { display: none; }

.checkpoints {
  padding-top: 16px;
  border-top: 1px solid var(--line-faint);
}

.checkpoints-head { display: flex; align-items: flex-start; gap: 16px; }
.checkpoints-head h3 { margin: 0; font-size: 13.5px; font-weight: 600; }
.checkpoints-head .btn { margin-left: auto; flex: none; }
.checkpoints-head .block-lede { margin-bottom: 0; }

.checkpoint-table { margin-top: 14px; }

/* A header row so the two columns of each pair are named once rather than on
   every row. The controls carry their own labels for a screen reader. */
.checkpoint-columns,
.checkpoint-row {
  display: grid;
  grid-template-columns: 52px minmax(0, 150px) minmax(0, 1fr) minmax(0, 1fr) auto 28px;
  gap: 10px;
  align-items: center;
}

.checkpoint-columns {
  padding: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
}
.checkpoint-columns[hidden] { display: none; }

.checkpoint-rows { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }

.checkpoint-row select,
.checkpoint-row input {
  width: 100%;
  min-height: 40px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
}

.checkpoint-row input { font-family: var(--mono); font-size: 12.5px; }

.checkpoint-row select:focus,
.checkpoint-row input:focus { outline: none; border-color: var(--accent); }

.checkpoint-row select {
  padding-right: 32px;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.checkpoint-row select option { background: var(--bg-soft); color: var(--text); }
.checkpoint-row select option:disabled { color: var(--dim); }

.checkpoint-row .icon-btn { font-size: 17px; line-height: 1; }

/* Two arrows rather than drag and drop: they work from the keyboard, and the row
   order is only a number that is saved with the rest of the project. */
.checkpoint-move { display: flex; gap: 2px; }
.checkpoint-move .icon-btn { width: 24px; height: 24px; font-size: 13px; line-height: 1; }
.checkpoint-move .icon-btn:disabled { opacity: 0.35; cursor: default; }

.checkpoint-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
}
.checkpoint-toggle input { width: auto; min-height: 0; margin: 0; accent-color: var(--accent); cursor: pointer; }

/* A row that is off keeps its values but is clearly not part of the flow. */
.checkpoint-row.is-disabled select,
.checkpoint-row.is-disabled input[data-role='token'],
.checkpoint-row.is-disabled input[data-role='provider-url'] { opacity: 0.55; }

@media (max-width: 700px) {
  .checkpoint-columns { display: none; }
  .checkpoint-row {
    grid-template-columns: minmax(0, 1fr) auto 28px;
    grid-template-areas:
      'provider toggle remove'
      'token token token'
      'url url url'
      'move move move';
    row-gap: 8px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--line-faint);
  }
  .checkpoint-row select { grid-area: provider; }
  .checkpoint-row input[data-role='token'] { grid-area: token; }
  .checkpoint-row input[data-role='provider-url'] { grid-area: url; }
  .checkpoint-toggle { grid-area: toggle; justify-self: end; }
  .checkpoint-move { grid-area: move; }
  .checkpoint-row .icon-btn { grid-area: remove; }
  .checkpoint-rows > :last-child { border-bottom: 0; padding-bottom: 0; }

  /* A script card is a name, the date it was created, the loadstring it is run with
     and its buttons. On a phone the name takes the full width and the rest drops
     under it, rather than the tail of the row being pushed off the panel. */
  .script-item-head { flex-wrap: wrap; }
  .script-item-name { flex: 1 0 100%; }
  .script-item-meta { min-width: 0; text-align: left; }
  .script-item-actions { margin-left: 0; flex-wrap: wrap; }

  /* The lede would otherwise hold the head open at its max width and push the
     button out of the panel. */
  .block-head > div { min-width: 0; }
}

.row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 16px; }

.script-items { margin: 0; padding: 0; list-style: none; }

.script-item {
  display: grid;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-faint);
}
.script-item:last-child { border-bottom: 0; }

.script-item-head { display: flex; align-items: center; gap: 12px; }

/* Sized like a field but styled like text, so renaming a script is not a trip
   through a separate form. The border only appears on hover or focus. */
.script-item-name {
  flex: 1;
  min-width: 0;
  padding: 5px 8px;
  margin-left: -8px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
}
.script-item-name:hover { border-color: var(--line-soft); }
.script-item-name:focus { outline: none; border-color: var(--accent); background: var(--bg); }

/* Fixed width so the sizes line up down the list rather than floating with the
   length of each label. */
.script-item-meta {
  flex: none;
  min-width: 68px;
  text-align: right;
  font-size: 12px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
.script-item-actions { flex: none; display: flex; gap: 6px; }

/* The loadstring, which is what the publisher hands out. Long by nature - it holds a
   URL - so it scrolls rather than wrapping, and the text can be selected. */
.script-item-stub {
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  overflow-x: auto;
}

.script-item-stub-text {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px;
  white-space: pre;
  color: var(--accent);
  text-decoration: none;
}
.script-item-stub-text:hover { text-decoration: underline; }

/* Read-only project and script details. */
.facts { display: flex; flex-direction: column; gap: 12px; margin: 0; }

.fact { display: flex; flex-direction: column; gap: 4px; }
.fact-label { font-size: 12.5px; color: var(--dim); }
.fact-value {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 13.5px;
  overflow-wrap: anywhere;
}
.fact-value code { font-family: var(--mono); font-size: 12.5px; }

.project-facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 24px;
}

.project-checkpoint-details {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 10px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line-faint);
}

.project-checkpoint-detail {
  min-width: 0;
  padding: 12px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}

.project-checkpoint-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.project-checkpoint-heading h3 { margin: 0; font-size: 13.5px; font-weight: 600; }

.project-checkpoint-status {
  padding: 3px 7px;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  background: var(--bg-soft);
}

.project-checkpoint-status.is-ready {
  color: var(--success-text);
}

.project-checkpoint-status.is-missing {
  color: var(--danger-text);
}

.project-checkpoint-status.is-trusted {
  color: var(--warning-text);
}

.project-checkpoint-status.is-disabled {
  color: var(--dim);
}

.project-checkpoint-detail p,
.project-checkpoint-empty {
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.project-checkpoint-empty { margin-top: 0; }

/* Generated redirects sit under the project facts, so they get the same separator
   the checkpoint details above them use. */
.redirect-block-head {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line-faint);
}
.redirect-block-head h3 { margin: 0; font-size: 13.5px; font-weight: 600; }

.script-ids { margin: 0; padding: 0; list-style: none; }

.script-id { display: grid; gap: 8px; padding: 12px 0; border-bottom: 1px solid var(--line-faint); }
.script-id:last-child { border-bottom: 0; }

.script-id-head { display: flex; align-items: baseline; gap: 12px; }
.script-id-name { font-size: 13.5px; font-weight: 500; }
.script-id-date {
  margin-left: auto;
  font-size: 12px;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}

.script-id-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.script-id-value {
  padding: 6px 9px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
  font-family: var(--mono);
  font-size: 12px;
}

/* A context menu, opened by right clicking a tab. Fixed rather than absolute, so the
   sidebar it belongs to cannot clip it. */
.context-menu {
  position: fixed;
  z-index: 40;
  min-width: 176px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.35);
}

.context-menu-item {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.context-menu-item:hover,
.context-menu-item:focus-visible { outline: none; background: var(--bg-soft); }

.context-menu[hidden] { display: none; }

/* Wide enough for the two columns: below this the label sits above its value, which
   is the order they are written in anyway. */
@media (min-width: 768px) {
  .fact { flex-direction: row; gap: 16px; }
  .fact dt { flex: none; width: 160px; }
}

/* ---------- settings ----------
   Laid out like the Supabase dashboard's account page: a single narrow column,
   a heading and a line of explanation per section, and a card under it. Inside a
   card each row puts the label on the left and the control on the right, and the
   buttons close the card against its right edge. */

.settings-page { max-width: 688px; margin: 0 auto; }

.settings-page .page-head { margin-bottom: 40px; }

.settings { display: flex; flex-direction: column; gap: 44px; }

.settings-section { display: flex; flex-direction: column; gap: 20px; }

/* Title and explanation belong together, so they are closer to each other than
   either is to the card. */
.settings-section-head { display: flex; flex-direction: column; gap: 4px; }

.settings-section h2 { margin: 0; font-size: 16px; font-weight: 600; }

.settings-lede { margin: 6px 0 16px; max-width: 76ch; font-size: 13.5px; line-height: 1.7; color: var(--muted); }
.settings-section-head .settings-lede { margin: 0; max-width: 62ch; }

.settings-card {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
  overflow: hidden;
}

/* The rows carry the dividers, so the footer that closes the card is not
   underlined as well and the last row keeps the one above the footer. */
.settings-row,
.settings-card-body { padding: 16px 18px; border-bottom: 1px solid var(--line-faint); }
.settings-card > *:last-child { border-bottom: 0; }

.settings-row { display: flex; flex-direction: column; gap: 10px; }

.settings-row-text { display: flex; flex-direction: column; min-width: 0; }
.settings-row-text label { font-size: 13.5px; line-height: 1.5; color: var(--text); }

/* Holds either a field or the buttons that act on the card. */
.settings-control { display: flex; align-items: center; justify-content: flex-end; gap: 12px; min-width: 0; }
.settings-control > .btn { flex: none; }
.settings-control > span { font-size: 13.5px; color: var(--text); }

/* A row that is nothing but its control - log out, delete account - has no label
   beside it, so there is nothing to be pushed away from: the button sits at the
   start of the card, under the heading it belongs to. */
.settings-row-actions .settings-control { justify-content: flex-start; }

.settings-control input {
  width: 100%;
  min-height: 34px;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
}
.settings-control input:focus { outline: none; border-color: var(--accent); }
.settings-control input[readonly] { background: var(--bg-soft); color: var(--dim); }

/* The feedback line sits immediately before the button, so a message and the
   action it belongs to are read together. */
.settings-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 18px;
}

.settings-danger h2 { color: var(--danger-text); }
.settings-danger .settings-card { border-color: var(--danger); }

/* The card js/dashboard.js puts up in place of the whole dashboard when it
   cannot start, which has no section around it to carry the padding. */
.settings-block {
  padding: 18px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--panel);
}
.settings-block h2 { margin: 0; font-size: 16px; font-weight: 600; }

.theme-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 10px; }

.theme-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--muted);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.theme-card:hover { background: var(--bg-soft); color: var(--text); }
.theme-card.is-active { border-color: var(--accent-color); color: var(--text); }

.theme-name { font-size: 13.5px; font-weight: 500; }

.theme-swatch { display: flex; gap: 5px; }
.theme-swatch span {
  width: 18px;
  height: 18px;
  border: 1px solid var(--line-faint);
  border-radius: 5px;
}

/* ---------- dashboard, narrow screens ---------- */



/* Wide enough for the row to split: the label takes what is left after the
   control. Below this the two stack, label first, which is also the order they
   are written in, so the tab sequence never jumps. */
@media (min-width: 768px) {
  .settings-row {
    flex-direction: row;
    align-items: center;
    gap: 24px;
  }

  .settings-row-text { flex: 1; }
  .settings-control { flex: none; width: 50%; }

  /* With no label to sit beside, the control takes the whole width so the button
     stays against the left edge rather than the middle of the card. */
  .settings-row-actions .settings-control { width: 100%; }
}

@media (min-width: 1280px) {
  .settings-control { width: 42%; }
}

@media (max-width: 820px) {
  .dash-body { flex-direction: column; }

  .dash-side {
    width: auto;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-right: 0;
    border-bottom: 1px solid var(--line-faint);
    overflow-x: auto;
  }

  .dash-tabs { flex-direction: row; }
  .dash-tab { white-space: nowrap; }
  .dash-side-foot { display: none; }

  .dash-main { padding: 16px; }

  .dash-usage, .dash-user { display: none; }

  .studio-grid {
    flex: none;
    min-height: 0;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }
  .panel .editor { flex: none; height: 300px; }
}

/* ---------- keys, blacklist and analytics ----------
   The three publisher tabs added on top of the key system. They share one table
   shape and one filter bar, because all three are lists of rows with a control or
   two above them. */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.filter-bar .field { margin-bottom: 0; min-width: 150px; }
.filter-bar .field-grow { flex: 1 1 220px; }
.filter-bar .btn { margin-bottom: 1px; }
.field-inline { margin-bottom: 0; min-width: 190px; }

.data-table {
  overflow-x: auto;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.data-table[hidden] { display: none; }

.data-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.data-table th {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  color: var(--dim);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
}

.data-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-faint);
  vertical-align: middle;
  white-space: nowrap;
}

.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover { background: var(--bg-soft); }

.data-table .cell-key {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.03em;
}

.data-table .cell-muted { color: var(--dim); }
.data-table .cell-wrap { white-space: normal; min-width: 180px; }
.data-table .cell-actions { text-align: right; }

.data-table .row-actions-cell {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
}

/* The extend control is a select beside a button, sized like the buttons it sits
   with rather than like a form field. */
.data-table .key-extend {
  display: flex;
  gap: 6px;
}

.data-table .key-extend-select {
  min-height: 32px;
  padding: 4px 26px 4px 10px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background-color: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.data-table .key-extend-select:focus { outline: none; border-color: var(--accent); }

.data-table .key-extend-select option { background: var(--bg-soft); color: var(--text); }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  font-size: 11.5px;
  background: var(--bg-soft);
}

.badge.is-valid { color: var(--success-text); border-color: var(--success); }
.badge.is-active { color: var(--accent-subtle); border-color: var(--accent-subtle); }
.badge.is-expired { color: var(--warning-text); }
.badge.is-revoked { color: var(--danger-text); border-color: var(--danger); }

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 12px;
}

.stat {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.stat span { color: var(--dim); font-size: 12px; }
.stat strong { font-size: 1.6rem; font-weight: 600; font-variant-numeric: tabular-nums; }

.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 160px;
  margin-top: 8px;
  padding: 10px 4px 0;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.bar-chart[hidden] { display: none; }

.bar {
  display: flex;
  flex: 1 1 0;
  align-items: flex-end;
  height: 100%;
  min-width: 2px;
}

.bar-fill {
  width: 100%;
  min-height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--accent-subtle);
}

.bar.is-zero .bar-fill { background: var(--line-faint); }
.bar:hover .bar-fill { background: var(--accent-hover); }


/* .field and .key-result set their own display, which beats the browser default
   for the hidden attribute. Without this a field marked hidden still shows. */
.filter-bar .field[hidden],
.key-result[hidden],
.filter-bar[hidden] { display: none; }

/* ---------- tooltips ----------
   The trigger is a small "?" pill: a tooltip nobody can find is not a tooltip.
   The bubble itself is one fixed-position node filled by js/tooltips.js, so it is
   never clipped by a scrolling table and the trigger only has to carry data-tip. */

.tip {
  display: inline-grid;
  place-items: center;
  width: 15px;
  height: 15px;
  margin-left: 5px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--dim);
  font-family: var(--font);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  vertical-align: middle;
  cursor: help;
  user-select: none;
  transition: color 0.15s, border-color 0.15s;
}

.tip:hover,
.tip:focus-visible {
  border-color: var(--accent-subtle);
  color: var(--text);
  outline: none;
}

.tooltip-layer {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 80;
  max-width: 260px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  color: var(--text);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

.tooltip-layer[hidden] { display: none; }

/* These wrappers set their own size and colour on every span they contain, which
   would otherwise inflate the "?" pill inside them. */
.stat .tip,
.field label .tip,
h2 .tip,
th .tip,
.block-lede .tip {
  font-size: 10px;
  line-height: 1;
  color: var(--dim);
}
