/* Foundation: tokens, base, type roles, grid. Everything else on the site is built from these
   rules: a module sets its own layout and space (from the tokens below) and takes its type from a
   role class in its HTML, or from the tokens when its element cannot carry one.

   Type (_docs/design.md, rule 4). One family, Inter. Five sizes, set far apart so that no two are
   a pixel or two from each other; two weights, 400 to read and 600 to name; one grey.
     XXL  68px (36 on a phone)  600  the home headline                                  .display
     XL   52px (36)             600  a page title                                       .title
     L    22px (18)             400  a lede; a label: a band's, in the left column (a    .lede, .sec-head,
                                     section's name, a year, a note's date), and a      .label
                                     block's ("Selected papers", "Seminar", "Join")
          22px (20)             600  the key sentence of a block: a research question,  .h2
                                     the leader's name, the title of a talk or a figure
     M    16px                  400  all running text; a link that leads on ("All … →")
                                600  the title of an entry: a paper, a card, a position, .h3
                                     an item, a member, a speaker
     S    14px                  400  grey metadata: authors, venue, dates, roles; a     .meta
                                     row of links (grey, red on hover)
                                400  small text in ink (a speaker, a footer)            .small
     zh   15px                  400  Chinese text, which reads a size larger than Latin, so 15px
                                     sits with 16px; open leading and a hair of tracking
   Labels. A label names the band beside it or the block under it. It is set in the regular weight
   at L, in ink: a heading by its size, quieter than the semibold titles it names. It wraps in its
   column (balanced, between words) and is never a count. Its capitals stand on the same line as
   the capitals of the first line beside it (see Band, below).
   Colour. Ink for what is read; one grey (--ink-2) for everything secondary, the author marks
   included; --ink-3 is never a word, only an underline or a "·" between items. Inside a grey
   line, ink marks what matters: the group's names, and a journal in semibold italic (.jnl), so a
   published paper stands out from a preprint in every list of papers. Red only for what is live
   (the recruiting dot, a next talk) and for hover; blue only inside figures.
   Space. A page is a stack of bands, each opened by one rule, with the same space above and below
   its content (--band), the footer included. Inside: 4px from a title to its grey line; 8px from
   there to the text and to its links, and from a block's label to what it labels; 16px between
   the items of a dense list, under a picture, and from a band's label to its content where the
   label stands above it (below 900px); 24px between entries; 32px between cards and between
   blocks.
   Measure. Short text (a summary, a description, news) at most 40em, about 80 characters a line;
   paragraphs read at length 33em, about 70. Paragraphs never end on one short word (pretty),
   titles are balanced, and names never break inside. */

:root {
  --bg: #ffffff;
  --ink: #111111;
  --ink-2: #6b6b6b;   /* the one text grey: everything secondary, the author marks (5.3:1 on white) */
  --ink-3: #a6a6a6;   /* never a word: underlines and the "·" between items */
  --hair: #e6e6e6;
  --rule: #111111;
  --red: #e4002b;
  --blue: #1f4fd8;

  --sans: "Inter", "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;

  --max: 1520px;                       /* widest content */
  --m: clamp(20px, 4.2vw, 72px);       /* outer margin */
  --g: clamp(16px, 1.8vw, 28px);       /* column gap */
  --sec: clamp(44px, 4.6vw, 76px);     /* space before the first band, after a page title or the hero,
                                          and under a page title that no band follows (404) */
  --band: clamp(28px, 2.8vw, 44px);    /* inside a band: from its rule to its content, and from its
                                          content to the next rule (the same above and below) */
  /* From the top of a line box to the top of its capitals: half the leading plus Inter's ascent
     above the cap height (0.969 - 0.727 of the size). Inter leaves the same below the baseline
     (descent 0.242), so a line of text has this much space above its capitals and below its
     baseline. A photo or a poster beside text is inset by it, so its edges meet the capitals of
     the first line and the baseline of the last. */
  --cap-l: calc(var(--fs-l) * 0.256);  /* L at 1.24 (a label; a key sentence too, within half a pixel): 5.6px, 4.6 on a phone */
  --cap-m: calc(var(--fs-m) * 0.286);  /* M at 1.3 (an entry title): 4.6px */

  /* Sizes */
  --fs-xxl: clamp(36px, 4.6vw, 68px);
  --fs-xl: clamp(36px, 3.6vw, 56px);
  --fs-l: clamp(18px, 0.5vw + 15px, 22px);
  --fs-key: clamp(20px, 0.5vw + 15px, 22px);   /* L for a key sentence: never under 20px, so on a phone it stays above an 18px lede */
  --fs-m: 1rem;
  --fs-s: 0.875rem;
  --fs-zh: 0.9375rem;

  /* Leading: tight on large type, open on text, more open for Chinese */
  --lh-m: 1.5;          /* 24px: text */
  --lh-s: 1.43;         /* 20px: metadata */
  --lh-head: 1.3;       /* a title at M */
  --lh-l: 1.24;         /* a heading or a label at L */
  --lh-lede: 1.32;      /* a lede at L */
  --lh-zh: 1.75;        /* Chinese text */

  /* Tracking: Inter's own, tighter as the size grows; a hair of space for Chinese */
  --ls-m: -0.011em;
  --ls-s: -0.004em;
  --ls-l: -0.019em;
  --ls-zh: 0.03em;

  /* Space: the same five steps in every module */
  --sp-1: 4px;     /* a title → its grey line */
  --sp-2: 8px;     /* a grey line → the text → its links; a label → what it labels; rows of a table */
  --sp-3: 16px;    /* between the items of a dense list; a picture → its caption; parts of a block;
                      a band's label → its content, where the label stands above it (phones) */
  --sp-4: 24px;    /* between entries: papers, items, positions */
  --sp-5: 32px;    /* between cards (members, posters, research lines) and between blocks */

  /* Measure */
  --measure: 40em;        /* short text beside a title or a date: about 80 characters a line */
  --measure-long: 33em;   /* paragraphs read at length: about 70 */
}

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

