/*
 * koti.so.
 *
 * The token block below is a **copy** of the one in hosting/public/style.css,
 * not an import. Different hostname, different Worker, different deploy — and a
 * stylesheet shared across two of those is a coupling that buys nothing and
 * costs a marketing change the ability to ship without touching sign-in. The
 * copy is small and the values are load-bearing, so they are repeated with the
 * measurements that make them load-bearing.
 *
 * --overlay is the one opaque ground, --e1/--e2/--e3/--e4 are the elevation
 * ladder (a surface is a few percent of white, and how much decides which rung
 * it is on), and the two text alphas are measured: 0.7 is 7.3:1 against the
 * ground and 0.58 is 5.4:1.
 *
 * Single theme, deliberately. Koti has no light appearance, so there is nothing
 * for a light variant here to be consistent with — and a marketing page that
 * looks unlike the product it is selling is lying quietly.
 */

:root {
  color-scheme: dark;

  --ground: #16181b;
  --text: #dde3ea;
  --muted: rgba(221, 227, 234, 0.7);
  --fine: rgba(221, 227, 234, 0.58);

  --e1: rgba(255, 255, 255, 0.035);
  --e2: rgba(255, 255, 255, 0.06);
  --e3: rgba(255, 255, 255, 0.085);
  --e4: rgba(255, 255, 255, 0.11);

  --accent: #92d858;
  --accent-rgb: 146, 216, 88;
  --accent-ink: #10240a;
  --error: #f0b6ae;

  --line: rgba(255, 255, 255, 0.12);

  /* One measure for every band of text, so headings and paragraphs in different
     sections line up down the left edge of the page rather than nearly. */
  --page: 1120px;
  --gutter: clamp(20px, 5vw, 48px);
}

* {
  box-sizing: border-box;
}

/*
 * `hidden` is an attribute, and every rule below that sets `display` beats it.
 * The waitlist's three steps are all `display: flex`, so without this line the
 * page ships with all three showing at once — a bug that is invisible in the
 * markup, invisible in the JavaScript, and obvious the moment anybody looks.
 */
[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font: 16px/1.6 -apple-system, BlinkMacSystemFont, 'SF Pro Text', ui-sans-serif, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3 {
  margin: 0;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(34px, 5vw, 52px);
  line-height: 1.08;
  font-weight: 600;
}

h2 {
  font-size: clamp(25px, 3vw, 33px);
  line-height: 1.16;
  font-weight: 600;
}

h3 {
  font-size: 16px;
  line-height: 1.35;
  font-weight: 600;
}

p {
  margin: 0;
}

a {
  color: inherit;
  text-underline-offset: 3px;
}

/* Visible, and on its own ground so it reads over both the page and a raised
   control. The accent is 10.3:1 against the ground. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Tighter on a field, which sits 7px under its own label: at 3px the ring runs
   through the descenders of the thing telling you what to type in it. */
input:focus-visible,
select:focus-visible {
  outline-offset: 2px;
}

/* The thank-you is focusable so the caret has somewhere to land, and it is not
   a control — a ring around a paragraph reads as an error. */
.wl-done:focus-visible {
  outline: none;
}

.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.lead {
  color: var(--muted);
  font-size: clamp(15.5px, 1.5vw, 17.5px);
  line-height: 1.6;
  max-width: 54ch;
}

.fine {
  color: var(--fine);
  font-size: 13px;
  line-height: 1.55;
}

.error {
  color: var(--error);
}

.mark {
  width: 26px;
  height: 26px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--e2);
  color: var(--text);
}

.mark svg {
  width: 17px;
  height: 17px;
  display: block;
}

.mark.is-small {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: none;
}

.mark.is-small svg {
  width: 14px;
  height: 14px;
}

/* --------------------------------------------------------------------- nav */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 16px var(--gutter);
  background: rgba(22, 24, 27, 0.92);
  backdrop-filter: saturate(160%) blur(14px);
}

/* The bar bleeds to the window edge; its contents do not. Same `--page` and the
   same gutters as every section below, so the wordmark sits directly above the
   headline rather than 40px to the left of it. */
.nav-inner {
  max-width: var(--page);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: -0.01em;
}

.nav-name {
  /* Its own selector so the mark can stand alone on a phone, where the name
     costs more room than it earns next to an icon that already says it. */
  display: inline;
}

.nav-cta {
  padding: 8px 14px;
  border-radius: 9px;
  background: var(--e2);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
}

.nav-cta:hover {
  background: var(--e3);
}

