@charset "UTF-8";
/*
  Entry point for the marketing site's stylesheet. Compiled to
  app/assets/builds/marketing.css by `yarn build:marketing-css`, which
  regenerates the token file first.

  marketing-tokens.css is generated from app/javascript/app/styles/theme.js and
  is found on the --load-path; @use inlines it here so every `var(--color-…)`
  below resolves from one stylesheet with no extra request.
*/
/* Generated from app/javascript/app/styles/theme.js by bin/build-marketing-tokens.mjs.
   Do not edit; change the tokens in app/javascript/app/styles/theme.js and rebuild with
   `yarn build:marketing-tokens`. */
:root {
  --color-black: #0b0c12;
  --color-black-darker: #0a0a0a;
  --color-charcoal: #12141c;
  --color-charcoal-light: #171a24;
  --color-charcoal-lighter: #1f2132;
  --color-slate: #343949;
  --color-slate-dark: #262a38;
  --color-white: #f4f5f7;
  --color-light-grey: #a2a7b5;
  --color-grey: #6b7186;
  --color-lime: #DEFD00;
  --color-lime-dark: #c2dd00;
  --color-lime-darkest: #4d5806;
  --color-lime-soft: #cbf32b;
  --color-olive-darkest: #1d2206;
  --color-red: #ff5a52;
  --color-red-bright: #e83030;
  --color-red-darkest: #560606;
  --color-maroon-darkest: #4a1c1a;
  --color-amber: #ffb020;
  --color-yellow: #f0c040;
  --color-yellow-darkest: #563f00;
  --color-brown-darkest: #4a3410;
  --color-brown-darker: #2a1d0a;
  --color-orange: #f07820;
  --color-orange-darkest: #632800;
  --color-sky-blue: #4fc3f7;
  --color-slate-blue: #7b98c8;
  --color-blue-grey: #9aa3b8;
  --color-blue-darkest: #0c3860;
  --color-navy-darkest: #182540;
  --color-green: #6ecb7a;
  --color-green-darkest: #1c3a16;
  --color-neutral-darkest: #1e1e1e;
  --color-neutral-darker: #252525;
  --color-neutral: #555555;
  --color-neutral-light: #888888;
  --font-mono: "SF Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --font-sans: "Helvetica Neue", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  --weight-regular: 400;
  --weight-medium: 600;
  --weight-bold: 700;
  --weight-heavy: 800;
  --line-height-compact: 1.2;
  --line-height-normal: 1.55;
  --line-height-large: 1.7;
}

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
}

body {
  min-height: 100vh;
  background-color: var(--color-black);
  color: var(--color-white);
  font-family: var(--font-sans);
  line-height: var(--line-height-large);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

table {
  border-collapse: collapse;
}

/* One focus treatment for the whole marketing site, matching the app's. */
:focus-visible {
  outline: 2px solid var(--color-lime);
  outline-offset: 2px;
}

::selection {
  background: var(--color-lime);
  color: var(--color-black-darker);
}

[hidden] {
  display: none !important;
}

/*
  Where marketing diverges from the app. The trading terminal is tuned for
  information per square inch — 14px body, 1.45rem h2. A landing page is read
  once, at a glance, so headings are display-sized and fluid, and body copy runs
  at the loosest of the three line heights.
*/
:root {
  --type-display: clamp(2.6rem, 6vw, 4.75rem);
  --type-h1: clamp(2.2rem, 4.8vw, 3.5rem);
  --type-h2: clamp(1.75rem, 3.2vw, 2.5rem);
  --type-h3: clamp(1.3rem, 2vw, 1.6rem);
  --type-h4: 1.15rem;
  --type-lead: clamp(1.05rem, 1.5vw, 1.25rem);
  --type-body: 1rem;
  --type-small: 0.875rem;
  --type-label: 0.6875rem;
}

body {
  font-size: var(--type-body);
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-sans);
  line-height: var(--line-height-compact);
  text-wrap: balance;
}

h1 {
  font-size: var(--type-h1);
  font-weight: var(--weight-heavy);
  letter-spacing: -0.03em;
}

h2 {
  font-size: var(--type-h2);
  font-weight: var(--weight-heavy);
  letter-spacing: -0.02em;
}

h3 {
  font-size: var(--type-h3);
  font-weight: var(--weight-bold);
  letter-spacing: -0.015em;
}