html {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: var(--lh-m);
  letter-spacing: var(--ls-m);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body { margin: 0; background: var(--bg); }
img, canvas, svg, video { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; letter-spacing: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
::selection { background: var(--red); color: #fff; }
:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }

/* Links: a title or a name that links has no line; a link inside a sentence a hairline in
   --ink-3. Both turn red on hover. */
a { color: inherit; text-decoration: none; }
a:hover { color: var(--red); }
.prose a, a.u { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.prose a:hover, a.u:hover { text-decoration-color: var(--red); }
.prose a.footnote, .prose a.reversefootnote { text-decoration: none; }   /* a note's number needs no line */
b, strong { font-weight: 600; }
/* sub and sup never open the leading of their line, and are never under 13px */
sub, sup { position: relative; font-size: max(13px, 0.75em); line-height: 0; vertical-align: baseline; }
sup { top: -0.45em; }
sub { bottom: -0.2em; }
/* two notes in a row read "3,4", not "34" */
sup[role="doc-noteref"] + sup[role="doc-noteref"]::before { content: ","; }

.skip { position: absolute; left: -999px; top: 8px; background: var(--ink); color: #fff; padding: 6px 10px; z-index: 10; }
.skip:focus { left: 8px; }
.sr { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
[hidden] { display: none !important; }
/* Text dated to appear on a day (data-from="YYYY-MM-DD") stays hidden until
   assets/js/modules/dated.js finds that the day has come. */
[data-from] { display: none !important; }

/* Type roles */
h1, h2, h3, h4, p { margin: 0; }
h1, h2, h3, h4 { font-weight: 600; text-wrap: balance; }
p, li, dd { text-wrap: pretty; }   /* no word left alone on a paragraph's last line */
.display { font-size: var(--fs-xxl); font-weight: 600; line-height: 0.98; letter-spacing: -0.04em; }
.title { font-size: var(--fs-xl); font-weight: 600; line-height: 1; letter-spacing: -0.04em; }
.h2 { font-size: var(--fs-key); font-weight: 600; line-height: var(--lh-l); letter-spacing: var(--ls-l); text-wrap: balance; }
.h3 { font-size: var(--fs-m); font-weight: 600; line-height: var(--lh-head); letter-spacing: var(--ls-m); text-wrap: balance; }
.lede { font-size: var(--fs-l); font-weight: 400; line-height: var(--lh-lede); letter-spacing: -0.017em; text-wrap: pretty; }
@media (min-width: 900px) { .lede { text-wrap: balance; } }   /* two or three even lines on a wide screen; full lines on a phone */
.label { font-size: var(--fs-l); font-weight: 400; line-height: var(--lh-l); letter-spacing: var(--ls-l); }   /* a block's name: "Selected papers", "Seminar" */
.small { font-size: var(--fs-s); line-height: var(--lh-s); letter-spacing: var(--ls-s); }
.meta { font-size: var(--fs-s); font-weight: 400; line-height: var(--lh-s); letter-spacing: var(--ls-s); color: var(--ink-2); }   /* venue, date, role: one grey line */
.muted { color: var(--ink-2); }
.faint { color: var(--ink-3); }
.num { font-variant-numeric: tabular-nums; }
.nw { white-space: nowrap; }          /* keeps e.g. "43, 100002 · 2026" on one line */
/* a journal in a paper's grey line (parts/venue.html); a preprint stays grey */
.jnl { color: var(--ink); font-weight: 600; }

/* Chinese. Every Chinese run drops Inter's negative tracking for a hair of space, and gets a
   space between Chinese and Latin letters or figures where the browser can add one. A name or a
   title inside a Latin line (span.zh) is a touch smaller, regular and grey, and never breaks
   inside; a heading that ends in one wraps line by line, so its Latin words stay together and
   the Chinese moves whole to the next line. A block of Chinese text sets its own size and leading
   (--fs-zh, --lh-zh, --ls-zh). */
.zh, :lang(zh) { letter-spacing: 0.02em; text-autospace: normal; }
span.zh { font-size: 0.9375em; font-weight: 400; color: var(--ink-2); white-space: nowrap; }
:is(h1, h2, h3, h4):has(> span.zh) { text-wrap: wrap; }

/* Two signs Inter's files do not carry, drawn here rather than borrowed from whatever font the
   system has: → after a link that leads on (span.arr), ✉ after a corresponding author (span.mk-c,
   parts/authors.html). The character stays in the page for copying and for screen readers; only
   its drawing is replaced, in the colour of the text, so it turns red on hover with its link. */
.arr, .mk-c { display: inline-block; overflow: hidden; white-space: nowrap; text-indent: 200%; background-color: currentColor; -webkit-mask: var(--sign) no-repeat 50% 50% / 100% 100%; mask: var(--sign) no-repeat 50% 50% / 100% 100%; }
.arr { --sign: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15 10'%3E%3Cpath d='M0 5h13.6M9.2.6 13.6 5 9.2 9.4' fill='none' stroke='%23000' stroke-width='1.35'/%3E%3C/svg%3E"); width: 0.94em; height: 0.625em; margin-left: 0.3em; vertical-align: 0.02em; }
/* the envelope half an em tall, its top on the capitals' line */
.mk-c { --sign: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 8'%3E%3Cpath d='M.65.65h9.7v6.7H.65zM.9 1 5.5 4.6 10.1 1' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3C/svg%3E"); width: 0.69em; height: 0.5em; margin-left: 0.16em; vertical-align: 0.227em; }
/* author marks ✉ * † in the text grey, whatever the colour of the name they follow */
.mk { color: var(--ink-2); font-weight: 400; }

/* Grid: a 12-column grid inside a centred wrap */
.wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--m); }
.grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g); }
.grid > * { grid-column: 1 / -1; min-width: 0; }

/* Band: a single rule, a label at the left, the content at the right. The rule is the only line;
   it touches nothing. The space between the rule and the content equals the space between the
   content and the next rule (--band), so every band sits evenly between its rules; the footer is
   the last band, and the end of the page is its next rule. Bands follow each other with nothing
   between them; the first band after a page title or the hero keeps a larger gap above its rule
   (--sec). Nothing inside a band adds space at its top or bottom edge: a module's first and last
   elements have no outer margin there.
   The label (a section's name, a year, a note's date) is set at L in the regular weight (see
   Labels, at the top). Label and content start together at the top of the band's content, and the
   capitals meet without any offset: every first line in the system leaves 4.6 to 6.2px above its
   capitals (--cap-l, --cap-m; 6.2 for running text), so each stands within a pixel of the label's. A
   photo that opens a band is inset by --cap-l (modules/people.css), so its top edge meets the
   label's capitals too. Beside the content the label keeps the key sentence's leading (1.24), so
   a two-line label and a two-line research question share their lines. Below 900px the label
   stands alone above the content, 16px over it, on the lede's leading (1.32): the space above its
   capitals (5.3px) then nearly equals the space under the last baseline of running text (6.2px),
   so the band reads even there too. */
.sec { margin-top: var(--sec); }
.sec + .sec { margin-top: 0; }
.sec > .grid { border-top: 1px solid var(--rule); padding-top: var(--band); padding-bottom: var(--band); row-gap: var(--sp-3); }
.sec-head { font-size: var(--fs-l); font-weight: 400; line-height: var(--lh-l); letter-spacing: var(--ls-l); text-wrap: balance; }
.sec-head.year { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
@media (max-width: 899px) {
  .sec-head { line-height: var(--lh-lede); }
}
@media (min-width: 900px) {
  .sec-head { grid-column: 1 / span 3; }
  .sec-body { grid-column: 4 / -1; }
}
@media (min-width: 1200px) {
  .sec-head { grid-column: 1 / span 2; }
  .sec-body { grid-column: 3 / -1; }
}

/* Page title block (all pages except home). A page that ends with its title (404) keeps the gap
   that a first band would have above its rule, here above the footer's rule. */
.page-head { margin-top: clamp(32px, 4vw, 64px); }
main > .page-head:last-child { margin-bottom: var(--sec); }
.page-head .grid { row-gap: 0; }
.page-head .lede { margin-top: clamp(14px, 1.5vw, 22px); max-width: 36em; }
.page-head .lede a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.page-head .lede a:hover { text-decoration-color: var(--red); }
@media (min-width: 900px) {
  .page-head .title { grid-column: 1 / span 10; }
  .page-head .lede { grid-column: 4 / span 8; }
}
@media (min-width: 1200px) {
  .page-head .lede { grid-column: 3 / span 8; }
}

/* Prose (Markdown pages and notes). Its first and last blocks keep no outer margin, so the text
   sits in its band like any other content (the notes end with their footnotes). */
.prose { max-width: 40rem; }
.prose p, .prose ul, .prose ol, .prose blockquote, .prose figure, .prose table, .prose pre { margin: 0 0 1.1em; }
.prose > :first-child { margin-top: 0; }
.prose > :last-child, .prose > :last-child > :last-child, .prose > :last-child > :last-child > :last-child { margin-bottom: 0; }
.prose h2 { font-size: var(--fs-key); line-height: var(--lh-l); letter-spacing: var(--ls-l); margin: 1.9em 0 0.55em; }
.prose h3 { font-size: var(--fs-m); line-height: var(--lh-head); margin: 1.7em 0 0.4em; }
.prose img { margin: 0 auto; }
.prose figcaption { font-size: var(--fs-s); line-height: var(--lh-s); letter-spacing: var(--ls-s); color: var(--ink-2); margin-top: 0.6em; }
.prose blockquote { color: var(--ink-2); }
.prose code, .prose pre { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.88em; letter-spacing: 0; }
.prose pre { overflow-x: auto; }
.prose iframe { display: block; width: 100%; border: 0; }
.prose .footnotes { font-size: var(--fs-s); line-height: var(--lh-s); color: var(--ink-2); }
.prose .footnotes p { margin: 0; }
.prose .footnotes li + li { margin-top: var(--sp-2); }
.katex-display { overflow-x: auto; overflow-y: hidden; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.001ms !important; animation-duration: 0.001ms !important; }
}
@media print {
  .site-head nav, .menu-btn { display: none !important; }
  a { text-decoration: none; }
}

/* Header: the lab's name at the left (the leader's name, so a visitor sees at once whose group
   this is; the Chinese name under it in grey), the tabs at the right, Home first, so the way back
   to the first page is a tab like the others and not only the name. No lines.
   Both at the text size (--fs-m): the name in semibold, the tabs regular and grey, the current
   tab in ink with a thin line under it. The tabs stay on one line from 900px (seven tabs fit
   with 18px between them at 900px, the gap growing to 34px). Below 900px a "Menu" button opens
   them as a list, one key line per tab, the current one marked by the same thin line. */
.site-head { padding-top: clamp(16px, 2vw, 28px); }
.site-head .grid { align-items: start; }
.brand { grid-column: 1 / span 6; font-size: var(--fs-m); font-weight: 600; line-height: 1.25; letter-spacing: var(--ls-m); }
.brand-zh { display: block; font-weight: 400; color: var(--ink-2); letter-spacing: 0.02em; }
.brand:hover .brand-zh { color: inherit; }
.nav { display: flex; flex-wrap: wrap; gap: 6px clamp(18px, 2vw, 34px); font-size: var(--fs-m); line-height: 1.25; font-weight: 400; }
.nav a { color: var(--ink-2); }
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); }
.nav a[aria-current="page"]::after { content: ""; display: block; height: 1px; background: var(--ink); margin-top: 4px; }
.menu-btn { display: none; font-size: var(--fs-m); line-height: 1.25; font-weight: 400; justify-self: end; }

@media (min-width: 900px) {
  .brand { grid-column: 1 / span 4; }
  .nav { grid-column: 5 / -1; justify-content: flex-end; flex-wrap: nowrap; }
}
@media (max-width: 899px) {
  .brand { grid-column: 1 / span 9; }
  .menu-btn { display: block; grid-column: 10 / -1; grid-row: 1; }
  .nav { display: none; flex-direction: column; align-items: flex-start; gap: var(--sp-3); padding: 28px 0 8px; font-size: var(--fs-key); font-weight: 600; line-height: var(--lh-l); letter-spacing: var(--ls-l); }   /* the open menu: one key line per tab */
  .nav a { color: var(--ink); }
  .nav a[aria-current="page"]::after { margin-bottom: -5px; }   /* the line takes no room: the tabs stay evenly spaced */
  .site-head.is-open .nav { display: flex; }
  html:not(.js) .nav { display: flex; }
  html:not(.js) .menu-btn { display: none; }
}

/* Footer: the last band (one rule, three short facts; under the email address, the small links
   of _data/navigation.yml `footer`: News, the notes feed). It follows the last band of the page
   directly, so the space above its rule is that band's own (--band); its own content has --band
   above and below, the end of the page being its next rule. */
.site-foot.sec { margin-top: 0; }
.site-foot .grid { row-gap: var(--sp-2); }
@media (min-width: 900px) {
  .f-name { grid-column: 1 / span 3; }
  .f-addr { grid-column: 4 / span 5; }
  .f-mail { grid-column: 10 / -1; }
}

/* Live figures sit directly on the white page: no frame, no caption. */
.vibe { margin: 0; }
.vibe-stage { position: relative; width: 100%; aspect-ratio: 16 / 9; }
.vibe-hero .vibe-stage { aspect-ratio: 4 / 3; }
.vibe-card .vibe-stage { aspect-ratio: 4 / 3; }
@media (min-width: 700px) {
  .vibe-hero .vibe-stage { aspect-ratio: 2.35 / 1; }
}
.vibe-page .vibe-stage { aspect-ratio: 4 / 3; }
@media (min-width: 700px) {
  .vibe-page .vibe-stage { aspect-ratio: 16 / 9; }
}
/* In a pop-up (a paper's "Interact", assets/js/modules/popfig.js; the panel is parts/dialog.css,
   1200px wide at most). Wide screens: the figure at its page shape (4:3) at the left, two thirds
   of the panel, never taller than the panel's space; at the right the paper as its entry shows
   it: the title (.h2), 4px to the grey venue line (.meta), 8px to the summary. Below 900px:
   title, venue line, the figure, the summary, 16px apart. */
.popfig { --pop-w: 1200px; display: grid; grid-template-columns: minmax(0, 1fr); grid-template-areas: "t" "v" "f" "s"; align-items: start; }
.popfig > .h2 { grid-area: t; max-width: 24em; }
.popfig > .popfig-venue { grid-area: v; margin-top: var(--sp-1); }
.popfig > .vibe { grid-area: f; margin-top: var(--sp-3); }
.popfig > .popfig-sum { grid-area: s; margin-top: var(--sp-3); max-width: var(--measure-long); }
.vibe-pop .vibe-stage { aspect-ratio: 4 / 3; width: min(100%, calc((100vh - 2 * var(--pop-gap, 12px) - var(--pop-bar, 44px) - var(--pop-pad, 20px)) * 4 / 3)); width: min(100%, calc((100dvh - 2 * var(--pop-gap, 12px) - var(--pop-bar, 44px) - var(--pop-pad, 20px)) * 4 / 3)); }
@media (min-width: 900px) {
  .popfig { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); grid-template-rows: auto auto 1fr; grid-template-areas: "f t" "f v" "f s"; column-gap: var(--g); }
  .popfig > .vibe { margin-top: 0; }
  .popfig > .popfig-sum { margin-top: var(--sp-2); }
}