/* -------------------------------------------------------------------- hero */

.hero {
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(40px, 7vw, 84px) var(--gutter) clamp(48px, 8vw, 96px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}

.hero-copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Capped rather than fluid: the window drawing stops being legible past about
   this width, and a hero whose right half is a 600px diagram of five grey bars
   is worse than one with air in it. */
.hero-art {
  display: flex;
  justify-content: center;
  max-width: 480px;
  width: 100%;
  justify-self: end;
}

.hero h1 {
  max-width: 15ch;
}

/* --------------------------------------------------------------- waitlist */

/*
 * One box, three states, and it must not resize as they swap — the sections
 * below it would jump under the reader's cursor between pressing a button and
 * seeing what it did. `min-height` rather than a fixed one: the error line and
 * the questions are genuinely different heights and pinning them would clip.
 */
.waitlist {
  margin-top: 6px;
  scroll-margin-top: 88px;
}

.wl-frame {
  min-height: 118px;
}

.wl-step {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 460px;
}

.wl-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}

.wl-row-end {
  justify-content: flex-end;
}

.wl-done {
  gap: 8px;
}

.wl-heading {
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.wl-note {
  max-width: 44ch;
}

/* The label a screen reader needs and the layout does not: the field's job is
   said by the placeholder and by the button beside it, and a visible "Your
   email address" over a single input is noise. Clipped rather than
   `display: none`, which would take it out of the accessibility tree too. */
.wl-hidden-label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Off screen rather than hidden: a bot filling fields reads the markup, and
   `hidden` or `display: none` is the first thing it learns to skip. Aria-hidden
   and tabindex -1 keep it away from anybody real. */
.wl-pot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

input[type='email'],
input[type='text'],
select {
  min-height: 46px;
  padding: 11px 13px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: var(--e2);
  color: var(--text);
  font: inherit;
  font-size: 14.5px;
}

input[type='email'] {
  flex: 1;
  min-width: 0;
}

input::placeholder {
  color: var(--fine);
}

select {
  appearance: none;
  /* Drawn rather than an asset, and in `currentColor` so it never disagrees with
     the text beside it. */
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 21px, calc(100% - 13px) 21px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

label,
legend {
  font-size: 13px;
  font-weight: 600;
  padding: 0;
}

.pills {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

/*
 * A radio you can hit. The input itself is clipped rather than removed, so it
 * keeps its role, its name and its keyboard behaviour — arrow keys still move
 * through the group — and `:has()` puts the selected state on the label around
 * it.
 */
.pill {
  position: relative;
  padding: 9px 13px;
  border-radius: 999px;
  background: var(--e2);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}

.pill input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.pill:hover {
  background: var(--e3);
}

.pill:has(input:checked) {
  background: rgba(var(--accent-rgb), 0.18);
  color: #a9e176;
}

.pill:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.primary {
  min-height: 46px;
  padding: 11px 18px;
  border: 0;
  border-radius: 10px;
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.primary:hover {
  opacity: 0.92;
}

.primary:disabled {
  opacity: 0.6;
  cursor: default;
}

.primary.as-link,
.ghost.as-link {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.ghost {
  min-height: 46px;
  padding: 11px 16px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
}

.ghost:hover {
  background: var(--e2);
  color: var(--text);
}

/* ------------------------------------------------------------------- bands */

.band {
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(48px, 7vw, 88px) var(--gutter);
  border-top: 1px solid var(--line);
}

.band-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(28px, 5vw, 60px);
  align-items: center;
}

.band-head {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 46ch;
}

.band-art {
  display: flex;
  justify-content: center;
  width: 100%;
}

/*
 * The other axis. Each row is a project, the pips are the sessions running in
 * it, and the lit row is the one you are standing on — which is the whole claim
 * the heading makes, and the one thing the hero's drawing cannot show, because
 * the hero is inside a single project.
 */
.pages {
  display: flex;
  flex-direction: column;
  gap: 7px;
  width: 100%;
  max-width: 330px;
  padding: 14px;
  border-radius: 14px;
  background: var(--e1);
  border: 1px solid var(--line);
}

.pg {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 12px;
  border-radius: 10px;
  background: var(--e2);
  opacity: 0.55;
}

.pg.is-on {
  background: var(--e3);
  opacity: 1;
  box-shadow: inset 2px 0 0 var(--accent);
}

.pg-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--fine);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pg.is-on .pg-name {
  color: var(--text);
}

.pg-cards {
  display: flex;
  flex: none;
  gap: 4px;
}

.pg-cards i {
  width: 12px;
  height: 16px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.16);
}

.pg-cards i.is-awake {
  background: rgba(var(--accent-rgb), 0.55);
}

/* ---------------------------------------------------------------- features */

.feature {
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(44px, 6vw, 76px) var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(28px, 5vw, 60px);
  align-items: center;
}

/* The art alternates sides down the page. `order` rather than two markup
   orders, so the copy always comes first in the document and a screen reader
   never meets a decorative diagram before the heading it illustrates. */
.feature.is-flipped .feature-copy {
  order: 2;
}

.feature-copy {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.feature-copy p {
  color: var(--muted);
  max-width: 52ch;
  font-size: 15.5px;
}

.feature-art {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
  justify-content: center;
}

/* ------------------------------------------------------------------- mocks */

/*
 * Everything below draws a piece of the product out of tokens. Nothing here is
 * an image and nothing is to scale — the job is to make the shape of the thing
 * legible next to the sentence describing it, not to stand in for a screenshot.
 */

.win {
  width: 100%;
  border-radius: 16px;
  overflow: hidden;
  background: var(--e1);
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}

.win-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--e2);
}

.dots {
  display: flex;
  gap: 5px;
}

.dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
}

