@font-face {
  font-family: "Inter";
  src: url("fonts/Inter.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

/* Near-black primary, alpha hairlines and the toolbar banana, as in the
   extension's theme.css, but on warm (stone) neutrals: the page is mostly
   amber and off-white, and cool zinc greys fought both. */
:root {
  --bg: #fafaf9;
  --surface: #ffffff;
  --fg: #1c1917;
  --muted: #625c57;
  --line: rgb(28 25 23 / 0.1);
  --primary: #1c1917;
  --primary-fg: #fafaf9;
  --brand: #f5a623;
  /* Darkest amber that still reads as the brand: 5.1:1 on --bg, so the
     14px eyebrows clear WCAG AA. #b86e00 was 3.8:1. */
  --brand-ink: #9a5c00;
  /* Image edges are pure black or white, never a tinted neutral: a tinted
     line picks up the surface behind it and reads as grime. */
  --shot-ring: rgb(0 0 0 / 0.1);
  --shot-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 12px 32px -8px rgb(0 0 0 / 0.14),
    0 40px 80px -24px rgb(0 0 0 / 0.12);
  /* Raised surfaces (cards, the outline button) get depth from a translucent
     stack rather than a solid border, so one token works on any background. */
  --elevation-raised:
    0 0 0 1px rgb(0 0 0 / 0.05), 0 1px 3px rgb(0 0 0 / 0.05), 0 4px 10px -4px rgb(0 0 0 / 0.05);
  --elevation-raised-hover:
    0 0 0 1px rgb(0 0 0 / 0.08), 0 1px 3px rgb(0 0 0 / 0.07), 0 6px 14px -4px rgb(0 0 0 / 0.08);
  /* Dividers draw at half a pixel on high-density screens. */
  --hairline: 1px;
  --radius: 14px;
  --wrap: 1120px;
  /* Half the width of the screenshots and videos (2396px), so on a 2x screen
     they draw pixel for pixel. At 1280px they were stretched 7% and every
     edge went soft. */
  --wrap-wide: 1198px;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0c0a09;
    --surface: #171412;
    --fg: #f5f5f4;
    --muted: #a8a29e;
    /* Translucent, like the light value, so it sits right on --bg and
       --surface alike. Matches the old solid #292524 on --bg. */
    --line: rgb(255 255 255 / 0.12);
    --primary: #fafaf9;
    --primary-fg: #1c1917;
    --brand-ink: #f5a623;
    --shot-ring: rgb(255 255 255 / 0.1);
    /* Drop shadows vanish on a near-black page; the ring carries the edge. */
    --shot-shadow: 0 0 #0000;
    --elevation-raised: 0 0 0 1px rgb(255 255 255 / 0.09);
    --elevation-raised-hover: 0 0 0 1px rgb(255 255 255 / 0.15);
    color-scheme: dark;
  }
}

@media (min-resolution: 2dppx) {
  :root {
    --hairline: 0.5px;
  }
}

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

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "cv11", "ss01";
}

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

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

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: inherit;
}

::selection {
  background: rgb(245 166 35 / 0.35);
}

:focus-visible {
  /* Neutral on purpose: an amber ring clashed with the amber UI around it. */
  outline: 2px solid var(--fg);
  outline-offset: 3px;
}

/* Zero specificity, so a control's own radius (the pill buttons) wins and
   the ring follows its shape instead of squaring it off. */
:where(:focus-visible) {
  border-radius: 6px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 20px;
}

/* ---------- Nav ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: var(--hairline) solid var(--line);
}

.nav-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: 60px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 640;
  font-size: 18px;
  letter-spacing: -0.02em;
  text-decoration: none;
  /* 44px tall hit area without moving the layout. */
  padding-block: 8px;
  margin-block: -8px;
}

.brand-mark {
  width: 22px;
  height: 22px;
  color: var(--brand);
}

.nav-links {
  display: flex;
  gap: 24px;
  margin-left: auto;
  font-size: 15px;
}

.nav-links a {
  /* 44px tall hit area without moving the layout. */
  padding-block: 10px;
  margin-block: -10px;
  color: var(--muted);
  text-decoration: none;
  transition: color 150ms var(--ease);
}

@media (hover: hover) {
  .nav-links a:hover {
    color: var(--fg);
  }
}

