/*
 * Passwordless landing page.
 *
 * Implemented from the Figma source (file Z73Dwa1aQScM3USWrz9Eb7, node 6:128).
 * Tokens below are the file's own named styles, kept under their Figma names so
 * the two stay traceable: Brand 2, Indigo/500, Indigo/50, Indigo/25, Gray/900,
 * Gray/500, Gray/200.
 *
 * The design is a fixed 1920 canvas; this is laid out in flow and flex so it
 * survives a real viewport. At >=1920 it matches the canvas; below that the
 * wells, type and grids scale down.
 */

:root {
  /* Figma named styles */
  --navy: #00003a; /* Brand 2      */
  --indigo-500: #6172f3; /* Indigo/500   */
  --indigo-50: #eef4ff; /* Indigo/50    */
  --indigo-25: #f5f8ff; /* Indigo/25    */
  --gray-900: #181d27; /* Gray/900     */
  --gray-500: #717680; /* Gray/500     */
  --gray-200: #e9eaeb; /* Gray/200     */
  --white: #fff;

  --disp: "Montserrat", ui-sans-serif, system-ui, sans-serif;
  --body: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;

  /* One content well for every section — nav, hero, panel inner, quotes rail,
     contact card, footer. The Figma canvas had these at 1441/1476/1480/1482,
     which is rounding noise, not design intent; five near-identical numbers
     just make the section edges fail to line up down the page. */
  --well: 1480px;
  /* The white panel is the one container deliberately wider than the well. */
  --panel-w: 1840px;
  --gutter: clamp(20px, 4vw, 40px);
  --section-y: clamp(64px, 8vw, 124px);

  color-scheme: light;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  background: var(--navy);
}

body {
  margin: 0;
  background: var(--white);
  color: var(--gray-900);
  font-family: var(--body);
  font-size: 16px;
  line-height: 24px;
  -webkit-font-smoothing: antialiased;
  /* `clip`, not `hidden`: `hidden` makes <body> itself the scroll container,
     which breaks wheel scrolling and scroll anchoring. `clip` just clips. */
  overflow-x: clip;
}

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

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--indigo-500);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  left: 16px;
  top: 12px;
  z-index: 99;
  background: var(--white);
  color: var(--navy);
  padding: 10px 16px;
  border-radius: 8px;
}

.well {
  width: 100%;
  max-width: var(--well);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  padding-inline: 24px;
  border-radius: 8px;
  font-family: var(--body);
  font-weight: 600;
  font-size: 16px;
  line-height: 24px;
  text-decoration: none;
  white-space: nowrap;
  transition: opacity 0.14s ease;
}

.btn:hover {
  opacity: 0.88;
}

/*
 * Platform glyph slot, to the right of the label.
 *
 * Drawn as a CSS mask filled with `currentColor` rather than an <img>, because
 * the same button appears with three different text colours (navy on white,
 * white on navy, white outlined). A flat single-colour file would be wrong in
 * two of the three; masking means the glyph always matches the label.
 *
 * Supply the artwork at the path below. Nothing renders until that file
 * exists — `mask-image` on a missing URL masks everything out, so the slot
 * stays invisible rather than showing a broken image or a solid block.
 */
.btn__icon {
  display: inline-block;
  flex: none;
  /* 814 x 1000 intrinsic — keep the 0.814 ratio exactly; masks stretch. */
  width: 14.65px;
  height: 18px;
  margin-left: 10px;
  translate: 0 -1px; /* optical centring — the mark sits low otherwise */
  background: currentColor;
  -webkit-mask: url("/assets/fig/platform-mark.svg") no-repeat center / contain;
  mask: url("/assets/fig/platform-mark.svg") no-repeat center / contain;
}

.btn--white {
  background: var(--white);
  color: var(--navy);
}

.btn--outline-white {
  border: 1px solid var(--white);
  color: var(--white);
}

.btn--outline-navy {
  border: 1px solid var(--navy);
  color: var(--navy);
}

/* ── Dark region ───────────────────────────────────────────────────────── */

