/* ========================================
   Overlake.bio - Consolidated Styles
   Combines: overlake-common.css, static-background.css, water-enhancements.css
   ======================================== */

/* ========================================
   0. FONTS & DESIGN TOKENS
   ======================================== */

/* Self-hosted Fraunces (variable serif) for headings only. No font CDN.
   Body text stays on the Water.css system sans stack. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../asset/fonts/Fraunces-latin.woff2") format("woff2");
}

:root {
  /* Spacing scale */
  --space-xs: 0.25rem;   /* 4px  */
  --space-sm: 0.5rem;    /* 8px  */
  --space-md: 1rem;      /* 16px */
  --space-lg: 1.5rem;    /* 24px */
  --space-xl: 2rem;      /* 32px */
  --space-2xl: 3rem;     /* 48px */
  --space-3xl: 4rem;     /* 64px */

  /* Border radius scale */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* Easing curves */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* Text tint — override Water.css neutrals with a faint cool (blue-grey)
     lean toward the background hue. Same lightness, just not pure white/grey,
     so the page reads as intentionally colour-coordinated with the water theme. */
  --text-bright: #eef2f8;  /* was #fff    — headings, logo, panel copy */
  --text-main:   #d3dae6;  /* was #dbdbdb — body text                 */
  --text-muted:  #9fadbe;  /* was #a9b1ba — section tags, small labels */
}

/* ========================================
   1. BACKGROUND
   ======================================== */

body {
  background:
    image-set(
      url("../asset/water-6901805_1920.webp") type("image/webp"),
      url("../asset/water-6901805_1920.jpg") type("image/jpeg")
    ) no-repeat center center fixed;
  /* Fallback for browsers without image-set() support */
  background-color: #202b38; /* match your CSS theme color */
  background-size: cover;
  background-attachment: fixed;
  background-blend-mode: multiply;
  line-height: 1.6;
  animation: fadeIn 0.8s ease-out;
}

p, li {
  line-height: 1.6;
}

/* Particles.js container */
#particles-js {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  animation: particlesFadeIn 6.1s ease-out forwards;
}

/* ========================================
   2. LOGO STYLES
   ======================================== */

.overlake-logo {
  text-align: right;
  line-height: 0.85;
  margin: 2rem 0;
  font-family: inherit; /* Uses water.css system fonts */
}

