/* Site enhancements: blue/black/white re-theme, header/nav redesign,
   custom cursor, language dropdown, hero neuron-network background.
   Loaded after styles-BSbdZIaz.css, so it can freely use / override the
   same CSS custom properties (the whole site reads colors through them). */

/* ---------- Inter, self-hosted (not Google Fonts' CDN): the site's
   CSP restricts font-src to 'self' data:, and self-hosting avoids a
   third-party request entirely. Replaced Sora site-wide -- Sora's
   geometric letterforms (round "a", "g") read as modern/startup-y at
   heading size, not what an academic site wants; Inter is a neutral,
   UI-optimized grotesque with no strong "personality" of its own, the
   standard choice for professional/institutional sites that still
   need to look current. Two files, not four/eight: Google only
   distributes Inter as a variable font, so one file per unicode
   subset covers every weight this site actually uses (400/500/600/700,
   declared as a range below), rather than needing a separate static
   file per weight the way Sora did. The variable font's default axis
   range is 100-900, but nothing here ever uses outside 400-700 --
   trimmed to that with fonttools' instancer (a real, measured 29%
   smaller download, 131KB to 93KB combined, for identical rendering
   at every weight actually in use). Two files because the name needs
   both subsets: "ü" is in the latin range, "Ş"/"ş" only exist in
   latin-ext -- the browser picks whichever range a given character
   needs automatically. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/inter-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/inter-var-latin.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;
}
:root {
  --sn-name-font: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Overrides the compiled bundle's own --font-sans (a system-font
     stack) -- since virtually every element reads its font through
     that one variable, this single override applies Inter site-wide
     without having to fight individual utility classes. */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* ---------- Re-theme: blue / black / white, matching the logo's blue.
   --primary is deliberately deeper than the logo's literal bright blue
   (#0878d1): an automated contrast audit (axe-core) found that exact
   blue failed WCAG AA (4.01:1, needs 4.5:1) as body-text link color
   against the site's light card/section backgrounds -- affecting real
   links (MEFELO, AERA, AAAL, BAAL in the About section) and every
   section's small uppercase kicker label. This deeper tone
   (#0560a6, 5.7:1 against --secondary, 6.5:1 against white) fixes
   that with real margin, and also reads calmer/more institutional
   than the brighter original -- which happens to suit an academic
   site better than the higher-saturation blue a SaaS product would
   use, so this one change serves both the accessibility fix and the
   "less SaaS, more traditional academic" design request together. ---------- */
:root {
  --primary: #0560a6;
  --primary-foreground: #ffffff;
  --primary-glow: #2879b0;
  --ink: #090b0f;
  --background: #ffffff;
  --foreground: #0b0f14;
  --card: #f6f8fa;
  --card-foreground: #0b0f14;
  --popover: #ffffff;
  --popover-foreground: #0b0f14;
  --secondary: #eef1f5;
  --secondary-foreground: #0b0f14;
  --muted: #eef1f5;
  --muted-foreground: #5b6472;
  --accent: #e7f1fc;
  --accent-foreground: #0b4e86;
  --border: #e2e6eb;
  --input: #e2e6eb;
  --ring: #0560a6;
  --gradient-hero: linear-gradient(120deg, #0560a6 0%, #4a8fc4 100%);
  --gradient-subtle: linear-gradient(180deg, #ffffff, #f3f6f9);
  --shadow-elegant: 0 20px 60px -20px rgba(5, 96, 166, 0.3);
  --shadow-soft: 0 4px 20px -4px rgba(11, 15, 20, 0.1);
}

/* ---------- Contact button: pulse removed regardless of source markup ---------- */
.sn-ring-pulse {
  animation: none !important;
  box-shadow: none !important;
}

/* Hero name: "Nural" was rendered as a blue gradient (bg-clip-text +
   transparent fill) while "Dr. Şükrü" stayed plain white -- at explicit
   request, the whole name is now solid white instead of split. */
h1 .bg-clip-text {
  background-image: none !important;
  -webkit-background-clip: initial !important;
  background-clip: initial !important;
  color: #ffffff !important;
}

/* ================= Header / navigation redesign ================= */
/* Near-opaque black: an RGBA background (never `opacity`, which would
   fade the nav text/controls along with the surface) plus a backdrop
   blur, so content scrolling underneath shows through only very
   faintly rather than the header meeting it as a hard, flat edge. A
   lower opacity (70%) was tried and read as washed-out/gray once
   bright content scrolled underneath, so this sits much closer to
   solid (~92%) while keeping a thin blurred edge rather than none.
   Deliberately constant -- it does not change on scroll or over
   different sections. */
header {
  position: sticky !important;
  top: 0 !important;
  margin: 0 !important;
  border-radius: 0 !important;
  background: rgba(255, 255, 255, 0.9) !important;
  border: 0 !important;
  border-bottom: 1px solid rgba(15, 23, 42, 0.08) !important;
  box-shadow: 0 12px 30px -18px rgba(15, 23, 42, 0.18) !important;
  backdrop-filter: blur(14px) saturate(130%) !important;
  -webkit-backdrop-filter: blur(14px) saturate(130%) !important;
  z-index: 50 !important;
}
/* Solid fallback for browsers without backdrop-filter support --
   otherwise nav text would sit over whatever's scrolling underneath
   at only 90% opacity, with nothing softening it. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  header {
    background: rgba(255, 255, 255, 0.96) !important;
  }
}
header > div {
  max-width: 1280px;
  min-height: 68px;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  padding-left: 28px !important;
  padding-right: 28px !important;
  position: relative;
}
@media (min-width: 1024px) {
  header > div {
    padding-left: 44px !important;
    padding-right: 44px !important;
  }
}
header a[href="#top"] {
  color: #0b0f14 !important;
  font-family: inherit;
}
/* Text-only wordmark, replacing the removed monogram. */
header a[href="#top"] span {
  display: inline !important;
  color: #0b0f14 !important;
  font-family: var(--sn-name-font);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.015em;
  white-space: nowrap;
  line-height: 1;
}
@media (min-width: 768px) {
  header a[href="#top"] span {
    font-size: 21px;
  }
}
@media (min-width: 1024px) {
  header a[href="#top"] span {
    font-size: 26px;
  }
}

/* Center nav: floating rounded-rect on a light surface (header is now
   a white/crystal glass panel, not dark). Was a full 9999px pill --
   sharpened toward the site's card/button radius scale (12px/8px,
   used elsewhere) as part of pulling the overall feel away from a
   SaaS-product look. */
header nav {
  background: rgba(15, 23, 42, 0.04);
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 12px;
  padding: 5px;
  gap: 2px !important;
}
header nav a {
  color: #5b6472 !important;
  border-radius: 8px;
  padding: 8px 16px;
  font-weight: 500;
  font-size: 13.5px;
  line-height: 1;
  transition: color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
header nav a:hover {
  color: #0b0f14 !important;
  background: rgba(15, 23, 42, 0.06);
}
header nav a:focus-visible {
  outline: 2px solid #6fc0ff;
  outline-offset: 2px;
}
header nav a.sn-nav-active {
  color: #ffffff !important;
  background: var(--primary);
  box-shadow: 0 0 0 1px rgba(8, 120, 209, 0.45), 0 4px 18px -3px rgba(8, 120, 209, 0.6);
}
header nav a.sn-nav-active:hover {
  background: var(--primary);
}

/* Language pill + Contact button, restyled for the white/crystal header */
header .sn-lang-trigger {
  background: rgba(15, 23, 42, 0.04);
  border: 1px solid rgba(15, 23, 42, 0.1);
  color: #0b0f14;
}
header .sn-lang-trigger:hover {
  border-color: var(--primary);
}
header .sn-lang-menu {
  background: #ffffff;
  border: 1px solid rgba(15, 23, 42, 0.1);
  color: #0b0f14;
  box-shadow: 0 20px 45px -12px rgba(15, 23, 42, 0.25);
}
header .sn-lang-option {
  color: #3a4250;
}
header .sn-lang-option:hover {
  background: rgba(15, 23, 42, 0.06);
  color: #0b0f14;
}
header .sn-lang-option[aria-selected="true"] {
  color: #ffffff;
  background: var(--primary);
  font-weight: 600;
}

header button:has(.lucide-mail) {
  /* Pinned so narrow-width padding/font trims (below) can never shrink
     it out of sync with the language control's own matching height. */
  height: 36px !important;
  box-sizing: border-box !important;
  border-radius: 8px !important;
  background: var(--primary) !important;
  box-shadow: 0 0 0 1px rgba(8, 120, 209, 0.5), 0 6px 20px -4px rgba(8, 120, 209, 0.65) !important;
  transition: transform 0.2s ease, box-shadow 0.2s ease, filter 0.2s ease !important;
}
header button:has(.lucide-mail):hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
  box-shadow: 0 0 0 1px rgba(8, 120, 209, 0.65), 0 8px 26px -4px rgba(8, 120, 209, 0.8) !important;
}
header button:has(.lucide-mail):focus-visible {
  outline: 2px solid #6fc0ff;
  outline-offset: 2px;
}

/* Hamburger toggle for small screens */
.sn-hamburger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 8px;
  border: 1px solid rgba(15, 23, 42, 0.1);
  background: rgba(15, 23, 42, 0.04);
  color: #0b0f14;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.sn-hamburger:hover {
  border-color: var(--primary);
}
.sn-hamburger:focus-visible {
  outline: 2px solid #6fc0ff;
  outline-offset: 2px;
}
.sn-hamburger svg {
  width: 18px;
  height: 18px;
}

@media (max-width: 420px) {
  header > div {
    padding-left: 5px !important;
    padding-right: 5px !important;
  }
  header > div > div:last-child {
    gap: 3px !important;
  }
  header a[href="#top"] span {
    /* Stay within the required 18-20px mobile range even at the
       narrowest supported width -- reduced carefully, never abbreviated. */
    font-size: 18px;
  }
  /* .sn-hamburger stays 44x44 (WCAG touch-target minimum) even here --
     it's an element this pass added, not part of the locked header
     design, so it isn't shrunk along with the rest at this width. The
     wordmark's serif letterforms need noticeably more room than the old
     sans-serif label did, so the rest of the chrome is trimmed further
     to compensate (verified down to 340px with no overflow). */
  .sn-lang-trigger {
    padding: 3px 4px;
    gap: 2px;
    font-size: 10px;
  }
  .sn-lang-flag {
    width: 15px;
    height: 11px;
  }
  .sn-lang-chevron {
    width: 9px !important;
    height: 9px !important;
  }
  header button:has(.lucide-mail) {
    padding-left: 6px !important;
    padding-right: 6px !important;
    gap: 4px !important;
    font-size: 11px;
  }
  header button:has(.lucide-mail) svg {
    width: 14px;
    height: 14px;
  }
}

/* Re-measured directly (a Playwright script checking the Contact
   button's actual right edge against the viewport, not a visual
   guess): the full nav pill + wordmark + language switcher + Contact
   button need just over 1024px to fit with any right-hand margin at
   all -- at 1024px itself the Contact button was already touching the
   edge (1px margin), and anywhere from ~970-1023px the row overflowed
   past the header's own padding entirely. 1100px is the first width
   with the padding properly restored (44px margin), so the nav stays
   hidden in favor of the hamburger through that whole broken range
   instead of only up to the old, now-stale 969px cutoff. Tailwind's
   compiled `md:flex` unhides the nav starting at 768px regardless of
   this rule's own range, so within the overlap the hide needs
   !important to win. */
@media (max-width: 1099px) {
  .sn-hamburger {
    display: inline-flex;
  }
  header nav {
    display: none !important;
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: #ffffff;
    border: 1px solid rgba(15, 23, 42, 0.1);
    border-radius: 16px;
    padding: 8px;
    box-shadow: 0 24px 48px -12px rgba(15, 23, 42, 0.3);
  }
  header nav.sn-mobile-open {
    display: flex !important;
  }
  header nav a {
    padding: 12px 14px;
    text-align: center;
    font-size: 14px;
  }
  /* The language switcher + Contact button (moved here by
     initMobileHeaderControls, out of the persistent header bar --
     that bar was carrying 4 separate controls and measurably
     overflowing at 320px) get a divider so they read as a distinct
     "secondary actions" row under the section links, not just more
     nav items. flex-wrap as a safety net at the very narrowest widths
     rather than a hard overflow. Centered (not left-packed) to match
     the centered nav links above it. */
  .sn-header-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 8px;
    padding: 12px 8px 4px;
    border-top: 1px solid rgba(15, 23, 42, 0.08);
  }
  /* The language trigger's dropdown normally right-anchors to line up
     under a header positioned at the row's right edge (see the
     unscoped .sn-lang-menu rule). Once moved into this centered mobile
     panel, the trigger can sit anywhere in the row, and a right-anchor
     was pushing the 160px-wide menu off the left edge of the screen
     entirely -- left-anchor instead. */
  .sn-header-controls .sn-lang-menu {
    left: 0;
    right: auto;
  }
  /* Wordmark centered in the row, hamburger pinned to the far right --
     both at explicit request. Absolute positioning takes the name out
     of the flex flow so margin-left:auto on the hamburger (the only
     remaining flex item once nav is closed/hidden) can push it all
     the way right without the two fighting over the same space. */
  header a[href="#top"] {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }
  .sn-hamburger {
    margin-left: auto;
  }
}

/* A previous pass hid the hamburger entirely below 480px on the theory
   that visitors would "just scroll" instead -- in practice that meant
   most phones (which are <=480px wide) had no way to jump to a
   section at all, just the name and language/contact controls with
   dead space between them. Reverted: the hamburger stays available
   down to the narrowest supported width. */

/* ---------- Language dropdown structure (colors themed above) ---------- */
.sn-lang-hide-original {
  display: none !important;
}
.sn-lang {
  position: relative;
  flex-shrink: 0;
}
.sn-lang-trigger {
  /* Matches the Contact button's own box exactly: 36px tall (8px
     vertical padding, 14px horizontal, 14px text, 8px corner radius),
     so the two controls read as one family instead of a small pill
     next to a large button. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 92px;
  height: 36px;
  box-sizing: border-box;
  border-radius: 8px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s, background 0.2s;
}
.sn-lang-trigger .sn-lang-chevron {
  width: 11px;
  height: 11px;
  opacity: 0.65;
  transition: transform 0.2s ease;
}
.sn-lang.is-open .sn-lang-chevron {
  transform: rotate(180deg);
}
.sn-lang-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 160px;
  padding: 6px;
  border-radius: 12px;
  display: grid;
  gap: 2px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  z-index: 40;
}
.sn-lang.is-open .sn-lang-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}
.sn-lang-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 7px 8px;
  border-radius: 8px;
  font-size: 13px;
  text-align: left;
}
.sn-lang-flag {
  display: inline-block;
  width: 18px;
  height: 13px;
  object-fit: cover;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
  flex-shrink: 0;
}

/* ---------- Social links (ORCID/LinkedIn/YouTube/X/Instagram),
   smaller at explicit request -- same pill shows up in both the hero
   and the footer's "Get in touch" block, so one rule covers both. ---------- */
a[class*="border-white/15"][class*="rounded-full"] {
  padding: 6px 8px !important;
  gap: 6px !important;
  font-size: 12px !important;
}
a[class*="border-white/15"][class*="rounded-full"] svg {
  width: 13px !important;
  height: 13px !important;
}
/* At exactly the width where the hero switches to its 2-column layout
   (lg: 1024px), the text column's suddenly-narrower width was just
   short of fitting all 5 buttons on one row -- Instagram wrapped onto
   its own row with a lot of empty space next to it (measured: 486px
   available vs ~505px needed at the default 12px gap). Tightening the
   gap for this row specifically closes that without shrinking the
   buttons further everywhere. */
.flex.flex-wrap.items-center.gap-3:has(a[href*="orcid.org"]) {
  gap: 6px !important;
}

/* ---------- Hero background: plain solid color, no light/glow effect
   -- tried an animated ambient glow through several iterations this
   project (multi-blob field, cursor-spotlight, single slow blob), but
   at explicit request it's gone entirely now in favor of a flat,
   simple academic-feeling background. ---------- */

/* ===================================================================
   Below-header visual system. Header is explicitly out of scope and
   untouched below. All selectors are scoped to `section` descendants
   (the header's own max-w-6xl container is a header child, not a
   section child, so it's naturally excluded) or to specific sections.
   =================================================================== */

/* Shared content width + responsive section rhythm. Tailwind's own
   max-w-6xl/py-20 utilities are same-specificity class selectors; this
   compound descendant selector already wins without needing !important
   for the width, but py-20 needs it since both are single utility
   classes on the same element. */
section[id] > div[class*="max-w-6xl"] {
  max-width: 1180px;
}
section[id]:not(#top):not(#contact) > div[class*="max-w-6xl"] {
  padding-top: 96px !important;
  padding-bottom: 96px !important;
}
@media (max-width: 1024px) {
  section[id]:not(#top):not(#contact) > div[class*="max-w-6xl"] {
    padding-top: 64px !important;
    padding-bottom: 64px !important;
  }
}
@media (max-width: 640px) {
  section[id]:not(#top):not(#contact) > div[class*="max-w-6xl"] {
    padding-top: 48px !important;
    padding-bottom: 48px !important;
  }
}

/* Subtle alternating section backgrounds (white / very light blue-gray).
   #top and #contact keep their intentional dark "bookend" treatment. */
#about,
#experience,
#publications,
#workshops {
  background: var(--secondary) !important;
}
#research,
#education,
#seminars {
  background: var(--background) !important;
}

/* One consistent card radius: the compact seminar/workshop list items
   used a smaller radius than the feature cards elsewhere; bring them
   in line with the 12-16px range used everywhere else. */
[class*="rounded-lg"][class*="border-border"][class*="bg-card"] {
  border-radius: 12px !important;
}

/* Comfortable paragraph measure (~60-72ch) for the long-form bio text. */
#about p {
  max-width: 68ch;
}

