/* ---------------------------------------------------------------- fonts

   The two families are served from this site, not from fonts.googleapis.com:
   a stylesheet fetched from Google sends every visitor's IP address there
   before the page has drawn, and this is a university site. The files are the
   same variable WOFF2 builds Google serves, under the SIL Open Font License;
   the licences sit beside them in content/fonts/.

   Both are variable fonts, so one file covers the whole weight range and, for
   Bricolage Grotesque, the width axis the display type varies. The latin-ext
   face is listed for names outside Latin-1; a browser downloads it only when a
   character in that range is used. */

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url('assets/fonts/bricolage-grotesque-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url('assets/fonts/bricolage-grotesque-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('assets/fonts/literata-normal-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('assets/fonts/literata-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Literata';
  font-style: italic;
  font-weight: 300 600;
  font-display: swap;
  src: url('assets/fonts/literata-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Literata';
  font-style: italic;
  font-weight: 300 600;
  font-display: swap;
  src: url('assets/fonts/literata-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Concept: Cohort
   People and impact first. The group's photographs are inconsistent in light,
   background and camera, so every one of them is pulled through a single
   hematoxylin-and-eosin duotone: the stain this group's digital pathology work
   is built on. Hover returns the real color. */

:root {
  /* Shared palette: leafy green and white, with clay as the contrast color.
     Clay is the split-complement of the green, so it reads as chosen rather than
     accidental, and ink-blue carries any second data series so a reader
     distinguishes the two by hue as well as by position. */
  --white:     #ffffff;
  --mist:      #f4f8f1;
  --leaf-pale: #dcedcb;
  --leaf:      #7fb05a;
  /* The wordmark's own green, from mlbiomed_logo_2025_green.pdf. Close to
     --leaf, and the logo file is what fixes the exact value. */
  --brand:     #6cbf47;
  --leaf-deep: #46753a;
  --forest:    #16281c;
  --slate:     #5f6f62;
  --clay:      #c2512e;
  --ink-blue:  #1f4e79;
  --clay-light: #e8794f;   /* clay lightened for text over photographs */

  --ink:      var(--forest);
  --ink-mid:  #41544a;
  --ink-soft: var(--slate);
  --paper:    var(--white);
  --paper-2:  var(--mist);
  --rule:     #d8e5d1;

  --plum-deep:  var(--forest);
  --eosin:      var(--leaf);
  --eosin-deep: var(--clay);

  --display: 'Bricolage Grotesque', 'Helvetica Neue', Arial, sans-serif;
  --body: 'Literata', Georgia, serif;
  --pad: clamp(20px, 5vw, 72px);
  color-scheme: light;
}

* { box-sizing: border-box; }

img, svg { max-width: 100%; }

/* The hidden attribute carries display: none in the user agent stylesheet,
   which any display declaration here outranks, and .feed .item and .controls
   both declare one. The news filter, the software ordering and the picked
   variants all hide by setting el.hidden, so this rule is what makes those
   scripts take effect, and it is also what keeps a control bar that awaits
   JavaScript out of the page with JavaScript off. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  /* A DOI, a repository URL or a German compound is wider than a phone column,
     and an unbroken token pushes the whole page sideways rather than
     overflowing its own box. */
  overflow-wrap: break-word;
  font: 400 17.5px/1.7 var(--body);
  font-variation-settings: 'opsz' 16;
  -webkit-font-smoothing: antialiased;
}

/* Links are marked by colour and weight. A link in running text carries the
   accent color and a heavier weight, and darkens on hover and keyboard focus;
   a link that is already a heading, a pill, a card or a navigation item is
   marked by the shape it sits in and inherits its color. */
a { color: inherit; text-decoration: none; }
p a, li a, address a, figcaption a, .note a, dd a {
  color: var(--eosin-deep);
  font-weight: 500;
}
p a:hover, li a:hover, address a:hover, figcaption a:hover, .note a:hover, dd a:hover,
p a:focus-visible, li a:focus-visible, address a:focus-visible,
figcaption a:focus-visible, .note a:focus-visible, dd a:focus-visible { color: var(--ink); }
.foot p a, .foot li a { color: #fff; }
.foot p a:hover, .foot li a:hover { color: var(--eosin); }
::selection { background: var(--leaf-pale); }
:focus-visible { outline: 3px solid var(--eosin-deep); outline-offset: 3px; }

h1, h2, h3 {
  font-family: var(--display);
  font-variation-settings: 'wdth' 92, 'opsz' 42;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.02;
  margin: 0;
}

.wrap { max-width: 1220px; margin: 0 auto; padding: 0 var(--pad); }

/* ---------------------------------------------------------------- duotone */

.duo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--forest);
  display: block;
}

/* Photographs keep their own colour. Images are shown in their original
   color everywhere except the people gallery, where black and white unifies a
   set of portraits shot under fourteen different lighting conditions, and hover
   returns the real thing. Only `filter` animates, so the transition stays
   smooth where the old blend-mode version snapped. */
.duo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: filter .4s ease;
}

.gallery .duo img { filter: grayscale(1) contrast(1.04); }
.gallery a:hover .duo img,
.gallery a:focus-visible .duo img { filter: none; }

@media (prefers-reduced-motion: reduce) {
  .duo img { transition: none; }
}

/* ---------------------------------------------------------------- header */

.top {
  /* Fixed rather than absolute so the bar stays on screen once the hero has
     scrolled past. It keeps overlaying the hero photograph, so it needs a scrim
     of its own: --forest at 62%, which is dark enough to hold white type over
     both a bright photograph and the paper-white sections underneath. */
  position: fixed;
  inset: 0 0 auto;
  z-index: 10;
  color: #fff;
  background: rgba(22, 40, 28, 0.62);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.top .wrap { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; min-height: 78px; }

.wordmark {
  display: block;
  text-decoration: none;
  margin-right: auto;
}

/* The mark is stacked, so its height is what has to hold the header against
   the six navigation items. 46px leaves 16px of air in the 78px bar. */
.wordmark img { display: block; height: 46px; width: auto; }

.menu { display: flex; gap: 20px; flex-wrap: wrap; }

.menu a {
  font-family: var(--display);
  font-variation-settings: 'wdth' 100;
  font-weight: 600;
  font-size: 14.5px;
  letter-spacing: 0.01em;
  text-decoration: none;
  padding: 4px 0;
  border-bottom: 2px solid transparent;
  opacity: .82;
}

.menu a:hover { opacity: 1; }
.menu a[aria-current='page'] { opacity: 1; border-bottom-color: var(--eosin); }

.top--solid { position: sticky; top: 0; color: var(--ink); background: var(--paper);
             border-bottom: 1px solid var(--rule); backdrop-filter: none; }
.top--solid .menu a[aria-current='page'] { border-bottom-color: var(--leaf-deep); }

/* ---------------------------------------------------------------- hero */

.hero { position: relative; min-height: min(92vh, 820px); display: grid; }
.hero .duo { position: absolute; inset: 0; }
.hero .duo img { height: 100%; }

.hero .scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.58) 0%, rgba(0,0,0,.16) 40%, rgba(0,0,0,.84) 100%);
  pointer-events: none;
}

