/* ============================================================
   3D Portfolio — stylesheet
   Accent colours are injected from config.js as CSS variables
   (--accent, --accent-2); everything else can be tweaked here.
   ============================================================ */

:root {
  /* "Cobalt & Amber" — deep cobalt night, amber lead, cobalt-blue second */
  --bg: #070c1a;
  --bg-soft: #0e1526;
  --card: rgba(255, 255, 255, 0.04);
  --card-border: rgba(255, 255, 255, 0.08);
  --text: #e9edf7;
  --text-dim: #8a94ad;
  --accent: #f2b544;      /* overridden from config.js */
  --accent-2: #6c8cff;    /* overridden from config.js */
  /* Channel-only copies of the two accents, so every translucent glow and
     gradient below derives from the accent instead of hardcoding it.
     main.js recomputes these from config.js on load, which means changing
     the accent there now recolours the tints too. */
  --accent-rgb: 242 181 68;
  --accent-2-rgb: 108 140 255;
  --bg-rgb: 7 12 26;      /* channel copy of --bg, for the navbar glass */
  /* Three type roles. Display and body are the same family today, but
     headings read through --font-display so swapping in a separate
     display face later is a one-line change. */
  --font-display: "Bricolage Grotesque", system-ui, sans-serif;
  --font-main: "Bricolage Grotesque", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --nav-h: 68px;
  --radius: 14px;
}

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

html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); }

body {
  font-family: var(--font-main);
  background: var(--bg);
  color: var(--text);
  line-height: 1.65;
  overflow-x: hidden;
}

.mono { font-family: var(--font-mono); }

/* Titles read through the display role. Identical to --font-main today,
   so this changes nothing visually — it exists so a separate display
   face can be introduced without hunting down every heading.
   Deliberately excludes .stat-value, .chip, .nav-logo and .project-tags,
   which belong to the mono role. */
.hero-name,
.section-title,
.subsection-title,
.tech-head h3,
.project-title,
.pub-title,
.cert-name,
.email-card h3 {
  font-family: var(--font-display);
}

.container { width: min(1120px, 92%); margin-inline: auto; }

::selection { background: var(--accent); color: var(--bg); }

/* Subtle glow blobs behind content */
body::before,
body::after {
  content: "";
  position: fixed;
  z-index: -2;
  width: 55vmax; height: 55vmax;
  border-radius: 50%;
  filter: blur(120px);
  opacity: 0.13;
  pointer-events: none;
}
body::before { background: var(--accent);   top: -20vmax; right: -18vmax; }
body::after  { background: var(--accent-2); bottom: -25vmax; left: -18vmax; }

/* ---------- Preloader ---------- */
#preloader {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center;
  background: var(--bg);
  transition: opacity 0.5s ease, visibility 0.5s ease;
}
#preloader.done { opacity: 0; visibility: hidden; }

/* "Neural Boot" preloader: particles assemble into <MSB/> — see the
   inline script right after #preloader in index.html for the logic */
#boot-stage {
  display: flex; flex-direction: column; align-items: center; gap: 1.4rem;
}
#boot-glyph { position: relative; }
#boot-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.boot-dot {
  position: absolute; left: 0; top: 0;
  width: 7px; height: 7px;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
}
#boot-caption {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0;
  transition: opacity 0.4s ease;
}
#boot-progress {
  width: 200px;
  height: 3px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.3s ease;
}
#boot-progress-fill {
  width: 0%;
  height: 100%;
  border-radius: 3px;
  background: var(--accent);
  box-shadow: 0 0 10px 1px var(--accent);
}

/* ---------- 3D canvas ---------- */
#bg-canvas {
  position: fixed; inset: 0;
  z-index: -1;
  display: block;
  opacity: 0;
  transition: opacity 1.2s ease;
}
#bg-canvas.on { opacity: 1; }

/* ---------- Navbar ---------- */
.navbar {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 50;
  height: var(--nav-h);
  transition: box-shadow 0.3s ease;
}
/* The glass blur lives on a pseudo-element: backdrop-filter on the
   navbar itself would turn it into the containing block for the
   fixed-position mobile menu and break its placement when scrolled. */
