/* Homepage layout, layered on css/base.css (tokens + the demo phone).
   Dials: DESIGN_VARIANCE 7, MOTION_INTENSITY 6, VISUAL_DENSITY 3.
   Motion moved 5 -> 6 when the hero gained a perpetual micro-interaction
   (the live pill), which Section 5 gates at > 5.

   Six layout families, one per section, so no family repeats
   (Section 4.7 Section-Layout-Repetition):
     A  hero          asymmetric split, 7/5 not 50/50
     B  how it works  stepped editorial stack with increasing indent
     C  features      asymmetric bento, 6 items in exactly 6 cells
     D  roadmap       left-aligned vertical timeline
     E  install       emphasis block, the page's one theme switch
     F  footer        baseline row

   Motion is CSS only (Section 7, band 4-7 "Fluid CSS"). No scroll listeners
   anywhere; reveals are driven by IntersectionObserver in js/home.js. */

/* ---- Rhythm. VISUAL_DENSITY 3 wants gallery spacing. ---- */
.r-section { padding-block: clamp(5rem, 11vw, 9rem); }
.r-shell {
  width: 100%;
  max-width: 78rem;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 3rem);
}

/* ---- Navbar. Height cap 80px (Section 4.7). ---- */
.r-nav {
  transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
  border-bottom: 1px solid transparent;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
}
.r-nav.is-scrolled {
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .r-nav, .r-nav.is-scrolled { background: var(--surface); }
}

.r-nav-toggle span {
  display: block;
  width: 1.5rem;
  height: 2px;
  margin: 3px 0;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), width 0.2s ease, opacity 0.2s ease;
}
.r-nav-toggle.is-open span:nth-child(1) { transform: translateY(8px) rotate(-45deg); }
.r-nav-toggle.is-open span:nth-child(2) { width: 0; opacity: 0; }
.r-nav-toggle.is-open span:nth-child(3) { transform: translateY(-8px) rotate(45deg); }

.r-nav-menu { overflow: hidden; max-height: 0; transition: max-height 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
.r-nav-menu.is-open { max-height: 26rem; }
@media (min-width: 1024px) {
  .r-nav-menu { max-height: none; overflow: visible; }
}

/* ================= A. HERO =================
   Asymmetric split: copy gets more room than the device, and the device
   sits lower. Anti-centre bias (Section 4.3) at DESIGN_VARIANCE 7. */
.r-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 12% 0%, var(--surface) 0%, transparent 62%),
    linear-gradient(168deg, var(--surface) 0%, var(--surface-2) 100%);
  padding-top: clamp(3rem, 6vw, 6rem);      /* hero top padding cap pt-24 */
  padding-bottom: clamp(4rem, 8vw, 7rem);
}
.r-hero-grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: center;
}
@media (min-width: 1024px) {
  .r-hero-grid { grid-template-columns: 7fr 5fr; gap: clamp(3rem, 5vw, 5rem); }
  .r-hero-device { transform: translateY(2.5rem); }   /* the offset */
}
/* Isohypses. Generated by marching squares over a gaussian height field, so
   the lines nest and close the way real contours do rather than being drawn
   by hand. Masked away from the copy, and printed in two weights: a real
   topographic map thickens every third line as an index contour and leaves
   the intermediates hairline. */
.r-contour {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
  color: var(--accent);
  -webkit-mask-image: radial-gradient(155% 135% at 76% 68%, #000 0%, rgba(0,0,0,0.75) 42%, rgba(0,0,0,0.3) 72%, transparent 94%);
  mask-image: radial-gradient(155% 135% at 76% 68%, #000 0%, rgba(0,0,0,0.75) 42%, rgba(0,0,0,0.3) 72%, transparent 94%);
}
.r-contour path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.r-contour .c0 { stroke-opacity: 0.13; }   /* index contour */
.r-contour .c1,
.r-contour .c2 { stroke-opacity: 0.05; }   /* intermediates */

/* Browsers without mask-image would show the field at full strength across
   the headline, so drop it further there. */
@supports not (mask-image: radial-gradient(#000, transparent)) {
  .r-contour .c0 { stroke-opacity: 0.07; }
  .r-contour .c1,
  .r-contour .c2 { stroke-opacity: 0.03; }
}

/* ================= B. STEPPED STACK =================
   Full-width rows with a growing indent. No cards, no three-column grid,
   grouped by hairlines only (Section 4.4). */
.r-steps { display: grid; gap: 0; }
.r-step {
  display: grid;
  gap: 0.75rem 2.5rem;
  padding-block: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--line);
}
.r-step:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 768px) {
  .r-step { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); align-items: start; }
  .r-step:nth-child(2) { padding-left: 4vw; }
  .r-step:nth-child(3) { padding-left: 8vw; }
}
.r-step-title { color: var(--ink); }
.r-step-body { color: var(--body); max-width: 46ch; }

