/* ==========================================================================
   Vole Genome Resource, design system
   --------------------------------------------------------------------------
   A risograph print aesthetic: a small set of spot inks on paper, hard black
   rules, offset shadows, and visible grain. Light-only by design, because the
   paper is the surface and a dark mode would undo the metaphor.

   Type has three voices and they carry meaning:
     display  Anton         headlines, poster weight
     ui       Jost          labels, buttons, navigation (geometric, Futura-ish)
     text     Source Serif  running prose and descriptions
     mono     IBM Plex Mono filenames, accessions, checksums
   ========================================================================== */

/* ---------- tokens ---------- */
:root {
  --paper:      #f3efe4;
  --paper-2:    #ece7d8;   /* sunk panels, hover */
  --ink:        #1d1a17;
  --ink-soft:   #4a423a;
  --ink-faint:  #7a6f5f;
  --rule:       #cfc6b2;

  /* spot inks, which double as the category coding in the catalog */
  --marigold:   #f0b64a;
  --pink:       #e8506d;
  --teal:       #12a3a0;
  --rust:       #7a3b2e;
  --darkred:    #9b1616;   /* CiFi, and anything needing red against rust */
  --sage:       #8a9a5b;

  /* Not one of ours. Cell Press blue, used on the publisher's own word in
     the paper credit and nowhere else on the site. */
  --cell-blue:  #027dbc;

  --gutter:     clamp(1.25rem, 4vw, 3rem);
  --measure:    68ch;
  --rule-w:     2.5px;

  --font-display: 'Anton', 'Haettenschweiler', 'Arial Narrow', Impact, sans-serif;
  --font-ui:      'Jost', 'Futura', 'Century Gothic', 'Avenir Next', sans-serif;
  --font-text:    'Source Serif 4', Georgia, 'Iowan Old Style', serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, 'Courier New', monospace;
}

/* paper grain, applied once to <body> */
@media (min-width: 1px) {
  body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    mix-blend-mode: multiply;
    opacity: .17;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23g)'/%3E%3C/svg%3E");
  }
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }

/* The user-agent's [hidden] rule is display:none, which any author `display`
   declaration outranks. .file is display:grid, so setting the hidden property
   from the catalog filter marked rows hidden without hiding them. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 17px/1.65 var(--font-text);
  font-synthesis-weight: none;
}

main, header, footer { position: relative; z-index: 1; }

h1, h2, h3 { margin: 0; text-wrap: balance; }
p { margin: 0 0 1em; max-width: var(--measure); }
img { max-width: 100%; height: auto; }

a { color: var(--rust); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--pink); }

:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--paper);
  padding: .75rem 1rem; font-family: var(--font-ui); z-index: 50;
}
.skip:focus { left: var(--gutter); top: .5rem; }

.wrap { max-width: 1180px; margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- masthead ---------- */
.masthead {
  border-bottom: var(--rule-w) solid var(--ink);
  background: var(--paper);
  position: sticky; top: 0; z-index: 20;
}
.masthead__in {
  display: flex; align-items: center; gap: 1.5rem;
  padding-block: .85rem;
}
.brand {
  margin-right: auto;
  display: flex; align-items: center; gap: .65rem;
  font: 400 1.15rem/1 var(--font-display);
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink); text-decoration: none;
}
.brand svg { display: block; }

.nav { display: flex; gap: 1.4rem; }
.nav a, .nav .navbtn {
  font: 500 .78rem/1 var(--font-ui);
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--rust); text-decoration: none; padding-bottom: .25rem;
  border-bottom: 3px solid transparent;
}
/* Contact opens a dialog rather than navigating, so it is a button. It has to
   look like the links beside it, which means undoing the button defaults. */
.nav .navbtn { background: none; border-inline: 0; border-top: 0; padding-inline: 0; cursor: pointer; }
.nav a:hover, .nav .navbtn:hover { color: var(--ink); }
.nav a[aria-current='page'] { color: var(--ink); border-bottom-color: var(--pink); }

.nav-toggle { display: none; }

/* ---------- buttons ---------- */
.btn {
  display: inline-block;
  font: 500 .78rem/1 var(--font-ui);
  letter-spacing: .1em; text-transform: uppercase;
  padding: .85rem 1.1rem;
  border: var(--rule-w) solid var(--ink);
  background: var(--ink); color: var(--paper);
  text-decoration: none;
  box-shadow: 4px 4px 0 var(--teal);
  transition: transform .1s ease, box-shadow .1s ease;
}
.btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--teal); color: var(--paper); }
.btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--teal); }
.btn--alt { background: var(--paper); color: var(--ink); box-shadow: 4px 4px 0 var(--pink); }
.btn--alt:hover { box-shadow: 6px 6px 0 var(--pink); color: var(--ink); }
.btn--sm { padding: .6rem .75rem; box-shadow: 3px 3px 0 var(--teal); }
.btn--sm:hover { box-shadow: 4px 4px 0 var(--teal); }