.overlake-main {
  font-size: 3em;
  font-weight: 200;
  color: var(--text-bright, #212529);
  letter-spacing: -0.01em;
  margin-bottom: 5px;
}

.overlake-lake {
  color: var(--links, #0076d1);
  font-weight: 300;
  text-shadow: 0 0 12px rgba(65, 173, 255, 0.15);
}

/* Bright, not blue — matches the ".bio" in the footer's .overlake-inline and
   keeps it legible against the water photograph. Only "lake" stays accented. */
.overlake-bio {
  font-size: 1.4em;
  color: var(--text-bright, #212529);
  font-weight: 400;
  letter-spacing: 0.1em;
  text-shadow: 0 0 10px rgba(65, 173, 255, 0.12);
}

/* Dark mode compatibility */
@media (prefers-color-scheme: dark) {
  .overlake-main {
    color: var(--text-bright, #ffffff);
  }
  .overlake-lake {
    color: var(--links, #7dc4e4);
  }
  .overlake-bio {
    color: var(--text-bright, #ffffff);
  }
}

/* Responsive sizing */
@media (max-width: 768px) {
  .overlake-main {
    font-size: 2.2em;
  }
  .overlake-bio {
    font-size: 1.1em;
  }
}

/* Header integration */
header .overlake-logo {
  margin: 1rem 0;
}

header .overlake-main {
  font-size: 2.5em;
}

header .overlake-bio {
  font-size: 1.2em;
}

/* Inline version for navigation or small spaces */
.overlake-inline {
  display: inline-block;
  font-size: 1.5em;
  font-weight: 300;
  color: var(--text-bright, #212529);
  text-decoration: none;
}

@media (hover: hover) {
  .overlake-inline:hover {
    color: var(--links, #0076d1);
    text-decoration: none;
  }
}

.overlake-inline .lake {
  color: var(--links, #0076d1);
  font-weight: 400;
}

/* Footer version */
footer .overlake-logo {
  text-align: center;
  margin: 2rem auto;
}

footer .overlake-main {
  font-size: 2em;
}

footer .overlake-bio {
  font-size: 1em;
}

/* ========================================
   3. UTILITY CLASSES
   ======================================== */

/* Justified text alignment */
.justified-text {
  text-align: justify;
  hyphens: auto;
  -webkit-hyphens: auto;
  overflow-wrap: break-word;
  word-break: normal;
}

/* Section tag separator and label in headings. The separator is plain text —
   headings no longer link out, so an accent here would suggest an affordance
   that isn't there. */
.section-sep {
  color: var(--text-main);
}

.section-tag {
  font-size: 0.75em;
  font-weight: 300;
  color: var(--text-muted);
  letter-spacing: 0.05em;
}

/* Minor labels in body copy: the one-line summary under a page's h2, the
   outlet name after the "|" in a media or blog entry, and the bracketed type
   marker on a publication. Same treatment as
   .panel-copy and .section-tag, but sized in rem rather than em — .section-tag
   only lands at ~14px because an h3 scales it up, and inside body text the
   same 0.75em would drop it to 12px. Body copy is already the system sans
   stack, so unlike .section-tag these need no font-family override. Grouped so
   the two stay in step. */
.page-intro,
.entry-source,
.team-role {
  font-size: 0.875rem;
  font-weight: 300;
  color: var(--text-muted);
}

/* The publication type markers wrap their label in <strong>, and the base
   stylesheet's weight and colour for that element are set on the child itself,
   so they outlive the span's. Hand them back so the marker matches the other
   minor labels rather than only shrinking to their size. */
.entry-source strong {
  font-weight: inherit;
  color: inherit;
}

/* Indented paragraphs */
.indented {
  margin-left: 2em;
}

.citation-widget {
  margin-top: 0.4rem;
}

.citation-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.citation-row .citation-text {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}

.citation-row .citation-widget {
  flex: 0 0 200px;
  margin-top: 0;
}

.citation-row .citation-widget img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-md);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
}

.citation-widget-right {
  text-align: right;
}

/* Full-width responsive figure */
.figure-full-width {
  width: 100%;
  margin: 0;
}

.figure-full-width img {
  width: 100%;
  height: auto;
  display: block;
  margin: 0;
}

/* ========================================
   4. ANIMATIONS
   ======================================== */

/* Subtle fade-in animation for page content */
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Opacity-only fade for the particles background */
@keyframes particlesFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Enhanced selection with shimmer */
@keyframes selectionShimmer {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}


/* Elegant focus ring pulse */
@keyframes focusPulse {
  from { box-shadow: 0 0 0 2px var(--links), 0 0 20px rgba(65, 173, 255, 0.3); }
  to { box-shadow: 0 0 0 2px var(--links), 0 0 25px rgba(65, 173, 255, 0.4); }
}

/* ========================================
   5. LINKS & NAVIGATION
   ======================================== */

/* Enhanced link hover effects */
a {
  transition: color 0.45s var(--ease-out-quart), text-shadow 0.45s var(--ease-out-quart);
}

@media (hover: hover) {
  a:hover {
    text-shadow: 0 0 8px rgba(65, 173, 255, 0.3);
    color: #60b7ff;
  }
}

/* Navigation buttons */
.button-nav {
  display: flex;
  justify-content: space-between;
  gap: 15px;
  margin: 25px 0;
  flex-wrap: wrap;
}

.button-nav .nav-button {
  flex: 1;
  text-align: center;
  min-width: 0;
  white-space: nowrap;
}

.nav-button {
  padding: 8px 12px;
  /* Flex-center the label so it stays centered on both axes even for the
     longest label ("documentation"); text-align can't center nowrap text
     that overflows its box, but justify-content can. */
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(32, 43, 56, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(65, 173, 255, 0.15);
  border-radius: var(--radius-md);
  text-decoration: none;
  transition:
    background-color 0.5s var(--ease-out-quart),
    border-color 0.5s var(--ease-out-quart),
    box-shadow 0.5s var(--ease-out-quart),
    color 0.5s var(--ease-out-quart),
    transform 0.5s var(--ease-out-quart);
  position: relative;
  overflow: hidden;
  /* Ensure nav-button text is visible */
  color: var(--text-main) !important;
  -webkit-text-fill-color: var(--text-main) !important;
}

@media (hover: hover) {
  .nav-button:hover {
    background: var(--links);
    color: var(--background-body) !important;
    -webkit-text-fill-color: var(--background-body) !important;
    transform: translateY(-2px);
    box-shadow:
      0 8px 22px rgba(0, 0, 0, 0.18),
      0 0 18px rgba(65, 173, 255, 0.18);
  }
}

/* Classy cursor interaction for buttons */
.nav-button::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
  transition: width 0.6s ease, height 0.6s ease;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

@media (hover: hover) {
  .nav-button:hover::before {
    width: 200px;
    height: 200px;
  }
}

/* Active page indicator.
   The underline is drawn with an inset box-shadow (not a thicker bottom
   border) so the border stays symmetric and the label stays vertically
   centered — a 2px border-bottom would shift the text up ~1px. */
.nav-button[aria-current="page"] {
  color: var(--links) !important;
  -webkit-text-fill-color: var(--links) !important;
  border-color: rgba(65, 173, 255, 0.5);
  background: rgba(65, 173, 255, 0.12);
  box-shadow:
    inset 0 -2px 0 var(--links),
    inset 0 0 18px rgba(65, 173, 255, 0.08);
}

/* ========================================
   5b. CALLOUT (semantic info note)
   ======================================== */

/* Same surface as the index.html navigation panels — border, layered
   gradient, drop shadow, and diagonal viewfinder corners. Static, though:
   this is a note rather than a link, so it gets no hover lift. Padding is
   wider than the panels' so the content clears the corner marks. */
.callout {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  padding: 1.5rem;
  border: 1px solid rgba(125, 196, 228, 0.22);
  border-radius: var(--radius-md);
  background:
    linear-gradient(135deg, rgba(32, 43, 56, 0.84), rgba(16, 25, 34, 0.66)),
    radial-gradient(circle at top right, rgba(125, 196, 228, 0.18), transparent 36%);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.24);
  position: relative;
  overflow: hidden;
}

.callout::before,
.callout::after {
  content: "";
  position: absolute;
  width: 1rem;
  height: 1rem;
  border: 0 solid rgba(125, 196, 228, 0.5);
  opacity: 0.6;
}

.callout::before {
  inset: 0.5rem auto auto 0.5rem;
  border-top-width: 1px;
  border-left-width: 1px;
}

.callout::after {
  inset: auto 0.5rem 0.5rem auto;
  border-bottom-width: 1px;
  border-right-width: 1px;
}

.callout > p {
  margin: 0;
}

/* Inline icons in body copy: the callout's note mark and the contact envelope.
   Stroked rather than filled, unlike the footer glyphs — those are brand marks
   that have to be solid, whereas a line icon at body-text size sits with the
   prose instead of blotting beside it. Drawn rather than set as a character,
   so neither depends on the reader having a font that carries the glyph, and
   neither can arrive as full colour on a platform that has an emoji form of
   it. Grouped so the two stay in step. */
.callout-icon,
.contact-icon {
  width: 1.05em;
  height: 1.05em;
  color: var(--links);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A flex item in .callout, nudged down to centre on the note's first line */
.callout-icon {
  flex: 0 0 auto;
  margin-top: 0.2em;
}

/* Sits in the text flow beside the address, so it needs a baseline shift.
   Water.css prefixes every mailto link with a colour emoji (and does the same
   for tel: and sms:, which this site has none of) — dropped here in favour of
   the icon above. */
.contact-icon {
  margin-right: 0.5em;
  vertical-align: -0.16em;
}

a[href^="mailto:"]::before {
  content: none;
}

/* Placeholder text for not-yet-populated sections */
.placeholder-note {
  text-align: center;
  font-size: 1.2em;
  margin: var(--space-xl) 0;
  color: var(--text-muted);
}

/* ========================================
   6. HEADINGS & TEXT
   ======================================== */

/* Serif headings (Fraunces) — editorial contrast against the sans body/logo */
h1, h2, h3, .panel-title {
  font-family: "Fraunces", Georgia, "Times New Roman", serif;
  font-weight: 600;
  font-optical-sizing: auto;
  letter-spacing: -0.01em;
}

h1, h2 {
  color: var(--links);
}


/* Subtle glow effects for important elements */
h1 {
  text-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
}

/* Keep the small heading labels/separators on the sans stack for contrast */
.section-tag, .section-sep {
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: normal;
}

/* Remove list bullets */
ul, ol {
  list-style: none;
  padding-left: 2em;
}

/* Put the markers back for a list of plain prose, where nothing else signals
   that the lines are items. The markers sit flush with the paragraph above
   rather than hanging in the gutter: the list drops the inherited padding and
   carries .indented instead, so it tracks that paragraph's margin at every
   breakpoint, and the marker moves inside the content box to start on the
   same edge. The negative text-indent then pulls the first line back out by
   the marker's own width, so wrapped lines sit under the text rather than
   under the marker — it cancels the padding exactly, which is what keeps the
   marker flush whatever the padding is set to. */
.pipeline-list {
  list-style: disc;
  list-style-position: inside;
  padding-left: 0;
}

.pipeline-list li {
  padding-left: 1.44em;
  text-indent: -1.44em;
}

/* Enhanced navigation feel (for both ul and ol) */
ul li, ol li {
  transition: transform 0.45s var(--ease-out-quart);
}

@media (hover: hover) {
  ul li:hover, ol li:hover {
    transform: translateX(3px);
  }

  /* Every other list on the site is link-bearing, so the nudge reads as an
     affordance. On prose it would promise a click that isn't there. */
  .pipeline-list li:hover {
    transform: none;
  }
}

/* ========================================
   7. FORMS & BUTTONS
   ======================================== */

/* Enhanced button interactions */
button, input[type="submit"], input[type="button"], input[type="reset"] {
  transition: all 0.4s var(--ease-out-quart);
  position: relative;
  overflow: hidden;
  /* Ensure button text is visible */
  color: var(--form-text) !important;
  -webkit-text-fill-color: var(--form-text) !important;
}

@media (hover: hover) {
  button:hover {
    box-shadow: 0 4px 15px rgba(65, 173, 255, 0.2);
    transform: translateY(-1px);
  }
}

button:active {
  transform: translateY(1px);
  box-shadow: 0 2px 8px rgba(65, 173, 255, 0.1);
}

/* Ripple effect for buttons */
button::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  transform: translate(-50%, -50%);
  transition: width 0.3s ease, height 0.3s ease;
}

button:active::after {
  width: 200px;
  height: 200px;
}

/* Classy cursor interaction for buttons */
button::before, summary::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
  transition: width 0.6s ease, height 0.6s ease;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

@media (hover: hover) {
  button:hover::before, summary:hover::before {
    width: 200px;
    height: 200px;
  }
}

/* Elegant form focus effects */
input:focus, textarea:focus, select:focus {
  transform: scale(1.02);
  box-shadow:
    0 0 0 2px var(--focus),
    0 4px 15px rgba(0, 150, 191, 0.1);
  backdrop-filter: blur(8px) saturate(1.2);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
}

/* ========================================
   8. CONTENT BLOCKS
   ======================================== */

/* Section rhythm + scroll-reveal easing.
   `transform` drives the reveal (opacity + rise). The hover state only touches
   box-shadow / background (a cyan glow, no lift) so it never fights the
   reveal's transform end-state — that collision is why the old lift died. */
section {
  opacity: 0.95;
  transition:
    opacity 0.7s var(--ease-out-quart),
    box-shadow 0.7s var(--ease-out-quart),
    transform 0.7s var(--ease-out-quart),
    background-color 0.7s var(--ease-out-quart);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  margin: 0 calc(-1 * var(--space-md));
  position: relative;
}

/* Cyan glow on hover, echoing the index.html navigation panels */
@media (hover: hover) {
  section:not(.panel-grid):hover {
    opacity: 1;
    background-color: rgba(32, 43, 56, 0.18);
    box-shadow:
      0 12px 34px rgba(0, 0, 0, 0.18),
      0 0 30px rgba(65, 173, 255, 0.12);
  }
}



/* ========================================
   8b. ENTRY RAIL (content pages)
   ======================================== */

/* The content pages are all one-section-per-entry, so each gets a rail down
   the left gutter with a node per section — the same content as before, read
   as a sequence rather than a stack. `.rail` draws the device; `.timeline`
   adds the one mark that only means anything on a page in date order, so
   pages carry `rail timeline` when their sections are dated (media, and the
   year groupings on publications and blog) and `rail` alone when they are not
   (projects, whose tag is a method rather than a year).

   Opted into with a class on <main>, never on the sections: the skill builder
   matches a bare `<section>` tag, so an attribute on one would drop that entry
   from the bundle. The rail and nodes are drawn with pseudo-elements that were
   otherwise unused, which leaves the markup, the <h3> convention and the
   scroll-reveal exactly as they were — the rail simply fades in with its own
   section, so the line draws itself down the page as you scroll.

   The rail lands on the text column's left edge, level with the page's h2,
   and the entries indent from it. Anchoring it there rather than out in the
   section's negative bleed is what keeps it on screen: below ~840px the body
   sits only 10px from the viewport edge while a section bleeds 16px past it,
   so a rail in that gutter would put half of every node off the page. The
   inset is the bleed itself, which the mobile breakpoint drops to zero. */
main.rail {
  --rail-inset: var(--space-md);
}

@media (max-width: 600px) {
  main.rail {
    --rail-inset: 0px;
  }
}

main.rail > section {
  padding-left: calc(var(--rail-inset) + var(--space-md));
}

/* One rail segment per section, drawn full height. Sections carry no vertical
   margin, so the segments meet and read as a single unbroken line. */
main.rail > section::before {
  content: "";
  position: absolute;
  left: var(--rail-inset);
  top: 0;
  bottom: 0;
  width: 1px;
  background: rgba(125, 196, 228, 0.22);
}

/* Fade the open ends, so a rail starts and stops rather than being cut off.
   A page can carry more than one run of sections — publications.html splits
   papers from proposals under separate h2s — so the ends are found by position
   rather than by counting: a section that opens a run sits right after that
   run's intro paragraph, and a section that closes one butts up against the
   next h2. */
main.rail > section:first-of-type::before,
main.rail > .page-intro + section::before {
  background: linear-gradient(
    to bottom, transparent, rgba(125, 196, 228, 0.22) 2.5rem);
}

main.rail > section:last-of-type::before {
  background: linear-gradient(
    to bottom, rgba(125, 196, 228, 0.22), transparent);
}

/* Deliberately its own rule rather than joined to the one above: a browser
   without :has() discards the whole selector list it appears in, which would
   take the :last-of-type fade down with it. Alone, it just no-ops. */
main.rail > section:has(+ h2)::before {
  background: linear-gradient(
    to bottom, rgba(125, 196, 228, 0.22), transparent);
}

/* A run of exactly one section opens and closes itself, so it needs both ends
   faded in a single gradient — otherwise whichever of the two rules above wins
   leaves the other end cut square. */
main.rail > .page-intro + section:last-of-type::before {
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(125, 196, 228, 0.22) 2.5rem,
    rgba(125, 196, 228, 0.22) calc(100% - 2.5rem),
    transparent);
}

main.rail > .page-intro + section:has(+ h2)::before {
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(125, 196, 228, 0.22) 2.5rem,
    rgba(125, 196, 228, 0.22) calc(100% - 2.5rem),
    transparent);
}

/* The node hangs off the heading rather than the section, so it tracks the
   first line of the title however the heading's own margins fall. Its offset
   is exactly the extra padding above, which puts it back on the rail. */
main.rail > section > h3 {
  position: relative;
}

main.rail > section > h3::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-md));
  top: 0.8em;                 /* centre of the first line at line-height 1.6 */
  width: 9px;
  height: 9px;
  margin-left: -4px;
  transform: translateY(-50%);
  border-radius: 50%;
  border: 1px solid rgba(125, 196, 228, 0.55);
  background: var(--background-body);
  transition:
    border-color 0.7s var(--ease-out-quart),
    box-shadow 0.7s var(--ease-out-quart);
}

/* A block short enough to skip year headings carries no <h3> for the node to
   hang on, so it goes on the first entry instead — same 0.8em drop, so it
   lands on that line's centre exactly as a heading node does. The extra
   horizontal offset is the list's own indent: `ul` carries padding-left: 2em,
   which the node has to climb back out of to reach the rail.

   Written out again rather than folded into the selector list above: :has() is
   discarded whole by browsers that lack it, and joining the two would take
   every node on the site down with it. Duplicated here, it only no-ops. */
main.rail > section:not(:has(h3)) li:first-child > p {
  position: relative;
}

main.rail > section:not(:has(h3)) li:first-child > p::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-md) - 2em);
  top: 0.8em;
  width: 9px;
  height: 9px;
  margin-left: -4px;
  transform: translateY(-50%);
  border-radius: 50%;
  border: 1px solid rgba(125, 196, 228, 0.55);
  background: var(--background-body);
  transition:
    border-color 0.7s var(--ease-out-quart),
    box-shadow 0.7s var(--ease-out-quart);
}

