/* ── Z-Index ──
 * Cross-cutting stacking values come from `js/layers.js`, which
 * injects them as `--z-*` custom properties on :root at bootstrap.
 * Use `z-index: var(--z-name)` for anything that has to stack against
 * another module's overlay; keep raw integers only for local stacking
 * (sibling nodes inside one component).  See js/layers.js for the
 * range table and naming.
 */

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

:root {
  --sky-0: #f0f7ff;
  --sky-1: #daeeff;
  --sky-2: #b5d9f7;
  --sky-3: #7dbfe8;
  --sky-4: #378add;
  --sky-5: #1a5fa8;
  --sky-6: #0c3d72;
  --ink: #0a1628;
  --ink-rgb: 10, 22, 40;
  --ink-mid: #1e3a5f;
  --mist: rgba(255, 255, 255, 0.55);
  --glass: rgba(255, 255, 255, 0.18);
  --glass-border: rgba(255, 255, 255, 0.35);
  /* Default accent for achievement toasts/cards when the set has no color.
     Deliberately NOT bound to --sky-4 so themes that retheme the sky
     (e.g. upside-down turns --sky-4 red) don't hijack unrelated toasts. */
  --achievement-default-accent: #378add;
}

/* ── Reduced Motion ──
   Users who request reduced motion (OS-level setting) get static visuals.
   Durations collapse to near-zero so transitions still settle end-state without
   animating; infinite keyframe animations pause on their first frame. Canvas
   dampening is handled in js/canvas.js. */
@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;
  }
}

/* ── Keyboard Focus Rings ── */
:focus-visible {
  outline-color: rgb(var(--theme-glow));
  outline-offset: 2px;
  animation: focusPulse 2s ease-in-out infinite;
}
@keyframes focusPulse {
  0%,
  100% {
    outline-color: rgba(var(--theme-glow), 0.4);
  }
  50% {
    outline-color: rgba(var(--theme-glow), 0.9);
  }
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: "Syne", sans-serif;
  background: var(--theme-bg);
  color: #fff;
  min-height: 100vh;
  overflow-x: hidden;
  --theme-primary: var(--sky-3);
  --theme-glow: 55, 138, 221;
  --theme-bg: var(--ink);
  --cursor-glow: var(--theme-glow);
  --logo-text-color: #fff;
  --logo-accent-color: var(--theme-primary);
}

/* OS cursor stays visible until cursor.js has both initialized and
   received its first mousemove — otherwise slow loads leave a window
   where neither cursor is showing. */
:where(body.has-custom-cursor),
:where(body.has-custom-cursor) :where(a, button, [role="button"], label) {
  cursor: none;
}

/* Custom cursor.
   --cursor-dot-size / --cursor-ring-size are registered so they
   interpolate smoothly when hover/press changes size. String-based
   idle animations (pendulum, metronome, yo-yo) read these vars for
   pivot offsets and rod-tip translations, so the dot keeps tracking
   the rod end even while the ring grows or shrinks. */
@property --cursor-dot-size {
  syntax: "<length>";
  inherits: true;
  initial-value: 12px;
}
@property --cursor-ring-size {
  syntax: "<length>";
  inherits: true;
  initial-value: 36px;
}
/* --rod-scale-y: ring's vertical scale factor when collapsed into a
   rod (pendulum, metronome, yo-yo). Registered so animations can
   interpolate it smoothly and the --rod-tip calc() cascades.
   Inherited so a single keyframe on :root can drive both the ring
   scaleY and the dot's derived translateY in lockstep. */
@property --rod-scale-y {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}
:root {
  --cursor-dot-size: 12px;
  --cursor-ring-size: 36px;
  /* Pivot points on the cursor column where rod-style idle animations
     hinge. Ring pivots via center top/bottom; the dot reaches the same
     point by translating its transform-origin by these offsets. */
  --cursor-pivot-top: calc(
    (var(--cursor-dot-size) - var(--cursor-ring-size)) / 2
  );
  --cursor-pivot-bottom: calc(
    (var(--cursor-dot-size) + var(--cursor-ring-size)) / 2
  );
  transition:
    --cursor-dot-size 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
    --cursor-ring-size 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
:root:has(#cursor.pressing) {
  transition:
    --cursor-dot-size 0.15s ease-out,
    --cursor-ring-size 0.15s ease-out;
}
#cursor {
  position: fixed;
  left: 0;
  top: 0;
  width: var(--cursor-dot-size);
  height: var(--cursor-dot-size);
  background: rgb(var(--cursor-glow));
  border-radius: var(--cursor-dot-radius, 50%);
  clip-path: var(--cursor-dot-clip, none);
  pointer-events: none;
  z-index: var(--z-cursor);
  will-change: translate;
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.3s;
}
/* Brand-default keeps the lighter sky dot for higher contrast on the dark
   canvas; themes follow the cascade through --cursor-glow. */
body:not([data-active-theme]) #cursor {
  background: var(--sky-3);
}
#cursor-ring {
  position: fixed;
  left: 0;
  top: 0;
  width: var(--cursor-ring-size);
  height: var(--cursor-ring-size);
  border-width: var(--cursor-ring-width, 1px);
  border-style: var(--cursor-ring-style, solid);
  border-color: rgba(var(--cursor-glow), 0.5);
  border-radius: var(--cursor-ring-radius, 50%);
  pointer-events: none;
  z-index: var(--z-cursor-ring);
  will-change: translate;
  animation: var(--cursor-ring-animation, none);
  opacity: 0;
  transition: opacity 0.3s;
}
#cursor.gravity-well {
  box-shadow: 0 0 calc(4px + 12px * var(--well-strength, 0))
    rgba(var(--cursor-glow), 0.6);
}
#cursor-ring.gravity-well::before {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  box-shadow: 0 0 12px rgba(var(--cursor-glow), 0.5);
  pointer-events: none;
  will-change: opacity;
  animation: well-breathe 2s ease-in-out infinite;
}
@keyframes well-breathe {
  0%,
  100% {
    opacity: 0.3;
  }
  50% {
    opacity: 1;
  }
}
@keyframes cursor-spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes cursor-wobble {
  0%,
  100% {
    transform: scale(1, 1);
  }
  33% {
    transform: scale(1.06, 0.95);
  }
  66% {
    transform: scale(0.95, 1.06);
  }
}
@keyframes cursor-ripple {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.2);
  }
}

/* ── Cursor Idle Animations ── */
@keyframes cursor-idle-blink {
  0%,
  30%,
  100% {
    opacity: 1;
  }
  15% {
    opacity: 0;
  }
}
#cursor.idle-blink {
  animation: cursor-idle-blink 4s ease-in-out infinite;
}

@keyframes cursor-idle-breathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.15);
  }
}
#cursor-ring.idle-breathe {
  animation: cursor-idle-breathe 4s ease-in-out infinite;
}

@keyframes cursor-idle-coin-spin-ring {
  0% {
    transform: perspective(100px) rotateY(0deg);
  }
  100% {
    transform: perspective(100px) rotateY(360deg);
  }
}
#cursor-ring.idle-coin-spin {
  animation: cursor-idle-coin-spin-ring 0.6s linear infinite;
}

@keyframes cursor-idle-drift {
  0% {
    transform: translate(0, 0);
  }
  25% {
    transform: translate(3px, -3px);
  }
  50% {
    transform: translate(0, -5px);
  }
  75% {
    transform: translate(-3px, -3px);
  }
  100% {
    transform: translate(0, 0);
  }
}
#cursor.idle-drift {
  animation: cursor-idle-drift 6s ease-in-out infinite;
}
#cursor-ring.idle-drift {
  animation: cursor-idle-drift 6s ease-in-out infinite;
  animation-delay: -1.5s;
}

/* Fidget spinner: ring becomes one of three lobes orbiting the dot
   (the bearing) at radius 18px. Two box-shadow copies render the
   other lobes in the element's local frame, so a single rotate()
   spins the tri-lobe silhouette around the cursor. Main lobe sits
   at (18, 0); shadow for lobe at angle φ is (18·cos φ − 18, 18·sin φ).
   φ = 120°: (−27, 15.59). φ = 240°: (−27, −15.59). */
@keyframes cursor-idle-fidget-spinner-intro {
  0% {
    width: 36px;
    height: 36px;
    background: transparent;
    border-color: rgba(var(--cursor-glow), 0.5);
    transform: translate(0, 0);
    box-shadow:
      0 0 0 rgba(var(--cursor-glow), 0),
      0 0 0 rgba(var(--cursor-glow), 0);
  }
  100% {
    width: 14px;
    height: 14px;
    background: rgba(var(--cursor-glow), 0.5);
    border-color: transparent;
    transform: translate(18px, 0);
    box-shadow:
      -27px 15.59px 0 rgba(var(--cursor-glow), 0.5),
      -27px -15.59px 0 rgba(var(--cursor-glow), 0.5);
  }
}
#cursor-ring.idle-fidget-spinner-intro {
  animation: cursor-idle-fidget-spinner-intro 0.5s ease-in forwards;
}

@keyframes cursor-idle-fidget-spinner {
  0% {
    transform: rotate(0deg) translate(18px, 0);
  }
  100% {
    transform: rotate(360deg) translate(18px, 0);
  }
}
#cursor-ring.idle-fidget-spinner {
  width: 14px;
  height: 14px;
  background: rgba(var(--cursor-glow), 0.5);
  border-color: transparent;
  box-shadow:
    -27px 15.59px 0 rgba(var(--cursor-glow), 0.5),
    -27px -15.59px 0 rgba(var(--cursor-glow), 0.5);
  animation: cursor-idle-fidget-spinner 0.9s linear infinite;
}

@keyframes cursor-idle-fidget-spinner-outro {
  0% {
    width: 14px;
    height: 14px;
    background: rgba(var(--cursor-glow), 0.5);
    border-color: transparent;
    transform: translate(18px, 0);
    box-shadow:
      -27px 15.59px 0 rgba(var(--cursor-glow), 0.5),
      -27px -15.59px 0 rgba(var(--cursor-glow), 0.5);
  }
  100% {
    width: 36px;
    height: 36px;
    background: transparent;
    border-color: rgba(var(--cursor-glow), 0.5);
    transform: translate(0, 0);
    box-shadow:
      0 0 0 rgba(var(--cursor-glow), 0),
      0 0 0 rgba(var(--cursor-glow), 0);
  }
}
#cursor-ring.idle-fidget-spinner-outro {
  animation: cursor-idle-fidget-spinner-outro 0.3s ease-out forwards;
}

@keyframes cursor-idle-hula-hoop-ring {
  0% {
    transform: translate(8px, 0) scale(1.06);
  }
  8% {
    transform: translate(7px, 4px) scale(1.03);
  }
  17% {
    transform: translate(4px, 7px) scale(0.97);
  }
  25% {
    transform: translate(0, 8px) scale(0.94);
  }
  33% {
    transform: translate(-4px, 7px) scale(0.97);
  }
  42% {
    transform: translate(-7px, 4px) scale(1.03);
  }
  50% {
    transform: translate(-8px, 0) scale(1.06);
  }
  58% {
    transform: translate(-7px, -4px) scale(1.03);
  }
  67% {
    transform: translate(-4px, -7px) scale(0.97);
  }
  75% {
    transform: translate(0, -8px) scale(0.94);
  }
  83% {
    transform: translate(4px, -7px) scale(0.97);
  }
  92% {
    transform: translate(7px, -4px) scale(1.03);
  }
  100% {
    transform: translate(8px, 0) scale(1.06);
  }
}
@keyframes cursor-idle-hula-hoop-dot {
  0% {
    transform: translate(-1.5px, 0);
  }
  25% {
    transform: translate(0, -1.5px);
  }
  50% {
    transform: translate(1.5px, 0);
  }
  75% {
    transform: translate(0, 1.5px);
  }
  100% {
    transform: translate(-1.5px, 0);
  }
}
#cursor-ring.idle-hula-hoop {
  animation: cursor-idle-hula-hoop-ring 0.8s linear infinite;
}
#cursor.idle-hula-hoop {
  animation: cursor-idle-hula-hoop-dot 0.8s ease-in-out infinite;
}

/* ── String-based idle animations (pendulum, metronome, yo-yo) ──

   All three collapse the ring into a vertical rod and attach the dot
   at its free tip. They share three invariants so hover/press size
   changes stay aligned automatically:

     1. Ring scaleY determines rod length. Default is --rod-scale-y
        (1.8 for pendulum & metronome; yo-yo overrides per keyframe).
     2. Rod tip sits at ring_size · (scaleY − 0.5) from the hinge pivot.
        --rod-tip encodes this so the dot's translateY matches.
     3. Dot's transform-origin is --cursor-pivot-top (ring top, for rods
        hanging below the cursor) or --cursor-pivot-bottom (for rods
        rising above), both defined on :root.

   To add a new rod-style animation: set --rod-tip on the dot rule,
   choose a pivot, and write paired keyframes. No pixel math required. */

#cursor-ring[class*="idle-pendulum"],
#cursor-ring[class*="idle-metronome"] {
  border-radius: 2px;
}
#cursor-ring[class*="idle-pendulum"],
#cursor[class*="idle-pendulum"],
#cursor-ring[class*="idle-metronome"],
#cursor[class*="idle-metronome"] {
  --rod-scale-y: 1.8;
}
#cursor-ring[class*="idle-pendulum"] {
  transform-origin: center top;
}
#cursor-ring[class*="idle-metronome"] {
  transform-origin: center bottom;
}
#cursor[class*="idle-pendulum"] {
  --rod-tip: calc(var(--cursor-ring-size) * (var(--rod-scale-y) - 0.5));
  transform-origin: 50% var(--cursor-pivot-top);
}
#cursor[class*="idle-metronome"] {
  --rod-tip: calc(var(--cursor-ring-size) * (var(--rod-scale-y) - 0.5) * -1);
  transform-origin: 50% var(--cursor-pivot-bottom);
}

/* Metronome: rod ticks back and forth above the cursor at a fixed
   tempo with a brief pause at each extreme. The weight dot rides
   the tip of the rod (rising upward via the negative --rod-tip). */
@keyframes cursor-idle-metronome-intro-ring {
  0% {
    transform: rotate(0deg) scaleX(1) scaleY(1);
    border-radius: 50%;
  }
  100% {
    transform: rotate(-18deg) scaleX(0.1) scaleY(var(--rod-scale-y));
    border-radius: 2px;
  }
}
@keyframes cursor-idle-metronome-intro-dot {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: rotate(-18deg) translateY(var(--rod-tip));
  }
}
#cursor-ring.idle-metronome-intro {
  animation: cursor-idle-metronome-intro-ring 0.4s ease-out forwards;
}
#cursor.idle-metronome-intro {
  animation: cursor-idle-metronome-intro-dot 0.4s ease-out forwards;
}

@keyframes cursor-idle-metronome-ring {
  0%,
  8% {
    transform: rotate(-18deg) scaleX(0.1) scaleY(var(--rod-scale-y));
  }
  50%,
  58% {
    transform: rotate(18deg) scaleX(0.1) scaleY(var(--rod-scale-y));
  }
  100% {
    transform: rotate(-18deg) scaleX(0.1) scaleY(var(--rod-scale-y));
  }
}
@keyframes cursor-idle-metronome-dot {
  0%,
  8% {
    transform: rotate(-18deg) translateY(var(--rod-tip)) scale(1);
  }
  4% {
    transform: rotate(-18deg) translateY(var(--rod-tip)) scale(1.4);
  }
  50%,
  58% {
    transform: rotate(18deg) translateY(var(--rod-tip)) scale(1);
  }
  54% {
    transform: rotate(18deg) translateY(var(--rod-tip)) scale(1.4);
  }
  100% {
    transform: rotate(-18deg) translateY(var(--rod-tip)) scale(1);
  }
}
#cursor-ring.idle-metronome {
  animation: cursor-idle-metronome-ring 1.2s linear infinite;
}
#cursor.idle-metronome {
  animation: cursor-idle-metronome-dot 1.2s linear infinite;
}

