html {
  max-width: 100%;
  scroll-behavior: smooth;
  /* Hard-fallback bg color so the browser never flashes white before
     Alpine initializes (body's :style="{ backgroundColor }" only kicks
     in after settings.json loads, leaving a render frame or two of
     transparent html → browser-default white). Without this, the
     white flash exaggerates contrast against subsequent dark layers
     and makes gradient transitions read as banding. */
  background-color: #1a1a1a;
}

/* Mobile fullscreen menu open → lock background scroll so the overlay
   covers a static page instead of letting the user scroll the site
   underneath. Only mobile; desktop nav has no overlay. */
html.rr-menu-open,
html.rr-menu-open body {
  overflow: hidden;
  touch-action: none;
}

/* Snap-scroll desktop UX (matches venn-studios.com parent site).
   Each <section> direct child of <main> anchors to viewport top.
   Skipped on mobile and when the user has reduced-motion enabled —
   mobile snap is jank-prone and breaks address-bar collapse, and
   reduced-motion users opt out of programmatic scroll choreography. */
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  /* Snap-type must live on the actual scroll container. body has
     overflow-x: hidden, which implicitly promotes its overflow-y to
     auto and makes body — not html — the scroller. Declaring the snap
     on html silently no-ops. */
  body {
    scroll-snap-type: y mandatory;
    /* Snap container's top padding — snap targets align to viewport_y=118
       (below the 118px fixed navbar) instead of viewport_y=0. Lets each
       non-hero section use its Figma-spec internal padding (e.g. py-32)
       without the navbar overlapping content. */
    scroll-padding-top: 118px;
  }
  main > section {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
  /* Hero is designed for the navbar to overlay its key art — opt out
     of the container's scroll-padding by shifting its snap target up
     by 118px so it lands at viewport_y=0. */
  main > section#hero {
    scroll-margin-top: -118px;
  }

  /* Matches the parent venn-studios.com pattern: one section per
     viewport, snap to top, navbar overlays. Sections handle navbar
     clearance with their own internal padding-top, not scroll-margin —
     scroll-margin > 0 was preventing proximity snap from engaging on
     sections like the trailer because the snap point sat awkwardly
     above the section's visible top edge. */

  /* Hero outer section needs explicit min-h-screen so mandatory snap
     lands the section's full viewport on it — the inner is a fixed
     lg:h-[820px] Figma stage, shorter than most lg viewports, so
     without this the next section bleeds into the bottom 80+px of the
     viewport when snapped back to hero. The dark fill below the inner
     is invisible since the bg matches the inner's #121212. */
  main > section#hero {
    min-height: 100vh;
    background-color: #1a1a1a;
  }

  /* Heroes outer section needs explicit min-h-screen + flex centering
     because its inner div is content-sized (~782px) rather than
     min-h-screen like the trailer's inner. Standardized to the
     site-wide spacing formula: each section.pt=144 + pb=48 → total
     192px of dark in scroll between adjacent sections, while pt
     still clears the 118px navbar with 26px breathing. */
  main > section#heroes {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-top: 144px;
    padding-bottom: 48px;
  }

  /* Figma-spec section padding: py-[32px] matches every "section/*"
     frame in the design file 1:1. Navbar clearance is handled by the
     body's scroll-padding-top: 118px above — sections snap below the
     navbar so the 32px is exactly the visible gap above the eyebrow. */
  main > section:not(#hero):not(#heroes):not(#lore-gameplay):not(#footer):not(#social) {
    padding-top: 32px;
    padding-bottom: 32px;
  }

  /* Social section has bigger Figma py (64) than other sections — it
     anchors the newsletter CTA and the tilted-card splash, so it gets
     more breathing room. */
  main > section#social {
    padding-top: 64px;
    padding-bottom: 64px;
  }
}

body {
  overflow-x: hidden;
  margin: 0 auto;
  width: 100%;
  background-color: #1a1a1a;
}

/* ========================================
   WCAG 2.2 ACCESSIBILITY STYLES
   ======================================== */

/* Skip Link - Hidden until focused */
.skip-link {
  position: absolute;
  top: -100px;
  left: 50%;
  transform: translateX(-50%);
  background: #FED687;
  color: #121212;
  padding: 12px 24px;
  text-decoration: none;
  font-weight: 600;
  z-index: 10000;
  border-radius: 0 0 8px 8px;
  transition: top 0.2s ease;
}

.skip-link:focus {
  top: 0;
  outline: 3px solid #F3F3F3;
  outline-offset: 2px;
}

/* Focus Visible - WCAG 2.4.7 & 2.4.13 */
:focus {
  outline: none;
}

:focus-visible {
  outline: 3px solid #FED687;
  outline-offset: 3px;
  border-radius: 2px;
}

/* Ensure focus is visible on dark backgrounds */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 3px solid #FED687;
  outline-offset: 3px;
}

/* Focus indicator for interactive cards */
.focus-card:focus-visible {
  outline: 3px solid #FED687;
  outline-offset: 4px;
  box-shadow: 0 0 0 6px rgba(254, 214, 135, 0.3);
}

