/* ============================================================
   Vincent Enimedez — Portfolio
   Theme variables, dark (default) + light
   ============================================================ */
:root {
  --accent: #6366f1;
  --accent-2: #22d3ee;
  --accent-glow: rgba(99, 102, 241, 0.35);
  --radius: 16px;
  --radius-sm: 10px;
  --font-sans: 'Space Grotesk', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  --transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  --max-width: 1120px;
}

/* Dark theme (default) */
[data-theme='dark'] {
  --bg: #0a0a12;
  --bg-2: #0f1020;
  --surface: rgba(255, 255, 255, 0.04);
  --surface-hover: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.09);
  --text: #e7e9f3;
  --text-dim: #9ba0b8;
  --text-faint: #6b7091;
  --grid-line: rgba(99, 102, 241, 0.06);
  --shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.7);
}

/* Light theme — a different personality: a "gallery wall" studio. Gray wall,
   white paper cards hanging from strings with binder clips, soft real shadows.
   Palette: charcoal ink + deep teal + steel blue (no pink). */
[data-theme='light'] {
  --accent: #0f766e;   /* deep teal */
  --accent-2: #2563eb; /* steel blue */
  --accent-glow: rgba(37, 99, 235, 0.22);
  --ink: #26262b;      /* charcoal */
  --bg: #e9e9ec;       /* studio wall gray */
  --bg-2: #ffffff;
  --surface: #ffffff;
  --surface-hover: #ffffff;
  --border: #d4d4d8;
  --text: #26262b;
  --text-dim: #55555c;
  --text-faint: #97979f;
  --grid-line: rgba(38, 38, 43, 0.045);
  --shadow: 0 14px 30px -10px rgba(0, 0, 0, 0.25);
}

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

html { scroll-behavior: smooth; scroll-padding-top: 90px; }

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.65;
  overflow-x: hidden;
  transition: background var(--transition), color var(--transition);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Animated background ---------- */
.bg-grid {
  position: fixed;
  inset: 0;
  z-index: -2;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 44px 44px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 40%, transparent 100%);
}
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -3;
  background:
    radial-gradient(600px circle at 15% 10%, var(--accent-glow), transparent 45%),
    radial-gradient(500px circle at 85% 30%, rgba(34, 211, 238, 0.18), transparent 45%);
  transition: opacity var(--transition);
}
#particles { position: fixed; inset: 0; z-index: -1; pointer-events: none; }

/* ---------- Intro loading screen ---------- */
body.loading { overflow: hidden; }
.loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 46px;
  background: var(--bg);
  perspective: 1000px; /* 3D scene for the letters */
  transition: transform 0.85s cubic-bezier(0.76, 0, 0.24, 1), opacity 0.6s ease 0.2s;
}
.loader.done { opacity: 0; pointer-events: none; }
/* Theme-switch mode: see-through backdrop — the page assembles behind the letters */
.loader.overlay {
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  backdrop-filter: blur(9px) saturate(1.15);
  -webkit-backdrop-filter: blur(9px) saturate(1.15);
}

/* Wavefront reconstruction: each piece settles into its new design at the
   exact moment the theme edge sweeps over it. The delay is set per element
   from how far down the viewport it sits, so nothing moves before the wave
   arrives, and --rip-y points it the way the wave is travelling. Small and
   soft on purpose — this reads as the design changing, not as things flying
   in from off-screen. */
.rip {
  animation: ripIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: var(--rip-d, 0s);
  /* Promote for the animation only — the class is removed when it ends.
     Without this a scale on a text-heavy block re-rasterises every frame. */
  will-change: transform, opacity;
}
/* Opacity and transform ONLY: both run on the compositor. An animated
   filter: blur() here re-rasterises every element every frame, and with
   forty of them mid-switch that is what the stutter was.

   The start state is dim but never invisible — `both` holds a waiting
   element here for the whole of its delay, and opacity 0 would blank out
   half the page the moment the fallback band passes. */
@keyframes ripIn {
  from {
    opacity: 0.35;
    transform: translateY(var(--rip-y, 5px)) scale(0.99);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* Exit: freeze the sway, then each letter flies back out to where it came
   from (reverse of the entrance), and the dots fade */
.loader.out .loader-letters { animation-play-state: paused; }
.loader.out .loader-letters span.l {
  animation: flyOut3d 0.7s cubic-bezier(0.5, 0, 0.75, 0) forwards;
  animation-delay: 0s !important; /* all leave together — no partial "FRESH" fragment */
}
.loader.out .loader-dots { opacity: 0; transition: opacity 0.3s ease; }
/* "FRESHMEN" — 3D letters fly in from deep space, assemble, then the whole
   word sways in 3D with a holographic light-sweep and a mirror reflection */
.loader-letters {
  display: flex;
  gap: 0.04em;
  transform-style: preserve-3d;
  will-change: transform;
  animation: word3dTurn 6s ease-in-out 1.7s infinite;
}
.loader-letters span.l {
  display: inline-block;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform, opacity;
  opacity: 0;
  animation: fly3d 1s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.loader-letters b {
  display: inline-block;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(2.3rem, 11vw, 5rem);
  letter-spacing: 1px;
  background: linear-gradient(110deg, var(--accent) 0%, #ffffff 25%, var(--accent-2) 50%, var(--accent) 78%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  filter: drop-shadow(0 8px 16px rgba(99, 102, 241, 0.4));
  -webkit-box-reflect: below 1px linear-gradient(transparent 58%, rgba(255, 255, 255, 0.14));
  animation: loaderShine 2.6s linear infinite;
}
.loader-dots { display: flex; gap: 9px; }
.loader-dots i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.4;
  animation: loaderDot 1s ease-in-out infinite;
}
.loader-dots i:nth-child(2) { animation-delay: 0.15s; }
.loader-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes fly3d {
  0%   { opacity: 0; transform: translate3d(var(--tx), var(--ty), var(--tz)) rotateX(var(--rx)) rotateY(var(--ry)); }
  100% { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0) rotateY(0); }
}
/* Reverse of fly3d — each letter sails back to its origin in space */
@keyframes flyOut3d {
  0%   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0) rotateY(0); }
  100% { opacity: 0; transform: translate3d(var(--tx), var(--ty), var(--tz)) rotateX(var(--rx)) rotateY(var(--ry)); }
}
/* Starts and ends at 0deg (matches the assembled state, so no snap) and
   eases smoothly both ways */
@keyframes word3dTurn {
  0%   { transform: rotateY(0deg) rotateX(0deg); }
  25%  { transform: rotateY(15deg) rotateX(-4deg); }
  50%  { transform: rotateY(0deg) rotateX(4deg); }
  75%  { transform: rotateY(-15deg) rotateX(-4deg); }
  100% { transform: rotateY(0deg) rotateX(0deg); }
}
@keyframes loaderShine { to { background-position: -250% 0; } }
@keyframes loaderDot { 0%, 100% { transform: translateY(0); opacity: 0.4; } 50% { transform: translateY(-7px); opacity: 1; } }

/* ---------- Layout ---------- */
.section {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 90px 24px;
}

/* ---------- Navbar ---------- */
.navbar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 32px;
  backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  border-bottom: 1px solid var(--border);
}
.logo {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 1.3rem;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -1px;
}
.logo-bracket { color: var(--accent); }
.nav-links { display: flex; gap: 30px; }
.nav-links a {
  position: relative;
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.94rem;
  font-weight: 500;
  transition: color var(--transition);
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -5px;
  width: 0; height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width var(--transition);
}
.nav-links a:hover { color: var(--text); }
.nav-links a:hover::after { width: 100%; }

.nav-actions { display: flex; align-items: center; gap: 14px; }
.theme-toggle {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: var(--transition);
}
.theme-toggle:hover { background: var(--surface-hover); transform: translateY(-2px); border-color: var(--accent); }
/* Animated sun/moon swap: the outgoing icon spins + shrinks away while the
   incoming one spins + grows in (both share the same grid cell). */
.theme-toggle svg { grid-area: 1 / 1; transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.4s ease; }
[data-theme='dark'] .icon-sun   { opacity: 1; transform: rotate(0deg) scale(1); }
[data-theme='dark'] .icon-moon  { opacity: 0; transform: rotate(-120deg) scale(0.3); pointer-events: none; }
[data-theme='light'] .icon-sun  { opacity: 0; transform: rotate(120deg) scale(0.3); pointer-events: none; }
[data-theme='light'] .icon-moon { opacity: 1; transform: rotate(0deg) scale(1); }

.menu-btn { display: none; flex-direction: column; gap: 5px; background: none; border: none; cursor: pointer; padding: 6px; }
.menu-btn span { width: 24px; height: 2px; background: var(--text); border-radius: 2px; transition: var(--transition); }

/* ---------- Directional theme reveal ----------
   The travelling edge IS the transition — light falls from the top, dark
   rises from below. Leaving the browser's default cross-fade on the root
   pseudo-elements plays both at once and reads as a muddy dissolve, so both
   are switched off explicitly. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-old(root) { z-index: 0; }
::view-transition-new(root) { z-index: 1; }

/* Fallback for browsers without View Transitions: a soft band of the incoming
   accent sweeping the same way the reveal would. Height, colour and travel
   are set per switch. The z-index has to beat everything — modals, the chat
   panel, the loader. */
