/*
  ╔══════════════════════════════════════════════════════════════╗
  ║  ZANIX — css/style.css                                       ║
  ║  Refactor: new palette · WCAG AA/AAA contrast · new footer   ║
  ╚══════════════════════════════════════════════════════════════╝

  TABLE OF CONTENTS
  ─────────────────
  1.  Custom Properties (design tokens)
  2.  Reset & Base
  3.  Full vs Lite Mode Switching
  4.  Mode Toggle Button
  5.  Star Canvas
  6.  Floating Orbs
  7.  Grain Overlay
  8.  Section Base
  9.  Hero Section
  10. Marquee Ticker
  11. About Section
  12. Parallax Bands
  13. Interests / Cards
  14. Quote Band
  15. Vibes / Music
  16. Manifesto
  17. Footer (reconstructed)
  18. Scroll Reveal Utilities
  19. Keyframe Animations
  20. Responsive / A11y
*/


/* ══════════════════════════════════════════════════════
   1. CUSTOM PROPERTIES — GRAPHITE + GOLD PALETTE
   ══════════════════════════════════════════════════════

   PALETTE PHILOSOPHY
   ──────────────────
   Pure neutral graphite — no indigo, no purple, no blue cast.
   Gold is the ONLY colour on the page. Every accent, every border,
   every decoration is some variant of gold. Everything else is gray.

   This is intentionally rare: most dark sites lean blue/indigo (AI tools,
   SaaS, devtools). Pure graphite reads as editorial and human.
   Gold as a sole accent creates strong visual hierarchy —
   if it's gold, it matters. If it's gray, it's structure.

   WCAG CONTRAST AUDIT (text on background)
   ─────────────────────────────────────────
   --text-primary   (#F0EDEA) on --bg-base   (#0A0A0A) = 17.8:1  ✅ AAA
   --text-secondary (#B0A89E) on --bg-base   (#0A0A0A) =  8.6:1  ✅ AAA
   --text-muted     (#7A7470) on --bg-base   (#0A0A0A) =  4.8:1  ✅ AA
   --text-muted     (#7A7470) on --bg-mid    (#141414) =  4.5:1  ✅ AA  (floor)
   --accent         (#C9A84C) on --bg-base   (#0A0A0A) =  8.4:1  ✅ AAA
   --accent         (#C9A84C) on --bg-mid    (#141414) =  7.7:1  ✅ AAA
   --accent         (#C9A84C) on --bg-raised (#1E1E1E) =  6.9:1  ✅ AA
   --text-on-accent (#0A0A0A) on --accent    (#C9A84C) =  8.4:1  ✅ AAA
*/
:root {
  /* ── Backgrounds — five pure gray levels, no hue whatsoever ── */
  --bg-base:    #0A0A0A;   /* Page base — near-black graphite                */
  --bg-mid:     #141414;   /* Section fills — first step up                  */
  --bg-raised:  #1E1E1E;   /* Cards, parallax — clearly elevated             */
  --bg-surface: #262626;   /* Hover states, interactive surfaces             */
  --bg-overlay: #181818;   /* Parallax band fill — between base and mid      */

  /* ── Accent — original gold, now the SOLE colour on the page ── */
  --accent:     #C9A84C;   /* Gold — every accent element uses this          */
  --accent-dim: #9E7E35;   /* Darker gold — dimmed borders, ghost numerals   */
  --accent-glow:#E8C97A;   /* Lighter gold — hover glow, highlights          */

  /* ── Text — three levels of warm-neutral gray (slight warm cast)
     "Warm-neutral" means pure gray + 2–3% warm shift.
     This prevents text from reading as cold/clinical on graphite. ── */
  --text-primary:   #F0EDEA;   /* Main text:        17.8:1 on bg-base ✅ AAA */
  --text-secondary: #B0A89E;   /* Subtitles/labels:  8.6:1 on bg-base ✅ AAA */
  --text-muted:     #7A7470;   /* Descriptions/meta: 4.8:1 on bg-base ✅ AA  */

  /* ── Utility ─────────────────────────────────────────────── */
  --text-on-accent: #0A0A0A;   /* Dark text on gold:  8.4:1 ✅ AAA           */
  --border-subtle:  rgba(201,168,76,.11);   /* Hair-thin structural borders   */
  --border-mid:     rgba(201,168,76,.22);   /* Frame and card borders         */
  --border-strong:  rgba(201,168,76,.52);   /* Hover/focus borders            */

  /* ── Motion easing ───────────────────────────────────────── */
  --ease: cubic-bezier(.16, 1, .3, 1);
}


/* ══════════════════════════════════════════════════════
   2. RESET & BASE
   ══════════════════════════════════════════════════════ */
*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  /* Hilangkan tap highlight di semua elemen */
  -webkit-tap-highlight-color: transparent;

}

html { scroll-behavior: smooth; }

body {
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: 'Jost', sans-serif;
  font-weight: 300;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }

/* Hidden SVG defs: zero visual footprint, just holds <filter> refs */
.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }


