/* ── Reset ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Design tokens (Figma → bosOnline-LP) ─────────────────── */
:root {
  --orange:      #ff7203;   /* --boscod/main */
  --orange-dark: #e56200;
  --orange-wash: #fba051;   /* bosonline.id page-background gradient tint */
  --text:        #212b36;   /* --text/primary */
  --white:       #ffffff;
  --gray-50:     #f9fafb;
  --gray-100:    #f3f4f6;
  --gray-700:    #374151;
  --font:        'Public Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  /* Figma button tokens */
  --btn-radius:  8px;       /* --button/radius */
  --btn-h:       48px;      /* all nav buttons */
  --btn-px-text: 10px;      /* --button/[text][large]--px */
  --btn-px-fill: 16px;      /* --button/[large]--px */
  --btn-gap:     8px;       /* --button/spacing */
  /* Figma spacing */
  --nav-px:      32px;
}

/* NOTE: `scroll-behavior: smooth` intentionally NOT set here — it conflicts with
   GSAP ScrollTrigger's scrub/snap (see script.js feature-section block). If smooth
   anchor scrolling is needed later, do it in JS so ScrollTrigger stays in sync. */
body {
  font-family: var(--font);
  color: var(--text);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;   /* safety net for decorative elements that deliberately
                            bleed past their container (e.g. .cta-ornament-1's
                            negative left offset) on viewports narrower than 1280px */
}

/* ── Nav header ───────────────────────────────────────────── */
.nav-header {
  position: sticky;
  top: 0;
  z-index: 100;
  /* bosonline.id's own header uses this exact gradient (its `header{}` rule,
     distinct from the steeper one on its hero section). */
  background: linear-gradient(180.67deg, var(--orange-wash) -602.94%, var(--white) 217.41%);
  transition: background 0.25s ease, box-shadow 0.25s ease;
}

/* Toggled by script.js once the page is scrolled past SCROLL_THRESHOLD — a
   barely-there translucent warm wash with a heavy frosted-glass blur, instead
   of the near-white gradient wash used at the top of the page. .nav-btn's
   text color is unaffected (already var(--text) unscrolled); .btn-masuk
   switches to match it below, rather than staying orange. */
.nav-header.is-scrolled {
  background: rgb(239 199 168 / 29%);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 4px 16px rgba(33, 43, 54, 0.12);
}

.nav-header.is-scrolled .btn-masuk {
  color: var(--text);
  border-color: var(--text);
}
.nav-header.is-scrolled .btn-masuk:hover {
  background: rgba(33, 43, 54, 0.06);
  border-color: var(--text);
}

/* Fixed-width container (live site: max-w-7xl = 1280px) */
.nav-wrapper {
  position: relative;
  max-width: 80rem;        /* 1280px */
  margin: 0 auto;
  /* padding: 0 var(--nav-px);  Figma: px-[80px] */
}

/* Figma: flex items-center justify-between, content height driven by h-[48px] buttons */
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 88px;            /* 20px top + 48px buttons + 20px bottom */
  padding: 0 var(--nav-px);
}

/* ── Logo ─────────────────────────────────────────────────── */
.nav-logo {
  display: block;
  text-decoration: none;
  flex-shrink: 0;
}

.logo {
  display: block;
  height: 48px;
  width: auto;
}

/* ── Desktop nav ──────────────────────────────────────────── */
/* Figma: flex gap-[24px] items-center  (center group, node 985:26404) */
.desktop-nav {
  display: flex;
  align-items: center;
  gap: 24px;
}

/* ── Nav button (text + optional chevron) ─────────────────── */
/* Figma: h-[48px] w-[108px] min-w-[64px] px-[10px] gap-[8px]
          rounded-[8px] font-bold text-[15px] leading-[26px] #212b36 */
.nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--btn-gap);
  height: var(--btn-h);
  min-width: 64px;
  padding: 0 var(--btn-px-text);
  background: none;
  border: none;
  border-radius: var(--btn-radius);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: var(--text);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  list-style: none;        /* for <summary> */
  user-select: none;
  transition: background 0.15s, color 0.15s;
}
.nav-btn::-webkit-details-marker { display: none; }
.nav-btn:hover { background: rgba(33,43,54,.06); }

/* Figma: end icon size-[24px] */
.nav-chevron {
  display: block;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  transition: transform 0.2s;
}
details[open] > .nav-btn .nav-chevron {
  transform: rotate(180deg);
}

/* ── Dropdown menu ────────────────────────────────────────── */
.dropdown {
  position: relative;
}

.dropdown-menu {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  background: var(--white);
  border: 1px solid var(--gray-100);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.08);
  padding: 8px 0;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.15s, transform 0.15s;
  z-index: 50;
  white-space: nowrap;
}
details[open] > .dropdown-menu {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.dropdown-item {
  display: block;
  padding: 8px 16px;
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  color: var(--gray-700);
  text-decoration: none;
  transition: background 0.1s;
}
.dropdown-item:hover { background: var(--gray-50); }

/* ── Auth buttons (right group, node 985:26409) ──────────── */
/* Figma: flex gap-[24px] items-center */
.desktop-auth {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-shrink: 0;
}

/* "Masuk" — outline style: transparent fill, orange border + text. Shared
   between the desktop nav (.desktop-auth) and the mobile drawer
   (.mobile-auth-row), so this one rule covers both — see the ≤820px note
   below on why .desktop-auth .btn-masuk is hidden there instead of a bare
   .btn-masuk selector. */
.btn-masuk {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 78px;    /* matches bosonline.id's own "Masuk" button width (measured ~77.56px) */
  height: var(--btn-h);
  padding: 0 calc(var(--btn-px-text) - 1px);   /* -1px compensates the new border so text stays visually centered at the same inset as before */
  background: none;
  border: 1px solid var(--orange);
  border-radius: var(--btn-radius);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: var(--orange);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s, border-color 0.15s;
}
.btn-masuk:hover { background: rgba(255,114,3,.08); border-color: var(--orange-dark); }

/* "Daftar Gratis" — Figma: bg-#ff7203 h-48px px-16px rounded-8px white text */
.btn-daftar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--btn-h);
  padding: 0 var(--btn-px-fill);
  background: var(--orange);
  border: none;
  border-radius: var(--btn-radius);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: var(--white);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s;
}
.btn-daftar:hover { background: var(--orange-dark); }

/* Daftar Gratis inside .nav-mobile-actions — visibility is controlled by that
   wrapper (display:none by default), so this is always inline-flex itself.
   Sized to Figma's "medium" button (node 1319:38469, the <=768px spec); the
   mobile tier below shrinks it further to "small" (node 1319:40064). */
.mobile-daftar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 0 12px;
  background: var(--orange);
  border: none;
  border-radius: var(--btn-radius);
  font-family: var(--font);
  font-size: 14px;
  font-weight: 700;
  line-height: 24px;
  color: var(--white);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s;
  flex-shrink: 0;
}
.mobile-daftar:hover { background: var(--orange-dark); }

/* ── Mobile actions group (<=768px) ──────────────────────── */
/* Figma nodes 1319:38467 (768) / 1319:40062 (mobile) — Daftar Gratis + the
   hamburger IconButton, grouped as ONE flex item of .nav-inner so
   justify-content:space-between only ever sees "logo" and "everything else"
   as the two ends, instead of spreading 3 separate items across the bar. */
.nav-mobile-actions {
  display: none;
  align-items: center;
  gap: 24px;             /* Figma: gap-[24px] at 768 (node 1319:38467) */
  flex-shrink: 0;
}

/* ── Hamburger (IconButton) ──────────────────────────────── */
.hamburger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  color: var(--text);
  flex-shrink: 0;
  transition: background 0.15s;
}
.hamburger:hover { background: rgba(33,43,54,.06); }

.hamburger-icon {
  width: 24px;
  height: 24px;
}

/* ── Mobile drawer ────────────────────────────────────────── */
/* Overlays the page instead of pushing it down: .nav-header is already
   position:sticky, which is a valid containing block for an absolutely
   positioned child, so `top:100%` alone tracks the nav bar's real height at
   every tier (80px / 72px) with no hardcoded per-breakpoint offset needed —
   it just sits flush against whatever the nav bar's current height is.
   z-index only has to clear its sibling .nav-wrapper (both children of
   .nav-header, so this is a LOCAL stack — not the page's global 0-100
   scale); .mobile-menu-overlay below sits behind the whole header on the
   page's own scale (z-index:99 vs .nav-header's 100), so the header bar
   itself — hamburger included — stays undimmed and clickable to close. */
.mobile-menu {
  display: none;
  flex-direction: column;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 1;
  background: var(--white);
  border-top: 1px solid var(--gray-100);
  box-shadow: 0 12px 24px rgba(33,43,54,0.12);
  overflow-x: hidden;
  overflow-y: auto;   /* Produk/Blog expanded together can outgrow a short phone viewport */
  max-height: 0;
  transition: max-height 0.3s ease;
}
/* 500px comfortably fits every row plus one expanded submenu (Produk, the
   larger of the two, at ~180px) with margin; capped against dvh too so a
   landscape phone gets an internal scrollbar instead of running off-screen. */
.mobile-menu.open { max-height: min(500px, calc(100dvh - 96px)); }

/* Background scrim — dims the page behind the open drawer. Kept OUTSIDE
   .nav-header in the DOM (see index.html) specifically so script.js's
   existing "click outside .nav-header" handler closes the drawer on scrim
   clicks too, without any dedicated JS. Visibility is pure CSS: `:has()`
   lets the scrim react to the drawer's own .open class on a shared ancestor,
   so no class-toggling JS is needed here either. */
.mobile-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: rgba(15,23,32,0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
body:has(.mobile-menu.open) .mobile-menu-overlay {
  opacity: 1;
  pointer-events: auto;
}

/* Shared by plain links (Cerita Penjual) AND the Produk/Blog <summary>
   triggers — flex+space-between is a no-op for a plain text-only <a> and is
   what lets the chevron sit flush right on the summary rows. */
.mobile-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 24px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--gray-100);
  cursor: pointer;
  list-style: none;     /* Firefox <summary> marker */
  transition: background 0.1s;
}
.mobile-link::-webkit-details-marker { display: none; }   /* Chrome/Safari <summary> marker */
.mobile-link:hover { background: var(--gray-50); }

.mobile-chevron {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  transition: transform 0.2s;
}
.mobile-dropdown[open] > .mobile-link .mobile-chevron { transform: rotate(180deg); }

/* Child category list — same max-height trick as .mobile-menu itself:
   .mobile-submenu is forced to always lay out (overriding <details>' own
   UA default of display:none for its non-summary content when closed) so
   max-height can animate it, exactly like the desktop .dropdown-menu
   overrides the same native hidden state (there via opacity, here via
   height since this is in-flow, not an absolute-positioned popover). */
.mobile-submenu {
  display: flex;
  flex-direction: column;
  background: var(--gray-50);
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}
.mobile-dropdown[open] > .mobile-submenu { max-height: 220px; }   /* fits Produk's 4 items */

.mobile-sublink {
  display: block;
  padding: 12px 24px 12px 40px;   /* indented under the parent label */
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  color: var(--gray-700);
  text-decoration: none;
  border-bottom: 1px solid var(--gray-100);
  transition: background 0.1s;
}
.mobile-sublink:last-child { border-bottom: none; }   /* avoid doubling up with .mobile-link's own divider right after */
.mobile-sublink:hover { background: var(--gray-100); }

/* Grid, not flex, for the two buttons: minmax(0,1fr) tracks split the row by
   pure available space, ignoring each button's own border/padding — flex's
   flex:1 + flex-basis:0% looked equivalent but still seeded its growth math
   from each item's border-box (.btn-masuk's 1px border + smaller padding vs
   .btn-daftar's 0 border + larger padding), so they never actually landed on
   equal widths, just a fixed ~12px apart. */
.mobile-auth-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  padding: 16px 24px;
}

/* .btn-masuk's own fixed 78px (sized to mirror bosonline.id's desktop button)
   would otherwise win here too — override it back to auto so it fills its
   grid cell like .btn-daftar does. Height already matches .btn-daftar's at
   every tier via the shared unscoped .btn-daftar/.btn-masuk shrink in the
   ≤820 block below (.desktop-auth's own .btn-masuk is hidden by then, so
   that shrink only ever reaches this drawer instance). */
.mobile-auth-row .btn-masuk {
  width: auto;
}

/* ── Responsive ───────────────────────────────────────────── */
/* Four explicit Figma frames drive the sizing at each tier, at four different
   canvas widths — taken literally (not run through the ~0.4x scale-down this
   project uses for Figma's 80px page-section padding) since these ARE the
   intended implementation values, not stylized mockup numbers:
     node 1293:15259 @1024  — full nav, unchanged sizes, just tighter padding
     node 1297:39611 @820   — logo/buttons shrink to "medium", Masuk dropped
     node 1319:38408 @768   — nav links + Masuk gone, hamburger appears
     node 1319:40003 @375   — same 768 layout, logo/buttons shrink to "small"
   Padding lives on .nav-inner only (not .nav-wrapper) at every tier — the two
   used to stack, which is what pushed "Daftar Gratis" off-screen below
   ~962px in an earlier pass at this.

   The hamburger/drawer SWITCHOVER POINT, though, isn't literally one of those
   4 frames — none of them are a static mockup of the messy in-between zone.
   Measured directly (headless Chrome, this exact content): the full desktop
   nav's natural width already exceeds the viewport starting at 845px, well
   above the 820px "medium" tier that's supposed to have already shrunk it by
   then — a ~25px dead zone where `overflow-x:hidden` was silently clipping
   "Daftar Gratis" off the right edge with no scrollbar to hint anything was
   wrong. Switching to the hamburger+drawer at 900px (55px of margin past the
   measured 845px break, absorbing minor cross-browser font-metric variance)
   closes that gap entirely — see the 900 block below, moved up from 768. */

