/* Hero and the decorative journey track.
   Default (no JavaScript, reduced motion, or any failure): the hero shows a
   still of the card and the story is three static frames in normal flow.
   Story tiers (data-tier="full" | "compact", set only after initialisation
   succeeds): a fixed stage draws the live art and the frames become captions. */

/* ---------- Hero ----------
   Two columns on wide screens: the copy, and the card in a soft studio light.
   The still image of the card is the default; once the live 3D card is drawing
   (data-card="live") the still steps aside and the canvas takes its place. The
   hero itself never forms a stacking context, so the backdrop (z 0) sits under
   the story stage (the journey, z 1) and the copy (z 2) sits over it. */
.hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  align-items: center;
  gap: var(--s4) var(--s5);
  min-height: 100svh;
  padding:
    calc(var(--header-h) + var(--s4))
    max(var(--gutter), env(safe-area-inset-right), calc((100% - var(--content-max)) / 2))
    var(--s6)
    max(var(--gutter), env(safe-area-inset-left), calc((100% - var(--content-max)) / 2));
}
.hero-backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(ellipse 34% 42% at 72% 50%, var(--studio-key), transparent 72%),
    radial-gradient(ellipse 46% 32% at 76% 86%, var(--studio-fill), transparent 70%);
}
/* A faint engineering grid, strongest behind the card and gone at the edges. */
.hero-backdrop::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--studio-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--studio-grid) 1px, transparent 1px);
  background-size: 56px 56px;
  background-position: center;
  -webkit-mask-image: radial-gradient(ellipse 52% 62% at 70% 50%, #000 15%, transparent 78%);
  mask-image: radial-gradient(ellipse 52% 62% at 70% 50%, #000 15%, transparent 78%);
}
/* The floor: a soft horizon line under the card. */
.hero-backdrop::after {
  content: '';
  position: absolute;
  left: 46%;
  right: 0;
  top: 74%;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--border-strong) 30%, var(--border-strong) 70%, transparent);
  opacity: 0.55;
}
.hero-copy { position: relative; z-index: 2; max-width: 620px; }
.hero-kicker { margin-bottom: var(--s2); }
/* Each discipline wraps as a unit, unless it is wider than the line itself. */
.kicker-item { display: inline-block; max-width: 100%; }
/* The heading hugs its text so the intro glow behind it never spills off-screen. */
.hero-name {
  width: fit-content;
  max-width: 100%;
  font-size: var(--name-size);
  line-height: 0.96;
  letter-spacing: -0.035em;
  font-weight: 450;
}
.hero-name-line { display: block; }
.hero-name-line + .hero-name-line { color: var(--ink-soft); }
.hero-name:focus { outline: none; }
.hero-subtitle {
  margin-top: var(--s3);
  max-width: 38ch;
  font-size: clamp(1.0625rem, 1.2vw, 1.25rem);
  color: var(--ink-soft);
}

/* Facts read like a spec sheet: label over value, ruled above. */
.hero-facts {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: start;
  gap: var(--s2) var(--s4);
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--border);
}
.hero-fact { display: grid; gap: 4px; align-content: start; }
.hero-fact dt { font-size: var(--text-kicker); letter-spacing: 0.2em; text-transform: uppercase; color: var(--copper); }
.hero-fact dd { font-size: var(--text-small); line-height: 1.4; }

.hero-projects { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin-top: var(--s3); }
.hero-projects-label { font-size: var(--text-kicker); letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); }
.hero-projects ul { display: flex; flex-wrap: wrap; gap: var(--s1); }
.hero-projects a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--text-small);
  text-decoration: none;
  transition: border-color var(--dur-hover) var(--ease-ui), color var(--dur-hover) var(--ease-ui);
}
.hero-projects a:hover { border-color: var(--copper); color: var(--copper-strong); }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s4); }

/* The visual: the three disciplines as a small workbench. A code window
   (Computer Science) and a market chart (Finance) stand behind the card
   (Computer Engineering). Sizes follow the visual's own width (cqw). */