.dark {
  position: relative;
  background: var(--navy);
  isolation: isolate;
  /* The glow artwork is a fixed 1920px wide and centred, so below a 1920px
     viewport it spills (1920 - vw) / 2 past each edge. Clip it here at its
     own container rather than leaning on a page-level overflow rule. */
  overflow: hidden;
}

.dark__glow,
.dark__fade-top,
.dark__fade-bottom {
  position: absolute;
  left: 0;
  right: 0;
  z-index: -1;
  pointer-events: none;
}

.dark__glow {
  top: 90px;
  display: flex;
  justify-content: center;
}

.dark__glow img {
  width: 1920px;
  max-width: none;
  opacity: 0.8;
  transform: rotate(180deg);
}

.dark__fade-top {
  top: 0;
  height: 841px;
  background: linear-gradient(to bottom, var(--navy), rgb(0 0 58 / 0%));
}

.dark__fade-bottom {
  top: 1032px;
  height: 441px;
  background: linear-gradient(to top, var(--navy), rgb(0 0 58 / 0%));
}

/* ── Nav ───────────────────────────────────────────────────────────────── */

.nav__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 124px;
}

.nav__brand img {
  width: 184px;
  height: 38px;
}

/*
 * Centred on the page, not on what is left over. In flow, the links sit
 * between a 184px wordmark and a ~98px button, so space-between puts their
 * midpoint about 40px right of centre. Taking them out of flow centres them on
 * the well, which is itself centred in the viewport, so the group lines up with
 * the page's axis no matter what the brand or the button weigh.
 */
.nav__links {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 40px;
  font-weight: 500;
  color: var(--white);
}

.nav__links a {
  text-decoration: none;
}

.nav__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 24px;
  flex: none;
}

.nav__actions .btn {
  height: 48px;
  padding-inline: 16px;
  font-size: 14px;
  line-height: 20px;
}

@media (max-width: 1100px) {
  .nav__links {
    display: none;
  }

  .nav__actions {
    width: auto;
  }
}

/* ── Hero ──────────────────────────────────────────────────────────────── */

.hero {
  padding-top: clamp(56px, 7vw, 96px);
}

.hero__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 40px;
}

.hero__copy {
  max-width: 961px;
}

.hero__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(40px, 5vw, 72px);
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--white);
}

.hero__lede {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 28px;
  color: var(--white);
}

.hero__copy .btn {
  margin-top: 48px;
}

.hero__badge {
  width: 109px;
  height: 109px;
  flex: none;
}

@media (max-width: 900px) {
  .hero__badge {
    display: none;
  }
}

/* ── Hero cards ────────────────────────────────────────────────────────── */

.hero__cards {
  display: grid;
  grid-template-columns: minmax(0, 979fr) minmax(0, 477fr);
  gap: 24px;
  margin-top: 80px;
}

@media (max-width: 1000px) {
  .hero__cards {
    grid-template-columns: 1fr;
  }
}

.showcase {
  position: relative;
  overflow: hidden;
  background: var(--white);
  border-radius: 24px;
  min-height: 528px;
  /* Right padding matches the left now that the body reaches that edge; it was
     0 while the copy was a narrow column pinned bottom-left. */
  padding: 61px 55px 64px;
  display: flex;
  flex-direction: column;
}

/*
 * Title and body sit side by side across the top, with the artwork filling the
 * space beneath. `flex-start` rather than `baseline` — the two have very
 * different type sizes, so a shared baseline would drop the body too far down.
 */
.showcase__copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 32px;
}

.showcase__title {
  margin: 0;
  flex: 0 1 auto;
  width: 100%;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(26px, 2.4vw, 36px);
  line-height: 1.22;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

.showcase__body {
  margin: 0;
  width: 100%;
  flex: 0 1 auto;
  color: var(--gray-500);
}

/* ── Supported languages ───────────────────────────────────────────────── */

.langs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
}

.lang {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border: 1px solid var(--gray-200);
  border-radius: 999px; /* capsule — any radius past half the height will do */
  color: var(--gray-900);
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  white-space: nowrap;
}

/*
 * The marks are single-path monochrome files with no colour of their own, so
 * whatever is painted through the mask becomes the logo. That is what lets a
 * plain <span> carry a brand-coloured mark with no per-language markup.
 */
