@import url("../../../_ds/fonts.css");
@import url("../../../_ds/theme.css");
@import url("../../../_shared/chrome.css");
@import url("../../../_shared/components.css");
@import url("../../../_shared/audience-switcher.css");

/* ──────────────────────────────────────────────────────────
   /workflows/serp-monitoring — Spoke page.

   Audience: SEO, growth, content teams.  Outcome: keyword
   rank tracking with daily diffs + drift alerts.

   Visual identity for the hero is The Rank Wall — a vertical
   rail running from #1 (top) to #20 (bottom) with keyword
   markers floating at their current rank.  Vertical
   orientation is the layout break vs the sibling spokes,
   each of which is horizontally oriented (terminal / brief /
   prices+Slack / drag-table).

   Brand accent for serp-monitoring is orange-6 — warm,
   attention-grabbing for drift alerts, distinct from the
   purple (CI) / cyan (PM, LE) family.

   WIP: Act 1 hero styled first.  Acts 2-4 land in follow-up
   commits.
─────────────────────────────────────────────────────────── */

body {
  overscroll-behavior-y: none;
}

main {
  position: relative;
}

.topbar {
  isolation: isolate;
  z-index: 200;
}

.back-to-top { cursor: pointer; }

/* ── Local accent scope ─────────────────────────────────── */
/* Brand-central colors are teal (positive movement, brand
   identity), orange is reserved for drift alerts (the rare,
   attention-worthy event).  Flat days fade to quaternary. */
[data-act="1"] {
  --sm-accent: var(--zen-orange-6, #F38C5A);
  --sm-accent-soft: rgba(243, 140, 90, 0.16);
  --sm-accent-border: rgba(243, 140, 90, 0.38);
  --sm-up: var(--zen-cyan-6, #7ADAE6);
  --sm-flat: var(--text-quaternary);
  --sm-down: var(--zen-orange-6, #F38C5A);
}

/* ──────────────────────────────────────────────────────────
   Act 1 — Hero (The Rank Wall).
   Centered artifact + H1 + slash-command row, same shape
   family as the other workflow heroes.
─────────────────────────────────────────────────────────── */

/* Sticky stage + curtain rise: the [data-act="1"] section is
   200vh tall and .sm-hero pins at top: 0 / height: 100vh —
   so the hero stays glued to the viewport for the first 100vh
   of stage scroll.  Act 2 (the next section) pulls itself up
   via margin-top: -100vh and z-index: 2, so it starts with
   its top edge at viewport bottom while the hero is pinned.
   As the user scrolls, Act 2 rises UP over the pinned hero
   (covering it from below) at the same time the hero is
   blurring + fading from the rAF scroll listener.  At
   scrollY ~100vh the curtain has fully covered the hero,
   the hero unpins, and Act 2 continues scrolling normally. */
[data-act="1"] {
  position: relative;
  min-height: 200vh;
  background: transparent;
  padding: 0;
  z-index: 1;
}

.sm-hero {
  position: sticky;
  top: 0;
  width: 100%;
  max-width: min(95vw, 1320px);
  margin: 0 auto;
  height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.1fr);
  column-gap: clamp(40px, 5vw, 88px);
  row-gap: clamp(40px, 6vh, 72px);
  align-items: center;
  padding: clamp(72px, 12vh, 120px) 0 clamp(48px, 8vh, 96px);
  box-sizing: border-box;
  will-change: filter, transform, opacity;
}

/* ── The Rank Wall ─────────────────────────────────────── */

.sm-wall {
  position: relative;
  width: 100%;
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-display, 20px);
  overflow: hidden;
  padding: clamp(20px, 2.4vh, 28px) clamp(20px, 2vw, 28px);
}

.sm-wall-head {
  margin: 0 0 clamp(18px, 2.4vh, 28px);
}

.sm-wall-meta {
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.sm-wall-meta-file { color: var(--sm-accent); font-weight: 600; }
.sm-wall-meta-sep  { color: var(--text-quaternary); }

/* ── Stage — holds scale, rail, and markers in a 3-col grid ─
   scale (axis labels) · rail (the vertical line) · markers
   (absolute, positioned by --rank).  The stage has fixed
   height so vertical % mapping is deterministic. */
.sm-wall-stage {
  position: relative;
  display: grid;
  grid-template-columns: clamp(44px, 5vw, 64px) clamp(2px, 0.2vw, 3px) minmax(0, 1fr);
  column-gap: clamp(16px, 2vw, 28px);
  height: clamp(440px, 56vh, 600px);
}

/* ── Scale axis — tick labels for #1, 5, 10, 15, 20 ────── */
.sm-wall-scale {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  height: 100%;
}
.sm-wall-scale li {
  position: absolute;
  right: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  transform: translateY(-50%);
  font-variant-numeric: tabular-nums;
}
/* Tick positions — each tick at (rank - 1) / 19 % of the
   stage height.  Mapping rank 1 → 0%, rank 20 → 100%. */
.sm-wall-scale li[data-tick="1"]  { top: 0%; }
.sm-wall-scale li[data-tick="5"]  { top: 21%; }
.sm-wall-scale li[data-tick="10"] { top: 47%; }
.sm-wall-scale li[data-tick="15"] { top: 74%; }
.sm-wall-scale li[data-tick="20"] { top: 100%; }

/* ── The rail — a single vertical hairline ─────────────── */
.sm-wall-rail {
  width: 1px;
  height: 100%;
  background: var(--border);
  justify-self: center;
  position: relative;
}

/* ── Markers — float on the rail at their current rank ─── */
.sm-wall-markers {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  height: 100%;
}

.sm-wall-marker {
  position: absolute;
  left: 0;
  right: 0;
  /* Rank → vertical position: (rank - 1) / 19 * 100% so
     rank 1 sits at top: 0% and rank 20 at top: 100%. */
  top: calc((var(--rank, 10) - 1) / 19 * 100%);
  transform: translate3d(0, -50%, 0);
  display: grid;
  grid-template-columns: 12px clamp(48px, 5vw, 64px) 1fr;
  column-gap: clamp(14px, 1.6vw, 22px);
  align-items: center;
  transition: top 900ms cubic-bezier(0.22, 1.4, 0.48, 1);
  will-change: top;
}

/* Dot — sits on the rail */
.sm-wall-marker-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--surface, #181210);
  border: 2px solid var(--text-primary);
  justify-self: center;
  margin-left: clamp(-30px, -3vw, -22px);
  position: relative;
  z-index: 2;
}

/* Delta indicator — replaces the sparkline. ↑/↓ arrow + a
   delta number that counts up from 0 to the target on reveal
   (driven by JS, set on .sm-wall-marker-delta-num).  Reads
   as a log line ("dropped 5 overnight"), not a fake mini
   chart.  Trend color = brand teal for up, orange-accent for
   down (= the alert color), text-quaternary for flat. */
.sm-wall-marker-delta {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-sm);
  font-weight: 700;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--sm-flat);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 460ms ease, transform 460ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-wall.is-revealed .sm-wall-marker-delta {
  opacity: 1;
  transform: none;
}
.sm-wall-marker[data-trend="up"]   .sm-wall-marker-delta { color: var(--sm-up); }
.sm-wall-marker[data-trend="down"] .sm-wall-marker-delta { color: var(--sm-down); }
.sm-wall-marker[data-trend="flat"] .sm-wall-marker-delta { color: var(--sm-flat); }

.sm-wall-marker-delta-arrow {
  font-size: 1.1em;
  line-height: 1;
}
.sm-wall-marker-delta-num {
  display: inline-block;
  min-width: 0.7em;
}

