:root {
  --bg-rgb: 14, 14, 18;
  --bg: #0e0e12;
  --panel: rgba(255, 255, 255, 0.04);
  --panel-2: rgba(255, 255, 255, 0.07);
  --fg: #f3f3f6;
  --muted: #9a9aa6;
  --border: rgba(255, 255, 255, 0.09);
  --green: #4ade80;
  --green-deep: #16a34a;
  --green-dim: rgba(74, 222, 128, 0.14);
  --on-green: #08130a;
  --radius: 18px;
  --topbar-h: 66px;
  --marquee-h: 34px;
  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--fg);
  font-family: -apple-system, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a {
  color: inherit;
}

code {
  font-family: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, monospace;
  font-size: 0.92em;
}

/* ---- Background texture ---- */
.bg-grid {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 70% 55% at 50% 20%, #000 40%, transparent 90%);
}
.bg-glow {
  position: fixed;
  top: -20%;
  left: 50%;
  transform: translateX(-50%);
  width: 1100px;
  height: 700px;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(closest-side, var(--green-dim), transparent 70%);
  filter: blur(10px);
}

/* ---- Topbar ----
   A frosted-glass material, not an opaque bar: strong blur + saturation so it
   reads as glass from the first frame, content scrolls underneath, and the
   bottom edge only firms up into a divider once something is actually
   scrolled under it. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 21;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  background: rgba(var(--bg-rgb), 0.66);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-bottom: 1px solid transparent;
  /* Light catching the top edge of the glass. */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  transition: border-color 0.3s ease, background 0.3s ease;
}
.topbar[data-scrolled="yes"] {
  border-bottom-color: var(--border);
  background: rgba(var(--bg-rgb), 0.85);
}
.topbar__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 1080px;
  margin: 0 auto;
  width: 100%;
}
.topbar__mark {
  color: var(--green);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -0.06em;
}
.topbar__name {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.topbar__links {
  display: flex;
  align-items: center;
  gap: 8px;
}
.topbar__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--fg) !important;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease,
    transform 0.1s ease;
}
.topbar__icon:hover {
  background: var(--panel-2);
}
.topbar__icon:active {
  transform: scale(0.96);
}
/* Only the glyph is red. The pill keeps the same neutral border and hover fill
   as the GitHub button so the two read as one set. */
.topbar__icon--yt {
  color: #ff3d3d !important;
}

/* ---- Marquee banner ----
   A solid green strip under the topbar. Two identical groups sit inside one
   flex track; animating the track to translateX(-50%) moves it by exactly one
   group's width, so the loop point is invisible. */
