/* Dark Nebula — the site's single locked theme. No dark mode: every color
   below is chosen to hold contrast across the whole gradient, so there is
   nothing to switch. */

html {
  scroll-padding-top: 84px;
}

body {
  background-image:
    radial-gradient(60% 50% at 12% 0%, rgba(34,211,238,.14), transparent 70%),
    radial-gradient(55% 55% at 100% 100%, rgba(244,114,182,.20), transparent 70%),
    linear-gradient(135deg, rgba(2,3,10,.3), rgba(10,4,20,.38)),
    /* End stop darkened from #E11D74 (M23): inkMuted #D7D7F0 on the raw stop
       was ~3.2:1; on #B0175F it's 4.74:1, and ~5.97:1 once the overlay and
       pink radial above are composited in. */
    linear-gradient(135deg, #05061A 0%, #1E1B6E 30%, #6D28D9 62%, #B0175F 100%);
  background-attachment: fixed;
  color: #FFFFFF;
  font-feature-settings: "cv11", "ss01";
}

::-webkit-scrollbar { height: 8px; width: 8px; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,.25); border-radius: 999px; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .js .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
  .live-dot::before, .timeline-dot.is-current::before, .animate-blink { animation: none; }
}

/* "Live" status badge — a real status color (green), not the brand accent,
   with a radar-ping dot so it actually reads as "happening now" instead of
   a flat label that blends into the panel around it. */
.live-badge {
  background: rgba(16,185,129,.16);
  border: 1px solid rgba(52,211,153,.45);
  color: #6EE7B7;
}
.live-dot { position: relative; display: inline-flex; width: 8px; height: 8px; flex: none; }
.live-dot::before {
  content: "";
  position: absolute; inset: -4px;
  border-radius: 9999px;
  background: #34D399;
  opacity: .55;
  animation: liveDotPing 1.8s cubic-bezier(0,0,.2,1) infinite;
}
.live-dot::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 9999px;
  background: #34D399;
}
@keyframes liveDotPing {
  0% { transform: scale(1); opacity: .6; }
  75%, 100% { transform: scale(2.6); opacity: 0; }
}

/* Hard on/off blink for the "Open to opportunities" status dot — distinct
   from Tailwind's animate-pulse, which only fades opacity to .5. */
.animate-blink {
  animation: blink 1.4s step-start infinite;
}
@keyframes blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* Same "live" language as .live-badge, but as a solid CTA button — the
   plain white pill it replaces looked identical to every other button on
   the card, with nothing marking it as a running, playable demo. */
.live-cta {
  background: linear-gradient(135deg, #10B981, #34D399);
  color: #052e2b;
  box-shadow: 0 0 0 1px rgba(52,211,153,.5), 0 10px 24px -10px rgba(16,185,129,.65);
}
.live-cta:hover { filter: brightness(1.08); }
.live-cta .live-dot::before,
.live-cta .live-dot::after { background: #052e2b; }

/* Only hide .reveal content when JS is running (an inline script in each
   page's <head> adds .js to <html>) — without JS it stays visible. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}
.js .reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* The one deliberate flourish carried over from the old theme: the vivid
   cyan-violet-pink gradient, reserved for the tagline and brand mark only —
   everything else stays solid white/off-white for guaranteed contrast. */
.text-gradient {
  background: linear-gradient(90deg, #22D3EE, #A78BFA 55%, #F472B6);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Same gradient, used as a solid fill for the small brand-mark badge in the
   header — a filled shape can carry the full vividness safely since it
   never has to hold body-text contrast itself. */
.brand-mark {
  background: linear-gradient(135deg, #22D3EE, #A78BFA, #F472B6);
  color: #0A0F2C;
}

/* Faint structural grid behind the hero — recolored to white, not gray,
   so it reads as part of this palette rather than a default template line. */
.grid-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.06) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.06) 1px, transparent 1px);
  background-size: 42px 42px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 0%, black 40%, transparent 90%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 0%, black 40%, transparent 90%);
}