.lang__mark {
  flex: none;
  width: 14px;
  height: 14px;
  /* Each pill supplies its own brand hex below. `currentColor` is the
     fallback, so a pill with no `--mark-color` still gets a mark matching its
     label rather than nothing at all. */
  background: var(--mark-color, currentColor);
  -webkit-mask: var(--mark) no-repeat center / contain;
  mask: var(--mark) no-repeat center / contain;
}

.lang--elixir {
  --mark: url("/assets/lang/elixir.svg");
  --mark-color: #4b275f;
}

.lang--go {
  --mark: url("/assets/lang/go.svg");
  --mark-color: #00add8;
}

.lang--java {
  --mark: url("/assets/lang/java.svg");
  --mark-color: #000000;
}

.lang--javascript {
  --mark: url("/assets/lang/javascript.svg");
  --mark-color: #f7df1e;
}

.lang--json {
  --mark: url("/assets/lang/json.svg");
  --mark-color: #000000;
}

.lang--php {
  --mark: url("/assets/lang/php.svg");
  --mark-color: #777bb4;
}

.lang--python {
  --mark: url("/assets/lang/python.svg");
  --mark-color: #3776ab;
}

.lang--ruby {
  --mark: url("/assets/lang/ruby.svg");
  --mark-color: #cc342d;
}

.lang--rust {
  --mark: url("/assets/lang/rust.svg");
  --mark-color: #000000;
}

.lang--scala {
  --mark: url("/assets/lang/scala.svg");
  --mark-color: #dc322f;
}

.lang--sql {
  --mark: url("/assets/lang/sql.svg");
  --mark-color: #4169e1;
}

.showcase__art {
  position: absolute;
  left: 0;
  top: 30%;
  width: 100%;
  max-width: none;
  pointer-events: none;
}

@media (max-width: 1300px) {
  .showcase {
    min-height: 0;
    padding-inline: 32px;
    max-height: 550px;
  }

  .showcase__art {
    position: static;
    margin-top: 32px;
    opacity: 1;
  }
}

/*
 * Narrow viewports.
 *
 * The bleed cannot survive here. `min-height` has already dropped to 0, so the
 * showcase collapses to the height of its copy — and an absolutely positioned
 * crop 120% wide, offset 30% down a box that is now only as tall as two
 * paragraphs, is clipped by `overflow: hidden` into a meaningless sliver.
 *
 * So the screenshot stops being a decorative bleed and becomes content: in
 * normal flow beneath the copy, full width, undimmed, at its own aspect ratio.
 */
@media (max-width: 1000px) {
  .showcase__art {
    position: static;
    margin-top: 16px;
    opacity: 1;
  }

  .showcase {
    padding: 32px 24px;
    max-height: 500px;
  }
}

.video {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 24px;
  background: var(--white);
  min-height: 528px;
}

.video__frame {
  position: relative;
  flex: 1 0 0;
  min-height: 300px;
  overflow: hidden;
}

.video__thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video__play {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 60px;
  height: 60px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 100px;
  background: rgb(255 255 255 / 16%);
  backdrop-filter: blur(2px);
  cursor: pointer;
}

.video__caption {
  padding: 32px 24px;
  background: var(--white);
}

.video__caption p {
  margin: 0;
  font-weight: 500;
  font-size: 20px;
  line-height: 30px;
  color: var(--gray-900);
}

.video__caption span {
  color: var(--gray-500);
}

/* ── Logo strip ────────────────────────────────────────────────────────── */

.logos {
  display: flex;
  align-items: center;
  /* A single mark, so there is nothing to space apart — centre it rather than
     strand it at the left edge of the rail. */
  justify-content: center;
  flex-wrap: wrap;
  gap: 32px;
  padding-block: var(--section-y);
  opacity: 0.6;
}

.logos img {
  height: 40px;
  width: auto;
}

/*
 * The placeholder logos were white but carried opacity 0.6-0.8 on their own
 * parts, so under the rail's 0.6 they landed near 0.42. opentide.svg is flat
 * white with none of that, so it needs the difference applied here to sit at
 * the same weight as the marks it replaced.
 */
.logos__mark {
  opacity: 0.7;
}

