/* =========================================================================
   APPLICATION PORTAL — style.css
   Layout, components, and the design-token system.
   Motion keyframes live in animations.css.
   ========================================================================= */

/* -------------------------------------------------------------------------
   TYPED CUSTOM PROPERTIES
   Registering these lets the browser interpolate them, so CSS transitions and
   keyframes can animate the composed card transform smoothly. The card's
   `transform` is built once from these; sway (CSS) and tilt (JS) only ever
   write numbers into them, so nothing fights over `transform`.
   ------------------------------------------------------------------------- */
@property --sway-x   { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --sway-rot { syntax: "<angle>";  inherits: false; initial-value: 0deg; }
@property --tilt-x   { syntax: "<angle>";  inherits: false; initial-value: 0deg; }
@property --tilt-y   { syntax: "<angle>";  inherits: false; initial-value: 0deg; }
@property --lift     { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --scale    { syntax: "<number>"; inherits: false; initial-value: 1; }

/* -------------------------------------------------------------------------
   DESIGN TOKENS
   Single source of truth for color, spacing, radius, shadow, glow and timing.
   ------------------------------------------------------------------------- */
:root {
  /* Water palette — bright, shallow, sunlit (matches the reference art).
     Kept light and airy so the water reads as translucent, not solid.
     Nudge --water-mid / --water-deep darker for a deeper, denser look. */
  --water-sky:      #f0faff;   /* just above the surface        */
  --water-shallow:  #ddf4fd;   /* directly under the surface    */
  --water-mid:      #c4ecfb;   /* mid column                    */
  --water-deep:     #a3e0f5;   /* toward the floor              */
  --water-glow:     #f8feff;   /* the bright central shaft      */

  /* Interface blues */
  --accent:         #0a95ff;   /* card fill / title             */
  --accent-bright:  #33b1ff;   /* highlights                    */
  --accent-deep:    #0066cc;   /* pressed / depth               */
  --glow:           #59c8ff;   /* the color light bleeds as     */

  /* Neutrals */
  --white:          #ffffff;
  --ink:            #063b63;   /* readable deep-blue text       */
  --border-glass:   rgba(255, 255, 255, 0.65);

  /* Glass surfaces */
  --glass-fill:     rgba(56, 168, 240, 0.28);
  --glass-fill-hi:  rgba(120, 205, 255, 0.42);
  --footer-fill:    rgba(120, 205, 255, 0.30);

  /* Spacing scale */
  --space-xs: 0.5rem;
  --space-sm: 1rem;
  --space-md: 1.75rem;
  --space-lg: 3rem;
  --space-xl: 5rem;

  /* Radius */
  --radius-card: 20px;
  --radius-pill: 999px;

  /* Shadows & glow */
  --shadow-soft:  0 18px 40px rgba(4, 60, 100, 0.22);
  --shadow-lift:  0 34px 70px rgba(4, 60, 100, 0.34);
  --glow-card:    0 0 0 1px rgba(255,255,255,0.55),
                  0 0 34px 6px rgba(89, 200, 255, 0.55);

  /* Motion durations (kept here so timing can be tuned in one place) */
  --sway-duration:   7s;
  --wave-duration:   55s;  /* slow, gentle waves — raise for slower, lower for faster (default was 14s) */
  --ray-duration:    12s;
  --caustic-duration:26s;
  --fog-duration:    60s;
  --shimmer-cycle:   9s;

  /* Focus ring */
  --focus-ring: 0 0 0 3px rgba(255, 255, 255, 0.9),
                0 0 0 6px rgba(10, 149, 255, 0.9);
}

/* -------------------------------------------------------------------------
   RESET / BASE
   ------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: "Segoe UI", "Helvetica Neue", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  overflow: hidden;               /* the scene is full-bleed; nothing scrolls */
  background: var(--water-shallow);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Anything decorative should never intercept pointer events */
.scene,
.scene *,
.bubbles { pointer-events: none; }

/* =========================================================================
   SCENE LAYERS
   ========================================================================= */
.scene {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

/* Vertical water column. A radial "shaft" of light brightens the centre,
   echoing the sunlit core in the reference art. */
.scene__water {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 80% at 50% 62%,
      var(--water-glow) 0%,
      transparent 55%),
    linear-gradient(to bottom,
      var(--water-sky)     0%,
      var(--water-shallow) 26%,
      var(--water-mid)     60%,
      var(--water-deep)    100%);
}

/* Ambient breathing light. water.js updates --ambient (0..1); only this
   overlay's opacity changes, which the compositor handles cheaply. */
.scene__water::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(90% 60% at 50% 20%,
      rgba(255, 255, 255, 0.6) 0%,
      transparent 60%);
  opacity: calc(var(--ambient, 0.5) * 0.4);
  will-change: opacity;
}

/* Layer stacking (back -> front) */
.scene__rays      { position: absolute; inset: 0; z-index: 2; overflow: hidden; }
.scene__caustics  { position: absolute; inset: 0; z-index: 3;
                    mix-blend-mode: screen; opacity: 0.5; }
.scene__fog       { position: absolute; inset: 0; z-index: 4; }
.scene__surface   { position: absolute; left: 0; right: 0; top: 0;
                    height: 46%; z-index: 5; }
.scene__particles { position: absolute; inset: 0; z-index: 6; }

/* --- God rays -------------------------------------------------------------
   Each ray is a soft, blurred parallelogram fanning down from the surface.
   Individual sway timing is set per-ray in animations.css. */
.ray {
  position: absolute;
  top: -12%;
  width: 14vw;
  height: 130%;
  background: linear-gradient(to bottom,
      rgba(255, 255, 255, 0.85),
      rgba(255, 255, 255, 0.0));
  filter: blur(22px);
  opacity: 0.12;
  transform-origin: top center;
  mix-blend-mode: screen;
  will-change: transform, opacity;
}
.ray--1 { left: 8%;  }
.ray--2 { left: 28%; width: 10vw; }
.ray--3 { left: 48%; width: 18vw; }
.ray--4 { left: 68%; width: 11vw; }
.ray--5 { left: 84%; }

/* --- Caustics -------------------------------------------------------------
   A tiled, procedurally-drawn light net (data-URI SVG) that slowly crawls.
   `screen` blend + low opacity keeps it as light, never as texture. */
.scene__caustics::before {
  content: "";
  position: absolute;
  inset: -30%;
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='300' height='300'>\
<filter id='t'>\
<feTurbulence type='fractalNoise' baseFrequency='0.012 0.02' numOctaves='2' seed='7'/>\
<feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 1.6 -0.5'/>\
<feGaussianBlur stdDeviation='2'/>\
</filter>\
<rect width='100%25' height='100%25' filter='url(%23t)'/>\
</svg>");
  background-size: 46% 46%;
  will-change: transform;
}

/* --- Fog ------------------------------------------------------------------ */
.fog {
  position: absolute;
  width: 65vw;
  height: 60vh;
  border-radius: 50%;
  background: radial-gradient(circle,
      rgba(255, 255, 255, 0.5) 0%,
      rgba(255, 255, 255, 0.0) 70%);
  filter: blur(40px);
  opacity: 0.22;
  will-change: transform;
}
.fog--1 { top: 22%; left: -20%; }
.fog--2 { top: 48%; left: 55%; }

/* =========================================================================
   BUBBLES
   Positioned from the top-left; bubbles.js drives transform + opacity.
   The glassy look comes from an off-centre highlight + a faint rim.
   ========================================================================= */
.bubbles {
  position: fixed;
  inset: 0;
  z-index: 8;                      /* above the scene, below the content */
  overflow: hidden;
}
.bubble {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.25) 22%,
      rgba(180, 226, 255, 0.10) 48%,
      rgba(120, 200, 255, 0.04) 70%);
  box-shadow:
    inset 0 0 6px rgba(255, 255, 255, 0.5),
    inset -2px -2px 5px rgba(60, 150, 220, 0.25);
  will-change: transform, opacity;
  contain: layout style paint;    /* isolate each bubble from layout cost */
}