@keyframes cursor-idle-metronome-outro-ring {
  0% {
    transform: scaleX(0.1) scaleY(var(--rod-scale-y));
    border-radius: 2px;
  }
  100% {
    transform: scaleX(1) scaleY(1);
    border-radius: 50%;
  }
}
@keyframes cursor-idle-metronome-outro-dot {
  0% {
    transform: translateY(var(--rod-tip)) scale(1);
  }
  100% {
    transform: translateY(0) scale(1);
  }
}
#cursor-ring.idle-metronome-outro {
  animation: cursor-idle-metronome-outro-ring 0.3s ease-out forwards;
}
#cursor.idle-metronome-outro {
  animation: cursor-idle-metronome-outro-dot 0.3s ease-out forwards;
}

@keyframes cursor-idle-orbit {
  0% {
    transform: rotate(0deg) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.08);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}
#cursor-ring.idle-orbit {
  animation: cursor-idle-orbit 8s ease-in-out infinite;
}

/* Pendulum: rod hangs from the cursor pivot and swings ±25°; dot
   rides at the rod's tip on the same arc. */
@keyframes cursor-idle-pendulum-intro-ring {
  0% {
    transform: rotate(0deg) scaleX(1) scaleY(1);
    border-radius: 50%;
  }
  100% {
    transform: rotate(-25deg) scaleX(0.08) scaleY(var(--rod-scale-y));
    border-radius: 2px;
  }
}
@keyframes cursor-idle-pendulum-intro-dot {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: rotate(-25deg) translateY(var(--rod-tip));
  }
}
#cursor-ring.idle-pendulum-intro {
  animation: cursor-idle-pendulum-intro-ring 0.4s ease-out forwards;
}
#cursor.idle-pendulum-intro {
  animation: cursor-idle-pendulum-intro-dot 0.4s ease-out forwards;
}

@keyframes cursor-idle-pendulum-ring {
  0%,
  100% {
    transform: rotate(-25deg) scaleX(0.08) scaleY(var(--rod-scale-y));
  }
  50% {
    transform: rotate(25deg) scaleX(0.08) scaleY(var(--rod-scale-y));
  }
}
@keyframes cursor-idle-pendulum-dot {
  0%,
  100% {
    transform: rotate(-25deg) translateY(var(--rod-tip));
  }
  50% {
    transform: rotate(25deg) translateY(var(--rod-tip));
  }
}
#cursor-ring.idle-pendulum {
  animation: cursor-idle-pendulum-ring 2.6s ease-in-out infinite;
}
#cursor.idle-pendulum {
  animation: cursor-idle-pendulum-dot 2.6s ease-in-out infinite;
}

@keyframes cursor-idle-pendulum-outro-ring {
  0% {
    transform: scaleX(0.08) scaleY(var(--rod-scale-y));
    border-radius: 2px;
  }
  100% {
    transform: scaleX(1) scaleY(1);
    border-radius: 50%;
  }
}
@keyframes cursor-idle-pendulum-outro-dot {
  0% {
    transform: translateY(var(--rod-tip));
  }
  100% {
    transform: translateY(0);
  }
}
#cursor-ring.idle-pendulum-outro {
  animation: cursor-idle-pendulum-outro-ring 0.3s ease-out forwards;
}
#cursor.idle-pendulum-outro {
  animation: cursor-idle-pendulum-outro-dot 0.3s ease-out forwards;
}

/* Yo-yo: ring acts like a rope cut under tension, then winds up to the
   hand — string and dot end at the wound-at-rest state so the main loop
   can begin its first throw. The dot stays put (translateY 0) for the
   entire intro; the ring does all the motion. Invariant across every
   keyframe of the main loop: translateY = 36·scaleY − 18. */
@keyframes cursor-idle-yo-yo-intro {
  0% {
    transform: scaleX(1) scaleY(1) rotate(0deg);
    border-radius: 50%;
  }
  10% {
    transform: scaleX(1.08) scaleY(0.88) rotate(0deg);
    border-radius: 45%;
  }
  25% {
    transform: scaleX(0.78) scaleY(1.3) rotate(14deg);
    border-radius: 35%;
  }
  40% {
    transform: scaleX(0.55) scaleY(1.6) rotate(-10deg);
    border-radius: 25%;
  }
  55% {
    transform: scaleX(0.32) scaleY(1.74) rotate(6deg);
    border-radius: 15%;
  }
  70% {
    transform: scaleX(0.16) scaleY(1.3) rotate(-3deg);
    border-radius: 8%;
  }
  85% {
    transform: scaleX(0.07) scaleY(0.8) rotate(1deg);
    border-radius: 4px;
  }
  100% {
    transform: scaleX(0.04) scaleY(0.5) rotate(0deg);
    border-radius: 2px;
  }
}
#cursor-ring.idle-yo-yo-intro {
  transform-origin: center top;
  animation: cursor-idle-yo-yo-intro 0.7s cubic-bezier(0.34, 1.4, 0.64, 1)
    forwards;
}

/* The yo-yo's scaleY timeline lives on :root as a single keyframes
   block; :has() activates it only while the ring is animating. Ring
   and dot then read --rod-scale-y and --rod-tip, keeping the string
   bottom and dot center paired without duplicated timelines. */
:root:has(#cursor.idle-yo-yo) {
  animation: cursor-idle-yo-yo-rod 1.6s linear infinite;
}
@keyframes cursor-idle-yo-yo-rod {
  0% {
    --rod-scale-y: 0.5;
    animation-timing-function: cubic-bezier(0.55, 0.05, 0.85, 0.4);
  }
  32% {
    --rod-scale-y: 2.67;
    animation-timing-function: cubic-bezier(0.2, 0, 0.3, 1);
  }
  37% {
    --rod-scale-y: 2.5;
    animation-timing-function: cubic-bezier(0.55, 0, 0.5, 1);
  }
  42% {
    --rod-scale-y: 2.58;
    animation-timing-function: cubic-bezier(0.12, 0.55, 0.45, 1);
  }
  80% {
    --rod-scale-y: 0.5;
    animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
  }
  100% {
    --rod-scale-y: 0.5;
  }
}
/* Ring animates its own transform (scaleX narrows as the string goes
   taut); scaleY reads the shared --rod-scale-y. Dot carries the bounce
   squash on keyframe 37%/42% and reads --rod-tip for position. */
@keyframes cursor-idle-yo-yo-string {
  0%,
  32%,
  42%,
  80%,
  100% {
    transform: scaleX(0.04) scaleY(var(--rod-scale-y));
  }
  37% {
    transform: scaleX(0.06) scaleY(var(--rod-scale-y));
  }
}
@keyframes cursor-idle-yo-yo-dot {
  0%,
  80%,
  100% {
    transform: translateY(var(--rod-tip));
  }
  37% {
    transform: translateY(var(--rod-tip)) scaleX(1.3) scaleY(0.72);
  }
  42% {
    transform: translateY(var(--rod-tip)) scaleX(1) scaleY(1);
  }
}
#cursor-ring.idle-yo-yo {
  transform-origin: center top;
  border-radius: 2px;
  animation: cursor-idle-yo-yo-string 1.6s linear infinite;
}
#cursor.idle-yo-yo {
  --rod-tip: calc(var(--cursor-ring-size) * (var(--rod-scale-y) - 0.5));
  animation: cursor-idle-yo-yo-dot 1.6s linear infinite;
}

@keyframes cursor-idle-yo-yo-outro {
  0% {
    transform: scaleX(0.04) scaleY(0.5);
    border-radius: 2px;
  }
  100% {
    transform: scaleX(1) scaleY(1);
    border-radius: 50%;
  }
}
#cursor-ring.idle-yo-yo-outro {
  transform-origin: center top;
  animation: cursor-idle-yo-yo-outro 0.3s ease-out forwards;
}

#cursor.visible,
#cursor-ring.visible {
  opacity: 1;
}
@media (hover: none), (pointer: coarse) {
  #cursor,
  #cursor-ring {
    display: none !important;
  }
  body {
    cursor: auto;
  }
}

/* Canvas background */
#bg-canvas {
  position: fixed;
  inset: 0;
  z-index: var(--z-canvas);
  pointer-events: none;
}

/* Grain overlay — opacity is overridable per-theme via --paper-grain-opacity
   (paper theme progressively boosts it) */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-grain);
  pointer-events: none;
  opacity: var(--paper-grain-opacity, 0.025);
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
  background-size: 128px;
}

/* Layout */
.page {
  position: relative;
  z-index: var(--z-page-content);
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/* NAV */
nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem 3rem;
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: rgba(var(--ink-rgb), 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  will-change: translate;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.nav-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

/* SVG Cloud Logo */
.cloud-svg {
  width: 44px;
  height: 32px;
  filter: drop-shadow(0 0 12px rgba(var(--theme-glow), 0.6));
}
.cloud-svg.logo-breathing {
  animation: logoBreath 3s ease-in-out infinite;
}
@keyframes logoBreath {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.08);
  }
}

.logo-text {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--logo-text-color);
}
.logo-text > span:not(.logo-letter) {
  color: var(--logo-accent-color);
}
.logo-letter {
  display: inline-block;
  will-change: translate;
  color: inherit;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 2rem;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 2.5rem;
  list-style: none;
}

.nav-links a {
  font-family: "DM Mono", monospace;
  font-size: 0.72rem;
  font-weight: 300;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  transition: color 0.3s;
  position: relative;
}
.nav-links a::after {
  content: "";
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--sky-3);
  transition: width 0.3s;
}
.nav-links a:hover,
.nav-links a.active {
  color: #fff;
}
.nav-links a:hover::after,
.nav-links a.active::after {
  width: 100%;
}
.nav-sparkle {
  position: absolute;
  border-radius: 50%;
  background: rgb(var(--theme-glow));
  pointer-events: none;
}

.nav-links a.nav-cta {
  font-family: "DM Mono", monospace;
  font-size: 0.72rem;
  text-transform: uppercase;
  color: rgb(var(--theme-glow));
  border: 1px solid rgba(var(--theme-glow), 0.4);
  padding: 0.55rem 1.2rem;
  border-radius: 100px;
  position: relative;
  transition:
    background 0.3s,
    border-color 0.3s,
    color 0.3s;
}
.nav-links a.nav-cta:hover,
.nav-links a.nav-cta.active {
  background: rgba(var(--theme-glow), 0.15);
  border-color: rgb(var(--theme-glow));
}
.nav-links a.nav-cta::after {
  display: none;
}

/* Hamburger menu */
.nav-burger {
  display: none;
  background: none;
  border: none;
  padding: 4px;
  color: rgba(255, 255, 255, 0.7);
  transition: color 0.3s;
}
.nav-burger:hover {
  color: #fff;
}
.nav-burger svg {
  width: 20px;
  height: 20px;
}
.nav-burger .burger-close {
  display: none;
}
.nav-burger.active .burger-open {
  display: none;
}
.nav-burger.active .burger-close {
  display: block;
}

/* HERO */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 2rem;
  position: relative;
  min-height: calc(100vh - 120px);
}

.hero-tag {
  font-family: "DM Mono", monospace;
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sky-3);
  margin-bottom: 2rem;
  opacity: 0;
  animation: fadeUp 0.9s 0.2s ease forwards;
  display: flex;
  align-items: center;
  gap: 10px;
}
.hero-tag::before,
.hero-tag::after {
  content: "";
  display: block;
  width: 28px;
  height: 1px;
  background: var(--sky-4);
  opacity: 0.5;
}

.hero-title {
  font-size: clamp(3.2rem, 8vw, 7.5rem);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.04em;
  margin-bottom: 1.8rem;
  opacity: 0;
  animation: fadeUp 0.9s 0.4s ease forwards;
}

.hero-title .line-1 {
  display: block;
  color: #fff;
}
.hero-title .line-2 {
  display: block;
  background: linear-gradient(
    135deg,
    var(--sky-2) 0%,
    var(--sky-4) 50%,
    var(--sky-3) 100%
  );
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  position: relative;
}

.hero-sub {
  font-family: "DM Mono", monospace;
  font-size: 0.88rem;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.45);
  letter-spacing: 0.04em;
  line-height: 1.7;
  max-width: 420px;
  margin-bottom: 3rem;
  opacity: 0;
  animation: fadeUp 0.9s 0.6s ease forwards;
}

.hero-actions {
  display: flex;
  gap: 1rem;
  align-items: center;
  opacity: 0;
  animation: fadeUp 0.9s 0.8s ease forwards;
}

.btn-primary {
  background: linear-gradient(135deg, var(--sky-4), var(--sky-5));
  color: #fff;
  text-decoration: none;
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.9rem 2rem;
  border-radius: 100px;
  position: relative;
  overflow: hidden;
  transition:
    transform 0.3s,
    box-shadow 0.3s;
  box-shadow: 0 0 30px rgba(var(--theme-glow), 0.35);
}
.btn-primary::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--sky-3), var(--sky-4));
  opacity: 0;
  transition: opacity 0.3s;
}
.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 40px rgba(var(--theme-glow), 0.5);
}
.btn-primary:hover::before {
  opacity: 1;
}
.btn-primary span {
  position: relative;
  z-index: 1;
}

/* ── Button Click Ripple ── */
.btn-ripple-clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
}
.btn-ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.35);
  pointer-events: none;
}

.btn-ghost {
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.9rem 1.5rem;
  transition: color 0.3s;
  display: flex;
  align-items: center;
  gap: 8px;
}
.btn-ghost:hover {
  color: #fff;
}
.btn-ghost svg {
  transition: transform 0.3s;
}
.btn-ghost:hover svg {
  transform: translateX(4px);
}

/* Floating cloud hero visual */
.hero-cloud-wrap {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

/* Scroll indicator */
.scroll-hint {
  position: absolute;
  bottom: 2.5rem;
  left: 50%;
  translate: -50% 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  opacity: 0;
  animation: fadeUp 1s 1.2s ease forwards;
}
.scroll-hint span {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.25);
}
.scroll-line {
  width: 1px;
  height: 40px;
  background: linear-gradient(
    to bottom,
    rgba(var(--theme-glow), 0.6),
    transparent
  );
  animation: scrollPulse 2s ease infinite;
}

/* SECTIONS */
section {
  padding: 6rem 3rem;
  position: relative;
  z-index: var(--z-page-content);
}

/* SERVICES */
.services {
  max-width: 1100px;
  margin: 0 auto;
}

.section-label {
  font-family: "DM Mono", monospace;
  font-size: 0.65rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--sky-3);
  margin-bottom: 3.5rem;
  display: flex;
  align-items: center;
  gap: 12px;
}
.section-label::before {
  content: "";
  display: block;
  width: 20px;
  height: 1px;
  background: var(--sky-4);
}

.services-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5px;
  background: rgba(var(--theme-glow), 0.06);
  border: 1px solid rgba(var(--theme-glow), 0.06);
  border-radius: 20px;
  overflow: hidden;
}

.service-card {
  background: rgba(var(--ink-rgb), 0.7);
  padding: 2.5rem;
  position: relative;
  overflow: hidden;
  transition: background 0.4s;
  backdrop-filter: blur(10px);
}
.service-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(var(--theme-glow), 0.4),
    transparent
  );
  transform: scaleX(0);
  transition: transform 0.5s;
}
.service-card:hover {
  background: rgba(var(--theme-glow), 0.05);
}
.service-card:hover::before {
  transform: scaleX(1);
}

.service-icon {
  width: 40px;
  height: 40px;
  margin-bottom: 1.5rem;
  color: var(--sky-3);
  opacity: 0.8;
}

.service-num {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  color: rgba(var(--theme-glow), 0.4);
  margin-bottom: 1rem;
}

.service-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: #fff;
  margin-bottom: 0.75rem;
  letter-spacing: -0.02em;
}

.service-desc {
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  font-weight: 300;
  line-height: 1.8;
  color: rgba(255, 255, 255, 0.38);
}

/* ABOUT STRIP */
.about-strip {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6rem;
  align-items: center;
}

