:root {
  --bg: #131316;
  --bg-deep: #0a0a0c;
  --panel: #1f2023;
  --panel-border: #2c2d31;
  --cream: #d9c9a3;
  --green: #3fa76f;
  --text: #f3f2ee;
  --text-muted: #97989d;
  --radius: 12px;
  /* Governs main/header's content column only - the hero photo, its
     glow, and the studio banner bleed to the true viewport edge via
     their own literal 100vw (not --shell), so raising this doesn't
     touch them. 1240px keeps text/paragraph line lengths and the
     interface carousel margined like the original design instead of
     stretching thin across a wide window - only the photo backgrounds
     were meant to go edge-to-edge. */
  --shell: 1240px;
  --display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow-x: hidden;
}

/* Fine grain overlay - gives the flat dark panels a little tactile texture,
   same spirit as the hardware being emulated. Fixed + low-opacity so it
   never fights with content contrast. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Ambient haze bleeding in from the page's left/right margins, for the
   full scroll length - keeps some atmosphere going even far from the
   hero glow, instead of the rest of the page reading as flat black. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background:
    radial-gradient(ellipse 420px 100% at 0% 50%, rgba(63, 167, 111, 0.09), transparent 65%),
    radial-gradient(ellipse 420px 100% at 100% 50%, rgba(217, 201, 163, 0.07), transparent 65%);
}

a { color: var(--green); text-decoration: none; }
a:hover { text-decoration: underline; }

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 28px 40px;
  max-width: var(--shell);
  width: 100%;
  margin: 0 auto;
  position: relative;
  z-index: 2;
}

.logo {
  font-family: var(--display);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--text);
}
.logo span { color: var(--green); }

nav a {
  color: var(--text-muted);
  margin-left: 28px;
  font-size: 14px;
}
nav a:hover { color: var(--text); text-decoration: none; }

main {
  flex: 1;
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 40px;
  position: relative;
  z-index: 2;
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  padding: 56px 0 80px;
}

.hero-visual {
  /* Bleeds past .hero's own padded box out to the true device edge -
     the actual bug chasing this same span of CSS through several
     rewrites was never this bleed mechanism, it was .hero-visual img's
     live filter:blur() (see that rule's own comment - a real, confirmed
     WebKit bug where a blurred element's ink overflow escapes an
     ancestor's overflow:hidden instead of being clipped by it). Once
     the blur moved into the image file itself, this could go back to
     spanning the full viewport instead of only main's own inset box. */
  position: absolute;
  top: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  /* Fixed height, not 100% of .hero - the source photo has its own
     built-in light-to-dark falloff (a lit desk in front, a much darker
     backdrop behind), and blurring it turned that falloff into a smooth
     but still visible band. At height:100% that band landed right under
     the price/CTA row, reading as a flat grey "plate" sitting under the
     text - neither the photo nor the page's own flat background, just
     a leftover of the photo's dark half. Capping the height means the
     image (and its fade) is done well above the CTA regardless of how
     tall .hero grows with content below it, so the CTA sits on the
     page's actual flat background instead of that leftover band. */
  height: 620px;
  z-index: 0;
  background: var(--bg);
  overflow: hidden;
  /* Fades the layer out at the top (settling in under the header) and
     over a long stretch at the bottom, ending well inside this fixed
     620px box - long enough that the photo's own light-to-dark falloff
     (see above) happens while already mostly faded, so it reads as part
     of the vignette instead of a hard edge. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, black 130px, black 45%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, black 130px, black 45%, transparent 100%);
}

.hero-visual img {
  /* Blur/saturate/brightness used to be a live CSS filter() here, plus
     a transform:scale(1.12) to hide the blur's soft edge. Confirmed by
     hiding .hero-visual entirely (display:none) that a real, reported
     horizontal scroll/overflow bug on a real device disappeared with
     it - filter:blur() is a well-documented category of WebKit bug
     where a blurred element's "ink overflow" can escape an ancestor's
     overflow:hidden instead of being clipped by it, especially
     combined with a transform on the same element. Baked the same
     blur/saturate/brightness into the image file itself instead
     (controller-render-blurred.jpg) so there's no live filter/
     transform left on this element at all - nothing left for that bug
     to apply to. */
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 58%;
}