h4,
h5,
h6 {
  font-size: var(--type-h4);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

p {
  line-height: var(--line-height-large);
  text-wrap: pretty;
}

/* The one heading larger than h1 — a page's opening statement. Not an element,
   because a hero's opening statement is still the h1 semantically. */
.display {
  font-size: var(--type-display);
  font-weight: var(--weight-heavy);
  letter-spacing: -0.035em;
  line-height: 1.04;
}

.lead {
  font-size: var(--type-lead);
  line-height: var(--line-height-large);
  color: var(--color-light-grey);
  max-width: 60ch;
}

.prose {
  color: var(--color-light-grey);
  max-width: 68ch;
}
.prose p + p,
.prose p + ul,
.prose ul + p {
  margin-top: var(--space-4);
}
.prose li + li {
  margin-top: var(--space-2);
}
.prose strong {
  color: var(--color-white);
  font-weight: var(--weight-medium);
}

/* Section kickers and stat keys, carrying over the app's `overline`. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--type-label);
  font-weight: var(--weight-bold);
  letter-spacing: 0.16em;
  line-height: var(--line-height-compact);
  text-transform: uppercase;
  color: var(--color-lime);
}

.eyebrow--muted {
  color: var(--color-grey);
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.text-muted {
  color: var(--color-light-grey);
}

.text-small {
  font-size: var(--type-small);
}

.link {
  color: var(--color-lime);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--color-lime) 40%, transparent);
  text-underline-offset: 0.2em;
  transition: color 0.15s ease;
}
.link:hover {
  color: var(--color-lime-dark);
}

/*
  These mirror MUI's default breakpoints deliberately. theme.js declares no
  `breakpoints` key, so MUI is running on its own defaults in the app; adding a
  key to theme.js purely to have something to read here would change app
  behaviour. Hard-coding the same numbers keeps marketing and app breakpoints
  aligned without touching the app.
*/
/* Exclusive of the breakpoint itself, so `up` and `down` on the same name never
   both match. */
/*
  Section rhythm is fluid rather than stepped, so vertical whitespace shrinks
  with the viewport instead of snapping at a breakpoint.
*/
:root {
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;
  --container-width: 1200px;
  --container-width-narrow: 760px;
  --container-width-wide: 1440px;
  --container-gutter: clamp(1rem, 4vw, 2.5rem);
  --section-space: clamp(3.5rem, 9vw, 7.5rem);
}

.container {
  width: 100%;
  max-width: calc(var(--container-width) + var(--container-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--container-gutter);
}

.container--narrow {
  max-width: calc(var(--container-width-narrow) + var(--container-gutter) * 2);
}

.container--wide {
  max-width: calc(var(--container-width-wide) + var(--container-gutter) * 2);
}

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

.section--tight {
  padding-block: calc(var(--section-space) * 0.5);
}

/* A hairline instead of alternating background fills, so the page reads as one
   continuous surface. */
.section--bordered {
  border-top: 1px solid var(--color-slate-dark);
}

.section--panel {
  background-color: var(--color-charcoal);
  border-block: 1px solid var(--color-slate-dark);
}

.section__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
  max-width: 68ch;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.stack--tight {
  gap: var(--space-3);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
}

/* Marketing grids are always "one column until there is room", never a
   fractional squeeze: every one of them pairs up at `sm` and only the wider
   variants keep going. */
.grid {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 600px) {
  .grid--2,
  .grid--3,
  .grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1200px) {
  .grid--4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Copy beside an image or screenshot; the wider track carries the visual. */
@media (min-width: 900px) {
  .grid--split {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
    align-items: center;
  }
}

/* Columns start together rather than centring on each other, for a row where
   one side is a tall screenshot and the other is four bullets — centred, the
   gap above the copy reads as a mistake. */
@media (min-width: 900px) {
  .grid--split-top {
    align-items: start;
  }
}

/* Copy reads first on a narrow screen; the visual leads once there is room
   beside it. Assumes the visual is the last child, which is also the order a
   screen reader and a phone get. */
@media (min-width: 900px) {
  .grid--visual-first > :last-child {
    order: -1;
  }
}

@media (min-width: 900px) {
  .grid--split-wide {
    grid-template-columns: 5fr 7fr;
    gap: var(--space-8);
    align-items: center;
  }
}

/* Square corners and a hairline border — the app's panel treatment. */
.panel {
  background-color: var(--color-charcoal-light);
  border: 1px solid var(--color-slate-dark);
  padding: var(--space-6);
}

.panel--flush {
  padding: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/*
  Square, mono, tracked, uppercase — the same shape as MuiButton's `brand` and
  `brandSecondary` variants in theme.js, sized up for marketing. The app's
  11px/10.5px buttons are too quiet to act as a page's primary call to action.
*/
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  position: relative;
  width: fit-content;
  flex-shrink: 0;
  padding: 0.875rem 1.625rem;
  border: 1px solid transparent;
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: var(--weight-bold);
  letter-spacing: 0.12em;
  line-height: var(--line-height-compact);
  text-transform: uppercase;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.btn:disabled,
.btn[aria-disabled=true] {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}

.btn--primary {
  background-color: var(--color-lime);
  border-color: var(--color-lime);
  color: var(--color-black-darker);
}
.btn--primary:hover {
  background-color: var(--color-lime-dark);
  border-color: var(--color-lime-dark);
}

.btn--secondary {
  background-color: transparent;
  border-color: var(--color-slate);
  color: var(--color-light-grey);
  font-weight: var(--weight-regular);
}
.btn--secondary:hover {
  border-color: var(--color-lime);
  color: var(--color-lime);
}

/* The lower-weight third option in a CTA cluster. */
.btn--ghost {
  background-color: transparent;
  border-color: transparent;
  color: var(--color-light-grey);
  padding-inline: 0.5rem;
}
.btn--ghost:hover {
  color: var(--color-lime);
}

.btn--large {
  padding: 1.0625rem 2.25rem;
  font-size: 0.8125rem;
}

.btn--small {
  padding: 0.625rem 1.125rem;
  font-size: 0.6875rem;
}

.btn--block {
  width: 100%;
}

img,
video,
svg,
canvas,
picture,
iframe {
  display: block;
  max-width: 100%;
}

img,
video {
  height: auto;
}

/* Screenshots of the terminal sit on a dark page; the hairline keeps the panel
   edge from dissolving into the background. */
.media {
  width: 100%;
  border: 1px solid var(--color-slate-dark);
  background-color: var(--color-charcoal);
}

.media--cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media--contain {
  object-fit: contain;
}

/* Reserves the box before the image loads, so a slow connection does not get a
   reflow halfway down the page. */
.media--wide {
  aspect-ratio: 16/9;
}

.media--square {
  aspect-ratio: 1/1;
}

/* Driven by marketing/shared/_video, which explains why playback is opt-in. */
.video {
  width: 100%;
  background-color: var(--color-charcoal);
  object-fit: cover;
}

figure {
  margin: 0;
}

figcaption {
  margin-top: var(--space-3);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-grey);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/*
  Page partials style a page's layout; this file styles the pieces that recur
  inside it on more than one page.
*/
/*
  Every marketing page opens with a headline over a background video, so the
  hero lives here rather than with any one page. A page adds only what is
  peculiar to it — the homepage's stat row, for instance.
*/
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  gap: var(--space-9);
  overflow: hidden;
}

/* The video is the section's backdrop, not part of its flow. It is clipped to
   the section and dimmed so the headline keeps its contrast whatever frame is
   showing. */
.hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--color-black) 58%, transparent), color-mix(in srgb, var(--color-black) 88%, transparent));
}