.navbar::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: rgb(var(--bg-rgb) / 0.75);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  opacity: 0;
  transition: opacity 0.3s ease;
}
.navbar.scrolled { box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35); }
.navbar.scrolled::before { opacity: 1; }
.nav-inner {
  height: 100%;
  display: flex; align-items: center; justify-content: space-between;
}
.nav-logo {
  font-family: var(--font-mono);
  font-weight: 600; font-size: 1.15rem;
  color: var(--accent);
  text-decoration: none;
  letter-spacing: 0.5px;
}
.nav-links {
  display: flex; align-items: center; gap: 1.8rem;
  list-style: none;
}
.nav-link {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.95rem;
  position: relative;
  transition: color 0.25s ease;
}
.nav-link::after {
  content: "";
  position: absolute; left: 0; bottom: -5px;
  width: 0; height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transition: width 0.25s ease;
}
.nav-link:hover, .nav-link.active { color: var(--text); }
.nav-link:hover::after, .nav-link.active::after { width: 100%; }
.nav-resume {
  border: 1px solid var(--accent);
  color: var(--accent);
  padding: 0.45rem 1.1rem;
  border-radius: 8px;
  transition: background 0.25s ease, color 0.25s ease;
}
.nav-resume::after { display: none; }
.nav-resume:hover { background: rgb(var(--accent-rgb) / 0.12); color: var(--accent); }

.nav-toggle {
  display: none;
  flex-direction: column; gap: 5px;
  background: none; border: none; cursor: pointer;
  padding: 6px;
  z-index: 60;
}
.nav-toggle span {
  width: 24px; height: 2px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---------- Hero ---------- */
.hero {
  min-height: 100svh;
  display: flex; align-items: center;
  position: relative;
  padding-top: var(--nav-h);
}
.hero-hello { color: var(--accent); font-size: 1rem; margin-bottom: 1rem; }
.hero-name {
  font-size: clamp(2.4rem, 7vw, 4.6rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -1px;
  margin-bottom: 0.6rem;
}
/* The white-to-amber ramp lives on an inline span, not the h1, so that
   box-decoration-break can restart it on every line. Painted on the block
   instead, the ramp is measured across the whole box: once the name wraps
   on a phone, the short second line sits at the white end and never
   reaches amber. Cloning per line makes every line read white-to-amber,
   exactly as it does on one line on desktop. Browsers without
   box-decoration-break fall back to a single ramp, which is still
   white-to-amber. */
.hero-name > span {
  background: linear-gradient(90deg, var(--text) 25%, var(--accent) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.hero-role {
  font-size: clamp(1.25rem, 3.4vw, 2rem);
  font-weight: 500;
  color: var(--text-dim);
  min-height: 1.4em;
  margin-bottom: 1.4rem;
}
.hero-role .mono { color: var(--accent); }
#typed { color: var(--text); }
.type-caret {
  color: var(--accent);
  animation: blink 1s step-end infinite;
  font-weight: 400;
}
@keyframes blink { 50% { opacity: 0; } }
.hero-tagline {
  max-width: 560px;
  color: var(--text-dim);
  font-size: 1.08rem;
  margin-bottom: 2.2rem;
}
.hero-cta { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 2.4rem; }

.scroll-hint {
  position: absolute; bottom: 28px; left: 50%;
  transform: translateX(-50%);
  width: 26px; height: 42px;
  border: 2px solid var(--text-dim);
  border-radius: 14px;
  opacity: 0.7;
}
.scroll-hint span {
  position: absolute; top: 7px; left: 50%;
  width: 4px; height: 8px;
  margin-left: -2px;
  background: var(--accent);
  border-radius: 2px;
  animation: scrollhint 1.8s ease-in-out infinite;
}
@keyframes scrollhint {
  0%   { transform: translateY(0);    opacity: 1; }
  70%  { transform: translateY(14px); opacity: 0; }
  100% { transform: translateY(0);    opacity: 0; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  padding: 0.8rem 1.7rem;
  border-radius: 10px;
  font-weight: 600;
  font-size: 0.97rem;
  text-decoration: none;
  transition: transform 0.22s ease, box-shadow 0.22s ease, background 0.22s ease;
}
.btn-solid {
  background: var(--accent);
  color: var(--bg);
}
.btn-solid:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 30px rgb(var(--accent-rgb) / 0.35);
}
.btn-ghost {
  border: 1px solid var(--accent);
  color: var(--accent);
}
.btn-ghost:hover {
  background: rgb(var(--accent-rgb) / 0.1);
  transform: translateY(-3px);
}
.btn-lg { padding: 1rem 2.4rem; font-size: 1.05rem; }

/* ---------- Socials ---------- */
.socials { display: flex; gap: 0.9rem; flex-wrap: wrap; }
.socials a {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 12px;
  border: 1px solid var(--card-border);
  background: var(--card);
  color: var(--text-dim);
  transition: transform 0.22s ease, color 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease;
}
.socials a:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-4px);
  box-shadow: 0 10px 24px rgb(var(--accent-rgb) / 0.18);
}
.socials svg { width: 20px; height: 20px; fill: currentColor; }

/* ---------- Sections ---------- */
.section { padding: clamp(4.5rem, 10vh, 7.5rem) 0; position: relative; }
.section-title {
  font-size: clamp(1.6rem, 4vw, 2.2rem);
  font-weight: 700;
  margin-bottom: 2.6rem;
  display: flex; align-items: baseline; gap: 0.7rem;
}
.section-title.centered { justify-content: center; }
.section-index { color: var(--accent); font-size: 0.75em; font-weight: 500; }
.section-title::after {
  content: "";
  flex: 1;
  max-width: 260px;
  height: 1px;
  background: linear-gradient(90deg, var(--card-border), transparent);
  align-self: center;
}
.section-title.centered::after { display: none; }

/* ---------- About ---------- */
.about-grid {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 3rem;
  align-items: start;
}
.photo-frame {
  position: relative;
  animation: floaty 5.5s ease-in-out infinite;
  border-radius: 50%;
}
/* soft pulsing glow behind the circular photo */
.photo-frame::before {
  content: "";
  position: absolute; inset: 6%;
  border-radius: 50%;
  background: rgb(var(--accent-rgb) / 0.34);
  filter: blur(32px);
  z-index: -1;
  animation: glowpulse 5.5s ease-in-out infinite;
}
/* glowing gradient ring that lights up on hover */
.photo-frame::after {
  content: "";
  position: absolute; inset: -6px;
  border-radius: 50%;
  padding: 2px;
  background: var(--accent);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.about-photo:hover .photo-frame::after {
  opacity: 1;
  animation: ringspin 4s linear infinite;
}
.about-photo:hover .photo-frame {
  filter: drop-shadow(0 0 26px rgb(var(--accent-rgb) / 0.45));
}
.photo-frame img {
  display: block; width: 100%; height: auto;
  border-radius: 50%;
  transition: transform 0.45s ease;
}
.about-photo:hover .photo-frame img { transform: scale(1.03); }
@keyframes ringspin { to { transform: rotate(360deg); } }
@keyframes floaty {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-14px); }
}
@keyframes glowpulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}
.about-text p { color: var(--text-dim); margin-bottom: 1.1rem; font-size: 1.03rem; }
.about-text p strong { color: var(--text); }