.win-path {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--fine);
}

.win-marks {
  display: flex;
  gap: 6px;
}

.win-marks i {
  width: 12px;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.16);
}

.win-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
}

/*
 * A page is a directory and it fills the window; the two clipped ones are the
 * pages a swipe would bring. They are the reason this drawing says anything at
 * all — a single page of cards is just a grid.
 */
.page {
  border-radius: 12px;
  padding: 10px;
}

.page.is-ghost {
  height: 34px;
  display: flex;
  align-items: center;
  background: var(--e1);
  opacity: 0.5;
}

.page-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--fine);
}

.page.is-live {
  background: var(--e2);
}

.cards {
  display: grid;
  grid-template-columns: 1fr 1fr 0.35fr;
  gap: 8px;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  height: 132px;
  padding: 10px;
  border-radius: 10px;
  background: var(--e2);
}

.card.is-awake {
  background: rgba(var(--accent-rgb), 0.11);
}

/* The card the strip has scrolled halfway off, which is what says there are
   more of them than fit. */
.card.is-edge {
  opacity: 0.45;
}

.card.is-wide {
  height: auto;
  width: 100%;
}

.card-top {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}

.bar {
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
}

.bar.is-accent {
  background: rgba(var(--accent-rgb), 0.5);
}

.bar.w40 {
  width: 40%;
}

.bar.w70 {
  width: 70%;
}

.bar.w85 {
  width: 85%;
}

.pulse {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.18);
}

.chip {
  align-self: flex-start;
  margin-top: auto;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.18);
  color: #a9e176;
  font-size: 10.5px;
  font-weight: 600;
}

.caret {
  width: 6px;
  height: 12px;
  margin-top: auto;
  border-radius: 1px;
  background: var(--text);
  opacity: 0.75;
  animation: blink 1.1s steps(1) infinite;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

.mock {
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border-radius: 14px;
  background: var(--e1);
  border: 1px solid var(--line);
}

.mock-line {
  font-size: 15px;
  font-weight: 600;
}

.mock-sub {
  font-size: 12.5px;
  color: var(--fine);
}

/* --- the notch, and what sits next to it -------------------------------- */

.menubar {
  position: relative;
  width: 100%;
  max-width: 340px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 12px;
  border-radius: 8px 8px 3px 3px;
  /* Not black. The notch below *is* black, and a black cutout on a black bar is
     a rectangle nobody can see — the whole drawing depends on the two reading as
     different things. This is the top of a desktop, not the menu bar itself. */
  background: linear-gradient(180deg, #2b3038, #1d2126);
}

.menubar-notch {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 78px;
  height: 13px;
  border-radius: 0 0 7px 7px;
  background: #000;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.menubar-item {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--text);
}

/* --- the finder --------------------------------------------------------- */

.mock.is-finder {
  gap: 8px;
}

.finder-field {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 0 11px;
  border-radius: 9px;
  background: var(--e2);
}

.finder-field .bar {
  flex: 1;
}

.finder-field .caret {
  margin: 0;
  height: 13px;
}

.finder-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 9px;
}

.finder-row.is-on {
  background: var(--e2);
}

.finder-row .bar {
  flex: 1;
}

.tag {
  flex: none;
  padding: 2px 7px;
  border-radius: 5px;
  background: var(--e3);
  font-size: 10px;
  font-weight: 600;
  color: var(--muted);
}

.stamp {
  flex: none;
  font-size: 10.5px;
  color: var(--fine);
}

/* --- a trigger firing --------------------------------------------------- */

.mock.is-trigger {
  align-items: stretch;
}

.trig-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 11px;
  border-radius: 9px;
  background: var(--e2);
}

