/* =====================================================
   PARTH SONI PORTFOLIO — "ANALYST REPORT" DESIGN
   Fonts: DM Sans (display + body) + Inter (data/tabular)
   Palette: warm paper · ink · ONE orange accent
   Shape system (documented, one scale per tier):
     Editorial / section surfaces  -> 0px (sharp, hairlines)
     Interactive small controls    -> 8px (filters, pills, buttons)
     Elevated cards                -> 14px (connect card, dash cards)
   Motion: transform/opacity only; prefers-reduced-motion honored.
   ===================================================== */

/* Self-hosted variable fonts (latin subset) — no third-party font requests */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/inter.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url(fonts/dmsans.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Sans';
  font-style: italic;
  font-weight: 100 1000;
  font-display: swap;
  src: url(fonts/dmsans-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

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

:root {
  --paper:        #f6f5f1;
  --paper-raise:  #fcfbf8;
  --ink:          #16130e;
  --ink-soft:     #4a453c;
  --ink-mute:     #756e62;
  --line:         #ddd8cc;
  --line-strong:  #b9b2a2;
  --accent:       #e85d04;
  --accent-deep:  #b44500;   /* text-on-light accent — WCAG AA on paper */
  --accent-soft:  #fdeee0;
  --green:        #15803d;
  --amber:        #b45309;
  --shadow-card:  0 1px 2px rgba(22,19,14,.05), 0 10px 30px -14px rgba(22,19,14,.14);
  --sans:         'DM Sans', system-ui, -apple-system, sans-serif;
  --data:         'Inter', system-ui, -apple-system, sans-serif;
  --maxw:         1180px;
  --pad:          24px;
}

html { scroll-behavior: smooth; color-scheme: light; }

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; }
button { font-family: inherit; cursor: pointer; }

/* In-page anchors land below the sticky header (redesign dropped the old 72px rule) */
section[id], div[id], footer[id] { scroll-margin-top: 80px; }

/* Data numerals render tabular (stable widths) everywhere numbers matter */
.big-num, .dash-metric-value, .exp-count, .proj-count-label,
.footer-grey-num, .connect-gh-total, .si-num, .sc-num, .gh-cell {
  font-family: var(--data);
  font-variant-numeric: tabular-nums;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: fixed; top: -100px; left: 16px; z-index: 200;
  background: var(--ink); color: var(--paper);
  padding: 10px 18px; border-radius: 8px;
  font-size: 14px; text-decoration: none;
  transition: top .2s ease;
}
.skip-link:focus { top: 16px; }

/* ===================== HEADER ===================== */
/* Progressive blur. Instead of one uniform translucent bar, three stacked
   backdrop layers each carry their own mask, so the veil is strongest at the
   viewport edge and dissolves to nothing at the bar's lower edge — content
   melts as it slides under rather than hitting a hard blurred brick. The
   paper tint rides the same layers, so it fades in step with the blur. */
#site-header {
  position: sticky; top: 0; z-index: 100;
  border-bottom: 1px solid var(--line);
}
.header-blur {
  position: absolute; inset: 0 0 -40px; /* bleed past the hairline into the page */
  pointer-events: none;
  z-index: 0;
}
.header-blur span {
  position: absolute; inset: 0;
  background: rgba(246,245,241,.54);
}
/* The ramp is tuned so the bar itself is as opaque as the flat veil it
   replaces: the three tints stack to ~.90 across the 64px bar, and every mask
   holds full strength until past the hairline. Only the 40px bleed below the
   hairline dissolves to nothing — that dissolve is the effect, so content
   emerges from the bar instead of being cut off by it. */
.header-blur span:nth-child(1) {
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}
.header-blur span:nth-child(2) {
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.92) 60%, transparent 88%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.92) 60%, transparent 88%);
}
.header-blur span:nth-child(3) {
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.8) 58%, transparent 78%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.8) 58%, transparent 78%);
}
.header-inner { position: relative; z-index: 1; }
/* No backdrop-filter (older Safari, locked-down build): fall back to a single
   flat translucent bar so the header stays legible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header-blur span { backdrop-filter: none; -webkit-backdrop-filter: none; mask-image: none; -webkit-mask-image: none; background: none; }
  .header-blur span:nth-child(2), .header-blur span:nth-child(3) { display: none; }
  .header-blur span:nth-child(1) { background: rgba(246,245,241,.94); }
}
.header-inner {
  max-width: var(--maxw); margin: 0 auto;
  padding: 0 var(--pad);
  height: 64px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}
.logo-box {
  font-family: var(--data);
  font-size: 15px; font-weight: 700; letter-spacing: .04em;
  color: var(--ink);
  white-space: nowrap;
}
.logo-box sup {
  font-size: 9px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent-deep);
  margin-left: 6px;
}
#site-header nav { display: flex; align-items: center; gap: 4px; }
#site-header nav a {
  font-size: 13.5px; font-weight: 500; color: var(--ink-soft);
  text-decoration: none; padding: 8px 12px; border-radius: 8px;
  transition: color .2s ease, background-color .2s ease;
}
#site-header nav a:hover { color: var(--ink); background: rgba(22,19,14,.05); }

.menu-toggle {
  display: none;
  background: none; border: 0; color: var(--ink);
  font-size: 22px; line-height: 1; padding: 8px;
}

.mobile-nav {
  position: fixed; top: 64px; left: 0; right: 0; z-index: 99;
  background: var(--paper-raise);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 20px 40px -24px rgba(22,19,14,.25);
  padding: 8px var(--pad) 16px;
  display: flex; flex-direction: column; gap: 2px;
  transform: translateY(-8px); opacity: 0; pointer-events: none;
  transition: transform .25s ease, opacity .25s ease;
}
.mobile-nav.open { transform: translateY(0); opacity: 1; pointer-events: auto; }
.mobile-link {
  font-size: 15px; font-weight: 500; color: var(--ink);
  text-decoration: none; padding: 12px 8px; border-radius: 8px;
}
.mobile-link:hover { background: rgba(22,19,14,.05); }

/* ===================== HERO ===================== */
#hero {
  position: relative; /* anchors the dot-grid backdrop pseudo below */
  max-width: var(--maxw); margin: 0 auto;
  padding: 72px var(--pad) 64px;
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 56px;
  align-items: start;
}