.theme-wipe {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 2147483000;
  pointer-events: none;
  opacity: 0;
  /* Moved with transform, so the band rides the compositor and the page
     underneath stays visible the whole way across. */
  transform: translateY(var(--from, 0));
  animation: themeSweep var(--sweep, 640ms) cubic-bezier(0.45, 0, 0.15, 1) forwards;
  will-change: transform, opacity;
}
/* Comes up fast, holds while it crosses the page, then lets go as it leaves —
   a plain fade-out over the whole sweep was gone before you could see it. */
@keyframes themeSweep {
  0%   { transform: translateY(var(--from, 0)); opacity: 0; }
  10%  { opacity: 1; }
  72%  { opacity: 0.9; }
  100% { transform: translateY(var(--to, 0)); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .theme-wipe { display: none; }
}

/* Layout switcher icon: rotates to hint the orientation */
#layoutToggle svg { transition: transform var(--transition); }
#layoutToggle.is-horizontal svg { transform: rotate(90deg); }

/* ---------- Horizontal (side-by-side) layout mode ---------- */
body.horizontal { overflow: hidden; height: 100vh; }
body.horizontal .page {
  display: flex;
  flex-direction: row;
  height: calc(100vh - 74px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}
body.horizontal .page > section,
body.horizontal .page > footer {
  flex: 0 0 100vw;
  width: 100vw;
  max-width: none;
  height: calc(100vh - 74px);
  margin: 0;
  overflow-y: auto;
  scroll-snap-align: start;
  padding: 44px max(24px, calc((100vw - var(--max-width)) / 2)) 40px;
}
body.horizontal .page > .hero { min-height: 0; }
body.horizontal .footer { border-top: none; }
body.horizontal .page::-webkit-scrollbar { height: 10px; }
body.horizontal .page::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; }
body.horizontal .page::-webkit-scrollbar-track { background: transparent; }

/* Nav dropdowns (background effects & music) */
.bg-switcher, .music-switcher { position: relative; display: flex; align-items: center; }
.bg-menu, .music-menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 180px;
  max-height: 70vh;
  overflow-y: auto;
  padding: 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-2);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 200;
  transform-origin: top right;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px) scale(0.96);
  pointer-events: none;
  transition: opacity 0.2s ease,
              transform 0.24s cubic-bezier(0.34, 1.45, 0.6, 1),
              visibility 0.24s;
}
.bg-menu.open, .music-menu.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.bg-menu button, .music-menu button {
  text-align: left;
  padding: 9px 14px;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: 0.88rem;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: var(--transition);
}
.bg-menu button:hover, .music-menu button:hover { background: var(--surface-hover); color: var(--text); }
.bg-menu button.active, .music-menu button.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-weight: 600;
}

/* Music icon while playing + the "Now Playing" pill */
#musicToggle.playing { color: var(--accent); border-color: var(--accent); }
#musicToggle.playing svg { animation: musicSpin 3.5s linear infinite; }
@keyframes musicSpin { to { transform: rotate(360deg); } }
.now-playing {
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  padding: 0;
  margin-right: -14px;        /* cancels the nav-actions flex gap while collapsed */
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--bg-2);
  box-shadow: var(--shadow);
  font-size: 0.82rem;
  color: var(--text);
  opacity: 0;
  pointer-events: none;
  transition: max-width 0.55s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.4s ease,
              padding 0.5s ease,
              margin-right 0.5s ease,
              border-color 0.4s ease;
}
.now-playing.show {
  max-width: 46vw;
  opacity: 1;
  padding: 7px 15px;
  margin-right: 0;
  border-color: var(--border);
}
/* On small screens the spinning icon is enough — the pill would crowd the bar */
@media (max-width: 680px) { .now-playing { display: none; } }
.now-playing strong { color: var(--accent); font-weight: 600; }
.np-text { max-width: 42vw; overflow: hidden; text-overflow: ellipsis; }
.np-eq { display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; flex: none; }
.np-eq i {
  width: 3px; height: 100%;
  transform-origin: bottom;
  border-radius: 2px;
  background: linear-gradient(var(--accent-2), var(--accent));
  animation: eq 0.9s ease-in-out infinite;
}
.np-eq i:nth-child(1) { animation-delay: 0s; }
.np-eq i:nth-child(2) { animation-delay: 0.25s; }
.np-eq i:nth-child(3) { animation-delay: 0.5s; }
@keyframes eq { 0%, 100% { transform: scaleY(0.35); } 50% { transform: scaleY(1); } }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  padding: 13px 28px;
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: var(--transition);
}
.btn-primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  box-shadow: 0 8px 24px -8px var(--accent-glow);
}
.btn-primary:hover { transform: translateY(-3px); box-shadow: 0 14px 34px -8px var(--accent-glow); }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-3px); }
.btn-block { width: 100%; text-align: center; border: none; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

/* ---------- Hero ---------- */
.hero {
  max-width: var(--max-width);
  margin: 0 auto;
  min-height: calc(100vh - 74px);
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  align-items: center;
  gap: 50px;
  padding: 40px 24px;
}
.hero-greeting {
  font-family: var(--font-mono);
  color: var(--accent-2);
  font-size: 0.95rem;
  margin-bottom: 14px;
}
.terminal-prompt { color: var(--accent); font-weight: 700; }
.hero-name {
  font-size: clamp(2.6rem, 6vw, 4.4rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -2px;
  margin-bottom: 10px;
}
.gradient-text {
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.hero-role {
  font-family: var(--font-mono);
  font-size: clamp(1.1rem, 2.5vw, 1.6rem);
  color: var(--text-dim);
  font-weight: 500;
  min-height: 1.6em;
  margin-bottom: 22px;
}
.cursor { color: var(--accent); animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }
.hero-desc { max-width: 520px; color: var(--text-dim); font-size: 1.05rem; margin-bottom: 32px; }
.hero-desc strong { color: var(--text); }
.hero-cta { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 32px; }
.hero-socials { display: flex; gap: 14px; }
.social-icon {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  text-decoration: none;
  transition: var(--transition);
}
.social-icon:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 8px 20px -8px var(--accent-glow);
}

.hero-extra-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 22px;
}
.btn-cv {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 24px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  transition: var(--transition);
}
.btn-cv:hover {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  border-color: transparent;
  transform: translateY(-3px);
  box-shadow: 0 10px 26px -8px var(--accent-glow);
}
.btn-cv svg { transition: transform var(--transition); }
.btn-cv:hover svg { transform: translateY(2px); }

.btn-coffee {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 24px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: linear-gradient(135deg, #f59e0b, #ea580c);
  color: #fff;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 8px 24px -8px rgba(234, 88, 12, 0.5);
  transition: var(--transition);
}
.btn-coffee:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px -8px rgba(234, 88, 12, 0.6);
}
.btn-coffee svg { transition: transform var(--transition); }
.btn-coffee:hover svg { transform: rotate(-8deg) scale(1.05); }

/* ---------- Buy Me a Coffee QR popup ---------- */
.qr-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.8);
  backdrop-filter: blur(6px);
}
.qr-modal.open { display: flex; animation: fadeIn 0.2s ease; }
.qr-box {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow-y: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-2);
  box-shadow: var(--shadow);
  padding: 34px 30px;
  text-align: center;
}
.qr-close {
  position: absolute;
  top: 14px; right: 16px;
  width: 40px; height: 40px;
  font-size: 1.7rem; line-height: 1;
  color: var(--text-dim);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
}
.qr-close:hover { color: #fff; background: #ea580c; border-color: transparent; transform: rotate(90deg); }
.qr-title { font-size: 1.5rem; font-weight: 700; margin-bottom: 8px; }
.qr-sub { color: var(--text-dim); font-size: 0.92rem; margin-bottom: 26px; }
.qr-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 20px;
}
.qr-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 16px;
}
.qr-card img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: #fff;               /* white keeps QR codes crisp & scannable */
  border-radius: 8px;
  padding: 8px;
  cursor: zoom-in;
  transition: transform var(--transition);
}
.qr-card img:hover { transform: scale(1.04); }
.qr-card span {
  display: block;
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}
.qr-empty { color: var(--text-faint); font-family: var(--font-mono); padding: 20px; }