/* 1024 — Figma: px-[40px], everything else identical to desktop */
@media (max-width: 1024px) {
  .nav-inner { padding: 0 40px; }
}

/* 900 — hamburger + drawer takes over here (not a literal Figma frame — see
   the note above). .desktop-nav/.desktop-auth's own "medium" sizing below
   (in the 820 block) is consequently dead past this point — those elements
   are display:none by the time ≤820 is even reached — left in place rather
   than deleted since it's harmless and this project's Figma-frame comments
   document intent, not just current reachability. */
@media (max-width: 900px) {
  .nav-inner { height: 80px; }   /* was 88px — Figma's own frame height here */

  .desktop-nav,
  .desktop-auth      { display: none; }
  .nav-mobile-actions { display: flex; }
  .mobile-menu        { display: flex; }
}

/* 820 — Figma: px-[24px], logo/nav-btn/Daftar Gratis drop to "medium".
   .btn-masuk is scoped to .desktop-auth specifically — that class is REUSED
   verbatim for the drawer's own "Masuk" link (.mobile-auth-row .btn-masuk),
   and an unscoped `.btn-masuk { display: none }` here was silently deleting
   Masuk from the drawer too at every width ≤820, i.e. everywhere the drawer
   is actually capable of being open. .btn-daftar's resize just below is
   intentionally left unscoped — that one IS meant to also shrink the
   drawer's own Daftar Gratis button, it's just never hidden outright. */
@media (max-width: 820px) {
  .nav-inner { padding: 0 24px; }
  .logo      { height: 40px; }

  .desktop-auth .btn-masuk { display: none; }

  .nav-btn {
    height: 36px;
    padding: 0 8px;       /* Figma: button/[text][medium]--px */
    font-size: 14px;
    line-height: 24px;
  }
  .nav-chevron { width: 20px; height: 20px; }

  .btn-daftar {
    height: 36px;
    padding: 0 12px;      /* Figma: button/[medium]--px */
    font-size: 14px;
    line-height: 24px;
  }

  /* Unscoped like .btn-daftar just above — .desktop-auth's own .btn-masuk is
     already display:none by this width, so this only ever reaches the
     drawer's instance, keeping it the same height as its row-mate. */
  .btn-masuk {
    height: 36px;
    padding: 0 12px;
    font-size: 14px;
    line-height: 24px;
  }
}

/* Mobile, down to a 375px reference width — Figma: px-[16px]. Same hamburger
   layout as 768, just every size drops one more notch: logo shrinks again,
   Daftar Gratis goes from "medium" to "small", the hamburger itself shrinks
   from a 40px to a 36px circle, and the two sit closer together (gap 8 vs 24). */
@media (max-width: 767px) {
  .nav-inner { padding: 0 16px; height: 72px; }
  .logo      { height: 32px; }   /* Figma: 31.765px, native aspect */

  .nav-mobile-actions { gap: 8px; }

  .mobile-daftar {
    height: 30px;
    padding: 0 8px;       /* Figma: button/[small]--px */
    font-size: 13px;
    line-height: 22px;
  }

  .hamburger      { width: 36px; height: 36px; }
  .hamburger-icon { width: 20px; height: 20px; }
}

/* ═══════════════════════════════════════════════════════════
   Hero Section  (Figma node 987:26530)
═══════════════════════════════════════════════════════════ */

/* Figma: bg-white px-[80px] py-[16px] flex items-center justify-between */
.hero-section {
  background: linear-gradient(180.67deg, var(--orange-wash) -232.59%, var(--white) 44.48%);
  overflow: hidden;
  padding: 40px 0;
  /* min-height: calc(100vh - 88px);   fallback */
  /* min-height: calc(100svh - 88px); fill remaining viewport below sticky nav */
  /* display: flex; */
  /* flex-direction: column; */
}

.hero-wrapper {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0 var(--nav-px);
  /* flex: 1; */
  /* display: flex; */
  /* flex-direction: column; */
}

.hero-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 120px;
  /* padding-bottom: 64px;
  padding-top: 64px; */
  /* flex: 1; */
}

/* Full-viewport hero — only for screens ≤1920px wide (below 1080p desktops)
   Disabled: svh caused viewport-dependent width/height inconsistencies during review.
@media (max-width: 1920px) {
  .hero-section {
    min-height: calc(100vh - 88px);
    min-height: calc(100svh - 88px);
    display: flex;
    flex-direction: column;
  }
  .hero-wrapper {
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  .hero-inner {
    padding: 64px 0;
    flex: 1;
  }
}
*/

/* ── Left content ───────────────────────────────────────── */
/* Figma: flex flex-col gap-[32px] items-start */
.hero-content {
  display: flex;
  flex-direction: column;
  gap: 32px;
  flex-shrink: 0;
  max-width: 492px;       /* Figma: w-[492px] headline container */
}

/* Figma: flex flex-col gap-[16px] items-start */
.hero-header {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Figma: flex flex-col items-start w-[492px] */
.hero-headline {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 492px;   /* was a hard 492px — overflowed every narrower .hero-content tier below */
}

.hero-line1 {
  display: flex;
  align-items: center;
}

/* Figma originally did this as a gradient on the whole "Atur Jualanmu Gratis"
   line, hard-stopped at a fixed 69.512% — that only lined up with "Gratis"
   at the exact 492px/48px desktop measurements it was computed from, so the
   tint drifted off the word as soon as the title wrapped/resized at smaller
   breakpoints. Scoping the background to the word's own <span> instead means
   it's always exactly as wide as "Gratis" renders, at any width or font-size. */
.hero-highlight {
  background: rgba(255,114,3,0.08);
}

/* Figma: Red Hat Display Bold 48px / 64px / #212b36 */
.hero-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma: Header Decoration — h-[32px] w-full. The logical box for the wave is
   443.5x33.133 at (1.5,-6.63), but Figma's own export (imgVector32, node
   987:26544) bleeds past that box on every side — inset[-12.06% -0.9% -12.07%
   -0.9%] of the logical box — which is why the downloaded asset's own native
   size is 451.501x41.1306, not 443.5x33.133. Positioned/sized here at the
   asset's real dimensions (box position minus each inset) rather than
   cropping it down to the logical box. */
.hero-deco {
  position: relative;
  height: 32px;
  width: 100%;
}

.hero-wave {
  position: absolute;
  left:   -2.49px;
  top:   -10.63px;
  width:  451.5px;
  height: 41.13px;
  aspect-ratio: 451.5 / 41.13;   /* lets width-only overrides below compute height */
  display: block;
}

/* ── Description block ──────────────────────────────────── */
/* Figma: flex flex-col gap-[32px] items-start w-full */
.hero-body {
  display: flex;
  flex-direction: column;
  gap: 56px;
  width: 100%;
}

/* Figma: Public Sans Regular 16px / 24px / #212b36 */
.hero-desc {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
}

/* Figma: flex items-center justify-between w-full */
.hero-interactive {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
}

/* Figma: TextField w-[320px] h-[54px]
   drop-shadow: 0 0 1px rgba(145,158,171,.2), 0 12px 12px rgba(145,158,171,.12)
   border: rgba(145,158,171,0.2) rounded-8px px-14px */
/* flex-shrink:0 here (this was the desktop-only original) pinned the field
   to a hard 320px no matter how narrow its row got — between 1024 and 820,
   .hero-content genuinely shrinks below 320px+gap+button, and a
   non-shrinking field was overflowing past its own column. min-width:0 lets
   it shrink past its children's own content-driven minimum too. Each tier
   below still sets its own `width` as an upper target (Figma's literal
   value for that breakpoint); this only stops it being forced wider than
   the space actually available in between. */
.hero-field {
  display: flex;
  align-items: center;
  gap: 8px;               /* Figma: pr-[8px] after adornment */
  width: 320px;
  min-width: 0;
  flex-shrink: 1;
  height: 54px;
  padding: 0 14px;
  border: 1px solid rgba(145,158,171,0.2);
  border-radius: 8px;
  background: var(--white);
  box-shadow: 0 0 1px rgba(145,158,171,0.2), 0 12px 12px rgba(145,158,171,0.12);
}

/* Figma: blue badge bg-[#3f8be7] h-24px min-w-24px px-6px rounded-6px
   text: Public Sans Bold 12px / 20px white */
.hero-badge {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 6px;
  background: var(--orange);
  border-radius: 6px;
  font-family: var(--font);
  font-size: 12px;
  font-weight: 700;
  line-height: 20px;
  color: var(--white);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Real input field — placeholder animated via JS typewriter */
.hero-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  color: #212b36;
}
.hero-input::placeholder { color: #919eab; }

/* Figma: bg-#ff7203 h-48px px-16px rounded-8px Public Sans Bold 15px/26px white */
.hero-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 16px;
  background: var(--orange);
  border: none;
  border-radius: 8px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: var(--white);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background 0.15s;
}
.hero-btn:hover { background: var(--orange-dark); }

/* ── Right image ────────────────────────────────────────── */
/* Figma: size-[600px] relative. 540px is only the size AT the 1280px desktop
   frame — .hero-content stays flex-shrink:0 (its nowrap title/badge sets its
   own real floor), so between 1280 and 1024 the row genuinely doesn't fit at
   540+120(gap)+content's own ~492px, and with the section's overflow:hidden
   that silently CROPPED the image instead of shrinking it. Letting the image
   flex-shrink (height:auto so aspect-ratio keeps it square as it shrinks) is
   the same "image absorbs the squeeze, content width protected" pattern
   already used at every breakpoint below 1024. */
.hero-image {
  position: relative;
  width:  540px;
  height: auto;
  aspect-ratio: 1 / 1;   /* lets the responsive tiers below override width only */
  flex-shrink: 1;
  min-width: 0;
}

/* Dot grid (Figma: Row × 6, left-20px top-80px, each 176×16px)
   Reproduced with CSS repeating dots */
.hero-dots {
  position: absolute;
  left: 20px;
  top:  80px;
  width:  176px;
  height: 112px;          /* 6 rows × ~16px + gaps ≈ 112px */
  background-image: radial-gradient(circle, rgba(255,114,3,0.35) 1.5px, transparent 1.5px);
  background-size: 16px 16px;
  pointer-events: none;
}