/* =========================================================================
   PAGE CONTENT
   ========================================================================= */
.page {
  position: relative;
  z-index: 10;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding: var(--space-lg) var(--space-md) 0;
}

/* --- Masthead / title ----------------------------------------------------- */
.masthead {
  text-align: center;
  padding-block: var(--space-xs) var(--space-md);
}

/* Logo scales fluidly with the viewport, matching the card sizing pattern. */
.masthead__logo {
  display: block;
  margin: 0 auto clamp(0.6rem, 1.8vw, 1.2rem);
  width: clamp(280px, 53vw, 620px);
  height: auto;
  max-width: 100%;
}

.title {
  --shimmer-x: -30%;
  position: relative;
  margin: 0;
  font-size: clamp(1.8rem, 4.4vw, 3.4rem);
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--accent);
  text-transform: uppercase;
  text-shadow:
    0 2px 0 rgba(255, 255, 255, 0.55),
    0 8px 26px rgba(10, 149, 255, 0.35);
}

/* The shimmer is a bright gradient clipped to the text and swept across.
   It sits in ::before so it never affects the readable base text. */
.title::before {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg,
      transparent 30%,
      rgba(255, 255, 255, 0.95) 48%,
      rgba(210, 240, 255, 0.9) 52%,
      transparent 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  background-size: 300% 100%;
  background-position: var(--shimmer-x) 0;
  pointer-events: none;
}

