/* ============================================================================
   Rounds — product landing page. Second art-direction pass.

   Deliberately self-contained: this page does NOT load /styles.css. Everything
   is scoped under .rn so it can never leak into the rest of the site.

   Pass one replaced the reference's surface (colour, type, depth, motion).
   This pass replaces its skeleton. The reference reads as a column of centred
   blocks: hero → full-bleed pinned slab → centred chapter head → two-column
   bento → inset dark band → dark CTA. This page now reads asymmetric:

   - The hero is a split. Copy left, the app window bleeding off the right
     edge — the window is bigger than the page, which is the pitch ("the
     search is larger than the container you keep it in").
   - The pinned showcase keeps its scroll-scale but the chapter head rides a
     sticky left rail BESIDE the shot, and the panel half-bleeds right.
   - The four feature cards hang off a vertical spine, alternating sides —
     the section's anatomy is a structure, not a grid. The layout shows the
     "rounds × people × questions" shape instead of describing it.
   - "Native" mirrors the hero: shot bleeding LEFT, copy right.
   - Privacy is a full-bleed dark act (the trust engine gets the gravity),
     and the dark run continues unbroken through the CTA and footer.

   Palette: "bright tech", not macOS grey. White paper, icy indigo-tinted
   sections, electric indigo accent with a cyan far-stop, indigo-black ink.
   Every text colour re-verified against WCAG AA — ratios inline below.
   ========================================================================= */

/* Families are loaded by the <link> in index.html, not @import: @import
   serialises behind this stylesheet and delays the first paint of text. */

