/*
  THE SITE'S OWN DRESS, cut from the app's palette rather than a new one.

  Every colour here is in `apps/mobile/src/palette.ts` — `pageBg`, `deepBg`,
  `primary`, and the two ends of `skyColor`. A front door in colours the product
  does not use is a front door to somewhere else.

  IT IS ONE SCHEME AND DELIBERATELY DARK. The app follows the device because a
  person reads weathr in bed and at a desk; a landing page is looked at once, on
  somebody else's terms, and a page that changed its mind about being light
  would be a page with two designs and one of them untested. Dark is the one the
  sky ramp is cut for.
*/

/*
  SELF-HOSTED, NOT GOOGLE FONTS. Quicksand is the app's face and this is the
  same file the app loads, copied out of the same package by `Dockerfile.web` —
  so the two cannot come to be set differently, and the front door makes no
  third-party request before it has drawn anything.
*/
@font-face {
  font-family: 'Quicksand';
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/Quicksand_500Medium.ttf') format('truetype');
}
@font-face {
  font-family: 'Quicksand';
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/Quicksand_700Bold.ttf') format('truetype');
}

:root {
  --page: #18242f;
  --deep: #161a1d;
  --panel: #1e2c39;
  --ink: #ffffff;
  --quiet: #9fb3c4;
  --primary: #1e88e5;
  --sky-top: #326ea0;
  --sky-light: #8cc4f2;
  --gutter: clamp(20px, 5vw, 48px);
  --column: 760px;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: 'Quicksand', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-weight: 500;
  font-size: 18px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ── The bar ─────────────────────────────────────────────────────────────── */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px var(--gutter);
  max-width: 1180px;
  margin: 0 auto;
}

.mark img {
  display: block;
}

.bar nav {
  display: flex;
  align-items: center;
  gap: 24px;
}

.bar nav a {
  color: var(--quiet);
  text-decoration: none;
}

.bar nav a:hover,
.bar nav a[aria-current='page'] {
  color: var(--ink);
}

/* ── The one button shape ────────────────────────────────────────────────── */

.cta,
.bar nav a.cta {
  background: var(--primary);
  color: #fff;
  border-radius: 999px;
  padding: 10px 22px;
  font-weight: 700;
  text-decoration: none;
  display: inline-block;
  transition: filter 120ms ease;
}

.cta:hover {
  filter: brightness(1.12);
}

.cta.big {
  font-size: 20px;
  padding: 16px 34px;
}

/*
  THE SECOND DOOR IS OUTLINED. `See it in action` and `Sign up free` stand side
  by side, and two filled pills would ask the reader to choose between two
  equally loud things — the demo is the one the page is arguing for.
*/
.cta.quiet {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.28);
}

.cta.quiet:hover {
  filter: none;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.6);
}

.doors {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 12px;
}

/* ── The hero, and the demo in it ────────────────────────────────────────── */

main {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--gutter) 40px;
}

.hero {
  padding: clamp(24px, 6vw, 64px) 0 8px;
}

h1 {
  font-size: clamp(40px, 7vw, 76px);
  line-height: 1.05;
  margin: 0 0 20px;
  letter-spacing: -0.02em;
}

.lead {
  font-size: clamp(19px, 2.4vw, 24px);
  color: var(--quiet);
  max-width: var(--column);
  margin: 0 0 36px;
}

/*
  SEE IT IN ACTION. Its own section under the hero, so the page opens on words
  and the eight megabytes of the app wait until somebody scrolls or presses
  their way here. `scroll-margin` keeps the heading on screen when a door
  scrolls to it.
*/
.action {
  padding: clamp(32px, 6vw, 64px) 0 0;
  scroll-margin-top: 16px;
}

.action .lead {
  margin-bottom: 28px;
}

/*
  THE DEMO'S BOX HOLDS ITS SHAPE BEFORE ANYTHING IS IN IT.

  The poster and the iframe that replaces it are the same size, so pressing does
  not move the page under the hand — which is what an iframe dropped into a page
  at its natural height does.
*/
/*
  AND IT IS TALL ENOUGH FOR THE DESK, which is a floor the APP sets. The app
  draws its desktop shell only in a window at least 900 wide and `MIN_HEIGHT`
  (746) tall — `apps/mobile/src/lib/layout.ts` — and inside a frame the frame
  IS the window. A 16:10 box capped at 72vh came out 648 tall on a 1440×900
  screen, so the page promised the desk and framed the phone. 780 clears the
  floor with the border and a little room for that floor to move; the phone
  rule below still takes the box back down, where only the poster is drawn.
*/
.demo {
  position: relative;
  height: clamp(780px, 86vh, 920px);
  border-radius: 18px;
  overflow: hidden;
  background: linear-gradient(180deg, var(--sky-top), var(--page));
  border: 1px solid rgba(255, 255, 255, 0.1);
}

