/* ==========================================================================
   Jiannan Tian's Page
   ========================================================================== */

:root {
  /* the banner bar. These are the ONLY per-site part of the banner: the rules in
     the header block below are identical across the sites that share it. */
  --bar: #c41e3a;
  --bar-fg: #ffffff;
  --bar-idx: rgba(255, 255, 255, .62);
  --bar-rule: rgba(255, 255, 255, .3);
  --bar-hover: rgba(255, 255, 255, .14);
  --bar-current-bg: var(--bg);
  --bar-current-fg: var(--accent);
  --bar-current-idx: var(--muted);
  --bar-mark-filter: none;
  --bg: #ffffff;
  --surface: #fafafa;
  --surface-2: #f0f0f0;
  --fg: #000000;
  --fg-soft: #333333;
  --muted: #6e6e6e;
  --rule: #e4e4e4;
  --rule-strong: #c9c9c9;
  --accent: #c41e3a;          /* Cardinal */
  --accent-fg: #ffffff;
  --accent-soft: #fbecef;
  --accent-line: #c41e3a;
  --bar-fg: #ffffff;

  --prose: 800px;
  --wide: 800px;     /* the column; the banner tracks it, so both scale together */

  --radius: 10px;
  --radius-sm: 6px;

  --shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 6px 20px -12px rgba(0, 0, 0, .28);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bar: #9d182e;
    --bar-current-fg: var(--fg);
    --bg: #121212;
    --surface: #1b1b1b;
    --surface-2: #242424;
    --fg: #f2f2f2;
    --fg-soft: #c9c9c9;
    --muted: #8a8a8a;
    --rule: #232323;
    --rule-strong: #3a3a3a;
    --accent: #ff7183;         /* Cardinal, lifted to carry on black */
    --accent-fg: #000000;
    --accent-soft: #2a1116;
    --accent-line: #ff7183;
    --bar-fg: #ffffff;
    --shadow: 0 1px 2px rgba(0, 0, 0, .6), 0 8px 24px -14px rgba(0, 0, 0, .9);
  }
}

  :root[data-theme="dark"] {
    --bar: #9d182e;
    --bar-current-fg: var(--fg);
    --bg: #121212;
    --surface: #1b1b1b;
    --surface-2: #242424;
    --fg: #f2f2f2;
    --fg-soft: #c9c9c9;
    --muted: #8a8a8a;
    --rule: #232323;
    --rule-strong: #3a3a3a;
    --accent: #ff7183;         /* Cardinal, lifted to carry on black */
    --accent-fg: #000000;
    --accent-soft: #2a1116;
    --accent-line: #ff7183;
    --bar-fg: #ffffff;
    --shadow: 0 1px 2px rgba(0, 0, 0, .6), 0 8px 24px -14px rgba(0, 0, 0, .9);
  }

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 4rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 15px/1.5 "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono",
        Menlo, Consolas, monospace;
  font-feature-settings: "kern" 1, "liga" 1;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; }

a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--rule-strong);
  text-decoration-thickness: .06em;
  text-underline-offset: .18em;
}
a:hover { text-decoration-color: currentColor; }

.btn, .skip, .card-thumb {
  text-decoration: none;
}

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

.wrap { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 1.25rem; }

/* Deliberately NOT a per-block max-width here: a block that sets `margin: 0`
   later in this file would silently drop the auto margins and sit flush left
   while its neighbours centred, and the section edges would go ragged. The wrap
   is the measure; every block inherits one edge from it. */
.prose { max-width: var(--prose); }

/* ---------- skip link ---------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: .6rem 1rem;
  background: var(--accent);
  color: var(--accent-fg);
  z-index: 100;
}
.skip:focus { left: 0; }

/* ---------- header: full-bleed banner ---------- */

