/* Mushroom v2, one stylesheet for all ten pages.

   The live site splits this across tokens.css + components.css + legal.css plus a
   per-page inline <style> block, which is why the same .btn is defined in one place
   and used in ten. v2 keeps tokens.css separate (so the "never hardcode a hex" rule
   stays greppable) and puts everything else here. Ten pages, one file, one cache
   entry.

   Needs tokens.css loaded first. Never hardcode a hex value in this file. */

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.65 -apple-system, "SF Pro Text", system-ui, "Segoe UI", sans-serif;
  letter-spacing: -.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4 { line-height: 1.12; letter-spacing: -.025em; margin: 0; text-wrap: balance; font-weight: 700; }
h1 { font-size: clamp(2.1rem, 5.2vw, 3.35rem); font-weight: 800; }
h2 { font-size: clamp(1.6rem, 4vw, 2.25rem); font-weight: 800; }
h3 { font-size: 1.1rem; }
p { text-wrap: pretty; }
a { color: inherit; }
img, video { max-width: 100%; }
[id] { scroll-margin-top: 76px; }

:where(a, button, input, select, textarea, summary):focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 3px;
  border-radius: 6px;
}

.wrap { width: min(100% - 2.5rem, 62rem); margin-inline: auto; }
.wrap--narrow { width: min(100% - 2.5rem, 44rem); margin-inline: auto; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Tighter than the live site's clamp(3rem, 8vw, 5.5rem). Density is most of what
   reads as "professional" rather than "landing page". */
section { padding: clamp(2.5rem, 6vw, 4.5rem) 0; }
.band { background: var(--bg2); border-block: 1px solid color-mix(in srgb, var(--line2) 45%, transparent); }
.band--deep { background: var(--bg3); }

/* ---------- section vocabulary ---------- */
.eyebrow {
  display: inline-flex; align-items: center; gap: .55rem;
  text-transform: uppercase; letter-spacing: .12em; font-size: .76rem; font-weight: 700;
  color: var(--red); margin: 0 0 .75rem;
}
.eyebrow::before { content: "+"; font-size: 1.15em; font-weight: 700; line-height: 1; opacity: .85; }
.lede { color: var(--ink2); max-width: 40rem; margin: .85rem 0 0; font-size: 1.05rem; }
.center { text-align: center; }
.center .lede, .center .eyebrow { margin-inline: auto; }
.center .lede { max-width: 38rem; }
.more { margin: 2rem 0 0; font-size: .95rem; }
.more a { color: var(--red); font-weight: 600; text-decoration: none; }
.more a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- nav ---------- */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid color-mix(in srgb, var(--line2) 45%, transparent);
}
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 56px; gap: 1rem; }
.brand {
  display: inline-flex; align-items: center; gap: .55rem;
  font-weight: 700; font-size: 1.05rem; letter-spacing: -.02em; text-decoration: none;
}
.brand img { border-radius: 8px; box-shadow: var(--shadow-sm); }
.nav-links { display: flex; align-items: center; gap: 1.4rem; }
.nav-links a { text-decoration: none; color: var(--ink2); font-size: .93rem; font-weight: 500; transition: color .12s; }
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--ink); }
.nav-links a.btn { color: var(--red-ink); }
@media (max-width: 46rem) { .nav-links a:not(.btn) { display: none; } }