/* ---------- Hero refinement (content/order/labels unchanged) ---------- */

/* Portrait: clean 4:5 frame with intentional cover-fit crop instead of
   the previous unconstrained object-contain image + heavy drop-shadow. */
#top img[alt^="Portrait of"] {
  width: 100%;
  max-width: 380px;
  aspect-ratio: 4 / 5;
  object-fit: cover !important;
  object-position: 50% 18%;
  filter: none !important;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 30px 60px -24px rgba(8, 120, 209, 0.4), 0 14px 32px -14px rgba(0, 0, 0, 0.55);
}

/* Button hierarchy: "View Publications" becomes the primary academic
   action, "Get in touch" becomes secondary. Destinations/labels/i18n
   are untouched -- this only swaps which one looks solid vs outline. */
#top a[href="#publications"] {
  background: var(--primary) !important;
  border-color: var(--primary) !important;
  color: #fff !important;
  box-shadow: 0 14px 32px -12px rgba(8, 120, 209, 0.55) !important;
  transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
#top a[href="#publications"]:hover {
  background: var(--primary-glow) !important;
}
#top .sn-reveal-delay-3 > :first-child {
  background: rgba(255, 255, 255, 0.05) !important;
  border: 1px solid rgba(255, 255, 255, 0.22) !important;
  color: #fff !important;
  box-shadow: none !important;
}
#top .sn-reveal-delay-3 > :first-child:hover {
  background: rgba(255, 255, 255, 0.1) !important;
}

