/* DBClient — the marketing site's own styles, on top of UI CSS (assets/css/ui.css).
   Tokens are UI CSS's --ui-* variables; the brand gradient is the app icon's. */

/* The grounds are soft and a little warm: paper in the light, charcoal in
   the dark — never pure white, never pure black, which glare beside the
   app's own windows. The warmth is slight, so a screenshot's neutral greys
   sit on the page without a colour cast between them. The ink is the
   ground's own dark (and, in the dark, its own light), and the primary
   button is a pill of that ink. Colour is the brand gradient's, and it is
   spent in one place: a headline's last words. */
:root {
  --ui-primary: #4b5cf0;
  --ui-bg: #f9f7f3;
  --ui-bg-subtle: #f2efe9;
  --ui-surface: #fffefc;
  --ui-border: #e6e1d8;
  --ui-text: #211f1c;
  --ui-text-muted: #6b665e;
  --ui-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --ui-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --ui-radius: 8px;
  --ui-radius-lg: 14px;

  --brand-blue: #2d6bff;
  --brand-indigo: #5b4cf5;
  --brand-violet: #9b3fea;
  --brand-pink: #e8479b;
  --brand-orange: #ff7a3d;
  --brand-gradient: linear-gradient(135deg, var(--brand-blue) 0%, var(--brand-indigo) 28%, var(--brand-violet) 54%, var(--brand-pink) 78%, var(--brand-orange) 100%);

  /* A card is one step off the ground it sits on: the quiet grey on the
     page, the page's white on a tinted band. */
  --card-bg: var(--ui-bg-subtle);
  --tint: color-mix(in srgb, var(--ui-primary) 10%, transparent);

  --site-max: 1120px;
  --site-gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-gap: clamp(4.5rem, 9vw, 8rem);
  --nav-height: 60px;
  --window-shadow: 0 0 0 1px rgba(0, 0, 0, 0.07), 0 2px 4px rgba(0, 0, 0, 0.04), 0 18px 40px -12px rgba(0, 0, 0, 0.16), 0 48px 96px -36px rgba(0, 0, 0, 0.2);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

[data-theme="dark"] {
  --ui-primary: #9299ff;
  --ui-bg: #1b1917;
  --ui-bg-subtle: #22201d;
  --ui-surface: #2a2724;
  --ui-border: #3a3632;
  --ui-text: #ede9e3;
  --ui-text-muted: #a39e96;
  --tint: color-mix(in srgb, var(--ui-primary) 16%, transparent);
  --window-shadow: 0 0 0 1px rgba(255, 255, 255, 0.09), 0 2px 4px rgba(0, 0, 0, 0.4), 0 18px 40px -12px rgba(0, 0, 0, 0.7), 0 48px 96px -36px rgba(0, 0, 0, 0.8);
}

/* Native controls, scrollbars and the canvas follow the appearance being
   drawn — the one the system asked for, or the one the toggle chose. */
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

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

html {
  scroll-behavior: smooth;
}

/* An anchor lands below the sticky navigation. The offset sits on the
   targets (every element with an id), not as scroll-padding on the root:
   with root padding, Chromium takes a focused control in the sticky bar
   for one hidden under the padding and scrolls the page hundreds of
   pixels to "uncover" it — every click of the theme toggle moved the
   page, and a clip playing in view was scrolled out of it. */
[id] { scroll-margin-top: calc(var(--nav-height) + 1rem); }

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

h1, h2, h3, .lede, .section-head p, figcaption { text-wrap: balance; }
p, li { text-wrap: pretty; }

body {
  margin: 0;
  font-family: var(--ui-font);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ui-text);
  background: var(--ui-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--ui-primary); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

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

kbd {
  font-family: var(--ui-font);
  font-size: 0.85em;
  padding: 0.1em 0.45em;
  border: 1px solid var(--ui-border);
  border-bottom-width: 2px;
  border-radius: 6px;
  background: var(--ui-surface);
  color: var(--ui-text);
  white-space: nowrap;
}

code:not(pre code) {
  font-family: var(--ui-font-mono);
  font-size: 0.9em;
  padding: 0.1em 0.4em;
  border-radius: 6px;
  background: var(--ui-bg-subtle);
  border: 1px solid var(--ui-border);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.container {
  width: min(100% - 2 * var(--site-gutter), var(--site-max));
  margin-inline: auto;
}

.gradient-text {
  background: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* ---- Buttons that extend UI CSS ---- */
.ui-btn {
  font-weight: 600;
  border-radius: 999px;
  padding: 0.7rem 1.35rem;
  font-size: 0.95rem;
  gap: 0.5rem;
  transition: transform var(--ui-transition), box-shadow var(--ui-transition), background var(--ui-transition);

  /* The primary button is a pill of the page's ink: near-black on the
     paper, near-white on the charcoal. No colour of its own, no glow. */
  &.brand {
    color: var(--ui-bg);
    background: var(--ui-text);
    border: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18), 0 6px 16px -10px rgba(0, 0, 0, 0.45);

    &:hover { text-decoration: none; transform: translateY(-1px); background: color-mix(in srgb, var(--ui-text) 88%, var(--ui-bg)); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18), 0 10px 22px -10px rgba(0, 0, 0, 0.5); }
    &:active { transform: translateY(0); }
    /* UI CSS marks focus with a change of fill; an ink pill has none to give, so it wears a ring. */
    &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
  }

  &.quiet {
    background: var(--ui-surface);
    color: var(--ui-text);
    border: 1px solid var(--ui-border);

    &:hover { text-decoration: none; border-color: color-mix(in srgb, var(--ui-text) 28%, var(--ui-border)); background: var(--ui-surface); }
    &:focus-visible { background: var(--ui-surface); outline: 2px solid var(--ui-primary); outline-offset: 2px; }
  }

  &.large { padding: 0.9rem 1.7rem; font-size: 1.05rem; }

  & svg { width: 1.1em; height: 1.1em; flex: none; }
}

/* ---- Navigation ---- */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-height);
  border-bottom: 1px solid color-mix(in srgb, var(--ui-border) 70%, transparent);
  background: color-mix(in srgb, var(--ui-bg) 78%, transparent);
  backdrop-filter: saturate(160%) blur(16px);
  -webkit-backdrop-filter: saturate(160%) blur(16px);

  & .container {
    height: 100%;
    display: flex;
    align-items: center;
    gap: 1.5rem;
  }

  /* The mark and the name — the bar's own child. (The primary button's class
     is `brand` too: a bare `.brand` here would dress the bar's Download
     button in the name's ink, which on an ink pill is no label at all.) */
  & .container > .brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: var(--ui-text);

    &:hover { text-decoration: none; }
    & img { width: 28px; height: 28px; border-radius: 7px; }
  }

  & .links {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    list-style: none;
    padding: 0;
    margin-block: 0;

    & a {
      display: inline-block;
      padding: 0.45rem 0.8rem;
      border-radius: 999px;
      color: var(--ui-text-muted);
      font-weight: 500;
      font-size: 0.95rem;

      &:hover { text-decoration: none; color: var(--ui-text); background: var(--ui-bg-subtle); }
      &[aria-current="page"] { color: var(--ui-text); }
    }
  }

  & .actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;

    & .ui-btn { padding: 0.5rem 1rem; font-size: 0.9rem; }
  }

  & .menu-toggle { display: none; }
}