/* ── White panel ───────────────────────────────────────────────────────── */

.panel {
  position: relative;
  z-index: 1;
  width: min(var(--panel-w), calc(100% - 2 * var(--gutter)));
  margin-inline: auto;
  background: var(--white);
  border-radius: clamp(24px, 3vw, 48px);
  overflow: hidden;
}

.panel__inner {
  width: 100%;
  max-width: var(--well);
  margin-inline: auto;
  padding: var(--section-y) var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 80px;
}

.head {
  max-width: 845px;
  margin-inline: auto;
  text-align: center;
}

.head__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(32px, 4vw, 60px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

.head__sub {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 28px;
  color: var(--gray-500);
}

/* ── Stats ─────────────────────────────────────────────────────────────── */

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

@media (max-width: 1000px) {
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 520px) {
  .stats {
    grid-template-columns: 1fr;
  }
}

.stat {
  border: 1px solid var(--gray-200);
  border-radius: 16px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 48px;
}

.stat__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.stat__n {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: 36px;
  line-height: 44px;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

.stat__icon {
  display: grid;
  place-items: center;
  padding: 12px;
  border-radius: 100px;
  background: var(--indigo-50);
}

.stat__label {
  margin: 0;
  font-weight: 500;
  color: var(--gray-500);
}

.rule {
  width: 100%;
  height: 0;
  margin: 0;
  border: 0;
  border-top: 1px solid var(--gray-200);
}

/* ── Split ─────────────────────────────────────────────────────────────── */

.split {
  display: grid;
  grid-template-columns: 431px minmax(0, 1fr);
  gap: 70px;
  align-items: flex-end;
}

@media (max-width: 1200px) {
  .split {
    grid-template-columns: 1fr;
    gap: 40px;
  }
}

.split__copy {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  height: 100%;
}

.split__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(26px, 2.4vw, 36px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

.split__body {
  margin: 32px 0 0;
  max-width: 400px;
  color: var(--gray-500);
}

.split__copy .btn {
  align-self: flex-start;
}

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

@media (max-width: 760px) {
  .split__cards {
    grid-template-columns: 1fr;
  }
}

.fcard {
  position: relative;
  overflow: hidden;
  border-radius: 24px;
  height: 465px;
  isolation: isolate;
}

.fcard__copy {
  position: absolute;
  inset: 32px 32px auto 32px;
  z-index: 3;
}

.fcard__title {
  margin: 0;
  font-weight: 500;
  font-size: 20px;
  line-height: 30px;
}

.fcard__sub {
  margin: 16px 0 0;
}

.fcard--dark {
  background: var(--navy);
}

.fcard--dark .fcard__title {
  color: var(--white);
}

.fcard--dark .fcard__sub {
  color: var(--white);
}

.fcard__bg {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 1036px;
  max-width: none;
  rotate: 180deg;
  z-index: 0;
}

.fcard__shot {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: 220px;
  width: 414px;
  max-width: none;
  border-radius: 12px;
  z-index: 2;
}

.fcard__veil {
  position: absolute;
  inset: 0 0 auto 0;
  height: 273px;
  z-index: 1;
  background: linear-gradient(to bottom, var(--navy), rgb(0 0 58 / 0%));
}

/*
 * Must sit after `.fcard__shot` above, not up with the `.split__cards` stacking
 * rule: media queries carry no extra specificity, so a later base declaration
 * of the same property wins regardless of the query.
 *
 * The shot is a fixed 414px, wider than the card once these stack — and
 * `overflow: hidden` then crops it symmetrically, leaving the middle third of a
 * screenshot. Scale it to the card instead; on a phone, seeing the whole window
 * beats a centred crop of it.
 */
@media (max-width: 760px) {
  .fcard__shot {
    width: calc(100% - 32px);
  }
}

.fcard--light {
  background: var(--indigo-25);
}

.fcard--light .fcard__title {
  color: var(--gray-900);
}

.fcard--light .fcard__sub {
  color: var(--gray-500);
}

.fcard__art {
  position: absolute;
  top: 200px;
  width: 100%;
  max-width: none;
}

/* ── Dark band ─────────────────────────────────────────────────────────── */

.band {
  position: relative;
  overflow: hidden;
  background: var(--navy);
  min-height: 903px;
  display: grid;
  place-items: center;
  isolation: isolate;
  padding-block: var(--section-y);
}

.band__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}

.band__veil {
  position: absolute;
  inset: 0 0 auto 0;
  height: 777px;
  z-index: -1;
  background: linear-gradient(to bottom, var(--navy), rgb(0 0 58 / 0%));
}

.band__inner {
  width: 100%;
  max-width: 845px;
  margin-inline: auto;
  padding-inline: var(--gutter);
  text-align: center;
  color: var(--white);
}

.band__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(32px, 4vw, 60px);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.band__sub {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 28px;
}

.band__inner .btn {
  margin-top: 80px;
}

/* ── Testimonials ──────────────────────────────────────────────────────── */

.quotes {
  position: relative;
  padding-top: var(--section-y);
  overflow: hidden;
}

/* The design bleeds the rail off both edges behind a white fade. */
.quotes::before,
.quotes::after {
  content: "";
  position: absolute;
  bottom: 0;
  height: 380px;
  width: min(300px, 18vw);
  z-index: 2;
  pointer-events: none;
}

.quotes::before {
  left: 0;
  background: linear-gradient(to right, var(--white), rgb(255 255 255 / 0%));
}

.quotes::after {
  right: 0;
  background: linear-gradient(to left, var(--white), rgb(255 255 255 / 0%));
}

.quotes__title {
  margin: 0 0 48px;
  text-align: center;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(26px, 2.4vw, 36px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

/*
 * The design shows the rail bleeding off both edges with a white fade. Real
 * scrolling beats a faked overflow, so it is a scroll-snap rail with the fades
 * painted over it.
 */
.quotes__rail {
  position: relative;
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* `%` of the parent, never `100vw` — vw includes the scrollbar width and
     the rest of the page measures in %, so the two disagree by ~15px and the
     rail sits at a different inset to every other section. */
  padding-inline: max(
    var(--gutter),
    calc((100% - var(--well)) / 2 + var(--gutter))
  );
  scrollbar-width: none;
}

.quotes__rail::-webkit-scrollbar {
  display: none;
}

.quote {
  flex: none;
  width: min(600px, 84vw);
  height: 380px;
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  padding: 32px 24px;
  border-radius: 12px;
  background: var(--indigo-25);
}

.stars {
  display: flex;
  align-items: center;
}

.quote__body {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 28px;
  color: var(--gray-900);
}

.quote__by p {
  margin: 0;
  font-size: 14px;
  line-height: 20px;
}

.quote__name {
  font-weight: 600;
  color: var(--gray-900);
}

.quote__role {
  color: var(--gray-500);
}

/* ── FAQ ───────────────────────────────────────────────────────────────── */

.faq {
  padding-block: var(--section-y);
}

.faq__title {
  margin: 0 0 48px;
  text-align: center;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(26px, 2.4vw, 36px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--gray-900);
}

.faq__list {
  width: 100%;
  max-width: 977px;
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.faq__item {
  border: 1px solid var(--gray-200);
  border-radius: 16px;
  background: var(--white);
  padding: 24px;
}

.faq__item[open] {
  background: var(--indigo-25);
  border-color: transparent;
}

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
  list-style: none;
  font-weight: 500;
  font-size: 20px;
  line-height: 30px;
  color: var(--gray-900);
}

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

.faq__chev {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 100px;
  background: var(--indigo-50);
}

.faq__item[open] .faq__chev {
  background: var(--white);
  rotate: 180deg;
}

.faq__item p {
  margin: 24px 0 0;
  color: var(--gray-500);
}

/* ── Contact CTA ───────────────────────────────────────────────────────── */

.contact {
  padding-inline: var(--gutter);
  padding-bottom: var(--section-y);
}

.contact__card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  width: 100%;
  max-width: var(--well);
  margin-inline: auto;
  min-height: 384px;
  display: grid;
  place-items: center;
  padding-block: 64px;
  border-radius: 24px;
  background: var(--indigo-500);
}

.contact__glow {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 1661px;
  max-width: none;
  z-index: -1;
  object-fit: cover;
}

.contact__inner {
  text-align: center;
  color: var(--white);
  padding-inline: var(--gutter);
}

.contact__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(32px, 4vw, 60px);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.contact__sub {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 28px;
}

.contact__inner .btn {
  margin-top: 80px;
}

/* ── Footer ────────────────────────────────────────────────────────────── */

.foot {
  background: var(--navy);
  color: var(--white);
  padding: 48px 0 32px;
}

.foot__inner {
  width: 100%;
  max-width: var(--well);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.foot__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 32px;
}

.foot__left {
  display: flex;
  align-items: center;
  gap: 80px;
  flex-wrap: wrap;
}

.foot__left img {
  width: 184px;
  height: 38px;
}

.foot__links {
  display: flex;
  align-items: center;
  gap: 40px;
  font-weight: 500;
}

.foot__links a {
  text-decoration: none;
}

.foot__social {
  display: flex;
  gap: 8px;
}

.foot__social a {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 100px;
  background: rgb(255 255 255 / 20%);
}

.foot__rule {
  width: 100%;
  height: 0;
  margin: 0;
  border: 0;
  border-top: 1px solid rgb(255 255 255 / 20%);
}

.foot__legal {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.foot__legal p {
  margin: 0;
  font-size: 14px;
  line-height: 20px;
}

.foot__legal-links {
  display: flex;
  gap: 32px;
  font-size: 12px;
  line-height: 18px;
}

.foot__legal-links a {
  text-decoration: none;
}

/* ── Text pages (privacy, terms) ───────────────────────────────────────────
 *
 * The chrome is the home page's: same .dark band, same nav, same footer. What
 * differs is what sits between them — a centred page header on the glow, then
 * one column of prose on white. Figma frame 21:419.
 */

/*
 * .dark's glow offsets and fade heights are placed for the home page's very
 * tall hero: an 841px top fade and a bottom fade starting at y=1032. Over a
 * ~320px header band the top fade alone would cover the whole thing in flat
 * navy and the bottom fade would fall outside it entirely. So the band gets
 * its own placement rather than inheriting numbers meant for a taller box.
 */
.dark--compact .dark__glow {
  top: auto;
  bottom: -560px;
}

/* Deep enough to sit the nav on near-flat navy, the way the frame does, rather
   than on the bright core of the glow. */
.dark--compact .dark__fade-top {
  height: 240px;
}

.dark--compact .dark__fade-bottom {
  top: auto;
  bottom: 0;
  height: 180px;
}

.pagehead {
  padding-block: clamp(40px, 5vw, 72px) clamp(56px, 7vw, 104px);
  text-align: center;
}

.pagehead__eyebrow {
  margin: 0 0 14px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 60%);
}

.pagehead__title {
  margin: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(36px, 4.6vw, 64px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--white);
  text-wrap: balance;
}

/*
 * A legal page can be shorter than the viewport, which would leave the footer
 * floating mid-screen with white body showing below it. Only these pages need
 * the sticky footer, so it hangs off a class on <body> rather than changing
 * the layout of the home page.
 */
.doc-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.doc-page .doc {
  flex: 1 0 auto;
}

.doc {
  background: var(--white);
  padding-block: var(--section-y);
}

/* Narrower than --well: this is the one place on the site with long-form
   reading text, which wants ~70 characters a line, not 1480px of them. */
.doc__inner {
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.prose {
  color: var(--gray-500);
  font-size: 17px;
  line-height: 1.75;
}

/* Flow spacing on the container, so a page of prose never needs per-element
   margins that collapse or double against each other. */
.prose > * + * {
  margin-top: 1.15em;
}

.prose h2 {
  margin-top: 2em;
  margin-bottom: 0;
  font-family: var(--disp);
  font-weight: 500;
  font-size: clamp(22px, 2.4vw, 28px);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--gray-900);
}

.prose h3 {
  margin-top: 1.6em;
  margin-bottom: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--gray-900);
}

.prose h2 + *,
.prose h3 + * {
  margin-top: 0.6em;
}

.prose a {
  color: var(--indigo-500);
  text-underline-offset: 3px;
}

.prose ul,
.prose ol {
  padding-left: 1.3em;
}

.prose li + li {
  margin-top: 0.4em;
}

.prose strong {
  color: var(--gray-900);
  font-weight: 600;
}

/* The "Last updated" line under the title. */
.doc__meta {
  margin: 0 0 32px;
  font-size: 14px;
  color: var(--gray-500);
}

/* Placeholder shown while a page has no copy yet. Delete the <p> with the
   copy that replaces it — the rule can stay for the next empty page. */
.doc__todo {
  margin: 0;
  padding: 20px 24px;
  border: 1px dashed var(--gray-200);
  border-radius: 12px;
  color: var(--gray-500);
  background: var(--indigo-25);
}

/* ── Docs page ─────────────────────────────────────────────────────────────
 *
 * Everything here is additive to .prose, which the legal pages already use.
 * The docs page is the only one with code, numbered steps and screenshots.
 */

/* System mono: a fourth webfont for a handful of command lines is not worth
   the request, and every Mac this page is read on has SF Mono. */
.prose code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 0.9em;
  background: var(--indigo-25);
  border: 1px solid var(--gray-200);
  border-radius: 5px;
  padding: 1px 5px;
}

.prose pre {
  margin: 0;
  padding: 16px 18px;
  background: var(--navy);
  border-radius: 12px;
  overflow-x: auto; /* long command lines scroll here, never the page */
}

.prose pre code {
  background: none;
  border: 0;
  padding: 0;
  font-size: 13.5px;
  line-height: 1.65;
  color: #d7dcf5;
  white-space: pre;
}

/* The shell prompt, so a command is not mistaken for output. */
.prose pre code .p {
  color: #6172f3;
  user-select: none;
}

.prose pre code .c {
  color: #8b93b8;
}

/* ── Setup steps ──────────────────────────────────────────────────────────
 * Numbered because setup genuinely is a sequence: the CLI cannot reach an app
 * with no profile, and the skill is no use before the CLI exists.
 */
.steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: 52px;
  padding-bottom: 36px;
}

