/* Media Preview Generator docs — the site dresses like the app it documents: near-black
   surfaces, one amber accent (Plex's own #e5a00d), no second hue competing.
   One exception, also the app's: the coffee link's cup is pink (--cup), because
   every other hue here already means something. It colours that icon only.
   Dark is the default because the product is dark; light exists because the
   reference page is 68k of prose and some people read long docs in daylight. */

/* ---------------------------------------------------------------- tokens -- */

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

  --amber: #e5a00d;
  --amber-bright: #f5c04a;
  --amber-deep: #b87d05;

  --gutter: clamp(1.25rem, 1rem + 2vw, 2.5rem);
  --measure: 68ch;
  --wide: 1200px;
  --radius: 14px;
  --radius-sm: 9px;

  --nav-h: 60px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

:root,
:root[data-theme="dark"] {
  --bg: #08080a;
  --bg-soft: #0d0d10;
  --surface: #121216;
  --surface-2: #191920;
  --surface-3: #22222b;
  --border: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.16);
  --text: #f4f4f5;
  --text-soft: #c9c9d1;
  /* Three text tones, not four. A fainter tertiary grey used to sit below --muted and failed WCAG AA
     wherever it was used — footer headings, frame titles, sidebar labels, all 12-13px (3.15:1 light,
     3.69:1 dark on --bg-soft). Any tone dark/light enough to pass is indistinguishable from --muted,
     so there is nothing between --muted and the background. */
  --muted: #94949f;
  --accent: var(--amber);
  --accent-text: var(--amber-bright);
  --accent-quiet: rgba(229, 160, 13, 0.12);
  --accent-line: rgba(229, 160, 13, 0.34);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 12px 32px -12px rgba(0, 0, 0, 0.7);
  --shadow-lg:
    0 2px 4px rgba(0, 0, 0, 0.5), 0 32px 64px -24px rgba(0, 0, 0, 0.85);
  --code-bg: #0f0f13;
  --good: #4ade80;
  --warn: #fbbf24;
  --bad: #f87171;
  --star: var(--amber);
  --cup: #e882b4;
  color-scheme: dark;
}

:root[data-theme="light"] {
  --bg: #fcfcfb;
  --bg-soft: #f6f6f4;
  --surface: #ffffff;
  --surface-2: #f7f7f5;
  --surface-3: #eeeeeb;
  --border: rgba(24, 24, 27, 0.11);
  --border-strong: rgba(24, 24, 27, 0.22);
  --text: #18181b;
  --text-soft: #33333a;
  --muted: #5f5f6b;
  --accent: var(--amber-deep);
  --accent-text: #93630a;
  --accent-quiet: rgba(229, 160, 13, 0.14);
  --accent-line: rgba(184, 125, 5, 0.4);
  --shadow:
    0 1px 2px rgba(24, 24, 27, 0.06), 0 10px 26px -14px rgba(24, 24, 27, 0.22);
  --shadow-lg:
    0 2px 6px rgba(24, 24, 27, 0.07), 0 28px 56px -22px rgba(24, 24, 27, 0.28);
  --code-bg: #f6f6f4;
  --good: #15803d;
  --warn: #a16207;
  --bad: #b91c1c;
  --star: var(--amber-deep);
  --cup: #b8327a;
  color-scheme: light;
}

/* ------------------------------------------------------------------ base -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1.5rem);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

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

a {
  color: var(--accent-text);
  text-decoration-color: var(--accent-line);
  text-underline-offset: 3px;
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

h1,
h2,
h3,
h4 {
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 650;
  margin: 0;
  text-wrap: balance;
}

code,
kbd,
pre,
samp {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 2.5rem 0;
}

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

.skip-link {
  position: absolute;
  left: 0.5rem;
  top: -3rem;
  z-index: 200;
  background: var(--accent);
  color: #1a1200;
  padding: 0.6rem 1rem;
  border-radius: var(--radius-sm);
  font-weight: 600;
  transition: top 0.15s var(--ease);
}

.skip-link:focus {
  top: 0.5rem;
}

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

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

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: min(100% - var(--gutter) * 2, 1400px);
  margin-inline: auto;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 660;
  font-size: 1.03rem;
  letter-spacing: -0.02em;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
}

.brand__mark {
  width: 27px;
  height: 27px;
  flex: none;
  border-radius: 7px;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.nav__link {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 520;
  padding: 0.45rem 0.7rem;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  transition:
    color 0.15s var(--ease),
    background 0.15s var(--ease);
}

.nav__link:hover {
  color: var(--text);
  background: var(--surface-2);
}

.nav__link[aria-current="page"] {
  color: var(--accent-text);
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition:
    color 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.icon-btn:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.icon-btn svg {
  width: 16px;
  height: 16px;
}

/* The toggle shows the theme you'd switch TO, so only one glyph is ever up. */
[data-theme="dark"] .icon-btn__sun,
[data-theme="light"] .icon-btn__moon {
  display: none;
}

.search-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: 34px;
  padding: 0 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  transition:
    border-color 0.15s var(--ease),
    color 0.15s var(--ease);
}

