/* =============================================================
   Nikolaos Synodinos — portfolio (v3)
   Monochrome ground, glistening gold throughout.
   White ↔ gold transitions; precise, clinical, alive.
   ============================================================= */

:root {
  /* Surfaces */
  --bg:        #08090a;   /* near-black */
  --bg-2:      #0e0f11;   /* raised panels / shimmer base */
  --line:      #2a2a2e;   /* rule / divider */
  --line-soft: rgba(240,237,232,0.08);

  /* Ink (warm off-white, stepped down by opacity) */
  --ink:       #f0ede8;
  --ink-soft:  rgba(240,237,232,0.66);
  --ink-faint: rgba(240,237,232,0.45);

  /* The single accent — and its glistening range */
  --gold:      #c9a84c;
  --gold-hi:   #f4e6ab;   /* champagne highlight */
  --gold-lo:   #93761f;   /* deep edge */
  --gold-grad: linear-gradient(110deg,
                 var(--gold-lo) 0%, var(--gold) 26%,
                 var(--gold-hi) 50%, var(--gold) 74%, var(--gold-lo) 100%);

  /* Brand colours (return only on hover, dusted with gold) */
  --linkedin:     #2d8fe0;
  --instagram:    #f592c0;
  --researchgate: #2bd4c4;
  --orcid:        #a6ce39;

  /* Type */
  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --sans:    "Inter", system-ui, -apple-system, sans-serif;

  /* Rhythm */
  --maxw: 1180px;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --section-pad: clamp(5rem, 12vh, 11rem);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------- Reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scrollbar-gutter: stable; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

::selection { background: rgba(201,168,76,0.28); color: #fff; }

/* The whole page lives under a slow gold aurora — soft blooms drift and
   breathe, breaking the monotony of the dark ground. */
body::before {
  content: "";
  position: fixed; inset: -25%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(34% 40% at 22% 26%, rgba(201,168,76,0.16), transparent 60%),
    radial-gradient(30% 36% at 82% 20%, rgba(201,168,76,0.11), transparent 60%),
    radial-gradient(44% 48% at 66% 84%, rgba(201,168,76,0.14), transparent 62%),
    radial-gradient(30% 34% at 12% 82%, rgba(201,168,76,0.10), transparent 60%);
  background-repeat: no-repeat;
  animation: aurora 22s ease-in-out infinite alternate;
  will-change: transform, opacity;
}
@keyframes aurora {
  0%   { transform: translate3d(-3%, -2%, 0) scale(1.05); opacity: 0.55; }
  50%  { transform: translate3d( 3%,  2%, 0) scale(1.16); opacity: 1; }
  100% { transform: translate3d(-1%,  3%, 0) scale(1.08); opacity: 0.72; }
}

/* Subtle vignette — lit from the centre */
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(120% 90% at 50% 30%, transparent 55%, rgba(0,0,0,0.55) 100%);
}
#site { position: relative; z-index: 1; }

/* Full stops stay the same colour as their heading (no gold) */
.gleam { color: inherit; -webkit-text-fill-color: currentColor; }

/* ---------- Glisten utility — moving gold, clipped to text ---------- */
@keyframes glisten {
  from { background-position: 220% 0; }
  to   { background-position: -80% 0; }
}

/* ---------- Accessibility ---------- */
.skip-link {
  position: fixed; top: 12px; left: 12px; z-index: 9999;
  background: var(--ink); color: var(--bg);
  padding: 10px 16px; border-radius: 8px; font-weight: 600;
  transform: translateY(-150%); transition: transform .2s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

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

/* ---------- Layout ---------- */
.section__inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding-inline: var(--gutter);
  width: 100%;
}
.section { padding-block: var(--section-pad); }

.section__index {
  font-size: 0.8rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 1.4rem;
}

.section__title, .aspect__title {
  font-family: var(--display);
  font-weight: 400;
  font-optical-sizing: auto;
  line-height: 1.04;
  letter-spacing: -0.015em;
  margin: 0 0 1.6rem;
  color: var(--ink);
}
.section__title { font-size: clamp(2rem, 5vw, 3.4rem); }

/* =============================================================
   DIVIDER — a golden line fading out each side, chevrons centre
   ============================================================= */
.divider {
  position: relative;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(2rem, 5vh, 3.4rem) var(--gutter);
  display: flex; align-items: center; justify-content: center;
  gap: clamp(14px, 3vw, 26px);
}
.divider::before, .divider::after {
  content: ""; height: 1px; flex: 1 1 0; max-width: 40%;
}
.divider::before { background: linear-gradient(to right, transparent, rgba(201,168,76,0.5)); }
.divider::after  { background: linear-gradient(to left,  transparent, rgba(201,168,76,0.5)); }
.divider__chev {
  flex: none;
  font-family: var(--sans); font-weight: 500;
  font-size: 0.95rem; letter-spacing: 0.34em; padding-left: 0.34em;
  background: var(--gold-grad); background-size: 240% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: glisten 3.6s linear infinite;
}

/* =============================================================
   INTRO — the opening: three gold points draw the tooth, then the
   formed tooth settles onto its hero position and the site fades up.
   ============================================================= */
.intro {
  position: fixed; inset: 0; z-index: 1000;
  pointer-events: none;
  overflow: hidden;
}
/* The hand-off: hero has already started underneath (pixel-identical), so
   this whole layer just needs to get out of the way — a plain opacity fade,
   no layout/reflow involved (see intro.js finish()). */
.intro.is-done { opacity: 0; transition: opacity .18s linear; }
@media (prefers-reduced-motion: reduce) { .intro.is-done { transition: none; } }
/* The dark backdrop is its OWN layer, so it can dissolve to reveal the site
   while the drawn tooth (the stage above it) stays put — no fade to black. */
.intro__bg { position: absolute; inset: 0; background: var(--bg); will-change: opacity; }

/* The drawing stage — centred, tooth-proportioned; JS flies it to the hero. */
.intro__stage {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(42vh, 300px);
  aspect-ratio: 200 / 263;
  will-change: transform, opacity;
}
.intro__svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* the intro reuses the hero ribbon classes (.tooth__glow / .tooth__core / .tooth__head) */

.intro__skip {
  position: absolute; bottom: 28px; right: 28px;
  pointer-events: auto;
  background: transparent; color: rgba(240,237,232,0.55);
  border: 1px solid rgba(240,237,232,0.22);
  border-radius: 999px; padding: 8px 20px;
  font-family: var(--sans); font-size: 0.74rem; letter-spacing: 0.14em;
  text-transform: uppercase; cursor: pointer;
  transition: color .2s, border-color .2s;
}
.intro__skip:hover { color: var(--gold); border-color: rgba(201,168,76,0.5); }

/* =============================================================
   HERO
   ============================================================= */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  padding: 7rem var(--gutter) 6rem;
}
.hero__grid {
  width: 100%; max-width: var(--maxw); margin: 0 auto;
  display: grid; grid-template-columns: 1fr; gap: 2.5rem;
  align-items: center;
}