.hero .body { position: relative; align-self: end; padding: 118px 0 clamp(38px, 5vw, 68px); color: #fff; }

.hero h1 {
  font-size: clamp(34px, 5.4vw, 74px);
  font-variation-settings: 'wdth' 86, 'opsz' 72;
  max-width: 13ch;
  margin: 0 0 20px;
  text-wrap: balance;
}

.hero h1 em { font-style: normal; color: var(--clay-light); }

.hero p {
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.6;
  max-width: 68ch;
  margin: 0;
  color: rgba(255, 255, 255, .9);
}

.hero .place {
  font-family: var(--display);
  font-variation-settings: 'wdth' 100;
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .78);
  margin: 0 0 18px;
}

.hero-caption {
  position: absolute;
  right: var(--pad);
  bottom: 14px;
  font-size: 12px;
  font-style: italic;
  color: rgba(255, 255, 255, .55);
}

/* ---------------------------------------------------------------- sections */

.band { padding: clamp(58px, 8vw, 116px) 0; }
/* Half the usual band opening, for the two places where a section follows a
   one-line page head or the hero and the full gap reads as a hole. Both halves
   of the gap are halved: the head's own bottom padding and the band's top. */
.band--tight { padding-top: clamp(29px, 4vw, 58px); }
.band--tint { background: var(--paper-2); }
.band--deep { background: var(--plum-deep); color: #fff; }
.band--deep h2, .band--deep h3 { color: #fff; }

.label {
  font-family: var(--display);
  font-variation-settings: 'wdth' 100;
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--eosin-deep);
  margin: 0 0 18px;
}

.band--deep .label { color: var(--eosin); }

h2.big { font-size: clamp(30px, 4.4vw, 56px); font-variation-settings: 'wdth' 88, 'opsz' 48; max-width: 20ch; text-wrap: balance; }

.say { font-size: clamp(20px, 2.1vw, 27px); line-height: 1.45; max-width: 42ch; color: var(--ink); }

.two-col { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: clamp(26px, 4vw, 64px); align-items: start; }
.two-col p { margin: 0 0 1em; color: var(--ink-mid); }

/* work cards */

.work { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr)); gap: 4px; margin-top: 42px; }