.kicker {
  display: inline-block;
  font: 500 .68rem/1 var(--font-ui);
  letter-spacing: .19em; text-transform: uppercase;
  background: var(--pink); color: var(--paper);
  padding: .45rem .7rem;
}

/* ---------- hero ---------- */
.hero__in {
  display: grid; grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
  gap: 2rem; align-items: center;
  padding-block: clamp(1.75rem, 4vw, 3rem);
}
.hero h1 {
  font: 400 clamp(2.6rem, 6.5vw, 4.15rem)/.95 var(--font-display);
  letter-spacing: .015em; text-transform: uppercase;
  margin: .8rem 0 .7rem;
}
.hero h1 em { font-style: normal; color: var(--pink); }
.hero p { color: var(--ink-soft); font-size: 1.05rem; }
.hero__cta { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1.4rem; }

/* The paper credit beside the button, set like a masthead: the journal in the
   display face behind a rule, with the DOI under it. Says where the work was
   published without borrowing a Cell Press logo, which would imply the journal
   endorses this resource rather than merely publishing the paper. */
.hero__cta--paper { align-items: center; gap: 1.1rem; }
.mast {
  display: block; text-decoration: none;
  border-left: 2px solid var(--cell-blue); padding-left: 1.1rem;
  transition: transform .12s ease;
}
.mast__k, .mast__doi {
  display: block; color: var(--ink-faint);
  font: 500 .66rem/1 var(--font-mono); letter-spacing: .14em; text-transform: uppercase;
}
.mast__k { font-size: .6rem; letter-spacing: .16em; margin-bottom: .34rem; }
.mast__doi { margin-top: .32rem; text-transform: none; letter-spacing: .08em; }
.mast__n {
  display: block; color: var(--ink);
  font: 400 1.3rem/1 var(--font-display); letter-spacing: .02em; text-transform: uppercase;
}
.mast__n .cell { color: var(--cell-blue); }
/* Hover moves no ink. Teal is the meadow vole in the headline directly above,
   so recolouring here read as a species cue for a moment. */
.mast:hover { transform: translateY(-2px); }
.mast:hover .mast__n {
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px;
}
.hero__art svg { width: 100%; height: auto; overflow: visible; }

/* The bar is exactly its four filled cells, boxed on all four sides and no
   wider than the content column. Nothing full-bleed: a rule running past the
   cells to the window edge read as two more, empty, cells in the row, and the
   hero's own bottom rule did the same across the top. The bar closes the hero. */
.strip__in {
  display: grid; grid-template-columns: repeat(4, 1fr);
  border: var(--rule-w) solid var(--ink);
}
.strip__in > div {
  padding: .8rem .5rem; text-align: center;
  font: 500 .68rem/1.3 var(--font-ui);
  letter-spacing: .12em; text-transform: uppercase;
  border-right: var(--rule-w) solid var(--ink);
}
.strip__in > div:last-child { border-right: 0; }

/* Stamped claims above the headline. A different species of object from the
   claims bar: mono type, double rule, a couple of degrees off square, and
   slightly transparent so the paper grain reads through the ink. */
.stamp { display: inline-block; transform: rotate(-2deg); margin: .2rem 0 .9rem; }
.stamp span {
  display: block;
  border: 3px double var(--rust); color: var(--rust);
  font: 500 .74rem/1.35 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase;
  padding: .5rem .8rem; opacity: .88;
}
.stamp span + span { border-top: 0; }

/* CiFi is the technology the single-library claim rests on. Dark red against
   the rust stamp, and a link out to its own site. The underline stays faint so
   the stamp reads as one object, and firms up on hover. */