/* Social links: visible, but quieter than the two primary actions. */
#top .sn-reveal-delay-4 a {
  opacity: 0.82;
  transition: opacity 0.2s ease, transform 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}
#top .sn-reveal-delay-4 a:hover {
  opacity: 1;
}

/* Stats strip: subtle dividers between items instead of only a top rule,
   spanning the full text-column width for even distribution. */
#top dl {
  max-width: 100% !important;
}
#top dl > div:not(:first-child) {
  border-left: 1px solid rgba(255, 255, 255, 0.12);
  padding-left: 24px;
}

/* ===================================================================
   Content-section redesign (below the hero). Header untouched above.
   =================================================================== */

/* "Academic affiliations" strip: switched from a dark bar (matching
   the hero above it) to a plain white one with dark text, at explicit
   request -- also gives the logo cards (each already a white rounded
   card baked into the image itself) a background they sit flush
   against instead of floating on dark. */
[class*="bg-black/40"] {
  background: #ffffff !important;
  border-top-color: rgba(15, 23, 42, 0.08) !important;
}
[class*="bg-black/40"] [class*="text-white/40"] {
  color: #0b0f14 !important;
}
/* The old marquee's scroll-edge fade overlays (JS removes them on
   init) painted the strip's old dark color over the edges -- hide
   them immediately too, so there's no dark flash before JS runs. */