.search-btn:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  height: 34px;
  flex: none;
  padding: 0 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 520;
  text-decoration: none;
  transition: border-color 0.15s var(--ease);
}

.nav-pill:hover {
  border-color: var(--border-strong);
}

.nav-pill svg {
  width: 16px;
  height: 16px;
  flex: none;
}

.nav-pill--star svg,
.footer__star {
  color: var(--star);
  fill: var(--star);
}

.nav-pill--coffee svg,
.footer__cup {
  color: var(--cup);
}


.search-btn svg {
  width: 14px;
  height: 14px;
  flex: none;
}

.search-btn kbd {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05rem 0.3rem;
  font-size: 0.72rem;
  color: var(--muted);
  background: var(--surface-2);
}

.nav__burger {
  display: none;
}

@media (max-width: 900px) {
  .nav__links,
  .search-btn kbd {
    display: none;
  }
  .nav__burger {
    display: inline-grid;
  }
}

/* Measured at 320: the brand, a worded search button and four 34px icons want
   387px inside a 275px bar, and the row pushed every page 86px sideways. Shed
   the parts that say something twice, widest first. The word goes before the
   icon, which keeps its aria-label; the coffee goes before anything
   structural, and it is still in the footer. */
/* The Star and Coffee words need ~110px the full nav row does not have below 1180px (measured: 24px
   over at 1100, 215px at 901). Once the nav links collapse into the burger at 900 there is room for
   the words again, until the 600px pass sheds every label. */
@media (min-width: 901px) and (max-width: 1180px), (max-width: 600px) {
  .nav-pill {
    width: 34px;
    padding: 0;
    justify-content: center;
  }
  .nav-pill__label {
    display: none;
  }
}

@media (max-width: 600px) {
  .search-btn {
    width: 34px;
    padding: 0;
    justify-content: center;
  }
  .search-btn__label {
    display: none;
  }
}

@media (max-width: 420px) {
  .nav__inner {
    gap: 0.4rem;
  }
  .nav-pill--coffee {
    display: none;
  }
}

/* --------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.7rem 1.25rem;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition:
    transform 0.12s var(--ease),
    background 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.btn:active {
  transform: translateY(1px);
}

.btn svg {
  width: 17px;
  height: 17px;
  flex: none;
}

.btn--primary {
  background: var(--amber);
  color: #1a1200;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22) inset;
}

.btn--primary:hover {
  background: var(--amber-bright);
}

.btn--ghost {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--text);
}

.btn--ghost:hover {
  background: var(--surface-2);
}

.btn--lg {
  padding: 0.85rem 1.6rem;
  font-size: 1rem;
}

/* -------------------------------------------------------------- sections -- */

.section {
  padding-block: clamp(3.5rem, 2rem + 6vw, 6.5rem);
}

.section--tint {
  background: var(--bg-soft);
  border-block: 1px solid var(--border);
}

.section__head {
  max-width: 42rem;
  margin-bottom: clamp(2rem, 1rem + 3vw, 3.25rem);
}

.section__head--center {
  margin-inline: auto;
  text-align: center;
}

.eyebrow {
  display: inline-block;
  font-size: 0.76rem;
  font-weight: 680;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: 0.75rem;
}

.section h2 {
  font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.35rem);
  margin-bottom: 0.85rem;
}

.section__lede {
  color: var(--muted);
  font-size: clamp(1rem, 0.97rem + 0.2vw, 1.09rem);
  margin: 0;
  text-wrap: pretty;
}

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

.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3rem, 1.5rem + 7vw, 6rem)
    clamp(2.5rem, 1rem + 5vw, 4.5rem);
}

/* A single warm bloom behind the headline, so the page has a light source
   without the gradient-banner look the stock theme had. */
.hero::before {
  content: "";
  position: absolute;
  inset: -40% 0 auto 50%;
  translate: -50% 0;
  width: min(1100px, 130%);
  aspect-ratio: 1;
  background: radial-gradient(
    circle,
    rgba(229, 160, 13, 0.16),
    transparent 62%
  );
  pointer-events: none;
  z-index: 0;
}

[data-theme="light"] .hero::before {
  background: radial-gradient(circle, rgba(229, 160, 13, 0.2), transparent 65%);
}

.hero > * {
  position: relative;
  z-index: 1;
}

.hero__inner {
  max-width: 50rem;
  margin-inline: auto;
  text-align: center;
}

.hero h1 {
  font-size: clamp(2.15rem, 1.3rem + 4.2vw, 4rem);
  letter-spacing: -0.035em;
  font-weight: 700;
  margin-bottom: 1.15rem;
}

.hero h1 em {
  font-style: normal;
  color: var(--accent-text);
}

.hero__sub {
  font-size: clamp(1.05rem, 0.98rem + 0.45vw, 1.28rem);
  color: var(--text-soft);
  margin: 0 auto 1.9rem;
  max-width: 40rem;
  text-wrap: pretty;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
}

.hero__meta {
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  justify-content: center;
  font-size: 0.86rem;
  color: var(--muted);
}

