/* Paper frame around the demos: authors and links under the title, section bar, TL;DR, section
   permalinks and BibTeX. Loaded after showcase.css and reuses its tokens, so the two read as one
   stylesheet. */

:root { --toc-h: 52px; }

/* The sticky section bar covers the top of the window, so the scroll port is padded by its height.
   That clears it for anchor jumps and also for keyboard focus: tabbing back to a control above the
   fold scrolls it in below the bar instead of underneath it, where it would be fully hidden. The
   extra 8px is room for the focus ring, which is drawn 4px outside the control. */
html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--toc-h) + 8px);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* Every linkable block lands a little clear of the bar when it is jumped to (14px with the 8px of
   scroll padding above). */
[id] { scroll-margin-top: 6px; }

/* The sections open with a hairline and a band of air above their number and heading. A jump
   skips that band: the number lands 20px below the bar, and the bar's own hairline stands in for
   the section rule, which ends up just under it. */
.viewer[id],
.mechanism[id] { scroll-margin-top: calc(12px - var(--space-section)); }

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

a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- Header ---------- */

/* A faint wash of the accent behind the title gives the opening screen some depth without an
   image; it fades out long before the section bar. The padding is sized so a 1280 x 800 laptop
   sees the title block, the bar and the start of the TL;DR before it scrolls, and grows only
   gently beyond that so a big monitor does not open on a band of empty wash. */
.page-top {
  padding: clamp(28px, 1.1vw + 27px, 64px) var(--gutter) clamp(24px, 1vw + 23px, 56px);
  background:
    radial-gradient(70% 90% at 50% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 70%);
}

/* The section bar below draws the rule, so the header needs none of its own. */
.page-top .page-head {
  max-width: var(--col-max);
  margin: 0 auto;
  padding: 0;
  border: 0;
  text-align: center;
}

.page-name {
  display: inline-flex;
  align-items: center;
  gap: .3em;
  margin: 0 0 clamp(10px, 1vw, 18px);
  color: var(--accent);
  font-size: clamp(1.0625rem, .8rem + .5vw, 1.375rem);
  font-weight: 650;
  letter-spacing: -.01em;
  line-height: 1.3;
}

.authors {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px 20px;
  max-width: 50rem;
  margin: clamp(16px, .8vw + 10px, 24px) auto 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-small);
}

/* Starts a new row of names wherever the author list should break. */
.authors .author-break {
  flex-basis: 100%;
  height: 0;
}

.authors a { color: var(--ink); }
.authors a:hover { color: var(--accent); text-decoration: none; }

/* The markers are the only link between a name and its lab, so they are text to be read, not
   ornament: never below 11px. A zero line height keeps the raised figure from opening up the line. */
.authors sup,
.affiliations sup {
  margin-left: 1px;
  color: var(--muted);
  font-size: max(11px, .72em);
  line-height: 0;
}

.affiliations {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px 22px;
  margin: 8px 0 0;
  color: var(--muted);
  font-size: var(--fs-micro);
}

.head-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: clamp(16px, .8vw + 10px, 24px);
}

.link-btn {
  display: inline-flex;
  height: 40px;
  align-items: center;
  gap: 8px;
  padding: 0 20px;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-ui);
  font-weight: 600;
  line-height: 1;
  transition: background-color .15s ease, border-color .15s ease;
}

.link-btn:hover {
  border-color: var(--accent);
  background: var(--accent);
  text-decoration: none;
}

/* A link that is not public yet keeps its place in the row, visibly inert. */
.link-btn.is-soon {
  border-color: var(--line);
  background: color-mix(in srgb, var(--paper) 70%, transparent);
  color: var(--ink);
  cursor: default;
}

.link-btn small {
  color: var(--muted);
  font-size: var(--fs-micro);
  font-weight: 500;
}

/* On a live (dark) button --muted is unreadable; soften the button's own text colour instead. */
.link-btn:not(.is-soon) small {
  color: inherit;
  opacity: .75;
}

/* ---------- Section bar ---------- */

/* Solid rather than frosted: a translucent bar lets headings and diagram labels scrolling under it
   show through as ghost text, which reads as a rendering fault. A hairline and a soft shadow do
   the lifting instead. */
.toc {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid var(--line-soft);
  background: var(--paper);
  box-shadow: 0 6px 18px -14px rgba(16, 24, 40, .35);
}

/* The hairline under the bar is part of --toc-h, so the scroll padding and the diagrams' height
   cap, which both read the token, match the bar to the pixel. */