/* ---- Left: identity ---- */
.hero__nav {
  display: flex; align-items: center; gap: 1.05em;
  font-size: clamp(1rem, 1.4vw, 1.18rem); letter-spacing: 0.04em;
  color: var(--ink-faint); margin: 0 0 1.8rem; flex-wrap: wrap;
}
.hero__nav a {
  color: var(--ink-faint); font-weight: 300;
  position: relative; transition: color .25s var(--ease);
}
.hero__nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 1px;
  background: var(--gold-grad); background-size: 200% 100%;
  transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease);
}
.hero__nav a:hover, .hero__nav a:focus-visible, .hero__nav a.is-lit { color: var(--gold); }
.hero__nav a:hover::after, .hero__nav a:focus-visible::after, .hero__nav a.is-lit::after { transform: scaleX(1); animation: glisten 2.4s linear infinite; }
.hero__nav-dot {
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--gold); flex: none;
  box-shadow: 0 0 8px rgba(201,168,76,0.5);
}

.hero__name {
  display: inline-block;            /* shrink-wrap, so the hero tooth lines up beside it */
  font-family: var(--display);
  font-weight: 300; font-optical-sizing: auto;
  line-height: 0.96; letter-spacing: -0.015em;
  margin: 0;
  font-size: clamp(3.2rem, 15vw, 6rem);
}
.hero__name-line { display: block; }
.gleam { font-style: normal; }