/* Screen Reader Only - Visually hidden but accessible */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Minimum touch target size - WCAG 2.5.8 */
.touch-target {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.touch-target-min {
  min-width: 24px;
  min-height: 24px;
}

/* Reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* High contrast mode support */
@media (prefers-contrast: high) {
  :root {
    --color-primary: #FFFFFF;
    --color-secondary: #E0E0E0;
  }

  a, button, [role="button"] {
    text-decoration: underline;
  }
}

/* Hide scrollbar for Chrome, Safari and Opera */
body::-webkit-scrollbar {
  display: none;
}

/* Hide scrollbar for IE, Edge and Firefox */
body {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

/* Hide scrollbar for roster list */
.scrollbar-hide::-webkit-scrollbar {
  display: none;
}

.scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
}

/* Alpine x-cloak — hides elements until Alpine hydrates, then the attribute
   is removed and x-show / regular CSS take over. Reliable replacement for
   inline `style="display: none"` SSR fallbacks (which can fight x-show). */
[x-cloak] { display: none !important; }

/* Hero navigation text transitions
   The two states (gold idle / white selected) cross-fade via opacity rather
   than animating gradient → solid color, which Safari renders as a flash.
   Letter-spacing and a soft glow lift the active label without shifting layout. */
.hero-text-selected {
  color: #F3F3F3 !important;
  background: none !important;
  -webkit-background-clip: border-box !important;
  -webkit-text-fill-color: #F3F3F3 !important;
  background-clip: border-box !important;
  letter-spacing: 0.018em;
  text-shadow: 0 0 28px rgba(254, 214, 135, 0.28);
  transition:
    color 0.35s cubic-bezier(0.22, 0.61, 0.36, 1),
    letter-spacing 0.45s cubic-bezier(0.22, 0.61, 0.36, 1),
    text-shadow 0.55s ease-out;
}

.hero-text-gold {
  color: transparent !important;
  background: var(--rr-gradient-gold) !important;
  -webkit-background-clip: text !important;
  -webkit-text-fill-color: transparent !important;
  background-clip: text !important;
  letter-spacing: 0;
  text-shadow: 0 0 0 transparent;
  transition:
    color 0.6s ease-out,
    letter-spacing 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
    text-shadow 0.4s ease-in;
}

/* Tactile press feedback — brief scale-down acknowledges the click before
   the cross-fade kicks in. */
.hero-item-pressable {
  transition: transform 0.18s cubic-bezier(0.22, 0.61, 0.36, 1);
  transform-origin: left center;
}
.hero-item-pressable:active {
  transform: scale(0.97);
}

/* Site-wide gradient curve.
   Mirrors the polished-metal feel of the gold hero-text gradient
   (`linear-gradient(1deg, #9A7340 -117.85%, #FED687 109.76%)` — stops
   ~118% outside on each side). Reuse anywhere a soft fade is needed:
   keep stops outside [0,100] by similar margins so CSS interpolates a
   thin middle slice, giving a flat plateau that trails off softly
   toward the edges with no perceivable stops. */
:root {
  --rr-fade-dark: 13, 13, 14;
  --rr-fade-strong: 0.92;
  --rr-fade-medium: 0.7;
  --rr-fade-soft: 0.45;
}

/* Nav links drop-shadow stack (Figma "buttons-dropshadow") — six
   stacked shadows give the cast-on-hero look without darkening the
   text itself. drop-shadow filter (vs text-shadow) covers both the
   nav text and the wishlist button image inside the same container. */
.rr-nav-shadow {
  filter:
    drop-shadow(0 4px 4px rgba(0, 0, 0, 0.25))
    drop-shadow(0 2px 1.5px rgba(0, 0, 0, 0.25))
    drop-shadow(0 6px 3px rgba(0, 0, 0, 0.21))
    drop-shadow(0 14px 4px rgba(0, 0, 0, 0.13))
    drop-shadow(0 24px 5px rgba(0, 0, 0, 0.04));
}

/* CTA button shimmer — TWO independent diagonal sheen sweeps, each
   masked to a different zone of the button. The frame streak only
   shows on the top + bottom wood-frame strips; the interior streak
   only shows in the middle band where the Steam logo + text sit.
   Different cycle durations (9s vs 13s) so the two streaks desync —
   they read as separate light beams hitting different surfaces of
   the button at different depths, rather than one paired sweep.
   mix-blend-mode: screen leaves dark areas untouched; only the gold
   flares. Skipped when prefers-reduced-motion. */
/* Reusable CTA polish: hover gold halo + hover-triggered specular
   shimmer sweep. Apply `.rr-cta-shine` to any gold-framed action
   button (Wishlist, Newsletter Subscribe/Submit). Both effects only
   activate on hover — no constant animation on idle CTAs. */
.rr-cta-shine {
  /* Glow size scales with `--glow-scale` (1 = hero Wishlist, 96px tall).
     Smaller CTAs add `.rr-cta-shine-sm` to halve the halo so it stays
     proportional to the button — see keyframes below. */
  --glow-scale: 1;
  position: relative;
  overflow: hidden;
  transition: box-shadow 280ms ease-out;
  box-shadow: 0 0 0 0 rgba(254, 214, 135, 0);
}

.rr-cta-shine-sm { --glow-scale: 0.55; }

/* Halo: gentle gold pulse breathing while hovered. */
.rr-cta-shine:hover {
  animation: cta-button-glow-pulse 2s ease-in-out infinite;
}

@keyframes cta-button-glow-pulse {
  0%, 100% {
    box-shadow:
      0 0 calc(14px * var(--glow-scale)) calc(2px * var(--glow-scale)) rgba(254, 214, 135, 0.10),
      0 0 calc(28px * var(--glow-scale)) calc(6px * var(--glow-scale)) rgba(254, 214, 135, 0.03);
  }
  50% {
    box-shadow:
      0 0 calc(26px * var(--glow-scale)) calc(4px * var(--glow-scale)) rgba(254, 214, 135, 0.26),
      0 0 calc(50px * var(--glow-scale)) calc(10px * var(--glow-scale)) rgba(254, 214, 135, 0.09);
  }
}

/* Shimmer pseudos: idle state parks the streak fully off-screen.
   No animation by default — only the :hover rule triggers a single
   sweep (1 iteration), so each hover-entry plays one shimmer pass. */
.rr-cta-shine::before,
.rr-cta-shine::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: screen;
  background-repeat: no-repeat;
  background-position: 170% 0;
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-mode: luminance;
          mask-mode: luminance;
}

