/* ==========================================================================
   Tynan Kelly — personal site
   Plain CSS, no build step. Design: refined academic.
   Sections: 1) Tokens/theme  2) Base  3) Nav  4) Hero  5) Content
             6) About  7) CV  8) Teaching  9) Footer  10) Responsive
   ========================================================================== */

/* 1) Design tokens + theme ------------------------------------------------- */
:root {
  interpolate-size: allow-keywords; /* lets height animate to/from auto */
  --font-display: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-sans: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --navy: #1f3a5f;
  --navy-strong: #16233b;
  --accent: #2f5c8f;

  --bg: #ffffff;
  --surface: #f5f6f8;
  --surface-2: #eef1f5;
  --text: #1a1d24;
  --muted: #5a6472;
  --border: #e3e7ec;

  --hero-overlay: linear-gradient(180deg, rgba(16,22,34,0.55) 0%, rgba(16,22,34,0.35) 45%, rgba(16,22,34,0.6) 100%);
  --nav-bg: rgba(16, 22, 34, 0.72);

  --nav-h: 78px;
  --maxw: 1120px;
  --radius: 10px;
  --shadow: 0 6px 24px rgba(16, 22, 34, 0.08);
}

@media (prefers-color-scheme: dark) {
  :root {
    --accent: #85b0e0;
    --bg: #0f1420;
    --surface: #161c2b;
    --surface-2: #1c2436;
    --text: #e7e9ee;
    --muted: #9aa4b2;
    --border: #27314a;
    --nav-bg: rgba(9, 13, 22, 0.78);
    --shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
  }
}

/* 2) Base ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--bg);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 500; line-height: 1.2; letter-spacing: 0.03em; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

img { max-width: 100%; display: block; }

.container { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 1.5rem; }

.skip-link {
  position: absolute; left: -999px; top: 0;
  background: var(--bg); color: var(--text); padding: 0.6rem 1rem; z-index: 200;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* Lowercase display style ---------------------------------------------------
   Applied only to site "chrome": navigation, buttons, page titles, and
   generic section labels. Real content — sentences, course names, proper
   nouns, citations — keeps its true capitalization. The HTML stays properly
   capitalized; this is presentation only, so it is easy to undo. */
.nav-links a,
.footer-links a,
.btn,
.hero-eyebrow,
.hero-title,
.section-title,
.cv-accordion--labels > details > summary {
  text-transform: lowercase;
}

/* 3) Navigation ------------------------------------------------------------ */
.site-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.site-nav .container {
  display: flex; align-items: center; justify-content: space-between;
  min-height: var(--nav-h);
}

/* Transparent over the hero photo, solidifying once you scroll into the
   page content. A 1-line script in each page's <head> toggles .nav-at-top
   on <html>. The solid bar is the default, so the nav stays readable even
   if scripting is unavailable. */