/* Decorative circles — Figma Ellipse6/7/8 (orange glows) */
/* Ellipse6: left-0 top-388px size-172px */
.hero-circle {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.hero-circle-1 {
  left: 0;
  top:  388px;
  width:  172px;
  height: 172px;
  background: radial-gradient(circle, rgba(255,114,3,0.35) 0%, rgba(255,114,3,0) 70%);
}
/* Ellipse7: left-460px top-378px size-140px */
.hero-circle-2 {
  left: 460px;
  top:  378px;
  width:  140px;
  height: 140px;
  background: radial-gradient(circle, rgba(255,114,3,0.25) 0%, rgba(255,114,3,0) 70%);
}
/* Ellipse8: left-260px top-88px size-231px */
.hero-circle-3 {
  left: 260px;
  top:   88px;
  width:  231px;
  height: 231px;
  background: radial-gradient(circle, rgba(255,140,3,0.55) 0%, rgba(255,114,3,0.15) 50%, rgba(255,114,3,0) 75%);
}

/* Main hero image — fills the container, centered */
.hero-img {
  position: absolute;
  inset: 0;
  width:  100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  display: block;
}

/* ── Hero responsive ──────────────────────────────────────
   Four explicit Figma frames (1024/820/768/375), taken at literal pixel
   values per tier — same method just used for the nav bar, and reusing the
   nav's own padding schedule (40/24/24/16) so the hero stays left-aligned
   with the logo/nav content at every width.
     node 1293:15340 @1024 — content shrinks to "medium" across the board
     node 1312:10339 @820  — re-fetched directly (was previously mis-read via
                              get_metadata on the wrong node): Content
                              Container is 366px, Image Container is 336px,
                              and header-interactive is flex-col gap-16 — the
                              field/button STACK here already, not a row.
     node 1319:38491 @768  — Content Container 360px, Image Container 314px,
                              header-interactive also stacked (flex-col).
     node 1319:40091 @375  — layout STACKS the whole row to a column
   The illustration is one flattened photo in this project (not Figma's
   individual row/ellipse/vector layers), so only .hero-image's box size
   changes per tier — same as resizing a photo frame. */

/* 1024 — the big jump: everything drops to Figma's "medium" component size */
@media (max-width: 1024px) {
  .hero-wrapper { padding: 0 40px; }

  /* Base .hero-inner keeps its desktop gap:120px, which — combined with
     justify-content:space-between — acts as a MINIMUM enforced gap, not a
     cap. Left unoverridden it forcibly ate into .hero-content's width below
     1024px (shrinking it to ~353px instead of its intended 475px, which is
     why the description text was wrapping to 3 lines instead of 2). These
     three values are exactly what's left over once Figma's own
     content/image widths are subtracted from each tier's own inner width —
     e.g. 1024 - 80(padding) - 475(content) - 382(image) = 87. */
  .hero-inner { gap: 87px; }

  .hero-content {
    flex: 0 1 475px;
    max-width: 475px;
    min-width: 0;
    gap: 24px;
  }
  .hero-title { font-size: 36px; line-height: 1.5; }
  .hero-body  { gap: 24px; }

  /* Desktop's bleed offsets were tuned for that exact export; at smaller
     tiers the wave is simply flush in its box, sized off its own aspect
     ratio (same simplification already used for the other squiggles). */
  .hero-wave { left: 0; top: 0; width: 324.5px; height: auto; }

  .hero-field { width: 320px; height: 40px; }   /* was 54px */

  /* Figma: components/button-medium */
  .hero-btn {
    height: 36px;
    padding: 0 12px;
    font-size: 14px;
    line-height: 24px;
  }

  .hero-image { flex: 0 1 382px; max-width: 382px; height: auto; }
}

/* 820 — Figma: px-[24px]; Content Container 366px, Image Container 336px.
   header-interactive STACKS here (flex-col gap-16, both children w-full) —
   not the side-by-side row that 1024 and desktop use. */
@media (max-width: 820px) {
  .hero-wrapper { padding: 0 24px; }
  .hero-inner   { gap: 70px; }   /* 820 - 48(padding) - 366(content) - 336(image) */

  /* flex-basis reset to this tier's own target width — left at 1024's 475px,
     only max-width would still technically clamp .hero-content to 366px, but
     the OVERSIZED basis makes the flex shrink algorithm freeze content at its
     max first and dump 100% of any remaining shortfall (e.g. a vertical
     scrollbar's ~15-17px) onto .hero-image alone, since it's the only item
     still flexible at that point. Matching flex-basis to max-width here makes
     both items shrink proportionally instead, keeping .hero-image close to
     its intended 336px even when a scrollbar or rounding eats a few px. */
  .hero-content { flex-basis: 366px; max-width: 366px; gap: 20px; }
  .hero-title   { font-size: 32px; }
  .hero-body    { gap: 20px; }
  .hero-wave    { width: 326px; }

  .hero-interactive { flex-direction: column; align-items: stretch; gap: 16px; }
  .hero-field { width: 100%; }
  .hero-btn   { width: 100%; }

  .hero-image { flex-basis: 336px; max-width: 336px; }
}

/* 768 — delta from 820: smaller content/image boxes; header-interactive
   stays stacked (same as 820). */
@media (max-width: 768px) {
  .hero-section { padding: 32px 0; }
  .hero-inner   { gap: 46px; }   /* 768 - 48(padding) - 360(content) - 314(image) */

  .hero-content { flex-basis: 360px; max-width: 360px; }
  .hero-wave    { width: 290px; }
  .hero-image   { flex-basis: 314px; max-width: 314px; }
}

/* Mobile, down to a 375px reference width — Figma: px-[16px]. Structural
   change: the row layout stacks into a column (content, then the image
   below it), and the field/button/image all go full-width. */
@media (max-width: 767px) {
  .hero-wrapper { padding: 0 16px; }
  .hero-section { padding: 24px 0; }

  /* align-items:stretch (not flex-start) — both stacked children (content,
     image) are meant to be full-width at this tier (Figma has "w-full" on
     both), and stretch is what actually achieves that. flex-start would
     leave .hero-content shrink-wrapped to its own content's natural width
     (its max-width:100% is only a CAP, not a forcing width) — that's what
     was happening before this fix: the description column rendered far
     narrower than the viewport instead of spanning it. */
  .hero-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 32px;
  }
  .hero-content { max-width: 100%; flex-basis: auto; }
  .hero-body    { gap: 16px; }

  .hero-interactive {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
  }
  .hero-field { width: 100%; max-width: none; }
  .hero-btn   { width: 100%; }

  /* .hero-inner is now flex-direction:column, so the main axis flipped to
     vertical — the inherited flex-basis:382px from the <=1024 tier would
     otherwise apply to HEIGHT here instead of width, fighting aspect-ratio.
     Reset it to auto so width:100% + aspect-ratio:1/1 (base rule) produce a
     proper full-width square. */
  .hero-image { flex: 0 0 auto; max-width: none; width: 100%; height: auto; }
}

.howto-section {
  background: var(--white);
  padding: 64px 0;
}

.howto-wrapper {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0 var(--nav-px);  /* matches .hero-wrapper — same section width as hero */
  display: flex;
  flex-direction: column;
  gap: 48px;
  align-items: center;
}

/* ── Section heading ────────────────────────────────────── */
.howto-heading {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
  width: 100%;
  /* side padding now inherited from .howto-wrapper */
}

/* Figma: gradient tint on title — same orange-tint pattern as hero */
.howto-title-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Figma: Red Hat Display Bold 48px/64px */
.howto-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma originally did this as a gradient on the whole title, hard-stopped
   at a fixed 30.758%→56.134% — only lined up with "Praktis" at the exact
   desktop measurements it was computed from (see .hero-highlight for the
   full explanation). Scoping the tint to the word's own <span> keeps it
   glued to "Praktis" at any width or font-size. */
.howto-highlight {
  background: rgba(255,114,3,0.08);
}

/* Figma: Public Sans Regular 16px/24px centered */
.howto-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
  text-align: center;
}

/* ── Cards row ──────────────────────────────────────────── */
.howto-cards {
  display: flex;
  gap: 32px;
  align-items: stretch;
  width: 100%;
}

/* ── Single card ────────────────────────────────────────── */
/* Figma: bg-white rounded-16px overflow-clip p-16px gap-24px
   shadow: 0 0 2px rgba(145,158,171,.2), 0 12px 24px -4px rgba(145,158,171,.12) */
.howto-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 24px;
  flex: 1;
  padding: 16px;
  background: var(--white);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 0 2px rgba(145,158,171,0.2), 0 12px 24px -4px rgba(145,158,171,0.12);
}

/* Figma: big ghost number — absolute bottom-71px right-54px
   translateX(100%) translateY(100%) → mostly clipped by overflow:hidden */
.howto-number {
  position: absolute;
  bottom: 71px;
  right: 54px;
  transform: translateX(100%) translateY(100%);
  font-family: var(--font);
  font-size: 110px;
  font-weight: 800;
  line-height: 80px;
  color: rgba(255,114,3,0.08);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
}

/* ── Icon box ───────────────────────────────────────────── */
/* Figma: size-[100px] relative. Shrinks to the literal 75px Figma value below
   1024px (see responsive block) rather than the old container-query clamp,
   which didn't match Figma's actual 100→75 numbers. */
.howto-icon {
  position: relative;
  width: 100px;
  aspect-ratio: 1 / 1;
  height: auto;
  flex-shrink: 0;
}

.howto-icon-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ── Text block ─────────────────────────────────────────── */
/* Figma: flex flex-col gap-16px items-start justify-center text-[#752f06] */
.howto-text {
  display: flex;
  flex-direction: column;
  gap: 16px;
  justify-content: center;
  flex: 1;
  min-width: 0;
}

/* Figma: Public Sans Bold 24px/36px */
.howto-card-title {
  font-family: var(--font);
  font-size: 24px;
  font-weight: 700;
  line-height: 36px;
  color: #752f06;
}

/* Figma: Public Sans Regular 14px/22px. No line-clamp: the previous 3-line
   clamp only ever fit at the exact 1024 frame width — at every other tier
   (1280, 900, 820, 768, 375) all three descriptions actually need 4-5 lines
   and were getting silently cut mid-sentence. Nothing in .howto-card/.howto-text
   relies on a fixed line count for layout — .howto-cards' align-items:stretch
   already equalizes card heights, so letting text wrap to however many lines
   it needs is safe. */
.howto-card-desc {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: #752f06;
}

/* ── How-to responsive ──────────────────────────────────────
   Four explicit Figma frames — 1296:36403 @1024, 1315:10694 @820,
   1319:38605 @768, 1319:40193 @375 (mobile reference) — but unlike nav/hero,
   values here FLUIDLY interpolate between tiers instead of snapping, via
   clamp(min, calc(min + (100vw - minWidth) * slope), max). Each clamp's
   min/max are literally the two adjacent frames' own numbers, so the value
   still lands exactly on the Figma spec at each frame's exact width — it
   just doesn't jump between them. Structural changes that can't be
   "half column" (card orientation, text-align, font-weight) stay as
   discrete breakpoint switches, same as every other section. */

/* Range A [820–1024]: 1024 frame → 820 frame. Also where the card's
   icon-above-text column layout kicks in (Figma: items-start justify-center
   flex-col), replacing the row layout .howto-card uses above 1024 (that
   desktop row orientation is a pre-existing deviation from Figma, but no
   desktop frame was supplied for this task — left untouched, see plan). */
@media (max-width: 1024px) {
  .howto-wrapper {
    padding: 0 clamp(24px, calc(24px + (100vw - 820px) * 0.078431), 40px);
    gap: 32px;
  }
  .howto-section { padding: 40px 0; }

  .howto-title {
    font-size: clamp(32px, calc(32px + (100vw - 820px) * 0.019608), 36px);
    line-height: 1.5;         /* Figma's own leading-[1.5] token at both ends */
    white-space: nowrap;
  }

  .howto-card { flex-direction: column; align-items: flex-start; justify-content: center; }

  .howto-icon { width: clamp(75px, calc(75px + (100vw - 820px) * 0.122549), 100px); }

  .howto-card-title {
    font-size:   clamp(18px, calc(18px + (100vw - 820px) * 0.009804), 20px);
    line-height: clamp(28px, calc(28px + (100vw - 820px) * 0.009804), 30px);
  }
}

/* Range B [768–820]: only the section's own vertical padding actually
   changes between these two frames — everything else holds its 820-tier
   value flat through 768 (Figma's 768 frame repeats 820's other numbers). */
@media (max-width: 768px) {
  .howto-section { padding: clamp(32px, calc(32px + (100vw - 768px) * 0.153846), 40px) 0; }
}

/* Range C [375–767] (mobile): cards stack into a single column and each
   card flips back to a row (icon left, text right) — Figma's mobile frame
   already matches this project's original row-card markup, so this is the
   *smallest* structural change of any tier. Side padding is pinned to the
   project's established 16px mobile gutter (matching hero/nav) rather than
   this frame's own literal 24px, so section edges stay aligned — see plan's
   Non-goals. */
@media (max-width: 767px) {
  .howto-wrapper { padding: 0 16px; gap: clamp(24px, calc(24px + (100vw - 375px) * 0.020408), 32px); }
  .howto-section { padding: clamp(24px, calc(24px + (100vw - 375px) * 0.020408), 32px) 0; }

  .howto-title {
    font-size: clamp(24px, calc(24px + (100vw - 375px) * 0.020408), 32px);
    white-space: normal;
    text-align: center;
  }
  .howto-subtitle {
    font-size:   clamp(14px, calc(14px + (100vw - 375px) * 0.005102), 16px);
    line-height: clamp(22px, calc(22px + (100vw - 375px) * 0.005102), 24px);
  }

  .howto-cards { flex-direction: column; gap: 16px; }         /* was 32px row gap */
  .howto-card  { flex-direction: row; align-items: center; }  /* flip back from column */

  .howto-card-title {
    font-size:   clamp(16px, calc(16px + (100vw - 375px) * 0.005102), 18px);
    line-height: clamp(24px, calc(24px + (100vw - 375px) * 0.010204), 28px);
    font-weight: 600;   /* Bold(700) → SemiBold(600), a real Figma token change */
  }
  .howto-card-desc {
    font-size:   clamp(12px, calc(12px + (100vw - 375px) * 0.005102), 14px);
    line-height: clamp(18px, calc(18px + (100vw - 375px) * 0.010204), 22px);
  }
  .howto-text { gap: clamp(8px, calc(8px + (100vw - 375px) * 0.020408), 16px); }
}

/* ═══════════════════════════════════════════════════════════
   Feature Section  (Figma nodes 1031:13433 + 1149:16809, merged)
═══════════════════════════════════════════════════════════ */

/* Ambient accent wash — breaks up the flat white behind the pinned stage.
   Deliberately broad and centred rather than hugging one side, since the rows
   alternate which side the collage sits on (see .feature-row:nth-child(even)). */
.feature-section {
  background:
    radial-gradient(70% 55% at 50% 42%, rgba(255,114,3,0.055), transparent 72%),
    var(--white);
  min-height: 100vh;   /* fallback */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  z-index: 0;          /* stays under the sticky .nav-header (z-index:100) when pinned */
}

.feature-wrapper {
  max-width: 80rem;
  margin: 0 auto;
  /* padding: 64px var(--nav-px); */
  display: flex;
  flex-direction: column;
  gap: 40px;
  width: 100%;
}

/* ── Heading (Figma 1031:13433) ─────────────────────────── */
/* Figma: flex-col gap-24px items-start w-[708px], centered within the 1280px row */
.feature-heading {
  display: flex;
  flex-direction: column;
  gap: 24px;
  align-items: flex-start;
  max-width: 708px;
  width: 100%;
  margin: 0 auto;
}

/* Figma: gradient tint on title */
.feature-title-wrap {
  display: flex;
  align-items: center;
}

/* Same fixed-%-gradient-on-the-line issue as .hero-highlight — see there for
   the full explanation. Scoping the tint to "Lengkap" itself instead keeps
   it glued to the word at any width or font-size. */
.feature-highlight {
  background: rgba(255,114,3,0.08);
}

/* Figma: Red Hat Display Bold 48px/64px */
.feature-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma: Public Sans Regular 16px/24px */
.feature-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
}

/* ── Feature stage (holds the scroll-swapped rows) ──────── */
/* Default = plain stacked flow. This is also the no-JS, mobile and
   reduced-motion fallback, so the section still reads correctly if
   GSAP never runs. */