/* One paper (parts/pub.html), scoped to the part's own class .pub so any list of papers can use
   it; the list around it (gaps, years, filter) belongs to the module. The picture at the left; at
   the right the title, authors, venue, the full summary (at most about 80 characters a line), a
   line of plain-text links and, when opened, the BibTeX in monospace (no box). On phones the
   picture sits beside the title and the summary runs the full width.
   Type from the roles: the title is the key (.h3); authors and venue one grey block (.meta), in
   which only the group's names and the journal are in ink, the journal semibold (.jnl); the
   summary is text; the links a grey row (.meta) that turns red on hover.
   Space: 4px from the title to the grey block, 8px to the summary, 8px to the links. */
.pub {
  display: grid;
  grid-template-columns: clamp(170px, 15vw, 220px) minmax(0, 1fr);
  grid-template-rows: auto auto auto auto auto 1fr;
  grid-template-areas: "img title" "img authors" "img venue" "img summary" "img links" "img bib";
  column-gap: clamp(18px, 1.7vw, 26px);
  align-items: start;
}
.pub .pub-img { grid-area: img; display: block; }
.pub .pub-img img { width: 100%; aspect-ratio: 4 / 3; object-fit: contain; background: #fff; }
.pub .pub-title { grid-area: title; max-width: var(--measure); }
.pub .pub-authors { grid-area: authors; margin-top: var(--sp-1); }
.pub .pub-venue { grid-area: venue; text-wrap: balance; }   /* phones: "13, e75 · 2025 · Review" stays one line, no "·" left at a line end */
.pub .pub-authors .me { color: var(--ink); }
.pub .pub-authors > span, .pub .pub-venue i { white-space: nowrap; }   /* never "S." | "Pigolotti" */
.pub .pub-summary { grid-area: summary; max-width: var(--measure); margin-top: var(--sp-2); }
.pub .pub-links { grid-area: links; list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }
.pub .pub-links button { color: inherit; }
.pub .pub-links a:hover, .pub .pub-links button:hover { color: var(--red); }
.pub .pub-links [aria-expanded="true"] { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.32em; }
html:not(.js) .pub .pub-bibtex { display: none; }
.pub .pub-bib { grid-area: bib; margin-top: var(--sp-2); }
.pub .pub-bib pre { margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.8125rem; line-height: 1.5; letter-spacing: 0; color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere; }
.pub .pub-bib button { margin-top: var(--sp-1); font-size: var(--fs-s); line-height: var(--lh-s); }
.pub .pub-bib button:hover { color: var(--red); }

@media (max-width: 699px) {
  .pub {
    grid-template-columns: 112px minmax(0, 1fr);
    grid-template-rows: auto auto 1fr auto auto auto;
    grid-template-areas: "img title" "img authors" "img venue" "summary summary" "links links" "bib bib";
    column-gap: var(--sp-3);
  }
  .pub:not(.has-img) { grid-template-areas: "title title" "authors authors" "venue venue" "summary summary" "links links" "bib bib"; }
  .pub .pub-summary { margin-top: var(--sp-3); }   /* under the picture */
}

/* very narrow phones: the reference and year may wrap rather than push the page sideways */
@media (max-width: 359px) { .pub .pub-venue .nw { white-space: normal; } }

/* One card of the Members band (parts/person.html), the same for everyone, and its pop-up. Sized
   by the grid it sits in; on wide screens the cards of a row share their lines
   (modules/people.css).
   The card: the photo, the name (an entry title, .h3: its Latin part kept whole on the first
   line, the Chinese name moving whole to the next), the role (.meta) and the line (text). The
   name is the card's button, and the whole card answers to it: a pointer over any of it turns
   the name and the line red and draws the photo a little closer, as a poster on /seminars/ does;
   the keyboard's focus ring goes round the whole card. */
.person { position: relative; }
.person .person-img { aspect-ratio: 1 / 1; overflow: hidden; }
.person .person-img img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1); }
/* without a photo: a soft warm glow that fades into the page, like a portrait out of focus; no
   edge, never grey. A pointer over the card warms it a little, as if a light came on. */
