/*
 * rowbeatapp.com: the "Liner Notes" design language, ported to the web.
 *
 * The tokens below are transcribed from the app rather than reinvented:
 * artifacts/rowbeat/constants/colors.ts for every color, and
 * artifacts/rowbeat/constants/design.ts for the type scale, tracking, radii
 * and spacing. If a value changes there, change it here too. These are the
 * same brand, and a site that drifts from the app is worse than no site.
 *
 * October 2026: the app moved from "Pace" (navy and ivory, Barlow Condensed
 * and Inter) to "Liner Notes" (slate and paper, three faces with one job
 * each), and this file moved with it; see .agents/memory/liner-notes-redesign.md.
 * The faces are the app's: Bricolage Grotesque ExtraBold for what is read at
 * a glance (headlines, numerals, the wordmark), upright and in sentence case;
 * Instrument Sans for sentences, chips and navigation; DM Mono for the small
 * capitals that name things (section labels, the caps under a numeral, the
 * privacy page's date line).
 *
 * Two rules carried over from the app, and both are easy to break by accident:
 *
 * - Amber means "act or chosen", never "healthy". Green (--rb-success) is for
 *   confirmed states.
 * - No photography. The app puts imagery on the screens a rower reads
 *   standing still, never over live metrics. This site is all reading, so it
 *   takes the other half of that rule: every panel sits on the flat page, and
 *   the hero's picture is an album the app would draw. The only photographs
 *   are the App Store's screenshots, which are the app itself.
 *
 * Two palettes, like the app: dark is the default and the original, and the
 * `prefers-color-scheme: light` block after the token list is the app's light
 * palette, transcribed from the same colors.ts. The app lets the rower choose
 * and deliberately does not follow the phone's appearance; the site has no
 * settings and no JavaScript, so it follows the system instead (decided
 * October 9, 2026). The rule light mode is built on is the app's: amber is a
 * fill and never ink on a light page, which is why the amber is split into
 * three tokens below.
 */

/*
 * The three typefaces, served from this folder rather than from Google Fonts.
 *
 * The privacy page says this site does no tracking. A stylesheet fetched from
 * fonts.googleapis.com sent every visitor's address to Google on every page
 * view, which made that sentence untrue of the site itself. The files are the
 * app's own TTFs (the @expo-google-fonts packages the app loads in
 * app/_layout.tsx), subset to Latin and converted to woff2 with fontTools in
 * October 2026, so the site sets exactly the cuts the app sets: Bricolage
 * Grotesque 800, Instrument Sans 400, 500 and 600, DM Mono 500. All three
 * faces are under the SIL Open Font License, which permits exactly this.
 *
 * A side benefit the README used to work around: headless screenshots render
 * the real faces without a network.
 */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("fonts/bricolage-grotesque-800.woff2") format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/instrument-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/instrument-sans-500.woff2") format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/instrument-sans-600.woff2") format("woff2");
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/dm-mono-500.woff2") format("woff2");
}

:root {
  /* Surfaces. Slate, the dark palette's page since October 2026. */
  --rb-bg: #1a2027;
  --rb-card: #242c34;
  --rb-border: #36414b;
  /* An unselected control needs a lighter edge than a divider does. */
  --rb-outline: #66737f;

  /* Text. Paper (the light palette's page) as this one's ink, 14.18:1. */
  --rb-fg: #f2eee6;
  --rb-muted: #9da9b3;
  --rb-decorative: #56616b;

  /* Accent. Action and selection only. Ink on amber is 9.09:1 in both palettes. */
  --rb-amber: #f5a623;
  --rb-on-amber: #141414;
  --rb-success: #4ade80;

  /*
   * The amber split three ways, as colors.ts splits it: --rb-amber is the
   * *fill* (a button, the skip link, the callout's rule), --rb-accent-ink is
   * the amber where it is small text or a glyph (links, section labels, the
   * current nav item, the step numbers, focus rings), and --rb-metric-ink is
   * the amber where it is a large numeral (the metric tiles, the tagline's
   * promise line). On slate all three are the same amber (8.10:1), so this
   * changes nothing here. They are separate because amber cannot be ink on a
   * light page (1.75:1 on paper, at any size), and the light block below gives
   * the two ink tokens the app's own answers: deep amber for small ink, ink
   * for numerals.
   */
  --rb-accent-ink: #f5a623;
  --rb-accent-ink-hover: #ffc25c;
  --rb-metric-ink: #f5a623;
  --rb-nav-hover-bg: var(--rb-card);

  /*
   * The opposite palette, for the one band on Home that runs in the other
   * mode (round ten's "One stroke, one bar"): paper with ink when the page is
   * slate, slate with paper when the page is paper. The same four values from
   * colors.ts, the other way up.
   */
  --rb-op-bg: #f2eee6;
  --rb-op-fg: #141414;
  --rb-op-card: #fbf8f2;
  --rb-op-muted: #6b655c;
  --rb-op-border: #d8d1c4;

  /* Shape */
  --rb-radius-card: 16px;
  --rb-radius-control: 12px;
  --rb-radius-pill: 999px;

  /*
   * Type: one face per job, as `typefaces` in design.ts has it. The fallbacks
   * are upright sans faces, because Bricolage is upright; the Arial Narrow
   * fallback that stood in for Barlow Condensed would now be the wrong shape.
   */
  --rb-headline: "Bricolage Grotesque", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --rb-body: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --rb-label: "DM Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --rb-gutter: 20px;
  --rb-measure: 720px;

  color-scheme: dark;
}