.hero__meta span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.hero__meta svg {
  width: 14px;
  height: 14px;
  color: var(--accent);
  flex: none;
}

.hero__shot {
  margin-top: clamp(2.5rem, 1.5rem + 4vw, 4rem);
}

/* --------------------------------------------------------- media frames -- */

/* Screenshots need a container or they read as loose rectangles on the page.
   The Plex row shot gets a plain frame; app shots get a faux title bar. */
.frame {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
}

.frame img {
  width: 100%;
}

.frame--chrome .frame__bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.85rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.frame__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--surface-3);
  flex: none;
}

.frame__title {
  margin-left: 0.5rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.76rem;
  color: var(--muted);
  font-family: var(--font-mono);
}

figure {
  margin: 0;
}

figcaption {
  margin-top: 0.85rem;
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
  text-wrap: pretty;
}

/* ----------------------------------------------------------------- cards -- */

.grid {
  display: grid;
  gap: 1.1rem;
}

.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.4rem;
  transition:
    border-color 0.15s var(--ease),
    transform 0.15s var(--ease);
}

.card--link {
  text-decoration: none;
  color: inherit;
  display: block;
}

.card--link:hover {
  border-color: var(--accent-line);
  transform: translateY(-2px);
}

.card__icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: var(--accent-quiet);
  color: var(--accent-text);
  margin-bottom: 0.95rem;
}

.card__icon svg {
  width: 19px;
  height: 19px;
}

.card h3 {
  font-size: 1.02rem;
  margin-bottom: 0.4rem;
}

.card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.6;
}

.card p + p {
  margin-top: 0.6rem;
}

.card__more {
  display: inline-block;
  margin-top: 0.85rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--accent-text);
}

/* An inline-block takes no underline from its link, so the underline stops at the text. As a flex
   item (the old inline-flex) the arrow was underlined on its own, a break away from the text. */
.card__more span {
  display: inline-block;
  margin-left: 0.35rem;
}

/* --------------------------------------------------------- pipeline -- */

/* Sources in, the app in the middle, results out, so the whole flow reads as one row
   instead of being spread over several sections. */
.pipeline {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: 0.85rem;
  max-width: 60rem;
  margin: 0 auto clamp(2rem, 1rem + 3vw, 3rem);
}

.pipeline__stage {
  flex: 1 1 14rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  text-align: center;
}

.pipeline__stage--core {
  border-color: var(--accent-line);
  background: var(--accent-quiet);
}

.pipeline__stage h3 {
  font-size: 0.94rem;
  margin-bottom: 0.3rem;
}

.pipeline__stage p {
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
}

.pipeline__arrow {
  align-self: center;
  color: var(--accent);
  font-size: 1.2rem;
  flex: none;
}

@media (max-width: 720px) {
  .pipeline__arrow {
    rotate: 90deg;
  }
}

/* --------------------------------------------------------- works with -- */

/* Capped at three columns so the six groups land as two even rows. The plain
   .grid--3 stretches to four on a wide screen and leaves two orphans. */
.grid--trio {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  max-width: 68rem;
  margin-inline: auto;
}

.supports {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.7rem;
}

.supports li {
  display: grid;
  gap: 0.1rem;
  font-size: 0.9rem;
}

.supports strong {
  color: var(--text);
  font-weight: 600;
}

.supports span {
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.5;
}

/* ------------------------------------------------------------ stat band -- */
/* Four numbers under the hero. Column counts are fixed rather than auto-fit
   because auto-fit put three across and left the fourth alone on a second row
   through the whole 900-1000px range. */

.stats-band {
  background: var(--bg-soft);
  border-block: 1px solid var(--border);
  padding-block: clamp(1.75rem, 1rem + 2.5vw, 2.75rem);
}

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 0.75rem + 2vw, 2.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stat__value {
  margin: 0;
  font-size: clamp(2.1rem, 1.6rem + 2.2vw, 3rem);
  line-height: 1;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

.stat__unit {
  margin-left: 0.22em;
  font-size: 0.4em;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--muted);
}

.stat__label {
  margin: 0.5rem 0 0;
  font-size: 0.98rem;
  font-weight: 640;
}

.stat__note {
  margin: 0.3rem 0 0;
  color: var(--muted);
  font-size: 0.86rem;
  text-wrap: pretty;
}

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

@media (min-width: 1000px) {
  .stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0;
  }
  .stat {
    padding-inline: clamp(1rem, 0.4rem + 1.6vw, 2rem);
  }
  .stat + .stat {
    border-left: 1px solid var(--border);
  }
  .stat:first-child {
    padding-left: 0;
  }
  .stat:last-child {
    padding-right: 0;
  }
}

/* ----------------------------------------------------------------- tour -- */
/* One grid, three layouts, no duplicated content. The steps and the pictures are
   siblings in reading order, so:
     narrow            one column, each step followed by its own picture
     wide, no script   two columns, each step beside its own picture
     wide, with script every picture moves into one pinned frame that changes
   Only the third is scoped under .js-tour-ready, and only site.js adds that class
   (after proving it can drive it — same contract as .reveal at the foot of this
   file). Nothing here is hidden or dimmed by CSS alone, so a blocked script leaves
   five readable steps and five visible pictures instead of a page of grey. */