/* Code window */
.hero-visual { display: flex; justify-content: center; perspective: 1500px; }
/* 3D flip: code window (front) <-> photo (back) */
.hero-flip {
  position: relative;
  width: 100%;
  max-width: 420px;
  transform-style: preserve-3d;
  transition: transform 1s cubic-bezier(0.6, 0, 0.2, 1);
}
.hero-flip.flipped { transform: rotateY(180deg); }
.hero-face { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.hero-front { position: relative; }
.hero-back {
  position: absolute;
  inset: 0;
  transform: rotateY(180deg);
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  background: var(--surface);
}
.hero-back img { width: 100%; height: 100%; object-fit: cover; display: block; }
.code-window {
  width: 100%;
  max-width: 420px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  backdrop-filter: blur(10px);
  box-shadow: var(--shadow);
  overflow: hidden;
  animation: float 6s ease-in-out infinite;
}
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
.code-window-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--text) 4%, transparent);
}
.dot { width: 12px; height: 12px; border-radius: 50%; }
.dot-red { background: #ff5f57; }
.dot-yellow { background: #febc2e; }
.dot-green { background: #28c840; }
.code-window-title { margin-left: 8px; font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-faint); }
.code-window-body { padding: 22px; font-family: var(--font-mono); font-size: 0.9rem; line-height: 1.9; overflow-x: auto; }
.tok-key { color: #c084fc; }
.tok-var { color: var(--accent-2); }
.tok-prop { color: #f472b6; }
.tok-str { color: #86efac; }
.tok-bool { color: #fbbf24; }
.tok-num { color: #fbbf24; }

/* ---------- Section head ---------- */
.section-head { display: flex; align-items: center; gap: 16px; margin-bottom: 40px; }
.section-head.center { justify-content: center; text-align: center; }
.section-num { font-family: var(--font-mono); color: var(--accent); font-size: 1.1rem; }
.section-title { font-size: clamp(1.7rem, 4vw, 2.4rem); font-weight: 700; letter-spacing: -1px; white-space: nowrap; }
.section-line { flex: 1; height: 1px; background: var(--border); }
.section-subtitle { color: var(--text-dim); margin-bottom: 40px; max-width: 600px; }

/* ---------- About ---------- */
.about-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 50px; align-items: start; }
.about-text p { color: var(--text-dim); margin-bottom: 18px; }
.about-text strong { color: var(--text); }
.about-tech-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  list-style: none;
  margin-top: 16px;
}
.about-tech-list li {
  font-family: var(--font-mono);
  font-size: 0.9rem;
  color: var(--text-dim);
  padding-left: 22px;
  position: relative;
}
.about-tech-list li::before { content: '▹'; position: absolute; left: 0; color: var(--accent-2); }

.about-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 32px;
  text-align: center;
  backdrop-filter: blur(10px);
}
.avatar {
  width: 130px; height: 130px;
  margin: 0 auto 24px;
  border-radius: 50%;
  box-shadow: 0 10px 30px -8px var(--accent-glow);
  cursor: pointer;
  outline: none;
}
.avatar-inner {
  position: relative;
  width: 100%; height: 100%;
}
.avatar-face {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}
/* profile2 sits behind; the front photo fades out on hover to reveal it,
   then fades back in when the cursor leaves */
.avatar-back { z-index: 1; }
.avatar-front { z-index: 2; opacity: 1; transition: opacity 0.5s ease; }
.avatar:hover .avatar-front,
.avatar:focus-within .avatar-front { opacity: 0; }
.avatar-img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: none; /* revealed by script.js once the photo loads */
}
.avatar-initials { font-size: 3rem; font-weight: 700; color: #fff; letter-spacing: -2px; }
.about-stats { display: flex; flex-direction: column; gap: 16px; }
.stat { border-top: 1px solid var(--border); padding-top: 16px; }
/* The two live counters share a row so the card doesn't grow too tall */
.stat-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.stat-num { display: block; font-size: 1.5rem; font-weight: 700; color: var(--accent); font-family: var(--font-mono); }
.stat-label { font-size: 0.82rem; color: var(--text-faint); }

/* ---------- Skills ---------- */
/* align-items: start -> each card is its own height, so expanding one
   card's "See more" doesn't stretch the others */
.skills-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 22px; align-items: start; }
.skill-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 28px;
  backdrop-filter: blur(10px);
  transition: var(--transition);
}
.skill-card:hover { transform: translateY(-6px); border-color: var(--accent); box-shadow: var(--shadow); }
.skill-icon {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, var(--accent-glow), rgba(34, 211, 238, 0.15));
  font-family: var(--font-mono);
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 18px;
}
.skill-card h3 { font-size: 1.2rem; margin-bottom: 8px; }
.skill-card p { color: var(--text-dim); font-size: 0.92rem; margin-bottom: 16px; }
.skill-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.skill-tags span, .project-tags span {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  padding: 4px 10px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
}
/* "See more" for long skill cards: hide tags past the 8th while collapsed */
.skill-tags { overflow: hidden; } /* clips cleanly during the height animation */
.skill-card.collapsed .skill-tags span:nth-child(n+9) { display: none; }
/* Extra tags fade + slide in when the card is expanded */
.skill-card:not(.collapsed) .skill-tags span:nth-child(n+9) { animation: skillTagIn 0.4s ease backwards; }
@keyframes skillTagIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.skill-more {
  margin-top: 14px;
  background: none; border: none; cursor: pointer;
  font-family: var(--font-mono); font-size: 0.78rem; font-weight: 500;
  color: var(--accent);
  display: inline-flex; align-items: center; gap: 5px;
  transition: color var(--transition), gap var(--transition);
}
.skill-more:hover { color: var(--accent-2); gap: 9px; }
.skill-more svg { transition: transform var(--transition); }
.skill-card:not(.collapsed) .skill-more svg { transform: rotate(180deg); }

/* ---------- Projects ---------- */
/* auto-fill (not auto-fit) so a single project stays card-sized, not full-width */
.projects-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 24px; }

/* Coming Soon placeholder (shown when the projects folder is empty) */
.projects-soon {
  grid-column: 1 / -1;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 1.25rem;
  color: var(--text-dim);
  padding: 54px 20px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

/* Project cards */
.pv-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(10px);
  overflow: hidden;
  transition: var(--transition);
  display: flex;
  flex-direction: column;
}
.pv-card:hover, .pv-card:focus-within {
  transform: translateY(-8px);
  border-color: var(--accent);
  box-shadow: var(--shadow);
}
.pv-thumb {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 20%, transparent),
    color-mix(in srgb, var(--accent-2) 20%, transparent));
}
button.pv-thumb { cursor: pointer; }
.pv-thumb img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition); }
.pv-noimg { display: grid; place-items: center; width: 100%; height: 100%; font-size: 3rem; }
.pv-card:hover .pv-thumb img { transform: scale(1.05); }
.pv-play {
  position: absolute; inset: 0; margin: auto;
  width: 62px; height: 62px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border: 2px solid rgba(255, 255, 255, 0.85);
  transition: var(--transition);
}
.pv-play svg { margin-left: 3px; }
.pv-card:hover .pv-play { background: var(--accent); border-color: transparent; transform: scale(1.12); }
.pv-body { padding: 18px 20px; display: flex; flex-direction: column; flex: 1; }
.pv-title { font-size: 1.15rem; font-weight: 600; margin-bottom: 4px; }
.pv-desc {
  margin-top: 8px; color: var(--text-dim); font-size: 0.9rem; line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* Buttons (shared by cards + the detail popup) */
.pv-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px; border-radius: 8px;
  font-family: var(--font-sans); font-size: 0.85rem; font-weight: 600;
  cursor: pointer; text-decoration: none; border: 1px solid transparent;
  transition: var(--transition);
}
.pv-view {                       /* card's "View Project" button */
  margin-top: 14px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}
.pv-view:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); transform: translateY(-2px); }
.pv-watch { background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff; }
.pv-watch:hover { transform: translateY(-2px); box-shadow: 0 8px 20px -8px var(--accent-glow); }
.pv-visit { background: transparent; color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.pv-visit:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); transform: translateY(-2px); }

/* Project detail popup */
.proj-modal {
  position: fixed; inset: 0; z-index: 1050;
  display: none; align-items: center; justify-content: center;
  padding: 24px; background: rgba(0, 0, 0, 0.82); backdrop-filter: blur(6px);
}
.proj-modal.open { display: flex; animation: fadeIn 0.2s ease; }
.proj-box {
  position: relative;
  width: 100%; max-width: 640px; max-height: 90vh; overflow-y: auto;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--bg-2); box-shadow: var(--shadow);
  padding-bottom: 28px;
}
.proj-close {
  position: absolute; top: 14px; right: 16px; z-index: 2;
  width: 40px; height: 40px; font-size: 1.7rem; line-height: 1;
  color: #fff; background: rgba(0, 0, 0, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 50%;
  cursor: pointer; transition: var(--transition);
}
.proj-close:hover { background: var(--accent); border-color: transparent; transform: rotate(90deg); }
.proj-title { font-size: 1.5rem; font-weight: 700; padding: 28px 30px 0; }
.proj-desc { color: var(--text-dim); font-size: 0.95rem; line-height: 1.75; padding: 16px 30px 0; }
.proj-actions { display: flex; flex-wrap: wrap; gap: 12px; padding: 24px 30px 0; }
/* Media gallery (all images + videos, clickable) */
.proj-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  padding: 18px 30px 0;
}
.proj-gallery.single { grid-template-columns: 1fr; }
.proj-media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  padding: 0;
}
.proj-media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--transition); }
.proj-media:hover img { transform: scale(1.06); }
.proj-media .pv-play { width: 46px; height: 46px; border-width: 2px; }
.proj-media .pv-play svg { width: 20px; height: 20px; }
/* "N items" badge on the card thumbnail */
.pv-count {
  position: absolute; bottom: 10px; right: 10px;
  font-family: var(--font-mono); font-size: 0.7rem; font-weight: 600;
  color: #fff; background: rgba(0, 0, 0, 0.55);
  padding: 3px 8px; border-radius: 6px;
}