/* Reveal stagger — matches the marker drop-in (120ms apart,
   delta fades in just after each marker settles). */
.sm-wall.is-revealed .sm-wall-marker:nth-child(1) .sm-wall-marker-delta { transition-delay: 360ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(2) .sm-wall-marker-delta { transition-delay: 480ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(3) .sm-wall-marker-delta { transition-delay: 600ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(4) .sm-wall-marker-delta { transition-delay: 720ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(5) .sm-wall-marker-delta { transition-delay: 840ms; }

/* Info block — rank number + keyword + optional badge */
.sm-wall-marker-info {
  display: inline-flex;
  align-items: baseline;
  gap: clamp(10px, 1.2vw, 16px);
  min-width: 0;
}
.sm-wall-marker-rank {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body);
  font-weight: 700;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.sm-wall-marker-kw {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: var(--mkt-body-sm);
  color: var(--text-secondary);
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Alert marker — drift badge + accent dot ──────────── */
.sm-wall-marker--alert .sm-wall-marker-dot {
  border-color: var(--sm-accent);
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--sm-accent) 18%, transparent),
    0 0 16px color-mix(in srgb, var(--sm-accent) 32%, transparent);
}
/* Idle breathing pulse — kicks in after the drift demo
   finishes so the alert keeps reading as "live" forever,
   not just a one-time visual.  Halo expands ~40% on the
   pulse peak, stays subtle to not become annoying. */
.sm-wall.is-revealed .sm-wall-marker--alert .sm-wall-marker-dot {
  animation: sm-alert-pulse 2.4s ease-in-out infinite;
  animation-delay: 4s;
}
@keyframes sm-alert-pulse {
  0%, 100% {
    box-shadow:
      0 0 0 4px color-mix(in srgb, var(--sm-accent) 18%, transparent),
      0 0 16px color-mix(in srgb, var(--sm-accent) 32%, transparent);
  }
  50% {
    box-shadow:
      0 0 0 7px color-mix(in srgb, var(--sm-accent) 26%, transparent),
      0 0 26px color-mix(in srgb, var(--sm-accent) 56%, transparent);
  }
}
.sm-wall-marker--alert .sm-wall-marker-rank {
  color: var(--sm-accent);
}
.sm-wall-marker-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--sm-accent);
  background: var(--sm-accent-soft);
  border: 1px solid var(--sm-accent-border);
  border-radius: var(--radius-full, 999px);
  white-space: nowrap;
}

/* ── Enter animation ────────────────────────────────────
   Before is-revealed: every marker stacked at the bottom
   (rank 20), opacity 0.  On reveal: each marker animates
   to its target --rank position with a stagger via
   transition-delay.  The spring overshoot in the easing
   curve (cubic-bezier 1.4 on the 2nd control point) makes
   each marker "snap" into place. */
.sm-wall:not(.is-revealed) .sm-wall-marker {
  top: 100%;
  opacity: 0;
}
.sm-wall.is-revealed .sm-wall-marker {
  opacity: 1;
  transition:
    top 900ms cubic-bezier(0.22, 1.4, 0.48, 1),
    opacity 500ms ease;
}
.sm-wall.is-revealed .sm-wall-marker:nth-child(1) { transition-delay:   0ms,   0ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(2) { transition-delay: 120ms, 120ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(3) { transition-delay: 240ms, 240ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(4) { transition-delay: 360ms, 360ms; }
.sm-wall.is-revealed .sm-wall-marker:nth-child(5) { transition-delay: 480ms, 480ms; }

/* Drift demo — when the alert marker is rewinding back to
   its previous rank, the transition is slower + the easing
   feels "weightless" to read as undo.  When it's dropping
   back to current, the easing is heavier + a horizontal
   shake punctuates the moment. */
.sm-wall-marker.is-rewinding {
  transition: top 700ms ease-in-out !important;
}
.sm-wall-marker.is-dropping {
  transition: top 800ms cubic-bezier(0.55, 0, 0.22, 1.6) !important;
  animation: sm-drift-shake 480ms ease-out 1;
}
@keyframes sm-drift-shake {
  0%, 100% { transform: translate3d(0, -50%, 0); }
  25%      { transform: translate3d(-4px, -50%, 0); }
  50%      { transform: translate3d( 4px, -50%, 0); }
  75%      { transform: translate3d(-2px, -50%, 0); }
}

/* ──────────────────────────────────────────────────────────
   Hero row — H1 left + slash-command copy widget right.
   Same pattern as sibling spokes.
─────────────────────────────────────────────────────────── */

/* In the side-by-side hero, this column stacks h1 on top
   of the slash-command widget vertically.  On narrow viewports
   (< 1100px) the .sm-hero grid collapses to one column and
   this stack appears below the rank wall — no change needed
   here, the flex stack works either way. */
.sm-hero-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(20px, 3.2vh, 32px);
  width: 100%;
  padding: 0;
}

.sm-hero-h {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.04;
  letter-spacing: -0.025em;
  color: var(--text-primary);
  font-weight: 500;
}
.sm-hero-h em {
  font-style: normal;
  font-weight: 400;
  color: inherit;
}

/* ── Slash-command copy widget ─────────────────────────── */
.sm-hero-cmd {
  position: relative;
  appearance: none;
  border: 1px solid var(--border-subtle);
  background: var(--sunken-base, rgba(255, 255, 255, 0.04));
  border-radius: 12px;
  padding: 14px 18px;
  display: inline-flex;
  align-items: center;
  gap: 14px;
  color: var(--text-primary);
  cursor: pointer;
  max-width: 440px;
  transition:
    border-color 220ms ease,
    background-color 220ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-hero-cmd:hover,
.sm-hero-cmd:focus-visible {
  border-color: color-mix(in srgb, var(--sm-accent) 45%, var(--border-subtle));
  transform: translateY(-1px);
}
.sm-hero-cmd.is-copied {
  border-color: var(--sm-accent);
}
.sm-hero-cmd-meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-right: 12px;
  border-right: 1px solid var(--border-subtle);
}
.sm-hero-cmd-prompt {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 14px;
  color: var(--sm-accent);
}
.sm-hero-cmd-label {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.sm-hero-cmd-code {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.005em;
}
.sm-hero-cmd-hint {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-quaternary);
}
.sm-hero-cmd.is-copied .sm-hero-cmd-hint {
  color: var(--sm-accent);
}
.sm-hero-cmd,
.sm-hero-cmd * { cursor: pointer; }

/* ── H1 row reveal ─────────────────────────────────────── */
.sm-hero-row[data-ci-reveal] > * {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(8px);
  transition:
    opacity 640ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 640ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 540ms ease;
}
.sm-hero-row[data-ci-reveal].is-revealed > * {
  opacity: 1;
  transform: none;
  filter: blur(0);
}
.sm-hero-row[data-ci-reveal].is-revealed > *:nth-child(1) { transition-delay:   0ms; }
.sm-hero-row[data-ci-reveal].is-revealed > *:nth-child(2) { transition-delay: 140ms; }

/* ── Responsive ──────────────────────────────────────── */

/* >= 1100px: side-by-side hero — copy LEFT, wall RIGHT.
   Order swap because the wall comes first in DOM (for the
   stacked mobile flow), but we want copy first visually on
   wide screens so the reader hits the headline first. */
@media (min-width: 1100px) {
  .sm-hero-row { order: 1; }
  .sm-wall { order: 2; }
}

/* < 1100px: collapse to single column AND drop the sticky
   stage.  Sticky-blur on phones/tablets makes the hero feel
   stuck and the blur effect is unreadable on small screens.
   Mobile gets a normal flow hero with the wall on top. */
@media (max-width: 1099px) {
  [data-act="1"] {
    min-height: auto;
    padding: clamp(96px, 13vh, 140px) 0 clamp(72px, 10vh, 120px);
  }
  .sm-hero {
    position: relative;
    top: auto;
    height: auto;
    min-height: 0;
    padding: 0;
    grid-template-columns: 1fr;
    filter: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* No curtain rise on phones — Act 2 flows in document
     order (sticky stage drops).  !important because the base
     rule with margin-top: -100vh is defined AFTER this media
     query in the file (source order wins ties on specificity)
     — without !important the curtain rise still applies on
     mobile and Act 2 covers the hero on first paint. */
  [data-act="2"].sm-how-section {
    margin-top: 0 !important;
  }
}

@media (max-width: 900px) {
  .sm-hero-cmd { max-width: 100%; }
  .sm-wall-stage {
    grid-template-columns: clamp(36px, 7vw, 48px) 2px minmax(0, 1fr);
    column-gap: 14px;
    height: clamp(380px, 60vh, 520px);
  }
  .sm-wall-marker { grid-template-columns: 12px clamp(40px, 11vw, 56px) 1fr; column-gap: 12px; }
}

@media (max-width: 600px) {
  .sm-hero-h { font-size: var(--mkt-h3); }
  .sm-wall-marker-kw { font-size: 12px; }
  .sm-wall-marker-delta { font-size: 12px; }
}

@media (min-width: 1600px) {
  .sm-hero { max-width: min(95vw, 1480px); }
  .sm-hero-h { font-size: 68px; }
  .sm-wall-stage { height: clamp(520px, 60vh, 680px); }
}
@media (min-width: 1920px) {
  .sm-hero { max-width: min(95vw, 1680px); }
  .sm-hero-h { font-size: 76px; }
  .sm-wall-stage { height: clamp(560px, 60vh, 720px); }
}
@media (min-width: 2400px) {
  .sm-hero { max-width: min(95vw, 1960px); }
  .sm-hero-h { font-size: 92px; }
  .sm-wall-stage { height: clamp(640px, 60vh, 820px); }
}

@media (prefers-reduced-motion: reduce) {
  .sm-wall-marker { transition: none; }
  .sm-wall-marker.is-dropping { animation: none; }
  .sm-wall-marker-delta {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .sm-wall.is-revealed .sm-wall-marker--alert .sm-wall-marker-dot {
    animation: none;
  }
  .sm-hero-row[data-ci-reveal] > * {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
}

/* ──────────────────────────────────────────────────────────
   Act 2 — How it works (teal band).

   Flat saturated teal-7 brand band, no gradient.  All text
   sits dark (warm zen-gray) on the teal so the band reads
   as a saturated editorial spread, not a mood image.
   Per-beat layout alternates left/right via
   .sm-how-step--mirror to break ritmo.  Orange shows up
   only on the drift cues in 04/05 — teal stays central.

   Dark-on-teal palette:
     ink: #1D1612 (warm zen-gray-1)
     soft text:   rgba(29, 22, 18, 0.74)
     muted text:  rgba(29, 22, 18, 0.55)
     hairline:    rgba(29, 22, 18, 0.20)
     subtle fill: rgba(29, 22, 18, 0.06)
─────────────────────────────────────────────────────────── */

[data-act="2"].sm-how-section {
  /* Curtain rise: pulled up 100vh into Act 1's stage so the
     teal band starts with its top at viewport bottom while
     the hero is pinned.  Higher z-index stacks Act 2 above
     the hero during the visual overlap — Act 2 LITERALLY
     covers the hero from below as the user scrolls.

     Background is teal-5 hardcoded as #7ADAE6 — the brand
     band color used on /mcp, /cli, etc.
     Don't use var(--zen-cyan-5) here: in dark mode the DS
     token inverts to a dark gray-teal, which is NOT the
     brand band.  DESIGN.md mandates the hardcoded hex for
     band acts that must read the same in both modes. */
  /* @pattern curtain-rise START
     Canonical "next act rises over the previous sticky stage" trick.
     Apply to the act immediately following a sticky-stage act.  As the
     user scrolls, this section pulls itself up via margin-top: -100vh
     and z-index: 2, covering the pinned hero from below.  At scroll
     ~100vh the hero is fully covered and unpins, this section continues
     scrolling normally.  Topbar inversion via body.is-on-teal fires
     mid-rise (rAF-throttled watcher on this section's rect.top).
     Mobile must override `margin-top: 0 !important` to disable.
     See docs/patterns.md → curtain-rise. */
  position: relative;
  z-index: 2;
  margin-top: -100vh;
  isolation: isolate;
  overflow: clip;
  background: #7ADAE6;
  color: #1D1612;
  padding: clamp(96px, 14vh, 160px) clamp(20px, 5vw, 80px) clamp(120px, 18vh, 200px);
  /* @pattern curtain-rise END */
}

.sm-how {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: min(95vw, 1240px);
  margin: 0 auto;
}

/* ── Headline block ─────────────────────────────────── */
.sm-how-head {
  max-width: 720px;
  margin: 0 0 clamp(64px, 10vh, 120px);
}
.sm-how-kicker {
  margin: 0 0 16px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(29, 22, 18, 0.62);
}
.sm-how-h {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.06;
  letter-spacing: -0.024em;
  font-weight: 500;
  color: #1D1612;
  text-wrap: balance;
}
.sm-how-h em {
  font-style: normal;
  font-weight: 500;
  color: inherit;
}
.sm-how-sub {
  margin: clamp(18px, 2.4vh, 28px) 0 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.55;
  color: rgba(29, 22, 18, 0.78);
  max-width: 600px;
  text-wrap: pretty;
}

/* ── Steps list ─────────────────────────────────────── */
.sm-how-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(80px, 13vh, 140px);
}

/* Scroll-linked progress model.  Each step gets --sm-progress
   set by JS based on its position in viewport (0 when entering
   from below, 1 when fully landed).  All inner animations
   (clock hand, engines, etc.) read that var via calc/clamp,
   so they play in REVERSE smoothly when the user scrolls up
   (progress goes 1 → 0).  No class toggles → no replaying
   forward on re-entry. */
.sm-how-step {
  --sm-progress: 0;
  display: grid;
  grid-template-columns: clamp(72px, 8vw, 120px) minmax(0, 1fr);
  column-gap: clamp(32px, 5vw, 80px);
  align-items: start;
  /* Parent fade-in in the first 18% of progress, then stays
     visible.  Quick fade so inner animations have room. */
  opacity: clamp(0, calc(var(--sm-progress) * 5.55), 1);
  transform: translateY(calc(28px * (1 - var(--sm-progress))));
  /* Smoothing transitions — scroll-linked progress jumps in
     discrete frames; a short ease softens both forward
     (down) and reverse (up) so the animation feels animated,
     not snapped. */
  transition:
    opacity 320ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Mirrored beats — body on the left, big number on the
   right.  Breaks ritmo every other step. */
.sm-how-step--mirror {
  grid-template-columns: minmax(0, 1fr) clamp(72px, 8vw, 120px);
}
.sm-how-step--mirror .sm-how-n {
  order: 2;
  justify-self: end;
}
.sm-how-step--mirror .sm-how-body {
  order: 1;
  text-align: left;
}

.sm-how-n {
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: clamp(64px, 8vw, 128px);
  line-height: 0.92;
  letter-spacing: -0.04em;
  font-weight: 500;
  color: rgba(29, 22, 18, 0.22);
  font-variant-numeric: tabular-nums;
}

.sm-how-body {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vh, 22px);
  min-width: 0;
}

.sm-how-step-h {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h4);
  line-height: 1.12;
  letter-spacing: -0.018em;
  font-weight: 500;
  color: #1D1612;
}
.sm-how-step-p {
  margin: 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body-sm);
  line-height: 1.55;
  color: rgba(29, 22, 18, 0.78);
  max-width: 56ch;
  text-wrap: pretty;
}
.sm-how-step-p code {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 0.92em;
  background: rgba(29, 22, 18, 0.10);
  color: #1D1612;
  padding: 1px 6px;
  border-radius: 4px;
}

.sm-how-art {
  margin-top: clamp(10px, 1.6vh, 18px);
  width: 100%;
  max-width: 560px;
}

/* ── 01 Define — keyword chips ──────────────────────── */
.sm-how-kw ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
}
.sm-how-kw li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 13px;
  color: #1D1612;
  background: rgba(29, 22, 18, 0.06);
  border: 1px solid rgba(29, 22, 18, 0.18);
  border-radius: 999px;
  padding: 6px 12px 6px 8px;
  white-space: nowrap;
}
.sm-how-kw-tick {
  font-weight: 600;
  color: rgba(29, 22, 18, 0.55);
}
.sm-how-kw-more {
  color: rgba(29, 22, 18, 0.62);
  background: transparent;
  border-color: rgba(29, 22, 18, 0.22);
  border-style: dashed;
}

/* ── 02 Schedule — 24h clock ────────────────────────── */
.sm-how-clock {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  color: #1D1612;
}
.sm-how-clock svg {
  width: 140px;
  height: 140px;
  display: block;
}
/* Hand sweeps 12 → 06 mapped to progress 0.20 → 0.85, dot
   fades in over 0.85 → 1.00.  Reverses smoothly on scroll
   up because progress decreases.  All divisors are literal
   constants (not var-expressions) so the calc re-evaluates
   reliably on every --sm-progress change. */
.sm-how-clock-hand {
  transform-origin: 60px 60px;
  transform: rotate(calc(-90deg + 90deg * clamp(0, calc((var(--sm-progress, 0) - 0.20) / 0.65), 1)));
  transition: transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-how-clock-dot {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.85) * 6.67), 1);
  filter: drop-shadow(0 0 6px rgba(29, 22, 18, 0.4));
  transition: opacity 280ms ease;
}
.sm-how-clock-label {
  margin: 0;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(29, 22, 18, 0.78);
}