/*
 * The light palette, for a visitor whose system is set to light. Every value
 * is the `light` palette in artifacts/rowbeat/constants/colors.ts, and the
 * rule is the app's: in light mode, amber is a fill and never ink. Amber on
 * paper is 1.75:1 and cannot be rescued at any size, so the two ink tokens
 * take the app's answers (deep amber #8a4b00, 5.88:1, for small text and
 * glyphs; ink for the big numerals) and the buttons, the callout's rule and
 * the hero wash keep the true amber. See .agents/memory/light-mode-palette.md.
 */
@media (prefers-color-scheme: light) {
  :root {
    --rb-bg: #f2eee6;
    --rb-card: #fbf8f2;
    --rb-border: #d8d1c4;
    --rb-outline: #7f796d;

    --rb-fg: #141414;
    --rb-muted: #6b655c;
    --rb-decorative: #a39c90;

    --rb-success: #137036;

    --rb-accent-ink: #8a4b00;
    --rb-accent-ink-hover: #6e3b00;
    --rb-metric-ink: #141414;
    /* The card is lighter than the page here, which would not read as a
       hover on paper, so the hover darkens instead. */
    --rb-nav-hover-bg: #e8e3d9;

    --rb-op-bg: #1a2027;
    --rb-op-fg: #f2eee6;
    --rb-op-card: #242c34;
    --rb-op-muted: #9da9b3;
    --rb-op-border: #36414b;

    color-scheme: light;
  }
}

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

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

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

body {
  margin: 0;
  background: var(--rb-bg);
  color: var(--rb-fg);
  font-family: var(--rb-body);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
}

/* ── Headline face ──────────────────────────────────────────────────────────
 * Bricolage Grotesque ExtraBold, exactly as the app sets it: heavy, upright,
 * sentence case, pulled in. The tracking is `tracking.display` (-0.04em) from
 * design.ts, and the line height is `displayLineHeight()`'s 1.0: Bricolage's
 * lowercase ascenders reach 0.721em and its descent is 0.27em, so a tighter
 * line clips the top of the first line on iOS. A browser overflows rather
 * than clips, so the same 1.0 here is for the look, not for safety.
 */
.rb-display {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-style: normal;
  letter-spacing: -0.04em;
  line-height: 1;
  margin: 0;
}

/* Section labels: small, letterspaced, upper case. The app's SectionLabel:
   DM Mono 500 at `type.section` (11pt) with `tracking.label` (0.08em). 12px
   here rather than 11, the smallest a label reads on a web page. */
.rb-section-label {
  font-family: var(--rb-label);
  font-weight: 500;
  font-style: normal;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  color: var(--rb-accent-ink);
  margin: 0 0 0.75rem;
}

a {
  color: var(--rb-accent-ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--rb-accent-ink-hover);
}

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

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

.rb-shell {
  max-width: var(--rb-measure);
  margin: 0 auto;
  padding-inline: var(--rb-gutter);
}

/* Home runs wider than the reading pages, as round ten drew it (1120px): the
   hero needs room for the headline beside the album, and the three phones
   need a row. The letter keeps its own 60ch measure inside that. */
.rb-home .rb-shell {
  max-width: 1120px;
}

/* ── Skip link ─────────────────────────────────────────────────────────── */
.rb-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--rb-amber);
  color: var(--rb-on-amber);
  padding: 10px 16px;
  border-radius: 0 0 var(--rb-radius-control) 0;
  font-weight: 600;
  z-index: 10;
}