.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: -2px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--navy);
  color: var(--white);
  font-family: var(--disp);
  font-size: 15px;
  font-weight: 500;
}

/* The rule joining one step to the next, stopping at the last. */
.steps > li::after {
  content: "";
  position: absolute;
  left: 15.5px;
  top: 38px;
  bottom: 8px;
  width: 1px;
  background: var(--gray-200);
}

.steps > li:last-child {
  padding-bottom: 0;
}

.steps > li:last-child::after {
  display: none;
}

.steps h3 {
  margin-top: 4px;
}

/* ── Screenshot slots ─────────────────────────────────────────────────────
 *
 * Placeholders until the real captures land. Each reserves its aspect ratio,
 * so dropping an image in shifts nothing on the page. To fill one: delete the
 * .shot__todo div, uncomment the <img>, and drop the file at the path named.
 */
.shot {
  margin: 20px 0 0;
}

.shot__frame {
  aspect-ratio: 16 / 10;
  border: 1px dashed var(--gray-200);
  border-radius: 12px;
  background: var(--indigo-25);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.shot__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.shot__todo {
  text-align: center;
  padding: 20px;
  color: var(--gray-500);
  font-size: 14px;
}

.shot__todo code {
  display: inline-block;
  margin-top: 6px;
}

.shot figcaption {
  margin-top: 10px;
  font-size: 14px;
  color: var(--gray-500);
}

/* ── Language grid ────────────────────────────────────────────────────────
 * A plain list of sixteen names reads as a wall; a grid lets the eye check
 * for its own language in one pass.
 */
.langgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.langgrid li {
  margin: 0;
  padding: 7px 12px;
  border: 1px solid var(--gray-200);
  border-radius: 8px;
  font-size: 14px;
  color: var(--gray-900);
}

.langgrid li span {
  color: var(--gray-500);
  font-size: 12.5px;
}

/* A callout for the one thing a reader must know before it bites them. */
.note {
  margin: 0;
  padding: 16px 18px;
  border-left: 2px solid var(--indigo-500);
  border-radius: 0 10px 10px 0;
  background: var(--indigo-25);
  font-size: 15px;
}