.hero-visual::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg,
      var(--bg) 0%,
      rgba(19, 19, 22, 0.6) 6%,
      transparent 16%,
      transparent 84%,
      rgba(19, 19, 22, 0.6) 94%,
      var(--bg) 100%);
}

/* Flat wash on top of the image - keeps the lede/CTA text legible
   regardless of what tone happens to be in that part of the photo. */
.hero-visual::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(13, 13, 15, 0.38);
}

.hero-glow {
  /* Bleeds to the true viewport edge like .hero-visual just above, same
     absolute + left:50% + width:100vw + negative margin-left combo.
     filter:blur(10px) is gone too - it was a second live blur filter on
     this page (the same WebKit ink-overflow-escapes-overflow:hidden bug
     .hero-visual img's blur hit).

     Shape is "ellipse", not "circle" - the actual bug behind the visible
     horizontal seam partway down the hero. With no explicit size, a
     radial-gradient's default sizing is farthest-corner; for "circle"
     that resolves to one radius shared by both axes, sized off this
     box's diagonal - and since the box is nearly the full viewport wide
     but only a couple hundred px tall, that shared radius is enormous
     next to the box's own height. "transparent 55%" never actually gets
     reached going downward before the box's bottom edge does, so the
     gradient just gets hard-clipped there instead of fading out - a
     sharp rectangle edge, not a soft glow. "ellipse" sizes its two radii
     independently per axis, so the vertical radius actually matches this
     short box and reaches transparent well inside it.

     Also scoped to sit behind the header/logo specifically (small,
     ending shortly past it) rather than stretching deep into the hero -
     it's meant as an accent behind the masthead, not ambient lighting
     for the whole hero. */
  position: absolute;
  top: -160px;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  height: 320px;
  background:
    radial-gradient(ellipse at 30% 30%, rgba(63, 167, 111, 0.28), transparent 55%),
    radial-gradient(ellipse at 75% 45%, rgba(217, 201, 163, 0.16), transparent 50%);
  pointer-events: none;
  z-index: 1;
}

.hero-inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: 56px;
  align-items: end;
}

.eyebrow {
  color: var(--cream);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 22px;
}

h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(40px, 5.6vw, 76px);
  line-height: 1.04;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

.lede {
  font-size: 18px;
  line-height: 1.65;
  color: var(--text-muted);
  margin: 0 0 24px;
}

.hero-cta {
  grid-column: 1 / -1;
  margin-top: 40px;
}

.cta-row {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

.buy-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--green);
  color: #0e1410;
  font-weight: 700;
  font-size: 16px;
  padding: 16px 28px;
  border-radius: var(--radius);
  transition: opacity 0.15s ease;
}
.buy-button:hover { opacity: 0.88; text-decoration: none; }

.price-old {
  position: relative;
  display: inline-block;
  opacity: 0.65;
}
.price-old::after {
  content: "";
  position: absolute;
  left: -3px;
  right: -3px;
  top: 50%;
  height: 2px;
  background: currentColor;
  transform: rotate(-14deg);
}

.price-note {
  color: var(--text-muted);
  font-size: 14px;
}
.price-note strong { color: var(--text); font-size: 15px; }

.platforms {
  margin-top: 28px;
  color: var(--text-muted);
  font-size: 13px;
  letter-spacing: 0.03em;
}

@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; }
  /* height/top only - width stays 100vw (set above) via the bleed
     mechanism, a fixed px width here would fight it on phones. */
  .hero-glow { height: 280px; top: -140px; }
}

/* ---------- Shared section rhythm ---------- */

section.features,
section.videos,
section.screens,
section.modes,
section.faq {
  padding: 96px 0;
  border-bottom: 1px solid var(--panel-border);
}

section.license { padding: 96px 0; }