.about-heading {
  font-size: clamp(2rem, 4vw, 3.2rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: #fff;
}
.about-heading em {
  font-style: normal;
  background: linear-gradient(135deg, var(--sky-2), var(--sky-4));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.about-body {
  font-family: "DM Mono", monospace;
  font-size: 0.8rem;
  font-weight: 300;
  line-height: 2;
  color: rgba(255, 255, 255, 0.42);
}

.about-stats {
  display: flex;
  gap: 2.5rem;
  margin-top: 2.5rem;
}
.stat-item {
}
.stat-num {
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  color: #fff;
  line-height: 1;
}
.stat-label {
  font-family: "DM Mono", monospace;
  font-size: 0.65rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.3);
  margin-top: 4px;
}

/* CONTACT */
.contact-inner {
  max-width: 1100px;
  margin: 0 auto;
}

.contact-card {
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.08) 0%,
    rgba(var(--ink-rgb), 0.9) 100%
  );
  border: 1px solid rgba(var(--theme-glow), 0.18);
  border-radius: 24px;
  padding: 4rem;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 3rem;
  align-items: center;
  position: relative;
  overflow: hidden;
}
.contact-card::before {
  content: "";
  position: absolute;
  top: -80px;
  right: -80px;
  width: 300px;
  height: 300px;
  background: radial-gradient(
    circle,
    rgba(var(--theme-glow), 0.12),
    transparent 70%
  );
  pointer-events: none;
}

.contact-heading {
  font-size: clamp(1.8rem, 3vw, 2.6rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  margin-bottom: 0.75rem;
}
.contact-sub {
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 0.04em;
}

.contact-links {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  flex-shrink: 0;
}

.contact-link {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.55);
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  padding: 0.75rem 1.25rem;
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  position: relative;
  transition: all 0.3s;
}
.contact-link:hover {
  color: #fff;
  border-color: rgba(var(--theme-glow), 0.3);
  background: rgba(var(--theme-glow), 0.08);
}
.contact-link svg {
  flex-shrink: 0;
  color: var(--sky-3);
}

/* FOOTER INFO */
.footer-info {
  position: relative;
  z-index: var(--z-page-content);
  padding: 4rem 3rem;
  border-top: 1px solid rgba(var(--theme-glow), 0.06);
}

.footer-info-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr;
  gap: 3rem;
}

.footer-brand {
  font-size: 1.15rem;
  font-weight: 700;
  color: #fff;
  margin-bottom: 0.75rem;
}

.footer-col-title {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sky-3);
  margin-bottom: 1rem;
}

.footer-text {
  font-family: "DM Mono", monospace;
  font-size: 0.72rem;
  font-weight: 300;
  line-height: 1.9;
  color: rgba(255, 255, 255, 0.35);
}

.footer-link {
  display: block;
  font-family: "DM Mono", monospace;
  font-size: 0.72rem;
  font-weight: 300;
  line-height: 1.9;
  color: rgba(255, 255, 255, 0.35);
  text-decoration: none;
  transition: color 0.3s;
}
.footer-link:hover {
  color: var(--sky-3);
}

/* FOOTER BAR */
footer {
  position: relative;
  z-index: var(--z-page-content);
  padding: 1.5rem 3rem;
  border-top: 1px solid rgba(var(--theme-glow), 0.05);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
footer::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: radial-gradient(
    ellipse at center,
    rgba(var(--theme-glow), 0.4) 0%,
    transparent 70%
  );
  box-shadow: 0 0 6px 1px rgba(var(--theme-glow), 0.15);
  opacity: 0;
  transition: opacity 2.5s ease;
  pointer-events: none;
}
footer.footer-hinting::after {
  opacity: 1;
  animation: footerHintGlow 3s ease-in-out 2.5s infinite;
}
@keyframes footerHintGlow {
  0%,
  100% {
    box-shadow: 0 0 6px 1px rgba(var(--theme-glow), 0.15);
  }
  50% {
    box-shadow: 0 0 10px 2px rgba(var(--theme-glow), 0.35);
  }
}

.footer-copy {
  font-family: "DM Mono", monospace;
  font-size: 0.65rem;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.2);
}

.footer-badge {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(var(--theme-glow), 0.4);
  display: flex;
  align-items: center;
  gap: 8px;
}
.footer-badge::before {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgb(var(--theme-glow));
  animation: pulse 2s ease infinite;
}

/* ANIMATIONS */
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes scrollPulse {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
}

@keyframes pulse {
  0%,
  100% {
    opacity: 0.4;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.3);
  }
}

/* Reveal on scroll */
.reveal {
  opacity: 0;
  transform: translateY(32px);
  transition:
    opacity 0.8s ease,
    transform 0.8s ease;
}
.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
.reveal-delay-1 {
  transition-delay: 0.1s;
}
.reveal-delay-2 {
  transition-delay: 0.2s;
}
.reveal-delay-3 {
  transition-delay: 0.3s;
}

/* RESPONSIVE */
@media (max-width: 900px) {
  nav {
    padding: 1.2rem 1.5rem;
  }
  .nav-links {
    gap: 1.5rem;
  }
  section {
    padding: 4rem 1.5rem;
  }
  .services-grid {
    grid-template-columns: 1fr;
  }
  .about-strip {
    grid-template-columns: 1fr;
    gap: 3rem;
  }
  .contact-card {
    grid-template-columns: 1fr;
    padding: 2.5rem;
  }
  .footer-info {
    padding: 3rem 1.5rem;
  }
  .footer-info-inner {
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
  }
  footer {
    padding: 1.5rem 1.5rem;
  }
}

@media (max-width: 700px) {
  .nav-burger {
    display: flex;
    align-items: center;
  }
  .nav-links {
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--nav-bg, rgba(var(--ink-rgb), 0.97));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    padding: 1rem 1.5rem;
    gap: 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition:
      opacity 0.25s ease,
      transform 0.25s ease,
      visibility 0.25s;
    pointer-events: none;
  }
  .nav-links.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
  }
  .nav-links li {
    padding: 0.75rem 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    opacity: 0;
    transform: translateY(-6px);
    transition:
      opacity 0.2s ease,
      transform 0.2s ease;
  }
  .nav-links li:last-child {
    border-bottom: none;
  }
  .nav-links.open li {
    opacity: 1;
    transform: translateY(0);
    transition-delay: calc(var(--i) * 0.05s);
  }
  .nav-cta {
    display: inline-block;
  }
  .nav-actions {
    gap: 1rem;
  }
  body.light-appearance .nav-links {
    border-bottom-color: rgba(0, 0, 0, 0.06);
  }
  body.light-appearance .nav-links li {
    border-bottom-color: rgba(0, 0, 0, 0.04);
  }
}

@media (max-width: 560px) {
  nav {
    padding: 1rem 1rem;
  }
  section {
    padding: 3rem 1rem;
  }
  .hero {
    padding: 0 1rem;
  }
  .hero-actions {
    flex-direction: column;
  }
  .service-card {
    padding: 2rem 1.5rem;
  }
  .about-stats {
    gap: 1.5rem;
  }
  .contact-card {
    padding: 2rem 1.5rem;
  }
  .footer-info {
    padding: 2.5rem 1rem;
  }
  .footer-info-inner {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  footer {
    padding: 1.2rem 1rem;
  }
}

/* Nav scroll-driven light transition (applied via JS) */
nav.nav-light .logo-text {
  color: var(--ink);
}
nav.nav-light .nav-links a {
  color: rgba(var(--ink-rgb), 0.55);
}
nav.nav-light .nav-links a:hover {
  color: var(--ink);
}
nav.nav-light .nav-links a::after {
  background: var(--sky-5);
}
nav.nav-light .nav-cta {
  color: var(--sky-5);
  border-color: rgba(26, 95, 168, 0.4);
}
nav.nav-light .nav-cta:hover {
  background: rgba(var(--theme-glow), 0.1);
}
nav.nav-light .nav-burger {
  color: rgba(var(--ink-rgb), 0.6);
}
nav.nav-light .nav-burger:hover {
  color: var(--ink);
}

/* Appearance toggle */
.appearance-toggle {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.5);
  transition:
    color 0.3s,
    border-color 0.3s,
    background 0.3s;
  position: relative;
}
.appearance-toggle:hover {
  color: #fff;
  border-color: rgba(var(--theme-glow), 0.4);
  background: rgba(var(--theme-glow), 0.08);
}
.appearance-toggle svg {
  width: 14px;
  height: 14px;
  display: none;
}
.appearance-toggle[data-appearance="light"] .icon-sun {
  display: block;
}
.appearance-toggle[data-appearance="dark"] .icon-moon {
  display: block;
}
.appearance-toggle[data-appearance="auto"] .icon-auto {
  display: block;
}
.appearance-toggle::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.65);
  background: rgba(var(--ink-rgb), 0.92);
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
.appearance-toggle:hover::after {
  opacity: 1;
}
nav.nav-light .appearance-toggle {
  color: rgba(var(--ink-rgb), 0.5);
  border-color: rgba(0, 0, 0, 0.1);
}
nav.nav-light .appearance-toggle:hover {
  color: var(--ink);
  border-color: rgba(26, 95, 168, 0.4);
  background: rgba(var(--theme-glow), 0.08);
}
nav.nav-light .appearance-toggle::after {
  color: rgba(var(--ink-rgb), 0.7);
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* LIGHT APPEARANCE (class-based for manual toggle support) */
body.light-appearance {
  --theme-bg: #f0f7ff;
}

body.light-appearance .section-label {
  color: var(--sky-5);
}
body.light-appearance .section-label::before {
  background: var(--sky-5);
}
body.light-appearance .services-grid {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.06);
}
body.light-appearance .service-card {
  background: rgba(255, 255, 255, 0.75);
}
body.light-appearance .service-card:hover {
  background: rgba(255, 255, 255, 0.9);
}
body.light-appearance .service-card::before {
  background: linear-gradient(
    90deg,
    transparent,
    rgba(var(--theme-glow), 0.3),
    transparent
  );
}
body.light-appearance .service-num {
  color: rgba(26, 95, 168, 0.5);
}
body.light-appearance .service-title {
  color: var(--ink);
}
body.light-appearance .service-desc {
  color: rgba(var(--ink-rgb), 0.55);
}

body.light-appearance .about-heading {
  color: var(--ink);
}
body.light-appearance .about-body {
  color: rgba(var(--ink-rgb), 0.6);
}
body.light-appearance .stat-num {
  color: var(--ink);
}
body.light-appearance .stat-label {
  color: rgba(var(--ink-rgb), 0.45);
}

body.light-appearance .contact-card {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.8) 0%,
    rgba(240, 247, 255, 0.9) 100%
  );
  border-color: rgba(var(--theme-glow), 0.2);
}
body.light-appearance .contact-card::before {
  background: radial-gradient(
    circle,
    rgba(var(--theme-glow), 0.08),
    transparent 70%
  );
}
body.light-appearance .contact-heading {
  color: var(--ink);
}
body.light-appearance .contact-sub {
  color: rgba(var(--ink-rgb), 0.5);
}
body.light-appearance .contact-link {
  color: rgba(var(--ink-rgb), 0.65);
  border-color: rgba(0, 0, 0, 0.08);
  background: rgba(255, 255, 255, 0.6);
}
body.light-appearance .contact-link:hover {
  color: var(--ink);
  border-color: rgba(var(--theme-glow), 0.3);
  background: rgba(255, 255, 255, 0.85);
}
body.light-appearance .contact-link svg {
  color: var(--sky-5);
}

body.light-appearance .footer-info {
  border-top-color: rgba(0, 0, 0, 0.06);
}
body.light-appearance .footer-brand {
  color: var(--ink);
}
body.light-appearance .footer-col-title {
  color: var(--sky-5);
}
body.light-appearance .footer-text {
  color: rgba(var(--ink-rgb), 0.5);
}
body.light-appearance .footer-link {
  color: rgba(var(--ink-rgb), 0.5);
}
body.light-appearance .footer-link:hover {
  color: var(--sky-5);
}

body.light-appearance footer {
  border-top-color: rgba(0, 0, 0, 0.05);
}
body.light-appearance .footer-copy {
  color: rgba(var(--ink-rgb), 0.3);
}
body.light-appearance .footer-badge {
  color: rgba(var(--theme-glow), 0.5);
}

body.light-appearance::after {
  opacity: 0.015;
}
body.light-appearance #cursor {
  background: var(--sky-4);
  mix-blend-mode: normal;
  box-shadow:
    0 0 6px rgba(var(--cursor-glow), 0.5),
    0 0 2px rgba(255, 255, 255, 0.7);
}
body.light-appearance #cursor-ring {
  border-color: rgba(var(--cursor-glow), 0.5);
  box-shadow: 0 0 4px rgba(var(--cursor-glow), 0.15);
}

/* ═══ UPSIDE DOWN ═══ */

/* Overlay — red vignette during build-up */
.ud-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-buildup);
  pointer-events: none;
}

/* Warning overlay */
.ud-warning {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-warning);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.88);
  opacity: 0;
  transition: opacity 0.3s;
  pointer-events: none;
}
.ud-warning.visible {
  opacity: 1;
}

.ud-warning-content {
  text-align: center;
  max-width: 440px;
  padding: 2rem;
}
.ud-warning-icon {
  font-size: 2.5rem;
  margin-bottom: 1rem;
  animation: ud-glitch 0.3s infinite;
}
.ud-warning-title {
  font-family: "DM Mono", monospace;
  font-size: 1.1rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #dd3737;
  margin-bottom: 1rem;
  animation: ud-glitch-text 2s infinite;
}
.ud-warning-sub {
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  font-weight: 300;
  color: rgba(255, 100, 100, 0.6);
  line-height: 1.8;
  margin-bottom: 1.5rem;
}
.ud-warning-hint {
  font-family: "DM Mono", monospace;
  font-size: 0.65rem;
  letter-spacing: 0.15em;
  color: rgba(255, 60, 60, 0.4);
  animation: ud-pulse 1.5s ease infinite;
}

/* Transition flash */
.ud-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  pointer-events: none;
  background: radial-gradient(
    ellipse at center,
    rgba(180, 0, 0, 0.3) 0%,
    #1a0505 60%
  );
}
.ud-wipe-return {
  background: radial-gradient(
    ellipse at center,
    rgba(var(--theme-glow), 0.3) 0%,
    #051020 60%
  );
}

@keyframes ud-glitch {
  0%,
  100% {
    transform: translate(0, 0);
  }
  20% {
    transform: translate(-2px, 1px);
  }
  40% {
    transform: translate(2px, -1px);
  }
  60% {
    transform: translate(-1px, -2px);
  }
  80% {
    transform: translate(1px, 2px);
  }
}

@keyframes ud-glitch-text {
  0%,
  92%,
  100% {
    transform: none;
    opacity: 1;
  }
  93% {
    transform: translate(-3px, 0) skewX(-5deg);
    opacity: 0.8;
  }
  94% {
    transform: translate(3px, 0) skewX(5deg);
    opacity: 0.6;
  }
  95% {
    transform: none;
    opacity: 1;
  }
  97% {
    transform: translate(-2px, 1px);
    opacity: 0.7;
  }
  98% {
    transform: none;
    opacity: 1;
  }
}

@keyframes ud-pulse {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 0.7;
  }
}

/* Upside Down — structural rules (always apply when flipped) */
body.upside-down .page {
  transform: scaleY(-1);
}

/* Nav is moved out of .page during flip so sticky isn't broken by the transform.
   Pin it to the visual bottom, flipped to match the upside-down world. */
body.upside-down > nav {
  position: fixed;
  bottom: 0;
  top: auto;
  left: 0;
  right: 0;
  transform: scaleY(-1);
}

/* Opt-in flip for elements that sit outside `.page` (fixed overlays, the
   shared canvas) and need to mirror with the page when upside-down is
   active.  Adding this class to a new overlay is preferred over reading
   `body.upside-down` from JS or doing manual y-axis math at draw time —
   the renderer stays in plain canvas-pixel coords and CSS handles the
   visual inversion. */
body.upside-down .flips-with-page {
  transform: scaleY(-1);
}