/* `minmax(0, 1fr)`, not the implicit `auto`: an auto column is at least as wide
   as its widest item's min-content, and at 320 the address bar's monospace path
   pushed that to 321px inside a 275px page. Measured. */
.tour {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 1.25rem + 3vw, 3.25rem);
}

/* Decoration for the pinned layout only. Hidden until site.js turns that on, so
   nobody else gets an empty groove down the page. */
.tour__rail {
  display: none;
}

.tour-step {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr);
  column-gap: 1.05rem;
  row-gap: 0.5rem;
  align-content: start;
}

.tour-step__num {
  grid-column: 1;
  grid-row: 1 / span 2;
  margin: 0;
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-soft);
  font-size: 0.95rem;
  font-weight: 680;
  font-variant-numeric: tabular-nums;
}

.tour-step__title {
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  margin: 0;
  font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.5rem);
  text-wrap: balance;
}

.tour-step__body {
  grid-column: 2;
  grid-row: 2;
  margin: 0;
  color: var(--muted);
  font-size: 0.97rem;
  text-wrap: pretty;
}

.tour-panel {
  margin: 0;
}

.tour-panel img {
  display: block;
  width: 100%;
  height: auto;
}

@media (min-width: 901px) {
  /* Wider pictures than Shortlist's 0.92fr / 1.08fr: four of the five captures are strips four to
     five times as wide as they are tall, and at Shortlist's split their text came out half size. */
  .tour {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    column-gap: clamp(2rem, 1rem + 3.5vw, 4rem);
    align-items: center;
  }

  .tour-step {
    grid-column: 1;
  }

  .tour-panel {
    grid-column: 2;
  }

  /* --- pinned layout, script only ------------------------------------- */

  .js-tour-ready .tour {
    grid-template-rows: repeat(var(--tour-steps), auto);
    align-items: start;
  }

  .js-tour-ready .tour__rail {
    display: block;
    position: absolute;
    left: calc(1.125rem - 1px);
    top: 0.5rem;
    bottom: 0.5rem;
    width: 2px;
    border-radius: 2px;
    background: var(--border);
    overflow: hidden;
  }

  .js-tour-ready .tour__rail-fill {
    display: block;
    width: 100%;
    height: 0;
    background: var(--accent);
    transition: height 0.12s linear;
  }

  .js-tour-ready .tour-step {
    min-height: 66vh;
    align-content: center;
    opacity: 0.42;
    transition: opacity 0.35s var(--ease);
  }

  .js-tour-ready .tour-step.is-active {
    opacity: 1;
  }

  .js-tour-ready .tour-step.is-active .tour-step__num {
    background: var(--accent);
    border-color: transparent;
    color: #1a1200;
  }

  /* Every panel occupies the whole second column and sticks inside it. `1 / -1`
     needs the rows to be explicit, which is what --tour-steps is for. */
  /* Stacked in one grid area, so each is its own box and none of them affects
     any other's size. Giving them all ONE fixed shape is the trap: these five
     run from 1.13:1 (the webhook page) to 5.2:1 (the server cards), and one
     shared frame would either shrink the tallest until the app's text is
     unreadable or leave the strips floating in a box of empty space.
     `object-fit: contain` stops a picture being cropped, not being shrunk. Each
     panel keeps its own shape instead; only the height cap below ever makes one
     letterbox, and only on a viewport too short to show it whole. */
  .js-tour-ready .tour-panel {
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: start;
    position: sticky;
    top: calc(var(--nav-h) + 7vh);
    /* One box for all five, with the picture centred in it, so the frame stops
       jumping up and down the viewport as the pictures swap. */
    height: calc(100vh - var(--nav-h) - 14vh);
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 0.35s var(--ease),
      visibility 0.35s;
  }

  .js-tour-ready .tour-panel.is-active {
    opacity: 1;
    visibility: visible;
  }

  .js-tour-ready .tour-panel .frame {
    min-height: 0;
    max-height: 100%;
    display: flex;
    flex-direction: column;
    background: var(--surface-2);
  }

  /* Only bites on a viewport too short to show a picture whole: the frame hits
     the box height, the picture shrinks inside it, and `contain` letterboxes it
     rather than cropping. */
  .js-tour-ready .tour-panel img {
    min-height: 0;
    object-fit: contain;
  }
}

/* -------------------------------------------------------- closing call -- */

.cta {
  position: relative;
  overflow: hidden;
  max-width: 46rem;
  margin-inline: auto;
  padding: clamp(2rem, 1.25rem + 3vw, 3.25rem)
    clamp(1.25rem, 0.75rem + 2vw, 2.5rem);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  text-align: center;
}

/* The same warm bloom as the hero, so the page opens and closes on one light
   source rather than fading out into a plain box. */