section.features h2,
section.videos h2,
section.screens h2,
section.modes h2,
section.faq h2,
section.license h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(28px, 3.4vw, 42px);
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 24px;
}

.feature-card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  padding: 22px;
}

.feature-card h3 {
  font-size: 15px;
  margin: 0 0 8px;
  color: var(--cream);
}

.feature-card p {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.55;
  margin: 0;
}

.section-note {
  color: var(--text-muted);
  font-size: 15px;
  margin: 0 0 40px;
  max-width: 640px;
  line-height: 1.65;
}

.carousel {
  position: relative;
}

.carousel-track {
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding: 2px 2px 6px;
  margin: 0 -2px;
}
.carousel-track::-webkit-scrollbar { display: none; }

.carousel-track > * {
  flex: 0 0 auto;
  scroll-snap-align: start;
}

.carousel-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--panel-border);
  background: var(--bg);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.92;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.carousel-btn:hover { opacity: 1; background: var(--panel); }
.carousel-prev { left: -20px; }
.carousel-next { right: -20px; }

@media (max-width: 640px) {
  .carousel-btn { display: none; }

  .screens-deck {
    width: min(760px, 90vw);
  }
}

.video-card {
  width: min(420px, 82vw);
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.video-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
}

.video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.video-caption {
  padding: 16px 18px;
}

.video-caption .video-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 4px;
}

.video-caption .video-tag {
  font-size: 12px;
  color: var(--cream);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.fan-tabs {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}

.fan-tab {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 600;
  padding: 10px 22px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.fan-tab:hover { color: var(--text); }
.fan-tab.active {
  background: var(--green);
  color: #0e1410;
  border-color: var(--green);
}

/* Real single-slide carousel: one screenshot visible at a time, full
   size, in a fixed-aspect frame. Switching tabs slides the outgoing
   slide off one side and brings the next one in from the other -
   direction follows tab order (a later tab enters from the right and
   pushes the current one out to the left, an earlier tab reverses it) -
   not the old fan deck's "one flies out, another flies into its spot"
   swap, and not the flat scroll-snap track either (which left the
   active screenshot off-center depending on scroll position). */
.screens-deck {
  position: relative;
  width: min(900px, 62vw);
  margin: 0 auto;
  aspect-ratio: 1800 / 936;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 30px 70px -16px rgba(0, 0, 0, 0.75);
}

.screen-slide {
  position: absolute;
  inset: 0;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--panel);
  transition: transform 0.5s cubic-bezier(0.22, 0.9, 0.24, 1);
}

.screen-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

.screen-slide[data-state="active"] { transform: translateX(0); z-index: 2; }
.screen-slide[data-state="left"] { transform: translateX(-100%); z-index: 1; }
.screen-slide[data-state="right"] { transform: translateX(100%); z-index: 1; }

section.banner {
  /* Bleeds to the true viewport edge, same as .hero-visual/.hero-glow -
     this element's own img was never blurred/filtered/transformed
     (that was only ever .hero-visual img and .hero-glow), so there was
     never actually a reason this one needed to stay boxed in. Normal
     document flow here (not position:absolute like the hero layers,
     which need to sit behind other content instead of taking up their
     own space), so the classic left:50% + width:100vw + negative
     margin-left combo applies directly without an extra position
     change. */
  position: relative;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  overflow: hidden;
  border-bottom: 1px solid var(--panel-border);
}

section.banner img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 760px;
  object-fit: cover;
  object-position: center bottom;
}

section.banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      var(--bg) 0%,
      rgba(19, 19, 22, 0.7) 5%,
      rgba(19, 19, 22, 0.3) 10%,
      transparent 18%,
      transparent 82%,
      rgba(19, 19, 22, 0.3) 90%,
      rgba(19, 19, 22, 0.7) 95%,
      var(--bg) 100%);
  pointer-events: none;
}

.modes-list {
  display: flex;
  flex-direction: column;
  gap: 32px;
  margin-top: 48px;
}

.mode-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 32px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--panel-border);
}
.mode-row:last-child { border-bottom: none; padding-bottom: 0; }