[class*="bg-black/40"] [class*="bg-gradient-to-r"],
[class*="bg-black/40"] [class*="bg-gradient-to-l"] {
  display: none !important;
}

/* Contact section's "Get in touch" eyebrow label uses --primary-glow as
   text color on a near-black background: 4.17:1, needs 4.5:1. Can't just
   change --primary-glow itself -- it's also used as the "View
   Publications" button's hover background, where the current value is
   tuned for contrast against white button text. Override this one
   consumer directly instead. */
.text-\[color\:var\(--primary-glow\)\] {
  color: #4a9bd0 !important;
}

/* ---------- Academic affiliations: static, deduplicated row instead
   of an infinitely-scrolling marquee. JS removes the duplicate <img>
   nodes and swaps the marquee/flex classes for these. A real grid, not
   flex-wrap: an earlier logo set had mismatched shapes (a near-square
   crest, wide wordmarks) that made equal-width grid cells scale each
   to a different height. The current logo set is four uniform,
   same-aspect-ratio cards (baked in, see below), so that problem no
   longer applies, and a grid gives evenly aligned columns/rows instead
   of flex-wrap's more organic, unaligned wrapping. ---------- */
.sn-affiliations-grid {
  display: grid !important;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  justify-items: center;
  align-items: center;
  gap: 20px 28px;
  width: 100% !important;
}
@media (max-width: 767.98px) {
  .sn-affiliations-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* The current logo set (NewUniLogos) ships as finished, uniform white
   rounded-rect cards baked directly into each file -- same canvas
   shape for all four -- so this wrapper is just a sizing/alignment
   box, not a second card drawn on top. (An earlier logo drop needed
   an externally-drawn card because those files were transparent
   cutouts of inconsistent shape/size; that's no longer the case, and
   re-adding a background/border/shadow here just doubled up on the
   image's own card and looked wrong.) */
.sn-affiliation-logo-box {
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* height:100%/width:auto (not max-height/max-width) is the point:
   every logo renders at the exact same pixel height, with width
   following its own natural aspect ratio. All four cards now share
   the same baked-in aspect ratio, so no extra size boost is needed
   for any one of them. */
.sn-affiliation-logo {
  height: 100%;
  width: auto;
  object-fit: contain;
}
@media (max-width: 767.98px) {
  .sn-affiliations-grid {
    gap: 16px 20px;
  }
  .sn-affiliation-logo-box {
    height: 58px;
  }
}

/* ---------- About: slightly more paragraph separation. ---------- */
#about .space-y-4 > p + p {
  margin-top: 22px;
}

/* ---------- Research cards: tighter padding, one restrained hover
   (upward shift + border color only -- no 3D tilt), full reduced-motion
   support (the shared .sn-tilt rule doesn't currently opt out). ---------- */
#research .sn-tilt {
  padding: 20px !important;
  transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
#research .sn-tilt:hover {
  transform: translateY(-4px) !important;
}
@media (prefers-reduced-motion: reduce) {
  .sn-tilt,
  .sn-tilt:hover {
    transform: none !important;
    transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
  }
}

/* ---------- Professional Positions timeline ---------- */
#experience .relative.border-l {
  contain: layout;
}
#experience h3 {
  font-size: 16px;
}
#experience .relative.border-l p {
  font-size: 13px;
  color: var(--muted-foreground);
}
#experience .relative.border-l > div > span[class*="rounded-full"][class*="bg-primary"] {
  background: var(--primary) !important;
  box-shadow: 0 0 0 4px color-mix(in oklab, var(--primary) 15%, transparent);
}
@media (max-width: 480px) {
  #experience .relative.border-l {
    padding-left: 20px;
  }
  #experience .relative.border-l span[class*="-left-"] {
    left: -26px !important;
  }
}