.hero-left { padding-top: 12px; }
.issue-tag {
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 18px;
  display: flex; align-items: center; gap: 10px;
}
.issue-tag::before {
  content: ""; width: 28px; height: 2px; background: var(--accent);
  border-radius: 2px;
}
.hero-h1 {
  font-size: clamp(44px, 6.4vw, 76px);
  font-weight: 800; letter-spacing: -.035em; line-height: 1.02;
  margin-bottom: 22px;
}
.hero-h1 em {
  font-style: italic; color: var(--accent-deep);
  font-weight: 800;
}
/* Kinetic hero headline: each line rises out of its own mask (the gsap
   signature move, vanilla). Pure CSS animation — it starts the moment the
   stylesheet applies, with no JS dependency, so it plays identically for
   no-JS visitors and never delays the headline behind script.js. The
   prefers-reduced-motion blocks below and in the global reduce section
   flatten it to instant. */
.hero-line {
  display: block;
  overflow: hidden;
  padding: .06em 0 .14em;  /* ascender/descender headroom inside the clip */
  margin: -.06em 0 -.14em; /* ...cancelled out, so line spacing is unchanged */
}
.hero-line-in { display: block; animation: hero-line-rise .55s cubic-bezier(.19, 1, .22, 1) .3s both; }
.hero-line:nth-child(2) .hero-line-in { animation-delay: .42s; }
@keyframes hero-line-rise {
  from { transform: translateY(122%); }
  to   { transform: translateY(0); }
}

/* The rest of the hero follows the headline on a fixed CSS beat. These
   elements are deliberately NOT in script.js's IO-driven fade-up list:
   stylesheet-driven timing keeps the entrance deterministic (and the LCP
   text never waits on JS). */
@media (prefers-reduced-motion: no-preference) {
  .issue-tag        { animation: hero-fade-in .45s ease .15s both; }
  .hero-sub         { animation: hero-fade-in .45s ease .42s both; }
  .hero-cta-row     { animation: hero-fade-in .45s ease .52s both; }
  .profile-kicker   { animation: hero-fade-in .45s ease .3s  both; }
  .hero-stat-block  { animation: hero-fade-in .45s ease .38s both; }
  .profile-pill-row { animation: hero-fade-in .45s ease .46s both; }
  .pull-quote       { animation: hero-fade-in .45s ease .54s both; }
}
@keyframes hero-fade-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hero-sub {
  font-size: 17.5px; line-height: 1.6; color: var(--ink-soft);
  max-width: 46ch; margin-bottom: 32px;
}
.hero-cta-row { display: flex; flex-wrap: wrap; gap: 14px; }

.btn-editorial {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: var(--ink);
  font-weight: 700; font-size: 15px; text-decoration: none;
  padding: 14px 26px; border-radius: 8px;
  border: 1px solid var(--accent);
  transition: transform .2s ease, box-shadow .2s ease;
}
.btn-editorial:hover { transform: translateY(-2px); box-shadow: 0 12px 24px -10px rgba(232,93,4,.45); }
.btn-editorial:active { transform: translateY(0) scale(.98); }

.btn-ghost-hero {
  display: inline-flex; align-items: center; gap: 10px;
  background: transparent; color: var(--ink);
  font-weight: 600; font-size: 15px; text-decoration: none;
  padding: 14px 26px; border-radius: 8px;
  border: 1px solid var(--line-strong);
  transition: border-color .2s ease, transform .2s ease;
}
.btn-ghost-hero:hover { border-color: var(--ink); transform: translateY(-2px); }
.btn-ghost-hero:active { transform: translateY(0) scale(.98); }

/* Profile card (hero right) */
.hero-right {
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 28px;
  display: flex; flex-direction: column; gap: 22px;
}
.profile-kicker {
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-mute);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.hero-stat-block { display: flex; }
.big-stat {
  padding-right: 22px;
  border-right: 1px solid var(--line);
}
.big-stat-last { flex: 1; }
.big-num {
  font-size: 30px; font-weight: 800; letter-spacing: -.02em;
  color: var(--ink);
  line-height: 1.15;
}
.big-desc { font-size: 13px; color: var(--ink-mute); margin-top: 4px; }

.profile-pill-row { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  font-family: var(--data);
  font-size: 12px; font-weight: 500;
  color: var(--ink-mute);
  border: 1px solid var(--line);
  border-radius: 999px; padding: 5px 13px;
}
.pill.active {
  color: var(--accent-deep);
  border-color: rgba(232,93,4,.4);
  background: var(--accent-soft);
}

.pull-quote {
  font-size: 17px; font-weight: 500; line-height: 1.5;
  color: var(--ink-soft);
  padding: 18px 20px;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 10px 10px 0;
}

/* ===================== CONNECT CARD ===================== */
.connect-section { border-top: 1px solid var(--line); }
.connect-inner { max-width: var(--maxw); margin: 0 auto; padding: 72px var(--pad); }
.connect-eyebrow {
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 20px;
}

