/* ============================================================
   Vincent Chiao — site styles

   TYPEFACE: Junicode (Peter S. Baker), subset to Latin, variable
   weight axis 400–700. Self-hosted from /fonts.
   To switch back to Sorts Mill Goudy, see the note at --serif.

   ONE DIAL FOR TYPE SIZE: --text below. Every other size on the
   site is calculated from it, so changing that one value rescales
   the whole page proportionally.
   ============================================================ */

@font-face {
  font-family: "Junicode";
  src: url("fonts/junicode-roman.woff2") format("woff2-variations"),
       url("fonts/junicode-roman.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Junicode";
  src: url("fonts/junicode-italic.woff2") format("woff2-variations"),
       url("fonts/junicode-italic.woff2") format("woff2");
  font-weight: 400 700;
  font-style: italic;      /* <- the only line that differs */
  font-display: swap;
}

:root {
  /* --- colour ------------------------------------------------ */
  --paper-rgb: 255 255 255;   /* white. This is the v2 variable: set it back
                                 to 243 245 244 for v1's silvery grey-green. */
  --paper:   rgb(var(--paper-rgb));
  --ink:     #16191a;
  --ink-mid: #5a5f63;   /* citations, metadata, navigation — neutral grey.
                           v1's #565e5c is tinted green, which reads as
                           dirty against pure white. */
  --rule:    #e2e4e6;   /* v1: #dbe0dd */
  /* Links carry no underline, so colour is the only resting cue. --link
     is set to clear 3:1 against --ink (3.3:1) as well as 4.5:1 against
     the paper (5.4:1). Hover deepens to --link-hi, which is the old,
     more subdued blue. Don't darken --link past about #33628f without
     bringing an underline back. */
  --link:    #3a6ea5;
  --link-hi: #27496d;

  /* --- type -------------------------------------------------- */
  /* For Sorts Mill Goudy instead: swap the family below and raise
     --text to about 1.2rem (Goudy has a much smaller x-height).  */
  --serif: "Junicode", Georgia, "Times New Roman", serif;
  --text:  1.075rem;    /* the one size dial — everything derives from this */


  --measure: 43rem;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--text);
  line-height: 1.66;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures;
  font-synthesis-weight: none;  /* if you switch to a font without a
                                   bold, weights degrade to roman rather
                                   than to a smeared fake bold */
  /* Deliberately NOT -webkit-font-smoothing: antialiased — it thins
     the strokes and starves an oldstyle face on macOS. */
}

.wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 1.5rem;
}

/* ---------- small capitals ----------
   These do the work a sans-serif or a bold would normally do.
   Labels are written in sentence case in the HTML, so they degrade
   to ordinary text if the font fails to load. */

nav, .eyebrow, .flag, .note, .seealso, details summary,
footer .wrap, .updated, .download, .contactlist .label, .entry .yr {
  font-variant-caps: small-caps;
  font-feature-settings: "smcp" 1;
  font-size: calc(var(--text) * 0.82);
  letter-spacing: 0.055em;
}

/* Masthead: name and navigation sit at (or just above) heading size. */
nav { font-size: calc(var(--text) * 1.26); letter-spacing: 0.045em; }

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

/* The masthead sticks to the top of the viewport as the page scrolls.

   The generous air above it is NOT the masthead's own padding — it is
   padding on <body>, which scrolls away. So the header is airy at rest
   and compact once it is stuck, without any JavaScript. The two values
   add up to the 2.5rem the header used to have on its own.

   It needs an opaque background (text scrolls underneath it) and a
   z-index above the t-backdrop image. To turn stickiness off, delete
   the position/top/z-index lines and move 1.35rem back onto
   .masthead .wrap's padding-top. */

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
  margin-bottom: 3.25rem;
}

.masthead .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  padding-top: 1.15rem;
  padding-bottom: 1.1rem;
}

body { padding-top: 1.35rem; }

/* In-page anchors (papers.html#progress) would otherwise land underneath
   the stuck header. */
html { scroll-padding-top: 5.5rem; }

.wordmark {
  font-size: calc(var(--text) * 1.72);
  letter-spacing: 0.06em;
  font-variant-caps: small-caps;
  font-feature-settings: "smcp" 1;
  color: var(--ink);
  text-decoration: none;
}

.wordmark:hover { color: var(--link); }

nav { display: flex; gap: 1.25rem; margin-left: auto; }

nav a {
  color: var(--ink-mid);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1.5px solid transparent;
}

nav a:hover { color: var(--ink); }
nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--link); }

/* ---------- generic type ---------- */

h1 {
  /* Same size as the masthead nav (--text * 1.26), which is also the
     h2 / .standfirst size. Was 1.95. */
  font-size: calc(var(--text) * 1.26);
  font-weight: 400;
  line-height: 1.2;
  margin: 0 0 1.75rem;
}

