/*
 * The marketing page's stylesheet.
 *
 * A file rather than a <style> block because this origin sends
 * `style-src 'self'` with no `'unsafe-inline'` — the same rule the dashboard
 * lives under, and not one worth loosening for a brochure.
 *
 * Every value below is sampled from `packages/ui/src/styles/tokens.css` and
 * `docs/DESIGN.md`. Sampled, not imported: this page ships no bundle, and a
 * mail-order copy of the token file is the price of rendering before any
 * JavaScript exists to have an opinion. The rules that make it look like the
 * product rather than like a template are the ones easiest to lose in a
 * redesign, so they are named here:
 *
 *   - Weights cap at 600. There is no 700 in this product. Titles carry
 *     hierarchy through size and tight tracking instead of heavier strokes.
 *   - Body is 17px, from the iOS text scale the application uses.
 *   - Elevation is a tight contact shadow plus a soft ambient one, so depth
 *     reads as light rather than as a smudge.
 *   - Mobile first, meant literally: every rule below describes a phone, and
 *     the media queries only ever add.
 */

:root {
  --paper: #f7f9fc;
  --paper-raised: #ffffff;
  --paper-sunken: #edf1f7;
  --ink: #131a2a;
  --ink-muted: #5b6579;
  --ink-faint: #66718a;
  --hairline: #e4e9f1;
  --accent: #2c77ee;
  --accent-soft: #e7effe;
  --accent-strong: #1d5ed6;
  --accent-contrast: #ffffff;

  --radius-control: 10px;
  --radius-surface: 16px;
  --radius-pill: 999px;

  --weight-medium: 500;
  --weight-strong: 600;

  --tracking-tight: -0.028em;
  --tracking-snug: -0.014em;

  --duration-press: 90ms;
  --duration-fast: 140ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  --elevation-raised: 0 1px 2px rgb(19 26 42 / 4%), 0 1px 1px rgb(19 26 42 / 3%);
  --elevation-lifted: 0 1px 2px rgb(19 26 42 / 4%), 0 10px 28px -16px rgb(19 26 42 / 16%);

  --font-ui:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --gutter: 20px;
  --shell: 1080px;
  --control-lg: 46px;

  color-scheme: light;
}

/* In dark the accent is re-derived rather than inverted (DESIGN.md), and the
 * shadows lean on a darker base because a black shadow on near-black is a
 * smudge with no light in it. */
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0b0f1a;
    --paper-raised: #141a2b;
    --paper-sunken: #070a12;
    --ink: #eef2fa;
    --ink-muted: #9aa6bd;
    --ink-faint: #8b97ae;
    --hairline: #232c42;
    --accent: #6f9dff;
    --accent-soft: #17233f;
    --accent-strong: #8fb3ff;
    --accent-contrast: #0a1428;

    --elevation-raised: 0 1px 2px rgb(0 0 0 / 32%), 0 1px 1px rgb(0 0 0 / 24%);
    --elevation-lifted: 0 1px 2px rgb(0 0 0 / 32%), 0 12px 32px -18px rgb(0 0 0 / 60%);

    color-scheme: dark;
  }
}

/* A thumb needs a bigger target than a cursor does, and that is a property of
 * the pointer rather than of the viewport (DESIGN.md). */
@media (pointer: coarse) {
  :root {
    --control-lg: 50px;
  }
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 1.0625rem;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
p,
ul,
ol,
figure {
  margin: 0;
}

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

@media (min-width: 640px) {
  :root {
    --gutter: 32px;
  }
}

/* ---- Header ------------------------------------------------------------ */

/* An anchor lands its target at the top of the viewport, which is where the
 * sticky header already is — so "See how it works" put the heading somebody
 * asked for underneath the bar. The offset is the header's height plus enough
 * room that the section reads as having a top rather than starting flush. */
:target,
[id] {
  scroll-margin-top: 80px;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 2;
  border-bottom: 1px solid transparent;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 60px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: inherit;
}

.brand__mark {
  display: block;
  width: 30px;
  height: 30px;
}

/* Type, not artwork. The mark keeps the fixed brand colour because it is
 * illustration and reads on either appearance; the name takes the ink of
 * wherever it stands, which is what lets one brand survive both. */
.brand__word {
  font-size: 1.25rem;
  font-weight: var(--weight-strong);
  letter-spacing: -0.04em;
  color: var(--ink);
}

/* ---- Controls ---------------------------------------------------------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-snug);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease),
    border-color var(--duration-fast) var(--ease),
    transform var(--duration-press) var(--ease);
}

.button--lg {
  min-height: var(--control-lg);
  padding: 0 24px;
  font-size: 1.0625rem;
}

.button--primary {
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: var(--elevation-raised);
}

.button--quiet {
  background: var(--paper-raised);
  border-color: var(--hairline);
  color: var(--ink);
}

/* A control has to yield inside the tap itself, which is why press is faster
 * than everything else. */
.button:active {
  transform: scale(0.985);
}

/* Hover is a mouse affordance. On a touch screen it sticks after a tap and
 * reads as a selection that is not one. */
@media (hover: hover) {
  .button--primary:hover {
    background: var(--accent-strong);
  }

  .button--quiet:hover {
    border-color: var(--accent);
    color: var(--accent);
  }
}

a:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-control);
}

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