.connect-card {
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.connect-tabs {
  position: relative;
  display: flex; gap: 4px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.connect-tabs::-webkit-scrollbar { display: none; }
.connect-tab {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 8px;
  background: none; border: 0;
  font-size: 13.5px; font-weight: 600; color: var(--ink-mute);
  padding: 10px 16px; border-radius: 8px;
  white-space: nowrap;
  transition: color .2s ease;
}
.connect-tab:hover { color: var(--ink); }
.connect-tab.active { color: var(--ink); }
.connect-tab svg.icon { color: var(--ink-mute); }
.connect-tab.active svg.icon { color: var(--accent-deep); }
.connect-indicator {
  position: absolute; z-index: 0; top: 10px; bottom: 10px;
  left: 0; width: 100%;
  background: var(--accent-soft);
  border: 1px solid rgba(232,93,4,.25);
  border-radius: 8px;
  transform-origin: left center;
  transform: translateX(0) scaleX(0);
  transition: transform .3s cubic-bezier(.32,.72,0,1);
}

.connect-body { padding: 26px 28px 30px; }
.connect-pane { display: none; }
.connect-pane.active { display: block; }
.connect-pane-label {
  font-family: var(--data);
  font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: 6px;
}
.connect-pane-title { font-size: 24px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 10px; }
.connect-pane-desc { font-size: 15px; color: var(--ink-soft); max-width: 58ch; }
.connect-gh-stats { color: var(--ink-mute); font-family: var(--data); font-size: 13.5px; }

.connect-gh-graph-wrap {
  margin: 18px 0 14px;
  overflow-x: auto; overflow-y: hidden;
  padding-bottom: 6px;
  scrollbar-width: thin;
}
.connect-gh-graph {
  --gh-cell: 9px; --gh-gap: 3px;
  display: flex; flex-direction: column; gap: 6px;
  width: fit-content; min-width: 100%;
}
.gh-months { position: relative; height: 14px; }
.gh-month-label {
  position: absolute; top: 0;
  font-family: var(--data);
  font-size: 10px; font-weight: 600;
  color: var(--ink-mute);
  white-space: nowrap;
  /* left is set per-label in JS: aligns with its month's first week column */
}
.gh-cells {
  display: grid;
  grid-template-rows: repeat(7, var(--gh-cell));
  grid-auto-columns: var(--gh-cell);
  grid-auto-flow: column;
  gap: var(--gh-gap);
  width: fit-content;
}
.gh-cell {
  width: var(--gh-cell); height: var(--gh-cell);
  border-radius: 2.5px;
  background: #eae6db;
  transition: transform .12s ease;
}
.gh-cell.lvl-1 { background: #f5c9a4; }
.gh-cell.lvl-2 { background: #f0a064; }
.gh-cell.lvl-3 { background: #e8730f; }
.gh-cell.lvl-4 { background: var(--accent-deep); }
.gh-cell:hover {
  transform: scale(1.3);
  outline: 1px solid rgba(22, 19, 14, .35);
}
.gh-loading { font-size: 13px; color: var(--ink-mute); padding: 12px 0; }
.connect-gh-total { font-size: 14px; color: var(--ink-soft); }

.connect-pane-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }
.connect-btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 600; text-decoration: none;
  padding: 11px 20px; border-radius: 8px;
  transition: transform .2s ease, background-color .2s ease, border-color .2s ease;
}
.connect-btn:active { transform: scale(.98); }
.connect-btn-solid {
  background: var(--accent); color: var(--ink);
  border: 1px solid var(--accent);
}
.connect-btn-solid:hover { transform: translateY(-1px); box-shadow: 0 8px 18px -8px rgba(232,93,4,.45); }
.connect-btn-ghost {
  background: transparent; color: var(--ink);
  border: 1px solid var(--line-strong);
}
.connect-btn-ghost:hover { border-color: var(--ink); }
.connect-btn-linkedin {
  background: #0a66c2; color: #fff;
  border: 1px solid #0a66c2;
}
.connect-btn-linkedin:hover { transform: translateY(-1px); }
.connect-pane-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.connect-chip {
  font-family: var(--data); font-size: 12px; font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px; padding: 5px 13px;
  background: var(--paper);
}
.connect-email-addr {
  font-family: var(--data); font-size: 18px; font-weight: 600;
  color: var(--ink); margin-top: 14px;
  padding: 12px 16px; background: var(--paper);
  border: 1px dashed var(--line-strong); border-radius: 8px;
  display: inline-block;
}

/* ===================== RULE / DIVIDER ===================== */
.rule-section {
  display: flex; align-items: center; gap: 20px;
  max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad) 56px;
}
.rule-line { flex: 1; height: 1px; background: var(--line); }
.rule-tag {
  font-family: var(--data);
  font-size: 11px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-mute); white-space: nowrap;
}

/* ===================== ABOUT + EDUCATION ===================== */
.two-col-layout {
  max-width: var(--maxw); margin: 0 auto;
  padding: 0 var(--pad) 88px;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 64px;
}
.big-heading {
  font-size: clamp(38px, 4.6vw, 54px);
  font-weight: 800; letter-spacing: -.03em; line-height: 1.04;
  margin-bottom: 28px;
  text-wrap: balance;
}
.about-body { font-size: 16px; color: var(--ink-soft); display: grid; gap: 18px; }
.about-body strong { color: var(--ink); font-weight: 700; }
.about-body em { color: var(--accent-deep); font-style: italic; }

.medium-callout {
  margin-top: 28px;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  background: var(--accent-soft);
  border: 1px solid rgba(232,93,4,.25);
  border-radius: 12px; padding: 18px 22px;
  flex-wrap: wrap;
}
.medium-callout-label {
  font-family: var(--data);
  font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent-deep); margin-bottom: 3px;
}
.medium-callout-desc { font-size: 14px; color: var(--ink-soft); max-width: 52ch; }
.medium-recent { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 7px; }
.medium-recent li { display: flex; align-items: baseline; gap: 10px; font-size: 13.5px; }
.medium-recent a { color: var(--ink); font-weight: 600; text-decoration: none; border-bottom: 1px solid rgba(232,93,4,.4); transition: color .2s ease, border-color .2s ease; }
.medium-recent a:hover { color: var(--accent-deep); border-color: var(--accent-deep); }
.medium-recent span { font-family: var(--data); font-size: 11px; font-weight: 600; color: var(--ink-mute); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.btn-medium {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 700; color: var(--accent-deep);
  text-decoration: none; white-space: nowrap;
  padding: 10px 6px;
  border-bottom: 2px solid var(--accent);
  transition: color .2s ease, border-color .2s ease;
}
.btn-medium:hover { color: var(--ink); border-color: var(--ink); }

/* Education aside */
.edu-aside {
  border-left: 1px solid var(--line);
  padding-left: 32px;
  display: flex; flex-direction: column; gap: 0;
}
.edu-entry {
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
}
.edu-entry:first-child { padding-top: 4px; }
.edu-entry-last { border-bottom: 0; }
.edu-year {
  font-family: var(--data);
  font-size: 12px; font-weight: 600; color: var(--accent-deep);
  letter-spacing: .04em; margin-bottom: 6px;
}
.edu-title { font-size: 17px; font-weight: 700; margin-bottom: 3px; }
.edu-school { font-size: 14px; color: var(--ink-soft); }
.edu-detail { font-size: 13px; color: var(--ink-mute); margin-top: 3px; }

/* ===================== EXPERIENCE ===================== */
.experience-section { border-top: 1px solid var(--line); background: var(--paper-raise); }
.experience-inner { max-width: var(--maxw); margin: 0 auto; padding: 88px var(--pad); }
.exp-header-row {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 20px;
  margin-bottom: 48px;
}
.section-h-light {
  font-size: clamp(34px, 4.2vw, 48px);
  font-weight: 800; letter-spacing: -.03em; line-height: 1.05;
}
.section-h-light em { font-style: italic; color: var(--accent-deep); }
.exp-count {
  font-size: 13px; font-weight: 600; color: var(--ink-mute);
  letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap;
}

.exp-timeline { display: flex; flex-direction: column; }
.exp-block {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: 40px;
}
.exp-meta { padding-top: 6px; }
.exp-date {
  font-family: var(--data);
  font-size: 13px; font-weight: 600; color: var(--accent-deep);
  margin-bottom: 4px;
}
.exp-location { font-size: 13px; color: var(--ink-mute); }
.exp-content { min-width: 0; }
.exp-company {
  font-family: var(--data);
  font-size: 12.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: 6px;
}
.exp-role { font-size: 24px; font-weight: 800; letter-spacing: -.02em; margin-bottom: 14px; }
.exp-bullets { list-style: none; display: grid; gap: 10px; margin-bottom: 18px; }
.exp-bullets li {
  position: relative; padding-left: 20px;
  font-size: 15px; color: var(--ink-soft);
}
.exp-bullets li::before {
  content: ""; position: absolute; left: 2px; top: 11px;
  width: 6px; height: 6px; border-radius: 2px;
  background: var(--accent);
}
.exp-tags { display: flex; flex-wrap: wrap; gap: 8px; }
.etag {
  font-family: var(--data); font-size: 12px; font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 4px 11px; background: var(--paper);
}
.exp-divider { height: 1px; background: var(--line); margin: 44px 0 44px 220px; }

/* ===================== PROJECTS ===================== */
.projects-section { border-top: 1px solid var(--line); }
.projects-inner { max-width: var(--maxw); margin: 0 auto; padding: 88px var(--pad); }
.proj-header-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
  margin-bottom: 40px;
}
.proj-h2 {
  font-size: clamp(34px, 4.2vw, 48px);
  font-weight: 800; letter-spacing: -.03em;
}
.proj-count-label {
  font-size: 13px; font-weight: 600; color: var(--ink-mute);
  letter-spacing: .06em; text-transform: uppercase;
}