@media (hover: hover) {
  main.rail > section:not(:has(h3)):hover li:first-child > p::before {
    border-color: var(--links);
    box-shadow: 0 0 12px rgba(65, 173, 255, 0.35);
  }
}

/* Head of the timeline: the most recent entry is filled rather than hollow.
   Only on the dated pages — elsewhere a filled first node would claim a
   recency, or a precedence, that the ordering doesn't carry. */
main.rail.timeline > section:first-of-type > h3::before {
  background: var(--links);
  border-color: var(--links);
  box-shadow: 0 0 10px rgba(65, 173, 255, 0.45);
}

/* Picks up the same cyan the section glow uses, so hovering an entry lights
   its point on the rail */
@media (hover: hover) {
  main.rail > section:hover > h3::before {
    border-color: var(--links);
    box-shadow: 0 0 12px rgba(65, 173, 255, 0.35);
  }
}

/* ========================================
   8c. TEAM CARD (about)
   ======================================== */

/* Portrait beside a bio. The card tracks .indented rather than sitting flush
   left, so it lines up with the prose above it at both breakpoints. The
   profile icons reuse .social-link — the same mark, size and hover lift as the
   footer, which is why that rule is no longer scoped to .footer-social.

   The card is a name, a role and its links beside a portrait, held as two flex
   columns aligned at the top so the name sits level with the top of the
   picture. */