.feature-stage {
  display: flex;
  flex-direction: column;
  gap: 56px;
  width: 100%;
}

/* Slider controls — only exist on the ≤1024px "Open Stage" slider tier (see
   responsive block below). Desktop pins via GSAP instead; the no-JS fallback
   (.feature-stage never gets .is-slider) also never shows them. */
.feature-controls { display: none; }

/* Added by script.js on desktop w/ motion allowed — all rows share
   one grid cell so they can cross-fade in place while pinned. */
.feature-stage.is-stacked { display: grid; gap: 0; }
.feature-stage.is-stacked > .feature-row { grid-area: 1 / 1; }

/* ── Feature row (Figma 1149:16809) ─────────────────────── */
.feature-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  width: 100%;
}

/* Alternate which side the collage sits on. All five rows share one grid cell
   in .is-stacked, so consecutive slides re-stage the composition left→right→left
   instead of only swapping the words. Purely a layout concern — GSAP animates
   opacity/y/scale, never position, so the timeline is unaffected. Reset back to
   a plain column at ≤767 (see the mobile block). */
.feature-row:nth-child(even) { flex-direction: row-reverse; }

/* Text column: highlighter bar + content, stretched to same height */
.feature-content {
  display: flex;
  gap: 16px;
  align-items: stretch;
  flex: 1 1 460px;
  min-width: 0;
  padding-top: 8px;
}

/* .feature-indicator styles now live in their own component:
   assets/components/feature-indicator/feature-indicator.css (linked in index.html <head>) */

.feature-text {
  position: relative;
  isolation: isolate;   /* contains .feature-step's z-index:-1 so it can't drop
                           behind .feature-section's own background */
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-bottom: 16px;
  flex: 1;
  min-width: 0;
}

/* Ghost step marker (01–05) — same recipe as .howto-number above, reused so the
   two sections share one visual language. Out of flow, so it costs the pinned
   stage zero height. It's the first child of .feature-text on purpose: that
   makes script.js's `.feature-text > *` sweep it into the existing crossfade
   stagger with no JS change — it leads the cascade on every slide swap. */
.feature-step {
  position: absolute;
  top: -34px;
  left: -6px;
  z-index: -1;
  font-family: 'Red Hat Display', sans-serif;
  font-size: 110px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: rgba(255,114,3,0.08);
  pointer-events: none;
  user-select: none;
}

/* Figma: Red Hat Display Bold 24px/36px */
.feature-item-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 36px;
  color: #212b36;
}

/* Figma: Public Sans Regular 14px/22px */
.feature-item-desc {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: #212b36;
}

/* Figma: text-button, h-30px px-4px, Public Sans Bold 13px/22px orange */
.feature-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 4px;
  border-radius: var(--btn-radius);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  line-height: 22px;
  color: var(--orange);
  text-decoration: none;
  width: fit-content;
  transition: background 0.15s;
}
.feature-cta:hover { background: rgba(255,114,3,.08); }

.feature-cta-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--orange);
  transition: transform 0.18s ease;
}
/* Arrow leans into the direction of travel on hover — tactile feedback, and
   transform-only so it stays off the main thread. */
.feature-cta:hover .feature-cta-icon { transform: translateX(3px); }

/* Sized closer to the source Figma frame (node 1149:16809: 621×452 — same
   492:358 proportions, just larger) than the previous 450px box. max-width
   doubles as the pin guardrail: height is derived from aspect-ratio
   (h = w × 0.7276), so capping the WIDTH in svh keeps the box from growing
   past what the pinned viewport has room for on a short laptop. Constraining
   width only is deliberate — set both dimensions and aspect-ratio stops doing
   anything. The ≤1024 tiers override max-width with their own literal Figma
   values, so this cap is effectively desktop-only — the only place the
   vh/svh sizing is live alongside the pin.
   Tried capping max-height directly instead and letting aspect-ratio
   "contain" the width (2026-09-14): doesn't work here. This box's width
   comes from `flex: 0 1 820px` on the row's main axis, so flexbox resolves
   width FIRST; aspect-ratio only fills in the still-auto height, and
   max-height then clips that derived height with no feedback path back to
   width. Result was real distortion (measured h/w ratio 0.51-0.59 against a
   0.7276 target at 1366x768/1440x900), visibly squashing the %-positioned
   .feature-layer* children. Don't retry without also decoupling width from
   the flex main-axis resolution.
   No fill, no frame, no shadow — the layers sit directly on the section
   background, matching the Figma reference (floating screenshots, not a
   boxed card). */
.feature-image-box {
  position: relative;
  flex: 0 1 820px;
  max-width: min(820px, 74svh);
  width: 100%;
  aspect-ratio: 492 / 358;   /* unchanged — keeps the Figma proportions at the new size */
  overflow: hidden;
}

.feature-collage {
  position: absolute;
  inset: 0;
  background: none;
}

/* image-rendering hint: these are dense full-app-UI screenshots (small text,
   thin borders) being downscaled a lot into a fairly small box — asks the
   browser to bias its resize filter toward preserving edge contrast rather
   than smoothing, which reads sharper for this kind of source than the
   default. Real fix if it's still not enough is sharper source crops (see
   the project chat for the full breakdown); this is the safe, free part of it. */
.feature-layer {
  position: absolute;
  object-fit: cover;
  border-radius: 8px;
  display: block;
  image-rendering: -webkit-optimize-contrast;
}


.feature-layer-form     { left: 15.85%; top: 8.66%;  width: 46.14%; height: 71.79%; }
.feature-layer-screen   { left: 60.57%; top: 8.66%;  width: 25.81%; height: 86.59%; }
.feature-layer-physical { left: 67.28%; top: 4.94%;  width: 23.37%; height: 11.65%; }
.feature-layer-toast    { left: 24.80%; top: 6.98%;  width: 26.22%; height: 12.28%; }
.feature-layer-variant  { left: 9.35%;  top: 64.39%; width: 24.59%; height: 21.73%; }
.feature-layer-digital  { left: 32.72%; top: 73.67%; width: 30.69%; height: 18.57%; }

.feature-layer2-panel    { left: 20.09%; top: 6.95%;  width: 51.36%; height: 70.78%; }
.feature-layer2-checkout { left: 47.72%; top: 15.34%; width: 22.38%; height: 82.15%; }
.feature-layer2-toggle   { left: 52.97%; top: 2.79%;  width: 26.30%; height: 11.66%; }
.feature-layer2-table    { left: 8.82%;  top: 6.95%;  width: 24.37%; height: 12.72%; }
.feature-layer2-stats    { left: 41.01%; top: 30.29%; width: 50.11%; height: 40.34%; object-fit: contain; } /* Figma: object-contain, not cropped */
.feature-layer2-status   { left: 17.39%; top: 65.11%; width: 18.24%; height: 17.35%; }

/* Figma node 1147:15164 — 3rd feature-image-box collage (store profile /
   storefront preview), percentages against the same 492×358 instance frame. */
.feature-layer3-store     { left: 52.85%; top: 2.80%;  width: 24.39%; height: 81.28%; }
.feature-layer3-biostore  { left: 27.20%; top: 16.94%; width: 27.50%; height: 30.81%; }
.feature-layer3-setting   { left: 18.45%; top: 43.25%; width: 35.91%; height: 53.83%; }
.feature-layer3-toast     { left: 55.97%; top: 70.93%; width: 25.74%; height: 6.64%;  }
.feature-layer3-url       { left: 32.01%; top: 11.22%; width: 35.11%; height: 9.18%;  }

/* Figma node 1148:15602 — 4th feature-image-box collage (shipping/courier
   options), percentages against the same 492×358 instance frame. */
.feature-layer4-panel  { left: 14.63%; top: 10.34%; width: 65.85%; height: 86.87%; }
.feature-layer4-idx    { left: 3.32%;  top: 33.28%; width: 26.77%; height: 10.28%; }
.feature-layer4-sap    { left: 29.55%; top: 31.45%; width: 26.32%; height: 10.81%; }
.feature-layer4-cargo  { left: 54.63%; top: 37.61%; width: 30.61%; height: 10.80%; }
.feature-layer4-order  { left: 41.46%; top: 3.07%;  width: 51.66%; height: 25.30%; }
.feature-layer4-cod    { left: 53.95%; top: 53.11%; width: 42.94%; height: 15.27%; }
.feature-layer4-label  { left: 9.57%;  top: 81.47%; width: 20.19%; height: 14.84%; }

/* Figma node 1149:16801 — 5th feature-image-box collage (payment methods),
   percentages against the same 492×358 instance frame. */
.feature-layer5-payment { left: 18.35%; top: 10.73%; width: 63.98%; height: 86.53%; }
.feature-layer5-summary { left: 49.19%; top: 3.02%;  width: 38.01%; height: 30.35%; }
.feature-layer5-toggle  { left: 10.57%; top: 22.47%; width: 39.43%; height: 16.91%; }
.feature-layer5-bri     { left: 13.96%; top: 42.55%; width: 65.61%; height: 10.14%; }
.feature-layer5-mandiri { left: 20.96%; top: 68.24%; width: 65.77%; height: 13.67%; }
.feature-layer5-qris    { left: 14.50%; top: 77.57%; width: 65.13%; height: 13.53%; }

/* Desktop-only type bump. Scoped to the same 1025px gate script.js uses for the
   GSAP branch, because that's the only tier with vertical slack to spend: the
   row's height is max(text, collage), and the collage is ~327px, so the text
   column can grow to about that before it starts pushing the pinned stage
   taller. The ≤1024 tiers keep their literal Figma sizes. */
@media (min-width: 1025px) {
  .feature-item-title {
    font-size: 30px;
    line-height: 1.25;
    text-wrap: balance;   /* kills orphan words on the longer titles */
  }
}

/* ── Feature responsive: "Open Stage" slider ───────────────────
   Two layouts. >1024 keeps the GSAP pin/crossfade (untouched, above).
   ≤1024 becomes a horizontal one-slide-at-a-time SLIDER: 1024–768 keeps
   content+image side by side (matches the project's own 1024/820/768 tier
   boundaries), ≤767 stacks image-on-top/text-below. Prev/next buttons and a
   "01 / 05" counter replace the .feature-indicator dot rail (hidden at
   these sizes — see feature-indicator.css). No card frame, no shadow, no
   peeking next slide — deliberately distinct from the boxed feature2-card
   slider below it.

   The slide track is native CSS scroll-snap — swipe/trackpad/keyboard
   scrolling need no JS. script.js only wires the buttons, the counter and
   the autoplay timer + its progress ring on the "next" button. Autoplay
   pauses invisibly on hover/touch-hold/keyboard-focus/off-screen/hidden-tab/
   reduced-motion — no visible pause control by design. */
@media (max-width: 1024px) {
  /* Drop the full-viewport min-height (and the vertical centering it was
     driving) for the 1024/820/768 tiers specifically — a plain 40px
     top/bottom padding on the section replaces it. Mobile (≤767, below)
     explicitly keeps the vh/svh sizing, so it's restored there. */
  .feature-section { min-height: 0; padding: 40px 0; }

  .feature-wrapper { padding: 0 40px; gap: 32px; }       /* was 64px var(--nav-px); vertical now lives on .feature-section above */

  /* Figma centres the heading at these tiers (title via justify-center on
     its wrap, subtitle via text-center) even though the outer block stays
     items-start — see node 1296:36707. Base .feature-heading is
     align-items:flex-start (left-aligned, the desktop look), so override. */
  .feature-heading { align-items: center; }
  .feature-title   { font-size: 36px; line-height: 1.5; white-space: nowrap; text-align: center; }
  .feature-subtitle{ text-align: center; }

  /* ── Track ── native scroll-snap strip, one slide = one .feature-row */
  .feature-stage.is-slider {
    position: relative;
    display: flex;
    flex-direction: row;
    gap: 24px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .feature-stage.is-slider::-webkit-scrollbar { display: none; }
  .feature-stage.is-slider > .feature-row {
    flex: 0 0 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;   /* one card per swipe/flick, like Apple's own
                                   media-card-gallery — a fast swipe can't
                                   sail past multiple slides in one gesture */
  }

  /* Kill desktop's row-reverse alternation and the collage/text vertical
     centering — every slide reads the same direction on the slider.
     Ungated (not scoped to .is-slider) so the no-JS stacked fallback also
     gets the slider's row layout instead of the desktop alternation. */
  .feature-row,
  .feature-row:nth-child(even) { flex-direction: row; align-items: center; gap: 40px; }

  /* ── Tile ── quiet tinted surface behind the screenshots, NOT the
     saturated feature2-card gradient — keeps the two sliders visually
     distinct. content-box so `inset: var(--tile-pad)` on .feature-collage
     keeps the %-positioned layers at their exact Figma proportions (a
     border-box + padding would shrink the box aspect-ratio resolves against
     — see CLAUDE.md's aspect-ratio gotcha). */
  .feature-image-box {
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
    box-sizing: content-box;
    --tile-pad: 24px;
    padding: var(--tile-pad);
    border-radius: 16px;
    background: linear-gradient(180deg, rgba(255,114,3,0.07), rgba(255,114,3,0.03)), var(--white);
    box-shadow: inset 0 0 0 1px rgba(255,114,3,0.12);
  }
  .feature-collage { inset: var(--tile-pad); }

  .feature-content {
    flex: 1 1 0;
    min-width: 0;
    padding-top: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0;
  }
  .feature-text { gap: 12px; padding-bottom: 0; }
  .feature-item-title { font-size: 22px; line-height: 32px; text-wrap: balance; }
  .feature-item-desc  { font-size: 14px; line-height: 22px; max-width: 60ch; text-wrap: pretty; }
  .feature-step        { font-size: 88px; top: -28px; left: 0; }   /* left:0, not the desktop -6px bleed — that negative
                                                                        offset pokes past .feature-stage's own overflow-x:auto
                                                                        edge and gets its left stroke clipped */

  /* ── Controls row ── counter left, buttons right. Prev/next are outlined
     circles (the strongest visual weight here is the slide's own orange CTA
     link, not the chrome around it). */
  .feature-controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin-top: -8px;
  }
  .feature-counter {
    font-family: 'Red Hat Display', sans-serif;
    font-weight: 700;
    font-size: 18px;
    font-variant-numeric: tabular-nums;
    color: var(--text);
  }
  .feature-counter-sep,
  .feature-counter-total { color: rgba(33,43,54,0.4); }

  .feature-nav { display: flex; align-items: center; gap: 12px; }

  .feature-nav-btn {
    position: relative;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;
    border: 1px solid rgba(145,158,171,0.32);
    border-radius: 50%;
    background: var(--white);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.2s cubic-bezier(.16,1,.3,1), border-color 0.2s;
  }
  .feature-nav-btn:active { transform: scale(0.94); }
  .feature-nav-btn:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
  .feature-nav-btn img { width: 24px; height: 24px; display: block; }

  /* Autoplay progress ring — a thin arc on the "next" button that fills over
     the auto-advance cycle, so the (invisible-pause) timer is still visible
     rather than a surprise. Only drawn while autoplay is actually armed. */
  .feature-nav-ring {
    position: absolute;
    inset: -1px;
    width: calc(100% + 2px);
    height: calc(100% + 2px);
    transform: rotate(-90deg);
    pointer-events: none;
  }
  .feature-nav-ring circle {
    fill: none;
    stroke: var(--orange);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-dasharray: 138.23;   /* 2 * PI * 22 */
    stroke-dashoffset: 138.23;
  }
  .feature-controls.is-autoplaying .feature-nav-ring circle {
    animation: feature-ring var(--feature-auto-ms, 5000ms) linear forwards;
  }
  @keyframes feature-ring { to { stroke-dashoffset: 0; } }
}