.theme-toggle {
  all: unset;
  cursor: pointer;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  display: inline-grid;
  place-items: center;
  color: var(--ui-text-muted);
  border: 1px solid var(--ui-border);
  background: var(--ui-surface);

  &:hover { color: var(--ui-text); }
  &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
  & svg { width: 18px; height: 18px; }
  /* The glyph is the stop the toggle is at, not the appearance drawn: a
     screen while the page follows the Mac, the sun or the moon for a pick. */
  & .sun, & .moon { display: none; }
}

[data-theme-preference="light"] .theme-toggle {
  & .system { display: none; }
  & .sun { display: block; }
}

[data-theme-preference="dark"] .theme-toggle {
  & .system { display: none; }
  & .moon { display: block; }
}

@media (max-width: 820px) {
  .site-nav {
    & .links {
      display: none;
      position: absolute;
      top: var(--nav-height);
      left: 0;
      right: 0;
      flex-direction: column;
      align-items: stretch;
      padding: 0.75rem var(--site-gutter) 1rem;
      background: var(--ui-bg);
      border-bottom: 1px solid var(--ui-border);
      box-shadow: var(--ui-shadow-lg);

      & a { padding: 0.7rem 0.9rem; font-size: 1.05rem; }
    }

    &.open .links { display: flex; }

    /* The links are out of the flow here, so the controls carry the push
       to the right edge themselves. */
    & .actions { margin-left: auto; }

    & .menu-toggle {
      all: unset;
      display: inline-grid;
      place-items: center;
      cursor: pointer;
      width: 36px;
      height: 36px;
      border-radius: 999px;
      border: 1px solid var(--ui-border);
      color: var(--ui-text);

      &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
      & svg { width: 18px; height: 18px; }
    }

    & .actions .ui-btn { padding: 0.45rem 0.85rem; font-size: 0.85rem; }
  }
}

/* The narrowest phones have no room for the button beside the mark; the
   hero's own button is a thumb away. */
@media (max-width: 359px) {
  .site-nav .actions .download { display: none; }
}

/* ---- Hero ---- */
/* The ground behind the hero is the page's own: no wash, no glow. The
   headline's last words carry the colour. */
.hero {
  position: relative;
  padding: clamp(3.5rem, 8vw, 6.5rem) 0 0;
  text-align: center;
  overflow: clip;

  & .eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    padding: 0.3rem 0.9rem 0.3rem 0.4rem;
    border-radius: 999px;
    border: 1px solid var(--ui-border);
    background: var(--ui-bg-subtle);
    color: var(--ui-text-muted);
    font-size: 0.85rem;
    font-weight: 500;

    /* A link in the pill (to the requirements) reads as the pill's text. */
    & a { color: inherit; }
    & .ui-badge { font-size: 0.72rem; background: var(--tint); color: var(--ui-primary); }
  }

  /* A words-only hero's pill is a label, not a fact sheet: even padding. */
  &.short .eyebrow { padding-inline: 0.9rem; }

  & h1 {
    margin: 1.25rem auto 1rem;
    max-width: 16ch;
    font-size: clamp(2.4rem, 6.2vw, 4.4rem);
    line-height: 1.05;
    font-weight: 700;
    letter-spacing: -0.035em;
  }

  & .lede {
    margin: 0 auto;
    max-width: 42rem;
    font-size: clamp(1.05rem, 1.8vw, 1.3rem);
    line-height: 1.5;
    color: var(--ui-text-muted);
  }

  & .actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.75rem;
    margin-top: 2rem;
  }

  & .fine-print {
    margin-top: 1rem;
    font-size: 0.85rem;
    color: var(--ui-text-muted);
  }

  /* A page whose hero is words alone: the first section follows closely. */
  &.short { padding-bottom: 0; }
  &.short + .section { padding-top: clamp(2.5rem, 5vw, 4rem); }
}

/* The home page's hero: the words and, with them, the app at work. On a
   narrow window the words stand above the pictures, centred. On a wide one
   the two share a row, and the row stands in the middle of the window — as
   much room left of the words as right of the pictures — so a whole picture
   is in view as the page loads, on a 1080p screen too, where width is
   plentiful and height is not. */
.hero.split {
  padding: clamp(2rem, 4.5vw, 3.5rem) 0 clamp(0.5rem, 2vw, 1.5rem);
  overflow: visible;

  & .hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 3rem);
    padding-inline: var(--site-gutter);
  }

  & .hero-copy { min-width: 0; }
  & .hero-show { min-width: 0; width: min(100%, 1100px); margin-inline: auto; }

  /* Beside the pictures the words' column is narrow: the version is a badge
     and the requirements are words after it, free to wrap — not one pill. */
  & .eyebrow {
    flex-wrap: wrap;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
  }

  & .install { margin: 1.25rem 0 0; }
}

@media (min-width: 1200px) {
  .hero.split {
    text-align: left;

    & .hero-grid {
      --hero-gap: clamp(2.5rem, 4vw, 4.5rem);
      /* All of a picture above the fold: no wider than the window's height
         has room for at the pictures' 2560:1704, once the bar, the hero's
         own padding and the tabs under the picture are taken off it — and
         never so wide that the words are left less than their 28rem. */
      --hero-show: min(1180px, 100% - var(--hero-gap) - 28rem, max(30rem, (100vh - var(--nav-height) - 11.5rem) * 2560 / 1704));
      /* The words take what the pictures leave, up to a column that reads
         well; what neither wants is shared by the two sides of the window. */
      grid-template-columns: clamp(28rem, 100% - var(--hero-gap) - var(--hero-show), 34rem) var(--hero-show);
      justify-content: center;
      align-items: center;
      gap: var(--hero-gap);
    }

    @supports (height: 100svh) {
      & .hero-grid { --hero-show: min(1180px, 100% - var(--hero-gap) - 28rem, max(30rem, (100svh - var(--nav-height) - 11.5rem) * 2560 / 1704)); }
    }

    & .eyebrow { justify-content: flex-start; font-size: 0.8rem; }
    & h1 { margin-inline: 0; max-width: none; font-size: clamp(2.4rem, 3.3vw, 3.5rem); }
    & .lede { margin-inline: 0; max-width: 34rem; font-size: clamp(1.02rem, 1.2vw, 1.2rem); }
    /* The two buttons side by side, and the one-line Homebrew command whole, in the words' column. */
    & .actions { justify-content: flex-start; flex-wrap: nowrap; }
    & .actions .ui-btn.large { padding: 0.8rem 1.3rem; font-size: 1rem; }
    & .install { font-size: 0.8rem; }

    & .hero-show { margin-inline: 0; width: 100%; }
  }
}