.stats-grid {
  margin-top: 3rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.1rem;
}
.stat-card {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1.4rem 1.2rem;
  text-align: center;
  transition: transform 0.25s ease, border-color 0.25s ease;
}
.stat-card:hover { transform: translateY(-5px); border-color: var(--accent); }
.stat-value {
  font-family: var(--font-mono);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--accent);
}
.stat-label { color: var(--text-dim); font-size: 0.9rem; margin-top: 0.3rem; }

/* ---------- Skills ---------- */
.tech-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1.2rem;
}
.tech-card {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1.5rem;
  transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}
.tech-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
}
.tech-head {
  display: flex; align-items: center; gap: 0.8rem;
  margin-bottom: 1.1rem;
}
.tech-head h3 { font-size: 1.05rem; font-weight: 600; }
.tech-icon {
  flex: none;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: rgb(var(--accent-rgb) / 0.14);
  border: 1px solid var(--card-border);
}
.tech-icon svg {
  width: 22px; height: 22px;
  stroke: var(--accent); fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.subsection-title {
  margin: 3rem 0 1.2rem;
  text-align: center;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text-dim);
}
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--card-border);
  color: var(--text-dim);
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.chip:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-2px); }

.soft-skills {
  display: flex; flex-wrap: wrap; gap: 0.6rem;
  justify-content: center;
}
.soft-skills .chip { border-color: rgb(var(--accent-2-rgb) / 0.35); }
.soft-skills .chip:hover { color: var(--accent-2); border-color: var(--accent-2); }

