/*3D Tunnel Experience*/

.tunnel-experience *,
.tunnel-experience *::before,
.tunnel-experience *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* .tunnel-experience IS the <body> element — body_class() puts the class there
   in WordPress, and index.html does the same locally. These rules used to be
   written as ".tunnel-experience html, .tunnel-experience body", which can
   never match (there is no html/body INSIDE body), so the reset silently did
   nothing and the theme's own body margin was left in place. */
.tunnel-experience {
  margin: 0;
  padding: 0;
  width: 100%;
  min-height: 100vh;
  overflow: hidden;          /* body overflow propagates to the viewport */
  background: #0d0e11;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;

  --accent: #1E5AA8;   /* Adrosonic deep blue */
  --ink: rgba(255, 255, 255, 0.92);
  --ink-dim: rgba(255, 255, 255, 0.45);
  --font: 'Space Grotesk', 'Arial', sans-serif;

  /* Design-system tokens, named as the Figma file names them. */
  --adro-electric: #00CCFF;   /* ADROSONIC Electric blue — Secondary */
  --adro-white:    #FFFFFF;   /* ADROSONIC White-Base */
  /* The scroll prompt is specified in Montserrat, not the Space Grotesk the
     rest of the page uses. Space Grotesk is the fallback so the hint still
     renders in a sane face if the Montserrat request is ever dropped. */
  --font-hint: 'Montserrat', 'Space Grotesk', 'Arial', sans-serif;
  /* The loading screen is set in Zalando Sans Expanded, the display face the
     design file specifies. Space Grotesk falls back into its place if the
     Google Fonts request is ever dropped. */
  --font-display: 'Zalando Sans Expanded', 'Space Grotesk', 'Arial', sans-serif;
}

.tunnel-experience .webgl {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}


/* ------------------------------------------------------------
   SITE LOGO — the page's only navigation.

   One asset: the site's own header logo (white wordmark on transparency,
   272 x 54 with its own built-in padding), so this page and the Astra header
   are never two different logos that drift apart.

   Sized by width alone, height auto, so the lockup can never be distorted and
   a replacement asset of different proportions still renders correctly. It is
   deliberately LARGER here than in the site header: this page is a full-bleed
   scene, not a header bar, and the same 272px that fills a header bar reads as
   a small sticker against the tunnel.
   ------------------------------------------------------------ */
.tunnel-experience #site-logo {
  /* 320px from ~1500px up, easing to 165px on a phone. This is the one number
     to change if the logo wants to be bigger or smaller. */
  --logo-w: clamp(165px, calc(14vw + 110px), 320px);

  position: fixed;
  /* ABOVE the loader (9999), not below it: main.js also reveals this link when
     the scene FAILS to load, and an escape hatch behind the failed loading
     screen would be no escape at all. */
  z-index: 10000;
  top:  calc(clamp(14px, 1.4vw, 20px) + env(safe-area-inset-top, 0px));
  left: calc(clamp(18px, 2.4vw, 36px) + env(safe-area-inset-left, 0px));

  display: block;
  text-decoration: none;
  color: #fff;                  /* only reached by the alt-text fallback below */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Negative margin cancels the padding, so the padding only grows the tap
     target without shifting the logo off its designed position. */
  padding: 10px;
  margin: -10px;

  /* Prefer NOT to put a `filter` on this element.
     ------------------------------------------------------------
     It sits over a full-screen WebGL canvas that repaints every frame, and a
     filter makes the compositor build a render surface for the overlay and
     re-run the filter pass on each of those repaints.

     Measured, because the first attempt at measuring this was wrong and it is
     worth recording how: unpaired A/B runs suggested drop-shadow was costing
     ~15fps, but that was monitorPerf()'s quality ladder stepping down DURING
     the experiment, not the filter. Re-measured with PAIRED samples after
     letting the ladder bottom out, the honest cost is ~1fps under a 6x CPU
     throttle (32.4 vs 31.3fps, the no-filter arm winning 9 of 14 pairs), and
     nothing at all unthrottled at 1920x1080.

     So: a drop shadow here is affordable, but it buys little — this corner of
     the scene is dark and the vignette darkens it further — and it is the one
     property most likely to hurt on a weak GPU. It is left off. If the logo
     ever needs separating from a bright background, prefer a static
     `background: radial-gradient(...)`: a plain paint on an already-promoted
     layer, with no per-frame filter pass. */

  /* Its own compositor layer, so the canvas repainting underneath never drags
     the logo into a re-raster — it stays a cached quad. Measured at zero cost
     either way at 1920x1080; this is insurance for weaker GPUs. */
  will-change: transform;

  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  /* Delayed so the fade-in starts after the loading screen is most of the way
     out, instead of the two brand marks overlapping at the same corner. */
  transition: opacity 0.8s ease 0.35s,
              transform 0.8s cubic-bezier(0.22, 1, 0.36, 1) 0.35s;
}