.team-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
  margin-left: 2em;
}

.team-photo {
  flex: 0 0 clamp(132px, 26%, 200px);
  width: clamp(132px, 26%, 200px);
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid rgba(125, 196, 228, 0.28);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.26);
}

.team-bio {
  flex: 1 1 auto;
  min-width: 0;
}

.team-bio h3 {
  margin: 0;
}

.team-role {
  margin-top: var(--space-xs);
  margin-bottom: var(--space-sm);
}

.team-social {
  display: flex;
  gap: var(--space-md);
  margin-top: var(--space-md);
}

/* Stack once there is no room for two columns, and follow .indented down to
   its narrow-screen margin so the card stays aligned with the prose. */
/* Stack once there is no room for two columns, and follow .indented down to
   its narrow-screen margin so the card stays aligned with the prose. */
@media (max-width: 600px) {
  .team-card {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
    margin-left: 0.5em;
  }

  .team-photo {
    flex-basis: auto;
    width: clamp(120px, 45%, 180px);
  }
}

/* ========================================
   8d. SITE THESIS (home)
   ======================================== */

/* The homepage's one line of prose, and the site's only h1. Deliberately
   carries no surface of its own — no border, fill or shadow — so it does not
   read as one more panel stacked above the panel grid. Bordered boxes compete
   with each other; unenclosed display type on the water photograph does not,
   and the open space around it is what makes it lead rather than queue.

   Sits directly in <main> rather than in a <section>, because a section would
   bring the hover glow and paint a phantom box behind a line that is meant to
   float. Fraunces at display size drops to weight 400: 600 at 2rem is heavy
   enough to shout, and the sentence carries the emphasis on its own. */