/*
  THE FRAME ARRIVES OVER THE POSTER, NOT IN PLACE OF IT. The app takes a few
  seconds to boot, and an empty box for those seconds reads as a broken embed;
  so the iframe stands on top at nothing and fades in once it has loaded.
*/
.demo iframe {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  transition: opacity 400ms ease;
}

.demo iframe.ready {
  opacity: 1;
}

.demo-poster {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  text-decoration: none;
  color: var(--ink);
}

.demo-play {
  width: 78px;
  height: 78px;
  border-radius: 50%;
  background: var(--primary);
  display: grid;
  place-items: center;
  transition: transform 140ms ease;
}

/* The triangle, drawn rather than fetched: one shape is not worth a request. */
.demo-play::after {
  content: '';
  border-left: 22px solid #fff;
  border-top: 14px solid transparent;
  border-bottom: 14px solid transparent;
  margin-left: 6px;
}

.demo-poster:hover .demo-play {
  transform: scale(1.06);
}

.demo-words {
  text-align: center;
  display: grid;
  gap: 4px;
}

.demo-words strong {
  font-size: 22px;
}

.demo-words small {
  color: var(--quiet);
  font-size: 16px;
}

.fineprint {
  color: var(--quiet);
  font-size: 15px;
  max-width: var(--column);
  margin: 16px 0 0;
}

/* ── The problems ────────────────────────────────────────────────────────── */

.problem,
.how,
.close {
  padding: clamp(40px, 7vw, 76px) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

h2 {
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.15;
  margin: 0 0 20px;
  max-width: var(--column);
  letter-spacing: -0.01em;
}

.problem p,
.close p {
  max-width: var(--column);
  color: var(--quiet);
  margin: 0 0 16px;
}

.problem p:first-of-type {
  color: var(--ink);
}

/* ── How it works ────────────────────────────────────────────────────────── */

.how ol {
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: 28px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  padding: 0;
  margin: 0;
}

.how li {
  counter-increment: step;
  background: var(--panel);
  border-radius: 14px;
  padding: 26px;
}

.how li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--primary);
  font-weight: 700;
  margin-bottom: 14px;
}

.how h3 {
  margin: 0 0 8px;
  font-size: 21px;
}

.how p {
  margin: 0;
  color: var(--quiet);
  font-size: 17px;
}

/* ── The manifesto ───────────────────────────────────────────────────────── */

/*
  ONE COLUMN AND A NUMBER BESIDE EACH RULE, where `How it works` is three cards
  in a row. Those are steps a reader takes in any order; these are rules a
  reader is meant to take in one at a time, and a paragraph each does not fit a
  card a third of a page wide.
*/
.manifesto {
  padding: 8px 0 clamp(40px, 7vw, 76px);
}

.manifesto ol {
  list-style: none;
  counter-reset: rule;
  max-width: var(--column);
  padding: 0;
  margin: 0;
}

.manifesto li {
  counter-increment: rule;
  display: grid;
  grid-template-columns: 56px 1fr;
  column-gap: 20px;
  padding: 30px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.manifesto li::before {
  content: counter(rule);
  grid-row: span 2;
  font-size: 44px;
  font-weight: 700;
  line-height: 1;
  color: var(--primary);
}

.manifesto h2 {
  font-size: clamp(22px, 3vw, 28px);
  margin: 0 0 10px;
}

.manifesto p {
  margin: 0;
  color: var(--quiet);
}

/* ── Problems and posts: the pages written to be READ ──────────────────────── */

/*
  A PAGE HEADED WITH A PROBLEM ANSWERS IT IN ITS FIRST BOX.

  `.answer` is the paragraph a search snippet and a model's citation both lift:
  the problem restated as an answer in under sixty words, standing on its own.
  It is drawn as a panel so a reader who came for the answer finds it without
  reading the page, which is the same reason it is written to stand alone.
*/
.crumbs {
  font-size: 15px;
  color: var(--quiet);
  margin: 0 0 18px;
}

.crumbs a {
  color: var(--quiet);
}

.kicker {
  display: inline-block;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sky-light);
  margin: 0 0 12px;
}

.answer {
  max-width: var(--column);
  background: var(--panel);
  border-left: 4px solid var(--primary);
  border-radius: 12px;
  padding: 20px 24px;
  margin: 0 0 8px;
}

.answer p {
  margin: 0;
  color: var(--ink);
}