.rb-skip:focus {
  left: 0;
}

/* ── Masthead ──────────────────────────────────────────────────────────────
 * The logo: "Wake", the four ascending amber bars standing on a water line
 * over a banded reflection, beside the lowercase wordmark. The bars' path is
 * copied verbatim from components/BrandLogo.tsx (one pitch, one slant,
 * heights 10/19/26/16, a rhythm that peaks on the third bar rather than a
 * ramp); the water and the reflection are the numbers in
 * scripts/wake-geometry.json, which wakeMark.test.ts holds to
 * src/utils/wakeMark.ts. Do not redraw any of it by hand; it is a contract
 * shared with scripts/generate-icon.py.
 */
.rb-masthead {
  /* Round ten rules the masthead off in ink, not a hairline. */
  border-bottom: 1.5px solid var(--rb-fg);
  background: var(--rb-bg);
}

/* On a phone the logo and the amber pill share the top row and the links sit
   under them; from tablet width it is one row, logo left, links and pill
   right, as round ten drew it. Grid, so the pill can sit on the logo's row
   without leaving the nav's markup order. */
.rb-masthead-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "logo get"
    "nav nav";
  align-items: center;
  gap: 10px 16px;
  padding-block: 14px;
}

.rb-masthead-inner .rb-logo { grid-area: logo; }
.rb-masthead-inner .rb-nav { grid-area: nav; }
.rb-masthead-inner .rb-get { grid-area: get; justify-self: end; }

@media (min-width: 768px) {
  .rb-masthead-inner {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "logo nav get";
    gap: 16px;
  }
}

.rb-logo {
  display: inline-flex;
  /* Baselines, not centers: the bars stand on the same line the letters do,
     as BrandLogo lays them out. */
  align-items: baseline;
  gap: 7px;
  text-decoration: none;
  color: var(--rb-fg);
}

.rb-logo:hover {
  color: var(--rb-fg);
}

/*
 * The mark's own box is the bars': 33 wide and 28 tall, to their baseline,
 * exactly as BrandLogo sizes the View around its Svg. The water and the
 * reflection hang below that edge and the water a little past the left,
 * drawn outside the box (the SVG's viewBox is wakeMark's VIEWBOX, -5 0
 * 42.4 43.2) rather than making it taller, so the logo takes the room the
 * bars always did and the box's bottom edge is what sits on the baseline.
 */
.rb-mark {
  position: relative;
  display: inline-block;
  width: 33px;
  height: 28px;
  flex: none;
}

.rb-mark svg {
  position: absolute;
  left: -5px;
  top: 0;
  width: 42.4px;
  height: 43.2px;
  overflow: visible;
}

/*
 * The wordmark is "rowbeat", set exactly as components/BrandLogo.tsx sets it:
 * all lowercase, one word, Bricolage Grotesque ExtraBold, pulled in a little
 * as display type wants.
 *
 * The numbers are the app's proportions, not a web guess. BrandLogo draws the
 * bars at 33 wide and the lettering at fontSize 32 with letterSpacing -1 and
 * paddingRight 1, so beside the same 33px mark the type is 2rem, the tracking
 * is -1/32 = -0.03125em and the trailing room the same. The mark is a graphic
 * whose halves have to stay locked together; changing one of these without
 * the other pulls it apart. Mixed-case "RowBeat" is correct in running prose
 * and wrong in the mark.
 */
.rb-wordmark {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-style: normal;
  font-size: 2rem;
  letter-spacing: -0.03125em;
  line-height: 1;
  padding-right: 0.03125em;
}

/* Navigation, as round ten drew it: DM Mono labels in capitals, in ink, and
   an amber "Get the app" pill at the end of the row. The pill is the one
   fill in the masthead, and amber means act. */
.rb-nav {
  display: flex;
  gap: 4px 10px;
  flex-wrap: wrap;
  align-items: center;
  /* The first label's text starts on the logo's left edge, not its padding's. */
  margin-left: -8px;
}

.rb-nav a {
  font-family: var(--rb-label);
  font-weight: 500;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--rb-fg);
  text-decoration: none;
  padding: 10px 8px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--rb-radius-control);
}

.rb-nav a:hover {
  background: var(--rb-nav-hover-bg);
}

.rb-nav a[aria-current="page"] {
  color: var(--rb-accent-ink);
}