.trig-row .bar {
  flex: 1;
}

.clock {
  width: 13px;
  height: 13px;
  flex: none;
  border-radius: 50%;
  border: 1.5px solid var(--muted);
  position: relative;
}

.clock::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 2px;
  width: 1.5px;
  height: 4.5px;
  background: var(--muted);
  transform: translateX(-50%);
}

/* Points at the card below it, and is the only thing in the drawing that says
   the two rows are cause and effect rather than a list. */
.trig-arrow {
  align-self: center;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 7px solid var(--fine);
}

/* --- one cookie jar per project ---------------------------------------- */

.mock.is-jars {
  gap: 12px;
}

.jar {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px;
  border-radius: 10px;
  background: var(--e2);
}

.jar-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  color: var(--fine);
}

.jar-tabs {
  display: flex;
  gap: 6px;
}

.jar-tabs i {
  height: 22px;
  flex: 1;
  border-radius: 5px;
  background: var(--e3);
}

/* --- the sun's three states -------------------------------------------- */

.mock.is-awake-states {
  flex-direction: row;
  gap: 8px;
  max-width: 340px;
}

.state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 14px 6px;
  border-radius: 10px;
  background: var(--e2);
}

.state-name {
  font-size: 10.5px;
  color: var(--fine);
  text-align: center;
}

.sun {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
}

.state.is-on .sun {
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.18);
}

.state.is-dark {
  background: #000;
}

/* ------------------------------------------------------------------- close */

.close {
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(56px, 8vw, 100px) var(--gutter);
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
}

/* ------------------------------------------------------------------ footer */

.foot {
  max-width: var(--page);
  margin: 0 auto;
  padding: 28px var(--gutter) 56px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  text-align: center;
}

/* A row of its own rather than three flex children on one line. `flex-basis:
   100%` on the note would have been the tidy version and does not work: a
   `max-width` clamps the hypothetical main size that the line break is decided
   from, so the note stays on the row and the measure is what breaks. */
.foot-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 16px 26px;
}

.foot-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 600;
  font-size: 14.5px;
}

.foot-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 18px;
  font-size: 13.5px;
  color: var(--muted);
}

.foot .fine {
  max-width: 62ch;
}

/* -------------------------------------------------------------- responsive */

/* One column below this: the art is decorative, and two columns of it against a
   40-character measure is worse than one of each. */
@media (max-width: 900px) {
  /*
   * `minmax(0, …)` and not `1fr`, which is `minmax(auto, 1fr)` and means "never
   * narrower than my min-content". Any long unbreakable string in a column —
   * a path, a command, an address — then widens the column past the page and the
   * whole document scrolls sideways, on the one viewport where that is worst.
   */
  .hero,
  .feature,
  .band-inner {
    grid-template-columns: minmax(0, 1fr);
  }

  .feature.is-flipped .feature-copy {
    order: 0;
  }

  .feature-art,
  .band-art {
    align-items: flex-start;
    justify-content: flex-start;
  }

  .hero h1 {
    max-width: none;
  }

  .hero-art {
    justify-self: start;
  }
}

@media (max-width: 380px) {
  .nav-name {
    display: none;
  }
}

@media (max-width: 520px) {
  .wl-row {
    flex-direction: column;
  }

  .wl-row-end {
    flex-direction: row;
  }

  .mock.is-awake-states {
    flex-direction: row;
  }
}

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

  .caret {
    animation: none;
  }
}

/* ------------------------------------------------------------------ legal */

/*
 * Terms, privacy, pricing and refunds. A reading surface rather than a card:
 * these are long, they are meant to be read, and a 420px column with a border
 * round it would be pretending they are a dialog.
 *
 * Carried over from hosting/public/style.css, where the same rules dressed the
 * same two documents on the sign-in host. They live here now because koti.so is
 * where the commercial pages live.
 */
.legal {
  max-width: 680px;
  margin: 0 auto;
  padding: 56px 24px 96px;
  text-align: left;
}