.hero__tagline {
  font-family: var(--sans); font-weight: 300;
  font-size: clamp(0.95rem, 2vw, 1.1rem);
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin: 1.6rem 0 0;
}

.hero__rule {
  display: block; height: 1px; width: 100%; margin-top: 2rem;
  background: linear-gradient(to right, var(--line), rgba(201,168,76,0.4), transparent);
}

/* ---- Right: a tooth traced by three gold meteors ---- */
.hero__right { position: relative; display: flex; justify-content: center; }
.tooth {
  position: relative;
  width: 100%; max-width: 360px; margin-inline: auto;
  aspect-ratio: 200 / 263;
}
.tooth__svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* No premade outline — the tooth exists only where the streaks are lit. */
.tooth__geo { fill: none; stroke: none; }

/* The neon streak: a CONTINUOUS filled ribbon that tapers + dims to its tail.
   `d` is rebuilt each frame by JS; fill is a per-streak gradient (head bright,
   tail faded essentially to black) — see window.toothGradDefs. */
.tooth__glow { opacity: 1; }
.tooth__core { opacity: 1; }
.tooth__head  { fill: #fff7e2; }                 /* bright neon head */
.tooth__head, .tooth__halo { transform-box: fill-box; transform-origin: center; }
.tooth__halo  { fill: var(--gold); opacity: 0; }

/* the active point pulses a soft halo */
.tooth__meteor.is-active .tooth__halo { animation: meteor-halo 1.4s ease-in-out infinite; }
.tooth__meteor.is-active .tooth__head { animation: meteor-head 1.4s ease-in-out infinite; }
@keyframes meteor-halo { 0%,100% { opacity: 0.18; transform: scale(0.7); } 50% { opacity: 0.55; transform: scale(1.7); } }
@keyframes meteor-head { 0%,100% { transform: scale(1); } 50% { transform: scale(1.45); } }

/* the aspect name — title case, set inside the tooth's hollow or just below it
   (never on the outline); position is computed in JS. */
.tooth__label {
  font-family: var(--sans); font-weight: 300;
  font-size: clamp(0.95rem, 1.3vw, 1.1rem); letter-spacing: 0.04em;
  fill: var(--gold-hi);
  opacity: 0; transition: opacity .45s var(--ease);
  pointer-events: none;
}
.tooth__meteor.is-active .tooth__label { opacity: 0.95; }

/* ---- Scroll cue — fixed bottom-left; hides while scrolling, returns when idle ---- */
.scroll-cue {
  position: fixed; z-index: 60;
  bottom: clamp(1rem, 3vh, 1.8rem); left: clamp(1rem, 5vw, 2.2rem);
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  color: var(--ink-faint);
  transition: color .25s var(--ease), opacity .5s var(--ease), transform .5s var(--ease);
}
.scroll-cue:hover { color: var(--gold); }
.scroll-cue.is-hidden { opacity: 0; transform: translateY(12px); pointer-events: none; }
.scroll-cue__text { font-size: 0.6rem; letter-spacing: 0.24em; text-transform: uppercase; }
.scroll-cue__line {
  width: 1px; height: 34px;
  background: linear-gradient(to bottom, currentColor, transparent);
  animation: cue 2.4s var(--ease) infinite;
  transform-origin: top;
}
@keyframes cue {
  0%   { transform: scaleY(0); opacity: 0; }
  40%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1) translateY(34px); opacity: 0; }
}

/* Two-column hero from 900px up */
@media (min-width: 900px) {
  .hero__grid { grid-template-columns: 55% 45%; gap: clamp(1.5rem, 4vw, 4rem); }
  .hero__name { font-size: clamp(3.4rem, 8vw, 7rem); }
  .scroll-cue { align-items: flex-start; }
}
@media (min-width: 1400px) {
  .hero__name { font-size: clamp(6rem, 8.5vw, 9.5rem); }
  .tooth { max-width: 400px; }
}

/* =============================================================
   ABOUT
   ============================================================= */
