/* dsh-plugin-mobile-ux — shared site styles
 *
 * One stylesheet for every page on the site. Layout is mobile-first: the base
 * rules are the phone layout, and the `@media (min-width: …)` blocks add the
 * desktop refinements. Nothing here depends on JavaScript.
 */

:root {
  color-scheme: light dark;

  --bg: #ffffff;
  --bg-soft: #f6f7f9;
  --bg-elevated: #ffffff;
  --border: #e3e6ea;
  --border-strong: #d3d8de;
  --fg: #14171a;
  --fg-soft: #5b6470;
  --fg-faint: #8b94a1;
  --accent: #247bbf;
  --accent-strong: #1b6299;
  --accent-soft: #eaf3fb;
  --code-bg: #f2f4f7;
  --code-fg: #1f2933;
  --ok: #1a7f4b;
  --ok-soft: #e8f6ee;
  --warn: #9a6b00;
  --warn-soft: #fdf5e3;
  --danger: #a4342f;
  --danger-soft: #fdeceb;
  --shadow-sm: 0 1px 2px rgb(16 24 40 / 6%);
  --shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 8px 24px rgb(16 24 40 / 7%);
  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 20px;
  --measure: 62rem;
  --gutter: 14px;
  /* Home-indicator / notch insets. `viewport-fit=cover` lets the page paint into
     them, so the chrome has to keep its own distance. */
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b0f14;
    --bg-soft: #11161d;
    --bg-elevated: #141a22;
    --border: #242c36;
    --border-strong: #303a46;
    --fg: #e6edf3;
    --fg-soft: #9aa4b2;
    --fg-faint: #6f7987;
    --accent: #6cb6f0;
    --accent-strong: #9ccdf7;
    --accent-soft: #12293c;
    --code-bg: #12181f;
    --code-fg: #d7e2ec;
    --ok: #4ac486;
    --ok-soft: #10281d;
    --warn: #e0b341;
    --warn-soft: #2a2210;
    --danger: #f08d86;
    --danger-soft: #2c1614;
    --shadow-sm: 0 1px 2px rgb(0 0 0 / 40%);
    --shadow: 0 1px 2px rgb(0 0 0 / 45%), 0 8px 24px rgb(0 0 0 / 35%);
  }
}

* {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  background:
    radial-gradient(58rem 30rem at 80% -12rem, var(--accent-soft), transparent 70%),
    var(--bg);
  background-repeat: no-repeat;
  color: var(--fg);
  font:
    16px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  overflow-wrap: break-word;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

code,
pre,
kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

code {
  background: var(--code-bg);
  border-radius: 6px;
  padding: 0.12em 0.4em;
  font-size: 0.9em;
  color: var(--code-fg);
  /* Inline code is often a whole command (`dsh plugin --profile web add …`) or a
     path. Without this it forms one unbreakable run that widens its grid track
     and, on a phone, the entire page. */
  overflow-wrap: anywhere;
}

.wrap {
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 calc(var(--gutter) + var(--safe-l)) 0 calc(var(--gutter) + var(--safe-r));
}

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  position: static;
  display: inline-block;
  margin: 8px;
}

/* ---------------------------------------------------------------- header -- */

header.top {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--border);
}

header.top .wrap {
  display: flex;
  align-items: center;
  /* Wrap rather than overflow: at some widths the brand, the page menu and the
     language switch cannot share one row, and a squeezed menu is worse than two
     tidy rows. The narrow-screen block below decides where the break falls. */
  flex-wrap: wrap;
  gap: 8px;
  min-height: 54px;
}

header.top .brand {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: inherit;
  min-width: 0;
  flex: none;
}

header.top .brand:hover {
  text-decoration: none;
}

header.top .brand img {
  width: 24px;
  height: 24px;
  flex: none;
}

header.top .name {
  font-weight: 650;
  letter-spacing: 0.2px;
  font-size: 14px;
  white-space: nowrap;
}

