/* AQcredix — founder portfolio.
   Theme tokens throughout; no hardcoded colour inside any media query. */

/* ---------------------------------- hero ---------------------------------- */

.fp-hero {
  background: var(--bg-deep-2);
  color: #fff;
  padding: 64px 0 48px;
  position: relative;
  overflow: hidden;
}
/* Stacked and centred: portrait, then name, then the rest. A max-width on the text keeps
   the measure readable — centred prose running the full page width is hard to track,
   because the eye loses the start of each line. */
.fp-hero-grid {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 22px;
}
/* The text block must CENTRE ITSELF as well as centre its text. As a flex child it is
   sized to content, so text-align alone left the block flush left and only centred the
   lines within their own box — which is what the screenshot showed. width:100% plus auto
   margins puts the box in the middle; text-align on the children does the rest.
   Everything is forced because .eyebrow is inline-flex and .fp-role/.fp-loc carry their
   own alignment from the shared stylesheet. */
.fp-hero-text {
  max-width: 62ch;
  width: 100%;
  margin-inline: auto;
  text-align: center;
}
.fp-hero-text > *,
.fp-hero-text h1,
.fp-hero-text .fp-role,
.fp-hero-text .fp-loc,
.fp-hero-text .fp-affil { text-align: center; }

/* The eyebrow is inline-flex with a leading dash rule, so it needs centring as a box. */
.fp-hero-text .eyebrow { display: inline-flex; justify-content: center; }

/* The post-nominals sit on their own centred line under the name rather than trailing it. */
.fp-hero-text h1 .fp-post { display: block; white-space: normal; margin-top: 4px; }

.fp-photo {
  width: 190px;
  height: 190px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid var(--accent-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .05);
  transition: transform 220ms ease;
  will-change: transform;
}
.fp-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fp-initials {
  font-family: var(--font-display);
  font-size: 58px;
  font-weight: 700;
  color: var(--accent-bright);
  letter-spacing: .02em;
}

.fp-hero h1 {
  font-size: clamp(28px, 4.4vw, 46px);
  letter-spacing: -.03em;
  margin: 10px 0 8px;
  line-height: 1.08;
}
.fp-post {
  font-size: .52em;
  font-weight: 600;
  color: var(--accent-bright);
  letter-spacing: 0;
  white-space: nowrap;
}
.fp-role { font-size: 16px; color: rgba(255, 255, 255, .86); margin-bottom: 4px; }
.fp-loc { font-size: 13.5px; color: rgba(255, 255, 255, .58); margin-bottom: 16px; }

.fp-tags { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 20px; justify-content: center; }
.fp-tag {
  font-size: 11.5px;
  font-weight: 600;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .14);
  color: rgba(255, 255, 255, .88);
}
.fp-links { display: flex; gap: 9px; flex-wrap: wrap; justify-content: center; }

/* Counters. Tabular figures so the width does not jitter while the number climbs. */
.fp-statband {
  width: 100%;
  text-align: center;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin-top: 42px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, .12);
}
.fp-stat .n {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 700;
  color: var(--accent-bright);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.fp-stat .l {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: rgba(255, 255, 255, .6);
  margin-top: 7px;
  display: block;
}

/* ------------------------------ scrolly card ------------------------------ */

.fp-lens { background: var(--bg-deep-1, var(--bg-deep-2)); color: #fff; padding: 70px 0; }
.fp-card {
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .04);
  padding: 28px;
  position: relative;
  min-height: 300px;
}
/* Faces share one box and cross-fade, so the pinned card never changes height. */
.fp-face {
  opacity: 0;
  visibility: hidden;
  position: absolute;
  inset: auto 28px auto 28px;
  transition: opacity 460ms ease;
}
[data-stage="0"] .fp-face[data-face="0"],
[data-stage="1"] .fp-face[data-face="1"],
[data-stage="2"] .fp-face[data-face="2"] {
  opacity: 1;
  visibility: visible;
  position: relative;
  inset: auto;
}
.fp-card h4 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent-bright);
  margin-bottom: 12px;
}
.fp-card p { font-size: 14.5px; line-height: 1.65; color: rgba(255, 255, 255, .82); }
.fp-face-list { list-style: none; padding: 0; margin: 16px 0 0; display: grid; gap: 8px; }
.fp-face-list li {
  font-size: 13.5px;
  padding-left: 18px;
  position: relative;
  color: rgba(255, 255, 255, .92);
}
.fp-face-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 7px;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--accent-bright);
}

