/* v3 Roadmap (2026-11-06). The page's own rules; the hero, the pills and the nav come from
   blog.css / home-v2.css / style.css. Outlined against untillabs.com/roadmap (docs/redesign/
   untillabs-roadmap-audit.md) and then made Vexil's: cream page, ink type, the mark's orange
   for what is live, Michroma as the instrument voice, and the aircraft's route as the spine. */

/* ---------- the hero: the night map with gold lines (was a gold wash, kept for ?wash=gold), the title set left ---------- */
[data-wash="gold"] { --w1: 222, 170, 36; --w2: 244, 208, 84; --deep: 176, 124, 16; --topo: 112, 72, 6; --pool: 255, 236, 150; }
.blog-hero[data-wash="gold"] .wash-bg { filter: saturate(1.1);
  background:
    radial-gradient(46% 58% at 18% 42%, rgba(var(--w2), 0.85), rgba(var(--w2), 0) 70%),
    radial-gradient(40% 54% at 76% 28%, rgba(var(--w2), 0.7), rgba(var(--w2), 0) 70%),
    radial-gradient(60% 50% at 50% 100%, rgba(var(--w1), 0.9), rgba(var(--w1), 0) 70%),
    linear-gradient(180deg, rgb(var(--deep)) 0%, rgb(var(--w1)) 45%, rgb(var(--w2)) 100%); }