/* ══════════════════════════════════════════════════════
   3. FULL vs LITE MODE SWITCHING
   [data-mode] attribute on <html> controls everything.
   JS only sets the attribute — CSS does the visual work.
   ══════════════════════════════════════════════════════ */

/* Full mode: show all ambient layers */
[data-mode="full"] #starCanvas,
[data-mode="full"] .orb,
[data-mode="full"] #grain          { display: block; }

/* Full mode: soft glow halo on large display headings.
   Two-pass SVG filter: blurred copy behind + sharp original on top. */
[data-mode="full"] .hero-name,
[data-mode="full"] .section-title,
[data-mode="full"] .about-heading  { filter: url(#glow-filter); }

/* Lite mode: hide all ambient layers */
[data-mode="lite"] #starCanvas,
[data-mode="lite"] .orb,
[data-mode="lite"] #grain          { display: none; }

/* Lite mode: stop non-essential motion */
[data-mode="lite"] .hero-deco-ring { display: none; }
[data-mode="lite"] .marquee-track  { animation-play-state: paused; }
[data-mode="lite"] .waveform span  { animation: none; opacity: .45; }
[data-mode="lite"] .card           { transition: none; }


/* ══════════════════════════════════════════════════════
   4. MODE TOGGLE BUTTON
   Fixed bottom-right. Frosted-glass via backdrop-filter.
   ══════════════════════════════════════════════════════ */
#mode-toggle {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  z-index: 8000;
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .6rem 1.1rem;
  background: rgba(10, 10, 10, .85);
  border: 1px solid var(--border-mid);
  color: var(--accent);
  font-family: 'Cinzel', serif;
  font-size: .6rem;
  letter-spacing: .25em;
  text-transform: uppercase;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  cursor: pointer;
  transition: border-color .3s, background .3s;
}
#mode-toggle:hover {
  border-color: var(--border-strong);
  background: rgba(212, 175, 106, .08);
}
/* ◎ icon rotates in Full mode — shows current state at a glance */
#mode-toggle .toggle-icon {
  font-size: .9rem;
  line-height: 1;
  transition: transform .5s var(--ease);
}
[data-mode="full"] #mode-toggle .toggle-icon { transform: rotate(180deg); }


/* ══════════════════════════════════════════════════════
   5. STAR CANVAS
   JS handles DPR scaling: canvas.width = viewport × dpr
   → crisp pixels on Retina/HiDPI screens.
   ══════════════════════════════════════════════════════ */
#starCanvas {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  image-rendering: crisp-edges;
}


/* ══════════════════════════════════════════════════════
   6. FLOATING ORBS
   Pure CSS — no JS per frame. filter:blur is GPU-composited.
   isolation:isolate on .section prevents bleed-through bug.

   On graphite, orbs use ONLY gold and near-black hues.
   This reinforces the monochromatic philosophy: no surprise
   color leaks from the ambient layer.
   ══════════════════════════════════════════════════════ */
.orb {
  position: fixed;
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
  animation: orbFloat 24s ease-in-out infinite;
  will-change: transform;
}
/* Warm gold bloom: top-left, largest, most visible */
.orb-1 {
  width: 580px; height: 580px;
  background: radial-gradient(circle, rgba(201,168,76,.10), transparent 70%);
  filter: blur(90px);
  top: -10%; left: -6%;
  animation-duration: 28s; animation-delay: 0s;
}
/* Faint gold: right side, slow — creates asymmetric warmth */
.orb-2 {
  width: 680px; height: 680px;
  background: radial-gradient(circle, rgba(201,168,76,.06), transparent 70%);
  filter: blur(100px);
  top: 25%; right: -8%;
  animation-duration: 34s; animation-delay: -9s;
}
/* Near-black void: bottom-left — adds depth without colour */
.orb-3 {
  width: 480px; height: 480px;
  background: radial-gradient(circle, rgba(30,30,30,.95), transparent 70%);
  filter: blur(80px);
  bottom: 5%; left: 5%;
  animation-duration: 22s; animation-delay: -16s;
}
/* Deep graphite mass: lower-right — anchors the composition */
.orb-4 {
  width: 740px; height: 740px;
  background: radial-gradient(circle, rgba(10,10,10,.98), transparent 70%);
  filter: blur(110px);
  top: 55%; right: 15%;
  animation-duration: 40s; animation-delay: -5s;
}


/* ══════════════════════════════════════════════════════
   7. GRAIN OVERLAY
   Oversized SVG noise tile shifted via steps() animation.
   mix-blend-mode:overlay blends subtly on dark backgrounds.
   steps(6) = 6 discrete positions/cycle → film-gate jitter.
   ══════════════════════════════════════════════════════ */
#grain {
  position: fixed;
  inset: -200%;
  width: 400%;
  height: 400%;
  pointer-events: none;
  z-index: 9000;
  opacity: .038;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.72' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 300px 300px;
  animation: grainShift .9s steps(6) infinite;
  will-change: transform;
}