.person .person-img.no-photo, .person-pop .pp-img.no-photo { position: relative; background: radial-gradient(closest-side at 50% 46%, #f0dacb 0%, #f6e9e1 42%, #fff 100%); }
.person .person-img.no-photo::after { content: ""; position: absolute; inset: 0; background: radial-gradient(closest-side at 50% 46%, #ebcab4 0%, #f3e0d3 48%, rgba(255, 255, 255, 0) 100%); opacity: 0; transition: opacity 0.8s ease; }
.person .person-name { margin-top: var(--sp-3); }
.person .person-open { text-align: inherit; }
.person .person-open::after { content: ""; position: absolute; inset: 0; }   /* the whole card */
.person .person-open:focus-visible { outline: none; }
.person .person-open:focus-visible::after { outline: 2px solid var(--red); outline-offset: 3px; }
.person .person-role { margin-top: var(--sp-1); }
.person .person-line { margin-top: var(--sp-2); }
.person:hover .person-open, .person:hover .person-line { color: var(--red); }
.person:hover .person-img img { transform: scale(1.03); }
.person:hover .person-img.no-photo::after { opacity: 1; }

/* The pop-up (in the site's panel, parts/dialog.css), 760px wide: a short profile, or an open
   position.
   A profile, from 600px: the photo (176px) at the left, its top on the capitals of the name
   beside it; at the right the name (.h2), 4px to the role and "since" (.meta), 8px to the line,
   8px to the links (a grey row). Under them, 32px apart, the profile's parts: each heading
   (.label) in the photo's column, its text beside it, the capitals of both on one line, as in a
   band of the page. Phones: a 96px photo beside the name, and each heading above its text (8px).
   An open position: the glow where a photo would be, and beside it the title (.h2) and when
   (.meta); then the summary, "We look for …" (grey, the lead-in semibold ink, as on /join/), how
   to apply and the link to /join/, 16px apart, beside the glow from 600px and under it (16px) on
   a phone. */
.person-pop { --pop-w: 760px; display: grid; grid-template-columns: 96px minmax(0, 1fr); column-gap: var(--sp-3); align-items: start; }
.person-pop .pp-img { grid-column: 1; aspect-ratio: 1 / 1; overflow: hidden; margin-top: var(--cap-l); }
.person-pop .pp-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
.person-pop .pp-id { grid-column: 2; min-width: 0; max-width: var(--measure); }
.person-pop .pp-role { margin-top: var(--sp-1); }
.person-pop .pp-role:empty { display: none; }   /* a `when` that has expired leaves nothing */
.person-pop .pp-id > .pp-text { margin-top: var(--sp-2); }
.person-pop .pp-links { margin-top: var(--sp-2); display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }
.person-pop .pp-label { grid-column: 1 / -1; margin-top: var(--sp-5); }
.person-pop .pp-label + * { grid-column: 1 / -1; margin-top: var(--sp-2); max-width: var(--measure); }
/* education: years | degree, place (.small); the years and places grey, the degree ink. The
   years' column is as wide as the widest years (subgrid; a fixed width before that), as in the
   group leader's positions (modules/people.css) */
.person-pop .pp-edu { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--sp-2) var(--sp-3); }
.person-pop .pp-edu li { grid-column: 1 / -1; display: grid; grid-template-columns: 6.5em minmax(0, 1fr); grid-template-columns: subgrid; column-gap: var(--sp-3); }
.person-pop .pp-years { color: var(--ink-2); white-space: nowrap; }
.person-pop .pp-what { color: var(--ink-2); }
.person-pop .pp-degree { color: var(--ink); }
.person-pop .pp-bio p:last-child { margin-bottom: 0; }
/* an open position: its text under the glow and the title on a phone, beside the glow from 600px */
.person-pop .pp-body { grid-column: 1 / -1; margin-top: var(--sp-3); max-width: var(--measure); }
.person-pop .pp-body > p + p { margin-top: var(--sp-3); }
.person-pop .pp-who { color: var(--ink-2); }
.person-pop .pp-who span { color: var(--ink); font-weight: 600; }
@media (min-width: 600px) {
  .person-pop { grid-template-columns: 176px minmax(0, 1fr); column-gap: var(--g); }
  .person-pop .pp-label { grid-column: 1; }
  .person-pop .pp-label + * { grid-column: 2; margin-top: var(--sp-5); }
  .person-pop.is-invite .pp-img { grid-row: 1 / span 2; }
  .person-pop .pp-body { grid-column: 2; }
}

/* The pop-up panel (assets/js/lib/dialog.js; opened by assets/js/modules/popup.js for any
   <template>, and by popfig.js for a paper's live figure).
   A white panel in the middle of the window, floating over the page. The page stays in view
   behind it under a light veil (white at 86%; where the browser can, white at 74% over a soft
   blur of the page), so the visitor knows where they are, and nothing behind competes with the
   panel; a click on the veil closes it. The panel reads against the veil by a hairline edge and a
   very soft, wide shadow (the one shadow on the site); square corners, as everywhere.
   At its top, a row of its own (44px, a finger's target) with "Close" at the right, at the text
   size, ink, red on hover; the row stays while the content scrolls under it.
   Width: what the content asks for with --pop-w on its outer element (720px when it says
   nothing, for text: 40em lines; a member 760px; a talk with its poster 1080px; a live figure
   with its paper 1200px), but never wider than the window less --pop-gap at each side (20px on a
   phone, up to 40px).
   Height: the content's, at most the window less --pop-gap above and below; longer content
   scrolls inside the panel, never the page behind it.
   Space inside: --pop-pad at the sides and the bottom (20px on a phone, up to 40px), and the
   Close row at the top (44px), so the content sits evenly in the panel.
   Motion (classes set by dialog.js): the panel emerges, it does not jump. Opening, the veil
   fades in (0.36s) while the panel fades in, rising 12px and growing from 98% (0.32s, a soft
   ease-out); with a live figure inside, it only rises, since a figure measures its own size as it
   starts. Closing is quicker and quieter: the panel fades, sinking 6px (0.18s), and the veil
   lifts (0.2s); only then is the panel closed. Content that replaces other content in an open
   panel fades in (0.24s). Under reduced motion, a plain fade (0.2s in, 0.15s out). */
.dlg {
  --pop-gap: clamp(20px, 5vw, 40px);     /* window edge → panel (20px on a phone: room to tap outside) */
  --pop-pad: clamp(20px, 2.8vw, 40px);   /* panel edge → content, at the sides and the bottom */
  --pop-bar: 44px;                        /* the Close row at the top */
  --pop-in: cubic-bezier(0.16, 1, 0.3, 1);     /* a long, soft ease-out */
  --pop-out: cubic-bezier(0.4, 0, 1, 1);       /* an ease-in */
  position: fixed;
  inset: 0;
  box-sizing: border-box;
  width: fit-content;
  height: fit-content;
  max-width: calc(100% - 2 * var(--pop-gap));
  max-height: calc(100% - 2 * var(--pop-gap));
  margin: auto;
  padding: 0 var(--pop-pad) var(--pop-pad);
  border: 0;
  border-radius: 0;
  background: var(--bg);
  color: var(--ink);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* a hairline edge (ink at 7%), then a close, faint shadow and a wide, soft one */
  box-shadow: 0 0 0 1px rgba(17, 17, 17, 0.07), 0 2px 6px rgba(17, 17, 17, 0.04), 0 24px 72px -12px rgba(17, 17, 17, 0.16);
  /* closed, and the moment before it opens */
  opacity: 0;
  transform: translateY(12px) scale(0.98);
}
.dlg:not([open]) { display: none; }                      /* also where <dialog> is unknown */
.dlg.is-in { opacity: 1; transform: none; transition: opacity 0.32s var(--pop-in), transform 0.32s var(--pop-in); }
.dlg.is-out { opacity: 0; transform: translateY(6px) scale(0.99); transition: opacity 0.18s var(--pop-out), transform 0.18s var(--pop-out); }
.dlg.is-fig { transform: translateY(12px); }              /* a live figure inside: no scale */
.dlg.is-fig.is-in { transform: none; }
.dlg.is-fig.is-out { transform: translateY(6px); }

/* the veil: the page behind, lightened (and softly blurred where the browser can) */
.dlg::backdrop { background: rgba(255, 255, 255, 0.86); opacity: 0; }
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .dlg::backdrop { background: rgba(255, 255, 255, 0.74); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); }
}
.dlg.is-in::backdrop { opacity: 1; transition: opacity 0.36s ease-out; }
.dlg.is-out::backdrop { opacity: 0; transition: opacity 0.2s cubic-bezier(0.4, 0, 1, 1); }   /* written out: older browsers give ::backdrop no custom properties */

.dlg:focus, .dlg:focus-visible { outline: none; }        /* the panel itself takes the focus, to scroll */
.dlg-bar { position: sticky; top: 0; z-index: 1; display: flex; justify-content: flex-end; height: var(--pop-bar); background: var(--bg); }
.dlg-close { margin-right: -12px; padding: 0 12px; font-size: var(--fs-m); line-height: var(--lh-head); color: var(--ink); }
.dlg-close:hover { color: var(--red); }
/* the content makes the panel as wide as it asks (--pop-w: the panel's width, padding included),
   never wider than the window allows */
.dlg-body > * { width: calc(var(--pop-w, 720px) - 2 * var(--pop-pad)); max-width: 100%; }
/* new content in a panel that is already open */
.dlg-body.is-new > * { animation: dlg-new 0.24s ease-out; }
@keyframes dlg-new { from { opacity: 0; } }

/* reduced motion: nothing moves, the panel and the veil only fade (foundation.css cuts every
   other transition to nothing) */
@media (prefers-reduced-motion: reduce) {
  .dlg, .dlg.is-in, .dlg.is-out, .dlg.is-fig, .dlg.is-fig.is-in, .dlg.is-fig.is-out { transform: none; }
  .dlg.is-in { transition: opacity 0.2s ease-out !important; }
  .dlg.is-out { transition: opacity 0.15s ease-in !important; }
  .dlg.is-in::backdrop { transition: opacity 0.2s ease-out; }
  .dlg.is-out::backdrop { transition: opacity 0.15s ease-in; }
}

/* Home, first screen: the words at the left (7 of 12 columns), the live cycle at the right (5).
   A laptop's first screen shows the header, the hero and the whole Research band under it
   (lines.css): measured at 1280×720, 1440×790, 1512×860 and 1920×950; at 1366×650 down to the
   titles of the research lines. Three rules make the room:
   - the figure is exactly as tall as the words beside it: the words alone set the height of the
     row and the figure's stage fills it (the cycle centres itself in any shape), so the figure
     never makes the hero taller;
   - the headline is XXL, but never more than 8.4vh: on a screen under about 800px tall its two
     lines step down a little (1366×650: 55px instead of 63);
   - the band after the hero has its rule --band below the hero's last line: the hero counts as
     the first band, with the same space under its content as inside every band (not --sec).
   Below 900px the figure follows the words, small (150-180px tall) and flush left.
   Type: the headline (.display), the intro a lede (.lede), the facts a grey line (.meta) in which
   the leader's name is ink (a name of the group, as in an author list), and the recruiting line in
   semibold text with its red dot: the one thing on the page that is live. */
.m-hero { margin-top: clamp(20px, 2.2vw, 36px); }
.m-hero .grid { row-gap: var(--sp-4); }
.m-hero .hero-line { font-size: clamp(36px, min(4.6vw, 8.4vh), 68px); }
.m-hero .hero-intro { margin-top: clamp(18px, 1.8vw, 28px); max-width: 32em; }
.m-hero .hero-facts { margin-top: clamp(16px, 1.6vw, 24px); }   /* .meta */
.m-hero .hero-facts > span { white-space: nowrap; }
.m-hero .hero-facts > span + span::before { content: "· "; }
.m-hero .hero-pi a { color: var(--ink); }
.m-hero .hero-pi a:hover { color: var(--red); }
/* The facts take one line where the column holds it (600px; the line is about 530); in a narrower
   column (screens 900-1050px wide) "Led by …" takes a line of its own, and in a phone's column
   (under 420px) every part does. A part that starts a line drops its "·", so no line starts with
   one. The widths leave room for a longer place; check them if the facts grow. */
.m-hero .hero-text { container-type: inline-size; }
@container (max-width: 599px) {
  .m-hero .hero-pi { display: block; }
  .m-hero .hero-facts > .hero-pi + span::before { content: none; }
}
@container (max-width: 419px) {
  .m-hero .hero-facts > span { display: block; }
  .m-hero .hero-facts > span + span::before { content: none; }
}
@supports not (container-type: inline-size) {   /* browsers before 2023 (some in-app ones): phones by the screen */
  @media (max-width: 599px) {
    .m-hero .hero-facts > span { display: block; }
    .m-hero .hero-facts > span + span::before { content: none; }
  }
}
.m-hero .hero-join { margin-top: var(--sp-2); font-weight: 600; }
.m-hero .hero-join a { display: inline-flex; align-items: baseline; gap: var(--sp-2); }
.m-hero .hero-join .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red); flex: none; transform: translateY(-1px); }
/* The figure. Below 900px: under the words, flush left, 150-180px tall and 7:5, the widest shape
   in which the cycle still sits in the middle of its stage (wider, it drifts right: cycle.js
   SHAPE.heroWide), so the middle of the stage, where the drive is zero, is the middle of the
   cycle. From 900px: the height of the words. */