/* ---------- "In Development" — projects with no media and no links ---------- */
.pv-wip {
  position: absolute; top: 10px; left: 10px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.02em;
  color: #1a1206;
  background: linear-gradient(135deg, #fbbf24, #f59e0b);
  box-shadow: 0 4px 12px -3px rgba(245, 158, 11, 0.6);
}
.pv-wip svg { flex: none; }
/* Hazard stripes behind the 🚧 placeholder so the card still looks designed */
.pv-card.is-wip .pv-thumb {
  background:
    repeating-linear-gradient(135deg,
      color-mix(in srgb, #f59e0b 12%, transparent) 0 16px,
      transparent 16px 32px),
    color-mix(in srgb, #f59e0b 6%, var(--bg-2));
}
.pv-card.is-wip .pv-noimg { opacity: 0.85; }
.pv-card.is-wip:hover, .pv-card.is-wip:focus-within { border-color: #f59e0b; }

/* Matching notice at the top of the project popup */
.proj-wip {
  display: flex; align-items: flex-start; gap: 10px;
  margin-bottom: 16px;
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 0.88rem; line-height: 1.6;
  color: var(--text);
  border: 1px solid color-mix(in srgb, #f59e0b 45%, transparent);
  background: color-mix(in srgb, #f59e0b 12%, transparent);
}
.proj-wip svg { flex: none; margin-top: 3px; color: #f59e0b; }
.proj-wip strong { color: #f59e0b; }
/* Darker amber reads properly on the light theme's white paper */
[data-theme='light'] .proj-wip {
  border-color: color-mix(in srgb, #b45309 40%, transparent);
  background: color-mix(in srgb, #f59e0b 16%, #fff);
}
[data-theme='light'] .proj-wip svg,
[data-theme='light'] .proj-wip strong { color: #b45309; }

/* ---------- Media viewer (fullscreen images/videos with prev/next) ---------- */
.media-viewer {
  position: fixed; inset: 0; z-index: 1150;
  display: none; align-items: center; justify-content: center;
  gap: 12px; padding: 30px 66px;
  background: rgba(0, 0, 0, 0.9); backdrop-filter: blur(8px);
}
.media-viewer.open { display: flex; animation: fadeIn 0.2s ease; }
.mv-stage {
  position: relative; flex: 1;
  max-width: 1100px; max-height: 86vh;
  display: grid; place-items: center;
}
.mv-img {
  max-width: 100%; max-height: 86vh; object-fit: contain;
  border-radius: 10px; box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.85);
}
.mv-video { position: relative; width: 100%; max-width: 980px; aspect-ratio: 16 / 9; }
.mv-video iframe {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; border-radius: 10px; background: #000;
}
.mv-nav {
  flex: none; width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer; color: #fff;
  background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);
  transition: var(--transition);
}
.mv-nav:hover { background: var(--accent); border-color: transparent; transform: scale(1.08); }
.media-viewer.single .mv-nav, .media-viewer.single .mv-count { display: none; }
.mv-close {
  position: absolute; top: 20px; right: 24px; z-index: 2;
  width: 46px; height: 46px; font-size: 1.9rem; line-height: 1; color: #fff;
  background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%; cursor: pointer; transition: var(--transition);
}
.mv-close:hover { background: var(--accent); border-color: transparent; transform: rotate(90deg); }
.mv-count {
  position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.8); font-family: var(--font-mono); font-size: 0.85rem;
}
@media (max-width: 640px) {
  .media-viewer { padding: 16px 8px; }
  .mv-nav { width: 42px; height: 42px; }
}

/* ---------- Live site preview (embedded iframe) ---------- */
.live-modal {
  position: fixed; inset: 0; z-index: 1150;
  display: none; align-items: center; justify-content: center; padding: 20px;
  background: rgba(0, 0, 0, 0.85); backdrop-filter: blur(8px);
}
.live-modal.open { display: flex; animation: fadeIn 0.2s ease; }
.live-box {
  width: 100%; max-width: 1120px; height: 86vh;
  display: flex; flex-direction: column;
  border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--border); background: var(--bg-2); box-shadow: var(--shadow);
}
.live-bar {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  border-bottom: 1px solid var(--border); background: var(--surface);
}
.live-url {
  flex: 1; font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.live-open {
  font-family: var(--font-mono); font-size: 0.8rem; color: var(--accent);
  text-decoration: none; padding: 5px 12px; white-space: nowrap;
  border: 1px solid var(--accent-glow); border-radius: 8px; transition: var(--transition);
}
.live-open:hover { background: var(--accent-glow); }
.live-close {
  width: 34px; height: 34px; font-size: 1.5rem; line-height: 1;
  color: var(--text-dim); background: none; border: none; cursor: pointer; transition: var(--transition);
}
.live-close:hover { color: var(--text); }
.live-frame-wrap { flex: 1; background: #fff; }
.live-frame { width: 100%; height: 100%; border: 0; display: block; }
.live-note { padding: 8px 14px; font-size: 0.75rem; color: var(--text-faint); text-align: center; }

/* Project video modal */
.video-modal {
  position: fixed; inset: 0; z-index: 1100;
  display: none; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(6px);
}
.video-modal.open { display: flex; animation: fadeIn 0.2s ease; }
.video-box { position: relative; width: 100%; max-width: 900px; }
.video-frame {
  position: relative; width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
  box-shadow: var(--shadow);
}
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-close {
  position: absolute; top: -48px; right: 0;
  width: 42px; height: 42px;
  font-size: 1.7rem; line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
}
.video-close:hover { background: var(--accent); border-color: transparent; transform: rotate(90deg); }
.video-caption { text-align: center; color: #fff; margin-top: 14px; font-family: var(--font-mono); font-size: 0.9rem; }
.project-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 28px;
  backdrop-filter: blur(10px);
  transition: var(--transition);
  display: flex;
  flex-direction: column;
}
.project-card:hover { transform: translateY(-8px); border-color: var(--accent); box-shadow: var(--shadow); }
.project-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; }
.project-folder { font-size: 2rem; }
.project-links { display: flex; gap: 14px; }
.project-links a {
  font-family: var(--font-mono);
  color: var(--text-dim);
  text-decoration: none;
  font-size: 1.1rem;
  transition: var(--transition);
}
.project-links a:hover { color: var(--accent); transform: translateY(-2px); }
.project-title { font-size: 1.25rem; margin-bottom: 10px; }
.project-desc { color: var(--text-dim); font-size: 0.92rem; flex: 1; margin-bottom: 18px; }
.project-tags { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------- Certificate year filter ---------- */
.cert-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px 30px;
  flex-wrap: wrap;
  margin-bottom: 40px;
}
.cert-head .section-subtitle { margin-bottom: 0; flex: 1 1 320px; }
.cert-filter { display: flex; gap: 8px; flex-wrap: wrap; }
.cert-filter button {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  padding: 7px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  transition: var(--transition);
}
.cert-filter button:hover { color: var(--text); border-color: var(--accent); transform: translateY(-2px); }
.cert-filter button.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  border-color: transparent;
}

/* ---------- Certificates page ---------- */
.page-hero { text-align: center; padding: 70px 24px 20px; max-width: var(--max-width); margin: 0 auto; }
.page-hero .hero-greeting { justify-content: center; }
.page-title { font-size: clamp(2rem, 5vw, 3rem); font-weight: 700; letter-spacing: -1.5px; margin-bottom: 12px; }
.page-subtitle { color: var(--text-dim); max-width: 560px; margin: 0 auto; }
.back-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 0.9rem;
  color: var(--text-dim); text-decoration: none;
  margin-bottom: 24px; transition: var(--transition);
}
.back-link:hover { color: var(--accent); transform: translateX(-3px); }

.certs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 24px;
}
/* When the filter leaves a single certificate, center it instead of
   stretching it across the whole row */
.certs-grid.is-single {
  grid-template-columns: minmax(300px, 380px);
  justify-content: center;
}
.cert-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(10px);
  overflow: hidden;
  transition: opacity 0.35s ease, transform 0.35s ease,
              border-color var(--transition), box-shadow var(--transition);
  display: flex;
  flex-direction: column;
}
.cert-card:hover { transform: translateY(-8px); border-color: var(--accent); box-shadow: var(--shadow); }
/* Year-filter fade: matching cards fade in, filtered-out ones fade away */
.cert-card.is-hidden { opacity: 0; transform: translateY(14px) scale(0.97); pointer-events: none; }
.cert-thumb {
  position: relative;
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--accent) 22%, transparent),
                    color-mix(in srgb, var(--accent-2) 22%, transparent));
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.cert-thumb {
  text-decoration: none;
  cursor: pointer;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: 0;
  width: 100%;
  font: inherit;
  color: inherit;
}
.cert-thumb img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--transition);
}
.cert-card:hover .cert-thumb img { transform: scale(1.04); }
.cert-badge { font-size: 3rem; opacity: 0.9; }
.cert-body { padding: 22px; display: flex; flex-direction: column; flex: 1; }
.cert-name { font-size: 1.12rem; font-weight: 600; margin-bottom: 6px; }
.cert-issuer { color: var(--text-dim); font-size: 0.92rem; margin-bottom: 4px; }
.cert-date { font-family: var(--font-mono); font-size: 0.8rem; color: var(--accent); margin-bottom: 14px; }
.cert-link {
  margin-top: auto;
  align-self: flex-start;
  font-family: var(--font-mono); font-size: 0.82rem;
  color: var(--accent); text-decoration: none;
  background: transparent;
  cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  padding: 7px 14px; border-radius: 8px;
  transition: var(--transition);
}
.cert-link:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }

/* Certificate preview lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1100; /* above the Buy-Me-a-Coffee popup (1000) */
  display: none;
  align-items: center;
  justify-content: center;
  padding: 30px;
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(6px);
}
.lightbox.open { display: flex; animation: fadeIn 0.2s ease; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.lightbox-img {
  max-width: 100%;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 10px;
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.8);
}
.lightbox-close {
  position: absolute;
  top: 18px; right: 26px;
  width: 46px; height: 46px;
  font-size: 2rem; line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
}
.lightbox-close:hover { background: var(--accent); border-color: var(--accent); transform: rotate(90deg); }
.certs-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-faint);
  font-family: var(--font-mono);
  padding: 40px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