header.top .navslot {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

header.top nav.pages {
  display: flex;
  align-items: center;
  /* Wraps inside its own row before it would clip a tab. In the 420-470px band
     the brand, four tabs and the language switch are just too wide together, and
     a clipped "安装指南" reads as a missing page. */
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 2px 4px;
}

header.top nav.pages::-webkit-scrollbar {
  display: none;
}

header.top nav.pages a {
  color: var(--fg-soft);
  font-size: 13.5px;
  padding: 5px 10px;
  border-radius: 999px;
  white-space: nowrap;
}

header.top nav.pages a:hover {
  background: var(--bg-soft);
  text-decoration: none;
}

header.top nav.pages a[aria-current="page"] {
  color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

.langs {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
  background: var(--bg-soft);
  flex: none;
}

.langs button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--fg-soft);
  font: inherit;
  font-size: 12.5px;
  padding: 3px 9px;
  cursor: pointer;
  line-height: 1.5;
  white-space: nowrap;
}

.langs button[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 650;
}

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

section {
  padding: 28px 0;
  border-top: 1px solid var(--border);
  /* Anchor targets must clear both sticky bars: the header plus the anchor
     strip. site.js keeps --header-h in step with the real header height. */
  scroll-margin-top: calc(var(--header-h, 54px) + 52px);
}

section:first-of-type {
  border-top: 0;
}

section > h2 {
  font-size: 19px;
  margin: 0 0 6px;
  letter-spacing: -0.2px;
}

section > p.sub {
  margin: 0 0 18px;
  color: var(--fg-soft);
  font-size: 14.5px;
}

/* ------------------------------------------------------------- controls -- */

/* Horizontally scrollable anchor bar. No menu: on a phone a scroll strip is
   faster than opening a panel, and it keeps the header one row tall. */
.anchors {
  position: sticky;
  /* Kept in step with the real header height by site.js; the fallback covers the
     no-JavaScript case. */
  top: var(--header-h, 54px);
  z-index: 15;
  margin: 0 0 4px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--border);
}

.anchors ul {
  display: flex;
  gap: 6px;
  margin: 0;
  padding: 8px var(--gutter);
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  max-width: var(--measure);
  margin-inline: auto;
}

.anchors ul::-webkit-scrollbar {
  display: none;
}

.anchors a {
  display: inline-block;
  white-space: nowrap;
  font-size: 13px;
  color: var(--fg-soft);
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  border-radius: 999px;
  padding: 3px 11px;
}

.anchors a:hover {
  color: var(--accent);
  border-color: var(--accent);
  text-decoration: none;
}

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

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

/* A grid or flex item defaults to `min-width: auto`, i.e. "never narrower than my
   content's min-content width". A card holding a `<pre>` (white-space: pre) or a
   wide table therefore refuses to shrink, the `1fr` track grows past its
   container, and the whole document ends up wider than the phone — which is what
   made the browser zoom the page out. Zeroing the automatic minimum lets the
   inner scroll containers (`.term pre`, `.table-scroll`) do their job instead. */
.cards > *,
.card > *,
.plan,
.plan .body,
ol.steps > li {
  min-width: 0;
}

.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow-sm);
}

.card h3 {
  margin: 0 0 4px;
  font-size: 15.5px;
}

.card .scope {
  font-size: 12.5px;
  color: var(--accent);
  margin: 0 0 10px;
}

.card ul {
  margin: 0;
  padding-left: 18px;
  font-size: 14.5px;
  color: var(--fg-soft);
}

.card li {
  margin: 4px 0;
}

.card li strong,
.card li b {
  color: var(--fg);
}

/* Plan cards: a whole method in one block. */
.plan {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin: 0 0 18px;
}

.plan > header {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--bg-soft), transparent);
}

.plan > header .num {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(140deg, var(--accent), var(--accent-strong));
}

.plan > header h3 {
  margin: 0;
  font-size: 17px;
}

.plan > header .badge {
  margin-left: auto;
  font-size: 12px;
  color: var(--fg-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
}

.plan .body {
  padding: 4px 16px 16px;
}

/* ------------------------------------------------------------- terminal -- */

.term {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--code-bg);
  margin: 12px 0;
}