/* The one fill in the masthead; amber means act. 44px tall on a phone, where
   it shares the logo's row, 48 from tablet width. */
.rb-get {
  display: inline-flex;
  align-items: center;
  font-family: var(--rb-body);
  font-weight: 600;
  font-size: 0.9375rem;
  background: var(--rb-amber);
  color: var(--rb-on-amber);
  border-radius: var(--rb-radius-pill);
  padding: 0 18px;
  min-height: 44px;
  text-decoration: none;
}

.rb-get:hover {
  background: #ffc25c;
  color: var(--rb-on-amber);
}

@media (min-width: 768px) {
  .rb-get {
    min-height: 48px;
    padding: 0 22px;
  }
}

/* ── Hero ──────────────────────────────────────────────────────────────────
 * Round ten's: a label, "Row to the beat.", one paragraph, the App Store badge
 * and a "How it works" button, with an album beside it on the flat page. No
 * photograph and no wash: the album is the picture, and it is RowBeat's own
 * (the app would draw this cover for this workout).
 */
.rb-hero {
  border-bottom: 1px solid var(--rb-border);
  background: var(--rb-bg);
}

.rb-hero-content {
  padding-block: 48px 56px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 44px 48px;
  align-items: center;
}

.rb-hero-copy {
  /* A grid column may not shrink below its content without this, and the
     headline is wide. */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

@media (min-width: 900px) {
  .rb-hero-content {
    grid-template-columns: minmax(0, 1fr) minmax(300px, 420px);
  }
}

/* A line of small capitals over a headline, DM Mono, in the muted ink. */
.rb-eyebrow {
  font-family: var(--rb-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  color: var(--rb-muted);
  margin: 0;
}

/* Round ten's hero headline: Bricolage at clamp(50px, 8vw, 112px), line
   height 0.88, tracking -0.05em. A sentence, with its period. */
.rb-h1 {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: clamp(3.125rem, 8vw, 7rem);
  line-height: 0.88;
  letter-spacing: -0.05em;
  margin: 0;
  text-wrap: balance;
}

.rb-hero-lede {
  font-size: 1.1875rem;
  line-height: 1.5;
  max-width: 30em;
  margin: 0;
}

.rb-hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  margin-top: 4px;
}

.rb-hero-actions .rb-store-badge {
  margin-top: 0;
}

/* The outlined button beside the App Store badge: round ten drew it as a pill
   beside a solid pill, but the badge is Apple's own rounded rectangle, 50px
   tall with about an 8px corner, so this takes the badge's height and corner
   and the two read as a pair. Ink outline, ink label. */
.rb-btn-line {
  display: inline-flex;
  align-items: center;
  min-height: 50px;
  padding: 0 20px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1.5px var(--rb-fg);
  color: var(--rb-fg);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9375rem;
}

.rb-btn-line:hover {
  color: var(--rb-fg);
  background: var(--rb-nav-hover-bg);
}

/* ── The album ────────────────────────────────────────────────────────────
 * The cover is the app's own drawing (components/AlbumCover.tsx over
 * src/utils/albumCover.ts): a 100-box with the title at left 7%, its
 * baseline at 18.41 (17 units of Bricolage), "SPM" at left 7.5% on 31.37
 * (5.2 of DM Mono), the logo's top-right corner 7 in from the corner with its
 * name 4.6 wide, and the count and shape on 95.33 (4.2 of DM Mono), 8 in from
 * each side. Container units make the box's 100 the cover's width, whatever
 * the cover is drawn at, so every size below is read straight off the app.
 * Under the cover, round ten's track list: number, title over artist, the
 * stroke rate in Bricolage with SPM under it.
 */
.rb-album {
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.18);
}

.rb-cover {
  position: relative;
  aspect-ratio: 1 / 1;
  container-type: inline-size;
  overflow: hidden;
  background: var(--cover);
  color: var(--cover-ink);
}

.rb-cover svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.rb-cover-title {
  position: absolute;
  left: 7cqw;
  top: 6cqw;
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: 17cqw;
  line-height: 0.8;
  letter-spacing: -0.05em;
  white-space: nowrap;
}

.rb-cover-unit,
.rb-cover-count,
.rb-cover-shape {
  position: absolute;
  font-family: var(--rb-label);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}

.rb-cover-unit {
  left: 7.5cqw;
  top: 27cqw;
  font-size: 5.2cqw;
  letter-spacing: 0.06em;
}