/* A hero with no backdrop video — /features and /why-sonic both open on copy
   alone — so there is nothing for the dimming layer to dim. */
.hero--plain::after {
  content: none;
}

/* The measure is capped on the text, not on the container: `.container` already
   owns the page's left edge, and narrowing it here would re-centre the hero and
   pull it out of line with every section below. */
.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-5);
}

.hero__heading {
  margin: 0;
  max-width: 18ch;
}

.hero__lead {
  margin: 0;
  max-width: 54ch;
  color: var(--color-white);
}

/*
  Named sub-sections stacked beside a visual, six of them on /platform. Here
  rather than in a page file because marketing/shared/_topic renders them. The
  rule between two replaces the Webflow export's `divider` element.
*/
.topics {
  display: grid;
  gap: var(--space-7);
}

.topic {
  gap: var(--space-4);
}

.topic + .topic {
  padding-top: var(--space-7);
  border-top: 1px solid var(--color-slate-dark);
}

/* Topics side by side rather than stacked, for a section with no visual to sit
   beside — /features has four of them, and three or four stacked tick-lists in
   a row is a very long scroll. Side by side the gutter separates them, so the
   rule above would only add noise. */
@media (min-width: 900px) {
  .topics--columns {
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    column-gap: var(--space-8);
  }
  .topics--columns > .topic + .topic {
    padding-top: 0;
    border-top: 0;
  }
}