@media (max-width: 820px) {
  .feature-wrapper { padding: 0 24px; }     /* vertical stays the flat 40px set at ≤1024 */
  .feature-title   { font-size: 32px; }
}

/* Only ≤767 stacks image-on-top / text-below — 1024 down through 768 stays
   side-by-side via the block above (the project's own 1024/820/768 tiers). */
@media (max-width: 767px) {
  /* Mobile keeps the vh/svh full-viewport sizing the ≤1024 tier above just
     turned off — restore it here since this rule is later in the cascade. */
  .feature-section { min-height: 100vh; min-height: 100svh; padding: 0; }

  .feature-wrapper { padding: 24px 16px; gap: 24px; }
  .feature-heading { max-width: 100%; align-items: center; }   /* base 708px cap would overflow a narrow phone; base align-items:flex-start left-anchors both children instead of centering the block, unlike Figma's centered mobile heading */
  .feature-title   { font-size: 24px; white-space: normal; text-align: center; }
  .feature-subtitle{ font-size: 14px; line-height: 22px; text-align: center; }

  /* No max-width cap here (unlike feature2-grid's slider): .feature-stage
     carries no horizontal padding of its own — .feature-image-box's tile
     padding lives on the CHILD, not the scroll container — so a
     `flex: 0 0 100%` row already resolves against the stage's true
     border-box width with no reserved-but-not-clipped space to cause a
     peek. The card/tile can just follow .feature-wrapper's full width. */
  .feature-stage.is-slider { gap: 16px; }

  .feature-row,
  .feature-row:nth-child(even) { flex-direction: column; align-items: stretch; gap: 20px; }

  /* Explicit resets so the row→column flip can't turn either child's
     flex-basis into a height target (the flex-basis axis-flip gotcha —
     see CLAUDE.md). */
  .feature-image-box {
    flex: 0 0 auto;
    --tile-pad: 16px;
    order: -1;   /* .feature-content is first in the DOM (it needs to read/reach
     first for screen readers and the side-by-side tiers above), but the
     requirement here is image-on-top: flip the VISUAL order only, content
     unchanged. */
    /* At ≤1024 (901–767, above) .feature-image-box gets its width from
       `flex: 1 1 0` — the flex algorithm distributes space against the
       item's OUTER (border-box) size regardless of box-sizing, so padding
       is naturally absorbed. Here `flex: 0 0 auto` opts the item OUT of
       that distribution, so it falls back to the plain `width: 100%`
       inherited from the base rule — and since this box is deliberately
       box-sizing:content-box (so .feature-collage's `inset: var(--tile-pad)`
       keeps the %-positioned layers at their exact Figma proportions),
       `width: 100%` sets the CONTENT to 100% and then adds the tile's own
       padding ON TOP, overflowing past .feature-wrapper by 2×--tile-pad.
       Subtract the padding back out explicitly so it still fills the row
       edge-to-edge without escaping it. */
    width: calc(100% - (var(--tile-pad) * 2));
  }
  .feature-content   { flex: 0 0 auto; justify-content: flex-start; align-items: center; }

  /* Image-on-top / text-below reads better centered than left-anchored —
     matches feature2's own mobile card (centered icon, centered-under text). */
  .feature-text { align-items: center; }
  .feature-item-title,
  .feature-item-desc { text-align: center; }
  .feature-item-title { font-size: 20px; line-height: 28px; }
  .feature-step { font-size: 56px; top: -8px; left: 50%; transform: translateX(-50%); }   /* re-centered now the text block itself is centered */

  .feature-nav { gap: 8px; }
}

/* ═══════════════════════════════════════════════════════════
   Feature 2 Section  (Figma node 1041:32886)
   Static 2×2 illustrated card grid — no GSAP/pin involved.
   Namespaced feature2-* to avoid colliding with the pinned
   .feature-* classes above.
═══════════════════════════════════════════════════════════ */

.feature2-section {
  background: var(--white);
  padding: 64px 0;
}

.feature2-wrapper {
  max-width: 80rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 48px;
}

/* Groups .feature2-grid + .feature2-nav under one flex column, gap:0 — the
   .feature2-wrapper gap (48/32/24/24px per tier) now only spaces the
   heading from this block as a whole; any spacing between the grid and the
   nav row within it comes from .feature2-grid's own bottom padding
   (shadow headroom), not a gap here. */
.feature2-body {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* ── Heading ────────────────────────────────────────────── */
.feature2-heading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  max-width: 708px;
  width: 100%;
  margin: 0 auto;
  padding: 0 var(--nav-px);
}

.feature2-title-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.feature2-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma originally did this as a gradient on the whole title, hard-stopped
   at a fixed 67.02%→90.605% — only lined up with "Mudah" at the exact
   desktop measurements it was computed from (see .hero-highlight for the
   full explanation). Scoping the tint to the word's own <span> keeps it
   glued to "Mudah" at any width or font-size. */
.feature2-highlight {
  background: rgba(255,114,3,0.08);
}

.feature2-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
  text-align: center;
}

/* ── Card grid ──────────────────────────────────────────── */
.feature2-grid {
  position: relative;          /* offsetParent for the slider's card.offsetLeft maths */
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 0 var(--nav-px);   /* right inset dropped again at the ≤900px slider tier — see that block */
}

/* Slider controls — only exist on the ≤900px slider tier (see responsive
   block). .feature2-cta now lives INSIDE .feature2-nav (CTA left, arrows
   right, same row), so hiding the nav hides the CTA with it — no separate
   selector needed. */
.feature2-nav { display: none; padding: 0 var(--nav-px); }

.feature2-row {
  display: flex;
  gap: 32px;
  width: 100%;
}

/* Figma's asymmetric fixed+flex widths, preserved via flex-basis rather than
   forcing equal columns */
.feature2-card--import { flex: 0 0 585px; }
.feature2-card--field  { flex: 1 1 0; min-width: 0; }
.feature2-card--order  { flex: 0 0 645px; }
.feature2-card--voucher{ flex: 1 1 0; min-width: 0; }

/* Figma: overflow-clip rounded-16px, shadow/card token, radial warm-peach gradient
   (exact Figma value, shared across all 4 cards — the per-card gradients in Figma
   differ only by a few px of center offset, imperceptible at this scale) */
.feature2-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 24px;
  height: 282px;
  padding: 16px;
  border-radius: 16px;
  overflow: hidden;
  background: radial-gradient(427.79% 148.92% at 22.31% 35.46%, #FFF 0%, #FEF0E7 54.73%, #FECCAC 100%);
  container-type: inline-size;   /* lets .feature2-icon size relative to card width */
  container-name: feature2-card;
  transition: transform 0.28s ease, box-shadow 0.28s ease;
}

/* hover:hover + pointer:fine = a device that can genuinely hover (mouse/
   trackpad), not a tap. Touch-only devices report hover:none, so the reveal/
   lift never triggers — and never gets stuck "on" after a tap the way plain
   :hover would. */
@media (hover: hover) and (pointer: fine) {
  .feature2-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 4px 8px rgba(145,158,171,0.24), 0 20px 32px -4px rgba(145,158,171,0.18);
  }
}

/* Shared decorative flourish — natural aspect ratio already ~matches card height,
   so no stretching; sits behind the icon, clipped by the card's overflow:hidden */
.feature2-bubbling {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: auto;
  z-index: 0;
  pointer-events: none;
}

/* Icon — dynamic, not pixel-fixed: scales with the card's own width via container
   query, capped at Figma's 250px on wide cards, floored at 120px on narrow ones.
   Now a .webp raster export (shadow baked into the pixels at export time) instead
   of the old SVG — the CSS drop-shadow workaround for the SVGs' own blurry
   filter-based shadows no longer applies and has been removed. */
.feature2-icon {
  position: relative;
  z-index: 1;
  width: clamp(120px, 40cqw, 250px);
  aspect-ratio: 1 / 1;
  height: auto;
  object-fit: contain;
  flex-shrink: 0;
  transition: transform 0.28s ease;
}

@media (hover: hover) and (pointer: fine) {
  .feature2-card:hover .feature2-icon {
    transform: scale(1.06);
  }
}

.feature2-text {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  color: #752f06;
  flex: 1;
  min-width: 0;
}

/* Figma: Public Sans BOLD 24px/36px — NOT Red Hat Display, unlike .feature-item-title */
.feature2-card-title {
  font-family: var(--font);
  font-size: 24px;
  font-weight: 700;
  line-height: 36px;
  color: #752f06;
}

.feature2-card-desc {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: #752f06;
}

/* ── Feature 2 responsive ───────────────────────────────────
   Two layouts. >900px keeps the 2×2 grid (Figma 1440 / 1024 frames).
   ≤900px becomes a horizontal one-card-at-a-time SLIDER with the next card
   peeking at the right edge, arrow buttons + CTA beneath (Figma touch
   frames 820 = 1376:15749, 768 = 1376:12647, 375 = 1319:40313; the 820
   design is applied all the way up to 900, matching the nav drawer's
   breakpoint). 768 is identical to 820; 375 shrinks the card and flips it
   vertical (250px icon on top).

   The slider is a native CSS scroll-snap strip — swipe/trackpad/keyboard
   scrolling need no JS at all; script.js only wires the two arrow buttons.
─────────────────────────────────────────────────────────── */

/* Landscape tablet — Figma 1024 frame */
@media (max-width: 1024px) {
  .feature2-section { padding: 40px 0; }
  .feature2-wrapper { gap: 32px; }
  .feature2-heading { padding: 0 40px; }
  .feature2-grid { padding: 0 40px; }
  .feature2-nav { padding: 0 40px; }

  .feature2-title { font-size: 36px; line-height: 48px; white-space: normal; }

  /* Figma drops the asymmetric widths here — all four cards go equal */
  .feature2-card--import,
  .feature2-card--order { flex: 1 1 0; }

  .feature2-card { height: auto; }
  .feature2-icon { width: 200px; }          /* fixed, not the container-query clamp */
  .feature2-card-title { font-size: 20px; line-height: 30px; }
}

/* Slider tier — Figma 820 frame (and 768, which is identical), applied ≤900.
   Gutter is the frame's own 24px; note nav/hero still sit at 40px between
   821–900, so section edges are 16px off there — deliberate, per the frame. */