.rr-cta-shine::before {
  /* Frame shimmer (wood). Warmer dusty tone, narrower streak. */
  background-size: 22% 100%;
  background-image: linear-gradient(
    105deg,
    transparent 0%,
    rgba(255, 220, 170, 0.04) 12%,
    rgba(255, 220, 170, 0.32) 50%,
    rgba(255, 220, 170, 0.0) 60%,
    transparent 100%
  );
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='1.6'/%3E%3C/filter%3E%3C/defs%3E%3Crect width='100' height='100' fill='white'/%3E%3Crect x='5' y='15' width='90' height='70' fill='black' filter='url(%23b)'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='1.6'/%3E%3C/filter%3E%3C/defs%3E%3Crect width='100' height='100' fill='white'/%3E%3Crect x='5' y='15' width='90' height='70' fill='black' filter='url(%23b)'/%3E%3C/svg%3E");
}

.rr-cta-shine::after {
  /* Interior shimmer (polished gold). Near-white, wider streak. */
  background-size: 38% 100%;
  background-image: linear-gradient(
    105deg,
    transparent 0%,
    rgba(255, 252, 240, 0.06) 12%,
    rgba(255, 252, 240, 0.78) 50%,
    rgba(255, 252, 240, 0.0) 60%,
    transparent 100%
  );
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='1.6'/%3E%3C/filter%3E%3C/defs%3E%3Crect width='100' height='100' fill='black'/%3E%3Crect x='5' y='15' width='90' height='70' fill='white' filter='url(%23b)'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='1.6'/%3E%3C/filter%3E%3C/defs%3E%3Crect width='100' height='100' fill='black'/%3E%3Crect x='5' y='15' width='90' height='70' fill='white' filter='url(%23b)'/%3E%3C/svg%3E");
}

/* CTA text overlay: localized label riding on top of the SVG border.
   Steam logo stays inside the SVG (kept as artwork). On `.group:hover`
   the gold-gradient text fill cross-fades to solid white — same 280ms
   transition the SVG text paths had when they were baked into the SVG. */
.rr-cta-text {
  background-clip: text;
  -webkit-background-clip: text;
  transition: -webkit-text-fill-color 280ms ease-out, color 280ms ease-out;
}
.group:hover .rr-cta-text,
.group:focus-visible .rr-cta-text {
  -webkit-text-fill-color: #FFFFFF;
  color: #FFFFFF;
}

/* Hover trigger: each hover-entry plays one shimmer pass. */
.rr-cta-shine:hover::before {
  animation: cta-shimmer-sweep 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) 1 forwards;
}
.rr-cta-shine:hover::after {
  animation: cta-shimmer-sweep 1.4s cubic-bezier(0.55, 0.0, 0.45, 1.0) 1 forwards;
  animation-delay: 0.027s;
}

/* ----------------------------------------------------------------
   .rr-btn-frame — translatable gold-framed button. Replaces the
   previous baked-text SVGs (btn-see-all, btn-subscribe). The label
   is HTML so each locale can swap the text.

   Look matches the SVG buttons it replaces: dark glass interior +
   gold outer stroke + inner deep-gold halo + painted drop-shadow.
   Doesn't use ::before/::after so it composes cleanly with the
   existing .rr-cta-shine (which owns both pseudos for shimmer/halo).

   Usage:
     <a class="rr-btn-frame">
       <span class="rr-btn-frame__label">{{label}}</span>
     </a>
   Variants:
     .rr-btn-frame.is-sm   — compact (See All)
     .rr-btn-frame.is-wide — wide (newsletter Subscribe)
   ---------------------------------------------------------------- */