.stamp a {
  font-weight: 600; text-decoration: none;
  border-bottom: 1px solid rgba(155, 22, 22, .38);
  /* a highlight band wider than the word, clipped to the glyphs and scrolled
     left to right, like light catching wet ink rather than a blinking effect */
  color: var(--darkred);
  background-image: linear-gradient(100deg,
      var(--darkred) 0%, var(--darkred) 42%, #ff9a6a 50%, var(--darkred) 58%, var(--darkred) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: cifi-shine 3.2s linear infinite;
}
.stamp a:hover { border-bottom-color: var(--darkred); }

@keyframes cifi-shine {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}

/* Looping motion is a migraine and vestibular trigger, and this sits above the
   fold on every visit. Anyone who has asked for reduced motion gets flat ink. */
@media (prefers-reduced-motion: reduce) {
  .stamp a {
    animation: none; background-image: none;
    color: var(--darkred); -webkit-text-fill-color: var(--darkred);
  }
}

/* Gene symbols keep their case and stay italic inside the uppercased bar.
   AVPR1A is the human symbol, Avpr1a the rodent one. */
.claim em { text-transform: none; font-style: italic; }

/* Claim inks. Marigold and sage are light enough to keep the dark text;
   teal, pink and rust need the paper colour to stay legible. */
.claim--marigold { background: var(--marigold); }
.claim--sage     { background: var(--sage); }
.claim--teal     { background: var(--teal); color: var(--paper); }
.claim--pink     { background: var(--pink); color: var(--paper); }
.claim--rust     { background: var(--rust); color: var(--paper); }
.claim--paper    { background: var(--paper); }
.claim--ink      { background: var(--ink); color: var(--paper); }

/* ---------- generic sections ---------- */
.section { padding-block: clamp(2rem, 5vw, 3.25rem); }
.section + .section { border-top: 1px solid var(--rule); }

.section__hd {
  display: flex; align-items: center; gap: .85rem;
  padding-bottom: .8rem; margin-bottom: 1.5rem;
  border-bottom: var(--rule-w) solid var(--ink);
}
.section__hd h2 {
  font: 400 1.5rem/1 var(--font-display);
  letter-spacing: .05em; text-transform: uppercase;
}
.section__hd .meta {
  margin-left: auto; font: italic 400 .9rem/1 var(--font-text); color: var(--ink-faint);
}
/* A span is display:inline, where width and height do not apply. Inside a flex
   section header it gets blockified and behaves; inside a card it collapsed to
   its own left and right borders and read as a stray pipe character. */
.swatch {
  display: block; width: 26px; height: 26px;
  border: var(--rule-w) solid var(--ink); flex: none;
}

.lede { font-size: 1.1rem; color: var(--ink-soft); max-width: var(--measure); }

/* card grid used on the landing page */
/* Species filter on the catalog. Deliberately not a .chip: species is a bigger
   cut than category, and the two controls sitting side by side need to read as
   different kinds of thing. Pressed state uses the species ink from the
   headline, so pink still means prairie everywhere on the site. */
.seg {
  font: 500 .68rem/1 var(--font-ui); letter-spacing: .1em; text-transform: uppercase;
  background: var(--paper); color: var(--ink);
  border: var(--rule-w) solid var(--ink); padding: .55rem .8rem;
  cursor: pointer; box-shadow: 3px 3px 0 var(--rule);
  transition: transform .1s ease, box-shadow .1s ease;
}
/* forced onto its own line inside the flex-wrap row */
.segs { display: flex; gap: .5rem; flex-basis: 100%; margin-top: .35rem; }
.seg:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--rule); }
.seg[aria-pressed='true'] {
  color: var(--paper); transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--rule);
}
.seg[data-sp='prairie'][aria-pressed='true'] { background: var(--pink); }
.seg[data-sp='meadow'][aria-pressed='true']  { background: var(--teal); }

/* Which species a file belongs to, as a square of ink rather than a word. The
   title attribute carries the name for anyone who needs it spelled out. */
.dot {
  display: inline-block; width: .58rem; height: .58rem;
  border: 1.5px solid var(--ink); margin-right: .5rem; vertical-align: .02em;
}
.dot--prairie { background: var(--pink); }
.dot--meadow  { background: var(--teal); }
.dot--both    { background: var(--ink); }

/* The browser links are cards, matching the grids above and below them rather
   than sitting between two of them as a pair of small buttons. */