/* ---------- announcement bar ---------- */
.announce {
  text-align: center; font-size: .88rem; font-weight: 500; padding: .55rem 1.25rem;
  color: var(--ink); background: color-mix(in srgb, var(--red) 8%, var(--bg));
  border-bottom: 1px solid color-mix(in srgb, var(--red) 15%, var(--line));
}
.announce b { color: var(--red); font-weight: 700; }
.announce a { color: var(--red); font-weight: 600; text-decoration: none; }
.announce a:hover { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  background: linear-gradient(180deg, color-mix(in srgb, var(--red) 88%, #fff), var(--red));
  color: var(--red-ink);
  border: 0; border-radius: var(--radius-pill);
  padding: .8rem 1.6rem;
  font: inherit; font-weight: 600; font-size: 1rem; line-height: 1.15; letter-spacing: -.01em;
  cursor: pointer; text-decoration: none;
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 30%, transparent),
              0 1px 2px var(--shadow),
              0 8px 20px color-mix(in srgb, var(--red) 22%, transparent);
  transition: transform .14s ease, box-shadow .14s ease, filter .14s ease;
}
.btn:hover {
  transform: translateY(-1px); filter: brightness(1.04);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 30%, transparent),
              0 2px 5px var(--shadow),
              0 12px 28px color-mix(in srgb, var(--red) 30%, transparent);
}
.btn:active { transform: translateY(0); filter: brightness(.97); }
.btn--ghost {
  background: color-mix(in srgb, var(--card) 70%, transparent); color: var(--ink);
  border: 1px solid var(--line2);
  box-shadow: var(--shadow-sm); font-weight: 500;
}
.btn--ghost:hover { transform: translateY(-1px); filter: none; border-color: var(--ink2); background: var(--card); box-shadow: var(--shadow-sm); }
.btn.btn--sm {
  padding: .44rem 1.05rem; font-size: .88rem; font-weight: 600;
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 22%, transparent), 0 1px 2px var(--shadow);
}
.btn.btn--sm:hover { box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 22%, transparent), 0 3px 8px color-mix(in srgb, var(--red) 30%, transparent); }
.cta-row { display: flex; flex-wrap: wrap; gap: .85rem; align-items: center; margin-top: 1.9rem; }
.center .cta-row { justify-content: center; }

/* ---------- theme toggle ----------
   One icon, not a sun that swaps to a moon. Under light-dark() there is no selector for
   "currently dark": prefers-color-scheme still reports the SYSTEM, so a swap would show
   the wrong glyph to exactly the readers who used the button. The half-filled circle is
   the standard appearance mark and is true in both directions, which is also one SVG and
   no state to keep in sync. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; padding: 0; margin-right: -.2rem;
  color: var(--ink2); background: none;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  cursor: pointer; transition: color .16s ease, background-color .16s ease;
}
.theme-toggle:hover { color: var(--ink); background: var(--bg2); }
.theme-toggle svg { display: block; width: 18px; height: 18px; }

/* ---------- hero ---------- */
header.hero { padding: clamp(3rem, 7vw, 5rem) 0 clamp(2.5rem, 5vw, 3.5rem); position: relative; overflow: hidden; }
/* The one tiled background on the site. DESIGN.md §8 records it as the standing
   exception: token-derived, faded out by mid-hero, reads as paper grain behind pixel
   art. Do not add a second, and do not extend this one past the hero. */