/* Expand/collapse control shared by Experience and Seminars.
   max-height is measured and set inline by JS (scrollHeight is
   unaffected by overflow:hidden clipping, so it can be read at any
   time), letting the transition below animate smoothly. */
.sn-expand-item {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  border-bottom-width: 0 !important;
  contain: layout;
  /* padding deliberately NOT transitioned: JS reads scrollHeight
     synchronously right after toggling the expanded class to compute
     max-height, and a transitioning padding value makes that read
     measure the barely-started (near-zero) padding instead of its
     final 14px -- clipping the second line of any multi-line row.
     Padding snapping instantly is not noticeable anyway since
     max-height/opacity are simultaneously animating the row in. */
  /* Cut from 0.28s/0.2s (measured: ~287ms from click to fully open,
     confirmed via transitionend -- not a bug, just a duration that
     read as sluggish) to make expand/collapse feel closer to instant
     while keeping enough motion that content doesn't just pop/vanish. */
  transition: max-height 0.15s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.1s ease, border-bottom-width 0.15s ease;
}
/* Seminars' "View all Seminars and Conferences" gap: each collapsed
   row is a card with its own 14px top/bottom padding (p-4). max-height:
   0 + overflow:hidden collapses the row's CONTENT, but padding still
   renders (border-box counts padding inside max-height in theory, but
   in practice on this flex row it doesn't get clipped) -- so all 8
   collapsed rows still showed their 28px of padding + 1px border,
   ~29px each, stacking into real, visible dead space above the
   button. Zero it the same way border-bottom-width already is. */