.spot-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 0;
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.spot-index {
  border-right: 1px solid var(--line);
  padding: 10px;
  display: flex; flex-direction: column;
  background: var(--paper);
}
.spot-item {
  display: flex; align-items: center; gap: 14px;
  background: none; border: 0; text-align: left;
  padding: 13px 14px; border-radius: 8px;
  transition: background-color .2s ease;
}
.spot-item:hover { background: rgba(22,19,14,.04); }
.spot-item.active { background: var(--accent-soft); }
.si-num {
  font-size: 12px; font-weight: 700; color: var(--ink-mute);
  min-width: 22px;
  transition: opacity .3s ease;
}
.spot-item.active .si-num { color: var(--accent-deep); }
.si-title { font-size: 14.5px; font-weight: 600; color: var(--ink-soft); line-height: 1.35; }
.spot-item.active .si-title { color: var(--ink); }

.spot-panels { padding: 32px 34px; min-width: 0; }
.spot-card { display: none; }
.spot-card.active { display: block; animation: panel-in .35s ease both; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.sc-media { margin: 2px 0 16px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--paper); aspect-ratio: 16 / 9; }
.sc-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

.sc-top { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.sc-num {
  font-size: 13px; font-weight: 700; color: var(--accent-deep);
}
.sc-title { font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.proj-featured-badge {
  font-family: var(--data); font-size: 11.5px; font-weight: 600;
  color: var(--accent-deep);
  background: var(--accent-soft);
  border: 1px solid rgba(232,93,4,.25);
  border-radius: 999px; padding: 4px 12px;
  white-space: nowrap;
}
.sc-desc { font-size: 15px; color: var(--ink-soft); margin-bottom: 18px; max-width: 62ch; }
.sc-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.ptag {
  font-family: var(--data); font-size: 12px; font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 4px 11px; background: var(--paper);
}
.spot-links { display: flex; flex-wrap: wrap; gap: 18px; }
.spot-link {
  font-size: 14.5px; font-weight: 700; color: var(--accent-deep);
  text-decoration: none;
  border-bottom: 2px solid rgba(232,93,4,.35);
  transition: border-color .2s ease, color .2s ease;
}
.spot-link:hover { color: var(--ink); border-color: var(--ink); }
.spot-private {
  font-family: var(--data); font-size: 12.5px; font-weight: 500;
  color: var(--ink-mute); font-style: italic;
}
.spot-hint {
  margin-top: 18px; font-size: 12.5px; color: var(--ink-mute);
  font-family: var(--data);
}
.spot-autoplay-note { color: var(--accent-deep); font-weight: 600; }
/* Inactive index numbers dim while auto-rotation runs (JS toggles .rotating) */
.spot-wrap.rotating .spot-item:not(.active) .si-num { opacity: .35; }

/* ===================== ANALYTICS DASHBOARD ===================== */
.dash-section { border-top: 1px solid var(--line); background: var(--paper-raise); }
.dash-inner { max-width: var(--maxw); margin: 0 auto; padding: 88px var(--pad); }
.dash-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 40px; align-items: start;
  margin-bottom: 36px;
}
.dash-header-side { padding-top: 8px; }
.dash-intro { font-size: 15.5px; color: var(--ink-soft); margin-bottom: 14px; }
.dash-intro span { font-weight: 700; color: var(--ink); font-family: var(--data); }

/* The snapshot caveat. Rendered only when the store read failed and the section
   is showing its embedded snapshot, so it sits above the figures it qualifies
   (script.js sets the text and unsets [hidden]). Takes the accent-on-paper
   idiom the active filter uses, because it is a caveat about the numbers below
   and should be read before them, not discovered under them. */
.dash-snapshot-note {
  font-family: var(--data);
  font-size: 13px; font-weight: 600; line-height: 1.5;
  color: var(--accent-deep);
  background: var(--accent-soft);
  border: 1px solid rgba(232,93,4,.4);
  border-radius: 8px;
  padding: 10px 14px;
  margin: 0 0 24px;
}

.dash-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.dash-filter {
  font-family: var(--data);
  font-size: 13px; font-weight: 600; color: var(--ink-soft);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 16px;
  transition: border-color .2s ease, color .2s ease, background-color .2s ease;
}
.dash-filter:hover { border-color: var(--line-strong); }
.dash-filter.active {
  color: var(--ink);
  background: var(--accent-soft);
  border-color: rgba(232,93,4,.4);
}

.dash-metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px; margin-bottom: 16px;
}
.dash-card {
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 22px 24px;
}
.dash-metric-label {
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: 8px;
}
.dash-metric-value {
  font-size: 34px; font-weight: 800; letter-spacing: -.03em;
  color: var(--ink); line-height: 1.1;
}
.dash-metric-sub { font-size: 13px; color: var(--ink-mute); margin-top: 4px; }