.prose {
  max-width: var(--column);
  padding: clamp(28px, 5vw, 52px) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.prose h2 {
  font-size: clamp(24px, 3.2vw, 32px);
  margin: 36px 0 14px;
}

.prose h2:first-child {
  margin-top: 0;
}

.prose h3 {
  font-size: 21px;
  margin: 28px 0 8px;
}

.prose p,
.prose li {
  color: var(--quiet);
}

.prose p {
  margin: 0 0 16px;
}

.prose strong {
  color: var(--ink);
}

.prose a,
.answer a,
.card-list a {
  color: var(--sky-light);
}

.prose ul,
.prose ol {
  padding-left: 22px;
  margin: 0 0 16px;
}

.prose li {
  margin: 0 0 8px;
}

.prose blockquote {
  margin: 20px 0;
  padding: 4px 0 4px 20px;
  border-left: 3px solid rgba(255, 255, 255, 0.2);
  color: var(--ink);
}

/* A comparison is a table, and a table is the one thing allowed to scroll. */
.table-wrap {
  overflow-x: auto;
  margin: 8px 0 20px;
}

.prose table {
  border-collapse: collapse;
  width: 100%;
  min-width: 520px;
  font-size: 16px;
}

.prose th,
.prose td {
  text-align: left;
  vertical-align: top;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--quiet);
}

.prose th {
  color: var(--ink);
}

/*
  THE FAQ IS `details`, so it opens with no script and a crawler reads every
  answer in the markup — the same text the FAQPage structured data carries.
*/
.faq details {
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding: 14px 0;
}

.faq summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--ink);
  font-size: 19px;
}

.faq details p {
  margin: 10px 0 0;
}

.sources {
  font-size: 15px;
}

.sources li {
  margin-bottom: 6px;
}

.byline {
  color: var(--quiet);
  font-size: 15px;
  margin: 0 0 24px;
}

/* ── The hub: six categories, each a run of cards ───────────────────────────── */

.category {
  padding: clamp(36px, 6vw, 64px) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  scroll-margin-top: 12px;
}

.category > p {
  max-width: var(--column);
  color: var(--quiet);
  margin: 0 0 24px;
}

.card-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.card-list li {
  background: var(--panel);
  border-radius: 14px;
  padding: 22px 24px;
}

.card-list h3 {
  font-size: 20px;
  margin: 0 0 8px;
  line-height: 1.3;
}

.card-list h3 a {
  color: var(--ink);
  text-decoration: none;
}

.card-list h3 a:hover {
  text-decoration: underline;
}

.card-list p {
  margin: 0;
  color: var(--quiet);
  font-size: 16px;
}

.card-list .meta {
  font-size: 14px;
  margin: 0 0 8px;
}

.related {
  padding: clamp(28px, 5vw, 52px) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* ── The close, and the foot ─────────────────────────────────────────────── */

.close .doors {
  margin-top: 12px;
}

footer {
  background: var(--deep);
  padding: 40px var(--gutter);
  text-align: center;
  color: var(--quiet);
}

footer img {
  opacity: 0.65;
}

footer p {
  margin: 10px 0 0;
  font-size: 15px;
}

.foot {
  text-align: left;
}

.foot-grid {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  gap: 32px;
  grid-template-columns: 2fr 1fr 1fr;
}

.foot-brand p {
  max-width: 340px;
}

.foot nav {
  display: grid;
  align-content: start;
  gap: 8px;
}

.foot nav h2 {
  font-size: 15px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 4px;
}

.foot nav a {
  color: var(--quiet);
  text-decoration: none;
  font-size: 16px;
}

.foot nav a:hover {
  color: var(--ink);
}

.foot .foot-line {
  max-width: 1180px;
  margin: 32px auto 0;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

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

  .foot-brand {
    grid-column: 1 / -1;
  }
}

/*
  ON A PHONE THE DEMO IS A LINK AND THE BOX IS SHORTER.

  The iframe is never used here — see `site.js` — so the poster is all this box
  will ever hold, and a 16:10 well most of the screen tall is a lot of nothing
  to scroll past on the way to the words.
*/
@media (max-width: 900px) {
  .demo {
    height: auto;
    aspect-ratio: 4 / 3;
    max-height: 420px;
  }

  /*
    ON A PHONE THE ROW IS THE WORDMARK, `Sign in` AND THE BUTTON. Somebody with
    an account on a phone that has never signed in lands here first, so `Sign
    in` is the one word that may not go; the pages it displaces are all in the
    foot, which carries the whole map of the site at every width.
  */
  .bar nav a.wide-only {
    display: none;
  }

  .manifesto li {
    grid-template-columns: 40px 1fr;
    column-gap: 14px;
  }

  .manifesto li::before {
    font-size: 34px;
  }
}

/*
  THREE THINGS ON ONE ROW AT PHONE WIDTH: the wordmark, a word and the button.
  At 400 points and full size they need about 410, so the row gives a little
  back rather than wrapping the button under the logo.
*/
@media (max-width: 440px) {
  .bar nav {
    gap: 16px;
  }

  .bar nav a {
    font-size: 16px;
  }

  .bar nav a.cta {
    padding: 8px 16px;
  }

  .mark img {
    width: 108px;
    height: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .demo-play,
  .demo iframe,
  .cta {
    transition: none;
  }
}