.site-nav {
  transition: background-color 0.25s ease, border-color 0.25s ease,
              backdrop-filter 0.25s ease;
}
html.nav-at-top .site-nav {
  background-color: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.brand {
  font-family: var(--font-display); font-size: clamp(1.45rem, 2.1vw, 1.75rem); font-weight: 500;
  color: #fff; letter-spacing: 0.02em;
}
.brand:hover { text-decoration: none; opacity: 0.9; }

.nav-links { list-style: none; display: flex; gap: 2rem; margin: 0; padding: 0; }
.nav-links a {
  color: rgba(255, 255, 255, 0.85); font-weight: 500; font-size: 0.98rem;
  padding: 0.4rem 0; position: relative;
}
.nav-links a:hover { color: #fff; text-decoration: none; }
.nav-links a[aria-current="page"] { color: #fff; }
.nav-links a[aria-current="page"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px;
  height: 2px; background: currentColor;
}

/* CSS-only mobile menu (checkbox hack) */
.nav-toggle { display: none; }
.nav-toggle-label {
  display: none; cursor: pointer; padding: 0.5rem; color: #fff;
}
.nav-toggle-label span,
.nav-toggle-label span::before,
.nav-toggle-label span::after {
  display: block; width: 24px; height: 2px; background: #fff; position: relative;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle-label span::before { content: ""; position: absolute; top: -7px; }
.nav-toggle-label span::after { content: ""; position: absolute; top: 7px; }

/* 4) Hero ------------------------------------------------------------------ */
.hero {
  position: relative;
  background: var(--hero-overlay), url("../assets/img/mountain.jpg");
  background-size: cover; background-position: center 40%;
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  padding-top: var(--nav-h); /* image flows behind the fixed nav */
}
.hero--home { min-height: 100vh; }
.hero--page { min-height: 50vh; }

.hero-inner { padding: 3rem 1.5rem; max-width: 900px; }
.hero-eyebrow {
  letter-spacing: 0.09em; font-size: clamp(1.1rem, 3vw, 1.6rem);
  font-weight: 400; color: rgba(255, 255, 255, 0.95); margin: 0 0 0.4rem;
}
.hero-title {
  font-size: clamp(2.5rem, 6vw, 4rem); margin: 0; color: #fff;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.35);
}

.hero-actions {
  margin-top: 2.5rem; display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center;
}
.btn {
  display: inline-block; font-family: var(--font-sans); font-weight: 600;
  font-size: 0.9rem; letter-spacing: 0.12em;
  padding: 0.85rem 1.6rem; border-radius: 4px; border: 1px solid transparent;
  cursor: pointer; transition: transform 0.15s ease, background 0.15s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-2px); }
.btn--solid { background: #fff; color: var(--navy-strong); }
.btn--solid:hover { background: #eef1f5; }
.btn--outline { background: transparent; color: #fff; border-color: rgba(255,255,255,0.7); }
.btn--outline:hover { background: rgba(255, 255, 255, 0.12); }
.btn--accent { background: var(--accent); color: #fff; }
.btn--accent:hover { filter: brightness(1.08); }

/* 5) Content --------------------------------------------------------------- */
.section { padding: 4.5rem 0; }
.section--tight { padding: 3rem 0; }
.section-title {
  font-size: clamp(1.8rem, 4vw, 2.4rem); margin: 0 0 1.75rem;
  color: var(--text);
}
.section-title::after {
  content: ""; display: block; width: 54px; height: 3px;
  background: var(--accent); margin-top: 0.75rem; border-radius: 2px;
}
.lead { font-size: 1.08rem; }
.prose p { margin: 0 0 1.15rem; }
.prose p:last-child { margin-bottom: 0; }

/* 6) About ----------------------------------------------------------------- */
.about-grid {
  display: grid; grid-template-columns: 320px 1fr; gap: 3rem; align-items: start;
}
.about-photo {
  border-radius: var(--radius); box-shadow: var(--shadow);
  width: 100%; height: auto;
}

/* 6b) Research — trefoil knot ----------------------------------------------
   The simplest nontrivial knot, drawn from its parametric equations. The curve
   is broken only at its three genuine under-crossings, which is what makes the
   over/under reading correct. It draws itself in on load, then rotates slowly. */
.research-grid {
  display: grid; grid-template-columns: 1fr 300px; gap: 3rem; align-items: center;
}
.knot { width: 100%; max-width: 300px; height: auto; overflow: visible; justify-self: center; }
.knot path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* Three arcs, one per span between under-crossings, drawn as separate paths
   with a staggered start (--d = 0 / 0.35 / 0.70s). They overlap in time, so
   two or three strokes are in motion at once, which reads more fluidly than
   one sequential stroke.

   The dash gap is deliberately longer than the dash (100 vs 101). With a
   plain `dasharray: 100` on a pathLength:100 path the pattern wraps, leaving
   the path's END point inside the dash at rest — which `stroke-linecap: round`
   renders as a stray dot just before an under-crossing until that arc's
   delay elapses. The uneven pattern removes the wrap, so no dot. */
.knot .strand {
  stroke: var(--accent); stroke-width: 5;
  stroke-dasharray: 100 101; stroke-dashoffset: 100;
  animation: knot-draw 1.5s cubic-bezier(.65, 0, .35, 1) forwards;
  animation-delay: var(--d, 0s);
}
@keyframes knot-draw { to { stroke-dashoffset: 0; } }
.knot-caption {
  text-align: center; color: var(--muted); font-size: 0.9rem;
  margin: 1rem 0 0; max-width: 300px; justify-self: center;
}

@media (prefers-reduced-motion: reduce) {
  .knot .strand { animation: none; stroke-dashoffset: 0; }
}

/* 7) CV -------------------------------------------------------------------- */
.cv-item { margin-bottom: 0.9rem; }
.cv-list { list-style: none; margin: 0; padding: 0; }
.cv-list li { padding: 0.35rem 0; border-bottom: 1px dashed var(--border); }
.cv-list li:last-child { border-bottom: none; }
.cv-list .cv-detail { color: var(--muted); }

.cv-accordion { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
details.cv-section { border-bottom: 1px solid var(--border); background: var(--bg); }
details.cv-section:last-child { border-bottom: none; }
details.cv-section > summary {
  cursor: pointer; list-style: none; padding: 1.05rem 1.4rem;
  font-family: var(--font-display); font-size: 1.05rem; font-weight: 500;
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface); transition: background 0.15s ease;
}
details.cv-section > summary:hover { background: var(--surface-2); }
details.cv-section > summary::-webkit-details-marker { display: none; }
details.cv-section > summary::after {
  content: "+"; font-family: var(--font-sans); font-weight: 400;
  font-size: 1.5rem; color: var(--muted); line-height: 1;
}
details.cv-section[open] > summary { background: var(--surface-2); }
details.cv-section[open] > summary::after { content: "\2013"; }
.cv-section-body { padding: 1.2rem 1.4rem; }

/* Animated open/close — progressive enhancement. Browsers without
   ::details-content / interpolate-size simply open instantly. */
details.cv-section::details-content {
  block-size: 0;
  overflow: hidden;
  transition: block-size 0.3s ease, content-visibility 0.3s allow-discrete;
}
details.cv-section[open]::details-content { block-size: auto; }
@media (prefers-reduced-motion: reduce) {
  details.cv-section::details-content { transition: none; }
}
.cv-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.cv-tags span {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.25rem 0.75rem; font-size: 0.9rem; color: var(--muted);
}
.cv-download { margin-top: 2rem; }

/* 8) Teaching -------------------------------------------------------------- */
.course-now {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem; margin-top: 1.25rem;
}
.course-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1.1rem 1.25rem;
}
.course-card .num { font-weight: 600; color: var(--accent); display: block; }
.course-card .name { color: var(--muted); font-size: 0.95rem; }

.teaching-block { margin-top: 2.5rem; }
.teaching-block h3 {
  font-size: 1.3rem; margin: 0 0 1rem; padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}
.teaching-block .role { font-weight: 600; margin: 1.1rem 0 0.5rem; color: var(--text); }
.course-log { list-style: none; margin: 0; padding: 0; }
.course-log li { padding: 0.4rem 0; border-bottom: 1px dashed var(--border); }
.course-log li:last-child { border-bottom: none; }
.course-log .num { font-weight: 600; }
.course-log .terms { color: var(--muted); }

/* 9) Footer ---------------------------------------------------------------- */
.site-footer {
  background: var(--navy-strong); color: rgba(255, 255, 255, 0.85);
  padding: 2.5rem 0;
}
.site-footer .container {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 1rem;
}
.footer-links { list-style: none; display: flex; gap: 1.5rem; margin: 0; padding: 0; }
.footer-links a { color: rgba(255, 255, 255, 0.85); font-size: 0.95rem; }
.footer-links a:hover { color: #fff; }
.footer-copy { font-size: 0.9rem; color: rgba(255, 255, 255, 0.6); }

/* 10) Responsive ----------------------------------------------------------- */
@media (max-width: 720px) {
  .nav-toggle-label { display: block; }
  .nav-links {
    position: absolute; top: var(--nav-h); left: 0; right: 0;
    flex-direction: column; gap: 0; background: var(--nav-bg);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    padding: 0.5rem 1.5rem 1rem; border-bottom: 1px solid rgba(255,255,255,0.08);
    max-height: 0; overflow: hidden; transition: max-height 0.25s ease;
  }
  .nav-links li { width: 100%; }
  .nav-links a { display: block; padding: 0.75rem 0; }
  .nav-toggle:checked ~ .nav-links { max-height: 320px; }
  .nav-toggle:checked ~ .nav-toggle-label span { background: transparent; }
  .nav-toggle:checked ~ .nav-toggle-label span::before { transform: rotate(45deg); top: 0; }
  .nav-toggle:checked ~ .nav-toggle-label span::after { transform: rotate(-45deg); top: 0; }

  .about-grid { grid-template-columns: 1fr; gap: 1.75rem; }
  .research-grid { grid-template-columns: 1fr; gap: 2.5rem; }
  .about-photo { max-width: 280px; }
  .section { padding: 3rem 0; }
}
