/*
  Homepage r8 cal.com-style concept: Hero + Nav retheme, scoped under `.home-r8-scope`
  (components/home/HomePage.tsx wraps <Nav>+<main> in that class for locale="en" only, so /id
  and every other route are unaffected — per the brief, "every other route... untouched").

  Token source: the approved mockup's own tokens.css (r8/r9,
  ~/Documents/Projects/Hermes/workspaces/design/noethera/2026-11-08-homepage-calcom-concept/mockup/tokens.css),
  light-mode values only, renamed with an r8- prefix so they never collide with the live site's
  own warm/brown token set (theme-tokens.css) — the two systems intentionally coexist on this
  preview branch: everything inside `.home-r8-scope` is cal.com monochrome, everything else
  (Problem/InPractice/WhatWeBuild/AILayer/WhereToStart/HowWeWork/FeaturedWork/FAQ/FinalCTA/Footer)
  keeps its current look. That full-page retheme is flagged as an explicit follow-up in the task
  report, not silently done here.
*/

/* r8 design tokens moved to app/styles/chrome-r8.css (t_dcb5abd0) -- loaded on every route. */

/* .w container width rule moved to app/styles/chrome-r8.css (t_dcb5abd0). */

/* Nav + mobile-menu styles moved to app/styles/chrome-r8.css (t_dcb5abd0) -- loaded on every route now, not just home. */

/* ---------------------------------- Hero ---------------------------------- */

.home-r8-scope .hero-r8 {
  background: var(--r8-bg);
  color: var(--r8-ink);
  overflow: hidden;
  /* Round-10 (Noe's 1280 reference measurement, t_2e1630d5): H1 ink-top sits at y=117 on a
     853-tall viewport, only ~50px under the nav pill -- not the ~160px this had before (that
     130px of dead air was pushing the gallery under the 900px fold). Tuned against a real
     1280x853 render (first pass at 70px landed H1-top at y~162, 45px too low; this is that
     measured correction), not hand-derived from the nav's own box model.
     Round-18 (item 11 follow-up): bottom trimmed 72->61px, giving back the 11px added to the
     top gap below so the section's total height (and the 4-viewport fit) is unchanged net. */
  padding: 25px 0 61px;
  position: relative;
}

/* Round-17 (Wira 2026-11-09 ~14:30, verbatim: "space dibawah top bar masih terpisah ya dari
   hero section? soalnya pattern dot matrixnya masih terpotong disitu"): nav (position:sticky,
   always-transparent at the flat/top state) reserves its own normal-flow height before this
   header begins, so `.hero-r8-dots` (inset:0 on THIS element, below) never painted behind it --
   a hard seam right at the nav's bottom edge. Pull this header's box up by the nav's height so
   it starts at the very top of the page/scope (y=0, behind the still-transparent nav), and add
   the same amount back as padding-top so every child inside (H1 etc.) renders at the same screen
   position regardless of the pull-up. Desktop/tablet only (min-width matches the nav's own
   flat/pill breakpoint boundary, app/home-r8.css ~264 `@media (max-width:680px)`): below that,
   `.nav-in` itself switches to `position:fixed` and no longer reserves flow height (measured
   navH=0 at 390), so there is nothing to pull the hero up behind there -- this rule would only
   double-shift it.

   Round-23, structural fix (t_eb5aac85, Wira 2026-11-10 ~11:42, verbatim: "yang hero section
   masih kejadian, kayak ada padding putih gitu, jadinya pattern titiknya seperti kepotong"):
   Round-17/18/22 all hard-coded this pull-up as a flat px snapshot of the nav's height measured
   on one day (80px, then 56px) -- every later round that touched the nav's own padding or logo
   size (Round-18's 4px->22px top-padding bump, Round-21b, aa7204d's 88px padding-top floor) moved
   the nav's REAL rendered height without anyone re-measuring and updating this one number, so the
   pull-up under/over-shot it and a white band (document y=0 to the hero's shifted top edge) showed
   the hero's own white background with a hard seam, instead of the dots layer running to y=0.
   Fixed structurally, not with another snapshot: `--r8-nav-h` is now the nav's LIVE rendered
   height (hooks/useNavHeightVar.ts, a ResizeObserver + synchronous mount measurement on
   components/home/Nav.tsx's own nav element, published onto this `.home-r8-scope` ancestor), so
   this pull-up always exactly matches the nav's current height -- on first load, after scrolling
   back to top, after a hard reload, and after any future round that changes the nav's size, with
   nothing left to keep in sync by hand. The 56px fallback (no-JS / pre-hydration paint) keeps
   today's measured flat-nav height as a reasonable default so there is no flash once JS attaches.

   Round-18 (item 11 follow-up, "air above the H1"): the net visual gap from the viewport top to
   the H1 (padding-top minus the margin-top pull-up) is bumped from the old 25px to 36px for the
   requested breathing room, taken from the hero's own bottom padding below instead of growing the
   section -- `--hero-r8-gap` below is that same gap, now expressed on its own instead of baked
   into a padding-top number that assumed a fixed margin-top. */
/* r13e item 1 (Wira 2026-11-09 ~21:25, verbatim: "harusnya defaulnya full desktop hero section,
   jadi responsive"): the old padding/margin tuning above (padding-top:92px / padding-bottom:61px)
   was hand-measured to fit the stack exactly at 4 specific viewport heights (800/900/864/1080) --
   anywhere else (1366x768, 2560x1440, an un-maximised browser window) the hero was either too
   short (big dead gap before the next section peeks in early) or, on a short window, cramped.
   A real min-height:100svh + vertical centering replaces the magic numbers: the hero now always
   occupies exactly one viewport on desktop (grows past it only if content genuinely needs more
   room, e.g. a very short window), and the whole stack (H1/sub/CTAs/gallery/trusted-by) centres
   as one block instead of being pinned to a fixed top offset -- so trusted-by stays visible (or,
   on a very tall/wide viewport, is deliberately centred rather than stranded far below the fold).
   Desktop/tablet only (matches the nav's own flat/pill breakpoint, same as the margin-top trick
   below); mobile (<=680px, its own rule further down) gets its own min-height:100svh treatment
   below, since the nav's mobile position:fixed already reserves zero flow height there (no
   margin-top pull-up needed -- the section already starts at document y=0, behind the fixed
   nav overlay, so 100svh here already spans the whole screen nav included). */
@media (min-width: 681px) {
  .home-r8-scope .hero-r8 {
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Round-23 (t_eb5aac85): was a flat -56px snapshot of the nav's height on one day; now the
       nav's LIVE height (see the big comment above this media query for the full root-cause
       writeup and hooks/useNavHeightVar.ts). */
    margin-top: calc(-1 * var(--r8-nav-h, 56px));
    min-height: 100svh;
    /* Round-21 (Wira 2026-11-10 09:40, same brief as the H1-clamp comment above): every size/gap
       below this point (padding-top here, the gallery margin-top, the panel height, the H1 font,
       the trusted-by margin-top) was a flat number tuned by eye at 900svh -- fine as a floor,
       but on anything shorter the stack simply ran past the viewport instead of shrinking, so
       the trusted-by row slid off the bottom of the first screen.
       `--hero-hs` is one shared height-scale derived straight from the viewport (1 at 900svh and
       taller -- exactly today's tuned sizes, unchanged -- shrinking below that) that every rule
       below multiplies its own flat number by, instead of each carrying its own separate
       breakpoint, so the whole stack scales together as one height-aware unit rather than a
       per-device patch at each of the 6 checked viewports. Squared (not linear) on purpose: a
       linear 100svh/900px only pulled the total stack back under the fold by ~1280x800's worth
       of slack -- nowhere near enough for 1280x634 (the stack is a near-fixed height, so it needs
       a steeper-than-linear pull the shorter the window gets) -- still pinned to exactly 1 at
       900svh and up either way (1 squared is still 1), so nothing above that line moves. Floored
       at 0.62 so even a 634-tall window keeps a visible (non-zero) top gap and readable type,
       rather than squeezing to zero. */
    --hero-hs-lin: clamp(0.58, calc(100svh / 900px), 1);
    --hero-hs: clamp(0.62, calc(var(--hero-hs-lin) * var(--hero-hs-lin)), 1);
    /* Round-22 (follow-up to Round-21, Noe's review of t_ab74d551/52378cc): Round-21's
       padding-top floor (60px) let the nav->H1 gap collapse to near-zero at short heights
       (margin-top above pulls the header up behind the nav, so visible gap = padding-top
       minus that pull -- at the old 60px floor that was ~4px, reading as jammed against the
       nav pill). Wira's complaint was the dead gap at 900svh, not "remove all air" at every
       height: floor raised so the gap never drops below ~32px, still reaching the original
       40px at 900svh+ (96*1=96, unchanged -- the max() picks whichever is bigger).
       The extra height this floor costs vs Round-21 is taken back from --hero-hs-deep below
       (squares --hero-hs again, so it still equals 1 -- no change -- at 900svh+, but pulls
       harder than --hero-hs alone below that), applied to the panel/gallery/ctas rules further
       down instead of back here.

       Round-23 (t_eb5aac85): this is now expressed as its own `--hero-r8-gap` (the nav->H1 gap
       alone, unchanged numbers: 32px floor, 40px at 900svh+), added on top of the nav's LIVE
       height (`--r8-nav-h`, hooks/useNavHeightVar.ts) instead of a flat padding-top number that
       silently assumed a specific margin-top. Same visible result at today's nav height, but the
       nav and gap components no longer have to be hand-kept in sync. */
    --hero-r8-gap: max(32px, calc(calc(96px * var(--hero-hs)) - 56px));
    --hero-hs-deep: clamp(0.4, calc(var(--hero-hs) * var(--hero-hs)), 1);
    padding-top: calc(var(--r8-nav-h, 56px) + var(--hero-r8-gap));
    /* t_8398eeaa: bottom padding trimmed (48->16px) to counter-balance the taller H1 margin-top
       and the taller wave stage above, keeping the trusted-by row's gap under the fold in the
       32-48px range Wira asked for (comments 20191/20193), tuned+measured live rather than
       computed, since --hero-hs/--hero-hs-deep's floors make the two don't scale 1:1. */
    padding-bottom: 16px;
  }
}

/* r13g-cont item 1 (Wira ~02:01, verbatim: "di mobile view bener hero section ini agar full
   page diawal"): mobile used to size to its natural content height only (padding 120/56 below),
   which could leave a gap before #problem (002) on a tall phone, or let 002 peek into the first
   screen on a short one. min-height:100svh + vertical centring makes the whole stack (H1/sub/
   CTAs/gallery/trusted-by) fill exactly one screen like desktop -- no blank band under the
   logos, 002 always starts after the fold. Checked 390x844 + 375x667. */
@media (max-width: 680px) {
  .home-r8-scope .hero-r8 {
    display: flex;
    flex-direction: column;
    /* Round-24 (t_dd2b0d70, Wira 2026-11-11 19:45, his own live-site iPhone photo + verbatim
       "Yg mepet top nya"): H1 jams against the fixed nav's logo at a short *visible* viewport
       height (Safari's toolbar eats real height). Mobile nav is position:fixed (reserves zero
       flow height, see the big Round-17/23 comment above the desktop media query) and this rule
       was plain `justify-content:center` in a bare `min-height:100svh` box -- at 390x844 (every
       prior round's own test height) that centres with a comfortable ~40px gap under the logo,
       but shrink the *visible* viewport and the same centred stack rides further up the screen
       with nothing reserving the nav's own footprint: ~0px gap at 390x664 (a real iPhone with the
       Safari chrome showing), literal overlap at 375x560. Noe's own repro + Wira's live-site photo
       both measured this on 7650698; every gate before this missed it because the evidence only
       ever used 390x844.
       Fix: reserve a hard floor -- padding-top = the nav's LIVE measured height (--r8-nav-h, the
       same var/hook the desktop rule above already uses) plus a flat 24px air gap -- and switch
       `justify-content:center` to the `safe` variant (Baseline across Safari/Chrome/Firefox since
       2023-24, https://caniuse.com/mdn-css_properties_justify-content_safe): the stack still
       centres in the remaining room on a tall viewport (390x844 keeps its ~40px+ gap, unchanged),
       but the moment centring would carry it above that floor, `safe` falls back to top-anchored
       at the floor instead -- "let the stack grow/scroll on a short viewport, don't let centring
       eat the top gap" is literally the CSS spec's own safe-alignment behaviour, not a new
       mechanism to maintain by hand. Letting the stack grow downward past the first screen on a
       very short viewport is accepted (matches the floor already in place for the gallery's own
       min-height elsewhere in this file); shrinking the whole stack further to force a 1-screen
       fit would re-open the "trusted-by slides off the bottom" bug Round-21 fixed. */
    justify-content: safe center;
    padding-top: calc(var(--r8-nav-h, 56px) + 24px);
    min-height: 100svh;
  }
}

.home-r8-scope .hero-r8-dots {
  /* Superseded (t_dd2b0d70, Wira 2026-11-11, scope-change relayed by Noe: "bagus nih" on Noe's
     light-dots sim — approving the dark instalment's hero dot/lamp language back onto the live
     light hero so both themes read as one family): the old Round-12/14 recipe (edge-only
     mask-composite distribution, 8px/10px hard-edge 0.9px-dot tile) is replaced below by the SAME
     28px-pitch soft dot + single-ellipse-fade mask the dark hero uses one file over
     (app/styles/dark-mode.css `.hero-r8-dots`), just re-tinted for ink-on-white instead of
     white-on-ink. Per Noe's measured recipe (`lightdots/` sim, not this scope's own
     `--r8-pat-dot` token, same reasoning as the dark pass: a different density/shape than every
     other page still using that shared token, so written directly here instead of overloading
     it): radial-gradient(circle, rgba(25,24,27,.30) 0, rgba(25,24,27,.10) 1.2px, transparent
     2.2px), 28px pitch at every width (no separate mobile tier, matching the dark hero's own
     Wira correction). Mask: same shape as dark's — a single continuous radial fade centred at
     50% 0% (the lamp's own ellipse), dots strongest under the glow, never fully disappearing
     outside it (floor rgba(0,0,0,0.45) on the mask, not transparent).
     Lightened (t_dd2b0d70, 2nd correction same day, Wira verbatim: "titiknya buat lebih light
     gray lagi, soalnya jadi kerasa berantakan"): .30/.10 read too busy/heavy — down to .13/.04
     per Noe's measured sim (darkest dot pixel ≈luma 244 on white, was ≈231). */
  background-image: radial-gradient(circle, rgba(25, 24, 27, 0.13) 0, rgba(25, 24, 27, 0.04) 1.2px, transparent 2.2px);
  background-size: 28px 28px;
  inset: 0;
  mask-image: radial-gradient(ellipse 55% 34% at 50% 0%, #000 0%, rgba(0, 0, 0, 0.45) 100%);
  -webkit-mask-image: radial-gradient(ellipse 55% 34% at 50% 0%, #000 0%, rgba(0, 0, 0, 0.45) 100%);
  position: absolute;
}

/* Light hero glow (t_dd2b0d70): new — light mode had no top-centre lamp before this pass.
   1st draft used the warm brand accent (rgba(139,105,87,...)); Wira corrected same-day
   ("sorry yang light mode kurang cocok, jangan coklat coba efek lampunya tapi hitam") — neutral
   black/ink tint instead, same ellipse shape/position as the dark lamp (50% 0%), Noe's measured
   recipe: ≈#f2f2f2 at the very top-centre edge, fading to pure white by ~45% of the section. */
.home-r8-scope .hero-r8::before {
  background: radial-gradient(ellipse 55% 34% at 50% 0%, rgba(25, 24, 27, 0.07) 0%, rgba(25, 24, 27, 0.03) 45%, transparent 100%);
  content: "";
  inset: 0;
  pointer-events: none;
  position: absolute;
  z-index: 0;
}

/* Hero dot-wave background (t_39e750e1 / t_8fcf267d): a WebGL plane of dots with rolling swells
   (components/home/HeroDotWave.tsx) REPLACES the static dot field + top lamp on this hero, in
   both themes: two dot patterns stacked read as noise, and the lamp would grey out the black sky
   above the plane. Background only, absolutely positioned: no layout change, hero copy untouched.
   The selectors carry [data-theme] so they outrank dark-mode.css's own .hero-r8 layer rules. */
[data-theme] .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-dots,
.home-r8-scope .hero-r8.hero-r8--wave .hero-r8-dots {
  display: none;
}

[data-theme] .home-r8-scope .hero-r8.hero-r8--wave::before,
.home-r8-scope .hero-r8.hero-r8--wave::before {
  content: none;
}

/* t_d4bcc064 (Wira ~13:55, dark wave crop: "efek pecah ... kayak video kualitas rendah"): the dark
   hero's static feTurbulence grain (dark-mode.css, .hero-r8::after) sat over the wave and read as
   compression noise. The wave hero is a flat theme colour behind crisp dots: no grain. */
[data-theme] .home-r8-scope .hero-r8.hero-r8--wave::after,
.home-r8-scope .hero-r8.hero-r8--wave::after {
  content: none;
}

.home-r8-scope .hero-r8--wave .hero-r8-wave {
  display: block;
  height: 100%;
  inset: 0;
  /* "Melayang" (Wira 11:07): feathered in under the CTA row. HeroDotWave sets --wave-in-0/
     --wave-in-w (fade-in band start + width) from the live layout; the fallbacks below are sane
     1440 pre-JS defaults.
     t_8398eeaa (Wira, bottom-edge screenshot: the old 2-stop linear fade read as a hard cut):
     each band is now explicit alpha stops at fixed fractions (0/.2/.4/.6/.8/1) following
     smoothstep (3t^2-2t^3) instead of one straight ramp -- zero slope at both ends of each band,
     so there's no visible kink where a fade begins or finishes, on either edge.
     t_8398eeaa round 3 (Wira ~12:01, verbatim: "efek glombangnya sampe bawah aja jadi trust
     cloent nya jg ada efeck dibawahnya cuman gradasi transparant biar teks dan logo tetap
     keliatan" -- supersedes the old single fade-out band that ended BEFORE the trusted-by row):
     the fade-out is now two eased segments reaching all the way to the hero's own bottom edge
     (100%): solid -> ~30% by the trusted-by row's own vertical middle (--wave-out2-0, set from
     that row's live rect), so the dots show through behind the label/logos at a legible ~30%
     rather than a hard stop before them -- then ~30% -> 0% continuing down to the hero's bottom,
     never behind the H1/subtitle (the fade-IN band above still keeps that area clean).
     t_c481bf5c (Wira ~14:4x, "Area hero: 30% atas buat copy, 70% buat ombak"): the wave's visible
     area now starts at 30% of the hero height (--wave-top-0): an eased 0 -> 18% fade over ~70px,
     held at a text-safe 18% behind the lower H1 and the subtitle, then the CTA band (--wave-in-*)
     takes it from 18% to full strength. Mobile uses the same top band. */
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) var(--wave-top-0, 30%),
    rgba(0, 0, 0, 0.019) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.2),
    rgba(0, 0, 0, 0.063) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.4),
    rgba(0, 0, 0, 0.117) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.6),
    rgba(0, 0, 0, 0.161) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.8),
    rgba(0, 0, 0, 0.18) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%)),
    rgba(0, 0, 0, 0.18) var(--wave-in-0, 38%),
    rgba(0, 0, 0, 0.265) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.2),
    rgba(0, 0, 0, 0.469) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.4),
    rgba(0, 0, 0, 0.711) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.6),
    rgba(0, 0, 0, 0.915) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.8),
    rgba(0, 0, 0, 1) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%)),
    rgba(0, 0, 0, 1) var(--wave-out-0, 58%),
    rgba(0, 0, 0, 0.9272) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.2),
    rgba(0, 0, 0, 0.7536) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.4),
    rgba(0, 0, 0, 0.5464) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.6),
    rgba(0, 0, 0, 0.3728) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.8),
    rgba(0, 0, 0, 0.3) var(--wave-out2-0, 72%),
    rgba(0, 0, 0, 0.2688) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.2),
    rgba(0, 0, 0, 0.1944) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.4),
    rgba(0, 0, 0, 0.1056) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.6),
    rgba(0, 0, 0, 0.0312) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.8),
    rgba(0, 0, 0, 0) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%))
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) var(--wave-top-0, 30%),
    rgba(0, 0, 0, 0.019) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.2),
    rgba(0, 0, 0, 0.063) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.4),
    rgba(0, 0, 0, 0.117) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.6),
    rgba(0, 0, 0, 0.161) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.8),
    rgba(0, 0, 0, 0.18) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%)),
    rgba(0, 0, 0, 0.18) var(--wave-in-0, 38%),
    rgba(0, 0, 0, 0.265) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.2),
    rgba(0, 0, 0, 0.469) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.4),
    rgba(0, 0, 0, 0.711) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.6),
    rgba(0, 0, 0, 0.915) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%) * 0.8),
    rgba(0, 0, 0, 1) calc(var(--wave-in-0, 38%) + var(--wave-in-w, 10%)),
    rgba(0, 0, 0, 1) var(--wave-out-0, 58%),
    rgba(0, 0, 0, 0.9272) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.2),
    rgba(0, 0, 0, 0.7536) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.4),
    rgba(0, 0, 0, 0.5464) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.6),
    rgba(0, 0, 0, 0.3728) calc(var(--wave-out-0, 58%) + var(--wave-out-w, 14%) * 0.8),
    rgba(0, 0, 0, 0.3) var(--wave-out2-0, 72%),
    rgba(0, 0, 0, 0.2688) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.2),
    rgba(0, 0, 0, 0.1944) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.4),
    rgba(0, 0, 0, 0.1056) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.6),
    rgba(0, 0, 0, 0.0312) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%) * 0.8),
    rgba(0, 0, 0, 0) calc(var(--wave-out2-0, 72%) + var(--wave-out2-w, 28%))
  );
  pointer-events: none;
  position: absolute;
  width: 100%;
  z-index: 0;
}

/* t_009f893d (Wira 2026-11-12 ~13:40, verbatim: "yang saya maksud muncul duluan itu full animasi
   ombaknya baru muncul copy teksnya biar elegan"): the static poster is gone. Load sequence:
   (1) the canvas fades in over 0.35s on its first rendered frame, already moving (the RAF loop
   starts with that frame); (2) HeroDotWave then sets data-hero-go on the hero and the copy enters
   (see the hero-wave-copy rules next to the entrance keyframes below). */
.home-r8-scope .hero-r8--wave .hero-r8-wave {
  opacity: 0;
  transition: opacity 0.35s ease-out;
}

.home-r8-scope .hero-r8--wave[data-dot-wave] .hero-r8-wave {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  /* everything at once: the canvas' single static frame appears with no fade */
  .home-r8-scope .hero-r8--wave .hero-r8-wave {
    transition: none;
  }
}

.home-r8-scope .hero-r8--wave .hero-r8-in {
  z-index: 1;
}

/* t_8fcf267d (Wira 11:17 "hapus visual 3 itu", preview branch): the cards are not rendered; this
   empty stage keeps their vertical room (same height clamp as .hero-r8-panel), so the wave floats
   between the CTA row and the trusted-by logos. Mobile keeps CTA right under the subtitle (the
   480px rules below reordered the cards above the CTA; there are no cards now). */
/* t_8398eeaa (Wira 2026-11-12 11:26, verbatim: "nah geser ketengah copy brandnnya, jangan
   terlalu ketas"): with the 3 cards gone, the H1/sub/CTA block read as glued under the nav.
   margin-top on the H1 below pushes the whole copy block (and, since HeroDotWave measures the
   CTA/stage live, the floating wave with it) down toward the hero's optical middle. Desktop is
   still the Round-21 auto-centered stack (.hero-r8 justify-content:center): the stage/trusted
   margin-top coefficients below are trimmed by roughly the same budget so the total box height
   -- and so trusted-by's on-screen position -- doesn't grow by the inserted amount's full halved
   share, keeping the hero's "fits about one viewport" fit from drifting. */