/* ================= C. BENTO =================
   6 items, exactly 6 cells (Section 4.7 cell-count rule), three sizes.
   Cells 1, 4 and 6 carry a tinted ground so the grid is not
   text-on-one-colour (Bento Background Diversity). */
.r-bento { display: grid; gap: clamp(0.75rem, 1.4vw, 1.1rem); }
.r-cell {
  position: relative;
  overflow: hidden;
  border-radius: 1.125rem;
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  background: var(--surface);
  border: 1px solid var(--line);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.3s ease;
}
.r-cell:hover { transform: translateY(-3px); border-color: var(--line-strong); }
.r-cell h3 { color: var(--ink); }
.r-cell p { color: var(--body); }
.r-cell--tint  { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent-strong) 20%, transparent); }
.r-cell--sage  { background: var(--sage-soft);   border-color: color-mix(in srgb, var(--sage) 24%, transparent); }
@supports not (border-color: color-mix(in srgb, red 20%, transparent)) {
  .r-cell--tint { border-color: #EBC9B8; }
  .r-cell--sage { border-color: #B9CDBE; }
}
.r-cell--wide  { display: grid; gap: 1.5rem; align-items: center; }

@media (min-width: 768px) {
  .r-bento { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .r-cell:nth-child(1) { grid-column: span 4; }
  .r-cell:nth-child(2) { grid-column: span 2; }
  .r-cell:nth-child(3) { grid-column: span 2; }
  .r-cell:nth-child(4) { grid-column: span 2; }
  .r-cell:nth-child(5) { grid-column: span 2; }
  .r-cell:nth-child(6) { grid-column: span 6; }
  .r-cell--wide { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); }
}

/* The loop motif, used as cell texture instead of stock photography.
   Documented Section 4.8 deviation: illustration-led until real
   photography is supplied. */
.r-cell-motif { position: absolute; right: -8%; bottom: -22%; width: 62%; opacity: 0.5; pointer-events: none; }
.r-cell-motif path { fill: none; stroke: var(--accent); stroke-opacity: 0.34; stroke-width: 2; stroke-linecap: round; }
.r-cell--sage .r-cell-motif path { stroke: var(--sage); stroke-opacity: 0.4; }

/* ================= D. TIMELINE =================
   Left-aligned vertical rail. Anti-centre bias; the previous build
   centred this section. */
.r-timeline { display: grid; gap: 0; }
.r-phase {
  position: relative;
  display: grid;
  gap: 0.6rem;
  padding: 0 0 clamp(2.25rem, 4vw, 3.25rem) clamp(2rem, 4vw, 3.25rem);
  border-left: 2px solid var(--line);
}
.r-phase:last-child { border-left-color: transparent; padding-bottom: 0; }
.r-phase::before {
  content: '';
  position: absolute;
  left: -0.5rem;
  top: 0.35rem;
  width: 0.875rem;
  height: 0.875rem;
  border-radius: 9999px;
  background: var(--dot, var(--accent));
  box-shadow: 0 0 0 5px var(--surface);
}
@media (min-width: 900px) {
  .r-phase { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: 0.6rem 3rem; align-items: start; }
}

/* ================= E. EMPHASIS BLOCK =================
   The page's single theme switch (Section 4.11 exception: one deliberate
   Color Block Story, not random alternation). */
.r-emphasis { background: var(--emphasis); color: var(--on-emphasis); }
.r-emphasis h2, .r-emphasis h3 { color: var(--on-emphasis); }
.r-emphasis p { color: var(--on-emphasis-muted); }
.r-panel {
  border-radius: 1.125rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  background: color-mix(in srgb, var(--on-emphasis) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-emphasis) 14%, transparent);
}
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .r-panel { background: rgba(253, 250, 246, 0.06); border-color: rgba(253, 250, 246, 0.14); }
}
.r-input {
  width: 100%;
  border-radius: 0.75rem;
  padding: 0.95rem 1rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  font-size: 1rem;
}
.r-input::placeholder { color: var(--muted); }