.rn {
  /* Surfaces. White paper, and the tinted sections carry a cool cast that is
     now mostly grey — the first pass sat at full chroma and read as pastel
     baby blue across whole sections. Chroma is down to 40% of that, with
     lightness pulled back a touch so desaturating didn't also wash the tonal
     step away from white (a greyer tint at the same lightness reads lighter).
     Ink stays indigo-black, not neutral black. */
  --paper:      #FFFFFF;   /* hero + spec bar */
  --frost:      #FFFFFF;   /* sections are white — the light half of the
                              page is now one continuous surface */
  --frost-2:    #FFFFFF;   /* was the deeper strip tint; kept as a token so
                              the strip can be re-tinted without markup edits */
  --card:       #FFFFFF;
  --ink:        #0A0A1F;   /* dark run: privacy → CTA → footer */
  --ink-2:      #14142E;   /* raised surface inside dark run */

  /* Text. Measured, not eyeballed:
     --t-mute  #53536E — 7.42:1 on --paper, 6.92:1 on --frost, 6.62:1 on
                --frost-2. Every sub-24px use clears 4.5:1 with margin.
     --t-body  #363650 — 10.4:1 on --frost-2, higher everywhere lighter.
     --t-faint is scaffolding-only: placeholder labels, deleted with them. */
  --t-strong:   #101024;
  --t-body:     #363650;
  --t-mute:     #53536E;
  --t-faint:    #9A9DB5;   /* placeholder labels only — never real copy */
  --t-on-dark:  #F2F4FF;
  --t-on-dark-mute: rgba(235,238,255,.72);   /* ≈12:1 on --ink */

  /* Accent. Electric indigo, cyan far stop.
     --acc   #3D46F2 — 6.26:1 under white text, 6.26:1 as text on --paper,
              5.58:1 on --frost-2. AA everywhere it appears.
     --acc-2 #0090C8 — gradient far stop; 3.61:1 on --paper, 3.22:1 on
              --frost-2 — clears the 3:1 large-text floor (only ever display
              sizes ≥42px).
     --acc-lit #8B93FF — accent as text/nodes on --ink: 7.17:1. */
  --acc:        #3D46F2;
  --acc-hover:  #2F38E4;
  --acc-ink:    #FFFFFF;
  --acc-2:      #0090C8;
  --acc-lit:    #8B93FF;
  /* Near-neutral now. At full chroma this band was the largest area of colour
     on the page and read as lavender rather than grey — the tint gradient
     covers most of a pinned 100vh section. */
  --cool:       #E7E8EC;   /* showcase atmosphere band — background-only */
  --cool-2:     #E6E9EA;   /* spare tint (cyan) */
  --cool-3:     #E9E8EC;   /* spare tint (violet) */
  --spine:      rgba(61,70,242,.30);   /* decorative line — no contrast duty */

  --line:       rgba(16,16,40,.08);
  --line-strong:rgba(16,16,40,.14);
  --line-dark:  rgba(255,255,255,.14);

  /* Geometry. 1200/980 from a 12-col × 76px grid with 24px gutters. The
     half-bleed sections compute their own left/right inset from the same
     --max so bled edges and contained edges share one grid. */
  --gutter:     24px;
  --max:        1200px;
  --bento:      980px;
  --r-card:     24px;
  --r-sect:     40px;
  --r-pill:     999px;
  /* Inset from viewport edge to the content column — the bleed sections pad
     one side with this and run the other side to the edge. */
  --edge:       max(var(--gutter), calc((100% - var(--max)) / 2 + var(--gutter)));

  /* Rhythm */
  --sect-pad:   144px;

  /* Depth: hairline-first. Cool-tinted ambient shadows, slightly bluer than
     pass one to sit with the new palette. */
  --lift:
    0 1px 2px rgba(10,10,31,.05),
    0 8px 24px rgba(10,10,31,.06),
    0 28px 64px -16px rgba(20,20,60,.14);
  --lift-sm:
    0 1px 2px rgba(10,10,31,.04),
    0 4px 14px -2px rgba(10,10,31,.08);

  /* Apple's sheet curve: fast out of the gate, long decelerating settle. */
  --ease: cubic-bezier(.32,.72,0,1);
  /* For colour/opacity only — transform on this curve looks like braking. */
  --ease-io: cubic-bezier(.45,0,.25,1);

  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-optical-sizing: auto;
  font-size: 16px;
  line-height: 1.5;
  color: var(--t-body);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body.rn-body { margin: 0; background: #FFFFFF; }

:where(.rn, .rn *, .rn *::before, .rn *::after) { box-sizing: border-box; }
/* Element resets are wrapped in :where() so they carry zero specificity —
   plain `.rn figure` selectors were (0,1,1) and outranked every (0,1,0)
   component rule. */
:where(.rn p, .rn h1, .rn h2, .rn h3, .rn h4, .rn ul, .rn ol, .rn figure, .rn dl) { margin: 0; }
:where(.rn ul, .rn ol) { padding: 0; list-style: none; }
:where(.rn a) { color: inherit; text-decoration: none; }
:where(.rn img, .rn video, .rn svg) { display: block; max-width: 100%; }

/* ---------------------------------------------------------------- primitives */

.rn-wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.rn-narrow { max-width: var(--bento); margin-inline: auto; }

/* Display type. Size-specific tracking; lh 1.04 so the display breathes. */
.rn-d1, .rn-d2, .rn-d3 {
  font-weight: 640;
  color: var(--t-strong);
  line-height: 1.04;
  text-wrap: balance;
}
/* Two lines is the ceiling for a hero headline. In the old narrow split column
   this had to drop to 60px to avoid a third line; on the full centred measure
   it can carry 72px and still set in two. */
.rn-d1 { font-size: clamp(40px, 5.4vw, 72px); letter-spacing: -.028em; }
.rn-d2 { font-size: clamp(32px, 4.2vw, 52px); letter-spacing: -.024em; }
.rn-d3 { font-size: clamp(24px, 2.8vw, 34px); letter-spacing: -.018em; }

.rn-lede {
  font-size: clamp(18px, 1.7vw, 21px);
  line-height: 1.45;
  color: var(--t-body);
  letter-spacing: -.012em;
  text-wrap: pretty;
}

/* Mono eyebrow — the typographic tell that says "software". */
.rn-mono {
  font-family: "DM Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--t-mute);
}

/* Headline emphasis: gradient ink, indigo → cyan. Both stops clear the 3:1
   large-text floor on every surface they appear on (6.26:1 and 3.61:1 on
   paper), so no point of the sweep dips below it. */
/* Flat accent, not a two-stop gradient. Once the page went white and the
   washes came out, the gradient headline was the only gradient left.
   Plain colour rather than the background-clip:text trick the gradient
   needed — clip:text requires a transparent text-fill, which means the real
   colour is invisible to any tool inspecting `color` (including a contrast
   audit, which read it as 1:1). 6.26:1 on white. */
.rn-hl { color: var(--acc); }

/* Buttons. Feedback lives on the press and it's instant — :active fires on
   pointer-down with a fast transition down and the slower settle back up. */
.rn-btn {
  display: inline-flex; align-items: center; gap: 10px;
  height: 48px; padding: 0 22px;
  border: 0; border-radius: var(--r-pill);
  font: inherit; font-size: 16px; font-weight: 500; letter-spacing: -.012em;
  cursor: pointer;
  transition: transform .45s var(--ease), background-color .3s var(--ease-io), opacity .3s var(--ease-io), box-shadow .45s var(--ease);
}
.rn-btn:hover { transform: translateY(-1px); }
.rn-btn:active { transform: scale(.97); transition-duration: .1s; }
.rn-btn-dark  { background: var(--ink); color: #fff; }
.rn-btn-dark:hover { background: #000; }
.rn-btn-light { background: #fff; color: var(--ink); box-shadow: var(--lift-sm); }
.rn-btn-acc   { background: var(--acc); color: var(--acc-ink); }   /* 6.26:1 */
.rn-btn-acc:hover { background: var(--acc-hover); }
.rn-btn-ghost { background: transparent; color: var(--t-body); }
.rn-btn-ghost:hover { color: var(--t-strong); }
/* "Coming soon" is a status, not a control. It is a <span>, so it takes no
   focus and offers no pointer, and it is styled as a quiet outlined marker
   rather than a filled button: a prominent button that does nothing on click
   reads as broken, and this page has no release and nothing to collect. The
   real action ("See how it works") carries the filled treatment instead. */
.rn-soon {
  display: inline-flex; align-items: center; gap: 8px;
  height: 48px; padding: 0 20px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  font-size: 16px; font-weight: 500; letter-spacing: -.012em;
  color: var(--t-mute);
  background: transparent;
  cursor: default;
  user-select: none;
}
.rn-soon::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--acc);
  flex: none;
}
.rn-soon-sm { height: 38px; padding: 0 15px; font-size: 14px; }
.rn-soon-lg { height: 48px; }
/* On the dark closing act the hairline and muted text need the inverted pair. */
.rn-cta .rn-soon, .rn-nav.is-dark .rn-soon {
  border-color: var(--line-dark);
  color: var(--t-on-dark-mute);
}
.rn-cta .rn-soon::before, .rn-nav.is-dark .rn-soon::before { background: var(--acc-lit); }

.rn-btn-sm { height: 38px; padding: 0 16px; font-size: 15px; }


.rn-badge {
  display: inline-flex; align-items: center; gap: 10px;
  height: 32px; padding: 0 14px 0 6px;
  background: rgba(255,255,255,.72);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: var(--lift-sm);
  font-size: 13px; color: var(--t-body); letter-spacing: -.01em;
}
.rn-badge b {
  display: inline-flex; align-items: center;
  height: 22px; padding: 0 9px; border-radius: var(--r-pill);
  background: var(--acc); color: var(--acc-ink);   /* 6.26:1 */
  font-size: 12px; font-weight: 600; letter-spacing: 0;
}

.rn-skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 18px; border-radius: 0 0 8px 0;
}
.rn-skip:focus { left: 0; }

.rn :focus-visible { outline: 2px solid var(--acc); outline-offset: 3px; border-radius: 4px; }

/* ---------------------------------------------------------------- placeholder

   No product shots exist yet. Every visual slot renders as a correctly
   proportioned frosted blank carrying a mono label that names the asset that
   belongs there. Delete .rn-ph and drop an <img> in its place. */

.rn-ph {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  /* Flat, and only just off-white: with the page now white, a placeholder
     needs to read as a reserved area without becoming the darkest thing on
     the screen. The hairline border does most of the work. */
  background: #F6F6F7;
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.85);   /* light catching the top edge */
  border-radius: 16px;
  overflow: hidden;
}
.rn-ph::after {
  content: attr(data-ph);
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--t-faint);
  text-align: center; padding: 0 20px; line-height: 1.7;
}
.rn-ph-dark {
  background: #17172E;
  border-color: var(--line-dark);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
}
.rn-ph-dark::after { color: rgba(255,255,255,.38); }