.term > .bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-soft) 70%, transparent);
}

.term > .bar .dots {
  display: inline-flex;
  gap: 4px;
}

.term > .bar .dots i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border-strong);
  display: block;
}

.term > .bar .file {
  font-size: 12px;
  color: var(--fg-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.term > .bar .chip {
  margin-left: auto;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-faint);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 8px;
  flex: none;
}

.term pre {
  margin: 0;
  padding: 12px 14px;
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.65;
  color: var(--code-fg);
  -webkit-overflow-scrolling: touch;
}

.term pre code {
  background: none;
  padding: 0;
  font-size: inherit;
  color: inherit;
}

/* One-line command blocks keep the same furniture but no window chrome. */
pre.shell {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.65;
  color: var(--code-fg);
  margin: 12px 0;
}

pre.shell .c,
.term .c {
  color: var(--fg-faint);
}

.tok-cmd {
  color: var(--accent-strong);
  font-weight: 600;
}

/* ---------------------------------------------------------------- steps -- */

ol.steps {
  counter-reset: step;
  list-style: none;
  margin: 0;
  padding: 0;
}

ol.steps > li {
  position: relative;
  padding: 0 0 16px 40px;
}

ol.steps > li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0;
  top: 1px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 700;
  display: grid;
  place-items: center;
}

ol.steps > li > b,
ol.steps > li > strong {
  display: block;
  margin-bottom: 2px;
}

ol.steps ul {
  list-style: disc;
  margin: 8px 0 0;
  padding-left: 18px;
  color: var(--fg-soft);
  font-size: 14.5px;
}

ol.steps ul li {
  padding: 0;
  margin: 4px 0;
}

ol.steps ul li::before {
  content: none;
  counter-increment: none;
}

/* ---------------------------------------------------------------- notes -- */

.note {
  border-left: 3px solid var(--warn);
  background: var(--warn-soft);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 11px 14px;
  font-size: 14px;
  color: var(--fg);
  margin: 14px 0;
}

.note.ok {
  border-left-color: var(--ok);
  background: var(--ok-soft);
}

.note.danger {
  border-left-color: var(--danger);
  background: var(--danger-soft);
}

.note strong,
.note b {
  color: inherit;
}

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

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

/* --------------------------------------------------------------- tables -- */

.table-scroll {
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  -webkit-overflow-scrolling: touch;
}

table {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 14px;
}

th,
td {
  text-align: left;
  padding: 10px 13px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

th {
  background: var(--bg-soft);
  font-weight: 600;
  color: var(--fg-soft);
  white-space: nowrap;
}

tr:last-child td {
  border-bottom: 0;
}

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

.hero {
  padding: 34px 0 6px;
}

.hero .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 11px;
  margin: 0 0 14px;
}

.hero h1 {
  font-size: clamp(24px, 6.2vw, 36px);
  line-height: 1.26;
  margin: 0 0 12px;
  letter-spacing: -0.4px;
}

.hero p.lead {
  font-size: 16.5px;
  color: var(--fg-soft);
  margin: 0 0 18px;
  max-width: 46rem;
}

.pills {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}

.pills li {
  font-size: 12.5px;
  color: var(--fg-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 11px;
  background: var(--bg-elevated);
}

/* ----------------------------------------------------------------- list -- */

ul.plain {
  margin: 0;
  padding-left: 20px;
  color: var(--fg-soft);
  font-size: 14.5px;
}

ul.plain li {
  margin: 5px 0;
}

ul.plain strong {
  color: var(--fg);
}

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

footer {
  border-top: 1px solid var(--border);
  margin-top: 20px;
  padding: 22px 0 calc(44px + var(--safe-b));
  color: var(--fg-soft);
  font-size: 13.5px;
}

footer .row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: center;
}

footer .sep {
  color: var(--fg-faint);
}

/* ------------------------------------------------------- mobile menu ---- */