.tunnel-experience #site-logo.show {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.tunnel-experience #site-logo-img {
  display: block;
  width: var(--logo-w);
  height: auto;
  /* Hover/active live on the IMAGE: the anchor's own opacity carries the
     reveal transition, and reusing it here would inherit that 0.35s delay. */
  transition: opacity 0.28s ease;
}

.tunnel-experience #site-logo:hover  #site-logo-img { opacity: 0.7; }
.tunnel-experience #site-logo:active #site-logo-img { opacity: 0.55; }

.tunnel-experience #site-logo:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.9);
  outline-offset: 2px;
  border-radius: 6px;
}

/* If the image 404s, main.js swaps it for a <span> carrying its alt text. The
   link has to keep working — it is the way off this page — so the text is
   dressed as a wordmark rather than left as a broken-image caption. */
.tunnel-experience #site-logo-img.failed {
  width: auto;
  font: 700 clamp(15px, 1.4vw, 20px)/1 var(--font);
  letter-spacing: 5px;
  color: #fff;
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .tunnel-experience #site-logo {
    transform: none;
    transition: opacity 0.2s linear;
  }
  .tunnel-experience #site-logo.show { transform: none; }
}


/* ------------------------------------------------------------
   LOADING SCREEN

   Design reference, frame 1922 x 843:
     heading   Zalando Sans Expanded 600 / 64px on a 78px line, #FFF
     gap       71px
     status    Zalando Sans Expanded 400 / 32px on a 39px line, #00CCFF
     gap       30px
     bar       390 x 2, white track

   Every one of those sizes is a multiple of the 32px status size, so the
   block is driven by a single font-size on .loader-inner and written in em
   from there. Changing that one clamp rescales the whole composition.
   ------------------------------------------------------------ */
.tunnel-experience #loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  /* Fallback backdrop, shown until the artwork loads and where WebGL is
     unavailable. */
  background:
    radial-gradient(ellipse 120% 62% at 52% 30%,
                    rgba(46, 68, 102, 0.55) 0%, transparent 70%),
    linear-gradient(180deg, #070c15 0%, #0b1220 38%, #05080e 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  transition: opacity 0.9s ease;
}

.tunnel-experience #loader.hide {
  opacity: 0;
  pointer-events: none;
}

/* ------------------------------------------------------------
   BACKDROP

   Two layers. `.loader-bg-still` is the design artwork exported with its
   lenticular effect already baked in; it is always present and does not
   move. `.loader-bg-live` is a canvas above it running the same effect in
   a shader, animated over a 2s loop. The canvas is only used when the
   pre-effect source layer is supplied; otherwise the still remains.
   ------------------------------------------------------------ */
.tunnel-experience #loader-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

/* background-image is applied by main.js: in WordPress the file lives in the
   Media Library, so a relative URL here would resolve against the theme. */
