* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  /* Tells the browser this page is dark-only, so native form controls
     (radio buttons, checkboxes, scrollbars) render with dark-appropriate
     chrome instead of defaulting to a light-mode ring/background regardless
     of the page's own CSS — accent-color alone only tints the checked
     state, not the control's base appearance. */
  color-scheme: dark;
  --bg: #0d0d0d;
  --surface: #111;
  --border: #1e1e1e;
  --text-primary: #f4f4f5;
  --text-secondary: #a1a1aa;
  /* 2026-08-12: lightened from #71717a (4.02:1 against --bg, fails WCAG AA's
     4.5:1 minimum for normal text) — this exact color is used at small sizes
     in the footer, hero footnote, and form placeholders, none of which
     qualify as "large text" (18pt/24px+) for the relaxed 3:1 threshold.
     #797983 (4.51:1) is visually near-identical, same hue, ~7% lighter. */
  --text-tertiary: #797983;
  /* 2026-08-15: swapped from purple (#a855f7) per Jack — reads as a generic
     AI-generated-startup color. Electric blue fits a monitoring/intelligence
     product better (radar/satellite association) and isn't the default
     everyone's site already looks like. */
  --accent: #0ea5e9;
  --accent-hover: #38bdf8;
  --radius: 12px;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg);
  color: var(--text-primary);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 32px;
  max-width: 1200px;
  margin: 0 auto;
  width: 100%;
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}

.logo-mark {
  color: var(--accent);
  font-size: 1.4rem;
}

.nav-links {
  display: flex;
  gap: 24px;
}

.nav-links a {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  transition: color 0.2s;
}

.nav-links a:hover {
  color: var(--text-primary);
}

main {
  flex: 1;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 32px;
  width: 100%;
}

.hero {
  padding: 100px 0 80px;
  text-align: center;
  max-width: 720px;
  margin: 0 auto;
}

.hero-badge {
  display: inline-block;
  padding: 6px 16px;
  border-radius: 100px;
  background: rgba(14, 165, 233, 0.1);
  border: 1px solid rgba(14, 165, 233, 0.25);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--accent);
  margin-bottom: 24px;
  letter-spacing: 0.02em;
}

.hero h1 {
  font-size: 3.5rem;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin-bottom: 20px;
  text-wrap: balance;
}

.gradient-text {
  background: linear-gradient(135deg, var(--accent), #2563eb);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Rotating last word in the hero headline (added 2026-08-16, approved via
   mockup first). Four words share one @keyframes rule, each offset by a
   negative animation-delay of one "slot" (2.6s) so they hand off back-to-
   back with no gap and no overlap — see the word-swap mockup's comment for
   the exact math this generalizes from (originally 2 words/5.2s cycle).
   Fixed-width box so the line's total width — and its centering — doesn't
   shift as different-length words rotate through. */
.swap {
  position: relative;
  display: inline-block;
  height: 1.1em;
  width: 4.3em;
  vertical-align: bottom;
  overflow: visible;
}
.swap span {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  background: linear-gradient(135deg, var(--accent), #2563eb);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: word-cycle 10.4s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.swap span:nth-child(1) { animation-delay: 0s; }
.swap span:nth-child(2) { animation-delay: -2.6s; }
.swap span:nth-child(3) { animation-delay: -5.2s; }
.swap span:nth-child(4) { animation-delay: -7.8s; }

@keyframes word-cycle {
  0%     { opacity: 0; transform: translateY(0.4em); }
  4%     { opacity: 1; transform: translateY(0); }
  21%    { opacity: 1; transform: translateY(0); }
  25%    { opacity: 0; transform: translateY(-0.4em); }
  25.01% { transform: translateY(0.4em); }
  100%   { opacity: 0; transform: translateY(0.4em); }
}

@media (prefers-reduced-motion: reduce) {
  .swap span { animation: word-cycle-reduced 10.4s step-end infinite; }
  @keyframes word-cycle-reduced {
    0%     { opacity: 1; transform: none; }
    24.9%  { opacity: 1; transform: none; }
    25%    { opacity: 0; transform: none; }
    99.9%  { opacity: 0; transform: none; }
    100%   { opacity: 1; transform: none; }
  }
}

.hero-subtitle {
  font-size: 1.1rem;
  color: var(--text-secondary);
  line-height: 1.7;
  max-width: 560px;
  margin: 0 auto 40px;
}

.app-store-wrapper {
  display: inline-flex;
  position: relative;
  align-items: center;
  justify-content: center;
}

.app-store-blur {
  filter: blur(4px);
  pointer-events: none;
  user-select: none;
}

.coming-soon-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 8px 20px;
  border-radius: 100px;
  background: var(--accent);
  color: white;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  z-index: 1;
}

.app-store-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 32px;
  background: var(--accent);
  color: white;
  text-decoration: none;
  border-radius: 12px;
  font-weight: 600;
  font-size: 1rem;
  transition: background 0.2s, transform 0.15s;
}

.app-store-button:hover {
  background: var(--accent-hover);
  transform: translateY(-2px);
}

.hero-footnote {
  margin-top: 16px;
  font-size: 0.8rem;
  color: var(--text-tertiary);
}

.features {
  padding: 80px 0;
  text-align: center;
}

.features h2,
.topics h2,
.contact h2 {
  font-size: 2rem;
  font-weight: 600;
  margin-bottom: 12px;
  letter-spacing: -0.02em;
}

.section-subtitle {
  color: var(--text-secondary);
  font-size: 1rem;
  margin-bottom: 48px;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  max-width: 960px;
  margin: 0 auto;
}

.feature-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px 24px;
  text-align: left;
  transition: border-color 0.2s;
}