/* lists, publications by direction */

.pubgroup { border-top: 2px solid var(--ink); padding-top: 8px; margin-top: 46px; }
.pubgroup > h3 { font-size: clamp(23px, 2.6vw, 32px); margin: 14px 0 6px; }
/* The lead line under a group heading runs to the rule above it rather than
   stopping at a reading measure: it is a one-sentence label for the section,
   not body copy, and a short measure left it visibly narrower than the rule. */
.pubgroup > p { margin: 0 0 18px; color: var(--ink-soft); max-width: 96%; font-size: 16.5px; }

.pub { padding: 18px 0; border-top: 1px solid var(--rule); display: grid;
       grid-template-columns: 96px minmax(0, 1fr) 200px; gap: 22px; align-items: start; }

/* Figures are wide and multi-panel, so they are fitted rather than cropped: a
   square crop of a six-panel figure shows one arbitrary corner of it. The cell
   holds its width for every row, with a figure or with an empty cell, so the
   text column keeps one width down the list.

   The cell stretches to the height of the text beside it, title through pills,
   and the image is taken out of flow to fill it. Out of flow is what keeps the
   sizing one-way: the row is as tall as its text, and a 1121px-tall source
   figure fits itself to that height. */
.pub .fig { width: 200px; align-self: stretch; position: relative; }
.pub .fig img { position: absolute; inset: 0; width: 100%; height: 100%;
                object-fit: contain; display: block;
                background: var(--paper-2); border: 1px solid var(--rule); border-radius: 2px; }
.pub .yr { font-family: var(--display); font-weight: 700; font-size: 15px; color: var(--ink-soft); }
/* Color comes from the shared .k-* palette the activity stream uses, so a
   paper reads the same green here as it does on the front page. */
.pub .yr span { display: block; font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; margin-top: 3px; }
.pub h4 { font-family: var(--body); font-weight: 600; font-size: 18.5px; line-height: 1.4; margin: 0 0 5px; max-width: 60ch; }
.pub h4 a:hover { color: var(--eosin-deep); }
.pub .au { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--ink-soft); }
/* The one-sentence gloss of the paper. Darker and a step larger than the author
   and venue lines above it, because it is the part of the row meant to be read
   rather than scanned, and wrapping at the same width as the title above it.
   ch is relative to font size, so matching the title's 60ch at 18.5px means
   60 * 18.5 / 15.5 here: the same measure in both, in the same body font. */
.pub .sum { margin: 7px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--ink-mid); max-width: 71.6ch; }

.pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.pills a {
  font-family: var(--display);
  font-weight: 600;
  font-size: 12.5px;
  text-decoration: none;
  border: 1px solid var(--rule);
  border-radius: 100px;
  padding: 5px 12px;
  color: var(--ink-mid);
}
.pills a:hover { border-color: var(--eosin-deep); color: var(--eosin-deep); }

/* ------------------------------------------------------------- controls

   A control changes what is on the page it sits on; a pill leaves the page.
   Both were a rounded outline in the same type at the same size, so the two
   kinds of target were told apart only by reading them. A control is now
   square-cornered and sits on a tinted ground, and the one in effect is filled
   leaf-deep; a pill keeps the rounded outline on paper. The bar is hidden
   until its script shows it, so it appears only with behaviour behind it.

   Both the order control on the software page and the kind filter on the
   activity feed use this. */
.controls { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; margin: 0 0 22px; }
.controls-label { font-family: var(--display); font-weight: 700; font-size: 12.5px;
                  letter-spacing: .16em; text-transform: uppercase; color: var(--eosin-deep); }