/* --- Stage / card grid ---------------------------------------------------- */
.stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cards {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  max-width: 1180px;
  display: flex;
  flex-wrap: wrap;                 /* wraps responsively on narrow screens */
  justify-content: center;
  gap: clamp(1rem, 2.4vw, 2.2rem);
}

/* Card container is a list item; the interactive surface is the <a> inside. */
.card {
  flex: 0 1 240px;
  perspective: 900px;              /* enables the hover tilt in 3D */
}

.card__link {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  min-height: 150px;
  padding: var(--space-md) 28px;
  text-decoration: none;
  color: var(--white);
  text-align: center;

  /* Glassmorphism: semi-transparent blue acrylic + backdrop blur */
  /* Glassmorphism fill. The two colours come from per-card custom properties
     (--card-hi / --card-lo) and fall back to the shared blue tokens, so a card
     is recoloured just by setting those two vars in the HTML. Keep the colours
     semi-transparent (alpha < 1) or you lose the frosted-glass look. */
  background:
    linear-gradient(150deg,
      var(--card-hi, var(--glass-fill-hi)) 0%,
      var(--card-lo, var(--glass-fill)) 60%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid var(--border-glass);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-soft),
              inset 0 1px 0 rgba(255, 255, 255, 0.6);

  /* One composed transform, built from the typed custom properties above.
     Only transform/opacity/box-shadow ever animate here — never width/height.
     Order: idle sway -> hover lift -> mouse-tilt (in 3D) -> hover scale. */
  transform:
    translate3d(var(--sway-x), 0, 0)
    rotate(var(--sway-rot))
    translateY(var(--lift))
    perspective(900px)
    rotateX(var(--tilt-x))
    rotateY(var(--tilt-y))
    scale(var(--scale));
  transition:
    box-shadow 0.35s ease,
    background 0.35s ease,
    --scale 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    --lift  0.4s cubic-bezier(0.22, 1, 0.36, 1),
    --tilt-x 0.2s ease-out,
    --tilt-y 0.2s ease-out;
  will-change: transform;
  cursor: pointer;
}

/* Moving light shimmer that glides across the glass */
.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(115deg,
      transparent 40%,
      rgba(255, 255, 255, 0.35) 50%,
      transparent 60%);
  background-size: 250% 100%;
  background-position: 150% 0;
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.card__image {
  width: 100%;                     /* fills the card, leaving the 28px link padding on each side */
  height: auto;
  object-fit: contain;             /* never distorts whatever image you drop in */
  border-radius: 16px;
  filter: drop-shadow(0 4px 12px rgba(4, 60, 100, 0.35));
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;            /* clicks/tilt pass through to the link */
}

.card__title {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-shadow: 0 1px 4px rgba(4, 60, 100, 0.4);
}