/* ---------- Projects ---------- */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 1.4rem;
}
.project-card {
  display: flex; flex-direction: column;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1.6rem;
  text-decoration: none;
  color: inherit;
  transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
  transform-style: preserve-3d;
  will-change: transform;
}
.project-card:hover {
  border-color: var(--accent);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.4);
}
.project-top {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1.1rem;
}
.project-icon {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 12px;
  background: rgb(var(--accent-rgb) / 0.14);
  border: 1px solid var(--card-border);
}
.project-icon svg { width: 24px; height: 24px; stroke: var(--accent); fill: none; stroke-width: 1.8; }
.project-ext svg { width: 20px; height: 20px; stroke: var(--text-dim); fill: none; stroke-width: 2; transition: stroke 0.2s ease, transform 0.2s ease; }
.project-card:hover .project-ext svg { stroke: var(--accent); transform: translate(2px, -2px); }
.project-title { font-size: 1.15rem; font-weight: 600; margin-bottom: 0.5rem; }
.project-desc { color: var(--text-dim); font-size: 0.95rem; flex: 1; margin-bottom: 1.1rem; }
.project-tags { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.project-tags span {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  color: var(--accent);
  background: rgb(var(--accent-rgb) / 0.08);
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
}

/* ---------- Publications ---------- */
.pub-list { display: flex; flex-direction: column; gap: 1.2rem; }
.pub-card {
  display: flex; gap: 1.3rem;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1.6rem;
  transition: transform 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}
.pub-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.38);
}
/* the peer-reviewed paper gets a highlighted treatment */
.pub-card.featured {
  border-color: rgb(var(--accent-rgb) / 0.4);
  background: rgb(var(--accent-rgb) / 0.07);
}
.pub-icon {
  flex: none;
  width: 52px; height: 52px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: rgb(var(--accent-rgb) / 0.16);
  border: 1px solid var(--card-border);
}
.pub-icon svg {
  width: 26px; height: 26px;
  stroke: var(--accent); fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.pub-card.featured .pub-icon svg { stroke: var(--accent-2); }
.pub-body { flex: 1; min-width: 0; }
.pub-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1.2rem;
  margin-bottom: 0.5rem;
}
.pub-title { font-size: 1.1rem; font-weight: 600; line-height: 1.4; }
.pub-btn {
  flex: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.5rem 0.95rem;
  border: 1px solid var(--accent);
  border-radius: 9px;
  color: var(--accent);
  font-size: 0.85rem; font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.22s ease, transform 0.22s ease;
}
.pub-btn:hover { background: rgb(var(--accent-rgb) / 0.12); transform: translateY(-2px); }
.pub-btn svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2.2; }
.pub-venue { color: var(--text); font-size: 0.9rem; opacity: 0.85; }
.pub-meta { color: var(--text-dim); font-size: 0.8rem; margin-top: 0.15rem; }
.pub-desc { color: var(--text-dim); font-size: 0.96rem; margin: 0.7rem 0 0.9rem; }