/* Career timeline */
.timeline { position: relative; list-style: none; margin: 0; padding: 0; }
.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  /* Mirrors the per-dot cyan -> violet -> pink coloring set inline by
     renderWorkTimeline() in main.js, so the connecting line reads as one
     continuous gradient instead of a plain white fade behind colored dots. */
  background: linear-gradient(to bottom, rgba(34,211,238,.55), rgba(167,139,250,.4), rgba(244,114,182,.3));
}
.timeline-item { position: relative; padding-left: 1.75rem; }
.timeline-item + .timeline-item { margin-top: 1.5rem; }
.timeline-dot {
  position: absolute;
  left: 0;
  top: 11px;
  width: 12px;
  height: 12px;
  border-radius: 9999px;
  background: #FFFFFF;
}
/* The current role gets a radar-ping ring in its own dot color (set inline
   via --dot-color by renderWorkTimeline() in main.js) — reuses the same
   liveDotPing keyframe as .live-dot so "still happening" reads consistently
   across the site, without pulling in the unrelated green status color. */
.timeline-dot.is-current::before {
  content: "";
  position: absolute; inset: -5px;
  border-radius: 9999px;
  background: var(--dot-color, #22D3EE);
  opacity: .55;
  animation: liveDotPing 1.8s cubic-bezier(0,0,.2,1) infinite;
}
.timeline-row { display: flex; flex-direction: column; gap: .25rem; align-items: flex-start; }

@media (min-width: 640px) {
  .timeline-item { padding-left: 0; }
  .timeline::before { left: 142px; }
  .timeline-dot { left: 136px; top: 13px; }
  .timeline-row { flex-direction: row; gap: 1.5rem; }
  .timeline-date { flex: 0 0 130px; }
}

/* Dark Nebula panel — translucent glass instead of a flat tint, since the
   backdrop is a vivid dark gradient rather than a light one. */
.panel-card {
  background: rgba(255,255,255,.07);
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 16px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

/* Baseline keyboard focus ring (L19) — high contrast on the dark gradient.
   Tailwind focus-visible: utilities (e.g. on link cards) override this. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
video:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* AI Prompt Mode identity (game.html + games.html) — the brand's
   cyan -> violet -> pink gradient, used as a border/glow so the premium,
   Gemini-graded mode reads as visibly distinct from the neutral white-glass
   classic challenge cards. Text inside stays white/off-white for contrast. */
.ai-shell {
  position: relative;
  border-radius: 20px;
  background: linear-gradient(160deg, rgba(34,211,238,.09), rgba(167,139,250,.11) 50%, rgba(244,114,182,.09));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 18px 48px -18px rgba(167,139,250,.55);
  animation: aiGlow 4.5s ease-in-out infinite;
}
/* 1px gradient border drawn by a masked pseudo-element so the fill above
   can stay translucent glass. */
.ai-shell::before {
  content: "";
  position: absolute;
  inset: 0;
  padding: 1px;
  border-radius: inherit;
  background: linear-gradient(135deg, #22D3EE, #A78BFA 50%, #F472B6);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
@keyframes aiGlow {
  0%, 100% { box-shadow: 0 18px 48px -18px rgba(167,139,250,.55); }
  50% { box-shadow: 0 18px 56px -14px rgba(244,114,182,.6); }
}
/* Inner cards inside the AI shell pick up a faint violet tint + border. */
.ai-shell .panel-card { border-color: rgba(167,139,250,.35); background: rgba(10,15,44,.35); }

.ai-pill {
  background: linear-gradient(135deg, rgba(34,211,238,.22), rgba(167,139,250,.22), rgba(244,114,182,.22));
  border: 1px solid rgba(196,181,253,.6);
  color: #FFFFFF;
}
.ai-cta {
  background: linear-gradient(135deg, #22D3EE, #A78BFA 55%, #F472B6);
  color: #0A0F2C;
  box-shadow: 0 10px 24px -12px rgba(167,139,250,.8);
}
.ai-cta:hover { filter: brightness(1.08); }
.ai-divider {
  height: 1px;
  background: linear-gradient(90deg, rgba(34,211,238,.7), rgba(167,139,250,.6), rgba(244,114,182,.0));
}

@media (prefers-reduced-motion: reduce) {
  .ai-shell { animation: none; }
}