.rr-btn-frame {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  isolation: isolate;
  padding: 12px 28px;
  min-height: 48px;
  background: rgba(18, 18, 18, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  cursor: pointer;
  border: 1.5px solid var(--accent);
  /* Inner deep-gold ring + painted-depth drop-shadow stack. */
  box-shadow:
    inset 0 0 0 1px rgba(154, 115, 64, 0.6),
    0 2px 3px rgba(0, 0, 0, 0.30),
    0 6px 6px rgba(0, 0, 0, 0.22),
    0 12px 8px rgba(0, 0, 0, 0.14);
  transition:
    box-shadow 280ms ease-out,
    border-color 280ms ease-out,
    transform 220ms ease-out;
}
.rr-btn-frame:hover,
.rr-btn-frame:focus-visible {
  /* Brighter inner ring + soft warm halo on hover. */
  box-shadow:
    inset 0 0 0 1px rgba(254, 214, 135, 0.9),
    0 0 14px 2px rgba(254, 214, 135, 0.18),
    0 2px 3px rgba(0, 0, 0, 0.30),
    0 6px 6px rgba(0, 0, 0, 0.22);
  border-color: var(--accent-soft);
  transform: translateY(-1px);
}
.rr-btn-frame__label {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 16px;
  line-height: 1;
  white-space: nowrap;
  background: var(--rr-gradient-gold);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  transition: -webkit-text-fill-color 280ms ease-out, color 280ms ease-out;
}
.rr-btn-frame:hover .rr-btn-frame__label,
.rr-btn-frame:focus-visible .rr-btn-frame__label {
  -webkit-text-fill-color: #FFFFFF;
  color: #FFFFFF;
}
.rr-btn-frame.is-sm {
  padding: 8px 18px;
  min-height: 38px;
}
.rr-btn-frame.is-sm .rr-btn-frame__label {
  font-size: 13px;
  letter-spacing: 0.08em;
}
.rr-btn-frame.is-wide {
  padding: 12px 56px;
  min-height: 50px;
}
.rr-btn-frame.is-wide .rr-btn-frame__label {
  font-size: 17px;
}

/* Hex Wishlist frame — translatable variant of the hex CTA, no Steam
   wordmark/logo (those stay baked into the hero CTA SVG). Uses two
   stacked elements instead of pseudos so it composes with .rr-cta-shine.
   The outer .rr-btn-hex provides the gold-outline silhouette; the inner
   .rr-btn-hex__inner provides the dark fill. The label rides on top.

   Usage:
     <a class="rr-btn-hex">
       <span class="rr-btn-hex__inner">
         <span class="rr-btn-hex__label">{{label}}</span>
       </span>
     </a>
   Variants:
     .rr-btn-hex.is-lg — mobile menu (72px) */
.rr-btn-hex {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  isolation: isolate;
  height: 48px;
  min-width: 140px;
  cursor: pointer;
  background: var(--rr-gradient-gold);
  --hex-cut: 8px;
  clip-path: polygon(
    var(--hex-cut) 0,
    calc(100% - var(--hex-cut)) 0,
    100% 50%,
    calc(100% - var(--hex-cut)) 100%,
    var(--hex-cut) 100%,
    0 50%
  );
  filter:
    drop-shadow(0 2px 3px rgba(0, 0, 0, 0.30))
    drop-shadow(0 6px 6px rgba(0, 0, 0, 0.22))
    drop-shadow(0 12px 8px rgba(0, 0, 0, 0.14));
  transition: transform 220ms ease-out, filter 220ms ease-out;
}
.rr-btn-hex:hover,
.rr-btn-hex:focus-visible {
  transform: translateY(-1px);
}
.rr-btn-hex__inner {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  inset: 1.5px;
  padding: 0 24px;
  background: #0d0d0d;
  clip-path: polygon(
    var(--hex-cut) 0,
    calc(100% - var(--hex-cut)) 0,
    100% 50%,
    calc(100% - var(--hex-cut)) 100%,
    var(--hex-cut) 100%,
    0 50%
  );
}
.rr-btn-hex__label {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 14px;
  line-height: 1;
  white-space: nowrap;
  background: var(--rr-gradient-gold);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  transition: -webkit-text-fill-color 280ms ease-out, color 280ms ease-out;
}
.rr-btn-hex:hover .rr-btn-hex__label,
.rr-btn-hex:focus-visible .rr-btn-hex__label {
  -webkit-text-fill-color: #FFFFFF;
  color: #FFFFFF;
}
.rr-btn-hex.is-lg {
  height: 72px;
  min-width: 220px;
  --hex-cut: 12px;
}
.rr-btn-hex.is-lg .rr-btn-hex__inner {
  padding: 0 36px;
}
.rr-btn-hex.is-lg .rr-btn-hex__label {
  font-size: 18px;
}

/* ----------------------------------------------------------------
   .rr-article-body — prose styling for news article body HTML.
   The body comes from locale JSON as raw HTML (<h1>, <h2>, <p>, <img>,
   iframes, links) and is dropped in via x-html, so it can't use
   per-element classes — every rule has to target tags directly.
   Matches Figma news-article (1:2055): Lora body / Cinzel headings /
   gold links / scoped image captions.
   ---------------------------------------------------------------- */
.rr-article-body {
  font-family: var(--font-body);
  color: var(--text-primary);
  font-size: 16px;
  line-height: 1.65;
  letter-spacing: 0.01em;
}
.rr-article-body > * + * { margin-top: 1.2em; }
.rr-article-body h1 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 28px;
  line-height: 1.2;
  letter-spacing: 0.02em;
  margin-top: 2em;
  background: var(--rr-gradient-gold);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.rr-article-body h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.3;
  letter-spacing: 0.02em;
  margin-top: 1.8em;
  color: var(--accent);
}
.rr-article-body h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 18px;
  line-height: 1.4;
  margin-top: 1.6em;
  color: var(--accent);
}
.rr-article-body p {
  color: rgba(243, 243, 243, 0.88);
}
.rr-article-body a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 220ms ease;
}
.rr-article-body a:hover { color: var(--accent-soft); }
.rr-article-body strong { color: var(--text-primary); font-weight: 600; }
.rr-article-body em { font-style: italic; }
.rr-article-body ul, .rr-article-body ol {
  padding-left: 1.5em;
  margin-top: 1em;
}
.rr-article-body li { margin: 0.4em 0; }
.rr-article-body img {
  display: block;
  width: 100%;
  height: auto;
  margin: 2em 0 0.5em;
  border: 1px solid var(--stroke);
}
.rr-article-body img + em,
.rr-article-body figcaption {
  display: block;
  font-size: 13px;
  color: var(--text-secondary);
  font-style: italic;
  margin-top: 0.4em;
}
.rr-article-body .post-video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin: 2em 0;
  border: 1px solid var(--stroke);
  overflow: hidden;
}
.rr-article-body .post-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.rr-article-body iframe {
  width: 100%;
  border: 0;
}