h2 {
  font-size: calc(var(--text) * 1.26);
  font-weight: 400;
  line-height: 1.3;
  margin: 0 0 0.55rem;
}

p { margin: 0 0 1.15rem; }

/* One link treatment for the whole site: --link, no rule. Colour is the
   only resting cue, so every link also shifts to --link-hi on hover and
   keeps the focus ring at the end of this file. See the note on --link
   in :root before changing the blue. The masthead nav and the CV
   download button are chrome, not prose links, and keep their own
   styling. */
a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hi); }

em, cite { font-style: italic; }

.eyebrow {
  color: var(--ink-mid);
  letter-spacing: 0.11em;
  margin: 0 0 1.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}

section + section .eyebrow { margin-top: 4rem; }

/* Oldstyle figures sit in the line the way an oldstyle face intends;
   lining tabular figures in the year column, where they must align. */
p, .cite, .abstract, .contactlist { font-variant-numeric: oldstyle-nums; }

/* ---------- landing page ---------- */

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

/* Title and affiliation are set exactly as the research-area headings
   (h2). To hold it back from competing with them, change colour to
   var(--ink-mid) — the size stays the same either way. */
.standfirst {
  font-size: calc(var(--text) * 1.26);
  font-weight: 400;
  line-height: 1.3;
  color: var(--ink);
  margin: 0 0 1.15rem;
}

.lede { font-size: inherit; }

.research h2 { margin-top: 0; }
.research section { margin-bottom: 2.8rem; }

.seealso { letter-spacing: 0.05em; }
.seealso a { margin-right: 1.15rem; }

/* ---------- publication entries ----------
   The year hangs in the left margin so the list scans
   chronologically at a glance, as in a printed vita. */

.entry {
  display: grid;
  grid-template-columns: 3.9rem 1fr;
  gap: 0 1.4rem;
  margin-bottom: 1.9rem;
}

.entry .yr {
  color: var(--ink-mid);
  font-variant-numeric: lining-nums tabular-nums;
  padding-top: 0.34rem;
  white-space: nowrap;
}

.entry .title {
  font-size: var(--text);
  font-weight: 500;        /* no effect in a font without a bold */
  line-height: 1.35;
  color: var(--link);
}

.entry .title:hover { color: var(--link-hi); }

/* An entry whose title is not a link — the book project, and the
   working papers, which are available by email rather than download. */
.entry .title.plain { color: var(--ink); }

.entry .cite {
  color: var(--ink-mid);
  font-size: calc(var(--text) * 0.88);
  line-height: 1.5;
  margin-top: 0.2rem;
}

.entry .cite a { color: var(--link); }
.entry .cite a:hover { color: var(--link-hi); }

.flag, .note { color: var(--ink-mid); }
.note { line-height: 1.5; margin-top: 0.3rem; letter-spacing: 0.03em; }

/* ---------- abstracts ---------- */

details { margin-top: 0.45rem; }

details summary {
  color: var(--ink-mid);
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  user-select: none;
}

details summary::-webkit-details-marker { display: none; }

details summary::before {
  content: "";
  width: 0; height: 0;
  border-left: 4px solid currentColor;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  transition: transform 0.14s ease;
}

details[open] summary::before { transform: rotate(90deg); }
details summary:hover { color: var(--ink); }

details .abstract {
  font-size: var(--text);
  line-height: 1.6;
  color: var(--ink);
  margin: 0.6rem 0 0;
  padding-left: 0.9rem;
  border-left: 2px solid var(--rule);
}

/* ---------- CV page ---------- */

.cvbar { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 1.5rem; margin-bottom: 1.6rem; }

.download {
  text-decoration: none;
  color: var(--paper);
  background: var(--link);
  padding: 0.45rem 1.05rem;
}

.download:hover { background: var(--link-hi); color: var(--paper); }
.updated { color: var(--ink-mid); }

.pdfframe {
  width: 100%;
  height: 78vh;
  min-height: 520px;
  border: 1px solid var(--rule);
  background: #fff;
}

/* ---------- book page ---------- */

.bookrow { display: flex; gap: 2.25rem; align-items: flex-start; margin-bottom: 1rem; }

/* The jacket is wrapped in a link to the publisher, so the flex sizing
   lives on the wrapper and the image just fills it. */
.bookrow .jacketlink { flex: 0 0 152px; display: block; }

.bookrow .jacket {
  display: block;
  width: 100%;
  border: 1px solid var(--rule);
  background: #e3e7e4;
  aspect-ratio: 2 / 3;
  object-fit: cover;
}

/* Publisher and year under the book title: quieter and smaller than
   .standfirst, which was set at heading size. */