.home-r8-scope .hero-r8--wave .hero-r8-stage {
  flex: none;
  /* t_8398eeaa (Wira ~11:54, verbatim: "titik gelombaknya tambah tingginya biar lebih cantik,
     karena yang sekarang terlihat pendek"): the stage is a layout spacer, not the wave's own
     bounding box (HeroDotWave's canvas is absolute/inset:0 on the whole .hero-r8, and reads this
     element's own bottom edge as where the bottom fade-out band ENDS) -- so this height directly
     sets how tall the fully-opaque wave band between the CTA and the fade-out reads. Raised back
     up past the original 288px (this round's earlier, too-short 190px pass is reverted) to fill
     more of the gap, per his ask. */
  /* t_44b7d670: shortened (two-point fit, same live-measured pairs as the H1 margin-top above)
     so the room the copy block's extra margin-top needs doesn't leave trusted-by's own air at its
     pre-change ~17-23px -- cuts ~64px at 1280x636 and ~126px at 1440x900, slightly more than the
     H1 shift itself, landing trusted-by's air at ~32-48px instead of just preserving it. */
  /* t_de763916 (Wira 2026-11-12 ~12:40, same screenshot: "titik ombaknya juga tambahin
     tingginya keatas"): ~1.4x taller than the t_44b7d670 cut (174 -> 244px coefficient, 210 ->
     294px ceiling, 50 -> 70px floor, 20.5 -> 28.7vw cap) -- not the full ~1.5x literally asked,
     held back ~10% so the extra height doesn't eat trusted-by's own air below the fold (the H1
     cut above already frees ~45px of total stack height for this to grow into). */
  height: clamp(70px, min(28.7vw, calc(244px * var(--hero-hs-deep, 1) - 7px)), 294px);
  margin-top: max(10px, calc(10px * var(--hero-hs-deep, 1)));
  pointer-events: none;
  width: 100%;
}

/* t_8398eeaa (Wira ~11:43, verbatim: "nice, coba implement sekarang" -- approved the WIP review
   shot, but relayed note was the centre still read upper ~40%): ~60px more at 1440x900 (900svh).
   The hero stack centres as a whole (.hero-r8 justify-content:center), so growing the H1's own
   top margin only shows up as roughly half that growth in the H1's on-screen position once the
   box re-centres -- this round's coefficient (17.7svh, up from 11svh) is picked so the NET shift
   is ~60px at 1440x900, not the raw added margin. Ceiling/floor scaled by the same ratio. */
/* t_8398eeaa (Wira ~11:52, screenshot at 1280x636, verbatim: "harusnya copy hero bisa di geser
   ke tengah lagi, gpp cta di tengah2 banget akrena dia gak full teks. lalu Trusted by growing
   businesses dan logo bisa digeser dikit kebawah karena space bawah terlalu tinggi"): supersedes
   the plain-svh version of this rule. Tied to --hero-hs (the shared height-scale every other gap
   in this hero already uses, see the big comment on .hero-r8's own padding-top above) instead of
   a bare svh fraction, so the CTA row lands at roughly the same fraction of the viewport at both
   1280x636 and 1440x900 -- a flat svh clamp drifted between the two (a plain % of height scales
   linearly, but the hero's own top gap/stage/trust margins all scale through --hero-hs, which is
   NOT linear below 900svh), which is why the first pass centred differently at his screen size
   than at 1440. */
@media (min-width: 681px) {
  .home-r8-scope .hero-r8-h1 {
    /* t_44b7d670 (Wira 2026-11-12 ~12:10, verbatim: "Masih kurnag ketengah lagi copynya" --
       Noe measured the copy block (H1-top..CTA-bottom) centred at ~40% of 1280x636, reads high).
       Hero overflows min-height:100svh at both 636 and 900 (measured live: hero height 666.75 at
       636, 925.4 at 900) -- justify-content:center has no slack to work with there, so any added
       margin here shows up as a FULL on-screen shift, not halved. Two-point fit (own
       getBoundingClientRect() reads, dev server, not hand math) targets the block centre landing
       at ~49% of viewport at both 1280x636 (hero-hs floor 0.62, net +41px) and 1440x900
       (hero-hs 1, net +109px): coefficient/offset solved from those two (hs, px) pairs, measured
       live via getBoundingClientRect() on a clean session (first pass overshot by a flat ~16px
       at both points -- a stray session/tab mixed a different task's page into the read; redone
       in a dedicated session + hard reload before every measurement). The stage height cut below
       removes more than this (R=64px/126px) so trusted-by lands with ~32-48px air, not just its
       pre-change ~17-23px. */
    /* t_de763916 (Wira 2026-11-12 ~12:40, verbatim with a 1280x636 screenshot: "copy bodynya
       naikin lagi keatas... karena yang sekarang jadi terasa kosong diatasnya"): d270557's -70px
       offset read too low (nav->H1 gap ~150px in his shot, block centred too high, past the
       prior 0f33a93 position he'd already called too high the other way). -115px sits between
       the two: a flat -45px cut at both measured hs points (hs 0.62 -> ~34px, hs 1 -> ~126px),
       same two-point-fit shape, aiming the block centre back down to ~43-45% instead of ~49%. */
    margin-top: max(24px, calc(241px * var(--hero-hs, 1) - 115px));
  }
}

@media (max-width: 680px) {
  .home-r8-scope .hero-r8--wave .hero-r8-stage {
    /* t_de763916 (brief: "wave too heavy... a slightly shorter band"): ~18% shorter than before
       (170/260 -> 140/210), paired with the opacity cut below for a calmer, lighter mobile wave. */
    height: clamp(140px, 24svh, 210px);
    /* t_8398eeaa (Wira ~11:56, mobile screenshot, verbatim: "gelombang juga dibawah dikit" --
       "32-48px of clean air between the buttons and the first dots"): height unchanged per his
       own note ("udah cukup tinggi di mobile" / "it's already tall enough... shift it down
       rather than stretching it") -- only the gap above it grows. */
    margin-top: clamp(10px, 7.5svh, 68px);
  }

  /* t_de763916 (brief: "wave too heavy, dense and dark-ish... lower alpha"): the canvas itself
     reads calmer at a flat reduced ceiling opacity on top of the existing fade mask, mobile only
     -- desktop/tablet keep full strength. */
  .home-r8-scope .hero-r8--wave[data-dot-wave] .hero-r8-wave {
    opacity: 0.78;
  }
}

@media (max-width: 480px) {
  .home-r8-scope .hero-r8--wave .hero-r8-ctas {
    margin-top: clamp(18px, 3svh, 28px);
    order: 0;
  }

  .home-r8-scope .hero-r8--wave .hero-r8-stage {
    flex: 1 1 auto;
    height: auto;
    /* t_de763916: ~17% shorter (240 -> 200px ceiling), matching the 680px band's own trim above. */
    min-height: clamp(130px, 22svh, 200px);
    order: 1;
  }
}

/* No WebGL (or a lost context): one static frame of the same wave. Only this rule references
   the images, so they are fetched only on that path. The blend drops the frame's own white/black
   ground onto the hero background. */
.home-r8-scope .hero-r8--wave[data-dot-wave="fallback"] .hero-r8-wave {
  background: url("/images/home-r8/hero-dot-wave-light.webp") center bottom / cover no-repeat;
  mix-blend-mode: multiply;
}

[data-theme="dark"] .home-r8-scope .hero-r8--wave[data-dot-wave="fallback"] .hero-r8-wave {
  background-image: url("/images/home-r8/hero-dot-wave-dark.webp");
  mix-blend-mode: screen;
}

.home-r8-scope .hero-r8-in {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Round-10: the reference's own vertical rhythm isn't uniform (10px/25px/48px/23px/30px
     between H1-sub-CTA-gallery-caption-trusted), so each child below carries its own
     margin-top instead of one flex `gap` value. */
  gap: 0;
  max-width: 1264px;
  position: relative;
  text-align: center;
}