@keyframes cta-shimmer-sweep {
  from { background-position: -70% 0; }
  to   { background-position: 170% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .rr-cta-shine::before,
  .rr-cta-shine::after { animation: none; opacity: 0; }
  .rr-cta-shine:hover { animation: none; }
}

/* Hero red-glow pulse: a duplicate of the key art, oversaturated and
   screen-blended on top, breathing in/out every 5.5s. Screen blend
   only adds light where the source is bright — the warm/red highlights
   (capes, blood markings, eyes) flare while the dark armor stays put.
   `prefers-reduced-motion` collapses to a static dimmed state. */
.hero-bg-pulse {
  filter: saturate(2.4) brightness(1.25) contrast(1.05);
  mix-blend-mode: screen;
  opacity: 0;
  animation: hero-pulse 5.5s ease-in-out infinite;
  will-change: opacity;
}

@keyframes hero-pulse {
  0%, 100% { opacity: 0; }
  44%, 56% { opacity: 0.55; }
}

/* Bottom fade: solid #121212 ramping in over the last 140px of the
   hero so the fog, embers, and image-crop edge don't draw a hard
   horizontal line where the section ends. z-index 2 sits above the
   key art (z=1) and atmosphere (z=2), but below the CTA / nav (z=3+). */
/* News card interactive states — match Figma "Gradient/Hover-Background"
   pattern: on hover, the card's vertical gradient ramps to #121212
   (darker than the idle #171717 stop) and borders + lift + warm halo
   add the standard interactive cue. */
.rr-news-card {
  transition:
    transform 280ms ease-out,
    border-color 280ms ease-out,
    box-shadow 280ms ease-out,
    background 280ms ease-out;
}
.rr-news-card:hover {
  transform: translateY(-2px);
  border-color: rgba(254, 214, 135, 0.4);
  box-shadow:
    0 4px 14px rgba(254, 214, 135, 0.05),
    0 2px 8px rgba(0, 0, 0, 0.45);
}
/* Featured card uses the dual-gradient bg — swap the dark stop on hover. */
.rr-news-card.is-featured:hover {
  background:
    linear-gradient(180deg, rgba(18, 18, 18, 0) 0%, #121212 100%),
    linear-gradient(90deg, rgba(18, 18, 18, 0.5) 0%, rgba(18, 18, 18, 0.5) 100%) !important;
}
/* Small cards use solid rgba(18,18,18,0.4) — darken to #121212 on hover. */
.rr-news-card.is-small:hover {
  background: #121212 !important;
}

/* FAQ card interactive states.
   - Idle: standard #242424 border + dark bg (handled inline in HTML).
   - Hover: subtle gold border tint + 2px translate up + soft warm glow.
     Reads as "this is clickable" without competing with the section.
   - Open (.is-open toggled by Alpine): brighter gold border + inset
     gold ring (0 0 0 1px) for double-edge accent, plus a soft halo. */
.rr-faq-card {
  transition:
    transform 280ms ease-out,
    border-color 280ms ease-out,
    box-shadow 280ms ease-out,
    background 280ms ease-out;
}
.rr-faq-card:hover {
  /* Match news cards' Figma hover bg #121212 (darker than idle 0.40 black). */
  background: #121212 !important;
  transform: translateY(-2px);
  border-color: rgba(254, 214, 135, 0.4);
  box-shadow:
    0 4px 14px rgba(254, 214, 135, 0.05),
    0 2px 8px rgba(0, 0, 0, 0.45);
}
.rr-faq-card.is-open {
  /* lg:min-h-[90px] allows the card to grow naturally with the
     answer-wrap's grid-rows transition — no need to override height,
     and no "vai-e-volta" drop from instant h:fixed → h:auto on open. */
  border-color: rgba(254, 214, 135, 0.45);
  box-shadow:
    0 0 0 1px rgba(254, 214, 135, 0.15),
    0 6px 20px rgba(254, 214, 135, 0.04),
    0 4px 12px rgba(0, 0, 0, 0.5);
}
.rr-faq-card.is-open:hover {
  transform: translateY(-2px);
}

.hero-bottom-fade {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 320px;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(26, 26, 26, 0.4) 35%,
    rgba(26, 26, 26, 0.85) 70%,
    #1a1a1a 100%
  );
}

@media (prefers-reduced-motion: reduce) {
  .hero-bg-pulse { animation: none; opacity: 0; }
}

/* Hero atmosphere: drifting mist + slow falling embers.
   Both layers are absolute siblings inside [data-name="hero"] (which is
   `relative overflow-hidden`). Pointer-events: none so they never block
   clicks on the play button / CTA / socials underneath.
   `prefers-reduced-motion` collapses both to static (no animation), and
   particle spawning is skipped entirely in the x-init guard. */
.hero-mist,
.hero-particles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  overflow: hidden;
}