.about__lead {
  font-family: var(--display);
  font-weight: 300; font-optical-sizing: auto;
  font-size: clamp(1.3rem, 3vw, 2rem);
  line-height: 1.4; color: var(--ink);
  max-width: 32ch; margin: 0;
}
/* Gold underline accent, matching the aspect headings — for uniformity. */
.about__title::after {
  content: ""; display: block; width: 56px; height: 2px;
  margin-top: 1.2rem;
  background: linear-gradient(to right, var(--gold), transparent);
}

/* =============================================================
   ASPECT SECTIONS (Dentistry / Research / Life)
   ============================================================= */
.aspect { position: relative; }
.aspect__title { font-size: clamp(2.4rem, 7vw, 5rem); }
.aspect__title::after {
  content: ""; display: block; width: 56px; height: 2px;
  margin-top: 1.2rem;
  background: linear-gradient(to right, var(--gold), transparent);
}
.aspect__body {
  max-width: 56ch; font-size: 1.08rem; color: var(--ink-soft);
  margin: 0;
}

/* Life: two-column copy + editorial focus list */
.life__grid {
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 6vw, 5rem); align-items: start; margin-top: 0.5rem;
}
@media (max-width: 760px) { .life__grid { grid-template-columns: 1fr; gap: 2.2rem; } }

.field-list { margin: 0; }
.field { padding: 1.05rem 0; border-top: 1px solid var(--line-soft); }
.field:first-child { border-top: none; padding-top: 0.2rem; }
.field__term {
  margin: 0 0 0.25rem;
  font-weight: 600; font-size: 0.74rem;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint);
}
.field__desc { margin: 0; color: var(--ink-soft); font-size: 1rem; line-height: 1.5; }

/* =============================================================
   ASPECT PHOTO — one professional photo beside Dentistry / Research.
   Empty frame holds the space until the photo is added.
   ============================================================= */
.aspect__layout {
  display: grid; grid-template-columns: 1fr clamp(240px, 30%, 330px);
  gap: clamp(2rem, 5vw, 4.5rem); align-items: start;
}
.aspect__layout--reverse { grid-template-columns: clamp(240px, 30%, 330px) 1fr; }
.aspect__main { min-width: 0; }                  /* let the grid track shrink, no overflow */

.aspect__photo { margin: 0; position: sticky; top: 12vh; }
.aspect__photo-frame {
  position: relative; overflow: hidden; border-radius: 14px;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  box-shadow: 0 16px 48px rgba(0,0,0,0.4);
}
/* A real photo keeps its own natural aspect ratio — uncropped; only the empty
   placeholder gets a fixed frame (nothing to preserve a ratio for). */
.aspect__photo.is-empty .aspect__photo-frame { aspect-ratio: 4 / 5; display: flex; align-items: center; justify-content: center; }
.aspect__photo-img { width: 100%; height: auto; display: block;
  transition: transform 0.9s var(--ease); }
.aspect__photo:hover .aspect__photo-img { transform: scale(1.04); }
.aspect__photo-ph, .marathon__placeholder {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.aspect__photo-ph::after, .marathon__placeholder::after {
  content: ""; position: absolute; inset: -20%;
  background-color: transparent;
  background-image: linear-gradient(118deg,
    transparent 38%, rgba(201,168,76,0.05) 46%, rgba(201,168,76,0.13) 50%,
    rgba(201,168,76,0.05) 54%, transparent 62%);
  background-size: 240px 240px; background-repeat: repeat;
  animation: wave-flow 9s linear infinite;
}
.portrait__hint {
  position: relative; z-index: 1;
  font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-faint);
}
.aspect__photo-cap {
  margin-top: 0.7rem; font-size: 0.78rem; letter-spacing: 0.04em; color: var(--ink-faint);
}
@media (max-width: 820px) {
  .aspect__layout, .aspect__layout--reverse { grid-template-columns: 1fr; gap: 2.4rem; }
  .aspect__layout--reverse .aspect__photo { order: 2; }   /* photo below the copy on small screens */
  .aspect__photo { position: static; max-width: 360px; }
}

/* =============================================================
   MARATHON — race photos + a tidy list of races (in Life).
   ============================================================= */