.hero {
  position: relative;
  padding-block: 48px 56px;
  overflow: hidden;
}

/*
 * The brand, used as light rather than as a rectangle of colour.
 *
 * `top: 0`, not a negative offset. The hero clips this to its own box, so a
 * gradient hoisted above the hero gets cut through its middle — the blue then
 * starts at full strength on the hero's first pixel, drawing a hard line under
 * a header that is sitting on plain paper. Starting it at the top edge means
 * the radial fades in from nothing, and the seam has nothing to draw.
 */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 50% auto;
  width: min(1100px, 160%);
  height: 620px;
  transform: translateX(-50%);
  background: radial-gradient(
    closest-side,
    color-mix(in srgb, var(--accent) 16%, transparent),
    transparent
  );
  pointer-events: none;
}

.hero > .shell {
  position: relative;
}

.hero__copy {
  max-width: 34rem;
}

/* No mark in here. It sat about 200px below the one in the header, at half the
 * size, and two of the same face that close together reads as a mistake rather
 * than as branding. The header carries the mark; this carries the words. */
.eyebrow {
  display: inline-block;
  margin-bottom: 18px;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.8125rem;
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-snug);
}

.hero h1 {
  font-size: 2.125rem;
  line-height: 1.08;
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-strong);
  text-wrap: balance;
}

.hero__lede {
  margin-top: 16px;
  font-size: 1.0625rem;
  color: var(--ink-muted);
  text-wrap: pretty;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 28px;
}

.hero__note {
  margin-top: 16px;
  font-size: 0.9375rem;
  color: var(--ink-faint);
}

.hero__art {
  margin-top: 44px;
}

@media (min-width: 900px) {
  .hero {
    padding-block: 72px 80px;
  }

  .hero > .shell {
    display: grid;
    grid-template-columns: 1.02fr 0.98fr;
    align-items: center;
    gap: 56px;
  }

  .hero h1 {
    font-size: 3rem;
  }

  .hero__lede {
    font-size: 1.1875rem;
  }

  .hero__art {
    margin-top: 0;
  }
}

@media (min-width: 1080px) {
  .hero h1 {
    font-size: 3.375rem;
  }
}

/* ---- The arrival card -------------------------------------------------- */

/*
 * A message landing, drawn in the product's own furniture rather than in a
 * screenshot: a screenshot goes stale the first time the inbox is touched,
 * and this is the one thing the page is actually claiming.
 */
.arrival {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-surface);
  background: var(--paper-raised);
  box-shadow: var(--elevation-lifted);
  overflow: hidden;
}

.arrival__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
  background: var(--paper-sunken);
  font-size: 0.8125rem;
  font-weight: var(--weight-medium);
  color: var(--ink-muted);
}

.arrival__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.arrival__body {
  padding: 18px 16px;
}

.arrival__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.arrival__from {
  font-size: 1.0625rem;
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-snug);
}

.arrival__time {
  font-size: 0.75rem;
  color: var(--ink-faint);
  white-space: nowrap;
}

.arrival__mail {
  margin-top: 2px;
  font-size: 0.8125rem;
  color: var(--ink-faint);
}

.arrival__message {
  margin-top: 12px;
  font-size: 0.9375rem;
  color: var(--ink-muted);
}

.arrival__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border-top: 1px solid var(--hairline);
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: var(--weight-strong);
}

.tag--quiet {
  background: var(--paper-sunken);
  color: var(--ink-faint);
}

/* ---- Sections ---------------------------------------------------------- */

.section {
  padding-block: 56px;
  border-top: 1px solid var(--hairline);
}

.section__head {
  max-width: 34rem;
  margin-bottom: 32px;
}

.section h2 {
  font-size: 1.75rem;
  line-height: 1.15;
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-strong);
  text-wrap: balance;
}