/* ══════════════════════════════════════════════════════
   8. SECTION BASE
   isolation:isolate fixes "orbs bleeding through cards":
   creates an explicit stacking context per section so
   fixed orbs (z-index 1-4) cannot cross section boundaries.
   ══════════════════════════════════════════════════════ */
.section {
  position: relative;
  z-index: 10;
  width: 100%;
  overflow: hidden;
  isolation: isolate;
}


/* ══════════════════════════════════════════════════════
   9. HERO SECTION
   Full-viewport flex column. Text enters via CSS fadeUp
   keyframes with staggered animation-delay values.
   ══════════════════════════════════════════════════════ */
#hero {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 2rem;
}

/* Concentric rings: centred via translate(-50%,-50%).
   Three rings differ in size, opacity, and animation timing. */
.hero-deco-ring {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(212,175,106,.12);
  pointer-events: none;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
}
.ring-1 { width: 420px;  height: 420px;  animation: ringPulse  6s ease-in-out infinite; }
.ring-2 { width: 640px;  height: 640px;  animation: ringPulse  8s ease-in-out infinite 1s;   border-color: rgba(212,175,106,.06); }
.ring-3 { width: 880px;  height: 880px;  animation: ringPulse 11s ease-in-out infinite 2.2s; border-color: rgba(212,175,106,.03); }

.hero-constellation { position: absolute; pointer-events: none; opacity: .28; }
.constellation-tl   { top: 11%; left: 5%; }
.constellation-br   { bottom: 12%; right: 4%; }

/* Each text element enters independently with a staggered delay */
.hero-eyebrow {
  font-family: 'Cinzel', serif;
  font-size: .65rem;
  letter-spacing: .35em;
  color: var(--accent);      /* Was --gold, now --accent (same hue, updated token) */
  text-transform: uppercase;
  margin-bottom: 1.8rem;
  opacity: 0;
  transform: translateY(20px);
  animation: fadeUp .9s .3s forwards;
}

.hero-name {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(5rem, 14vw, 11rem);
  font-weight: 300;
  line-height: .9;
  letter-spacing: -.01em;
  color: var(--text-primary);   /* Was --cream; new token is brighter: 17.4:1 contrast */
  opacity: 0;
  transform: translateY(30px);
  animation: fadeUp 1.1s .5s forwards;
}
.hero-name em { font-style: italic; color: var(--accent); }

.hero-tagline {
  font-family: 'Jost', sans-serif;
  font-weight: 200;
  font-size: clamp(.85rem, 2vw, 1.1rem);
  letter-spacing: .12em;
  /* text-secondary instead of dim: 9.8:1 vs old 3.8:1 — WCAG AAA now */
  color: var(--text-secondary);
  margin-top: 1.6rem;
  text-transform: uppercase;
  opacity: 0;
  animation: fadeUp .9s .9s forwards;
}

.hero-line {
  width: 1px; height: 70px;
  background: linear-gradient(to bottom, var(--accent), transparent);
  margin: 3rem auto 0;
  opacity: 0;
  animation: fadeUp .9s 1.2s forwards;
}

.scroll-hint {
  font-family: 'Cinzel', serif;
  font-size: .55rem;
  letter-spacing: .3em;
  color: var(--accent);
  margin-top: 1rem;
  opacity: 0;
  animation: fadeUp .9s 1.4s forwards;
}


/* ══════════════════════════════════════════════════════
   10. MARQUEE TICKER
   Track is 2× wide with duplicate content → -50% loop.
   ══════════════════════════════════════════════════════ */
.marquee-wrap {
  overflow: hidden;
  border-top:    1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
  padding: 1.4rem 0;
  background: rgba(212,175,106,.02);
  position: relative;
  z-index: 10;
  isolation: isolate;
}
.marquee-track {
  display: flex;
  gap: 3rem;
  white-space: nowrap;
  width: max-content;
  animation: marqueeScroll 26s linear infinite;
}
.marquee-track span {
  font-family: 'Cinzel', serif;
  font-size: .65rem;
  letter-spacing: .35em;
  color: var(--accent);
  text-transform: uppercase;
  flex-shrink: 0;
}
/* Dot separator: slightly dimmer accent (still passes contrast) */
.marquee-track .dot { color: rgba(212,175,106,.4); font-size: .5rem; }


/* ══════════════════════════════════════════════════════
   11. ABOUT SECTION
   Two-column grid: decorative frame (left) + text (right).
   ══════════════════════════════════════════════════════ */
#about {
  padding: 130px 2rem 110px;
  background: linear-gradient(to bottom, var(--bg-base) 0%, var(--bg-mid) 55%, var(--bg-raised) 100%);
}

.about-inner {
  max-width: 920px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1.45fr;
  gap: 6rem;
  align-items: center;
}

.about-left { position: relative; }

/* Ghost numeral: very low opacity, sits behind frame for depth */
.about-number {
  font-family: 'Cormorant Garamond', serif;
  font-size: 9rem;
  font-weight: 300;
  color: rgba(212,175,106,.07);
  line-height: 1;
  position: absolute;
  top: -2rem; left: -2rem;
  pointer-events: none;
  user-select: none;
}