/* ---------------------------- centre timeline ----------------------------
   Three columns: card | spine | card. Entries alternate sides so the section fills the
   full width rather than hugging one margin, and the travelling light runs up the middle.
   The side is set by a class from JS, not :nth-child — the education list restarts the
   sequence and CSS counting would put two entries on the same side across the two lists. */

.fp-timeline { position: relative; padding: 8px 0; }

/* The unlit track. The lit portion is .fp-spine, drawn over it by founder-motion.js. */
.fp-timeline::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: var(--border);
}

.fp-item {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 64px 1fr;
  align-items: center;
  margin-bottom: 34px;
}

/* Each entry occupies one side; the opposite cell stays empty so the spine is never
   crowded and the eye can follow it straight down. */
.fp-item.is-right .fp-item-card { grid-column: 3; text-align: left; }
.fp-item.is-right .fp-item-year { grid-column: 1; text-align: right; }
.fp-item.is-left  .fp-item-card { grid-column: 1; text-align: right; }
.fp-item.is-left  .fp-item-year { grid-column: 3; text-align: left; }
.fp-node { grid-column: 2; display: flex; justify-content: center; }

.fp-item-card {
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  /* Entries fade in as they reach the reading line and fade back as they leave, so the
     eye is always drawn to the one the light is passing. */
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 620ms cubic-bezier(.22,.61,.36,1),
              transform 620ms cubic-bezier(.22,.61,.36,1),
              border-color 400ms ease;
}
.fp-item.is-right .fp-item-card { transform: translate(26px, 22px); }
.fp-item.is-left  .fp-item-card { transform: translate(-26px, 22px); }
.fp-item.is-lit .fp-item-card {
  opacity: 1;
  transform: none;
  border-color: var(--brand-2);
}
/* Seen but no longer at the reading line: still legible, no longer competing. */
.fp-item.is-seen .fp-item-card { opacity: .55; transform: none; }

.fp-item-card h4 { margin: 0 0 3px; font-size: 16px; }
.fp-when { font-family: var(--font-mono); font-size: 11.5px; color: var(--fg-faint); margin-bottom: 5px; }
.fp-now { font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 999px;
  background: var(--brand-tint); color: var(--brand-2); margin-left: 5px; }
.fp-org { font-size: 14px; color: var(--brand-2); font-weight: 600; }
.fp-type { font-size: 12.5px; color: var(--fg-faint); margin-top: 2px; }
.fp-item-card p { font-size: 13.5px; color: var(--fg-muted); margin-top: 8px; line-height: 1.6; }

.fp-item-year {
  font-family: var(--font-display);
  font-size: clamp(26px, 4vw, 44px);
  font-weight: 700;
  letter-spacing: -.03em;
  color: var(--border-strong, var(--border));
  line-height: 1;
  padding: 0 22px;
  transition: color 420ms ease, opacity 420ms ease;
  opacity: .5;
}
.fp-item.is-lit .fp-item-year { color: var(--brand-2); opacity: 1; }
.fp-item.is-seen .fp-item-year { opacity: .45; }

.fp-dot {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border);
  transition: background 320ms ease, border-color 320ms ease, box-shadow 320ms ease,
              transform 320ms cubic-bezier(.34,1.56,.64,1);
}
.fp-item.is-lit .fp-dot {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  box-shadow: 0 0 16px 3px var(--accent-bright);
  transform: scale(1.35);
}
.fp-item.is-seen .fp-dot { background: var(--brand-2); border-color: var(--brand-2); }