@media (max-width: 640px) {
  .nav-links {
    display: none;
  }
  .nav-inner .btn-small {
    margin-left: auto;
  }
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 48px;
  padding-inline: 22px;
  border-radius: 999px;
  background: var(--primary);
  color: var(--primary-fg);
  font-weight: 560;
  font-size: 16px;
  text-decoration: none;
  white-space: nowrap;
  transition:
    transform 160ms var(--ease),
    opacity 160ms var(--ease),
    background-color 160ms var(--ease),
    box-shadow 160ms var(--ease);
}

/* Hover only where there is a pointer, so a tapped button doesn't stay
   dimmed on a phone. */
@media (hover: hover) {
  .btn:hover {
    opacity: 0.88;
  }
}

.btn:active {
  transform: scale(0.96);
}

/* A leading icon reads as extra padding; take 2px back on that side. */
.btn:has(> .btn-icon:first-child) {
  padding-left: 20px;
}

.btn-small {
  position: relative;
  height: 36px;
  padding-inline: 16px;
  font-size: 14px;
}

/* 36px looks right in the nav bar; the hit area grows to 44px. */
.btn-small::before {
  content: "";
  position: absolute;
  inset: -4px 0;
}

/* A raised white pill beside the solid one, rather than an outline: the
   shadow stack reads as a surface, where a flat ring read as a cut-out. */
.btn-ghost {
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--elevation-raised);
}

@media (hover: hover) {
  .btn-ghost:hover {
    opacity: 1;
    box-shadow: var(--elevation-raised-hover);
  }
}

.btn-icon {
  width: 18px;
  height: 18px;
  flex: none;
}

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

.hero {
  padding-top: 88px;
  text-align: center;
}

.eyebrow {
  font-size: 14px;
  font-weight: 560;
  color: var(--brand-ink);
  letter-spacing: 0;
  margin-bottom: 14px;
}