@media (max-width: 900px) {
  .feature2-section { padding: 32px 0; }
  .feature2-wrapper { gap: 24px; }
  .feature2-heading { padding: 0 24px; }
  .feature2-grid { padding-left: 24px; padding-right: 24px; }   /* right inset dropped: lets the next card peek past the viewport edge */
  .feature2-nav { padding: 0 24px; }

  .feature2-title { font-size: 32px; line-height: 48px; }

  /* The two desktop rows dissolve so all four cards become direct flex
     items of the track (no markup change; desktop still needs the rows for
     its asymmetric 585/645 bases). */
  .feature2-row { display: contents; }

  /* The grid becomes the scroll-snap track. `overflow-x:auto` forces the
     vertical axis to clip too, so pad the block axis to leave room for the
     card's static shadow (touch devices never trigger the hover lift — that
     rule is gated behind hover:hover+pointer:fine — so only the resting
     `0 12px 24px -4px` shadow needs headroom, ~28px).
     NOTE: this used to also carry a `margin-block: -8px -40px` to cancel
     that padding back out of the page's flow height. Don't do that: a
     negative bottom margin only shrinks how much space THIS box reserves
     for the NEXT sibling — it does not move this box's own border/padding
     edge, which still paints at its full (padded) size. The result was
     `.feature2-nav` starting to lay out 40px above where `.feature2-grid`
     visually ends, so the two literally overlapped. The padding below is
     now real, uncancelled flow space — a slightly bigger gap before the
     controls row, but no overlap. */
  /* .feature2-grid carries its own padding-left (the scroll container's own
     box-padding, not the wrapper's) so the snap algorithm must be told about
     it explicitly: without scroll-padding-inline-start, Chrome auto-scrolls
     past that padding on load to snap the first card flush to the scrollport
     edge (scrollLeft lands on 24, not 0), silently eating the left gutter. */
  .feature2-grid {
    flex-direction: row;
    gap: 32px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: 24px;
    padding-block: 4px 28px;
    scrollbar-width: none;
  }
  .feature2-grid::-webkit-scrollbar { display: none; }

  /* Figma: 600px card, horizontal (200px icon left, text right), shadow/card.
     The `100% − 23px` guard keeps a 23px peek of the next card on any
     viewport narrower than the card itself. Track's default
     align-items:stretch = equal-height cards (Figma's self-stretch). */
  .feature2-card,
  .feature2-card--import,
  .feature2-card--field,
  .feature2-card--order,
  .feature2-card--voucher {
    flex: 0 0 min(600px, calc(100% - 23px));
  }
  .feature2-card {
    scroll-snap-align: start;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    min-height: 0;
    height: auto;
    box-shadow: 0 0 2px rgba(145,158,171,0.2), 0 12px 24px -4px rgba(145,158,171,0.12);
  }

  /* Control row — CTA left, arrows right. Same shape/sizing as
     .feature-section's own .feature-controls above (the two sliders read as
     one consistent control system): 48px bordered circles, 12px gap. */
  .feature2-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
  }
  .feature2-arrows { display: flex; align-items: center; gap: 12px; }
  .feature2-arrow {
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;
    border: 1px solid rgba(145,158,171,0.32);
    border-radius: 50%;
    background: var(--white);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.2s cubic-bezier(.16,1,.3,1), border-color 0.2s;
  }
  .feature2-arrow:active { transform: scale(0.94); }
  .feature2-arrow img {
    width: 24px;
    height: 24px;
    display: block;
  }
  .feature2-arrow:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

  /* CTA — same button as the CTA section, fixed 160px wide per Figma; a
     normal flex child of .feature2-nav (left slot) rather than its own
     centered row below the arrows. .cta-btn-primary already sets its own
     display:inline-flex, so only the width needs overriding here. */
  .feature2-nav > .feature2-cta { width: 160px; }
}

/* Mobile (375 reference) — same slider, card shrinks to 320px and flips
   top-and-bottom (250px centred icon, left-aligned text below). */
@media (max-width: 767px) {
  .feature2-section { padding: 24px 0; }
  .feature2-wrapper { gap: 24px; }
  .feature2-heading { padding: 0 16px; }
  .feature2-grid { padding-left: 16px; padding-right: 16px; scroll-padding-inline-start: 16px; }
  .feature2-nav { padding: 0 16px; }

  .feature2-title { font-size: 24px; line-height: 36px; }
  .feature2-subtitle { font-size: 14px; line-height: 22px; }

  .feature2-grid { gap: 16px; }

  .feature2-card,
  .feature2-card--import,
  .feature2-card--field,
  .feature2-card--order,
  .feature2-card--voucher {
    flex: 0 0 min(320px, calc(100% - 23px));
  }
  .feature2-card {
    flex-direction: column;   /* icon on top, text below */
    align-items: center;      /* centres the icon; text block stays full-width/left via .feature2-text{width:100%} */
  }
  .feature2-text { width: 100%; }
  .feature2-icon { width: 250px; max-width: 100%; }
  .feature2-card-title { font-size: 16px; line-height: 24px; font-weight: 600; }
  .feature2-card-desc { font-size: 12px; line-height: 18px; }

  /* Arrow/button sizing stays the same 48px as ≤900 — one size at every
     slider tier, matching .feature-controls. Only the CTA narrows. */
  .feature2-nav > .feature2-cta { width: 145px; }
}

/* ═══════════════════════════════════════════════════════════
   Why It Section  (Figma node 1145:11661)
   Left: image column — intentionally left as a blank placeholder box.
   Right: heading + 4-item checklist with dividers.
═══════════════════════════════════════════════════════════ */

.whyit-section {
  background: var(--white);
  padding: 64px 0;
}

.whyit-wrapper {
  max-width: 80rem;
  margin: 0 auto;   /* no self padding — matches .nav-wrapper pattern */
}

.whyit-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  padding: 0 var(--nav-px);
  width: 100%;
}

/* ── Left: blank image placeholder ─────────────────────── */
/* Figma: w-590 h-634 — sized dynamically (flex + max-width + aspect-ratio)
   rather than pixel-fixed, per project convention. Image content intentionally
   left unimplemented — plain placeholder box for now. */
.whyit-image-box {
  position: relative;
  flex: 0 1 500px;
  max-width: 500px;
  width: 100%;
  aspect-ratio: 590 / 634;   /* unchanged — keeps the original proportions at the new width */
  border-radius: 16px;
  overflow: hidden;
}

/* Position/size taken from Figma node 1241:10778's main photo layer — actual
   layer size is 524×588 (confirmed in Figma inspect), converted to % of the
   590×634 root; position (left/top) unchanged from the inset-chain calc since
   this layer isn't clipped by its parent. 524/588 ≈ 0.891 matches the source
   photo's native aspect (2096/2353 ≈ 0.891) almost exactly, so cover/contain
   now produce effectively the same result — decorative circle, badges and
   icons from that design are intentionally NOT implemented. */
.whyit-img {
  position: absolute;
  z-index: 1;         /* sits above the background ornaments */
  left: 3.61%;
  top: 3.25%;
  width: 88.81%;    /* 524 / 590 */
  height: 92.74%;   /* 588 / 634 */
  object-fit: cover;
  object-position: center top;
  display: block;
}

/* Background ornaments — Figma: two Vector layers, both exactly 388×388px
   (65.76% × 61.20% of the 590×634 root), same asset placed twice unscaled */
.whyit-bubbling {
  position: absolute;
  z-index: 0;
  width: 65.76%;
  height: 61.20%;
  pointer-events: none;
  transform-origin: center;

  /* Rest state = pre-reveal (Figma t=0: opacity 0, scale 1) */
  opacity: 0;
  transform: scale(1);
}

.whyit-bubbling-1 { left: 34.25%; top: 37.47%; }  /* Figma node 1241:10779 */
.whyit-bubbling-2 { left: 0.17%;  top: 3.23%;  }  /* Figma node 1241:10780 */

/* Reveal / dissolve — translated from the Figma motion export at
   assets/components/whyit-bubbling/whyit-bubbling.motion.json (node
   1241:10779; same timing applied to both bubbling instances).

   Triggered via JS class toggling (script.js) rather than :hover directly —
   relying on `:hover` removal to hand off from an animation-held value to a
   `transition` is unreliable across browsers (transitions don't consistently
   pick up smoothly from a value an animation was holding via
   fill-mode:forwards), which is why the mouse-leave dissolve wasn't smooth.
   Swapping animation-name via a class change restarts reliably everywhere. */

/* Reveal — runs once on hover-in (not looped, overriding Figma's own
   playbackStyle:"loop" — this is a hover reveal, not a continuous loop),
   holds its final state (opacity 1, scale 1) while still hovered. */
.whyit-image-box.is-hovering .whyit-bubbling {
  animation:
    whyit-bubbling-fade  2448.046ms linear forwards,
    whyit-bubbling-scale 2448.046ms linear forwards;
}

@keyframes whyit-bubbling-fade {
  0%      { opacity: 0; }                                                     /* 0→200ms: held at 0 */
  8.17%   { opacity: 0; animation-timing-function: cubic-bezier(0.5,0,0.2,1); } /* 200→900ms: fade in */
  36.76%  { opacity: 1; }                                                     /* 900ms→end: held at 1 */
  100%    { opacity: 1; }
}

@keyframes whyit-bubbling-scale {
  0%      { transform: scale(1);   animation-timing-function: cubic-bezier(0.5,0,0.2,1); } /* 0→900ms: pop up */
  36.76%  { transform: scale(1.2); }                                          /* 900→1400ms: held at 1.2 */
  57.19%  { transform: scale(1.2); animation-timing-function: cubic-bezier(0.8,0,0.5,1); }  /* 1400→2300ms: settle */
  93.95%  { transform: scale(1);   }                                          /* 2300ms→end: held at 1 */
  100%    { transform: scale(1);   }
}

/* Dissolve — the reveal's first ~900ms fade, played as a fade-out (opacity
   1→0), reusing the "settle" curve reversed. Fires on mouse-leave. */
.whyit-image-box.is-leaving .whyit-bubbling {
  animation: whyit-bubbling-dissolve 700ms cubic-bezier(0.8,0,0.5,1) forwards;
}

@keyframes whyit-bubbling-dissolve {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* Floating icon badges — Figma: 3 "Icon Container" layers (1241:10785 cart,
   1241:10787 bag, 1241:10789 shield-check), each ~98×98px visually. Local
   assets (assets/img/whyit/*.webp, 523×523) are 4x that, same aspect as the
   SVGs they replaced, so the sizing math below is unchanged — box size is
   still derived from the original 131×131 SVG export (which included
   drop-shadow bleed), and each asset is centered on Figma's inset-box
   midpoint rather than matching raw edges, so the bleed margin doesn't shift
   the visual card off-target. */
.whyit-icon {
  position: absolute;
  z-index: 2;   /* above the photo */
  width: 22.20%;    /* 131 / 590 */
  height: 20.66%;   /* 131 / 634 */
  pointer-events: none;
}

.whyit-icon-bag    { left: 18.47%; top: 11.37%; }  /* Figma node 1241:10787 */
.whyit-icon-cart   { left: 5.88%;  top: 71.38%; }  /* Figma node 1241:10785 */
.whyit-icon-shield { left: 71.79%; top: 63.33%; }  /* Figma node 1241:10789 */

/* Hover-in bounce — reuses the same .is-hovering trigger the bubbling
   ornaments use (toggled in script.js), one-shot per hover-enter, staggered
   per icon for a playful cascading pop instead of all three moving at once. */
.whyit-image-box.is-hovering .whyit-icon-bag    { animation: whyit-icon-bounce 0.6s ease-out; animation-delay: 0ms; }
.whyit-image-box.is-hovering .whyit-icon-cart   { animation: whyit-icon-bounce 0.6s ease-out; animation-delay: 100ms; }
.whyit-image-box.is-hovering .whyit-icon-shield { animation: whyit-icon-bounce 0.6s ease-out; animation-delay: 200ms; }

@keyframes whyit-icon-bounce {
  0%   { transform: translateY(0)    scale(1);    }
  30%  { transform: translateY(-8px) scale(1.08); }
  60%  { transform: translateY(2px)  scale(0.98); }
  100% { transform: translateY(0)    scale(1);    }
}

/* ── Right: heading + checklist ─────────────────────────── */
.whyit-content {
  flex: 0 1 578px;   /* was 1 1 480px — grow disabled so it doesn't absorb the space the image-box resize freed up */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.whyit-heading {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  width: 100%;
}

.whyit-title-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
}

.whyit-title-highlight {
  display: flex;
  align-items: center;
}

.whyit-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma originally did this as a gradient on the whole title, hard-stopped
   at a fixed 65.762%→91.234% — only lined up with "Serius" at the exact
   desktop measurements it was computed from (see .hero-highlight for the
   full explanation). Scoping the tint to the word's own <span> keeps it
   glued to "Serius" at any width or font-size. */
.whyit-highlight {
  background: rgba(255,114,3,0.08);
}

.whyit-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
}

.whyit-list {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.whyit-item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 0;
  width: 100%;
}

.whyit-item-header {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
}

.whyit-check-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}

/* Figma: Public Sans Bold 18px/28px */
.whyit-item-title {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 700;
  line-height: 28px;
  color: #212b36;
  flex: 1;
}

/* Figma: pl-40px = 24px icon + 16px gap, aligns under the title text */
.whyit-item-desc {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
  padding-left: 40px;
}

.whyit-divider {
  height: 1px;
  width: 100%;
  background: rgba(145,158,171,0.2);
  flex-shrink: 0;
}

/* ── Why It responsive ──────────────────────────────────────
   Four explicit Figma frames (1024 / 820 / 768 / 375). Side-by-side at 1024,
   then stacked (image on top, heading centred) at every tier below.
   Shared 40 / 24 / 24 / 16 horizontal gutter, like the other sections.
─────────────────────────────────────────────────────────── */

/* Landscape tablet — Figma 1024 frame: still image ∥ text */
@media (max-width: 1024px) {
  .whyit-section { padding: 40px 0; }
  .whyit-inner { gap: 24px; padding-left: 40px; padding-right: 40px; }

  .whyit-image-box { flex: 1 1 0; max-width: none; }   /* grows to fill the row */
  .whyit-content   { flex: 0 0 460px; gap: 24px; }

  .whyit-title      { font-size: 36px; line-height: 1.5; white-space: normal; }
  .whyit-item-title { font-size: 20px; line-height: 30px; }
  .whyit-item-desc  { font-size: 14px; line-height: 22px; }
}