/* ---------- Contact ---------- */
.contact { text-align: center; }
.contact-intro { max-width: 540px; margin: 0 auto 40px; color: var(--text-dim); }
.contact-form { max-width: 620px; margin: 0 auto 30px; text-align: left; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.form-group { margin-bottom: 18px; }
.form-group label { display: block; font-size: 0.85rem; margin-bottom: 8px; color: var(--text-dim); font-weight: 500; }
.form-group input, .form-group textarea {
  width: 100%;
  padding: 13px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 0.95rem;
  transition: var(--transition);
  resize: vertical;
}
.form-group input:focus, .form-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.form-status { text-align: center; margin-top: 14px; font-size: 0.9rem; min-height: 1.2em; }
.form-status.success { color: #34d399; }
.form-status.error { color: #f87171; }
.contact-email {
  font-family: var(--font-mono);
  color: var(--accent);
  text-decoration: none;
  font-size: 1rem;
  border-bottom: 1px solid transparent;
  transition: var(--transition);
}
.contact-email:hover { border-color: var(--accent); }

/* ---------- Footer ---------- */
.footer { text-align: center; padding: 40px 24px; border-top: 1px solid var(--border); color: var(--text-faint); }
.footer strong { color: var(--text); }
.footer-sub { font-family: var(--font-mono); font-size: 0.82rem; margin-top: 6px; }

/* ---------- Reveal animation ---------- */
[data-reveal] { opacity: 0; transform: translateY(30px); transition: opacity 0.7s ease, transform 0.7s ease; }
[data-reveal].visible { opacity: 1; transform: translateY(0); }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; text-align: left; padding-top: 30px; min-height: auto; margin-top: 40px; }
  .hero-visual { order: -1; }
  .about-grid { grid-template-columns: 1fr; }
  .nav-links {
    position: fixed;
    top: 74px; right: 0;
    flex-direction: column;
    background: var(--bg-2);
    border-left: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: 24px 32px;
    gap: 20px;
    transform: translateX(110%);
    transition: transform var(--transition);
    border-radius: 0 0 0 var(--radius);
  }
  .nav-links.open { transform: translateX(0); }
  .menu-btn { display: flex; }
  .menu-btn.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .menu-btn.open span:nth-child(2) { opacity: 0; }
  .menu-btn.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}
@media (max-width: 540px) {
  .form-row { grid-template-columns: 1fr; }
  .navbar { padding: 14px 20px; }
  .about-tech-list { grid-template-columns: 1fr; }
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto; }
}

/* ============================================================
   CV GENERATOR
   ============================================================ */
.cvgen-modal {
  position: fixed; inset: 0; z-index: 1200;
  display: none; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.82);
  backdrop-filter: blur(6px);
}
.cvgen-modal.open { display: flex; animation: fadeIn 0.2s ease; }
.cvgen-box {
  position: relative;
  width: 100%; max-width: 760px;
  max-height: 90vh; overflow-y: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-2);
  box-shadow: var(--shadow);
  padding: 34px 30px 30px;
}
.cvgen-close {
  position: absolute; top: 14px; right: 16px;
  width: 40px; height: 40px; font-size: 1.7rem; line-height: 1;
  color: var(--text-dim); background: var(--surface);
  border: 1px solid var(--border); border-radius: 50%;
  cursor: pointer; transition: var(--transition);
}
.cvgen-close:hover { color: #fff; background: var(--accent); border-color: transparent; transform: rotate(90deg); }
.cvgen-title { font-size: 1.4rem; font-weight: 700; text-align: center; }
.cvgen-sub { color: var(--text-dim); text-align: center; font-size: 0.9rem; margin: 6px 0 24px; }
.cvgen-back {
  background: none; border: none; color: var(--text-dim);
  font-family: var(--font-mono); font-size: 0.85rem; cursor: pointer;
  margin-bottom: 10px; transition: var(--transition);
}
.cvgen-back:hover { color: var(--accent); }

.cv-preview {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; background: #fff; margin-bottom: 22px;
  min-height: 120px; display: grid; place-items: center;
}
.cv-preview img { width: 100%; display: block; }

.cvgen-formats { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 420px; margin: 0 auto; }
.cvgen-fmt {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 22px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-family: var(--font-sans); font-weight: 600; font-size: 1.05rem;
  cursor: pointer; transition: var(--transition);
}
.cvgen-fmt:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: var(--shadow); }
.cvgen-fmt:disabled { opacity: 0.5; cursor: wait; transform: none; }
.cvgen-fmt-ico { font-size: 2rem; }
.cvgen-fmt small { color: var(--text-faint); font-weight: 400; font-size: 0.75rem; }
.cvgen-status { text-align: center; margin-top: 18px; min-height: 1.2em; color: var(--text-dim); font-size: 0.9rem; }

/* ============================================================
   ANIMATION ENHANCEMENTS
   scroll progress, scroll-spy, staggered card reveals, 3D tilt,
   custom cursor, tickers, hero letters, parallax, form feedback
   ============================================================ */

/* Scroll progress bar */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 3px;
  z-index: 1301;
  pointer-events: none;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 0.12s linear;
}

/* Scroll-spy: the section currently in view stays highlighted in the nav */
.nav-links a.active { color: var(--text); }
.nav-links a.active::after { width: 100%; }

/* Staggered card reveal (classes are removed by script.js once played) */
.card-reveal { opacity: 0; }
.card-reveal.in {
  opacity: 1;
  animation: cardIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) backwards;
  animation-delay: var(--rv-delay, 0s);
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(28px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* 3D tilt cards with a cursor-following glare highlight */
.tilt-card { position: relative; will-change: transform; }
.tilt-glare {
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.3s ease;
  background: radial-gradient(420px circle at var(--gx, 50%) var(--gy, 50%),
              rgba(255, 255, 255, 0.14), transparent 55%);
}
.tilt-card:hover .tilt-glare { opacity: 1; }

/* Custom cursor (fine-pointer devices only; enabled by script.js) */
@media (hover: hover) and (pointer: fine) {
  body.custom-cursor, body.custom-cursor * { cursor: none !important; }
}
.cursor-dot, .cursor-ring {
  position: fixed; top: 0; left: 0;
  z-index: 10000;
  pointer-events: none;
  border-radius: 50%;
  opacity: 0;
}
body.custom-cursor .cursor-dot {
  opacity: 1;
  width: 6px; height: 6px;
  background: var(--accent-2);
  box-shadow: 0 0 10px var(--accent-2);
}
body.custom-cursor .cursor-ring {
  opacity: 1;
  width: 36px; height: 36px;
  border: 1.5px solid color-mix(in srgb, var(--accent) 65%, transparent);
  transition: width 0.25s ease, height 0.25s ease, border-color 0.25s ease,
              background 0.25s ease, opacity 0.3s ease;
}
body.custom-cursor .cursor-ring.big {
  width: 58px; height: 58px;
  border-color: var(--accent-2);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
body.cursor-hidden .cursor-dot, body.cursor-hidden .cursor-ring { opacity: 0 !important; }

/* Hero name assembles letter by letter after the intro */
.hero-name .lw { display: inline-block; white-space: nowrap; }
.hero-name .lt {
  display: inline-block;
  opacity: 0;
  animation: heroLt 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.gradient-text .lt {
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
@keyframes heroLt {
  from { opacity: 0; transform: translateY(24px) rotate(6deg) scale(0.8); }
  to   { opacity: 1; transform: none; }
}

/* Hero visual eases smoothly during/after the mouse parallax
   (keeps the opacity fade from the scroll-reveal system) */
.hero-visual { transition: opacity 0.7s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1); }

/* Contact form feedback: shake on error, confetti canvas on success */
.contact-form.shake { animation: formShake 0.45s ease; }
@keyframes formShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-10px); }
  40% { transform: translateX(9px); }
  60% { transform: translateX(-6px); }
  80% { transform: translateX(4px); }
}
.confetti-canvas { position: fixed; inset: 0; z-index: 9998; pointer-events: none; }

/* Footer heartbeat */
.heartbeat {
  display: inline-block;
  animation: heartbeat 1.4s ease-in-out infinite;
  transform-origin: center;
}
@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  14% { transform: scale(1.3); }
  28% { transform: scale(1); }
  42% { transform: scale(1.22); }
  56% { transform: scale(1); }
}

/* ============================================================
   FLOATING AI ASSISTANT  (button bottom-left + chat panel)
   ============================================================ */
/* The dock is the fixed part and never animates, so mobile browsers keep
   painting it; --vv-lift is set by script.js from visualViewport so the
   button stays above a collapsing address bar. */