/* ------------------------------ peer review ------------------------------ */

.fp-review { background: var(--brand-tint); }
.fp-review-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.fp-journal-card {
  padding: 26px;
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  position: relative;
}
.fp-q {
  position: absolute;
  top: 20px;
  right: 20px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--ok-tint, var(--brand-tint));
  color: var(--ok, var(--brand-2));
}
.fp-journal-card h3 { font-size: 18px; margin: 0 0 6px; padding-right: 54px; }
.fp-pub-by { font-size: 13px; color: var(--brand-2); font-weight: 700; margin-bottom: 10px; }
.fp-journal-card p { font-size: 14px; color: var(--fg-muted); line-height: 1.6; }

/* ----------------------------- publications ----------------------------- */

.fp-pubs { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.fp-pub {
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg-elevated);
  position: relative;
}
.fp-pub-n {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--fg-faint);
  margin-bottom: 8px;
}
.fp-pub h4 { font-size: 15.5px; line-height: 1.4; margin: 0 0 8px; }
.fp-journal { font-size: 13px; color: var(--brand-2); font-weight: 600; }
.fp-date { color: var(--fg-faint); font-weight: 400; }
.fp-pub p { font-size: 13.5px; color: var(--fg-muted); margin-top: 10px; line-height: 1.6; }

.fp-project {
  margin-top: 22px;
  padding: 26px;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
  background: var(--accent-bright-tint);
}
.fp-project h4 { font-size: 17px; margin: 10px 0 10px; }
.fp-project p { font-size: 14px; line-height: 1.7; color: var(--fg-muted); }

/* ---------------------------- certifications ---------------------------- */

.fp-certs-band { background: var(--bg-elevated); }
.fp-certs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.fp-cert {
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg);
}
.fp-cert h5 { font-size: 14px; margin: 0 0 6px; line-height: 1.4; }
.fp-issuer { font-size: 12.5px; color: var(--brand-2); font-weight: 600; }
.fp-cert-meta { font-size: 11.5px; color: var(--fg-faint); margin-top: 5px; }

.fp-affil { font-size: 12.5px; color: rgba(255, 255, 255, .5); margin-bottom: 14px; }

/* The two flagged credentials, given room. */
.fp-certs-top { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 18px; }
.fp-cert-top {
  padding: 24px;
  border-color: var(--brand-2);
  background: var(--brand-tint);
  position: relative;
}
.fp-cert-badge {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--brand-2);
  margin-bottom: 9px;
}
.fp-cert-top h5 { font-size: 16.5px; line-height: 1.35; }
.fp-cert-top p { font-size: 13px; color: var(--fg-muted); margin: 9px 0 0; line-height: 1.6; }
.fp-cert-note { font-size: 12px; color: var(--fg-muted); margin: 7px 0 0; line-height: 1.55; }

.fp-skills { display: flex; flex-wrap: wrap; gap: 9px; }
.fp-skill {
  font-size: 13px;
  font-weight: 600;
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--fg-muted);
  transition: transform 180ms ease, border-color 180ms ease, color 180ms ease;
}
.fp-skill:hover {
  border-color: var(--brand-2);
  color: var(--brand-2);
  transform: translateY(-2px);
}

.fp-cta {
  text-align: center;
  padding: 52px 26px;
  border-radius: var(--r-xl);
  background: var(--brand-tint);
  border: 1px solid var(--border);
}
.fp-cta h2 { font-size: clamp(22px, 3vw, 32px); margin-bottom: 12px; }
.fp-cta p {
  color: var(--fg-muted);
  max-width: 56ch;
  margin: 0 auto 22px;
  font-size: 15px;
}