.home-r8-scope .hero-r8-h1 {
  font-family: var(--f);
  /* Round-10: reference H1 block is ~123px tall for 2 lines at 1280 wide (~56px font,
     line-height 1.1 unchanged) -- scales to ~63px at 1440, clamp lets it breathe up to 1920.
     First pass at 4.4vw measured ~6-7% narrower than the reference's own line-1/line-2 ink
     width (667px/359px vs 707px/386px at 1280) -- bumped to 4.7vw to close that gap.

     Round-16 (Wira 2026-11-09 ~14:35, verbatim: "heading 1 di hero section di perkecil aja
     biar Trusted by growing businesses muat dalam 1 hero section full height diawal load"):
     measured live at 1280x800/1440x900/1536x864/1920x1080 (CDP viewport overrides, logo row's
     own getBoundingClientRect().bottom vs window.innerHeight) -- 1280x800 was the only one
     still short, by ~5px, once the caption above was removed. Scaled the whole clamp down
     (32/4.7vw/72 -> 30/4.3vw/64, same 2-line/1.1-leading shape) instead of a breakpoint-only
     patch, so every size gets a bit more headroom, not just the one that was failing.

     Round-21 (Wira 2026-11-10 09:40, verbatim: "kepotong dikit bawahnya ... atasnya kok kayak
     ada space putih kosong"): that round-16 tuning only covered 4 specific viewport HEIGHTs
     (800/900/864/1080); the 4.3vw preferred value is pure width-based, so it stays the same
     size on a 1280x634 window as on a 1280x1200 one even though the stack (H1/sub/CTAs/gallery/
     trusted-by) is a near-fixed total height -- on a short window the content simply overflows
     past the viewport (min-height:100svh is a floor, not a cap) and the trusted-by logo row
     renders below the first screen. `min(4.3vw, 64px * --hero-hs)` (the shared height-scale
     variable, see the comment on .hero-r8's own padding-top above) makes the ceiling itself
     height-aware: unchanged at 900svh and up (the --hero-hs:1 case matches the original flat
     64px exactly), smaller only where the window is short relative to its width. */
  font-size: clamp(30px, min(4.3vw, calc(64px * var(--hero-hs, 1))), 64px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.home-r8-scope .hero-r8-h1-line {
  display: inline-block;
  white-space: nowrap;
}

/* Round-20 (Wira direct, 2026-11-09 ~16:10): 2 lines at every width, mobile included, via the
   font-size clamp alone (media query below) -- no manual <br> inside line 1 any more, so no
   hero-r8-h1-break rule to carry here either (round-19's 3-line mobile shape is reverted). */

/* Round-18 (item 7, Wira 2026-11-09 ~15:00): line 2 is just the rotating word, reusing the
   shared HeroRotatingEmphasis component/CSS (globals.css ~1748-1811, which targets `.hero h1`)
   under the r8 h1's own class instead -- same italic/colour/sizing-reserve mechanism, no new
   component or word list (lib/home-content.ts titleEmphasisWords). */
.home-r8-scope .hero-r8-h1 .hero-line-inner:has(.hero-emphasis-rotator) {
  align-items: flex-end;
  display: inline-flex;
}

.home-r8-scope .hero-r8-h1 i,
.home-r8-scope .hero-r8-h1 .hero-emphasis-rotator i,
.home-r8-scope .hero-r8-h1 .hero-emphasis-sizer span {
  /* Superseded (t_caffb5b2, Wira approved 2026-11-10 ~16:34 "opsi 3 coba implement", the
     italic-gradient-trial follow-up): the 2026-11-09 ~16:16 "ganti warnanya jangan coklat" call
     below is reversed by this new, explicitly re-approved brown (--accent-italic, same hex as the
     old --acc this rule used to read, #8b6957) -- this is the one rule in the cascade actually
     matching the home hero's DOM (.home-r8-scope .hero-r8-h1 ...), so the shared h1 em/i, h2 em/i
     rule in globals.css alone never reached it without this override. */
  color: var(--accent-italic);
  font-family: var(--font-italic);
  font-size: 1em;
  font-style: italic;
  font-synthesis: none;
  font-weight: 700;
  letter-spacing: inherit;
  line-height: inherit;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-rotator {
  align-items: end;
  display: inline-grid;
  line-height: inherit;
  /* Wira direct, 2026-11-09 ~16:16 (verbatim): "yang di desktop belum rata tengah yang your
     growthnya" -- a fixed reserved-width box (sized to the widest word, left-aligned text)
     always left a trailing empty gap after short words, so the "your <word>" line's visible
     content sat left-of-centre under line 1 above. The sizer is now disabled (below) so this
     box hugs the ACTIVE word only; combined with .hero-r8-h1-your having no forced width, the
     whole line's own content width changes with the word and .hero-r8-in's text-align:center
     re-centres it correctly every rotation -- a real re-centre each tick rather than a reserved
     empty margin on one side. 0.28em reads as one normal word space after "your" (18376: was a
     literal space character + this padding stacking into ~2 spaces; the literal space is gone
     from the JSX now, this padding is the only gap). */
  padding-left: 0.28em;
  vertical-align: bottom;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-sizer,
.home-r8-scope .hero-r8-h1 .hero-emphasis-mask {
  grid-area: 1 / 1;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-sizer {
  /* See the rotator comment above: disabled (not just visually hidden) so it no longer reserves
     the widest word's width in the grid track -- the box now sizes to the active word alone. */
  display: none;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-sizer span {
  grid-area: 1 / 1;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-mask {
  /* t_d4b92f2c: grid, not flex -- the outgoing and incoming words share one cell during the
     crossfade (HeroRotatingEmphasis.tsx); the component eases this box's width between them. */
  align-items: end;
  display: grid;
  justify-items: start;
  line-height: inherit;
  margin-bottom: -0.08em;
  overflow: visible;
  padding-bottom: 0.08em;
}

.home-r8-scope .hero-r8-h1 .hero-emphasis-mask i {
  display: inline-block;
  grid-area: 1 / 1;
  transform-origin: 50% 62%;
  white-space: nowrap;
}

.home-r8-scope .hero-r8-sub {
  color: var(--r8-muted);
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.5;
  margin-top: 10px;
  max-width: 46ch;
}

/* t_736a3d78 (Wira 2026-11-10 19:20, verbatim: "desc dibawah heading jadi terpisah 3 lines,
   harusnya cukup 2lines aja"): the ID sentence-1+2 line ("Brand yang lebih jelas. Pengalaman
   digital yang lebih baik.") measures ~515px at the hero's flat 19px font (1188px+ viewports),
   wider than the shared 46ch (~500px) cap tuned for EN's shorter equivalent, so it wrapped onto
   a second physical line -- 3 lines total instead of 2. 48ch (~522px) is the smallest ch bump
   that keeps it on one line (measured live, CDP, 1280x900) without widening the column enough to
   affect EN at all (EN's own copy is well under 46ch already). ch is font-relative, so this holds
   at the mobile floor too -- the floor is viewport-width-bound there anyway, not ch-bound, for
   both locales alike. */
html[lang="id"] .home-r8-scope .hero-r8-sub {
  max-width: 48ch;
}

.home-r8-scope .hero-r8-ctas {
  align-items: center;
  display: flex;
  gap: 20px;
  /* Round-22: sub->CTA gap, flat 25px at 900svh+ (--hero-hs-deep falls back to 1, matching the
     mockup's tuned value), shrinks below that to help pay for the raised nav->H1 floor above. */
  margin-top: max(14px, calc(25px * var(--hero-hs-deep, 1)));
}

.home-r8-scope .hero-r8-ctas .btn {
  background: var(--r8-ink);
  border: 1px solid var(--r8-ink);
  border-radius: var(--r8-pill);
  color: #fff;
  font-weight: 600;
  padding: 14px 26px;
}

.home-r8-scope .hero-r8-ctas .btn:hover {
  background: #2a292d;
  border-color: #2a292d;
}

.home-r8-scope .hero-r8-see-work {
  align-items: center;
  color: var(--r8-ink);
  display: inline-flex;
  font-weight: 600;
  gap: 8px;
  text-decoration: none;
}

.home-r8-scope .hero-r8-see-work .arr {
  transition: transform 0.2s ease;
}

.home-r8-scope .hero-r8-see-work:hover .arr {
  transform: translateX(4px);
}

/* ---- 3-panel gallery: ~1fr 2.45fr 1fr per Wira's handoff, equal height, 16px gap ---- */

.home-r8-scope .hero-r8-gallery {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr 2.45fr 1fr;
  /* Round-21 (Wira 2026-11-10 09:40): see the --hero-hs comment on .hero-r8's own padding-top
     above -- flat 40px, unchanged at 900svh and up (--hero-hs:1), shrinks in proportion below
     that so the short-window stack has room for the trusted-by row underneath. */
  margin-top: max(16px, calc(40px * var(--hero-hs-deep, 1)));
  width: 100%;
}

.home-r8-scope .hero-r8-panel {
  background: var(--r8-panel);
  border: 1px solid var(--r8-line-2);
  border-radius: var(--r8-card);
  /* Round-10: reference panel row is ~265px tall at 1280 wide (~290px at 1440).
     Round-21 (Wira 2026-11-10 09:40): the 20.5vw preferred value alone was pure width-based, so
     it stayed full-size on a short-but-wide window (e.g. 1440x780) even though that's exactly
     the case that no longer fits. min(20.5vw, 288px * --hero-hs) tracks whichever dimension is
     tighter -- unchanged at every viewport this was already tuned for (--hero-hs:1 there makes
     the second term exactly 288px, so vw stays the binding term and it still hits the 288px
     ceiling), shorter only where the window's height, not its width, is the real constraint.
     Round-22: swapped to --hero-hs-deep (still 1 at 900svh+, falls off harder below) so the
     card absorbs more of the shrink the raised nav->H1 gap needs; floor stays 150px so labels
     never clip. */
  height: clamp(150px, min(20.5vw, calc(288px * var(--hero-hs-deep, 1))), 288px);
  overflow: hidden;
  position: relative;
}

.home-r8-scope .hero-r8-panel-ai {
  background: #f1ece6;
}

/* r13g item 3 (Wira's v3-b pick): the panel is a plain full-bleed photo tile now, same pattern
   as its two siblings (.hero-r8-panel-ai above) -- the old contain/flex-column/sampled-backdrop
   treatment this block carried (built for the retired illustration placeholder) is gone. */
.home-r8-scope .hero-r8-panel-app {
  align-self: start;
}

.home-r8-scope .hero-r8-img {
  z-index: 0;
}

/* r13g item 3: the app panel is a plain full-bleed photo like its siblings now -- the old
   blurred-backdrop/contain/feathered-edge treatment this block carried (for the retired
   illustration placeholder, object-fit:contain) no longer applies to anything in this panel. */

.home-r8-scope .hero-r8-panel-website {
  padding: 10px;
}

.home-r8-scope .hero-r8-browser {
  background: #fff;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  position: relative;
  width: 100%;
}

.home-r8-scope .hero-r8-chrome {
  align-items: center;
  background: #fafafa;
  border-bottom: 1px solid rgba(25, 24, 27, 0.08);
  display: flex;
  flex: 0 0 auto;
  height: 30px;
  justify-content: space-between;
  padding: 0 12px;
  position: relative;
  z-index: 2;
}

.home-r8-scope .hero-r8-chrome-dots {
  display: flex;
  gap: 6px;
}

.home-r8-scope .hero-r8-chrome-dots span {
  background: rgba(25, 24, 27, 0.22);
  border-radius: 999px;
  height: 7px;
  width: 7px;
}

.home-r8-scope .hero-r8-chrome-url {
  background: rgba(25, 24, 27, 0.07);
  border-radius: 999px;
  height: 8px;
  width: min(42%, 220px);
}

.home-r8-scope .hero-r8-chrome-nav {
  align-items: center;
  display: flex;
  gap: 5px;
}

.home-r8-scope .hero-r8-chrome-nav i {
  background: rgba(25, 24, 27, 0.22);
  border-radius: 999px;
  display: block;
  height: 2px;
  width: 14px;
}

.home-r8-scope .hero-r8-browser-img {
  flex: 1 1 auto;
  position: relative;
}

/* Round-10 (task item 4): plain uppercase tracked text, not a pill/chip, bottom-left of each
   panel (or, for the website panel, of the inset browser-img so it sits over the photo and not
   over the grey card's own padding). A soft light halo (not a filled box) keeps contrast on
   whichever part of the photo it lands on, matching the reference's unboxed look.
   Round-18 (item 2, diagnosis t_06f8c6ea c18351): "APPS & SYSTEMS" read tight against the phone
   photo's own shadow/bottom edge at 1440 even though box-math clearance was positive -- give
   every label its own clearer zone (14->20px). */
.home-r8-scope .hero-r8-label {
  bottom: 20px;
  color: var(--r8-ink);
  font-size: 10px;
  font-weight: 600;
  left: 14px;
  letter-spacing: 0.14em;
  position: absolute;
  text-shadow: 0 1px 10px rgba(255, 255, 255, 0.75), 0 1px 3px rgba(255, 255, 255, 0.85);
  text-transform: uppercase;
  z-index: 2;
}

/* r13g item 3: the app panel's label is a full-bleed overlay again now, same as its two
   siblings (no special-case: the flex-column/static-label treatment above is gone). */

/* Round-16 (Wira 2026-11-09 ~14:35, verbatim: "hapus aja") -- the caption paragraph between
   the gallery and the logo row is gone (HeroR8.tsx); its own rule (font-size 15px, margin-top
   20px) is removed with it. */

.home-r8-scope .hero-r8 .hero-client-trust {
  /* Round-10 (Noe's 1280 measurement): the shared .client-marquee-h (120px) centres the logo
     glyphs inside a fixed track, leaving ~35-40px of invisible slack above them that the
     reference doesn't have (its logo row sits right under the caption, no border line). Shrink
     the track for this scope only -- the shared component/other pages keep their 120px.
     Round-16 (Wira 2026-11-09 ~14:35, verbatim: "hapus aja" the caption line + fit the whole
     hero above the fold): the caption paragraph between the gallery and this block is gone
     (HeroR8.tsx), so the old 43(gallery)+20(caption margin)+~19(caption line)+25(this margin) ≈
     87px gap collapses to one direct margin here -- tightened to 28px (32px still clipped
     1280x800 by ~5px once measured live; see the H1-clamp comment above for the fuller fit
     pass), not a straight sum of the removed caption's own spacing.

     Round-18 (item 6, Wira 2026-11-09 ~15:00, verbatim: "kenapa Trusted by growing businesses
     gak jalan animasi lagi?"): Round-15's static-centred-row override (this scope only) is
     removed below -- desktop now falls straight through to the shared component's own
     continuous scroll + edge mask-image fade + pause-on-hover/focus + reduced-motion-static
     behaviour (globals.css ~1990-2080), unchanged, instead of re-disabling it here.

     Round-20 (Wira direct, 2026-11-09 ~16:18, verbatim: "icon Trusted by growing businesses
     perkecil biar gak terliat makan section hero"): logos were full size (--client-marquee-k:1,
     the shared global default) and the 64px track read heavy next to the smaller H1/sub above.
     --client-marquee-k scaled to 0.65 (desktop) -- measured the 4 widest reference logos at
     k:1 (26-48px tall) down to ~17-31px, centred on the ~24-28px ask -- track shrunk from 64px
     to 44px to match (no more empty vertical space around the now-smaller glyphs), and
     margin-top opened up from 28px to 40px for "more air above it" (still clears the first
     viewport at 1280x800/1440x900/1536x864/1920x1080, re-measured live). */
  --client-marquee-h: 44px;
  --client-marquee-k: 0.65;
  /* Round-21 (Wira 2026-11-10 09:40): see the --hero-hs comment on .hero-r8's own padding-top
     above -- flat 40px, unchanged at 900svh and up (--hero-hs:1), shrinks in proportion below
     that so the logo row itself has a better chance of staying above the fold. */
  /* t_8398eeaa: trimmed 40->26px alongside the stage margin-top above, to budget room for the
     new h1 margin-top (same media-query family) without growing the box's total height. */
  margin-top: max(16px, calc(10px * var(--hero-hs, 1)));
  /* r13f item 2: explicit gap below the logo row and before #problem (002), instead of relying
     on margin-collapsing with that section's own top padding (r13f-build-notes.md §2). */
  margin-bottom: var(--r8-s7);
  width: 100%;
}

/* Wira, 2026-11-09 ~16:35 (verbatim): "line dibawah trusted client hapus aja, karena di mobile
   jadi gak cantik posisinya" -- the shared .client-marquee component (app/globals.css) paints a
   border-top hairline above the logo row; it read fine at 1440 but looked unanchored on mobile.
   Dropped for this scope only (.home-r8-scope), at every width -- /id's own Hero still uses the
   same shared component unchanged. No extra spacing added: the existing 40px margin-top above
   already keeps the gap to the caption balanced without the line (checked 390 + 1440). */
.home-r8-scope .hero-r8 .hero-client-trust .client-marquee {
  border-top: 0;
}

/* t_009f893d (Wira 2026-11-12 ~13:29, verbatim: "logo trust clientnnya cukup tampilkan 7 aja lalu
   slider jalan untuk semua client, jangan selebar sekarang"): desktop window ~7 logo slots wide,
   centred under the label. Measured live: one slot (logo + 48px gap) is ~91px at
   --client-marquee-k 0.65, so 7 slots = ~640px; the soft edge fades sit inside that window
   (12% each side, wider than the shared 5% so they still read as fades on the narrower box).
   The track still slides through every client (globals.css animation, untouched). Mobile keeps
   its own full-width window (<=680px rule below). */
@media (min-width: 681px) {
  .home-r8-scope .hero-r8 .hero-client-trust .client-marquee {
    margin-inline: auto;
    mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
    max-width: 640px;
  }
}

/* t_009f893d (Wira 2026-11-12 ~13:27, verbatim: "bagusnya top section 2 dibikin putih yang sama
   dengan hero section baru graddasi pattern ke background pattern yang sekarang"): no hard edge
   where the hero ends. Section 2 starts in the hero's own background (--r8-bg, both themes) and
   eases (smoothstep stops) into its own --r8-bg-2 over --seam (~190px at 1280, 216px at 1440,
   120px on phones); its grid fades in from 0 over the same band (mask on the grid layer), then
   keeps its existing bottom fade. The heading sits below the band at every width (measured:
   ~250px / ~156px from the section top), so it lands on the fully settled pattern. The hero's own
   wave fade already reaches 0 at the hero's bottom edge, so the two fades chain.
   t_9d43655a (Wira 2026-11-12 ~18:3x, "like About, on every page incl. home, light + dark"): the
   --r8-bg -> --r8-bg-2 ramp is gone. In dark it read as a lighter band (#131316 -> #242428) under
   the wave; About has none. Section 2 now paints the hero's own --r8-bg end to end, via the one
   shared "first section after a hero" rule in app/styles/hero-visual-r8.css. The grid fade-in band
   below stays. */

.home-r8-scope .hero-r8--wave + .r8-sec.r13-grid-bg::before {
  --seam: clamp(120px, 15vw, 220px);
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0.104) calc(var(--seam) * 0.2),
    rgba(0, 0, 0, 0.352) calc(var(--seam) * 0.4),
    rgba(0, 0, 0, 0.648) calc(var(--seam) * 0.6),
    rgba(0, 0, 0, 0.896) calc(var(--seam) * 0.8),
    #000 var(--seam),
    #000 86%,
    transparent
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, 0.104) calc(var(--seam) * 0.2),
    rgba(0, 0, 0, 0.352) calc(var(--seam) * 0.4),
    rgba(0, 0, 0, 0.648) calc(var(--seam) * 0.6),
    rgba(0, 0, 0, 0.896) calc(var(--seam) * 0.8),
    #000 var(--seam),
    #000 86%,
    transparent
  );
}

/* t_57d08c3e (Wira 2026-11-12 ~12:58, verbatim: "kayaknya 5 terlalu dikit, mending segini aja" on
   a screenshot of the earlier, un-capped d270557 width -- ~8 logos visible): reverts the
   t_de763916 max-5 window above (max-width:460px) outright. The track itself was never touched
   by that rule either way (still scrolls through all 17 clients, globals.css's own
   client-marquee animation + both <ul> sets); removing the cap just lets .client-marquee go back
   to its default width:100% of the .w container, same as before t_de763916, so ~8 logos show at
   once at desktop widths with the existing edge mask-image fades at both ends unchanged. Mobile
   (<=680px) was never touched by the capped rule either -- no change there. */

/* t_8398eeaa (Noe/Wira, mobile screenshot: the shared component's 5%/95% edge mask -- fine at
   desktop's ~900px+ track width -- is only ~17px at a 334px mobile track, too thin to read as a
   fade next to a dark/light logo silhouette: it looked like a hard clip. Wider fade fractions,
   this scope + width only (desktop/other .client-marquee instances untouched). */
@media (max-width: 680px) {
  .home-r8-scope .hero-r8 .hero-client-trust .client-marquee {
    mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
  }
}

.home-r8-scope .hero-r8 .hero-client-trust .client-marquee-set {
  gap: 48px;
  padding-right: 48px;
}

.home-r8-scope .hero-r8 .hero-client-trust .lbl {
  color: var(--r8-muted);
  display: block;
  font-family: var(--m);
  font-size: 12px;
  letter-spacing: 0.14em;
  /* r13f item 2: 14px -> 26px, more room between the label and the logo row. */
  margin-bottom: 26px;
  text-align: center;
  text-transform: uppercase;
}

/* Round-20+ (Wira direct, 2026-11-10 ~02:0x, verbatim: "logonya harusnya ada animasi jalan
   seperti di desktop view") -- reverts Round-18's static-wrap mobile treatment below: the
   shared continuous-scroll marquee (edge-fade mask, pause-on-hover/focus, reduced-motion-static,
   app/globals.css ~2052-2126) now runs on mobile too, same behaviour as desktop. Keeps only the
   Round-20 mobile logo-scale-down (0.55, below the desktop 0.65) -- the narrower viewport still
   wants smaller glyphs than desktop's. */
@media (max-width: 860px) {
  .home-r8-scope .hero-r8 .hero-client-trust {
    --client-marquee-k: 0.55;
  }
}

/* t_e3ba32c6 (designer MOTION-SPEC.md, commit adad4f7, Components item 1 "Hero entrance"):
   rebuilds the ad hoc t_3a7d4e09 stagger (2026-11-10 ~14:55, predates this spec's gate) onto the
   spec's own data-hero-enter="1..4" contract (H1 -> subhead -> CTA row -> gallery), a clean
   0.06s step reusing the exact premiumEase bezier cubic-bezier(0.16,1,0.3,1) already used for
   every inner-page hero (`pg-hero-in`, globals.css) -- no new easing curve. Attribute-selected
   (not class-selected) so the markup itself documents the contract (HeroR8.tsx), one shared rise
   keyframe for all 4 groups (opacity + translateY(16px) -> rest, no blur, matches the spec) so
   the gallery no longer gets its own scale-based variant. Delays 0/0.06/0.12/0.18s, 0.42s
   duration: the last group (gallery) starts at 0.18s and settles at 0.6s, inside the spec's
   <=700ms hero budget. Plays once at paint, no JS wait (no hydration-LCP risk).
   One deliberate deviation from the spec's literal "opacity:0": starts at 0.01 instead, the same
   trick motion.css already uses sitewide for [data-reveal] ("reads the same, but still counts as
   painted for the LCP tracker") -- the gallery group wraps the website panel's `priority` image,
   so a literal opacity:0 start risks the LCP tracker holding off "painted" until the animation
   resolves, the exact regression t_3a7d4e09's own scale variant was already written to avoid.
   Trusted-by's own fade-in (unchanged, not one of the spec's 4 groups) is untouched below. */
@keyframes hero-enter-in {
  from {
    opacity: 0.01;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.home-r8-scope .hero-r8-in > [data-hero-enter] {
  animation: hero-enter-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
/* t_57d08c3e: +0.18s flat on every delay below (0/0.06/0.12 -> 0.18/0.24/0.3s). The wave hero
   (the only one on this page) overrides these with its own wave-first sequence below
   (t_009f893d). */
.home-r8-scope .hero-r8-in > [data-hero-enter="1"] { animation-delay: 0.18s; }
.home-r8-scope .hero-r8-in > [data-hero-enter="2"] { animation-delay: 0.24s; }
.home-r8-scope .hero-r8-in > [data-hero-enter="3"] { animation-delay: 0.3s; }
.home-r8-scope .hero-r8-in > [data-hero-enter="4"] { animation-delay: 0.36s; }

/* t_530a0dc5 (Wira "ya 1", 2026-11-13 ~07:19, option A: "judulnya langsung tampil, gerakan
   naiknya tetap ada" -- headline visible from the first frame, rise motion stays): the H1
   (data-hero-enter="1") was this page's LCP element pre-fix, and Chrome only marks an element
   painted for LCP once its computed opacity is > 0 -- the shared 0.01-start fade above was
   gating LCP on it. Same keyframe shape, same 0.42s duration/easing/delay as hero-enter-in (only
   opacity pinned to 1 throughout), so the rise distance/timing is byte-identical and only the
   fade is gone.
   Measured after the H1-only fix (Lighthouse trace, largest-contentful-paint-element audit,
   3/3 runs): the LCP element then SHIFTS to the subline (`p.hero-r8-sub`, data-hero-enter="2"
   -- it has a bigger painted rect than the H1 at this copy) and stays gated on its own fade
   (Render Delay ~91% of LCP, ~4.7s) -- pre-mortem item 1, just one element over. The brief's
   explicit call ("whether the subline/CTA keep their stagger, as long as the LCP element isn't
   gated on a fade") covers this: the subline keeps the same rise/stagger, loses the fade too.
   CTA (3) and gallery (4, currently unrendered, HERO_CARDS=false) keep their fade -- neither was
   ever the measured LCP candidate. This is the safety-path (no-JS/no-WebGL) fallback entrance;
   the wave-hero path below is what Home actually plays. */
@keyframes hero-enter-in-rise-only {
  from {
    opacity: 1;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.home-r8-scope .hero-r8-in > [data-hero-enter="1"],
.home-r8-scope .hero-r8-in > [data-hero-enter="2"] {
  animation-name: hero-enter-in-rise-only;
}

.home-r8-scope .hero-r8-in > .hero-client-trust {
  animation: pg-hero-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: 0.32s;
}

/* t_009f893d (Wira ~13:40: the animated wave first, then the copy, "biar elegan"): on the wave
   hero the copy waits for the wave. HeroDotWave sets data-hero-go on the hero ~0.2s after the
   canvas' first frame; that swaps in a fresh animation (hero-wave-copy-b, the same keyframes under
   another name, so it starts from its first frame at that moment, no jump) with an 8px rise and a
   0.06s stagger: H1 -> sub -> CTA -> trusted-by, all settled ~0.6s after it starts. Safety: the
   copy is in the SSR HTML, and without data-hero-go (no JS yet, no WebGL, or no frame by ~0.85s)
   the default animation below plays anyway from 0.9s, pure CSS. HeroDotWave only sets the flag
   before 0.85s, so the two never both run. Opacity/transform only (CLS 0); 0.01 start opacity as
   above so the H1 still counts as painted for LCP. */
@keyframes hero-wave-copy-a {
  from {
    opacity: 0.01;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes hero-wave-copy-b {
  from {
    opacity: 0.01;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter],
.home-r8-scope .hero-r8--wave .hero-r8-in > .hero-client-trust {
  animation: hero-wave-copy-a 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter="1"] { animation-delay: 0.9s; }
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter="2"] { animation-delay: 0.96s; }
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter="3"] { animation-delay: 1.02s; }
.home-r8-scope .hero-r8--wave .hero-r8-in > .hero-client-trust { animation-delay: 1.08s; }
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter],
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > .hero-client-trust {
  animation-name: hero-wave-copy-b;
}
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter="1"] { animation-delay: 0s; }
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter="2"] { animation-delay: 0.06s; }
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter="3"] { animation-delay: 0.12s; }
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > .hero-client-trust { animation-delay: 0.18s; }

/* t_530a0dc5: same fix as hero-enter-in-rise-only above, for the wave-hero path Home actually
   plays (t_009f893d) -- pre-go (copy-a, 0.9s safety delay) and post-go (copy-b, the real
   sequence once HeroDotWave's first frame lands). H1 + subline opaque throughout (see the
   measured LCP-shift note above hero-enter-in-rise-only: the subline is the actual LCP
   candidate once the H1 stops gating it), 8px rise and the stagger unchanged; CTA/trusted-by
   keep the fade. */
@keyframes hero-wave-copy-a-rise-only {
  from {
    opacity: 1;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes hero-wave-copy-b-rise-only {
  from {
    opacity: 1;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter="1"],
.home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter="2"] {
  animation-name: hero-wave-copy-a-rise-only;
}
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter="1"],
.home-r8-scope .hero-r8--wave[data-hero-go] .hero-r8-in > [data-hero-enter="2"] {
  animation-name: hero-wave-copy-b-rise-only;
}

@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .hero-r8--wave .hero-r8-in > [data-hero-enter],
  .home-r8-scope .hero-r8--wave .hero-r8-in > .hero-client-trust {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .hero-r8-in > [data-hero-enter],
  .home-r8-scope .hero-r8-in > .hero-client-trust {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* t_e3ba32c6 (MOTION-SPEC.md Components item 5 "Hero gallery panel hover + press", the other
   confirmed gap -- app/home-r8.css carried zero :hover/:active rule on .hero-r8-panel before
   this): desktop hover lifts the panel translateY(-4px) + a soft shadow at 0.3s --ease-out
   (hover:hover + pointer:fine only, so touch never sticks a hover state); touch press is
   scale(0.97) at 0.1s --ease-out under hover:none + pointer:coarse, same values already proven
   on .btn/.pg-filter/.pg-work-card sitewide. Transform/shadow only -- the panel's own size
   (height, grid track) never changes, so this cannot shift layout or reflow. */
@media (hover: hover) and (pointer: fine) {
  .home-r8-scope .hero-r8-panel {
    transition: transform 0.3s var(--ease-out, ease), box-shadow 0.3s var(--ease-out, ease);
  }
  .home-r8-scope .hero-r8-panel:hover {
    box-shadow: 0 16px 32px -18px rgba(17, 17, 17, 0.35);
    transform: translateY(-4px);
  }
}

@media (hover: none) and (pointer: coarse) {
  .home-r8-scope .hero-r8-panel {
    transition: transform 0.1s var(--ease-out, ease);
  }
  .home-r8-scope .hero-r8-panel:active {
    transform: scale(0.97);
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .hero-r8-panel {
    transition: none;
  }
}

@media (max-width: 1100px) {
  .home-r8-scope .hero-r8-gallery {
    grid-template-columns: 1fr 2fr 1fr;
  }
}

@media (max-width: 860px) {
  .home-r8-scope .hero-r8 {
    padding: 120px 0 56px;
  }

  /* Wira, 2026-11-09 ~13:20 (verbatim): "Tinggi CTA nya kayaknya mending dibikin 1 line aja
     biar lebih rapi dan compact" -- one row, centred, compact auto-width pill + link instead
     of a full-width stacked column; ~half the previous vertical space, still >=44px tap
     target on the pill. Desktop (hero-r8-ctas base rule above) untouched. */
  .home-r8-scope .hero-r8-ctas {
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    gap: 16px;
    width: auto;
  }

  .home-r8-scope .hero-r8-ctas .btn {
    justify-content: center;
    width: auto;
    min-height: 44px;
    padding: 14px 22px;
    font-size: 14px;
    white-space: nowrap;
  }

  .home-r8-scope .hero-r8-see-work {
    font-size: 14px;
    padding: 12px 2px;
    white-space: nowrap;
  }

  /* Wira direct, 2026-11-09 ~13:00 (verbatim): "yang mobil di optimasi, harusnya tetap bisa
     sepert desktop viewnya, jadi tetap tampol 3 gambar itu, gpp kecil" -- desktop stays
     untouched; mobile drops the horizontal-scroll gallery (Round-12) for a scaled-down version
     of the SAME 3-up row, same 1fr/2.45fr/1fr ratio, all 3 panels visible at once, no scroll,
     no stacking. Also applies at 768 (item 3: "tetap 3-up"), since this breakpoint already
     covers 680-860. */
  .home-r8-scope .hero-r8-gallery {
    display: grid;
    gap: 7px;
    grid-template-columns: 1fr 2.45fr 1fr;
    margin-inline: 0;
    overflow-x: visible;
    padding-inline: 0;
    width: 100%;
  }

  .home-r8-scope .hero-r8-panel {
    border-radius: 13px;
    flex: initial;
    height: clamp(130px, 34vw, 160px);
    scroll-snap-align: unset;
    width: auto;
  }

  .home-r8-scope .hero-r8-panel-website {
    order: initial;
    width: auto;
  }

  .home-r8-scope .hero-r8-panel-ai,
  .home-r8-scope .hero-r8-panel-app {
    width: auto;
  }

  /* Noe follow-up (t_bc552569): labels still wrapped to 2 lines at 390/375 inside the narrow
     1fr side panels even at 8.5px -- drop tracking and shrink one notch further + force a
     single line so they never wrap over the artwork. The wider centre panel keeps the base
     mobile values below (fits one line already). */
  .home-r8-scope .hero-r8-label {
    bottom: 6px;
    font-size: 8.5px;
    left: 6px;
    letter-spacing: 0.08em;
  }

  .home-r8-scope .hero-r8-panel-ai .hero-r8-label,
  .home-r8-scope .hero-r8-panel-app .hero-r8-label {
    font-size: 7px;
    letter-spacing: 0;
    white-space: nowrap;
  }

  /* r13g continuation (Noe 02:12 re-check, 390): "APPS & SYSTEMS" (the longest of the 3 side
     labels) still touched/ran past the narrow 1fr panel's right edge at 7px -- its own tighter
     size + a right inset so the panel's overflow:hidden never has to clip live text. */
  .home-r8-scope .hero-r8-panel-app .hero-r8-label {
    font-size: 6.3px;
    right: 6px;
  }

  /* t_03e6ee53 item 4: tighter reserved strip at the panel's own smaller mobile height
     (clamp(130px,34vw,160px)) -- same static-flow frame/label split as desktop, just less
     padding so the phone still reads at a sensible size inside the shorter box. */
  .home-r8-scope .hero-r8-label-app {
    padding: 4px 6px 0;
  }

  /* Browser chrome scaled down to match the much shorter centre panel (item 1: "the browser
     chrome scaled down in the centre panel"). */
  .home-r8-scope .hero-r8-chrome {
    height: 18px;
    padding: 0 7px;
  }

  .home-r8-scope .hero-r8-chrome-dots {
    gap: 4px;
  }

  .home-r8-scope .hero-r8-chrome-dots span {
    height: 5px;
    width: 5px;
  }

  .home-r8-scope .hero-r8-chrome-url {
    height: 6px;
  }

  .home-r8-scope .hero-r8-chrome-nav i {
    width: 10px;
  }
}

/* t_65176c87 (Wira direct, "di mobile view ctanya coba bikin 1 kolom aja jadi start project lalu
   dibawahnya see our work tapi dengan font lebih kecil", OK'd 2026-11-13): one-column CTA stack,
   strictly below the 860px compact-row rule above (max-width:767.98px, so 768px/860px stay
   byte-identical -- this block only ever matches a narrower range than that one). "Start a
   Project" keeps its real .btn shape/colour/44px-floor, just stretched width:100%; "See our
   work" centres directly below at 13px/500 (down from the 860px rule's 14px/600) -- the existing
   min-height:44px/padding on .btn already holds its own floor, and this rule's line-height:20px +
   12px top/bottom padding holds See our work's own 44px tap height the same way. */
@media (max-width: 767.98px) {
  .home-r8-scope .hero-r8-ctas {
    flex-direction: column;
    width: 100%;
  }

  .home-r8-scope .hero-r8-ctas .btn {
    width: 100%;
  }

  .home-r8-scope .hero-r8-see-work {
    font-size: 13px;
    font-weight: 500;
    line-height: 20px;
    padding: 12px 2px;
  }
}

/* t_dcb5abd0 item 3 (comment 18770 on t_3b37c210, still open after e18e704's min-height:100svh
   fix): the mobile hero stack (H1/sub/CTAs/gallery/trusted-by) is a near-fixed ~489px tall
   regardless of viewport, so centring it (justify-content:center above) just splits whatever is
   left over evenly above and below -- on a 390x844 phone that is a ~178px gap on EACH side, read
   live as "big gap under the nav" (top half) and a ~25%-of-screen dead band under the logos
   (bottom half, nothing else there to break it up). Grow the gallery tiles and the gallery/
   trusted-by rhythm so more of a tall phone's screen is real content, shrinking both gaps by the
   same amount the centring maths adds back. Scaled in svh (not a flat px) so it tracks the actual
   viewport instead of one hand-tuned number -- checked live at 390x844 and 430x932. Height-gated
   (>=700px tall): 375x667 (667 tall) has almost no gap to begin with and stays on the base mobile
   rule above, per the brief ("375x667 stays as is"). */
@media (max-width: 680px) and (min-height: 700px) {
  .home-r8-scope .hero-r8-gallery {
    margin-top: clamp(48px, 7svh, 64px);
  }

  .home-r8-scope .hero-r8-panel {
    height: clamp(170px, 26svh, 230px);
  }

  .home-r8-scope .hero-r8 .hero-client-trust {
    margin-top: clamp(48px, 8svh, 78px);
  }
}

/* Round-20 (Wira direct, 2026-11-09 ~16:10, verbatim: "untuk di mobile view di hero section
   headingnya juga mirip desktop 2 lines aja, perkecil aja ukuran fontnya dibanding nambah
   lines" -- overrides the round-19 3-line mobile shape below): 2 lines at every width now,
   mobile included -- "Build the system behind" / "your <rotating>". No manual <br> left in the
   markup; the vw-heavy low end of this clamp is sized so the full 24-char line 1 stays on one
   line at 360-430 with the .w 24px-per-side gutter (48px total, see .w in globals.css) --
   measured live, S-104 CHECK: 360/375/390/430, plus the longest rotating word "next stage." on
   the your-line at 360. */
@media (max-width: 480px) {
  .home-r8-scope .hero-r8-h1 {
    /* t_de763916: tried a flat vw bump for "H1 reads small and weak" (brief) but line 1 ("Build
       the system behind", 24 chars, single nowrap span) is already at its one-line ceiling here
       -- live measurement at 360/375/390 showed the text's own width is ~12x its font-size, and
       the available column (viewport - 48px .w gutter) only has room for ~7.2-7.3vw before it
       clips off the right edge (measured overflow at the originally-tried 8.2vw: 354px text vs
       312px column at 360). Reverted to the exact Round-16 clamp (no regression) -- a real size
       bump here needs either a wider column or breaking line 1 onto 2 lines (reopening Round-20's
       explicitly-chosen single-line shape), out of scope for this pass; the "H1 reads small"
       complaint is addressed instead via the composition changes below (less dead air above it,
       more H1->sub->CTA rhythm, a calmer/shorter wave) rather than literally enlarging the type. */
    font-size: clamp(19px, 7vw, 34px);
    max-width: none;
    /* t_de763916: the empty top air (this addition on top of the untouched nav+24px floor) is
       cut back hard -- 13.3svh/140px ceiling down to 7.5svh/80px -- so the copy starts noticeably
       higher, freeing room for the taller rhythm below (sub/CTA margins) without growing the
       total stack. The nav-clearance floor itself (max() base) is unchanged. */
    margin-top: clamp(6px, 7.5svh, 80px);
  }

  /* t_6b3012cc (Wira, 2026-11-10 ~18:40, verbatim, with a 390 screenshot: "di mobile view
     kayakya mending visual nya dibikin 3 row dibanding 1 row 3 kolom gini, tapi pastikan muat
     100% height diawal"): the 3-up gallery from the 860px rule above becomes 3 full-width
     stacked rows at this width, and the whole hero (header clearance + H1 + paragraph + CTAs +
     all 3 rows) must fit the first screen with zero scroll. Every vertical gap down to the
     gallery is retuned height-aware (svh-scaled, same pattern as --hero-hs on desktop) so a
     short window (375x667) tightens instead of overflowing, instead of inheriting the 860px
     rule's flat 120px top padding (tuned for a 1-row gallery, not 3 stacked rows). Checked live
     at 390x844, 414x896, 360x780 and 375x667 -- CDP viewport overrides + real
     getBoundingClientRect() reads, not hand math (.evidence/t_6b3012cc/). */
  .home-r8-scope .hero-r8 {
    display: flex;
    flex-direction: column;
    /* Round-24 (t_dd2b0d70): was a hard `height:100svh` + `overflow:hidden` box, squeezing the
       whole stack to always fit exactly one screen -- the padding-top below was a flat svh-scaled
       clamp with no idea where the real (fixed-position) nav actually ends, so at some real
       widths/heights it under-shot and the H1 rode up under the nav logo (Wira's live-site photo
       + Noe's repro, see the big comment on the 680px mobile rule above). `min-height` (a floor,
       not a cap) + no `overflow:hidden` lets the stack grow past the first screen and the page
       scroll on a viewport too short for both "one screen" AND the nav clearance floor below --
       per Wira's own fix direction, don't let the old fit-one-screen tuning eat the top gap. */
    min-height: 100svh;
    justify-content: flex-start;
    /* `--r8-nav-h` now resolves on mobile too (hooks/useNavHeightVar.ts Round-24 update: falls
       back to the fixed `.nav-in`'s own rendered bottom edge when the outer `<nav>` collapses to
       0, which it always does on mobile -- see that hook's own comment). `max()` keeps the
       existing svh-tuned clamp as the result whenever it's already bigger than the floor (so
       nothing changes on a viewport where the old tuning already cleared the nav), and only lets
       the floor win where the clamp used to under-shoot -- same pattern as the desktop
       `--hero-r8-gap` floor above (Round-22). */
    padding: max(calc(var(--r8-nav-h, 56px) + 24px), clamp(58px, 11svh, 84px)) 0 0;
  }

  .home-r8-scope .hero-r8-in {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
  }

  .home-r8-scope .hero-r8-sub {
    /* t_de763916 (brief: "give the copy block more vertical rhythm (H1 -> sub -> CTA
       spacing)"): 8 -> 14px, a touch more separation from the bigger H1 above. */
    margin-top: 14px;
  }

  /* t_317dccac: equalised with the gallery/trusted gaps below so para->visual, visual->CTA and
     CTA->trusted read as one even rhythm once the CTA row moves after the gallery (was
     2.6svh/22px, a holdover from when this was the para->CTA gap only). */
  .home-r8-scope .hero-r8-ctas {
    margin-top: clamp(10px, 2.4svh, 20px);
  }

  /* ---- 3 full-width stacked rows (was the 860px rule's 3-up 1fr/2.45fr/1fr grid) ---- */
  .home-r8-scope .hero-r8-gallery {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: clamp(6px, 1.2svh, 10px);
    margin-top: clamp(10px, 2.4svh, 20px);
    min-height: 0;
    /* t_317dccac: on the shortest covered window (375x667) the 3 panels' own 88px floor
       (`.hero-r8-panel` below) adds up to more than this flex-shrunk box actually gets --
       `min-height: 0` above lets the OUTER box shrink past what its children can, so without a
       clip the 3rd panel used to bleed out of the gallery's own box into whatever sits right
       after it in flow. Before this task that was the trusted/logos row (already an accepted
       "may fall below" degradation); now the CTA row sits there instead, and an overlapped CTA
       is not acceptable. `overflow: hidden` keeps that bleed contained inside the gallery's own
       box (a touch of panel 3 crops at 375x667 only -- 390x844/414x896/360x780 have enough
       height that the panels never hit this floor, confirmed live, no visible change there) so
       the CTA and trusted label after it are never covered. */
    overflow: hidden;
  }

  .home-r8-scope .hero-r8-panel {
    flex: 1 1 0;
    height: auto;
    min-height: 88px;
    width: 100%;
  }

  /* .hero-r8-panel-app carries `align-self: start` for the desktop/tablet grid row (keeps it
     from stretching to the row's own height there) -- in this column flex layout that axis is
     width, so left un-overridden it would stop the app row from spanning full width like its
     two siblings. */
  .home-r8-scope .hero-r8-panel-app {
    align-self: stretch;
  }

  /* The website card's browser-chrome frame doesn't read cleanly at a stacked-row height
     (~88-130px, checked live): drop it and fall back to the same plain full-bleed card its two
     siblings already use, per the brief ("keep it only if it still reads cleanly at row
     height; otherwise use the plain card like the other two"). */
  .home-r8-scope .hero-r8-panel-website {
    padding: 0;
  }

  .home-r8-scope .hero-r8-browser {
    background: transparent;
    border-radius: 0;
  }

  .home-r8-scope .hero-r8-chrome {
    display: none;
  }

  /* The 860px rule's narrow-1fr-column label hacks (6.3-8.5px, tracking stripped, right-inset)
     no longer apply -- every row is now full-width, so the label gets the same comfortable
     treatment on all 3 rows instead of 3 different cramped sizes. */
  .home-r8-scope .hero-r8-label,
  .home-r8-scope .hero-r8-panel-ai .hero-r8-label,
  .home-r8-scope .hero-r8-panel-app .hero-r8-label {
    bottom: 10px;
    font-size: 9.5px;
    left: 12px;
    letter-spacing: 0.1em;
    right: auto;
    white-space: nowrap;
  }

  .home-r8-scope .hero-r8-label-app {
    padding: 0;
  }

  .home-r8-scope .hero-r8 .hero-client-trust {
    margin-top: clamp(10px, 2.4svh, 20px);
  }
}

/* t_317dccac (Wira via noe, 2026-11-10 ~20:25, verbatim: "Btw di mobile view cta nya mending
   dibawah visual diastas label trusted by ... Biar mudah di akses"; approved after Noe's mock):
   on mobile only, the CTA row sits below the 3 stacked visual rows and above "Trusted by
   growing..." -- easier thumb reach right where the decision is made, after the visuals sold it.
   DOM order is left exactly as written in HeroR8.tsx (heading -> paragraph -> CTA -> gallery ->
   trusted) -- that is the more conservative a11y/reading order (CTA is announced once, right
   after the pitch, not buried after 3 images) and screen-reader/tab order is unaffected by a
   purely-visual flex `order` reorder. Visual order becomes h1 -> sub -> gallery -> CTA ->
   trusted via flex `order` on the already-column-flex .hero-r8-in (480px rule above). The
   entrance stagger (data-hero-enter, home-r8.css ~line 630) is attribute-keyed to DOM position,
   so its 0.12s/0.18s steps are swapped here to track the new VISUAL order instead: the gallery
   (data-hero-enter="4") now appears 3rd and takes the earlier 0.12s step, the CTA row
   (data-hero-enter="3") now appears 4th and takes the later 0.18s step. h1/sub/trusted keep
   their original position (1st, 2nd, last) so their delays are untouched. */
@media (max-width: 480px) {
  .home-r8-scope .hero-r8-gallery {
    order: 1;
  }

  .home-r8-scope .hero-r8-ctas {
    order: 2;
  }

  .home-r8-scope .hero-r8 .hero-client-trust {
    order: 3;
  }

  .home-r8-scope .hero-r8-in > [data-hero-enter="3"] {
    animation-delay: 0.18s;
  }

  .home-r8-scope .hero-r8-in > [data-hero-enter="4"] {
    animation-delay: 0.12s;
  }
}

/* t_88b35a94 (Noe visual-check of t_317dccac's 375x667 evidence, "3rd gallery row is hard-cut at
   the fold-safe box: no rounded bottom corners, no label, photo sliced flat"): the 480px rule
   above sizes the gallery box (flex:1 1 auto, min-height:0) from whatever vertical space is LEFT
   after h1/sub/CTAs/trusted at a flat 88px-per-panel floor -- at 844/896/780-tall phones that
   leftover space already clears 3*88+2*gap, but at the shortest covered window (375x667) it falls
   ~53px short, and `overflow: hidden` on .hero-r8-gallery silently clipped the 3rd panel's bottom
   (where its rounded corners + label live) instead of shrinking the panels to fit. Fix: on short
   AND narrow phones only (height<=700 so 780/844/896 are untouched, matching Noe's "390/414/360
   are OK" sign-off), scale the panel floor and gallery gap down with their own svh clamps so all 3
   rows -- corners, label, photo -- fit inside the box with no clip. Tuned live at the floor of this
   range, 375x667 (CDP viewport override + real getBoundingClientRect() reads): panel min-height
   clamp(64px, 10.2svh, 88px) and gap clamp(4px, 0.9svh, 10px) put the gallery's natural content
   height at ~214px against a now-roomier ~221px box (padding-top/sub-margin/gallery-margin also
   trimmed a touch below), a small positive margin instead of the old deficit -- confirmed no clip,
   all 3 labels visible, CTA still above the fold. 360x780 and 390x844 fall outside this query
   (height>700) and keep the unmodified 88px/680's rows Noe already approved. */
@media (max-width: 480px) and (max-height: 700px) {
  .home-r8-scope .hero-r8 {
    /* Round-24 (t_dd2b0d70): same nav-clearance floor as the base 480px rule above, `max()`'d
       against this breakpoint's own (shorter) clamp so the floor still wins here too -- this is
       exactly the range (390x664, 375x560, 360x640) where the old flat clamp under-shot worst. */
    padding-top: max(calc(var(--r8-nav-h, 56px) + 24px), clamp(44px, 8svh, 84px));
  }

  .home-r8-scope .hero-r8-sub {
    margin-top: 6px;
  }

  .home-r8-scope .hero-r8-gallery {
    gap: clamp(4px, 0.9svh, 10px);
    margin-top: clamp(8px, 1.8svh, 20px);
  }

  .home-r8-scope .hero-r8-panel {
    min-height: clamp(64px, 10.2svh, 88px);
  }

  .home-r8-scope .hero-r8-ctas {
    margin-top: clamp(8px, 1.8svh, 20px);
  }

  .home-r8-scope .hero-r8 .hero-client-trust {
    margin-top: clamp(8px, 1.8svh, 20px);
  }
}

/* t_57d08c3e (Wira 2026-11-12 ~12:58, verbatim: "client logo mending ketasin aja soalnya
   terlalu kebawah di mobile view"): placed after every other mobile `.hero-client-trust` rule
   above (same 3-class specificity throughout this file, so source order decides) so this
   margin-bottom bump is never shadowed by one of them.
   The stage right above trusted-by is `flex: 1 1 auto` (the <=480px rule near the top of this
   file) -- it absorbs whatever vertical room `.hero-r8-in` has left after its other (fixed-size)
   children, well past its own min-height floor (measured live: ~275px actual vs a ~186px floor
   at 390x844) -- so growing trusted-by's own bottom margin here shrinks the stage by that exact
   same amount (the two are the only variables in a fixed-total-height equation, measured live,
   1:1, not approximate) and moves trusted-by up by that same amount with it: also "shortening
   the wave band" asked for in the same breath, as a direct consequence rather than a second
   lever. +80px lands inside the asked 60-100px band (measured live: trusted-by top 708 -> 628px
   at 390x844, 708 being this task's own baseline); the stage still clears its min-height floor at
   every checked width (390/375/360, both at the tall 844/667 and the short 560/640 heights --
   lowest margin measured ~130px at 375x560, right at its floor, no overlap with the CTA row above
   it), and the air below the logos grows from 48px to 128px, comfortably past the >=24px floor. */
@media (max-width: 480px) {
  .home-r8-scope .hero-r8--wave .hero-client-trust {
    margin-bottom: calc(var(--r8-s7) + 80px);
  }
}

/* t_736a3d78 (Wira 2026-11-10 ~19:20, "pastikan semua page aman ... baik desktop dan mobile
   view"): at <=480px ID's 3-sentence hero paragraph can't fit the desktop 2-line split (measured
   full-text width 784px vs a 334px mobile column -- no readable font-size closes that gap), so
   below the fix stays viewport-aware instead of literal-2-lines: drop the manual sentence-1+2
   vs sentence-3 break (hide .hero-r8-sub-break) and hand the whole 3-sentence block to
   `text-wrap: balance`, which distributes it across the minimum lines the column allows (3, not
   the unbalanced 4 the unmodified break produced) with no single-word orphan line. EN keeps the
   desktop <br> everywhere (its 2 sentences already fit 2 lines at every width, nothing to fix). */
@media (max-width: 480px) {
  html[lang="id"] .home-r8-scope .hero-r8-sub {
    text-wrap: balance;
  }

  html[lang="id"] .home-r8-scope .hero-r8-sub-break {
    display: none;
  }
}

/* t_88b35a94 (nice-to-have, same brief): the comment above says EN's 2 sentences "already fit 2
   lines at every width" via the manual <br>, but at 375 the FIRST sentence ("A clearer brand. A
   better digital experience.") itself greedy-wraps to 2 lines before the <br> even applies, and
   the browser's default wrap leaves "experience." alone on its own line -- 3 lines total, same
   orphan shape as the ID fix above, just one sentence earlier. Scoped to EN's first sentence only
   (`.hero-r8-sub-break` already isolates it: everything before that <br>): `text-wrap: balance`
   redistributes that sentence's own wrap point without touching the <br> or the 3rd line after it,
   confirmed live at 375x667 -- no height change (still 72px, so the gallery budget above is
   unaffected), line 2 becomes "digital experience." (2 words), no single-word orphan. */
@media (max-width: 480px) {
  html[lang="en"] .home-r8-scope .hero-r8-sub {
    text-wrap: balance;
  }
}

/*
  ============================================================================
  Sections below the hero (t_db329ba4): 002-009 + final CTA + footer, ported
  from the same r8 mockup (shots r8c/r8d). Components/home/HomeR8Sections.tsx.
  Every selector here is scoped under .home-r8-scope; nothing bleeds onto /id.
  ============================================================================
*/

/* r8 spacing-scale vars (--r8-s1..s9 etc) moved to app/styles/chrome-r8.css (t_dcb5abd0). */

.home-r8-scope .r8-sec {
  padding: var(--r8-s9) 0;
}

.home-r8-scope .r8-alt {
  background: var(--r8-bg-2, #f9f9fa);
}

.home-r8-scope .r8-eyebrow {
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--r8-muted);
}

/* t_51e0397e (Wira 2026-11-10 ~21:56, "headinya harusnya bisa 2 lines aja ... perkecil aja
   fontnnya"): same cut as the pages-r8.css/services-r8.css copies of this rule -- 48px ceiling
   wrapped a long two-sentence r8 section headline to 3 lines inside the 640(->720)px centred
   column. */
.home-r8-scope .r8-h2,
.home-r8-scope .r8-sec h2 {
  font-size: clamp(22px, 2.3vw, 34px);
  line-height: 1.18;
  letter-spacing: -0.02em;
  font-weight: 700;
  margin: 0;
  text-wrap: balance;
}

.home-r8-scope .r8-sec h3 {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.2;
  margin: 0;
}

.home-r8-scope .r8-muted {
  color: var(--r8-muted);
}

.home-r8-scope .r8-max-65ch {
  max-width: 65ch;
}

.home-r8-scope .r8-strong {
  font-weight: 700;
  color: var(--r8-ink);
}

.home-r8-scope .r8-link {
  font-size: 13px;
  font-weight: 700;
  color: var(--r8-ink);
  display: inline-flex;
  align-items: center;
  padding: 12px 0;
  margin-top: auto;
}

/* qa-dev t_2a22d8be non-blocking (home-r8.css:1093): hub tiles/links/FAQ summaries had no
   :focus-visible ring (only the CTA band + mega-menu did). Matches the established
   outline: 2px solid var(--focus) pattern used elsewhere (e.g. .btn:focus-visible). */
.home-r8-scope .r8-link:focus-visible {
  border-radius: var(--r);
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.home-r8-scope .r8-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  font-size: 14px;
  padding: 11px 20px;
  border-radius: var(--r8-r);
  border: 1px solid var(--r8-ink);
  min-height: 44px;
  text-decoration: none;
  background: var(--r8-ink);
  color: #fff;
}

.home-r8-scope .r8-btn:hover {
  background: #2a292d;
}

.home-r8-scope .r8-btn-outline {
  background: transparent;
  color: var(--r8-ink);
  border-color: var(--r8-line-ui);
}

.home-r8-scope .r8-btn-outline:hover {
  background: rgba(25, 24, 27, 0.05);
}

/* ================================================================
   002 · The reality — speaking visual (r12, replaces the old 4-col list +
   chips-row build; Wira 2026-11-09 ~15:40, approved via Noe's refinement).
   Source of truth: Hermes/workspaces/design/noethera/
   2026-11-09-homepage-journey-services-hub/mockup/{index.html,styles.css}.
   Reuses the page's own "converging lines + travelling pulse" grammar
   (precedent: the mini-orbit in journey stage 3, the hub's own radial
   pattern below) and the exact approved "One system" pill (old
   .r8-diagram-hub) as the centre pop label — no new primitive invented.
   ================================================================ */

/* r13f item 3 (Wira: back to the 3D hairline visual, each popup tied to the sequence, looping):
   the stage is the positioning context (relative) so each popup's left/top % sits over the
   hairline figure itself, not floating in page whitespace. Replaces the r13e bordered-panel
   rebuild (.r13-reality-panel/.r8-reality-visual/.r8-reality-dot/.r8-reality-core/
   .r8-reality-caption/.r8-reality-dots-row), all removed with this round. */
.home-r8-scope .r13-problem-stage { position: relative; width: 100%; max-width: 460px; margin: 0 auto; }
/* r13g item 4 (Wira 01:42): no popup stage wrapper any more (markup simplified to a plain
   board), so the board's size now comes directly from this scoped override instead of the old
   `.r13-problem-stage` ancestor -- keeps the same ~460px "read clearly, not tiny" size as before. */
.home-r8-scope #problem .r8-sec-head-visual .r13-hairline-wrap { max-width: 560px; margin: 0; width: 100%; }

/* r13g item 4 (Wira 01:42, popups replaced with a plain static card row below the board): same
   cal.com outer-card pattern as Industries/Featured work (white, hairline border, large radius),
   no inset visual panel here -- just the number (tinted per its own stage accent), title, one
   line of body copy, same copy as before. */
.home-r8-scope .r13-problem-cards {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--r8-s5); margin-top: var(--r8-s7);
}
.home-r8-scope .r13-problem-card {
  background: #fff; border: 1px solid var(--r8-line-2); border-radius: 20px; padding: var(--r8-s4);
}
.home-r8-scope .r13-problem-card .n { display: block; font-family: var(--m); font-size: 12px; font-weight: 700; margin-bottom: 8px; }
.home-r8-scope .r13-problem-card .t { margin: 0 0 4px; font-size: 15px; font-weight: 700; color: var(--r8-ink); line-height: 1.3; }
.home-r8-scope .r13-problem-card .d { margin: 0; font-size: 12.5px; color: var(--r8-muted); line-height: 1.5; }
.home-r8-scope .r13-problem-card[data-callout="1"] .n { color: var(--r8-acc-blue); }
.home-r8-scope .r13-problem-card[data-callout="2"] .n { color: var(--r8-acc-green); }
.home-r8-scope .r13-problem-card[data-callout="3"] .n { color: var(--r8-acc-orange); }
.home-r8-scope .r13-problem-card[data-callout="4"] .n { color: var(--r8-acc-purple); }
@media (max-width: 900px) {
  .home-r8-scope .r13-problem-cards { grid-template-columns: repeat(2, 1fr); gap: var(--r8-s4); }
}
@media (max-width: 560px) {
  .home-r8-scope .r13-problem-cards { grid-template-columns: 1fr; }
}

/* compact popup callout (r13f-build-notes.md §3: 150px wide, 8px/10px padding -- a tight tag,
   not a card) */
.home-r8-scope .r8-reality-callout {
  position: absolute;
  width: 150px;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--r8-bg);
  box-shadow: inset 0 0 0 1px var(--r8-line-2), 0 10px 24px -14px rgba(17, 17, 17, 0.22);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s var(--ease-out, ease);
  pointer-events: none;
  z-index: 2;
}
.home-r8-scope .r8-reality-callout.is-active { opacity: 1; visibility: visible; }
.home-r8-scope .r8-reality-callout .n { display: block; font-size: 10px; color: var(--r8-faint); margin-bottom: 1px; font-weight: 700; }
.home-r8-scope .r8-reality-callout .t { font-size: 12.5px; font-weight: 700; color: var(--r8-ink); margin: 0 0 1px; }
.home-r8-scope .r8-reality-callout .d { font-size: 10.5px; color: var(--r8-muted); line-height: 1.35; margin: 0; }
/* this stage's 4 anchors sit at custom corners (not a symmetric 4-dot layout), so every popup
   just centres on its own chosen anchor point, no pop-up/pop-down offset needed. */
.home-r8-scope .r13-problem-stage .r8-reality-callout { transform: translate(0, 0); }

/* one soft accent per problem, matching the journey rail's own stage tints 1:1 */
.home-r8-scope .r8-reality-callout[data-callout="1"] .n { color: var(--r8-acc-blue); }
.home-r8-scope .r8-reality-callout[data-callout="2"] .n { color: var(--r8-acc-green); }
.home-r8-scope .r8-reality-callout[data-callout="3"] .n { color: var(--r8-acc-orange); }
.home-r8-scope .r8-reality-callout[data-callout="4"] .n { color: var(--r8-acc-purple); }

@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .r8-reality-callout { opacity: 1 !important; visibility: visible !important; }
}

@media (max-width: 860px) {
  .home-r8-scope .r13-problem-stage { max-width: 320px; }
  .home-r8-scope .r8-reality-callout { width: 118px; padding: 7px 8px; }
  .home-r8-scope .r8-reality-callout .t { font-size: 11px; }
  .home-r8-scope .r8-reality-callout .d { font-size: 9.5px; }

  #problem.r8-sec .r8-sec-head-visual {
    display: flex;
    margin-top: var(--r8-s7);
  }
}

/* ================================================================
   003 · The system — journey rail (r12, merges the old 003 "In practice"
   accordion + 004 "What we build" bento into one 4-stage rail). Each
   stage reuses an existing visual grammar (dv-maps/ai, wo-gauge, a new
   mini-orbit, gs-report chart) -- no new visual primitive, only new
   layout classes (r8-journey-*).
   ================================================================ */

.home-r8-scope .r8-journey-rail {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--r8-s6);
  margin-top: var(--r8-s8);
}
/* r13e item 4 (Wira 2026-11-09 ~21:25, verbatim: "visualnya double uinya yang gak perlu"): this
   rail used to draw its OWN thin track + a travelling pulse dot (::before + .r8-journey-pulse,
   animating end to end every 5s) directly above the 4 cards -- a second, unlabelled progress
   indicator duplicating the real one (.r13-journey-rail-progress, the numbered 1-2-3-4
   stepper rendered just above this grid, already wired to the live scroll-sequencer step). Each
   card's own number badge (`.r8-journey-card::before`, content:attr(data-n)) repeated that same
   1/2/3/4 a third time. Both are removed; the numbered stepper above is now the one and only
   progress UI, and the 48px of per-card top padding reserved for the badge is reclaimed so the
   card's own visual starts right at the row top (this rule's own "top-aligned in one row"). */
.home-r8-scope .r8-journey-card { position: relative; z-index: 1; display: flex; flex-direction: column; }

.home-r8-scope .r8-journey-visual {
  background: none;
  box-shadow: none;
  padding: 0;
  height: 190px;
  display: flex; flex-direction: column; justify-content: flex-start; align-items: stretch; gap: var(--r8-s2);
  margin-bottom: var(--r8-s4);
  overflow: visible;
}
.home-r8-scope .r8-journey-tag { font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--r8-muted); display: block; }
.home-r8-scope .r8-journey-card h3 { font-size: 22px; margin: var(--r8-s1) 0 var(--r8-s2); font-weight: 700; }
.home-r8-scope .r8-journey-card p { font-size: 14px; color: var(--r8-muted); line-height: 1.5; margin: 0 0 var(--r8-s3); }
/* r12 polish: card is a flex column (rule above) so this group can be pushed to the bottom with
   margin-top: auto, keeping "Learn more" on one baseline across all 4 stages even though their
   body paragraph lengths differ (Noe's visual-check finding). Stage 3 adds a product chip below
   the link in markup (reading order kept for a11y) -- `order` keeps the link itself as the last
   *visual* flex item so its own bottom edge (hence the "Learn more" baseline) stays flush with
   the card bottom whether or not a chip is present, instead of the chip's extra line pushing it
   up relative to the other 3 stages. */
.home-r8-scope .r8-journey-link-group { display: flex; flex-direction: column; gap: 6px; margin-top: auto; padding-top: var(--r8-s3); }
.home-r8-scope .r8-journey-link-group .r8-link { order: 2; }
.home-r8-scope .r8-journey-product-chip { order: 1; }
.home-r8-scope .r8-journey-product-chip { font-size: 11px; color: var(--r8-faint); }

.home-r8-scope .r8-journey-foot {
  margin-top: var(--r8-s7);
  font-size: 15px;
  font-weight: 600;
  display: inline-flex; gap: 6px; align-items: center;
}

@media (max-width: 860px) {
  .home-r8-scope .r8-journey-rail { grid-template-columns: repeat(2, 1fr); gap: var(--r8-s6) var(--r8-s5); }
}
@media (max-width: 640px) {
  .home-r8-scope .r8-journey-rail { grid-template-columns: 1fr; gap: 0; margin-top: var(--r8-s6); }
  .home-r8-scope .r8-journey-card { padding-bottom: var(--r8-s7); }
  .home-r8-scope .r8-journey-card:last-child { padding-bottom: 0; }
}

/* -- mini visuals, one per stage (floats directly on the section bg, no card/box-in-box,
   per this page's own "hindari container didalam container" rule) -- */
.home-r8-scope .r8-dv-maps-row { display: flex; align-items: center; gap: 11px; }
.home-r8-scope .r8-dv-pin { width: 26px; height: 26px; flex: none; color: var(--r8-acc-blue); }
.home-r8-scope .r8-dv-pin svg { width: 100%; height: 100%; }
.home-r8-scope .r8-dv-maps-text { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.home-r8-scope .r8-dv-maps-text .t { font-size: 14px; font-weight: 700; color: var(--r8-ink); }
.home-r8-scope .r8-dv-maps-text .d { font-size: 11.5px; color: var(--r8-muted); }
/* r13e item 4: "filling its column" -- the AI-overview quote used to be 2 bare lines of italic
   text floating under the maps row, the sparsest of the 4 visuals next to the gauge/orbit/chart.
   A filled panel (same --r8-panel flat fill every other mini-visual's card chrome already uses)
   growing to the rest of the 190px box reads as deliberate content, not empty space. */
.home-r8-scope .r8-dv-ai-float {
  background: var(--r8-panel);
  border-radius: 12px;
  flex: 1;
  margin-top: var(--r8-s3);
  padding: var(--r8-s3);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.home-r8-scope .r8-dv-ai-head { font-size: 9px; color: var(--r8-muted); letter-spacing: 0.06em; }
.home-r8-scope .r8-dv-ai-float p { margin: 4px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--r8-ink); font-style: italic; }

.home-r8-scope .r8-wo-url-pill { display: inline-flex; align-items: center; gap: 7px; padding: 6px 14px; border: 1px solid var(--r8-line-ui); border-radius: var(--r8-pill); }
.home-r8-scope .r8-wo-url-pill .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--r8-acc-blue); flex: none; }
.home-r8-scope .r8-wo-url-pill span:last-child { font-size: 11px; color: var(--r8-muted); }
.home-r8-scope .r8-wo-mid { display: flex; align-items: center; gap: var(--r8-s4); margin-top: var(--r8-s4); flex: 1; }
.home-r8-scope .r8-wo-gauge { flex: none; width: 82px; height: 82px; position: relative; }
.home-r8-scope .r8-wo-gauge svg { width: 100%; height: 100%; }
.home-r8-scope .r8-wo-gauge-track { fill: none; stroke: var(--r8-line); stroke-width: 7; }
.home-r8-scope .r8-wo-gauge-fill { fill: none; stroke: var(--r8-acc-green); stroke-width: 7; stroke-linecap: round; }
.home-r8-scope .r8-wo-gauge-label { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.home-r8-scope .r8-wo-gauge-label .n { font-size: 18px; font-weight: 700; color: var(--r8-ink); line-height: 1; }
.home-r8-scope .r8-wo-gauge-label .u { font-size: 8px; color: var(--r8-muted); margin-top: 1px; }
.home-r8-scope .r8-wo-gauge-cap { display: flex; flex-direction: column; gap: 3px; }
.home-r8-scope .r8-wo-gauge-cap .t { font-size: 13px; font-weight: 700; color: var(--r8-ink); }
.home-r8-scope .r8-wo-gauge-cap .d { font-size: 11px; color: var(--r8-muted); }

/* gs-report (Strategic Review) — shared with journey stage 4; the "drop" line/dot recolours
   from the old --r8-acc2 brown/grey to --r8-acc-orange per round-11 (no brown/terracotta). */
.home-r8-scope .r8-gs-report { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: space-between; gap: var(--r8-s3); }
.home-r8-scope .r8-gs-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--r8-s2); font-size: 10.5px; color: var(--r8-muted); letter-spacing: 0.04em; text-transform: uppercase; }
/* r13e fix round: the label and the "N fixes found" value ran into each other with no gap at
   this box's fixed 190px width -- label now truncates with an ellipsis instead of colliding. */
.home-r8-scope .r8-gs-head .l { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-r8-scope .r8-gs-head .v { flex: none; color: var(--r8-ink); font-weight: 700; text-transform: none; letter-spacing: 0; }
.home-r8-scope .r8-gs-chart-wrap { display: block; width: 100%; height: 100%; flex: 1; }
.home-r8-scope .r8-gs-area { fill: var(--r8-line-2); opacity: 0.65; }
.home-r8-scope .r8-gs-line { fill: none; stroke: var(--r8-line-ui); stroke-width: 2; }
.home-r8-scope .r8-gs-line-drop { fill: none; stroke: var(--r8-acc-orange); stroke-width: 2; }
.home-r8-scope .r8-gs-dot { fill: var(--r8-bg); stroke: var(--r8-line-ui); stroke-width: 2; }
.home-r8-scope .r8-gs-dot.is-drop { stroke: var(--r8-acc-orange); }
.home-r8-scope .r8-gs-axis-row { display: flex; justify-content: space-between; padding: 0 2px; font-size: 10.5px; color: var(--r8-muted); }

.home-r8-scope .r8-mini-orbit { position: relative; width: 100%; height: 100%; }
.home-r8-scope .r8-mini-orbit-lines { position: absolute; inset: 0; width: 100%; height: 100%; }
.home-r8-scope .r8-mini-orbit-lines path { fill: none; stroke: var(--r8-acc-purple); stroke-opacity: 0.4; stroke-width: 1.2; stroke-dasharray: 3 4; }
.home-r8-scope .r8-mini-orbit-fx circle { fill: var(--r8-acc-purple); }
@media (prefers-reduced-motion: reduce) { .home-r8-scope .r8-mini-orbit-fx { display: none; } }
.home-r8-scope .r8-mini-orbit-node {
  position: absolute; width: 24px; height: 24px; border-radius: 7px; background: var(--r8-bg);
  box-shadow: inset 0 0 0 1px var(--r8-line-ui); display: flex; align-items: center; justify-content: center;
  transform: translate(-50%, -50%);
  color: var(--r8-ink);
}
.home-r8-scope .r8-mini-orbit-node svg { width: 14px; height: 14px; }
.home-r8-scope .r8-mini-orbit-core {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: var(--r8-ink); color: #fff; border-radius: 12px; padding: 10px 16px;
}
.home-r8-scope .r8-mini-orbit-core svg { width: 20px; height: 20px; color: var(--r8-acc-purple); }
.home-r8-scope .r8-mini-orbit-core span { font-family: var(--m); font-size: 9px; letter-spacing: 0.08em; }

/* r13e item 4 (Noe 2026-11-09 22:13): "one family" framed UI-moment panel, reused by all 4
   #system stage visuals -- same chrome, same header style, each fills the fixed 190px box. */
.home-r8-scope .r8-journey-frame {
  background: var(--r8-panel); border-radius: 12px; flex: 1; min-height: 0;
  padding: var(--r8-s3); display: flex; flex-direction: column; gap: var(--r8-s2);
}
.home-r8-scope .r8-jf-head { font-size: 9px; color: var(--r8-muted); letter-spacing: 0.06em; font-weight: 600; }

/* Found: a mini Google Maps card -- road-grid texture + pin, listing bar below. */
.home-r8-scope .r8-jf-map { position: relative; flex: 1; min-height: 0; border-radius: 8px; overflow: hidden; background: var(--r8-bg); }
.home-r8-scope .r8-jf-map-grid { position: absolute; inset: 0; width: 100%; height: 100%; }
.home-r8-scope .r8-jf-map-grid path { stroke: var(--r8-line); stroke-width: 1; }
.home-r8-scope .r8-jf-pin { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -60%); width: 28px; height: 28px; color: var(--r8-acc-blue); }
.home-r8-scope .r8-jf-pin svg { width: 100%; height: 100%; }
.home-r8-scope .r8-jf-listing { display: flex; align-items: baseline; justify-content: space-between; gap: var(--r8-s2); }
.home-r8-scope .r8-jf-listing .t { font-size: 13px; font-weight: 700; color: var(--r8-ink); }
.home-r8-scope .r8-jf-listing .d { font-size: 11px; color: var(--r8-muted); }

/* Asks & books: inquiry -> booking chat bubbles, replaces the old floating-dot orbit (no purple). */
.home-r8-scope .r8-jf-chat { flex: 1; min-height: 0; display: flex; flex-direction: column; justify-content: center; gap: 8px; }
.home-r8-scope .r8-jf-bubble { max-width: 86%; padding: 7px 11px; border-radius: 13px; font-size: 11.5px; line-height: 1.4; }
.home-r8-scope .r8-jf-bubble.in { align-self: flex-start; background: var(--r8-bg); color: var(--r8-ink); box-shadow: inset 0 0 0 1px var(--r8-line-ui); border-bottom-left-radius: 4px; }
.home-r8-scope .r8-jf-bubble.out { align-self: flex-end; background: var(--r8-acc-green); color: #fff; border-bottom-right-radius: 4px; }

/* Keeps improving: same panel chrome around the existing growth-scan report. */
.home-r8-scope .r8-jf-chart.r8-journey-frame { padding: var(--r8-s3); }
.home-r8-scope .r8-jf-chart .r8-gs-report { flex: 1; min-height: 0; }

/* ================================================================
   Our Services hub (r12, new 004 slot) — radial 8-tile diagram around the
   real Noethera monogram (mask-on-currentColor, same technique as the
   nav's own .nm/.nw), then a hairline divider + 3-col icon+name+one-liner
   grid. Reference: cal.com integrations hub (Wira's own screenshot pick).
   ================================================================ */

.home-r8-scope .r8-hub-head { max-width: 640px; }
/* r13g item 5/9: reusable header-centring utility (003/004/008 chip+H2+desc blocks). Centres the
   TEXT inside its host box AND the host box itself on the page (round-2 fix: margin:auto on the
   box, not just its children, or a 640/680px box with no margin of its own just reads as centred
   around the WRONG axis -- see r13g-build-notes.md ROUND 2 item 1). */
.home-r8-scope .r13-center-head { text-align: center; margin-left: auto; margin-right: auto; }
.home-r8-scope .r13-center-head > * { margin-left: auto; margin-right: auto; }
.home-r8-scope .r13-center-head .r8-hub-head-btns { justify-content: center; }
.home-r8-scope .r8-hub-chip {
  display: inline-flex; align-items: center; font-family: var(--m); font-size: 12px; letter-spacing: 0.04em;
  border: 1px solid var(--r8-line-ui); border-radius: var(--r8-pill); padding: 6px 16px; color: var(--r8-ink);
}
.home-r8-scope .r8-hub-head-btns { display: flex; gap: var(--r8-s3); margin-top: var(--r8-s6); flex-wrap: wrap; justify-content: center; }

.home-r8-scope .r8-hub-panel {
  background: var(--r8-panel);
  border-radius: 28px;
  margin-top: var(--r8-s8);
  padding: var(--r8-s7) var(--r8-s5);
}
.home-r8-scope .r8-hub-diagram {
  position: relative;
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  aspect-ratio: 1120 / 620;
}
.home-r8-scope .r8-hub-connectors { position: absolute; inset: 0; width: 100%; height: 100%; }
.home-r8-scope .r8-hub-line { fill: none; stroke: var(--r8-line-ui); stroke-width: 1.3; opacity: 0.55; }
.home-r8-scope .r8-hub-fx circle { fill: var(--r8-ink); opacity: 0.8; }
@media (prefers-reduced-motion: reduce) { .home-r8-scope .r8-hub-fx { display: none; } }

.home-r8-scope .r8-hub-core {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 15%; aspect-ratio: 1 / 1;
  background: var(--r8-ink); border-radius: 22%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 0 rgba(255,255,255,0.04) inset;
}
/* Real asset, mask-on-currentColor — the same technique app/globals.css uses for the nav's
   own .nm/.nw (not a filter:invert hack; that was only needed by the mockup's file:// tooling). */
.home-r8-scope .r8-hub-logo {
  width: 54%;
  height: 54%;
  display: inline-block;
  background: currentColor;
  color: #fff;
  /* perf t_5619af31: same source as globals.css .nm, 320x320 WebP instead of the 1080x1080 PNG
     (14.6KB -> 1.2KB) -- this tile never exceeds ~90px CSS, no visual change. */
  mask-image: url("/assets/noethera-monogram.webp");
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: contain;
  -webkit-mask-image: url("/assets/noethera-monogram.webp");
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: contain;
}

.home-r8-scope .r8-hub-tile {
  position: absolute; transform: translate(-50%, -50%);
  width: 64px; height: 64px;
  background: var(--tile-tint-bg, var(--r8-bg)); border: 1px solid var(--r8-line-ui); border-radius: 18px;
  display: flex; align-items: center; justify-content: center;
  color: var(--tile-tint, var(--r8-ink));
}
.home-r8-scope .r8-hub-tile svg { width: 26px; height: 26px; }
.home-r8-scope .r8-icon { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* qa-dev t_2a22d8be non-blocking: hub tiles are focusable Links with no visible focus ring. */
.home-r8-scope .r8-hub-tile:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* Services hub tiles + grid icons: one soft tint each (Wira 2026-11-09 "sedikit bewarna") — a
   light tile-fill tint (8% alpha) + matching icon stroke, never a solid/opaque colour panel. */
.home-r8-scope .r8-tint-blue   { --tile-tint: var(--r8-acc-blue);   --tile-tint-bg: rgba(110,143,189,0.08); }
.home-r8-scope .r8-tint-green  { --tile-tint: var(--r8-acc-green);  --tile-tint-bg: rgba(131,96,80,0.08); }
.home-r8-scope .r8-tint-orange { --tile-tint: var(--r8-acc-orange); --tile-tint-bg: rgba(217,146,72,0.08); }
.home-r8-scope .r8-tint-purple { --tile-tint: var(--r8-acc-purple); --tile-tint-bg: rgba(140,131,196,0.08); }
.home-r8-scope .r8-tint-teal   { --tile-tint: var(--r8-acc-teal);   --tile-tint-bg: rgba(79,163,160,0.08); }

.home-r8-scope .r8-hub-divider { height: 1px; background: var(--r8-line-2); margin: var(--r8-s8) 0 var(--r8-s7); }

.home-r8-scope .r8-hub-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--r8-s6) var(--r8-s5); }
.home-r8-scope .r8-hub-grid-item { display: flex; flex-direction: row; align-items: flex-start; gap: var(--r8-s3); }
.home-r8-scope .r8-hub-grid-icon {
  width: 40px; height: 40px; flex: none; border-radius: 12px; background: var(--tile-tint-bg, var(--r8-bg));
  box-shadow: inset 0 0 0 1px var(--r8-line); display: flex; align-items: center; justify-content: center;
  color: var(--tile-tint, var(--r8-ink));
}
.home-r8-scope .r8-hub-grid-icon svg { width: 20px; height: 20px; }
.home-r8-scope .r8-hub-grid-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.home-r8-scope .r8-hub-grid-item h3 { font-size: 16px; margin: 0; font-weight: 700; }
.home-r8-scope .r8-hub-grid-item p { font-size: 13.5px; color: var(--r8-muted); line-height: 1.5; margin: 0 0 2px; }

@media (max-width: 860px) {
  .home-r8-scope .r8-hub-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Mobile 390: hub diagram collapses to a compact centred logo + wrapped tile chips (no curved
   connectors at this width — they'd become illegible hairline spaghetti on a 360-390 viewport). */
.home-r8-scope .r8-hub-compact { display: none; }
@media (max-width: 640px) {
  .home-r8-scope .r8-hub-head-btns .r8-btn { width: 100%; }

  .home-r8-scope .r8-hub-panel { padding: var(--r8-s6) var(--r8-s4); border-radius: 20px; }
  .home-r8-scope .r8-hub-diagram { display: none; }
  .home-r8-scope .r8-hub-compact { display: flex; flex-direction: column; align-items: center; gap: var(--r8-s5); }
  .home-r8-scope .r8-hub-compact .r8-hub-core { position: static; transform: none; width: 72px; }
  .home-r8-scope .r8-hub-compact-tiles { display: flex; flex-wrap: wrap; gap: var(--r8-s2); justify-content: center; }
  .home-r8-scope .r8-hub-compact-tiles .r8-hub-tile { position: static; transform: none; width: 48px; height: 48px; border-radius: 14px; }
  .home-r8-scope .r8-hub-compact-tiles .r8-hub-tile svg { width: 20px; height: 20px; }

  .home-r8-scope .r8-hub-grid { grid-template-columns: 1fr; gap: var(--r8-s5); }
}

/* ---------------------------- 005 · AI layer, agents, industries, start ---------------------------- */

.home-r8-scope .r8-ai-band { text-align: center; }
.home-r8-scope .r8-ai-band h2 { max-width: 22ch; margin: var(--r8-s3) auto 0; }
.home-r8-scope .r8-supporting { max-width: 58ch; margin: var(--r8-s4) auto 0; color: var(--r8-muted); font-size: 17px; }
.home-r8-scope .r8-ai-foot { margin-top: var(--r8-s6); font-size: 17px; }

.home-r8-scope .r8-agent-cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--r8-s5); margin-top: var(--r8-s6); }
.home-r8-scope .r8-agent-card { border: 1px solid var(--r8-line-2); border-radius: var(--r8-card); padding: var(--r8-s6); display: flex; flex-direction: column; }
.home-r8-scope .r8-agent-card h3 { font-size: 22px; margin-bottom: var(--r8-s2); }
.home-r8-scope .r8-agent-card p { font-size: 15px; color: var(--r8-muted); margin-bottom: var(--r8-s4); }
.home-r8-scope .r8-agent-card ul { list-style: none; margin: 0 0 var(--r8-s4); padding: 0; display: flex; flex-direction: column; gap: 8px; }
.home-r8-scope .r8-agent-card li { font-size: 14.5px; display: flex; gap: 8px; }
.home-r8-scope .r8-agent-card li::before { content: "\2713"; color: var(--r8-ok); font-weight: 700; }

.home-r8-scope .r8-orbit-fig { position: relative; width: 100%; max-width: 420px; aspect-ratio: 1 / 1; margin: 0 auto var(--r8-s4); }
.home-r8-scope .r8-orbit-grid-bg { position: absolute; inset: 4%; border-radius: 50%; background-image: linear-gradient(var(--r8-line) 1px, transparent 1px), linear-gradient(90deg, var(--r8-line) 1px, transparent 1px); background-size: 12.5% 12.5%; -webkit-mask-image: radial-gradient(circle, #000 55%, transparent 100%); mask-image: radial-gradient(circle, #000 55%, transparent 100%); }
.home-r8-scope .r8-orbit-rings-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.home-r8-scope .r8-orbit-core-glow { position: absolute; left: 50%; top: 50%; width: 52%; height: 52%; transform: translate(-50%, -50%); border-radius: 50%; filter: blur(16px); z-index: 0; }
.home-r8-scope .r8-agent-card.is-arion .r8-orbit-core-glow { background: radial-gradient(circle, rgba(22,163,74,.30), transparent 72%); }
.home-r8-scope .r8-agent-card.is-auxon .r8-orbit-core-glow { background: radial-gradient(circle, rgba(217,97,27,.30), transparent 72%); }
.home-r8-scope .r8-orbit-core { position: absolute; left: 50%; top: 50%; width: 33%; aspect-ratio: 1 / 1; transform: translate(-50%, -50%); border-radius: 50%; background: var(--r8-bg); box-shadow: inset 0 0 0 1px var(--r8-line-2); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4%; z-index: 2; }
.home-r8-scope .r8-orbit-mark { width: 48%; height: auto; overflow: visible; }
.home-r8-scope .r8-orbit-core-label { font-size: 10px; letter-spacing: .08em; font-weight: 700; }
.home-r8-scope .r8-agent-card.is-arion .r8-orbit-core-label { color: #1D7A52; }
.home-r8-scope .r8-agent-card.is-auxon .r8-orbit-core-label { color: #D9611B; }
.home-r8-scope .r8-orbit-node { position: absolute; width: 14%; aspect-ratio: 1 / 1; border-radius: 50%; background: var(--r8-bg); box-shadow: inset 0 0 0 1px var(--r8-line-2); display: flex; align-items: center; justify-content: center; transform: translate(-50%, -50%); z-index: 2; }
.home-r8-scope .r8-orbit-node svg { width: 58%; height: 58%; }
.home-r8-scope .r8-orbit-node.is-muted svg { color: var(--r8-muted); }
.home-r8-scope .r8-orbit-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 5px 12px; margin: 0; padding: 0; list-style: none; font-size: 10px; color: var(--r8-muted); }
.home-r8-scope .r8-orbit-legend span { display: flex; align-items: center; gap: 5px; }
.home-r8-scope .r8-orbit-legend i { width: 7px; height: 7px; border-radius: 50%; flex: none; display: block; }
.home-r8-scope .r8-orbit-caption { text-align: center; margin-top: var(--r8-s3); font-size: 10px; letter-spacing: .06em; color: var(--r8-muted); text-transform: uppercase; }

/* Round-18 (item 8, verbatim from the r8 mockup decor.css ~406-408): the animated connector/
   orbit dots hide under reduced-motion, falling back to the static end dots/rings that are
   always rendered regardless. */
@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .r8-orbit-fx {
    display: none;
  }
}

.home-r8-scope .r8-agent-logo-chip { display: inline-flex; align-items: center; gap: 8px; margin-bottom: var(--r8-s3); font-weight: 700; font-size: 16px; }
.home-r8-scope .r8-agent-logo-mark { width: 26px; height: 18px; flex: none; }
.home-r8-scope .r8-agent-card.is-arion .r8-agent-logo-chip { color: #1D7A52; }
.home-r8-scope .r8-agent-card.is-auxon .r8-agent-logo-chip { color: #D9611B; }

.home-r8-scope .r8-loop-wrap { margin-top: var(--r8-s8); border: 1px solid var(--r8-line-2); border-radius: var(--r8-card); padding: var(--r8-s7); }
.home-r8-scope .r8-loop-caption { text-align: center; font-size: 14px; color: var(--r8-muted); margin: 0 0 var(--r8-s5); }
.home-r8-scope .r8-loop-steps { display: flex; align-items: center; justify-content: space-between; gap: var(--r8-s3); flex-wrap: wrap; }
.home-r8-scope .r8-loop-step { flex: 1; min-width: 150px; text-align: center; font-size: 14px; }
.home-r8-scope .r8-loop-step .num { font-size: 11px; color: var(--r8-faint); display: block; margin-bottom: 4px; }

.home-r8-scope .r8-industry-tags { display: flex; flex-wrap: wrap; gap: var(--r8-s4); margin-top: var(--r8-s6); }
.home-r8-scope .r8-industry-tag { font-size: 15px; font-weight: 600; padding: 11px 20px; border-radius: var(--r8-pill); border: 1px solid var(--r8-line-2); }

.home-r8-scope .r8-start-diagram { margin-top: var(--r8-s7); display: flex; align-items: center; justify-content: center; gap: var(--r8-s5); flex-wrap: wrap; }
.home-r8-scope .r8-start-node { font-size: 14px; padding: 12px 20px; border: 1px solid var(--r8-line-2); border-radius: var(--r8-pill); }
.home-r8-scope .r8-start-node.is-start { background: var(--r8-ink); color: #fff; border-color: var(--r8-ink); font-weight: 700; }
.home-r8-scope .r8-start-note { margin-top: var(--r8-s6); font-size: 15px; color: var(--r8-muted); text-align: center; }
.home-r8-scope .r8-start-note a { font-weight: 700; color: var(--r8-ink); display: inline-flex; align-items: center; padding: 13px 4px; }

@media (max-width: 860px) {
  .home-r8-scope .r8-agent-cards { grid-template-columns: 1fr; }
  .home-r8-scope .r8-orbit-fig { max-width: 300px; }
  .home-r8-scope .r8-orbit-legend { font-size: 9.5px; gap: 4px 9px; }
  .home-r8-scope .r8-loop-steps { flex-direction: column; align-items: stretch; }
}

/* ---------------------------- 007 · How we work ---------------------------- */

.home-r8-scope .r8-how-steps { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--r8-s5); margin-top: var(--r8-s6); }
.home-r8-scope .r8-how-step .num { font-size: 14px; color: var(--r8-faint); display: block; margin-bottom: var(--r8-s3); }
.home-r8-scope .r8-how-step h3 { font-size: 17px; margin-bottom: 6px; }
.home-r8-scope .r8-how-step p { font-size: 14px; color: var(--r8-muted); margin: 0; }

@media (max-width: 860px) {
  .home-r8-scope .r8-how-steps { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------------------- 008 · Featured work ---------------------------- */

/* r13f item 8 (cal.com card pattern, same as Industries item 6, "perkecil ukurannya dikit"):
   outer white hairline card + inset panel holding the cover photo, 3 columns (was 2), shorter
   visual (16/10 vs the old taller crop), tighter padding than Industries (--r8-s3=12px vs
   --r8-s4=16px). Still all 6 projects, same copy/order/URLs. */
.home-r8-scope .r8-work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--r8-s4); margin-top: var(--r8-s6); }
/* t_3a7d4e09: subtle hover lift (2px translate + hairline darken, no shadow) on the Featured
   work product cards -- transform/border-color only, --ease-out family timing. */
.home-r8-scope .r8-work-card {
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid var(--r8-line-2);
  border-radius: 24px;
  padding: var(--r8-s3);
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .home-r8-scope .r8-work-card:hover {
    transform: translateY(-2px);
    border-color: var(--r8-line-ui, #8c8c8c);
  }
}
.home-r8-scope .r8-img-wrap { aspect-ratio: 16 / 10; overflow: hidden; background: var(--r8-bg-2); border-radius: 18px; }
.home-r8-scope .r8-img-wrap img { width: 100%; height: 100%; object-fit: cover; display: block; }
.home-r8-scope .r8-work-card-body { padding: var(--r8-s3) var(--r8-s1) 0; }
.home-r8-scope .r8-work-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--r8-s3); margin-bottom: var(--r8-s2); }
.home-r8-scope .r8-work-card-label { font-size: 11px; color: var(--r8-faint); }
.home-r8-scope .r8-work-card-arrow { width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--r8-line-2); display: flex; align-items: center; justify-content: center; font-size: 14px; flex: none; color: var(--r8-ink); }
.home-r8-scope .r8-work-card h3 { font-size: 17px; margin: var(--r8-s2) 0; }
.home-r8-scope .r8-work-card p { font-size: 14px; color: var(--r8-muted); margin: 0; }

@media (max-width: 900px) {
  .home-r8-scope .r8-work-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .home-r8-scope .r8-work-grid { grid-template-columns: 1fr; }
}

/* ---------------------------- 009 · FAQ ---------------------------- */

.home-r8-scope .r8-faq-pattern { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: var(--r8-s8); align-items: start; margin-top: var(--r8-s6); }
.home-r8-scope .r8-faq-left { display: flex; flex-direction: column; }
.home-r8-scope .r8-faq-left .r8-btn { margin-top: var(--r8-s6); align-self: flex-start; }
.home-r8-scope .r8-faq-item { background: var(--r8-panel); border-radius: var(--r8-card); margin-bottom: var(--r8-s3); break-inside: avoid-column; }
.home-r8-scope .r8-faq-item summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: var(--r8-s4); padding: var(--r8-s6); font-size: 18px; font-weight: 600; border-radius: var(--r8-card); }
.home-r8-scope .r8-faq-item summary::-webkit-details-marker { display: none; }
.home-r8-scope .r8-faq-chev-btn { width: 32px; height: 32px; border-radius: 50%; background: var(--r8-bg); box-shadow: inset 0 0 0 1px var(--r8-line-2); display: flex; align-items: center; justify-content: center; flex: none; color: var(--r8-ink); transition: transform .15s var(--ease-out, ease); }
.home-r8-scope .r8-faq-chev-btn svg { width: 14px; height: 14px; }
.home-r8-scope .r8-faq-item[open] .r8-faq-chev-btn { transform: rotate(180deg); }
.home-r8-scope .r8-faq-item .r8-faq-answer { padding: 0 var(--r8-s6) var(--r8-s6); font-size: 15.5px; color: var(--r8-muted); max-width: 65ch; }

/* Round-18 (item 9, diagnosis t_06f8c6ea c18351): split the question list into 2 balanced
   columns at >=1024px instead of one long column -- native CSS multicol balances top alignment
   for free, `break-inside: avoid-column` above keeps each card whole. All-closed-by-default is
   the component change (no more `open={index === 0}`); `name="r8-faq-group"` on every <details>
   gives native, JS-free one-open-at-a-time exclusivity. */
@media (min-width: 1024px) {
  .home-r8-scope .r8-faq-list { column-count: 2; column-gap: var(--r8-s6); }
}

@media (max-width: 860px) {
  .home-r8-scope .r8-faq-pattern { grid-template-columns: 1fr; gap: var(--r8-s5); }
  .home-r8-scope .r8-faq-item summary { min-height: 44px; }
}

/* ---------------------------- Final CTA ---------------------------- */

/* r13g continuation (Noe must-fix: "CTA pattern invisible"): .r8-cta-band was position:relative
   WITHOUT its own z-index, so it never established a stacking context -- its ::before/::after
   (z-index:-1) resolved against the nearest ancestor that DOES establish one (further up the
   tree), which could paint them behind a sibling section's opaque background instead of behind
   this band's own text. z-index:0 here makes .r8-cta-band itself the stacking context, so -1
   children are guaranteed to sit between this band's own background and its in-flow content. */
.home-r8-scope .r8-cta-band { position: relative; z-index: 0; overflow: hidden; text-align: center; background: var(--r8-ink); color: #fff; border-radius: var(--r8-card); padding: var(--r8-s9) var(--r8-s6); }
.home-r8-scope .r8-cta-band .r8-eyebrow { color: rgba(255,255,255,.6); }
.home-r8-scope .r8-cta-band h2 { color: inherit; max-width: 30ch; margin: var(--r8-s3) auto 0; font-size: clamp(26px, 3.2vw, 36px); text-wrap: balance; }
.home-r8-scope .r8-cta-band p { color: inherit; opacity: .78; max-width: 48ch; margin: var(--r8-s4) auto 0; font-size: 17px; }
.home-r8-scope .r8-cta-band-btns { display: flex; gap: var(--r8-s4); justify-content: center; flex-wrap: wrap; margin-top: var(--r8-s6); }
.home-r8-scope .r8-cta-band-btns .btn { border-radius: var(--r8-pill); }
/* r13g continuation (Noe must-fix: "Talk to Noethera lost its button look"): the primary CTA
   reuses the site-wide .btn-acc (dark-ink fill, white text) -- on THIS band, whose own background
   is that same --r8-ink, the button blended into the band and read as bare white text with no
   visible pill. Dark-band-local override: white fill + dark text, the inverse pairing every dark
   CTA band on this page family uses. */
.home-r8-scope .r8-cta-band-btns .btn-acc {
  background: #fff;
  border-color: #fff;
  color: var(--r8-ink);
}
.home-r8-scope .r8-cta-band-btns .btn-acc:hover {
  background: rgba(255, 255, 255, 0.88);
  border-color: rgba(255, 255, 255, 0.88);
}
.home-r8-scope .r8-cta-band .r8-btn-outline { color: #fff; border-color: rgba(255,255,255,.35); }
.home-r8-scope .r8-cta-band .r8-btn-outline:hover { background: rgba(255,255,255,.08); }
/* r13g item 10, redone (Wira 2026-11-10 ~11:00, verbatim: "iya hitam aja, tinggal garis
   kotak2nya bikin lebih tipis agar lebih premium dan gak ngalangin teks"): the band stays pure
   black/neutral -- no sage/green glow at all (the old ::after is gone, not just recoloured).
   The grid itself drops from 0.1 to 0.05 alpha (quieter hairline) and widens 44px -> 56px
   (calmer, less busy field); a third mask layer (radial, centred on the text column) fades the
   grid out specifically behind the heading/paragraph/buttons instead of only at the band's own
   outer edges, so it never reads through the text at any band height (short 2-line service-page
   copy or the taller home copy alike). z-index:-1 (not 0) so it paints below the band's own
   in-flow text without needing z-index on every child (stacking-context ordering: a negative
   z-index child of a positioned ancestor paints under normal in-flow content, above the
   ancestor's own background). Text already sits on the band's solid dark fill -- no contrast
   impact. */
.home-r8-scope .r8-cta-band::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.09) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image:
    linear-gradient(to bottom, transparent, black 16%, black 84%, transparent),
    linear-gradient(to right, transparent, black 10%, black 90%, transparent),
    radial-gradient(ellipse 50% 48% at 50% 46%, transparent 30%, black 85%);
  -webkit-mask-composite: source-in, source-in;
  mask-image:
    linear-gradient(to bottom, transparent, black 16%, black 84%, transparent),
    linear-gradient(to right, transparent, black 10%, black 90%, transparent),
    radial-gradient(ellipse 50% 48% at 50% 46%, transparent 30%, black 85%);
  mask-composite: intersect, intersect;
}
/* the shared a:focus-visible outline colour (--focus) is a warm brown tuned for light panels;
   on this band's own dark fill, give the ring an explicit light override so it always clears
   the WCAG 2.2 AA 3:1 focus-indicator minimum regardless of theme. */
.home-r8-scope .r8-cta-band a:focus-visible,
.home-r8-scope .r8-cta-band button:focus-visible {
  outline-color: rgba(255, 255, 255, 0.9);
}

@media (max-width: 860px) {
  .home-r8-scope .r8-cta-band { padding: var(--r8-s7) var(--r8-s4); }
  .home-r8-scope .r8-cta-band h2 { font-size: clamp(26px, 7vw, 36px); }
}

/* Footer styles moved to app/styles/chrome-r8.css (t_dcb5abd0) -- loaded on every route now, not just home. */

/* ---------------------------- 002/003 heading+visual row (t_c61a5e7a) ---------------------------- */
/* Round-14 (Wira verbatim, "di section The reality harusnya visual sejajar headingnya" / "di
   section In practice harusnya visualnya sejejar headingnnya"): the hairline figure was docked
   beside the panel/accordion (a sibling of `.r8-reality-panel`/`.r8-accordion`, both below the
   heading), so visually it sat a full heading+body's height lower than the heading, next to the
   panel instead of the heading. Per the approved r8 mockup's own fix for this exact finding
   (~/Documents/Projects/Hermes/workspaces/design/noethera/2026-11-08-homepage-calcom-concept/
   mockup/index.html ~3042-3047, `.sec-head-row`/`.sec-head-text`/`.sec-head-visual`): heading +
   body and the visual now share one top-aligned row (heading left, visual right); the
   panel/accordion moves to its own full-width block directly below that row, own top margin
   unchanged (so this is a markup move, not a new spacing system -- see HomeR8Sections.tsx). */
.home-r8-scope .r8-sec-head-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--r8-s6);
  align-items: center;
}

.home-r8-scope .r8-sec-head-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* r13g continuation (Noe/Wira "perbesar papan"): equal-width column (was 3fr 2fr, a ~40% column
   that forced the board artificially small with empty space around it) + vertically centred
   against the heading block, not pinned to its top. */
.home-r8-scope .r8-sec-head-visual {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--r8-s4);
}