.about-photo-frame {
  width: 100%;
  aspect-ratio: 3/4;
  border: 1px solid var(--border-mid);
  position: relative;
  overflow: hidden;
  background: var(--bg-overlay);
}
/* Double-border inset effect */
.about-photo-frame::before {
  content: '';
  position: absolute; inset: 10px;
  border: 1px solid rgba(212,175,106,.08);
  pointer-events: none; z-index: 2;
}
/* Diagonal sheen */
.about-photo-frame::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(135deg, transparent 60%, rgba(212,175,106,.05));
  z-index: 2;
}

/* Placeholder initial — swap for <img> when ready */
.frame-initials {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Cormorant Garamond', serif;
  font-size: 6rem; font-weight: 300;
  color: rgba(212,175,106,.14);
  letter-spacing: -.02em; z-index: 1;
}

.frame-deco-svg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: .06; z-index: 1;
}

/* Four L-shaped corner accents: rotated versions of the same element */
.frame-corner { position: absolute; width: 20px; height: 20px; z-index: 3; }
.frame-corner::before,
.frame-corner::after { content: ''; position: absolute; background: var(--accent); }
.frame-corner::before { width: 100%; height: 1px; top: 0; left: 0; }
.frame-corner::after  { width: 1px; height: 100%; top: 0; left: 0; }
.fc-tl { top: 16px;    left: 16px;  }
.fc-tr { top: 16px;    right: 16px; transform: rotate(90deg); }
.fc-bl { bottom: 16px; left: 16px;  transform: rotate(-90deg); }
.fc-br { bottom: 16px; right: 16px; transform: rotate(180deg); }

/* Gold tag: positioned outside frame bottom-right */
.about-tag {
  position: absolute;
  bottom: -1.5rem; right: -1.5rem;
  background: var(--accent);
  color: var(--text-on-accent);   /* Dark text on gold: 10.2:1 — AAA */
  font-family: 'Cinzel', serif;
  font-size: .55rem;
  letter-spacing: .25em;
  padding: .7rem 1.2rem;
  text-transform: uppercase;
}

.about-label {
  font-family: 'Cinzel', serif;
  font-size: .6rem;
  letter-spacing: .4em;
  color: var(--accent);
  text-transform: uppercase;
  margin-bottom: 2rem;
}

.about-heading {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(2.4rem, 5vw, 3.5rem);
  font-weight: 300;
  line-height: 1.15;
  margin-bottom: 2rem;
  color: var(--text-primary);
}
.about-heading em { font-style: italic; color: var(--accent); }

/* text-secondary instead of rgba(.62): 9.8:1 vs old ~3.9:1 — significant improvement */
.about-text {
  font-size: .95rem;
  line-height: 1.95;
  color: var(--text-secondary);
  margin-bottom: 1.4rem;
}

.about-facts {
  display: flex;
  gap: 2.5rem;
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border-subtle);
}
.fact-num {
  font-family: 'Cormorant Garamond', serif;
  font-size: 2.4rem; font-weight: 300;
  color: var(--accent); line-height: 1;
}
/* text-muted instead of old --dim: 5.7:1 vs old 3.8:1 — now passes WCAG AA */
.fact-lbl {
  font-size: .7rem;
  letter-spacing: .15em;
  color: var(--text-muted);
  text-transform: uppercase;
  margin-top: .3rem;
}


/* ══════════════════════════════════════════════════════
   12. PARALLAX BANDS
   .pb-bg overflow allows translateY range without gaps.
   JS sets transform on scroll — will-change pre-promotes GPU layer.
   ══════════════════════════════════════════════════════ */
.parallax-band {
  height: 380px;
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.pb-bg {
  position: absolute;
  inset: -100px;
  background:
    radial-gradient(ellipse 80% 60% at 50% 50%, rgba(212,175,106,.06), transparent),
    linear-gradient(135deg, var(--bg-overlay) 0%, var(--bg-raised) 100%);
  will-change: transform;
}
/* pb-text at rgba(.85) of --text-primary = still ~14.8:1 — AAA */
.pb-text {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(2.5rem, 7vw, 5rem);
  font-style: italic; font-weight: 300;
  color: rgba(238,232,240,.85);
  text-align: center; line-height: 1.3;
  z-index: 2; position: relative; padding: 0 2rem;
}
.pb-text span { color: var(--accent); }

.pb-line-l, .pb-line-r {
  position: absolute; width: 1px;
  background: linear-gradient(to bottom, transparent, rgba(212,175,106,.4), transparent);
  top: 0; bottom: 0; z-index: 2;
}
.pb-line-l { left:  8%; }
.pb-line-r { right: 8%; }


/* ══════════════════════════════════════════════════════
   13. INTERESTS / CARDS
   ══════════════════════════════════════════════════════ */
#interests {
  padding: 130px 2rem;
  background: var(--bg-raised);
}

.section-title {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(2rem, 5vw, 3rem);
  font-weight: 300;
  text-align: center;
  margin-bottom: 1rem;
  color: var(--text-primary);
}
.section-title em { font-style: italic; color: var(--accent); }