/* ══════════════════════════════════════════════════════════════
   Theme contract
   ══════════════════════════════════════════════════════════════
   A theme sets these tokens on body[data-active-theme="<name>"];
   everything else cascades from base.

   Required:
     --theme-primary   Solid accent color, used where chrome wants a flat
                       color that may diverge from --theme-glow (logo
                       accent default, paper's chrome).
     --theme-glow      RGB triplet for halos, cursor, chrome accent.
                       Used inside rgba(...) by any-alpha consumers.

   Optional:
     --theme-bg        Page background.
     --logo-text-color, --logo-accent-color
     --sky-3, --sky-4, --sky-5, --sky-6   Override brand palette stops
     --cursor-dot-clip, --cursor-dot-radius
     --cursor-ring-radius, --cursor-ring-style,
       --cursor-ring-width, --cursor-ring-animation

   Beyond tokens, themes are free to override any selector for theme-
   defining art (hero gradients, button gradients, feature blocks like
   .frost-card or .pixel-card, custom cursor shapes).  Don't override
   what the cascade already provides.
   ══════════════════════════════════════════════════════════════ */

/* Upside Down — visual theme (only when active theme) */
body[data-active-theme="upside-down"] {
  --sky-3: #e87d7d;
  --sky-4: #dd3838;
  --sky-5: #a81a1a;
  --sky-6: #720c0c;
  --theme-primary: #e04050;
  --theme-glow: 221, 55, 55;
  --cursor-ring-style: dashed;
  --cursor-ring-width: 1.5px;
  --cursor-ring-animation: cursor-spin 6s linear infinite;
  --theme-bg: #280a0a;
}

body[data-active-theme="upside-down"] #bg-canvas {
  filter: hue-rotate(160deg) saturate(1.3) brightness(0.6);
}

body[data-active-theme="upside-down"] #cursor {
  background: var(--sky-3);
  box-shadow:
    2px -1px 0 rgba(255, 50, 50, 0.5),
    -2px 1px 0 rgba(80, 120, 255, 0.4);
}
body[data-active-theme="upside-down"] .hero-title .line-2 {
  background: linear-gradient(
    135deg,
    #f7b5b5 0%,
    var(--sky-4) 50%,
    var(--sky-3) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
}

body[data-active-theme="upside-down"] .btn-primary {
  background: linear-gradient(135deg, var(--sky-4), var(--sky-5));
}
body[data-active-theme="upside-down"] .btn-primary::before {
  background: linear-gradient(135deg, var(--sky-3), var(--sky-4));
}

body[data-active-theme="upside-down"] .about-heading em {
  background: linear-gradient(135deg, #f7b5b5, var(--sky-4));
  -webkit-background-clip: text;
  background-clip: text;
}

/* Card gravity-defying hover — cards float up in the flipped world.
   The page is flipped via scaleY(-1), so positive translateY in CSS
   renders as upward motion on screen. Shadow offsets are also inverted. */
body[data-active-theme="upside-down"] .service-card {
  transition:
    background 0.4s,
    box-shadow 0.5s ease,
    translate 0.5s ease;
}
body[data-active-theme="upside-down"] .service-card:hover {
  translate: 0 8px;
  box-shadow:
    0 -16px 40px rgba(var(--theme-glow), 0.12),
    0 -6px 16px rgba(0, 0, 0, 0.15);
}

body[data-active-theme="upside-down"] .nav-cta {
  color: var(--sky-3);
}
body[data-active-theme="upside-down"] .nav-cta:hover {
  border-color: var(--sky-3);
}

body[data-active-theme="upside-down"] .contact-card {
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.08) 0%,
    rgba(40, 10, 10, 0.9) 100%
  );
}

body[data-active-theme="upside-down"]::after {
  opacity: 0.04;
}

/* ═══════════════════════════════════════════════
   Frozen Theme
   ═══════════════════════════════════════════════ */

/* Frost breath particles */
.frost-breath {
  position: fixed;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(180, 230, 255, 0.9),
    rgba(var(--frost-edge-rgb), 0.3)
  );
  pointer-events: none;
  z-index: var(--z-theme-effect);
}
.frost-breath.warm {
  background: radial-gradient(
    circle,
    rgba(255, 200, 120, 0.9),
    rgba(255, 140, 40, 0.3)
  );
}

/* Frost overlay — corner creep */
.frost-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-buildup);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  --frost-size: 8%;
  background:
    radial-gradient(
      ellipse at 0% 0%,
      rgba(180, 230, 255, 0.35) 0%,
      transparent var(--frost-size)
    ),
    radial-gradient(
      ellipse at 100% 0%,
      rgba(200, 240, 255, 0.3) 0%,
      transparent var(--frost-size)
    ),
    radial-gradient(
      ellipse at 0% 100%,
      rgba(200, 240, 255, 0.3) 0%,
      transparent var(--frost-size)
    ),
    radial-gradient(
      ellipse at 100% 100%,
      rgba(180, 230, 255, 0.35) 0%,
      transparent var(--frost-size)
    );
}

/* Frost wipe transition */
.frost-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background: radial-gradient(
    ellipse at center,
    rgba(200, 240, 255, 0.95),
    rgba(140, 210, 245, 0.98)
  );
  opacity: 0;
  transition: opacity 0.4s ease-in;
  pointer-events: none;
}
.frost-wipe.thaw {
  background: radial-gradient(
    ellipse at center,
    rgba(255, 220, 160, 0.95),
    rgba(255, 180, 100, 0.98)
  );
}

/* Frost ripple on card click */
.frost-ripple {
  position: absolute;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(var(--frost-edge-rgb), 0.3),
    transparent 70%
  );
  pointer-events: none;
}

/* ── Frozen — visual theme (only when active theme) ── */
body[data-active-theme="frozen"] #bg-canvas {
  filter: saturate(0.4) brightness(1.25);
}

body[data-active-theme="frozen"] .nav-logo {
  filter: saturate(0.2) brightness(1.4);
}
body[data-active-theme="frozen"] .cloud-svg {
  filter: drop-shadow(0 0 14px rgba(var(--frost-edge-rgb), 0.7));
}

body[data-active-theme="frozen"] {
  --theme-primary: #88d4f7;
  --theme-glow: 0, 200, 240;
  --frost-edge-rgb: 0, 220, 255;
  --cursor-dot-clip: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  --cursor-ring-width: 1.5px;
}
body[data-active-theme="frozen"] #cursor-ring {
  border-color: rgba(var(--frost-edge-rgb), 0.5);
  box-shadow: 0 0 8px rgba(var(--frost-edge-rgb), 0.25);
}

body[data-active-theme="frozen"] .hero-title .line-2 {
  background: linear-gradient(135deg, #b5f0ff 0%, #00c8ff 50%, #60d8f0 100%);
  -webkit-background-clip: text;
  background-clip: text;
}

body[data-active-theme="frozen"] .btn-primary {
  background: linear-gradient(135deg, #00b8e8, #0090c0);
}
body[data-active-theme="frozen"] .btn-primary::before {
  background: linear-gradient(135deg, #40d0f0, #00b8e8);
}

body[data-active-theme="frozen"] .about-heading em {
  background: linear-gradient(135deg, #b5f0ff, #00c8ff);
  -webkit-background-clip: text;
  background-clip: text;
}

/* Card frost interaction — mouse-tracking gradient + frost creep edges */
body.frozen .frost-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      circle at var(--frost-x, 50%) var(--frost-y, 50%),
      rgba(var(--frost-edge-rgb), 0.12) 0%,
      transparent 60%
    ),
    linear-gradient(
      180deg,
      rgba(var(--frost-edge-rgb), 0.08) 0%,
      transparent 15%
    ),
    linear-gradient(
      0deg,
      rgba(var(--frost-edge-rgb), 0.06) 0%,
      transparent 12%
    ),
    linear-gradient(
      90deg,
      rgba(var(--frost-edge-rgb), 0.05) 0%,
      transparent 10%
    ),
    linear-gradient(
      270deg,
      rgba(var(--frost-edge-rgb), 0.05) 0%,
      transparent 10%
    );
  background-size:
    100% 100%,
    100% 0%,
    100% 0%,
    0% 100%,
    0% 100%;
  background-repeat: no-repeat;
  background-position: center, top, bottom, left, right;
  pointer-events: none;
  opacity: 0;
  transition:
    opacity 0.3s,
    background-size 0.6s ease-out;
}
body.frozen .frost-card:hover::after {
  opacity: 1;
  background-size:
    100% 100%,
    100% 40%,
    100% 30%,
    25% 100%,
    25% 100%;
}

/* Frozen card state */
body.frozen .service-card.card-frozen {
  background: rgba(var(--theme-glow), 0.08);
  box-shadow: inset 0 0 20px rgba(var(--frost-edge-rgb), 0.1);
}
body.frozen .service-card.card-frozen::before {
  transform: scaleX(1);
  background: linear-gradient(
    90deg,
    transparent,
    rgba(var(--frost-edge-rgb), 0.6),
    transparent
  );
}

body[data-active-theme="frozen"]::after {
  opacity: 0.04;
}

/* ═══════════════════════════════════════════════
   Deep Sea Theme
   ═══════════════════════════════════════════════ */

/* Ripple rings — concentric expanding circles from cursor */
.deep-sea-ripple {
  position: fixed;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  border: 1.5px solid rgba(0, 200, 180, 0.5);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: var(--z-theme-effect);
}

/* Water creep overlay — dark teal gradients from edges */
.deep-sea-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-buildup);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  --water-size: 8%;
  background:
    radial-gradient(
      ellipse at 0% 0%,
      rgba(0, 60, 80, 0.5) 0%,
      transparent var(--water-size)
    ),
    radial-gradient(
      ellipse at 100% 0%,
      rgba(0, 50, 70, 0.45) 0%,
      transparent var(--water-size)
    ),
    radial-gradient(
      ellipse at 0% 100%,
      rgba(0, 50, 70, 0.45) 0%,
      transparent var(--water-size)
    ),
    radial-gradient(
      ellipse at 100% 100%,
      rgba(0, 60, 80, 0.5) 0%,
      transparent var(--water-size)
    );
}

/* Pressure vignette — deep navy/black from edges */
.deep-sea-vignette {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-buildup);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  background: radial-gradient(
    ellipse at center,
    transparent 30%,
    rgba(0, 10, 20, 0.9) 100%
  );
}

/* Deep sea wipe transition */
.deep-sea-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background: linear-gradient(
    180deg,
    rgba(0, 20, 40, 0.98),
    rgba(0, 40, 60, 0.95),
    rgba(0, 20, 40, 0.98)
  );
  opacity: 0;
  transition: opacity 0.4s ease-in;
  pointer-events: none;
}
.deep-sea-wipe.resurface {
  background: linear-gradient(
    180deg,
    rgba(180, 220, 240, 0.95),
    rgba(255, 240, 200, 0.95),
    rgba(180, 220, 240, 0.95)
  );
}

/* ── Deep Sea — visual theme (only when active theme) ── */
body[data-active-theme="deep-sea"] {
  --sky-3: #0a5060;
  --sky-4: #064050;
  --sky-5: #003040;
  --sky-6: #001a28;
  --theme-primary: #00ffc8;
  --logo-text-color: #b8f5e0;
  --logo-accent-color: rgb(var(--theme-glow));
  --theme-bg: #001018;
}

body[data-active-theme="deep-sea"] #bg-canvas {
  filter: hue-rotate(310deg) saturate(1.4) brightness(0.35);
}

body[data-active-theme="deep-sea"] .cloud-svg {
  filter: grayscale(1) brightness(0.55)
    drop-shadow(0 0 14px rgba(0, 255, 180, 0.5));
}

body[data-active-theme="deep-sea"] {
  --theme-glow: 0, 200, 160;
  --cursor-ring-animation: cursor-wobble 3s ease-in-out infinite;
}
body[data-active-theme="deep-sea"] #cursor {
  box-shadow:
    -3px -3px 4px rgba(180, 255, 230, 0.35) inset,
    1px 1px 2px rgba(0, 60, 50, 0.25) inset;
}
body[data-active-theme="deep-sea"] #cursor-ring {
  border-color: rgba(0, 255, 180, 0.4);
}

body[data-active-theme="deep-sea"] .hero-title .line-2 {
  background: linear-gradient(
    135deg,
    #80ffd4 0%,
    rgb(var(--theme-glow)) 50%,
    #00a080 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
}

body[data-active-theme="deep-sea"] .btn-primary {
  background: linear-gradient(135deg, #00806a, #005848);
  box-shadow: 0 0 30px rgba(var(--theme-glow), 0.3);
}
body[data-active-theme="deep-sea"] .btn-primary::before {
  background: linear-gradient(135deg, #00a088, #00806a);
}
body[data-active-theme="deep-sea"] .btn-primary:hover {
  box-shadow: 0 8px 40px rgba(var(--theme-glow), 0.45);
}

body[data-active-theme="deep-sea"] .about-heading em {
  background: linear-gradient(135deg, #80ffd4, rgb(var(--theme-glow)));
  -webkit-background-clip: text;
  background-clip: text;
}

/* Card caustic interaction — animated water-light ripple + shimmer border */
body.deep-sea .caustic-card {
  transition:
    background 0.4s,
    box-shadow 0.6s ease;
}
body.deep-sea .caustic-card:hover {
  box-shadow:
    inset 0 0 30px rgba(0, 255, 180, 0.04),
    0 0 20px rgba(0, 255, 180, 0.06);
}
body.deep-sea .caustic-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    circle at var(--caustic-x, 50%) var(--caustic-y, 50%),
    rgba(0, 255, 180, 0.12) 0%,
    rgba(var(--theme-glow), 0.04) 40%,
    transparent 60%
  );
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}
body.deep-sea .caustic-card:hover::after {
  opacity: 1;
  animation: causticShimmer 3s ease-in-out infinite;
}
@keyframes causticShimmer {
  0%,
  100% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.3);
  }
}

body[data-active-theme="deep-sea"] .contact-card {
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.08) 0%,
    rgba(0, 16, 24, 0.92) 100%
  );
}

body[data-active-theme="deep-sea"]::after {
  opacity: 0.04;
}

/* ═══════════════════════════════════════════════════════════════
   Blocky Theme — "Voxelbreeze"
   ═══════════════════════════════════════════════════════════════ */

/* ── Progressive indicator overlays ── */
.blocky-scanlines {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-effect);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  background: repeating-linear-gradient(
    0deg,
    transparent,
    transparent 2px,
    rgba(0, 0, 0, 0.15) 2px,
    rgba(0, 0, 0, 0.15) 4px
  );
}
.blocky-grid {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-effect);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  background-image:
    linear-gradient(rgba(var(--theme-glow), 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--theme-glow), 0.08) 1px, transparent 1px);
  background-size: 6px 6px;
}
.blocky-static {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-effect);
  pointer-events: none;
  opacity: 0;
  background: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.03) 0px,
    rgba(0, 0, 0, 0.05) 1px,
    rgba(255, 255, 255, 0.02) 2px,
    transparent 3px
  );
}

/* ── Blocky wipe transition — resolution cascade ── */
.blocky-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background: radial-gradient(
    ellipse at center,
    rgba(90, 180, 60, 0.95),
    rgba(60, 40, 20, 0.98)
  );
  opacity: 0;
  transition: opacity 0.5s ease-in;
  pointer-events: none;
}
.blocky-wipe.unblocky {
  background: radial-gradient(
    ellipse at center,
    rgba(160, 200, 240, 0.95),
    rgba(20, 40, 80, 0.98)
  );
  transition: opacity 0.4s ease-in;
}

/* ── Blocky — visual theme (only when active theme) ── */
body[data-active-theme="blocky"] {
  --theme-bg: #0a1230;
}

body[data-active-theme="blocky"] #bg-canvas {
  filter: contrast(1.15) saturate(1.3);
  image-rendering: pixelated;
}

body[data-active-theme="blocky"] .nav-logo {
  filter: saturate(0.8) brightness(1.1);
}
body[data-active-theme="blocky"] .cloud-svg {
  filter: drop-shadow(0 0 10px rgba(var(--theme-glow), 0.4));
}

body[data-active-theme="blocky"] {
  --theme-primary: #ffa040;
  --theme-glow: 100, 255, 100;
  --logo-accent-color: rgb(var(--theme-glow));
  --cursor-dot-radius: 0;
  --cursor-ring-radius: 0;
}
body[data-active-theme="blocky"] #cursor-ring {
  border-color: rgba(var(--theme-glow), 0.4);
}

