/* ===========================================================================
   Hand-written additions and corrections.

   assets/css/site.css is regenerated from each Claude Design export by
   tools/unbundle.py, so anything written there is lost on the next rebuild.
   This file is never regenerated. Everything we add by hand lives here.


   The page is authored with inline styles, so most rules need !important to
   win. Each one is keyed off the inline value it corrects, which keeps it
   self-documenting and lets it survive a fresh export.

   Do not edit index.html for styling.
   =========================================================================== */

/* === PDF links ============================================================
   The "PDF" link under a publication's journal line, revealed by the script
   at the bottom of index.html once the file exists in papers/. */

/* .card-meta is a flex row, so give the link a full-width basis to put it on
   its own line rather than squeezing it in beside the journal name. */
.card-meta { flex-wrap: wrap; }
.card-meta .pdf-link { flex: 0 0 100%; }

.pdf-a {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  padding-bottom: 1px;
}
.pdf-a:hover { color: var(--color-accent-900); text-decoration: none; }

/* The two affordances on a card whose PDF is present. */
/* `hidden` is only a user-agent `display: none` rule, so any author `display`
   declaration defeats it. Without this the actions show on every card, including
   the ones whose PDF is not there. */
.paper-actions[hidden] { display: none; }

.paper-actions {
  display: flex;
  flex: 0 0 100%;
  align-items: center;
  gap: 14px;
  margin-top: 12px;
}

.paper-read {
  font-family: var(--font-heading);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-neutral-100);
  background: var(--color-accent-800);
  border: 0;
  padding: 7px 14px;
  cursor: pointer;
  transition: background-color .18s ease;
}
.paper-read::after { content: " \2197"; }          /* north-east arrow */
.paper-read:hover { background: var(--color-accent-900); }

/* A publication card with a readable PDF invites the click; one without is
   left exactly as it was. */
article.card[data-paper-ready] {
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
article.card[data-paper-ready]:hover {
  border-color: var(--color-accent-800) !important;
  box-shadow: 0 6px 20px rgb(18 35 58 / 13%);
  transform: translateY(-2px);
}
article.card[data-paper-ready]:focus-within {
  border-color: var(--color-accent-800) !important;
}


/* === Posters ==============================================================
   Rows in Talks and Posters whose presentation PDF is hosted. These are
   compact list rows rather than cards, so the treatment is quieter: a tinted
   band on hover and a small link under the venue. */

.poster-actions[hidden] { display: none; }        /* see the note above */
.poster-actions { margin-top: 5px; }

/* A row can offer the published abstract record, the hosted poster, or both.
   They belong together under the venue rather than split between the date
   gutter and the content cell, so unbundle.py moves the external one down
   into this flex row. Abstract first, then poster. The poster half keeps its
   own hidden wrapper, so a row with an abstract and no uploaded poster shows
   just the one link and no empty gap. */
.talk-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 18px;
  margin-top: 5px;
}
.talk-actions .poster-actions { margin-top: 0; }

.poster-a {
  font-family: var(--font-heading);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  padding-bottom: 1px;
}
.poster-a::after { content: " \2197"; }
.poster-a:hover { color: var(--color-accent-900); text-decoration: none; }

/* The tint wants to bleed 12px into the gutters; the row must not move.
   Doing that with a negative margin and matching padding fails twice over:
   the row carries an inline `padding:14px 0` from the export that wins over
   the stylesheet, and even with !important the row's border box still grows
   by 24px, so the divider rule above a row with a hosted poster ran wider
   than the rules around it. Painting the tint with a pseudo-element instead
   leaves the row's geometry untouched, so every row in the section shares one
   left edge and one rule width whether or not its poster is uploaded. */
.talk-row[data-paper-ready] {
  cursor: pointer;
  position: relative;
}
.talk-row[data-paper-ready]::before {
  content: "";
  position: absolute;
  inset: 0 -12px;
  background: transparent;
  transition: background-color .18s ease;
  pointer-events: none;
}
.talk-row[data-paper-ready]:hover::before,
.talk-row[data-paper-ready]:focus-within::before {
  background: color-mix(in srgb, var(--color-accent-700) 7%, transparent);
}
/* Keep the text above the tint. */
.talk-row[data-paper-ready] > * { position: relative; }