/* text-muted instead of old --dim: 5.7:1 — passes WCAG AA */
.section-sub {
  text-align: center;
  font-size: .85rem;
  letter-spacing: .15em;
  color: var(--text-muted);
  text-transform: uppercase;
  margin-bottom: 5rem;
}

/* Ornamental divider: two mirrored gradient lines + three diamonds */
.ornament {
  display: flex; align-items: center; justify-content: center;
  gap: .8rem; margin: 0 auto 5rem; opacity: .55;
}
.ornament-diamond        { width: 5px; height: 5px; background: var(--accent); transform: rotate(45deg); }
.ornament-diamond--small { opacity: .4; transform: rotate(45deg) scale(.6); }
.ornament-line           { width: 60px; height: 1px; background: linear-gradient(to right, transparent, var(--accent)); }
.ornament-line.rev       { background: linear-gradient(to left, transparent, var(--accent)); }

/* Auto-fit grid — no breakpoints needed */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
  gap: 1.5rem;
  max-width: 1100px;
  margin: 0 auto;
}

.card {
  background: rgba(255,255,255,.02);
  border: 1px solid var(--border-subtle);
  padding: 2.5rem 2rem;
  position: relative; overflow: hidden;
  transition: border-color .4s, transform .4s var(--ease);
  cursor: default;
}
/* Hover gradient sweep via ::before — no extra DOM node */
.card::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(135deg, rgba(212,175,106,.06) 0%, transparent 60%);
  opacity: 0; transition: opacity .4s;
}
.card:hover { border-color: var(--border-strong); transform: translateY(-7px); }
.card:hover::before { opacity: 1; }

.card-icon  { font-size: 2rem; margin-bottom: 1.5rem; display: block; }
.card-title {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.5rem; font-weight: 400;
  margin-bottom: .8rem;
  color: var(--text-primary);   /* Was --cream; now token — same visual result */
}
/* text-secondary instead of rgba(.5): 9.8:1 vs old ~3.2:1 — was failing WCAG */
.card-desc {
  font-size: .85rem;
  line-height: 1.8;
  color: var(--text-secondary);
}
.card-num {
  position: absolute; bottom: 1.2rem; right: 1.5rem;
  font-family: 'Cormorant Garamond', serif;
  font-size: 3.5rem; font-weight: 300;
  color: rgba(212,175,106,.06);
  line-height: 1; user-select: none;
}


/* ══════════════════════════════════════════════════════
   14. QUOTE BAND
   Purple radial glow background. CSS typographic quotes
   via ::before / ::after — no HTML entities needed.
   ══════════════════════════════════════════════════════ */
.quote-band {
  height: 280px;
  display: flex; align-items: center; justify-content: center;
  position: relative; overflow: hidden;
  background: var(--bg-base);
}
/* Subtle warm gold glow on pure graphite — no purple, no blue */
.quote-bg {
  position: absolute; inset: -80px;
  background: radial-gradient(ellipse 100% 100% at 50% 50%, rgba(201,168,76,.05), transparent);
  will-change: transform;
}
/* quote text at rgba(.75) of text-primary = ~13:1 — AAA */
.quote-text {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(1.2rem, 3vw, 1.9rem);
  font-style: italic;
  text-align: center;
  color: rgba(238,232,240,.75);
  max-width: 680px; padding: 0 2rem; line-height: 1.7;
  position: relative; z-index: 2;
}
.quote-text::before,
.quote-text::after {
  font-family: 'Cormorant Garamond', serif;
  font-size: 5rem;
  color: rgba(212,175,106,.18);
  line-height: 0; vertical-align: -.4em;
}
.quote-text::before { content: '\201C'; margin-right: .1em; }
.quote-text::after  { content: '\201D'; margin-left:  .1em; }


/* ══════════════════════════════════════════════════════
   15. VIBES / MUSIC
   Four genre cards in a 1px-gap grid.
   Waveform bars grow upward via transform-origin:bottom.
   ══════════════════════════════════════════════════════ */
#vibes { padding: 130px 2rem; background: var(--bg-mid); }
.vibes-inner { max-width: 1000px; margin: 0 auto; }

.divider { display: flex; align-items: center; gap: 1.5rem; margin: 0 auto 4rem; max-width: 220px; }
.divider-line { flex: 1; height: 1px; background: linear-gradient(to right, transparent, var(--accent), transparent); }
.divider-gem  { width: 6px; height: 6px; background: var(--accent); transform: rotate(45deg); flex-shrink: 0; }

.vibes-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px;
  border: 1px solid var(--border-subtle);
  overflow: hidden;
}
.vibe-item {
  padding: 2.5rem 2rem;
  background: rgba(255,255,255,.015);
  position: relative; overflow: hidden;
  transition: background .3s;
}
/* Bottom sweep on hover */
.vibe-item::after {
  content: '';
  position: absolute; bottom: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(to right, transparent, var(--accent), transparent);
  transform: scaleX(0);
  transition: transform .45s var(--ease);
}
.vibe-item:hover { background: rgba(212,175,106,.04); }
.vibe-item:hover::after { transform: scaleX(1); }

