/* RiypeGsap.css */

#riype-section {
  --riype-bg: #000000;
  --riype-surface: #1e1e1e;
  --riype-surface-2: #141414;
  --riype-ink: #ffffff;
  --riype-muted: rgba(255, 255, 255, 0.55);
  --riype-faint: rgba(255, 255, 255, 0.2);
  --riype-hair: rgba(255, 255, 255, 0.1);
  --riype-accent: #8fa876;
  --riype-accent-dim: #5c6e4a;
  --riype-warm: #c9a15a;

  --riype-font:
    "Poppins", "Inter", "SF Pro Display", -apple-system, BlinkMacSystemFont,
    sans-serif;

  --riype-tracking-tight: -0.02em;
  --riype-tracking-wide: 0.08em;
  --riype-tracking-wider: 0.2em;
  --riype-tracking-widest: 0.4em;

  --riype-stage-w: 1920px;
  --riype-stage-h: 1080px;

  position: relative;
  background: var(--riype-bg);
  padding: 0;
  margin: 0;
  display: block;
}

#riype-section * {
  box-sizing: border-box;
}

/* ---------------------------------------------------------------------
   FILM / STAGE / CAMERA / WORLD
   (DESKTOP + MOBILE-LANDSCAPE — completely unchanged from the original.
   Portrait-mobile overrides live in the dedicated media query far below
   and convert these into a fluid, non-scaled layout instead.)
   --------------------------------------------------------------------- */
.riype-film {
  position: relative;
  width: 100%;
  background: var(--riype-bg);
}

.riype-stage {
  position: sticky;
  top: 0;
  z-index: 10;

  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: var(--riype-bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.riype-camera {
  position: relative;
  width: var(--riype-stage-w);
  height: var(--riype-stage-h);
  flex: none;
  perspective: 1400px;
  perspective-origin: 50% 50%;
  transform-origin: center center;
  overflow: hidden;
}

.riype-world {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

.riype-layer {
  position: absolute;
  inset: 0;
}

.riype-layer-grid {
  transform: translateZ(-40px);
  opacity: 0.05;
}
.riype-grid-svg {
  width: 100%;
  height: 100%;
}
.riype-grid-svg line {
  stroke: #ffffff;
  stroke-width: 1;
}

.riype-corner-marks {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 40;
  opacity: 0.35;
}
.riype-corner {
  position: absolute;
  width: 22px;
  height: 22px;
  fill: none;
}
.riype-corner path {
  fill: none;
  stroke: var(--riype-muted);
  stroke-width: 1.5;
}
.riype-corner.tl {
  top: 48px;
  left: 48px;
}
.riype-corner.tr {
  top: 48px;
  right: 48px;
  transform: rotate(90deg);
}
.riype-corner.br {
  bottom: 48px;
  right: 48px;
  transform: rotate(180deg);
}
.riype-corner.bl {
  bottom: 48px;
  left: 48px;
  transform: rotate(270deg);
}

/* ---------------------------------------------------------------------
   BEATS
   --------------------------------------------------------------------- */
.riype-beat {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}

/* BEAT 01 — OPENING */
.riype-particle-field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.riype-particle-field circle {
  fill: var(--riype-muted);
}

.riype-opening-label {
  position: absolute;
  font-family: var(--riype-font);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: var(--riype-tracking-widest);
  text-transform: uppercase;
  color: var(--riype-muted);
  opacity: 0;
}

.riype-center-line {
  position: absolute;
  left: 960px;
  top: 0;
  width: 1px;
  height: 1080px;
  background: var(--riype-hair);
  opacity: 0;
}

/* BEAT 02 — TITLE */
.riype-beat-title {
  display: flex;
  align-items: center;
  justify-content: center;
}
.riype-title-block {
  text-align: center;
}
.riype-big-title {
  margin: 0;
  display: flex;
  justify-content: center;
  gap: 0.14em;
  font-weight: 700;
  font-size: 220px;
  line-height: 1;
  letter-spacing: var(--riype-tracking-tight);
  color: var(--riype-ink);
}
.riype-big-title .riype-char {
  display: inline-block;
  transform: translateY(55%);
  opacity: 0;
}
.riype-subtitle {
  margin: 28px 0 0;
  font-weight: 500;
  font-size: 26px;
  letter-spacing: var(--riype-tracking-wider);
  color: var(--riype-muted);
  text-transform: uppercase;
  display: flex;
  justify-content: center;
  gap: 0.5em;
  flex-wrap: wrap;
}
.riype-subtitle .riype-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(10px);
}

/* BEAT 03 — FRUIT / DEVICE / SCAN */
.riype-fruit-wrap,
.riype-device-wrap {
  position: absolute;
  width: 340px;
  opacity: 0;
}
.riype-fruit-svg,
.riype-device-svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}
.riype-scan-beam-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.riype-tech-label {
  position: absolute;
  font-family: var(--riype-font);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: var(--riype-tracking-widest);
  text-transform: uppercase;
  color: var(--riype-muted);
  opacity: 0;
}

/* BEAT 04 — SENSOR DATA */
.riype-data-stream {
  position: absolute;
  width: 600px;
  opacity: 0;
}
.riype-data-label {
  font-family: var(--riype-font);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: var(--riype-tracking-wider);
  text-transform: uppercase;
  color: var(--riype-muted);
  margin-bottom: 6px;
}
.riype-data-svg {
  width: 100%;
  height: 64px;
  overflow: visible;
}
.riype-numeric-ticker {
  position: absolute;
  font-family: var(--riype-font);
  font-weight: 600;
  font-size: 20px;
  color: var(--riype-ink);
  font-variant-numeric: tabular-nums;
  opacity: 0;
}
.riype-numeric-ticker .riype-unit {
  font-weight: 500;
  color: var(--riype-muted);
}

/* BEAT 05 — PROCESSING / CONVERGENCE */
.riype-convergence-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* BEAT 06 — NEURAL NETWORK */
.riype-network-wrap {
  position: absolute;
}
.riype-network-svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}
.riype-network-svg line {
  stroke: var(--riype-hair);
  stroke-width: 1;
  opacity: 0.55;
}
.riype-network-svg circle.riype-node {
  fill: var(--riype-faint);
}
.riype-network-svg circle.riype-pulse {
  fill: var(--riype-accent);
}