/* Hover / focus: scale up, lift, glow, reveal shimmer, raise above siblings.
   :focus-visible mirrors :hover so keyboard users get the same affordance. */
.card__link:hover,
.card__link:focus-visible {
  --scale: 1.28;                   /* per brief: scale to 128% */
  --lift: -10px;
  /* Brighten the card's OWN colour on hover: a white wash sits over the same
     per-card fill, so a green card lightens to green, a blue one to blue, etc. */
  background:
    linear-gradient(150deg, rgba(255,255,255,0.28), rgba(255,255,255,0.06)),
    linear-gradient(150deg,
      var(--card-hi, var(--glass-fill-hi)) 0%,
      var(--card-lo, var(--glass-fill)) 60%);
  box-shadow: var(--shadow-lift), var(--glow-card),
              inset 0 1px 0 rgba(255, 255, 255, 0.75);
}
.card:hover,
.card:focus-within { z-index: 5; } /* hovered card sits cleanly on top */

.card__link:hover::after,
.card__link:focus-visible::after {
  opacity: 1;
  animation: glass-shimmer 1.1s ease forwards;
}

.card__link:focus-visible {
  outline: none;
  box-shadow: var(--shadow-lift), var(--focus-ring);
}

/* Host layer for ripple rings spawned by ripple.js */
.card__ripples {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
}

/* =========================================================================
   FOOTER
   ========================================================================= */
.footer {
  position: relative;
  z-index: 10;
  margin-top: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);

  background: var(--footer-fill);
  -webkit-backdrop-filter: blur(10px) saturate(130%);
  backdrop-filter: blur(10px) saturate(130%);
  border-top: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 -8px 30px rgba(4, 60, 100, 0.18);
  overflow: hidden;
}

/* A slow band of light sweeps the footer — the "underwater reflection". */
.footer::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
      transparent 35%,
      rgba(255, 255, 255, 0.35) 50%,
      transparent 65%);
  background-size: 250% 100%;
  will-change: transform;
  animation: footer-reflect 8s linear infinite;
  pointer-events: none;
}

.footer__text {
  margin: 0;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-deep);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* --- Ambient sound toggle ------------------------------------------------- */
.sound-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.4rem 0.9rem;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-deep);
  background: rgba(255, 255, 255, 0.35);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background 0.25s ease, transform 0.25s ease;
}
.sound-toggle:hover { background: rgba(255, 255, 255, 0.55); }
.sound-toggle:active { transform: scale(0.96); }
.sound-toggle:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Speaker glyph drawn in CSS; the "on" bars appear when pressed. */
.sound-toggle__icon {
  position: relative;
  width: 12px;
  height: 12px;
  border-radius: 2px 0 0 2px;
  background: currentColor;
  box-shadow: 6px 0 0 -2px currentColor;
}
.sound-toggle__icon::after {
  content: "";
  position: absolute;
  left: 14px;
  top: 50%;
  width: 6px;
  height: 6px;
  border: 2px solid currentColor;
  border-left: 0;
  border-radius: 0 6px 6px 0;
  transform: translateY(-50%) scaleX(0);
  transform-origin: left center;
  transition: transform 0.25s ease;
}
.sound-toggle[aria-pressed="true"] .sound-toggle__icon::after {
  transform: translateY(-50%) scaleX(1);
}

/* =========================================================================
   RESPONSIVE
   ========================================================================= */
@media (max-width: 900px) {
  .cards { max-width: 560px; }
  .card  { flex: 0 1 220px; }
}

@media (max-width: 560px) {
  .page { padding-top: var(--space-md); }
  .card { flex: 1 1 100%; max-width: 320px; }
  .card__link:hover,
  .card__link:focus-visible { --scale: 1.12; } /* gentler on small screens */
  .footer { flex-direction: column; gap: var(--space-xs); }
}

/* =========================================================================
   ACCESSIBILITY: reduced motion
   Honour the OS preference by freezing ambient motion and heavy effects,
   while keeping the interface fully usable.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.12s !important;
  }
  .scene__caustics,
  .scene__particles,
  .bubbles { display: none; }
}