/* The bar bleeds to the viewport so nothing scrolls through beside it; the CELLS
   are what stay clamped to the text column. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bar);
  color: var(--bar-fg);
}

.banner {
  display: flex;
  align-items: stretch;
  width: 100%;
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0;
  background: var(--bar);
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.banner::-webkit-scrollbar { display: none; }

.banner > li { display: flex; flex: 1 1 0; min-width: 0; }

.banner > li + li { border-left: 1px solid var(--bar-rule); }

.banner a,
.banner .cell {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0;
  flex: 1;
  min-width: 0;
  padding: .34rem .7rem .4rem;
  color: var(--bar-fg);
  text-decoration: none;
  white-space: nowrap;
  transition: background .12s ease, color .12s ease;
}

.banner .idx {
  font-size: .58rem;
  line-height: 1.35;
  font-weight: 500;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
  color: var(--bar-idx);
}

.banner .label {
  font-size: .82rem;
  line-height: 1.3;
  font-weight: 400;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
}

.banner .brand-cell {
  flex: 0 0 auto;
  overflow: hidden;
  max-width: 14rem;
  transition: max-width .24s ease, opacity .18s ease;
}

/* while the page's own name is on screen, the banner's copy is redundant. It
   collapses to zero width rather than switching off, so the other cells widen
   into the space instead of jumping. */
.site-header[data-name-visible] .brand-cell.decorative {
  max-width: 0;
  opacity: 0;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .banner .brand-cell { transition: none; }
}

.banner .brand-cell .label { font-weight: 600; }

.banner .brand-cell .idx { display: flex; align-items: center; gap: .4rem; }
.banner .brand-cell img { width: 14px; height: 16px; filter: var(--bar-mark-filter); }

.banner a:hover { background: var(--bar-hover); text-decoration: none; }

.banner a[aria-current="page"] { background: var(--bar-current-bg); color: var(--bar-current-fg); }
.banner a[aria-current="page"] .idx { color: var(--bar-current-idx); }
.banner a[aria-current="page"]:hover { background: var(--bar-current-bg); }

.banner .ext .idx::after { content: "\2197"; }

@media (max-width: 46rem) {
  .banner a, .banner .cell { padding: .3rem .7rem .35rem; }
  .banner .label { font-size: .88rem; }
  /* grow to fill the bar when there is room, never shrink below the label when
     there is not -- `0 0 auto` did the second half only, so a narrow window left
     the cells huddled at the left with dead bar beside them */
  .banner > li { flex: 1 0 auto; }
  .banner .brand-cell.decorative { display: none; }
  .banner { max-width: 100%; }
}

/* ---------- headings & sections ---------- */

.section { padding: 1.9rem 0 0; }

.section-head {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  margin-bottom: .7rem;
  padding-bottom: .35rem;
  border-bottom: 1px solid var(--rule);
}

.section-head h2 {
  margin: 0;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg);
}

.section-head .hint { font-size: .9rem; color: var(--muted); }

p { margin: 0 0 .55rem; }
p:last-child { margin-bottom: 0; }

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

.hero { padding: 1.6rem 0 .3rem; }

/* seal on the left, spanning name + links */
.hero-id {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  margin: 0 0 1.05rem;
}

/* the Hg element tile, the group's own mark */
.hero-mark {
  flex: none;
  display: block;
  width: 76px;
  height: auto;
}

.hero h1 {
  margin: 0 0 .3rem;
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.4rem);
  line-height: 1.08;
  letter-spacing: -.025em;
}

.hero h1 .degree,
.hero .role .degree {
  font-size: .8em;
  font-weight: inherit;
  letter-spacing: .055em;
  text-transform: uppercase;
}

/* a page's one-line gloss sits BESIDE its title, on the title's baseline, rather
   than starting a second line for a fragment */
.page-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .3rem .9rem;
}

.hero .role {
  margin: 0;
  color: var(--fg-soft);
  font-size: 1.02rem;
}

.hero .bio { color: var(--fg-soft); }
.hero .bio strong { color: var(--fg); font-weight: 600; }

@media (max-width: 40rem) {
  .hero { padding-top: 2rem; }
  .hero-id { gap: .85rem; margin-bottom: 1.5rem; }
  .hero-mark { width: 56px; }
}

/* ---------- callout ---------- */

.callout {
  margin: 1.2rem 0 0;
  padding: 0 0 0 1rem;
  border: 0;
  border-left: 1px solid var(--rule-strong);
  background: none;
}

/* the label runs into the sentence rather than sitting on its own line */
.callout-label {
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg);
}
.callout-label::after { content: ":"; }

.callout p { color: var(--fg-soft); }

.callout .email { color: var(--fg); }

/* ---------- news ---------- */

.news { margin: 0; padding: 0; list-style: none; }