.marathon { margin-top: clamp(3rem, 7vh, 5rem); }
.marathon__eyebrow {
  font-size: 0.72rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 0.8rem;
}
.marathon__intro {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.1rem, 2.4vw, 1.5rem); line-height: 1.4;
  color: var(--ink); max-width: 42ch; margin: 0 0 1.8rem;
}
.marathon__strip {
  display: grid; grid-template-columns: repeat(var(--ms-cols, 3), 1fr);
  gap: clamp(0.7rem, 2vw, 1.1rem);
}
.marathon__shot {
  position: relative; overflow: hidden; border-radius: 12px;
  background: var(--bg-2);
  border: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: center;
}
/* Real photos keep their own natural aspect ratio — uncropped; only the
   empty placeholder gets a fixed 3:2 frame. */
.marathon__shot.is-empty { aspect-ratio: 3 / 2; }
.marathon__img { width: 100%; height: auto; display: block;
  transition: transform 0.9s var(--ease); }
.marathon__shot:hover .marathon__img { transform: scale(1.05); }

.race-list { list-style: none; margin: clamp(1.6rem, 4vh, 2.4rem) 0 0; padding: 0; }
.race {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: 0.95rem 0.2rem; border-top: 1px solid var(--line-soft);
}
.race:last-child { border-bottom: 1px solid var(--line-soft); }
.race__event {
  font-family: var(--display); font-size: clamp(1.05rem, 2.4vw, 1.35rem); color: var(--ink);
  transition: color 0.25s var(--ease);
}
a.race__event::after { content: " ↗"; font-family: var(--sans); font-size: 0.8rem; color: var(--ink-faint); transition: color .25s var(--ease); }
/* A gentle gold glisten sweeps across the event name on hover (matching the
   affiliations logos), settling on gold rather than looping. */
a.race__event:hover {
  background: linear-gradient(100deg,
    var(--ink) 0%, var(--ink) 32%, var(--gold-hi) 44%, var(--gold) 50%,
    var(--gold-hi) 56%, var(--gold) 68%, var(--gold) 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: race-glisten 2.6s var(--ease) 1 forwards;
}
a.race__event:hover::after { color: var(--gold); }
@keyframes race-glisten { from { background-position: 220% 0; } to { background-position: 0% 0; } }
.race__time {
  font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
  color: var(--gold); font-weight: 500; font-size: 0.95rem; white-space: nowrap;
}
.race--soft .race__event { color: var(--ink-faint); font-family: var(--sans); font-size: 0.95rem; }

@media (max-width: 560px) {
  .marathon__strip { grid-template-columns: 1fr; }
}

/* =============================================================
   SHIMMER PLACEHOLDERS (cases + publications)
   One broad, soft gold wave sweeps across the whole surface — not a
   tiled/striped pattern. The hump sits inside an oversized background
   that travels fully off-screen at both ends of the loop, so the point
   where the animation restarts is invisible (nothing is on-screen there).
   ============================================================= */
@keyframes wave-flow { from { background-position: 0 0; } to { background-position: 260px 260px; } }
@keyframes wave-sweep { from { background-position: -110% 0; } to { background-position: 210% 0; } }

/* the gold wave, as a reusable tiled background (still used by photo
   placeholders below, which keep the original oblique tile treatment) */

/* Cases + publications: one broad, edge-faded wave (item 5) */
.cases__grid, .shimmer-row {
  background-color: var(--bg-2);
  background-repeat: no-repeat;
  background-size: 260% 100%;
  background-image: linear-gradient(100deg,
    transparent 0%, transparent 34%,
    rgba(201,168,76,0.05) 42%, rgba(201,168,76,0.15) 50%, rgba(201,168,76,0.05) 58%,
    transparent 66%, transparent 100%);
  animation: wave-sweep 8s ease-in-out infinite;
}

.cases { margin-top: 3rem; }
.cases__label, .pubs__label {
  margin: 0 0 1.4rem; font-size: 0.8rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-faint);
}
.pubs__label--soft { text-transform: none; letter-spacing: 0.04em; font-size: 0.92rem; }