.sn-expand-item {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}
/* Same specificity fix as #seminars ul > li.sn-expand-item below: a
   plain ".sn-items-expanded .sn-expand-item" selector (3 classes) was
   losing this restore to that id+tag+class rule the same way the
   collapsed-state zero-out was losing earlier, so expanded rows were
   still rendering with 0 padding -- cramped, uneven-looking spacing
   next to the always-padded rows above them. */
#seminars ul.sn-items-expanded > li.sn-expand-item {
  padding-top: 14px !important;
  padding-bottom: 14px !important;
}
/* The actual cause of the long-reported gap above "View complete career
   history": Experience's timeline uses Tailwind's space-y-8 utility
   (margin-bottom: 2rem on every child but the last, in this build) for
   its normal 32px rhythm between entries. That margin applies to EVERY
   direct child regardless of visibility -- so each of the 5 collapsed
   .sn-expand-item rows before the last one still carries its own 32px
   margin-bottom even though max-height:0 collapses its own box to
   nothing, and those margins simply stack: 5 x 32px = ~160px of dead
   space between the last visible entry and the button, on top of the
   button's own margin. Zero it out while collapsed and restore the
   exact same pattern (all but the last) only once expanded (seminars'
   list doesn't use space-y-* for its rhythm, so it never had this
   problem). */