.topic__title {
  margin: 0;
}

/*
  A row of headline numbers: the homepage's under its hero, /why-sonic's under
  "The Numbers that Speak for Themselves". Each number is a `<dl>` entry, so the
  value and its label stay associated.
*/
.stat-list {
  display: grid;
  gap: var(--space-6);
  margin: 0;
}
@media (min-width: 600px) {
  .stat-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .stat-list--3up {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 900px) {
  .stat-list--4up {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.stat__value {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: var(--weight-heavy);
  line-height: var(--line-height-compact);
  color: var(--color-lime);
}

.stat__label {
  margin: 0;
  font-size: var(--type-small);
  line-height: var(--line-height-normal);
  color: var(--color-light-grey);
}

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 600px) {
  .checklist--columns {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-6);
  }
}

.checklist__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  color: var(--color-light-grey);
  line-height: var(--line-height-normal);
}

/* Sized in `em` and nudged by the cap-height difference so the tick sits on the
   first line of text at any font size. */
.checklist__tick {
  width: 1.25em;
  height: 1.25em;
  margin-top: 0.1em;
  flex-shrink: 0;
  color: var(--color-lime);
}

.checklist__term {
  color: var(--color-white);
  font-weight: var(--weight-medium);
  /* The arrow the Webflow copy spelled out as a literal character. */
}
.checklist__term::after {
  content: " →";
  color: var(--color-lime);
}

.testimonial {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-5);
}

.testimonial__quote {
  margin: 0;
  color: var(--color-white);
  font-size: var(--type-lead);
  line-height: var(--line-height-normal);
  text-wrap: pretty;
}

.testimonial__author {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-top: 0;
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-slate-dark);
  text-transform: none;
  letter-spacing: normal;
  font-family: var(--font-sans);
  font-size: var(--type-small);
}

.testimonial__name {
  color: var(--color-white);
  font-weight: var(--weight-medium);
}

.testimonial__role {
  color: var(--color-grey);
  font-family: var(--font-mono);
  font-size: var(--type-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.cta-band {
  border-top: 1px solid var(--color-slate-dark);
  background-color: var(--color-charcoal);
}

.cta-band__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  text-align: center;
}

.cta-band__intro {
  margin: 0;
}

/*
  Sticky header with a hairline base, matching the app's panel treatment. The
  mobile menu is a drop-down panel rather than a full-screen overlay: at four
  links plus two buttons it never needs the whole viewport.
*/
.site-logo {
  display: block;
  width: 152px;
  height: auto;
}

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: var(--space-4);
  z-index: 20;
  padding: var(--space-3) var(--space-4);
  background-color: var(--color-lime);
  color: var(--color-black-darker);
  font-family: var(--font-mono);
  font-size: var(--type-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transform: translateY(-200%);
}
.skip-link:focus {
  transform: translateY(0);
}

.site-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background-color: color-mix(in srgb, var(--color-black) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-slate-dark);
}

.site-nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  min-height: 4.5rem;
}

.site-nav__brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.site-nav__toggle {
  display: none;
  padding: var(--space-3);
  margin-right: calc(var(--space-3) * -1);
  color: var(--color-white);
}

/* Three bars drawn from one element: the box is the middle bar, the
   pseudo-elements the outer two. They collapse into an X when open. */
.site-nav__toggle-bars {
  display: block;
  position: relative;
  width: 1.25rem;
  height: 2px;
  background-color: currentColor;
  transition: background-color 0.15s ease;
}
.site-nav__toggle-bars::before, .site-nav__toggle-bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: currentColor;
  transition: transform 0.15s ease;
}
.site-nav__toggle-bars::before {
  top: -6px;
}
.site-nav__toggle-bars::after {
  top: 6px;
}