/* Particles share the fog's air space: screen blend lets each ember
   add warm light to the mist where they overlap (instead of sitting
   on top as crisp dots), and a sub-pixel blur softens them so they
   read as glowing motes diffused by the fog rather than hard sparks. */
.hero-particles {
  mix-blend-mode: screen;
  filter: blur(0.6px);
}

/* Real fog: three pre-rendered PNG cloud-texture layers (danielstuart14
   /CSS_FOG_ANIMATION pattern). Each layer is 200% viewport width with
   two 50%-wide tiles of the same texture inside; animating `left` from
   0 to -100% slides the layer one viewport-width left while the second
   tile takes over the visible area — invisible seamless loop.
   Two animations per layer: opacity breathing (each at different timing
   so layers fade independently) + lateral drift. The wrapper filter
   tints the fog warm and softens it into clouds.
   The radial mask carves a soft transparent hole over the CTA region
   so the fog never obscures the title / ink stain / Wishlist button. */
.hero-mist {
  width: 100%;
  height: 100%;
  filter: blur(1px) grayscale(0.18) saturate(1.1) sepia(0.18);
  -webkit-mask-image: radial-gradient(
    ellipse 30% 30% at 50% 56%,
    transparent 0%,
    transparent 50%,
    rgba(0, 0, 0, 0.55) 78%,
    #000 100%
  );
          mask-image: radial-gradient(
    ellipse 30% 30% at 50% 56%,
    transparent 0%,
    transparent 50%,
    rgba(0, 0, 0, 0.55) 78%,
    #000 100%
  );
}

.hero-mist .fog {
  position: absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 100%;
}

.hero-mist .fog .image01,
.hero-mist .fog .image02 {
  float: left;
  height: 100%;
  width: 50%;
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
}

.hero-mist #foglayer_01 .image01,
.hero-mist #foglayer_01 .image02 {
  background-image: url('imgs/fog1.png');
}
.hero-mist #foglayer_02 .image01,
.hero-mist #foglayer_02 .image02,
.hero-mist #foglayer_03 .image01,
.hero-mist #foglayer_03 .image02 {
  background-image: url('imgs/fog2.png');
}

.hero-mist #foglayer_01 {
  animation:
    foglayer_01_opacity 18s linear infinite,
    foglayer_moveme 44s linear infinite;
}
.hero-mist #foglayer_02 {
  animation:
    foglayer_02_opacity 26s linear infinite,
    foglayer_moveme 36s linear infinite;
}
.hero-mist #foglayer_03 {
  animation:
    foglayer_03_opacity 22s linear infinite,
    foglayer_moveme 52s linear infinite;
}

@keyframes foglayer_01_opacity {
  0%   { opacity: 0.10; }
  22%  { opacity: 0.50; }
  40%  { opacity: 0.28; }
  58%  { opacity: 0.40; }
  80%  { opacity: 0.16; }
  100% { opacity: 0.10; }
}
@keyframes foglayer_02_opacity {
  0%   { opacity: 0.50; }
  25%  { opacity: 0.20; }
  50%  { opacity: 0.10; }
  80%  { opacity: 0.30; }
  100% { opacity: 0.50; }
}
@keyframes foglayer_03_opacity {
  0%   { opacity: 0.45; }
  27%  { opacity: 0.18; }
  52%  { opacity: 0.36; }
  68%  { opacity: 0.22; }
  100% { opacity: 0.45; }
}
@keyframes foglayer_moveme {
  0%   { left: 0; }
  100% { left: -100%; }
}

/* Fire ember: warm radial gradient core + box-shadow halo for glow.
   Three motion patterns (assigned per-particle in x-init):
   - rise: bottom-up, wind biases horizontally (--p-wind-x)
   - drift: horizontal cross-wind from off-screen edges, --p-wind-x
     positive = enters from left, negative = enters from right.
   --p-sway adds a small per-particle perturbation on top of the wind
   vector so paths curve instead of being straight lines. */