/* ---- Carousel: the hero's pictures, one at a time ---- */
.carousel {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.9rem;

  /* Every slide is the same window at the same size, so they share one
     cell, and a change of slide is a cross-fade of what is inside the
     window. A slide that is not shown is not drawn at all — which also
     keeps its picture from loading before it is wanted. A finger's drag
     across the pictures is the script's; down the page, the browser's. */
  & .stage { display: grid; touch-action: pan-y; }
  & .slide { grid-area: 1 / 1; min-width: 0; display: none; }
  & .slide.current { display: block; }
  /* The slide coming in lies over the one going out, and fades in. */
  & .slide.entering { display: block; z-index: 1; opacity: 0; }
  & .slide.entering.shown { opacity: 1; transition: opacity 500ms var(--ease); }

  /* The tabs are one run of inline pills, centred under the pictures;
     on a phone the run wraps. */
  & .bar { text-align: center; line-height: 1; }
  & .tabs { display: inline; }

  & .tab {
    all: unset;
    display: inline-block;
    margin: 0.125rem 0;
    cursor: pointer;
    padding: 0.35rem 0.85rem;
    border-radius: 999px;
    font-size: 0.88rem;
    font-weight: 550;
    line-height: 1.4;
    color: var(--ui-text-muted);
    transition: background var(--ui-transition), color var(--ui-transition);

    &:hover { color: var(--ui-text); }
    &[aria-selected="true"] { color: var(--ui-text); background: var(--ui-bg-subtle); box-shadow: inset 0 0 0 1px var(--ui-border); }
    &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
  }

}

/* The tabs are the script's to answer: without it, the first picture stands alone. */
html:not(.js) .carousel .bar { display: none; }

@media (prefers-reduced-motion: reduce) {
  .carousel .slide.entering.shown { transition: none; }
}

/* ---- Window frames for screenshots ---- */
.window {
  border-radius: 14px;
  box-shadow: var(--window-shadow);
  overflow: hidden;
  background: transparent;
  line-height: 0;

  & img, & video { width: 100%; height: auto; }

  /* The screenshot's own corners are already cut round; the frame only
     clips the shadow's edge. The shadow is neutral and opens with a
     hairline ring, so a light window does not melt into a light page nor
     a dark one into a dark page. */
  &.panel { background: var(--ui-surface); }
}

/* ---- Zoom: every picture and clip opens enlarged ---- */
.zoom {
  all: unset;
  display: block;
  width: 100%;
  cursor: zoom-in;
  line-height: 0;

  /* The window clips its corners, so the ring sits just inside its edge. */
  &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: -3px; border-radius: 14px; }
  & img, & video { width: 100%; height: auto; display: block; }
}

html.lightbox-open { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #fff;
  place-items: center;
  cursor: zoom-out;

  &[open] { display: grid; }
  &::backdrop { background: rgba(16, 14, 12, 0.74); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }

  /* The frame is the picture itself, as large as the screen allows. */
  & .frame {
    display: grid;
    place-items: center;
    max-width: min(95vw, 1800px);
    max-height: 95vh;
    cursor: default;
  }

  & .stage {
    display: grid;
    place-items: center;
    min-height: 0;

    & img, & video {
      display: block;
      max-width: min(95vw, 1800px);
      max-height: 95vh;
      width: auto;
      height: auto;
      object-fit: contain;
      border-radius: 14px;
      box-shadow: 0 40px 100px -30px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255, 255, 255, 0.08);
    }
  }

  & .close {
    all: unset;
    position: fixed;
    top: 1rem;
    right: 1rem;
    width: 40px;
    height: 40px;
    display: grid;
    place-items: center;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    cursor: pointer;

    &:hover { background: rgba(255, 255, 255, 0.22); }
    &:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
    & svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
  }
}

@media (prefers-reduced-motion: no-preference) {
  .lightbox[open] {
    opacity: 1;
    transition: opacity 220ms var(--ease);

    @starting-style { opacity: 0; }

    & .frame {
      transform: none;
      transition: transform 260ms var(--ease);

      @starting-style { transform: scale(0.96) translateY(10px); }
    }
  }
}

/* ---- Install snippet ---- */
.install {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  max-width: 100%;
  padding: 0.55rem 0.6rem 0.55rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--ui-border);
  background: var(--ui-surface);
  font-family: var(--ui-font-mono);
  font-size: 0.85rem;
  color: var(--ui-text);

  /* A flex item shrinks below its text only when told to (min-width: 0),
     on itself and on the code inside — else a phone scrolls sideways. */
  min-width: 0;

  & .prompt { color: var(--ui-text-muted); user-select: none; }
  & code { background: none; border: none; padding: 0; font-size: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto; }

  & .copy {
    all: unset;
    cursor: pointer;
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 999px;
    color: var(--ui-text-muted);
    flex: none;

    &:hover { background: var(--ui-bg-subtle); color: var(--ui-text); }
    &:focus-visible { outline: 2px solid var(--ui-primary); }
    &.copied { color: var(--ui-success); }
    & svg { width: 16px; height: 16px; }
    & .check { display: none; }
    &.copied .check { display: block; }
    &.copied .clipboard { display: none; }
  }
}

/* ---- Sections ---- */
.section {
  padding: var(--section-gap) 0 0;

  /* A band is a change of tone and nothing else: no rules above or below. */
  &.tinted {
    --card-bg: var(--ui-surface);
    margin-top: var(--section-gap);
    padding: var(--section-gap) 0;
    background: var(--ui-bg-subtle);
  }

  &:last-of-type { padding-bottom: var(--section-gap); }
}

.section-head {
  max-width: 44rem;
  margin: 0 auto 3.5rem;
  text-align: center;

  & .kicker {
    display: inline-block;
    margin-bottom: 0.75rem;
    font-size: 0.78rem;
    font-weight: 650;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ui-primary);
  }

  & h2 {
    margin: 0 0 0.75rem;
    font-size: clamp(1.8rem, 4vw, 2.7rem);
    line-height: 1.12;
    font-weight: 700;
    letter-spacing: -0.03em;
  }

  & p { margin: 0; font-size: 1.1rem; color: var(--ui-text-muted); }
  & p .guide { font-size: 1rem; }
  /* A second thought under the first (the buy section's way to renewing): set apart, a size down. */
  & p + p { margin-top: 0.85rem; font-size: 1rem; }

  &.left { text-align: left; margin-inline: 0; }

  /* A second heading inside a section: a step down in size, a section's
     breath above it. */
  &.sub {
    margin-top: clamp(4rem, 8vw, 6.5rem);
    margin-bottom: 2.5rem;

    & h2 { font-size: clamp(1.5rem, 3vw, 2rem); }
    & p { font-size: 1.05rem; }
  }
}

/* A section that only introduces the ones after it — a heading and the
   chips to its chapters: the first chapter follows closely. */