/* ---- Shared ---- */
.r-eyebrow {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-strong);
}
.r-lead { color: var(--body); max-width: 52ch; }
.r-icon { display: inline-flex; color: var(--accent-strong); }
.r-icon svg { width: 1.55rem; height: 1.55rem; }
.r-cell--sage .r-icon { color: var(--sage); }
.r-emphasis .r-icon { color: var(--accent-strong); }

.r-badge {
  display: inline-block;
  border-radius: 9999px;
  padding: 0.3rem 0.75rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.r-btn-secondary {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--ink);
  border-radius: 9999px;
  box-shadow: 0 2px 10px rgba(28, 20, 16, 0.07);
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease,
              transform 0.25s ease, box-shadow 0.25s ease;
}
.r-btn-secondary:hover {
  background: var(--ink);
  color: var(--surface);
  border-color: var(--ink);
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(28, 20, 16, 0.16);
}
.r-btn-secondary:active { transform: translateY(0) scale(0.985); }

.r-btn-ghost {
  border: 1px solid color-mix(in srgb, var(--on-emphasis) 34%, transparent);
  color: var(--on-emphasis);
  border-radius: 9999px;
  transition: background-color 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}
.r-btn-ghost:hover {
  background: color-mix(in srgb, var(--on-emphasis) 10%, transparent);
  border-color: var(--on-emphasis);
  transform: translateY(-2px);
}
.r-btn-ghost:active { transform: translateY(0) scale(0.985); }

/* Stagger without per-element utility classes: the index drives the delay
   (Section 5.D, CSS cascade variant). */
.r-stagger > * { transition-delay: calc(var(--i, 0) * 90ms); }

/* Focus parity with the rest of the site. */
.r-nav a:focus-visible,
.r-nav button:focus-visible,
.r-nav-menu a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .r-cell, .r-btn-secondary, .r-btn-ghost, .r-nav-toggle span, .r-nav-menu { transition: none !important; }
  .r-cell:hover, .r-btn-secondary:hover, .r-btn-ghost:hover { transform: none; }
  .r-stagger > * { transition-delay: 0ms !important; }
}

/* ---- Contrast corrections found in the Section 14 pass ---- */

/* The hero headline arrives through data-i18n-html, and the translated string
   carries its own `text-terra-400` span. That hardcoded #E8714A measured
   2.93:1 on the cream ground, just under the 3:1 large-text floor. Rebinding
   it to the accent token fixes light (4.30:1) without touching copy in three
   languages, and improves dark too (6.20:1). */
h1 .text-terra-400,
h2 .text-terra-400 { color: var(--accent) !important; }

/* The active language button ran 4.30:1 at 11px, under the 4.5:1 floor for
   small text. accent-strong clears it at 5.92:1. */
.lang-btn.active { color: var(--accent-strong); }

/* The secondary CTA is surface-on-surface, which works in light but made the
   button invisible in dark: 1.00 separation from the page and a 1.58:1 border.
   Dark gets a lifted fill and an edge that actually clears 3:1. */
@media (prefers-color-scheme: dark) {
  .r-btn-secondary {
    background: #3D3128;
    border-color: #8A7460;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
  }
  .r-btn-secondary:hover {
    background: var(--ink);
    color: var(--surface);
    border-color: var(--ink);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.55);
  }
}