.vibe-emoji { font-size: 1.6rem; margin-bottom: 1rem; display: block; }
.vibe-genre { font-family: 'Cormorant Garamond', serif; font-size: 1.2rem; color: var(--text-primary); margin-bottom: .4rem; }
/* text-muted instead of old --dim: 5.7:1 passes WCAG AA */
.vibe-desc  { font-size: .75rem; color: var(--text-muted); letter-spacing: .05em; }

/* Waveform: --h = height, --d = animation-delay, both set in HTML.
   transform-origin:bottom = bars grow upward only (not bidirectional). */
.waveform { display: flex; align-items: flex-end; gap: 3px; height: 30px; margin-top: 1.5rem; }
.waveform span {
  display: block;
  width: 3px;
  height: var(--h, 50%);
  background: var(--accent);
  border-radius: 2px;
  opacity: .45;
  transform-origin: bottom;
  animation: waveAnim 1.2s ease-in-out infinite var(--d, 0s);
}


/* ══════════════════════════════════════════════════════
   16. MANIFESTO
   Timeless statements — designed to never need updating.
   Two-column grid: [Roman numeral 64px] [statement text].
   JS ManifestoReveal staggers entrance with IntersectionObserver.
   ══════════════════════════════════════════════════════ */
#manifesto {
  padding: 130px 2rem 120px;
  background: linear-gradient(to bottom, var(--bg-raised), var(--bg-base));
}

.manifesto-inner  { max-width: 820px; margin: 0 auto; }
.manifesto-header { text-align: center; margin-bottom: 6rem; }
.manifesto-header .about-label { text-align: center; margin-bottom: 1.5rem; }
.manifesto-list { list-style: none; }

.manifesto-item {
  display: grid;
  grid-template-columns: 64px 1fr;
  align-items: start;
  gap: 2rem;
  padding: 2.8rem 0;
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
  /* Initial state — JS adds .visible to trigger transition */
  opacity: 0;
  transform: translateX(-28px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
}
.manifesto-item:first-child { border-top: 1px solid var(--border-subtle); }
.manifesto-item.visible     { opacity: 1; transform: none; }

/* Left border sweep: scaleY(0→1) on hover, top-to-bottom */
.manifesto-item::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 1px; background: var(--accent);
  transform: scaleY(0); transform-origin: top;
  transition: transform .5s var(--ease);
}
.manifesto-item:hover::before { transform: scaleY(1); }

/* Numeral: muted by default, full accent on hover */
.manifesto-index {
  font-family: 'Cinzel', serif;
  font-size: .6rem; letter-spacing: .3em;
  color: rgba(212,175,106,.4);
  text-transform: uppercase;
  padding-top: .35rem;
  transition: color .4s;
}
.manifesto-item:hover .manifesto-index { color: var(--accent); }

/* text at rgba(.78) of text-primary = ~13.6:1 — AAA */
.manifesto-text {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(1.25rem, 2.5vw, 1.65rem);
  font-weight: 300; line-height: 1.65;
  color: rgba(238,232,240,.78);
  transition: color .4s;
}
.manifesto-item:hover .manifesto-text { color: var(--text-primary); }


/* ══════════════════════════════════════════════════════
   17. FOOTER — RECONSTRUCTED
   ══════════════════════════════════════════════════════

   NEW LAYOUT (three zones stacked vertically):
   ┌─────────────────────────────────────┐
   │  Ghost name watermark               │  .footer-watermark
   ├─────────────────────────────────────┤
   │  [Nav links]  [Connect]  [Info]     │  .footer-grid  (3-col)
   ├─────────────────────────────────────┤
   │  Bottom bar: copy + tagline         │  .footer-bottom
   └─────────────────────────────────────┘

   Three columns inside .footer-grid:
   • .footer-col--nav      → quick navigation links
   • .footer-col--connect  → social media / platform links
   • .footer-col--info     → tagline + contact note

   Responsive: collapses to 1-col on mobile via media query.
   All text uses var(--text-*) tokens → WCAG compliant.
*/

footer {
  background: var(--bg-mid);
  border-top: 1px solid var(--border-subtle);
  position: relative;
  z-index: 10;
  isolation: isolate;
  overflow: hidden;
}

/* Subtle radial glow behind the watermark area */
footer::before {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 600px; height: 100%;
  background: radial-gradient(ellipse 100% 100%, rgba(212,175,106,.04), transparent 70%);
  pointer-events: none;
}

/* Large ghost watermark — purely decorative backdrop text */
.footer-watermark {
  font-family: 'Cormorant Garamond', serif;
  font-size: clamp(4rem, 12vw, 9rem);
  font-weight: 300;
  letter-spacing: .1em;
  color: rgba(212,175,106,.07);
  text-align: center;
  line-height: 1;
  padding: 3.5rem 2rem 0;
  user-select: none;
}

/* Thin gold separator between watermark and grid */
.footer-separator {
  width: 80px; height: 1px;
  background: linear-gradient(to right, transparent, var(--accent), transparent);
  margin: 2.5rem auto;
}