.hub__asm {
  display: block; margin-top: .7rem;
  font: 500 .62rem/1 var(--font-mono); letter-spacing: .1em; color: var(--ink-faint);
}
.hub--prairie { box-shadow: 5px 5px 0 var(--pink); }
.hub--meadow  { box-shadow: 5px 5px 0 var(--teal); }
.hub--prairie:hover { box-shadow: 8px 8px 0 var(--pink); }
.hub--meadow:hover  { box-shadow: 8px 8px 0 var(--teal); }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.1rem; }
.card {
  border: var(--rule-w) solid var(--ink); background: var(--paper);
  padding: 1.1rem 1.15rem; text-decoration: none; color: var(--ink);
  box-shadow: 5px 5px 0 var(--rule);
  transition: transform .1s ease, box-shadow .1s ease;
}
.card:hover { transform: translate(-2px, -2px); box-shadow: 7px 7px 0 var(--marigold); color: var(--ink); }
.card h3 { font: 500 1rem/1.25 var(--font-ui); letter-spacing: .04em; text-transform: uppercase; }
.card p { font-size: .95rem; color: var(--ink-soft); margin: .5rem 0 0; }
.card .n { font: 400 2rem/1 var(--font-display); color: var(--rust); }

/* ---------- catalog ---------- */
.tools {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  padding-block: .9rem;
  background: var(--paper-2);
  border-bottom: var(--rule-w) solid var(--ink);
  position: sticky; top: 57px; z-index: 15;
}
.tools input {
  flex: 1 1 240px; min-width: 0;
  border: var(--rule-w) solid var(--ink); background: var(--paper);
  padding: .6rem .75rem; font: 400 .95rem/1 var(--font-text); color: var(--ink);
}
.tools input::placeholder { color: var(--ink-faint); }
.chip {
  border: var(--rule-w) solid var(--ink); background: var(--paper);
  padding: .55rem .7rem; cursor: pointer;
  font: 500 .68rem/1 var(--font-ui); letter-spacing: .11em; text-transform: uppercase;
}
.chip[aria-pressed='true'] { background: var(--ink); color: var(--paper); }

.files { border-bottom: var(--rule-w) solid var(--ink); }
.file {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 82px 110px auto;
  gap: .9rem; align-items: center;
  padding: .8rem 0;
  border-bottom: 1px solid var(--rule);
}
.file:last-child { border-bottom: 0; }
.file:hover { background: var(--paper-2); box-shadow: 0 0 0 var(--gutter) var(--paper-2); }
.file__name { font: 500 .92rem/1.3 var(--font-mono); letter-spacing: -.01em; word-break: break-all; }
.file__desc { font-size: .92rem; color: var(--ink-soft); margin: .2rem 0 0; max-width: none; }
.file__fmt {
  font: 500 .62rem/1 var(--font-ui); letter-spacing: .11em; text-transform: uppercase;
  border: 2px solid var(--ink); padding: .4rem .3rem; text-align: center;
}
.file__size { font: 400 .85rem/1 var(--font-mono); text-align: right; }
.file__sum  { font: 400 .66rem/1 var(--font-mono); color: var(--ink-faint); text-align: right; margin-top: .35rem; }
/* Action group: one row, right-aligned. The copy control is a square icon so
   three actions never wrap. */
.file__act { display: flex; gap: .35rem; align-items: stretch; justify-content: flex-end; }
.file__act .btn { text-align: center; box-shadow: 3px 3px 0 var(--teal); white-space: nowrap; }
.file__act .btn--alt { box-shadow: 3px 3px 0 var(--rule); }
.file__act .btn--alt:hover { box-shadow: 4px 4px 0 var(--pink); }

button.copy {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .6rem; cursor: pointer; flex: none;
}
button.copy svg { display: block; }
button.copy.is-copied { background: var(--teal); color: var(--paper); border-color: var(--ink); }

/* Citation blocks. The button sits inside the block's top-right corner and
   only firms up on hover, so it never competes with the citation itself. */
.copyable { position: relative; }
.copyable > blockquote, .copyable > pre { margin-block: 1.1rem; }
.copybtn {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--ink-faint);
  border: 1px solid var(--rule); padding: .38rem;
  cursor: pointer; opacity: .55;
  transition: opacity .12s ease, color .12s ease, border-color .12s ease;
}
.copybtn svg { display: block; }
/* short lines: the corner is free */
.copybtn--corner { position: absolute; top: .5rem; right: .5rem; }
/* full-measure prose: sits under the block, past the DOI, so nothing overlaps */
.copybtn--after { display: flex; margin: -.5rem 0 1.1rem auto; }
.copybtn--inline { opacity: 1; flex: none; }
.copyable:hover .copybtn, .copybtn:focus-visible { opacity: 1; color: var(--ink); border-color: var(--ink); }
.copybtn.is-copied { opacity: 1; background: var(--teal); color: var(--paper); border-color: var(--ink); }

/* Contact dialog. Same paper, rule and hard offset as everything else, so it
   reads as a card lifted off the page rather than as browser chrome. */