header.hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(color-mix(in srgb, var(--ink) 10%, transparent) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(75% 55% at 50% 0%, #000, transparent 78%);
  mask-image: radial-gradient(75% 55% at 50% 0%, #000, transparent 78%);
  opacity: .45;
}
header.hero > * { position: relative; z-index: 1; }
.hero .sub {
  font-size: clamp(1.05rem, 2.2vw, 1.22rem); color: var(--ink2);
  max-width: 36rem; margin: 1.1rem auto 0;
}
.hero-for {
  margin: 1.1rem auto 0; max-width: 34rem;
  font-size: .92rem; color: var(--ink2);
}
.hero-for b { color: var(--ink); font-weight: 600; }
.hero-note { margin: 1rem 0 0; font-size: .85rem; color: var(--ink2); }

.ledge { display: flex; flex-direction: column; align-items: center; margin-bottom: 1.6rem; }
.ledge-line { width: min(15rem, 60%); height: 1px; background: linear-gradient(90deg, transparent, var(--line2), transparent); }

.trust {
  display: flex; flex-wrap: wrap; gap: .5rem 1.1rem; justify-content: center;
  margin-top: 1.6rem; color: var(--ink2); font-size: .85rem; font-weight: 500;
}
.trust span { display: inline-flex; align-items: center; gap: .4rem; }

/* ---------- macOS window frame ----------
   The component that does most of the "professional Mac app" work. Wrap any
   screenshot in it. Falls back to an empty frame with a caption when the shot does
   not exist yet, which is currently every one of them (see v2/README.md). */
.macwin {
  border: 1px solid var(--line2);
  border-radius: var(--radius-win);
  overflow: hidden;
  background: var(--card);
  box-shadow: var(--shadow-lg);
  margin: 2.2rem auto 0;
  max-width: 52rem;
}
.macwin-bar {
  display: flex; align-items: center; gap: .45rem;
  padding: .55rem .7rem;
  background: color-mix(in srgb, var(--ink) 5%, var(--card));
  border-bottom: 1px solid var(--line);
}
.macwin-bar i {
  width: 11px; height: 11px; border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 20%, transparent);
  flex: none;
}
.macwin-title {
  margin-inline: auto; padding-right: 2.4rem;
  font-size: .78rem; font-weight: 500; color: var(--ink2);
}
.macwin img, .macwin video { display: block; width: 100%; height: auto; }
/* ---------- .shot: a screenshot that already has its own macOS chrome ----------
   Every real capture in assets/ contains traffic lights, a menu bar or the dock, so
   wrapping one in .macwin would draw a second titlebar over the app's own. .shot is
   just the frame: rounded, hairline, lifted. Use .macwin only for chrome-less content
   like the hero video. */
.shot {
  display: block; margin: 2.2rem auto 0;
  max-width: 46rem; width: 100%;
  border: 1px solid var(--line2); border-radius: var(--radius-win);
  box-shadow: var(--shadow-lg);
  overflow: hidden; background: var(--card);
}
.shot img { display: block; width: 100%; height: auto; }
/* Portrait captures need capping, and they do not all need the same cap: the chat
   panels are 700x1210 (aspect .58) and the app windows are around 870x1040 (aspect
   .84), so one max-width either towers or shrinks to nothing. Two steps covers both. */
.shot--tall { max-width: 21rem; }   /* chat panels */
.shot--mid  { max-width: 28rem; }   /* app windows: reminders, settings */
.shot--pair { display: grid; gap: 1.2rem; grid-template-columns: 1fr; margin-top: 2.2rem; }
@media (min-width: 46rem) {
  .shot--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; justify-items: center; }
  .shot--pair .shot { margin-top: 0; }
}
.shot-cap { margin: .7rem 0 0; font-size: .85rem; color: var(--ink2); text-align: center; }

/* placeholder body, used until real screenshots exist */
.macwin-todo {
  display: grid; place-items: center; gap: .4rem;
  min-height: 17rem; padding: 2rem;
  color: var(--ink2); font-size: .9rem; text-align: center;
  background:
    radial-gradient(60% 60% at 50% 40%, var(--tint), transparent 70%),
    var(--card);
}
.macwin-todo b { color: var(--ink); font-size: 1rem; }

/* ---------- cards ---------- */
/* text-align:left so a .grid inside a .center section keeps its cards left-ranged.
   .nudges sets its own centering and is unaffected. */
.grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); grid-auto-rows: 1fr; margin-top: 2.2rem; text-align: left; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(21rem, 100%), 1fr)); }
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-card); padding: 1.5rem;
  box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: color-mix(in srgb, var(--red) 22%, var(--line)); }
.card h3 { margin-bottom: .35rem; }
.card p { margin: 0; color: var(--ink2); font-size: .95rem; }
.card--flat:hover { transform: none; box-shadow: var(--shadow-sm); border-color: var(--line); }

/* There was a .ico here: an emoji in a tinted rounded square, used fourteen times.
   Emoji share no stroke weight and no optical size, they are drawn by the OS rather
   than by us, and they were the loudest thing on a site whose whole identity is
   hand-drawn pixel art. The labels carry the meaning on their own. */

/* ---------- plain list, no card ----------
   Cards everywhere flattens the hierarchy: when every block is raised, none is.
   Used where the content is a list to read, not a set of tiles to scan. */
.stack { display: grid; margin-top: 2.2rem; text-align: left; }
@media (min-width: 52rem) {
  .stack--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 3rem; }
  .stack--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 2.5rem; }
}
/* top hairline only, never bottom: the same rule then reads correctly at one, two
   and three columns without a per-column :last-child exception. */