/* BEAT 07 — RESULT */
.riype-beat-result {
  display: flex;
  align-items: center;
  justify-content: center;
}
.riype-result-layout {
  display: flex;
  align-items: center;
  gap: 48px;
  opacity: 0;
}
.riype-check-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  opacity: 0;
}
.riype-checkmark {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--riype-accent);
  color: #0a0f06;
  font-size: 26px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.riype-metric-sublabel {
  margin: 0;
  font-family: var(--riype-font);
  font-weight: 500;
  font-size: 15px;
  letter-spacing: var(--riype-tracking-wider);
  text-transform: uppercase;
  color: var(--riype-muted);
  white-space: nowrap;
}
.riype-device-screen {
  position: relative;
  width: 320px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.riype-screen-bezel {
  width: 320px;
  height: 240px;
  background: var(--riype-surface-2);
  border: 2px solid var(--riype-hair);
  border-radius: 18px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.riype-screen-inner {
  text-align: center;
  padding: 16px;
}
.riype-metric-value {
  font-family: var(--riype-font);
  font-weight: 700;
  font-size: 72px;
  line-height: 1;
  color: var(--riype-warm);
  letter-spacing: var(--riype-tracking-tight);
  margin: 0;
  opacity: 0;
  transform: translateY(20px);
}
.riype-metric-label {
  margin-top: 10px;
  font-family: var(--riype-font);
  font-weight: 500;
  font-size: 18px;
  letter-spacing: var(--riype-tracking-wider);
  text-transform: uppercase;
  color: var(--riype-accent);
  opacity: 0;
}
.riype-screen-buttons {
  display: flex;
  gap: 10px;
  justify-content: center;
  width: 100%;
}
.riype-screen-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: transparent;
  border: 1.5px solid var(--riype-hair);
  border-radius: 10px;
  padding: 8px 10px;
  font-family: var(--riype-font);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--riype-muted);
  cursor: pointer;
  opacity: 0;
  transition:
    border-color 0.2s,
    color 0.2s;
  min-width: 64px;
  flex: 1;
}
.riype-screen-btn .riype-btn-icon {
  font-size: 16px;
  line-height: 1;
  color: var(--riype-accent);
}
.riype-screen-btn:hover,
.riype-screen-btn:focus-visible {
  border-color: var(--riype-accent);
  color: var(--riype-ink);
}
.riype-screen-btn:focus-visible {
  outline: 2px solid var(--riype-accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   Persistent chrome (eyebrow + CTA), pinned above the film, screen-space
   --------------------------------------------------------------------- */
.riype-chrome {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 45;
  pointer-events: none;
}
.riype-chrome-top {
  top: 0;
  padding: 40px 48px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.riype-num {
  font-family: var(--riype-font);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: var(--riype-tracking-wide);
  color: var(--riype-faint);
}
.riype-eyebrow-desc {
  font-family: var(--riype-font);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--riype-tracking-wide);
  text-transform: uppercase;
  color: var(--riype-faint);
}
.riype-chrome-bottom {
  bottom: 0;
  padding: 0 48px 44px;
  display: flex;
  justify-content: center;
}
.riype-chrome-bottom .riype-cta-wrap {
  pointer-events: all;
  text-align: center;
}
.riype-project-summary {
  max-width: 640px;
  margin: 0 auto 20px;
  font-family: var(--riype-font);
  font-size: 15px;
  line-height: 1.7;
  color: var(--riype-muted);
  font-weight: 300;
}
.riype-btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: #fff;
  color: #000;
  font-weight: 700;
  font-size: 15px;
  padding: 16px 28px;
  border-radius: 100px;
  text-decoration: none;
  transition:
    transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.25s;
  border: none;
}
.riype-btn-primary:hover {
  transform: translateY(-3px);
  opacity: 0.88;
}
.riype-btn-primary:focus-visible {
  outline: 2px solid var(--riype-accent);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------------
   RESPONSIVE — small-screen chrome padding (applies to all narrow
   viewports, orientation-agnostic; unchanged from the original file).
   --------------------------------------------------------------------- */
@media (max-width: 720px) {
  .riype-corner {
    width: 14px;
    height: 14px;
  }
  .riype-corner.tl,
  .riype-corner.tr {
    top: 20px;
  }
  .riype-corner.bl,
  .riype-corner.br {
    bottom: 20px;
  }
  .riype-corner.tl,
  .riype-corner.bl {
    left: 20px;
  }
  .riype-corner.tr,
  .riype-corner.br {
    right: 20px;
  }
  .riype-chrome-top {
    padding: 20px 20px;
  }
  .riype-chrome-bottom {
    padding: 0 20px 24px;
  }
  .riype-project-summary {
    font-size: 13px;
  }
  .riype-btn-primary {
    padding: 14px 22px;
    font-size: 14px;
  }
}

/* =======================================================================
   MOBILE PORTRAIT — OPTION B: FLUID LAYOUT (no fixed-canvas scaling)
   =======================================================================

   STRATEGY (see JS for the matching half — fitStage() now no-ops on
   portrait mobile, camera scale is fixed at 1 and CSS takes over):

   This deliberately abandons the "shrink a 1920×1080 canvas to fit a
   phone" model that every previous pass fought with. Instead, following
   CourierGuard's proven approach:

     1. .riype-camera and .riype-world stop being a fixed 1920×1080 box.
        They become fluid (100% / 100dvh), matching .riype-stage exactly
        — there is no scale transform to fight anymore.

     2. Every beat becomes a normal, centered flex column
        (display:flex; flex-direction:column; align-items:center;
        justify-content:center; gap:...) with max-width:92vw — the same
        shape as CourierGuard's .cg-layer. Elements inside a beat switch
        from `position:absolute; left:Npx; top:Npx` (canvas coordinates)
        to `position:static` and rely on flex gap/order for placement.

     3. Typography switches to clamp()-based fluid units instead of
        fixed px, so text scales smoothly with the viewport rather than
        being pinned to one canvas-derived size — exactly CourierGuard's
        .cg-xl / .cg-lg / .cg-md pattern.

     4. SVGs that carry meaningful internal coordinate systems (the
        neural network's 1000×620 viewBox, the data-stream 600×64
        waveform viewBoxes, the convergence-line 1920×1080 overlay) KEEP
        their viewBox math completely untouched, per your constraint —
        only their WRAPPER becomes fluid-width (width:100%, max-width
        capped) so the SVG scales the way `<svg width="100%">` already
        naturally does in CourierGuard, without any JS-driven canvas
        scale involved.

     5. GSAP's animations are unaffected: the master timeline still
        tweens `opacity`, `y`, SVG `attr`, and text content on the exact
        same element IDs. None of those tweens set `left`/`top`/canvas
        position directly (verified against RiypeGsap.js — the only
        positional tweens are relative `x` deltas on
        #riypeDataFruitWrap and internal SVG `attr` changes), so
        switching the CSS positioning model out from under them doesn't
        conflict with anything GSAP is doing.

   Desktop and mobile-landscape are completely unaffected: none of this
   is reachable outside `(max-width: 720px) and (orientation: portrait)`,
   and JS's fitStage() branch for that case is a no-op that leaves scale
   at 1 rather than computing anything — see RiypeGsap.js.
   ========================================================================= */
@media (max-width: 720px) and (orientation: portrait) {
  .riype-stage {
    height: 100dvh;
    max-width: 100vw;
    overflow: hidden;
  }

  .riype-camera {
    /* No more fixed 1920×1080 box, no more scale transform (JS leaves
       scale at 1 on this path — see fitStage()). The camera now simply
       IS the viewport.

       IMPORTANT: the base (desktop) rule sets `flex: none` so the
       fixed 1920px box never shrinks inside .riype-stage's flex
       layout. That flex:none is still active here and was never
       reset, so `width:100%` was being measured unreliably against a
       flex item that thinks it isn't allowed to flex — this is the
       actual cause of the left/right overflow, not the SVG content.
       Resetting flex + adding an explicit max-width:100vw backstop
       guarantees the camera can never exceed the viewport regardless
       of how the flex sizing resolves. */
    flex: 1 1 auto;
    width: 100%;
    max-width: 100vw;
    height: 100%;
    perspective: none;
    overflow: hidden;
  }

  .riype-world {
    /* No transform-style/3D needed once the camera dolly system is
       inert on this path; keep inset:0 so beats can still fill it. */
    position: absolute;
    inset: 0;
    max-width: 100vw;
    overflow: hidden;
  }

  /* -----------------------------------------------------------------
     BEATS BECOME CENTERED FLEX COLUMNS
     Every beat keeps `position:absolute; inset:0` (from the base
     rule) so the existing opacity-based beat crossfades still work
     unchanged — only its INTERNAL layout becomes flex instead of a
     blank canvas that children position themselves on with left/top.
     ----------------------------------------------------------------- */
  .riype-beat {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    padding: 0 6vw;
    text-align: center;
  }

  /* -----------------------------------------------------------------
     BEAT 01 — OPENING
     The four corner labels and center line are a landscape-only
     composition device (spread across a wide canvas) that has no
     equivalent meaning on a narrow phone. On mobile portrait they
     collapse into a single small stacked label group instead of
     trying to preserve four separate screen-quadrant positions.
     ----------------------------------------------------------------- */
  .riype-particle-field {
    /* Ambient background particles still work as a full-bleed layer. */
    position: absolute;
    inset: 0;
  }
  .riype-opening-label {
    position: static;
    font-size: clamp(0.7rem, 3.4vw, 0.85rem);
    letter-spacing: var(--riype-tracking-wider);
  }
  .riype-center-line {
    display: none; /* landscape-only compositional device */
  }

  /* -----------------------------------------------------------------
     BEAT 02 — TITLE
     Already flex-centered on desktop; just switch to fluid type.
     ----------------------------------------------------------------- */
  .riype-big-title {
    font-size: clamp(2.4rem, 20vw, 4.6rem);
    gap: 0.08em;
    flex-wrap: wrap;
  }
  .riype-subtitle {
    font-size: clamp(0.85rem, 3.6vw, 1.15rem);
    margin-top: 14px;
    gap: 0.4em;
  }

  /* -----------------------------------------------------------------
     BEAT 03 — FRUIT / DEVICE / SCAN
     Desktop shows fruit and device side by side across a wide canvas;
     on mobile they stack vertically, both centered, which reads
     naturally as "device scans fruit" top-to-bottom instead of
     left-to-right.
     ----------------------------------------------------------------- */
  .riype-fruit-wrap,
  .riype-device-wrap {
    position: static;
    width: min(60vw, 260px);
    opacity: 0; /* GSAP still controls this via fromTo/to */
  }
  .riype-scan-beam-svg {
    display: none; /* landscape-only beam between two side-by-side elements */
  }
  .riype-tech-label {
    position: static;
    font-size: clamp(0.7rem, 3.4vw, 0.85rem);
  }

  /* -----------------------------------------------------------------
     BEAT 04 — SENSOR DATA
     Desktop shows the fruit on the left and four data-stream rows with
     right-aligned tickers stretching across a 1920-wide canvas. On
     mobile this becomes a single centered column: fruit, then each
     stream with its ticker directly beneath (not far to the right).
     ----------------------------------------------------------------- */
  .riype-data-fruit-wrap,
  #riypeDataFruitWrap {
    position: static !important;
    width: min(50vw, 200px);
  }
  .riype-data-stream {
    position: static;
    width: min(84vw, 420px);
  }
  .riype-data-label {
    font-size: clamp(0.62rem, 2.8vw, 0.75rem);
  }
  .riype-numeric-ticker {
    /* Hidden on mobile — the data streams alone carry the "sensor
       data" story without the numeric readouts. */
    display: none;
  }
  .riype-fruit-svg {
    /* Hide the fruit illustration itself; its wrapper stays in the DOM
       (GSAP still tweens its opacity harmlessly) so no layout gap. */
    display: none;
  }
  #riypeBeatData {
    /* Base .riype-beat rule already centers via flex; reinforced here
       now that the ticker/fruit removal leaves only the data streams,
       so the remaining column reads as centered content, not a
       leftover left-aligned block. */
    align-items: center;
    text-align: center;
  }

  /* -----------------------------------------------------------------
     BEAT 05 — PROCESSING / CONVERGENCE
     The three-inputs-converge-on-one-point story is inherently a
     landscape composition (lines drawing horizontally across a wide
     canvas toward a target). On mobile, replace it with a simpler,
     equally clear vertical story: the three input labels stack, each
     with a short vertical connector, converging downward onto the
     multimodal label — same narrative, portrait-native shape. The SVG
     convergence lines (which have desktop-specific x1/y1/x2/y2 targets
     baked into the GSAP timeline) are hidden on mobile; the labels
     alone, stacked with connecting visual rhythm via spacing/opacity,
     carry the story instead.
     ----------------------------------------------------------------- */
  .riype-convergence-svg {
    display: none;
  }
  #riypeLabelCV,
  #riypeLabelSpec,
  #riypeLabelSensorData,
  #riypeLabelMultimodal {
    position: static !important;
    font-size: clamp(0.7rem, 3.4vw, 0.85rem);
  }
  #riypeLabelMultimodal {
    margin-top: 10px;
    color: var(--riype-ink);
    font-weight: 600;
  }

  /* -----------------------------------------------------------------
     BEAT 06 — NEURAL NETWORK
     The SVG's internal 1000×620 viewBox and all node/connection math
     are untouched (per constraint) — only the wrapper goes fluid so
     the SVG scales via width:100% the way any CourierGuard diagram
     does, instead of being a fixed-px absolute box inside a scaled
     camera.
     ----------------------------------------------------------------- */
  #riypeLabelNetTitle,
  #riypeLabelInference {
    /* These carry inline left/top/transform from the HTML (canvas
       coordinates like left:960px; top:970px), which the fluid
       mobile layout doesn't use — left uncorrected they push content
       outside the viewport, causing Beat 06 to overflow. !important is
       required to beat the inline style's specificity. */
    position: static !important;
    left: auto !important;
    top: auto !important;
    transform: none !important;
  }
  #riypeLabelNetTitle {
    font-size: clamp(0.75rem, 3.2vw, 0.95rem);
  }
  .riype-network-wrap {
    position: static;
    width: min(92vw, 620px);
    max-width: 100%;
    height: auto;
    aspect-ratio: 1000 / 620;
    overflow: hidden;
    /* The base .riype-network-svg rule sets overflow:visible, which on
       desktop is needed so GSAP's later scale-down of #riypeNetworkWrap
       (scale:0.55 in createNetworkTimeline) still reads against the
       wide canvas. On mobile the wrapper is fluid-width and centered
       instead of sitting on a 1920px canvas with room to spare, so
       that same overflow:visible lets the SVG's content bleed past the
       wrapper's edges into the viewport sides. Clip it here instead —
       the network's node/connection geometry is comfortably inside its
       own 1000×620 viewBox, so clipping the wrapper doesn't cut off
       any of the diagram itself. */
  }
  .riype-network-svg {
    overflow: hidden;
  }
  #riypeLabelInference {
    font-size: clamp(0.68rem, 3vw, 0.8rem);
  }

  /* -----------------------------------------------------------------
     BEAT 07 — RESULT
     Already flex-based on desktop (.riype-result-layout uses
     display:flex); just stack it vertically and enlarge typography.
     ----------------------------------------------------------------- */
  .riype-result-layout {
    flex-direction: column;
    gap: 24px;
  }
  .riype-device-screen,
  .riype-screen-bezel {
    width: min(80vw, 300px);
  }
  .riype-screen-bezel {
    height: auto;
    aspect-ratio: 320 / 240;
  }
  .riype-metric-value {
    font-size: clamp(2.8rem, 16vw, 4.5rem);
  }
  .riype-metric-label {
    font-size: clamp(0.85rem, 3.8vw, 1.05rem);
  }
  .riype-metric-sublabel {
    font-size: clamp(0.68rem, 3vw, 0.8rem);
  }
  .riype-screen-btn {
    font-size: clamp(0.55rem, 2.4vw, 0.65rem);
    padding: 8px 6px;
    min-width: 0;
  }

  /* -----------------------------------------------------------------
     Chrome bottom CTA: prevent the summary/CTA from feeling cramped
     ----------------------------------------------------------------- */
  .riype-chrome-bottom .riype-cta-wrap {
    max-width: 92vw;
  }
  .riype-project-summary {
    max-width: 440px;
  }
}