.toc-inner {
  display: flex;
  width: var(--col);
  height: calc(var(--toc-h) - 1px);
  align-items: center;
  gap: 18px;
  margin: 0 auto;
}

.toc-home {
  flex: 0 0 auto;
  color: var(--ink);
  font-size: var(--fs-ui);
  font-weight: 650;
  letter-spacing: -.01em;
}

.toc-home:hover { color: var(--accent); text-decoration: none; }

.toc ol {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  gap: 2px;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  list-style: none;
  /* Kept thin rather than hidden, so readers without a trackpad can still see and drag it. */
  scrollbar-width: thin;
}

.toc ol::-webkit-scrollbar { height: 3px; }
.toc ol::-webkit-scrollbar-thumb { border-radius: 3px; background: var(--line); }

.toc li { flex: 0 0 auto; }

/* The links sit at the far end of the bar, opposite the name. An auto margin rather than
   justify-content, because a margin collapses when the list overflows, so the first link stays
   reachable by scrolling on narrow screens. */
.toc li:first-child { margin-left: auto; }

.toc ol a {
  display: block;
  padding: 6px 12px;
  border-radius: 999px;
  color: var(--muted);
  font-size: var(--fs-micro);
  font-weight: 500;
  white-space: nowrap;
  transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}

.toc ol a:hover {
  color: var(--ink);
  text-decoration: none;
}

.toc ol a:focus-visible { outline-offset: -2px; }

/* The section being read is the one place the bar uses colour: the accent on its tint, inside a
   ring that reaches 3:1 against the bar, so the state does not rest on the tint alone. */
.toc ol a[aria-current="true"] {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-ring);
  color: var(--accent);
}

/* Focus on the current link would otherwise only thicken a ring that is already there. A band of
   paper inside the accent outline, as base had, makes the focused state its own look. The ring
   stays inside the link, because the list's scroller would clip anything drawn outside it. */
.toc ol a[aria-current="true"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  box-shadow: inset 0 0 0 4px var(--paper);
}

@media (forced-colors: active) {
  .toc ol a[aria-current="true"] { outline: 2px solid CanvasText; outline-offset: -2px; }
  .toc ol a[aria-current="true"]:focus-visible { outline: 3px solid Highlight; outline-offset: -3px; }
}

@media (max-width: 720px) {
  :root { --toc-h: 46px; }
  .toc-home { display: none; }
}

/* On a narrow bar the links can overflow, so its right edge fades out to show there is more to
   scroll to. The spacer after the last link is as wide as the fade, so the last link can scroll
   clear of it, and the scroll padding does the same for a link that keyboard focus scrolls into
   view, so it never stops half faded. The scroll spy only scrolls the bar when the current item
   runs past its visible edge, and the fade sits inside that edge, so each item's box reaches one
   fade-width past its link (the negative margin gives the space back): an item whose link is
   under the fade counts as cut off, and the bar brings it out. */
@media (max-width: 780px) {
  .toc ol {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    scroll-padding-inline: 0 28px;
  }

  .toc ol::after {
    content: "";
    flex: 0 0 28px;
  }

  .toc li {
    padding-inline-end: 28px;
    margin-inline-end: -28px;
  }
}

/* Once the spy scrolls the bar on a phone, links also pass out of its left edge, where they were
   cut off hard at the gutter with no sign of anything before them. The list therefore reaches out
   over the empty gutter and fades in across it: at rest the fade covers only blank gutter and the
   first link still starts in line with the page, while a link scrolled past the edge dissolves
   instead of being sliced. The name is hidden at this width, so nothing sits under the reach, and
   the spy's offsets are measured inside the list, so they move with it. */
@media (max-width: 720px) {
  .toc ol {
    margin-inline-start: calc(-1 * var(--gutter));
    padding-inline-start: var(--gutter);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--gutter), #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 var(--gutter), #000 calc(100% - 28px), transparent);
    scroll-padding-inline: var(--gutter) 28px;
  }
}

/* Just above the phone layout the name still shares the bar, and the links with their full
   padding came within a few pixels of fitting, so the bar scrolled a sliver and left the last link
   in the fade. A little less padding and gap lets every link fit, clear of the fade, down to 721px. */
@media (min-width: 721px) and (max-width: 780px) {
  .toc-inner { gap: 12px; }
  .toc ol a { padding-inline: 9px; }
}