.rb-cover-count,
.rb-cover-shape {
  bottom: 4cqw;
  font-size: 4.2cqw;
  letter-spacing: 0.04em;
}

.rb-cover-count {
  left: 8cqw;
}

.rb-cover-shape {
  right: 8cqw;
}

/* The lockup at the cover's top right, at BrandLogo's proportions: 4.6cqw of
   name is 32 BrandLogo units, so the mark's 33 x 28 box is 4.6 / 32 of that. */
.rb-cover-logo {
  position: absolute;
  right: 7cqw;
  top: 7cqw;
  display: inline-flex;
  align-items: baseline;
  gap: 1cqw;
  font-size: 4.6cqw;
  color: var(--cover-ink);
}

.rb-cover-logo .rb-mark {
  width: 4.74cqw;
  height: 4.025cqw;
}

.rb-cover-logo .rb-mark svg {
  position: absolute;
  left: -0.72cqw;
  top: 0;
  width: 6.1cqw;
  height: 6.21cqw;
}

.rb-cover-logo .rb-wordmark {
  font-size: 1em;
}

.rb-tracks-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  font-family: var(--rb-label);
  font-weight: 500;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--rb-card);
  color: var(--rb-fg);
  border-bottom: 1.5px solid var(--rb-fg);
}

.rb-tracks {
  margin: 0;
  padding: 8px 18px 12px;
  list-style: none;
  background: var(--rb-card);
}

.rb-tracks li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  min-height: 48px;
  border-bottom: 1px solid var(--rb-border);
}

.rb-tracks li:last-child {
  border-bottom: 0;
}

.rb-track-n {
  font-family: var(--rb-label);
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--rb-muted);
  font-variant-numeric: tabular-nums;
}

.rb-track-s {
  min-width: 0;
}