/* The two case slots read as ONE panel — the wave flows across the seam. */
.cases__grid {
  position: relative; overflow: hidden;
  display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--line-soft); border-radius: 14px;
}
.shimmer-card {
  margin: 0; aspect-ratio: 4 / 3; position: relative; z-index: 2;
  background: transparent;                    /* let the grid's wave show through */
  display: flex; align-items: center; justify-content: center;
}
.shimmer-card + .shimmer-card { border-left: 1px solid var(--line-soft); }
.shimmer-card__text {
  position: relative; z-index: 2;
  font-size: 0.82rem; letter-spacing: 0.04em; color: var(--ink-faint);
}

.pubs { margin-top: 3rem; }
.pub-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.8rem; }
.shimmer-row {
  height: 56px; border-radius: 12px;
  border: 1px solid var(--line-soft);
}

/* =============================================================
   CONNECT
   ============================================================= */
.connect__links {
  list-style: none; padding: 0; margin: 0;
  border-top: 1px solid var(--line-soft);
}
.connect__link {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.3rem 0.2rem;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.4rem, 4vw, 2.2rem);
  color: var(--ink); position: relative;
  transition: padding-left .3s var(--ease);
}
.connect__link::after {
  content: "↗"; font-family: var(--sans); font-size: 0.9rem;
  color: var(--ink-faint); transition: color .25s, transform .3s var(--ease);
}
#link-email::after { content: "→"; }
/* hover: a GOLD wave sweeps every letter to gold first, then a second wave
   carries them into the app's brand colour. Two passes, ending on the brand. */