.site-thesis {
  position: relative;
  padding-left: var(--space-lg);
  font-size: clamp(1.45rem, 3.6vw, 2.15rem);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin: var(--space-xl) 0 var(--space-2xl);
  color: var(--text-bright);
  text-shadow: 0 0 18px rgba(65, 173, 255, 0.1);
  text-wrap: balance;
}

/* A quotation rule, and the only mark the line carries. It keeps the
   statement's left edge on the panel grid's alignment while the text steps in
   from it, so the block reads as set apart rather than as another box.

   Fades down its length the way the entry rail fades at its ends on the
   content pages — the same device, so the homepage belongs to that system
   instead of introducing a second one. Inset top and bottom by a fraction of
   an em so it tracks the cap height rather than overshooting into the leading. */
.site-thesis::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.2em;
  bottom: 0.3em;
  width: 2px;
  border-radius: 1px;
  background: linear-gradient(
    to bottom, var(--links), rgba(125, 196, 228, 0.22));
}

/* One accented word, the way the wordmark accents "lake" — enough to give the
   line a focal point without a box around it. */
.thesis-accent {
  color: var(--links);
}

@media (max-width: 600px) {
  .site-thesis {
    padding-left: var(--space-md);
    margin: var(--space-lg) 0 var(--space-xl);
  }
}