/* Step numerals on /install. The disc is accent-strong, which is DARK terra in
   light mode and LIGHT salmon in dark, so a pinned label colour fails one of
   them: --on-accent gave 2.14:1 in dark. --surface is the one token that
   always inverts opposite to --accent-strong, so it clears both.
   Light 5.92:1, dark 8.43:1. */
.r-numeral { background: var(--accent-strong); color: var(--surface); }

/* ---- Hero live pill ----
   The beta notice is a real status indicator, and it links to /install, so
   the hover state promises something that actually exists.

   Sage, and actually sage now: the old tint was 5% saturation in light, which
   is why it read grey. Glass dilutes hue toward the backdrop, so the fill is
   solved backwards from the colour it needs to composite to, not picked by
   eye. At 0.8 over the hero it lands on 12% saturation in light and 36% in
   dark.

   Glass per Section 5: not just a blur, but a 1px edge and an inset top
   highlight for refraction, with solid fallbacks for both no-backdrop-filter
   and prefers-reduced-transparency.

   Motion mirrors the demo phone's play button: a soft halo blooming outward
   on a loop, plus a scale on hover. The halo is a filled shape at low
   opacity, never a 1px ring. Transform and opacity only, so unlike the play
   button this costs no box-shadow repaints. */
.r-live-pill {
  --pill-hover: 1;
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 1.05rem;
  border-radius: 9999px;
  transform-origin: center;
  background: rgba(183, 218, 195, 0.8);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
  backdrop-filter: blur(10px) saturate(150%);
  border: 1px solid color-mix(in srgb, var(--sage) 30%, transparent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    0 1px 10px rgba(59, 94, 71, 0.1);
  transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.25s ease, background-color 0.25s ease;
}
.r-live-pill .r-eyebrow { color: #2B4E3B; }

@media (prefers-color-scheme: dark) {
  .r-live-pill {
    background: rgba(50, 89, 70, 0.8);
    border-color: color-mix(in srgb, var(--sage) 38%, transparent);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.1),
      0 1px 12px rgba(0, 0, 0, 0.3);
  }
  .r-live-pill .r-eyebrow { color: #AED6BA; }
}

/* Solid fallbacks: no blur support, or the reader has asked for less
   transparency. Both land on the same composited colour. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .r-live-pill { background: #C3DEC9; }
  @media (prefers-color-scheme: dark) { .r-live-pill { background: #33503F; } }
}
@media (prefers-reduced-transparency: reduce) {
  .r-live-pill { background: #C3DEC9; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-reduced-transparency: reduce) and (prefers-color-scheme: dark) {
  .r-live-pill { background: #33503F; }
}

.r-live-pill:hover {
  --pill-hover: 1.045;
  transform: scale(var(--pill-hover));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 4px 18px rgba(59, 94, 71, 0.18);
}
.r-live-pill:active { --pill-hover: 0.995; }
.r-live-pill:focus-visible {
  outline: 3px solid var(--sage);
  outline-offset: 3px;
}

/* The halo, blooming outward like the play button's pulse. */
.r-live-pill::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 9999px;
  background: var(--sage);
  opacity: 0;
  transform-origin: center;
}

@media (prefers-reduced-motion: no-preference) {
  .r-live-pill { animation: r-heartbeat 1.5s ease-in-out infinite; will-change: transform; }
  .r-live-pill::after { animation: r-heartbeat-halo 1.5s ease-out infinite; }
}

/* lub-dub, then just enough rest to keep it a pulse and not a throb */
@keyframes r-heartbeat {
  0%   { transform: scale(calc(var(--pill-hover) * 1)); }
  11%  { transform: scale(calc(var(--pill-hover) * 1.03)); }
  22%  { transform: scale(calc(var(--pill-hover) * 1.005)); }
  33%  { transform: scale(calc(var(--pill-hover) * 1.019)); }
  53%  { transform: scale(calc(var(--pill-hover) * 1)); }
  100% { transform: scale(calc(var(--pill-hover) * 1)); }
}
@keyframes r-heartbeat-halo {
  0%   { transform: scale(1);    opacity: 0.28; }
  60%  { transform: scale(1.18); opacity: 0; }
  100% { transform: scale(1.18); opacity: 0; }
}