.m-hero .vibe-hero .vibe-stage { --h: clamp(150px, 40vw, 180px); aspect-ratio: auto; height: var(--h); width: min(100%, 1.4 * var(--h)); }
@media (min-width: 900px) {
  .m-hero .hero-text { grid-column: 1 / span 7; }
  .m-hero .hero-fig { grid-column: 8 / -1; position: relative; min-height: 240px; }
  .m-hero .hero-fig .vibe { position: absolute; inset: 0; }
  .m-hero .vibe-hero .vibe-stage { width: 100%; height: 100%; }
}
.m-hero + .sec { margin-top: var(--band); }

/* Home: the research lines side by side, one column each (on a phone: one below the other, a small
   figure beside the title and question). Type from the roles: the line's title an entry title
   (.h3), its guiding question text.
   From 700px each figure is a wide strip over its title, 5:2, so the whole band fits in a laptop's
   first screen under the hero (hero.css); on a screen at most 820px tall (from 1200px wide: most
   laptops) the strip is 3:1. The figures draw themselves for any shape and keep their own margin,
   so the title follows the strip at 8px. */
.m-lines .ln { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5) var(--g); }
.m-lines .ln-card { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); column-gap: var(--sp-3); align-content: start; }
.m-lines .ln-card .vibe { grid-row: 1 / span 2; align-self: start; }
.m-lines .ln-title, .m-lines .ln-q { grid-column: 2; }
.m-lines .ln-card:hover { color: inherit; }
.m-lines .ln-card:hover .ln-title { color: var(--red); }
.m-lines .ln-q { margin-top: var(--sp-1); }
@media (min-width: 700px) {
  /* one column per line: three lines fill the row (also at 900-940px, where the label column
     narrows the body to ~610px); a fourth would make four narrower columns */
  .m-lines .ln { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
  .m-lines .ln-card { display: block; }
  .m-lines .vibe-card .vibe-stage { aspect-ratio: 5 / 2; }
  .m-lines .ln-title { margin-top: var(--sp-2); }
}
@media (min-width: 1200px) and (max-height: 820px) {
  .m-lines .vibe-card .vibe-stage { aspect-ratio: 3 / 1; }
}

/* Home: the selected papers, a small picture and three lines each. One column below 900px; two
   columns from 900px, with a small picture (96px) until 1200px and 176px from there.
   Type as a paper on /publications/ (parts/pub.css): the title an entry title (.h3); authors and
   venue one grey block (.meta), in which the group's names and the journal are in ink, the
   journal semibold (.jnl), so the published papers stand out from the preprints. */
.m-selected .rp { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4) var(--g); }
.m-selected .rp-item { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 0 var(--sp-3); align-items: start; }
.m-selected .rp-img { display: block; }
.m-selected .rp-img img { width: 100%; aspect-ratio: 4 / 3; object-fit: contain; }
.m-selected .rp-text { grid-column: 2; }
.m-selected .rp-authors { margin-top: var(--sp-1); }
.m-selected .rp-authors .me { color: var(--ink); }
.m-selected .rp-authors > span { white-space: nowrap; }   /* a name never breaks: not "D. M." | "Busiello" */
/* a word joiner keeps ✉ with its name: the mark never starts a line on its own (no margin here,
   since an edge with a margin lets the line break there anyway) */