.modal {
  max-width: 30rem; width: calc(100% - 2rem);
  background: var(--paper); color: var(--ink);
  border: var(--rule-w) solid var(--ink); box-shadow: 8px 8px 0 var(--pink);
  padding: 1.6rem 1.7rem 1.5rem;
}
.modal::backdrop { background: rgba(29, 26, 23, .45); }
.modal h2 {
  font: 400 1.5rem/1 var(--font-display); letter-spacing: .05em; text-transform: uppercase;
  margin: 0 0 1rem;
}
.modal__x {
  position: absolute; top: .5rem; right: .7rem;
  background: none; border: 0; cursor: pointer;
  font: 400 1.5rem/1 var(--font-ui); color: var(--ink-faint); padding: .2rem .3rem;
}
.modal__x:hover { color: var(--ink); }
.modal__field {
  display: flex; align-items: center; gap: .6rem;
  border: var(--rule-w) solid var(--ink); background: var(--paper-2); padding: .7rem .75rem;
}
.modal__field code {
  flex: 1 1 auto; min-width: 0; overflow-x: auto; white-space: nowrap;
  font: 400 .8rem/1.4 var(--font-mono); background: none; padding: 0;
}

.modal__list { list-style: none; margin: .9rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; }
.modal__list a { font: 400 .8rem/1.4 var(--font-mono); color: var(--rust); }

/* Confirmation for the copy action. Fixed to the viewport so it is visible
   wherever in the catalog the click happened. */
.toast {
  position: fixed; left: 50%; bottom: 1.5rem; transform: translate(-50%, .6rem);
  background: var(--ink); color: var(--paper);
  border: var(--rule-w) solid var(--ink); box-shadow: 5px 5px 0 var(--teal);
  padding: .8rem 1.2rem;
  font: 500 .78rem/1 var(--font-ui); letter-spacing: .1em; text-transform: uppercase;
  opacity: 0; pointer-events: none; z-index: 60;
  transition: opacity .16s ease, transform .16s ease;
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

.catalog-foot {
  display: flex; flex-wrap: wrap; gap: 1.6rem;
  padding-block: 1.1rem; font-size: .92rem; color: var(--ink-faint);
}

/* ---------- prose pages ---------- */
/* The measure belongs on the prose, not on the container: code blocks have no
   reason to be as narrow as a line of reading text. Headings keep it so their
   underlines stay the width they were. Paragraphs are capped globally already. */
.prose { max-width: none; }
.prose h2, .prose h3, .prose blockquote, .prose ul, .prose ol { max-width: var(--measure); }
.prose h2 {
  font: 400 1.45rem/1.15 var(--font-display); letter-spacing: .04em; text-transform: uppercase;
  margin: 2.2rem 0 .8rem; padding-bottom: .4rem; border-bottom: 2px solid var(--ink);
}
.prose h3 { font: 500 1.05rem/1.3 var(--font-ui); letter-spacing: .05em; margin: 1.6rem 0 .5rem; }
.prose code {
  font: 400 .88em/1.4 var(--font-mono);
  background: var(--paper-2); padding: .12em .35em; border: 1px solid var(--rule);
}
.prose pre {
  background: var(--ink); color: var(--paper);
  padding: 1rem 1.1rem; overflow-x: auto;
  border: var(--rule-w) solid var(--ink); box-shadow: 5px 5px 0 var(--teal);
  /* The RIS title line runs to 138 characters, wider than the page itself, so
     width alone cannot stop it scrolling. Wrapping is safe here: the copy
     button reads textContent, which keeps the real line breaks either way. */
  white-space: pre-wrap;
}
.prose pre code { background: none; border: 0; color: inherit; padding: 0; font-size: .85rem; }
.prose blockquote {
  margin: 1.4rem 0; padding: .3rem 0 .3rem 1.1rem;
  border-left: 4px solid var(--marigold); color: var(--ink-soft); font-style: italic;
}
.prose table { width: 100%; border-collapse: collapse; margin: 1.3rem 0; font-size: .95rem; }
.prose th {
  text-align: left; font: 500 .7rem/1 var(--font-ui); letter-spacing: .11em; text-transform: uppercase;
  border-bottom: var(--rule-w) solid var(--ink); padding: .6rem .5rem;
}
.prose td { border-bottom: 1px solid var(--rule); padding: .55rem .5rem; }

/* ---------- footer ---------- */
.footer { border-top: var(--rule-w) solid var(--ink); margin-top: 2rem; }
.footer__hd {
  font: 500 .68rem/1 var(--font-ui); letter-spacing: .2em; text-transform: uppercase;
  color: var(--rust); padding-block: 1.4rem .85rem;
  border-bottom: var(--rule-w) solid var(--ink);
}
.logos {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 1.9rem 2.75rem; padding-block: 1.9rem;
}
.logos a { display: flex; align-items: center; transition: opacity .15s ease; }
.logos img { display: block; }

/* Two renditions, selected by `logo_style` in site.yaml.
   Mono sits back into the paper; colour stands at full strength. */
.logos--mono a   { opacity: .62; }
.logos--mono a:hover { opacity: 1; }
.logos--colour a { opacity: 1; }
.logos--colour a:hover { opacity: .78; }

.colophon {
  border-top: 1px solid var(--rule);
  padding-block: 1.2rem 2.2rem;
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  font-size: .9rem; color: var(--ink-faint);
}
.colophon p { margin: 0; max-width: none; }
.colophon__built { margin-left: auto !important; }
@media (max-width: 700px) { .colophon__built { margin-left: 0 !important; } }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .hero__in { grid-template-columns: 1fr; }
  .hero__art { order: -1; }
  .strip__in { grid-template-columns: repeat(2, 1fr); }
  .strip__in > div:nth-child(2) { border-right: 0; }
  .strip__in > div:nth-child(-n+2) { border-bottom: var(--rule-w) solid var(--ink); }
  .file { grid-template-columns: minmax(0, 1fr) auto; row-gap: .5rem; }
  .file__fmt { grid-row: 2; justify-self: start; padding-inline: .6rem; }
  .file__size, .file__act { grid-column: 2; }
  .file__size { text-align: right; }
  .tools { position: static; }
}