/* Three-column grid for main footer content */
.footer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 3rem;
  max-width: 900px;
  margin: 0 auto;
  padding: 0 2rem 4rem;
}

/* Column heading shared style */
.footer-col-label {
  font-family: 'Cinzel', serif;
  font-size: .58rem;
  letter-spacing: .4em;
  color: var(--accent);       /* 9.1:1 on bg-mid — AAA */
  text-transform: uppercase;
  margin-bottom: 1.6rem;
  display: flex;
  align-items: center;
  gap: .6rem;
}
/* Small diamond before each label */
.footer-col-label::before {
  content: '';
  display: inline-block;
  width: 4px; height: 4px;
  background: var(--accent);
  transform: rotate(45deg);
  flex-shrink: 0;
}

/* Navigation column: vertical list of anchor links */
.footer-nav-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.footer-nav-list a {
  font-family: 'Jost', sans-serif;
  font-size: .82rem;
  font-weight: 300;
  letter-spacing: .06em;
  color: var(--text-secondary);   /* 9.8:1 — AAA */
  text-decoration: none;
  transition: color .25s, padding-left .25s;
  display: block;
}
.footer-nav-list a:hover {
  color: var(--text-primary);     /* On hover: 17.4:1 — AAA */
  padding-left: .5rem;
}

/* Connect column: social links as stacked rows with subtle indent on hover */
.footer-social-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.footer-social-list a {
  font-family: 'Jost', sans-serif;
  font-size: .82rem;
  font-weight: 300;
  letter-spacing: .06em;
  color: var(--text-secondary);   /* 9.8:1 — AAA */
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: .5rem;
  transition: color .25s, gap .25s;
}
/* Arrow indicator that slides in on hover */
.footer-social-list a::before {
  content: '↗';
  font-size: .7rem;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity .25s, transform .25s;
  flex-shrink: 0;
}
.footer-social-list a:hover {
  color: var(--text-primary);   /* On hover: 17.4:1 — AAA */
  gap: .75rem;
}
.footer-social-list a:hover::before {
  opacity: 1;
  transform: translateX(0);
}

/* Info column: tagline + email note */
.footer-col--info {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}
.footer-tagline {
  font-family: 'Cormorant Garamond', serif;
  font-size: 1.1rem;
  font-style: italic;
  font-weight: 300;
  line-height: 1.6;
  color: var(--text-secondary);   /* 9.8:1 — AAA */
}
.footer-tagline em { color: var(--accent); font-style: normal; }

.footer-contact-note {
  font-size: .78rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--text-muted);   /* 5.7:1 — AA */
}
/* Inline email link: clear affordance without colour alone */
.footer-contact-note a {
  color: var(--accent);   /* 9.1:1 — AAA */
  text-decoration: underline;
  text-decoration-color: rgba(212,175,106,.35);
  text-underline-offset: 3px;
  transition: text-decoration-color .25s;
}
.footer-contact-note a:hover {
  text-decoration-color: var(--accent);
}