/* r12: the hairline-figure aside (HairlineFigure.tsx, .r8-hairline-aside) that used to dock here
   beside 002/003's heading is gone with those sections' old build -- 002 now renders its own
   speaking visual directly in `.r8-sec-head-visual` (see the 002 block above), and the journey
   rail (new 003) does not use this shared heading+visual row layout at all. */

@media (max-width: 860px) {
  .home-r8-scope .r8-sec-head-row {
    display: block;
  }

  .home-r8-scope .r8-sec-head-visual {
    display: none;
  }
}

/* Services mega-menu (desktop + mobile drawer) styles moved to app/styles/chrome-r8.css (t_dcb5abd0). */

/* ================================================================
   r13 homepage fixes (t_7c662192, Wira approved 2026-11-09 ~20:55) -- ported from the approved
   concept mockup/fixes.css onto the real tokens, additive on top of the rules above. Covers
   items 1 (nav padding/scrolled pill -- see app/globals.css, global nav), 3-9, 12.
   Source: ~/Documents/Projects/Hermes/workspaces/design/noethera/2026-11-09-homepage-r13-concept/
   ================================================================ */

/* ---- item 12: one shared section chip, lighter hairline border ---- */
.home-r8-scope .r8-chip {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  font-family: var(--m);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--r8-ink);
  border: 1px solid var(--r8-line-2);
  border-radius: var(--r8-pill);
  padding: 5px 14px;
  background: var(--r8-bg);
  line-height: 1.4;
}