/* ── 03 Query — engine grid ─────────────────────────── */
.sm-how-engines ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Engine list cascade — every divisor and subtractand is a
   literal so the calc re-evaluates reliably on every
   --sm-progress change. */
.sm-how-engines li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 10px 14px;
  background: rgba(29, 22, 18, 0.05);
  border: 1px solid rgba(29, 22, 18, 0.16);
  border-radius: 8px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 13px;
  color: #1D1612;
  transition:
    opacity 280ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-how-engines li[data-engine-step="1"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.20) * 5), 1);
  transform: translateX(calc(-12px + 12px * clamp(0, calc((var(--sm-progress, 0) - 0.20) * 5), 1)));
}
.sm-how-engines li[data-engine-step="2"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.30) * 5), 1);
  transform: translateX(calc(-12px + 12px * clamp(0, calc((var(--sm-progress, 0) - 0.30) * 5), 1)));
}
.sm-how-engines li[data-engine-step="3"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.40) * 5), 1);
  transform: translateX(calc(-12px + 12px * clamp(0, calc((var(--sm-progress, 0) - 0.40) * 5), 1)));
}
.sm-how-engines li[data-engine-step="4"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.50) * 5), 1);
  transform: translateX(calc(-12px + 12px * clamp(0, calc((var(--sm-progress, 0) - 0.50) * 5), 1)));
}
.sm-how-engines li[data-engine-step="5"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.60) * 5), 1);
  transform: translateX(calc(-12px + 12px * clamp(0, calc((var(--sm-progress, 0) - 0.60) * 5), 1)));
}
.sm-how-engine-name {
  letter-spacing: -0.005em;
}
.sm-how-engine-status {
  padding: 2px 8px;
  background: rgba(29, 22, 18, 0.10);
  border-radius: 4px;
  font-weight: 600;
  color: #1D1612;
  letter-spacing: 0.04em;
}