.hero-visual {
  position: relative;
  z-index: 1;
  aspect-ratio: 5 / 4;
  width: 100%;
  container-type: inline-size;
}
.hero-panel {
  position: absolute;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--panel-border);
  border-radius: clamp(8px, 1.8cqw, 14px);
  background: var(--panel-bg);
  box-shadow: var(--panel-shadow);
  font-size: clamp(6.5px, 1.72cqw, 12px);
  line-height: 1.55;
  transition: transform 120ms linear;
}
.hero-panel--code {
  left: 0;
  top: 0;
  width: 60%;
  transform: translate3d(calc(var(--px, 0) * -7px), calc(var(--py, 0) * -6px), 0);
}
.hero-panel--chart {
  right: 0;
  top: 22%;
  width: 57%;
  transform: translate3d(calc(var(--px, 0) * -4px), calc(var(--py, 0) * -3px), 0);
}
.panel-bar {
  display: flex;
  align-items: center;
  gap: 0.8em;
  padding: 0.7em 1em;
  border-bottom: 1px solid var(--panel-border);
  background: var(--panel-bar);
  color: var(--code-ink);
  white-space: nowrap;
}
.panel-dots { display: inline-flex; gap: 0.45em; }
.panel-dots i { width: 0.8em; height: 0.8em; border-radius: 50%; background: var(--border-strong); }
.panel-title { overflow: hidden; text-overflow: ellipsis; font-weight: 500; }
.panel-dim { color: var(--code-com); font-weight: 400; }
.panel-quote { margin-left: auto; font-variant-numeric: tabular-nums; }
.panel-tag {
  margin-left: auto;
  padding: 0.15em 0.75em;
  border: 1px solid color-mix(in srgb, var(--copper) 45%, transparent);
  border-radius: 999px;
  color: var(--copper);
  font-size: 0.86em;
  letter-spacing: 0.06em;
}
.panel-quote + .panel-tag { margin-left: 0; }
.is-up { color: var(--chart-up); }
.is-down { color: var(--chart-down); }