body[data-active-theme="blocky"] .hero-title .line-2 {
  background: linear-gradient(135deg, #a0ff80 0%, #60d040 50%, #40b030 100%);
  -webkit-background-clip: text;
  background-clip: text;
}

body[data-active-theme="blocky"] .btn-primary {
  background: linear-gradient(135deg, #2d8a2e, #1a6b1b);
  box-shadow: 0 0 30px rgba(var(--theme-glow), 0.25);
}
body[data-active-theme="blocky"] .btn-primary::before {
  background: linear-gradient(135deg, #40b040, #2d8a2e);
}
body[data-active-theme="blocky"] .btn-primary:hover {
  box-shadow: 0 8px 40px rgba(var(--theme-glow), 0.4);
}

body[data-active-theme="blocky"] .about-heading em {
  background: linear-gradient(135deg, #a0ff80, #60d040);
  -webkit-background-clip: text;
  background-clip: text;
}

/* Card pixel interaction — pulsing selection border + scan-line sweep */
body.blocky .pixel-card {
  transition: background 0.4s;
}
body.blocky .pixel-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(var(--theme-glow), 0.08) 48%,
    rgba(var(--theme-glow), 0.15) 50%,
    rgba(var(--theme-glow), 0.08) 52%,
    transparent 100%
  );
  background-size: 100% 300%;
  background-position: 0% 0%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
body.blocky .pixel-card:hover {
  outline: 2px dashed rgba(var(--theme-glow), 0.5);
  outline-offset: 2px;
  animation: pixelPulse 1s ease-in-out infinite alternate;
}
body.blocky .pixel-card:hover::after {
  opacity: 1;
  animation: pixelScan 2s steps(12) infinite;
}
@keyframes pixelPulse {
  0% {
    outline-offset: 2px;
    outline-color: rgba(var(--theme-glow), 0.3);
  }
  100% {
    outline-offset: 4px;
    outline-color: rgba(var(--theme-glow), 0.6);
  }
}
@keyframes pixelScan {
  0% {
    background-position: 0% 0%;
  }
  100% {
    background-position: 0% 100%;
  }
}

body[data-active-theme="blocky"] .contact-card {
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.08) 0%,
    rgba(10, 18, 48, 0.92) 100%
  );
}

body[data-active-theme="blocky"]::after {
  opacity: 0.03;
}

/* ── Light appearance overrides for blocky ── */
body.light-appearance[data-active-theme="blocky"] {
  --theme-bg: #e8f0ff;
}
body.light-appearance[data-active-theme="blocky"] #bg-canvas {
  filter: contrast(1.1) saturate(1.2);
  image-rendering: pixelated;
}
body.light-appearance[data-active-theme="blocky"] #cursor {
  background: rgb(60, 200, 60);
}
body.light-appearance[data-active-theme="blocky"] #cursor-ring {
  border-color: rgba(60, 200, 60, 0.4);
}

/* ── Rainy — storm overlay & wipe transitions ── */

.storm-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-theme-buildup);
  opacity: 0;
  transition: opacity 0.3s;
  background: radial-gradient(
    ellipse at center,
    transparent 40%,
    rgba(30, 40, 55, 0.6) 100%
  );
}

.storm-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background: linear-gradient(180deg, #1a2030 0%, #2a3545 50%, #1a2530 100%);
  opacity: 0;
  transition: opacity 0.4s ease-in-out;
  pointer-events: none;
}
.storm-wipe.clearing {
  background: linear-gradient(0deg, #3a4a5a 0%, #5a6a7a 50%, #7a8a9a 100%);
}

/* ── Rainy — visual theme (only when active theme) ── */

body[data-active-theme="rainy"] {
  --sky-3: #5a6a80;
  --theme-primary: #6a9fc0;
  --theme-glow: 160, 185, 210;
  --rainy-deep-rgb: 90, 122, 154;
  --cursor-dot-radius: 0 50% 50% 50%;
  --cursor-ring-animation: cursor-ripple 2s ease-in-out infinite;
  --theme-bg: #101820;
}
body[data-active-theme="rainy"] #bg-canvas {
  filter: saturate(0.6) brightness(0.7) hue-rotate(10deg);
}

body.rainy .cloud-svg {
  filter: saturate(0.3) brightness(0.8);
}

body[data-active-theme="rainy"] .hero-tag {
  color: rgba(180, 200, 220, 0.9);
}
body[data-active-theme="rainy"] .hero-title {
  background: linear-gradient(135deg, #8a9bb5, #5a6a80);
  -webkit-background-clip: text;
  background-clip: text;
}
body[data-active-theme="rainy"] .hero-sub {
  color: rgba(160, 180, 200, 0.85);
}

body[data-active-theme="rainy"] .btn-primary {
  background: linear-gradient(135deg, #5a7a9a, #3a5a7a);
  box-shadow: 0 0 20px rgba(var(--rainy-deep-rgb), 0.3);
}
body[data-active-theme="rainy"] .btn-primary:hover {
  box-shadow: 0 0 30px rgba(var(--rainy-deep-rgb), 0.5);
}
body[data-active-theme="rainy"] .btn-outline {
  border-color: rgba(140, 170, 200, 0.35);
  color: rgba(var(--theme-glow), 0.9);
}

body[data-active-theme="rainy"] .service-card {
  background: rgba(20, 30, 45, 0.7);
  border-color: rgba(100, 130, 170, 0.12);
}
body[data-active-theme="rainy"] .service-card:hover {
  border-color: rgba(120, 150, 190, 0.25);
  box-shadow: 0 8px 32px rgba(60, 90, 130, 0.15);
}
body[data-active-theme="rainy"] .service-num {
  color: rgba(120, 150, 190, 0.5);
}
body[data-active-theme="rainy"] .service-title {
  color: rgba(190, 210, 230, 0.95);
}
body[data-active-theme="rainy"] .service-desc {
  color: rgba(150, 175, 200, 0.75);
}

/* Rain card interactions */
body.rainy .rain-card {
  position: relative;
  overflow: hidden;
}
body.rainy .rain-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(180, 200, 220, 0.04) 100%
  );
  pointer-events: none;
  opacity: 0.6;
}
body.rainy .rain-card::before {
  content: "";
  position: absolute;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(var(--theme-glow), 0.12) 0%,
    transparent 70%
  );
  left: var(--rain-x, -100%);
  top: var(--rain-y, -100%);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 1;
  transition: opacity 0.3s;
}

.rain-ripple {
  position: absolute;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid rgba(var(--theme-glow), 0.3);
  pointer-events: none;
  z-index: 2;
}

body[data-active-theme="rainy"] #contact {
  border-color: rgba(var(--rainy-deep-rgb), 0.2);
}
body[data-active-theme="rainy"] .contact-heading {
  color: rgba(190, 210, 230, 0.95);
}
body[data-active-theme="rainy"] .contact-sub {
  color: rgba(150, 175, 200, 0.75);
}
body[data-active-theme="rainy"] .contact-link {
  background: rgba(20, 30, 45, 0.6);
  border-color: rgba(100, 130, 170, 0.15);
  color: rgba(170, 195, 220, 0.9);
}

body[data-active-theme="rainy"] footer {
  border-top-color: rgba(var(--rainy-deep-rgb), 0.1);
}
body[data-active-theme="rainy"] .footer-info {
  border-top-color: rgba(var(--rainy-deep-rgb), 0.08);
}
body[data-active-theme="rainy"]::after {
  opacity: 0.03;
}

body[data-active-theme="rainy"] #cursor {
  transform: rotate(45deg);
}
body[data-active-theme="rainy"] #cursor-ring {
  border-color: rgba(var(--theme-glow), 0.4);
}

/* Splash particles (progressive indicator clicks) */
.rain-splash {
  position: fixed;
  border-radius: 50%;
  background: rgba(var(--theme-glow), 0.7);
  pointer-events: none;
  z-index: var(--z-page-overlay);
}
.rain-splash.clearing {
  background: rgba(200, 180, 140, 0.7);
}

/* Hero-tag sway animation */
@keyframes rain-sway {
  0%,
  100% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(var(--sway-deg, 1deg));
  }
  75% {
    transform: rotate(calc(-1 * var(--sway-deg, 1deg)));
  }
}

/* ── Light appearance overrides for rainy ── */
body.light-appearance[data-active-theme="rainy"] {
  --theme-bg: #d0d8e4;
}
body.light-appearance[data-active-theme="rainy"] #bg-canvas {
  filter: saturate(0.55) brightness(0.85) hue-rotate(5deg);
}
body.light-appearance[data-active-theme="rainy"] .service-card {
  background: rgba(200, 215, 230, 0.6);
  border-color: rgba(100, 130, 170, 0.15);
}
body.light-appearance[data-active-theme="rainy"] #cursor {
  background: rgb(100, 130, 170);
}
body.light-appearance[data-active-theme="rainy"] #cursor-ring {
  border-color: rgba(100, 130, 170, 0.4);
}

/* ── Paper Theme ── */

/* Wipe — ink brush sweep diagonally */
.paper-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background: linear-gradient(
    115deg,
    transparent 0%,
    rgba(var(--ink-color-rgb), 0.85) 40%,
    rgba(var(--ink-color-rgb), 0.95) 50%,
    rgba(var(--ink-color-rgb), 0.85) 60%,
    transparent 100%
  );
  background-size: 250% 100%;
  background-position: 100% 0;
  opacity: 0;
  transition: opacity 0.4s ease-in-out;
  pointer-events: none;
}
.paper-wipe.eraser {
  background: linear-gradient(
    -115deg,
    transparent 0%,
    rgba(245, 232, 210, 0.88) 40%,
    rgba(245, 232, 210, 0.96) 50%,
    rgba(245, 232, 210, 0.88) 60%,
    transparent 100%
  );
  background-size: 250% 100%;
}

/* Progressive overlay — edge ink-seep, vignette */
.paper-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-buildup);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  background:
    radial-gradient(
      ellipse at center,
      transparent 55%,
      rgba(var(--ink-color-rgb), 0.18) 100%
    ),
    linear-gradient(
      to right,
      rgba(var(--ink-color-rgb), 0.08) 0%,
      transparent 8%,
      transparent 92%,
      rgba(var(--ink-color-rgb), 0.08) 100%
    );
}

/* Page-turn transform — applied only when paper is active.
   Motion smoothing is handled in JS via rAF lerp; no CSS transition. */
body.paper .page {
  translate: var(--paper-page-x, 0) 0;
  rotate: var(--paper-page-rot, 0);
}

/* ── Paper — visual theme (only when active theme) ── */

body[data-active-theme="paper"] {
  --ink-color: #1a1512;
  --ink-color-rgb: 26, 21, 18;
  --paper-color: #f5efdc;
  --theme-primary: #a89580;
  --theme-glow: 60, 40, 30;
  --logo-text-color: #d4c0a8;
  --theme-bg: var(--paper-color);
}
body[data-active-theme="paper"] #bg-canvas {
  /* Canvas still runs (fury + ink), but sky/atmosphere are skipped in JS.
     The filter desaturates whatever fury renders so lightning reads as ink. */
  filter: saturate(0.15) contrast(1.1) sepia(0.35);
}

/* Grain — boost well above the default while paper is active */
body[data-active-theme="paper"]::after {
  opacity: var(--paper-grain-opacity, 0.18);
}

/* Cloud SVG — reduce to inky outline feel */
body.paper .cloud-svg {
  filter: saturate(0) contrast(1.25) brightness(0.35);
}

/* Cursor — little pencil.
   The pencil SVG is drawn with its graphite tip at viewBox center (12, 12),
   shaft rotated -45° up-right so the cursor hotspot is the tip itself.
   mix-blend-mode is removed: screen-blending a dark pencil onto warm
   paper wipes it out. The ring becomes a faint square guide. */
body[data-active-theme="paper"] #cursor {
  background: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg transform='rotate(-45 12 12)'%3E%3Cpolygon points='12,12 15,10 15,14' fill='%232a1f18'/%3E%3Cpolygon points='15,10 15,14 17,14.2 17,9.8' fill='%23e8c485'/%3E%3Crect x='17' y='9.8' width='4.5' height='4.4' fill='%23d4a55a'/%3E%3Crect x='21.5' y='9.8' width='0.7' height='4.4' fill='%23a8a8b0'/%3E%3Crect x='22.2' y='9.8' width='1.4' height='4.4' fill='%23e54a4a'/%3E%3Cpolygon points='12,12 15,10 17,9.8 21.5,9.8 22.2,9.8 23.6,9.8 23.6,14.2 22.2,14.2 21.5,14.2 17,14.2 15,14' fill='none' stroke='%231a1512' stroke-width='0.6' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E")
    center center / 100% 100% no-repeat;
  width: 24px;
  height: 24px;
  mix-blend-mode: normal;
  border-radius: 0;
}
body[data-active-theme="paper"] #cursor-ring {
  border-width: 1px;
  border-color: rgba(var(--ink-color-rgb), 0.3);
  border-radius: 0;
}

/* Hero — ink on paper, no gradients */
body[data-active-theme="paper"] .hero-tag {
  color: rgba(var(--ink-color-rgb), 0.85);
}
body[data-active-theme="paper"] .hero-title {
  background: none;
  color: var(--ink-color);
  -webkit-text-fill-color: var(--ink-color);
}
body[data-active-theme="paper"] .hero-title .line-1,
body[data-active-theme="paper"] .hero-title .line-2 {
  background: none;
  color: var(--ink-color);
  -webkit-text-fill-color: var(--ink-color);
}
body[data-active-theme="paper"] .hero-sub {
  color: rgba(var(--ink-color-rgb), 0.75);
}

/* Hover thickening — every semantic text element gets a shadow scaled by
   its --paper-ink-proximity var (0..1), set by JS based on cursor distance.
   Intentionally broad: nav, buttons, footer, any UI visible while paper is
   active all participate. The site's just playing at being a sketchbook
   anyway — no reason to carve out chrome. */
body[data-active-theme="paper"]
  :is(h1, h2, h3, h4, h5, h6, p, span, a, li, em, strong) {
  text-shadow: 0 0 calc(3px * var(--paper-ink-proximity, 0))
    rgba(var(--ink-color-rgb), calc(0.55 * var(--paper-ink-proximity, 0)));
}

/* Buttons — inked */
body[data-active-theme="paper"] .btn-primary {
  background: var(--ink-color);
  color: var(--paper-color);
  box-shadow: 0 2px 0 0 rgba(var(--ink-color-rgb), 0.35);
}
body[data-active-theme="paper"] .btn-primary:hover {
  box-shadow: 0 3px 0 0 rgba(var(--ink-color-rgb), 0.5);
}
body[data-active-theme="paper"] .btn-ghost,
body[data-active-theme="paper"] .btn-outline {
  border-color: var(--ink-color);
  color: var(--ink-color);
}

/* Service cards — lined-paper notebook, slight per-card rotation */
body[data-active-theme="paper"] .service-card {
  background:
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent 22px,
      rgba(var(--ink-color-rgb), 0.1) 22px,
      rgba(var(--ink-color-rgb), 0.1) 23px
    ),
    var(--paper-color);
  border: 1.5px solid var(--ink-color);
  color: var(--ink-color);
}
body[data-active-theme="paper"] .service-num {
  color: rgba(var(--ink-color-rgb), 0.5);
}
body[data-active-theme="paper"] .service-title {
  color: var(--ink-color);
}
body[data-active-theme="paper"] .service-desc {
  color: rgba(var(--ink-color-rgb), 0.75);
}
body.paper .paper-card:nth-child(3n + 1) {
  transform: rotate(-0.6deg);
}
body.paper .paper-card:nth-child(3n + 2) {
  transform: rotate(0.35deg);
}
body.paper .paper-card:nth-child(3n + 3) {
  transform: rotate(-0.2deg);
}

body[data-active-theme="paper"] .nav-cta {
  color: var(--theme-primary);
  border-color: var(--theme-primary);
}
body[data-active-theme="paper"] .nav-cta:hover,
body[data-active-theme="paper"] .nav-cta.active {
  background: var(--theme-primary);
  color: var(--paper-color);
}