.stack > div { padding: 1.15rem 0; border-top: 1px solid var(--line2); }
.stack h3 { margin: 0 0 .3rem; font-size: 1rem; }
.stack p { margin: 0; color: var(--ink2); font-size: .95rem; }
.stack .more { margin-top: .55rem; font-size: .9rem; }
.stack--num > div { display: grid; grid-template-columns: 1.5rem minmax(0, 1fr); column-gap: .9rem; }
.stack--num .n { grid-row: span 2; font-weight: 700; color: var(--red); line-height: 1.62; }

/* six wellness nudges, no boxes, sized to their own text */
.nudges { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.7rem 1.2rem; margin-top: 2.2rem; text-align: center; }
@media (min-width: 52rem) { .nudges { grid-template-columns: repeat(3, 1fr); } }
.nudge h3 { font-size: 1rem; margin-bottom: .3rem; }
.nudge p { margin: 0; color: var(--ink2); font-size: .88rem; }

/* ---------- split sections ----------
   Every band on the homepage used to be the same shape: eyebrow, centred heading,
   centred lede, grid of cards. Two of them now put the copy on one side and a
   portrait capture on the other, which is also the only way those tall screenshots
   stop floating small in a lot of empty page. */
.split { display: grid; gap: 2rem 3rem; align-items: center; margin-top: 2.4rem; }
@media (min-width: 58rem) {
  .split { grid-template-columns: minmax(0, 1fr) 20rem; }
  .split--rev { grid-template-columns: 20rem minmax(0, 1fr); }  /* media first in the DOM */
}
.split .shot { margin-top: 0; max-width: 100%; }
.split .nudges, .split .stack { margin-top: 0; }
/* the left column is narrower than the section, so three across would not fit */
.split .nudges { grid-template-columns: repeat(2, 1fr); text-align: left; }

/* compact two-column list, used on /features */
.grid--compact { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 0 1.8rem; margin-top: 1.3rem; }
/* The 1.5rem gutter held an emoji, one of forty seven down this page, drawn by the
   reader's OS in whatever size and weight it felt like. Removed with the rest. */
.compact { padding: .8rem 0; border-top: 1px solid var(--line); }
.compact h3 { font-size: .97rem; margin: 0 0 .1rem; }
.compact p { margin: 0; color: var(--ink2); font-size: .88rem; }

/* stat row, used by Friends / Spore Storage on /features */
.specs { display: flex; flex-wrap: wrap; gap: .8rem; justify-content: center; margin-top: 2rem; }
.spec {
  display: flex; flex-direction: column; align-items: center; gap: .15rem;
  min-width: 7.5rem; padding: 1rem 1.2rem;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: var(--shadow-sm);
}
.spec b { font-size: 1.4rem; font-weight: 800; line-height: 1.1; color: var(--red); font-variant-numeric: tabular-nums; }
.spec span { font-size: .82rem; color: var(--ink2); }

.reqs { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; margin-top: 1.5rem; }
.req { font-size: .85rem; color: var(--ink2); border: 1px solid var(--line2); border-radius: var(--radius-pill); padding: .35rem .9rem; }

/* ---------- the facts block ----------
   A <dl> of one unambiguous sentence per question. Serves humans, and is the single
   structure answer engines quote most reliably. See v2/README.md §LLMO. */
.facts {
  margin: 2rem 0 0; display: grid; gap: 0;
  border: 1px solid var(--line); border-radius: var(--radius-card);
  background: var(--card); box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.facts > div { display: grid; gap: .15rem .9rem; padding: .95rem 1.3rem; border-top: 1px solid var(--line); }
.facts > div:first-child { border-top: 0; }
.facts dt { font-weight: 600; font-size: .93rem; }
.facts dd { margin: 0; color: var(--ink2); font-size: .93rem; }
@media (min-width: 44rem) {
  .facts > div { grid-template-columns: 13rem 1fr; align-items: baseline; }
}

/* ---------- comparison table ---------- */
.compare-scroll { overflow-x: auto; margin-top: 2rem; -webkit-overflow-scrolling: touch; }
.compare {
  width: 100%; min-width: 34rem; border-collapse: collapse;
  font-size: .93rem; background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius-card);
  overflow: hidden;
}
.compare th, .compare td { padding: .8rem 1rem; text-align: left; border-top: 1px solid var(--line); vertical-align: top; }
.compare thead th { border-top: 0; background: var(--tint); font-weight: 700; font-size: .88rem; }
.compare tbody th { font-weight: 600; color: var(--ink); width: 14rem; }
.compare td { color: var(--ink2); }
.compare .yes { color: var(--red); font-weight: 600; }