.roadmap .blog-hero { --peek: 0px; min-height: 100svh; align-items: stretch; padding-bottom: clamp(44px, 7vh, 90px); }
.rm-hero-foot { position: relative; z-index: 1; width: 100%; max-width: var(--col); margin: auto auto 0; display: flex; align-items: flex-end; justify-content: space-between; gap: clamp(24px, 4vw, 60px); }
.roadmap .blog-title { width: auto; margin: 0; text-align: left; color: #f4efe1; text-shadow: 0 2px 40px rgba(0, 0, 0, 0.4); }
.roadmap .blog-hero[data-wash="gold"] .blog-title { color: var(--ink); text-shadow: 0 2px 40px rgba(112, 72, 6, 0.18); }


/* ---------- shared type ---------- */
.rm-main { position: relative; }
.rm-sec { padding: clamp(56px, 9vw, 120px) 0; }
.rm-eyebrow { margin: 0 0 14px; }
.rm-h2 { margin: 0 0 clamp(14px, 2vw, 22px); font-size: clamp(34px, 4.6vw, 64px); font-weight: 600; letter-spacing: -0.035em; line-height: 0.98; text-wrap: balance; }
.rm-h2-wide { max-width: 16ch; }
.rm-h3 { margin: 0 0 clamp(18px, 2.4vw, 30px); font-size: clamp(24px, 2.6vw, 34px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; }
.rm-display { margin: 0 0 clamp(16px, 2vw, 26px); font-size: clamp(38px, 5.4vw, 80px); font-weight: 600; letter-spacing: -0.04em; line-height: 0.96; text-wrap: balance; max-width: 16ch; }
.rm-lede { margin: 0; font-size: clamp(17px, 1.6vw, 20px); line-height: 1.5; color: var(--ink); max-width: 48ch; }
.rm-note { margin: clamp(24px, 4vw, 48px) 0 0; color: var(--muted); }
/* reveals: a short rise as each block arrives */
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1), transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
.js .reveal.is-on { opacity: 1; transform: none; }
.rm-beats .reveal:nth-child(2) { transition-delay: 0.12s; } .rm-beats .reveal:nth-child(3) { transition-delay: 0.24s; }

/* ---------- THE ROUTE (2026-11-07): a pinned sideways chapter, after untillabs.com's
   "What we are doing" — open type, one thin ink line with + ticks, drawn as you scroll ---------- */
/* the pace (Ryan, 2026-11-08: "slow the trail ... a happy medium"): the frame holds for --hold
   of scroll while the trail sets out from stop 01, then slides at 1/1.4 of the scroll */
/* --stay: once Why now has slid into place the frame holds a while longer, so its reveal gets
   time on screen before the page moves on (Ryan, 2026-11-08: "I could easily blow past it") */
.hz { --run: 160vw; --hold: 45svh; --pace: 1.4; --stay: 75svh; position: relative; height: calc(100svh + var(--hold) + var(--run) * var(--pace) + var(--stay)); }
.hz-pin { position: sticky; top: 0; height: 100svh; overflow: hidden; }
.hz-track { position: absolute; left: 0; top: 0; width: calc(100vw + var(--run)); height: 100%; will-change: transform; }
.hz-line { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
/* the map: contours drawn once onto a canvas the size of the sheet, sliding with it */
.hz-topo { position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none; }
/* the trail: a dashed line, faint ahead, orange where it has been walked (revealed through a mask) */
.hz-line path { stroke-linecap: round; stroke-linejoin: round; }
.hz-line .hz-line-ahead { stroke: var(--ink); stroke-width: 1.8; stroke-dasharray: 5 6; opacity: 0.38; }
.hz-line .hz-line-gone { stroke: var(--signal-bright); stroke-width: 2.6; stroke-dasharray: 5 6; }
.hz-line .hz-mask { stroke: #fff; stroke-width: 14; stroke-dasharray: var(--len, 1); stroke-dashoffset: var(--off, var(--len, 1)); }
/* waypoints: a small ring on the trail, filled orange once walked */
.hz-line .hz-wp { fill: var(--bg); stroke: var(--ink); stroke-width: 1.4; transition: fill 0.4s, stroke 0.4s; }
.hz-line .hz-wp.is-on { fill: var(--signal-bright); stroke: var(--signal-bright); }
.hz-line .hz-wp-ring { fill: none; stroke: var(--signal-bright); stroke-width: 1; opacity: 0; transition: opacity 0.4s; }
.hz-line .hz-wp-ring.is-on { opacity: 0.5; }
.hz-block { position: absolute; z-index: 1; opacity: 0; transform: translateY(14px); transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1), transform 0.9s cubic-bezier(0.22, 1, 0.36, 1); }
.hz-block.is-on { opacity: 1; transform: none; }
/* where each block sits on the long sideways sheet (x in vw, y in the frame's height) */
.hz-a { left: 6vw;   top: 20%; width: min(30vw, 440px); }
.hz-b { left: 40vw;  top: 46%; width: min(22vw, 320px); }
.hz-c { left: 104vw; top: 15%; width: min(54vw, 800px); }
.hz-num { margin: 0 0 18px; color: var(--signal); }
.hz-h { margin: 0 0 22px; font-size: clamp(40px, 4.2vw, 64px); font-weight: 600; letter-spacing: -0.035em; line-height: 1; }
.hz-c .hz-h { margin-bottom: 14px; font-size: clamp(40px, 4.2vw, 64px); }
/* Why now: the deck's headline, then its three numbers, big */
.hz-lead { margin: 0 0 clamp(20px, 3.4svh, 34px); font-size: clamp(22px, 2.1vw, 32px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; color: var(--ink); }
.hz-lead span { color: var(--signal); }
.hz-stats { display: grid; grid-template-columns: repeat(3, auto); justify-content: start; gap: clamp(22px, 3vw, 48px); margin: 0 0 clamp(16px, 3svh, 28px); }
.hz-stat { position: relative; margin: 0; padding-top: 12px; }
.hz-stat::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: rgba(16, 21, 27, 0.18); }
.hz-fig { margin: 0 0 6px; font-size: clamp(34px, 3.6vw, 56px); font-weight: 600; letter-spacing: -0.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.hz-stat dd { margin: 0; max-width: 17ch; font-size: 14px; line-height: 1.35; color: var(--muted); }
.hz-c .hz-after { max-width: 54ch; }
.hz-src { margin: 12px 0 0; font-size: 10.5px; letter-spacing: 0.04em; color: var(--muted); opacity: 0.8; max-width: 70ch; }
/* Why now's reveal, driven by the scroll wheel (2026-11-08, Ryan: "have the scroll wheel reveal
   that same UI ... the UI is controlled by the scroll speed"). js/roadmap.js sets a 0..1 progress
   per piece as you scroll through the end of the slide and the hold after it: --t on each .rv
   (rises out of a mask), --u on the headline (the orange rule under the second beat), and per stat
   --k (its rule draws), --a (the number, which counts with it) and --b (its label). Scrolling back
   up winds it back. Every var falls back to 1, so no JS and phones show it finished. */
.hz-c.is-on { opacity: 1; transform: none; }
.hz-c .rv { opacity: var(--t, 1); transform: translateY(calc((1 - var(--t, 1)) * 26px)); clip-path: inset(0 0 calc((1 - var(--t, 1)) * 120% - 20%) 0); }
.hz-lead span { display: inline-block; background: linear-gradient(currentColor, currentColor) 0 100% / calc(var(--u, 1) * 100%) 2px no-repeat; padding-bottom: 3px; }
.hz-stat::before { transform: scaleX(var(--k, 1)); transform-origin: 0 50%; }
.hz-stat .hz-fig { opacity: var(--a, 1); transform: translateY(calc((1 - var(--a, 1)) * 14px)); }
.hz-stat dd { opacity: var(--b, 1); transform: translateY(calc((1 - var(--b, 1)) * 14px)); }

/* Tyler's photos beside the blank stops: they pop up as they scroll in (js adds is-up) */
.hz-photo { position: absolute; top: -80px; width: min(19vw, 260px); margin: 0; opacity: 0; transform: translateY(60px) scale(0.86) rotate(var(--tilt, 0deg)); transform-origin: 50% 80%; transition: opacity 0.6s ease, transform 0.9s cubic-bezier(0.34, 1.45, 0.5, 1); }
.hz-photo.is-up { opacity: 1; transform: rotate(var(--tilt, 0deg)); }
.hz-photo-left { right: calc(100% + 8vw); --tilt: -2deg; }
.hz-photo-right { left: calc(100% + 8vw); --tilt: 2deg; }
.hz-photo img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; border-radius: 3px; box-shadow: 0 1px 2px rgba(16, 21, 27, 0.12), 0 18px 44px -12px rgba(16, 21, 27, 0.45); background: #1a1410; }
.hz-photo figcaption { margin-top: 10px; font-size: 10.5px; letter-spacing: 0.04em; line-height: 1.45; color: var(--muted); }
.hz-p { margin: 0; font-size: 16px; line-height: 1.5; color: var(--ink); max-width: 34ch; }
.hz-cols { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 3vw, 44px); }
.hz-seq { margin: 18px 0 0; color: var(--signal); }
/* go to market, down the trail: the deck's headline, then a stage per stop */
.hz-gtm { position: relative; z-index: 1; margin-bottom: clamp(120px, 20svh, 200px); }
.hz-gtm-in { max-width: min(36vw, 520px); }
.hz-gtm-h { margin: 0; font-size: clamp(36px, 3.8vw, 58px); font-weight: 600; letter-spacing: -0.035em; line-height: 1.02; }
.hz-gtm-h em { font-style: normal; color: var(--signal); }
.hz-stage .hz-num { margin-bottom: 8px; }
.hz-year { margin: 0 0 6px; font-size: clamp(64px, 7vw, 112px); font-weight: 600; letter-spacing: -0.05em; line-height: 0.9; font-variant-numeric: tabular-nums; }
.hz-stage .hz-mkt { margin: 0 0 18px; color: var(--signal); text-transform: uppercase; letter-spacing: 0.14em; font-size: 12px; }
.hz-stage-h { margin: 0 0 12px; font-size: clamp(22px, 1.9vw, 28px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
.hz-stage .hz-year, .hz-stage .hz-mkt { opacity: 0; transform: translateY(18px); transition: opacity 0.7s ease, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1); }
.hz-stage.is-on .hz-year, .hz-stage.is-on .hz-mkt { opacity: 1; transform: none; }
.hz-stage.is-on .hz-mkt { transition-delay: 0.12s; }
/* the second fire photo tucks in behind the first, fanned the other way */
.hz-photo-right { z-index: 2; }
.hz-photo-right.hz-photo-back { z-index: 1; top: -170px; --tilt: 5deg; margin-left: 4vw; }
.hz-photo-right.hz-photo-back2 { z-index: 0; top: -110px; --tilt: 10deg; margin-left: 11vw; }
.hz-photo-back figcaption { visibility: hidden; }
/* after the turn: the line runs down out of the frame and comes in to stop 05 */
.hz-drop { position: relative; overflow: hidden; padding: clamp(140px, 22svh, 240px) 0 clamp(150px, 22svh, 240px); }
.hz-drop .hz-topo, .hz-drop .hz-line { position: absolute; left: 0; top: 0; }
.hz-down { position: relative; z-index: 1; }
/* the blank stops on the way down: alternating sides, a long run of trail between them */
.hz-down .hz-block { position: relative; left: auto; top: auto; width: min(30vw, 400px); margin: 0 0 clamp(200px, 34svh, 340px); }
.hz-down .hz-block:nth-child(odd) { margin-left: auto; margin-right: 6vw; }
.hz-down .hz-block:nth-child(2) { margin-left: 12vw; }
.hz-down .hz-block:last-child { margin-bottom: 0; }
.hz-drop + .rm-why { padding-top: 22px; }   /* the trail's last waypoint sits right over the eyebrow */

/* ---------- THE WHY ---------- */
.rm-why-grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(28px, 5vw, 80px); align-items: center; margin: clamp(22px, 3vw, 40px) 0 clamp(60px, 8vw, 110px); }
.rm-why-copy .why-seq { margin: 18px 0 0; color: var(--signal); }
.rm-why-photo { margin: 0; }
.rm-why-photo picture { display: block; border-radius: 22px; overflow: hidden; aspect-ratio: 4 / 3; background: var(--surface); }   /* the frame on the picture, so the credit sits under it */
.rm-why-photo figcaption { margin-top: 10px; font-size: 10.5px; letter-spacing: 0.04em; line-height: 1.45; color: var(--muted); }
.rm-why-photo img { width: 100%; height: 100%; object-fit: cover; display: block; filter: saturate(0.85) contrast(1.02); }
.rm-why-photo.reveal { transition-delay: 0.15s; }
.rm-beats { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(24px, 4vw, 56px); }
.rm-beat-word { margin: 0 0 10px; font-size: clamp(44px, 6.4vw, 96px); font-weight: 600; letter-spacing: -0.045em; line-height: 0.95; }
.rm-beat p { margin: 0; font-size: 16px; line-height: 1.5; color: var(--ink); max-width: 30ch; }

/* ---------- THE OUTLOOK ---------- */
.rm-outlook { padding-top: 0; }
.rm-outlook-grid { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: clamp(24px, 5vw, 80px); padding-top: clamp(40px, 6vw, 80px); border-top: 1px solid var(--hair); }
.rm-outlook-links { display: flex; flex-wrap: wrap; gap: 14px 34px; margin: clamp(22px, 3vw, 36px) 0 0; }
.rm-outlook-links a { color: var(--signal); font-weight: 600; text-decoration: underline; text-underline-offset: 5px; text-decoration-thickness: 1px; transition: color 0.2s; }
.rm-outlook-links a:hover { color: var(--ink); }

/* ---------- RADIO CHECK ---------- */
.rm-check { padding: clamp(60px, 10vw, 140px) 0 clamp(40px, 6vw, 80px); text-align: center; }
.rm-check-call { margin: 0 0 16px; color: var(--signal); }
.rm-check-line { margin: 0 auto clamp(22px, 3vw, 36px); max-width: 18ch; font-size: clamp(30px, 4.4vw, 60px); font-weight: 600; letter-spacing: -0.035em; line-height: 1; text-wrap: balance; }
.rm-check-pill { --rot: 0deg; --d: 0.25s; font-size: clamp(22px, 2.6vw, 34px); margin: 0 auto; }

/* ---------- phones ---------- */
@media (max-width: 900px) {
  .rm-hero-foot { flex-direction: column; align-items: flex-start; gap: 14px; }
  /* the route: no pin, one column, the line straight down the left */
  .hz { height: auto; padding: 40px 0 0; }
  .hz-pin { position: relative; height: auto; overflow: visible; }
  .hz-track { position: relative; width: auto; height: auto; transform: none !important; padding: 0 var(--gutter, 20px) 0 calc(var(--gutter, 20px) + 30px); }
  /* the trail: dots down the left, filled orange as you read (see the trail block at the end) */
  .hz-line { display: none; }
  .hz-topo { display: block; z-index: 0; }
  .hz-block { position: relative; left: auto; top: auto; width: auto; padding: 0 0 56px; }
  .hz-cols { grid-template-columns: 1fr; gap: 14px; }
  .hz-stats { grid-template-columns: 1fr; gap: 18px; }
  .hz-gtm { margin-bottom: 40px; }
  .hz-gtm-in { max-width: none; }
  .hz-photo-back { display: none; }
  .hz-photo, .hz-photo-left, .hz-photo-right { position: relative; top: auto; left: auto; right: auto; width: min(100%, 360px); margin: 28px 0 0; }
  .hz-drop { height: auto; padding: 0 var(--gutter, 20px) 20px calc(var(--gutter, 20px) + 30px); }
  .hz-down .hz-block, .hz-down .hz-block:nth-child(n) { width: auto; margin: 0; padding: 0 0 56px; }
  .rm-why-grid, .rm-outlook-grid { grid-template-columns: 1fr; }
  .rm-why-photo { order: -1; }
  .rm-why-photo picture { aspect-ratio: 16 / 10; }
  .rm-beats { grid-template-columns: 1fr; gap: 26px; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal, .rm-track-gone { transition: none !important; }
  .js .reveal { opacity: 1; transform: none; }
  .hz-block { transition: none !important; opacity: 1; transform: none; }
  .hz-stage .hz-year, .hz-stage .hz-mkt { transition: none; opacity: 1; transform: none; }
  .hz-photo { transition: none !important; opacity: 1; transform: rotate(var(--tilt, 0deg)); }
}
/* the map fades in under the hero and out into the page below the drop */
.hz-drop .hz-topo { -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent 100%); mask-image: linear-gradient(180deg, #000 70%, transparent 100%); }

/* the hero scrolls away like any page, its colour draining as it goes (js/roadmap.js) */
.rm-hero .wash { will-change: filter; }

/* the mission's standard line, set apart as a statement (Ryan, 2026-11-08: "emphasize it"),
   in the voice of the Why now lead: bigger, heavier, the key words in orange */
.hz-standard { margin: 18px 0 0; max-width: 20ch; font-size: clamp(20px, 1.8vw, 26px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.18; color: var(--ink); text-wrap: balance; }
.hz-standard span { color: var(--signal); }
/* phones: the route's map fades in from the top rather than starting on a hard edge */
@media (max-width: 900px) { #hzTopo { -webkit-mask-image: linear-gradient(180deg, transparent, #000 140px); mask-image: linear-gradient(180deg, transparent, #000 140px); } }

/* phones: the route as a trail (Ryan, 2026-11-08: "the same UI as the timeline on mobile, but a
   dotted line mimicking a trail"). Grey dots down the left, orange dots over them up to the read
   line (--fill from js/roadmap.js), and each numbered stop gets the timeline's marker and spur,
   lit as the stop comes into view. */
@media (max-width: 900px) {
  .hz-track::before, .hz-drop::before, .hz-track::after, .hz-drop::after {
    content: ""; position: absolute; z-index: 0; left: calc(var(--gutter, 20px) + 5px); top: 0; bottom: 0; width: 3px; pointer-events: none;
    background: radial-gradient(circle at 50% 50%, var(--dot) 1.3px, transparent 1.7px) 0 0 / 3px 9px repeat-y;
  }
  .hz-track::before, .hz-drop::before { --dot: rgba(16, 21, 27, 0.32); }
  .hz-track::after, .hz-drop::after { --dot: var(--signal-bright); clip-path: inset(0 0 calc(100% - var(--fill, 0) * 100%) 0); }
  .hz-block:has(> .hz-num)::before { content: ""; position: absolute; left: -22px; top: 0.62em; width: 16px; height: 1px; background: var(--hair, rgba(16, 21, 27, 0.18)); transform: scaleX(0); transform-origin: left; transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.12s, background 0.7s ease 0.12s; }
  .hz-block:has(> .hz-num)::after { content: ""; position: absolute; left: -27px; top: calc(0.62em - 3px); width: 5px; height: 5px; background: var(--bg); border: 1px solid rgba(16, 21, 27, 0.3); transform: scale(0.6); transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.05s, border-color 0.7s ease 0.12s, background 0.7s ease 0.12s; }
  .hz-block.is-on:has(> .hz-num)::before { transform: scaleX(1); background: var(--signal-bright); }
  .hz-block.is-on:has(> .hz-num)::after { transform: scale(1); background: var(--signal-bright); border-color: var(--signal-bright); }
  /* no stop numbers beside the trail (Ryan, 2026-11-08); the marker moves down to the heading */
  .hz-block > .hz-num { display: none; }
  .hz-drop > .col { margin-inline: 0; width: auto; max-width: none; }   /* the drop's stops line up with the route's, on the same trail */
  .hz-block { --mk: 20px; } .hz-block.hz-stage { --mk: 30px; }   /* the middle of the first line: a 40px heading, a 64px year */
  .hz-block:has(> .hz-num)::before { top: var(--mk, 22px); }
  .hz-block:has(> .hz-num)::after { top: calc(var(--mk, 22px) - 3px); }
  /* each part of a stop rises in after the other as it comes into view (Ryan, 2026-11-08: "a reveal
     to each part as it goes down"), staggered like the timeline's date, title and text */
  .js .hz-block > * { opacity: 0; transform: translateY(12px); transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1); }
  .js .hz-block.is-on > * { opacity: 1; transform: none; }
  .js .hz-block.is-on > :nth-child(1) { transition-delay: 0.1s; }
  .js .hz-block.is-on > :nth-child(2) { transition-delay: 0.2s; }
  .js .hz-block.is-on > :nth-child(3) { transition-delay: 0.3s; }
  .js .hz-block.is-on > :nth-child(4) { transition-delay: 0.4s; }
  .js .hz-block.is-on > :nth-child(n+5) { transition-delay: 0.5s; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) { .hz-block:has(> .hz-num)::before, .hz-block:has(> .hz-num)::after, .js .hz-block > * { transition: none; } .js .hz-block > * { opacity: 1; transform: none; } }
/* the standard line now leads its block, above the belief paragraph (Ryan, 2026-11-08) */
.hz-standard:first-child { margin: 0 0 16px; }