/* ---------- TL;DR ---------- */

/* Four open columns under a hairline each, instead of four grey boxes. A short accent stroke
   leads each hairline and the point's heading takes the accent, so the four claims read as the
   page's headline before any of the detail. */
.tldr-points {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px clamp(24px, 2.6vw, 44px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tldr-points li {
  position: relative;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.tldr-points li::before {
  content: "";
  position: absolute;
  top: -2px;
  left: 0;
  width: 2rem;
  height: 3px;
  border-radius: 2px;
  background: var(--accent);
}

.tldr-points h3 {
  margin: 0 0 6px;
  color: var(--accent);
  font-size: var(--fs-h3);
  font-weight: 650;
  letter-spacing: -.01em;
  line-height: 1.3;
}

.tldr-points p {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-small);
  text-wrap: pretty;
}

/* The headings already carry the colour, so the figures in the text are set in ink and weight.
   Each figure is a range, and a line break after its en dash ("1.42– / 2.92×") splits the one
   number a reader came for, so a figure always stays on one line. */
.tldr-points b { color: var(--ink); font-weight: 650; white-space: nowrap; }

@media (max-width: 1100px) {
  .tldr-points { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .tldr-points { grid-template-columns: minmax(0, 1fr); gap: 20px; }
}

/* ---------- Section permalinks ---------- */

/* Out of the flow, so a centred heading stays centred on its own text. It is set in the muted
   grey rather than a pale accent, because the mark is a link and has to read at 4.5:1 too. */
.permalink {
  position: absolute;
  margin-left: .35em;
  color: var(--muted);
  font-weight: 400;
  opacity: 0;
  transition: opacity .15s ease;
}

.permalink:hover { color: var(--accent); text-decoration: none; }

h2:hover .permalink,
.permalink.is-copied { opacity: 1; }

/* The confirmation sits beside the mark so the heading never reflows. */
.permalink.is-copied::after {
  content: "Link copied";
  margin-left: .6em;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--fs-tiny);
  font-weight: 500;
  letter-spacing: 0;
  vertical-align: .35em;
}

@media (hover: none) {
  .permalink { opacity: .7; }
}

/* ---------- BibTeX ---------- */

.bibtex {
  position: relative;
}

.bibtex pre {
  margin: 0;
  padding: 22px 26px;
  padding-right: 96px;
  overflow-x: auto;
  border-radius: var(--radius-m);
  background: var(--surface);
  color: var(--ink-soft);
  /* Long author lists wrap instead of hiding behind a scroller the keyboard cannot reach. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* A wrapped author list continues under its value, past "  author  = {", instead of falling
     back under "@article". Browsers without hanging indents drop the line and wrap as before. */
  text-indent: 13ch hanging each-line;
  font-family: var(--mono);
  font-size: var(--fs-micro);
  line-height: 1.7;
}

/* White on the grey plate, so the one control in the block still reads as a button. It is wide
   enough for "Copied", so the label swap does not nudge it. */
.bibtex .pill {
  position: absolute;
  top: 14px;
  right: 14px;
  min-width: 5.4rem;
  background: var(--paper);
  box-shadow: var(--shadow-raised);
  transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}

/* Hover takes the same accent-on-tint look as the current section in the bar. */
.bibtex .pill:hover,
.bibtex .pill:focus-visible {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-ring);
  color: var(--accent);
}

/* The script only swaps the label to "Copied" for 1.6s, so the press also darkens the ring and
   holds it for about that long: the confirmation reads as a state rather than a flicker. The ring
   lives on its own layer and appears at once on press, so even a quick click shows all of it, and
   the focus outline keeps no delay of its own. */
.bibtex .pill::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--accent);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease 1.4s;
}

.bibtex .pill:active::after {
  opacity: 1;
  transition: none;
}

/* The page closes on the same hairline that opens every section, so the BibTeX card is followed
   by a rule rather than running straight into the bottom of the window. showcase.css leaves a
   section and a half of air under the rule, so it reads as the end of the page, not a cut. */
.mechanism:last-of-type .mechanism-inner::after {
  content: "";
  display: block;
  margin-top: var(--space-section);
  border-top: 1px solid var(--line);
}

@media (max-width: 720px) {
  .bibtex pre { padding: 18px; padding-top: 58px; }
}

@media print {
  .toc, .permalink, .bibtex .pill { display: none; }
  .page-top { background: none; }
  .video-frame { box-shadow: none; }
}