.mode-row .mode-name {
  font-family: var(--display);
  color: var(--cream);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.mode-row p {
  margin: 0;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1.65;
  max-width: 620px;
}

.faq-list { display: flex; flex-direction: column; gap: 10px; margin-top: 40px; }

.faq-item {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  padding: 4px 22px;
}

.faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 18px 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.faq-item summary::-webkit-details-marker { display: none; }

.faq-item summary::after {
  content: "+";
  color: var(--green);
  font-size: 22px;
  font-weight: 400;
  flex-shrink: 0;
}
.faq-item[open] summary::after { content: "−"; }

.faq-item p {
  margin: 0 0 20px;
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.65;
}

.license-list {
  list-style: none;
  padding: 0;
  margin: 32px 0 0;
  color: var(--text-muted);
  font-size: 16px;
  line-height: 2.1;
}
.license-list li::before {
  content: "—";
  color: var(--green);
  margin-right: 10px;
}

footer {
  border-top: 1px solid var(--panel-border);
  padding: 32px 40px 48px;
  max-width: var(--shell);
  width: 100%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  position: relative;
  z-index: 2;
}

footer .links a {
  color: var(--text-muted);
  font-size: 13px;
  margin-right: 20px;
}
footer .links a:hover { color: var(--text); text-decoration: none; }
footer .links a#lostKeyLink { margin-right: 0; }

footer .copyright {
  color: var(--text-muted);
  font-size: 13px;
}

.legal-page main {
  padding-top: 72px;
  padding-bottom: 80px;
  max-width: 760px;
}

.legal-page h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(32px, 4vw, 44px);
  margin-bottom: 8px;
}

.legal-page .updated {
  color: var(--text-muted);
  font-size: 13px;
  margin-bottom: 44px;
}

.legal-page h2 {
  font-size: 19px;
  margin: 40px 0 12px;
  color: var(--cream);
}

.legal-page p, .legal-page li {
  color: var(--text-muted);
  font-size: 16px;
  line-height: 1.75;
}

.legal-page ul { padding-left: 20px; }

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(6, 6, 8, 0.7);
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}
.modal-overlay.open { display: flex; }

.modal {
  position: relative;
  width: 100%;
  max-width: 380px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  padding: 28px 24px 24px;
}

.modal h3 {
  margin: 0 0 8px;
  font-size: 18px;
  color: var(--text);
}

.modal-note {
  margin: 0 0 20px;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.55;
}

.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 4px;
}
.modal-close:hover { color: var(--text); }

#lostKeyForm {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

#lostKeyForm input {
  background: var(--bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  color: var(--text);
  font-size: 15px;
  padding: 12px 14px;
}
#lostKeyForm input:focus {
  outline: none;
  border-color: var(--green);
}

.modal-submit {
  background: var(--green);
  color: #0e1410;
  font-weight: 600;
  font-size: 15px;
  border: none;
  border-radius: var(--radius);
  padding: 12px 16px;
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.modal-submit:hover { opacity: 0.88; }
.modal-submit:disabled { opacity: 0.6; cursor: default; }

.modal-result {
  margin: 16px 0 0;
  font-size: 13px;
  color: var(--cream);
  line-height: 1.5;
}

@media (max-width: 640px) {
  .hero { padding: 40px 0 0; }
  header { flex-direction: column; align-items: flex-start; gap: 12px; padding: 24px; }
  /* Narrower than desktop's 40px, but reduced further from an earlier
     24px specifically so .hero-visual/.hero-glow (which now just fill
     main's own content box, no bleed-past-padding trick - see their own
     comments) read closer to the real device edge instead of leaving a
     visibly wide margin down each side on a phone. */
  main { padding: 0 16px; }
  nav a { margin-left: 0; margin-right: 20px; }
  .mode-row { grid-template-columns: 1fr; gap: 8px; }
  section.features, section.videos, section.screens, section.modes, section.faq, section.license {
    padding: 64px 0;
  }
}