.pubinfo {
  font-size: calc(var(--text) * 0.92);
  color: var(--ink-mid);
  margin: 0 0 1.15rem;
}

.bookrow .about { flex: 1 1 auto; }
.bookrow .about h2 { margin-top: 0; }

/* ---------- contact ---------- */

.contactlist { list-style: none; padding: 0; margin: 0 0 2.25rem; }
.contactlist li { margin-bottom: 0.3rem; }

.contactlist .label {
  color: var(--ink-mid);
  letter-spacing: 0.11em;
  display: block;
  margin-top: 1.4rem;
}

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

footer { margin-top: 5rem; border-top: 1px solid var(--rule); }

footer .wrap {
  padding-top: 1.5rem;
  padding-bottom: 3.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.6rem 2rem;
  color: var(--ink-mid);
}

footer a { color: var(--link); }
footer a:hover { color: var(--link-hi); }
footer .profiles a { margin-left: 1.15rem; }

/* ---------- accessibility & motion ---------- */

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

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ---------- small screens ---------- */

@media (max-width: 640px) {
  :root { --text: 1.02rem; }

  body { padding-top: 0.6rem; }   /* 0.6 + 1.15 = the 1.75rem it had */

  /* On a phone the nav wraps to its own line, so the stuck header is
     about 133px — roughly a sixth of the viewport. If that feels like
     too much, uncomment to let the header scroll away on small screens
     while keeping it sticky on the desktop. */
  /* .masthead { position: static; } */
  nav { gap: 1rem; }

  .entry { grid-template-columns: 1fr; gap: 0; }
  .entry .yr { padding-top: 0; margin-bottom: 0.1rem; }

  .bookrow { flex-direction: column; gap: 1.5rem; }
  .bookrow .jacketlink { flex: 0 0 auto; width: 152px; }
  .pdfframe { display: none; }
  footer .profiles a { margin: 0 1.15rem 0 0; }
}

/* ============================================================
   v3 — the Bruegel
   ============================================================

   THE IMAGE: Pieter Bruegel the Elder, "Children's Games" (1560),
   Kunsthistorisches Museum, Vienna. The painter died in 1569, so the
   painting is public domain; the photograph reproduced here is a
   Wikimedia scan, desaturated and level-lifted locally. Unlike the
   Libeskind in v2, nothing here needs clearing.

   WHY IT IS A DIFFERENT PROBLEM FROM v2: the Libeskind is line work on
   white, so it dissolves into a white page and has no edge. A painting
   is a dense rectangle of mid-greys. It cannot dissolve; it will always
   be an object on the page, and the only question is what kind of object.
   Hence three treatments below, chosen by a class on <body>:

     t-plate      the whole panel at the text measure, presented as a
                  book plate: hairline frame, caption beneath.
     t-band       a wide crop of the central ground — the part where the
                  games actually are — read as a frieze, not a picture.
     t-backdrop   v1's technique with v2's image: very faint, fixed,
                  behind the text, fading out down and to the right.

   Set exactly one. The paper is warmed slightly off white for the plate
   and band, because a warm-grey reproduction on pure #fff sits in a
   glare; --paper-rgb is still the single dial.
   ------------------------------------------------------------ */

body.t-plate, body.t-band { --paper-rgb: 250 249 247; }

.hero { margin: 0 0 3.25rem; }

.hero img {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 auto;
}

.hero figcaption {
  font-variant-caps: small-caps;
  font-feature-settings: "smcp" 1;
  font-size: calc(var(--text) * 0.82);
  letter-spacing: 0.055em;
  color: var(--ink-mid);
  text-align: center;
  margin-top: 0.9rem;
}

/* --- t-plate ------------------------------------------------
   The frame is a hairline in --rule, not a border on the image
   itself: it sits a hair outside so the dark edge of the panel
   never touches the line. */

body.t-plate .hero img {
  border: 1px solid var(--rule);
  padding: 0;
}

body.t-plate .hero { margin-top: 0.25rem; }

/* --- t-band -------------------------------------------------
   Shallow (about 2.2:1) and full measure. A band this shallow stops
   competing with the text for the top of the page; it behaves like a
   rule with a picture in it. */