/* ---- item 3: #problem heading column width + description paragraph ---- */
.home-r8-scope .r13-problem-head { max-width: 640px; }
.home-r8-scope .r13-problem-desc { margin-top: var(--r8-s3); font-size: 15px; line-height: 1.6; color: var(--r8-muted); max-width: 58ch; }
/* r13e item 3: #problem no longer renders a Branches figure here (removed -- it was the
   "isometric board" half of the clutter Wira flagged); this base rule is still shared
   infrastructure for the process section's Terrain figure further below
   (.r13-process-visual .r13-hairline-wrap overrides just its size/margin on top of this). */
.home-r8-scope .r13-hairline-wrap {
  --hairline-plate: var(--r8-bg);
  --hairline-hi: #19181b;
  --hairline-edge: #6E8FBD;
  --hairline-mid: #a9b6c9;
  --hairline-lo: #e4e8ee;
  --hairline-stroke: 0.9;
  width: 100%;
  max-width: 360px;
  margin: 0 auto var(--r8-s5);
}

/* ---- item 4: #system journey, sequential per-step animation (dormant -> live) ---- */
/* r13f item 4: 0 -> 64px top margin, explicit room between the intro paragraph and the rail. */
.home-r8-scope .r13-journey-rail-progress { position: relative; height: 32px; margin: 64px auto var(--r8-s7); max-width: 100%; }
.home-r8-scope .r13-journey-rail-progress .track { position: absolute; top: 15px; left: 12.5%; right: 12.5%; height: 1px; background: var(--r8-line-2); }
.home-r8-scope .r13-journey-rail-progress .fill { position: absolute; top: 15px; left: 12.5%; height: 1px; background: var(--r8-ink); width: 0; transition: width 0.6s var(--ease-out, ease); }
.home-r8-scope .r13-journey-rail-progress .dots { position: absolute; inset: 0; display: flex; justify-content: space-between; padding: 0 12.5%; }
.home-r8-scope .r13-journey-rail-progress .dot {
  width: 30px; height: 30px; border-radius: 50%; background: var(--r8-bg);
  border: 1.5px solid var(--r8-line-2); display: flex; align-items: center; justify-content: center;
  font-family: var(--m); font-size: 12px; color: var(--r8-faint);
  transition: border-color 0.3s var(--ease-out, ease), color 0.3s var(--ease-out, ease), transform 0.3s var(--ease-out, ease);
}
.home-r8-scope .r13-journey-rail-progress .dot.is-live { transform: scale(1.12); }
.home-r8-scope .r13-journey-rail-progress .dot.r8-tint-blue.is-live   { border-color: var(--r8-acc-blue);   color: var(--r8-acc-blue); }
.home-r8-scope .r13-journey-rail-progress .dot.r8-tint-green.is-live  { border-color: var(--r8-acc-green);  color: var(--r8-acc-green); }
.home-r8-scope .r13-journey-rail-progress .dot.r8-tint-teal.is-live   { border-color: var(--r8-acc-teal);   color: var(--r8-acc-teal); }
.home-r8-scope .r13-journey-rail-progress .dot.r8-tint-orange.is-live { border-color: var(--r8-acc-orange); color: var(--r8-acc-orange); }