.site-nav__menu {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-nav__links {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-nav__link {
  font-family: var(--font-mono);
  font-size: var(--type-label);
  font-weight: var(--weight-bold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-light-grey);
  white-space: nowrap;
  transition: color 0.15s ease;
}
.site-nav__link:hover {
  color: var(--color-white);
}
.site-nav__link[aria-current=page] {
  color: var(--color-lime);
}

.site-nav__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

@media (max-width: 899.98px) {
  .site-nav__toggle {
    display: block;
  }
  .site-nav__menu {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-5);
    padding: var(--space-6) var(--container-gutter) var(--space-7);
    background-color: var(--color-charcoal);
    border-bottom: 1px solid var(--color-slate-dark);
  }
  .site-nav__links {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-5);
  }
  .site-nav__actions .btn {
    width: 100%;
  }
  /* Open by default until the script takes over, so the links stay reachable
     with JavaScript disabled or still loading. */
  .site-nav--js .site-nav__menu {
    display: none;
  }
  .site-nav--js.site-nav--open .site-nav__menu {
    display: flex;
  }
  .site-nav--open .site-nav__toggle-bars {
    background-color: transparent;
  }
  .site-nav--open .site-nav__toggle-bars::before {
    transform: translateY(6px) rotate(45deg);
  }
  .site-nav--open .site-nav__toggle-bars::after {
    transform: translateY(-6px) rotate(-45deg);
  }
}
.site-footer {
  margin-top: var(--section-space);
  border-top: 1px solid var(--color-slate-dark);
  background-color: var(--color-charcoal);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-8);
  padding-block: var(--space-8);
}
@media (min-width: 900px) {
  .site-footer__inner {
    grid-template-columns: 5fr 7fr;
    gap: var(--space-9);
  }
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 38ch;
}