.section.intro {
  & .section-head { margin-bottom: 0; }
  & + .section { padding-top: clamp(3rem, 6vw, 4.5rem); }
}

/* The door at a section's foot. */
.more { margin: clamp(3rem, 6vw, 4.5rem) 0 0; text-align: center; }

/* ---- Guide links: every feature and every specification names its page in the docs ---- */
.guide {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.92rem;
  font-weight: 600;
  white-space: nowrap;

  &::after { content: "→"; transition: transform var(--ui-transition); }
  &:hover { text-decoration: none; }
  &:hover::after { transform: translateX(3px); }
}

/* ---- Chapter chips: a long page's sections, one tap each ---- */
.chapters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem;
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;

  & a {
    display: inline-block;
    padding: 0.4rem 0.95rem;
    border-radius: 999px;
    border: 1px solid var(--ui-border);
    color: var(--ui-text);
    font-size: 0.9rem;
    font-weight: 500;

    &:hover { text-decoration: none; background: var(--ui-bg-subtle); }
  }
}

/* ---- Engine strip ---- */
/* Twelve tiles: six to a row, so the grid is two full rows (then four by
   three, then three by four) and never leaves a ragged last row. */
.engines {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.75rem;

  & .engine {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    min-width: 0;
    padding: 1.25rem 0.5rem 1.1rem;
    border-radius: var(--ui-radius-lg);
    border: 1px solid transparent;
    background: var(--card-bg);
    color: var(--ui-text);
    font-size: 0.9rem;
    font-weight: 600;
    text-align: center;
    transition: border-color var(--ui-transition), background var(--ui-transition);

    & img { width: 34px; height: 34px; object-fit: contain; }
    & small { display: block; font-weight: 500; color: var(--ui-text-muted); font-size: 0.75rem; }
    &:hover { text-decoration: none; border-color: var(--ui-border); }
    &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
  }

  /* Beside a feature's words the tiles are smaller, four to a row. */
  &.compact {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.6rem;

    & .engine { padding: 1rem 0.35rem 0.85rem; font-size: 0.82rem; gap: 0.5rem; }
    & .engine img { width: 28px; height: 28px; }
  }
}

@media (max-width: 900px) {
  .engines { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .engines, .engines.compact { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* A black mark (TimescaleDB's badge) turns near-white on the dark ground. */
[data-theme="dark"] img.needs-light { filter: brightness(0) invert(0.92); }
/* A mark with a twin for the dark ground (IBM's Db2 badge, CockroachDB's beetle): one img per appearance, the other stood down —
   wherever the mark is shown: a tile, a service tag, the docs. */
img.dark-only { display: none; }
[data-theme="dark"] img.light-only { display: none; }
[data-theme="dark"] img.dark-only { display: block; }

.engine-note {
  margin: 1.5rem auto 0;
  max-width: 48rem;
  text-align: center;
  color: var(--ui-text-muted);
  font-size: 0.95rem;

  & .services {
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.4rem;
    margin-top: 0.75rem;

    & img { width: 16px; height: 16px; object-fit: contain; }
  }
}

/* ---- Engine pages: a page per engine (postgresql.html …), made by scripts/engine-pages.mjs ---- */
/* The hero's pill names the engine, with its mark. */
.hero .eyebrow.engine-mark {
  padding-inline: 0.7rem 0.95rem;
  color: var(--ui-text);
  font-weight: 600;

  & img { width: 20px; height: 20px; object-fit: contain; }
}

/* Among the twelve tiles, the one for the page being read wears the page's ink, as the featured plan does — and is a
   mark, not a link: a click on it would only jump to the top of the page it is on. */
.engines .engine[aria-current="page"] { border-color: var(--ui-text); cursor: default; }

/* What stands behind the engine's row of the features table: its cards, under the row. */
.engine-cards { margin-top: clamp(2rem, 4vw, 3rem); }

/* The engine's fact sheet, as the docs have it: a term and what it is, line by line. */
.engine-facts {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.45rem 1rem;
  margin: 1.5rem 0 0;
  padding: 1.1rem 1.25rem;
  border-radius: var(--ui-radius-lg);
  background: var(--card-bg);
  font-size: 0.92rem;

  & dt { color: var(--ui-text-muted); white-space: nowrap; }
  & dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
}

/* Two guides under the facts: side by side, and one under the other where there is no room. */
.feature-row .copy .guides {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin: 1.5rem 0 0;

  & .guide { margin-top: 0; }
}

/* The hosted services built on the engine: a short table, held to the width of its words, a fact to a line. */
.services-table {
  max-width: 36rem;
  margin: 1.5rem auto 0;

  & table td:not(:first-child), & table th:not(:first-child) { width: auto; white-space: nowrap; }
}

/* ---- Feature rows (text beside a screenshot) ---- */
.feature-row {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  margin-top: clamp(3rem, 7vw, 5.5rem);

  &:first-of-type { margin-top: 0; }
  /* A flipped row flips its columns too, so a picture is the same size on either side. */
  &.flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  &.flip .copy { order: 2; }
  &.flip .shot { order: 1; }

  & .copy {
    & .kicker {
      display: inline-flex;
      align-items: center;
      gap: 0.5rem;
      font-size: 0.8rem;
      font-weight: 700;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--ui-primary);
      margin-bottom: 0.75rem;

      & svg { width: 18px; height: 18px; }
    }

    & h3 {
      margin: 0 0 0.75rem;
      font-size: clamp(1.5rem, 2.6vw, 2rem);
      line-height: 1.15;
      font-weight: 700;
      letter-spacing: -0.025em;
    }

    & p { margin: 0 0 1rem; color: var(--ui-text-muted); font-size: 1.05rem; }

    & ul {
      margin: 1rem 0 0;
      padding: 0;
      list-style: none;
      display: grid;
      gap: 0.5rem;

      & li {
        position: relative;
        padding-left: 1.6rem;
        color: var(--ui-text);
        font-size: 0.98rem;

        &::before {
          content: "";
          position: absolute;
          left: 0;
          top: 0.55em;
          width: 0.9rem;
          height: 0.9rem;
          background: var(--ui-primary);
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3 3 7-7' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
          -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3 3 7-7' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
        }
      }
    }

    & .guide { margin-top: 1.5rem; }
  }

  & .shot { min-width: 0; }

  /* A portrait sheet beside the words is held to a sheet's width. */
  & .shot.narrow { max-width: 25rem; margin-inline: auto; width: 100%; }
}

@media (max-width: 900px) {
  .feature-row, .feature-row.flip {
    grid-template-columns: minmax(0, 1fr);

    &.flip .copy { order: 1; }
    &.flip .shot { order: 2; }
  }
}

/* ---- Feature cards ---- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 1rem;

  /* Six cards are two rows of three, never four and a ragged two. */
  &.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* A card is a tone, not a box: no rule around it, nothing that moves
     under the pointer (the card is not a link; its guide is). */
  & .card {
    display: flex;
    flex-direction: column;
    padding: 1.6rem;
    border-radius: var(--ui-radius-lg);
    background: var(--card-bg);

    & .icon {
      width: 38px;
      height: 38px;
      display: grid;
      place-items: center;
      border-radius: 10px;
      color: var(--ui-primary);
      background: var(--tint);
      margin-bottom: 1rem;

      & svg { width: 19px; height: 19px; }
    }

    & h3 { margin: 0 0 0.4rem; font-size: 1.08rem; font-weight: 650; letter-spacing: -0.01em; }
    & p { margin: 0; color: var(--ui-text-muted); font-size: 0.95rem; }
    /* The guide sits on the card's floor, so a row of cards lines them up. */
    & .guide { margin-top: auto; padding-top: 1rem; font-size: 0.88rem; align-self: flex-start; white-space: normal; }
    & .install { margin-top: 1rem; align-self: stretch; }
  }
}

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

@media (max-width: 600px) {
  .cards.three { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Gallery of panels ---- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 1.5rem;
  align-items: start;

  & figure {
    margin: 0;

    & figcaption {
      margin-top: 1rem;
      font-size: 0.95rem;
      color: var(--ui-text-muted);

      & strong { color: var(--ui-text); font-weight: 650; }
      & .guide { font-size: 0.88rem; margin-left: 0.15rem; }
    }
  }
}

/* ---- Video clips ---- */
.clips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: 1.5rem;

  & figure { margin: 0; }
  & figcaption { margin-top: 1rem; color: var(--ui-text-muted); font-size: 0.95rem; }
  & figcaption strong { color: var(--ui-text); font-weight: 650; }
  & figcaption .guide { font-size: 0.88rem; margin-left: 0.15rem; }
  & video { background: var(--ui-bg-subtle); }
}

/* ---- Numbers ---- */
/* Each figure is a link to the page of the docs that backs it. */
.numbers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
  margin-top: 3.5rem;
  text-align: center;

  & .number {
    display: block;
    padding: 1.25rem 0.5rem;
    border-radius: var(--ui-radius-lg);
    color: var(--ui-text);

    &:hover { text-decoration: none; background: var(--card-bg); }
    &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 2px; }

    & b {
      display: block;
      font-size: 2.6rem;
      font-weight: 700;
      letter-spacing: -0.035em;
      line-height: 1.1;
    }

    & span { color: var(--ui-text-muted); font-size: 0.9rem; }
  }
}