/* ── 04 Diff — yesterday vs today table ─────────────── */
.sm-how-diff {
  background: rgba(29, 22, 18, 0.05);
  border: 1px solid rgba(29, 22, 18, 0.18);
  border-radius: 12px;
  overflow: hidden;
}
.sm-how-diff table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 13px;
  color: #1D1612;
}
.sm-how-diff th,
.sm-how-diff td {
  text-align: left;
  padding: 10px 16px;
  border-bottom: 1px solid rgba(29, 22, 18, 0.12);
}
.sm-how-diff thead th {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(29, 22, 18, 0.60);
  background: rgba(29, 22, 18, 0.04);
}
.sm-how-diff th:nth-child(2),
.sm-how-diff th:nth-child(3),
.sm-how-diff th:nth-child(4),
.sm-how-diff td:nth-child(2),
.sm-how-diff td:nth-child(3),
.sm-how-diff td:nth-child(4) {
  text-align: right;
  width: 64px;
  font-variant-numeric: tabular-nums;
}
.sm-how-diff tbody tr:last-child td {
  border-bottom: none;
}

/* Scroll-linked cascade for the diff rows — each row maps a
   range of --sm-progress so they cascade in/out smoothly
   in both scroll directions.  Same 0.20-window stagger
   pattern as the engine list. */