#experience .sn-expand-item {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}
#experience .sn-items-expanded .sn-expand-item:not(:last-child) {
  margin-bottom: 2rem !important;
}
.sn-items-expanded .sn-expand-item {
  opacity: 1;
}
.sn-items-expanded .sn-expand-item.sn-seminar-row {
  border-bottom-width: 1px !important;
}
@media (prefers-reduced-motion: reduce) {
  .sn-expand-item {
    transition: none;
  }
}
.sn-expand-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  min-height: 44px;
  padding: 9px 16px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.sn-expand-toggle:hover {
  border-color: var(--primary);
  background: var(--accent);
}
.sn-expand-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.sn-expand-toggle .sn-expand-chev {
  width: 13px;
  height: 13px;
  transition: transform 0.2s ease;
}
.sn-expand-toggle[aria-expanded="true"] .sn-expand-chev {
  transform: rotate(180deg);
}

/* ---------- Seminars & Conferences: compact, year-first rows. ---------- */
#seminars ul {
  gap: 0 !important;
  display: block !important;
  contain: layout;
}
#seminars ul > li.sn-seminar-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  border-radius: 0 !important;
  border: 0 !important;
  border-bottom: 1px solid var(--border) !important;
  padding: 14px 2px !important;
  background: transparent !important;
}
#seminars ul > li.sn-seminar-row:last-child,
#seminars ul > li.sn-expand-item:last-child {
  border-bottom: 0 !important;
}
#seminars ul > li.sn-expand-item {
  /* Same selector specificity as .sn-seminar-row above (id + tag +
     class), placed after it so it wins the tie for collapsed rows and
     actually zeroes their padding -- the plain ".sn-expand-item {
     padding: 0 !important }" rule elsewhere in this file loses to that
     rule above (higher specificity: id+tag+class beats a bare class)
     and had no effect on its own. */
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}
.sn-year-badge {
  flex-shrink: 0;
  min-width: 54px;
  padding-top: 1px;
  font-size: 15px;
  font-weight: 700;
  color: var(--primary);
  font-variant-numeric: tabular-nums;
}
.sn-seminar-body {
  flex: 1;
  min-width: 0;
  line-height: 1.55;
  font-size: 15px !important;
}

/* ---------- Site-wide readability pass: bump reading-content font
   sizes a step up across every section. Scoped to #sn-main so the
   header's pill nav/buttons -- already precisely tuned to a fixed
   36px height -- are left untouched. ---------- */
#sn-main .text-3xl {
  font-size: 34px !important;
  line-height: 1.15 !important;
}
#sn-main .text-base {
  font-size: 17px !important;
  line-height: 1.5 !important;
}
#sn-main .text-sm {
  font-size: 15px !important;
  line-height: 1.6 !important;
}
#top p {
  font-size: 19px !important;
}
#about p,
#publications li {
  font-size: 17px !important;
  line-height: 1.65 !important;
}