/* ---- Pricing ---- */
/* The plans share their rows (subgrid): names, prices, terms and lists sit
   on the same lines across the three, whatever each one's words run to. */
.plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  column-gap: 1.25rem;
  row-gap: 0;
  align-items: stretch;

  & .plan {
    position: relative;
    display: grid;
    grid-row: span 8;
    grid-template-rows: subgrid;
    align-content: start;
    margin-bottom: 1.25rem;
    padding: 1.9rem;
    border-radius: 18px;
    border: 2px solid transparent;
    background: var(--card-bg);

    /* The one plan the page points at wears a ring of the page's ink, and
       its ribbon is a pill of it — the primary button's dress. */
    &.featured {
      border-color: var(--ui-text);
      background: var(--ui-surface);
      box-shadow: 0 24px 50px -32px rgba(0, 0, 0, 0.35);
    }

    & .ribbon {
      position: absolute;
      top: -0.8rem;
      left: 50%;
      transform: translateX(-50%);
      padding: 0.25rem 0.8rem;
      border-radius: 999px;
      background: var(--ui-text);
      color: var(--ui-bg);
      font-size: 0.75rem;
      font-weight: 700;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      white-space: nowrap;
    }

    & h3 { margin: 0; font-size: 1.15rem; font-weight: 650; }
    & .for { margin: 0.25rem 0 1.25rem; color: var(--ui-text-muted); font-size: 0.92rem; }

    & .price {
      display: flex;
      align-items: baseline;
      gap: 0.4rem;
      margin-bottom: 0.2rem;

      & b { font-size: 2.8rem; font-weight: 700; letter-spacing: -0.04em; line-height: 1; }
      & span { color: var(--ui-text-muted); font-size: 0.95rem; }
    }

    /* The second price: what a year costs after the first. */
    & .then { margin: 0 0 0.75rem; font-size: 0.95rem; font-weight: 600; }
    & .terms { margin: 0 0 1.5rem; color: var(--ui-text-muted); font-size: 0.85rem; }

    /* The licence count and what it comes to, first year and after. */
    & .seats {
      display: grid;
      gap: 0.5rem;
      grid-row: 7;
      align-self: start;
      margin: 0 0 1.5rem;
      padding: 0.85rem 1rem;
      border-radius: var(--ui-radius-lg);
      background: var(--ui-bg);
      font-size: 0.9rem;
      color: var(--ui-text-muted);

      & label { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; color: var(--ui-text); font-weight: 600; }
      & p { margin: 0; }

      & input {
        width: 5rem;
        padding: 0.35rem 0.5rem;
        border-radius: 8px;
        border: 1px solid var(--ui-border);
        background: var(--ui-surface);
        color: var(--ui-text);
        font: inherit;
        font-weight: 500;
        text-align: center;

        &:focus-visible { outline: 2px solid var(--ui-primary); outline-offset: 1px; }
      }

      & output { font-weight: 650; color: var(--ui-text); }
    }

    & ul {
      margin: 0 0 1.75rem;
      padding: 0;
      list-style: none;
      display: grid;
      gap: 0.55rem;
      /* The row is as tall as the longest list; a shorter one keeps its own pitch. */
      align-content: start;
      align-self: start;
      font-size: 0.95rem;

      & li {
        position: relative;
        padding-left: 1.5rem;

        &::before {
          content: "";
          position: absolute;
          left: 0;
          top: 0.5em;
          width: 0.85rem;
          height: 0.85rem;
          border-radius: 999px;
          background: var(--ui-success);
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3 3 7-7' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
          -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.5l3 3 7-7' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
        }

        &.muted { color: var(--ui-text-muted); }
        &.muted::before { background: var(--ui-text-muted); opacity: 0.5; }
      }
    }

    & .ui-btn { grid-row: 8; align-self: end; justify-content: center; width: 100%; }
  }
}

/* A comparison is rules between rows and nothing else: no box around it,
   no band behind its head. */
/* Under the plans: the way to renewing, in plain sight. Someone who came
   to pay for another year would otherwise read three "buy" buttons and buy
   a second key. */
.renew-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.6rem 0.9rem;
  margin: 2rem auto 0;
  font-weight: 600;
  text-align: center;

  & span { font-size: 0.95rem; font-weight: 400; color: var(--ui-text-muted); }
}