.rb-track-s b {
  display: block;
  font-weight: 600;
  font-size: 0.9375rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rb-track-s span {
  display: block;
  font-size: 0.8125rem;
  color: var(--rb-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rb-track-r {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: 1.375rem;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.rb-track-r small {
  display: block;
  font-family: var(--rb-label);
  font-weight: 500;
  font-size: 0.625rem;
  line-height: 1.2;
  letter-spacing: 0.06em;
  color: var(--rb-muted);
}

.rb-track-more {
  min-height: 40px;
}

/* ── The opposite band: One stroke, one bar ───────────────────────────────
 * Round ten's dark band, in the mode the page is not in (the --rb-op tokens).
 * Everything inside takes the band's own tokens, never the page's, so the
 * page's ink is never drawn on the band's ground.
 */
.rb-opposite {
  background: var(--rb-op-bg);
  color: var(--rb-op-fg);
  border-bottom: 0;
}

.rb-opposite-inner {
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.rb-split-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px 40px;
}

.rb-split-head p {
  margin: 0;
  max-width: 26em;
  font-size: 1.125rem;
  line-height: 1.5;
}

.rb-opposite .rb-split-head p {
  color: var(--rb-op-fg);
}

/* Round ten's section headline: clamp(36px, 5vw, 60px), line height 0.94,
   tracking -0.045em. */
.rb-h2 {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: clamp(2.25rem, 5vw, 3.75rem);
  line-height: 0.94;
  letter-spacing: -0.045em;
  margin: 0;
  text-wrap: balance;
}

.rb-beat {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px 36px;
}

.rb-wake-pulse {
  display: block;
  width: clamp(120px, 30vw, 170px);
  flex-shrink: 0;
  overflow: visible;
  color: var(--rb-op-fg);
}

.rb-count {
  flex: 1 1 300px;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}

.rb-count span {
  border-radius: 10px;
  padding: 10px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--rb-label);
  font-weight: 500;
  font-size: 0.6875rem;
  line-height: 1.3;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--rb-op-card);
  color: var(--rb-op-muted);
  box-shadow: inset 0 0 0 1px var(--rb-op-border);
  min-width: 0;
  overflow: hidden;
}

.rb-count b {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: 1.875rem;
  line-height: 1;
  letter-spacing: -0.03em;
  color: inherit;
}

/*
 * The pulse, from src/utils/wakePulse.ts. One count is 0.5 s (120 a minute),
 * a cycle one count for each of the four bars; bar n lifts n counts after the
 * first. A lift is scaleY(1.14) with the skew that keeps the bar's 12-degree
 * lean (tan⁻¹(0.213 × 0.14 / 1.14) = 1.4984°), about the baseline (y 28, the
 * SVG's user units via transform-box: view-box); its reflection does the
 * same, mirrored, about the reflection's top (y 31.16). Each strip of
 * reflection drifts 0.842 units (1.6 of the spec's 100-box) either side over
 * 2.6 s, strip j 0.45 s ahead of the first. The count lights one cell for one
 * count, the fourth in amber. Reduced motion stops all of it and lights the
 * fourth cell, the beat.
 */
@keyframes rb-lift {
  0% { transform: none; }
  8% { transform: skewX(-1.4984deg) scaleY(1.14); }
  24%, 100% { transform: none; }
}

@keyframes rb-lift-r {
  0% { transform: none; }
  8% { transform: skewX(1.4984deg) scaleY(1.14); }
  24%, 100% { transform: none; }
}

@keyframes rb-drift {
  0%, 100% { transform: translateX(-0.842px); }
  50% { transform: translateX(0.842px); }
}

.rb-wake-pulse .rb-lift,
.rb-wake-pulse .rb-lift-r,
.rb-wake-pulse .rb-drift {
  transform-box: view-box;
}

.rb-wake-pulse .rb-lift {
  transform-origin: 0 28px;
  animation: rb-lift 2s ease-out infinite;
}

.rb-wake-pulse .rb-lift-r {
  transform-origin: 0 31.16px;
  animation: rb-lift-r 2s ease-out infinite;
}

.rb-wake-pulse .rb-drift {
  animation: rb-drift 2.6s ease-in-out infinite;
}

@keyframes rb-lit {
  0%, 24.9% { background: var(--rb-op-fg); color: var(--rb-op-bg); }
  25%, 100% { background: var(--rb-op-card); color: var(--rb-op-muted); }
}

@keyframes rb-lit-beat {
  0%, 24.9% { background: var(--rb-amber); color: var(--rb-on-amber); }
  25%, 100% { background: var(--rb-op-card); color: var(--rb-op-muted); }
}

.rb-count span { animation: rb-lit 2s steps(1) infinite; }
.rb-count span:nth-child(2) { animation-delay: -1.5s; }
.rb-count span:nth-child(3) { animation-delay: -1s; }
.rb-count span:nth-child(4) { animation-name: rb-lit-beat; animation-delay: -0.5s; }

@media (prefers-reduced-motion: reduce) {
  .rb-wake-pulse .rb-lift,
  .rb-wake-pulse .rb-lift-r,
  .rb-wake-pulse .rb-drift,
  .rb-count span {
    animation: none !important;
  }
  .rb-count span:nth-child(4) {
    background: var(--rb-amber);
    color: var(--rb-on-amber);
  }
}

/* ── How it works: three steps, each with its phone ─────────────────────── */
.rb-steps {
  display: grid;
  gap: 28px;
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .rb-steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.rb-step {
  min-width: 0;
}

.rb-step-phone {
  width: min(66%, 260px);
  height: auto;
  margin: 0 auto 18px;
}

@media (min-width: 720px) {
  .rb-step-phone {
    width: 100%;
    margin: 0 0 18px;
  }
}

.rb-step p {
  margin: 0;
  color: var(--rb-muted);
  font-size: 0.9375rem;
}

/* ── Genre chips, round ten's: a dot in the genre's color on a quiet pill ── */
.rb-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0;
  margin: 28px 0 0;
  list-style: none;
}

.rb-chips li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 14px 0 8px;
  border-radius: var(--rb-radius-pill);
  background: var(--rb-card);
  box-shadow: inset 0 0 0 1px var(--rb-border);
  font-weight: 600;
  font-size: 0.875rem;
}

.rb-chips i {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  flex-shrink: 0;
}

.rb-eras {
  margin-top: 24px;
}

/* ── Status strip ───────────────────────────────────────────────────────── */
/* The App Store badge is Apple's own artwork, stored here rather than
   hot-linked so the site still loads nothing from anyone else. Apple asks for
   the badge unaltered and at least 40px tall onscreen, with clear space
   around it; 50px keeps it comfortably above both and above the 44px target. */
.rb-store-badge {
  display: inline-flex;
  align-items: center;
  /* A quarter of the badge's height is Apple's minimum clear space; 16px
     keeps the icon outside it. */
  gap: 16px;
  margin-top: 28px;
  line-height: 0;
  border-radius: 8px;
}

.rb-store-badge img {
  display: block;
  height: 50px;
  width: auto;
}

/* The app's own icon beside the badge, the same file as the favicon (and as
   artifacts/rowbeat/assets/images/icon-wake.png: the Wake mark, slate on
   amber, from 1.2.0). The PNG is a full square, so the corners are rounded
   here at iOS's proportion (about 22% of the side). It is inside the same
   link as the badge and carries an empty alt, so a screen reader hears one
   link, "Download on the App Store", not two. */
.rb-store-icon {
  border-radius: 11px;
}

.rb-store-badge:focus-visible {
  outline: 2px solid var(--rb-accent-ink);
  outline-offset: 4px;
}

/* ── Sections ──────────────────────────────────────────────────────────── */
main {
  display: block;
}

.rb-band {
  padding-block: 48px;
  border-bottom: 1px solid var(--rb-border);
}

.rb-band:last-of-type {
  border-bottom: 0;
}

/* A section's headline: the app's screen title, `type.screenTitle` (32pt
   Bricolage, sentence case), grown a little for a page that is read at arm's
   length rather than from a cradle. */
.rb-band h2 {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-style: normal;
  letter-spacing: -0.04em;
  line-height: 1;
  font-size: clamp(2rem, 8vw, 2.75rem);
  margin: 0 0 8px;
}

/* A card's or a question's title: Bricolage in sentence case, as the app
   titles a card or a sheet. */
.rb-band h3 {
  font-family: var(--rb-headline);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-size: 1.25rem;
  margin: 0 0 6px;
}

.rb-lede {
  color: var(--rb-muted);
  font-size: 1.0625rem;
  margin: 0 0 28px;
  max-width: 60ch;
}

.rb-band p {
  max-width: 68ch;
}

/* ── Cards ─────────────────────────────────────────────────────────────── */
.rb-cards {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .rb-cards.rb-cards-2,
  .rb-cards.rb-cards-3 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .rb-cards.rb-cards-3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

.rb-card {
  background: var(--rb-card);
  border: 1px solid var(--rb-border);
  border-radius: var(--rb-radius-card);
  padding: 22px;
}

.rb-card p {
  margin: 0;
  color: var(--rb-muted);
  font-size: 0.9375rem;
}

.rb-card p + p {
  margin-top: 10px;
}

/* The step number: an outlined disc, the same device the app uses for an
   unselected control. Amber would read as something to tap. */
.rb-step-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--rb-outline);
  border-radius: 50%;
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: 1rem;
  color: var(--rb-accent-ink);
  margin-bottom: 12px;
}