.controls [role="group"] { display: flex; flex-wrap: wrap; gap: 6px; }
.controls button {
  font-family: var(--display);
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: .02em;
  color: var(--ink-mid);
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 7px 14px;
  cursor: pointer;
}
.controls button:hover { border-color: var(--leaf-deep); color: var(--leaf-deep); }
.controls button[aria-pressed="true"] { border-color: var(--leaf-deep); color: var(--white);
                                        background: var(--leaf-deep); }

/* software */

.tools { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(310px, 100%), 1fr)); gap: 26px; }
.tool { position: relative; border: 1px solid var(--rule); border-radius: 4px; padding: 26px; background: #fff; display: flex; flex-direction: column; gap: 10px; }
.tool:hover { border-color: var(--eosin); }
.tool h3 { font-size: 22px; }
/* The card title carries the link to the repository and its ::after covers the
   card, so a click anywhere on the card follows it. The pills sit above that
   layer and keep their own targets. */
.tool h3 a { color: inherit; text-decoration: none; }
.tool h3 a::after { content: ""; position: absolute; inset: 0; border-radius: 4px; }
.tool:hover h3 a { color: var(--eosin-deep); }
.tool h3 a:focus-visible::after { outline: 2px solid var(--leaf-deep); outline-offset: 3px; }
.tool .pills { position: relative; z-index: 1; }
.tool .t { font-family: var(--display); font-weight: 600; font-size: 15px; color: var(--eosin-deep); margin: -4px 0 0; }
.tool p { margin: 0; font-size: 16px; line-height: 1.55; color: var(--ink-mid); }
.tool .facts { font-size: 13.5px; color: var(--ink-soft); border-top: 1px solid var(--rule); padding-top: 12px; margin-top: auto; }

/* join */

.joins { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); gap: 30px; margin-top: 40px; }
.joins h3 { font-size: 21px; margin: 0 0 8px; font-variation-settings: 'wdth' 92, 'opsz' 24; }
.joins p { margin: 0; color: rgba(255, 255, 255, .76); font-size: 16px; line-height: 1.55; }

.cta {
  display: inline-block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 16px;
  background: var(--eosin);
  color: var(--plum-deep);
  text-decoration: none;
  padding: 14px 26px;
  border-radius: 3px;
  margin-top: 30px;
}
.cta:hover { background: #fff; }

.contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 34px; }
.contact-grid h3 { font-size: 15px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--eosin-deep); font-variation-settings: 'wdth' 100; margin: 0 0 12px; }
.contact-grid address { font-style: normal; font-size: 18px; line-height: 1.7; color: var(--ink-mid); }

/* footer */