.cta::before {
  content: "";
  position: absolute;
  inset: -55% 15% auto;
  height: 18rem;
  background: radial-gradient(closest-side, var(--accent-quiet), transparent);
  pointer-events: none;
}

.cta > * {
  position: relative;
}

.cta h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.1rem);
  margin-bottom: 0.75rem;
}

.cta p {
  margin: 0 auto;
  max-width: 34rem;
  color: var(--muted);
  text-wrap: pretty;
}

.cta .hero__cta {
  margin-top: 1.75rem;
}

/* --------------------------------------------------------------- table -- */

.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  -webkit-overflow-scrolling: touch;
}

.table-scroll table {
  border-collapse: collapse;
  width: 100%;
  min-width: 44rem;
  font-size: 0.91rem;
}

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

.table-scroll thead th {
  background: var(--surface-2);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 640;
  white-space: nowrap;
}

.table-scroll tbody tr:last-child td {
  border-bottom: 0;
}

.table-scroll tbody tr:hover {
  background: var(--surface-2);
}

.table-scroll td:first-child {
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

.yes {
  color: var(--good);
  font-weight: 700;
}

.no {
  color: var(--muted);
}

/* ---------------------------------------------------------------- code -- */

.codeblock {
  position: relative;
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.codeblock__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0.6rem 0.55rem 1rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
  color: var(--muted);
  font-family: var(--font-mono);
}

.codeblock pre {
  margin: 0;
  padding: 1.1rem;
  overflow-x: auto;
  font-size: 0.86rem;
  line-height: 1.75;
  -webkit-overflow-scrolling: touch;
}

.copy {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 0.75rem;
  font-family: var(--font-sans);
  cursor: pointer;
  transition:
    color 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.copy:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.copy[data-copied="true"] {
  color: var(--good);
  border-color: var(--good);
}

.copy svg {
  width: 13px;
  height: 13px;
}

/* ----------------------------------------------------------------- faq -- */

.faq {
  max-width: 48rem;
  margin-inline: auto;
  display: grid;
  gap: 0.65rem;
}

.faq details {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.faq details[open] {
  border-color: var(--border-strong);
}

.faq summary {
  cursor: pointer;
  padding: 1rem 1.2rem;
  font-weight: 600;
  font-size: 0.98rem;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

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

.faq summary::after {
  content: "";
  width: 8px;
  height: 8px;
  flex: none;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  rotate: 45deg;
  translate: 0 -2px;
  transition: rotate 0.2s var(--ease);
}

.faq details[open] summary::after {
  rotate: -135deg;
  translate: 0 2px;
}

.faq__body {
  padding: 0 1.2rem 1.15rem;
  color: var(--muted);
  font-size: 0.93rem;
}

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

.faq__body > :last-child {
  margin-bottom: 0;
}

/* -------------------------------------------------------------- callout -- */

.callout {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.85rem;
  padding: 1rem 1.2rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: 0.92rem;
}

.callout svg {
  width: 18px;
  height: 18px;
  color: var(--accent);
  margin-top: 0.2rem;
  flex: none;
}

.callout > div > :first-child {
  margin-top: 0;
}

.callout > div > :last-child {
  margin-bottom: 0;
}

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

.footer {
  border-top: 1px solid var(--border);
  background: var(--bg-soft);
  padding-block: 3rem 2rem;
  font-size: 0.9rem;
}

.footer__grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  margin-bottom: 2.25rem;
}

.footer h4 a {
  /* "Plex how-to" is both a column heading and a real page, so its heading is a link. It must still
     read as a heading rather than as the first item in its own list. */
  color: inherit;
  text-decoration: none;
}

.footer h4 a:hover {
  color: var(--text);
}

.footer h4 {
  font-size: 0.78rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.85rem;
  font-weight: 640;
}

.footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.footer a {
  color: var(--muted);
  text-decoration: none;
}

.footer__support {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.footer__support svg {
  width: 13px;
  height: 13px;
  flex: none;
}

/* Sub-pages sit under their section rather than reading as siblings of it. */
.footer__kid {
  padding-left: 0.75rem;
  font-size: 0.9em;
}

.footer a:hover {
  color: var(--accent-text);
}

.footer__blurb {
  color: var(--muted);
  margin: 0.75rem 0 0;
  max-width: 22rem;
  font-size: 0.88rem;
}

.footer__base {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--border);
  padding-top: 1.5rem;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ---------------------------------------------------------- docs layout -- */

.docs {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr) 200px;
  gap: clamp(1.5rem, 1rem + 2vw, 3rem);
  width: min(100% - var(--gutter) * 2, 1400px);
  margin-inline: auto;
  align-items: start;
}

.sidebar,
.toc {
  position: sticky;
  top: calc(var(--nav-h) + 1.5rem);
  max-height: calc(100vh - var(--nav-h) - 3rem);
  overflow-y: auto;
  padding-block: 2rem;
  font-size: 0.9rem;
  scrollbar-width: thin;
}

.sidebar h4,
.toc h4 {
  font-size: 0.74rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.75rem;
  font-weight: 640;
}

.sidebar ul,
.toc ul {
  list-style: none;
  margin: 0 0 1.75rem;
  padding: 0;
  display: grid;
  gap: 0.15rem;
}

.sidebar a {
  display: block;
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-sm);
  color: var(--muted);
  text-decoration: none;
  transition:
    color 0.15s var(--ease),
    background 0.15s var(--ease);
}

.sidebar a:hover {
  color: var(--text);
  background: var(--surface-2);
}

/* Guide sub-pages, shown only while you're inside that section. Scoped under
   .sidebar so it outweighs the `.sidebar ul` margin reset above it. */
.sidebar .sidebar__children {
  margin: 0.2rem 0 0.5rem 0.85rem;
  padding-left: 0.7rem;
  border-left: 1px solid var(--border);
  gap: 0;
}

.sidebar__children a {
  padding: 0.3rem 0.6rem;
  font-size: 0.85rem;
}

.sidebar a[aria-current="page"] {
  color: var(--accent-text);
  background: var(--accent-quiet);
  font-weight: 600;
}

.toc a {
  display: block;
  padding: 0.28rem 0 0.28rem 0.75rem;
  border-left: 2px solid var(--border);
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  line-height: 1.45;
  transition:
    color 0.15s var(--ease),
    border-color 0.15s var(--ease);
}

.toc a:hover {
  color: var(--text);
}

.toc a.is-active {
  color: var(--accent-text);
  border-left-color: var(--accent);
}

.toc a[data-level="3"] {
  padding-left: 1.5rem;
  font-size: 0.81rem;
}

@media (max-width: 1180px) {
  .docs {
    grid-template-columns: 230px minmax(0, 1fr);
  }
  .toc {
    display: none;
  }
}

@media (max-width: 900px) {
  .docs {
    grid-template-columns: minmax(0, 1fr);
  }
  .sidebar {
    display: none;
    position: static;
    max-height: none;
    padding-block: 1rem 0;
    border-bottom: 1px solid var(--border);
  }
  .sidebar.is-open {
    display: block;
  }
}

/* ---------------------------------------------------------------- prose -- */

.prose {
  padding-block: 2.5rem 4rem;
  min-width: 0;
}

.prose > * {
  max-width: var(--measure);
}

.prose__head {
  margin-bottom: 2.25rem;
  padding-bottom: 1.75rem;
  border-bottom: 1px solid var(--border);
}

.prose__head h1 {
  font-size: clamp(1.85rem, 1.4rem + 2vw, 2.65rem);
  letter-spacing: -0.03em;
  margin-bottom: 0.65rem;
}

.prose__head p {
  margin: 0;
  color: var(--muted);
  font-size: 1.05rem;
  text-wrap: pretty;
}

.prose h2 {
  font-size: 1.5rem;
  margin: 2.75rem 0 0.9rem;
  padding-top: 0.5rem;
}

.prose h3 {
  font-size: 1.17rem;
  margin: 2rem 0 0.7rem;
}

.prose h4 {
  font-size: 1.02rem;
  margin: 1.6rem 0 0.5rem;
}

.prose p,
.prose ul,
.prose ol {
  margin: 0 0 1.1rem;
}

.prose li {
  margin-bottom: 0.4rem;
}

.prose li > ul,
.prose li > ol {
  margin-top: 0.4rem;
  margin-bottom: 0.5rem;
}

.prose strong {
  color: var(--text);
  font-weight: 640;
}

.prose blockquote {
  margin: 1.5rem 0;
  padding: 0.9rem 1.2rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-soft);
}

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

.prose blockquote > :last-child {
  margin-bottom: 0;
}

.prose :not(pre) > code {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 0.1em 0.38em;
  color: var(--accent-text);
  /* NOT `nowrap`. It defeated the `overflow-wrap` beside it, so a long inline code span — an API
     path, or the ranking formula — set a min-content width wider than a phone and panned the whole
     page sideways. Reference was 555px of content in a 316px viewport. */
  white-space: normal;
  overflow-wrap: anywhere;
}

.prose pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem;
  overflow-x: auto;
  margin: 0 0 1.3rem;
  font-size: 0.86rem;
  line-height: 1.7;
  -webkit-overflow-scrolling: touch;
}