/* r13e fix round (web-dev, this ticket): item 3 -- all 4 stage visuals must always show their
   resting (finished) content; only the ACTIVE stage gets a highlight replay on top. The base
   rules below used to start at opacity:0/empty and only reached their final look while
   `.r13-step-live` was present -- once the sequencer moved on, the class (and with it the
   `forwards`-animated end state) was gone and the element snapped back to its invisible base
   rule, reading as an empty grey card for 3 of every 4 stages. Base rules are now the resting
   FINAL state; `.r13-step-live` re-triggers the same motion as a one-shot highlight replay
   (explicit 0%/100% keyframes so the replay doesn't depend on the base rule's value). */
.home-r8-scope .r8-wo-gauge-fill { stroke-dasharray: 188.5; stroke-dashoffset: 15.1; }
.home-r8-scope .r13-step-live .r8-wo-gauge-fill { animation: r13GaugeFill 1.1s var(--ease-out, ease); }
@keyframes r13GaugeFill { 0% { stroke-dashoffset: 188.5; } 100% { stroke-dashoffset: 15.1; } }
.home-r8-scope .r8-wo-gauge-label, .home-r8-scope .r8-wo-gauge-cap { opacity: 1; transform: none; }
.home-r8-scope .r13-step-live .r8-wo-gauge-label, .home-r8-scope .r13-step-live .r8-wo-gauge-cap { animation: r13FadeUpReplay 0.5s var(--ease-out, ease) 0.7s; }
@keyframes r13FadeUpReplay { 0% { opacity: 0.35; transform: translateY(6px); } 100% { opacity: 1; transform: translateY(0); } }

.home-r8-scope .r8-gs-line, .home-r8-scope .r8-gs-line-drop { stroke-dasharray: 200; stroke-dashoffset: 0; }
.home-r8-scope .r13-step-live .r8-gs-line { animation: r13Draw 0.6s var(--ease-out, ease); }
.home-r8-scope .r13-step-live .r8-gs-line-drop { animation: r13Draw 0.6s var(--ease-out, ease) 0.5s; }
@keyframes r13Draw { 0% { stroke-dashoffset: 200; } 100% { stroke-dashoffset: 0; } }
.home-r8-scope .r8-gs-dot { opacity: 1; }
.home-r8-scope .r13-step-live .r8-gs-dot { animation: r13FadeUpReplay 0.3s var(--ease-out, ease) 1.1s; }

/* r13e item 4: the map card and chat bubbles follow the same resting-visible / replay-on-live
   contract as the two stages above. */
.home-r8-scope .r8-jf-map, .home-r8-scope .r8-jf-listing { opacity: 1; transform: none; }
.home-r8-scope .r13-step-live .r8-jf-map { animation: r13FadeUpReplay 0.5s var(--ease-out, ease) 0.1s; }
.home-r8-scope .r13-step-live .r8-jf-listing { animation: r13FadeUpReplay 0.5s var(--ease-out, ease) 0.35s; }
.home-r8-scope .r8-jf-bubble { opacity: 1; transform: none; }
.home-r8-scope .r13-step-live .r8-jf-bubble.in { animation: r13FadeUpReplay 0.4s var(--ease-out, ease) 0.1s; }
.home-r8-scope .r13-step-live .r8-jf-bubble.out { animation: r13FadeUpReplay 0.4s var(--ease-out, ease) 0.45s; }

@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .r8-wo-gauge-label, .home-r8-scope .r8-wo-gauge-cap, .home-r8-scope .r8-gs-dot,
  .home-r8-scope .r8-jf-map, .home-r8-scope .r8-jf-listing, .home-r8-scope .r8-jf-bubble { opacity: 1 !important; transform: none !important; animation: none !important; }
  .home-r8-scope .r8-wo-gauge-fill, .home-r8-scope .r8-gs-line, .home-r8-scope .r8-gs-line-drop { animation: none !important; }
  .home-r8-scope .r8-wo-gauge-fill { stroke-dashoffset: 15.1 !important; }
  .home-r8-scope .r8-gs-line, .home-r8-scope .r8-gs-line-drop { stroke-dashoffset: 0 !important; }
  .home-r8-scope .r13-journey-rail-progress .fill { transition: none !important; }
}

/* ---- item 5: Our Services hub tile labels (title + subtitle) ---- */
.home-r8-scope .r8-hub-tile-label {
  position: absolute; width: 148px; display: flex; flex-direction: column; gap: 1px;
  pointer-events: none;
}
.home-r8-scope .r8-hub-tile-label .t { font-size: 12.5px; font-weight: 700; color: var(--r8-ink); line-height: 1.25; }
.home-r8-scope .r8-hub-tile-label .s { font-size: 10.5px; color: var(--r8-muted); line-height: 1.3; }
.home-r8-scope .r8-hub-tile-label.is-left { transform: translate(calc(-100% - 52px), -50%); text-align: right; align-items: flex-end; }
.home-r8-scope .r8-hub-tile-label.is-right { transform: translate(52px, -50%); text-align: left; align-items: flex-start; }
@media (max-width: 1060px) {
  .home-r8-scope .r8-hub-tile-label { width: 118px; }
  .home-r8-scope .r8-hub-tile-label.is-left { transform: translate(calc(-100% - 44px), -50%); }
  .home-r8-scope .r8-hub-tile-label.is-right { transform: translate(44px, -50%); }
}
@media (max-width: 860px) {
  .home-r8-scope .r8-hub-tile-label { display: none; }
}
.home-r8-scope .r8-hub-compact-tile { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 92px; }
.home-r8-scope .r8-hub-compact-tile .r8-hub-tile { position: static; transform: none; }
.home-r8-scope .r8-hub-compact-tile .t { font-size: 11px; font-weight: 700; text-align: center; line-height: 1.25; color: var(--r8-ink); }

/* ---- item 6: #ai-band + #agents merged into one section, real product crops ---- */
.home-r8-scope .r13-ai-agents { background: var(--r8-bg); }
/* r13f item 5: ONE left-aligned composed header replaces the old centred .r13-ai-head +
   left-aligned .r13-agents-head pair (two H2s, two alignments). */
.home-r8-scope .r13-ai-head-combined { text-align: left; max-width: 640px; margin: 0 0 var(--r8-s8); }
/* r13g continuation (Noe must-fix): item 6 -- ONE heading + ONE desc, centred on the page width.
   Higher specificity (two classes) beats the left-aligned rule above regardless of cascade order. */
.home-r8-scope .r13-ai-head-combined.r13-center-head { text-align: center; margin-left: auto; margin-right: auto; }
.home-r8-scope .r13-ai-head-combined.r13-center-head .r8-supporting { margin: var(--r8-s4) auto 0; }
.home-r8-scope .r13-agents-kicker {
  display: block; text-align: center; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--r8-muted); margin: 0 0 var(--r8-s5);
}
/* r13g continuation: shared header-centring utility (build notes item 5), reused by 003/004/008.
   max-width keeps the centred block readable; margin:auto centres the BOX itself on the page
   (not just its own text), the real bug the round-2 build notes called out. */
.home-r8-scope .r13-center-head { text-align: center; max-width: 720px; margin-left: auto; margin-right: auto; }
.home-r8-scope .r13-center-head > * { margin-left: auto; margin-right: auto; }
/* r13f follow-up (t_03e6ee53 item 2): `.r8-supporting`'s shared base rule centres itself
   (`margin: var(--r8-s4) auto 0`) inside a 58ch max-width box -- built for the OLD centred 005
   layout. Now that this column is left-aligned, that auto-centering silently indented this one
   paragraph ~38px right of the h2/chip/every other line in the column (measured x=126 vs x=88 at
   1440). Left-align it here, same as every other child of this column. */
.home-r8-scope .r13-ai-head-combined .r8-supporting { margin: var(--r8-s4) 0 0; }
.home-r8-scope .r13-ai-head-div { border-top: 1px solid var(--r8-line-2); margin: var(--r8-s6) 0; }
.home-r8-scope .r13-agents-h3 { font-size: clamp(20px, 2.2vw, 26px); font-weight: 700; line-height: 1.2; margin: 0; }
.home-r8-scope .r13-agent-cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--r8-s5); align-items: stretch; }
/* t_3a7d4e09: subtle hover lift (2px translate + hairline darken, no shadow) on the Arion/Auxon
   visual cards, same --ease-out family timing already used for every other hover in this file
   (work-card hairline brighten @0.2s). border:1px solid transparent at rest keeps box size
   identical before/after hover -- zero CLS, the border-color flip is the only paint change. */