/* ---------- Certifications ---------- */
.cert-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.1rem;
}
.cert-card {
  position: relative;
  display: flex; align-items: flex-start; gap: 1rem;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 1.3rem;
  color: inherit; text-decoration: none;
  transition: transform 0.25s ease, border-color 0.25s ease;
}
a.cert-card:hover { transform: translateY(-4px); border-color: var(--accent); }
.cert-icon {
  flex: none;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: rgb(var(--accent-rgb) / 0.14);
  border: 1px solid var(--card-border);
}
.cert-icon svg {
  width: 22px; height: 22px;
  stroke: var(--accent); fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.cert-name { font-size: 1rem; font-weight: 600; line-height: 1.4; }
.cert-issuer { color: var(--text-dim); font-size: 0.9rem; margin-top: 0.2rem; }
.cert-year { color: var(--accent); font-size: 0.8rem; margin-top: 0.25rem; }
.cert-ext { position: absolute; top: 1rem; right: 1rem; }
.cert-ext svg { width: 17px; height: 17px; stroke: var(--text-dim); fill: none; stroke-width: 2; }
a.cert-card:hover .cert-ext svg { stroke: var(--accent); }

/* ---------- Contact ---------- */
.contact-inner {
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.contact-blurb { max-width: 540px; color: var(--text-dim); margin-bottom: 2rem; font-size: 1.05rem; }
#contact-email { margin-bottom: 2.2rem; }
.contact-location { margin-top: 2rem; color: var(--text-dim); font-size: 0.88rem; }

/* ---------- Email chooser modal ---------- */
.email-modal {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  padding: 1rem;
  background: rgba(6, 9, 18, 0.72);
  opacity: 0; visibility: hidden;
  transition: opacity 0.25s ease, visibility 0.25s ease;
}
.email-modal.open { opacity: 1; visibility: visible; }
.email-card {
  position: relative;
  width: min(380px, 94vw);
  background: var(--bg-soft);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  padding: 1.9rem 1.6rem 1.6rem;
  text-align: center;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
  transform: translateY(16px) scale(0.97);
  transition: transform 0.25s ease;
}
.email-modal.open .email-card { transform: none; }
.email-card h3 { font-size: 1.25rem; margin-bottom: 0.35rem; }
.email-card .email-addr {
  font-family: var(--font-mono);
  font-size: 0.9rem;
  color: var(--accent);
  margin-bottom: 1.4rem;
  word-break: break-all;
}
.email-opts { display: flex; flex-direction: column; gap: 0.7rem; }
.email-opt {
  display: flex; align-items: center; gap: 0.85rem;
  width: 100%;
  padding: 0.85rem 1.05rem;
  border-radius: 10px;
  background: var(--card);
  border: 1px solid var(--card-border);
  color: var(--text);
  font: inherit; font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.email-opt:hover { border-color: var(--accent); transform: translateY(-2px); }
.email-opt .opt-ic { font-size: 1.15rem; line-height: 1; }
.email-close {
  position: absolute; top: 0.7rem; right: 0.7rem;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  background: none; border: none;
  color: var(--text-dim);
  font-size: 1.15rem;
  cursor: pointer;
  border-radius: 8px;
  transition: color 0.2s ease, background 0.2s ease;
}
.email-close:hover { color: var(--text); background: var(--card); }

/* ---------- Footer ---------- */
.footer {
  padding: 2rem 0 2.4rem;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.85rem;
  border-top: 1px solid var(--card-border);
}
.footer a { color: var(--accent); text-decoration: none; }

/* ---------- Reveal-on-scroll ---------- */
.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.reveal.visible { opacity: 1; transform: none; }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  /* The nav collapses here rather than at 720px: with Certifications
     added, eight items no longer fit on one line below ~790px. */
  .nav-toggle { display: flex; }
  .nav-links {
    position: fixed; top: 0; right: 0; bottom: 0; left: 32%;
    height: 100dvh;
    flex-direction: column; justify-content: center;
    gap: 2.2rem;
    background: var(--bg-soft);
    transform: translateX(110%);
    transition: transform 0.35s ease;
    box-shadow: -20px 0 50px rgba(0, 0, 0, 0.4);
  }
  .nav-links.open { transform: translateX(0); }
  .nav-link { font-size: 1.15rem; }

  .about-grid { grid-template-columns: 1fr; }
  .about-photo { max-width: 280px; margin-inline: auto; }
  .tech-grid { grid-template-columns: 1fr; }
  .pub-card { flex-direction: column; gap: 1rem; }
  .pub-head { flex-direction: column; gap: 0.8rem; }
  .pub-btn { align-self: flex-start; }
}

@media (max-width: 720px) {
  .hero-cta { flex-direction: column; align-items: center; width: 100%; }
  .hero-cta .btn { width: min(230px, 72%); text-align: center; }
  .hero .socials { justify-content: center; width: 100%; }
}

/* ---------- Custom cursor: "Liquid Blob" ----------
   A droplet that squashes and stretches along its heading, and splits
   into four brackets that clamp whatever it hovers. Desktop-only: the
   .blob-cursor class is added from main.js and only on a fine pointer
   with motion allowed, so touch and reduced-motion keep the native
   cursor. Everything here is scoped to that class — remove the class
   and the site is exactly as it was. */
#blob-cursor {
  position: fixed;
  inset: 0;
  z-index: 200;        /* above the preloader (100) and the nav (50) */
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
}
#blob-cursor.on { opacity: 1; }

/* `.blob-cursor *` beats every single-class cursor:pointer rule in this
   file, so the native pointer is hidden without needing !important */
body.blob-cursor,
body.blob-cursor * { cursor: none; }

.blob-body,
.blob-drop {
  position: absolute;
  left: 0;
  top: 0;
  will-change: transform;
}
.blob-body i,
.blob-drop i {
  display: block;
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50%;
}
.blob-body i {
  width: 26px;
  height: 26px;
  background: radial-gradient(circle at 35% 32%, #ffe3a3, var(--accent) 45%, var(--accent-2));
  box-shadow: 0 0 18px rgb(var(--accent-rgb) / 0.5);
}
.blob-drop i {
  width: 9px;
  height: 9px;
  background: var(--accent-2);
  opacity: 0.65;
}

/* the four corner brackets that clamp a hovered element */
.blob-corner {
  position: absolute;
  width: 14px;
  height: 14px;
  border: 2px solid var(--accent);
  opacity: 0;
  transition: opacity 0.18s ease;
}
.blob-corner.tl { border-right: 0; border-bottom: 0; }
.blob-corner.tr { border-left: 0;  border-bottom: 0; }
.blob-corner.bl { border-right: 0; border-top: 0; }
.blob-corner.br { border-left: 0;  border-top: 0; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .type-caret, .scroll-hint span { animation: none; }
  .photo-frame, .photo-frame::before { animation: none; }
  .about-photo:hover .photo-frame::after { animation: none; }
  * { transition-duration: 0.01ms !important; }
}