.rn-ph-16x10 { aspect-ratio: 16/10; }
.rn-ph-16x9  { aspect-ratio: 16/9; }
.rn-ph-4x3   { aspect-ratio: 4/3; }
.rn-ph-1x1   { aspect-ratio: 1/1; }
.rn-ph-fill  { position: absolute; inset: 0; border-radius: inherit; }

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

.rn-nav {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  display: flex; align-items: center;
  height: 68px;
  transition: background-color .3s var(--ease-io), border-color .3s var(--ease-io), backdrop-filter .3s var(--ease-io);
  border-bottom: 1px solid transparent;
}
/* Toolbar material: content scrolls under a translucent layer. */
.rn-nav.is-stuck {
  background: rgba(255,255,255,.72);
  backdrop-filter: saturate(180%) blur(22px);
  -webkit-backdrop-filter: saturate(180%) blur(22px);
  border-bottom-color: var(--line);
}
/* Over the dark run the bar inverts rather than disappearing. */
.rn-nav.is-dark { color: #fff; }
.rn-nav.is-dark.is-stuck { background: rgba(10,10,31,.72); border-bottom-color: var(--line-dark); }
.rn-nav.is-dark .rn-nav-links a { color: var(--t-on-dark-mute); }
.rn-nav.is-dark .rn-nav-links a:hover { color: #fff; }
.rn-nav.is-dark .rn-btn-dark { background: #fff; color: var(--ink); }
.rn-nav.is-dark .rn-mark-name { color: #fff; }
.rn-nav.is-dark .rn-back { color: var(--t-on-dark-mute); border-color: var(--line-dark); }
/* The divider between the portfolio link and the product mark is a dark
   hairline; over the dark run it disappears entirely. */
.rn-nav.is-dark .rn-mark { border-left-color: var(--line-dark); }

.rn-nav-inner {
  display: flex; align-items: center; gap: 24px;
  width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter);
}
/* Divider marks the handover from portfolio to product. */
.rn-mark {
  display: inline-flex; align-items: center; gap: 9px;
  padding-left: 20px; margin-left: -4px;
  border-left: 1px solid var(--line-strong);
}
.rn-mark-name { font-size: 18px; font-weight: 640; letter-spacing: -.022em; color: var(--t-strong); }
.rn-nav-links { margin-left: auto; display: flex; align-items: center; gap: 28px; }
.rn-nav-links a { font-size: 15px; font-weight: 500; letter-spacing: -.01em; color: var(--t-mute); transition: color .2s var(--ease-io); }
.rn-nav-links a:hover { color: var(--t-strong); }

/* Small return path to the portfolio. */
/* Sits at the far left, ahead of the Rounds mark: this page belongs to the
   portfolio, so the way back is the first thing in the bar rather than a
   trailing afterthought. The rule reads left-to-right as origin then product. */
.rn-back {
  display: inline-flex; align-items: center; gap: 7px;
  height: 30px; padding: 0 12px 0 9px;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  font-size: 13px; color: var(--t-mute);
  transition: color .2s var(--ease-io), border-color .2s var(--ease-io);
  white-space: nowrap;
}
.rn-back:hover { color: var(--t-strong); border-color: var(--t-strong); }
.rn-back svg { width: 13px; height: 13px; flex: none; }

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

   Asymmetric split: copy on the content grid's left columns, the app window
   starting at the grid seam and bleeding off the right edge of the viewport.
   The crop is deliberate — the window doesn't fit the page. */

.rn-hero {
  position: relative;
  background: var(--paper);
  padding-top: 68px;
  overflow: clip;
}
/* The atmospheric wash is gone — the hero is plain white. The element stays in
   the markup as an inert layer so a future wash has somewhere to live without
   a markup edit. */
.rn-hero-grid { display: none; }

/* Single column: centred copy, then the product shot full width beneath it.
   This replaces the asymmetric copy-left / window-bleeding-right split. With
   one message and one asset, the stack lets the shot be seen whole instead of
   cropped, and gives the headline the full measure so it sets at a larger size
   in two lines rather than three in a narrow column. */
.rn-hero-split {
  position: relative;
  display: block;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-block: 72px var(--sect-pad);
}
.rn-hero-copy { text-align: center; max-width: 760px; margin-inline: auto; }
/* Rhythm widens as it descends: the badge sits close to the headline, the
   lede gets air beneath a 72px display, and the CTAs get more still. A flat
   24px between all three made the lede crowd the headline. */
.rn-hero-copy > * + * { margin-top: 20px; }
.rn-hero-copy .rn-lede { margin-top: 30px; }
.rn-hero-copy .rn-hero-cta { margin-top: 40px; }
.rn-hero-copy h1 { max-width: 17ch; margin-inline: auto; }
.rn-hero-copy .rn-lede {
  /* balance, not pretty. Centred and three lines deep, this block shows its
     rag: `pretty` only protects the last line and left 646/193/356 — a full
     line, a 193px stub, then the second sentence. `balance` evens the widths
     to 400/439/356 and holds that regardless of the measure, so the result
     does not depend on a hand-tuned ch value. */
  text-wrap: balance;
  max-width: 46ch;
  margin-inline: auto;
  line-height: 1.5;
  color: var(--t-body);
}
.rn-hero-cta { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; }

/* Contained, not bled: the whole window is visible, sitting on its own shadow. */
.rn-hero-shot { position: relative; margin-top: 64px; }
.rn-hero-shot .rn-ph {
  border-radius: var(--r-card);
  border-color: var(--line-strong);
  box-shadow: var(--lift);
}


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

   Two screenshots of the same window, one per appearance. Which one shows is
   pure CSS so it is right on the first paint: the default follows the reader's
   own prefers-color-scheme, and an explicit data-shot from the toggle wins over
   it. That ordering matters because without JS the page still shows the
   appearance the reader actually uses.
   -------------------------------------------------------------------------- */

/* No margin reset here: :where() already zeroes figure margins, and declaring
   it again at this point in the file overrode .rn-hero-shot's margin-top and
   collapsed the gap between the CTAs and the screenshot. */
.rn-shot { position: relative; }
.rn-shot-img {
  width: 100%; height: auto; display: block;
  border-radius: var(--r-card);
  box-shadow: var(--lift);
}
.rn-shot-dark { display: none; }
@media (prefers-color-scheme: dark) {
  .rn-shot:not([data-shot]) .rn-shot-light { display: none; }
  .rn-shot:not([data-shot]) .rn-shot-dark  { display: block; }
}
.rn-shot[data-shot="light"] .rn-shot-light { display: block; }
.rn-shot[data-shot="light"] .rn-shot-dark  { display: none; }
.rn-shot[data-shot="dark"]  .rn-shot-light { display: none; }
.rn-shot[data-shot="dark"]  .rn-shot-dark  { display: block; }

.rn-shot-toggle {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  margin-top: 18px;
}
.rn-shot-seg {
  display: inline-flex; padding: 3px;
  background: var(--frost-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}
.rn-shot-seg button {
  appearance: none; border: 0; background: transparent;
  font: inherit; font-size: 13px; font-weight: 500; letter-spacing: -.01em;
  color: var(--t-mute);
  padding: 6px 14px; border-radius: var(--r-pill);
  cursor: pointer;
  transition: color .2s var(--ease-io), background-color .2s var(--ease-io);
}
.rn-shot-seg button:hover { color: var(--t-strong); }
.rn-shot-seg button[aria-pressed="true"] {
  background: var(--card);
  color: var(--t-strong);
  box-shadow: 0 1px 2px rgba(10,10,31,.10);
}

/* -------------------------------------------------------------- spec ribbon

   Kicker left, facts right, one hairline band — a spec-sheet header, not the
   reference's centred logo bar. */

.rn-spec-bar { background: var(--paper); padding-bottom: 110px; }
.rn-spec-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px 48px; flex-wrap: wrap;
  border-top: 1px solid var(--line);
  padding-top: 28px;
}
.rn-spec-list { display: flex; flex-wrap: wrap; gap: 8px 48px; }
.rn-spec-list li { display: flex; flex-direction: column; gap: 5px; text-align: left; padding: 4px 0; }
.rn-spec-list .rn-spec-v {
  font-size: 20px; font-weight: 640; letter-spacing: -.02em; color: var(--t-strong);
}
.rn-spec-list .rn-spec-k {
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 10px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; color: var(--t-mute);
}

/* ------------------------------------------------------------------ chapter */

.rn-chapter { position: relative; background: var(--frost); padding-bottom: var(--sect-pad); }

/* Sticky showcase, recomposed. The 200vh track and the --rn-scrub scale are
   the same interaction as pass one; the composition is not. Inside the pin:
   a two-column grid — the chapter head rides the left rail while the shot
   sits beside it and half-bleeds off the right viewport edge. Scale origin
   is the right edge so the bled edge stays glued while the panel settles. */
.rn-showcase { position: relative; height: 200vh; }
.rn-showcase-stick {
  position: sticky; top: 0; height: 100vh;
  display: grid;
  grid-template-columns: minmax(280px, 4fr) minmax(0, 7fr);
  gap: clamp(32px, 4vw, 72px);
  align-items: center;
  padding: 96px 0 88px var(--edge);
  overflow: clip;
}
/* The coloured band behind the pin is gone; the pinned shot now sits on plain
   white and carries itself on its own shadow and hairline. Kept as an inert
   layer so the per-chapter --tint hook survives. */
.rn-showcase-tint { display: none; }
.rn-chapter-head { position: relative; text-align: left; }
.rn-chapter-head .rn-mono { display: block; margin-bottom: 20px; color: var(--acc); }
.rn-chapter-head .rn-d2 { max-width: 14ch; }
.rn-chapter-head .rn-lede { max-width: 40ch; margin-top: 22px; color: var(--t-mute); }

.rn-showcase-panel {
  position: relative;
  width: 100%;
  height: min(74vh, 46vw);
  border-radius: var(--r-card) 0 0 var(--r-card);
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(10,10,31,.06), 0 32px 80px -20px rgba(20,20,60,.30);
  transform: scale(calc(.94 + var(--rn-scrub, 0) * .06));
  transform-origin: 100% 50%;
  will-change: transform;
}
.rn-showcase-panel .rn-ph { height: 100%; border: 0; border-radius: 0; box-shadow: none; }

/* -------------------------------------------------------------------- spine

   The four cards hang off a vertical line, alternating sides down the page —
   a pipeline, not a grid. Each card carries a node dot on the line. This is
   the composition doing the marketing brief's work: a spreadsheet is a stack
   of rows; a search has joints and branches. */

.rn-spine {
  position: relative;
  max-width: var(--bento);
  margin: 110px auto 0;
}
.rn-spine::before {
  content: "";
  position: absolute; left: 50%; top: -56px; bottom: -48px; width: 2px;
  margin-left: -1px;
  background: linear-gradient(180deg, transparent, var(--spine) 6%, var(--spine) 94%, transparent);
}
.rn-step { position: relative; width: calc(50% - 48px); }
/* The lead card carries a taller shot. Notes is the feature the maker would
   demo first, and it owns the chapter's full-bleed image already; this gives
   it weight in the spine without widening it, which would break the strict
   two-column alternation the connectors depend on. */
.rn-step-lead .rn-card-media .rn-ph { min-height: 300px; }

.rn-step:nth-child(odd)  { margin-right: auto; }
.rn-step:nth-child(even) { margin-left: auto; margin-top: -190px; }
.rn-step + .rn-step:nth-child(odd) { margin-top: 64px; }
/* Node dot, centred on the spine. */
.rn-step::after {
  content: "";
  position: absolute; top: 40px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--acc);
  box-shadow: 0 0 0 5px var(--frost), 0 0 0 6px var(--spine);
}
.rn-step:nth-child(odd)::after  { right: -54px; }
.rn-step:nth-child(even)::after { left: -54px; }
/* Connector from card to node. */
.rn-step::before {
  content: "";
  position: absolute; top: 45px; width: 42px; height: 2px;
  background: var(--spine);
}
.rn-step:nth-child(odd)::before  { right: -42px; }
.rn-step:nth-child(even)::before { left: -42px; }

.rn-card {
  display: flex; flex-direction: column;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--lift-sm);
  overflow: hidden;
}
.rn-card-media { padding: 20px 20px 0; }
.rn-card-media .rn-ph { aspect-ratio: 16/10; border-radius: 14px 14px 0 0; border-bottom: 0; }
.rn-card-body { padding: 22px 26px 28px; }
.rn-card-body h3 { font-size: 18px; font-weight: 640; letter-spacing: -.018em; color: var(--t-strong); margin-bottom: 7px; }
.rn-card-body p  { font-size: 15px; line-height: 1.5; color: var(--t-mute); letter-spacing: -.006em; }

/* Terminus note, hanging off the end of the spine. */
.rn-spine-note {
  max-width: 52ch;
  margin: 96px auto 0;
  text-align: center;
  font-size: 14px; color: var(--t-mute); letter-spacing: -.01em;
}

/* -------------------------------------------------------------- native strip

   Mirrors the hero: the dark-mode shot bleeds off the LEFT edge, copy sits
   right. A credential gets a band, not a chapter. */

.rn-strip { background: var(--frost-2); padding-block: 120px; }
.rn-strip-split {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(32px, 4vw, 72px);
  align-items: center;
  padding-right: var(--edge);
}
.rn-strip-media { min-width: 0; }
.rn-strip-media .rn-ph {
  border-radius: 0 var(--r-card) var(--r-card) 0;
  border-left: 0;
  box-shadow: var(--lift);
}
.rn-strip-copy { max-width: 480px; }
.rn-strip-copy .rn-mono { display: block; margin-bottom: 18px; color: var(--acc); }
.rn-strip-copy h2 { margin-bottom: 16px; }
.rn-strip-copy p { color: var(--t-mute); font-size: 17px; line-height: 1.55; letter-spacing: -.01em; }
.rn-strip-facts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 26px; }
.rn-strip-facts li {
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--t-mute);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 7px 13px;
}