.hero-particle {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: radial-gradient(circle, #FFE6B0 0%, #FFB35A 30%, #D9531E 70%, transparent 100%);
  box-shadow:
    0 0 6px rgba(255, 179, 90, 0.85),
    0 0 14px rgba(217, 83, 30, 0.6),
    0 0 22px rgba(217, 83, 30, 0.3);
  opacity: 0;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  will-change: transform, opacity;
}

@keyframes hero-particle-rise {
  0% {
    transform: translate3d(0, 0, 0) scale(0.4);
    opacity: 0;
  }
  10% {
    opacity: var(--p-opacity, 0.55);
  }
  30% {
    transform: translate3d(
      calc(var(--p-wind-x, 0px) * 0.22 + var(--p-sway, 0px) *  0.5),
      calc(var(--p-rise, -800px) * 0.28),
      0
    ) scale(0.9);
  }
  55% {
    transform: translate3d(
      calc(var(--p-wind-x, 0px) * 0.5 + var(--p-sway, 0px) * -0.6),
      calc(var(--p-rise, -800px) * 0.55),
      0
    ) scale(1);
  }
  82% {
    transform: translate3d(
      calc(var(--p-wind-x, 0px) * 0.82 + var(--p-sway, 0px) *  0.7),
      calc(var(--p-rise, -800px) * 0.82),
      0
    ) scale(0.7);
    opacity: calc(var(--p-opacity, 0.55) * 0.7);
  }
  100% {
    transform: translate3d(var(--p-wind-x, 0px), var(--p-rise, -800px), 0) scale(0.35);
    opacity: 0;
  }
}

@keyframes hero-particle-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(0.4);
    opacity: 0;
  }
  14% {
    opacity: var(--p-opacity, 0.55);
  }
  50% {
    transform: translate3d(
      calc(var(--p-wind-x, 1500px) * 0.5),
      calc(var(--p-rise, -120px) * 0.5 + var(--p-sway, 0px)),
      0
    ) scale(0.95);
  }
  82% {
    transform: translate3d(
      calc(var(--p-wind-x, 1500px) * 0.85),
      calc(var(--p-rise, -120px) * 0.85 + var(--p-sway, 0px) * -0.7),
      0
    ) scale(0.75);
    opacity: calc(var(--p-opacity, 0.55) * 0.55);
  }
  100% {
    transform: translate3d(var(--p-wind-x, 1500px), var(--p-rise, -120px), 0) scale(0.4);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-mist { animation: none; }
  .hero-particle { animation: none; opacity: 0; }
}

/* Trailer frame: 16:9 player with thin gold ornament lines top + bottom.
   Each line is a horizontal gradient fading at the ends + a soft glow,
   plus a small diamond accent at center to break the pure-line silhouette
   (Elden Ring-style "gold dust" feel without raster textures). Pseudos
   sit just outside the player edges so they read as a frame ornament
   rather than overlapping the video. */
.rr-trailer-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #0a0a0a;
}

.rr-trailer-frame > button,
.rr-trailer-frame > iframe {
  border-radius: 2px;
}

.rr-trailer-frame::before,
.rr-trailer-frame::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(254, 214, 135, 0) 4%,
    rgba(254, 214, 135, 0.45) 22%,
    rgba(254, 214, 135, 0.95) 50%,
    rgba(254, 214, 135, 0.45) 78%,
    rgba(254, 214, 135, 0) 96%,
    transparent 100%
  );
  box-shadow:
    0 0 6px rgba(254, 214, 135, 0.55),
    0 0 14px rgba(254, 214, 135, 0.28),
    0 0 28px rgba(254, 214, 135, 0.12);
}
.rr-trailer-frame::before { top: -2px; }
.rr-trailer-frame::after  { top: 100%; }

/* Diamond accents at center of each gold line — small rotated squares
   with the same gold gradient. Both top + bottom use the SAME transform
   so they read as identical mirror points instead of subtly different. */
.rr-trailer-ornament {
  position: absolute;
  left: 50%;
  width: 10px;
  height: 10px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: linear-gradient(180deg, #FED687 0%, #9A7340 100%);
  box-shadow:
    0 0 6px rgba(254, 214, 135, 0.7),
    0 0 14px rgba(254, 214, 135, 0.3);
  pointer-events: none;
}
.rr-trailer-ornament.is-top    { top: -1px; }
.rr-trailer-ornament.is-bottom { top: calc(100% + 1px); }

/* Play button: gold-gradient ring with dark interior disc, matching the
   site's gold buttons elsewhere (rr-display-gold, hero CTA frame). The
   ring is the parent's bg gradient; ::before pseudo carves the inner
   dark disc 2px inset, leaving a visible gold ring. */
.rr-trailer-play {
  width: 78px;
  height: 78px;
  border-radius: 50%;
  background: var(--rr-gradient-gold);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 240ms ease-out, box-shadow 240ms ease-out;
  box-shadow:
    0 0 0 0 rgba(254, 214, 135, 0),
    0 4px 16px rgba(0, 0, 0, 0.45);
}

.rr-trailer-play::before {
  content: '';
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: rgba(18, 18, 18, 0.78);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 0;
  transition: background-color 240ms ease-out;
}

.rr-trailer-play svg {
  position: relative;
  z-index: 1;
  /* SVG path already has built-in optical compensation
     (centroid 0.33 right of viewBox center) — no padding nudge. */
}

.rr-trailer-frame > button:hover .rr-trailer-play,
.rr-trailer-frame > button:focus-visible .rr-trailer-play {
  transform: scale(1.06);
  box-shadow:
    0 0 22px rgba(254, 214, 135, 0.5),
    0 0 44px rgba(254, 214, 135, 0.2),
    0 4px 16px rgba(0, 0, 0, 0.45);
}
.rr-trailer-frame > button:hover .rr-trailer-play::before,
.rr-trailer-frame > button:focus-visible .rr-trailer-play::before {
  background: rgba(28, 22, 12, 0.78);
}

/* Dim overlay on the loop video — gives the user a visual nudge that
   the "real" trailer is one click away (the dimmed preview reads as a
   teaser, not the final picture). Slight vignette via radial mix:
   uniform base + a subtle darkening at the corners. On hover the dim
   eases off, suggesting the click will brighten the video. */
.rr-trailer-frame > button::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 90% 90% at 50% 50%, rgba(0,0,0,0.18) 40%, rgba(0,0,0,0.46) 100%),
    rgba(0, 0, 0, 0.22);
  pointer-events: none;
  transition: opacity 240ms ease-out;
}
.rr-trailer-frame > button:hover::before,
.rr-trailer-frame > button:focus-visible::before {
  opacity: 0.55;
}