.hero h1 {
  font-size: clamp(40px, 7vw, 76px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.02;
  max-width: 22ch;
  margin-inline: auto;
}

.lede {
  max-width: 34em;
  margin: 24px auto 0;
  font-size: clamp(17px, 2vw, 20px);
  color: var(--muted);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 36px;
}

.shot {
  margin: 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow:
    0 0 0 1px var(--shot-ring),
    var(--shot-shadow);
}

.shot-hero {
  margin-top: 72px;
}

/* The hero text reads in order: eyebrow, headline, lede, buttons. Only once
   per visit, and not at all under reduced motion. The screenshot is left
   out on purpose: fading it in stopped Chrome counting it as the largest
   paint, which moved Largest Contentful Paint from ~40ms to ~600ms. */
@media (prefers-reduced-motion: no-preference) {
  .hero > :not(.shot-hero) {
    animation: rise 500ms var(--ease) backwards;
  }
  .hero > :nth-child(2) {
    animation-delay: 60ms;
  }
  .hero > :nth-child(3) {
    animation-delay: 120ms;
  }
  .hero > :nth-child(4) {
    animation-delay: 180ms;
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

@media (max-width: 640px) {
  .hero {
    padding-top: 56px;
  }
  .shot {
    border-radius: 10px;
  }
  .shot-hero {
    margin-top: 44px;
  }
}

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

.section {
  padding-top: 128px;
}

@media (max-width: 640px) {
  .section {
    padding-top: 88px;
  }
}

.section-title {
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 700;
  text-align: center;
}

.section-lede {
  margin-top: 12px;
  text-align: center;
  color: var(--muted);
}

/* ---------- Modes ---------- */

.modes {
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
}

/* Five cards never leave one stranded: three over two, each row filling the
   width, then pairs with the last card across both columns. */
@media (max-width: 1040px) {
  .modes {
    grid-template-columns: repeat(6, 1fr);
  }
  .mode {
    grid-column: span 2;
  }
  .mode:nth-child(n + 4) {
    grid-column: span 3;
  }
}

@media (max-width: 640px) {
  .modes {
    grid-template-columns: repeat(2, 1fr);
  }
  .mode,
  .mode:nth-child(n + 4) {
    grid-column: auto;
  }
  .mode:last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 480px) {
  .modes {
    grid-template-columns: 1fr;
  }
  .mode:last-child {
    grid-column: auto;
  }
}

.mode {
  display: flex;
  flex-direction: column;
  padding: 24px;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--elevation-raised);
}

.mode svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  margin-bottom: 20px;
}

.mode h3 {
  font-size: 17px;
  font-weight: 640;
  letter-spacing: -0.01em;
}

.mode p {
  margin-top: 6px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.5;
  flex: 1;
}

.mode kbd {
  align-self: flex-start;
  margin-top: 20px;
}

/* Stands where a card's shortcut would be, for the mode that ships without
   one. Its line height matches a key's box, so the cards' last lines align. */
.mode-note {
  margin-top: 20px;
  color: var(--muted);
  font-size: 13px;
  line-height: 24px;
}

kbd {
  display: inline-block;
  /* The tracking below leaves a gap after the last glyph; the right padding
     gives it back so the keys sit centred. */
  padding: 2px calc(8px - 0.14em) 2px 8px;
  border-radius: 6px;
  background: var(--bg);
  box-shadow:
    inset 0 0 0 1px var(--line),
    inset 0 -1px 0 var(--line);
  font-family: inherit;
  font-size: 13px;
  font-weight: 560;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
  white-space: nowrap;
  color: var(--fg);
}

/* The tracking above spaces out the ⌘⇧ glyphs; spelled-out keys read as
   letter-spaced words with it. */
kbd.kbd-text {
  padding-right: 8px;
  letter-spacing: 0;
}

/* ---------- Feature rows ---------- */

/* Screenshots break out of the text column to a wider measure. They are the
   product, and at text width the UI in them is too small to read. */
.shot-wide {
  position: relative;
  left: 50%;
  width: min(var(--wrap-wide), calc(100vw - 40px));
  translate: -50% 0;
}

.features {
  display: grid;
  /* minmax(0, …) stops a wide screenshot from stretching the track itself. */
  grid-template-columns: minmax(0, 1fr);
  /* Tighter than .section's 128px so the four rows read as one group. */
  gap: 112px;
}

/* Label, heading and text stack in one column. A side-by-side split put a
   44px heading next to 17px body text, and no alignment of the two ever
   looked settled. */
.feature-copy {
  max-width: 600px;
  margin-bottom: 48px;
}

.feature-copy h2 {
  font-size: clamp(28px, 3.4vw, 44px);
  font-weight: 700;
}

.feature-text {
  margin-top: 18px;
  color: var(--muted);
}

.feature-text p + p {
  margin-top: 14px;
}

@media (max-width: 900px) {
  .features {
    gap: 72px;
  }
  .feature-copy {
    margin-bottom: 32px;
  }
}

/* Feature screenshots rise in once as they enter the viewport. The hidden
   state needs the html.js class, so without JavaScript they simply show.
   transform, not translate: .shot-wide centres itself with translate, and
   the two compose instead of overwriting each other. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 700ms var(--ease),
    transform 700ms var(--ease);
}

.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] {
    transform: none;
  }
}

/* Each feature video sits over its screenshot and only shows once it is
   playing (see the script in index.html). */
.feature-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}

.has-played .feature-video {
  opacity: 1;
}

/* Bottom left, because the Peel preview in the videos keeps its own buttons in
   the bottom right corner. Dark glass reads over dark scenes and light ones. */
.video-toggle {
  position: absolute;
  left: 14px;
  bottom: 14px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgb(28 25 23 / 0.62);
  color: #fafaf9;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.14);
  backdrop-filter: blur(12px) saturate(1.4);
  -webkit-backdrop-filter: blur(12px) saturate(1.4);
  cursor: pointer;
  transition:
    transform 160ms var(--ease),
    background-color 160ms var(--ease);
}

/* 36px looks right on the video; the hit area grows to 44px. */
.video-toggle::before {
  content: "";
  position: absolute;
  inset: -4px;
}

@media (hover: hover) {
  .video-toggle:hover {
    background: rgb(28 25 23 / 0.8);
  }
}

.video-toggle:active {
  transform: scale(0.94);
}

.video-toggle svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

/* The triangle's weight sits left of its box; nudge it to look centred. */
.video-toggle .icon-play {
  translate: 1px 0;
}