.dash-charts {
  display: grid;
  /* Stacked full-width: the monthly trend (34 points) needs every pixel of
     the card — side by side it was crammed into ~600px of a 1440px screen. */
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}
.dash-chart-card { padding: 24px 26px; }
.dash-chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.dash-chart-title {
  font-family: var(--data); font-size: 13px; line-height: 16px;
  font-weight: 500; color: #333333;
}
.dash-chart-sub {
  font-family: var(--data); font-size: 12px; line-height: 16px;
  font-weight: 500; color: #6f6f6f;
}
.dash-chart-figure { position: relative; min-height: 200px; }
.dash-chart-figure svg { display: block; width: 100%; height: auto; }

/* Line chart — explicit SVG styles (the analyst-report CSS rewrite dropped
   these, leaving unstyled black fills and 16px labels). Axis ticks at 11px:
   intentional density exception to the 12/16 label token. */
.dash-grid-line { stroke: #e9e4db; stroke-width: 1; }
.dash-y-label,
.dash-x-label {
  font-family: var(--data); font-size: 11px; font-weight: 500;
  fill: #6f6f6f; font-variant-numeric: tabular-nums;
}
.dash-line-path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dash-area-path { fill: url(#dashLineGrad); }
.dash-dot { fill: var(--accent); stroke: #ffffff; stroke-width: 1.5; }
.dash-hover-line {
  stroke: var(--accent); stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0; transition: opacity .15s ease;
}
.dash-hover-dot {
  fill: #ffffff; stroke: var(--accent); stroke-width: 2;
  opacity: 0; transition: opacity .15s ease;
}

.dash-tooltip {
  position: absolute;
  transform: translate(-50%, calc(-100% - 10px));
  pointer-events: none;
  background: #333333; color: #ffffff;
  font-family: var(--data); font-size: 11px; line-height: 16px;
  font-weight: 500; font-variant-numeric: tabular-nums;
  padding: 4px 9px; border-radius: 6px;
  white-space: nowrap; z-index: 5;
  box-shadow: 0 4px 14px rgba(22,19,14,.22);
}
.dash-tooltip[hidden] { display: none; }

/* Bar chart — vertical columns (JS grows scaleY from the bottom and floats
   each value above the bar tip via an inline bottom offset). */
.dash-bar-figure {
  height: 220px;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding-top: 26px;
}
.dash-bar-col {
  flex: 1;
  height: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}
.dash-bar-area {
  position: relative;
  flex: 1;
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.dash-bar {
  position: relative;
  width: 100%;
  max-width: 56px;
  height: 100%;
  transform: scaleY(0);
  transform-origin: bottom;
  background: var(--accent);
  border-radius: 6px 6px 2px 2px;
  transition: transform .6s cubic-bezier(.22,1,.36,1), background .2s ease;
}
.dash-bar:hover { background: color-mix(in srgb, var(--accent) 82%, var(--ink)); }
.dash-bar-val {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--data); font-size: 11px; line-height: 14px;
  font-weight: 600; color: #6f6f6f;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* bottom is set per-bar in JS: sits just above the bar's visual top */
}
.dash-bar-col:hover .dash-bar-val { color: var(--accent-deep); }
.dash-bar-genre {
  margin-top: 8px;
  font-family: var(--data); font-size: 12px; line-height: 16px;
  font-weight: 500; color: #6f6f6f;
  text-align: center;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===================== SKILLS ===================== */
.skills-full-section { border-top: 1px solid var(--line); }
.skills-full-inner { max-width: var(--maxw); margin: 0 auto; padding: 88px var(--pad); }
.skills-two-col {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 48px;
}
.skills-col-label {
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 16px;
}
.skills-chip-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.skill-chip {
  font-family: var(--data); font-size: 13px; font-weight: 500;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 999px; padding: 8px 17px;
  background: var(--paper-raise);
  transition: border-color .2s ease, color .2s ease;
}
.skill-chip:hover { border-color: var(--line-strong); color: var(--ink); }
.expert-chip {
  color: var(--accent-deep);
  border-color: rgba(232,93,4,.4);
  background: var(--accent-soft);
  font-weight: 600;
}

/* ===================== CERTIFICATES ===================== */
.certs-section { border-top: 1px solid var(--line); background: var(--paper-raise); }
.certs-inner { max-width: var(--maxw); margin: 0 auto; padding: 88px var(--pad); }
.cert-grid {
  margin-top: 40px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.cert-card {
  display: block;
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  text-decoration: none;
  box-shadow: 0 1px 2px rgba(22,19,14,.04);
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.cert-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-card);
  border-color: rgba(232,93,4,.35);
}
.cert-img-wrap { aspect-ratio: 16/9; overflow: hidden; background: var(--paper); }
.cert-img-wrap img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.cert-card:hover .cert-img-wrap img { transform: scale(1.04); }
.cert-info { padding: 14px 18px 16px; }
.cert-issuer {
  font-family: var(--data);
  font-size: 11px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: 3px;
}
.cert-name { font-size: 16px; font-weight: 700; }
.cert-more-card .cert-name { color: var(--accent-deep); }

/* ===================== FOOTER ===================== */
#contact {
  border-top: 1px solid var(--line);
  max-width: var(--maxw); margin: 0 auto;
  padding: 88px var(--pad) 0;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 56px;
}
.footer-h3 {
  font-size: clamp(36px, 4.4vw, 52px);
  font-weight: 800; letter-spacing: -.03em; line-height: 1.05;
  margin-bottom: 16px;
}
.footer-sub { font-size: 15.5px; color: var(--ink-soft); margin-bottom: 28px; }
.btn-footer-contact {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: var(--ink);
  font-weight: 700; font-size: 15px; text-decoration: none;
  padding: 14px 26px; border-radius: 8px;
  border: 1px solid var(--accent);
  transition: transform .2s ease, box-shadow .2s ease;
}
.btn-footer-contact:hover { transform: translateY(-2px); box-shadow: 0 12px 24px -10px rgba(232,93,4,.45); }
.btn-footer-contact:active { transform: translateY(0) scale(.98); }

.footer-right { display: flex; flex-direction: column; gap: 26px; }
.footer-links-block { display: flex; flex-direction: column; gap: 8px; }
.footer-links-label {
  font-family: var(--data);
  font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-mute); margin-bottom: 6px;
}
.footer-link {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 500; color: var(--ink-soft);
  text-decoration: none; width: fit-content;
  transition: color .2s ease;
}
.footer-link:hover { color: var(--ink); }
.footer-link svg.icon { color: var(--accent-deep); width: 18px; height: 14px; }
.footer-link-accent { color: var(--accent-deep); font-weight: 700; }
.footer-resume-note { font-size: 12.5px; color: var(--ink-mute); }
.footer-copy {
  font-family: var(--data); font-size: 12.5px; color: var(--ink-mute);
  margin-top: auto; padding-top: 16px;
}

.footer-grey {
  grid-column: 1 / -1;
  margin-top: 56px;
  background: var(--paper-raise);
  border: 1px solid var(--line);
  border-top-left-radius: 14px; border-top-right-radius: 14px;
  padding: 36px 40px;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) auto auto;
  gap: 48px; align-items: start;
}
.footer-grey-label {
  font-family: var(--data);
  font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent-deep); margin-bottom: 12px;
}
.footer-grey-title {
  font-size: 26px; font-weight: 800; letter-spacing: -.02em; line-height: 1.15;
  margin-bottom: 10px;
}
.footer-grey-body { font-size: 14px; color: var(--ink-soft); max-width: 44ch; }
.footer-grey-stat-row { display: flex; gap: 34px; padding-top: 6px; }
.footer-grey-num {
  font-size: 30px; font-weight: 800; letter-spacing: -.02em;
  color: var(--ink);
}
.footer-grey-stat-label {
  font-family: var(--data); font-size: 12px; color: var(--ink-mute);
  margin-top: 2px;
}
/* ===================== OPENING SPLASH ===================== */
/* A one-shot paper curtain: the PS mark, wordmark and rule assemble, then the
   panel dissolves. Transform/opacity only, and it hides itself from CSS alone
   (splash-out ends at opacity 0 / visibility hidden), so a visitor whose
   script never ran is never trapped behind it. script.js only removes the
   node a beat later and skips the curtain on a repeat visit. */
/* Holds the page still while the curtain plays. Taking the viewport scrollbar
   away for those two seconds would widen the layout by its width and pop every
   centred element sideways the instant the curtain lifts, so script.js pays
   the scrollbar back with an equal padding-right (see the splash controller).
   `scrollbar-gutter: stable` cannot stand in for it: Chrome does not reserve
   the gutter for a viewport whose overflow propagated as hidden. */
body.is-splashing { overflow: hidden; }
#splash {
  position: fixed; inset: 0; z-index: 9999;
  display: grid; place-items: center;
  background: var(--paper);
  animation: splash-out .5s cubic-bezier(.76,0,.24,1) .7s forwards;
}
.splash-stage { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.splash-mark {
  width: 62px; height: 62px;
  display: grid; place-items: center;
  background: var(--ink); color: var(--paper);
  font-family: var(--data); font-size: 22px; font-weight: 700;
  letter-spacing: .04em;
  animation: splash-mark .45s cubic-bezier(.22,1,.36,1) both;
}
.splash-name {
  font-family: var(--data); font-size: 13px; font-weight: 600;
  letter-spacing: .34em; text-transform: uppercase; color: var(--ink);
  padding-left: .34em; /* offsets the trailing letter-space so it reads centred */
  animation: splash-rise .4s cubic-bezier(.22,1,.36,1) .08s both;
}
.splash-rule {
  width: 54px; height: 2px; background: var(--accent);
  animation: splash-rule .4s cubic-bezier(.22,1,.36,1) .18s both;
}
.splash-kicker {
  font-size: 11px; font-weight: 500; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-mute);
  animation: splash-rise .4s cubic-bezier(.22,1,.36,1) .26s both;
}
@keyframes splash-mark { from { opacity: 0; transform: scale(.82) rotate(-6deg); } to { opacity: 1; transform: none; } }
@keyframes splash-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes splash-rule { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: scaleX(1); } }
@keyframes splash-out { to { opacity: 0; visibility: hidden; transform: translateY(-2%) scale(1.015); } }
@media (prefers-reduced-motion: reduce) { #splash { display: none; } }

/* ===================== EDGE BLUR ===================== */
/* Bottom-of-viewport progressive blur — the same layered, masked-blur trick as
   the header, here hinting at the report below the fold. script.js owns the
   opacity: it stays off until scroll is confirmed, turns off again at the end
   of the page, and steps aside for a focused field, so it never sits over the
   footer or a form being typed into. */
.edge-blur {
  position: fixed; left: 0; right: 0; bottom: 0; height: 96px;
  z-index: 90; pointer-events: none;
  opacity: 0; transition: opacity .3s ease;
}
.edge-blur span { position: absolute; inset: 0; }
.edge-blur span:nth-child(1) {
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  mask-image: linear-gradient(to top, #000 0%, transparent 62%);
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 62%);
}
.edge-blur span:nth-child(2) {
  backdrop-filter: blur(11px) saturate(140%);
  -webkit-backdrop-filter: blur(11px) saturate(140%);
  mask-image: linear-gradient(to top, #000 0%, transparent 34%);
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 34%);
}

/* ===================== REVEAL MOTION ===================== */
.fade-up {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .7s cubic-bezier(.32,.72,0,1),
              transform .7s cubic-bezier(.32,.72,0,1);
  will-change: opacity, transform;
}
.fade-up.visible { opacity: 1; transform: translateY(0); }

/* ===================== RESPONSIVE ===================== */
@media (max-width: 1024px) {
  #hero { grid-template-columns: 1fr; gap: 40px; }
  .two-col-layout { grid-template-columns: 1fr; gap: 44px; }
  .dash-metrics { grid-template-columns: repeat(2, 1fr); }
  .dash-header { grid-template-columns: 1fr; gap: 16px; }
  .exp-block { grid-template-columns: 1fr; gap: 12px; }
  .exp-divider { margin-left: 0; }
  .spot-wrap { grid-template-columns: 1fr; }
  .spot-index { border-right: 0; border-bottom: 1px solid var(--line); flex-direction: row; flex-wrap: wrap; }
  .spot-item { padding: 10px 14px; }
  .cert-grid { grid-template-columns: repeat(2, 1fr); }
  .skills-two-col { grid-template-columns: 1fr; gap: 32px; }
  /* minmax(0,…): bare 1fr lets wide content (resume CTAs, stat rows) force
     the footer past the viewport and give the page a sideways scroll */
  #contact { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .footer-grey { grid-template-columns: minmax(0, 1fr); gap: 28px; }
}

@media (max-width: 640px) {
  #site-header nav { display: none; }
  .menu-toggle { display: block; }
  #hero { padding: 48px var(--pad) 48px; }
  .hero-h1 { font-size: clamp(38px, 11vw, 52px); }
  .dash-metrics { grid-template-columns: 1fr; }
  .dash-chart-figure { overflow-x: auto; }
  /* Keep the SVG legible on phones: the viewBox is pixel-space with a 540px
     floor (script.js), and this min-width is that floor — below it the card
     scrolls instead of crushing the chart. */
  .dash-chart-figure svg { min-width: 540px; }
  /* Same idea for the bar chart: give each column enough room for its
     genre label and scroll the card instead of crushing them */
  .dash-bar-figure .dash-bar-col { min-width: 78px; }
  .cert-grid { grid-template-columns: 1fr; }
  .connect-body { padding: 22px 18px 24px; }
  .spot-panels { padding: 24px 20px; }
  .rule-section { flex-direction: column; gap: 12px; padding-bottom: 40px; }
}

/* ===================== REDUCED MOTION ===================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .fade-up, .fade-up.visible {
    opacity: 1; transform: none; transition: none; will-change: auto;
  }
  .hero-line-in { animation: none !important; }
}

/* ===================== ANTIGRAVITY DEPTH ===================== */
/* Floating, weightless surfaces with spatial hover. GPU-only (transform/shadow). */
@media (prefers-reduced-motion: no-preference) {
  .dash-card, .dash-chart-card, .cert-card, .connect-card {
    transition: transform .35s cubic-bezier(.22,.61,.36,1),
                box-shadow .35s cubic-bezier(.22,.61,.36,1),
                border-color .35s ease;
    will-change: transform;
  }
  .dash-card:hover, .dash-chart-card:hover, .cert-card:hover, .connect-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 2px 4px rgba(22,19,14,.05),
                0 20px 44px -18px rgba(22,19,14,.24);
    border-color: color-mix(in srgb, var(--ink) 16%, var(--line));
  }
}