@media (prefers-reduced-motion: reduce) {
  article.card[data-paper-ready],
  .talk-row[data-paper-ready]::before,
  .paper-read { transition: none; }
  article.card[data-paper-ready]:hover { transform: none; }
}


/* === Outbound links =======================================================
   Every link that leaves the site gets the same north-east arrow the poster
   and paper links carry, so a reader can tell at a glance what is a link.
   Matched on the href rather than a class, because index.html is generated
   from the Claude Design export and these links carry no class of their own;
   an attribute selector keeps working when the page is rebuilt.

   Relative links are not matched, so the reader's own controls and the
   "View poster" / "Read paper" links -- which point at files in posters/ and
   papers/ -- keep the single arrow they already had and never get a second. */

/* The same face the poster links wear, so every arrow link reads as one
   family: condensed heading type, uppercase, letter-spaced, with a hairline
   underline that is quieter than a browser default. */
a[href^="http"]:not(.btn) {
  font-family: var(--font-heading);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent);
  padding-bottom: 1px;
}
a[href^="http"]:not(.btn):hover { color: var(--color-accent-900); }

/* The export fits a long journal name by shrinking it with a container-query
   font size and pinning it to one line: `clamp(11px,4.6cqi,14.5px)` plus
   `white-space:nowrap`, inline on a span inside the link. Uppercasing the
   text and opening the letter-spacing made it wider than that clamp had
   budgeted for, and nowrap turned the excess into sideways scroll -- 17px at
   768 and 31px at 1024.

   Only the three longest journal names carry that span; every other link is
   plain text and takes the 12px above. So the clamp was also the reason the
   journal lines came out at two different sizes -- "Brain Sciences, 2024" at
   the clamp's 14.5px ceiling next to "Cells, 2024" at 12px. Dropping both
   declarations makes every outbound link one size and lets a long name wrap
   instead of scrolling the page sideways. !important because what they
   override is inline. */
a[href^="http"]:not(.btn) [style*="font-size:clamp"] {
  font-size: inherit !important;
  white-space: normal !important;
}

a[href^="http"]:not(.btn)::after { content: "\00A0\2197"; }

/* A no-break space so the arrow cannot be orphaned onto its own line, and
   an empty alt string so screen readers do not announce "north east arrow"
   after every link. The pair is deliberate: a browser without support for
   the alt syntax drops the second rule as invalid and keeps the first. */
a[href^="http"]:not(.btn)::after { content: "\00A0\2197" / ""; }

/* mailto: and tel: are left alone -- the arrow conventionally means "opens
   elsewhere on the web", and the address is already self-evidently an
   address.

   .btn is excluded for two reasons. A filled button already reads as
   something you click, so the arrow earns less there than on an inline text
   link. And the hero and contact rows sit next to "Get in touch", an
   internal anchor that would never take an arrow -- marking its three
   neighbours and not it would look like an oversight rather than a
   distinction. Those rows are also flex-nowrap with a container-query font
   size and already ran 7px over at 320px; three arrows pushed that to 35. */


/* === Full-screen paper reader ============================================
   Opened by clicking a publication card. The point is that a reviewer can
   read the paper without being navigated away from the site. */

html.reader-open { overflow: hidden; }              /* stop the page behind scrolling */

.reader {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  background: var(--color-accent-900);
}
.reader[hidden] { display: none; }

.reader-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 14px 20px;
  border-bottom: 1px solid color-mix(in srgb, #f5f5f8 20%, transparent);
}

.reader-heading { min-width: 0; }                   /* let the title truncate */

.reader-venue {
  margin: 0 0 3px;
  font-family: var(--font-heading);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent-300);
}