@media (max-width: 640px) {
  .video-toggle {
    left: 8px;
    bottom: 8px;
    width: 32px;
    height: 32px;
  }
  .video-toggle::before {
    inset: -6px;
  }
}

/* ---------- Details ---------- */

.details {
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px 48px;
}

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

@media (max-width: 480px) {
  .details {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

.details li {
  padding-top: 18px;
  border-top: var(--hairline) solid var(--line);
}

.details svg {
  display: block;
  width: 20px;
  height: 20px;
  margin-bottom: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Beside the heading in the three-column layout; stacked above it below that. */
@media (min-width: 901px) {
  .details li {
    display: grid;
    grid-template-columns: 20px 1fr;
    column-gap: 14px;
  }

  .details svg {
    margin-bottom: 0;
    align-self: center;
  }

  .details p {
    grid-column: 2;
  }
}

.details h3 {
  font-size: 17px;
  font-weight: 640;
  letter-spacing: -0.01em;
}

.details p {
  margin-top: 6px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.5;
}

/* ---------- Privacy ---------- */

.privacy-card {
  padding: clamp(32px, 6vw, 64px);
  border-radius: 24px;
  background: var(--primary);
  color: var(--primary-fg);
}

.privacy-card h2 {
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 700;
}

.privacy-points {
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
}

@media (max-width: 900px) {
  .privacy-points {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}

.privacy-points h3 {
  font-size: 17px;
  font-weight: 640;
  letter-spacing: -0.01em;
}

.privacy-points p {
  margin-top: 6px;
  font-size: 15px;
  line-height: 1.55;
  opacity: 0.7;
}

/* ---------- FAQ ---------- */

.faq {
  max-width: 760px;
}

.faq .section-title {
  margin-bottom: 40px;
}

.faq details {
  border-bottom: var(--hairline) solid var(--line);
}

.faq details:first-of-type {
  border-top: var(--hairline) solid var(--line);
}

.faq summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 20px 0;
  font-weight: 560;
  cursor: pointer;
  list-style: none;
}

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

/* Plus that turns into a minus: the vertical bar collapses on open. */
.faq summary::after {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background:
    linear-gradient(currentColor, currentColor) center / 14px 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 14px no-repeat;
  opacity: 0.5;
  transition: background-size 200ms var(--ease);
}

.faq details[open] summary::after {
  background-size:
    14px 2px,
    2px 0;
}

/* The answer grows open with the plus-to-minus icon, on the same 200ms.
   Browsers without ::details-content keep the instant toggle. */
@media (prefers-reduced-motion: no-preference) {
  .faq details {
    interpolate-size: allow-keywords;
  }
  .faq details::details-content {
    block-size: 0;
    overflow-y: clip;
    transition:
      block-size 200ms var(--ease),
      content-visibility 200ms var(--ease) allow-discrete;
  }
  .faq details[open]::details-content {
    block-size: auto;
  }
}

/* Pulled up with translate, not a negative margin: the margin leaked out of
   the closing answer and dipped the row 3px before it settled. */
.faq details p {
  padding-bottom: 18px;
  translate: 0 -4px;
  color: var(--muted);
  max-width: 60ch;
}

/* ---------- Closer + footer ---------- */

.closer {
  text-align: center;
  padding-bottom: 128px;
}

.closer h2 {
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 700;
  letter-spacing: -0.035em;
}

.closer p {
  margin: 16px 0 32px;
  color: var(--muted);
}

.footer {
  border-top: var(--hairline) solid var(--line);
  font-size: 14px;
  color: var(--muted);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 16px;
  padding-block: 28px;
}

.footer-credit {
  display: grid;
  gap: 6px;
}

.maker {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The mark and the name are one link, with the name at the weight of the
   header's "Peel". */
.footer .maker a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 640;
}

/* The mark is 15 pixels by 5. It is drawn at exactly three times that so
   every pixel covers whole screen pixels and stays square. It takes the
   page's own ink, not Fluffy Pixel's navy, so the footer stays in Peel's
   palette. */
.maker-logo {
  flex: none;
  width: 45px;
  height: 15px;
  color: var(--fg);
}

/* ---------- Easter egg: monkeys out of the closer's banana ---------- */

/* On its own line under the closer's button, far enough below it that the
   tooltip fits in between. */
.egg {
  position: relative;
  display: flex;
  width: fit-content;
  margin: 88px auto 0;
  color: var(--brand);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* An invisible overlay grows the hit area without moving the layout. */
.egg::after {
  content: "";
  position: absolute;
  inset: -12px;
}

/* The amber disc that says the banana is pokable. */
.egg::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  transition: background-color 150ms var(--ease);
}

@media (hover: hover) {
  .egg:hover::before {
    background: color-mix(in srgb, var(--brand) 18%, transparent);
  }
}

.egg:active::before {
  background: color-mix(in srgb, var(--brand) 30%, transparent);
}

.egg-mark {
  position: relative;
  width: 24px;
  height: 24px;
}

/* Inverse, like the extension's tooltip, and centred over the banana. */
.egg-tip {
  position: absolute;
  bottom: calc(100% + 14px);
  left: 50%;
  translate: -50% 0;
  padding: 5px 9px;
  border-radius: 7px;
  background: var(--primary);
  color: var(--primary-fg);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

@media (hover: hover) {
  .egg:hover .egg-tip {
    opacity: 1;
    visibility: visible;
    /* Same wait as the extension's tooltip, so a pointer passing by doesn't
       set it off. */
    transition-delay: 320ms;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .egg-mark {
    transition: transform 150ms var(--ease);
  }
  .egg:active .egg-mark {
    transform: scale(0.85);
  }
  .egg-tip {
    translate: -50% 3px;
    transition:
      opacity 150ms var(--ease),
      translate 150ms var(--ease),
      visibility 150ms;
  }
  .egg:hover .egg-tip {
    translate: -50% 0;
  }
  /* The squish that throws the monkeys. */
  .egg.is-poked .egg-mark {
    animation: monkey-poke 320ms var(--ease);
  }
}

/* A poke dismisses the tooltip until the pointer leaves, so it doesn't sit
   over the monkeys. Placed after the hover rules it overrides. */
.egg.tip-dismissed .egg-tip {
  opacity: 0;
  visibility: hidden;
  transition-delay: 0s;
}

@keyframes monkey-poke {
  0% {
    transform: scale(0.8) rotate(-12deg);
  }
  45% {
    transform: scale(1.14) rotate(9deg);
  }
  100% {
    transform: scale(1) rotate(0deg);
  }
}

.monkey-swarm {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 100;
}

/* Inter has no emoji, so the platform emoji fonts are named outright. */
.monkey-fly,
.monkey-landed {
  position: absolute;
  line-height: 1;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  transform: translate(-50%, -50%);
}

.monkey-fly {
  will-change: transform, opacity;
}

.footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

/* Four links don't fit across a phone, and wrapping left the last one alone
   on its own line. Two rows of two instead. */
@media (max-width: 480px) {
  .footer nav {
    display: grid;
    grid-template-columns: repeat(2, max-content);
    gap: 16px 28px;
  }
}

.footer a {
  /* Taller hit area on touch without moving the layout. */
  display: inline-block;
  padding-block: 12px;
  margin-block: -12px;
  text-decoration: none;
  transition: color 150ms var(--ease);
}

@media (hover: hover) {
  .footer a:hover {
    color: var(--fg);
  }
}

/* ---------- Document pages: changelog and privacy policy ---------- */

/* One reading column, about 75 characters wide. These pages are for reading,
   so nothing on them moves. */
.doc {
  max-width: 680px;
  padding-top: 88px;
  padding-bottom: 128px;
}

/* The changelog adds a column for each version beside the same text width. */
.doc-wide {
  max-width: 880px;
}

.doc-head h1 {
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 700;
  letter-spacing: -0.035em;
}

.doc-lede {
  margin-top: 16px;
  color: var(--muted);
}

@media (max-width: 640px) {
  .doc {
    padding-top: 56px;
    padding-bottom: 88px;
  }
}

.doc code {
  padding: 1px 5px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  color: var(--fg);
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.86em;
  /* A long token breaks instead of pushing a phone into sideways scroll. */
  overflow-wrap: anywhere;
}

.doc strong {
  color: var(--fg);
  font-weight: 620;
}

/* Changelog: the version and its date hold the left column and stay in view
   while a long release scrolls past. */
.releases {
  margin-top: 56px;
}

/* Side navigation: the changelog drawn as a waveform. One bar per version
   runs down the right edge, as wide as that release was big, darker for a
   release that added features than for the fixes after it, and amber for the
   one being read. It opens into a plain list of versions and dates. Only where there is room beside the text, and only with
   JavaScript, which builds it. */
.toc {
  position: fixed;
  top: 50%;
  right: 6px;
  z-index: 6;
  display: none;
  translate: 0 -50%;
}

@media (min-width: 1080px) {
  .js .toc {
    display: block;
  }
}

.toc-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-height: calc(100vh - 200px);
  margin: 0;
  padding: 12px 10px;
  border: 0;
  border-radius: 12px;
  background: none;
  cursor: pointer;
}

/* A bar is centred in a 24px column, so the widths swell out from one axis.
   Each has a 9px slot, and the slots give way before the rail outgrows the
   window, so it still fits after many more releases. */
.toc-rail span {
  display: grid;
  flex: 0 1 9px;
  place-items: center;
  width: 24px;
  min-height: 5px;
}

.toc-rail span::before {
  content: "";
  width: var(--w);
  /* Fine lines: a thicker bar read as heavy beside the text. */
  height: 2px;
  border-radius: 1px;
  background: color-mix(in srgb, var(--fg) 24%, transparent);
  transition: background-color 200ms var(--ease);
}

/* Finer still where the screen can draw it cleanly. */
@media (min-resolution: 2dppx) {
  .toc-rail span::before {
    height: 1.5px;
  }
}

.toc-rail .is-minor::before {
  background: color-mix(in srgb, var(--fg) 58%, transparent);
}

.toc-rail .is-active::before {
  background: var(--brand-ink);
}

/* The open list grows out of the rail, over it, and is kept plain on purpose:
   with month headings, bars, and two weights it read as busy. The shadow
   lives here and the scrolling a level down, so
   the fade at the list's edges can't eat the shadow. */
.toc-panel {
  position: absolute;
  top: 50%;
  right: 0;
  width: 168px;
  overflow: hidden;
  border-radius: 20px;
  background: var(--surface);
  box-shadow:
    var(--elevation-raised-hover),
    0 16px 40px -12px rgb(0 0 0 / 0.18);
  translate: 0 -50%;
  transform-origin: right center;
  /* Closed, and leaving a little faster than it arrives. */
  opacity: 0;
  visibility: hidden;
  transform: translateX(6px) scale(0.98);
  transition:
    opacity 130ms var(--ease),
    transform 130ms var(--ease),
    visibility 0s 130ms;
}

.toc.is-open .toc-panel {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity 180ms var(--ease),
    transform 180ms var(--ease),
    visibility 0s;
}

.toc[data-instant] .toc-panel {
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .toc .toc-panel {
    transform: none;
    transition: none;
  }
}

/* No scrollbar. Rows slide under the year at the top and fade out at the
   bottom, which says there is more; the list's own bottom padding lets the
   last row clear that fade. */
.toc-scroll {
  position: relative;
  max-height: min(560px, calc(100vh - 160px));
  padding: 0 6px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  mask-image: linear-gradient(#000 calc(100% - 24px), transparent);
}

.toc-list {
  list-style: none;
  margin: 0;
  padding: 0 0 18px;
}

/* The year its releases belong to. It holds the top of the list while they
   scroll, because the list opens centred on the current version and a
   heading that scrolled away would leave the dates without a year. */
.toc-year {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 12px 12px 6px;
  background: var(--surface);
  color: var(--muted);
  font-size: 12px;
  font-weight: 560;
  font-variant-numeric: tabular-nums;
  line-height: 18px;
}

.toc-list a {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 5px 12px;
  border-radius: 999px;
  color: var(--muted);
  font-size: 13px;
  line-height: 20px;
  text-decoration: none;
  white-space: nowrap;
  /* Inside the row, so the list's scrolling edge can't clip the ring. */
  outline-offset: -2px;
}

.toc-version {
  color: var(--fg);
  font-size: 14px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

@media (hover: hover) {
  .toc-list a:hover {
    background: color-mix(in srgb, var(--fg) 5%, transparent);
  }
}

.toc-list a[aria-current] {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  color: var(--fg);
}

/* Back to top, in the corner once there is somewhere to go back from. */
.to-top {
  position: fixed;
  right: max(20px, env(safe-area-inset-right));
  bottom: max(20px, env(safe-area-inset-bottom));
  z-index: 5;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--elevation-raised-hover);
  transition:
    opacity 200ms var(--ease),
    transform 200ms var(--ease),
    visibility 200ms;
}

.to-top svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.to-top:active {
  transform: scale(0.94);
}

/* Hidden needs the html.js class, so without JavaScript the button is simply
   always there. */
.js .to-top:not(.is-visible) {
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
}

@media (prefers-reduced-motion: reduce) {
  .js .to-top:not(.is-visible) {
    transform: none;
  }
}

.release {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  column-gap: 48px;
  padding-block: 44px;
  border-top: var(--hairline) solid var(--line);
  /* A linked version lands clear of the sticky nav. */
  scroll-margin-top: 60px;
}

.release-head {
  position: sticky;
  top: 92px;
  align-self: start;
}

.release-head h2 {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}

.release-head a {
  text-decoration: none;
}

@media (hover: hover) {
  .release-head a:hover {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
  }
}

.release-head time {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: 14px;
}

.release-body {
  color: var(--muted);
  font-size: 16px;
}

/* New, Improved, Fixed: the same amber label as the landing page's eyebrows,
   so it can't be mistaken for a note's bold opening sentence. */
.release-body h3 {
  margin-top: 28px;
  color: var(--brand-ink);
  font-size: 14px;
  font-weight: 560;
  letter-spacing: 0;
  line-height: 1.6;
}

/* The first label sits on the version's line. */
.release-body > :first-child {
  margin-top: 3px;
}

.release-body ul {
  margin: 10px 0 0;
  padding-left: 18px;
}

.release-body li + li {
  margin-top: 10px;
}

.release-body li::marker {
  color: color-mix(in srgb, var(--muted) 55%, transparent);
}

.release-body p + h3 {
  margin-top: 20px;
}

.release-body kbd {
  margin-inline: 1px;
}

@media (max-width: 760px) {
  .release {
    grid-template-columns: minmax(0, 1fr);
    padding-block: 36px;
  }
  .release-head {
    position: static;
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 14px;
  }
  .release-head time {
    margin-top: 0;
  }
  .release-body > :first-child {
    margin-top: 0;
  }
}

/* Privacy policy: headings over paragraphs, and one table. */
.prose {
  margin-top: 56px;
  color: var(--muted);
}

.prose h2 {
  margin-top: 56px;
  color: var(--fg);
  font-size: 26px;
  font-weight: 700;
}

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

.prose p,
.prose ul {
  margin-top: 16px;
}

.prose ul {
  margin-bottom: 0;
  padding-left: 18px;
}

.prose li + li {
  margin-top: 10px;
}

.prose li::marker {
  color: color-mix(in srgb, var(--muted) 55%, transparent);
}

.prose a {
  color: var(--fg);
  text-decoration-color: color-mix(in srgb, var(--fg) 35%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color 150ms var(--ease);
}

@media (hover: hover) {
  .prose a:hover {
    text-decoration-color: var(--fg);
  }
}

.prose table {
  width: 100%;
  margin-top: 28px;
  border-collapse: collapse;
  font-size: 15px;
  line-height: 1.5;
  text-align: left;
}

.prose th,
.prose td {
  padding: 14px 0;
  border-top: var(--hairline) solid var(--line);
  vertical-align: top;
}

.prose thead th {
  padding-top: 0;
  border-top: 0;
  color: var(--fg);
  font-size: 14px;
  font-weight: 560;
}

.prose tbody th {
  width: 190px;
  padding-right: 24px;
  font-weight: 400;
  white-space: nowrap;
}

/* On a phone each permission sits above its reason. */
@media (max-width: 520px) {
  .prose thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .prose tr,
  .prose tbody th,
  .prose td {
    display: block;
    width: auto;
  }
  .prose tr {
    padding-block: 14px;
    border-top: var(--hairline) solid var(--line);
  }
  .prose tbody th,
  .prose td {
    padding: 0;
    border-top: 0;
  }
  .prose td {
    margin-top: 6px;
  }
}

/* The page you are on, in the footer's links. */
.footer a[aria-current="page"] {
  color: var(--fg);
}