/* Contact */
body[data-active-theme="paper"] #contact {
  border-color: rgba(var(--ink-color-rgb), 0.25);
}
body[data-active-theme="paper"] .contact-heading {
  color: var(--ink-color);
}
body[data-active-theme="paper"] .contact-sub {
  color: rgba(var(--ink-color-rgb), 0.7);
}
body[data-active-theme="paper"] .contact-link {
  background: transparent;
  border-color: rgba(var(--ink-color-rgb), 0.3);
  color: var(--ink-color);
}

/* Footer */
body[data-active-theme="paper"] footer {
  border-top-color: rgba(var(--ink-color-rgb), 0.2);
}
body[data-active-theme="paper"] .footer-info {
  border-top-color: rgba(var(--ink-color-rgb), 0.15);
}
body[data-active-theme="paper"] .footer-badge::before {
  background: var(--ink-color);
}
body[data-active-theme="paper"] .footer-copy,
body[data-active-theme="paper"] .footer-text,
body[data-active-theme="paper"] .footer-brand,
body[data-active-theme="paper"] .footer-col-title,
body[data-active-theme="paper"] .footer-link,
body[data-active-theme="paper"] .footer-badge {
  color: var(--ink-color);
}

/* Section labels, about headings — all ink */
body[data-active-theme="paper"] .section-label,
body[data-active-theme="paper"] .about-heading,
body[data-active-theme="paper"] .about-body,
body[data-active-theme="paper"] .stat-num,
body[data-active-theme="paper"] .stat-label {
  color: var(--ink-color);
}

/* "Full-stack" emphasis — base rule applies a sky-blue gradient via
   -webkit-text-fill-color: transparent.  Override both the gradient
   and the fill so the emphasis reads as ink, matching the rest of the
   heading rather than reverting to brand blue. */
body[data-active-theme="paper"] .about-heading em {
  background: none;
  color: var(--ink-color);
  -webkit-text-fill-color: var(--ink-color);
}

/* Light-appearance paper — brighter paper, darker ink */
body.light-appearance[data-active-theme="paper"] {
  --paper-color: #fbf2dd;
  --ink-color: #140e0a;
  --ink-color-rgb: 20, 14, 10;
}
body.light-appearance[data-active-theme="paper"] #bg-canvas {
  filter: saturate(0.2) contrast(1.05) sepia(0.3);
}

/* ══════════════════════════════════════════════════════════════
   Achievements — Cloudlog
   ══════════════════════════════════════════════════════════════ */

/* ── Nav Button ── */

.achievement-btn {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.5);
  transition:
    color 0.3s,
    border-color 0.3s,
    background 0.3s;
  position: relative;
}
.achievement-btn:hover,
.achievement-btn.active {
  color: #fff;
  border-color: rgba(var(--theme-glow), 0.4);
  background: rgba(var(--theme-glow), 0.08);
}
.achievement-btn svg {
  width: 14px;
  height: 14px;
}

/* Nav-light variant */
nav.nav-light .achievement-btn {
  color: rgba(var(--ink-rgb), 0.5);
  border-color: rgba(0, 0, 0, 0.1);
}
nav.nav-light .achievement-btn:hover,
nav.nav-light .achievement-btn.active {
  color: var(--ink);
  border-color: rgba(26, 95, 168, 0.4);
  background: rgba(var(--theme-glow), 0.08);
}

/* Tooltip — matches appearance-toggle pattern */
.achievement-btn::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.65);
  background: rgba(var(--ink-rgb), 0.92);
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
.achievement-btn:hover::after {
  opacity: 1;
}
nav.nav-light .achievement-btn::after {
  color: rgba(var(--ink-rgb), 0.7);
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* ── Badge ── */

.achievement-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 14px;
  height: 14px;
  border-radius: 7px;
  background: var(--sky-4, #378add);
  color: #fff;
  font-family: "DM Mono", monospace;
  font-size: 0.5rem;
  font-weight: 700;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  line-height: 1;
  pointer-events: none;
}
.achievement-badge.visible {
  display: flex;
}
.achievement-badge.pulse {
  animation: achievement-badge-pulse 0.6s ease-out;
}
@keyframes achievement-badge-pulse {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.4);
  }
  100% {
    transform: scale(1);
  }
}

/* ── Panel ── */

.achievement-panel {
  position: fixed;
  top: 0;
  right: 0;
  width: 360px;
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  background: rgba(var(--ink-rgb), 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  z-index: var(--z-panel);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.3s ease-out;
  overflow: hidden;
}
.achievement-panel.open {
  transform: translateX(0);
}

/* ── Panel Header ── */

.achievement-header {
  padding: 1.2rem 1.2rem 0.8rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.achievement-title-row {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}
.achievement-title {
  font-family: "Syne", sans-serif;
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  margin: 0;
}
.achievement-points-total {
  font-family: "DM Mono", monospace;
  font-size: 0.7rem;
  color: var(--sky-3, #7dbfe8);
  letter-spacing: 0.05em;
}
.achievement-close {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.4);
  padding: 4px;
  transition: color 0.2s;
}
.achievement-close:hover {
  color: #fff;
}
.achievement-close svg {
  width: 14px;
  height: 14px;
}

/* Hint toggle */
.achievement-header-controls {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 0.3rem;
}
.achievement-hint-toggle {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.4);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.achievement-hint-toggle input {
  accent-color: var(--sky-4);
}
.achievement-mark-read {
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.3);
  background: none;
  border: none;
  padding: 0;
  transition: color 0.2s;
}
.achievement-mark-read:hover {
  color: rgba(255, 255, 255, 0.6);
}

/* ── Tabs ── */
/* Horizontal tab row between the Cloudlog header and the scrollable body.
   Switches between the Achievements view (grouped sets) and Activity
   view (reverse-chron log of unlocks). */

.achievement-tabs {
  display: flex;
  gap: 0.2rem;
  padding: 0 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.achievement-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 0.9rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: rgba(255, 255, 255, 0.4);
  font-family: "Syne", sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: -1px;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}
.achievement-tab:hover {
  color: rgba(255, 255, 255, 0.7);
}
.achievement-tab.active {
  color: #fff;
  border-bottom-color: var(--sky-3);
}
.achievement-tab-badge {
  display: none;
  padding: 1px 6px;
  background: var(--sky-3);
  color: #0a1628;
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  border-radius: 100px;
  min-width: 16px;
  text-align: center;
}
.achievement-tab-badge.visible {
  display: inline-block;
}

/* Tab views — only the active one is rendered.  The default (Achievements)
   is marked .active at build time in buildPanel. */
/* Each tab view owns its own scroll position so switching tabs returns
   the user to where they were, not to a shared scrollTop carried over
   from the other tab.  Padding lives on the view, not the body, so the
   hover-halo and click-pop pseudo-elements have horizontal breathing
   room before hitting the scroll-container clip box (overflow-y: auto
   clips on both axes per spec — there is no scroll-vertical-only mode). */
.achievement-view {
  display: none;
  flex-direction: column;
  gap: 0.8rem;
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  padding: 0.8rem;
}
.achievement-view.active {
  display: flex;
}
/* Direct children of the scroll container must not flex-shrink, or
   the column layout will compress them below their natural height
   when the content fits — collapsing the intro card and any sections
   shorter than they should be. */
.achievement-view > * {
  flex-shrink: 0;
}
.achievement-view::-webkit-scrollbar {
  width: 4px;
}
.achievement-view::-webkit-scrollbar-track {
  background: transparent;
}
.achievement-view::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 2px;
}

/* ── Activity view ── */
/* Reverse-chron stack of toast-style rows.  Each row reuses the live
   .achievement-toast markup so the two surfaces stay visually identical. */

.activity-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.2rem;
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.4);
  letter-spacing: 0.04em;
}
.activity-clear {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.5);
  font-family: inherit;
  font-size: 0.55rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 100px;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}
.activity-clear:hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.3);
}

.activity-empty {
  padding: 1.5rem 0.5rem;
  text-align: center;
  color: rgba(255, 255, 255, 0.35);
  font-family: "DM Mono", monospace;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
}

.activity-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Onboarding hint shown above the activity list while the user is still
   in the discovery phase.  Slimmer than the Achievements-tab intro card
   so it reads as a tip, not a peer of the entries below it. */
.activity-intro-hint {
  padding: 0.5rem 0.65rem;
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.1) 0%,
    rgba(var(--theme-glow), 0.03) 100%
  );
  border-left: 2px solid var(--achievement-default-accent);
  border-radius: 0 6px 6px 0;
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.03em;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.7);
}

.activity-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
/* Embedded toast inside the activity list — override the live-toast's
   slide-in styles so it sits as a normal list item.  Higher specificity
   (two classes + one type) wins over the live-toast rules without needing
   !important. */
.activity-list .activity-row .achievement-toast {
  position: relative;
  transform: none;
  translate: none;
  opacity: 1;
  width: 100%;
}
.activity-list .activity-row.unseen .achievement-toast {
  outline: 1px solid rgba(125, 191, 232, 0.4);
  outline-offset: 1px;
}
.activity-list .activity-row.shine .achievement-toast {
  animation: activity-row-shine 0.8s ease-out;
}
@keyframes activity-row-shine {
  0% {
    background: rgba(255, 255, 255, 0.15);
  }
  100% {
    background: transparent;
  }
}
.activity-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.4rem;
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 0.04em;
}
.activity-time {
  flex: 1;
}
.activity-dismiss,
.activity-restore {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.3);
  padding: 2px;
  display: inline-flex;
  align-items: center;
  transition: color 0.2s ease;
}
.activity-dismiss:hover {
  color: rgba(255, 100, 100, 0.8);
}
.activity-restore:hover {
  color: rgba(125, 191, 232, 0.95);
}
.activity-dismiss svg,
.activity-restore svg {
  width: 10px;
  height: 10px;
}

/* Trashed rows are dimmed so they read as "out of sight, recoverable". */
.activity-list .activity-row.trashed .achievement-toast {
  opacity: 0.55;
  filter: saturate(0.7);
}
.activity-list .activity-row.trashed:hover .achievement-toast {
  opacity: 0.85;
  filter: none;
}

/* ── Theme-switch row ── */
/* Slimmer than achievement rows so they read as ambient transitions
   rather than peer events.  Theme color flows through --theme-color
   set inline; the left border + icon adopt it so each theme has a
   distinct visual signature in the log. */
.activity-theme-switch {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.6rem;
  background: rgba(255, 255, 255, 0.03);
  border-left: 2px solid var(--theme-color, rgba(255, 255, 255, 0.2));
  border-radius: 0 4px 4px 0;
  transition:
    background 0.2s ease,
    opacity 0.2s ease;
}
.activity-theme-switch:hover {
  background: rgba(255, 255, 255, 0.06);
}
.activity-theme-switch-icon {
  display: inline-flex;
  width: 14px;
  height: 14px;
  color: var(--theme-color, rgba(255, 255, 255, 0.5));
  flex-shrink: 0;
}
.activity-theme-switch-icon svg {
  width: 100%;
  height: 100%;
}
.activity-theme-switch-text {
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.7);
  letter-spacing: 0.03em;
}
.activity-list .activity-row.trashed .activity-theme-switch {
  opacity: 0.55;
  filter: saturate(0.7);
}
.activity-list .activity-row.trashed:hover .activity-theme-switch {
  opacity: 0.85;
  filter: none;
}

/* Footer — trash-view toggle.  Absent when the log is empty AND there's
   nothing in the trash. */
.activity-footer {
  display: flex;
  justify-content: center;
  padding: 0.4rem 0 0.2rem;
  margin-top: 0.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.activity-trash-toggle {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.45);
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 100px;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}
.activity-trash-toggle:hover {
  color: rgba(255, 255, 255, 0.85);
  border-color: rgba(255, 255, 255, 0.25);
}

/* ── Panel Body ── */

.achievement-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* ── Panel Footer ── */

.achievement-footer {
  padding: 0.8rem 1.2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.achievement-hide-btn {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.3);
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  padding: 0;
  transition: color 0.2s;
}
.achievement-hide-btn:hover {
  color: rgba(255, 255, 255, 0.6);
}
.achievement-count-total {
  position: relative;
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.3);
  letter-spacing: 0.05em;
}
.achievement-count-total::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  right: 0;
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.65);
  background: rgba(var(--ink-rgb), 0.92);
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
.achievement-count-total:hover::after {
  opacity: 1;
}

/* ── Achievement Set ── */

.achievement-set {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.achievement-set.dimmed {
  opacity: 0.6;
}
.achievement-set-header {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem;
  border-left: 3px solid rgba(255, 255, 255, 0.15);
  border-radius: 0 4px 4px 0;
  background: rgba(10, 18, 32, 0.95);
}
.achievement-set-name {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: "Syne", sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.8);
  flex: 1;
}
/* Theme icon shown next to the set name — tinted to the set accent color
   via currentColor on the SVG.  Matches the HUD's theme icon sizing. */
.achievement-set-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  color: var(--set-color, rgba(255, 255, 255, 0.7));
  filter: drop-shadow(0 0 3px currentColor);
}
.achievement-set-icon svg {
  width: 100%;
  height: 100%;
}
.achievement-set.dimmed .achievement-set-icon {
  filter: none;
  opacity: 0.6;
}
.achievement-set-count {
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.4);
  letter-spacing: 0.04em;
}

/* Progress bar */
.achievement-progress {
  width: 100%;
  height: 2px;
  background: rgba(255, 255, 255, 0.06);
  border-radius: 1px;
  overflow: hidden;
  margin-top: 2px;
}
.achievement-progress-bar {
  height: 100%;
  background: var(--achievement-default-accent);
  border-radius: 1px;
  transition: width 0.4s ease-out;
}

/* ── Achievement Card ── */

.achievement-card {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
  position: relative;
  transition:
    opacity 0.3s,
    background 0.3s;
}
.achievement-card.locked,
.achievement-card.hidden-ach {
  opacity: 0.4;
}
.achievement-card.unlocked {
  opacity: 1;
  background: rgba(255, 255, 255, 0.04);
}
.achievement-card.unlocked:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* Glow pseudo-element — opacity animation is GPU-composited */
.achievement-card.unlocked::before,
.achievement-toast::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow:
    0 0 20px -2px var(--set-color, #7dbfe8),
    0 0 4px 0 var(--set-color, #7dbfe8);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
  will-change: opacity;
}
.achievement-card.unlocked:hover::before,
.achievement-toast:hover::before {
  animation: card-glow 2s ease-in-out infinite;
}
@keyframes card-glow {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

/* Shimmer sweep on hover */
.achievement-card.unlocked::after,
.achievement-toast::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    105deg,
    transparent 0%,
    transparent 40%,
    rgba(255, 255, 255, 0.06) 50%,
    transparent 60%,
    transparent 100%
  );
  background-size: 400% 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
}
.achievement-card.unlocked:hover::after,
.achievement-toast:hover::after {
  opacity: 1;
  animation: card-shimmer 6s linear infinite;
}
@keyframes card-shimmer {
  0% {
    background-position: 150% 0;
  }
  100% {
    background-position: -150% 0;
  }
}