.reader-title {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.2;
  color: var(--color-neutral-100);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.reader-actions { display: flex; align-items: center; gap: 8px; flex: none; }

.reader-btn {
  font-family: var(--font-heading);
  font-size: 12.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-neutral-100);
  background: transparent;
  border: 1px solid color-mix(in srgb, #f5f5f8 32%, transparent);
  padding: 8px 14px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .18s ease, border-color .18s ease;
}
.reader-btn:hover {
  background: color-mix(in srgb, #f5f5f8 14%, transparent);
  border-color: color-mix(in srgb, #f5f5f8 55%, transparent);
  color: var(--color-neutral-100);
  text-decoration: none;
}
.reader-close {
  background: var(--color-neutral-100);
  color: var(--color-accent-900);
  border-color: var(--color-neutral-100);
}
.reader-close:hover { background: #fff; color: var(--color-accent-900); }

.reader-body { flex: 1; min-height: 0; background: var(--color-neutral-200); }

.reader-frame { width: 100%; height: 100%; border: 0; display: block; }

/* Keyboard focus has to stay obvious against the dark bar. */
.reader-btn:focus-visible,
.paper-read:focus-visible {
  outline: 2px solid var(--color-neutral-100);
  outline-offset: 2px;
}

/* Below this the reader is not used at all — the PDF opens natively — but the
   bar still needs to survive a narrow window on a laptop. */
@media (max-width: 860px) {
  .reader-bar { padding: 12px 16px; gap: 14px; }
  .reader-title { font-size: 16px; }
  .reader-btn { padding: 7px 11px; font-size: 11.5px; }
}


/* === Photo viewer ========================================================
   The five-photo strip in About. Clicking a thumbnail shows it large over
   the page with its caption beneath. It shows the full-size original from
   photos/ when there is one, and otherwise the export's 520px square; either
   way it fits the screen and never upscales a photo past its own size. Same backdrop and Close button as the paper
   reader, so the two read as one family. Wired by the script at the bottom
   of index.html. */

.photo-tile { cursor: zoom-in; }
.photo-tile img { transition: transform .3s ease; }
.photo-tile:hover img { transform: scale(1.05); }
.photo-tile:focus-visible {
  outline: 2px solid var(--color-accent-700);
  outline-offset: 2px;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 64px 24px 24px;
  background: var(--color-accent-900);
}
.lightbox[hidden] { display: none; }

.lightbox-close { position: absolute; top: 14px; right: 20px; }

.lightbox-figure {
  margin: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.lightbox-img {
  display: block;
  max-width: min(1100px, 100%);
  max-height: calc(100vh - 150px);
  max-height: calc(100dvh - 150px);
  width: auto;
  height: auto;
  object-fit: contain;
  box-shadow: 0 10px 40px rgb(0 0 0 / 35%);
}

.lightbox-caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  width: 100%;
  margin-top: 14px;
  font-family: var(--font-heading);
  font-size: 15px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--color-neutral-100);
}
.lightbox-count {
  flex: none;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  color: var(--color-accent-300);
}

.lightbox-nav {
  flex: none;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  line-height: 1;
  color: var(--color-neutral-100);
  background: transparent;
  border: 1px solid color-mix(in srgb, #f5f5f8 32%, transparent);
  border-radius: 50%;
  cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease;
}
.lightbox-nav:hover {
  background: color-mix(in srgb, #f5f5f8 14%, transparent);
  border-color: color-mix(in srgb, #f5f5f8 55%, transparent);
}
.lightbox-single .lightbox-nav { display: none; }

.lightbox-nav:focus-visible {
  outline: 2px solid var(--color-neutral-100);
  outline-offset: 2px;
}

/* On a phone the arrows would steal a third of the width. Float them over
   the photo's edges instead; swiping also works. */
@media (max-width: 700px) {
  .lightbox { padding: 60px 12px 16px; }
  .lightbox-close { top: 12px; right: 12px; }
  .lightbox-nav {
    position: absolute;
    top: 50%;
    width: 40px;
    height: 40px;
    margin-top: -20px;
    font-size: 28px;
    background: color-mix(in srgb, var(--color-accent-900) 55%, transparent);
  }
  .lightbox-prev { left: 8px; }
  .lightbox-next { right: 8px; }
  .lightbox-caption { font-size: 13.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .photo-tile img, .lightbox-nav { transition: none; }
  .photo-tile:hover img { transform: none; }
}

/* === Responsive corrections ==============================================
   The export has no media queries at all; these are all ours. */

/* --- 1. The About section's two-column grid ------------------------------
   Authored as `minmax(300px,340px) minmax(0,1fr)`. Neither track can shrink
   below 300px, so once the viewport drops under roughly 860px the second
   track is squeezed to 0px and the entire About narrative and photo strip
   render one character wide, overflowing the page. Collapse to one column. */
@media (max-width: 860px) {
  [style*="minmax(300px,340px)"] {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 32px !important;
  }
}

/* --- 2. Grids that reserve more width than a phone has -------------------
   `repeat(auto-fit, minmax(Npx, 1fr))` drops to a single column on its own,
   but that column still claims Npx. Below Npx + 48px of section padding it
   overflows, so let the track shrink. */
@media (max-width: 480px) {
  [style*="repeat(auto-fit,minmax(340px"],
  [style*="repeat(auto-fit,minmax(320px"],
  [style*="repeat(auto-fit,minmax(300px"],
  [style*="repeat(auto-fit,minmax(280px"],
  [style*="repeat(auto-fit,minmax(200px"] {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* --- 3. The five-photo strip in About ------------------------------------
   Five tiles across a phone leaves each about 60px. Two rows of larger
   thumbnails read far better. */
@media (max-width: 700px) {
  [style*="repeat(5,minmax(0,1fr))"] {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  }
}
@media (max-width: 380px) {
  [style*="repeat(5,minmax(0,1fr))"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}

/* --- 4. Nowrap text -------------------------------------------------------
   Journal names, the institution line and several kickers are set to
   `white-space: nowrap` to keep them tidy on a desktop. On a phone they are
   the main source of sideways scroll. Wrapping is always better than
   overflowing. */
@media (max-width: 700px) {
  [style*="white-space:nowrap"] {
    white-space: normal !important;
  }
  /* Buttons are short enough to stay on one line and look wrong broken. */
  a.btn[style*="white-space:nowrap"] {
    white-space: nowrap !important;
  }
}

/* --- 4b. Header brand, and the contact label/value rows -------------------
   The header bar is one flex row that wraps on a phone: the brand takes the
   first line and the nav the second. space-between leaves the brand hard
   against the left edge while the nav below it centres, which reads as a
   mistake rather than a choice. Centring the whole bar lines the two up.

   The contact rows are label-and-value pairs laid out with space-between and
   no gap. On a wide screen the two ends are far apart; on a phone the value
   grows until it touches the label -- "InstitutionUniversity of Toledo...".
   Stacking them puts the value on its own line with room to wrap. */
@media (max-width: 700px) {
  header > div[style*="justify-content:space-between"] {
    justify-content: center !important;
  }

  div[style*="justify-content:space-between"][style*="padding-bottom:10px"] {
    flex-direction: column;
    gap: 3px;
  }
}

/* A gap at every width, so the pair can never close up even before the
   stacking kicks in. */
div[style*="justify-content:space-between"][style*="padding-bottom:10px"] {
  gap: 4px 24px;
}

/* --- 5. Date-gutter lists (talks, posters, positions) --------------------
   An 86px fixed gutter is a large share of a 320px screen. */
@media (max-width: 480px) {
  [style*="grid-template-columns:86px 1fr"] {
    grid-template-columns: 68px minmax(0, 1fr) !important;
  }
}

/* --- 6. Breathing room ---------------------------------------------------
   Trim the 24px section gutters and the large vertical padding on phones. */
@media (max-width: 480px) {
  section > div,
  header > div,
  footer > div {
    padding-left: 18px !important;
    padding-right: 18px !important;
  }
  section > div {
    padding-top: 44px !important;
    padding-bottom: 44px !important;
  }
}

/* --- 7. Footer ----------------------------------------------------------
   Two items justified apart collide on a narrow screen. */
@media (max-width: 480px) {
  footer > div {
    flex-direction: column !important;
    gap: 6px !important;
  }
}

/* --- 8. Last resort ------------------------------------------------------
   A single long unbroken token (a DOI, a URL) should wrap rather than push
   the page wide. */
@media (max-width: 700px) {
  body { overflow-wrap: break-word; }
}

/* --- 9. Anchor targets under the sticky header ---------------------------
   The header stays fixed at the top, so a nav click scrolls the section
   heading underneath it. On a phone the header wraps to two rows (~144px)
   and the heading is hidden completely. Offset every anchor target by more
   than the header's height. */
section[id] { scroll-margin-top: 84px; }

@media (max-width: 860px) {
  section[id] { scroll-margin-top: 160px; }
}