.tunnel-experience .loader-bg-still {
  position: absolute;
  inset: 0;
  background-position: center center;
  background-repeat: no-repeat;
  /* cover: the artwork is 2.28:1 and centred, so a taller viewport crops
     the margins rather than letterboxing. */
  background-size: cover;
}

.tunnel-experience .loader-bg-live {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  /* Revealed only once the first rendered frame is on the canvas. */
  transition: opacity 0.45s ease;
}

.tunnel-experience .loader-bg-live.show { opacity: 1; }

/* The still is hidden once the canvas is live. The canvas is transparent
   where the shader has not painted, so leaving the still underneath would
   blend a baked frame into a rendered one. */
.tunnel-experience #loader-bg.live .loader-bg-still {
  opacity: 0;
  transition: opacity 0.45s ease;
}

.tunnel-experience .loader-inner {
  /* Base size for the block: 32px at the reference width, 15px on a phone.
     Pure vw between the bounds so the heading keeps a constant share of the
     viewport width. */
  font-size: clamp(15px, 1.665vw, 32px);

  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 92vw;
  /* The design sits the block slightly below centre. Doubled because a top
     margin on a centred flex item shifts it by half the value. */
  margin-top: 2vh;
}

.tunnel-experience .slogan {
  font-family: var(--font-display);
  font-size: 2em;                    /* Figma: 64 */
  font-weight: 600;
  line-height: 1.219;                /* Figma: 78 / 64 */
  text-transform: capitalize;        /* Figma: capitalize */
  color: var(--adro-white);
  margin-bottom: 1.109em;            /* Figma: 71 / 64 */
  /* Shrink to fit so the reveal below clips the text edge rather than a
     full-width block's. */
  width: max-content;
  max-width: 100%;
}

/* Typed reveal. main.js sets --slogan-chars from the heading's own text
   length; the fallback covers the frame before that runs. */
.tunnel-experience .slogan {
  animation: tunnelType calc(var(--slogan-chars, 38) * 32ms)
             steps(var(--slogan-chars, 38), end) 0.25s both;
}

@keyframes tunnelType {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

.tunnel-experience #progress {
  font-family: var(--font-display);
  font-size: 1em;                    /* Figma: 32 */
  font-weight: 400;
  line-height: 1.219;                /* Figma: 39 / 32 */
  color: var(--adro-electric);       /* Figma: #00CCFF */
  margin-bottom: 0.9375em;           /* Figma: 30 / 32 */
  white-space: nowrap;
  opacity: 0;
  animation: tunnelFadeUp 1s ease 0.15s forwards;
}

.tunnel-experience .loader-track {
  /* Figma: 390 x 2, white. The clamp stops it collapsing on small
     viewports. */
  width: clamp(220px, 12.1875em, 390px);
  max-width: 78vw;
  height: 2px;
  background: var(--adro-white);
  overflow: hidden;
  opacity: 0;
  animation: tunnelFadeUp 1s ease 0.15s forwards;
}

/* Progress fill: electric blue over the white track. */
.tunnel-experience #loader-bar {
  height: 100%;
  width: 0%;
  background: var(--adro-electric);
  transition: width 0.25s ease;
}