.m-selected .rp-authors .mk::before { content: "\2060"; }
.m-selected .rp-all { margin-top: var(--sp-4); }
@media (min-width: 700px) {
  .m-selected .rp-item { grid-template-columns: 176px minmax(0, 1fr); column-gap: var(--sp-4); }
}
@media (min-width: 900px) {
  .m-selected .rp { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .m-selected .rp-item { grid-template-columns: 96px minmax(0, 1fr); column-gap: var(--sp-3); }
}
@media (min-width: 1200px) {
  .m-selected .rp-item { grid-template-columns: 176px minmax(0, 1fr); column-gap: var(--sp-4); }
}

/* Home, last section: the news at the left; the seminar, open positions and the group leader in a
   narrower column at the right (from 1200px; below the news, two across, on smaller screens).
   "Seminar", "Join" and "Group leader" are labels inside the section (.label), set like the
   section's own label "News", since they head blocks of the same rank.
   News text: a paper's title (a link holding the title in italics) is set as a title, upright and
   semibold, so each item opens on its key point; other links are underlined; a journal stays in
   italics. Dates are grey (.meta), in tabular figures, on the baseline of the item's first line.
   The poster and the portrait start on the capitals of the title beside them (--cap-m); the
   portrait, which ends the section, stops --cap-l above its bottom, where a last baseline would,
   so the section has the same space under it as over its first line. */
.m-more .hm-news, .m-more .hm-side { min-width: 0; }
.m-more .hm-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.m-more .hm-list li { display: grid; grid-template-columns: 5.4em minmax(0, 1fr); column-gap: var(--sp-3); align-items: baseline; }
.m-more .hm-list time { white-space: nowrap; }
@media (max-width: 699px) {   /* phones: the month above the text, as on /news/ */
  .m-more .hm-list li { grid-template-columns: minmax(0, 1fr); row-gap: 1px; }
}
.m-more .hm-list p { max-width: var(--measure); }
.m-more .hm-list a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.m-more .hm-list a:hover { text-decoration-color: var(--red); }
.m-more .hm-list a:has(> em) { text-decoration: none; }
.m-more .hm-list a > em { font-style: normal; font-weight: 600; }
.m-more .hm-go { margin-top: var(--sp-3); }

.m-more .hm-side { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5) var(--g); align-content: start; margin-top: var(--sp-5); }
.m-more .hm-label { margin-bottom: var(--sp-2); }
.m-more .hm-next { margin: calc(-1 * var(--sp-1)) 0 var(--sp-2); color: var(--red); }   /* a second label line, red: live */
.m-more .hm-talk, .m-more .hm-pi-row { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--sp-3); align-items: start; }
.m-more .hm-talk.has-img, .m-more .hm-pi-row.has-img { grid-template-columns: 96px minmax(0, 1fr); }
.m-more .hm-poster, .m-more .hm-pi-img { display: block; margin-top: var(--cap-m); }
.m-more .hm-pi-img { margin-bottom: var(--cap-l); }
.m-more .hm-poster img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; object-position: top; }
.m-more .hm-pi-img img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.m-more .hm-who { margin-top: var(--sp-1); }
.m-more .hm-name + .hm-meta { margin-top: var(--sp-1); }
.m-more .hm-open { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.m-more .hm-open span { color: var(--ink-2); }

@media (min-width: 700px) {
  .m-more .hm-side { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 900px) {
  .m-more .hm-news, .m-more .hm-side { grid-column: 4 / -1; }
}
@media (min-width: 1200px) {
  .m-more .hm-news { grid-column: 4 / span 5; grid-row: 1; }
  .m-more .hm-side { grid-column: 9 / -1; grid-row: 1; grid-template-columns: minmax(0, 1fr); margin-top: 0; }
}
@media (min-width: 1200px) {
  .m-more .hm-news { grid-column: 3 / span 6; }
}
/* a talk in English says so after its title, small and grey, as on /seminars/ */
.m-more .hm-lang { font-size: var(--fs-s); font-weight: 400; letter-spacing: var(--ls-s); color: var(--ink-2); white-space: nowrap; }

/* /news/: one band per year, labelled with the year (whose capitals meet those of the first item
   without an offset, foundation.css); in each, a month at the left (.meta, on the baseline of the
   item's first line) and one or two sentences of text at the right (at most about 80 characters a
   line). As on the home page, a paper's title opens its item upright and semibold; other links are
   underlined; journals stay in italics. */
.m-news .news-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.m-news .news-list li { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; }
.m-news .news-list p { max-width: var(--measure); }
@media (min-width: 700px) {
  .m-news .news-list li { grid-template-columns: 6.5em minmax(0, 1fr); column-gap: var(--g); align-items: baseline; }
  .m-news .news-list p { grid-column: 2; }
}
.m-news .news-list a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.m-news .news-list a:hover { text-decoration-color: var(--red); }
.m-news .news-list a:has(> em) { text-decoration: none; }
.m-news .news-list a > em { font-style: normal; font-weight: 600; }

/* /research/ (modules/research.html). Every rule is scoped to .m-research.
   A line reads: the guiding question (the line's key sentence, .h2), its idea in a short
   paragraph, its selected papers, a link to all its papers; the live figure beside it from 900px,
   and above it below 900px, as a 2:1 strip, so that the band ends with text. The text takes most
   of the width (7 of the body's 10 columns, 6 of 9 below 1200px) and the figure the rest (3
   columns): the figure gives a feeling and needs little room, while a wide text keeps the band
   short instead of a narrow column beside empty space (the owner's call, 8 November 2026). The
   paragraph runs to about 90 characters a line at most. The label column holds the line's name
   (the band's label, foundation.css): at L like the question beside it, so their capitals and
   baselines meet without an offset.
   A selected paper: its title semibold, balanced (no word left alone on its last line), its venue
   a grey line (.meta) in which a journal is set in ink (.jnl) and a preprint stays grey. */

.m-research[id] { scroll-margin-top: 24px; }

/* label column: the line's name (an h2 inside the label, set as the label) */
.m-research .rl-name { font: inherit; letter-spacing: inherit; }

.m-research .rl-q { max-width: 30em; }   /* .h2 */
.m-research .rl-text { margin-top: var(--sp-3); max-width: 44em; }

.m-research .rl-sel { margin-top: var(--sp-5); }
.m-research .rl-papers { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: grid; gap: var(--sp-3); }
.m-research .rl-papers li { line-height: var(--lh-head); text-wrap: balance; }
.m-research .rl-p { font-weight: 600; }
.m-research .rl-v { display: block; margin-top: var(--sp-1); }   /* .meta */
.m-research .rl-all { margin-top: var(--sp-3); }

.m-research .rl-fig { margin-top: var(--sp-4); width: 100%; max-width: 520px; }
.m-research .rl-fig .vibe-stage { aspect-ratio: 4 / 3; }

@media (min-width: 900px) {
  .m-research .rl { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); column-gap: var(--g); align-items: start; }
  .m-research .rl-main { grid-column: 1 / span 6; }
  .m-research .rl-fig { grid-column: 7 / -1; margin-top: 2px; max-width: none; }
}
@media (min-width: 1200px) {
  .m-research .rl { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .m-research .rl-main { grid-column: 1 / span 7; }
  .m-research .rl-fig { grid-column: 8 / -1; }
}

/* directions (research.yml next): a title (.h3) and a sentence each, as the entries of other pages */
.m-research .rd-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4) var(--g); }
.m-research .rd-x { margin-top: var(--sp-1); max-width: var(--measure); }
@media (min-width: 900px) {
  .m-research .rd-list { grid-template-columns: repeat(9, minmax(0, 1fr)); }
  .m-research .rd:nth-child(odd) { grid-column: 1 / span 5; }
  .m-research .rd:nth-child(even) { grid-column: 6 / -1; }
}
@media (min-width: 1200px) {
  .m-research .rd-list { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .m-research .rd:nth-child(odd) { grid-column: 1 / span 6; }
  .m-research .rd:nth-child(even) { grid-column: 7 / -1; }
}

/* Phones: the figure comes first, as a wide strip under the line's name (as on the home cards),
   so the band ends with its text and its space below matches the space above. */
@media (max-width: 899px) {
  .m-research .rl { display: flex; flex-direction: column; }
  .m-research .rl-fig { order: -1; margin: 0 0 var(--sp-3); max-width: none; }
  .m-research .rl-fig .vibe-stage { aspect-ratio: 2 / 1; }
}

/* /publications/ (modules/pubs.html): the head (the profiles in one line, the key to the author
   marks, the filter), then one band per year, labelled with the year. No counts. Every rule is
   scoped to .m-pubs; one entry is parts/pub.html, styled by parts/pub.css. */

/* Head. Phones: title, lede, key, filter. */
.m-pubs .page-head .lede { max-width: none; font-size: var(--fs-s); line-height: 22px; letter-spacing: var(--ls-s); color: var(--ink-2); }
.m-pubs .page-head .lede a { color: var(--ink); }
.m-pubs .page-head .lede a:hover { color: var(--red); }
.m-pubs .pubs-key { margin-top: var(--sp-2); }
.m-pubs .pubs-key > span { white-space: nowrap; }
.m-pubs .pubs-key > span:not(:last-child)::after { content: " ·"; }
.m-pubs .pubs-key .mk-c { margin-left: 0; }   /* the key's ✉ opens its line */

/* Filter: plain-text toggles; the current one in ink and underlined, the others grey. */
.m-pubs .pubs-filter { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); margin-top: var(--sp-3); font-size: var(--fs-s); line-height: 22px; letter-spacing: var(--ls-s); }
.m-pubs .pubs-filter button { color: var(--ink-2); text-align: left; }
.m-pubs .pubs-filter [aria-pressed="true"] { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.36em; }
.m-pubs .pubs-filter button:hover { color: var(--red); }
html:not(.js) .m-pubs .pubs-filter { display: none; }

/* From 900px the key stands in the label column, its lines beside the profiles line and the
   filter, on one pitch (22px). */
@media (min-width: 900px) {
  .m-pubs .page-head .lede { grid-column: 4 / -1; grid-row: 2; margin-top: var(--sp-3); }
  .m-pubs .pubs-filter { grid-row: 3; margin-top: 0; row-gap: 0; }
  .m-pubs .pubs-key { grid-column: 1 / span 3; grid-row: 2 / span 2; align-self: start; margin-top: var(--sp-3); line-height: 22px; }
  .m-pubs .pubs-key > span { display: block; white-space: normal; }
  .m-pubs .pubs-key > span:not(:last-child)::after { content: none; }
}
@media (min-width: 1200px) {
  .m-pubs .page-head .lede { grid-column: 3 / -1; }
  .m-pubs .pubs-key { grid-column: 1 / span 2; }
}

/* Years: bands like any other, one after the other. The filter belongs to the list it filters, so
   the first band shown (whichever the filter leaves) follows the head closely, 16px under it,
   rather than a page title's --sec: the space is the head's own, not a year's. */
.m-pubs .page-head { padding-bottom: var(--sp-3); }
.m-pubs .pubs-year { margin-top: 0; }
.m-pubs .pubs-list { display: grid; row-gap: var(--sp-4); }