.feature-card:hover {
  border-color: var(--accent);
}

.feature-icon {
  font-size: 1.8rem;
  margin-bottom: 16px;
}

.feature-card h3 {
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 8px;
}

.feature-card p {
  font-size: 0.85rem;
  color: var(--text-secondary);
  line-height: 1.6;
}

.topics {
  padding: 80px 0;
  text-align: center;
}

.topic-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  max-width: 720px;
  margin: 0 auto;
}

.topic-card {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 100px;
  padding: 10px 20px;
  font-size: 0.9rem;
  font-weight: 500;
  transition: border-color 0.2s;
}

.topic-card:hover {
  border-color: var(--accent);
}

.topic-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.showcase {
  padding: 80px 0;
  text-align: center;
}

.showcase-grid {
  /* Stacked, not side-by-side — a 3-up row squeezed each card too narrow
     and forced horizontal scrolling on common viewport widths. One wide
     column reads better and never scrolls sideways. Container is wider
     than the card's own 560px cap (+ ~24px iframe body padding) so the
     card actually reaches its full width instead of being invisibly
     clipped by a same-size container. */
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 620px;
  margin: 0 auto;
}

.showcase-embed {
  width: 100%;
  height: 230px;
  border: none;
  /* The embed card itself renders its own background/border (server-side,
     via buildEmbedCard) — no card chrome added here so it looks identical
     to what a third-party site pasting this same embed code would see. */
}

.showcase-embed--timeline {
  /* Taller variant for cards passing ?timeline= (buildEmbedCardTimeline
     adds a "Recent Activity" section under the description). Extra
     transparent space below on any card that ends up shorter than this is
     invisible against the page background, so one shared height is fine. */
  height: 340px;
}

.faq {
  padding: 80px 0;
  text-align: center;
}

.faq-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 720px;
  margin: 0 auto;
  text-align: left;
}

.faq-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color 0.2s;
  /* No padding here — it lives on summary/p instead so the entire visible
     rectangle is part of the clickable <summary>, not just the question
     text. A native <details> only toggles on clicks inside <summary>, so
     padding on this outer element would create dead space around the edges
     that looks clickable but isn't. */
}

.faq-item:hover {
  border-color: var(--accent);
}

.faq-item summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
  list-style: none;
  padding: 20px 24px;
}

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

.faq-item summary::after {
  content: '+';
  float: right;
  color: var(--text-tertiary);
  font-weight: 400;
}

.faq-item[open] summary::after {
  content: '−';
}

.faq-item p {
  padding: 0 24px 20px;
  margin-top: -6px;
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.6;
}

.contact {
  padding: 80px 0 120px;
  text-align: center;
}

.contact-form {
  max-width: 440px;
  margin: 32px auto 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.contact-form input,
.contact-form textarea {
  width: 100%;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.2s;
  box-sizing: border-box;
}

.contact-form input:-webkit-autofill,
.contact-form textarea:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 100px var(--surface) inset !important;
  -webkit-text-fill-color: var(--text-primary) !important;
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--text-tertiary);
}

.contact-form input:focus,
.contact-form textarea:focus {
  border-color: var(--accent);
}

.contact-button {
  display: inline-block;
  padding: 14px 32px;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 500;
  font-size: 0.95rem;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.2s, transform 0.15s;
}

.contact-button:hover {
  background: var(--accent-hover);
  transform: translateY(-2px);
}

.radio-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 16px;
}

.radio-group label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.85rem;
  color: var(--text-secondary);
  cursor: pointer;
  /* .contact sets text-align:center on the whole section — invisible on a
     single line, but once a long label wraps to 2 lines on a narrow
     screen, the wrapped line inherits that centering and looks off next
     to a left-aligned radio button. Force left regardless of ancestor. */
  text-align: left;
}

.radio-group input[type="radio"] {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* Commission form's conditional follow-ups (added 2026-08-16) — shown/hidden
   purely with CSS :has(), no JavaScript, matching this site's existing
   zero-JS approach everywhere else. The visible one always matches whichever
   radio is currently checked; the hidden one is excluded from HTML
   constraint validation automatically (elements with display:none are
   "barred from constraint validation" per spec), so it's safe to leave
   these un-required without worrying about a hidden field blocking submit. */
.followup { display: none; }
.contact-form:has(#vis-public:checked) .followup-public { display: block; }
/* .followup-private is also a .radio-group (needs flex, not block, to keep
   its own column layout — see the shared .radio-group rule above). */
.contact-form:has(#vis-private:checked) .followup-private { display: flex; }

footer {
  border-top: 1px solid var(--border);
  padding: 48px 32px 24px;
}

.footer-content {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  gap: 48px;
}

.footer-tagline {
  color: var(--text-tertiary);
  font-size: 0.85rem;
  margin-top: 8px;
}

.footer-col h2 {
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 12px;
  color: var(--text-secondary);
}

.footer-col a {
  display: block;
  color: var(--text-tertiary);
  text-decoration: none;
  font-size: 0.85rem;
  margin-bottom: 8px;
  transition: color 0.2s;
}

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

.footer-bottom {
  max-width: 1200px;
  margin: 32px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  text-align: center;
  color: var(--text-tertiary);
  font-size: 0.8rem;
}

@media (max-width: 768px) {
  .hero h1 {
    font-size: 2.25rem;
  }

  .hero {
    padding: 60px 0 48px;
  }

  .feature-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .nav-links {
    gap: 16px;
  }

  .footer-content {
    flex-direction: column;
    gap: 32px;
  }
}