.prose pre code {
  background: none;
  border: 0;
  padding: 0;
  color: var(--text-soft);
  white-space: pre;
}

/* Long reference tables are the main reason this site needs a wide column. */
.prose table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.89rem;
  margin: 0 0 1.3rem;
}

.prose .table-scroll {
  max-width: none;
  margin-bottom: 1.3rem;
}

.prose .table-scroll table {
  margin: 0;
}

.prose th,
.prose td {
  text-align: left;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.prose thead th {
  background: var(--surface-2);
  font-size: 0.77rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.prose img {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-block: 1.3rem;
  max-width: 100%;
}

.prose .anchor {
  opacity: 0;
  margin-left: 0.4rem;
  color: var(--muted);
  text-decoration: none;
  font-weight: 400;
  transition: opacity 0.15s var(--ease);
}

.prose h2:hover .anchor,
.prose h3:hover .anchor,
.anchor:focus-visible {
  opacity: 1;
}

/* prev / next */

.pager {
  display: grid;
  gap: 0.85rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  margin-top: 3.5rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
  max-width: var(--measure);
}

.pager a {
  display: block;
  padding: 0.95rem 1.15rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s var(--ease);
}

.pager a:hover {
  border-color: var(--accent-line);
}

.pager small {
  display: block;
  color: var(--muted);
  font-size: 0.78rem;
  margin-bottom: 0.2rem;
}

.pager strong {
  color: var(--accent-text);
  font-size: 0.95rem;
}

.pager .is-next {
  text-align: right;
}

.edit-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 2rem;
  font-size: 0.86rem;
  color: var(--muted);
  text-decoration: none;
}

.edit-link:hover {
  color: var(--accent-text);
}

.edit-link svg {
  width: 14px;
  height: 14px;
}

/* --------------------------------------------------------------- search -- */

.search-dialog {
  width: min(100% - 2rem, 40rem);
  max-height: min(70vh, 34rem);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-lg);
  margin-top: 9vh;
  overflow: hidden;
}