.marquee {
  position: fixed;
  top: var(--topbar-h);
  left: 0;
  right: 0;
  z-index: 19;
  height: var(--marquee-h);
  overflow: hidden;
  background: var(--green);
  color: var(--on-green);
  display: flex;
  align-items: center;
}
.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee-scroll 22s linear infinite;
}
.marquee__group {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.marquee__item {
  display: inline-flex;
  align-items: center;
  padding: 0 22px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* ---- Hero ----
   A full-screen landing hero: the mark, the name, the pitch, one action, and a
   chevron cueing that there's more below. */
.hero {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  max-width: 880px;
  margin: 0 auto;
  padding: 48px 24px 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.hero__marks {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  perspective: 1400px;
  margin: 0 0 40px;
  padding-top: 16px;
  user-select: none;
}
.mark {
  font-size: clamp(7rem, 20vw, 15rem);
  font-weight: 800;
  line-height: 1;
  color: var(--green);
  transform-style: preserve-3d;
  transform: rotateX(0deg) rotateY(0deg);
  will-change: transform;
  transition: transform 0.12s ease-out;
  filter: drop-shadow(0 22px 30px rgba(0, 0, 0, 0.6));
}
.mark--inverted {
  animation-delay: -2.4s;
}
@keyframes float {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -10px; }
}
.hero__marks[data-float="yes"] .mark {
  animation: float 6s ease-in-out infinite;
}

.hero__title {
  margin: 6px 0 0;
  font-size: clamp(2.1rem, 5vw, 3rem);
  font-weight: 800;
  line-height: 1.05;
  /* Tracking is size-specific: large display type reads too loose at 0, so it
     tightens as it grows rather than using one fixed value everywhere. */
  letter-spacing: -0.035em;
}
.hero__tagline {
  margin: 14px 0 0;
  max-width: 560px;
  color: var(--muted);
  font-size: 16px;
  line-height: 1.6;
  letter-spacing: -0.005em;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 28px;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: 12px;
  font-weight: 600;
  font-size: 14.5px;
  letter-spacing: -0.005em;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  /* Feedback lives on the press: :active fires the instant the pointer goes down,
     not on release, so the button never feels like it's waiting on you. */
  transition: transform 0.1s cubic-bezier(0.16, 1, 0.3, 1), filter 0.15s ease, background 0.15s ease;
}
.btn:active {
  transform: scale(0.96);
  transition-duration: 0.05s;
}
.btn--primary {
  background: var(--green);
  color: var(--on-green);
}
.btn--primary:hover {
  filter: brightness(1.08);
}
.btn--ghost {
  background: var(--panel);
  color: var(--fg);
  border-color: var(--border);
}
.btn--ghost:hover {
  background: var(--panel-2);
}
.btn--muted {
  background: transparent;
  color: var(--muted);
  border-color: var(--border);
}
.btn--muted:hover {
  color: var(--fg);
  background: var(--panel);
}
.btn__tag {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--muted);
}

.hero__chevron {
  position: absolute;
  left: 50%;
  bottom: 36px;
  transform: translateX(-50%);
  display: inline-flex;
  color: var(--green);
  opacity: 0.85;
  animation: chevron-bounce 2s ease-in-out infinite;
}
.hero__chevron:hover {
  opacity: 1;
}
@keyframes chevron-bounce {
  0%, 100% {
    transform: translate(-50%, 0);
  }
  50% {
    transform: translate(-50%, 10px);
  }
}

/* ---- Sections ---- */
/* 1080px matches the topbar's inner width, and it's what the two-column split
   below needs. Every section shares it so the hairline rules between them all
   line up; the text inside is capped separately at a readable measure rather
   than being allowed to run the full width. */
.section {
  position: relative;
  z-index: 1;
  max-width: 1080px;
  margin: 0 auto;
  padding: 64px 24px;
  border-top: 1px solid var(--border);
}
.section__title {
  margin: 0 0 12px;
  font-size: 1.6rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--green);
}
.section__lede {
  margin: 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.7;
  max-width: 640px;
}
.section__disclaimer {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.6;
  max-width: 560px;
}
.accent {
  color: var(--green);
  font-weight: 700;
}
.section__note {
  margin-top: 16px;
  max-width: 760px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.7;
}
.section__note a {
  color: var(--green);
  text-decoration: none;
}
.section__note a:hover {
  text-decoration: underline;
}

/* ---- Split layout (What it does) ----
   Copy and feature cards on the left at a comfortable reading measure, demo
   video parked on the right. The video sticks while the cards scroll past it,
   so it stays available for the whole section instead of scrolling away after
   the first card. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 440px;
  gap: 44px;
  align-items: start;
}
.split__main {
  min-width: 0;
}
.split__aside {
  position: sticky;
  /* Clears the fixed topbar + marquee, plus a little breathing room. */
  top: calc(var(--topbar-h) + var(--marquee-h) + 24px);
}

.demo {
  position: relative;
  margin: 0;
}
/* The glow is a blurred copy of the frame sitting behind it, not a box-shadow:
   a shadow would be clipped by the frame's own overflow:hidden (needed to keep
   the iframe inside the rounded corners), and this way the light bleeds outward
   the way a screen actually spills onto its surroundings. */
.demo::before {
  content: "";
  position: absolute;
  inset: -6px -6px 30px;
  z-index: 0;
  border-radius: calc(var(--radius) + 8px);
  background: var(--green);
  opacity: 0.28;
  filter: blur(26px);
  pointer-events: none;
  transition: opacity 0.35s ease;
}
.demo:hover::before {
  opacity: 0.42;
}
.demo__frame {
  position: relative;
  z-index: 1;
  aspect-ratio: 16 / 9;
  border: 1px solid rgba(74, 222, 128, 0.45);
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
  box-shadow:
    0 0 0 1px rgba(74, 222, 128, 0.12),
    0 18px 40px rgba(0, 0, 0, 0.5);
}
.demo__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.demo__caption {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.5;
}
.demo__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--green);
  box-shadow: 0 0 0 4px var(--green-dim);
}