.legal h1 {
  margin: 0 0 6px;
  font-size: 30px;
  line-height: 1.12;
  letter-spacing: -0.02em;
}

.legal .updated {
  margin: 0 0 36px;
  color: var(--muted);
  font-size: 13.5px;
}

.legal h2 {
  margin: 36px 0 10px;
  font-size: 18px;
}

.legal h3 {
  margin: 22px 0 6px;
  font-size: 15px;
}

.legal p,
.legal li {
  font-size: 15px;
  line-height: 1.65;
  color: var(--muted);
}

/* The base rule zeroes every margin, which is right for a landing page built
   out of flex columns and wrong for prose — without this, consecutive
   paragraphs read as one wall and a reader loses their place mid-clause. */
.legal p {
  margin: 0 0 14px;
}

.legal ul {
  margin: 0 0 14px;
}

.legal strong,
.legal b {
  color: var(--text);
}

.legal ul {
  padding-left: 20px;
}

.legal li {
  margin-bottom: 7px;
}

.legal table {
  width: 100%;
  border-collapse: collapse;
  margin: 14px 0;
  font-size: 14px;
}

.legal th,
.legal td {
  padding: 9px 10px;
  border: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  color: var(--muted);
}

.legal th {
  font-weight: 600;
  color: var(--text);
}

/* The details only the company can fill in. Marked rather than invented, so a
   placeholder cannot quietly survive to production — there are none left, and
   the rule stays for the next revision that adds one. */
.legal .todo {
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(220, 160, 30, 0.18);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.87em;
}

.legal .back {
  display: inline-block;
  margin-top: 40px;
  color: var(--muted);
  font-size: 13.5px;
}

/* Every commercial page carries the same set of links and the same company
   line, because a reviewer landing on any one of them should be able to reach
   the other three and see who is behind it. */
.legal-foot {
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}

.legal-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 18px;
  font-size: 13.5px;
  color: var(--muted);
}

/* ----------------------------------------------------------------- plans */

/*
 * Two prices, not two products. Side by side rather than in a comparison table,
 * because there is nothing to compare across — every row would read "yes", and a
 * matrix of yeses is a way of pretending there is a decision to make.
 */
.plans {
  max-width: var(--page);
  margin: 0 auto;
  padding: 8px var(--gutter) 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
}

.plan {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 26px;
  border-radius: 16px;
  background: var(--e1);
  border: 1px solid var(--line);
}

/* The button sits on the floor of the card whatever the note above it says, so
   two cards with different-length notes still line their buttons up. */
.plan .primary,
.plan .ghost {
  margin-top: 18px;
  justify-content: center;
}

.plan .ghost {
  background: var(--e2);
  color: var(--text);
}

.plan .ghost:hover {
  background: var(--e3);
}

/* The yearly one is a rung up the ladder rather than a different colour, the
   same way the recommended provider is on the sign-in screen. */
.plan.is-lead {
  background: var(--e2);
  border-color: rgba(var(--accent-rgb), 0.35);
}

.plan-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.plan-tag {
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.18);
  color: #a9e176;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0;
}

.plan-price {
  font-size: 15px;
  color: var(--muted);
}

.plan-price b {
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--text);
}

.plan-note {
  font-size: 13px;
  color: var(--fine);
}

.plans-foot {
  max-width: var(--page);
  margin: 0 auto;
  padding: 16px var(--gutter) 24px;
  font-size: 13.5px;
  color: var(--fine);
}

/* ------------------------------------------------------------- page head */

/*
 * The top of a page that is not the landing page. Same measure and gutters as
 * everything else; a smaller h1 than the hero's, because this one is a label
 * for the page rather than a claim about the product.
 */
.head {
  max-width: var(--page);
  margin: 0 auto;
  padding: clamp(36px, 6vw, 68px) var(--gutter) clamp(20px, 3vw, 32px);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.head h1 {
  font-size: clamp(30px, 4vw, 42px);
}

/* ----------------------------------------------------------------- ticks */

.ticks {
  list-style: none;
  margin: clamp(20px, 3vw, 28px) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px 28px;
}

.ticks li {
  position: relative;
  padding-left: 26px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
}

/* Drawn rather than a character: a check glyph is a different width in every
   font stack, and this one has to line up down a column. */
.ticks li::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 8px;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

/* -------------------------------------------------------------------- qa */

.qa {
  margin-top: clamp(20px, 3vw, 28px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 22px 32px;
}

.q {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.q p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--muted);
  max-width: 46ch;
}