/* Click pop — squish then spring back */
.achievement-card.unlocked.clicked,
.achievement-toast.clicked {
  animation: card-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes card-pop {
  0% {
    transform: translateY(0) scale(1);
  }
  35% {
    transform: translateY(0) scale(0.96);
  }
  70% {
    transform: translateY(0) scale(1.03);
  }
  100% {
    transform: translateY(0) scale(1);
  }
}

/* Click shimmer — fast single sweep */
.achievement-toast.clicked::after {
  opacity: 1;
  animation: card-shimmer-flash 0.4s ease-out;
}
@keyframes card-shimmer-flash {
  0% {
    background-position: 150% 0;
  }
  100% {
    background-position: -150% 0;
  }
}

.achievement-card.shine {
  animation: achievement-shine 0.8s ease-out;
}
@keyframes achievement-shine {
  0% {
    background: rgba(255, 255, 255, 0.15);
  }
  100% {
    background: rgba(255, 255, 255, 0.04);
  }
}

.achievement-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.5);
}
.achievement-icon svg {
  width: 18px;
  height: 18px;
}
.achievement-card.unlocked .achievement-icon {
  color: var(--sky-3, #7dbfe8);
}

.achievement-text {
  flex: 1;
  min-width: 0;
  min-height: 2.9rem;
}
.achievement-card-title {
  font-family: "Syne", sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.8);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.achievement-card.locked .achievement-card-title,
.achievement-card.hidden-ach .achievement-card-title {
  color: rgba(255, 255, 255, 0.5);
}
.achievement-card-desc {
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.35);
  line-height: 1.4;
  margin-top: 1px;
}
.achievement-card.unlocked .achievement-card-desc {
  color: rgba(255, 255, 255, 0.5);
}
.achievement-card-time {
  display: inline-block;
  font-family: "DM Mono", monospace;
  font-size: 0.5rem;
  color: rgba(255, 255, 255, 0.25);
  margin-top: 2px;
  letter-spacing: 0.03em;
  transition: color 0.2s;
}
.achievement-card-time:hover {
  color: rgba(255, 255, 255, 0.45);
}
.achievement-card-pts {
  flex-shrink: 0;
  font-family: "DM Mono", monospace;
  font-size: 0.6rem;
  font-weight: 700;
  color: var(--achievement-default-accent);
  opacity: 0.6;
  min-width: 20px;
  text-align: right;
}
.achievement-card.unlocked .achievement-card-pts {
  opacity: 1;
}

/* ── Unseen Indicator ── */

.achievement-card.unseen .achievement-card-time::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--set-color, var(--achievement-default-accent));
  box-shadow: 0 0 6px var(--set-color, var(--achievement-default-accent));
  margin-right: 5px;
  vertical-align: middle;
  position: relative;
  top: -0.5px;
  animation: unseen-pulse 2s ease-in-out infinite;
  transition:
    opacity 0.4s,
    transform 0.4s;
}
@keyframes unseen-pulse {
  0%,
  100% {
    opacity: 0.7;
    box-shadow: 0 0 4px var(--set-color, var(--achievement-default-accent));
  }
  50% {
    opacity: 1;
    box-shadow: 0 0 10px var(--set-color, var(--achievement-default-accent));
  }
}
.achievement-card.seen-fade .achievement-card-time::before {
  opacity: 0;
  transform: scale(0);
}

/* ── Card Progress (progressive achievements) ── */

.achievement-card-progress-text {
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.35);
  white-space: nowrap;
  letter-spacing: 0.03em;
}
.achievement-card-progress-bar-wrap {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: rgba(255, 255, 255, 0.06);
  border-radius: 0 0 6px 6px;
  overflow: hidden;
}
.achievement-card-progress-bar-fill {
  height: 100%;
  background: var(--set-color, var(--achievement-default-accent));
  border-radius: 0 0 6px 6px;
  transition: width 0.4s ease-out;
}
/* Segmented variant — one tick per progress unit, used when the count
   is small enough that individual segments are still readable.  The
   wrap's own track background shows through the gaps as the unfilled
   tick. */
.achievement-card-progress-bar-wrap.segmented {
  display: flex;
  gap: 2px;
  background: transparent;
}
.achievement-card-progress-bar-segment {
  flex: 1;
  height: 100%;
  background: rgba(255, 255, 255, 0.06);
  transition: background 0.3s ease-out;
}
.achievement-card-progress-bar-segment.filled {
  background: var(--set-color, var(--achievement-default-accent));
}

/* ── Relocked Card State ── */

.achievement-card.relocked {
  opacity: 0.7;
  border-left: 2px dashed rgba(255, 200, 50, 0.35);
}
.achievement-card.relocked .achievement-icon {
  opacity: 0.7;
}
.achievement-card.relocked .achievement-card-pts {
  opacity: 0.5;
}
.achievement-card.de-shine {
  animation: achievement-de-shine 0.8s ease-out;
}
@keyframes achievement-de-shine {
  0% {
    background: rgba(255, 255, 255, 0.02);
  }
  30% {
    background: rgba(255, 200, 50, 0.08);
  }
  100% {
    background: rgba(255, 255, 255, 0.02);
  }
}

/* ── Intro Card ── */

/* Onboarding card prepended to the Achievements view while the user is
   still in the discovery phase.  Visually distinct from regular cards
   (gradient tint, accent left border, soft pulse) so it reads as
   contextual guidance rather than another locked entry. */
.achievement-card.achievement-intro-card {
  opacity: 1;
  background: linear-gradient(
    135deg,
    rgba(var(--theme-glow), 0.12) 0%,
    rgba(var(--theme-glow), 0.04) 100%
  );
  border-left: 2px solid var(--achievement-default-accent);
  padding-left: calc(0.5rem - 2px);
  overflow: hidden;
}
.achievement-card.achievement-intro-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow:
    inset 0 0 24px -8px rgba(125, 191, 232, 0.3),
    0 0 12px -4px rgba(var(--theme-glow), 0.2);
  pointer-events: none;
  animation: achievement-intro-pulse 4s ease-in-out infinite;
}
@keyframes achievement-intro-pulse {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}
.achievement-intro-icon {
  color: var(--achievement-default-accent);
  filter: drop-shadow(0 0 6px rgba(var(--theme-glow), 0.6));
}
.achievement-card.achievement-intro-card .achievement-card-title {
  color: rgba(255, 255, 255, 0.95);
  font-weight: 600;
}
.achievement-card.achievement-intro-card .achievement-card-desc {
  color: rgba(255, 255, 255, 0.7);
}

/* ── Re-lock Toast ── */

.achievement-toast-relock {
  border-left-color: rgba(255, 200, 50, 0.5);
}
.achievement-toast-relock-icon {
  opacity: 0.6;
}

/* ── Achievement Tooltip ── */

.achievement-tooltip {
  position: fixed;
  z-index: var(--z-tooltip);
  max-width: 320px;
  padding: 0.4rem 0.65rem;
  background: rgba(var(--ink-rgb), 0.95);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.7);
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%) translateY(4px);
  transition:
    opacity 0.2s,
    transform 0.2s;
  white-space: nowrap;
}
.achievement-tooltip.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
body.light-appearance .achievement-tooltip {
  background: rgba(240, 247, 255, 0.96);
  border-color: rgba(0, 0, 0, 0.1);
  color: rgba(var(--ink-rgb), 0.65);
}

/* ── Toast Notifications ── */

.achievement-toast-container {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
}

.achievement-toast {
  --toast-accent: var(--achievement-default-accent);
  --set-color: var(--toast-accent);
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 0.9rem;
  background: rgba(var(--ink-rgb), 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 3px solid var(--toast-accent);
  border-radius: 8px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  transform: translateY(120%);
  opacity: 0;
  transition:
    transform 0.3s ease-in,
    opacity 0.3s ease-in;
  width: 340px;
  max-width: calc(100vw - 3rem);
}
.achievement-toast.enter {
  transform: translateY(0);
  opacity: 1;
  transition:
    transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.4s ease-out;
}
.achievement-toast.exit {
  transform: translateY(120%);
  opacity: 0;
  transition:
    transform 0.3s ease-in,
    opacity 0.3s ease-in;
}

.achievement-toast-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  color: var(--toast-accent);
}
.achievement-toast-icon svg {
  width: 20px;
  height: 20px;
}
.achievement-toast-body {
  flex: 1;
  min-width: 0;
}
.achievement-toast-title {
  font-family: "Syne", sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  color: #fff;
}
.achievement-toast-desc {
  font-family: "DM Mono", monospace;
  font-size: 0.55rem;
  color: rgba(255, 255, 255, 0.5);
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.achievement-toast-pts {
  flex-shrink: 0;
  font-family: "DM Mono", monospace;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--toast-accent);
  min-width: 20px;
  text-align: right;
}

/* ── Activation Toast ── */

.achievement-activation-toast {
  position: fixed;
  top: 5rem;
  left: 50%;
  transform: translateX(-50%) translateY(-12px);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 1rem;
  background: rgba(var(--ink-rgb), 0.92);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 100px;
  z-index: var(--z-toast);
  opacity: 0;
  transition:
    opacity 0.4s ease-out,
    transform 0.4s ease-out;
  pointer-events: none;
}
.achievement-activation-toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.achievement-activation-toast span {
  font-family: "DM Mono", monospace;
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.8);
  letter-spacing: 0.05em;
}
.achievement-activation-icon {
  width: 16px;
  height: 16px;
  color: var(--sky-3, #7dbfe8);
}
.achievement-activation-icon svg {
  width: 16px;
  height: 16px;
}

/* ── Activation Pulse Ring ── */

.achievement-pulse-ring {
  position: fixed;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 2px solid var(--sky-3, #7dbfe8);
  pointer-events: none;
  z-index: var(--z-toast);
  transform: translate(-50%, -50%) scale(0);
  will-change: transform, opacity;
  animation: achievement-pulse-expand 0.8s ease-out forwards;
}
@keyframes achievement-pulse-expand {
  0% {
    transform: translate(-50%, -50%) scale(0);
    opacity: 0.8;
  }
  100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0;
  }
}

/* ── First-Paint Mote ── */

/* Onboarding mote spawned at the visitor's first cursor movement.
   Size and motion are JS-driven; this rule only carries the visual
   style. */
.first-paint-mote {
  position: fixed;
  border-radius: 50%;
  background: radial-gradient(
    circle at center,
    var(--sky-3, #7dbfe8) 0%,
    rgba(125, 191, 232, 0.6) 40%,
    transparent 75%
  );
  box-shadow:
    0 0 8px var(--sky-3, #7dbfe8),
    0 0 16px rgba(125, 191, 232, 0.4);
  pointer-events: none;
  z-index: var(--z-toast);
  transform: translate(-50%, -50%);
  will-change: transform, opacity;
}
body.light-appearance .first-paint-mote {
  background: radial-gradient(
    circle at center,
    rgba(var(--theme-glow), 0.9) 0%,
    rgba(var(--theme-glow), 0.4) 40%,
    transparent 75%
  );
  box-shadow:
    0 0 8px rgba(var(--theme-glow), 0.7),
    0 0 16px rgba(var(--theme-glow), 0.3);
}

/* ── Theme History HUD ── */
/* Two stacked pills: a small handle tab on top (with a chevron), and a
   wider track pill below (with theme icons).  The handle tab looks
   identical in tucked and expanded states — the track just shows/hides
   beneath it.  That way the chevron's visual position is always "a small
   tab hanging off the nav bar", never embedded in the track. */

.theme-history-hud {
  position: absolute;
  top: 100%;
  left: 50%;
  translate: -50% -4px;
  margin-top: 8px;
  opacity: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  pointer-events: auto;
  transition:
    opacity 0.5s ease-out,
    translate 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.theme-history-hud.ready {
  opacity: 1;
  translate: -50% 0;
}

/* ── Handle pill ── */
/* Small floating tab at the top of the HUD column.  A single chevron
   button rotates with the HUD's tucked/expanded state. */
.thh-handle-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px 8px;
  background: rgba(10, 18, 32, 0.5);
  border: 1px solid rgba(120, 160, 220, 0.14);
  border-radius: 100px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition:
    background 0.3s ease,
    border-color 0.3s ease;
}
.theme-history-hud:not(.tucked) .thh-handle-slot {
  background: rgba(10, 18, 32, 0.6);
  border-color: rgba(120, 160, 220, 0.22);
}
.thh-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 12px;
  padding: 0;
  background: none;
  border: none;
  color: rgba(180, 210, 240, 0.55);
  transition: color 0.2s ease;
}
.thh-handle:hover,
.thh-handle:focus-visible {
  color: rgba(200, 230, 255, 0.95);
  outline: none;
}
.thh-handle svg {
  width: 12px;
  height: 6px;
  transition: transform 0.25s ease;
}
/* Chevron points down when tucked (invitation to expand), and flips up
   when the HUD is open (invitation to tuck). */
.theme-history-hud:not(.tucked) .thh-handle svg {
  transform: rotate(180deg);
}

/* ── Track pill ── */
/* Separate pill below the handle, holding the theme icons and labels.
   Hidden entirely when tucked. */
.thh-track {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  max-width: calc(100vw - 1rem);
  background: rgba(10, 18, 32, 0.55);
  border: 1px solid rgba(120, 160, 220, 0.18);
  border-radius: 100px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition:
    padding 0.3s cubic-bezier(0.22, 1, 0.36, 1),
    background 0.3s ease,
    border-color 0.3s ease;
}
.theme-history-hud.expanded .thh-track {
  padding: 8px 14px;
  background: rgba(10, 18, 32, 0.82);
  border-color: rgba(120, 160, 220, 0.32);
}
.theme-history-hud.tucked .thh-track {
  display: none;
}

.thh-slot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 3px 4px;
  margin: 0;
  /* Match the label's font-size so `1ch` in --thh-slot-width resolves at
     label scale — otherwise ch inherits the 16px body size and slots are
     roughly 2x wider than needed. */
  font-size: 9px;
  width: var(--thh-slot-width, 8ch);
  background: none;
  border: none;
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.4);
  font-family: "DM Mono", monospace;
  cursor: default;
  transition:
    color 0.25s ease,
    background 0.25s ease,
    transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.thh-slot.discovered {
  color: var(--theme-color, #7dbfe8);
}
.thh-slot.discovered:hover {
  background: rgba(255, 255, 255, 0.06);
  transform: translateY(-1px);
}
.thh-slot.discovered:focus-visible {
  outline: 1px solid var(--theme-color, #7dbfe8);
  outline-offset: 2px;
}
.thh-slot.active::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--theme-color, #7dbfe8);
  box-shadow: 0 0 6px 1px var(--theme-color, #7dbfe8);
  translate: -50% 0;
}

.thh-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  filter: drop-shadow(0 0 4px currentColor);
}
.thh-slot.undiscovered .thh-icon {
  filter: none;
  opacity: 0.35;
}

.thh-label {
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition:
    max-height 0.3s ease,
    opacity 0.25s ease 0.05s;
}
.theme-history-hud.expanded .thh-label {
  max-height: 14px;
  opacity: 0.9;
}

/* Active-theme pulse — soft halo in the theme's accent color */
@keyframes thh-pulse {
  0% {
    box-shadow: 0 0 0 0 var(--theme-color, #7dbfe8);
    opacity: 0.6;
  }
  100% {
    box-shadow: 0 0 0 14px transparent;
    opacity: 0;
  }
}
.thh-slot.pulse .thh-icon {
  animation: thh-pulse 1.2s ease-out;
}

/* Newly discovered — periodic sheen sweep for the first few seconds.
   Uses the same pattern as card-shimmer: linear easing + full off-screen
   sweep per cycle so there's no visible pause at either edge when looping. */
@keyframes thh-shimmer {
  0% {
    background-position: 150% 0;
  }
  100% {
    background-position: -150% 0;
  }
}
.thh-slot.just-discovered::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 8px;
  pointer-events: none;
  background: linear-gradient(
    110deg,
    transparent 40%,
    rgba(255, 255, 255, 0.28) 50%,
    transparent 60%
  );
  background-size: 400% 100%;
  animation: thh-shimmer 2.2s linear infinite;
}

/* Reduced motion — keep HUD functional but drop shimmer + pulse */
@media (prefers-reduced-motion: reduce) {
  .thh-slot.just-discovered::before,
  .thh-slot.pulse .thh-icon {
    animation: none;
  }
}

/* Narrow viewport — below this, the labelled track would overflow past
   nav's edges even with all five labels fitting individually (gaps +
   padding accumulate).  Hide labels, collapse slot width to the icon. */
@media (max-width: 560px) {
  .thh-track {
    gap: 2px;
  }
  .thh-slot {
    width: auto;
    padding: 3px 6px;
  }
  .thh-label {
    display: none;
  }
}

/* ── VHS Theme ── */

/* Wipe — vertical-roll static.  The rolling animation runs continuously
   so the static keeps moving for the entire cover+reveal window; without
   `infinite`, the keyframe finishes early and the wipe freezes mid-fade. */
.vhs-wipe {
  position: fixed;
  inset: 0;
  z-index: var(--z-theme-wipe);
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.9) 0,
      rgba(0, 0, 0, 0.9) 3px,
      rgba(255, 255, 255, 0.7) 3px,
      rgba(255, 255, 255, 0.7) 4px,
      rgba(0, 0, 0, 0.9) 4px,
      rgba(0, 0, 0, 0.9) 7px,
      rgba(140, 180, 220, 0.45) 7px,
      rgba(140, 180, 220, 0.45) 8px,
      rgba(255, 80, 220, 0.25) 8px,
      rgba(255, 80, 220, 0.25) 9px,
      rgba(80, 255, 220, 0.25) 9px,
      rgba(80, 255, 220, 0.25) 10px
    ),
    rgba(40, 50, 70, 0.7);
  background-size: 100% 24%;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s linear;
  animation: vhs-wipe-roll 0.4s linear infinite paused;
}
.vhs-wipe.active {
  opacity: 1;
  animation-play-state: running;
}
@keyframes vhs-wipe-roll {
  from {
    background-position-y: 0;
  }
  to {
    background-position-y: 100%;
  }
}
.vhs-wipe.eject {
  background: linear-gradient(
    to bottom,
    rgba(40, 50, 70, 0.6) 0%,
    rgba(0, 0, 0, 0.97) 48%,
    rgba(0, 0, 0, 0.97) 52%,
    rgba(40, 50, 70, 0.6) 100%
  );
  background-size: 100% 100%;
  animation: vhs-wipe-eject 0.5s ease-in-out forwards;
}
@keyframes vhs-wipe-eject {
  from {
    background-size: 100% 100%;
  }
  to {
    background-size: 100% 1px;
    background-position-y: 50%;
  }
}