/* -------------------------------- 3D tilt --------------------------------
   Pointer-only; scrolly.js and founder.js both refuse to bind this on touch. The sheen
   follows --mx/--my, written by JS once per frame. */
html.fp-tilt-on [data-tilt] {
  transition: transform 260ms cubic-bezier(.22, .61, .36, 1), box-shadow 260ms ease;
  transform-style: preserve-3d;
}
html.fp-tilt-on [data-tilt].is-tilting {
  transition: transform 60ms linear, box-shadow 260ms ease;
  box-shadow: var(--shadow-2);
  z-index: 2;
}
html.fp-tilt-on [data-tilt]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 260ms ease;
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%),
              rgba(255, 255, 255, .16), transparent 55%);
}
html.fp-tilt-on [data-tilt].is-tilting::after { opacity: 1; }

/* --------------------------------- mobile ---------------------------------
   Layout only. No colours here, so mobile keeps inheriting every palette fix. */
/* ===================== scroll-linked timeline spine ===================== */
/* The lit portion, drawn down the CENTRE over the track. Scaled by founder-motion.js from
   scroll position, so stopping halfway leaves it halfway. */
.fp-spine { position: absolute; left: 50%; margin-left: -1px; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, var(--brand-2), var(--accent-bright));
  transform-origin: top; transform: scaleY(0); }
/* The travelling head: a glow riding the end of the drawn line. */
.fp-spine::after { content: ""; position: absolute; left: -5px; bottom: -6px;
  width: 12px; height: 12px; border-radius: 50%; background: var(--accent-bright);
  box-shadow: 0 0 18px 5px var(--accent-bright); }

/* ===================== publications =====================
   STACKED IS THE DEFAULT. The horizontal reel is opt-in below, and only for devices with
   a real pointer.

   WHY NOT A WIDTH QUERY. Chrome's "Desktop site" toggle makes an Android phone report a
   ~1024px viewport, so every max-width query sees a laptop and the reel came back on a
   phone that had explicitly been told to stack. Width describes the window; it says
   nothing about what is holding the device. `hover: hover` and `pointer: fine` describe
   the INPUT, and a touchscreen reports coarse in desktop mode too — so this is the only
   signal that survives the toggle.

   Defaulting to stacked also means any browser that reports neither gets the readable
   layout rather than a pinned rail it cannot drive. */
.fp-reel { height: auto; position: relative; }
.fp-reel-pin { position: static; height: auto; overflow: visible; display: block; }
.fp-reel-rail { display: block; }
.fp-reel-rail .fp-pub { width: 100%; margin-bottom: 12px; border-radius: var(--r-md); }
.fp-reel-rail .fp-pub:last-child { margin-bottom: 0; }
/* Both describe an interaction that does not exist in the stacked layout. */
.fp-reel-bar, .fp-reel-hint { display: none; }

/* ---- the reel proper: pointer devices only ---- */
@media (hover: hover) and (pointer: fine) and (min-width: 901px) {
  .fp-reel { height: var(--fp-reel-h, 200vh); }
  .fp-reel-pin { position: sticky; top: 96px; height: 76vh; overflow: hidden;
    display: flex; flex-direction: column; justify-content: center; }
  .fp-reel-rail { display: flex; gap: 18px; will-change: transform; }
  .fp-reel-rail .fp-pub { flex: 0 0 340px; width: auto; margin-bottom: 0;
    border-radius: var(--r-lg); }
  .fp-reel-bar { display: block; height: 3px; background: var(--border);
    border-radius: 2px; margin-top: 20px; }
  .fp-reel-bar span { display: block; height: 100%; border-radius: 2px;
    background: var(--brand-2); transform-origin: left; transform: scaleX(0); }
  .fp-reel-hint { display: block; font-size: 11.5px; color: var(--fg-faint);
    margin-top: 9px; text-transform: uppercase; letter-spacing: .07em; }
}