.ai-fab-dock {
  position: fixed;
  right: 26px;
  bottom: calc(26px + var(--vv-lift, 0px) + env(safe-area-inset-bottom, 0px));
  z-index: 940;
  width: 58px; height: 58px;
  pointer-events: none;
  /* own compositing layer: some mobile WebViews drop fixed elements from
     the paint pass until an unrelated repaint happens */
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.ai-fab {
  position: relative;
  width: 100%; height: 100%;
  pointer-events: auto;
  display: grid; place-items: center;
  border: none; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  cursor: pointer;
  box-shadow: 0 12px 30px -8px var(--accent-glow), 0 4px 12px rgba(0, 0, 0, 0.25);
  animation: aiFloat 4s ease-in-out infinite;
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow var(--transition);
}
.ai-fab:hover { transform: translateY(-4px) scale(1.06); box-shadow: 0 18px 40px -8px var(--accent-glow); }
.ai-fab:active { transform: scale(0.96); }
@keyframes aiFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
.ai-fab-icon { position: relative; z-index: 1; transition: transform var(--transition); }
.ai-fab:hover .ai-fab-icon { transform: rotate(-8deg) scale(1.05); }
/* Expanding pulse ring to draw the eye */
.ai-fab-pulse {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.5;
  animation: aiPulse 2.4s ease-out infinite;
}
@keyframes aiPulse {
  0%   { transform: scale(1); opacity: 0.45; }
  70%  { transform: scale(1.7); opacity: 0; }
  100% { transform: scale(1.7); opacity: 0; }
}
/* Hover tooltip (sits to the left of the right-anchored button) */
.ai-fab-tip {
  position: absolute; right: calc(100% + 12px);
  padding: 6px 12px; border-radius: 8px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border);
  font-size: 0.8rem; font-weight: 500; white-space: nowrap;
  box-shadow: var(--shadow);
  opacity: 0; transform: translateX(6px); pointer-events: none;
  transition: opacity var(--transition), transform var(--transition);
}
.ai-fab:hover .ai-fab-tip { opacity: 1; transform: translateX(0); }
.ai-fab.open { animation: none; }
.ai-fab.open .ai-fab-pulse { display: none; }
.ai-fab.open .ai-fab-tip { display: none; }

/* Chat panel */
.ai-chat {
  position: fixed;
  right: 26px;
  bottom: calc(96px + var(--vv-lift, 0px) + env(safe-area-inset-bottom, 0px));
  z-index: 945;
  width: 370px; max-width: calc(100vw - 40px);
  height: 500px; max-height: calc(100vh - 130px);
  display: flex; flex-direction: column;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-2);
  box-shadow: var(--shadow);
  overflow: hidden;
  transform-origin: bottom right;
  opacity: 0; visibility: hidden;
  transform: translateY(16px) scale(0.94);
  pointer-events: none;
  transition: opacity 0.25s ease,
              transform 0.3s cubic-bezier(0.34, 1.45, 0.6, 1),
              visibility 0.3s;
}
.ai-chat.open { opacity: 1; visibility: visible; transform: translateY(0) scale(1); pointer-events: auto; }

.ai-chat-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
}
.ai-chat-ava {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
}
.ai-chat-id { flex: 1; line-height: 1.25; }
.ai-chat-id strong { display: block; font-size: 0.98rem; }
.ai-chat-status { display: inline-flex; align-items: center; gap: 6px; font-size: 0.75rem; opacity: 0.9; }
.ai-chat-status i {
  width: 7px; height: 7px; border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 8px #4ade80;
}
.ai-chat-clear {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  color: #fff; background: rgba(255, 255, 255, 0.15);
  border: none; border-radius: 50%;
  cursor: pointer; transition: var(--transition);
}
.ai-chat-clear:hover { background: rgba(255, 255, 255, 0.3); }
.ai-chat-close {
  width: 32px; height: 32px; flex: none;
  font-size: 1.5rem; line-height: 1; color: #fff;
  background: rgba(255, 255, 255, 0.15); border: none; border-radius: 50%;
  cursor: pointer; transition: var(--transition);
}
.ai-chat-close:hover { background: rgba(255, 255, 255, 0.3); transform: rotate(90deg); }

.ai-chat-body {
  flex: 1; overflow-y: auto;
  padding: 18px 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.ai-msg {
  max-width: 82%;
  padding: 11px 14px;
  font-size: 0.9rem; line-height: 1.55;
  border-radius: 14px;
  white-space: pre-wrap; word-wrap: break-word;
  animation: aiMsgIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
@keyframes aiMsgIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.ai-msg-bot {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  border-bottom-left-radius: 4px;
}
.ai-msg-user {
  align-self: flex-end;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  border-bottom-right-radius: 4px;
}
/* Code inside bot replies */
.ai-msg pre {
  margin: 8px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--border);
  overflow-x: auto;
  white-space: pre;
}
[data-theme='light'] .ai-msg pre { background: #16182b; }
.ai-msg pre code {
  background: none; border: none; padding: 0;
  color: #a5f3fc;
}
.ai-msg code {
  font-family: var(--font-mono);
  font-size: 0.82em;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 5px;
  padding: 1px 5px;
  color: var(--accent-2);
}
/* Typing indicator */
.ai-typing { display: inline-flex; gap: 4px; align-items: center; }
.ai-typing i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-faint);
  animation: aiTyping 1s ease-in-out infinite;
}
.ai-typing i:nth-child(2) { animation-delay: 0.15s; }
.ai-typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes aiTyping { 0%, 100% { transform: translateY(0); opacity: 0.4; } 50% { transform: translateY(-4px); opacity: 1; } }

.ai-chat-input {
  display: flex; align-items: flex-end; gap: 8px;
  padding: 12px; border-top: 1px solid var(--border);
  background: var(--bg);
}
.ai-chat-input textarea {
  flex: 1;
  max-height: 96px;
  padding: 10px 14px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-sans); font-size: 0.9rem;
  line-height: 1.4; resize: none;
  transition: var(--transition);
}
.ai-chat-input textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
.ai-chat-send {
  width: 42px; height: 42px; flex: none;
  display: grid; place-items: center;
  border: none; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff; cursor: pointer;
  transition: var(--transition);
}
.ai-chat-send:hover { transform: scale(1.08); }
.ai-chat-send:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

@media (max-width: 540px) {
  .ai-fab-dock { right: 18px; bottom: calc(20px + var(--vv-lift, 0px) + env(safe-area-inset-bottom, 0px)); }
  .ai-chat {
    right: 12px; left: 12px; width: auto; max-width: none;
    bottom: calc(88px + var(--vv-lift, 0px) + env(safe-area-inset-bottom, 0px));
  }
  /* bigger tap target for thumbs */
  .ai-speak { width: 25px; height: 25px; vertical-align: -6px; }
  .ai-voice-item { padding: 9px; }
  .ai-voice-item .vplay { width: 28px; height: 28px; }
}

/* ---------- AI voice (text-to-speech) ---------- */
.ai-chat-voice {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  color: #fff; background: rgba(255, 255, 255, 0.15);
  border: none; border-radius: 50%;
  cursor: pointer; transition: var(--transition);
}
.ai-chat-voice:hover { background: rgba(255, 255, 255, 0.3); }
.ai-chat-voice.on { background: rgba(255, 255, 255, 0.42); }

/* Settings sheet that slides down from under the chat header */
.ai-voice-panel {
  position: absolute;
  top: 66px; left: 10px; right: 10px;
  z-index: 6;
  padding: 12px 14px 14px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg-2);
  box-shadow: 0 18px 40px -14px rgba(0, 0, 0, 0.55);
  opacity: 0; visibility: hidden;
  transform: translateY(-10px) scale(0.98);
  transform-origin: top center;
  transition: opacity 0.2s ease, transform 0.25s cubic-bezier(0.34, 1.4, 0.6, 1), visibility 0.25s;
}
.ai-voice-panel.open { opacity: 1; visibility: visible; transform: none; }
.ai-voice-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.ai-voice-top strong { font-size: 0.9rem; }
.ai-voice-x {
  width: 24px; height: 24px; line-height: 1;
  font-size: 1.2rem; color: var(--text-faint);
  background: none; border: none; cursor: pointer; border-radius: 6px;
}
.ai-voice-x:hover { color: var(--text); background: var(--surface); }

.ai-voice-list { max-height: 178px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.ai-voice-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: var(--surface);
  color: var(--text);
  font-size: 0.8rem; text-align: left;
  cursor: pointer; transition: var(--transition);
}
.ai-voice-item:hover { border-color: var(--accent); }
.ai-voice-item.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
.ai-voice-item .vname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ai-voice-item .vtag {
  flex: none; font-family: var(--font-mono); font-size: 0.65rem;
  padding: 2px 5px; border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent-2);
}
.ai-voice-item .vplay {
  flex: none; width: 24px; height: 24px;
  display: grid; place-items: center;
  border: none; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff; cursor: pointer;
  transition: var(--transition);
}
.ai-voice-item .vplay:hover { transform: scale(1.12); }

.ai-voice-rate { display: block; margin-top: 12px; font-size: 0.78rem; color: var(--text-dim); }
.ai-voice-rate span { display: flex; justify-content: space-between; margin-bottom: 4px; }
.ai-voice-rate b { color: var(--accent-2); font-family: var(--font-mono); }
.ai-voice-rate input { width: 100%; accent-color: var(--accent); cursor: pointer; }
.ai-voice-auto { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 0.78rem; color: var(--text-dim); cursor: pointer; }
.ai-voice-auto input { accent-color: var(--accent); cursor: pointer; }
.ai-voice-empty { font-size: 0.78rem; color: var(--text-faint); padding: 6px 2px; }

/* Speaker button that trails the last word of every AI reply */
.ai-speak {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: -3px;
  width: 21px; height: 21px; margin-left: 6px;
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent-2);
  cursor: pointer;
  transition: var(--transition);
}
.ai-speak:hover { color: #fff; background: var(--accent); border-color: var(--accent); transform: scale(1.1); }
.ai-speak .i-stop { display: none; }
.ai-speak.speaking { color: #fff; background: var(--accent); border-color: var(--accent); animation: aiSpeakPulse 1.2s ease-in-out infinite; }
.ai-speak.speaking .i-play { display: none; }
.ai-speak.speaking .i-stop { display: block; }
@keyframes aiSpeakPulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-glow); }
  50%      { box-shadow: 0 0 0 5px transparent; }
}