.sm-how-diff tbody tr {
  transition:
    opacity 280ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
    background-color 180ms ease;
}
.sm-how-diff tbody tr[data-row-step="1"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.20) * 5), 1);
  transform: translateY(calc(10px - 10px * clamp(0, calc((var(--sm-progress, 0) - 0.20) * 5), 1)));
}
.sm-how-diff tbody tr[data-row-step="2"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.30) * 5), 1);
  transform: translateY(calc(10px - 10px * clamp(0, calc((var(--sm-progress, 0) - 0.30) * 5), 1)));
}
.sm-how-diff tbody tr[data-row-step="3"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.40) * 5), 1);
  transform: translateY(calc(10px - 10px * clamp(0, calc((var(--sm-progress, 0) - 0.40) * 5), 1)));
}
.sm-how-diff tbody tr[data-row-step="4"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.50) * 5), 1);
  transform: translateY(calc(10px - 10px * clamp(0, calc((var(--sm-progress, 0) - 0.50) * 5), 1)));
}
.sm-how-diff tbody tr[data-row-step="5"] {
  opacity: clamp(0, calc((var(--sm-progress, 0) - 0.60) * 5), 1);
  transform: translateY(calc(10px - 10px * clamp(0, calc((var(--sm-progress, 0) - 0.60) * 5), 1)));
}
.sm-how-diff td:first-child {
  color: #1D1612;
}
.sm-how-diff-up   { color: #1D1612; font-weight: 600; }
.sm-how-diff-flat { color: rgba(29, 22, 18, 0.40); }
.sm-how-diff-down { color: #A8421C; font-weight: 600; }
.sm-how-diff-alert {
  background: rgba(168, 66, 28, 0.10);
}
.sm-how-diff-alert td:first-child {
  color: #A8421C;
  font-weight: 600;
}

/* ── 05 Alert — minimal notification card ───────────────
   Editorial notification primitive.  Default state is a
   transparent card with only a dark hairline border — the
   teal band shows through.  On hover the card fills white
   and gets a teal-tinted soft shadow.  Header is one line:
   purple Zenrows wordmark + the timestamp pushed right.
   No CTA — this is a static demo of what an alert looks
   like, not a real action surface. */
.sm-how-alert {
  max-width: 440px;
}
.sm-how-alert-card {
  background: transparent;
  color: #1D1612;
  border: 1px solid rgba(29, 22, 18, 0.22);
  border-radius: 10px;
  padding: 18px 20px 16px;
  font-family: var(--font-base);
  transition:
    background-color 240ms ease,
    box-shadow 240ms ease,
    border-color 240ms ease,
    transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-how-alert-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
  font-size: 12px;
  color: rgba(29, 22, 18, 0.62);
}
.sm-how-alert-mark {
  /* Wordmark from /_assets/zenrows-logo.svg painted brand
     purple-7 (#7C4FE8) via mask-image — same SVG asset the
     homepage topbar uses, just recolorized. */
  display: inline-block;
  width: 72px;
  height: 16px;
  background-color: #7C4FE8;
  -webkit-mask-image: url("../../../_assets/zenrows-logo.svg");
  mask-image: url("../../../_assets/zenrows-logo.svg");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: left center;
  mask-position: left center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.sm-how-alert-time {
  margin-left: auto;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(29, 22, 18, 0.55);
}
.sm-how-alert-title {
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: #1D1612;
}
.sm-how-alert-body {
  margin: 0;
  font-size: 13.5px;
  color: rgba(29, 22, 18, 0.78);
  line-height: 1.55;
}
.sm-how-alert-body code {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 0.92em;
  background: rgba(29, 22, 18, 0.08);
  color: #1D1612;
  padding: 1px 5px;
  border-radius: 3px;
}

/* ── Responsive (Act 2) ─────────────────────────────── */
@media (max-width: 900px) {
  .sm-how-step,
  .sm-how-step--mirror {
    grid-template-columns: 1fr;
    row-gap: 12px;
  }
  .sm-how-step--mirror .sm-how-n { order: 0; justify-self: start; }
  .sm-how-step--mirror .sm-how-body { order: 0; }
  .sm-how-n { font-size: clamp(56px, 14vw, 88px); }
  .sm-how-step-h { font-size: var(--mkt-h4); }
  .sm-how-h { font-size: var(--mkt-h4); }
  .sm-how-steps { gap: clamp(56px, 11vh, 88px); }
}

@media (max-width: 600px) {
  .sm-how-diff th,
  .sm-how-diff td {
    padding: 8px 10px;
  }
  .sm-how-diff th:nth-child(2),
  .sm-how-diff th:nth-child(3),
  .sm-how-diff th:nth-child(4),
  .sm-how-diff td:nth-child(2),
  .sm-how-diff td:nth-child(3),
  .sm-how-diff td:nth-child(4) {
    width: 48px;
  }
  .sm-how-engines li { padding: 8px 12px; gap: 12px; }
  .sm-how-alert-card { padding: 14px 16px 12px; }
}

@media (min-width: 1600px) {
  .sm-how { max-width: min(95vw, 1380px); }
  .sm-how-h { font-size: 64px; }
  .sm-how-step-h { font-size: 34px; }
  .sm-how-step-p { font-size: 17px; }
  .sm-how-n { font-size: 140px; }
  .sm-how-art { max-width: 640px; }
  .sm-how-alert { max-width: 520px; }
  .sm-how-clock svg { width: 160px; height: 160px; }
}
@media (min-width: 1920px) {
  .sm-how { max-width: min(95vw, 1560px); }
  .sm-how-h { font-size: 72px; }
  .sm-how-step-h { font-size: 38px; }
  .sm-how-step-p { font-size: 18px; }
  .sm-how-n { font-size: 156px; }
  .sm-how-art { max-width: 720px; }
  .sm-how-alert { max-width: 560px; }
  .sm-how-clock svg { width: 180px; height: 180px; }
  .sm-how-diff table,
  .sm-how-engines li { font-size: 14px; }
}
@media (min-width: 2400px) {
  .sm-how { max-width: min(95vw, 1820px); }
  .sm-how-h { font-size: 88px; }
  .sm-how-step-h { font-size: 44px; }
  .sm-how-step-p { font-size: 20px; }
  .sm-how-n { font-size: 184px; }
  .sm-how-art { max-width: 840px; }
  .sm-how-alert { max-width: 640px; }
  .sm-how-clock svg { width: 220px; height: 220px; }
  .sm-how-diff table,
  .sm-how-engines li { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .sm-how-step {
    --sm-progress: 1;
  }
  [data-act="1"] {
    min-height: 100vh;
  }
  .sm-hero {
    position: relative;
    height: auto;
    min-height: 100vh;
    filter: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ──────────────────────────────────────────────────────────
   Interactive surfaces — hover transitions + cursor portal.

   Every surface listed in the JS cursorSelector gets
   `cursor: pointer` (plus children) so the spinning O follower
   is the sole pointer on hover.  Hover state itself is a
   subtle background/border lift + 220ms ease so the act
   feels alive without bouncing.
─────────────────────────────────────────────────────────── */

/* ── Act 1: wall markers — hover lifts the marker and
       brightens the row.  Drift demo's transform overrides
       this via !important during the rewinding/dropping
       phases, so hover-feel only activates after the demo. */
.sm-wall-marker,
.sm-wall-marker * { cursor: pointer; }
.sm-wall-marker {
  /* The base translateY(-50%) keeps each marker centered on
     its rank line; the hover state adds a translateX for a
     subtle "leaning into the rail" feel. */
}
.sm-wall.is-revealed .sm-wall-marker:hover .sm-wall-marker-rank {
  color: var(--sm-accent);
  transition: color 200ms ease;
}
.sm-wall.is-revealed .sm-wall-marker:hover .sm-wall-marker-kw {
  color: var(--text-primary);
  transition: color 200ms ease;
}

/* ── Act 2: keyword chips ─────────────────────────────── */
.sm-how-kw li,
.sm-how-kw li * { cursor: pointer; }
.sm-how-kw li {
  transition:
    background-color 200ms ease,
    border-color 200ms ease,
    transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-how-kw li:not(.sm-how-kw-more):hover {
  background: rgba(29, 22, 18, 0.12);
  border-color: rgba(29, 22, 18, 0.34);
  transform: translateY(-1px);
}
.sm-how-kw-more:hover {
  border-color: rgba(29, 22, 18, 0.38);
  color: rgba(29, 22, 18, 0.86);
  transform: translateY(-1px);
}

/* ── Act 2: engine rows ───────────────────────────────── */
.sm-how-engines li,
.sm-how-engines li * { cursor: pointer; }
.sm-how-engines li {
  /* The existing reveal cascade transitions opacity/transform
     so hover composites onto a separate transform vector via
     translateX — the slight rightward nudge reads as "row
     ready to fire". */
}
.sm-how-step[data-step="03"] .sm-how-engines li:hover {
  background: rgba(29, 22, 18, 0.12);
  border-color: rgba(29, 22, 18, 0.32);
  transform: translateX(4px);
  transition: background-color 200ms ease, border-color 200ms ease, transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-how-step[data-step="03"] .sm-how-engines li:hover .sm-how-engine-status {
  background: rgba(29, 22, 18, 0.18);
}

/* ── Act 2: diff rows ─────────────────────────────────── */
.sm-how-diff tbody tr,
.sm-how-diff tbody tr * { cursor: pointer; }
.sm-how-diff tbody tr {
  transition: background-color 180ms ease;
}
.sm-how-diff tbody tr:not(.sm-how-diff-alert):hover {
  background: rgba(29, 22, 18, 0.08);
}
.sm-how-diff-alert {
  transition: background-color 200ms ease;
}
.sm-how-diff-alert:hover {
  background: rgba(168, 66, 28, 0.18);
}

/* ── Act 2: Slack-style alert card ────────────────────── */
.sm-how-alert-card,
.sm-how-alert-card * { cursor: pointer; }
.sm-how-alert-card:hover {
  background: #FFFFFF;
  border-color: rgba(29, 22, 18, 0.10);
  transform: translateY(-3px);
  /* Teal glow — saturated teal-7 (#2BA8B8) at moderate
     alpha so the drop reads as a teal halo, not a dark
     shadow.  Wider blur + bigger spread amplifies the
     "belongs to the teal surface" feel. */
  box-shadow:
    0 26px 60px rgba(43, 168, 184, 0.55),
    0 8px 20px rgba(43, 168, 184, 0.32);
}

/* ──────────────────────────────────────────────────────────
   Topbar adaptation on the teal band.

   When the teal-5 Act 2 covers the viewport top, body gets
   .is-on-teal (set by serp-monitoring.js initTealTopbar).
   The topbar swaps from white-on-dark to dark-on-teal so
   the chrome stays legible over the saturated surface, and
   the cursor portal flips from teal-5 (invisible on teal)
   to purple-7 (the contrast color).  Pattern copied 1:1
   from /mcp + /cli.
─────────────────────────────────────────────────────────── */



/* ──────────────────────────────────────────────────────────
   Act 3 — The shape of your rankings.

   Returns to dark background after the teal Act 2 band.  A
   single editorial line chart shows 12 weeks of rank history
   for one keyword, painting in as the section enters the
   viewport.  Three HTML annotation callouts pin over chart
   anchor dots and fade in at their progress thresholds.
   Scroll-linked via --sm-shape-progress (0 → 1).
─────────────────────────────────────────────────────────── */

/* Sticky stage: section is 220vh tall (= 100vh pinned +
   120vh of scroll budget for paint).  .sm-shape-frame pins
   at top: 0 / height: 100vh while the user scrolls through.
   Scroll-linked --sm-shape-progress is mapped to the stage
   scroll range (not the section's viewport position), so
   the chart paints in sync with scroll and the user keeps
   moving once it's done. */
[data-act="3"].sm-shape-section {
  --sm-shape-progress: 0;
  position: relative;
  z-index: 3;
  min-height: 220vh;
  background: transparent;
  padding: 0;
  color: var(--text-primary);
}

.sm-shape-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  /* justify-content: flex-start so content anchors to the
     padding-top edge.  With center, when content was taller
     than the available area it overflowed UPWARD past the
     padding and tucked under the topbar.  flex-start makes
     overflow go DOWNWARD into hidden territory instead. */
  justify-content: flex-start;
  align-items: stretch;
  /* tighter top/bottom so head + chart + foot all fit (and the foot is not
     clipped by overflow:hidden) on short laptop viewports, not just tall ones. */
  padding: clamp(80px, 9vh, 116px) clamp(20px, 5vw, 80px) clamp(28px, 3.5vh, 60px);
  box-sizing: border-box;
  overflow: hidden;
}

.sm-shape {
  position: relative;
  width: 100%;
  max-width: min(95vw, 1320px);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 2vh, 28px);
}

.sm-shape-head {
  /* Wide enough so "Twelve weeks of one keyword." stays on
     one line at large H1 sizes — the line-break only happens
     at the explicit <br/>.  Was 720px which forced a third
     wrap line at wide-tier H1 sizes. */
  max-width: clamp(720px, 60vw, 1080px);
}
.sm-shape-kicker {
  margin: 0 0 16px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.sm-shape-h {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.06;
  letter-spacing: -0.024em;
  font-weight: 500;
  color: var(--text-primary);
  text-wrap: balance;
}
.sm-shape-h em {
  font-style: normal;
  font-weight: 500;
  color: inherit;
}
.sm-shape-sub {
  margin: clamp(18px, 2.4vh, 28px) 0 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 60ch;
  text-wrap: pretty;
}

/* ── Chart frame ────────────────────────────────────────── */
.sm-shape-chart {
  position: relative;
  width: 100%;
  margin: 0;
  /* Flatter aspect (3.85:1 instead of 3.15:1) so head + chart
     + foot all fit inside a 768px-tall laptop viewport once
     the topbar clearance + bottom padding are subtracted. */
  aspect-ratio: 1200 / 300;
  /* Hairline frame + subtle inner gradient so the chart reads
     as an editorial figure, not a UI panel. */
  background: linear-gradient(
    to bottom,
    rgba(122, 218, 230, 0.02) 0%,
    transparent 100%
  );
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}
.sm-shape-chart svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

/* Gridlines + axis labels ─────────────────────────────── */
.sm-shape-grid line {
  stroke: var(--border-subtle);
  stroke-width: 1;
}
.sm-shape-axis text,
.sm-shape-x text {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  fill: var(--text-tertiary);
}
.sm-shape-x text {
  font-size: 10px;
}

/* The rank line — scroll-painted via stroke-dashoffset.
   pathLength=100 normalizes so any line length maps to 0-100
   for the dasharray.  Color is brand teal hardcoded so it
   reads identically in dark mode. */
.sm-shape-line {
  stroke: #7ADAE6;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: calc(100 - var(--sm-shape-progress, 0) * 100);
  filter: drop-shadow(0 0 8px rgba(122, 218, 230, 0.35));
  transition: stroke-dashoffset 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Filled area under the line — fades in along with the
   line.  Reveals depth without competing with the stroke. */
.sm-shape-area {
  fill: url(#sm-shape-area-grad);
  fill: rgba(122, 218, 230, 0.06);
  opacity: clamp(0, calc(var(--sm-shape-progress, 0) * 1.5), 0.85);
  clip-path: inset(0 calc(100% - var(--sm-shape-progress, 0) * 100%) 0 0);
  transition:
    opacity 320ms ease,
    clip-path 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Anchor dots — appear at their callout's progress threshold.
   The three callouts trigger at progress 0.18, 0.50, 0.78
   corresponding to the x-position of each anchor on the line. */
.sm-shape-dot {
  fill: #7ADAE6;
  filter: drop-shadow(0 0 6px rgba(122, 218, 230, 0.55));
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 280ms ease, transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-shape-dot[data-anchor="1"] {
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.18) * 12), 1);
  transform: scale(clamp(0, calc((var(--sm-shape-progress, 0) - 0.18) * 12), 1));
}
.sm-shape-dot[data-anchor="2"] {
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.50) * 12), 1);
  transform: scale(clamp(0, calc((var(--sm-shape-progress, 0) - 0.50) * 12), 1));
}
.sm-shape-dot[data-anchor="3"] {
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.78) * 12), 1);
  transform: scale(clamp(0, calc((var(--sm-shape-progress, 0) - 0.78) * 12), 1));
}

/* ── Callouts ──────────────────────────────────────────── */
.sm-shape-callout {
  position: absolute;
  max-width: 220px;
  padding: 12px 14px;
  background: var(--surface, #181210);
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  font-family: var(--font-base);
  /* Reveal: opacity + translateY tied to per-callout progress
     threshold so each appears as the line passes its dot. */
  transition:
    opacity 320ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sm-shape-callout-date {
  margin: 0 0 4px;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #7ADAE6;
  font-weight: 600;
}
.sm-shape-callout-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-secondary);
}
.sm-shape-callout-text strong {
  color: var(--text-primary);
  font-weight: 600;
}
.sm-shape-callout-text code {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 0.92em;
  color: #7ADAE6;
  background: rgba(122, 218, 230, 0.10);
  padding: 1px 5px;
  border-radius: 3px;
}

/* Callout positioning — anchored to the line dots via %
   of the chart container.  Day 15 (x=215/1200=18%), Day 31
   (x=450/1200=37.5%), Day 55 (x=780/1200=65%). */
.sm-shape-callout[data-callout="1"] {
  left: 13%;
  top: 58%;
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.20) * 8), 1);
  transform: translateY(calc(12px - 12px * clamp(0, calc((var(--sm-shape-progress, 0) - 0.20) * 8), 1)));
}
.sm-shape-callout[data-callout="2"] {
  left: 31%;
  top: 8%;
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.52) * 8), 1);
  transform: translateY(calc(12px - 12px * clamp(0, calc((var(--sm-shape-progress, 0) - 0.52) * 8), 1)));
}
.sm-shape-callout[data-callout="3"] {
  left: 63%;
  top: 6%;
  opacity: clamp(0, calc((var(--sm-shape-progress, 0) - 0.80) * 8), 1);
  transform: translateY(calc(12px - 12px * clamp(0, calc((var(--sm-shape-progress, 0) - 0.80) * 8), 1)));
}