.home-r8-scope .r13-agent-card {
  border-radius: 24px; overflow: hidden; background: var(--r8-bg-2, #f9f9fa); display: flex; flex-direction: column;
  border: 1px solid transparent;
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .home-r8-scope .r13-agent-card:hover {
    transform: translateY(-2px);
    border-color: var(--r8-line-ui, #8c8c8c);
  }
}
.home-r8-scope .r13-agent-card img { width: 100%; display: block; object-fit: cover; aspect-ratio: 16 / 9.2; }
.home-r8-scope .r13-agent-card-body { padding: var(--r8-s5); display: flex; flex-direction: column; gap: 8px; }
.home-r8-scope .r13-agent-card-body h3 { margin: 0; font-size: 20px; }
.home-r8-scope .r13-agent-card-body p { margin: 0; font-size: 13.5px; color: var(--r8-muted); line-height: 1.5; }
@media (max-width: 860px) {
  .home-r8-scope .r13-agent-cards { grid-template-columns: 1fr; }
}

/* r13e item 5: real orbit/channel diagrams, ported read-only from the two product repos. Both
   cards share one aspect-ratio box (same as the old cropped PNG used) so they stay equal height;
   the stage itself is a centred square inside it so both products render at the same visual
   scale regardless of their own source viewBox. */
.home-r8-scope .r13-agent-card-visual { position: relative; width: 100%; aspect-ratio: 16 / 9.2; background: var(--r8-bg-2, #f9f9fa); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.home-r8-scope .r13-ao-stage { position: relative; height: 90%; aspect-ratio: 1; }
.home-r8-scope .r13-ao-rings { position: absolute; inset: 0; width: 100%; height: 100%; }
/* r13e item 2 (this ticket): Arion's travelling signal dots -- SVG circles riding the same 6
   dashed `d` paths via CSS offset-path/offset-distance, inside the same 540-viewBox SVG so they
   scale with the card exactly like the paths they ride on. Left-side paths run node->ring (so
   0%->100% reads as "flowing in"); right-side paths already run ring->node in the markup (so the
   same 0%->100% keyframe reads as "flowing out") -- one shared keyframe, six offset-paths. */
.home-r8-scope .r13-ao-sig { fill: #16A34A; opacity: 0; filter: drop-shadow(0 0 2px rgba(22,163,74,.4)); }
.home-r8-scope .r13-ao-sig-1 { offset-path: path("M127 150 Q 200 190 222 236"); }
.home-r8-scope .r13-ao-sig-2 { offset-path: path("M83 270 L 196 270"); }
.home-r8-scope .r13-ao-sig-3 { offset-path: path("M127 390 Q 200 350 222 304"); }
.home-r8-scope .r13-ao-sig-4 { offset-path: path("M318 236 Q 340 190 413 150"); }
.home-r8-scope .r13-ao-sig-5 { offset-path: path("M344 270 L 457 270"); }
.home-r8-scope .r13-ao-sig-6 { offset-path: path("M318 304 Q 340 350 413 390"); }
@keyframes r13AoSig { 0% { offset-distance: 0%; opacity: 0; } 15% { opacity: 1; } 82% { opacity: 1; } 100% { offset-distance: 100%; opacity: 0; } }
.home-r8-scope .r13-ao-sig { animation: r13AoSig 3.2s ease-in-out infinite; }
.home-r8-scope .r13-ao-sig-1 { animation-delay: 0s; }
.home-r8-scope .r13-ao-sig-2 { animation-delay: 0.55s; }
.home-r8-scope .r13-ao-sig-3 { animation-delay: 1.1s; }
.home-r8-scope .r13-ao-sig-4 { animation-delay: 1.65s; }
.home-r8-scope .r13-ao-sig-5 { animation-delay: 2.2s; }
.home-r8-scope .r13-ao-sig-6 { animation-delay: 2.75s; }
@media (prefers-reduced-motion: reduce) { .home-r8-scope .r13-ao-sig { display: none; } }

@keyframes r13AoSpin { to { transform: rotate(360deg); } }
.home-r8-scope .r13-ao-spin { transform-origin: 50% 50%; animation: r13AoSpin 18s linear infinite; }
@media (prefers-reduced-motion: reduce) { .home-r8-scope .r13-ao-spin { animation: none; } }
.home-r8-scope .r13-ao-core {
  position: absolute; left: 50%; top: 50%; width: 27%; aspect-ratio: 1; transform: translate(-50%, -50%);
  border-radius: 50%; background: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  z-index: 2;
}
.home-r8-scope .r13-ao-core-arion { box-shadow: 0 0 0 1px rgba(22,163,74,.18), 0 0 0 10px rgba(22,163,74,.06), 0 16px 32px -16px rgba(21,128,61,.4); }
.home-r8-scope .r13-ao-core-arion svg { width: 50%; color: #16A34A; }
.home-r8-scope .r13-ao-core-arion span { font: 600 9px/1 var(--m); letter-spacing: 0.1em; text-transform: uppercase; color: #15803d; margin-top: 2px; }
/* t_5a66a8c2 (Wira verbatim, "lebih tipis biar terasa lebih premium"): peach halo pulled way
   back to read as a faint glow like Arion's, not a visible gradient ring; mark stays orange. */
.home-r8-scope .r13-ao-core-auxon { box-shadow: 0 0 0 1px rgba(217,146,72,.14), 0 0 0 6px rgba(217,146,72,.035), 0 16px 24px -18px rgba(180,110,40,.22); }
.home-r8-scope .r13-ao-core-auxon img { width: 62%; height: auto; }
/* t_65176c87: new AUXON label, identical type/size/tracking/position to ARION's own span above
   (.r13-ao-core-arion span, same file) -- text-transform:uppercase renders it "AUXON". Colour is
   a label-only tuned shade (#A36422, HSL L 57%->39% of the live #D99248 orange, same hue/sat):
   #D99248 fails AA text contrast on the white disc (2.57:1 vs the 4.5:1 text floor), #A36422
   clears it (4.77:1) -- same fix pattern as Arion's own #15803d label-only green. Dark mode
   needs no tuning (dark-mode.css override uses the true mark orange, already AA-safe there). */
.home-r8-scope .r13-ao-core-auxon span {
  font: 600 9px/1 var(--m);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A36422;
  margin-top: 2px;
}
.home-r8-scope .r13-ao-node {
  position: absolute; width: 13%; aspect-ratio: 1; margin: -6.5% 0 0 -6.5%;
  border-radius: 50%; background: #fff; box-shadow: 0 0 0 1px #e7e7e7, 0 6px 14px -8px rgba(17,17,17,.3);
  display: flex; align-items: center; justify-content: center; color: var(--r8-ink); z-index: 2;
}
.home-r8-scope .r13-ao-node svg { width: 46%; height: 46%; }
/* r13e fix (this ticket): labels were always display:none; source HeroSystemOrbit shows them
   beside each node down to its own 1180px breakpoint. Mirrored here with the card's own smaller
   scale (mono, 7px) and the existing .r13-ao-l/.r13-ao-r side classes (left column labels
   right-aligned toward the node, right column labels left-aligned away from it, same convention
   as source's .r4-l/.r4-r). Hidden only below 640px per the ticket (never fit at 390). */
.home-r8-scope .r13-ao-nl {
  position: absolute; top: 50%; transform: translateY(-50%); white-space: nowrap;
  font: 600 10.5px/1.2 var(--m); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--r8-muted); pointer-events: none;
}
.home-r8-scope .r13-ao-l .r13-ao-nl { right: calc(100% + 6px); text-align: right; }
.home-r8-scope .r13-ao-r .r13-ao-nl { left: calc(100% + 6px); }
@media (max-width: 640px) {
  .home-r8-scope .r13-ao-nl { display: none; }
}
.home-r8-scope .r13-ao-n1 { left: 23.5%; top: 27.8%; }
.home-r8-scope .r13-ao-n2 { left: 15.4%; top: 50%; }
.home-r8-scope .r13-ao-n3 { left: 23.5%; top: 72.2%; }
.home-r8-scope .r13-ao-n4 { left: 76.5%; top: 27.8%; }
.home-r8-scope .r13-ao-n5 { left: 84.6%; top: 50%; }
.home-r8-scope .r13-ao-n6 { left: 76.5%; top: 72.2%; }
@media (max-width: 480px) {
  .home-r8-scope .r13-ao-node { width: 15%; margin: -7.5% 0 0 -7.5%; }
}

/* r13e item 1 (this ticket): Auxon's channel-glyph orbit -- 8 chips on 3 lanes + 4 travelling
   signal dots + a caption, faithful to HeroChannelOrbit.tsx's own geometry and colours (not the
   old 8-plain-dot version). The whole assembly is scaled down and nudged up inside
   `.r13-ao-auxon-inner` so the bottom lane-3 chip (fb, at the same ~95%-down position the source
   places it) clears the caption below instead of sitting on top of it. */
/* r13g continuation (Wira 2026-11-10 ~01:58, verbatim override: "gak usah pake label... bikin
   mirip dengan visual auxon asli"): labels + caption removed, so the 0.82 shrink that only
   existed to clear the caption below is gone too -- full scale now matches Arion's own stage
   (same shared .r13-ao-stage box, same visual size, both cards read at equal weight). */
.home-r8-scope .r13-ao-auxon-inner { position: absolute; inset: 0; }
.home-r8-scope .r13-ao-auxon-rings { position: absolute; inset: 0; width: 100%; height: 100%; }
/* t_5a66a8c2 (Wira verbatim, "linkarannya tipis dan putus2... biar terasa lebih premium"): was
   stroke-width 0.6 in this 100-unit viewBox -- at this card's shared stage size that rendered
   ~3x heavier than Arion's own rings (stroke-width 1 in its 540-unit viewBox, same physical
   stage). 0.19 equalizes the two (1 * 100/540 = 0.185) so both cards read the same line weight.
   Innermost ring (r=24, lane 1) gets a dash pattern, matching Arion's own innermost ring. */
.home-r8-scope .r13-ao-auxon-rings circle { stroke: rgba(17,17,17,.1); stroke-width: 0.19; }
.home-r8-scope .r13-ao-auxon-ring-in { stroke-dasharray: 1 2.6; }
.home-r8-scope .r13-ao-auxon-node {
  position: absolute; width: 13%; aspect-ratio: 1; transform: translate(-50%, -50%);
  border-radius: 50%; background: #fff; box-shadow: 0 0 0 1px #e7e7e7, 0 6px 14px -8px rgba(17,17,17,.3);
  display: flex; align-items: center; justify-content: center; z-index: 2;
}
.home-r8-scope .r13-ao-auxon-node svg { width: 46%; height: 46%; }
/* r13g motion port (Wira 01:40, auxon/src/app/marketing-r4.css L369-421): the lane wrapper is
   the element that actually spins (one rigid ring per tier); each node keeps its original
   left/top position inside it (unchanged), so the whole tier orbits together. .r13-ao-auxon-g
   counter-rotates the icon+label by the exact same amount so they stay upright throughout. */
.home-r8-scope .r13-ao-auxon-lane { position: absolute; inset: 0; transform-origin: 50% 50%; }
.home-r8-scope .r13-ao-lane1 { --r13-ao-entry: 30deg; }
.home-r8-scope .r13-ao-lane2 { --r13-ao-entry: -24deg; }
.home-r8-scope .r13-ao-lane3 { --r13-ao-entry: 18deg; }
.home-r8-scope .r13-ao-auxon-g {
  position: absolute; inset: 0; transform-origin: 50% 50%;
  display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .home-r8-scope .r13-ao-auxon-lane {
    animation: r13AoAuxonSpin 3.6s ease 0.3s both, r13AoAuxonIdle 64s linear 3.9s infinite;
  }
  .home-r8-scope .r13-ao-auxon-g {
    animation: r13AoAuxonUnspin 3.6s ease 0.3s both, r13AoAuxonIdleG 64s linear 3.9s infinite;
  }
}
@keyframes r13AoAuxonSpin { from { transform: rotate(var(--r13-ao-entry, 0deg)); } }
@keyframes r13AoAuxonUnspin { from { transform: rotate(calc(-1 * var(--r13-ao-entry, 0deg))); } }
@keyframes r13AoAuxonIdle { to { transform: rotate(360deg); } }
@keyframes r13AoAuxonIdleG { to { transform: rotate(-360deg); } }
/* r13f item 5 (this ticket t_03e6ee53 item 3 follow-up; Wira 2026-11-10 00:40 verbatim:
   "pada visual auxon labelnya buat sebelah kanan atau kirinya biar lebih rapi kayak arion") --
   was: a mono label centred BELOW every node at 6.5px (unreadable) -- for the two lane-1 nodes
   sitting on the ring r=24 (web/book, at the circle's own left/right equator), "below" pushed the
   label down into the lane-2 ring (r=35)'s own curve, visually cutting through its own text
   ("Website"/"Booking" read as colliding with/crossed by the next ring). Match Arion's own
   .r13-ao-nl treatment beside it exactly (same 7px mono/uppercase, same side-of-icon placement,
   not underneath): every node gets its label to the LEFT if it sits in the left half of the
   circle, RIGHT if in the right half -- moving along the horizontal (tangential) axis instead of
   straight down clears every ring's curve at every lane, not just lane 1. */
.home-r8-scope .r13-ao-auxon-nl {
  position: absolute; top: 50%; transform: translateY(-50%); white-space: nowrap;
  font: 600 10.5px/1.2 var(--m); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--r8-muted); pointer-events: none;
}
.home-r8-scope .r13-ao-c-web .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-wa .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-ig .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-search .r13-ao-auxon-nl {
  left: auto; right: 100%; margin-right: 6px; text-align: right;
}
.home-r8-scope .r13-ao-c-book .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-pin .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-tt .r13-ao-auxon-nl,
.home-r8-scope .r13-ao-c-fb .r13-ao-auxon-nl {
  left: 100%; margin-left: 6px; text-align: left;
}
/* hidden only below 640px (never fits at 390), same floor as Arion's own .r13-ao-nl. */
@media (max-width: 640px) {
  .home-r8-scope .r13-ao-auxon-nl { display: none; }
}
/* t_5a66a8c2 (Wira verbatim, "no grey fill"): chips were tinted blue-grey for these 4 icons --
   Arion's own chips are always plain white with a hairline border regardless of icon colour, the
   colour lives in the icon itself (`color` below), not the chip. Drop the bg/border override so
   this chip falls back to the shared white/hairline .r13-ao-auxon-node rule above. */
.home-r8-scope .r13-ao-c-web, .home-r8-scope .r13-ao-c-book, .home-r8-scope .r13-ao-c-search, .home-r8-scope .r13-ao-c-pin {
  color: #3A6A85;
}
.home-r8-scope .r13-ao-c-fb { color: #0866FF; }
.home-r8-scope .r13-ao-c-wa { color: #25D366; }
.home-r8-scope .r13-ao-c-tt { color: #000; }
@media (max-width: 480px) {
  .home-r8-scope .r13-ao-auxon-node { width: 15%; }
}
/* 4 signal dots (web/book/wa/ig -- the source's own NODES[].sg set): fade in at the node, then
   travel inward to the core, fading out just before they'd overlap it -- same read as
   HeroChannelOrbit's r4-sg/r4-sig. */
/* t_5a66a8c2: these are the dots visible mid-animation in the brief's screenshot ("the two
   orange orbit dots") -- shrunk + the box-shadow halo ring swapped for a drop-shadow blur, to
   match Arion's own small accent-dot treatment (.r13-ao-fx/.r13-ao-sig) instead of standing out
   as a bigger, haloed blob. */
.home-r8-scope .r13-ao-auxon-sig {
  position: absolute; width: 3%; aspect-ratio: 1; max-width: 5px; border-radius: 50%;
  transform: translate(-50%, -50%); background: var(--r8-acc-orange); opacity: 0;
  filter: drop-shadow(0 0 2px rgba(217,146,72,.45)); z-index: 1;
}
@keyframes r13AoAuxonSig { 0% { opacity: 0; } 10% { opacity: 1; } 78% { opacity: 1; } 100% { opacity: 0; left: 50%; top: 50%; } }
.home-r8-scope .r13-ao-auxon-sig { animation: r13AoAuxonSig 3.6s cubic-bezier(.45,0,.55,1) infinite; }
.home-r8-scope .r13-ao-sig-ig { animation-delay: 0s; }
.home-r8-scope .r13-ao-sig-web { animation-delay: 0.25s; }
.home-r8-scope .r13-ao-sig-wa { animation-delay: 0.5s; }
.home-r8-scope .r13-ao-sig-book { animation-delay: 0.75s; }
@media (prefers-reduced-motion: reduce) { .home-r8-scope .r13-ao-auxon-sig { display: none; } }
/* Caption sits OUTSIDE `.r13-ao-auxon-inner` (not scaled/shifted with it), in the clearance that
   wrapper's transform now leaves at the bottom of the stage -- this is the fix for "the dot
   overlapping the caption must go" (the fb chip and the caption used to occupy the same band). */
.home-r8-scope .r13-ao-auxon-cap { position: absolute; bottom: 1%; left: 50%; transform: translateX(-50%); font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--r8-muted); }
@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .r13-ao-auxon-inner { animation: none; }
}


/* ---- item 7: #industries, continuous auto-scroll card slider ----
   t_872a21ad (2026-11-11): replaces the static 4/2-col CSS-grid row with a flex row inside a
   native overflow-x:auto scroller, nudged by rAF (see IndustriesSlider in HomeR8Sections.tsx).
   Approved mockup: 2026-11-11-industries-slider/mockup/a/index.html. Card look (hairline border,
   radius 28/22, no shadow, per-card muted accent) is UNCHANGED from the old grid -- only the row
   mechanism (grid -> flex track) and the photo ratio (16:11 -> 4:3, per the mockup) move. */
.home-r8-scope .industries-slider-outer { margin-top: var(--r8-s7); }
.home-r8-scope .industries-slider {
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
  scroll-behavior: auto;
  -webkit-overflow-scrolling: touch;
  scroll-padding-inline: var(--r8-s2);
}
.home-r8-scope .industries-slider::-webkit-scrollbar { display: none; }
.home-r8-scope .islider-track { display: flex; gap: var(--r8-s5); width: max-content; padding: 2px var(--r8-s2) 10px; }
/* reduced motion: the JS never starts the rAF loop (checked at init) -- this media query just
   adds scroll-snap so the now-fully-manual row still feels like a deliberate row, not an
   accidental endless scroll. */
@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .industries-slider { scroll-snap-type: x proximity; }
  .home-r8-scope .islider-track > .r13-industry-card { scroll-snap-align: start; }
}
/* r13f item 6 (cal.com card pattern, Wira: "beberapa card kita"): outer white hairline card (was:
   the grey tint WAS the card, photo bled to its own edge) with an INSET panel holding the photo,
   a visible gap to the outer edge on all sides -- title + sub sit below the inset panel, inside
   the outer card. */
/* t_3a7d4e09: same hover lift as the other product/service cards in this file. */
.home-r8-scope .r13-industry-card {
  display: flex; flex-direction: column;
  flex: 0 0 272px;
  background: #fff;
  border: 1px solid var(--r8-line-2);
  border-radius: 28px;
  padding: 16px;
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .home-r8-scope .r13-industry-card:hover {
    transform: translateY(-2px);
    border-color: var(--r8-line-ui, #8c8c8c);
  }
}
.home-r8-scope .r13-industry-card:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 28px;
}
.home-r8-scope .r13-industry-card .visual {
  position: relative; width: 100%; aspect-ratio: 4 / 3; background: var(--tile-tint-bg, var(--r8-bg-2));
  border-radius: 20px; overflow: hidden;
}
.home-r8-scope .r13-industry-card .visual img { width: 100%; height: 100%; object-fit: cover; display: block; }
.home-r8-scope .r13-industry-card .body { padding: var(--r8-s4) var(--r8-s2) var(--r8-s2); display: flex; flex-direction: column; gap: 4px; }
.home-r8-scope .r13-industry-card .name { font-size: 15px; font-weight: 700; line-height: 1.3; color: var(--r8-ink); }
.home-r8-scope .r13-industry-card .sub { font-size: 12.5px; color: var(--r8-muted); line-height: 1.45; }
@media (max-width: 900px) {
  .home-r8-scope .islider-track { gap: var(--r8-s4); }
  .home-r8-scope .r13-industry-card { border-radius: 22px; padding: 12px; }
  .home-r8-scope .r13-industry-card .visual { border-radius: 16px; }
}
@media (max-width: 680px) {
  .home-r8-scope .r13-industry-card { flex: 0 0 230px; }
}

/* r13e item 6: muted-natural per-card accent, one per industry, matching each v2 photo's own
   baked-in tone (industries-imagery-spec.md v2 addendum) -- replaces the old shared
   r8-tint-blue/green/orange/purple/teal mapping (Wira rejected lavender/purple outright). Shows
   as a thin top accent bar on the card (--tile-accent) and a pale fallback ground behind the
   image while it loads (--tile-tint-bg); the photo itself fully covers the box at 16:11, so the
   fallback is never visible once loaded. */
.home-r8-scope .r13-industry-card.ind-acc-sand       { --tile-accent: #B9A98C; --tile-tint-bg: rgba(185,169,140,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-blue-gray  { --tile-accent: #8C9BAE; --tile-tint-bg: rgba(140,155,174,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-sage       { --tile-accent: #8FA187; --tile-tint-bg: rgba(143,161,135,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-oat        { --tile-accent: #D7C9A8; --tile-tint-bg: rgba(215,201,168,0.16); }
.home-r8-scope .r13-industry-card.ind-acc-terracotta { --tile-accent: #C98B6E; --tile-tint-bg: rgba(201,139,110,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-olive      { --tile-accent: #A98F5E; --tile-tint-bg: rgba(169,143,94,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-slate      { --tile-accent: #7D8A96; --tile-tint-bg: rgba(125,138,150,0.14); }
.home-r8-scope .r13-industry-card.ind-acc-taupe      { --tile-accent: #A89584; --tile-tint-bg: rgba(168,149,132,0.14); }

/* ---- item 8: merged process section (#start + #how), hairline Terrain figure, 5-step spine ----
   R13F ITEM 7 ROUND 3 (designer's fixed layout, t_999baf39, Wira-confirmed 2026-11-10 00:40: visual
   aligned to the right of the heading+desc): was a 2-col grid with the visual centred against the
   WHOLE step list's height (heavy-left, visual parked low). Now `.r13-process-top` pairs
   heading+desc (left) with the hairline visual (right) at the SAME row height; the 5 steps move to
   a full-width row below, so neither block measures its height against the other's unrelated
   content anymore. */
.home-r8-scope .r13-process-head { max-width: 560px; }
/* t_d76535a9: this head column narrows to ~400px at 1024 (1.1fr/1fr grid, gap eats into the
   560px max-width) -- too narrow for the shared .r8-h2 clamp on the longest ID copy ("Kami
   petakan alurnya duluan. Baru kami bangun yang memang dibutuhkan.") without wrapping to 3
   lines. Scoped smaller clamp, same pattern as the FAQ-left fix above. */
.home-r8-scope .r13-process-head h2.r8-h2 { font-size: clamp(18px, 1.6vw, 24px); line-height: 1.2; }
.home-r8-scope .r13-system-head { max-width: 620px; }
.home-r8-scope .r13-work-head { max-width: 640px; }
.home-r8-scope .r13-process-top { display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--r8-s8); margin-top: var(--r8-s8); align-items: stretch; }
.home-r8-scope .r13-process-steps { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--r8-s5); margin-top: var(--r8-s8); align-items: start; }
.home-r8-scope .r13-process-step {
  display: flex; flex-direction: column; gap: var(--r8-s3); min-height: 190px;
  padding-top: var(--r8-s4); padding-right: var(--r8-s3); border-top: 1px solid var(--r8-line);
  transition: color 0.3s var(--ease-out, ease);
  /* r13f round 2 item 9: last words of some steps ("discover,", "reports") ran right up against
     the column edge with no breathing room; border-top still spans the full column width
     (box-sizing: border-box), only the text gets the inset. */
  box-sizing: border-box;
}
.home-r8-scope .r13-process-step .num { font-family: var(--m); font-size: 13px; color: var(--r8-faint); }
.home-r8-scope .r13-process-step.is-live .num { color: var(--r8-ink); }
.home-r8-scope .r13-process-step h3 { margin: 0 0 4px; font-size: 16px; font-weight: 700; color: var(--r8-muted); }
.home-r8-scope .r13-process-step p { margin: 0; font-size: 13.5px; color: var(--r8-faint); line-height: 1.5; }
.home-r8-scope .r13-process-step.is-live h3 { color: var(--r8-ink); }
.home-r8-scope .r13-process-step.is-live p { color: var(--r8-muted); }
/* step 01's own paragraph is by far the longest (6 lines vs 2-3 for steps 2-5); a bigger gap
   before the fork callout keeps its last line from reading as touching the card below. */
.home-r8-scope .r13-process-fork {
  /* t_03e6ee53: this section is .r8-alt (background: var(--r8-bg-2)) -- a card filled with that
     SAME token is invisible against its own section, reading as plain unstyled text (found while
     screenshotting this round). White, like every other card pattern on an alt section
     (Industries/Featured-work's own `background:#fff`), actually shows as a card here. */
  margin-top: var(--r8-s8); padding: var(--r8-s4); border-radius: 16px; max-width: 680px;
  background: var(--r8-bg, #fff); font-size: 13.5px; color: var(--r8-muted); line-height: 1.6;
}
.home-r8-scope .r13-process-fork b { color: var(--r8-ink); }
.home-r8-scope .r13-process-note { margin-top: var(--r8-s5); font-size: 13.5px; color: var(--r8-muted); }
.home-r8-scope .r13-process-note a { font-weight: 700; color: var(--r8-ink); }
.home-r8-scope .r13-process-visual {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  height: 100%; gap: var(--r8-s4);
}
.home-r8-scope .r13-process-visual .r13-hairline-wrap { max-width: 380px; margin-bottom: 0; }
.home-r8-scope .r13-hairline-stage { position: relative; width: 100%; max-width: 380px; }
.home-r8-scope .r13-hairline-stage .r13-hairline-wrap { max-width: none; }
/* r13e item 7: labelled pins over the Terrain figure, one per process step, cumulative as the
   matching step scrolls into view (useTerrainPins); reduced-motion shows all 5 immediately. */
.home-r8-scope .r13-terrain-pins { position: absolute; inset: 0; pointer-events: none; }
.home-r8-scope .r13-terrain-pin {
  position: absolute; transform: translate(-50%, -100%) scale(0.85); opacity: 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.home-r8-scope .r13-terrain-pin.is-shown { opacity: 1; transform: translate(-50%, -100%) scale(1); }
.home-r8-scope .r13-terrain-pin-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--r8-acc-orange); box-shadow: 0 0 0 4px rgba(217,146,72,.22); }
.home-r8-scope .r13-terrain-pin-label {
  font-size: 10px; font-weight: 700; white-space: nowrap; color: #fff; background: var(--r8-ink);
  padding: 3px 9px; border-radius: 8px; letter-spacing: 0.01em;
}
@media (prefers-reduced-motion: reduce) {
  .home-r8-scope .r13-terrain-pin { transition: none; opacity: 1; transform: translate(-50%, -100%) scale(1); }
}
@media (max-width: 640px) {
  .home-r8-scope .r13-terrain-pin-label { font-size: 9px; padding: 2px 7px; }
}
.home-r8-scope .r13-process-caption { text-align: center; }
.home-r8-scope .r13-process-caption .t { font-size: 15px; font-weight: 700; color: var(--r8-ink); }
.home-r8-scope .r13-process-caption .d { font-size: 12.5px; color: var(--r8-muted); margin-top: 2px; }
@media (max-width: 960px) {
  .home-r8-scope .r13-process-top { grid-template-columns: 1fr; }
  .home-r8-scope .r13-process-visual { margin-top: var(--r8-s7); height: auto; }
  .home-r8-scope .r13-process-steps { grid-template-columns: 1fr; margin-top: var(--r8-s7); }
  .home-r8-scope .r13-process-step { min-height: 0; }
}

/* ---- item 9: FAQ redesign -- sticky left column + grey filled question cards ---- */
/* Defensive guard (t_bfa4e0ae, 2026-11-10): `#faq > .w` is also the exact selector any OTHER
   page's stylesheet keys its own `#faq` section-wrapper grid to (services.css did, scoped away
   now, see that file). Next.js keeps a client-side-navigated-away route's CSS in the DOM, so any
   future unscoped `#faq > .w` rule from elsewhere would silently re-hijack this wrapper into a
   grid and squeeze `.r13-faq-grid` into its first track. Pin it to a plain block here so nothing
   outside this scope can ever win on specificity against a bare `#faq > .w`.
*/
.home-r8-scope #faq > .w { display: block; }
.home-r8-scope .r13-faq-grid { display: grid; grid-template-columns: 35fr 65fr; gap: var(--r8-s8); align-items: start; margin-top: var(--r8-s6); }
.home-r8-scope .r13-faq-left { position: sticky; top: 120px; display: flex; flex-direction: column; gap: var(--r8-s3); align-self: start; }
/* t_d76535a9: the 35fr FAQ-left column is as narrow as ~270px at 1024 -- too narrow for the
   full .r8-h2 clamp (up to 34px) on the longest EN/ID FAQ-intro copy without wrapping to 3
   lines. Scoped smaller clamp (h2 beats .r8-h2 on specificity: class+element > class alone). */
.home-r8-scope .r13-faq-left h2.r8-h2 { margin: 0; font-size: clamp(16px, 1.3vw, 20px); line-height: 1.22; text-wrap: balance; }
.home-r8-scope .r13-faq-left p { margin: 0; color: var(--r8-muted); font-size: 15px; }
.home-r8-scope .r13-faq-ask {
  display: inline-flex; align-items: center; gap: 6px; align-self: flex-start;
  border: 1px solid var(--r8-line-2); border-radius: var(--r8-pill); padding: 10px 18px;
  font-size: 13.5px; font-weight: 600; margin-top: 4px; color: var(--r8-ink);
}
.home-r8-scope .r13-faq-right { display: flex; flex-direction: column; gap: 12px; }
.home-r8-scope .r13-faq-card {
  background: var(--r8-bg-2, #f9f9fa); border-radius: 18px; padding: 0; overflow: hidden;
}
.home-r8-scope .r13-faq-card summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  padding: 20px 22px; font-size: 15px; font-weight: 700; gap: 12px; min-height: 64px; box-sizing: border-box;
  color: var(--r8-ink);
}
.home-r8-scope .r13-faq-card summary::-webkit-details-marker { display: none; }
/* qa-dev t_2a22d8be non-blocking: FAQ <summary> had no :focus-visible ring. outline-offset
   is negative (ring sits inside the card) since summary already fills the card's own padding box. */
.home-r8-scope .r13-faq-card summary:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -3px;
}
.home-r8-scope .r13-faq-card .chev {
  width: 32px; height: 32px; border-radius: 50%; background: #fff; flex: none;
  display: flex; align-items: center; justify-content: center; transition: transform 0.25s var(--ease-out, ease);
  box-shadow: 0 1px 2px rgba(17,17,17,0.08); color: var(--r8-ink);
}
.home-r8-scope .r13-faq-card[open] .chev { transform: rotate(180deg); }
.home-r8-scope .r13-faq-card .ans { padding: 0 22px 20px; font-size: 14px; color: var(--r8-muted); line-height: 1.6; margin: 0; }
.home-r8-scope .r13-faq-ask-more {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 22px; border-radius: 18px; background: var(--r8-bg-2, #f9f9fa); color: var(--r8-muted); font-size: 15px; font-weight: 600;
}
.home-r8-scope .r13-faq-ask-more .left { display: flex; align-items: center; gap: 10px; }
.home-r8-scope .r13-faq-ask-more .dotmark { width: 22px; height: 22px; border-radius: 50%; background: var(--r8-ink); flex: none; }
.home-r8-scope .r13-faq-ask-more .circ { width: 32px; height: 32px; border-radius: 50%; background: #fff; display: flex; align-items: center; justify-content: center; flex: none; box-shadow: 0 1px 2px rgba(17,17,17,0.08); color: var(--r8-ink); }
@media (max-width: 860px) {
  .home-r8-scope .r13-faq-grid { grid-template-columns: 1fr; gap: var(--r8-s6); }
  /* qa-dev mobile gate t_9e424081 must-fix 4: .r13-text-fade (unconditional `position: relative`,
     declared later in this file, same specificity as the selector below) was winning the cascade
     over this `position: static` reset, so the desktop `top: 120px` from the unconditional
     `.r13-faq-left` rule above kept applying -- shifting the box ~120px down into the first FAQ
     card's own tap area (~88px overlap, confirmed via click-listener counter staying 0 vs
     programmatic .click() working). Target both classes together so this reset always wins
     regardless of source order, and clear `top` explicitly. */
  .home-r8-scope .r13-faq-left,
  .home-r8-scope .r13-faq-left.r13-text-fade { position: static; top: auto; }
}

/* r13e item 4: superseded -- the per-card ::before badge + .r8-journey-pulse travelling dot are
   removed at the source above now, not just display:none'd here. Kept only as a changelog
   breadcrumb; nothing in this file still targets .r8-journey-card::before. */

/* ================================================================
   r13f item 9 — square-grid (variant B) section background texture, faded at the edges, varied
   strength per section; per Wira (2026-11-10 00:20, verbatim): "untuk di square grid bagusnya
   ketika ada teks diatasnya ada fade background semi transparant biar teksnya gak ketutupan" --
   wherever text sits on top of the grid, a soft semi-transparent wash in the section's own
   background colour sits behind that text block so the grid never visually runs through it.
   r13g item 11 (background rhythm, full list in r13g-build-notes.md): #problem (002),
   #system (003), #services-hub (004), #industries, #start (006), #work (008) and #faq (009) all
   carry the grid now; #ai-band (005, Wira's explicit call) and the hero (own dot pattern) stay
   plain so a second texture never competes with the Auxon orbit / hero photos.
   ================================================================ */
.home-r8-scope .r13-grid-bg { position: relative; }
.home-r8-scope .r13-grid-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--r8-line-2) 1px, transparent 1px),
    linear-gradient(to bottom, var(--r8-line-2) 1px, transparent 1px);
  background-size: 56px 56px;
  /* faded at the edges (vertical fade, robust regardless of a section's own rendered height --
     never full-strength at the section's own top/bottom edge) */
  mask-image: linear-gradient(to bottom, transparent, black 14%, black 86%, transparent);
  -webkit-mask-image: linear-gradient(to bottom, transparent, black 14%, black 86%, transparent);
  opacity: var(--r13-grid-opacity, 0.6);
}
.home-r8-scope .r13-grid-bg > .w,
.home-r8-scope .r13-grid-bg > .industries-slider-outer { position: relative; z-index: 1; }
/* varied strength per section */
.home-r8-scope .r13-grid-bg--soft { --r13-grid-opacity: 0.35; }
.home-r8-scope .r13-grid-bg--med { --r13-grid-opacity: 0.6; }
.home-r8-scope .r13-grid-bg--strong { --r13-grid-opacity: 0.9; }
@media (max-width: 640px) {
  .home-r8-scope .r13-grid-bg::before { background-size: 40px 40px; }
}
@media (forced-colors: active) {
  .home-r8-scope .r13-grid-bg::before { display: none; }
}

/* soft semi-transparent background fade behind any text block sitting on the grid, in the
   section's own background colour (color-mix, same technique already used across this repo --
   app/globals.css's own .scrim/text-shadow rules) so the text never reads against raw grid
   lines. ~80-85% of the section's bg colour at the text block's own centre, feathering to
   transparent outward (radial, not a hard box). */
.home-r8-scope .r13-text-fade { position: relative; }
.home-r8-scope .r13-text-fade::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -20px -28px;
  pointer-events: none;
  background: radial-gradient(
    ellipse 120% 100% at 30% 35%,
    color-mix(in srgb, var(--r8-bg) 85%, transparent) 0%,
    color-mix(in srgb, var(--r8-bg) 85%, transparent) 52%,
    transparent 100%
  );
}
/* .r8-alt sections sit on --r8-bg-2 (grey), not --r8-bg (white) -- match the scrim to the
   section's own actual background so it reads seamless, not as a visible white patch. */
.home-r8-scope .r8-alt:not(.pg-hero + *, .hero-r8 + *) .r13-text-fade::before {
  background: radial-gradient(
    ellipse 120% 100% at 30% 35%,
    color-mix(in srgb, var(--r8-bg-2, #f9f9fa) 85%, transparent) 0%,
    color-mix(in srgb, var(--r8-bg-2, #f9f9fa) 85%, transparent) 52%,
    transparent 100%
  );
}

/* r13-text-fade, "block" variant (t_61ea6adc) -- see app/styles/pages-r8.css for the full
   writeup. Centred, self-relative ellipse sized to cover a whole multi-line text column (not
   just one heading block), so it scales to any box height/width. */
.home-r8-scope .r13-text-fade--block { position: relative; }
.home-r8-scope .r13-text-fade--block::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -24px -28px;
  pointer-events: none;
  background: radial-gradient(
    ellipse 85% 85% at 50% 50%,
    color-mix(in srgb, var(--r8-bg) 88%, transparent) 0%,
    color-mix(in srgb, var(--r8-bg) 88%, transparent) 55%,
    transparent 100%
  );
}
.home-r8-scope .r8-alt:not(.pg-hero + *, .hero-r8 + *) .r13-text-fade--block::before {
  background: radial-gradient(
    ellipse 85% 85% at 50% 50%,
    color-mix(in srgb, var(--r8-bg-2, #f9f9fa) 88%, transparent) 0%,
    color-mix(in srgb, var(--r8-bg-2, #f9f9fa) 88%, transparent) 55%,
    transparent 100%
  );
}

/* t_e73b5a75 (Wira 2026-11-12 ~14:18, verbatim: "nah yang mobil view kayaknya truet by client nya
   mending taruh dsetelah cta, jadi copy dan client posisinya semua ditengah biar rapi"): mobile
   only (<=680px). Supersedes the mobile stage spacer and the t_57d08c3e margin-bottom bump above:
   the stage is not laid out, so H1 -> sub -> CTA -> trusted-by is one group, centred both ways in
   the hero. The nav floor (padding-top: nav + 24px, N-2026-10-29-2) is kept; `safe center` falls
   back to top-anchored at that floor on a short screen, so the group never rides under the nav.
   padding-bottom shifts the optical centre up to ~47% of a 390x844 viewport (the nav floor alone
   would put it at ~52-55%) and leaves room for the full wave band below the group. The wave mask is
   placed from the CTA and trusted-by rects (HeroDotWave.tsx, mobile branch).
   t_8419fa1f (Wira 2026-11-12 ~18:0x, verbatim: "better di hero section mobile itu balikin kayak
   desktop view aja"): the centred group left ~half a screen of empty fading wave between trusted-by
   and section 2. Mobile now mirrors desktop: copy (H1/sub/CTA) in the top part, H1 at ~28% of the
   viewport like desktop's ~26%, the wave filling the middle, trusted-by pinned to the hero's bottom
   edge (margin-top: auto). The nav floor (padding-top: nav + 24px, N-2026-10-29-2) is unchanged.
   Short screens: the CTA keeps a 40px minimum gap to trusted-by, so when there is no room the logos
   flow below it and the hero grows (min-height is a floor) instead of overlapping. */
@media (max-width: 680px) {
  .home-r8-scope .hero-r8.hero-r8--wave {
    justify-content: flex-start;
    /* t_3e65a10c (Wira 2026-11-12 20:34, verbatim: "Kayaknya client perlu di naikin dikit ksrna
       ketutupan chat sudut kanan bawah"): the old clamp(24px, 4svh, 40px) left the logo row at
       ~H-42, under the fixed chat toggle (44px, top at H-68 on 481-680px and H-60 on <=480px,
       app/styles/arion-chat-overrides.css). The bottom padding now clears the toggle top by
       >=12px (the marquee adds 8px under the logos): 76px here, 68px at <=480px below. */
    padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px));
  }

  @media (max-width: 480px) {
    .home-r8-scope .hero-r8.hero-r8--wave {
      padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px));
    }
  }

  .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-in {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 0;
  }

  .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-h1 {
    margin-top: clamp(16px, calc(28svh - 94px), 180px);
  }

  .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-stage {
    display: none;
  }

  .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-ctas {
    margin-bottom: 40px;
    order: 2;
  }

  .home-r8-scope .hero-r8.hero-r8--wave .hero-client-trust {
    margin-bottom: 0;
    margin-top: auto;
    order: 3;
  }

  /* Wave mask, mobile (t_8419fa1f, desktop shape): faint behind the H1/subtitle, ~30% across the
     CTA row, full strength between the CTA and trusted-by, then eased down to ~30% behind the logos
     and 0 at the hero's bottom edge (the section-2 seam). Eased (smoothstep) stops, same alpha
     fractions as the desktop mask. */
  .home-r8-scope .hero-r8.hero-r8--wave .hero-r8-wave {
    --wm-in: var(--wave-m-in-0, 50%);
    --wm-inw: var(--wave-m-in-w, 6%);
    --wm-up: var(--wave-m-up-0, 72%);
    --wm-upw: var(--wave-m-up-w, 8%);
    --wm-out: var(--wave-m-out-0, 88%);
    --wm-outw: var(--wave-m-out-w, 12%);
    mask-image: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0) var(--wave-top-0, 30%),
      rgba(0, 0, 0, 0.019) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.2),
      rgba(0, 0, 0, 0.063) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.4),
      rgba(0, 0, 0, 0.117) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.6),
      rgba(0, 0, 0, 0.161) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.8),
      rgba(0, 0, 0, 0.18) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%)),
      rgba(0, 0, 0, 0.18) var(--wm-in),
      rgba(0, 0, 0, 0.192) calc(var(--wm-in) + var(--wm-inw) * 0.2),
      rgba(0, 0, 0, 0.222) calc(var(--wm-in) + var(--wm-inw) * 0.4),
      rgba(0, 0, 0, 0.258) calc(var(--wm-in) + var(--wm-inw) * 0.6),
      rgba(0, 0, 0, 0.288) calc(var(--wm-in) + var(--wm-inw) * 0.8),
      rgba(0, 0, 0, 0.3) calc(var(--wm-in) + var(--wm-inw)),
      rgba(0, 0, 0, 0.3) var(--wm-up),
      rgba(0, 0, 0, 0.376) calc(var(--wm-up) + var(--wm-upw) * 0.2),
      rgba(0, 0, 0, 0.548) calc(var(--wm-up) + var(--wm-upw) * 0.4),
      rgba(0, 0, 0, 0.752) calc(var(--wm-up) + var(--wm-upw) * 0.6),
      rgba(0, 0, 0, 0.924) calc(var(--wm-up) + var(--wm-upw) * 0.8),
      rgba(0, 0, 0, 1) calc(var(--wm-up) + var(--wm-upw)),
      rgba(0, 0, 0, 1) var(--wm-out),
      rgba(0, 0, 0, 0.896) calc(var(--wm-out) + var(--wm-outw) * 0.2),
      rgba(0, 0, 0, 0.648) calc(var(--wm-out) + var(--wm-outw) * 0.4),
      rgba(0, 0, 0, 0.352) calc(var(--wm-out) + var(--wm-outw) * 0.6),
      rgba(0, 0, 0, 0.104) calc(var(--wm-out) + var(--wm-outw) * 0.8),
      rgba(0, 0, 0, 0) calc(var(--wm-out) + var(--wm-outw))
    );
    -webkit-mask-image: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0) var(--wave-top-0, 30%),
      rgba(0, 0, 0, 0.019) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.2),
      rgba(0, 0, 0, 0.063) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.4),
      rgba(0, 0, 0, 0.117) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.6),
      rgba(0, 0, 0, 0.161) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%) * 0.8),
      rgba(0, 0, 0, 0.18) calc(var(--wave-top-0, 30%) + var(--wave-top-w, 8%)),
      rgba(0, 0, 0, 0.18) var(--wm-in),
      rgba(0, 0, 0, 0.192) calc(var(--wm-in) + var(--wm-inw) * 0.2),
      rgba(0, 0, 0, 0.222) calc(var(--wm-in) + var(--wm-inw) * 0.4),
      rgba(0, 0, 0, 0.258) calc(var(--wm-in) + var(--wm-inw) * 0.6),
      rgba(0, 0, 0, 0.288) calc(var(--wm-in) + var(--wm-inw) * 0.8),
      rgba(0, 0, 0, 0.3) calc(var(--wm-in) + var(--wm-inw)),
      rgba(0, 0, 0, 0.3) var(--wm-up),
      rgba(0, 0, 0, 0.376) calc(var(--wm-up) + var(--wm-upw) * 0.2),
      rgba(0, 0, 0, 0.548) calc(var(--wm-up) + var(--wm-upw) * 0.4),
      rgba(0, 0, 0, 0.752) calc(var(--wm-up) + var(--wm-upw) * 0.6),
      rgba(0, 0, 0, 0.924) calc(var(--wm-up) + var(--wm-upw) * 0.8),
      rgba(0, 0, 0, 1) calc(var(--wm-up) + var(--wm-upw)),
      rgba(0, 0, 0, 1) var(--wm-out),
      rgba(0, 0, 0, 0.896) calc(var(--wm-out) + var(--wm-outw) * 0.2),
      rgba(0, 0, 0, 0.648) calc(var(--wm-out) + var(--wm-outw) * 0.4),
      rgba(0, 0, 0, 0.352) calc(var(--wm-out) + var(--wm-outw) * 0.6),
      rgba(0, 0, 0, 0.104) calc(var(--wm-out) + var(--wm-outw) * 0.8),
      rgba(0, 0, 0, 0) calc(var(--wm-out) + var(--wm-outw))
    );
  }
}