.compare {
  margin-top: 3.5rem;
  overflow-x: auto;

  /* Under a heading of its own, the heading's margin is the gap. */
  &.flush { margin-top: 0; }

  & table {
    width: 100%;
    border-collapse: collapse;
    border: 0;
    border-radius: 0;
    background: none;
    font-size: 0.95rem;

    & th, & td {
      padding: 0.85rem 1rem;
      border-bottom: 1px solid var(--ui-border);
      text-align: left;
      vertical-align: top;
    }

    & thead { background: none; }

    & thead th {
      font-size: 0.75rem;
      font-weight: 650;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ui-text-muted);
      border-bottom: 1px solid var(--ui-border);
    }

    & td:first-child { font-weight: 550; }
    & td:first-child .ui-text-muted { display: block; font-weight: 400; font-size: 0.85rem; }
    & td:not(:first-child), & th:not(:first-child) { text-align: center; width: 18%; }
    /* A mark stands alone on its line, so the marks of a column stand in one
       line down the page; what there is to say about one is a caption under it. */
    & td .yes, & td .no { display: block; line-height: 1.6; }
    & td .yes { color: var(--ui-success); font-weight: 700; }
    & td .no { color: var(--ui-text-muted); }
    & td small { display: block; margin-top: 0.1rem; font-size: 0.82rem; line-height: 1.4; color: var(--ui-text-muted); text-wrap: balance; }
  }
}

.faq {
  max-width: 48rem;
  margin: 0 auto;

  & details {
    border-bottom: 1px solid var(--ui-border);

    & summary {
      cursor: pointer;
      list-style: none;
      padding: 1.1rem 2.25rem 1.1rem 0;
      font-weight: 650;
      font-size: 1.05rem;
      position: relative;

      &::-webkit-details-marker { display: none; }

      &::after {
        content: "+";
        position: absolute;
        right: 0.25rem;
        top: 50%;
        transform: translateY(-50%);
        font-size: 1.4rem;
        font-weight: 400;
        color: var(--ui-text-muted);
        transition: transform var(--ui-transition);
      }
    }

    &[open] summary::after { transform: translateY(-50%) rotate(45deg); }

    & p { margin: 0 0 1.1rem; color: var(--ui-text-muted); }
  }
}

/* ---- Download ---- */
.download-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 2rem;
  align-items: center;
  padding: clamp(1.5rem, 4vw, 3rem);
  border-radius: 20px;
  background: var(--card-bg);

  & .icon { width: 96px; height: 96px; border-radius: 22px; box-shadow: var(--ui-shadow-lg); }
  & h2 { margin: 1rem 0 0.25rem; font-size: 1.8rem; letter-spacing: -0.03em; }
  & .version { color: var(--ui-text-muted); }
  & .version b { color: var(--ui-text); }
  & .actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.5rem; }
  & .requirements { margin: 1.25rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.4rem; color: var(--ui-text-muted); font-size: 0.92rem; }
  & .spec-link { margin: 0.9rem 0 0; }

  & .steps {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    /* The one column sized to the space, not to the snippet's text. */
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    counter-reset: step;

    & li {
      position: relative;
      min-width: 0;
      padding-left: 2.6rem;
      counter-increment: step;

      &::before {
        content: counter(step);
        position: absolute;
        left: 0;
        top: 0.05rem;
        width: 1.8rem;
        height: 1.8rem;
        display: grid;
        place-items: center;
        border-radius: 999px;
        background: var(--tint);
        color: var(--ui-primary);
        font-size: 0.85rem;
        font-weight: 700;
      }

      & b { display: block; margin-bottom: 0.15rem; }
      & span { color: var(--ui-text-muted); font-size: 0.92rem; }
      & .install { display: flex; margin-top: 0.5rem; }
    }
  }
}

@media (max-width: 820px) {
  /* minmax(0, …): a bare 1fr is minmax(auto, 1fr), and the install
     snippet's min-content would widen the track past the phone. */
  .download-card { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Releases: the version and its date beside what changed ---- */
.release-list {
  max-width: 58rem;
  margin-inline: auto;
}

.release {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  gap: 0.5rem clamp(1.5rem, 4vw, 3rem);
  padding: 2.25rem 0;
  border-top: 1px solid var(--ui-border);

  &:first-child { border-top: 0; padding-top: 0; }

  & h2 {
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.2;

    & a { color: var(--ui-text); }
    & .ui-badge { font-size: 0.72rem; letter-spacing: 0; background: var(--tint); color: var(--ui-primary); }
  }

  /* Landed on from a link to one release: the release that was asked for says so. */
  &:target h2 a { color: var(--ui-primary); }

  & .meta { margin: 0.25rem 0 0; color: var(--ui-text-muted); font-size: 0.9rem; }
  & .headline { margin: 0.2rem 0 1rem; font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em; }

  & .changes {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.65rem;

    /* The kind of change in a column of its own, the words beside it. */
    & li { display: grid; grid-template-columns: 5.2rem minmax(0, 1fr); gap: 0.75rem; align-items: baseline; }
  }

  & .kind {
    justify-self: start;
    padding: 0.08rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 650;
    letter-spacing: 0.02em;
    background: var(--ui-bg-subtle);
    color: var(--ui-text-muted);

    &.new { background: var(--tint); color: var(--ui-primary); }
  }

  /* A release the page learned of from GitHub: whatever its notes say there. */
  & .notes {
    color: var(--ui-text-muted);
    display: grid;
    gap: 0.5rem;
    overflow-wrap: anywhere;

    & p, & ul { margin: 0; }
    & ul { padding-left: 1.2rem; }
    & strong { color: var(--ui-text); display: block; margin-top: 0.5rem; }
    & strong:first-child { margin-top: 0; }
    & b { color: var(--ui-text); font-weight: 600; }
    & code { font-size: 0.85em; white-space: normal; overflow-wrap: anywhere; }
  }
}

@media (max-width: 720px) {
  .release { grid-template-columns: minmax(0, 1fr); }
  .release header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.9rem; }
  .release .meta { margin: 0; }
  .release .changes li { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; }
}

/* ---- Callouts ---- */
/* The page's last word is a quiet panel in the band's tone; its button is
   the one thing on it in colour. */
.callout {
  padding: clamp(2.75rem, 6vw, 4.75rem) var(--site-gutter);
  border-radius: 28px;
  text-align: center;
  background: var(--card-bg);

  & h2 { margin: 0 0 0.75rem; font-size: clamp(1.8rem, 4vw, 2.6rem); font-weight: 700; line-height: 1.12; letter-spacing: -0.03em; }
  & p { margin: 0 auto 1.75rem; max-width: 36rem; color: var(--ui-text-muted); font-size: 1.1rem; }

  & .actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
  }

  & .install { margin: 0; }
}