/* Hover: lift, brighter border, brand-teal accent on the
   date pill. */
.sm-shape-callout,
.sm-shape-callout * { cursor: pointer; }
.sm-shape-callout:hover {
  border-color: rgba(122, 218, 230, 0.42);
  background: var(--surface-elevated, #1F1815);
}

/* ── Mouse scrubber ─────────────────────────────────────
   Vertical guide line that follows the cursor X across the
   chart, with a tip showing the rank for that day.  Driven
   by --scrub-x set in JS on mousemove.  Hidden until the
   chart is hovered. */
.sm-shape-chart { cursor: pointer; }
.sm-shape-chart svg { cursor: pointer; }
.sm-shape-scrubber {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(var(--scrub-x, 0), 0, 0);
  transition: opacity 200ms ease;
  z-index: 4;
}
.sm-shape-chart:hover .sm-shape-scrubber {
  opacity: 1;
}
.sm-shape-scrubber-line {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 100%;
  background: linear-gradient(
    to bottom,
    rgba(122, 218, 230, 0) 0%,
    rgba(122, 218, 230, 0.55) 12%,
    rgba(122, 218, 230, 0.55) 88%,
    rgba(122, 218, 230, 0) 100%
  );
  box-shadow: 0 0 8px rgba(122, 218, 230, 0.4);
}
.sm-shape-scrubber-tip {
  position: absolute;
  top: 18px;
  left: 12px;
  padding: 10px 12px;
  background: rgba(24, 18, 16, 0.94);
  border: 1px solid rgba(122, 218, 230, 0.32);
  border-radius: 6px;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  gap: 2px;
  backdrop-filter: blur(6px);
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backdrop-filter: blur(6px);
}
.sm-shape-scrubber.is-flipped .sm-shape-scrubber-tip {
  left: auto;
  right: 12px;
}
.sm-shape-scrubber-day {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.sm-shape-scrubber-rank {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 15px;
  font-weight: 700;
  color: #7ADAE6;
  letter-spacing: -0.005em;
}

/* ── Foot caption ──────────────────────────────────────── */
.sm-shape-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
}
.sm-shape-foot span:not([class]) {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 10px;
  color: var(--text-quaternary);
}
.sm-shape-foot code {
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.04);
  padding: 2px 8px;
  border-radius: 4px;
}
.sm-shape-foot-sep {
  color: var(--text-quaternary);
  margin: 0 4px;
}