/* ---------------------------------------------------------------------
   MOBILE LANDSCAPE — explicit no-op vs. the portrait block above. A
   landscape phone behaves like a small desktop under the unchanged
   min(vw/1920, vh/1080) letterbox fit, which is already correct here.
   --------------------------------------------------------------------- */
@media (max-width: 720px) and (orientation: landscape) {
  /* Intentionally empty. */
}

/* ---------------------------------------------------------------------
   REDUCED MOTION — disable pin/scrub, keep content readable & static
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .riype-film {
    height: auto !important;
  }
  .riype-stage {
    position: relative;
    height: auto;
    min-height: 100vh;
    padding: 100px 24px;
  }
  .riype-camera {
    transform: none !important;
    width: 100%;
    max-width: 900px;
    height: auto;
    perspective: none;
  }
  .riype-world {
    position: relative;
    transform: none !important;
  }
  .riype-beat {
    position: relative;
    opacity: 1 !important;
    inset: auto;
    display: block;
    margin-bottom: 56px;
  }
  .riype-layer-grid,
  .riype-corner-marks,
  .riype-particle-field,
  .riype-center-line,
  .riype-scan-beam-svg {
    display: none;
  }
  .riype-big-title {
    font-size: clamp(3rem, 12vw, 6rem);
    flex-wrap: wrap;
  }
  .riype-big-title .riype-char,
  .riype-subtitle .riype-word,
  .riype-fruit-wrap,
  .riype-device-wrap,
  .riype-tech-label,
  .riype-data-stream,
  .riype-numeric-ticker,
  .riype-network-wrap,
  .riype-result-layout,
  .riype-check-group,
  .riype-metric-value,
  .riype-metric-label,
  .riype-screen-btn {
    opacity: 1 !important;
    transform: none !important;
  }
  .riype-fruit-wrap,
  .riype-device-wrap,
  .riype-tech-label,
  .riype-data-stream,
  .riype-numeric-ticker,
  .riype-network-wrap {
    position: relative;
    left: auto !important;
    top: auto !important;
    margin: 16px auto;
  }
  .riype-result-layout {
    flex-wrap: wrap;
    justify-content: center;
  }
  .riype-chrome {
    position: relative;
  }
}