body.t-band .hero img { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
body.t-band .hero figcaption { text-align: right; }

/* --- t-backdrop ---------------------------------------------
   The <figure> is hidden and the image is painted behind everything
   instead, at low opacity, with two paper-coloured gradients fading it
   out to the right and downwards so it dissolves under the text rather
   than stopping at an edge. Hidden below 900px, where it would read as
   an accident rather than a choice.

   Dials: --hero-opacity, --hero-blur, --hero-w. */

body.t-backdrop {
  --hero-opacity: 0.13;
  --hero-blur: 0px;      /* 1px calms the figure detail under text */
  --hero-w: min(74vw, 1180px);
  --hero-ratio: 1.379;   /* the trimmed scan is 1218 × 883 */
}

body.t-backdrop .hero { display: none; }

/* Centred on the viewport, so the painting sits behind the text column
   rather than off to one side. Because it is centred, the horizontal
   fade has to be symmetric — paper at both edges, clear through the
   middle — where the off-centre version only needed to fade one way. */

body.t-backdrop::before {
  content: "";
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: var(--hero-w);
  aspect-ratio: var(--hero-ratio);
  background-image:
    linear-gradient(to right,
      rgb(var(--paper-rgb) / 1) 0%,
      rgb(var(--paper-rgb) / 0) 26%,
      rgb(var(--paper-rgb) / 0) 74%,
      rgb(var(--paper-rgb) / 1) 100%),
    linear-gradient(to bottom, rgb(var(--paper-rgb) / 0) 58%, rgb(var(--paper-rgb) / 1) 100%),
    url("bruegel-games.jpg");
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  opacity: var(--hero-opacity);
  filter: blur(var(--hero-blur));
  pointer-events: none;
  z-index: 0;
  display: none;
}

/* Keeps every bit of text above the image. */
body.t-backdrop main,
body.t-backdrop footer { position: relative; z-index: 1; }
/* the masthead is already sticky + z-index 20, so it must NOT be reset
   to position: relative here */

@media (min-width: 900px) {
  body.t-backdrop::before { display: block; }
}

@media (max-width: 640px) {
  .hero { margin-bottom: 2.25rem; }
}

/* --- t-backdrop-mask ----------------------------------------
   The centred backdrop, but held off the text.

   The problem with plain t-backdrop is that centring puts the busiest
   part of the painting directly under the prose, so the only way to keep
   the text legible is to fade the whole image until there is nothing
   left of it. Masking separates the two: the image is painted at a real
   strength (0.30, more than twice t-backdrop's 0.13) and then a band of
   solid paper — as wide as the text column plus a soft feather — is laid
   over the middle of it. The margins carry the picture; the measure
   stays clean.

   The element is the full viewport, not the image's own box, so 50% in
   the gradient below is the centre of the *screen* and --mask-half can
   be given in rem to track --measure. Keep --mask-half a little wider
   than half the text column (currently 40rem of text → 20rem half).

   Dials: --hero-opacity, --hero-w, --mask-half, --mask-feather. */

body.t-backdrop-mask {
  --hero-opacity: 0.30;
  --hero-blur: 0px;
  --hero-w: min(105vw, 1500px);
  --mask-half: 21rem;      /* half the protected band */
  --mask-feather: 8rem;    /* how gradually it releases into the image */
}

body.t-backdrop-mask .hero { display: none; }

/* The sticky masthead is an opaque paper band. Left where it normally
   sits — below 1.35rem of body padding — it cuts a white stripe across
   the painting with a sliver of image stranded above it. So in this
   variant the band is flush to the top of the viewport and carries the
   header's air as its own padding: a solid panel over the picture,
   which is legible as a decision rather than as a seam. */
body.t-backdrop-mask { padding-top: 0; }
body.t-backdrop-mask .masthead .wrap { padding-top: 2.2rem; }

body.t-backdrop-mask::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image:
    linear-gradient(to right,
      rgb(var(--paper-rgb) / 0) 0,
      rgb(var(--paper-rgb) / 0) calc(50% - var(--mask-half) - var(--mask-feather)),
      rgb(var(--paper-rgb) / 1) calc(50% - var(--mask-half)),
      rgb(var(--paper-rgb) / 1) calc(50% + var(--mask-half)),
      rgb(var(--paper-rgb) / 0) calc(50% + var(--mask-half) + var(--mask-feather)),
      rgb(var(--paper-rgb) / 0) 100%),
    linear-gradient(to bottom,
      rgb(var(--paper-rgb) / 0) 0,
      rgb(var(--paper-rgb) / 0) 50%,
      rgb(var(--paper-rgb) / 1) 100%),
    url("bruegel-games.jpg");
  background-size: cover, cover, var(--hero-w) auto;
  background-position: center, center, center top;
  background-repeat: no-repeat;
  opacity: var(--hero-opacity);
  filter: blur(var(--hero-blur));
  pointer-events: none;
  z-index: 0;
  display: none;
}

body.t-backdrop-mask main,
body.t-backdrop-mask footer { position: relative; z-index: 1; }

/* Below this width the margins are too narrow to show any of the
   painting, and the mask would cover all of it. */
@media (min-width: 1100px) {
  body.t-backdrop-mask::before { display: block; }
}