/* ── Responsive (Act 3) ────────────────────────────────── */

/* < 1100px: drop the sticky stage on tablet/phone — sticky-
   stage scroll-paint feels stuck on short viewports.  The
   chart flows in normal document order with its own progress
   computed from its viewport position. */
@media (max-width: 1099px) {
  [data-act="3"].sm-shape-section {
    min-height: auto;
    padding: clamp(96px, 14vh, 160px) 0 clamp(120px, 18vh, 200px);
  }
  .sm-shape-frame {
    position: relative;
    top: auto;
    height: auto;
    overflow: visible;
    padding: 0 clamp(20px, 5vw, 80px);
  }
  .sm-shape-scrubber { display: none; }
}

@media (max-width: 900px) {
  .sm-shape-h { font-size: var(--mkt-h4); }
  .sm-shape-callout {
    max-width: 160px;
    padding: 10px 12px;
    font-size: 12px;
  }
  .sm-shape-callout-text { font-size: 12px; }
}

@media (max-width: 600px) {
  .sm-shape-chart { aspect-ratio: 4 / 3; }
  .sm-shape-callout {
    max-width: 140px;
    padding: 8px 10px;
  }
  .sm-shape-callout-text { font-size: 11px; line-height: 1.45; }
}

@media (min-width: 1600px) {
  .sm-shape { max-width: min(95vw, 1480px); }
  .sm-shape-h { font-size: 64px; }
  .sm-shape-sub { font-size: 19px; }
  .sm-shape-callout { max-width: 260px; padding: 14px 16px; }
  .sm-shape-callout-text { font-size: 14px; }
}
@media (min-width: 1920px) {
  .sm-shape { max-width: min(95vw, 1680px); }
  .sm-shape-h { font-size: 72px; }
  .sm-shape-sub { font-size: 20px; }
  .sm-shape-callout { max-width: 280px; }
  .sm-shape-callout-text { font-size: 15px; }
}
@media (min-width: 2400px) {
  .sm-shape { max-width: min(95vw, 1960px); }
  .sm-shape-h { font-size: 88px; }
  .sm-shape-sub { font-size: 23px; }
  .sm-shape-callout { max-width: 320px; }
  .sm-shape-callout-text { font-size: 17px; }
}

@media (prefers-reduced-motion: reduce) {
  [data-act="3"].sm-shape-section { --sm-shape-progress: 1; }
}

/* ──────────────────────────────────────────────────────────
   Act 4 — Closer (teal band).

   Saturated teal-5 brand band wraps Act 4 + footer so the
   page resolves on one continuous chord.  Centered editorial
   composition: kicker, three-line H2 with italic on the
   middle line, sub, CTA stack, cross-link to the sibling
   monitoring spoke.  Mesh-gradient backdrop with four
   blurred bubbles drifts on independent loops over the
   whole band.  Topbar adapts via body.is-on-teal.
─────────────────────────────────────────────────────────── */

.sm-teal-band {
  position: relative;
  background: #7ADAE6;
  overflow: hidden;
  isolation: isolate;
}

[data-act="4"].sm-close-section {
  position: relative;
  z-index: 1;
  background: transparent;
  color: #1D1612;
  padding: clamp(96px, 14vh, 180px) clamp(20px, 5vw, 80px) clamp(120px, 18vh, 220px);
  display: flex;
  justify-content: center;
}