.foot { background: var(--ink); color: #efe7f0; padding: 52px 0 60px; }
.foot .wrap { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); gap: 30px; }
.foot h4 { font-family: var(--display); font-weight: 700; font-size: 12.5px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--eosin); margin: 0 0 12px; }
.foot p, .foot li { font-size: 15px; line-height: 1.65; color: rgba(255, 255, 255, .72); margin: 0 0 6px; }
.foot ul { list-style: none; padding: 0; margin: 0; }
.foot a { color: #fff; }
.foot a:hover { color: var(--eosin); }
.foot .end { grid-column: 1 / -1; border-top: 1px solid rgba(255, 255, 255, .16); padding-top: 18px; font-size: 13.5px; font-style: italic; color: rgba(255, 255, 255, .5); }

.pagehead { padding: clamp(52px, 7vw, 96px) 0 clamp(30px, 4vw, 46px); }
.pagehead--tight { padding-bottom: clamp(15px, 2vw, 23px); }
.pagehead h1 { font-size: clamp(36px, 5.6vw, 74px); font-variation-settings: 'wdth' 88, 'opsz' 60; max-width: 17ch; text-wrap: balance; }
.pagehead p { font-size: clamp(17px, 1.6vw, 20px); line-height: 1.6; max-width: 72ch; color: var(--ink-mid); margin: 20px 0 0; }
/* A one-sentence page head is set to the full column so it stays on one line
   where the width allows, and balances into even lines where it is narrower. */
.pagehead p.lede { max-width: none; text-wrap: balance; }

/* Registers differ in headline length, so the display scale follows the voice. */


/* ---------------------------------------------------------------- activity feed */

.feed { display: grid; gap: 0; border-top: 2px solid var(--ink); }

.feed .item { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 26px;
              padding: 22px 0; border-bottom: 1px solid var(--rule); }
.feed .when { font-family: var(--display); font-weight: 700; font-size: 13px; letter-spacing: .08em;
              text-transform: uppercase; color: var(--ink-soft); }
.feed .added { display: block; margin-top: 3px; font-weight: 400; font-size: 11px;
               letter-spacing: .06em; text-transform: none; color: var(--ink-soft); opacity: .8; }
.feed .kind { display: inline-block; margin-top: 8px; font-family: var(--display); font-weight: 700;
              font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
              border: 1px solid currentColor; border-radius: 100px; padding: 4px 10px; }

.k-paper    { color: var(--leaf-deep); }
.k-preprint { color: var(--clay); }
.k-review   { color: var(--slate); }
.k-code     { color: var(--leaf-deep); }
.k-people   { color: var(--ink-blue); }
.k-event    { color: var(--clay); }
.k-talk     { color: var(--ink-blue); }
.k-award    { color: var(--leaf-deep); }

.feed h3 { font-family: var(--body); font-weight: 600; font-size: 19.5px; line-height: 1.4;
           letter-spacing: 0; margin: 0 0 6px; max-width: 58ch; }
.feed h3 a:hover { color: var(--eosin-deep); }
.feed p { margin: 0; font-size: 16px; line-height: 1.55; color: var(--ink-mid); max-width: 70ch; }
.feed .where { font-size: 14.5px; font-style: italic; color: var(--ink-soft); margin-top: 4px; }
.feed .sum { font-size: 15.5px; line-height: 1.55; color: var(--ink-mid); margin-top: 6px; max-width: 70ch; }

/* The count under the filter, shown only while a kind is selected: with All in
   effect the feed is its own answer. */
.filtercount { font-family: var(--display); font-weight: 600; font-size: 12.5px;
               letter-spacing: .04em; color: var(--ink-soft); margin: -8px 0 14px; }

.checkflag { display: inline-block; font-family: var(--display); font-weight: 700; font-size: 11px;
             letter-spacing: .1em; text-transform: uppercase; color: var(--clay);
             border: 1px dashed var(--clay); border-radius: 100px; padding: 3px 9px; margin-left: 8px; }

/* ---------------------------------------------------------------- people gallery */

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr)); gap: 26px 20px; }
.gallery a { text-decoration: none; display: block; }
.gallery .duo { aspect-ratio: 3 / 4; border-radius: 3px; }
.gallery b { display: block; font-family: var(--display); font-variation-settings: 'wdth' 94, 'opsz' 20;
             font-weight: 700; font-size: 17px; margin-top: 12px; }
.gallery span { display: block; font-family: var(--display); font-weight: 600; font-size: 13px;
                color: var(--eosin-deep); margin-top: 2px; }

.profile { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 34px; padding: 30px 0;
           border-bottom: 1px solid var(--rule); scroll-margin-top: 90px; }
.profile .duo { aspect-ratio: 3 / 4; border-radius: 3px; }
.profile h3 { font-size: 25px; margin: 0 0 4px; font-variation-settings: 'wdth' 92, 'opsz' 28; }
.profile .r { font-family: var(--display); font-weight: 600; font-size: 14px; color: var(--eosin-deep); margin: 0 0 12px; }
.profile p { margin: 0; color: var(--ink-mid); }

.note { font-family: var(--body); font-size: 13.5px; line-height: 1.7; color: var(--ink-soft);
         border-top: 1px solid var(--rule); padding-top: 12px; margin: 30px 0 0; max-width: 76ch; }

/* ---------------------------------------------------------------- affiliations */

.logos { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 24px; }
.logos .logo { text-decoration: none; border: 0; display: inline-flex; align-items: center; }
.logos img { height: 32px; width: auto; display: block; filter: brightness(0) invert(1); opacity: .8; }
.logos .logo:hover img { opacity: 1; }
.wordmark-fallback { font-family: var(--display); font-weight: 700; font-size: 12.5px; letter-spacing: .1em;
                     color: rgba(255,255,255,.72); border: 1px solid rgba(255,255,255,.3);
                     border-radius: 100px; padding: 7px 13px; }
