/* =====================================================================
   polish.css — visual refinement + motion layer
   Loads after redesign.css; uses its tokens (blue/cyan on near-black).
   Additive only, so the whole layer can be removed cleanly.
   ===================================================================== */

/* ---- 1. Foundations ------------------------------------------------- */
::selection { background: rgba(var(--cyan-rgb), 0.28); color: #eaf6ff; }
body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }

a, button, .btn,
.pub-card-v2, .blog-card, .pub-card, .project-card, .cert-card-v2,
.cve-card-item, .publication-card, .platform-badge,
.skill-tag, .blog-tag, .blog-tag-cat, .hof-item, .hof-item-link, .hero-socials a {
  transition: color .25s ease, background-color .25s ease, border-color .25s ease,
              box-shadow .35s ease, transform .35s cubic-bezier(.2, .7, .2, 1);
}

a:focus-visible, button:focus-visible, .btn:focus-visible,
input:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
}

/* ---- 2. Hero: depth behind an otherwise flat, empty dark hero ------- */
.hero { position: relative; }
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(52% 48% at 50% 33%, rgba(var(--blue-rgb), 0.26), transparent 72%),
    radial-gradient(42% 44% at 73% 66%, rgba(var(--cyan-rgb), 0.14), transparent 72%),
    radial-gradient(40% 42% at 25% 62%, rgba(var(--blue-rgb), 0.11), transparent 72%);
  animation: heroAurora 20s ease-in-out infinite alternate;
  will-change: transform, opacity;
}
@keyframes heroAurora {
  0%   { transform: translate3d(0, 0, 0) scale(1);        opacity: .85; }
  50%  { transform: translate3d(1.5%, -1%, 0) scale(1.06); opacity: 1; }
  100% { transform: translate3d(-1.5%, 1%, 0) scale(1.02); opacity: .8; }
}
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 210px; z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--bg));
}
.hero-bg-grid {
  background-image:
    linear-gradient(rgba(var(--cyan-rgb), 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--cyan-rgb), 0.05) 1px, transparent 1px) !important;
  mask-image: radial-gradient(ellipse 72% 62% at 50% 42%, #000 30%, transparent 80%) !important;
  -webkit-mask-image: radial-gradient(ellipse 72% 62% at 50% 42%, #000 30%, transparent 80%) !important;
}
/* particle network canvas (injected by fx.js) sits behind the content */
.hero-particles {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: .6;
  -webkit-mask-image: radial-gradient(ellipse 78% 70% at 50% 46%, transparent 6%, #000 52%);
  mask-image: radial-gradient(ellipse 78% 70% at 50% 46%, transparent 6%, #000 52%);
}
.hero .hero-content { position: relative; z-index: 2; }
.hero-typed-wrapper { letter-spacing: .4px; }
/* Caret: a solid block pressed against the last character, the way a terminal
   draws it, instead of a thin blinking underscore. Typed.js still inserts a
   '_' glyph - it is hidden with color:transparent and the box is painted from
   the element's own background, so it inherits whichever --cyan the active
   theme defines (gray in editorial) with no per-skin override needed.
   Font, size and colour of the line itself are untouched. */
.typed-cursor {
  display: inline-block;
  width: .55ch;
  height: 1.08em;
  margin-left: .08em;
  vertical-align: -.17em;
  background: var(--cyan);
  color: transparent;
  overflow: hidden;
  font-weight: 400;
  animation: none;
}
/* Solid while characters are landing; blinks only while the finished line
   rests. A terminal does not blink between keystrokes - that is the motion
   being matched. main.js toggles .is-idle around each typing run. */
.typed-cursor.is-idle { animation: blink 1s infinite; }
.hero-tagline { letter-spacing: .2px; }
.hero-socials a:hover {
  transform: translateY(-3px);
  border-color: var(--cyan);
  box-shadow: 0 0 20px rgba(var(--cyan-rgb), .40);
}

/* ---- 3. Cards: depth, cover zoom, animated gradient-glow border ---- */
.pub-card-v2, .blog-card, .pub-card, .project-card,
.cert-card-v2, .cve-card-item, .publication-card { position: relative; }

.pub-card-v2, .blog-card, .pub-card, .project-card,
.cert-card-v2, .cve-card-item, .publication-card {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .03), 0 12px 30px -20px rgba(0, 0, 0, .9);
}
.pub-card-v2:hover, .blog-card:hover, .pub-card:hover, .project-card:hover,
.cert-card-v2:hover, .cve-card-item:hover, .publication-card:hover {
  transform: translateY(-6px);
  border-color: var(--border-glow);
  box-shadow:
    0 0 0 1px rgba(var(--cyan-rgb), .18),
    0 26px 54px -22px rgba(0, 0, 0, .95),
    0 0 50px -16px rgba(var(--cyan-rgb), .38);
}
/* cover image zoom (pub-cover already clips overflow) */
.pub-card-v2 .pub-cover img, .blog-card img {
  transition: transform .6s cubic-bezier(.2, .7, .2, 1);
}
.pub-card-v2:hover .pub-cover img, .blog-card:hover img { transform: scale(1.07); }
/* animated gradient-glow border, revealed on hover */
.pub-card-v2::after, .blog-card::after, .project-card::after, .cert-card-v2::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  pointer-events: none; opacity: 0; transition: opacity .4s ease;
  background: linear-gradient(135deg,
    rgba(var(--cyan-rgb), .8), rgba(var(--blue-rgb), 0) 42%,
    rgba(var(--blue-rgb), 0) 58%, rgba(var(--blue-rgb), .8));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}
.pub-card-v2:hover::after, .blog-card:hover::after,
.project-card:hover::after, .cert-card-v2:hover::after { opacity: 1; }

/* ---- 4. Tags: understated, professional (research-blog style) ----- */
/* scoped to the card tag rows so this wins over blog.css regardless of order */
.pub-tags-v2, .blog-tags-v2 { display: flex; flex-wrap: wrap; gap: .42rem; align-items: center; }

.pub-tags-v2 .blog-tag-cat, .blog-tags-v2 .blog-tag-cat {
  font-family: var(--font-mono);
  font-size: .64rem; font-weight: 600; letter-spacing: .8px; text-transform: uppercase;
  padding: .3rem .6rem; border-radius: 6px;
  background: rgba(var(--cyan-rgb), .12);
  color: var(--cyan);
  border: 1px solid rgba(var(--cyan-rgb), .30);
}
.pub-tags-v2 .blog-tag, .blog-tags-v2 .blog-tag {
  font-family: var(--font-mono);
  font-size: .64rem; letter-spacing: .5px;
  padding: .3rem .6rem; border-radius: 6px;
  background: rgba(var(--tint-rgb), .035);
  color: var(--text-muted);
  border: 1px solid var(--border);
  transition: color .2s ease, border-color .2s ease, background-color .2s ease;
}
.pub-tags-v2 .blog-tag:hover, .blog-tags-v2 .blog-tag:hover {
  color: var(--cyan);
  border-color: rgba(var(--cyan-rgb), .4);
  background: rgba(var(--cyan-rgb), .08);
}
/* skill/experience tags elsewhere keep a refined pill */
.skill-tag { border-radius: 999px; border: 1px solid var(--border-glow); }
.skill-tag:hover { border-color: var(--cyan); color: var(--cyan); background: rgba(var(--cyan-rgb), .10); }

/* blog tag-filter pill row */
.tag-filter { display: flex; flex-wrap: wrap; gap: .5rem; justify-content: center; }
.pill-count { font-size: .72em; opacity: .55; margin-left: .4em; }
.pill-link { text-decoration: none; display: inline-flex; align-items: center; }

/* ---- 5. Buttons + pulsing CTA ------------------------------------- */
.btn { border-radius: 10px; letter-spacing: .2px; }
.btn-primary { box-shadow: 0 8px 22px -10px rgba(var(--blue-rgb), .75); }
.btn-primary:hover { box-shadow: 0 12px 30px -8px rgba(var(--blue-rgb), .85); }
.nav-cta { position: relative; isolation: isolate; }
.nav-cta::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1;
  animation: ctaPulse 3.4s ease-out infinite;
}
@keyframes ctaPulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--blue-rgb), .5); }
  70%  { box-shadow: 0 0 0 12px rgba(var(--blue-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--blue-rgb), 0); }
}

/* ---- 6. Section titles: subtle glow ------------------------------- */
.section-title { text-shadow: 0 0 34px rgba(var(--cyan-rgb), .18); }

/* ---- Respect reduced motion --------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hero::before, .nav-cta::before { animation: none !important; }
  .hero-particles { display: none !important; }
  a, button, .btn, .pub-card-v2, .blog-card, .pub-card, .project-card,
  .cert-card-v2, .cve-card-item, .publication-card { transition: none !important; }
}