/* ---- Numbered step guide (Get started) ---- */
.steps {
  margin-top: 34px;
  /* Kept to a reading measure inside the wider section: full-width code blocks
     and prose would both be uncomfortable to scan at 1080px. */
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: 30px;
}
.step {
  display: flex;
  gap: 16px;
}
.step__num {
  flex: none;
  width: 26px;
  height: 26px;
  margin-top: 1px;
  border-radius: 999px;
  background: var(--green-dim);
  border: 1px solid rgba(74, 222, 128, 0.35);
  color: var(--green);
  font-weight: 700;
  font-size: 12.5px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.step__body {
  flex: 1;
  min-width: 0;
}
.step__title {
  margin: 0 0 6px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.step__text {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.65;
}
.step__text:last-child {
  margin-bottom: 0;
}
.step__text a {
  color: var(--green);
  text-decoration: none;
}
.step__text a:hover {
  text-decoration: underline;
}

/* Two across, not three: the cards now live in the narrower left column of the
   split, and three would leave each one too cramped to read. It goes back to
   three once the split stacks and the column is full width. */
.grid {
  margin-top: 30px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}
.card {
  padding: 18px 18px 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* A settle curve that approximates a critically-damped spring (no overshoot),
     reserved for hover/press, since real velocity-aware springs are for gestures. */
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.35s ease,
    background 0.35s ease, box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.card:hover {
  transform: translateY(-3px);
  border-color: rgba(74, 222, 128, 0.3);
  background: var(--panel-2);
  box-shadow: 0 14px 28px rgba(0, 0, 0, 0.35);
}
.card h3 {
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.card p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}

/* ---- Code block ---- */
.code {
  margin: 0 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--panel);
}
.code:last-child {
  margin-bottom: 0;
}
.code__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px 8px 16px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
}
.code__lang {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.code__copy {
  background: none;
  border: 1px solid var(--border);
  color: var(--fg);
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 7px;
  cursor: pointer;
  transition: background 0.15s ease;
}
.code__copy:hover {
  background: var(--panel-2);
}
.code__body {
  margin: 0;
  padding: 16px 18px;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.7;
  color: var(--fg);
}

/* ---- Footer ---- */
.footer {
  position: relative;
  z-index: 1;
  max-width: 1080px;
  margin: 0 auto;
  padding: 28px 24px 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: var(--muted);
  font-size: 12.5px;
  border-top: 1px solid var(--border);
}
.footer a {
  color: var(--muted);
  text-decoration: none;
}
.footer a:hover {
  color: var(--fg);
}

/* ---- Responsive ---- */
.br-desktop {
  display: inline;
}
/* Below this the two columns would squeeze both the cards and the video, so
   they stack, with the demo dropping below the copy, where a full-width player
   reads better than a cramped side rail. */
@media (max-width: 1040px) {
  .split {
    grid-template-columns: minmax(0, 1fr);
    gap: 34px;
  }
  .split__aside {
    position: static;
    max-width: 640px;
  }
  .grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 720px) {
  .br-desktop {
    display: none;
  }
  .grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 480px) {
  .grid {
    grid-template-columns: 1fr;
  }
  .footer {
    flex-direction: column;
    gap: 6px;
    align-items: flex-start;
  }
}

/* ---- Scroll reveal ----
   A simple, non-gesture transition (scroll position triggers it, not a finger),
   so a plain eased transition is appropriate; springs are reserved for things
   the user directly touches, like the hero marks below. Scoped under html.js
   (set by script.js) so content stays visible by default if JS never runs,
   instead of getting stuck at opacity: 0. */
html.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
/* Needs to out-specificity the rule above (which carries an extra `html` type
   selector for the no-JS gate), or this override never wins and content stays
   invisible even after JS adds is-visible. */
html.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ---- Reduced motion ----
   Not "no feedback": a gentler, non-vestibular equivalent. Slides/parallax/spring
   tilt drop out; short opacity cross-fades and color/border changes (which aid
   comprehension without moving anything) stay. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .hero__marks[data-float="yes"] .mark {
    animation: none;
  }
  .hero__chevron {
    animation: none;
  }
  .marquee__track {
    animation: none;
  }
  .marquee__group[aria-hidden="true"] {
    display: none;
  }
  .reveal {
    transform: none;
    transition: opacity 0.3s ease;
  }
  .card {
    transition: border-color 0.2s ease, background 0.2s ease;
  }
  .card:hover {
    transform: none;
    box-shadow: none;
  }
  .topbar {
    transition: background 0.2s ease;
  }
}

/* ---- Reduced transparency ----
   The topbar is the only translucent material on the page; make it frostier
   (near-solid, no blur) instead of a full opaque swap. */
@media (prefers-reduced-transparency: reduce) {
  .topbar {
    background: rgba(var(--bg-rgb), 0.98);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-bottom-color: var(--border);
  }
}

/* ---- Increased contrast ----
   Near-solid surfaces with a defined border instead of a faint translucent panel. */
@media (prefers-contrast: more) {
  :root {
    --border: rgba(255, 255, 255, 0.28);
    --muted: #c2c2ca;
  }
  .card,
  .code,
  .btn--ghost,
  .btn--muted {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--border);
  }
}