.sm-end {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 760px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

[data-act="4"] .sm-end-kicker {
  margin: 0 0 clamp(24px, 3vh, 36px);
  color: color-mix(in srgb, #1D1612 60%, transparent);
}

.sm-end-h {
  margin: 0;
  font-family: var(--font-display, "Rawest", system-ui, sans-serif);
  font-size: var(--mkt-h2);
  line-height: 1.06;
  letter-spacing: -0.024em;
  font-weight: 500;
  color: #1D1612;
  text-wrap: balance;
}
.sm-end-h em {
  font-style: normal;
  font-weight: 500;
  color: inherit;
}

.sm-end-sub {
  margin: clamp(24px, 3.2vh, 36px) 0 0;
  font-family: var(--font-base);
  font-size: var(--mkt-body);
  line-height: 1.55;
  color: color-mix(in srgb, #1D1612 76%, transparent);
  max-width: 56ch;
  text-wrap: pretty;
}

/* Destinations strip — surfaces the "this is infrastructure
   that ships to your stack" framing from the GTM doc.
   Horizontal pill row, hairline borders, monospace labels.
   Wraps cleanly on narrow viewports. */
.sm-end-dests {
  list-style: none;
  margin: clamp(28px, 4vh, 40px) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 10px;
}
.sm-end-dests li {
  font-family: var(--font-code, "IBM Plex Mono", monospace);
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 5px 12px;
  border: 1px solid color-mix(in srgb, #1D1612 22%, transparent);
  border-radius: 999px;
  color: color-mix(in srgb, #1D1612 72%, transparent);
  background: transparent;
  white-space: nowrap;
  transition: background-color 200ms ease, border-color 200ms ease, color 200ms ease;
}
.sm-end-dests li,
.sm-end-dests li * { cursor: pointer; }
.sm-end-dests li:hover {
  background: color-mix(in srgb, #1D1612 8%, transparent);
  border-color: color-mix(in srgb, #1D1612 38%, transparent);
  color: #1D1612;
}

.sm-end-cta {
  margin-top: clamp(28px, 4vh, 40px);
  justify-content: center;
}
[data-act="4"] .cta-stack-tag {
  color: color-mix(in srgb, #1D1612 65%, transparent);
}

/* CTA button — always purple in the closer regardless of
   body.is-on-teal state.  The default .btn-marketing color
   doesn't pop against teal-5; purple-7 (#7C4FE8) is the
   brand contrast for this band. */

.sm-end-link {
  margin-top: clamp(24px, 3.2vh, 36px);
  align-self: center;
}

/* Closer reveal — header → H2 → sub → CTA → cross-link
   stagger via the existing [data-ci-reveal] hook. */
.sm-end[data-ci-reveal] > * {
  opacity: 0;
  transform: translateY(20px);
  filter: blur(8px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1),
    filter 600ms ease;
}
.sm-end[data-ci-reveal].is-revealed > * {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}
.sm-end[data-ci-reveal].is-revealed > *:nth-child(1) { transition-delay:   0ms; }
.sm-end[data-ci-reveal].is-revealed > *:nth-child(2) { transition-delay: 120ms; }
.sm-end[data-ci-reveal].is-revealed > *:nth-child(3) { transition-delay: 280ms; }
.sm-end[data-ci-reveal].is-revealed > *:nth-child(4) { transition-delay: 400ms; }
.sm-end[data-ci-reveal].is-revealed > *:nth-child(5) { transition-delay: 520ms; }
.sm-end[data-ci-reveal].is-revealed > *:nth-child(6) { transition-delay: 640ms; }

/* ── Mesh + bubbles ─────────────────────────────────────
   Four blurred bubbles drift on independent loops over the
   teal-band wrapper, covering Act 4 + the footer.  Same brand
   recipe as /workflows/lead-enrichment — smaller bubbles
   (42% × 55%) + lighter blur (72px) + contain: paint keep
   the compositor happy on integrated GPUs. */
.sm-end-mesh {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  contain: paint;
}
.sm-end-bubble {
  position: absolute;
  width: 42%;
  height: 55%;
  border-radius: 50%;
  filter: blur(72px);
  opacity: 0.72;
  will-change: transform;
  transform: translateZ(0);
  backface-visibility: hidden;
}
.sm-end-bubble[data-bubble="1"] {
  background: #9B6FFF;
  top: -10%;
  left: -10%;
  animation: sm-end-bubble-1 22s ease-in-out infinite alternate;
}
.sm-end-bubble[data-bubble="2"] {
  background: #FFFFFF;
  top: 15%;
  left: 50%;
  animation: sm-end-bubble-2 26s ease-in-out infinite alternate;
}
.sm-end-bubble[data-bubble="3"] {
  background: #6ED49A;
  top: 40%;
  left: 5%;
  animation: sm-end-bubble-3 24s ease-in-out infinite alternate;
}
.sm-end-bubble[data-bubble="4"] {
  background: #F5C56A;
  top: 5%;
  left: 65%;
  opacity: 0.45;
  animation: sm-end-bubble-4 30s ease-in-out infinite alternate;
}
@keyframes sm-end-bubble-1 { 0% { transform: translate3d(0,0,0); } 100% { transform: translate3d( 20%, 15%, 0); } }
@keyframes sm-end-bubble-2 { 0% { transform: translate3d(0,0,0); } 100% { transform: translate3d(-15%, 18%, 0); } }
@keyframes sm-end-bubble-3 { 0% { transform: translate3d(0,0,0); } 100% { transform: translate3d( 22%,-12%, 0); } }
@keyframes sm-end-bubble-4 { 0% { transform: translate3d(0,0,0); } 100% { transform: translate3d(-18%, 12%, 0); } }

@media (prefers-reduced-motion: reduce) {
  .sm-end-bubble { animation: none; }
  .sm-end[data-ci-reveal] > * {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
}

/* ── Footer: standard dark (no gradient) ────────────────
   Opaque warm-dark block over the mesh, default light text.
   Act 4 above keeps the teal. */
.site-footer {
  background: var(--background);
  position: relative;
  z-index: 1;
}

/* ── Responsive (Act 4) ──────────────────────────────── */
@media (max-width: 900px) {
  [data-act="4"].sm-close-section {
    padding: clamp(80px, 11vh, 120px) clamp(20px, 5vw, 32px) clamp(96px, 14vh, 160px);
  }
}
@media (max-width: 600px) {
  .sm-end-h { font-size: var(--mkt-h4); }
}
@media (min-width: 1600px) {
  .sm-end { max-width: 880px; }
  .sm-end-h { font-size: 64px; }
  .sm-end-sub { font-size: 19px; }
}
@media (min-width: 1920px) {
  .sm-end { max-width: 1000px; }
  .sm-end-h { font-size: 72px; }
  .sm-end-sub { font-size: 20px; }
}
@media (min-width: 2400px) {
  .sm-end { max-width: 1200px; }
  .sm-end-h { font-size: 88px; }
  .sm-end-sub { font-size: 23px; }
}

/* ══════════════════════════════════════════════════════════
   BU light overrides.  --font-display auto-flips to Mq12 via
   DS-level override.
═══════════════════════════════════════════════════════════ */
html:not(.dark) body {
  background: var(--zen-gray-3);
  color: var(--text-primary);
}
/* Per-page rgba-white flips below. */
html:not(.dark) .sm-shape-foot code { background: rgba(29, 22, 18, 0.04); }

/* Teal text on light bg — callout date/code + scrubber rank flip. */
html:not(.dark) .sm-shape-callout-date,
html:not(.dark) .sm-shape-callout-text code,
html:not(.dark) .sm-shape-scrubber-rank {
  color: #1C9E97;
}

/* Callout :hover + scrubber tip read as dark tooltips on a light
   page in BU.  Defaults use hardcoded dark warm fills (callout
   hover via var(--surface-elevated, #1F1815) — the var is
   undefined so the fallback always wins; scrubber tip via
   rgba(24, 18, 16, 0.94)).  Flip both to light fills in BU and
   tighten the text colour for the day label.  Pablo flagged
   2026-06-15. */
html:not(.dark) .sm-shape-callout:hover {
  background: #FFFFFF;
  border-color: rgba(122, 218, 230, 0.5);
}
html:not(.dark) .sm-shape-scrubber-tip {
  background: rgba(255, 255, 255, 0.96);
  border-color: rgba(122, 218, 230, 0.4);
  box-shadow: 0 8px 24px -10px rgba(29, 22, 18, 0.18);
}
html:not(.dark) .sm-shape-scrubber-day {
  color: var(--text-tertiary);
}