.news li {
  display: grid;
  grid-template-columns: 4.25rem minmax(0, 1fr);
  gap: .75rem;
  padding: .28rem 0;
  border-bottom: 1px solid var(--rule);
}
.news li:last-child { border-bottom: 0; }

.news time,
.news .when {
  font-variant-numeric: tabular-nums;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--muted);
  padding-top: .12rem;
}

.news p { margin: 0; color: var(--fg-soft); }

@media (max-width: 30rem) {
  .news li { grid-template-columns: minmax(0, 1fr); gap: .15rem; }
}

/* a small category label. It rides ON a heading, so it must stay clearly the
   smaller of the two: the thing being named is the heading, not the label. */
.chip {
  display: inline-block;
  padding: .06rem .38rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .04em;
  white-space: nowrap;
  vertical-align: .12em;
}

/* ---------- cards (responsive grid: events, software) ---------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

.card:hover { border-color: var(--rule-strong); box-shadow: var(--shadow); }

.card-thumb {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
}

/* software covers carry a name, not a place: half the height says it just as
   well and gets three products onto a screen */
.cards.compact .card-thumb {
  aspect-ratio: 32 / 9;
  background: var(--surface-2);
  border-bottom: 1px solid var(--rule);
}

.card-thumb img,
.card-thumb .placeholder { display: block; width: 100%; height: 100%; object-fit: cover; }

/* inline, so it reads the page's own --accent rather than a colour baked into a
   file: an <img> cannot see the document's custom properties */
.card-thumb .placeholder { font-family: inherit; }

.card-body { display: flex; flex-direction: column; gap: .35rem; padding: .8rem .95rem .9rem; flex: 1; }

/* the venue tag rides on the work's name, not a line of its own */
.card h3 .chip { margin-right: .5rem; }

/* the name and where to go sit on ONE line: a card that says two short things
   should not spend three rows saying them */
.card-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem .7rem;
}

.card h3 { margin: 0; font-size: 1.12rem; line-height: 1.2; letter-spacing: -.015em; }

.card .subtitle { margin: 0; color: var(--fg-soft); font-size: .88rem; line-height: 1.35; }

/* the date rides on the name's line: same line, lower voice, so the workshop is
   still what the heading says */
.card h3 .when {
  font-weight: 400;
  font-size: .82em;
  color: var(--muted);
  white-space: nowrap;
}



.btn {
  display: inline-block;
  padding: .16rem .5rem;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  background: var(--bg);
  font-size: .87rem;
  font-weight: 550;
  color: var(--fg-soft);
}
.btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); text-decoration: none; }

/* the same pill, sitting on the cover it belongs to */
.btn.on-cover {
  position: absolute;
  right: .6rem;
  bottom: .6rem;
  background: var(--bg);
  border-color: transparent;
  color: var(--fg);
  box-shadow: 0 1px 6px rgba(0, 0, 0, .3);
}

.card details { border-top: 1px solid var(--rule); padding-top: .65rem; }

.card summary {
  cursor: pointer;
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  list-style: none;
}
.card summary::-webkit-details-marker { display: none; }
.card summary::before { content: "▸ "; display: inline-block; transition: transform .15s ease; }
.card details[open] summary::before { content: "▾ "; }
.card summary:hover { color: var(--accent); }

.card details p { margin: .4rem 0 0; font-size: .9rem; line-height: 1.45; color: var(--fg-soft); }

/* ---------- footer ---------- */

.site-footer { margin-top: 2.4rem; border-top: 1px solid var(--rule); background: var(--surface); }

.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.25rem;
  align-items: baseline;
  padding-top: 1rem;
  padding-bottom: 1.6rem;
  font-size: .85rem;
  color: var(--muted);
}

@media print {
  .site-header, .site-footer, .card-links { display: none; }
  .card details { display: block; }
  body { font-size: 11pt; }
}

/* where an event actually sits: its host conference, date, and city */
.card .meta {
  margin: 0;
  font-size: .88rem;
  color: var(--muted);
}
.card .meta strong { color: var(--fg-soft); font-weight: 700; }

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

.people { margin: 0; padding: 0; list-style: none; }

.people > li { padding: .5rem 0; border-bottom: 1px solid var(--rule); }
.people > li:last-child { border-bottom: 0; }

.people .person { margin: 0; }

.people .person-name { font-weight: 600; }

.people .person-role { color: var(--muted); font-size: .92rem; margin-left: .5em; }