.section__head p {
  margin-top: 12px;
  font-size: 1.0625rem;
  color: var(--ink-muted);
  text-wrap: pretty;
}

@media (min-width: 768px) {
  .section {
    padding-block: 80px;
  }

  .section h2 {
    font-size: 2.125rem;
  }
}

/*
 * Column counts are stated rather than left to `auto-fit`. Six cards divide
 * evenly by one, two, and three, and `auto-fit` was picking the count from
 * whatever the minimum track happened to be — which put two columns on a
 * viewport wide enough to have earned three.
 */
.grid {
  display: grid;
  gap: 14px;
  grid-template-columns: 1fr;
}

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

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

.card {
  padding: 22px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-surface);
  background: var(--paper-raised);
  box-shadow: var(--elevation-raised);
}

.card__glyph {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-bottom: 14px;
  border-radius: var(--radius-control);
  background: var(--accent-soft);
  color: var(--accent);
}

.card__glyph svg {
  width: 18px;
  height: 18px;
}

.card h3 {
  font-size: 1.0625rem;
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-snug);
}

.card p {
  margin-top: 8px;
  font-size: 0.9375rem;
  color: var(--ink-muted);
  text-wrap: pretty;
}

/* ---- Steps ------------------------------------------------------------- */

/*
 * One column or three, never two.
 *
 * Three steps in a two-column grid leaves the third alone on a row of its own,
 * which reads as a fourth step that failed to load rather than as the end of a
 * sequence. `auto-fit` did exactly that between roughly 700px and 900px, so the
 * count is stated and the middle case is skipped.
 */
.steps {
  counter-reset: step;
  display: grid;
  gap: 14px;
  padding: 0;
  list-style: none;
  grid-template-columns: 1fr;
}

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

.steps li {
  counter-increment: step;
  display: flex;
  flex-direction: column;
  row-gap: 8px;
  padding: 22px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-surface);
  background: var(--paper-raised);
  box-shadow: var(--elevation-raised);
}

.steps li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  /* Adds to the container's row-gap, so the number sits further from its title
   * than the title does from its own paragraph. */
  margin-bottom: 6px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.8125rem;
  font-weight: var(--weight-strong);
}

.steps h3 {
  font-size: 1.0625rem;
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-snug);
}

.steps p {
  font-size: 0.9375rem;
  color: var(--ink-muted);
}

/* Pushed to the foot of its card. Only the first step carries one, and a row
 * of equal-height cards where one is packed to the brim and the others trail
 * off reads as three different components rather than three steps. */
.snippet {
  /* `auto` pushes it to the foot of the card. The container's `row-gap` is what
   * guarantees clearance from the paragraph, because on the tallest card in the
   * row there is no free space left for `auto` to resolve to. */
  /* All four sides, because `pre` carries a default block margin that the
   * reset above does not cover — it was adding a stray 12px under the card. */
  margin: auto 0 0;
  padding: 12px 14px;
  border-radius: var(--radius-control);
  background: var(--paper-sunken);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--ink-muted);
  /* Wraps rather than scrolls. In the narrowest three-column case the line is
   * 288px in a 223px box, and a horizontal scroller inside a card reads as a
   * sentence that has been cut off — the reader cannot see that there is more.
   * This one is illustrative, so a second line costs nothing. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.snippet b {
  color: var(--accent);
  font-weight: var(--weight-strong);
}

/* ---- Closing band ------------------------------------------------------ */

.band {
  margin-top: 48px;
  padding: 40px 24px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-surface);
  background: var(--paper-raised);
  box-shadow: var(--elevation-lifted);
  text-align: center;
}

.band__mark {
  width: 56px;
  height: 56px;
  margin-bottom: 16px;
}

.band h2 {
  font-size: 1.75rem;
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-strong);
  text-wrap: balance;
}

.band p {
  max-width: 30rem;
  margin: 12px auto 24px;
  color: var(--ink-muted);
  text-wrap: pretty;
}

/* ---- Footer ------------------------------------------------------------ */

.site-footer {
  border-top: 1px solid var(--hairline);
  padding-block: 28px 40px;
  color: var(--ink-faint);
  font-size: 0.9375rem;
}

.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
}

.site-footer a {
  color: var(--ink-faint);
}

/* Motion is decoration here, and the product turns it off rather than
 * shortening it when somebody has asked for less. */
@media (prefers-reduced-motion: reduce) {
  * {
    transition-duration: 0ms !important;
  }
}