.rb-step .rb-step-number {
  margin-bottom: 8px;
}



/* ── Pills ─────────────────────────────────────────────────────────────────
 * The app's choice chips (components/ui/Pill.tsx), shown here as a read-only
 * list of what is on offer: Instrument Sans SemiBold, outlined in ink, which
 * is how an unchosen pill has looked since the October 2026 redesign (the
 * chosen one is outlined in amber). Unselected styling throughout: nothing on
 * a web page is chosen.
 */
.rb-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0;
  margin: 0 0 8px;
  list-style: none;
}

.rb-pills li {
  border: 1px solid var(--rb-fg);
  border-radius: var(--rb-radius-pill);
  padding: 7px 14px;
  font-family: var(--rb-body);
  font-weight: 600;
  font-size: 0.9375rem;
  color: var(--rb-fg);
  line-height: 1.3;
}


/* A second-level label inside a band, under the amber section label. Muted
   rather than amber: amber is for action and selection, and these only name
   the list beneath them. */
.rb-sublabel {
  color: var(--rb-muted);
}

.rb-sublabel-spaced {
  margin-top: 28px;
}

/* ── Definition-style rows, used by Privacy ────────────────────────────── */
.rb-rows {
  margin: 0;
  padding: 0;
}

.rb-rows dt {
  font-family: var(--rb-headline);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-size: 1.125rem;
  color: var(--rb-fg);
  margin-top: 22px;
}

.rb-rows dt:first-child {
  margin-top: 0;
}

.rb-rows dd {
  margin: 6px 0 0;
  color: var(--rb-muted);
  max-width: 68ch;
}

/* ── Q&A blocks, used by Support ───────────────────────────────────────── */
.rb-qa {
  border-top: 1px solid var(--rb-border);
  padding-top: 22px;
  margin-top: 22px;
}

.rb-qa:first-of-type {
  border-top: 0;
  padding-top: 0;
  /* Not zero: the first question still needs air under the section heading it
     sits below, or the two read as one block of type. */
  margin-top: 24px;
}

.rb-qa h3 {
  margin-bottom: 8px;
}