/* ===================== COMPONENT POLISH ===================== */
/* Upgrades borrowed from the Oct 2026 reel stack (gsap.com / threeui.com /
   stackkit.dev / 21st.dev), rebuilt as vanilla CSS+JS so the strict CSP
   keeps holding: a skills ticker, cursor tilt + glare on certificate cards,
   a soft sheen on dashboard cards, a nav underline slide, a live-source
   ping ring, button icon nudges, a hero dot-grid and numbered kickers.
   All of it is transform/opacity only and switches off for touch devices
   and prefers-reduced-motion. */

/* — Skills ticker (between hero and connect) — */
.skill-ticker {
  border-top: 1px solid var(--line);
  overflow: hidden;
  padding: 13px 0 12px;
}
.skill-ticker-track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 36s linear infinite;
}
.skill-ticker:hover .skill-ticker-track { animation-play-state: paused; }
.skill-ticker-seq {
  display: flex; align-items: center; gap: 30px;
  font-family: var(--data);
  font-size: 12px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-mute);
  white-space: nowrap;
}
.skill-ticker-seq span::after {
  content: "✦";
  margin-left: 30px;
  color: var(--accent);
  font-size: 10px;
}
@keyframes ticker-scroll { to { transform: translateX(-50%); } }

/* — Numbered section kickers — */
.section-kicker {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--data);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 16px;
}
.section-kicker::before {
  content: ""; width: 28px; height: 2px; border-radius: 2px;
  background: var(--accent);
}
.section-kicker b { color: var(--accent-deep); font-weight: 700; }