/* ---------- licence picker ---------- */
.picker {
  margin-top: 2.2rem;
  display: grid; gap: 1.2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 56rem) { .picker { grid-template-columns: 1fr 1fr; align-items: start; gap: 1.8rem; } }
.picker fieldset { border: 0; padding: 0; margin: 0 0 1.4rem; }
.picker legend { padding: 0; font-weight: 600; font-size: 1rem; margin-bottom: .6rem; }
.picker legend small { display: block; font-weight: 400; font-size: .85rem; color: var(--ink2); margin-top: .15rem; }
.opts { display: flex; flex-wrap: wrap; gap: .5rem; }
.opt {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .5rem 1rem; cursor: pointer;
  background: var(--card); border: 1px solid var(--line2); border-radius: var(--radius-pill);
  font-size: .92rem; color: var(--ink2);
  transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.opt:hover { border-color: var(--ink2); color: var(--ink); }
.opt input { margin: 0; accent-color: var(--red); }
.opt:has(input:checked) { border-color: var(--red); color: var(--ink); background: var(--tint); font-weight: 600; }
.opt:has(input:focus-visible) { outline: 3px solid var(--ring); outline-offset: 3px; }

.result {
  position: sticky; top: 76px;
  background: var(--card); border: 1px solid var(--line2);
  border-radius: var(--radius-card); padding: 1.6rem;
  box-shadow: var(--shadow-md);
}
.result h3 { font-size: 1.3rem; }
.result .price-line { font-size: 2.1rem; font-weight: 800; letter-spacing: -.03em; margin: .5rem 0 .1rem; }
.result .price-note { margin: 0 0 1.1rem; font-size: .87rem; color: var(--ink2); }
.result .btn { width: 100%; }
.result ul { margin: 0 0 1.2rem; padding: 0; list-style: none; display: grid; gap: .45rem; font-size: .92rem; }
.result li { display: grid; grid-template-columns: 1.15rem 1fr; gap: .55rem; color: var(--ink2); }
.result li::before { content: "+"; color: var(--red); font-weight: 700; }
.result li.no::before { content: "-"; color: var(--ink2); }
.result .why { margin: 1rem 0 0; font-size: .85rem; color: var(--ink2); }
/* The "before you commit" box. This is the part that stops someone buying twice, so it
   sits above the button rather than under it. */
.result .heads-up {
  margin: 0 0 1.1rem; padding: .8rem 1rem;
  background: var(--tint); border: 1px solid color-mix(in srgb, var(--red) 20%, var(--line));
  border-radius: 12px;
}
.result .heads-up b { display: block; font-size: .85rem; margin-bottom: .3rem; }
.result .heads-up ul { margin: 0; gap: .35rem; }
.result .heads-up li { grid-template-columns: 1.15rem 1fr; font-size: .87rem; color: var(--ink); }
.result .heads-up li::before { content: "!"; color: var(--red); font-weight: 700; }
.result .runner-up { margin: 1rem 0 0; font-size: .85rem; color: var(--ink2); }
.result .runner-up a { color: var(--red); font-weight: 600; }
@media (max-width: 56rem) { .result { position: static; } }

/* ---------- pricing card ---------- */
.pay {
  position: relative; max-width: 30rem; margin: 2.4rem auto 0;
  background: linear-gradient(180deg, color-mix(in srgb, var(--spot) 6%, var(--card)), var(--card));
  border: 1px solid var(--line2);
  border-radius: 22px; padding: clamp(1.8rem, 4vw, 2.4rem);
  box-shadow: var(--shadow-lg);
  text-align: center;
}
.pay::after {
  content: ""; position: absolute; top: 0; left: 15%; right: 15%; height: 3px;
  background: linear-gradient(90deg, transparent, var(--red), transparent);
}
.price-big { font-size: 3rem; font-weight: 800; letter-spacing: -.03em; margin-top: .2rem; }
.excl { color: var(--ink2); font-size: .9rem; margin: .2rem 0 1.3rem; }
.pay .btn { width: 100%; }
.meta { margin: 1rem 0 0; font-size: .85rem; color: var(--ink2); }

/* ---------- FAQ / prose (help, legal, faq) ---------- */
.prose { max-width: 44rem; }
.prose h2 { margin: 2.6rem 0 .8rem; font-size: clamp(1.35rem, 3vw, 1.7rem); }
.prose h3 { margin: 1.8rem 0 .5rem; font-size: 1.08rem; }
.prose p, .prose li { color: var(--ink2); }
.prose p { margin: .7rem 0; }
.prose ul, .prose ol { margin: .7rem 0; padding-left: 1.3rem; }
.prose li { margin: .3rem 0; }
.prose a { color: var(--red); text-decoration: none; }
.prose a:hover { text-decoration: underline; text-underline-offset: 3px; }
/* .prose a is (0,1,1) and .btn is (0,1,0), so without this a button inside prose is
   painted red on red and the label vanishes. Same reason .nav-links a.btn exists. */
.prose a.btn { color: var(--red-ink); }
.prose a.btn:hover { text-decoration: none; }
.prose a.btn--ghost { color: var(--ink); }
.prose code, .prose pre {
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .88em;
  background: var(--bg2); border: 1px solid var(--line); border-radius: 6px;
}
.prose code { padding: .1rem .35rem; }
.prose pre { padding: .9rem 1.1rem; overflow-x: auto; border-radius: 10px; }
.prose pre code { background: none; border: 0; padding: 0; }
.prose blockquote {
  margin: 1.2rem 0; padding: .8rem 1.2rem;
  border-left: 3px solid var(--red); background: var(--tint);
  border-radius: 0 10px 10px 0; color: var(--ink);
}
.page-head { padding: clamp(2.5rem, 6vw, 4rem) 0 0; }
.page-head h1 { font-size: clamp(1.9rem, 4.5vw, 2.7rem); }
.crumb { font-size: .87rem; color: var(--ink2); margin: 0 0 .8rem; }
.crumb a { color: var(--ink2); text-decoration: none; }
.crumb a:hover { color: var(--ink); text-decoration: underline; }
.toc { display: flex; flex-wrap: wrap; gap: .5rem; margin: 1.6rem 0 0; }
.toc a {
  font-size: .87rem; text-decoration: none; color: var(--ink2);
  border: 1px solid var(--line2); border-radius: var(--radius-pill); padding: .32rem .85rem;
}
.toc a:hover { color: var(--ink); border-color: var(--ink2); }

/* ---------- footer ---------- */
footer { border-top: 1px solid var(--line); padding: 2.4rem 0 3rem; color: var(--ink2); font-size: .9rem; }
footer a { color: var(--red); text-decoration: none; }
footer a:hover { text-decoration: underline; }
footer a.btn { color: var(--red-ink); }
.foot-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.foot-tagline { max-width: 30rem; margin: 1rem 0 1.5rem; font-size: .92rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: .5rem 1.2rem; }

/* ---------- the sprite ----------
   48x48 frames, nearest neighbour, integer scale only. DESIGN.md §4. */
.shroom {
  width: 96px; height: 96px;
  background-image: url("assets/cute%20mushroom%20walk.png");
  background-size: 384px 96px;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  animation: walk .6s steps(4) infinite;
}
@keyframes walk { to { background-position: -384px 0; } }
.shroom--idle {
  background-image: url("assets/cute%20mushroom%20idle.png");
  background-size: 864px 96px;
  animation: idle 1.4s steps(9) infinite;
}
@keyframes idle { to { background-position: -864px 0; } }
/* A section divider the mushroom walks along, back and forth. The walk sheet is
   already loaded by the hero, so this costs one hairline and one keyframe set, and
   it is the only thing on the page that no other site can copy. `left` rather than
   translateX because scaleX is doing the turn and the two would fight over the same
   property. One element crawling a 26s linear path is not a paint problem. */
.walkline { position: relative; height: 48px; margin-top: 3rem; }
.walkline::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--line2), transparent);
}
/* walk-sm, not walk: this shorthand sets animation-name, so it would otherwise put the
   96px keyframe back on a 48px sprite. */