.panel-code {
  flex: 1;
  margin: 0;
  padding: 0.9em 0;
  overflow: hidden;
  color: var(--code-ink);
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.98em;
  line-height: 1.6;
  tab-size: 2;
  /* Long lines run off the edge like a real editor, fading out. */
  -webkit-mask-image: linear-gradient(90deg, #000 82%, transparent);
  mask-image: linear-gradient(90deg, #000 82%, transparent);
}
.code-line { display: block; padding-right: 1em; white-space: pre; }
.code-ln { display: inline-block; width: 3.4em; padding-right: 1.2em; text-align: right; color: var(--code-com); opacity: 0.8; user-select: none; }
.tok-kw { color: var(--code-kw); }
.tok-str { color: var(--code-str); }
.tok-num { color: var(--code-num); }
.tok-fn { color: var(--code-fn); }
.tok-com { color: var(--code-com); font-style: italic; }
.tok-pun { color: var(--code-pun); }
.code-caret {
  display: inline-block;
  width: 0.55em;
  height: 1.15em;
  margin-left: 0.1em;
  vertical-align: text-bottom;
  background: var(--copper);
  animation: caret-blink 1.1s steps(1) infinite;
}
@keyframes caret-blink { 50% { opacity: 0; } }

.panel-chart { display: block; width: 100%; height: auto; padding: 0.2em 0.7em 0.3em; overflow: visible; }
.panel-stat { padding: 0.6em 1em 0; color: var(--code-ink); font-size: 0.95em; }
.panel-stat b { font-weight: 500; }
.panel-stat b:first-of-type { color: var(--chart-up); }
.chart-grid { fill: none; stroke: var(--chart-grid); stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart-last { fill: none; stroke: var(--code-com); stroke-width: 1; stroke-dasharray: 2 3; opacity: 0.6; vector-effect: non-scaling-stroke; }
.chart-axis { fill: var(--code-com); font: 400 15px var(--font-body); font-variant-numeric: tabular-nums; }
.chart-legend--1 { fill: var(--chart-ema-1); }
.chart-legend--2 { fill: var(--chart-ema-2); }
.chart-wick { fill: none; stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart-wick.is-up { stroke: var(--chart-up); }
.chart-wick.is-down { stroke: var(--chart-down); }
.chart-body.is-up { fill: var(--chart-up); }
.chart-body.is-down { fill: var(--chart-down); }
.chart-ema, .chart-rsi { fill: none; stroke-width: 1.4; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.chart-ema--1 { stroke: var(--chart-ema-1); }
.chart-ema--2 { stroke: var(--chart-ema-2); stroke-dasharray: 4 3; }
.chart-rsi { stroke: var(--chart-rsi); }
.chart-tag.is-up { fill: var(--chart-up); }
.chart-tag.is-down { fill: var(--chart-down); }
.chart-tag-text { fill: #fff; font: 500 14px var(--font-body); font-variant-numeric: tabular-nums; }
.panel-note { padding: 0 1em 0.7em; font-size: 0.85em; text-align: right; }

.hero-card-slot { position: absolute; left: -2%; top: 47%; width: 74%; }
.hero-card {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 34px 34px rgb(0 0 0 / 0.38));
  transition: opacity 600ms var(--ease-ui);
}
.hero-card-tag {
  position: absolute;
  right: 0;
  bottom: 7%;
  display: flex;
  align-items: center;
  gap: 0.7em;
  font-size: clamp(9px, 1.9cqw, 13px);
  color: var(--ink-soft);
  white-space: nowrap;
}
.hero-card-tag .panel-tag { margin: 0; }

/* First view only: the code types in and the chart draws, once. */
html.intro-running .code-line { animation: code-type 460ms var(--ease-ui) both; }
html.intro-running .panel-chart { animation: chart-draw 1300ms var(--ease-ui) 200ms both; }
@keyframes code-type { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes chart-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
html.intro-running .code-line:nth-child(1) { animation-delay: 150ms; }
html.intro-running .code-line:nth-child(2) { animation-delay: 235ms; }
html.intro-running .code-line:nth-child(3) { animation-delay: 320ms; }
html.intro-running .code-line:nth-child(4) { animation-delay: 405ms; }
html.intro-running .code-line:nth-child(5) { animation-delay: 490ms; }
html.intro-running .code-line:nth-child(6) { animation-delay: 575ms; }
html.intro-running .code-line:nth-child(7) { animation-delay: 660ms; }
html.intro-running .code-line:nth-child(8) { animation-delay: 745ms; }
html.intro-running .code-line:nth-child(9) { animation-delay: 830ms; }
html.intro-running .code-line:nth-child(10) { animation-delay: 915ms; }
html.intro-running .code-line:nth-child(11) { animation-delay: 1000ms; }
html.intro-running .code-line:nth-child(12) { animation-delay: 1085ms; }
html[data-motion-paused] .code-caret { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .code-caret { animation: none; } }
html[data-card='live'] .hero-card { opacity: 0; }

@media (max-width: 1023px) {
  .hero { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); gap: var(--s3); }
  .hero-facts { grid-template-columns: repeat(2, auto); }
}
/* Narrow: one column. The copy's children join the hero's flow so the card can
   sit between the introduction and the details. */
@media (max-width: 859px) {
  .hero { display: flex; flex-direction: column; align-items: stretch; gap: 0; padding-bottom: var(--s5); }
  .hero-copy { display: contents; }
  .hero-copy > * { position: relative; z-index: 2; }
  .hero-visual { order: 1; width: min(100%, 520px); margin: var(--s4) auto var(--s1); }
  .hero-facts, .hero-projects, .hero-actions { order: 2; }
  .hero-backdrop {
    background:
      radial-gradient(ellipse 70% 22% at 50% 52%, var(--studio-key), transparent 72%),
      radial-gradient(ellipse 80% 20% at 50% 64%, var(--studio-fill), transparent 70%);
  }
  .hero-backdrop::before {
    -webkit-mask-image: radial-gradient(ellipse 70% 30% at 50% 50%, #000 15%, transparent 78%);
    mask-image: radial-gradient(ellipse 70% 30% at 50% 50%, #000 15%, transparent 78%);
  }
  .hero-backdrop::after { display: none; }
}
@media (max-width: 599px) {
  .hero-name { font-size: clamp(40px, 12.4vw, 60px); }
  .hero-card-tag { bottom: 2%; }
  .hero-card-tag .panel-tag + * { display: none; }
  .hero-subtitle { font-size: 1rem; }
  .hero-facts { grid-template-columns: 1fr 1fr; gap: var(--s2); }
  .hero-fact:first-child { grid-column: 1 / -1; }
}

/* ---------- Journey: static frames (default) ---------- */
.journey {
  position: relative;
  z-index: 1;
  padding-block: var(--section-pad);
}
.journey-head { text-align: center; margin-bottom: var(--s6); }
.journey-title { font-size: clamp(2rem, 4vw, 3.5rem); }
.journey-intro { margin: var(--s2) auto 0; max-width: 52ch; color: var(--ink-soft); }
.beats {
  display: grid;
  gap: var(--s6);
  max-width: calc(var(--content-max) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.beat { scroll-margin-top: calc(var(--header-h) + var(--s2)); }
.beat-figure {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--s5);
  align-items: center;
}
.beat-art { width: 100%; height: auto; }
.beat-caption { max-width: 46ch; }
.beat-title { font-size: clamp(1.75rem, 3vw, 2.5rem); margin: var(--s1) 0 var(--s2); }
.beat-caption p:not(.kicker) { color: var(--ink-soft); }
/* One layer, one skill: the layer's name, the skill, then the proof. */
.layer-list { display: grid; gap: var(--s2); margin-top: var(--s3); }
.layer-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; padding-left: var(--s2); border-left: 2px solid var(--copper); }
.layer-name { font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.layer-skill { font-weight: 500; color: var(--ink); }
.layer-text { flex-basis: 100%; font-size: var(--text-small); color: var(--ink-soft); }
@media (max-width: 859px) {
  .beat-figure { grid-template-columns: 1fr; gap: var(--s3); }
}
.stage { display: none; }

/* ---------- Journey: story tiers ---------- */

/* The story keeps the visitor's place itself (resize re-anchors to the same
   progress), so the browser's scroll anchoring would correct twice (PF-3). */
html[data-tier='full'],
html[data-tier='compact'] { overflow-anchor: none; }
html[data-tier='full'] .journey,
html[data-tier='compact'] .journey {
  height: var(--journey-h, 300vh);
  padding: 0;
}
html[data-tier='full'] .journey-head,
html[data-tier='compact'] .journey-head {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
html[data-tier='full'] .beats,
html[data-tier='compact'] .beats { display: block; padding: 0; max-width: none; }
html[data-tier='full'] .beat,
html[data-tier='compact'] .beat {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--beat-y, 0);
  height: var(--beat-h, 100vh);
  pointer-events: none;
  scroll-margin-top: 0;
}
html[data-tier='full'] .beat-figure,
html[data-tier='compact'] .beat-figure { display: block; height: 100%; }
html[data-tier='full'] .beat-art,
html[data-tier='compact'] .beat-art { display: none; }
/* Captions are pinned in place and faded by the story state (one at a time). */
html[data-tier='full'] .beat-caption,
html[data-tier='compact'] .beat-caption {
  position: fixed;
  z-index: 3;
  top: calc(var(--header-h) + 18vh);
  left: 0;
  visibility: hidden;
  opacity: 0;
  margin-left: max(var(--gutter), calc((100vw - var(--content-max)) / 2));
  width: min(380px, calc(100vw - 2 * var(--gutter)));
  padding: var(--s3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  pointer-events: auto;
}
html[data-tier='compact'] .beat-caption {
  top: auto;
  bottom: calc(var(--s2) + env(safe-area-inset-bottom));
  margin: 0 var(--gutter);
  width: calc(100vw - 2 * var(--gutter));
  padding: var(--s2) var(--s3);
}
html[data-tier='compact'] .stage-label { font-size: 0.75rem; padding: 3px 8px; }
/* Pinned captions stay short: the layer list tightens on wide screens, and on
   narrow ones shows each layer and its skill only (the proofs are in the
   reduced-motion and no-JS versions). */
html[data-tier='full'] .layer-list { gap: 10px; margin-top: var(--s2); }
html[data-tier='full'] .layer-text { font-size: 0.8125rem; }
html[data-tier='compact'] .layer-list { grid-template-columns: 1fr 1fr; gap: 8px 12px; margin-top: 10px; }
html[data-tier='compact'] .layer-list li { flex-direction: column; gap: 0; padding-left: 10px; }
html[data-tier='compact'] .layer-skill { font-size: var(--text-small); }
html[data-tier='compact'] .layer-text { display: none; }
html[data-tier='compact'] .beat-title { font-size: 1.5rem; margin: 4px 0 6px; }
html[data-tier='compact'] .beat-caption p:not(.kicker) { font-size: var(--text-small); }

html[data-tier='full'] .stage,
html[data-tier='compact'] .stage {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--stage-o, 1);
  transform-origin: 50% 50%;
  will-change: opacity, transform;
}
.stage.is-parked { visibility: hidden; }
.stage-canvas { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 600ms var(--ease-ui); }
.stage-svg { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; overflow: visible; }
.stage-labels { position: absolute; inset: 0; z-index: 2; }
.art-board-fill { fill: var(--board-fill); stroke: none; }
.stage-label {
  position: absolute;
  left: 0; top: 0;
  padding: 4px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-solid);
  color: var(--ink);
  font-size: 0.875rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
  opacity: 0;
}
.stage-leader { stroke: var(--line-frame); }
.stage .led-glow { stroke: none; }

/* Later content scrolls over a dimmed backdrop, then a solid page. */
html[data-tier='full'] .after,
html[data-tier='compact'] .after {
  position: relative;
  z-index: 2;
  background: linear-gradient(to bottom, transparent 0, color-mix(in srgb, var(--bg) 70%, transparent) 30vh, var(--bg) 70vh);
}

.scroll-hint {
  position: absolute;
  left: 50%;
  bottom: var(--s3);
  width: 20px;
  height: 44px;
  z-index: 2;
  transform: translateX(-50%);
  opacity: 0;
  pointer-events: none;
}
.scroll-hint path { stroke: var(--muted); }

/* ---------- Intro states ----------
   The intro only adds starting states while it runs; every resting state is the
   finished one. */

.hero-name { position: relative; isolation: isolate; }
.name-bloom {
  position: absolute;
  inset: -12% -6%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--gold) 55%, transparent), color-mix(in srgb, var(--copper) 18%, transparent) 60%, transparent);
  opacity: 0;
  pointer-events: none;
  will-change: transform, filter, opacity;
}

.site-header::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--copper) 40%, transparent), color-mix(in srgb, var(--copper) 80%, transparent), transparent);
  opacity: 0.55;
  transform-origin: 50% 50%;
  transition: transform 700ms var(--ease-ui), opacity 700ms var(--ease-ui);
  pointer-events: none;
}
html.intro-running:not(.intro-header) .site-header::after { transform: scaleX(0); opacity: 0; }