/* — Hero dot-grid backdrop — */
#hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background-image: radial-gradient(rgba(22,19,14,.10) 1px, transparent 1.4px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(620px 420px at 76% 6%, #000, transparent 72%);
  mask-image: radial-gradient(620px 420px at 76% 6%, #000, transparent 72%);
}

/* — Nav underline slide — */
#site-header nav a { position: relative; }
#site-header nav a::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px;
  height: 2px; border-radius: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform .25s cubic-bezier(.22,1,.36,1);
}
#site-header nav a:hover::after { transform: scaleX(1); }

/* — Button icon nudge — */
.btn-editorial svg.icon, .btn-ghost-hero svg.icon, .btn-footer-contact svg.icon {
  transition: transform .2s ease;
}
.btn-editorial:hover svg.icon, .btn-ghost-hero:hover svg.icon, .btn-footer-contact:hover svg.icon {
  transform: translateX(3px);
}

/* — Certificate cards: cursor tilt + glare (pointer devices only; JS drives
     the tilt and glare custom properties, CSS only reads them) — */
.cert-card {
  position: relative;
  transform: perspective(800px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: transform .18s ease-out, box-shadow .35s ease, border-color .35s ease;
  will-change: transform;
}
.cert-card:hover {
  transform: perspective(800px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) translateY(-5px);
}
.cert-card::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  border-radius: inherit; pointer-events: none;
  background: radial-gradient(240px circle at var(--glare-x, 50%) var(--glare-y, 40%), rgba(255,255,255,.34), transparent 65%);
  opacity: 0; transition: opacity .25s ease;
}
.cert-card:hover::after { opacity: 1; }

/* — Dashboard cards: soft cursor-tracked sheen (no tilt; charts stay flat) — */
.dash-card { position: relative; }
.dash-card::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  border-radius: inherit; pointer-events: none;
  background: radial-gradient(280px circle at var(--glare-x, 50%) var(--glare-y, -30%), rgba(232,93,4,.07), transparent 62%);
  opacity: 0; transition: opacity .3s ease;
}
.dash-card:hover::after { opacity: 1; }

/* - Inline icon SVGs: Font Awesome 6 path data inlined; replaces the
     ~290KB Font Awesome CSS + webfonts from the CDN. The 1em box tracks
     the surrounding font-size exactly like the old <i> glyphs did. - */
svg.icon {
  width: 1em; height: 1em;
  display: inline-block;
  fill: currentColor;
  vertical-align: -.125em;
  flex: none;
}

/* — Touch devices / reduced motion: tilt, glare and ticker off — */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .cert-card, .cert-card:hover { transform: none; }
  .cert-card::after, .dash-card::after { display: none; }
  .skill-ticker-track { animation: none; }
}