/* Heroes ambient lighting — two soft radials substituting for the hard
   scrims. Each radial is positioned at a text region, sized in section
   coordinates so the fade extends across the whole section width
   without a bounding rectangle to clip it. No visible edge: the alpha
   fades all the way to 0 well before reaching the section boundary,
   inside the same plane as the splash and bg.
   z-index 5 sits above splash (3) and bg (2), below text (10).
   The vertical mask only softens the top/bottom of the section where
   it meets adjacent sections. */
#heroes::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      ellipse 32% 60% at 19% 50%,
      rgba(var(--rr-fade-dark), 0.7) 0%,
      transparent 100%
    ),
    radial-gradient(
      ellipse 26% 42% at 80% 24%,
      rgba(var(--rr-fade-dark), 0.85) 0%,
      transparent 100%
    );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 12%,
    #000 88%,
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    #000 12%,
    #000 88%,
    transparent 100%
  );
  pointer-events: none;
  z-index: 5;
}

/* Mobile menu link hover — simpler than .rr-link's dual-layer cross-fade
   to avoid the visible position shift the pseudo overlay caused on long
   characters with accents. Stays in a single text run, just animates the
   background-clip:text gradient by toggling background-size on hover.
   Both states use the SAME element + glyphs, so there's no jump. */
.rr-menu-link {
  font-family: var(--font-body);
  color: var(--text-primary);
  font-feature-settings: 'liga' off, 'clig' off;
  background-image: var(--rr-gradient-gold);
  background-clip: text;
  -webkit-background-clip: text;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: center;
  transition: color 220ms ease, -webkit-text-fill-color 220ms ease;
}
.rr-menu-link:hover,
.rr-menu-link:focus-visible {
  color: transparent;
  -webkit-text-fill-color: transparent;
}

/* rr-fade-feather mask now active on mobile too — softens the splash
   edges into the dark section background the same way it does on desktop.
   (Previously disabled on mobile when the image used object-cover; with
   object-contain on mobile the image fills the container exactly, so the
   mask sits flush against the visible edges and reads as a soft border.) */

/* Hero navigation: idle vs selected state.
   Idle items sit flush-left with the eyebrow ("GATHER YOUR PARTY"). When a
   hero is selected, the caret fades in to the LEFT of the label and the
   label slides right (padding-left) to leave room for the caret. Hover
   only restyles the text (white + glow). Same row-shift choreography on
   mobile + desktop — only the slide distance differs to match the smaller
   mobile type. */
[data-name="hero-item"] {
  position: relative;
  padding-left: 0;
  transition: padding-left 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}
[data-name="hero-item"].hero-item-active {
  padding-left: 42px;
}

[data-name="caret-faq"] {
  position: absolute;
  left: 0;
  top: 50%;
  opacity: 0;
  transform: translate(-12px, -50%);
  transition:
    opacity 0.28s ease-in,
    transform 0.28s ease-in;
}
[data-name="caret-faq"].caret-active {
  opacity: 1;
  transform: translate(0, -50%);
  transition:
    opacity 0.45s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

@media (min-width: 1024px) {
  [data-name="hero-item"].hero-item-active {
    padding-left: 50px;
  }
}

@keyframes scrollBounce {
  0%, 100% { transform: translateY(-8px); }
  50% { transform: translateY(8px); }
}

.animate-scroll-bounce {
  animation: scrollBounce 2s ease-in-out infinite;
}

/* News Article Content Styles */
.news-content-styles h1 {
  /* container/title-h1 */
  display: flex;
  padding: 1.5rem 1rem;
  justify-content: center;
  align-items: center;
  font-family: Lora;
  font-size: 1.5rem; /* 24px */
  font-style: normal;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  background: var(--rr-gradient-gold-alt);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  font-feature-settings: 'liga' off, 'clig' off;
  margin-top: 1.5rem;
}

@media (min-width: 1024px) {
  .news-content-styles h1 {
    padding: 1.5rem 12rem; /* 192px on desktop */
  }
}

.news-content-styles h2 {
  /* container/subtitle-h2 */
  display: flex;
  padding: 1.5rem 1rem;
  justify-content: center;
  align-items: center;
  font-family: Lora;
  font-size: 1.25rem; /* 20px */
  font-style: normal;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  background: var(--rr-gradient-gold-alt);
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  font-feature-settings: 'liga' off, 'clig' off;
  margin-top: 1.5rem;
}

@media (min-width: 1024px) {
  .news-content-styles h2 {
    padding: 1.5rem 12rem; /* 192px on desktop */
  }
}

.news-content-styles p {
  /* desktop/body-article */
  align-self: stretch;
  color: #F3F3F3;
  font-family: Lora;
  font-size: 1rem; /* 16px mobile */
  font-style: normal;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.02em;
  font-feature-settings: 'liga' off, 'clig' off;
  margin-bottom: 1rem;
}

@media (min-width: 768px) {
  .news-content-styles p {
    font-size: 1.125rem; /* 18px desktop */
  }
}

.news-content-styles p:last-child {
  margin-bottom: 0;
}

.news-content-styles img {
  height: auto;
  align-self: stretch;
  aspect-ratio: 922 / 519.09;
  background: lightgray 50% / cover no-repeat;
  margin: 1rem 0;
  width: 100%;
  object-fit: cover;
}