/* ========================================
   9. HOME NAVIGATION PANELS
   ======================================== */

.panel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

/* The three children are centred as one cluster rather than spread to the
   panel edges. Spacing is asymmetric on purpose — a wider gap under the
   ordinal sets it apart as a label, while the description sits close under
   the title so the two read as a single unit. Uniform spacing made all three
   look like an evenly-spaced list. */
.navigation-panel {
  min-height: 220px;
  display: grid;
  align-content: center;
  justify-items: center;
  text-align: center;
  gap: 0;
  padding: 1.15rem;
  border: 1px solid rgba(125, 196, 228, 0.22);
  border-radius: var(--radius-md);
  background:
    linear-gradient(135deg, rgba(32, 43, 56, 0.84), rgba(16, 25, 34, 0.66)),
    radial-gradient(circle at top right, rgba(125, 196, 228, 0.18), transparent 36%);
  color: var(--links);
  text-decoration: none;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.24);
  position: relative;
  overflow: hidden;
  transition:
    transform 0.55s var(--ease-out-quart),
    border-color 0.55s var(--ease-out-quart),
    box-shadow 0.55s var(--ease-out-quart);
}

/* Viewfinder corners at opposite ends of the panel. A single floating bracket
   read as a stray mark once the content was centred; a diagonal pair hugs the
   edges instead, so it frames the cluster rather than competing with it. */
.navigation-panel::before,
.navigation-panel::after {
  content: "";
  position: absolute;
  width: 1.5rem;
  height: 1.5rem;
  border: 0 solid rgba(125, 196, 228, 0.5);
  opacity: 0.6;
  transition: transform 0.55s var(--ease-out-quart), opacity 0.55s var(--ease-out-quart);
}

.navigation-panel::before {
  inset: 0.7rem auto auto 0.7rem;
  border-top-width: 1px;
  border-left-width: 1px;
}

.navigation-panel::after {
  inset: auto 0.7rem 0.7rem auto;
  border-bottom-width: 1px;
  border-right-width: 1px;
}

/* Muted to match .panel-copy: the ordinal is decoration, so the two quiet
   supporting elements bracket the title rather than compete with it. */
.panel-index {
  color: var(--text-muted);
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-decoration: none;
  margin-bottom: var(--space-md);
}

.panel-title {
  color: inherit;
  font-size: 2.1rem;
  line-height: 1;
}

/* Same minor-label treatment as .section-tag ("Data", "AI") on the content
   pages: small, light, muted — so the serif panel title stays dominant.
   0.875rem matches the ~14px .section-tag renders at inside an h3; the font
   family already resolves identically (both start at system-ui). */
.panel-copy {
  max-width: 24rem;
  font-size: 0.875rem;
  font-weight: 300;
  color: var(--text-muted);
  line-height: 1.45;
  text-decoration: none;
  /* Clears the descender on "Projects" without breaking the title pairing */
  margin-top: var(--space-sm);
}

@media (hover: hover) {
  .navigation-panel:hover {
    text-decoration: none;
    transform: translateY(-4px);
    border-color: rgba(125, 196, 228, 0.54);
    box-shadow:
      0 22px 60px rgba(0, 0, 0, 0.34),
      0 0 36px rgba(65, 173, 255, 0.12);
  }

  /* The pair pushes apart on hover — the frame opening up */
  .navigation-panel:hover::before {
    opacity: 1;
    transform: translate(-3px, -3px);
  }

  .navigation-panel:hover::after {
    opacity: 1;
    transform: translate(3px, 3px);
  }
}


/* ========================================
   9b. CONNECT YOUR AGENT (home)
   ======================================== */

/* A plain content section, styled exactly like the sections on the inner
   pages — no border, no panel background, just the shared `section` padding
   and hover glow. Only the download affordance carries styling, and it
   borrows the established .nav-button language rather than inventing one. */
.agent-connect {
  margin-top: var(--space-lg);
  text-align: right;
}

/* The measure stays capped, so the block has to be pushed to the right edge —
   text-align alone would leave it sitting on the left with ragged-right text. */
.agent-connect p {
  max-width: 44rem;
  margin-left: auto;
}

/* Flex children ignore text-align, so the row needs its own end alignment. */
.agent-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
}