.search-dialog::backdrop {
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(3px);
}

.search-dialog__input {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--border);
}

.search-dialog__input svg {
  width: 17px;
  height: 17px;
  color: var(--muted);
  flex: none;
}

.search-dialog__input input {
  flex: 1;
  border: 0;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 1rem;
  outline: none;
  min-width: 0;
}

.search-results {
  overflow-y: auto;
  max-height: calc(min(70vh, 34rem) - 4rem);
  padding: 0.5rem;
  margin: 0;
  list-style: none;
}

.search-results li a {
  display: block;
  padding: 0.65rem 0.8rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: inherit;
}

.search-results li a:hover,
.search-results li a:focus-visible,
.search-results li.is-active a {
  background: var(--accent-quiet);
}

.search-results strong {
  display: block;
  font-size: 0.93rem;
  color: var(--text);
}

.search-results small {
  display: block;
  color: var(--muted);
  font-size: 0.82rem;
  margin-top: 0.15rem;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.search-results mark {
  background: var(--accent-quiet);
  color: var(--accent-text);
  border-radius: 3px;
  padding: 0 2px;
}

.search-empty {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
}

/* ---------------------------------------------------------------- utils -- */

.stack-lg > * + * {
  margin-top: clamp(1.75rem, 1rem + 2.5vw, 2.75rem);
}

.center {
  text-align: center;
}

.mt-lg {
  margin-top: clamp(1.75rem, 1rem + 2.5vw, 2.75rem);
}

/* --------------------------------------------------------------- reveal -- */
/* Fade-up for section reveals. Visible at rest by design: `.reveal` on its own
   carries no hidden state, so this file plus no JS (or JS that threw, or a
   browser with no IntersectionObserver) renders every section normally. Only
   site.js adds `.js-reveal-ready` to <html>, and only after it has confirmed it
   can un-hide again — CSS never hides content on its own.

   No prefers-reduced-motion block here: the sitewide rule near the top of this
   file already forces transition-duration to 0.01ms on every element, so this
   transition is already imperceptible under it. site.js skips the observer
   entirely in that case, so the class is never even added. */
.reveal {
  opacity: 1;
  transform: none;
}

.js-reveal-ready .reveal {
  opacity: 0;
  transform: translateY(16px);
}

/* The transition lives on the VISIBLE state, not the hidden one. Put it on the
   hidden rule and the browser animates INTO it: site.js adds .js-reveal-ready
   after first paint, every section below the fold fades out over half a second,
   and only then fades back in. Measured, not guessed — an offscreen section
   read opacity 0.0166 mid-fade-out. Here the hide is instantaneous and only the
   reveal animates, because a transition is read from the after-change style. */
.js-reveal-ready .reveal.is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.5s var(--ease),
    transform 0.5s var(--ease);
}

/* ------------------------------------------------ GitHub alert callouts -- */
/* docs/_plugins/github_markdown.rb turns `> [!NOTE]` and friends into these boxes. The label says
   which kind it is in words; the colour only repeats it. */