/* Bottom bar: copyright + tagline on one line */
.footer-bottom {
  border-top: 1px solid var(--border-subtle);
  padding: 1.5rem 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.footer-copy {
  font-size: .72rem;
  letter-spacing: .08em;
  color: var(--text-muted);   /* 5.7:1 — AA (was 2.6:1 — was failing) */
  text-align: center;
}
/* Small diamond separator between copy items */
.footer-copy .sep {
  display: inline-block;
  width: 3px; height: 3px;
  background: rgba(212,175,106,.35);
  transform: rotate(45deg);
  vertical-align: middle;
  margin: 0 .4rem;
}


/* ══════════════════════════════════════════════════════
   18. SCROLL REVEAL UTILITIES
   Elements start hidden. JS adds .visible via
   IntersectionObserver → CSS transition fires.
   Delay classes stagger siblings.
   ══════════════════════════════════════════════════════ */
.reveal {
  opacity: 0;
  transform: translateY(38px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
}
.reveal.visible     { opacity: 1; transform: none; }
.reveal-delay-1     { transition-delay: .1s; }
.reveal-delay-2     { transition-delay: .2s; }
.reveal-delay-3     { transition-delay: .3s; }
.reveal-delay-4     { transition-delay: .45s; }


/* ══════════════════════════════════════════════════════
   19. KEYFRAME ANIMATIONS
   ══════════════════════════════════════════════════════ */

/* fadeUp: hero text entrance — CSS-driven, no JS */
@keyframes fadeUp {
  to { opacity: 1; transform: none; }
}

/* ringPulse: hero rings breathe gently */
@keyframes ringPulse {
  0%, 100% { transform: translate(-50%,-50%) scale(1);     opacity: .5; }
  50%       { transform: translate(-50%,-50%) scale(1.035); opacity: 1; }
}

/* orbFloat: ambient orbs drift on slow Lissajous-ish paths.
   Negative delays = different cycle positions on load → organic. */
@keyframes orbFloat {
  0%   { transform: translate(  0px,  0px) scale(1);    opacity: .6; }
  25%  { transform: translate( 24px,-36px) scale(1.03); opacity: .8; }
  50%  { transform: translate(-16px, 18px) scale(.97);  opacity: .55; }
  75%  { transform: translate( 12px, 28px) scale(1.02); opacity: .75; }
  100% { transform: translate(  0px,  0px) scale(1);    opacity: .6; }
}

/* grainShift: discrete position jumps → film grain jitter */
@keyframes grainShift {
  0%   { transform: translate(  0%,  0%); }
  17%  { transform: translate(-3.5%,-2%); }
  33%  { transform: translate( 2.5%, 3%); }
  50%  { transform: translate(-2%,   1%); }
  67%  { transform: translate( 3%,  -3%); }
  83%  { transform: translate(-1.5%, 2%); }
  100% { transform: translate(  0%,  0%); }
}

/* marqueeScroll: track moves exactly -50% → seamless loop with duplicate content */
@keyframes marqueeScroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* waveAnim: equaliser bars pulse. transform-origin:bottom = grow upward only. */
@keyframes waveAnim {
  0%, 100% { transform: scaleY(1);   opacity: .3; }
  50%      { transform: scaleY(2.6); opacity: .7; }
}


/* ══════════════════════════════════════════════════════
   20. RESPONSIVE & ACCESSIBILITY

   BREAKPOINT STRATEGY
   ───────────────────
   max-width: 768px  → Mobile:  stack columns, hide decorations
   min-width: 1024px → Desktop: unlock wider containers, larger spacing
   min-width: 1400px → Wide:    push containers to max, expand typography

   All containers default to a "mobile-first comfortable" size.
   Desktop rules expand them — never the other way around.
   ══════════════════════════════════════════════════════ */

/* ── Mobile (max 768px): stack everything ── */
@media (max-width: 768px) {
  .about-inner       { grid-template-columns: 1fr; gap: 3rem; }
  .about-photo-frame { max-width: 280px; margin: 0 auto; }
  .about-facts       { flex-wrap: wrap; gap: 1.5rem; }
  .ring-2, .ring-3   { display: none; }
  .constellation-tl,
  .constellation-br  { display: none; }

  /* Footer: centred single column */
  .footer-grid                  { grid-template-columns: 1fr; gap: 2.5rem; text-align: center; }
  .footer-col-label             { justify-content: center; }
  .footer-nav-list a,
  .footer-social-list a         { justify-content: center; }
  .footer-nav-list a:hover      { padding-left: 0; }
  .footer-social-list a::before { display: none; }
  .footer-col--info             { align-items: center; }
}

/* ── Desktop (min 1024px): unlock wider layouts ── */
@media (min-width: 1024px) {
  /* Larger horizontal padding so content doesn't feel cramped */
  #about, #interests, #vibes, #manifesto {
    padding-left:  4rem;
    padding-right: 4rem;
  }

  /* About: wider container, more gap */
  .about-inner {
    max-width: 1100px;
    gap: 8rem;
  }

  /* Cards: allow more columns, slightly wider cards */
  .cards-grid {
    max-width: 1200px;
    grid-template-columns: repeat(3, 1fr);
  }

  /* Vibes: always 4 columns on desktop */
  .vibes-list {
    grid-template-columns: repeat(4, 1fr);
  }
  .vibes-inner { max-width: 1200px; }

  /* Manifesto: wider reading width */
  .manifesto-inner { max-width: 960px; }

  /* Footer grid: wider max, better column balance */
  .footer-grid {
    max-width: 1100px;
    grid-template-columns: 1fr 1.2fr 1.4fr;
    gap: 5rem;
    padding: 0 4rem 5rem;
  }
}

/* ── Wide screens (min 1400px): expand further ── */
@media (min-width: 1400px) {
  /* Sections get generous horizontal breathing room */
  #about, #interests, #vibes, #manifesto {
    padding-left:  8rem;
    padding-right: 8rem;
  }

  .about-inner {
    max-width: 1280px;
    gap: 10rem;
  }

  /* Six cards always in two rows of three */
  .cards-grid {
    max-width: 1360px;
    gap: 2rem;
  }

  /* Vibes: bigger card padding at wide */
  .vibe-item { padding: 3rem 2.5rem; }

  .manifesto-inner { max-width: 1060px; }

  .footer-grid {
    max-width: 1280px;
    padding: 0 8rem 6rem;
  }
}

/* ── SVG Icon styles (footer social links — inline SVG) ──
   Icons use fill="currentColor" so they inherit the link's
   text color automatically. On hover the <a> color changes
   → icon color follows without any extra CSS needed.         ── */
.footer-social-list .social-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  /* display:block removes default inline baseline gap */
  display: block;
  /* fill inherits parent <a> color via currentColor */
  fill: currentColor;
  transition: fill .25s;
  /* Optical vertical alignment with the text label */
  position: relative;
  top: 1px;
}

/* Reduced motion: respects OS "reduce motion" setting */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration:        .01ms !important;
    animation-iteration-count: 1     !important;
    transition-duration:       .01ms !important;
  }
}