.agent-download,
.agent-copy {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 8px 14px;
  background: rgba(32, 43, 56, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(65, 173, 255, 0.15);
  border-radius: var(--radius-md);
  color: var(--text-main);
  text-decoration: none;
  transition:
    background-color 0.5s var(--ease-out-quart),
    border-color 0.5s var(--ease-out-quart),
    box-shadow 0.5s var(--ease-out-quart),
    color 0.5s var(--ease-out-quart),
    transform 0.5s var(--ease-out-quart);
}

.agent-download svg,
.agent-copy svg {
  width: 1.05em;
  height: 1.05em;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Secondary action: same shape, no fill — the zip is the primary path */
.agent-copy {
  background: transparent;
  color: var(--text-muted);
}

/* Brief confirmation after the URL lands on the clipboard */
.agent-copy.is-copied {
  color: var(--links);
  border-color: rgba(65, 173, 255, 0.5);
}

@media (hover: hover) {
  /* Shares the lift and shadow with .agent-download (and .nav-button, and the
     footer icons) — hover motion is consistent across the site. Only the fill
     differs, which is what marks this as the secondary action. */
  .agent-copy:hover {
    background: rgba(32, 43, 56, 0.4);
    color: var(--text-main);
    transform: translateY(-2px);
    text-decoration: none;
    text-shadow: none;
    box-shadow:
      0 8px 22px rgba(0, 0, 0, 0.18),
      0 0 18px rgba(65, 173, 255, 0.18);
  }

  .agent-download:hover {
    background: var(--links);
    color: var(--background-body);
    transform: translateY(-2px);
    text-decoration: none;
    text-shadow: none;
    box-shadow:
      0 8px 22px rgba(0, 0, 0, 0.18),
      0 0 18px rgba(65, 173, 255, 0.18);
  }
}

/* Same minor-label treatment as .panel-copy / .section-tag */
.agent-meta {
  font-size: 0.875rem;
  font-weight: 300;
  color: var(--text-muted);
  margin-left: var(--space-sm);
}

/* Cancels the inline-span offset above; `auto` keeps this paragraph flush with
   the others against the right edge rather than pinned to the left. */
.agent-connect p.agent-meta {
  margin-left: auto;
}

.agent-connect code {
  font-size: 0.9em;
}

@media (max-width: 600px) {
  /* Stack the button and its size label instead of letting them collide */
  .agent-meta {
    display: block;
    margin-left: 0;
    margin-top: var(--space-sm);
  }
}

/* ========================================
   10. TABLES & IMAGES
   ======================================== */

/* Elegant table hover effects */
tbody tr {
  transition: background-color 0.2s ease, transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  transform: perspective(1000px) rotateX(0deg);
}

@media (hover: hover) {
  tbody tr:hover {
    background-color: rgba(65, 173, 255, 0.05);
    transform: perspective(1000px) rotateX(2deg) scale(1.001);
    z-index: 1;
    position: relative;
  }
}

/* Smooth image hover effects */
img {
  transition: transform 0.55s var(--ease-out-quart), filter 0.55s var(--ease-out-quart);
  border-radius: var(--radius-sm);
}

@media (hover: hover) {
  img:hover {
    transform: scale(1.02);
    filter: brightness(1.1);
  }
}

/* ========================================
   11. DETAILS & SUMMARY
   ======================================== */

/* Enhanced details/summary */
details {
  transition: box-shadow 0.4s var(--ease-out-quart), transform 0.4s var(--ease-out-quart);
  border-radius: var(--radius-md);
  position: relative;
  overflow: hidden;
}

details[open] {
  transform: scale(1.005);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
  border-radius: var(--radius-lg);
}

summary {
  transition: color 0.4s var(--ease-out-quart);
  position: relative;
  overflow: hidden;
}

@media (hover: hover) {
  summary:hover {
    color: var(--links);
  }
}

/* ========================================
   12. FOOTER
   ======================================== */

/* Subtle footer enhancement */
footer {
  transition: border-color 0.3s ease;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm) var(--space-md);
}

footer > p {
  margin: 0;
}

@media (hover: hover) {
  footer:hover {
    border-color: var(--links);
  }
}

/* Footer social / contact icons — right-aligned on the copyright line */
.footer-social {
  display: flex;
  gap: var(--space-lg);
  margin-left: auto;
}

.social-link {
  display: inline-flex;
  color: var(--text-muted);
  transition: color 0.45s var(--ease-out-quart),
              filter 0.45s var(--ease-out-quart),
              transform 0.45s var(--ease-out-quart);
}

.social-link svg {
  width: 22px;
  height: 22px;
  display: block;
  fill: currentColor;
}

@media (hover: hover) {
  .social-link:hover {
    color: var(--links);
    filter: drop-shadow(0 0 6px rgba(65, 173, 255, 0.35));
    transform: translateY(-2px);
  }
}

.social-link:focus-visible {
  color: var(--links);
  outline: none;
  filter: drop-shadow(0 0 6px rgba(65, 173, 255, 0.35));
}

/* ========================================
   13. GLOBAL ENHANCEMENTS
   ======================================== */

/* Smooth page transitions */
html {
  scroll-behavior: smooth;
}

/* Keep anchored headings clear of the top edge on in-page jumps */
h1, h2, h3, [id] {
  scroll-margin-top: var(--space-xl);
}

/* Skip-to-content link: hidden until keyboard-focused */
.skip-link {
  position: absolute;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: 10000;
  padding: var(--space-sm) var(--space-md);
  background: var(--links);
  color: var(--background-body);
  border-radius: var(--radius-md);
  text-decoration: none;
  font-weight: 500;
  transform: translateY(-150%);
  transition: transform 0.25s var(--ease-out-expo);
}

.skip-link:focus {
  transform: translateY(0);
}

/* Scroll-reveal: sections rise + fade once as they enter the viewport.
   Only active when JS adds .reveal-enabled to <html>, so no-JS = fully visible. */
.reveal-enabled section:not(.panel-grid) {
  opacity: 0;
  transform: translateY(16px);
  will-change: opacity, transform;
  /* Transition (all four properties) is inherited from the base `section`
     rule so reveal and hover share one consistent, mellow timing. */
}

.reveal-enabled section.in-view {
  opacity: 0.95;
  transform: none;
}

/* Enhanced selection with shimmer */
::selection {
  background: linear-gradient(45deg, var(--selection), var(--links), var(--selection));
  background-size: 300% 300%;
  animation: selectionShimmer 2s ease-in-out infinite;
  text-shadow: none;
}

/* Enhanced scrollbar */
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--scrollbar-thumb), var(--links));
  transition: background 0.2s ease;
}