.walkline .shroom { position: absolute; bottom: 1px; left: 0; animation: walk-sm .6s steps(4) infinite, stroll 26s linear infinite; }
@keyframes stroll {
  0%   { left: 0;                   transform: scaleX(1); }
  48%  { left: calc(100% - 48px);   transform: scaleX(1); }
  50%  { left: calc(100% - 48px);   transform: scaleX(-1); }
  98%  { left: 0;                   transform: scaleX(-1); }
  100% { left: 0;                   transform: scaleX(1); }
}

/* A keyframe travels the FULL rendered sheet width, so every background-size needs its
   own. Reuse one across two sizes and the tail frames land past the sheet, which with
   no-repeat paints nothing and the sprite blinks rather than walks. */
.shroom--sm { width: 48px; height: 48px; background-size: 192px 48px; animation-name: walk-sm; }
@keyframes walk-sm { to { background-position: -192px 0; } }
.shroom--sm.shroom--idle { background-size: 432px 48px; }
@keyframes idle-sm { to { background-position: -432px 0; } }
.shroom--sm.shroom--idle { animation-name: idle-sm; }

/* ---------- skins strip ----------
   Ten idle sheets, same 432x48 geometry, so the row never reflows by colour. Black and
   white are greyscale rather than hue rotations, and both keep the sprite's white outer
   outline, which is what stops either of them dissolving into the band behind it. */