.logos .logo:hover .wordmark-fallback { color: #fff; border-color: var(--eosin); }

/* The footer row sits on forest, so its marks are knocked out to white. The
   funder row on the research page sits on tinted paper, where the official
   colors are the point and knocking them out would be wrong. */
/* Five marks to a row, so the eight funders read as a block rather than as a
   line that rewraps at every window width. The row is laid out with flex and
   the cell width is set from the count, so a partly filled row --- the
   last three, FIMM-EMBL, HiLIFE and the University --- is centered under the
   row above instead of hanging off its left edge. The count drops on narrow
   screens where five would leave 60px a logo. */
.logos--funders { --per-row: 5; --logo-gap: 34px;
                  display: flex; flex-wrap: wrap; justify-content: center;
                  gap: 30px var(--logo-gap); margin-top: 30px; align-items: center; }
.logos--funders .logo {
  flex: 0 0 calc((100% - (var(--per-row) - 1) * var(--logo-gap)) / var(--per-row));
  justify-content: center;
}
.logos--funders img { height: 53px; max-width: 100%; object-fit: contain; filter: none; opacity: 1; }
/* Official marks differ in how much of their own box the artwork fills, and in
   whether the name sits beside the symbol or under it, so each is set against
   its neighbors by eye. 53px is the height a one-line mark reads at. */
.logos--funders .logo--uh img { height: 87px; }
.logos--funders .logo--sigrid-juselius img { height: 84px; }
.logos--funders .logo--csc img { height: 76px; }
.logos--funders .logo--research-council-finland img,
.logos--funders .logo--fimm img { height: 56px; }
.logos--funders .logo:hover img { opacity: .75; }
.logos--funders .wordmark-fallback { color: var(--ink-soft); border-color: var(--rule); }
.logos--funders .logo:hover .wordmark-fallback { color: var(--ink); border-color: var(--leaf-deep); }

/* ---------------------------------------------------------------- responsive

   Two breakpoints. At 860px the three side-by-side layouts --- the feed's date
   column, a profile's portrait column and a paper's figure column --- become
   one column, because none of the three holds its shape at a tablet width. At
   560px the header, the type scale and the tap targets are set for a phone
   held in one hand. */

@media (max-width: 860px) {
  .logos--funders { --per-row: 3; }
  .feed .item, .profile { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  /* The figure column is dropped rather than stacked: a multi-panel figure at
     phone width costs a download for an unreadable result. */
  .two-col, .pub { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .pub .fig { display: none; }
  /* A portrait laid out as its own row would otherwise run the full column
     width at 3:4, which is most of a phone screen for one face. */
  .profile .duo { max-width: 168px; }
  .hero { min-height: 78vh; }
  .hero-caption { display: none; }
}

@media (max-width: 560px) {
  .logos--funders { --per-row: 2; }
  /* The gallery is held at two columns here. The 160px minimum track resolves
     to a single column once the wrap is narrower than 340px, which is a 375px
     screen, and one 3:4 portrait then runs about 450px down the page. */
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body { font-size: 17px; }
  .menu { gap: 4px 14px; }
  /* The six items wrap to a second line under the wordmark on a phone, so each
     one is given a target of its own rather than a 14px baseline to hit. */
  .menu a { font-size: 13px; padding: 8px 0; }
  .top .wrap { min-height: 62px; gap: 8px 16px; padding-top: 10px; padding-bottom: 10px; }
  .wordmark img { height: 34px; }
  /* Pills and controls are the tappable targets outside running text; both go
     to a 40px box, near the 44px a thumb wants, while the type size that sets
     them stays as it is. */
  .pills a { padding: 9px 14px; }
  .controls button { padding: 10px 14px; }
  .feed .item { padding: 18px 0; }
  .feed h3 { font-size: 18.5px; }
  .hero .body { padding-top: 96px; }
  .band { padding: clamp(44px, 9vw, 58px) 0; }
  .tool { padding: 20px; }
  .foot { padding: 40px 0 46px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}

/* ---------------------------------------------------------------- feed image

   A photograph on an activity entry, shown in its own colour: the
   people gallery is the only place color is removed. */
.feed-fig { margin: 14px 0 0; max-width: 60ch; }
.feed-fig img { width: 100%; height: auto; display: block; border-radius: 3px; }
.feed-fig figcaption {
  margin-top: 8px;
  font-family: var(--body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.feed-fig .credit { color: var(--slate); }
.feed-fig .credit::before { content: " · "; }

/* Same separator in the hero, where the credit follows the place and date
   on one line over the photograph. */
.hero-caption .credit::before { content: " · "; }