/* ---------- Workshops: lighter than Publications/Seminars. ---------- */
#workshops ul {
  gap: 12px !important;
}
#workshops li {
  box-shadow: none !important;
  background: transparent !important;
  border-color: var(--border) !important;
}

/* ---------- Contact: tighter spacing, connected to the footer below. ---------- */
#contact > div {
  padding-top: 72px !important;
  padding-bottom: 56px !important;
}
#contact .grid.md\:grid-cols-2 {
  align-items: start;
}
footer {
  border-top: 0 !important;
  padding-top: 0 !important;
}
footer > div {
  padding-top: 20px !important;
}

/* ===================================================================
   Interaction / responsive / accessibility pass. Header untouched.
   =================================================================== */

/* ---------- Navigation: offset anchored sections below the sticky
   header, smooth pointer scrolling (off under reduced motion). ---------- */
section[id] {
  scroll-margin-top: 88px;
}
html {
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* ---------- Skip link: visually hidden until keyboard-focused. ---------- */
.sn-skip-link {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 2147483647;
  transform: translateY(-140%);
  background: var(--primary);
  color: #fff;
  padding: 10px 18px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 8px 24px -6px rgba(0, 0, 0, 0.4);
  transition: transform 0.15s ease;
}
.sn-skip-link:focus {
  transform: translateY(0);
}

/* ---------- Back-to-top button ---------- */
.sn-to-top {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--primary);
  box-shadow: var(--shadow-soft);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s, border-color 0.2s ease, background-color 0.2s ease;
}
.sn-to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.sn-to-top:hover {
  border-color: var(--primary);
  background: var(--accent);
}
.sn-to-top:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.sn-to-top svg {
  width: 19px;
  height: 19px;
}
@media (prefers-reduced-motion: reduce) {
  .sn-to-top {
    transition: opacity 0.2s ease, visibility 0.2s;
    transform: none !important;
  }
}

/* ---------- Focus-visible safety net for the site's own pre-existing
   interactive elements (links, buttons, cards) -- additive only, never
   removes an outline without this replacement already covering it. ---------- */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Ensure aria-current="location" gets the same active
   treatment already defined for header nav links (no redesign). ---------- */
header nav a[aria-current="location"] {
  color: #ffffff !important;
  background: var(--primary);
  box-shadow: 0 0 0 1px rgba(8, 120, 209, 0.45), 0 4px 18px -3px rgba(8, 120, 209, 0.6);
}

/* ---------- Responsive QA fixes ----------
   Horizontal-overflow guard is scoped to #sn-main rather than html/body:
   overflow-x:hidden on *any* axis makes that element a CSS "scroll
   container" per spec (regardless of the other axis's value), and a
   sticky descendant sticks relative to its nearest scroll-container
   ancestor -- so hidden on body silently breaks the header's
   position:sticky (confirmed: removing it restored top:0 immediately).
   #sn-main is a *sibling* of the header, not an ancestor, so scoping
   the guard there fixes horizontal overflow without touching the
   header's containing-block chain at all. */
#sn-main {
  overflow-x: hidden;
}
/* #top is position:relative but never gets a stacking context of its
   own (no z-index/isolation in the original markup), so its "-z-10"
   decorative background layer -- used by both the hero lights below
   and, before them, the site's own neuron-network canvas -- escapes
   to the document root and paints behind literally everything on the
   page instead of just behind the hero's own content. Confirmed by
   temporarily forcing that layer to solid opaque red: still hidden
   without this. isolation:isolate contains it properly. */
#top {
  isolation: isolate;
}
#top h1 {
  overflow-wrap: break-word;
  /* Same identity as the header wordmark. The "Nural" span keeps its own
     gradient/background-clip color rule from the base stylesheet --
     only family/weight are set here, so that isn't touched. Font-size
     is reduced from the original text-5xl/6xl/7xl because bold display
     serif/sans faces at that size wrapped ("Nural" landing alone on its
     own line) against the column's max-width. Re-verified not to wrap
     at any width for the current font. */
  font-family: var(--sn-name-font);
  font-weight: 700;
  font-size: 35px !important;
}
@media (min-width: 640px) {
  #top h1 {
    font-size: 50px !important;
  }
}
@media (min-width: 1024px) {
  #top h1 {
    font-size: 60px !important;
  }
}
#publications p,
#seminars .sn-seminar-body,
#workshops li {
  overflow-wrap: break-word;
}
@media (max-width: 480px) {
  .sn-to-top {
    right: 14px;
    bottom: 14px;
  }
}