/* ==== t_5603656c hero CTA hover/focus/press, "sheen" (V3, Wira 2026-11-12: "ya v3").
   Wira: "tinggal bikin cta nya lebih cantik, karena saat ini gak ada edanya ketika button di
   hover". Rules: no shadows, no layout shift (secondary's hover pill is a ::before painted
   OUTSIDE the link's own box, so its size/position never change), hover only on fine pointers
   (no sticky hover on touch), 200ms ease-out colour, colour-only under prefers-reduced-motion.
   `html:root` keeps the specificity these rules were tuned with over the older hero rules. ==== */

html:root .home-r8-scope .hero-r8-ctas {
  --cta-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --cta-ring: var(--r8-ink);
  /* Near-opaque so the dot-wave doesn't show through the pill (reads as a calm surface). */
  --cta-sec-fill: rgba(244, 244, 245, 0.94);
  --cta-sec-line: rgba(25, 24, 27, 0.26);
}

html:root[data-theme="dark"] .home-r8-scope .hero-r8-ctas {
  --cta-ring: #f2f2f2;
  --cta-sec-fill: rgba(28, 28, 30, 0.94);
  --cta-sec-line: rgba(255, 255, 255, 0.34);
}

html:root .home-r8-scope .hero-r8-ctas .btn {
  isolation: isolate;
  overflow: hidden;
  position: relative;
  transition:
    background-color 0.2s var(--cta-ease),
    border-color 0.2s var(--cta-ease),
    color 0.2s var(--cta-ease),
    transform 0.12s var(--cta-ease);
}

html:root .home-r8-scope .hero-r8-ctas .btn:focus-visible {
  outline: 2px solid var(--cta-ring);
  outline-offset: 3px;
}

html:root .home-r8-scope .hero-r8-see-work {
  isolation: isolate;
  position: relative;
  transition: color 0.2s var(--cta-ease);
}

/* The secondary's hover pill: same height as the primary (measured), outside the link's box. */
html:root .home-r8-scope .hero-r8-see-work::before {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r8-pill, 999px);
  content: "";
  /* 1280: link box 24px tall vs the 44px primary -> -10px = identical pill height; -12px
     sides keep an 8px gap to the primary (20px row gap). Mobile link already has 12px 2px
     padding (48px box), so its pill sits closer. */
  inset: -10px -12px;
  pointer-events: none;
  position: absolute;
  transition:
    background-color 0.2s var(--cta-ease),
    border-color 0.2s var(--cta-ease),
    clip-path 0.25s var(--cta-ease);
  z-index: -1;
}

@media (max-width: 860px) {
  html:root .home-r8-scope .hero-r8-see-work::before {
    inset: 0 -10px;
  }
}

html:root .home-r8-scope .hero-r8-see-work:focus-visible {
  outline: none;
}

html:root .home-r8-scope .hero-r8-see-work:focus-visible::before {
  outline: 2px solid var(--cta-ring);
  outline-offset: 3px;
}

html:root .home-r8-scope .hero-r8-see-work .arr {
  display: inline-block;
  transition: transform 0.2s var(--cta-ease), color 0.2s var(--cta-ease);
}

/* Kill the old unconditional 4px nudge; each variant re-adds 3px under fine-pointer hover. */
html:root .home-r8-scope .hero-r8-see-work:hover .arr {
  transform: none;
}

/* Arrow nudge (3px) on fine-pointer hover. */
@media (hover: hover) and (pointer: fine) {
  html:root .home-r8-scope .hero-r8-see-work:hover .arr {
    transform: translateX(3px);
  }
}

/* ---------- Sheen ---------- */
/* Primary: one soft light band sweeps left->right once on hover-in; it jumps back unseen on
   hover-out (no transition at rest), so it never sweeps backwards. No glow, no shadow. */
html:root .home-r8-scope .hero-r8-ctas .btn::after {
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgba(255, 255, 255, 0) 30%,
    rgba(255, 255, 255, 0.2) 50%,
    rgba(255, 255, 255, 0) 70%,
    transparent 100%
  );
  content: "";
  inset: 0;
  pointer-events: none;
  position: absolute;
  transform: translateX(-110%);
  z-index: -1;
}
html:root[data-theme="dark"] .home-r8-scope .hero-r8-ctas .btn::after {
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgba(139, 105, 87, 0) 30%,
    rgba(139, 105, 87, 0.2) 50%,
    rgba(139, 105, 87, 0) 70%,
    transparent 100%
  );
}
/* Secondary: fill wipes in from the left. */
html:root .home-r8-scope .hero-r8-see-work::before {
  background: var(--cta-sec-fill);
  border-color: var(--cta-sec-line);
  clip-path: inset(0 100% 0 0 round var(--r8-pill, 999px));
}
@media (hover: hover) and (pointer: fine) {
  html:root .home-r8-scope .hero-r8-ctas .btn:hover {
    background: #232226;
    border-color: #232226;
  }
  html:root[data-theme="dark"] .home-r8-scope .hero-r8-ctas .btn:hover {
    background: #ebe8e5 !important;
    border-color: #ebe8e5 !important;
  }
  html:root .home-r8-scope .hero-r8-ctas .btn:hover::after {
    transform: translateX(110%);
    transition: transform 0.6s var(--cta-ease);
  }
  html:root .home-r8-scope .hero-r8-see-work:hover::before {
    clip-path: inset(0 0 0 0 round var(--r8-pill, 999px));
  }
}
html:root .home-r8-scope .hero-r8-see-work:focus-visible::before {
  clip-path: none;
}

/* ---------- Touch: subtle press only (the existing coarse .btn:active scale .97 stays) ---------- */
@media (hover: none) and (pointer: coarse) {
  html:root .home-r8-scope .hero-r8-see-work:active::before {
    background: var(--cta-sec-fill);
    border-color: var(--cta-sec-line);
    clip-path: none;
    transition-duration: 0.1s;
  }
}

/* ---------- Reduced motion: colour only, nothing moves ---------- */
@media (prefers-reduced-motion: reduce) {
  html:root .home-r8-scope .hero-r8-see-work:hover .arr {
    transform: none;
  }
  html:root .home-r8-scope .hero-r8-ctas .btn::after {
    display: none;
  }
  html:root .home-r8-scope .hero-r8-see-work::before {
    clip-path: none;
    background: transparent;
    border-color: transparent;
  }
  html:root .home-r8-scope .hero-r8-see-work:hover::before {
    background: var(--cta-sec-fill);
    border-color: var(--cta-sec-line);
  }
  html:root .home-r8-scope .hero-r8-ctas .btn:active {
    transform: none;
  }
}