/* ---------- research themes ---------- */

.themes { margin: 0; padding: 0; list-style: none; max-width: var(--prose); }

.themes > li { padding: .7rem 0; border-bottom: 1px solid var(--rule); }
.themes > li:last-child { border-bottom: 0; }

.themes h3 { margin: 0 0 .2rem; font-size: 1rem; letter-spacing: -.01em; }

.themes p { margin: 0; color: var(--fg-soft); font-size: .92rem; }

/* ---------- per-page accents ---------- */

/* The banner already separates its mechanism from its palette, so a page picks a
   colour by redeclaring tokens and nothing else moves. A LIGHT bar (Y) flips the
   washes to black: white-on-yellow is about 1.9:1 and unreadable. */

[data-accent="b2"] { --bar: #003399; --accent: #003399; --accent-soft: #e8edf9; --accent-line: #003399; }
[data-accent="ink"] { --bar: #595857; --accent: #595857; --accent-soft: #eeeeed; --accent-line: #595857; }

[data-accent="g"] {
  /* G!80!black: white on it is 5.2:1, so the bar keeps white text */
  --bar: #007b00;
  --accent: #007b00;
  --accent-soft: #e6f2e6;
  --accent-line: #007b00;
}

[data-accent="y"] {
  --bar: #f1c40f;
  --bar-fg: #1a1500;
  --bar-idx: rgba(0, 0, 0, .62);
  --bar-rule: rgba(0, 0, 0, .28);
  --bar-hover: rgba(0, 0, 0, .10);
  /* Y itself is 1.7:1 on white, so body text that carries the accent takes a
     darkened cut of it; the BAR keeps the true colour. */
  --accent: #8a6d00;
  --accent-soft: #fdf6d9;
  --accent-line: #8a6d00;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"])[data-accent="b2"] { --bar: #00297a; --accent: #8aa6ff; --accent-soft: #101a3a; --accent-line: #8aa6ff; }
  :root:not([data-theme="light"])[data-accent="ink"] { --bar: #474646; --accent: #bdbcba; --accent-soft: #1e1e1d; --accent-line: #bdbcba; }
  :root:not([data-theme="light"])[data-accent="g"] { --bar: #006200; --accent: #5fd35f; --accent-soft: #0c1f0c; --accent-line: #5fd35f; }
  :root:not([data-theme="light"])[data-accent="y"] { --bar: #c19d0c; --accent: #f1c40f; --accent-soft: #2a2405; --accent-line: #f1c40f; }
}

  :root[data-theme="dark"][data-accent="b2"] { --bar: #00297a; --accent: #8aa6ff; --accent-soft: #101a3a; --accent-line: #8aa6ff; }
  :root[data-theme="dark"][data-accent="ink"] { --bar: #474646; --accent: #bdbcba; --accent-soft: #1e1e1d; --accent-line: #bdbcba; }
  :root[data-theme="dark"][data-accent="g"] { --bar: #006200; --accent: #5fd35f; --accent-soft: #0c1f0c; --accent-line: #5fd35f; }
  :root[data-theme="dark"][data-accent="y"] { --bar: #c19d0c; --accent: #f1c40f; --accent-soft: #2a2405; --accent-line: #f1c40f; }

/* ---------- theme switch ---------- */

/* Floating, bottom right, out of the flow: reachable anywhere on the page rather
   than only where the page ends. */
.theme-switch {
  position: fixed;
  bottom: .75rem;
  /* Floating, but on the CONTENT's right edge rather than the viewport's: pinned
     to the centre line, then pushed out by half the measure less its own width.
     min() keeps it inside the column once the viewport is narrower than --wide. */
  left: 50%;
  transform: translateX(calc(min(50vw, var(--wide) / 2) - 1.25rem - 100%));
  z-index: 30;
  display: inline-flex;
  gap: 1px;
  padding: 2px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg);
  opacity: .7;
  transition: opacity .15s ease;
}

.theme-switch:hover,
.theme-switch:focus-within { opacity: 1; }

.theme-switch button {
  appearance: none;
  border: 0;
  border-radius: 999px;
  padding: .18rem .5rem;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: .68rem;
  line-height: 1.4;
  cursor: pointer;
}

.theme-switch button:hover { color: var(--fg); }

.theme-switch button[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

@media print { .theme-switch { display: none; } }