@keyframes tunnelFadeUp {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Below this width the heading wraps, and a right-edge clip across several
   lines reads as a wipe rather than typing. Use the fade-up instead. */
@media (max-width: 1024px) {
  .tunnel-experience .slogan {
    width: auto;
    white-space: normal;
    text-wrap: balance;
    clip-path: none;
    opacity: 0;
    animation: tunnelFadeUp 1.1s cubic-bezier(0.22, 1, 0.36, 1) 0.1s forwards;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tunnel-experience .slogan,
  .tunnel-experience #progress,
  .tunnel-experience .loader-track {
    animation: none;
    opacity: 1;
    clip-path: none;
    transform: none;
  }
}


.tunnel-experience #vignette {
  position: fixed;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background: radial-gradient(ellipse 130% 100% at 50% 45%,
              transparent 58%, rgba(4, 5, 8, 0.5) 100%);
}


/* ------------------------------------------------------------
   SCROLL PROMPT — label above, mouse capsule below.

   Figma: text Montserrat 300 / 18px, 18px gap, capsule 25 x 42 with rx 12.5
   (rx = half the width, so it is a full pill), fill #144074 at 21%, 1px stroke
   #00CCFF at 10%, and a 10 x 6 chevron in Electric blue.

   Every size is derived from ONE number, --cap-w, so the whole prompt scales
   as a unit and keeps the design's proportions at any viewport.
   ------------------------------------------------------------ */
.tunnel-experience #hint {
  --cap-w: clamp(21px, 1.7vw, 25px);

  position: fixed;
  bottom: calc(clamp(24px, 3.2vh, 38px) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%) translateY(14px);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 1.2vw, 18px);          /* Figma: 18 */
  opacity: 0;
  transition: opacity 0.9s ease, transform 0.9s ease;
  pointer-events: none;
}

.tunnel-experience #hint.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.tunnel-experience #hint-text {
  font-family: var(--font-hint);
  font-size: clamp(14px, 1.25vw, 18px);   /* Figma: 18 */
  font-weight: 300;
  line-height: normal;
  color: var(--adro-white);
  text-align: center;
  white-space: nowrap;
}

/* The capsule. Drawn, not uploaded: a rounded box with a fill and a 1px
   stroke is precisely border-radius + background + border. 999px gives the
   same full pill as Figma's rx 12.5 on a 25-wide box, at any size. */
.tunnel-experience .hint-mouse {
  width: var(--cap-w);
  height: calc(var(--cap-w) * 42 / 25);
  flex: none;
  border-radius: 999px;
  background: rgba(20, 64, 116, 0.21);          /* #144074 @ 21% */
  border: 1px solid rgba(0, 204, 255, 0.10);    /* #00CCFF @ 10% */
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--adro-electric);                  /* the chevron inherits this */
}

/* The chevron's artboard is 12 x 8 and its ink spans 10 x 6 inside that, so
   sizing the SVG to 12/25 of the capsule width lands the visible chevron on
   Figma's 10 x 6 exactly when the capsule is at its full 25px. */
.tunnel-experience .hint-arrow {
  display: block;
  width: calc(var(--cap-w) * 12 / 25);
  height: auto;
}

/* The chevron rises, bottom to top — the direction the camera travels when you
   scroll forward, so the prompt shows the gesture rather than just naming it.

   Two deliberate performance choices, because this sits over a WebGL canvas
   that repaints every frame:
     1. ONLY transform and opacity are animated. Both are compositor-only, so
        the loop never triggers layout or paint over the scene.
     2. The animation is declared on `.show` alone. noteInteraction() drops
        that class on the visitor's first scroll, which STOPS the animation
        outright rather than merely hiding it — the old .hint-line drip kept
        ticking behind opacity: 0 for the rest of the visit. */
.tunnel-experience #hint.show .hint-arrow {
  --arrow-travel: calc(var(--cap-w) * 0.32);    /* ~8px at full size */
  will-change: transform, opacity;
  animation: tunnelScrollArrow 1.9s cubic-bezier(0.33, 0, 0.2, 1) infinite;
}

@keyframes tunnelScrollArrow {
  0%   { transform: translateY(var(--arrow-travel));               opacity: 0; }
  20%  { transform: translateY(calc(var(--arrow-travel) *  0.45)); opacity: 1; }
  70%  { transform: translateY(calc(var(--arrow-travel) * -0.8));  opacity: 1; }
  100% { transform: translateY(calc(var(--arrow-travel) * -1));    opacity: 0; }
}

/* No animation wanted: the chevron simply rests centred, which is exactly the
   static Figma composition. Nothing else needs overriding. */
@media (prefers-reduced-motion: reduce) {
  .tunnel-experience #hint.show .hint-arrow { animation: none; }
}