/* Portrait tablet — Figma 820 frame: stacked, heading centred */
@media (max-width: 820px) {
  .whyit-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 24px;
    padding-left: 24px;
    padding-right: 24px;
  }

  /* Explicit flex so the basis doesn't flip to a height target in the column */
  .whyit-image-box { flex: 0 0 auto; max-width: 519px; width: 100%; margin: 0 auto; }
  .whyit-content   { flex: 0 0 auto; width: 100%; }

  .whyit-heading    { align-items: center; gap: 16px; }
  .whyit-title-wrap { align-items: center; }
  .whyit-title      { font-size: 32px; text-align: center; }
  .whyit-subtitle   { text-align: center; }
  .whyit-item-title { font-size: 18px; line-height: 28px; }
}

/* Small tablet — Figma 768 frame: identical to 820 bar the section padding */
@media (max-width: 768px) {
  .whyit-section { padding: 32px 0; }
}

/* Mobile (375 reference) */
@media (max-width: 767px) {
  .whyit-section { padding: 24px 0; }
  .whyit-inner { padding-left: 16px; padding-right: 16px; }

  .whyit-title      { font-size: 24px; }
  .whyit-subtitle   { font-size: 14px; line-height: 22px; }
  .whyit-item-title { font-size: 16px; line-height: 24px; font-weight: 600; }
  .whyit-item-desc  { font-size: 12px; line-height: 18px; }
}

/* ═══════════════════════════════════════════════════════════
   FAQ Section  (Figma node 1121:13170)
═══════════════════════════════════════════════════════════ */

.faq-section {
  background: var(--white);
  padding: 64px 0;
  /* .faq-dots is anchored to the section's bottom-left and, on narrow
     viewports, runs past the right edge (Figma lets it bleed). `clip` on the
     x-axis contains that bleed without forcing a y-axis scroll container, so
     the dots can still sit flush at the true bottom edge. */
  overflow-x: clip;
}

.faq-wrapper {
  position: relative;   /* positioning root for .faq-dots */
  max-width: 80rem;
  margin: 0 auto;   /* no self padding — matches .nav-wrapper pattern */
}

.faq-inner {
  position: relative;
  z-index: 1;   /* keeps the content above .faq-dots, which follows it in the DOM */
  display: flex;
  align-items: flex-start;
  gap: 88px;
  padding: 0 var(--nav-px);
  width: 100%;
}

/* ── Left: heading ──────────────────────────────────────── */
.faq-header {
  flex: 0 1 584px;
  max-width: 584px;
  width: 100%;
}

.faq-heading {
  display: flex;
  flex-direction: column;
  gap: 24px;
  align-items: flex-start;
  width: 100%;
}

.faq-title-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
  width: 100%;
}

/* squiggle removed — Figma's Vector 32 is hidden in every FAQ frame */

.faq-title-highlight {
  display: flex;
  align-items: center;
}

.faq-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
}

/* Figma originally did this as a gradient on the whole title, hard-stopped
   at a fixed 20.377%→47.258% — only lined up with "Sering" at the exact
   desktop measurements it was computed from (see .hero-highlight for the
   full explanation). Scoping the tint to the word's own <span> keeps it
   glued to "Sering" at any width or font-size. */
.faq-highlight {
  background: rgba(255,114,3,0.08);
}

.faq-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
}

/* Decorative dot cluster — Figma node 529:65022 "Frame 2087325911", downloaded
   directly from Figma CDN to assets/vector/faq/frame-dots.svg (415×193 native,
   matching the frame exactly — no object-fit compensation needed).

   Position — Figma sits this flush at the very bottom of the section, past
   its own bottom padding. Positioned against .faq-wrapper (not .faq-inner,
   whose height is dynamic/content-driven) so the horizontal alignment still
   matches the content area, with bottom:-64px deliberately breaking past
   .faq-section's own 64px bottom padding to reach the section's true edge —
   an absolutely positioned child normally stops at the padding edge, so this
   negative offset is what makes it "ignore" that padding. */
.faq-dots {
  position: absolute;
  z-index: 0;      /* sits behind .faq-inner (see its z-index) */
  left: 85px;    /* 165 - 80, converting Figma's 80px section padding to our 32px scheme */
  bottom: -64px;   /* cancels out .faq-section's padding-bottom: 64px */
  width: 415px;
  height: 193px;
  pointer-events: none;
}

/* ── Right: accordion list ─────────────────────────────── */
.faq-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1;
  min-width: 0;
}

/* Figma: widget/acordion/faq — border rgba(145,158,171,.32), shadow/card token,
   rounded-8px, px-16 py-8 */
.faq-item {
  width: 100%;
  border: 1px solid rgba(145,158,171,0.32);
  border-radius: 8px;
  box-shadow: 0 0 1px rgba(145,158,171,0.2), 0 12px 12px rgba(145,158,171,0.12);
  background: var(--white);
  padding: 8px 16px;
}

.faq-item-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  cursor: pointer;
  list-style: none;
}
.faq-item-summary::-webkit-details-marker { display: none; }

/* Figma: Red Hat Display Bold 24px/36px */
.faq-item-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 36px;
  color: #212b36;
  flex: 1;
  min-width: 0;
}

/* Figma: IconButton — 40px circular hit-area, 24px chevron centered */
.faq-item-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 500px;
  flex-shrink: 0;
}
.faq-item-toggle svg {
  width: 24px;
  height: 24px;
  transition: transform 0.2s;
}
/* Closed: chevron points right. Open: rotated to point up (Figma uses two
   different icon assets for these two states — reproduced with one icon + rotation) */
details[open] > .faq-item-summary .faq-item-toggle svg {
  transform: rotate(-90deg);
}

.faq-item-divider {
  height: 1px;
  width: 100%;
  background: rgba(145,158,171,0.2);
  margin: 16px 0;
}

/* Figma: Public Sans Regular 14px/22px */
.faq-item-answer {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: #212b36;
  padding-bottom: 8px;
}

/* ── FAQ responsive ────────────────────────────────────────
   Four Figma frames (1024 / 820 / 768 / 375). Below the >1024 base the
   2-column split collapses: header stacks on top, centred, accordion
   full-width beneath. 820 & 768 differ only in section padding.
   Shared 40 / 24 / 24 / 16 horizontal gutter.
─────────────────────────────────────────────────────────── */

/* Landscape tablet — Figma 1024 frame: header stacks, centred */
@media (max-width: 1024px) {
  .faq-section { padding: 40px 0; }

  .faq-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 32px;
    padding-left: 40px;
    padding-right: 40px;
  }

  .faq-header      { flex: 0 0 auto; max-width: none; width: 100%; }
  .faq-heading     { align-items: center; gap: 24px; }
  .faq-title-block { align-items: center; max-width: 584px; }
  .faq-title       { font-size: 36px; line-height: 1.5; text-align: center; white-space: normal; }
  .faq-subtitle    { text-align: center; width: 100%; }

  .faq-dots { left: 165px; bottom: -40px; }   /* Figma keeps it flush at the section's true bottom */
}

/* Portrait tablet — Figma 820 frame */
@media (max-width: 820px) {
  .faq-inner   { gap: 24px; padding-left: 24px; padding-right: 24px; }
  .faq-heading { gap: 16px; }
  .faq-title   { font-size: 32px; }

  .faq-item-title      { font-size: 20px; }        /* line-height stays 36 (Figma) */
  .faq-item-toggle     { width: 36px; height: 36px; }
  .faq-item-toggle svg { width: 20px; height: 20px; }
}

/* Small tablet — Figma 768 frame: identical to 820 bar the section padding */
@media (max-width: 768px) {
  .faq-section { padding: 32px 0; }
  .faq-dots { bottom: -32px; }
}

/* Mobile (375 reference) */
@media (max-width: 767px) {
  .faq-section { padding: 24px 0; }
  .faq-inner { gap: 24px; padding-left: 16px; padding-right: 16px; }

  .faq-title    { font-size: 24px; }
  .faq-subtitle { font-size: 14px; line-height: 22px; }

  .faq-item-title      { font-size: 18px; }        /* line-height stays 36 (Figma) */
  .faq-item-toggle     { width: 28px; height: 28px; }
  .faq-item-toggle svg { width: 18px; height: 18px; }
  .faq-item-answer     { font-size: 12px; line-height: 18px; }
  .faq-dots { bottom: -24px; }
}

/* ═══════════════════════════════════════════════════════════
   CTA Section  (Figma node 1123:34336)
═══════════════════════════════════════════════════════════ */

/* Figma: exact layered gradient — diagonal orange tint over a white base */
.cta-section {
  background:
    linear-gradient(-87.9165deg, rgba(255,114,3,0.5) 15.789%, rgba(251,190,152,0.3) 56.524%),
    linear-gradient(90deg, rgb(255,255,255) 0%, rgb(255,255,255) 100%);
  padding: 64px 0;
  /* The ornaments only bleed past this section's own *padding* — their
     coordinates keep them pinned to their exact original Figma absolute
     position regardless of this padding value (see each rule's "FigmaY - our
     padding" comment below). .cta-mockup is the one exception: it's anchored
     from the bottom (bottom:-64px, see its own rule) specifically so it
     always reaches this section's true bottom edge no matter what this
     padding value is, rather than staying pinned to Figma's raw y:49 the way
     the ornaments do. overflow:hidden clips .cta-ornament-2's excess height
     (its export's aspect ratio runs taller than Figma's 331px frame — see its
     rule below) so it can't hang below the section as stray whitespace/
     artwork. body{overflow-x:hidden} stays as a secondary safety net for
     narrow viewports. */
  overflow: hidden;
}

.cta-wrapper {
  position: relative;   /* positioning root for the ornaments/mockup below */
  max-width: 80rem;
  margin: 0 auto;   /* no self padding — matches .nav-wrapper pattern */
}

.cta-inner {
  display: flex;
  align-items: center;
  gap: 40px;
  padding: 0 var(--nav-px);
  min-height: 302px;   /* Figma section height (400) minus its 2×49px vertical padding — a content-derived constant, independent of our own section padding */
}

/* ── Background ornaments ──────────────────────────────── */
/* Figma: two "element" layers. Positioned against .cta-wrapper (not .cta-inner)
   so top/left ignore .cta-section's own padding entirely: left is Figma's
   value minus its 80px horizontal section padding (.cta-wrapper maps 1:1 to
   that content width, same conversion used for the FAQ dots); top is Figma's
   value minus this section's own 64px top padding, landing each ornament at
   its exact original Y position and letting it bleed past the wrapper's edges
   exactly as Figma does — no z-index needed, DOM order (these come first)
   keeps them behind the content/mockup that follow. */
.cta-ornament {
  position: absolute;
  pointer-events: none;
}

.cta-ornament-1 {
  left: -80px;   /* 0 - 80 */
  top: -64px;    /* 0 - 64 */
  width: 670px;
  height: 221px;
}

.cta-ornament-2 {
  left: 353px;   /* 433 - 80 */
  top: 5px;      /* 69 - 64 */
  width: 1007px;
  height: auto;   /* asset's own aspect ratio — its export has extra vertical bleed vs Figma's 331px frame */
}

/* ── Left: heading + actions ────────────────────────────── */
.cta-content {
  display: flex;
  flex-direction: column;
  gap: 40px;
  align-items: flex-start;
  flex: 0 1 584px;
  max-width: 584px;
  width: 100%;
  z-index: 1;
}

/* Figma: "content" — title+subtitle grouped at gap-16, separate from the
   outer gap-40 between this block and the button row below */
.cta-heading {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
  width: 100%;
}

.cta-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
}

.cta-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
}

.cta-actions {
  display: flex;
  align-items: center;
  gap: 24px;
}

/* Figma: bg-#ff7203 h-48px rounded-8px white text — same spec as .btn-daftar */
.cta-btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 16px;
  background: var(--orange);
  border: none;
  border-radius: 8px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: var(--white);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s;
}
.cta-btn-primary:hover { background: var(--orange-dark); }

.cta-divider-text {
  font-family: var(--font);
  font-size: 15px;
  font-weight: 400;
  color: #212b36;
}

/* New variant — outlined secondary button, doesn't exist elsewhere in this
   project yet (all other buttons are solid-fill) */
.cta-btn-outline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 24px;
  background: transparent;
  border: 1px solid rgba(145,158,171,0.32);
  border-radius: 8px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 700;
  line-height: 26px;
  color: #212b36;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s, border-color 0.15s;
}
.cta-btn-outline:hover { background: rgba(145,158,171,0.08); border-color: rgba(145,158,171,0.48); }

/* ── Device mockup ──────────────────────────────────────── */
/* Positioned against .cta-wrapper (like the ornaments above). Horizontal is
   still Figma's x:790.05 minus the 80px horizontal section padding, same
   conversion as everywhere else. Vertical is anchored from the BOTTOM instead
   of the top: bottom:-64px cancels out .cta-section's own padding-bottom
   (64px), same "ignore padding" technique as .faq-dots — an absolutely
   positioned child normally stops at the padding edge, so this negative
   offset is what pushes it past that edge to the section's true bottom,
   regardless of whatever padding value the section has. (A top-anchored
   offset pinned to Figma's raw y:49 doesn't self-correct like this — it
   drifted out of place as soon as the section's own padding changed to no
   longer match Figma's 49px 1:1, which is why this is bottom-anchored now.) */
.cta-mockup {
  position: absolute;
  left: 710px;    /* 790.05 - 80 */
  bottom: -64px;  /* cancels out .cta-section's padding-bottom: 64px */
  width: 607px;
  aspect-ratio: 607 / 351;
  z-index: 1;
}