.callout__label {
  margin: 0 0 0.3rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.prose .callout {
  margin: 1.4rem 0;
}
.callout--warning {
  border-left-color: var(--warn);
}
.callout--warning svg,
.callout--warning .callout__label {
  color: var(--warn);
}
.callout--caution {
  border-left-color: var(--bad);
}
.callout--caution svg,
.callout--caution .callout__label {
  color: var(--bad);
}

/* "Facts checked" date under a page's heading, rendered from front matter. */
.prose__facts {
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.85rem;
}

/* Three words of brand name push the nav buttons off the bar on a phone. */
@media (max-width: 520px) {
  .nav .brand__name {
    display: none;
  }
}

/* ------------------------------------------------- landing figures -- */
/* The three-player strip and the HDR pair: a framed picture with a caption under it. */
.players,
.pair {
  margin: 0;
}
/* The three players side by side are 4.5 times as wide as they are tall: across a phone each player
   is a postage stamp. Below 901px the strip keeps a readable width and scrolls sideways, as the
   tour's pictures do; the caption links each player at full size. */
@media (max-width: 900px) {
  .players__scroll {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  .players__scroll img {
    width: max(100%, 46rem);
    max-width: none;
  }
}

/* The pair is two 320px preview frames, the size the servers show them, side by side: never wider
   than its own 708px, or the frames would be blown up past what the preview file holds. */
.pair {
  max-width: 44.25rem;
  margin-inline: auto;
}
.players figcaption,
.pair figcaption {
  margin-top: 0.9rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
}
/* The hero's picture is the product's result: a preview thumbnail over a player's seek bar, in the
   lower fifth of the capture. Stacked under the centred headline it started below the fold of a
   1440x900 or 1280x800 screen, so a visitor's first view was the player's empty top bar. From 1000px
   the text and the player sit side by side, and the whole player is in the first view. */
@media (min-width: 1000px) {
  .hero > .wrap {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    align-items: center;
    gap: clamp(2.5rem, 1rem + 2.5vw, 4rem);
  }
  .hero__inner {
    margin: 0;
    text-align: left;
  }
  .hero h1 {
    font-size: clamp(2.6rem, 1rem + 2.3vw, 3.4rem);
  }
  .hero__sub {
    margin-inline: 0;
    font-size: 1.12rem;
  }
  .hero__cta,
  .hero__meta {
    justify-content: flex-start;
  }
  .hero__shot {
    margin-top: 0;
  }
}

/* The hero's requirement is a link to the mounts it means. Laid out like the ticks beside it: the
   base rule makes every svg a block, which would put the icon on a line of its own. */
.hero__meta a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: inherit;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.hero__meta a:hover {
  color: var(--text);
}

/* The tour's captures are cut to one idea each: four wide strips and one nearly square (the webhook
   steps). Across the picture column the square one would show the app a third to a half larger than
   the strips and fill the pinned frame top to bottom; narrowed to the strips' scale, it reads as one
   more card from the same app. */
.tour-panel--tall .frame {
  max-width: 32rem;
  margin-inline: auto;
}

/* Each tour picture links to the full-size capture, for a closer look. */
.tour-panel__shot {
  display: block;
  cursor: zoom-in;
}

/* In the pinned layout the frame is a flex column that shrinks the picture to fit a short
   viewport; the link sits between them, so it has to pass that on. */
@media (min-width: 901px) {
  .js-tour-ready .tour-panel__shot {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
}

/* One column (phones, small tablets): fitted to the width, a strip's app text came out a third of
   its size and couldn't be read. Below 901px each picture is shown at 0.6 of its own size or the
   column width, whichever is larger, and scrolls sideways inside its frame. The cut-off edge shows
   there is more; a tap opens the whole capture. --shot-w is the capture's CSS width (tour.yml). */
@media (max-width: 900px) {
  .tour-panel__shot {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  .tour-panel__shot img {
    width: max(100%, calc(var(--shot-w) * 0.6));
    max-width: none;
  }
}
/* The pinned tour's rail runs down through the centre of every step number. The rail is positioned
   and the numbers weren't, so it painted over them and struck each digit through. */
.tour-step__num {
  position: relative;
  z-index: 1;
}

/* The compose file is three times the docker run's length; each block keeps its own height rather
   than stretching docker run into an empty box. */
.install__code {
  align-items: start;
}

/* The quick start's requirements line: two balanced lines under the code, not one long one. */
.install__note {
  max-width: 46rem;
  margin-inline: auto;
  color: var(--muted);
  font-size: 0.92rem;
  text-wrap: balance;
}

/* A section's closing button may wrap: "See the side-by-side comparison" is wider than a 320px
   phone's column, and .btn never wraps, so it pushed the page sideways. */
.center > .btn {
  max-width: 100%;
  white-space: normal;
}

/* Keeps a hyphenated word whole: "built-in" and "read-write" broke at the hyphen on a phone. */
.nowrap {
  white-space: nowrap;
}

/* Room between the "only a media server and Docker" line and the cards it introduces. */
.works-with__note {
  margin: 1.75rem auto 1.5rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.92rem;
}

/* A fourth works-with card would make grid--trio's three groups an uneven 3+1, so the per-server
   skip-button requirements sit here as a short list instead. */
.works-with__skip {
  max-width: 34rem;
  margin: 1.75rem auto 0;
}

.works-with__skip .works-with__note {
  margin: 0 0 0.9rem;
}

/* Three stats (the facts, before any benchmark number) sit in one row of three from 720px, with the
   same dividers as the row of four, instead of two-plus-one or four columns with one left empty. */
@media (min-width: 720px) {
  .stats--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
  }
  .stats--3 .stat {
    padding-inline: clamp(1rem, 0.4rem + 1.6vw, 2rem);
  }
  .stats--3 .stat + .stat {
    border-left: 1px solid var(--border);
  }
  .stats--3 .stat:first-child {
    padding-left: 0;
  }
  .stats--3 .stat:last-child {
    padding-right: 0;
  }
}