/* ------------------------------------------------------------------ privacy

   The trust engine. Full-bleed dark — not the reference's inset rounded
   band — and the ink runs unbroken from here through the CTA and footer:
   the close of the page is one continuous dark statement. */

.rn-priv {
  background: var(--ink);
  color: var(--t-on-dark);
  padding: 140px 0 120px;
}
.rn-priv .rn-mono { color: var(--acc-lit); }   /* 7.17:1 on --ink */
.rn-priv .rn-d2 { color: #fff; }
.rn-priv-head { max-width: 720px; }
.rn-priv-head .rn-mono { display: block; margin-bottom: 18px; }
.rn-priv-head p { margin-top: 20px; color: var(--t-on-dark-mute); font-size: 17px; line-height: 1.55; }
.rn-priv-body {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: center;
  margin-top: 72px;
}
.rn-priv-media .rn-ph { border-radius: var(--r-card); }
.rn-priv-ledger li { border-top: 1px solid var(--line-dark); padding: 24px 0 26px; }
.rn-priv-ledger li:last-child { border-bottom: 1px solid var(--line-dark); }
.rn-priv-ledger h3 { font-size: 16px; font-weight: 600; letter-spacing: -.014em; color: #fff; margin-bottom: 8px; }
.rn-priv-ledger p  { font-size: 14px; line-height: 1.55; color: var(--t-on-dark-mute); }

/* -------------------------------------------------------------- closing CTA

   Continues the dark run. Statement left, actions right — a signature line,
   not the reference's centred dark block. */

.rn-cta { background: var(--ink); color: #fff; padding: 40px 0 130px; }
.rn-cta-inner {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: 40px 48px;
  align-items: center;
  border-top: 1px solid var(--line-dark);
  padding-top: 104px;
}
.rn-cta .rn-d1 { color: #fff; max-width: 14ch; }
.rn-cta-copy p { margin-top: 22px; color: var(--t-on-dark-mute); font-size: 17px; }
.rn-cta-actions {
  justify-self: end;
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
}
.rn-cta .rn-btn-ghost { color: #fff; }
.rn-cta .rn-btn-ghost:hover { color: #fff; opacity: .72; }
.rn-cta-fine { margin-top: 12px; font-size: 13px; color: rgba(235,238,255,.60); }

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

.rn-foot { background: var(--ink); color: var(--t-on-dark-mute); padding: 0 var(--gutter) 56px; }
.rn-foot-inner {
  max-width: var(--max); margin-inline: auto;
  border-top: 1px solid var(--line-dark); padding-top: 40px;
  display: flex; flex-wrap: wrap; gap: 28px 48px; align-items: flex-start;
}
.rn-foot-brand { margin-right: auto; max-width: 300px; }
.rn-foot-brand .rn-mark-name { color: #fff; }
.rn-foot-brand p { margin-top: 12px; font-size: 14px; line-height: 1.6; }
.rn-foot-col { display: flex; flex-direction: column; gap: 11px; }
.rn-foot-col .rn-mono { color: rgba(235,238,255,.5); margin-bottom: 4px; }
.rn-foot-col a { font-size: 14px; color: var(--t-on-dark-mute); transition: color .2s var(--ease-io); }
.rn-foot-facts span:not(.rn-mono) { font-size: 14px; color: var(--t-on-dark-mute); }
.rn-foot-col a:hover { color: #fff; }
.rn-foot-base {
  max-width: var(--max); margin: 44px auto 0;
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  font-size: 13px; color: rgba(235,238,255,.60);
}

/* ------------------------------------------------------------------ reveals */

/* Gated on .rn-js, which the head script sets before first paint. No JS
   simply means no animation. 18px travel on the sheet curve. */
.rn-js .rn-rise { opacity: 0; transform: translateY(18px); }
.rn-js .rn-rise.is-in {
  opacity: 1; transform: none;
  transition: opacity .6s var(--ease-io), transform .8s var(--ease);
  transition-delay: var(--rn-delay, 0s);
}

/* ---------------------------------------------------------------- responsive */

@media (max-width: 1024px) {
  .rn { --sect-pad: 104px; --r-sect: 32px; }
  .rn-showcase-stick { grid-template-columns: minmax(240px, 5fr) minmax(0, 7fr); }
  .rn-priv-body { grid-template-columns: 1fr; gap: 48px; }
  .rn-cta-inner { grid-template-columns: 1fr; }
  .rn-cta-actions { justify-self: start; }
}

/* Tablet. The jump from 1024 straight to 760 left 768px devices running the
   desktop two-column splits at roughly half the width they were designed for
   (a 296px chapter rail, for one). The remaining split layouts stack here;
   phone-specific chrome still waits for 760. */
@media (max-width: 900px) {
  .rn-hero-split { padding-block: 56px var(--sect-pad); }

  /* Unpin. A 100vh pin needs width to be worth the scroll it costs; below this
     it is just a tall image the reader has to wait out. */
  .rn-showcase { height: auto; }
  .rn-showcase-stick {
    position: static; height: auto;
    grid-template-columns: 1fr; gap: 36px;
    padding: 88px var(--gutter) 0 var(--edge);
  }
  .rn-showcase-panel { height: auto; aspect-ratio: 16/10; transform: none; }

  .rn-strip-split { grid-template-columns: 1fr; gap: 36px; }
  .rn-strip-copy { order: -1; max-width: 620px; }
}

@media (max-width: 760px) {
  .rn { --gutter: 18px; --sect-pad: 80px; --r-sect: 24px; --r-card: 18px; }
  .rn-nav-links { display: none; }
  .rn-nav-inner { gap: 10px; }
  /* Keep the glyph as the return affordance and drop the words; the footer
     carries a full-width "James Made" link for anyone who needs the label. */
  /* Leads the bar now, so no auto margin. Glyph only — the words don't fit
     beside the product mark at this width, and the footer carries the label. */
  .rn-back { padding: 0; width: 30px; justify-content: center; }
  .rn-mark { padding-left: 14px; }
  .rn-btn-sm { margin-left: auto; }
  .rn-back-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .rn-mark-name { font-size: 17px; }
  .rn-btn-sm { padding: 0 14px; }
  /* The nav marker and the hero marker both read "Coming soon" and, stacked on
     a phone, land within one screen of each other. The hero owns it. */
  .rn-nav .rn-soon { display: none; }

  .rn-hero-grid { height: 620px; }
  /* Hero stacks; the shot keeps a gentler bleed so the crop still reads. */
  .rn-hero-split { padding-block: 40px 64px; }
  .rn-hero-copy h1 { max-width: none; }
  /* The split only ever had padding-left, because on desktop the shot is meant
     to run off the right edge. Stacked, that left every line of copy flush to
     the screen edge with no gutter at all. The gutter belongs on the copy, not
     the split — the shot still needs to bleed. */

  .rn-hero-shot { margin-top: 40px; }
  .rn-shot-toggle { justify-content: center; margin-top: 14px; }
  /* Buttons stack full-width-left; the ghost button's inline padding was
     indenting it out of line with the filled one above it. */
  .rn-hero-cta { flex-direction: column; align-items: stretch; gap: 8px; }
  .rn-hero-cta .rn-btn { justify-content: center; }
  .rn-hero-cta .rn-btn-ghost { justify-content: center; }

  .rn-spec-bar { padding-bottom: 72px; }
  .rn-spec-inner { flex-direction: column; align-items: flex-start; gap: 18px; padding-top: 22px; }
  /* Grid, not flex-wrap. Five facts of uneven width wrapped 4+1 on a phone,
     which reads as an accident rather than a layout. A fixed three-column
     grid gives a deliberate 3+2 with the columns aligned. */
  .rn-spec-list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px 16px; width: 100%; }
  .rn-spec-list .rn-spec-v { font-size: 17px; }
  .rn-spec-list .rn-spec-k { font-size: 10px; letter-spacing: .08em; }

  /* Sticky showcases collapse to a stacked head + plain image on phones:
     pinned 100vh panels on a small screen cost scroll and give back nothing. */
  .rn-showcase { height: auto; }
  .rn-showcase-stick {
    position: static; height: auto;
    grid-template-columns: 1fr; gap: 32px;
    padding: 64px var(--gutter) 0;
  }
  .rn-chapter-head { padding-right: 0; }
  .rn-showcase-panel { height: auto; aspect-ratio: 4/3; transform: none; border-radius: var(--r-card); }
  .rn-chapter-head .rn-d2, .rn-chapter-head .rn-lede { max-width: none; }

  /* Spine collapses to a left rail: line on the left, cards hanging right. */
  .rn-spine { margin-top: 56px; }
  .rn-spine::before { left: 5px; top: -24px; bottom: -24px; }
  .rn-step,
  .rn-step:nth-child(odd),
  .rn-step:nth-child(even) { width: auto; margin: 0 0 0 30px; }
  .rn-step + .rn-step { margin-top: 24px !important; }
  .rn-step::after,
  .rn-step:nth-child(odd)::after,
  .rn-step:nth-child(even)::after { left: -30px; right: auto; top: 28px; width: 10px; height: 10px; box-shadow: 0 0 0 4px var(--frost), 0 0 0 5px var(--spine); }
  .rn-step::before,
  .rn-step:nth-child(odd)::before,
  .rn-step:nth-child(even)::before { left: -20px; right: auto; top: 32px; width: 20px; }
  .rn-spine-note { margin-top: 48px; text-align: left; padding-left: 30px; }

  .rn-strip { padding-block: 72px; }
  .rn-strip-split { grid-template-columns: 1fr; gap: 32px; padding-right: var(--gutter); }
  .rn-strip-copy { order: -1; padding-left: var(--gutter); max-width: none; }
  .rn-strip-media .rn-ph { border-radius: 0 var(--r-card) var(--r-card) 0; }

  .rn-priv { padding: 88px 0 72px; }
  .rn-priv-body { margin-top: 48px; gap: 40px; }

  .rn-cta { padding: 24px 0 88px; }
  .rn-cta-inner { padding-top: 72px; }

  .rn-foot-inner { gap: 26px 34px; }
  .rn-foot-brand { max-width: none; flex-basis: 100%; }
}

/* Touch. Every interactive element measured under Apple's 44pt minimum on a
   phone: footer links were 21px tall, the portfolio back glyph 30x30. Gated on
   a coarse pointer so the desktop layout keeps its tighter rhythm — this is a
   hit-area fix, not a styling change, and the visual size of the text is the
   same either way. */
@media (pointer: coarse) {
  .rn-foot-col a,
  .rn-foot-facts span:not(.rn-mono),
  .rn-nav-links a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* The column is a vertical list, so a taller row simply spaces it; the gap
     comes off so the rhythm doesn't double up. */
  .rn-foot-col { gap: 0; }
  .rn-foot-col .rn-mono { margin-bottom: 8px; }

  .rn-back { width: 44px; height: 44px; }
  .rn-back svg { width: 15px; height: 15px; }

  /* The mark is a link home; give it the same floor. */
  .rn-mark { min-height: 44px; }

  /* The nav's compact Download pill is the page's primary conversion and was
     the last element under the floor at 38px. */
  .rn-btn-sm { height: 44px; }

  /* Segmented toggle: 32px tall reads fine with a cursor, not with a thumb. */
  .rn-shot-seg button { min-height: 44px; padding-inline: 18px; }

  /* Hover styling that sticks after a tap reads as a stuck state on touch. */
  .rn-btn:hover { transform: none; }
}

/* Frostier, not just quieter: translucency preferences get near-solid chrome. */
@media (prefers-reduced-transparency: reduce) {
  .rn-nav.is-stuck { background: rgba(255,255,255,.97); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .rn-nav.is-dark.is-stuck { background: rgba(10,10,31,.97); }
  .rn-badge { backdrop-filter: none; -webkit-backdrop-filter: none; background: #fff; }
}

@media (prefers-reduced-motion: reduce) {
  .rn-js .rn-rise { opacity: 1; transform: none; transition: none; }
  .rn-btn:hover, .rn-btn:active { transform: none; }
  .rn-showcase { height: auto; }
  .rn-showcase-stick { position: static; height: auto; padding-block: 96px; }
  .rn-showcase-panel { transform: none; height: auto; aspect-ratio: 16/10; }
}