/* A wrapping flex row fits as many as the width allows, which for ten put nine on one
   line and left the tenth alone underneath. Only 2, 5 and 10 divide ten evenly, so they
   are the only column counts with no orphan on the last row, and ten across needs a
   1,000px band. Hence a grid that steps 2 to 5, skipping the 3 and 4 a flex row picks. */
.skins {
  display: grid; grid-template-columns: repeat(2, 96px);
  gap: .9rem; justify-content: center; margin-top: 2rem;
}
/* 5 x 96px + 4 x .9rem = 537.6px of content, and .wrap gives the viewport less 2.5rem. */
@media (min-width: 40rem) { .skins { grid-template-columns: repeat(5, 96px); } }
.skin {
  width: 96px; height: 96px;
  background-size: 864px 96px; background-repeat: no-repeat;
  image-rendering: pixelated;
  animation: idle 1.4s steps(9) infinite;
}
.skin-red    { background-image: url("assets/skins/idle-red.png"); }
.skin-orange { background-image: url("assets/skins/idle-orange.png"); animation-delay: -.15s; }
.skin-yellow { background-image: url("assets/skins/idle-yellow.png"); animation-delay: -.3s; }
.skin-green  { background-image: url("assets/skins/idle-green.png"); animation-delay: -.45s; }
.skin-teal   { background-image: url("assets/skins/idle-teal.png"); animation-delay: -.6s; }
.skin-blue   { background-image: url("assets/skins/idle-blue.png"); animation-delay: -.75s; }
.skin-purple { background-image: url("assets/skins/idle-purple.png"); animation-delay: -.9s; }
.skin-pink   { background-image: url("assets/skins/idle-pink.png"); animation-delay: -1.05s; }
.skin-black  { background-image: url("assets/skins/idle-black.png"); animation-delay: -1.2s; }
.skin-white  { background-image: url("assets/skins/idle-white.png"); animation-delay: -1.35s; }

/* ---------- scroll reveal. Only hides once JS arms it, so no-JS shows everything. */
.js .rise { opacity: 0; transform: translateY(16px); transition: opacity .6s, transform .6s; }
.js .rise.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .rise, .rise { opacity: 1; transform: none; }
  .shroom { background-position: 0 0; }
}