.rb-qa p,
.rb-qa ol,
.rb-qa ul {
  color: var(--rb-muted);
  margin: 0 0 10px;
}

.rb-qa ol,
.rb-qa ul {
  padding-left: 1.25rem;
}

.rb-qa li {
  margin-bottom: 6px;
}

.rb-qa strong {
  color: var(--rb-fg);
  font-weight: 600;
}

/* ── Callout: the one thing on a page worth interrupting for ───────────── */
.rb-callout {
  background: var(--rb-card);
  border: 1px solid var(--rb-border);
  border-left: 3px solid var(--rb-amber);
  border-radius: var(--rb-radius-control);
  padding: 18px 20px;
  margin: 24px 0;
}

.rb-callout p {
  margin: 0;
  color: var(--rb-fg);
}

.rb-callout p + p {
  margin-top: 10px;
}

/* ── The letter ───────────────────────────────────────────────────────── */
/* The one first-person section. Body text in the full foreground rather than
   the muted lede color, because a letter is the thing to read, not a caption
   to a heading. The sign-off is set flush right, the way a letter is signed,
   with the name in the headline face: a byline, not a script signature, which
   would be the only typeface on the site that did not come from the app. */
.rb-letter p {
  color: var(--rb-fg);
  font-size: 1.0625rem;
  line-height: 1.6;
  max-width: 60ch;
  margin: 0 0 18px;
}

.rb-letter-signoff {
  max-width: 60ch;
  margin-top: 28px;
  text-align: right;
}

.rb-letter .rb-letter-name {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-style: normal;
  font-size: 2rem;
  line-height: 1;
  letter-spacing: -0.04em;
  margin: 0;
}

.rb-letter .rb-letter-role {
  color: var(--rb-muted);
  font-size: 0.9375rem;
  margin: 6px 0 0;
  /* The letter's own measure, so the sign-off sits under the text's right
     edge rather than drifting to the page's. */
  max-width: none;
  margin-left: auto;
}

/* ── Contact block ─────────────────────────────────────────────────────── */
.rb-contact-address {
  font-family: var(--rb-headline);
  font-weight: 800;
  font-size: clamp(1.25rem, 5.5vw, 1.75rem);
  letter-spacing: -0.02em;
  word-break: break-word;
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
}

/* ── Requirements list ─────────────────────────────────────────────────── */
.rb-checklist {
  list-style: none;
  padding: 0;
  margin: 0;
}

.rb-checklist li {
  position: relative;
  padding-left: 28px;
  margin-bottom: 12px;
  color: var(--rb-muted);
  max-width: 62ch;
}

.rb-checklist li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rb-decorative);
}

.rb-checklist strong {
  color: var(--rb-fg);
  font-weight: 600;
}

/* ── Footer ────────────────────────────────────────────────────────────── */
.rb-footer {
  border-top: 1.5px solid var(--rb-fg);
  padding-block: 32px 40px;
  color: var(--rb-muted);
  font-size: 0.875rem;
}

.rb-footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 16px;
}

.rb-footer-nav a {
  color: var(--rb-muted);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.rb-footer-nav a:hover {
  color: var(--rb-fg);
}

.rb-footer p {
  margin: 0 0 8px;
  max-width: 68ch;
}

.rb-fineprint {
  /* Small, but still a sentence someone might read, so it is `muted`, not
     `decorative`. See the design-language note: `decorative` was chosen as a
     decoration tint and then reused for small copy it could not carry. At
     this size on slate it does not read. */
  color: var(--rb-muted);
  font-size: 0.8125rem;
}

/* ── Page header for the inner pages ───────────────────────────────────── */
.rb-page-head {
  padding-block: 44px 8px;
}

.rb-page-head h1 {
  font-size: clamp(2.75rem, 12vw, 4rem);
}

.rb-page-head .rb-lede {
  margin-top: 16px;
  margin-bottom: 0;
}

/* The date line on the privacy page: a DM Mono label, like every small line
   that names a thing. */
.rb-updated {
  font-family: var(--rb-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  /* `muted`, not `decorative`: the date a privacy policy was last changed is
     one of the few things on the page a reader actively goes looking for. */
  color: var(--rb-muted);
  margin-top: 20px;
}

@media (min-width: 768px) {
  :root {
    --rb-gutter: 32px;
  }

  .rb-band {
    padding-block: 64px;
  }

  .rb-hero-content {
    padding-block: 72px 80px;
  }
}