/* A year's last paper: its picture (white margin included) may be taller than its text; letting
   the picture run 16px into the band's padding keeps the space under the last line equal to the
   space above the first. */
@media (min-width: 700px) {
  .m-pubs .pubs-list > .pub:last-child .pub-img { margin-bottom: calc(-1 * var(--sp-3)); }
}

/* People page (modules/people.html). Members' and invitations' cards, and their pop-ups:
   parts/person.css.
   Type from the roles: the leader's name a key sentence (.h2), his position grey text, the bio
   text (at most about 70 characters a line), the positions list and the links small (.small);
   alumni: the name in text, the rest grey. */

/* Group leader. Wide screens: portrait | name, position, bio | positions and links. Tablets:
   portrait | name, position, bio, with the positions and links below. Phones: a small portrait
   beside the name, the rest below.
   The portrait keeps the photo's own shape (4:5, never cropped to fit the text) at a moderate
   size, about 230px wide on a laptop: present, in proportion with the text, not dominant (the
   owner's choice after trying 270px, 190px and a crop to the text's height). */
.m-pi .pi { display: grid; column-gap: var(--g); align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  grid-template-areas: "img id" "bio bio" "side side"; }
/* the portrait's top edge on the capitals of the label and of the name beside it (--cap-l) */
.m-pi .pi-photo { grid-area: img; margin-top: var(--cap-l); }
.m-pi .pi-img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 30%; }
.m-pi .pi-id { grid-area: id; }
.m-pi .pi-bio { grid-area: bio; margin-top: var(--sp-3); max-width: var(--measure-long); }
.m-pi .pi-bio p + p { margin-top: var(--sp-3); }
.m-pi .pi-side { grid-area: side; margin-top: var(--sp-4); }
@media (min-width: 600px) {
  .m-pi .pi { grid-template-columns: clamp(160px, 26%, 220px) minmax(0, 1fr);
    grid-template-areas: "img id" "img bio" "side side"; grid-template-rows: auto auto auto; }
}
@media (min-width: 1200px) {
  .m-pi .pi { grid-template-columns: clamp(200px, 16vw, 240px) minmax(0, 1.4fr) minmax(0, 1fr);
    grid-template-areas: "img id side" "img bio side" ". . side"; grid-template-rows: auto auto 1fr; }
  .m-pi .pi-side { margin-top: 0; }
}
.m-pi .pi-pos { margin-top: var(--sp-1); color: var(--ink-2); }
/* positions: the years column is as wide as its widest label (subgrid; a fixed width before that) */
.m-pi .pi-cv { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--sp-2) var(--sp-3); }   /* .small */
.m-pi .pi-cv li { grid-column: 1 / -1; display: grid; grid-template-columns: 6em minmax(0, 1fr); grid-template-columns: subgrid; column-gap: var(--sp-3); }
.m-pi .cv-years { white-space: nowrap; font-variant-numeric: tabular-nums; }
.m-pi .cv-years, .m-pi .cv-what { color: var(--ink-2); }
.m-pi .cv-role { color: var(--ink); }
.m-pi .pi-links { margin-top: var(--sp-3); display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); }   /* .small */

/* Members: two a row on phones, then as many 150px+ (tablets 170px+) columns as fit; on wide
   screens five a row, each exactly two columns of the page grid. */
.m-members .members { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5) var(--g); }
@media (min-width: 560px) { .m-members .members { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } }
@media (min-width: 900px) { .m-members .members { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); } }
@media (min-width: 1200px) { .m-members .members { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
/* the photos' top edge on the label's capitals (--cap-l), as the leader's portrait */
.m-members .person-img { margin-top: var(--cap-l); }
/* From 900px a row of cards shares its lines: names, roles and lines start at one height across
   the row, however a name wraps (each card spans four rows of the list's grid, as a subgrid). The
   space between rows of cards is then each card's top padding, cancelled above the first row;
   the card's button, which covers the card, leaves that padding out.
   Phones keep plain cards: two narrow columns would leave gaps under one-line names. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 900px) {
    .m-members .members { row-gap: 0; margin-top: calc(-1 * var(--sp-5)); }
    .m-members .person { display: grid; grid-row: span 4; grid-template-rows: subgrid; align-content: start; padding-top: var(--sp-5); }
    .m-members .person-open::after { top: var(--sp-5); }
    .m-members .person-img { grid-row: 1; }
    .m-members .person-name { grid-row: 2; }
    .m-members .person-role { grid-row: 3; }
    .m-members .person-line { grid-row: 4; }
  }
}

/* Alumni: one line each, the name in ink, the rest grey and small */
.m-alumni .alumni { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-1); }
.m-alumni .al-meta { font-size: var(--fs-s); letter-spacing: var(--ls-s); color: var(--ink-2); }
.m-alumni .num { white-space: nowrap; }


/* Seminar (/seminars/, modules/seminar.html): next talk, about, then the talks by year.
   Every rule is scoped to .m-seminar: the page's sections, and the <article> of a talk's pop-up.
   Type from the roles (in the HTML): a speaker semibold (.who; under a poster an entry title,
   .h3), a talk's title text (under a poster .small, balanced), dates and affiliations grey
   (.meta), dates in tabular figures; the next talk's and the pop-up's title a key sentence (.h2),
   its Chinese title grey under it. The Chinese about text is set for Chinese (--fs-zh, open
   leading, a hair of tracking). A talk in English says so in words right after its title,
   "· in English" (.sem-lang), small and grey, wherever the title is shown (poster cards, rows,
   the next talk, the pop-up); on phones, where a poster's title is hidden, under its date. */
.m-seminar .sem-lang { font-size: var(--fs-s); font-weight: 400; line-height: inherit; letter-spacing: var(--ls-s); color: var(--ink-2); white-space: nowrap; }
.m-seminar .sem-poster .sem-lang-when { display: none; }

/* label · value pairs (place, host, recording): .small */
.m-seminar .sem-kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--sp-1) var(--sp-3); margin: 0; }
.m-seminar .sem-kv dt { color: var(--ink-2); }
.m-seminar .sem-kv dd { margin: 0; }
.m-seminar .sem-kv a, .m-seminar .sem-refs a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.m-seminar .sem-kv a { white-space: nowrap; }
.m-seminar .sem-kv a:hover, .m-seminar .sem-refs a:hover { text-decoration-color: var(--red); }
.m-seminar .who { font-weight: 600; }
.m-seminar p.zh { color: var(--ink-2); }   /* a talk's title in Chinese, under the English one */