.site-footer__links {
  display: grid;
  gap: var(--space-7);
}
@media (min-width: 600px) {
  .site-footer__links {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 900px) {
  .site-footer__links {
    justify-items: end;
  }
}

.site-footer__group {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.site-footer__group ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.site-footer__group a {
  font-size: var(--type-small);
  color: var(--color-light-grey);
  transition: color 0.15s ease;
}
.site-footer__group a:hover {
  color: var(--color-lime);
}
.site-footer__group a[aria-current=page] {
  color: var(--color-white);
}

.site-footer__bottom {
  padding-block: var(--space-5);
  border-top: 1px solid var(--color-slate-dark);
}

/*
  Homepage-only layout. Anything here that a second page ends up needing should
  move to a shared partial rather than be copied.
*/
/* `.hero` and the `.stat-list` inside it are both shared — see _components.scss.
   All that is homepage-specific is the rule that separates the stats from the
   headline above them. */
.hero__stat-list {
  padding-top: var(--space-7);
  border-top: 1px solid var(--color-slate-dark);
}

/* The phone shot is portrait and tall; capping it stops it from setting the
   row height on a wide screen. */
.revolution__figure {
  display: flex;
  justify-content: center;
}

.revolution__image {
  width: auto;
  max-height: 32rem;
}

.capability {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.capability__icon {
  width: 3.5rem;
  height: auto;
}

.capability__title {
  margin: 0;
}

.security__image {
  width: 100%;
  height: auto;
}

/*
  /platform-only layout. The hero, the `topics` stack and the split grids are
  all shared — see _components.scss and _layout.scss.
*/
/* Without the homepage's stat row the hero has only three short elements in it,
   which is not enough to give the backdrop video a shape of its own. */
.platform-hero {
  justify-content: center;
  min-height: clamp(30rem, 68vh, 44rem);
}

/*
  /features-only layout. The hero, the `topics` stack and the split grids are
  all shared — see _components.scss and _layout.scss.
*/
/* The phone mockup is portrait and tall; capping it stops it from setting the
   height of the row beside it. */
.data-sources__video {
  width: auto;
  max-height: 26rem;
  margin-inline: auto;
}

/*
  /why-sonic-only layout. The hero, the split grids, the stat row and the tick
  lists are all shared — see _components.scss and _layout.scss.
*/
/* The phone shot is narrower than the column it sits in; centring it stops it
   from hugging the gutter beside the copy. */
.freedom__image {
  margin-inline: auto;
}

/* The globe closes the stats band rather than sitting beside it, so it spans
   the container with the section's own rhythm above it. */
.numbers__image {
  width: 100%;
  margin-top: var(--space-8);
}

.pillar {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.pillar__icon {
  width: 3rem;
  height: auto;
}

/* h4 size on an h3 element: four of these sit in one row and the longest runs
   to eight words, which at the h3 size wraps to four lines on a laptop. */
.pillar__title {
  margin: 0;
  font-size: var(--type-h4);
}

.join__inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-6);
}
@media (min-width: 900px) {
  .join__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/*
  /contact-support-only styling. The form primitives live here rather than in
  _components.scss because this is the only form on the marketing site; move
  them up if a second one appears.

  Inputs deliberately match the app's: square corners, a charcoal well inside a
  slate hairline, and a lime focus ring.
*/
.contact-form {
  display: grid;
  gap: var(--space-6);
}

.contact-form__fields {
  display: grid;
  gap: var(--space-5);
  /* Name and Surname pair up; email and message span the row. */
}
@media (min-width: 600px) {
  .contact-form__fields {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 600px) {
  .field--wide {
    grid-column: 1/-1;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-family: var(--font-mono);
  font-size: var(--type-label);
  font-weight: var(--weight-medium);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-light-grey);
}

.field__input {
  width: 100%;
  padding: 0.75rem 1rem;
  background-color: var(--color-charcoal);
  border: 1px solid var(--color-slate-dark);
  border-radius: 0;
  color: var(--color-white);
  font-family: inherit;
  font-size: var(--type-body);
  line-height: var(--line-height-normal);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.field__input:hover {
  border-color: var(--color-slate);
}
.field__input {
  /* The ring itself comes from the site-wide `:focus-visible` in _reset; the
     border is lifted to lime so the well reads as active behind it. */
}
.field__input:focus {
  border-color: var(--color-lime);
}
.field__input::placeholder {
  color: var(--color-grey);
}

textarea.field__input {
  resize: vertical;
  min-height: 9rem;
}

.field--invalid .field__input {
  border-color: var(--color-red);
}

.field__error {
  margin: 0;
  color: var(--color-red);
  font-size: var(--type-small);
  line-height: var(--line-height-normal);
}

.contact-form__errors {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-red);
  background-color: color-mix(in srgb, var(--color-red) 12%, transparent);
  color: var(--color-white);
  font-weight: var(--weight-medium);
}

.contact-form__success {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  border-color: var(--color-lime);
}
.contact-form__success h3 {
  margin: 0;
}
.contact-form__success p {
  margin: 0;
}

.contact-form__aside {
  margin-top: var(--space-6);
  font-size: var(--type-small);
}

/*
  /legal-only styling. The page is one long contract rather than a sequence of
  marketing sections, so the work here is typography: a measure you can read a
  clause in, and enough vertical rhythm that scanning for a clause number works.

  Everything is scoped under `.legal-doc`; these rules are a document style, not
  a site style, and `h3 { border-top }` leaking onto the other five pages would
  be a mess. The selectors are written out flat rather than nested because a
  comment inside a nested block makes Sass emit the empty parent ruleset.
*/
.legal-doc__title {
  margin-bottom: var(--space-7);
}

/* Wider than `.prose`'s 68ch, which is where the ticket's 70–75 character
   measure lands. Wins over `.prose` on source order: pages/ is @used last. */
.legal-doc__body {
  max-width: 72ch;
}

/* A clause heading is a scan target: the rule above it and the extra space give
   the eye somewhere to stop. The first one sits under the intro paragraph and
   wants the same treatment, so there is no `:first-of-type` exception.

   `scroll-margin-top` clears the sticky nav, so a #clause-N link lands with the
   heading below it rather than behind it. */
.legal-doc h3 {
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-slate-dark);
  color: var(--color-white);
  scroll-margin-top: var(--space-9);
}

/* `.prose` spaces p-after-p and p-after-ul; a paragraph opening a clause
   follows a heading, which it does not cover. */
.legal-doc h3 + p,
.legal-doc h3 + ul,
.legal-doc h3 + address {
  margin-top: var(--space-5);
}

/* Markers sit in the gutter beside the measure rather than inside it, so a
   wrapped bullet lines up with the first word above it. */
.legal-doc ul {
  padding-left: var(--space-5);
  list-style: disc;
}

.legal-doc li::marker {
  color: var(--color-grey);
}

.legal-doc__contact {
  font-style: normal;
  line-height: var(--line-height-large);
}