/* Narrow screens keep the chrome in a single 54px row and put both the page
   links and the section links behind one button. The arrangement this replaces
   stacked a two-row header over a sticky anchor strip: measured at 132px of
   chrome, 23% of an iPhone SE screen, with a horizontally scrolling pill row
   that hid half its items and told the reader nothing about where they were.
   The drawer is an overlay, so it costs no layout height at all.
 *
 * Order matters in this file: the base rules below `display: none` the button,
 * and every media query that changes that comes after them. Putting a media
 * query block above its base rule silently loses the override — which is
 * exactly how the first version of this shipped a permanently hidden button. */
.menu-toggle {
  display: none;
  appearance: none;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--fg-soft);
  font: inherit;
  font-size: 13px;
  padding: 4px 11px 4px 9px;
  cursor: pointer;
  white-space: nowrap;
}

.menu-toggle::before {
  content: "";
  width: 13px;
  height: 9px;
  background:
    linear-gradient(var(--fg-soft), var(--fg-soft)) 0 0 / 100% 1.5px no-repeat,
    linear-gradient(var(--fg-soft), var(--fg-soft)) 0 50% / 100% 1.5px no-repeat,
    linear-gradient(var(--fg-soft), var(--fg-soft)) 0 100% / 100% 1.5px no-repeat;
}