/* ---- Docs: the contents beside the pages ---- */
.docs {
  display: grid;
  grid-template-columns: 14.5rem minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

/* The contents stay in view while the pages scroll; on their own they
   scroll too, when the window is shorter than the list. */
.docs-toc {
  position: sticky;
  top: calc(var(--nav-height) + 1.5rem);
  max-height: calc(100vh - var(--nav-height) - 3rem);
  overflow-y: auto;
  padding: 0 0.5rem 2.5rem 0;
  font-size: 0.9rem;
  /* A list longer than the window fades out at its foot rather than ending mid-line. */
  mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent);
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent);
  scrollbar-width: thin;

  & h4 {
    margin: 1.5rem 0 0.4rem;
    font-size: 0.72rem;
    font-weight: 650;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ui-text-muted);
  }

  & div:first-child h4 { margin-top: 0; }
  & ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }

  & a {
    display: block;
    padding: 0.28rem 0.7rem;
    border-radius: 7px;
    color: var(--ui-text-muted);

    &:hover { text-decoration: none; color: var(--ui-text); background: var(--ui-bg-subtle); }
    /* The page being read, kept current by the script as the reader scrolls. */
    &[aria-current="true"] { color: var(--ui-primary); background: var(--tint); font-weight: 600; }
  }
}

.docs-body {
  min-width: 0;

  & .chapter {
    & > h2 {
      margin: 0 0 0.5rem;
      font-size: clamp(1.6rem, 3vw, 2.1rem);
      font-weight: 700;
      line-height: 1.15;
      letter-spacing: -0.03em;
    }

    & > .about { margin: 0 0 1.5rem; color: var(--ui-text-muted); font-size: 1.05rem; max-width: 42rem; }
    & + .chapter { margin-top: clamp(3.5rem, 7vw, 5.5rem); }
  }

  /* One page of the docs: what the thing is, how to do it, how it works. */
  & .doc {
    padding: 2rem 0 0.5rem;
    border-top: 1px solid var(--ui-border);
    max-width: 46rem;

    & h3 { margin: 0 0 0.6rem; font-size: 1.3rem; font-weight: 650; letter-spacing: -0.02em; line-height: 1.25; }

    & h4 {
      margin: 1.5rem 0 0.5rem;
      font-size: 0.72rem;
      font-weight: 650;
      letter-spacing: 0.1em;
      text-transform: uppercase;
      color: var(--ui-text-muted);
    }

    /* A connection string or a Keychain service name is one long word: it wraps, or a phone scrolls sideways. */
    overflow-wrap: anywhere;

    & p { margin: 0 0 0.9rem; }
    & ol, & ul { margin: 0 0 1rem; padding-left: 1.3rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
    & li::marker { color: var(--ui-text-muted); }

    /* Landed on from a guide link: the page that was asked for says so. */
    &:target h3 { color: var(--ui-primary); }

    /* The screen the page is about, after its opening words and before the
       steps: a window fills the column; a sheet stands near its own size. */
    & .doc-shot {
      margin: 1.4rem 0 1.75rem;

      & .window { margin: 0; }
      /* Narrower than the sheet's own points, each of them: a 2x render
         shown any larger would be a blur. */
      &.sheet .window { max-width: 32rem; }
      &.prompt .window { max-width: 26rem; }
      &.tall .window { max-width: 22rem; }
      & video { background: var(--ui-bg-subtle); }
      & figcaption { margin-top: 0.75rem; font-size: 0.88rem; color: var(--ui-text-muted); }
    }

    /* How it works underneath: a quieter block, set apart from the steps. */
    & .tech {
      margin: 1.5rem 0 1rem;
      padding: 1.1rem 1.3rem;
      border-radius: var(--ui-radius-lg);
      background: var(--ui-bg-subtle);
      font-size: 0.93rem;

      & h4 { margin-top: 0; }
      & ul { margin-bottom: 0; }
      & p:last-child { margin-bottom: 0; }
    }

    & .table-wrap { overflow-x: auto; margin: 0 0 1rem; }

    /* The engines: a fact sheet each, two to a row, each one a link's target. */
    & .engine-docs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); gap: 0.9rem; margin: 1.25rem 0 1rem; }

    & .engine-doc {
      padding: 1.1rem 1.25rem;
      border-radius: var(--ui-radius-lg);
      background: var(--ui-bg-subtle);
      font-size: 0.9rem;

      & h4 { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.6rem; font-size: 1rem; font-weight: 650; letter-spacing: 0; text-transform: none; color: var(--ui-text); }
      & h4 img { width: 20px; height: 20px; object-fit: contain; }
      & dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.3rem 0.9rem; margin: 0; }
      & dt { color: var(--ui-text-muted); white-space: nowrap; }
      & dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
      &:target { outline: 2px solid var(--ui-primary); outline-offset: -2px; }
    }

    & table {
      width: 100%;
      border-collapse: collapse;
      font-size: 0.92rem;

      & th, & td { padding: 0.55rem 0.9rem 0.55rem 0; border-bottom: 1px solid var(--ui-border); text-align: left; vertical-align: top; }
      & thead th { font-size: 0.72rem; font-weight: 650; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ui-text-muted); }
      & td:first-child { font-weight: 600; white-space: nowrap; }
    }
  }
}

@media (max-width: 900px) {
  .docs { grid-template-columns: minmax(0, 1fr); }

  /* On a phone the contents lead the page, in two columns, and scroll away. */
  .docs-toc {
    position: static;
    max-height: none;
    overflow: visible;
    mask-image: none;
    -webkit-mask-image: none;
    padding: 1.25rem;
    border-radius: var(--ui-radius-lg);
    background: var(--ui-bg-subtle);
    columns: 2 9rem;
    column-gap: 1.5rem;

    & div { break-inside: avoid; }
    & div:first-child h4 { margin-top: 0; }
  }
}

/* ---- Prose pages ---- */
.prose {
  /* The container's own gutters: on a phone the words keep clear of the glass. */
  width: min(100% - 2 * var(--site-gutter), 44rem);
  margin: 0 auto;
  padding: var(--section-gap) 0;

  & h1 { font-size: clamp(2rem, 4vw, 2.8rem); letter-spacing: -0.03em; margin: 0 0 0.5rem; }
  & .updated { color: var(--ui-text-muted); margin: 0 0 2rem; }
  & h2 { font-size: 1.3rem; margin: 2rem 0 0.5rem; letter-spacing: -0.02em; }
  & p, & li { color: var(--ui-text); }
  & ul { padding-left: 1.2rem; }
}

/* ---- The store: the pricing page's buy form ---- */
/* One card in the middle of its band: the plan, how many, who for, and a
   button per way to pay. It works through the script (the store is asked
   what it sells, and answers with the payment page), so without the script
   the form stands down and a line says why. */