/* ============================================================
   LIGHT MODE — GALLERY WALL PERSONALITY
   A photo-studio wall: gray backdrop with soft lighting, white
   paper cards hanging from strings with binder clips, gentle
   tilts and real drop shadows. Charcoal + teal + steel blue.
   ============================================================ */

/* Studio wall lighting: bright at the top, soft vignette at the edges */
[data-theme='light'] body::before {
  background:
    radial-gradient(1100px 620px at 50% 0%, rgba(255, 255, 255, 0.85), transparent 62%),
    linear-gradient(180deg, #f0f0f3 0%, #e2e2e6 60%, #d8d8dd 100%);
}

/* FRESHMEN letters in the light outfit: teal -> charcoal -> blue sheen */
[data-theme='light'] .loader-letters b {
  background: linear-gradient(110deg, var(--accent) 0%, #26262b 28%, var(--accent-2) 52%, var(--accent) 78%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  filter: drop-shadow(0 8px 16px rgba(37, 99, 235, 0.28));
  -webkit-box-reflect: below 1px linear-gradient(transparent 58%, rgba(38, 38, 43, 0.10));
}

/* Navbar: a clean white gallery rail floating on the wall */
[data-theme='light'] .navbar {
  top: 12px;
  margin: 0 14px;
  border: 1px solid #e1e1e5;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.22);
}
[data-theme='light'] .logo { color: var(--ink); }
[data-theme='light'] .logo-bracket { color: var(--accent-2); }
[data-theme='light'] .theme-toggle {
  border: 1px solid #dedee2;
  background: #ffffff;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.10);
}
[data-theme='light'] .theme-toggle:hover { border-color: var(--accent-2); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15); }
[data-theme='light'] .bg-menu,
[data-theme='light'] .music-menu {
  border: 1px solid #e1e1e5;
  box-shadow: 0 18px 36px -10px rgba(0, 0, 0, 0.28);
}
[data-theme='light'] .now-playing.show { border-color: #e1e1e5; box-shadow: 0 8px 18px rgba(0, 0, 0, 0.14); }

/* ---- The hanging papers -------------------------------------------- */
/* Every showcase card is a sheet of paper clipped to a string on the wall */
[data-theme='light'] .skill-card,
[data-theme='light'] .pv-card,
[data-theme='light'] .cert-card,
[data-theme='light'] .about-card,
[data-theme='light'] .project-card,
[data-theme='light'] .projects-soon,
[data-theme='light'] .contact-form {
  background: #ffffff;
  border: 1px solid #e5e5e9;
  border-radius: 3px;                /* paper, not app-card */
  box-shadow:
    0 14px 26px -10px rgba(0, 0, 0, 0.30),
    0 3px 8px rgba(0, 0, 0, 0.08);
  backdrop-filter: none;
  position: relative;
  overflow: visible;                 /* let the clips poke out the top */
  margin-top: 30px;                  /* room for strings + clips */
}
/* Two binder clips on strings at the top of each sheet */
[data-theme='light'] .skill-card::before,
[data-theme='light'] .pv-card::before,
[data-theme='light'] .cert-card::before,
[data-theme='light'] .about-card::before,
[data-theme='light'] .project-card::before,
[data-theme='light'] .projects-soon::before,
[data-theme='light'] .contact-form::before,
[data-theme='light'] .skill-card::after,
[data-theme='light'] .pv-card::after,
[data-theme='light'] .cert-card::after,
[data-theme='light'] .about-card::after,
[data-theme='light'] .project-card::after,
[data-theme='light'] .projects-soon::after,
[data-theme='light'] .contact-form::after {
  content: '';
  position: absolute;
  top: -36px;
  width: 16px;
  height: 44px;
  pointer-events: none;
  z-index: 3;
  background:
    /* the string */
    linear-gradient(180deg, #a9a9af, #8d8d93) top center / 1.5px 31px no-repeat,
    /* clip highlight lip */
    linear-gradient(180deg, #6b6b72, #6b6b72) center bottom 9px / 10px 2px no-repeat,
    /* the clip body */
    linear-gradient(180deg, #3c3c43 0%, #1f1f24 100%) bottom center / 16px 13px no-repeat;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.35));
}
[data-theme='light'] .skill-card::before,
[data-theme='light'] .pv-card::before,
[data-theme='light'] .cert-card::before,
[data-theme='light'] .about-card::before,
[data-theme='light'] .project-card::before,
[data-theme='light'] .projects-soon::before,
[data-theme='light'] .contact-form::before { left: 14%; }
[data-theme='light'] .skill-card::after,
[data-theme='light'] .pv-card::after,
[data-theme='light'] .cert-card::after,
[data-theme='light'] .about-card::after,
[data-theme='light'] .project-card::after,
[data-theme='light'] .projects-soon::after,
[data-theme='light'] .contact-form::after { right: 14%; }

/* Papers hang with a slight natural tilt, alternating direction */
[data-theme='light'] .skills-grid .skill-card:nth-child(odd),
[data-theme='light'] .projects-grid .pv-card:nth-child(odd),
[data-theme='light'] .certs-grid .cert-card:nth-child(odd):not(.is-hidden) { transform: rotate(-0.9deg); }
[data-theme='light'] .skills-grid .skill-card:nth-child(even),
[data-theme='light'] .projects-grid .pv-card:nth-child(even),
[data-theme='light'] .certs-grid .cert-card:nth-child(even):not(.is-hidden) { transform: rotate(0.9deg); }
/* On hover the paper straightens and lifts toward you */
[data-theme='light'] .skill-card:hover,
[data-theme='light'] .pv-card:hover,
[data-theme='light'] .cert-card:hover,
[data-theme='light'] .project-card:hover {
  transform: rotate(0deg) translateY(-6px);
  border-color: #dcdce0;
  box-shadow:
    0 26px 44px -12px rgba(0, 0, 0, 0.34),
    0 6px 14px rgba(0, 0, 0, 0.10);
}

/* Section headers: charcoal "label tape" number, thin gallery rule */
[data-theme='light'] .section-num {
  background: #26262b;
  color: #ffffff;
  padding: 3px 12px;
  border-radius: 2px;
  transform: rotate(-2deg);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.22);
}
[data-theme='light'] .section-line { background: #cfcfd4; }

/* Buttons: paper buttons with soft shadows; primary is solid steel blue */
[data-theme='light'] .btn-primary {
  background: var(--accent-2);
  border-radius: 8px;
  box-shadow: 0 10px 20px -6px rgba(37, 99, 235, 0.45);
}
[data-theme='light'] .btn-primary:hover { box-shadow: 0 14px 26px -6px rgba(37, 99, 235, 0.55); }
[data-theme='light'] .btn-ghost {
  background: #ffffff;
  border: 1px solid #d8d8dd;
  border-radius: 8px;
  color: var(--ink);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.10);
}
[data-theme='light'] .btn-ghost:hover { border-color: var(--accent-2); color: var(--accent-2); }
[data-theme='light'] .btn-cv {
  background: #ffffff;
  border: 1px solid #d8d8dd;
  border-radius: 8px;
  color: var(--accent);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.10);
}
[data-theme='light'] .btn-cv:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
[data-theme='light'] .btn-coffee { border-radius: 8px; box-shadow: 0 10px 20px -6px rgba(234, 88, 12, 0.4); }
[data-theme='light'] .social-icon {
  background: #ffffff;
  border: 1px solid #d8d8dd;
  color: var(--ink);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.10);
}
[data-theme='light'] .social-icon:hover { color: var(--accent-2); border-color: var(--accent-2); }

/* Skill cards: charcoal clip-metal icons, gray paper tags */
[data-theme='light'] .skill-icon {
  background: #26262b;
  color: #ffffff;
  border-radius: 6px;
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.22);
}
[data-theme='light'] .skill-tags span,
[data-theme='light'] .project-tags span {
  background: #f4f4f6;
  border: 1px solid #dcdce0;
  border-radius: 5px;
  color: #44444b;
}
[data-theme='light'] .skill-more { color: var(--accent-2); }

/* Certificates: filter chips like gallery tags */
[data-theme='light'] .cert-filter button {
  background: #ffffff;
  border: 1px solid #d8d8dd;
  color: var(--ink);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.08);
}
[data-theme='light'] .cert-filter button.active {
  background: #26262b;
  border-color: #26262b;
  color: #ffffff;
}
[data-theme='light'] .cert-thumb { border-bottom: 1px solid #e5e5e9; }
[data-theme='light'] .cert-link,
[data-theme='light'] .pv-view,
[data-theme='light'] .pv-visit {
  background: #ffffff;
  border: 1px solid #d8d8dd;
  border-radius: 6px;
  color: var(--accent-2);
}
[data-theme='light'] .pv-watch { border-radius: 6px; background: var(--accent-2); box-shadow: 0 6px 14px -4px rgba(37, 99, 235, 0.5); }

/* Hero: the code window is a framed dark print; photo gets a white mat */
[data-theme='light'] .code-window {
  background: #212126;
  border: 8px solid #ffffff;
  border-radius: 4px;
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.38);
  backdrop-filter: none;
}
[data-theme='light'] .code-window-bar { background: rgba(255, 255, 255, 0.06); border-bottom: 1px solid rgba(255, 255, 255, 0.10); }
[data-theme='light'] .code-window-title { color: #9a9aa2; }
[data-theme='light'] .tok-prop { color: #93c5fd; }   /* was pink — now sky blue */
[data-theme='light'] .tok-key { color: #7dd3fc; }
[data-theme='light'] .hero-back {
  border: 8px solid #ffffff;
  border-radius: 4px;
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.38);
}
[data-theme='light'] .avatar-face { box-shadow: inset 0 0 0 4px #ffffff; }

/* Contact form: a hanging paper sheet with clean inputs */
[data-theme='light'] .contact-form { padding: 28px; }
[data-theme='light'] .form-group input,
[data-theme='light'] .form-group textarea {
  background: #fafafa;
  border: 1px solid #d8d8dd;
  border-radius: 6px;
}
[data-theme='light'] .form-group input:focus,
[data-theme='light'] .form-group textarea:focus {
  border-color: var(--accent-2);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

/* Modals & popups: white prints under gallery lighting */
[data-theme='light'] .proj-box,
[data-theme='light'] .qr-box,
[data-theme='light'] .cvgen-box,
[data-theme='light'] .live-box {
  border: 1px solid #e1e1e5;
  border-radius: 8px;
  box-shadow: 0 30px 60px -18px rgba(0, 0, 0, 0.45);
}
[data-theme='light'] .qr-card {
  background: #ffffff;
  border: 1px solid #e5e5e9;
  border-radius: 4px;
  box-shadow: 0 10px 20px -8px rgba(0, 0, 0, 0.25);
}

/* AI assistant in the gallery outfit */
[data-theme='light'] .ai-fab { box-shadow: 0 14px 28px -8px rgba(37, 99, 235, 0.5), 0 4px 12px rgba(0, 0, 0, 0.18); }
[data-theme='light'] .ai-chat { border: 1px solid #e1e1e5; box-shadow: 0 30px 60px -18px rgba(0, 0, 0, 0.4); }
[data-theme='light'] .ai-msg-bot { background: #f4f4f6; border: 1px solid #e1e1e5; }
[data-theme='light'] .ai-chat-input textarea { background: #fafafa; border: 1px solid #d8d8dd; }

/* Footer: the bottom of the wall */
[data-theme='light'] .footer { border-top: 1px solid #d4d4d9; }

/* ---- About card: a framed portrait on the wall ----
   Charcoal frame + white mat, hung from a nail by a V-string —
   different hardware than the clipped paper sheets around it. */
[data-theme='light'] .about-card {
  border: 12px solid #26262b;
  border-radius: 3px;
  background: #ffffff;
  margin-top: 52px;
  box-shadow:
    0 26px 48px -14px rgba(0, 0, 0, 0.42),
    0 6px 14px rgba(0, 0, 0, 0.12),
    inset 0 0 0 1px #e3e3e7;            /* thin mat opening line */
}
/* The nail head at the apex */
[data-theme='light'] .about-card::before {
  content: '';
  top: -48px;
  left: 50%;
  right: auto;
  width: 13px;
  height: 13px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #77777e, #232328 72%);
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.35));
}
/* The V-string from the frame's top corners up to the nail */
[data-theme='light'] .about-card::after {
  content: '';
  top: -42px;
  left: 0;
  right: auto;
  width: 100%;
  height: 42px;
  border-radius: 0;
  filter: none;
  background:
    linear-gradient(to top right,
      transparent calc(50% - 1px), #96969c calc(50% - 1px),
      #96969c calc(50% + 1px), transparent calc(50% + 1px))
      left top / 50.2% 100% no-repeat,
    linear-gradient(to top left,
      transparent calc(50% - 1px), #96969c calc(50% - 1px),
      #96969c calc(50% + 1px), transparent calc(50% + 1px))
      right top / 50.2% 100% no-repeat;
}
/* Inside the frame: gallery-matted portrait */
[data-theme='light'] .about-card .avatar {
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
}
[data-theme='light'] .about-card .stat { border-top: 1px solid #e3e3e7; }
[data-theme='light'] .about-card .stat-num { color: var(--accent); }

/* ---- About card v2: a real hanging picture frame ----
   Beveled molding, picture wire to a nail, natural tilt that
   straightens on hover, and an engraved brass name plate. */
[data-theme='light'] .about-card {
  border: 14px solid #232328;
  transform: rotate(-1.4deg);            /* hangs naturally, not perfectly level */
  transform-origin: 50% -44px;           /* pivots from the nail */
  transition: transform 0.5s cubic-bezier(0.34, 1.4, 0.64, 1);
  box-shadow:
    0 0 0 1px #4a4a52,                   /* outer molding highlight */
    0 34px 54px -18px rgba(0, 0, 0, 0.55),  /* wall shadow */
    0 10px 18px rgba(0, 0, 0, 0.16),
    inset 0 0 0 1px #0d0d11,             /* inner frame seam */
    inset 0 0 0 3px #dfdfe3;             /* mat bevel */
}
[data-theme='light'] .about-card:hover { transform: rotate(0deg); }
/* Picture wire: attaches behind the frame's top edge, not at the corners */
[data-theme='light'] .about-card::after {
  left: 13%;
  width: 74%;
  height: 38px;
  top: -38px;
}
/* Engraved brass name plate on the mat */
[data-theme='light'] .about-card .about-stats::after {
  content: 'VINCENT ENIMEDEZ';
  position: absolute;
  left: 50%;
  bottom: 9px;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 2.5px;
  white-space: nowrap;
  color: #5f4d1e;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
  background: linear-gradient(180deg, #e9cd7e, #cfa951 55%, #b28e40);
  border: 1px solid #997b34;
  border-radius: 3px;
  padding: 3px 12px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.55);
}
[data-theme='light'] .about-card { padding-bottom: 52px; }

/* ---- Hero code window in light mode: a clean light editor print ----
   (Replaces the dark terminal, whose punctuation was invisible on light.) */
[data-theme='light'] .code-window {
  background: #ffffff;
  border: 1px solid #e1e1e5;
  border-radius: 10px;
  box-shadow:
    0 24px 44px -14px rgba(0, 0, 0, 0.30),
    0 4px 12px rgba(0, 0, 0, 0.08);
}
[data-theme='light'] .code-window-bar {
  background: #f3f3f5;
  border-bottom: 1px solid #e5e5e9;
}
[data-theme='light'] .code-window-title { color: #6f6f76; }
[data-theme='light'] .code-window-body { color: #3f3f46; }   /* braces, colons, commas readable */
[data-theme='light'] .tok-key  { color: #2563eb; }  /* const        -> steel blue  */
[data-theme='light'] .tok-var  { color: #0f766e; }  /* vincent      -> deep teal   */
[data-theme='light'] .tok-prop { color: #1e40af; }  /* name, role.. -> navy        */
[data-theme='light'] .tok-str  { color: #15803d; }  /* strings      -> green       */
[data-theme='light'] .tok-bool { color: #b45309; }  /* true         -> amber       */
[data-theme='light'] .tok-num  { color: #b45309; }  /* Infinity     -> amber       */

/* <VE/> brackets turn green once Drive data is confirmed flowing */
.logo-bracket { transition: color 0.7s ease, text-shadow 0.7s ease; }
.logo-bracket.online {
  color: #22c55e;
  text-shadow: 0 0 10px rgba(34, 197, 94, 0.55);
}
[data-theme='light'] .logo-bracket.online {
  color: #16a34a;
  text-shadow: 0 0 8px rgba(22, 163, 74, 0.35);
}

/* ---- Light mode: certificates ride a zipline ----
   A steel wire runs above the certificates; each one hangs from its
   clips and slides gently along the wire. Hovering a certificate
   stops it so you can read it. (The wire is drawn per-card and
   counter-animated with the exact inverse motion, so it stays
   visually pinned while the paper slides along it.) */
@keyframes zipCard {
  0%, 100% { transform: translateX(-18px); }
  50%      { transform: translateX(18px); }
}
@keyframes zipWire {
  0%, 100% { transform: translateX(18px); }
  50%      { transform: translateX(-18px); }
}
[data-theme='light'] .certs-grid .cert-card {
  animation: zipCard 7s ease-in-out infinite;
}
[data-theme='light'] .certs-grid .cert-card .cert-body::after {
  content: '';
  position: absolute;
  top: -31px;                 /* crosses the tops of the clip strings */
  left: -30px;
  right: -30px;               /* reaches into the grid gaps so neighboring
                                 segments join into one continuous wire */
  height: 3px;
  z-index: 2;                 /* under the clips (3), over the wall */
  border-radius: 2px;
  background: linear-gradient(180deg, #bcbcc2, #8d8d93);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
  pointer-events: none;
  animation: zipWire 7s ease-in-out infinite;
}
/* Vary speed and phase so each certificate travels on its own rhythm —
   a card and its own wire always share identical timing, keeping the
   inverse motion perfectly in sync */
[data-theme='light'] .certs-grid .cert-card:nth-child(even),
[data-theme='light'] .certs-grid .cert-card:nth-child(even) .cert-body::after {
  animation-duration: 8.6s;
  animation-delay: -2.7s;
}
[data-theme='light'] .certs-grid .cert-card:nth-child(3n),
[data-theme='light'] .certs-grid .cert-card:nth-child(3n) .cert-body::after {
  animation-duration: 9.8s;
  animation-delay: -4.9s;
}
/* Cursor on a certificate: it stops sliding */
[data-theme='light'] .certs-grid .cert-card:hover,
[data-theme='light'] .certs-grid .cert-card:hover .cert-body::after {
  animation-play-state: paused;
}