/* 1. next talk */
.m-seminar .sem-next { display: grid; gap: var(--sp-5); }
/* the poster takes one column of the poster grid below (3, 4 or 6 columns), the text the rest */
.m-seminar .sem-next-talk { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3) var(--g); align-items: start; }
.m-seminar .sem-next-talk.has-poster { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.m-seminar .sem-next-talk.has-poster .sem-next-text { grid-column: 2 / -1; }
@media (min-width: 700px) { .m-seminar .sem-next-talk.has-poster { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .m-seminar .sem-next-talk.has-poster { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.m-seminar .sem-next-img { display: block; width: 100%; }
.m-seminar .sem-next-img img { width: 100%; }
.m-seminar .sem-next-text { display: grid; gap: var(--sp-2); align-content: start; max-width: var(--measure); }
.m-seminar .sem-next-when { color: var(--red); }   /* .label: live */
.m-seminar .sem-more { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.m-seminar .sem-more:hover, .m-seminar .sem-next-img:hover + .sem-next-text .sem-more { color: var(--red); text-decoration-color: var(--red); }

/* 2. about: English (at most about 70 characters a line), and Chinese beside it */
.m-seminar .sem-about { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-3) var(--g); align-items: start; }
@media (min-width: 900px) { .m-seminar .sem-about { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); } }
.m-seminar .sem-about p + p { margin-top: var(--sp-3); }
.m-seminar .sem-en > p:not(.sem-links) { max-width: var(--measure-long); }
.m-seminar .sem-zh { font-size: var(--fs-zh); line-height: var(--lh-zh); letter-spacing: var(--ls-zh); color: var(--ink-2); max-width: 30em; }
/* the Chinese text's lines are taller: start its first line on the English first line's baseline */
@media (min-width: 900px) { .m-seminar .sem-zh { margin-top: calc((var(--lh-m) * 16px - var(--lh-zh) * var(--fs-zh)) / 2); } }
.m-seminar .sem-link, .m-seminar .sem-links a { white-space: nowrap; }   /* .sem-links: .small */

/* 3a. talks with a poster: the poster, then date, speaker and title */
.m-seminar .sem-posters { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-5) var(--g); }
@media (min-width: 700px) { .m-seminar .sem-posters { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .m-seminar .sem-posters { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
.m-seminar .sem-poster { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-1); width: 100%; text-align: left; }
.m-seminar .sem-img { display: block; aspect-ratio: 1; overflow: hidden; margin-bottom: calc(var(--sp-3) - var(--sp-1)); }
.m-seminar .sem-img img { width: 100%; height: 100%; object-fit: cover; object-position: top; transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1); }
.m-seminar .sem-poster:hover .sem-img img { transform: scale(1.03); }
.m-seminar .sem-poster .who { overflow-wrap: anywhere; }   /* .h3 */
.m-seminar .sem-poster .ttl { text-wrap: balance; }      /* .small */
.m-seminar .sem-poster:hover .who, .m-seminar .sem-poster:hover .ttl { color: var(--red); }
/* phones: three posters a row are too narrow for the title; it stays in the poster, the pop-up
   and the button's name for screen readers. "in English" shows under the date, without its "·" */
@media (max-width: 599px) {
  .m-seminar .sem-poster .who { font-size: var(--fs-s); letter-spacing: var(--ls-s); }
  .m-seminar .sem-poster .ttl { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .m-seminar .sem-poster .sem-lang-when { display: block; }
  .m-seminar .sem-poster .sem-lang-when .sem-dot { display: none; }
}

/* 3b. every other talk: one line (date, speaker, title, affiliation) on wide screens, rows of a
   table 8px apart; speaker and affiliation beside the title on tablets, stacked on phones: two to
   four lines a talk, so the items of a list, 16px apart */
.m-seminar .sem-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
@media (min-width: 1200px) { .m-seminar .sem-rows { gap: var(--sp-2); } }
.m-seminar .sem-posters + .sem-rows { margin-top: var(--sp-5); }
.m-seminar .sem-row { display: grid; grid-template-columns: 3.9em minmax(0, 1fr); grid-template-areas: "when who" ". ttl" ". aff"; column-gap: var(--sp-3); width: 100%; text-align: left; align-items: baseline; line-height: var(--lh-head); }
.m-seminar .sem-row .when { grid-area: when; }   /* .meta */
.m-seminar .sem-row .who { grid-area: who; }
.m-seminar .sem-row .ttl { grid-area: ttl; text-wrap: balance; }
.m-seminar .sem-row .aff { grid-area: aff; }     /* .meta */
.m-seminar .sem-row:hover .who, .m-seminar .sem-row:hover .ttl { color: var(--red); }
@media (min-width: 700px) {
  .m-seminar .sem-row { grid-template-columns: 3.9em minmax(0, 1.5fr) minmax(0, 3.5fr); grid-template-rows: auto 1fr; grid-template-areas: "when who ttl" ". aff ttl"; column-gap: var(--g); }
}
@media (min-width: 1200px) {
  .m-seminar .sem-row { grid-template-columns: 3.9em minmax(0, 1.25fr) minmax(0, 4.4fr) minmax(0, 2.9fr); grid-template-rows: auto; grid-template-areas: "when who ttl aff"; }
}

/* the pop-up: a talk's <template>, shown in the site's pop-up panel (parts/dialog.css) by
   modules/popup.js. 1080px wide: the poster at the left (two fifths), staying in view while the
   details scroll; the details at the right (three fifths, about 37em): the series number and date
   (.meta), 8px to the title (.h2), 4px to its Chinese title (grey), 16px to the speaker (semibold,
   the affiliation grey under it), 16px to place, host and recording (.small), 24px to the
   abstract and to a figure, 32px to each further block (References, Speaker: .label, 8px to what
   it labels). Below 800px the poster is on top, the details under it. A talk without a poster is
   the details alone, in a 720px panel. Until it has loaded, a poster keeps a 3:4 place, so the
   text under it does not jump, and shows its thumbnail (already loaded by the list) behind. */
.m-seminar.sem-talk { --pop-w: 1080px; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4) var(--g); align-items: start; }
@media (min-width: 800px) { .m-seminar.sem-talk { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); } }
.m-seminar.sem-talk.no-poster { --pop-w: 720px; grid-template-columns: minmax(0, 1fr); }
.m-seminar .sem-talk-poster { width: 100%; height: auto; aspect-ratio: auto 3 / 4; max-height: calc(100vh - 2 * var(--pop-gap, 12px) - var(--pop-bar, 44px) - var(--pop-pad, 20px)); max-height: calc(100dvh - 2 * var(--pop-gap, 12px) - var(--pop-bar, 44px) - var(--pop-pad, 20px)); object-fit: contain; object-position: left top; background-repeat: no-repeat; background-position: left top; background-size: contain; }
@media (min-width: 800px) { .m-seminar .sem-talk-poster { position: sticky; top: var(--pop-bar, 44px); } }
.m-seminar .sem-talk-text { max-width: var(--measure); }
.m-seminar .sem-talk-text > * + * { margin-top: var(--sp-3); }
.m-seminar .sem-talk-text > .h2 { margin-top: var(--sp-2); }
.m-seminar .sem-talk-text > .sem-talk-zh { margin-top: var(--sp-1); }
.m-seminar .sem-talk-text > .sem-talk-abs, .m-seminar .sem-talk-text > .sem-talk-fig { margin-top: var(--sp-4); }
.m-seminar .sem-talk-text > .label { margin-top: var(--sp-5); }
.m-seminar .sem-talk-text > .label + * { margin-top: var(--sp-2); }
.m-seminar .sem-talk-text .prose p:last-child { margin-bottom: 0; }
.m-seminar .sem-talk-fig { margin-left: 0; margin-right: 0; margin-bottom: 0; }
.m-seminar .sem-talk-fig figcaption { margin-top: var(--sp-2); }
.m-seminar .sem-refs { margin-bottom: 0; padding-left: 1.4em; display: grid; gap: var(--sp-2); }
/* the poster in a talk's pop-up opens at full size (the organiser's original resolution) in a new
   tab, so its small print can be read */
.m-seminar .sem-talk-full { display: block; cursor: zoom-in; }
@media (min-width: 800px) { .m-seminar .sem-talk-full { position: sticky; top: var(--pop-bar, 44px); align-self: start; } .m-seminar .sem-talk-full .sem-talk-poster { position: static; } }

/* posters that open a band start on the label's capitals, as the leader's portrait does */
.m-seminar .sec-body > .sem-posters:first-child, .m-seminar .sem-next-img { margin-top: var(--cap-l); }
/* very narrow phones: a long joined title may break rather than push the page sideways */
@media (max-width: 399px) { .m-seminar .sem-row .ttl { overflow-wrap: anywhere; } }

/* /join/: positions in two columns, how to apply, and the same in Chinese.
   Type from the roles: a position's title an entry title (.h3) with its Chinese name grey after
   it (span.zh), its "when" a grey line (.meta), its text; "We look for" opens its paragraph in
   semibold ink, the rest of it grey. The Chinese block is set for Chinese: --fs-zh, open leading,
   a hair of tracking, and a space between Chinese and Latin or figures (foundation.css). */
.m-join .join-pos { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4) var(--g); }
@media (min-width: 760px) { .m-join .join-pos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.m-join .join-pos li { scroll-margin-top: 24px; }
.m-join .join-pos .h3 .zh { margin-left: 0.3em; }
.m-join .join-pos .meta { margin-top: var(--sp-1); }
/* when dated.js removes a past `when` that was all the grey line held, no empty line stays */
.m-join .join-pos .meta:empty { display: none; }
.m-join .join-text { margin-top: var(--sp-2); max-width: var(--measure); }
.m-join .join-who { color: var(--ink-2); }
.m-join .join-who span { color: var(--ink); font-weight: 600; }
.m-join .join-apply { max-width: 60em; }
.m-join a[href^="mailto:"] { white-space: nowrap; }
.m-join .join-zh { display: grid; gap: var(--sp-2); font-size: var(--fs-zh); line-height: var(--lh-zh); letter-spacing: var(--ls-zh); }
.m-join .join-zh p { max-width: 44em; }
.m-join .join-zh a[href^="mailto:"] { letter-spacing: var(--ls-m); }
/* the positions in Chinese: two columns, on the lines of the two above; four from 1200px. A title
   and its time never split (they move to the next line whole) */
.m-join .join-zh-pos { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-1) var(--g); }
@media (min-width: 1200px) { .m-join .join-zh-pos { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.m-join .join-zh-pos span { white-space: nowrap; }
.m-join .join-zh-t { font-weight: 600; margin-right: 0.4em; }

/* /others/: one band per section of _data/others.yml, its items in one or two columns; each a
   linked title, "kind · year" and the description.
   Type from the roles: an item's title an entry title (.h3), its "kind · year" a grey line
   (.meta) close under it, its description text one step below (at most about 80 characters). */
.m-others .oth-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4) var(--g); }
@media (min-width: 1100px) { .m-others .oth-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.m-others .oth-title a:hover { color: var(--red); }
.m-others .meta { margin-top: var(--sp-1); }
.m-others .oth-desc { margin-top: var(--sp-2); max-width: var(--measure); }
.m-others .oth-desc a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--ink-3); }
.m-others .oth-desc a:hover { text-decoration-color: var(--red); }