.buy {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
  max-width: 34rem;
  margin: 0 auto;
  padding: clamp(1.4rem, 4vw, 2.25rem);
  border-radius: 18px;
  background: var(--ui-surface);
  box-shadow: 0 24px 50px -36px rgba(0, 0, 0, 0.35);

  & fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
  & legend, & .buy-licences > label { padding: 0; margin-bottom: 0.5rem; font-size: 0.8125rem; font-weight: 500; }

  /* The two paid plans, side by side: the one chosen wears the page's ink, as the featured plan above does. */
  & .buy-plan-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); gap: 0.6rem; }
  & .buy-plan {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.8rem 0.9rem;
    border-radius: var(--ui-radius-lg);
    border: 2px solid var(--ui-border);
    cursor: pointer;

    &:has(input:checked) { border-color: var(--ui-text); }
    &:has(input:focus-visible) { outline: 2px solid var(--ui-primary); outline-offset: 2px; }
    & input { margin: 0.25rem 0 0; accent-color: var(--ui-text); }
    & b { display: block; font-weight: 650; }
    & small { display: block; margin-top: 0.1rem; font-size: 0.82rem; line-height: 1.4; color: var(--ui-text-muted); }
  }

  & .buy-licences { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.4rem 1rem; }
  & .buy-licences > label { margin: 0; font-size: 0.95rem; font-weight: 600; }
  & .buy-licences .buy-note { grid-column: 1 / -1; }

  /* Fewer, the count, more: one pill. */
  & .stepper {
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    border: 1px solid var(--ui-border);
    background: var(--ui-bg);

    & button {
      all: unset;
      cursor: pointer;
      display: grid;
      place-items: center;
      width: 2.4rem;
      height: 2.4rem;
      border-radius: 999px;
      font-size: 1.15rem;
      color: var(--ui-text-muted);

      &:hover { color: var(--ui-text); background: var(--ui-bg-subtle); }
      &:focus-visible { outline: 2px solid var(--ui-primary); }
    }

    & input {
      width: 3.2rem;
      padding: 0.3rem 0;
      border: 0;
      background: none;
      color: var(--ui-text);
      font: inherit;
      font-weight: 650;
      text-align: center;
      appearance: textfield;
      -moz-appearance: textfield;

      &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { appearance: none; -webkit-appearance: none; margin: 0; }
      &:focus-visible { outline: 2px solid var(--ui-primary); border-radius: 6px; }
    }
  }

  & .buy-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.9rem; }
  & .buy-note { margin: 0; font-size: 0.82rem; line-height: 1.45; color: var(--ui-text-muted); }
  & .buy-note:empty { display: none; }

  /* What is charged today, as large as a plan's price is. */
  & .buy-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin: 0;
    padding-top: 1.25rem;
    border-top: 1px solid var(--ui-border);
    font-weight: 600;

    & output { font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; line-height: 1; }
  }
  & .buy-total + .buy-note { margin-top: -1rem; }

  & .buy-actions {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;

    & .ui-btn { justify-content: center; width: 100%; }
    & .ui-btn[hidden] { display: none; }
    & .ui-btn:disabled { opacity: 0.55; cursor: default; transform: none; }
  }

  & .ui-alert { font-size: 0.9rem; }
  & .ui-alert[hidden], & .ui-field[hidden] { display: none; }

  & .buy-secure {
    margin: 0;
    font-size: 0.8rem;
    color: var(--ui-text-muted);
    text-align: center;
    text-wrap: balance;

    & svg { display: inline; width: 13px; height: 13px; margin-right: 0.4rem; vertical-align: -2px; }
  }
}

.buy-needs-script, .prices-need-script { display: none; }
html:not(.js) .buy { display: none; }
html:not(.js) .buy-needs-script, html:not(.js) .prices-need-script { display: block; }

/* ---- The thank-you page, after a payment ---- */
.thanks {
  text-align: center;

  /* The spinner sits before the words it belongs to. */
  & .waiting { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.6rem; }
  /* The waiting is the script's: without it, the page says where the keys are instead. */
  & .no-script { display: none; }
  & [hidden] { display: none; }
  & .ui-alert { text-align: left; font-size: 0.92rem; & p { margin: 0; color: inherit; } & a { color: inherit; text-decoration: underline; } }

  /* A key is one long word and every character of it counts: it wraps, it never trails off. */
  & .keys { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.6rem; justify-items: center; margin: 0 0 2rem; }
  & .key {
    display: flex;
    margin: 0;
    border-radius: 16px;
    font-size: 0.95rem;

    & code { white-space: normal; overflow-wrap: anywhere; text-overflow: clip; overflow: visible; text-align: left; }
  }

  & .thanks-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-top: 2rem; }
  /* What to do with a key: three steps, read from the left like the rest of a page of words. */
  & .activate { display: grid; gap: 0.4rem; max-width: 34rem; margin: 0 auto 1.5rem; padding-left: 1.4rem; text-align: left; color: var(--ui-text-muted); & strong { color: var(--ui-text); } }
}

html:not(.js) .thanks .waiting { display: none; }
html:not(.js) .thanks .no-script { display: block; }

/* ---- The renew page: a licence named by its key and email, its renewal quoted, then paid ---- */
.renew {
  text-align: center;

  & [hidden] { display: none; }
  & .buy { text-align: left; }
  & .waiting { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.6rem; }
  & .ui-alert { text-align: left; font-size: 0.92rem; & p { margin: 0; color: inherit; } & a { color: inherit; text-decoration: underline; } }
  & .thanks-actions, & .renew-again { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-top: 2rem; }

  /* The licence's facts: what it is called on the left, what it is on the right. */
  & .renew-facts {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;
    margin: 0;

    & div { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.25rem 1rem; }
    & dt { color: var(--ui-text-muted); font-size: 0.92rem; }
    & dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; text-align: right; }
    & div:first-child dd { font-family: var(--ui-font-mono); font-size: 0.9rem; font-weight: 500; }
  }
}

.renew-needs-script { display: none; }
html:not(.js) .renew .buy { display: none; }
html:not(.js) .renew-needs-script { display: block; }

/* ---- Footer ---- */
.site-footer {
  padding: 3rem 0 2.5rem;
  border-top: 1px solid var(--ui-border);
  color: var(--ui-text-muted);
  font-size: 0.9rem;

  & .container {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    justify-content: space-between;
    align-items: flex-start;
  }

  & .brand {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    color: var(--ui-text);
    font-weight: 700;

    & img { width: 24px; height: 24px; border-radius: 6px; }
  }

  & nav {
    display: flex;
    gap: 2.5rem;
    flex-wrap: wrap;

    & ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
    & h4 { margin: 0 0 0.6rem; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ui-text-muted); }
    & a { color: var(--ui-text-muted); }
    & a:hover { color: var(--ui-text); }
  }

  & .legal { width: 100%; margin-top: 1rem; font-size: 0.82rem; }
  & .legal p { margin: 0.25rem 0; }
}

/* ---- Reveal on scroll ---- */
/* Only once the script is known to be running (the head sets html.js):
   without it every section stays visible, for crawlers, print and readers
   with scripts off. */
@media (prefers-reduced-motion: no-preference) {
  html.js .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 700ms var(--ease), transform 700ms var(--ease);

    &.in-view { opacity: 1; transform: none; }
    /* A block that is itself a link's target is where the reader is already
       looking: it stands still. Sliding in, it would be measured 18px low
       and come to rest tucked under the navigation. */
    &:target { opacity: 1; transform: none; transition: none; }
  }
}