.connect__link:hover {
  padding-left: 0.9rem;
  background: linear-gradient(100deg,
    var(--brand, var(--gold)) 0%, var(--brand, var(--gold)) 30%,
    var(--gold-hi) 36%, var(--gold) 42%, var(--gold) 58%, var(--gold-hi) 64%,
    var(--ink) 72%, var(--ink) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: link-glint 3.2s var(--ease) 1 forwards;
}
.connect__link:hover::after { color: var(--brand, var(--gold)); transform: translateX(4px); }
@keyframes link-glint { from { background-position: 100% 0; } to { background-position: 0% 0; } }
#link-linkedin     { --brand: var(--linkedin); }
#link-instagram    { --brand: var(--instagram); }
#link-researchgate { --brand: var(--researchgate); }
#link-orcid        { --brand: var(--orcid); }
#link-email        { --brand: var(--gold); }

/* CV button — a long gold fill that sweeps in at an angle (item 6) */
.cv-button {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 0.6rem;
  margin-top: 2.6rem;
  padding: 0.9rem 1.7rem;
  border: 1px solid var(--gold); border-radius: 999px;
  color: var(--gold); background: transparent;
  font-weight: 500; font-size: 0.95rem;
  transition: background .4s var(--ease), box-shadow .4s var(--ease), color .4s var(--ease);
}
.cv-button__shine { position: relative; z-index: 1; }
.cv-button svg { position: relative; z-index: 1; }
.cv-button::before {
  content: ""; position: absolute; inset: -1px;
  background: linear-gradient(115deg,
    transparent 30%,
    rgba(201,168,76,0.18) 42%,
    rgba(244,230,171,0.5) 50%,
    rgba(201,168,76,0.18) 58%,
    transparent 70%);
  background-size: 260% 100%;
  background-position: 160% 0;
}
.cv-button:hover {
  background: rgba(201,168,76,0.10);
  box-shadow: 0 0 34px rgba(201,168,76,0.20);
}
.cv-button:hover::before {
  background-position: -160% 0;
  transition: background-position 1.25s var(--ease);
}

/* =============================================================
   AFFILIATIONS — a slow, quiet banner. Logos rest as ink outlines;
   hovering one eases its true colours back, in full quality.
   ============================================================= */
.affiliations { padding-block: clamp(3.5rem, 9vh, 7rem); }
.affiliations__title {
  text-align: center; margin: 0 0 clamp(1.8rem, 4vh, 2.8rem);
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.15rem, 2.2vw, 1.5rem); letter-spacing: 0.005em; color: var(--ink-soft);
  transition: color .5s var(--ease);
}
/* the heading lights up gold whenever any logo is hovered */
.affiliations:has(.logo-chip:hover) .affiliations__title { color: var(--gold); }
.marquee {
  position: relative; overflow: hidden;
  -webkit-mask: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
          mask: linear-gradient(to right, transparent, #000 9%, #000 91%, transparent);
}
.marquee__track {
  display: flex; align-items: center; width: max-content;
  gap: clamp(1.6rem, 4vw, 3rem);
  list-style: none; margin: 0; padding: 0;
  /* Stays still until JS marks it ready (`.is-ready`, in app.js) — the very
     first render is only a single un-doubled set of logos while images are
     still loading; animating that immediately would slide it half off and
     jump-cut mid-logo the moment the real seamless set swaps in. */
}
.marquee__track.is-ready {
  animation: scroll-x 40s linear infinite;     /* duration replaced by JS for constant speed */
}
/* Hover-pause only where hover is a real, non-sticky pointer gesture — on
   touch devices `:hover` latches after a tap (and only releases on a tap
   elsewhere), which made the marquee look stuck/only-moving-on-odd-taps. */
@media (hover: hover) {
  .marquee:hover .marquee__track { animation-play-state: paused; }
}
@keyframes scroll-x { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.marquee__item { flex: none; }
.logo-chip {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: clamp(84px, 11vw, 112px);
  padding: 0 clamp(22px, 3.4vw, 34px);
  background: transparent; border-radius: 12px;
  transition: background .6s var(--ease);
}
/* A gentle gold sheen sweeps across the chip on hover — echoed by the
   heading turning gold (via :has() below). */
.logo-chip::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  border-radius: inherit; pointer-events: none;
  background: linear-gradient(100deg,
    transparent 30%, rgba(244,230,171,0.4) 48%,
    rgba(244,230,171,0.55) 50%, rgba(244,230,171,0.4) 52%, transparent 70%);
  background-size: 250% 100%; background-position: 160% 0;
  opacity: 0;
}
.logo-chip:hover::after, .logo-chip:focus-visible::after {
  opacity: 1;
  animation: glisten 1.8s var(--ease) 1;
}
/* Default: a flat ink-coloured outline (same tone as the text). On hover the
   true colours ease back at full PNG quality, on a clean light chip so colour
   logos read crisply — no gold flash, no blend modes, nothing to degrade them. */
.logo-chip__img {
  position: relative; z-index: 1;
  height: clamp(46px, 7vw, 68px); width: auto; display: block;
  filter: brightness(0) invert(0.92) opacity(0.62);
  transition: filter .7s var(--ease);
}
.logo-chip:hover, .logo-chip:focus-visible { background: #f4f1ea; }
.logo-chip:hover .logo-chip__img,
.logo-chip:focus-visible .logo-chip__img { filter: none; }

/* =============================================================
   FOOTER
   ============================================================= */
.footer { position: relative; padding-block: clamp(3rem, 8vh, 6rem); border-top: 1px solid var(--line-soft); }

/* The reading room — a quiet door in the far corner. */
.footer__desk {
  position: absolute;
  right: clamp(0.9rem, 3vw, 1.6rem);
  bottom: clamp(0.9rem, 3vw, 1.6rem);
  width: 18px; height: 18px;
  color: var(--ink-faint);
  opacity: 0.35;
  transition: color 0.35s var(--ease), opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.footer__desk svg { width: 100%; height: 100%; display: block; }
.footer__desk:hover,
.footer__desk:focus-visible {
  color: var(--gold);
  opacity: 1;
  transform: translateY(-1px);
}

/* The clinic — a second quiet door, opposite corner. */
.footer__dent {
  position: absolute;
  left: clamp(0.9rem, 3vw, 1.6rem);
  bottom: clamp(0.9rem, 3vw, 1.6rem);
  width: 18px; height: 18px;
  color: var(--ink-faint);
  opacity: 0.35;
  transition: color 0.35s var(--ease), opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.footer__dent svg { width: 100%; height: 100%; display: block; }
.footer__dent:hover,
.footer__dent:focus-visible {
  color: var(--gold);
  opacity: 1;
  transform: translateY(-1px);
}
.footer__inner { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.6rem; }
.footer__motif { margin: 0 0 0.4rem; }
.footer__chev {
  font-family: var(--sans); font-weight: 500;
  font-size: 0.9rem; letter-spacing: 0.34em; padding-left: 0.34em;
  background: var(--gold-grad); background-size: 240% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: glisten 3.6s linear infinite;
}
.footer__name { font-family: var(--display); font-size: 1.2rem; margin: 0; }
.footer__copy { font-size: 0.82rem; color: var(--ink-faint); margin: 0; }

/* =============================================================
   AWARD / DISTINCTION CALLOUT — gold, for when it's earned
   ============================================================= */
.is-award {
  color: var(--gold);
  border-left: 2px solid var(--gold);
  padding-left: 1rem;
}

/* =============================================================
   TOUCH DEVICES — no hover, so the gold glistens on its own (item 11)
   ============================================================= */
@media (hover: none) {
  /* No hover to reveal them — so show the real logos, full quality, on a light
     chip (the outline treatment is a desktop hover affordance). */
  .logo-chip { background: #f4f1ea; }
  .logo-chip__img { filter: none; }
  /* Connect links glisten gold on their own, slowly and staggered. */
  .connect__link {
    background: linear-gradient(110deg,
      var(--ink) 0%, var(--ink) 42%, var(--gold) 50%, var(--ink) 58%, var(--ink) 100%);
    background-size: 260% 100%;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: glisten 6.5s linear infinite;
  }
  .connect__link:nth-child(even) { animation-delay: -3.25s; }
}

/* =============================================================
   RESPONSIVE
   ============================================================= */
@media (max-width: 640px) {
  :root { --section-pad: clamp(4rem, 10vh, 7rem); }
  /* Whole hero (name + tooth, stacked) must fit inside the small viewport so
     nothing is hidden behind the phone's bottom URL bar. `svh` already excludes
     that bar; the fix is keeping the stacked content SHORTER than svh. So:
     tighter top/bottom padding (+ safe-area), a tighter stack gap, a slightly
     smaller name, and a smaller tooth. Measured to fit ~620px of content. */
  .hero {
    padding-top: 2.75rem;
    padding-bottom: calc(1.5rem + env(safe-area-inset-bottom, 0px));
  }
  .hero__grid { gap: 1.1rem; }
  .hero__nav { justify-content: flex-start; margin-bottom: 1.1rem; font-size: 1.12rem; }
  .hero__name { font-size: clamp(2.95rem, 14vw, 5.4rem); }
  .hero__tagline { margin-top: 1rem; font-size: 1.08rem; }
  .hero__rule { margin-top: 1.25rem; }
  .tooth { max-width: 305px; }
  .cases__grid { grid-template-columns: 1fr; }
  .connect__link { font-size: 1.5rem; }
  .scroll-cue { left: var(--gutter); }
  /* The desktop clamp() floors at 84px regardless of viewport — too big to
     show more than one logo at a time on a phone. Shrink it here so a
     couple are visible together, same as the desktop experience. */
  .logo-chip { height: 52px; padding: 0 12px; }
  .logo-chip__img { height: 28px; }
}

/* Extra-short viewports (small phones, landscape): the tooth is the most
   compressible piece — shrink it further so the hero never overflows. */
@media (max-width: 640px) and (max-height: 720px) {
  .tooth { max-width: 252px; }
  .hero__name { font-size: clamp(2.6rem, 12.5vw, 4.3rem); }
}

/* =============================================================
   REDUCED MOTION
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; opacity: 0.6; }
  .scroll-cue__line { animation: none; }
  .cases__grid, .shimmer-row { animation: none; }
  .aspect__photo-ph::after, .marathon__placeholder::after { animation: none; }
  .tooth__meteor .tooth__halo, .tooth__meteor .tooth__head { animation: none; }
  .divider__chev, .footer__chev { animation: none; }
  .marquee__track { animation: none; }
  .connect__link { animation: none; }
  .logo-chip::after { display: none; }
  a.race__event:hover { animation: none; }
  [data-reveal] { opacity: 1 !important; filter: none !important; transform: none !important; }
}
