@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
    U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #0b0b0d;
  --bg-alt: #111114;
  --fg: #f2f2f3;
  --muted: #9a9aa2;
  --accent: #5b8cff;
  --accent-hover: #7ba0ff;
  --border: #232327;
  --card: #17171a;
  --font-sans: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  /* Deep blue -> bright azure, used for both the ring and the bloom behind it. */
  --glow: linear-gradient(115deg, #1e40af 0%, #2f6bff 30%, #0ea5e9 62%, #38bdf8 82%, #2f6bff 100%);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  line-height: 1.5;
}

h1, h2 {
  font-weight: 700;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

.wrap {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 24px;
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  border-radius: 12px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.2s ease, filter 0.2s ease;
}

/* Silver gradient border, black fill, white text.
   Two backgrounds: the flat fill clipped to padding-box sits on top of the
   gradient clipped to border-box, so only the 1px border shows the gradient. */
.btn-primary {
  position: relative;
  padding: 15px 30px;
  font-size: 1rem;
  color: #fff;
  border: 1.5px solid transparent;
  background:
    linear-gradient(#0d0d10, #0d0d10) padding-box,
    linear-gradient(135deg, #c9c9d1 0%, #5c5c65 22%, #d5d5dc 46%, #4a4a52 68%, #b0b0b9 88%, #64646d 100%) border-box;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06) inset, 0 8px 24px -12px rgba(0, 0, 0, 0.9);
}

/* Hover lifts the button and brightens the silver rim into a blue glow, so
   the state change is obvious rather than a subtle brightness shift. */
.btn-primary:hover {
  transform: translateY(-2px);
  background:
    linear-gradient(#131319, #101015) padding-box,
    linear-gradient(135deg, #eaeaf2 0%, #8f9fd0 22%, #ffffff 46%, #6d7ea8 68%, #dfe4f5 88%, #7d8db8 100%) border-box;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.12) inset,
    0 12px 30px -12px rgba(0, 0, 0, 0.95),
    0 0 28px -6px rgba(91, 140, 255, 0.45);
}

.btn-primary:active {
  transform: translateY(1px);
}

.btn-small {
  padding: 10px 18px;
  font-size: 0.88rem;
  color: #fff;
  border: 1.5px solid transparent;
  background:
    linear-gradient(#0d0d10, #0d0d10) padding-box,
    linear-gradient(135deg, #c9c9d1 0%, #5c5c65 22%, #d5d5dc 46%, #4a4a52 68%, #b0b0b9 88%, #64646d 100%) border-box;
}

.btn-small:hover {
  filter: brightness(1.12);
}

.apple-icon {
  flex-shrink: 0;
}

/* Hero */
.hero {
  padding: 96px 0 56px;
  text-align: center;
}

.hero h1 {
  font-size: 2.6rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 20px;
}

.subhead {
  max-width: 620px;
  margin: 0 auto 36px;
  color: var(--muted);
  font-size: 1.15rem;
}

.cta-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.hint {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}

/* Screenshots */
.screenshot-section {
  padding: 5px 0 80px;
}

.screenshot-section .wrap img,
.screenshot-section .wrap video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
  border: 1px solid var(--border);
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.7);
}

/* Screenshots that already carry their own window chrome and dark surround
   sit flush on the page with no added frame. */
.screenshot-section .wrap img.no-frame,
.screenshot-section .wrap video.no-frame {
  border: none;
  border-radius: 0;
  box-shadow: none;
}

/* Media cropped flush to the app window needs the window's own corner radius
   back, otherwise its square black corners show against the page. */
.screenshot-section .wrap video.no-frame {
  border-radius: 11px;
}

/* Glowing gradient ring + outer bloom around the demo.
   The wrapper's own gradient background shows through its padding as the ring;
   ::before repaints that same gradient, heavily blurred, as the bloom behind. */
.glow-frame {
  position: relative;
  isolation: isolate;
  padding: 2px;
  border-radius: 13px;
  background: var(--glow);
}

/* Two bloom layers: a tight bright halo hugging the ring, and a wide soft
   wash further out. Together they read as light spilling onto the page. */
.glow-frame::before,
.glow-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--glow);
  pointer-events: none;
}

.glow-frame::before {
  z-index: -1;
  filter: blur(20px);
  opacity: 0.9;
}

.glow-frame::after {
  z-index: -2;
  filter: blur(70px);
  opacity: 0.65;
  transform: scale(1.04);
}

.glow-frame video {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 800px) {
  .glow-frame::before { filter: blur(12px); }
  .glow-frame::after { filter: blur(40px); }
}

/* Price line. The two side pieces are absolutely positioned against the
   panel's own edges, and the run across the panel is the panel's border-top,
   so the three parts cannot drift apart or leave a gap at the join.

   The previous version used a rounded bridge element: border-radius pulled
   the border inwards from the corner while the lines ended at the corner
   point, which is where the gap came from. Square corners here, so the
   border spans the panel's full width and the ends meet exactly.

   Hidden below the panel breakpoint, where there is no box to run along. */
.ticker {
  display: none;
  position: absolute;
  top: 0;
  /* An svg is a replaced element: with height auto it sizes from its viewBox
     ratio and ignores bottom, so the height is set explicitly. */
  height: 100%;
  width: calc((100vw - var(--panel-w)) / 2);
  pointer-events: none;
  filter: drop-shadow(0 0 8px rgba(246, 70, 93, 0.22));
}

/* Weight comes from the same variable the wrap border uses, so the line is a
   single consistent thickness the whole way round. */
.ticker polyline {
  stroke-width: var(--line-w);
}

.ticker-left {
  right: 100%;
}

.ticker-right {
  left: 100%;
}

/* Social proof. Padding is symmetric, and the neighbouring sections are
   tuned so the visible gap above and below matches. */
.about {
  --panel-w: 880px;
  /* Integer: Chromium rounds border-width to whole pixels, so a fractional
     value would render thinner on the border than on the svg strokes. */
  --line-w: 2px;
  --line-c: rgba(246, 70, 93, 0.4);
  --panel-radius: 22px;
  position: relative;
  padding: 160px 0;
}

.about-inner {
  position: relative;
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 22px;
  text-align: left;
}

.avatar {
  flex-shrink: 0;
  width: 76px;
  height: 76px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid rgba(108, 180, 255, 0.3);
}

.about-inner p {
  margin: 0;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.6;
}

.about-inner a {
  color: var(--accent);
  text-decoration: none;
}

.about-inner a:hover {
  color: var(--accent-hover);
}

/* Larger where there is room for it. Placed after the base rules so it wins
   on equal specificity. */
@media (min-width: 1281px) {
  .ticker {
    display: block;
  }

  /* No panel fill: the red line forms the top edge and the quote sits under
     it. Padding and width are kept so the line's join stays aligned. */
  .about-inner {
    gap: 26px;
    max-width: var(--panel-w);
    padding: 30px 38px;
  }

  /* The line wrapping the box: up each side to the halfway point, around the
     rounded corners and across the top. Drawn as a real border with no bottom
     edge, so weight and colour are the same values the strokes use. */
  .about-inner::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 50%;
    border: var(--line-w) solid var(--line-c);
    border-bottom: 0;
    border-radius: var(--panel-radius) var(--panel-radius) 0 0;
    pointer-events: none;
    filter: drop-shadow(0 0 8px rgba(246, 70, 93, 0.22));
  }

  .about-inner p {
    font-size: 20px;
  }

  /* Scaled by the same ratio as the text (20/16) so the pairing holds. */
  .avatar {
    width: 95px;
    height: 95px;
  }
}

@media (max-width: 767px) {
  /* Too little width to sit a photo beside the quote. */
  .avatar {
    display: none;
  }

  .about-inner {
    gap: 0;
  }
}

/* Features, stacked as rows inside the final CTA. Kept narrow so the two
   flanking videos never reach the text. */
.feature-rows {
  position: relative;
  /* Fluid: fills the column up to a readable cap. Above the video breakpoint
     it also scales with the viewport so it never crowds the two frames. */
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  /* Cards carry their own padding, so they need less space between them. */
  gap: 20px;
  text-align: left;
}

/* Card per feature. The border is a gradient clipped to border-box, brighter
   along the top edge and fading down, which reads as light catching the rim
   rather than a flat outline. */
.feature-row {
  position: relative;
  z-index: 1;
  padding: 28px 30px 30px;
  border-radius: 26px;
  border: 1px solid transparent;
  background:
    linear-gradient(#101014, #0e0e11) padding-box,
    linear-gradient(170deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.07) 34%, rgba(255, 255, 255, 0.03) 70%) border-box;
  box-shadow:
    0 24px 50px -34px rgba(0, 0, 0, 0.95),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

.feature-row h2 {
  font-size: 1.3rem;
  /* Body line-height (1.5) adds leading below the heading, so most of the
     visible gap comes from that rather than the margin. */
  line-height: 1.2;
  margin: 0 0 5px;
}

.feature-row p {
  color: var(--muted);
  margin: 0;
  font-size: 1.02rem;
}

/* On narrower screens the card keeps shrinking but its padding and radius do
   not, which leaves the copy cramped inside a disproportionately round box.
   Scale them down with it. */
@media (max-width: 700px) {
  .feature-rows {
    gap: 16px;
  }

  .feature-row {
    padding: 22px 22px 24px;
    border-radius: 20px;
  }

  .feature-row h2 {
    font-size: 1.15rem;
  }

  .feature-row p {
    font-size: 0.95rem;
  }
}

@media (max-width: 430px) {
  .feature-row {
    padding: 18px 18px 20px;
    border-radius: 16px;
  }

  .feature-row h2 {
    font-size: 1.05rem;
  }

  .feature-row p {
    font-size: 0.9rem;
  }
}

/* Each card carries a shot of the feature. Hidden while the flanking videos
   are on screen, since they already show the app. */
.card-shot {
  display: none;
  width: 100%;
  height: auto;
  margin-top: 20px;
  border-radius: 12px;
  /* Echoes the treatment on the flanking videos these stand in for. */
  border: 1px solid rgba(108, 180, 255, 0.38);
  box-shadow:
    0 0 22px -8px rgba(47, 107, 255, 0.45),
    0 0 46px -18px rgba(56, 189, 248, 0.3);
}

@media (max-width: 1280px) {
  .card-shot {
    display: block;
  }
}

/* Final CTA */
.cta-final {
  position: relative;
  text-align: center;
  /* Top padding matches the video section's bottom padding, so the About
     block above sits with equal space on each side. Bottom stays larger to
     keep the full video frame clear of the overflow clip. */
  padding: 80px 0 130px;
  overflow: hidden;
}

/* Two decorative copies of the demo, each pushed 60% past its edge so only
   40% of the frame is on screen and it reads as running off the page. */
/* A mask clips to the element's box, so a glow on the masked element itself
   gets erased. The wrapper carries the mask and 70px of padding; the glow
   lives on the video inside, safely within the masked area. */
.cta-glow {
  position: absolute;
  top: 50%;
  box-sizing: border-box;
  padding: 70px;
  /* Content box stays the intended video width; scales with the viewport so
     the two copies never close in on the text. */
  width: calc(min(830px, 42vw) + 140px);
  pointer-events: none;
  z-index: 0;
}

.cta-video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 11px;
  /* Brighter than the bloom so the edge stays crisp against it. */
  border: 1px solid rgba(108, 180, 255, 0.8);
  /* Subtler cousin of the hero's bloom. */
  box-shadow:
    0 0 46px -14px rgba(47, 107, 255, 0.5),
    0 0 92px -28px rgba(56, 189, 248, 0.34);
}

/* Shifted so 60% of the frame is on screen, fading out towards the page edge
   and staying solid on the inner, text-facing side. */
.cta-glow-left {
  left: 0;
  transform: translate(-41.5%, -50%);
  -webkit-mask-image: linear-gradient(to right, transparent 41%, rgba(0, 0, 0, 0.5) 58%, #000 74%);
  mask-image: linear-gradient(to right, transparent 41%, rgba(0, 0, 0, 0.5) 58%, #000 74%);
}

.cta-glow-right {
  right: 0;
  transform: translate(41.5%, -50%);
  -webkit-mask-image: linear-gradient(to left, transparent 41%, rgba(0, 0, 0, 0.5) 58%, #000 74%);
  mask-image: linear-gradient(to left, transparent 41%, rgba(0, 0, 0, 0.5) 58%, #000 74%);
}

.cta-final .wrap {
  position: relative;
  z-index: 1;
}

/* At this larger size the solid inner edge reaches the headline below about
   1200px (measured), so the copies drop out rather than sit under the text. */
/* Once the flanking videos appear, the cards share the width with them, so
   they scale as a fraction of the viewport rather than holding a fixed size. */
@media (min-width: 1281px) {
  .feature-rows {
    max-width: min(780px, 44vw);
  }
}

/* Below this the flanking videos are gone, so the About block tightens up.
   The visible gap is the sum of neighbouring paddings: 20 + 20 = 40px. */
@media (max-width: 1280px) {
  .cta-glow {
    display: none;
  }

  .screenshot-section {
    padding-bottom: 20px;
  }

  .about {
    padding: 40px 0;
  }

  .cta-final {
    padding: 20px 0 96px;
  }

  /* No videos to leave room for, so the cards run the full page width.
     The wrap's 1100px cap has to go too, or it centres with wide margins. */
  .cta-final .wrap {
    max-width: none;
    padding: 0 20px;
  }

  .feature-rows {
    max-width: none;
  }

  /* Keep the demo clear of the screen edges. */
  .glow-frame {
    margin: 0 10px;
  }
}

@media (max-width: 700px) {
  .cta-final {
    padding: 20px 0 72px;
  }
}

/* Footer */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 28px 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.site-footer .wrap {
  display: flex;
  gap: 24px;
  align-items: center;
  flex-wrap: wrap;
  max-width: none;
  margin: 0;
  padding: 0 20px;
}

/* Pushed to the far end, away from the links. */
.copyright {
  margin-left: auto;
}

@media (max-width: 600px) {
  .copyright {
    margin-left: 0;
  }
}

.site-footer a {
  color: var(--muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--fg);
}

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

  .hero {
    padding: 64px 0 40px;
  }
}