@media (max-width: 640px) {
  .masthead__in { flex-wrap: wrap; }
  .nav { order: 3; width: 100%; gap: 1rem; overflow-x: auto; padding-bottom: .3rem; }
  .cards { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; scroll-behavior: auto !important; }
  .btn:hover, .card:hover, .mast:hover { transform: none; }
}

@media print {
  body::before, .tools, .nav, .btn { display: none; }
  body { background: #fff; }
  .file { break-inside: avoid; }
}

/* Accession shown for citation on files we host ourselves. Not a link, since
   the download button already points where the bytes actually are. */
.file__desc .acc {
  font: 400 .82em/1 var(--font-mono);
  background: var(--paper-2); border: 1px solid var(--rule);
  padding: .15em .4em; color: var(--ink-soft);
}

/* The paper this resource accompanies, stated on the landing page rather than
   buried on /cite/. A data resource should name its source of record. */
/* ---------- headline species inks ---------- */
.hl-prairie { color: var(--pink); }
.hl-meadow  { color: var(--teal); }

/* ---------- the vole ----------
   Walks in from the left margin, shoulders the capital P, turns and leaves the
   way it came. right:100% puts its right edge at the word's left edge, so
   translateX(0) is nose-to-letter contact and everything else is clear of the
   type: a screenshot never catches it covering a glyph. Travel sits on .vole
   and the gait on .vbody so the two transforms compose. The gait keyframes run
   only while the animal moves and hold flat once it stops, because CSS cannot
   animate animation-name. */

/* the word is the positioning context; without this the vole anchors to the
   page instead and lands off-screen */
.hl-prairie{position:relative;display:inline-block;color:var(--pink)}
.vole{position:absolute;right:100%;bottom:0;width:52px;height:auto;overflow:visible;
      pointer-events:none}
/* translateX(0) = nose touching the P. Negative = clear of the word.
   Positive Y moves it above cap height, where there are no glyphs to cover. */
.vbody{transform-box:fill-box;transform-origin:50% 100%}
.vtail{transform-box:fill-box;transform-origin:100% 50%}
.vlegA,.vlegB{transform-box:fill-box;transform-origin:50% 0}
@keyframes gait{0%,100%{transform:translateY(0) scaleY(1)}
                45%{transform:translateY(-4px) scaleY(1.05)}
                70%{transform:translateY(0) scaleY(.96)}}
@keyframes wag{0%,100%{transform:rotate(0deg)}50%{transform:rotate(-16deg)}}
@keyframes step{0%,100%{transform:rotate(-16deg)}50%{transform:rotate(18deg)}}
@keyframes idle{0%,100%{transform:translateY(0) scaleY(1)}50%{transform:translateY(0) scaleY(1.03)}}
@keyframes sniff{0%,100%{transform:rotate(0deg)}25%{transform:rotate(-4deg)}75%{transform:rotate(3deg)}}
/* the P rocking, identical in all four */
@keyframes wobble{0%,26%,100%{transform:rotate(0deg)}
                  31%{transform:rotate(-8deg)}
                  37%{transform:rotate(6deg)}
                  43%{transform:rotate(-3deg)}
                  49%{transform:rotate(1deg)}
                  55%{transform:rotate(0deg)}}


.hl-prairie .pcap{display:inline-block;transform-origin:50% 100%;animation:wobble 9s ease-in-out infinite}
.hl-prairie .vole{animation:runN3 9s ease-in-out infinite}
.hl-prairie .vbody{animation:pN3body 9s linear infinite}
.hl-prairie .vtail{animation:wag .3s ease-in-out infinite}
.hl-prairie .vlegA{animation:pN3legA 9s linear infinite}
.hl-prairie .vlegB{animation:pN3legB 9s linear infinite}
@keyframes pN3body{0.00%{transform:translateY(0) scaleY(1)}2.17%{transform:translateY(-4px) scaleY(1.05)}4.33%{transform:translateY(0) scaleY(1)}6.50%{transform:translateY(-4px) scaleY(1.05)}8.67%{transform:translateY(0) scaleY(1)}10.83%{transform:translateY(-4px) scaleY(1.05)}13.00%{transform:translateY(0) scaleY(1)}15.17%{transform:translateY(-4px) scaleY(1.05)}17.33%{transform:translateY(0) scaleY(1)}19.50%{transform:translateY(-4px) scaleY(1.05)}21.67%{transform:translateY(0) scaleY(1)}23.83%{transform:translateY(-4px) scaleY(1.05)}26.00%{transform:translateY(0) scaleY(1)}28.17%{transform:translateY(-4px) scaleY(1.05)}30.33%{transform:translateY(0) scaleY(1)}32.50%{transform:translateY(-4px) scaleY(1.05)}34.67%{transform:translateY(0) scaleY(1)}36.83%{transform:translateY(-4px) scaleY(1.05)}39.00%{transform:translateY(0) scaleY(1)}41.17%{transform:translateY(-4px) scaleY(1.05)}43.33%{transform:translateY(0) scaleY(1)}45.50%{transform:translateY(-4px) scaleY(1.05)}47.67%{transform:translateY(0) scaleY(1)}49.83%{transform:translateY(-4px) scaleY(1.05)}52.00%{transform:translateY(0) scaleY(1)}52.01%{transform:translateY(0) scaleY(1)}100%{transform:translateY(0) scaleY(1)}}
@keyframes pN3legA{0.00%{transform:rotate(-16deg)}2.17%{transform:rotate(18deg)}4.33%{transform:rotate(-16deg)}6.50%{transform:rotate(18deg)}8.67%{transform:rotate(-16deg)}10.83%{transform:rotate(18deg)}13.00%{transform:rotate(-16deg)}15.17%{transform:rotate(18deg)}17.33%{transform:rotate(-16deg)}19.50%{transform:rotate(18deg)}21.67%{transform:rotate(-16deg)}23.83%{transform:rotate(18deg)}26.00%{transform:rotate(-16deg)}28.17%{transform:rotate(18deg)}30.33%{transform:rotate(-16deg)}32.50%{transform:rotate(18deg)}34.67%{transform:rotate(-16deg)}36.83%{transform:rotate(18deg)}39.00%{transform:rotate(-16deg)}41.17%{transform:rotate(18deg)}43.33%{transform:rotate(-16deg)}45.50%{transform:rotate(18deg)}47.67%{transform:rotate(-16deg)}49.83%{transform:rotate(18deg)}52.00%{transform:rotate(-16deg)}52.01%{transform:rotate(0deg)}100%{transform:rotate(0deg)}}
@keyframes pN3legB{0.00%{transform:rotate(18deg)}2.17%{transform:rotate(-16deg)}4.33%{transform:rotate(18deg)}6.50%{transform:rotate(-16deg)}8.67%{transform:rotate(18deg)}10.83%{transform:rotate(-16deg)}13.00%{transform:rotate(18deg)}15.17%{transform:rotate(-16deg)}17.33%{transform:rotate(18deg)}19.50%{transform:rotate(-16deg)}21.67%{transform:rotate(18deg)}23.83%{transform:rotate(-16deg)}26.00%{transform:rotate(18deg)}28.17%{transform:rotate(-16deg)}30.33%{transform:rotate(18deg)}32.50%{transform:rotate(-16deg)}34.67%{transform:rotate(18deg)}36.83%{transform:rotate(-16deg)}39.00%{transform:rotate(18deg)}41.17%{transform:rotate(-16deg)}43.33%{transform:rotate(18deg)}45.50%{transform:rotate(-16deg)}47.67%{transform:rotate(18deg)}49.83%{transform:rotate(-16deg)}52.00%{transform:rotate(18deg)}52.01%{transform:rotate(0deg)}100%{transform:rotate(0deg)}}
@keyframes runN3{0%{transform:translate(-150px,0) scaleX(1)}
                 22%,26%{transform:translate(0,0) scaleX(1)}
                 32%{transform:translate(-26px,0) scaleX(1)}
                 40%{transform:translate(-20px,0) scaleX(1)}
                 46%{transform:translate(-20px,0) scaleX(-1)}
                 52%,100%{transform:translate(-170px,0) scaleX(-1)}}
@media (prefers-reduced-motion: reduce) {
  .vole { display: none; }
  .hl-prairie .pcap { animation: none; }
}

/* ---------- CiFi in running text ----------
   Same shine as the stamp, at body size. Underlined so it reads as a link
   rather than as decorated text, since the animation alone is not an
   affordance. Selected by href so the copy stays plain markdown. */
/* CiFi in the hero paragraph: the dark red and the link, but no shine. The
   stamp two lines above is already shining, and two on one screen cancel each
   other out. */
.hero__lede a[href*="cifi.dennislab.org"] {
  color: var(--darkred); font-weight: 600; text-decoration: none;
  border-bottom: 1px solid rgba(155, 22, 22, .38);
}
.hero__lede a[href*="cifi.dennislab.org"]:hover { border-bottom-color: var(--darkred); }

.intro a[href*="cifi.dennislab.org"] {
  font-weight: 600; text-decoration: none;
  border-bottom: 1.5px solid rgba(155, 22, 22, .45);
  color: var(--darkred);
  background-image: linear-gradient(100deg,
      var(--darkred) 0%, var(--darkred) 42%, #ff9a6a 50%, var(--darkred) 58%, var(--darkred) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: cifi-shine 3.2s linear infinite;
}
.intro a[href*="cifi.dennislab.org"]:hover { border-bottom-color: var(--darkred); }

@media (prefers-reduced-motion: reduce) {
  .intro a[href*="cifi.dennislab.org"] {
    animation: none; background-image: none;
    color: var(--darkred); -webkit-text-fill-color: var(--darkred);
  }
}

/* ---------- introduction, set as an article ----------
   Larger type in a narrower column: around 60-70 characters per line is where
   the eye reliably finds the start of the next one. The opening paragraph runs
   as a standfirst and the second takes a drop cap, so the section has two
   entry points rather than one block of prose. */
/* Text column plus the illustration. 420px leaves the prose around 56
   characters, which is still inside the band where the eye finds the next line
   reliably, and it is wide enough that the two chromosomes read as a figure
   rather than as an ornament. */
.intro { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: clamp(2rem, 5vw, 4rem);
         align-items: start; }
/* No frame, no rule, no panel. The PNG is transparent and sits on the paper;
   any container turns it back into a pasted-in rectangle. */
.intro__fig img { width: 100%; height: auto; display: block; }
.intro__fig p {
  font: 400 .8rem/1.55 var(--font-ui); color: var(--ink-faint);
  margin: .9rem 0 0; max-width: none;
}
@media (max-width: 900px) {
  .intro { grid-template-columns: 1fr; }
  .intro__fig { max-width: 460px; }
}

.intro p {
  font: 400 1.14rem/1.72 var(--font-text);
  color: var(--ink-soft);
  max-width: 64ch;
  margin: 0 0 1.4em;
}
.intro .stand {
  font: 400 clamp(1.2rem, 2.4vw, 1.42rem)/1.5 var(--font-text);
  color: var(--ink);
  max-width: 56ch;
  margin-bottom: 1.6em;
}
.intro .drop::first-letter {
  float: left;
  font: 400 3.4em/.78 var(--font-display);
  color: var(--pink);
  margin: .06em .1em 0 0;
  text-transform: uppercase;
}
/* a floated cap beside a 3-line paragraph looks broken on a phone */
@media (max-width: 560px) {
  .intro .drop::first-letter { float: none; font-size: 1em; line-height: inherit;
                               color: inherit; margin: 0; }
}