/* Figma: absolute within the mockup's own 607×351 frame — content-relative
   left already subtracted, converted here to % of the mockup box itself */
.cta-mockup-desktop {
  position: absolute;
  left: 13.53%;    /* (852.2 - 790.05) / 607 */
  top: 0%;         /* (49 - 49) / 351 */
  width: 89.79%;   /* 545 / 607 */
  height: auto;
  z-index: 1;
}

.cta-mockup-mobile {
  position: absolute;
  left: 0%;        /* (790.09 - 790.05) / 607 ≈ 0 */
  top: 13.96%;     /* (98 - 49) / 351 */
  width: 32.29%;   /* 196 / 607 */
  height: auto;
  z-index: 2;   /* phone sits in front of the tablet, matching Figma's paint order */
}

/* ── CTA responsive ────────────────────────────────────────
   Figma frames 1024 / 820 / 768 / 375. The section never stacks: the text
   column stays left and the device mockup stays absolutely positioned,
   bleeding off the right edge (clipped by .cta-section's overflow:hidden).
   At 375 the mockup + ornaments are dropped and only the text remains —
   heading left, buttons in a centred row (no "atau").
   820 & 768 share one frame apart from viewport width.
─────────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .cta-section { padding: 40px 0; }
  .cta-inner {
    gap: 32px;
    min-height: 273px;
    padding-left: 40px;
    padding-right: 40px;
  }

  .cta-content { flex: 0 1 428px; max-width: 428px; gap: 32px; }
  .cta-heading { gap: 8px; }
  .cta-title { font-size: 36px; line-height: 1.5; }
  .cta-subtitle { font-size: 14px; line-height: 22px; }

  /* Figma's compact button spec for every tier below desktop */
  .cta-actions { gap: 24px; }
  .cta-btn-primary,
  .cta-btn-outline {
    height: 36px;
    padding-left: 12px;
    padding-right: 12px;
    font-size: 14px;
    line-height: 24px;
  }
  .cta-btn-outline { border-width: 2px; }
  .cta-divider-text { font-size: 14px; }

  /* ornament tops track the reduced section padding (Figma y − 40) */
  .cta-ornament-1 { top: -40px; }
  .cta-ornament-2 { top: 29px; }

  .cta-mockup { left: 540px; width: 607px; bottom: -40px; }
}

@media (max-width: 820px) {
  .cta-inner { padding-left: 24px; padding-right: 24px; }
  .cta-content { flex-basis: 380px; max-width: 380px; }
  .cta-title { font-size: 32px; }
  .cta-mockup { left: 484px; width: 508px; }
}

/* 768 — Figma frame identical to 820 apart from viewport width; no rules needed */

@media (max-width: 767px) {
  .cta-section { padding: 40px 0; }
  .cta-inner { min-height: 0; gap: 24px; padding-left: 16px; padding-right: 16px; }

  .cta-content { flex-basis: auto; max-width: 100%; gap: 24px; }
  .cta-title { font-size: 20px; }

  .cta-actions { width: 100%; justify-content: center; }
  .cta-divider-text { display: none; }        /* Figma drops "atau" at mobile */

  .cta-mockup { display: none; }              /* Figma drops the mockup at mobile */
  .cta-ornament-1,
  .cta-ornament-2 { display: none; }
}

/* ═══════════════════════════════════════════════════════════
   Others Section  (Figma node 1123:35009 / instance 214:46921,
   "Section/Others" — bosAgen / bosCOD / PastiAsli cross-sell cards)
═══════════════════════════════════════════════════════════ */

.others-section {
  background: var(--white);
  padding: 64px 0;
}

.others-wrapper {
  max-width: 80rem;
  margin: 0 auto;   /* no self padding — matches .nav-wrapper pattern */
}

.others-inner {
  display: flex;
  flex-direction: column;
  gap: 48px;
  align-items: center;
  padding: 0 var(--nav-px);
  width: 100%;
}

/* ── Headline ────────────────────────────────────────────── */
.others-headline {
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: center;
  width: 100%;
}

.others-title-highlight {
  display: flex;
  align-items: center;
  justify-content: center;
}

.others-title {
  font-family: 'Red Hat Display', sans-serif;
  font-size: 48px;
  font-weight: 700;
  line-height: 64px;
  color: #212b36;
  white-space: nowrap;
  text-align: center;
}

/* Figma originally did this as a gradient sized to a fixed 558px title box,
   hard-stopped at 0%→32.334% — only lined up with "Jelajahi" at that exact
   width (see .hero-highlight for the full explanation). Scoping the tint to
   the word's own <span> keeps it glued to "Jelajahi" at any width or
   font-size. */
.others-highlight {
  background: rgba(255,114,3,0.08);
}

.others-subtitle {
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #212b36;
  text-align: center;
}

/* ── Product cards row ──────────────────────────────────────
   Figma "Frame 427321789" — three equal columns, each a plain vertical
   stack (illustration + wordmark tucked beneath, then divider / desc / CTA).
   No absolute positioning: the illustration is an in-flow element sized to
   the column, so the whole thing scales cleanly down to a single column. */
.others-row {
  display: flex;
  gap: 32px;
  align-items: flex-start;
  width: 100%;
}

.others-card {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
}

/* illustration + wordmark sit tight together (Figma groups them with no gap,
   then the card's own 24px gap separates them from the divider) */
.others-illu {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* Full illustration graphic (photo + ring + baked-in courier badges),
   pre-flattened per-product at assets/img/other-products/*.webp (native
   1580×1376). In flow at the top of the card, sized to ~90% of the column
   like Figma's Group box. */
.others-illustration {
  width: 92%;
  max-width: 300px;
  height: auto;
  transition: transform 0.28s ease;
}
@media (hover: hover) and (pointer: fine) {
  .others-card:hover .others-illustration { transform: scale(1.05); }
}

.others-logo {
  width: 70%;
  max-width: 260px;
  height: auto;
}

.others-divider {
  width: 100%;
  max-width: 280px;
  height: 1px;
  border: none;
  background: rgba(145,158,171,0.2);
}

.others-desc {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 400;
  line-height: 22px;
  color: #212b36;
  text-align: center;
  width: 100%;
  max-width: 280px;
}

.others-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 30px;
  width: 100%;
  max-width: 280px;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 700;
  line-height: 22px;
  color: var(--orange);
  text-decoration: none;
}
.others-cta:hover { color: var(--orange-dark); }

.others-cta-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* ── Others responsive ─────────────────────────────────────
   Figma frames 1024 / 820 / 768 / 375. Three-column row holds until 375,
   where it stacks to one column and bosCOD is promoted to the top.
─────────────────────────────────────────────────────────── */

/* Landscape tablet — Figma 1024 frame */
@media (max-width: 1024px) {
  .others-section { padding: 40px 0; }
  .others-inner   { gap: 32px; padding-left: 40px; padding-right: 40px; }
  .others-headline { gap: 24px; }
  .others-title { font-size: 36px; line-height: 1.5; white-space: normal; }
}

/* Portrait tablet — Figma 820 frame */
@media (max-width: 820px) {
  .others-inner { gap: 24px; padding-left: 24px; padding-right: 24px; }
  .others-headline { gap: 16px; }
  .others-row { gap: 32px; }
}

/* Small tablet — Figma 768 frame: identical to 820 bar the section padding */
@media (max-width: 768px) {
  .others-section { padding: 32px 0; }
}

/* Mobile (375 reference) — single column, bosCOD first */
@media (max-width: 767px) {
  .others-section { padding: 24px 0; }
  .others-inner { padding-left: 16px; padding-right: 16px; }

  .others-title { font-size: 24px; }
  .others-subtitle { font-size: 14px; line-height: 22px; }

  .others-row { flex-direction: column; align-items: center; gap: 24px; }
  .others-card { max-width: 360px; }
  .others-card[data-product="boscod"] { order: -1; }   /* Figma promotes bosCOD */

  .others-illustration { width: 90%; max-width: 320px; }
  .others-desc { font-size: 12px; line-height: 18px; }
}

/* ═══════════════════════════════════════════════════════════
   Footer  (duplicated from bosonline.id's own footer — this design
   isn't laid out as its own frame in the Figma file the way other
   sections are, so structure/copy/links/breakpoint were reverse-
   engineered from the live site's compiled bundle; bosOnline logo
   and Kominfo logo downloaded directly from that same live site.
   Social icons are inlined as SVG, copied from the same lucide-react
   glyphs the live site uses (facebook/instagram/message-circle-more
   "WhatsApp"/music-2 "TikTok"/youtube) rather than re-drawn from
   scratch. Single breakpoint at 767px, matching the source site's
   own Tailwind "md" (768px) cutoff.

   footer-bg.svg (dot pattern + swirl lines) was rebuilt from Figma
   node 365:72445 instead, since that background DOES exist there and
   the live site's own version had the swirl positioned differently.
   Combined 1440×527 canvas = Figma's own section box, so both pieces
   use Figma's raw coordinates directly (no padding conversion needed
   — background-size:cover scales the whole canvas uniformly):
     - dot pattern (node 365:72415): native 415×415, translate(-264,47)
     - swirl lines (node 365:72443, clipped by frame 365:72444): native
       1272.79×1048.39, translate(407.71,-144.3) — derived from that
       frame's own inset-[-27.38%_-30.37%_-71.55%_-30.34%] math. )
═══════════════════════════════════════════════════════════ */

/* Distinct from the plain-white sections above/below it. footer-bg.svg is
   bosonline.id's own full footer ornament (dot cluster left + flowing line
   pattern right, both baked into one 1440x527 asset) — background-size:cover
   + center matches the live site's own technique exactly, so it scales the
   same way at every viewport including mobile (where cover crops it down to
   just a sliver top-right + bottom-right, same as the live site) instead of
   needing separate per-breakpoint positioning. A rounded top edge + lifted
   shadow reads as a "shelf" that visually separates the footer from
   .others-section above, rather than the two sections just running together
   at a flat seam. */
.footer-section {
  background:
    url('assets/vector/footer/footer-bg.svg') center / cover no-repeat,
    linear-gradient(180deg, var(--white) 0%, rgba(251,160,81,0.10) 100%);
  padding: 64px 0;
  color: var(--text);
  position: relative;
  border-radius: 32px 32px 0 0;
  box-shadow: 0 -24px 48px -32px rgba(33,43,54,0.12);
}

.footer-wrapper {
  max-width: 80rem;
  margin: 0 auto;   /* no self padding — matches .nav-wrapper pattern */
}

.footer-inner {
  padding: 0 var(--nav-px);
  width: 100%;
}

/* Brand column flexible on the left; the three link columns (grouped in
   .footer-links-group, Figma node 363:72282) pushed to the right — matches
   Figma's own items-start justify-between on this row. */
.footer-grid {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 40px;
}

.footer-brand {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.footer-logo {
  width: 144px;
  height: auto;
  margin: 8px 4px;
}

.footer-socials {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  color: var(--orange);
}

.footer-social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 6px;
  color: inherit;
  transition: color 0.15s;
}
.footer-social-link:hover { color: #fb923c; }

.footer-social-icon {
  width: 24px;
  height: 24px;
}

.footer-company {
  font-size: 18px;
  font-weight: 600;
}

.footer-address {
  font-size: 16px;
  line-height: 1.5;
}

.footer-registered {
  width: fit-content;
}

.footer-registered-title {
  font-size: 16px;
  font-weight: 600;
  width: fit-content;
}

.footer-kominfo-logo {
  width: 64px;
  height: auto;
  margin: 8px auto 0;
  display: block;
}

/* Three link columns (Figma node 363:72282): gap-[56px] items-start */
.footer-links-group {
  display: flex;
  align-items: flex-start;
  gap: 56px;
}

/* Each column (Figma e.g. node 365:72403): flex-col gap-[8px] items-start */
.footer-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  text-align: left;
}

.footer-col-title {
  font-size: 18px;
  font-weight: 700;
  line-height: 28px;
  color: var(--orange);
}

/* List (Figma "List" frame): flex-col gap-[16px] items-start py-[8px] */
.footer-links {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  padding: 8px 0;
  list-style: none;
  text-align: left;
}

.footer-links a {
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: #1d1b1e;
  text-decoration: none;
  transition: color 0.15s;
}
.footer-links a:hover { color: #9ca3af; }

.footer-bottom {
  border-top: 1px solid rgba(156,163,175,0.5);
  margin-top: 32px;
  padding-top: 32px;
  text-align: center;
}

.footer-copyright {
  color: #1f2937;
}

/* ── Footer responsive (matches the source site's single "md" cutoff) ── */
@media (max-width: 767px) {
  .footer-grid {
    flex-direction: column;
    gap: 24px;
  }

  .footer-brand { gap: 24px; }

  .footer-socials { gap: 4px; }
  .footer-social-link { margin: 4px; }
  .footer-social-icon { width: 18px; height: 18px; }

  .footer-company { font-size: 16px; }
  .footer-address, .footer-registered-title { font-size: 14px; }

  /* Columns no longer sit in one wide row on mobile — let them wrap */
  .footer-links-group { flex-wrap: wrap; gap: 24px 40px; }
  .footer-col-title { font-size: 16px; }
  .footer-links a { font-size: 14px; }

  /* Source site lays these 2-4 links out as a 2-row grid that fills
     column-by-column on mobile, instead of one long stacked list */
  .footer-links {
    grid-template-columns: none;
    grid-template-rows: repeat(2, auto);
    grid-auto-flow: column;
    gap: 16px;
  }
}