::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--links), var(--scrollbar-thumb-hover));
}

/* Elegant focus ring */
*:focus-visible {
  outline: 2px solid transparent;
  box-shadow:
    0 0 0 2px var(--links),
    0 0 20px rgba(65, 173, 255, 0.3);
  animation: focusPulse 1s ease-in-out infinite alternate;
}

/* Elegant loading state */
body.loading * {
  opacity: 0.7;
  pointer-events: none;
}

/* ========================================
   14. RESPONSIVE DESIGN
   ======================================== */

/* Mobile-friendly touch enhancements */
@media (max-width: 600px) {
  /* Fixed background attachment triggers costly repaints on scroll on mobile */
  body {
    background-attachment: scroll;
  }

  .nav-button {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .panel-title {
    font-size: 1.65rem;
  }

  .button-nav {
    flex-direction: column;
  }

  .button-nav .nav-button {
    flex: none;
    width: 100%;
  }

  .panel-grid {
    grid-template-columns: 1fr;
  }

  .navigation-panel {
    min-height: 170px;
  }

  section {
    margin: 0;
  }

  .justified-text {
    text-align: left;
    hyphens: none;
    -webkit-hyphens: none;
  }

  .overlake-inline {
    font-size: 1.1em;
  }

  .indented {
    margin-left: 0.5em;
  }

  .citation-row {
    flex-direction: column;
    gap: 0.65rem;
  }

  .citation-row .citation-widget {
    flex-basis: auto;
    width: min(240px, 100%);
    align-self: flex-end;
  }

}

/* ========================================
   15. ACCESSIBILITY
   ======================================== */

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  #particles-js {
    display: none;
  }

  /* Never leave reveal content hidden if motion is reduced */
  .reveal-enabled section:not(.panel-grid) {
    opacity: 0.95 !important;
    transform: none !important;
  }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ========================================
   16. PRINT
   ======================================== */

@media print {
  body {
    background: #fff !important;
    color: #111 !important;
    font-family: Georgia, "Times New Roman", serif;
    padding: 1.5cm;
    animation: none;
  }

  /* Drop decorative and interactive chrome from the printed page */
  #particles-js,
  .button-nav,
  .skip-link,
  .callout-icon,
  .contact-icon,
  footer {
    display: none !important;
  }

  .overlake-main,
  .overlake-lake,
  .overlake-bio,
  h1, h2, h3 {
    color: #111 !important;
    text-shadow: none !important;
  }

  a {
    color: #0645ad !important;
    text-decoration: underline;
  }

  /* Expose destination URLs for external links */
  main a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }

  .reveal-enabled section:not(.panel-grid) {
    opacity: 1 !important;
    transform: none !important;
  }

  section {
    margin: 0 0 0.6cm;
    padding: 0;
    background: none !important;
    box-shadow: none !important;
    page-break-inside: avoid;
  }

  /* The panel surfaces (home grid, and the about callout that now shares
     their styling) are dark-on-dark for the screen. On paper the fill would
     swallow the text, so flatten them to a plain rule and drop the decorative
     corner marks, which would otherwise print as stray ticks. */
  .navigation-panel,
  .callout {
    background: none !important;
    box-shadow: none !important;
    border: 1px solid #bbb !important;
    min-height: 0 !important;
  }

  .navigation-panel::before,
  .navigation-panel::after,
  .callout::before,
  .callout::after,
  main.rail > section::before,
  main.rail > section > h3::before {
    display: none !important;
  }

  /* The rail is gone, so the gutter it stood in goes with it */
  main.rail > section {
    padding-left: 0 !important;
  }

  .panel-index,
  .panel-title,
  .panel-copy {
    color: #111 !important;
  }

  /* A drop shadow prints as a grey smudge; the border carries the frame */
  .team-photo {
    box-shadow: none !important;
    border: 1px solid #bbb !important;
  }

  h2, h3 {
    page-break-after: avoid;
  }
}
