/* =============================================================
   Rahil Sahu — enhance.css
   ADDITIVE LAYER. Loads after styles.css. Nothing here is required
   for the site to work; with JS off, none of it activates.

   Adds:
     A · Book cover with a real page-turn (two leaves, 3D)
     B · Liquid glass surfaces (iOS-style: blur, specular rim, refraction)
     C · Ambient graphics (drifting light field, grid, grain, spotlight)
     D · Gel-in reveals and pointer-reactive sheen

   Constraints honoured: no inline styles, no external assets,
   no third-party fonts. CSP style-src 'self' safe.
   ============================================================= */

/* -------------------- 0 · Tokens -------------------- */

:root {
  /* Glass — light */
  --g-tint:        rgba(255, 255, 255, 0.46);
  --g-tint-strong: rgba(255, 255, 255, 0.66);
  --g-edge:        rgba(255, 255, 255, 0.85);
  --g-edge-low:    rgba(11, 15, 20, 0.10);
  --g-spec:        rgba(255, 255, 255, 0.92);
  --g-shade:       rgba(11, 15, 20, 0.07);
  --g-cast:        rgba(11, 15, 20, 0.16);
  --g-blur:        18px;
  --g-sat:         180%;
  --g-bright:      1.04;
  --g-r:           16px;
  --g-r-lg:        22px;

  /* Book — warm paper */
  --bk-board:      #fffdf7;
  --bk-board-2:    #f3e8d0;
  --bk-paper:      #f8f0de;
  --bk-paper-2:    #e9dcc2;
  --bk-foil:       #b8862f;
  --bk-stamp:      #b3271e;
  --bk-ink:        #2e2620;
  --bk-ink-dim:    #6f6257;
  --bk-backdrop:   #ece0c6;

  /* Ambient */
  --amb-1:         rgba(185, 28, 28, 0.20);
  --amb-2:         rgba(30, 64, 175, 0.16);
  --amb-3:         rgba(77, 124, 15, 0.14);
  --amb-grid:      rgba(11, 15, 20, 0.05);

  /* Motion */
  --g-ease:        cubic-bezier(.22, 1, .36, 1);
  --g-spring:      cubic-bezier(.34, 1.56, .64, 1);
}

[data-theme="dark"] {
  --g-tint:        rgba(255, 255, 255, 0.055);
  --g-tint-strong: rgba(255, 255, 255, 0.10);
  --g-edge:        rgba(255, 255, 255, 0.16);
  --g-edge-low:    rgba(255, 255, 255, 0.07);
  --g-spec:        rgba(255, 255, 255, 0.30);
  --g-shade:       rgba(0, 0, 0, 0.45);
  --g-cast:        rgba(0, 0, 0, 0.55);
  --g-sat:         160%;
  --g-bright:      1.22;

  --amb-1:         rgba(248, 113, 113, 0.17);
  --amb-2:         rgba(96, 165, 250, 0.14);
  --amb-3:         rgba(163, 230, 53, 0.10);
  --amb-grid:      rgba(255, 255, 255, 0.045);
}

@media (prefers-color-scheme: dark) {
  [data-theme="auto"] {
    --g-tint:        rgba(255, 255, 255, 0.055);
    --g-tint-strong: rgba(255, 255, 255, 0.10);
    --g-edge:        rgba(255, 255, 255, 0.16);
    --g-edge-low:    rgba(255, 255, 255, 0.07);
    --g-spec:        rgba(255, 255, 255, 0.30);
    --g-shade:       rgba(0, 0, 0, 0.45);
    --g-cast:        rgba(0, 0, 0, 0.55);
    --g-sat:         160%;
    --g-bright:      1.22;
    --amb-1:         rgba(248, 113, 113, 0.17);
    --amb-2:         rgba(96, 165, 250, 0.14);
    --amb-3:         rgba(163, 230, 53, 0.10);
    --amb-grid:      rgba(255, 255, 255, 0.045);
  }
}

/* =============================================================
   A · BOOK COVER — warm report cover, Duo-style unfold
   ============================================================= */

/* Boot guard: set by enhance.js the instant it parses, so the page
   never flashes before the cover is in the DOM. If JS is disabled the
   class is never added and the site renders untouched. */