.chapters::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 22px; bottom: 22px;
  width: 1px;
  background: color-mix(in srgb, var(--muted) 35%, transparent);
  transform-origin: 50% 0;
  transition: transform 600ms var(--ease-ui);
  pointer-events: none;
}
html.intro-running:not(.intro-chapters) .chapters::before { transform: scaleY(0); }
.chapters ol { position: relative; }

html[data-tier] .scroll-hint { opacity: 0.8; transition: opacity var(--dur-reveal) var(--ease-ui); }
html.intro-running:not(.intro-hint) .scroll-hint { opacity: 0; }
@media (max-height: 640px) { .scroll-hint { display: none; } }

/* ---------- Ambient board after the handoff (optional) ----------
   ±0.5° breathing over 8s and a restrained copper sweep every 6s on the dimmed
   backdrop. Stopped by Pause motion and reduced motion; never part of the
   deterministic story. */
.stage.is-ambient .stage-svg,
.stage.is-ambient .stage-canvas { animation: board-breathe 8s ease-in-out infinite; transform-origin: 58% 52%; }
.stage.is-ambient::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  background: linear-gradient(105deg, transparent 40%, color-mix(in srgb, var(--copper) 9%, transparent) 50%, transparent 60%);
  background-size: 300% 100%;
  animation: copper-sweep 6s var(--ease-scene) infinite;
  pointer-events: none;
}
@keyframes board-breathe { 0%, 100% { transform: rotate(-0.5deg); } 50% { transform: rotate(0.5deg); } }
@keyframes copper-sweep { 0% { background-position: 100% 0; } 70%, 100% { background-position: 0 0; } }
html[data-motion-paused] .stage.is-ambient .stage-svg,
html[data-motion-paused] .stage.is-ambient .stage-canvas,
html[data-motion-paused] .stage.is-ambient::after { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .stage.is-ambient .stage-svg, .stage.is-ambient .stage-canvas, .stage.is-ambient::after { animation: none; } }