/* ===================== staggered entrance ===================== */
.fp-pubs > *, .fp-certs > *, .fp-certs-top > *, .fp-skills > * {
  opacity: 0; transform: translateY(16px);
  transition: opacity 560ms ease var(--fp-stagger, 0ms),
              transform 560ms cubic-bezier(.22,.61,.36,1) var(--fp-stagger, 0ms); }
.fp-stagger-in > * { opacity: 1; transform: none; }

.is-magnetic { transition: transform 90ms linear !important; }

/* ------------------------------- tablets -------------------------------
   Alternating survives here: a 768px tablet gives each card ~300px, which is enough to
   read. Only the year column shrinks, since it was sized for a desktop measure. */
@media (max-width: 900px) {
  .fp-item { grid-template-columns: 1fr 40px 1fr; margin-bottom: 26px; }
  .fp-item-year { font-size: clamp(20px, 4vw, 30px); padding: 0 12px; }
  .fp-item-card { padding: 14px 15px; }
  .fp-item-card h4 { font-size: 15px; }
  .fp-item.is-right .fp-item-card { transform: translate(16px, 18px); }
  .fp-item.is-left  .fp-item-card { transform: translate(-16px, 18px); }
  .fp-item.is-lit .fp-item-card, .fp-item.is-seen .fp-item-card { transform: none; }

  .fp-review-grid { grid-template-columns: 1fr; }
  .fp-certs { grid-template-columns: repeat(2, 1fr); }
  .fp-certs-top { grid-template-columns: 1fr; }
}

/* -------------------------------- phones --------------------------------
   Alternating is KEPT — he asked for the same effect everywhere — but the year moves
   inside the card and the spine narrows, so each card gets roughly 46% of the width
   instead of the ~35% it would keep with a separate year column. Below this the cards
   would be too narrow to read, which is why the year is folded in rather than the
   alternation being dropped. */
@media (max-width: 620px) {
  .fp-item { grid-template-columns: 1fr 26px 1fr; margin-bottom: 20px; }
  .fp-item-card { padding: 11px 12px; border-radius: var(--r-md); }
  .fp-item-card h4 { font-size: 13.5px; line-height: 1.35; }
  .fp-when { font-size: 10px; }
  .fp-org { font-size: 12px; }
  .fp-type { font-size: 11px; }
  .fp-item-card p { font-size: 11.5px; margin-top: 6px; }
  /* The year column would eat half the row at this width; it becomes a chip on the card
     so the alternation is preserved without starving the text. */
  .fp-item-year { display: none; }
  .fp-item-card::before {
    content: attr(data-year);
    display: block;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    line-height: 1;
    margin-bottom: 5px;
    opacity: .55;
  }
  .fp-item.is-lit .fp-item-card::before { opacity: 1; }
  .fp-item.is-right .fp-item-card { transform: translate(9px, 14px); }
  .fp-item.is-left  .fp-item-card { transform: translate(-9px, 14px); }
  .fp-item.is-lit .fp-item-card, .fp-item.is-seen .fp-item-card { transform: none; }
  .fp-dot { width: 10px; height: 10px; }

  .fp-certs { grid-template-columns: 1fr; }
  .fp-statband { grid-template-columns: repeat(2, 1fr); gap: 22px 14px; }
  .fp-photo { width: 130px; height: 130px; }
  .fp-initials { font-size: 40px; }
  .fp-post { display: block; white-space: normal; }

  /* The reel stays pinned and scroll-driven here too — position:sticky is supported on
     iOS and Android, and touch-action:pan-y keeps vertical scrolling native, so the page
     scrolls the reel sideways exactly as it does on desktop. */
  /* Publications are stacked by default now — see the reel block above. Nothing to
     undo here. */
}
}

@media (prefers-reduced-motion: reduce) {
  .fp-pubs > *, .fp-certs > *, .fp-certs-top > *, .fp-skills > * {
    opacity: 1 !important; transform: none !important; transition: none !important; }
  .fp-spine { transform: scaleY(1) !important; }
}