/* ── VHS — visual theme (only when active theme) ── */

body[data-active-theme="vhs"] {
  --vhs-phosphor: #b4f0b4;
  --vhs-phosphor-rgb: 180, 240, 180;
  --vhs-tape: #708ca0;
  --theme-primary: var(--vhs-phosphor);
  --theme-glow: 220, 255, 220;
}

body[data-active-theme="vhs"] #bg-canvas {
  filter: saturate(0.7) contrast(1.15) brightness(0.88);
}

/* Persistent scanline overlay — always on while VHS is active.  Bright
   line + dark gap + faint cyan tint per band; the slow vertical drift
   keeps the lines from looking pasted on, exactly like a CRT held up
   against a real signal. */
body[data-active-theme="vhs"]::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.32) 0,
    rgba(0, 0, 0, 0.32) 2px,
    rgba(120, 200, 180, 0.05) 2px,
    rgba(120, 200, 180, 0.05) 3px,
    transparent 3px,
    transparent 4px
  );
  animation: vhs-scanline-drift 4s linear infinite;
}
@keyframes vhs-scanline-drift {
  from {
    background-position-y: 0;
  }
  to {
    background-position-y: 4px;
  }
}

/* CRT vignette — corners darken slightly so the page reads as a curved
   tube.  Sits above scanlines (z 2) and below page content. */
body[data-active-theme="vhs"]::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background: radial-gradient(
    ellipse at center,
    transparent 50%,
    rgba(0, 0, 0, 0.35) 90%,
    rgba(0, 0, 0, 0.55) 100%
  );
  mix-blend-mode: multiply;
}

/* Static noise overlay — full-screen SVG turbulence at low alpha.  The
   slow position drift gives it the constant boil that real tape hiss
   has, without the cost of a JS-driven canvas redraw every frame. */
body[data-active-theme="vhs"] .vhs-noise {
  position: fixed;
  inset: -50%;
  width: 200%;
  height: 200%;
  pointer-events: none;
  z-index: 3;
  opacity: 0.18;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.7 0 0 0 0 0.85 0 0 0 0 0.75 0 0 0 0.55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
  animation: vhs-noise-drift 0.6s steps(6) infinite;
  mix-blend-mode: screen;
}
@keyframes vhs-noise-drift {
  0% {
    transform: translate(0, 0);
  }
  20% {
    transform: translate(-3%, 2%);
  }
  40% {
    transform: translate(2%, -2%);
  }
  60% {
    transform: translate(-2%, -1%);
  }
  80% {
    transform: translate(1%, 3%);
  }
  100% {
    transform: translate(0, 0);
  }
}

/* Iconic VHS rolling tracking band — drifts down the screen on a long
   cycle and *distorts* the content directly beneath it using
   backdrop-filter (hue-rotate + saturate + brightness + blur), which is
   what reads as the actual tearing on real worn tape.  ::before and
   ::after are the tear's leading/trailing chroma fringes.
   z 4 sits above the noise (z 3). */
body[data-active-theme="vhs"] .vhs-tracking-band {
  position: fixed;
  left: 0;
  right: 0;
  height: 30px;
  pointer-events: none;
  z-index: 4;
  top: -10%;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.5) 0,
      rgba(255, 255, 255, 0.5) 1px,
      rgba(0, 0, 0, 0.6) 1px,
      rgba(0, 0, 0, 0.6) 2px,
      rgba(160, 220, 240, 0.4) 2px,
      rgba(160, 220, 240, 0.4) 3px
    ),
    linear-gradient(
      to bottom,
      rgba(255, 80, 220, 0.2) 0%,
      rgba(255, 255, 255, 0.1) 50%,
      rgba(80, 255, 220, 0.2) 100%
    );
  backdrop-filter: hue-rotate(25deg) saturate(0.35) brightness(1.45)
    contrast(1.6) blur(1.4px);
  -webkit-backdrop-filter: hue-rotate(25deg) saturate(0.35) brightness(1.45)
    contrast(1.6) blur(1.4px);
  animation: vhs-tracking-roll 7s linear infinite;
}
/* Leading edge — the bright chromatic tear that peels away from the
   band's top.  Strong hue rotation makes the underlying pixels
   visibly shift colour the instant the band reaches them. */
body[data-active-theme="vhs"] .vhs-tracking-band::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -5px;
  height: 5px;
  background: linear-gradient(
    to bottom,
    rgba(255, 80, 220, 0.55) 0%,
    rgba(255, 80, 220, 0.2) 100%
  );
  backdrop-filter: hue-rotate(120deg) saturate(2.4) brightness(1.25) blur(0.6px);
  -webkit-backdrop-filter: hue-rotate(120deg) saturate(2.4) brightness(1.25)
    blur(0.6px);
}
/* Trailing edge — the darker, desaturated drag that remains as the
   band passes by.  Reads as content "snapping back" after the tear. */
body[data-active-theme="vhs"] .vhs-tracking-band::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 4px;
  background: linear-gradient(
    to bottom,
    rgba(80, 255, 220, 0.35) 0%,
    transparent 100%
  );
  backdrop-filter: hue-rotate(-40deg) saturate(0.5) brightness(0.85) blur(0.8px);
  -webkit-backdrop-filter: hue-rotate(-40deg) saturate(0.5) brightness(0.85)
    blur(0.8px);
}
@keyframes vhs-tracking-roll {
  0% {
    top: -10%;
    opacity: 0;
  }
  4% {
    opacity: 1;
  }
  92% {
    opacity: 1;
  }
  100% {
    top: 110%;
    opacity: 0;
  }
}

/* Cursor — CRT pixel with chromatic edges + phosphor bloom */
body[data-active-theme="vhs"] #cursor {
  background: rgba(220, 245, 220, 0.95);
  box-shadow:
    -1px 0 0 rgba(255, 80, 220, 0.55),
    1px 0 0 rgba(80, 255, 220, 0.55),
    0 0 8px rgba(var(--theme-glow), 0.45);
  width: 8px;
  height: 8px;
}
body[data-active-theme="vhs"] #cursor-ring {
  border-color: rgba(160, 200, 160, 0.35);
  border-width: 1px;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(0, 0, 0, 0.08) 2px,
    rgba(0, 0, 0, 0.08) 3px
  );
}

/* Cloud SVG — slight tint and brightness drop (tape decay feel) */
body.vhs .cloud-svg {
  filter: saturate(0.5) hue-rotate(70deg) brightness(0.85);
}

/* Hero — chromatic offset on text.  Doubled-up shadows produce the
   characteristic NTSC channel split — magenta to the left, cyan to the
   right — with a soft phosphor halo behind the white core. */
body[data-active-theme="vhs"] .hero-title {
  color: #e0f0e0;
  text-shadow:
    -2.5px 0 0 rgba(255, 60, 200, 0.7),
    -1px 0 0 rgba(255, 120, 220, 0.4),
    2.5px 0 0 rgba(60, 255, 220, 0.7),
    1px 0 0 rgba(120, 255, 220, 0.4),
    0 0 14px rgba(var(--vhs-phosphor-rgb), 0.35);
  -webkit-text-fill-color: #e0f0e0;
  background: none;
}
body[data-active-theme="vhs"] .hero-tag {
  color: rgba(190, 245, 190, 0.9);
  text-shadow:
    -1.5px 0 0 rgba(255, 60, 200, 0.55),
    1.5px 0 0 rgba(60, 255, 220, 0.55),
    0 0 8px rgba(var(--vhs-phosphor-rgb), 0.3);
}
body[data-active-theme="vhs"] .hero-sub {
  color: rgba(210, 230, 210, 0.9);
  text-shadow:
    -0.8px 0 0 rgba(255, 60, 200, 0.3),
    0.8px 0 0 rgba(60, 255, 220, 0.3);
}

/* Buttons — tape-deck style with phosphor glow */
body[data-active-theme="vhs"] .btn-primary {
  background: linear-gradient(180deg, #2a3a3a 0%, #1a2a2a 100%);
  color: var(--vhs-phosphor);
  border: 1px solid rgba(var(--vhs-phosphor-rgb), 0.4);
  box-shadow: inset 0 0 8px rgba(var(--vhs-phosphor-rgb), 0.15);
}
body[data-active-theme="vhs"] .btn-outline {
  border-color: rgba(var(--vhs-phosphor-rgb), 0.55);
  color: var(--vhs-phosphor);
}

/* Service cards — tape labels.  Class is applied by enableCardEffects. */
body.vhs .vhs-card {
  background: linear-gradient(
    180deg,
    rgba(60, 70, 80, 0.85) 0%,
    rgba(40, 50, 60, 0.85) 100%
  );
  border: 1px solid rgba(var(--vhs-phosphor-rgb), 0.25);
  position: relative;
}
body.vhs .vhs-card::after {
  content: "";
  position: absolute;
  top: 8px;
  right: 8px;
  width: 36px;
  height: 14px;
  background: rgba(var(--vhs-phosphor-rgb), 0.12);
  border: 1px dashed rgba(var(--vhs-phosphor-rgb), 0.3);
}

/* Nav CTA, contact, footer */
body[data-active-theme="vhs"] .nav-cta {
  border-color: rgba(var(--vhs-phosphor-rgb), 0.5);
  text-shadow:
    -1px 0 0 rgba(255, 80, 220, 0.4),
    1px 0 0 rgba(80, 255, 220, 0.4);
}
body[data-active-theme="vhs"] .nav-cta:hover {
  background: var(--vhs-phosphor);
  color: #0a1a0a;
  text-shadow: none;
}
body[data-active-theme="vhs"] #contact {
  border-color: rgba(var(--vhs-phosphor-rgb), 0.25);
}
body[data-active-theme="vhs"] footer {
  border-top-color: rgba(var(--vhs-phosphor-rgb), 0.2);
}

/* Light-appearance VHS: keep chromatic edges, reduce filter aggression */
body.light-appearance[data-active-theme="vhs"] {
  --vhs-phosphor: #4ca84c;
  --vhs-phosphor-rgb: 76, 168, 76;
}
body.light-appearance[data-active-theme="vhs"] #bg-canvas {
  filter: saturate(0.85) contrast(1.05);
}
body.light-appearance[data-active-theme="vhs"] .hero-title {
  color: #1a3a1a;
  -webkit-text-fill-color: #1a3a1a;
  text-shadow:
    -1.5px 0 0 rgba(200, 60, 170, 0.6),
    1.5px 0 0 rgba(60, 200, 170, 0.6);
}

/* Progressive indicator — buildup scanlines.  Opacity ramps via a custom
   property as force grows.  Lives at z 50 (theme buildup range). */
.vhs-scanlines {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-theme-buildup);
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2px,
    rgba(0, 0, 0, 0.18) 2px,
    rgba(0, 0, 0, 0.18) 3px
  );
  opacity: var(--vhs-scanline-opacity, 0);
  transition: opacity 0.2s linear;
}

/* One-shot static interruption flash. */
.vhs-static-flash {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-theme-buildup-flash);
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.6) 0,
      rgba(0, 0, 0, 0.6) 1px,
      rgba(255, 255, 255, 0.4) 1px,
      rgba(255, 255, 255, 0.4) 2px
    ),
    rgba(60, 70, 90, 0.4);
  opacity: 0;
  animation: vhs-static-flash 0.1s linear forwards;
}
@keyframes vhs-static-flash {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* Click-glitch one-shot.  Sized + positioned by JS at the click point. */
.vhs-glitch-rect {
  position: fixed;
  pointer-events: none;
  z-index: var(--z-theme-click-glitch);
  background: rgba(var(--vhs-phosphor-rgb), 0.18);
  border: 1px solid rgba(255, 80, 220, 0.45);
  animation: vhs-glitch-snap 50ms linear forwards;
}
@keyframes vhs-glitch-snap {
  0% {
    transform: translateX(6px);
    opacity: 1;
  }
  100% {
    transform: translateX(0);
    opacity: 0;
  }
}

/* Tracking-drift wobble — applied to .page via JS-driven custom property.
   Uses the standalone `translate` property so it composes with upside-down's
   `transform: scaleY(-1)` instead of clobbering it. */
body[data-active-theme="vhs"] .page {
  translate: var(--vhs-drift-x, 0) 0;
  transition: translate 60ms linear;
}

/* Color-cast filter ramps via custom property as force grows.  Indicator
   stages 2/4 set --vhs-buildup-cast on body to drive the effect. */
body.vhs[data-vhs-buildup="true"] #bg-canvas {
  filter: saturate(var(--vhs-buildup-saturate, 1))
    sepia(var(--vhs-buildup-sepia, 0)) contrast(1.1) brightness(0.92);
}

/* Reduced motion — keep the static look (scanlines, vignette, chromatic
   text) but suppress the animated overlays that move continuously.  The
   theme still reads as VHS without the rolling tracking band, the noise
   boil, or the scanline drift. */
@media (prefers-reduced-motion: reduce) {
  body[data-active-theme="vhs"]::before {
    animation: none;
  }
  body[data-active-theme="vhs"] .vhs-noise,
  body[data-active-theme="vhs"] .vhs-tracking-band {
    display: none;
  }
}

/* ── Upside-down theme adjustments ── */

body.upside-down .achievement-toast-container {
  bottom: auto;
  top: 1.5rem;
  transform: scaleY(-1);
}

/* ── Light appearance ── */

/* Cloudlog panel keeps its dark palette in both appearances — the
   panel is dense with tab labels, hint toggles, theme icons, and
   progress bars that were designed against a dark background.
   Inverting to light produced low-contrast greys across several
   elements, so we stay dark for consistency.  The nav button and its
   badge still adopt light-appearance styling; those sit on the site
   chrome, not inside the panel. */
body.light-appearance .achievement-view::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.1);
}

/* Light appearance toasts */
body.light-appearance .achievement-toast {
  background: rgba(240, 247, 255, 0.95);
  border-color: rgba(0, 0, 0, 0.08);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
body.light-appearance .achievement-toast-title {
  color: var(--ink);
}
body.light-appearance .achievement-toast-desc {
  color: rgba(var(--ink-rgb), 0.5);
}
body.light-appearance .achievement-activation-toast {
  background: rgba(240, 247, 255, 0.95);
  border-color: rgba(0, 0, 0, 0.08);
}
body.light-appearance .achievement-activation-toast span {
  color: var(--ink);
}

/* Light appearance badge */
body.light-appearance .achievement-badge {
  background: var(--sky-5, #1a5fa8);
}

/* ── Mobile ── */

@media (max-width: 700px) {
  .achievement-panel {
    width: 100vw;
  }
  .achievement-toast-container {
    right: 0.75rem;
    left: 0.75rem;
    bottom: 0.75rem;
  }
  .achievement-toast {
    max-width: none;
  }
}