.menu-toggle[aria-expanded="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.menu-drawer {
  border-top: 1px solid var(--border);
  background: var(--bg);
  box-shadow: 0 18px 28px rgb(16 24 40 / 12%);
  max-height: min(76vh, 30rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.menu-drawer[hidden] {
  display: none;
}

/* Not `.wrap`: the drawer lives inside `header.top`, where `.wrap` is a flex row
   for the brand and the controls, and reusing it here laid the group headings and
   their links out side by side. */
.menu-inner {
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 12px calc(var(--gutter) + var(--safe-l)) 14px calc(var(--gutter) + var(--safe-r));
}

.menu-group {
  margin: 0 0 6px;
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

.menu-drawer ul {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
}

.menu-drawer li {
  margin: 0 0 2px;
}

.menu-drawer li a {
  display: block;
  padding: 11px 12px;
  border-radius: 10px;
  color: var(--fg);
  font-size: 15px;
  /* Comfortably past the 44px touch-target minimum with the row padding. */
  min-height: 44px;
  box-sizing: border-box;
}

.menu-drawer li a:hover {
  background: var(--bg-soft);
  text-decoration: none;
}

.menu-drawer li a[aria-current] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

/* Body scroll must not continue underneath the open drawer. */
body.menu-open {
  overflow: hidden;
}

/* Phone: 560px and below — one row, drawer instead of tabs and anchor strip. */
@media (max-width: 560px) {
  .menu-toggle {
    display: inline-flex;
  }

  /* The header must stay above its own drawer. */
  header.top {
    z-index: 40;
  }

  header.top .wrap {
    flex-wrap: nowrap;
    align-items: center;
  }

  header.top nav.pages {
    display: none;
  }

  header.top .navslot {
    margin-left: auto;
    flex-wrap: nowrap;
  }

  /* The section links live in the drawer now; the strip itself would eat 47px
     of every screen for a horizontal scroll that hides half its items. */
  .anchors {
    display: none;
  }

  section {
    scroll-margin-top: calc(var(--header-h, 54px) + 8px);
  }

}

/* Very narrow phones: the brand may wrap under the controls rather than push
   them off the row. The tabs are already gone at this point, so this only has
   to keep the language switch and the menu button reachable. */
@media (max-width: 469px) {
  header.top .wrap {
    row-gap: 0;
  }

  header.top .navslot {
    gap: 8px;
  }

  header.top .name {
    font-size: 13.5px;
  }
}

/* 561px and up: the tabs fit inline again, so the drawer is gone and the anchor
   strip becomes the section navigation — horizontal between 561 and 719px, then
   the left column from 720px up (see the next block). */
@media (min-width: 561px) {
  .menu-toggle,
  .menu-drawer {
    display: none;
  }

  body.menu-open {
    overflow: visible;
  }
}

@media (min-width: 720px) {
  :root {
    --gutter: 22px;
  }

  body {
    /* Named areas rather than a float or a flex row: the anchor column has to be
       *shorter* than the grid for `position: sticky` to have room to travel, and a
       stretch-aligned flex item would be exactly as tall as the text column. */
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr);
    grid-template-areas:
      'header header'
      'anchors main'
      'footer footer';
    align-items: start;
  }

  header.top {
    grid-area: header;
  }

  footer {
    grid-area: footer;
  }

  /* The chrome spans the page instead of sitting in a centred column: with a
     full-width text column, a centred 62rem strip above and below it looks like a
     different site bolted on. */
  header.top .wrap,
  footer .wrap {
    max-width: none;
  }

  .anchors {
    grid-area: anchors;
    position: sticky;
    /* The header is 58px here and stays put, so the column starts under it. */
    top: 0;
    width: auto;
    /* Bounded by the viewport so a long list stays reachable; the header above it
       is not part of this column. */
    max-height: calc(100vh - 70px);
    overflow-y: auto;
    margin: 0;
    background: none;
    backdrop-filter: none;
    border-bottom: 0;
    padding: 26px 4px 26px 0;
    scrollbar-width: thin;
  }

  .anchors ul {
    display: block;
    max-width: none;
    margin: 0;
    padding: 0 0 0 var(--gutter);
    overflow: visible;
  }

  .anchors li {
    margin: 0 0 5px;
  }

  .anchors a {
    display: block;
    border: 0;
    background: none;
    border-radius: 8px;
    padding: 6px 10px;
    font-size: 13.5px;
    /* Room for a long label to take two lines without the row jumping. */
    line-height: 1.35;
  }

  .anchors a:hover,
  .anchors a[aria-current="true"] {
    background: var(--accent-soft);
    color: var(--accent);
    text-decoration: none;
  }

  main {
    grid-area: main;
    /* `minmax(0, 1fr)` on the column does the shrinking; this keeps the element
       itself from reintroducing the automatic minimum inside it. */
    min-width: 0;
    /* The page uses the window: sidebar at the left edge, text running to the
       right gutter. `--measure` here is wide enough that it only bites on a very
       large monitor, which is why the column is not re-centred — `main.wrap` still
       carries `margin: 0 auto` from the base rule, so any max-width that actually
       binds would centre the text again. */
    max-width: var(--measure);
    margin: 0;
    padding-right: var(--gutter);
  }

  section {
    /* The anchor column is not sticky furniture covering the content, so only the
       header has to be cleared when jumping to a section. */
    scroll-margin-top: 14px;
  }

  section {
    /* The anchor column is not sticky furniture, so only the header has to be
       cleared when jumping to a section. */
    scroll-margin-top: calc(var(--header-h, 58px) + 14px);
  }

  header.top .wrap {
    min-height: 58px;
    gap: 12px;
  }

  header.top .name {
    font-size: 15px;
  }

  header.top nav.pages a {
    font-size: 14px;
    padding: 5px 12px;
  }

  section {
    padding: 40px 0;
  }

  section > h2 {
    font-size: 22px;
  }

  .hero {
    padding: 56px 0 10px;
  }

  .hero p.lead {
    font-size: 18px;
  }

  .cards {
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 14px;
  }

  .card {
    padding: 18px;
  }

  .plan > header {
    padding: 16px 20px;
  }

  .plan .body {
    padding: 4px 20px 20px;
  }
}

/* Desktop uses the window rather than re-centring a narrow column: the sidebar is
   fixed on the left, the right gap is just the gutter, and the text stops at this
   measure. Measured at 1440px before this cap: the longest prose lines ran 69-79
   characters, past the comfortable 45-75 band; 74rem brings them back to ~62. */
@media (min-width: 1100px) {
  :root {
    --measure: 86rem;
  }
}

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