html.enh-boot,
html.enh-locked { overflow: hidden; }
html.enh-boot { background: var(--bk-backdrop); }
html.enh-boot body { visibility: hidden; }
html.enh-boot body .enh-keep,
html.enh-boot body .enh-unfold { visibility: visible; }
/* During the unfold the site is revealed from behind the opening cover,
   so the body must be visible while the boot lock is still on. */
html.enh-unfolding body { visibility: visible; }

.enh-book {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  gap: 1.25rem;
  padding: clamp(1rem, 4vw, 3rem);
  background:
    radial-gradient(120% 90% at 50% 6%, #faf5e9 0%, var(--bk-backdrop) 58%, #dccfae 100%);
  overscroll-behavior: contain;
  -webkit-tap-highlight-color: transparent;
}

/* Warm drifting light behind the book */
.enh-book::before {
  content: "";
  position: absolute;
  inset: -20%;
  pointer-events: none;
  background:
    radial-gradient(38% 30% at 22% 28%, rgba(201, 162, 39, 0.20), transparent 70%),
    radial-gradient(34% 28% at 78% 68%, rgba(178, 39, 30, 0.10), transparent 70%);
  filter: blur(40px);
  animation: enh-drift 22s var(--g-ease) infinite alternate;
}

@keyframes enh-drift {
  0%   { transform: translate3d(-2%, -1%, 0) scale(1); }
  100% { transform: translate3d(3%, 2%, 0) scale(1.08); }
}

/* Auto-adjusting book: substantial on desktop, comfortable on phones */
.enh-stage {
  position: relative;
  width: clamp(300px, 86vw, 540px);
  aspect-ratio: 5 / 6.6;
  max-height: 64vh;
  perspective: 1600px;
  animation: enh-book-in 900ms var(--g-spring) both;
}

@keyframes enh-book-in {
  from { opacity: 0; transform: translate3d(0, 26px, 0) scale(.94); }
  to   { opacity: 1; transform: none; }
}

.enh-body {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

.enh-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 14px;
  overflow: hidden;
}

.enh-face-back { transform: rotateY(180deg); }

/* --- The paper cover: ivory sheet, warm ink --- */
.enh-cover {
  background:
    radial-gradient(130% 100% at 50% 0%, rgba(255, 255, 255, 0.75), transparent 55%),
    linear-gradient(165deg, var(--bk-board) 0%, var(--bk-board-2) 100%);
  color: var(--bk-ink);
  border: 1px solid rgba(146, 106, 44, 0.22);
  padding: clamp(1.4rem, 6%, 2.4rem);
  display: flex;
  flex-direction: column;
  box-shadow:
    0 34px 80px -24px rgba(96, 64, 20, 0.38),
    0 4px 18px rgba(96, 64, 20, 0.12),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* Paper grain — drawn, not loaded */
.enh-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .55;
  background-image:
    repeating-linear-gradient(90deg, rgba(146, 106, 44, 0.05) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(0deg, rgba(146, 106, 44, 0.04) 0 1px, transparent 1px 4px);
}

.enh-band {
  font-family: var(--font-mono);
  font-size: .52rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #f0d488;
  background: linear-gradient(90deg, #3a2817, #5c4020 50%, #3a2817);
  border: 1px solid rgba(201, 162, 39, 0.65);
  border-radius: 3px;
  padding: .42rem .5rem;
  text-align: center;
  position: relative;
  z-index: 1;
  box-shadow: inset 0 1px 0 rgba(240, 212, 136, 0.25);
}

.enh-foil {
  height: 2px;
  margin: 1.1rem 0 1rem;
  position: relative;
  z-index: 1;
  background: linear-gradient(90deg,
    transparent, var(--bk-foil) 12%, #ecd28a 50%, var(--bk-foil) 88%, transparent);
  box-shadow: 0 0 10px rgba(184, 134, 47, 0.4);
}

.enh-monogram {
  font-family: var(--font-mono);
  font-size: .95rem;
  letter-spacing: .1em;
  color: #a5762a;
  position: relative;
  z-index: 1;
}

.enh-doctype {
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bk-ink-dim);
  margin-top: 1.4rem;
  position: relative;
  z-index: 1;
}

.enh-name {
  font-size: clamp(2.2rem, calc(5vw + 1rem), 3.4rem);
  line-height: .98;
  font-weight: 800;
  letter-spacing: -.03em;
  margin: .45rem 0 .5rem;
  color: var(--bk-ink);
  position: relative;
  z-index: 1;
}

.enh-role {
  font-size: .85rem;
  line-height: 1.5;
  color: #57503f;
  max-width: 30ch;
  position: relative;
  z-index: 1;
}

.enh-meta {
  margin-top: auto;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .32rem .9rem;
  font-family: var(--font-mono);
  font-size: .6rem;
  letter-spacing: .04em;
  position: relative;
  z-index: 1;
  padding-top: 1.2rem;
}
.enh-meta dt { color: #9a8a6c; }
.enh-meta dd { color: var(--bk-ink); margin: 0; }

/* Barcode strip — pure CSS, warm ink on paper */
.enh-barcode {
  margin-top: 1rem;
  height: 26px;
  position: relative;
  z-index: 1;
  opacity: .85;
  background: repeating-linear-gradient(90deg,
    #2e2620 0 2px, transparent 2px 4px,
    #2e2620 4px 5px, transparent 5px 9px,
    #2e2620 9px 12px, transparent 12px 14px);
  mask-image: linear-gradient(90deg, #000 0 62%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 62%, transparent 100%);
}

/* Validation stamp — a wax seal pressed into cream */
.enh-stamp {
  position: absolute;
  right: clamp(.9rem, 5%, 1.5rem);
  top: 33%;
  width: 108px;
  height: 108px;
  border: 2px solid var(--bk-stamp);
  border-radius: 50%;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 1px;
  color: var(--bk-stamp);
  font-family: var(--font-mono);
  font-size: .48rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  rotate: -12deg;
  opacity: .94;
  z-index: 2;
  box-shadow:
    inset 0 0 0 5px rgba(178, 39, 30, 0.12),
    inset 0 0 18px rgba(178, 39, 30, 0.10);
  animation: enh-stamp-press 700ms var(--g-spring) 620ms both;
}
.enh-stamp b { font-size: .95rem; letter-spacing: .02em; display: block; }

@keyframes enh-stamp-press {
  0%   { opacity: 0; scale: 1.8; filter: blur(3px); }
  70%  { opacity: .94; scale: .95; filter: blur(0); }
  100% { opacity: .94; scale: 1; }
}

/* --- Inside face: distribution list, glimpsed as the halves swing open --- */
.enh-inside {
  background: linear-gradient(200deg, #f7efdb 0%, #eeddbe 100%);
  color: #57503f;
  border: 1px solid rgba(146, 106, 44, 0.22);
  padding: clamp(1.4rem, 6%, 2.4rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .5rem;
  font-family: var(--font-mono);
  font-size: .62rem;
  letter-spacing: .05em;
  line-height: 1.7;
}
.enh-inside h3 {
  font-size: .56rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #a5762a;
  margin: 0 0 .4rem;
}
.enh-inside ul { list-style: none; margin: 0; padding: 0; }
.enh-inside li { border-bottom: 1px dashed rgba(120, 90, 40, 0.3); padding: .3rem 0; }

/* --- Unfold overlay: the two halves and the hinge glow ---
   Built by JS at open time from a clone of the book. The site is
   revealed from behind as the halves swing open, Duo-style. */
.enh-unfold {
  position: fixed;
  inset: 0;
  z-index: 9001;
  pointer-events: none;
  perspective: 1600px;
}

.enh-half {
  position: fixed;
  overflow: hidden;
  transform-style: preserve-3d;
  will-change: transform, filter, opacity;
}
.enh-half-l { transform-origin: right center; border-radius: 14px 0 0 14px; }
.enh-half-r { transform-origin: left center;  border-radius: 0 14px 14px 0; }

.enh-half-inner {
  position: relative;
  transform-style: preserve-3d;
}
/* Clones must not replay the stamp press mid-unfold */
.enh-half .enh-stamp { animation: none; }

.enh-hinge {
  position: fixed;
  width: 4px;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 251, 240, 0.95) 18%,
    rgba(240, 212, 136, 0.9) 50%,
    rgba(255, 251, 240, 0.95) 82%,
    rgba(255, 255, 255, 0) 100%);
  filter: blur(5px);
  opacity: 0;
  will-change: transform, opacity;
}

/* --- Controls --- */
.enh-controls {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .7rem;
  animation: enh-book-in 900ms var(--g-spring) 260ms both;
}

.enh-openbtn {
  font: inherit;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff8ea;
  padding: .9rem 1.7rem;
  border-radius: 999px;
  border: 1px solid rgba(120, 40, 25, 0.5);
  background: linear-gradient(180deg, #c33a2c, #9c261b);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -2px 0 rgba(0, 0, 0, 0.22),
    0 14px 30px -12px rgba(156, 38, 27, 0.55);
  cursor: pointer;
  transition: transform 260ms var(--g-spring), filter 260ms ease;
}
.enh-openbtn:hover { filter: brightness(1.06); transform: translateY(-2px) scale(1.03); }
.enh-openbtn:active { transform: scale(.96); }
.enh-openbtn:focus-visible { outline: 2px solid #a5762a; outline-offset: 3px; }

.enh-hint {
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .14em;
  color: #7a6c55;
  margin: 0;
}

.enh-skip {
  position: absolute;
  top: max(1rem, env(safe-area-inset-top));
  right: 1rem;
  font-family: var(--font-mono);
  font-size: .6rem;
  letter-spacing: .12em;
  color: #7a6c55;
  background: none;
  border: 0;
  padding: .55rem .7rem;
  cursor: pointer;
  border-radius: 8px;
  z-index: 3;
}
.enh-skip:hover { color: #2e2620; }
.enh-skip:focus-visible { outline: 2px solid #a5762a; outline-offset: 2px; }

/* The site itself arrives like a sheet settling into place as the
   cover unfolds over it. Fixed decorative layers are excluded. */
html.enh-reveal body > *:not(.enh-book):not(.enh-unfold):not(#veil):not(.enh-ambient):not(.enh-grain):not(.enh-spot):not(.enh-svgdefs):not(.matrix-canvas):not(.scroll-progress):not(.skip-link):not(.palette-backdrop):not(.palette-flash) {
  animation: enh-sheet-in 860ms var(--g-ease) both;
}
@keyframes enh-sheet-in {
  from { opacity: 0; scale: 1.03; filter: blur(8px); }
  to   { opacity: 1; scale: 1;    filter: blur(0); }
}
/* =============================================================
   B · LIQUID GLASS
   ============================================================= */

.enh-glass,
html.enh-on .site-header,
html.enh-on .proj-card,
html.enh-on .learn-card,
html.enh-on .ai-card,
html.enh-on .also-card,
html.enh-on .cred,
html.enh-on .ctf,
html.enh-on .metric,
html.enh-on .form-field input,
html.enh-on .form-field select,
html.enh-on .form-field textarea {
  background: var(--g-tint);
  -webkit-backdrop-filter: blur(var(--g-blur)) saturate(var(--g-sat)) brightness(var(--g-bright));
  backdrop-filter: blur(var(--g-blur)) saturate(var(--g-sat)) brightness(var(--g-bright));
  border: 1px solid var(--g-edge-low);
  box-shadow:
    inset 0 1px 0 var(--g-spec),
    inset 0 -1px 0 var(--g-shade),
    inset 1px 0 0 var(--g-edge-low),
    0 12px 34px -16px var(--g-cast);
}

html.enh-on .proj-card,
html.enh-on .learn-card,
html.enh-on .ai-card,
html.enh-on .also-card,
html.enh-on .cred,
html.enh-on .ctf,
html.enh-on .metric {
  border-radius: var(--g-r);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  transition:
    scale 420ms var(--g-spring),
    translate 420ms var(--g-spring),
    box-shadow 420ms var(--g-ease),
    background 420ms var(--g-ease);
}

/* Specular sheen: a fixed diagonal highlight, as on a curved glass edge */
html.enh-on .proj-card::before,
html.enh-on .learn-card::before,
html.enh-on .ai-card::before,
html.enh-on .also-card::before,
html.enh-on .cred::before,
html.enh-on .ctf::before,
html.enh-on .metric::before,
.enh-glass::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(135deg,
    var(--g-spec) 0%,
    transparent 26%,
    transparent 72%,
    var(--g-edge-low) 100%);
  opacity: .5;
}

/* Pointer-tracked highlight — the glass catches the light where you touch */
html.enh-on .proj-card::after,
html.enh-on .learn-card::after,
html.enh-on .ai-card::after,
html.enh-on .also-card::after,
html.enh-on .cred::after,
html.enh-on .ctf::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 320ms var(--g-ease);
  background: radial-gradient(
    22rem 22rem at var(--px, 50%) var(--py, 50%),
    color-mix(in oklab, var(--accent) 22%, transparent),
    transparent 62%);
}

html.enh-on .proj-card:hover::after,
html.enh-on .learn-card:hover::after,
html.enh-on .ai-card:hover::after,
html.enh-on .also-card:hover::after,
html.enh-on .cred:hover::after,
html.enh-on .ctf:hover::after { opacity: 1; }

/* Lift — uses `scale`/`translate` properties, not `transform`, so it never
   fights the tilt transform main.js writes inline. */
@media (hover: hover) and (pointer: fine) {
  html.enh-on .proj-card:hover,
  html.enh-on .learn-card:hover,
  html.enh-on .ai-card:hover,
  html.enh-on .also-card:hover,
  html.enh-on .cred:hover,
  html.enh-on .ctf:hover {
    scale: 1.014;
    translate: 0 -3px;
    background: var(--g-tint-strong);
    box-shadow:
      inset 0 1px 0 var(--g-spec),
      inset 0 -1px 0 var(--g-shade),
      0 22px 50px -20px var(--g-cast);
  }
}

/* Header becomes a floating glass bar once you scroll off the top */
html.enh-on .site-header {
  border-bottom: 1px solid var(--g-edge-low);
  transition: box-shadow 420ms var(--g-ease), background 420ms var(--g-ease);
}
html.enh-on.enh-scrolled .site-header {
  background: var(--g-tint-strong);
  box-shadow:
    inset 0 1px 0 var(--g-spec),
    0 14px 34px -22px var(--g-cast);
}

/* Pills: nav links, buttons, toggles */
html.enh-on .site-nav a {
  border-radius: 999px;
  padding-inline: .6rem;
  transition: background 300ms var(--g-ease), scale 300ms var(--g-spring), color 220ms ease;
}
html.enh-on .site-nav a:hover {
  background: var(--g-tint-strong);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  scale: 1.05;
}

html.enh-on .btn,
html.enh-on .theme-toggle,
html.enh-on .fx-toggle,
html.enh-on .tool-filter,
html.enh-on .ctf-submit {
  border-radius: 999px;
  -webkit-backdrop-filter: blur(12px) saturate(165%);
  backdrop-filter: blur(12px) saturate(165%);
  box-shadow:
    inset 0 1px 0 var(--g-spec),
    inset 0 -1px 0 var(--g-shade),
    0 8px 22px -14px var(--g-cast);
  transition: scale 280ms var(--g-spring), box-shadow 280ms var(--g-ease), background 280ms var(--g-ease);
}

/* The gel press — squish on touch, like iOS controls */
html.enh-on .btn:active,
html.enh-on .theme-toggle:active,
html.enh-on .fx-toggle:active,
html.enh-on .tool-filter:active,
html.enh-on .ctf-submit:active { scale: .955; }

html.enh-on .btn-ghost:hover,
html.enh-on .tool-filter:hover { background: var(--g-tint-strong); }

/* Tool chips: small glass lozenges */
html.enh-on .tool {
  border-radius: 12px;
  background: var(--g-tint);
  -webkit-backdrop-filter: blur(10px) saturate(150%);
  backdrop-filter: blur(10px) saturate(150%);
  border: 1px solid var(--g-edge-low);
  box-shadow: inset 0 1px 0 var(--g-spec);
  transition: scale 260ms var(--g-spring), background 260ms var(--g-ease);
}
html.enh-on .tool:hover { scale: 1.05; background: var(--g-tint-strong); }

/* Form fields */
html.enh-on .form-field input,
html.enh-on .form-field select,
html.enh-on .form-field textarea { border-radius: 12px; }

/* Optional true refraction: the backdrop is displaced at the rim, the way
   real glass bends what sits behind it. Enabled by JS only where the engine
   actually supports an SVG filter in backdrop-filter. */
html.enh-warp.enh-on .proj-card,
html.enh-warp.enh-on .learn-card,
html.enh-warp.enh-on .ai-card,
html.enh-warp.enh-on .also-card,
html.enh-warp.enh-on .cred,
html.enh-warp.enh-on .ctf,
html.enh-warp.enh-on .site-header {
  -webkit-backdrop-filter: blur(var(--g-blur)) saturate(var(--g-sat)) brightness(var(--g-bright)) url(#enh-refract);
  backdrop-filter: blur(var(--g-blur)) saturate(var(--g-sat)) brightness(var(--g-bright)) url(#enh-refract);
}

/* Touch devices: a live backdrop blur re-renders on every scroll frame and
   mobile GPUs choke on it — that is the stutter. Keep the tint, border and
   shadow language, just drop the blur. Desktop keeps the full glass. */
@media (hover: none), (pointer: coarse) {
  .enh-glass,
  html.enh-on .site-header,
  html.enh-on .proj-card,
  html.enh-on .learn-card,
  html.enh-on .ai-card,
  html.enh-on .also-card,
  html.enh-on .cred,
  html.enh-on .ctf,
  html.enh-on .metric,
  html.enh-on .tool,
  html.enh-on .form-field input,
  html.enh-on .form-field select,
  html.enh-on .form-field textarea,
  html.enh-on .site-nav a:hover {
    /* The enh-warp variant below has higher specificity; the !important
       keeps this deliberate perf override winning on touch devices. */
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
}

.enh-svgdefs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* =============================================================
   C · AMBIENT GRAPHICS
   Sits at z-index -1, behind the matrix canvas (z-index 0) so the
   existing effect stays exactly as it was, just with depth behind it.
   ============================================================= */

.enh-ambient {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.enh-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  will-change: transform;
}
.enh-orb-1 {
  width: 46vmax; height: 46vmax;
  top: -14vmax; left: -10vmax;
  background: var(--amb-1);
  animation: enh-orb-a 30s var(--g-ease) infinite alternate;
}
.enh-orb-2 {
  width: 38vmax; height: 38vmax;
  bottom: -12vmax; right: -8vmax;
  background: var(--amb-2);
  animation: enh-orb-b 38s var(--g-ease) infinite alternate;
}
.enh-orb-3 {
  width: 30vmax; height: 30vmax;
  top: 42%; left: 52%;
  background: var(--amb-3);
  animation: enh-orb-c 34s var(--g-ease) infinite alternate;
}

@keyframes enh-orb-a {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  100% { transform: translate3d(14vw, 10vh, 0) scale(1.22); }
}
@keyframes enh-orb-b {
  0%   { transform: translate3d(0, 0, 0) scale(1.1); }
  100% { transform: translate3d(-16vw, -8vh, 0) scale(.9); }
}
@keyframes enh-orb-c {
  0%   { transform: translate3d(-6vw, 4vh, 0) scale(.95); }
  100% { transform: translate3d(8vw, -10vh, 0) scale(1.25); }
}

/* While the user is scrolling, freeze the ambient drift so the browser
   isn't repainting huge blurred layers every frame. JS toggles the class
   and removes it ~160ms after the last scroll event; the drift resumes
   exactly where it paused. */
html.enh-scrolling .enh-orb { animation-play-state: paused; }

/* Blueprint grid — reads as an architecture drawing under the glass */
.enh-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--amb-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--amb-grid) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 78%);
}

/* Film grain, drawn with an inline SVG data URI (img-src 'self' data: is allowed) */
.enh-grain {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: .12;
  /* No mix-blend-mode: a fixed full-viewport blend layer forces the
     compositor to re-blend the entire screen on every scroll frame,
     which reads as shimmer/jank. Plain alpha grain costs far less. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}
[data-theme="dark"] .enh-grain { opacity: .1; }

/* Cursor spotlight — pointer devices only */
.enh-spot {
  position: fixed;
  z-index: 55;
  width: 26rem; height: 26rem;
  left: 0; top: 0;
  margin: -13rem 0 0 -13rem;
  pointer-events: none;
  opacity: 0;
  border-radius: 50%;
  background: radial-gradient(circle,
    color-mix(in oklab, var(--accent) 12%, transparent) 0%,
    transparent 62%);
  transition: opacity 500ms ease;
  will-change: transform;
}
html.enh-pointer .enh-spot { opacity: .9; }

@media (hover: none), (pointer: coarse) {
  .enh-spot { display: none; }
}

/* =============================================================
   D · GEL-IN REVEALS
   Uses `scale`/`translate`/`filter` only — never `transform` — so the
   existing tilt and magnetic-button code keeps full control of it.
   ============================================================= */

html.enh-on .enh-gel {
  opacity: 0;
  scale: .97;
  translate: 0 18px;
  filter: blur(10px);
}

html.enh-on .enh-gel.enh-in {
  opacity: 1;
  scale: 1;
  translate: 0 0;
  filter: blur(0);
  transition:
    opacity 760ms var(--g-ease),
    scale 900ms var(--g-spring),
    translate 900ms var(--g-spring),
    filter 700ms var(--g-ease);
}

/* Section headings get a light sweep as they arrive */
html.enh-on .enh-sweep {
  background-image: linear-gradient(105deg,
    transparent 38%,
    color-mix(in oklab, var(--accent) 34%, transparent) 50%,
    transparent 62%);
  background-size: 260% 100%;
  background-position: 190% 0;
  -webkit-background-clip: text;
  background-clip: text;
}
html.enh-on .enh-sweep.enh-in {
  animation: enh-sweep 1500ms var(--g-ease) 180ms 1;
}
@keyframes enh-sweep {
  from { background-position: 190% 0; }
  to   { background-position: -90% 0; }
}

/* Depth: panels drift a few pixels against the scroll */
html.enh-on .enh-parallax { will-change: translate; }

/* =============================================================
   E · REDUCED MOTION, PRINT, NARROW SCREENS
   ============================================================= */

@media (prefers-reduced-motion: reduce) {
  .enh-stage,
  .enh-controls { animation: none; }
  .enh-book::before,
  .enh-orb-1, .enh-orb-2, .enh-orb-3 { animation: none; }
  .enh-stamp { animation: none; opacity: .94; }
  html.enh-reveal body > *:not(.enh-book):not(.enh-unfold):not(#veil):not(.enh-ambient):not(.enh-grain):not(.enh-spot):not(.enh-svgdefs):not(.matrix-canvas):not(.scroll-progress):not(.skip-link):not(.palette-backdrop):not(.palette-flash) { animation: none; }
  html.enh-on .enh-gel { opacity: 1; scale: 1; translate: 0; filter: none; }
  html.enh-on .enh-gel.enh-in { transition: none; }
  html.enh-on .enh-sweep.enh-in { animation: none; }
  .enh-spot { display: none; }
  .enh-grain { opacity: .12; }
}

@media print {
  .enh-book, .enh-ambient, .enh-grain, .enh-spot, .enh-svgdefs { display: none !important; }
  html.enh-on .proj-card,
  html.enh-on .learn-card,
  html.enh-on .ai-card,
  html.enh-on .also-card,
  html.enh-on .cred,
  html.enh-on .ctf,
  html.enh-on .metric,
  html.enh-on .site-header {
    background: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
  }
}

/* Backdrop-filter is the whole effect; without it, fall back to a solid
   surface so nothing turns into unreadable transparent text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  html.enh-on .proj-card,
  html.enh-on .learn-card,
  html.enh-on .ai-card,
  html.enh-on .also-card,
  html.enh-on .cred,
  html.enh-on .ctf,
  html.enh-on .metric,
  html.enh-on .site-header { background: var(--surface); }
}

@media (max-width: 560px) {
  .enh-stamp { width: 84px; height: 84px; top: 31%; }
  .enh-stamp b { font-size: .78rem; }
  :root { --g-blur: 14px; }
  .enh-orb { filter: blur(52px); }
}

@media (max-height: 620px) {
  .enh-stage { max-height: 58vh; }
}
