/* tokens.css: every colour, font, size, space, shape and duration of the site.
   The colours are the owner's sequential ramp "Termeh", which he made for water surface elevation and
   depth (his words of 2026-11-14). Every semantic colour below is one of the seven, or a mix of them in
   OKLab; the night ground and the day ink are also darkened with black.

   Two themes. The html element carries data-theme="light" (day) or "dark" (night); src/scripts/theme.js
   sets it before the first paint, from the stored choice or else the visitor's system setting. Without
   the script the page follows the system setting through color-scheme. Each semantic colour is
   light-dark(day, night). The contrast of every pair of text and ground is computed by
   tools/theme_contrast.py, which holds the same mixes. */
:root {
  color-scheme: light dark;

  /* Termeh, light to deep */
  --foam-mist: #e5f0ee;
  --glacial-blue: #c8dfe3;
  --powder-aqua: #a9ccd7;
  --river-teal: #7fb5c1;
  --slate-blue: #5d95a8;
  --deep-channel: #3e738e;
  --night-current: #274e68;

  /* the page: ground, surfaces, ink */
  --ground: light-dark(var(--foam-mist), color-mix(in oklab, var(--night-current) 62%, black));
  --wash: light-dark(color-mix(in oklab, var(--foam-mist) 55%, var(--glacial-blue)), color-mix(in oklab, var(--night-current) 78%, black));
  --ink: light-dark(color-mix(in oklab, var(--night-current) 78%, black), var(--foam-mist));
  --ink-2: light-dark(color-mix(in oklab, var(--deep-channel) 45%, var(--night-current)), var(--powder-aqua));
  --rule: light-dark(color-mix(in oklab, var(--slate-blue) 60%, var(--deep-channel)), var(--slate-blue));
  --rule-soft: light-dark(var(--powder-aqua), color-mix(in oklab, var(--deep-channel) 55%, var(--night-current)));

  /* his name: the block that marks it, and the type on it */
  --bed: light-dark(color-mix(in oklab, var(--deep-channel) 60%, var(--night-current)), var(--slate-blue));
  --on-bed: light-dark(var(--foam-mist), color-mix(in oklab, var(--night-current) 45%, black));

  /* links, focus, the open page */
  --link-line: light-dark(color-mix(in oklab, var(--deep-channel) 45%, var(--night-current)), var(--slate-blue));
  --link-hover: light-dark(var(--night-current), var(--river-teal));
  --focus: light-dark(var(--deep-channel), var(--river-teal));
  --current: light-dark(var(--deep-channel), var(--river-teal));     /* the line under the menu item of the page that is open */

  /* the first page of a paper: its white takes this tint (multiply), so its black type stays black */
  --sheet: light-dark(var(--glacial-blue), color-mix(in oklab, var(--glacial-blue) 60%, var(--powder-aqua)));

  /* the pop-up viewer of the certificates (2026-11-14): a deep, opaque layer over the page,
     with light type on it in both themes. tools/theme_contrast.py checks the type on this colour.
     It was 97% opaque; on a phone in the day theme the page's own text showed through under the
     caption (verification, 2026-11-14), so it is now fully opaque. */
  --scrim-solid: light-dark(color-mix(in oklab, var(--night-current) 85%, black), color-mix(in oklab, var(--night-current) 40%, black));
  --scrim: var(--scrim-solid);
  --on-scrim: var(--foam-mist);
  --on-scrim-2: var(--powder-aqua);

  /* the still band under the menu of every page but the home page (RiverBand.astro) */
  --water: light-dark(var(--deep-channel), var(--night-current));
  --trace-slow: light-dark(var(--river-teal), var(--slate-blue));
  --trace-fast: light-dark(var(--foam-mist), var(--glacial-blue));
  --trace-mid: color-mix(in oklab, var(--trace-slow), var(--trace-fast));
  --shore: light-dark(var(--deep-channel), var(--powder-aqua));

  /* the river of the home page with his name in the water (HeroRiver.astro, src/scripts/hero-river.js,
     2026-11-14). hero-river.js reads the seven Termeh colours and every token below. The water uses the
     ramp and mixes of it; the land uses the greens and sand tones below, chosen to sit beside the ramp.
     After a change of any of these, the four still pictures in public/hero/ are photographed again. */
  --river-pool: light-dark(color-mix(in oklab, var(--night-current) 82%, black), color-mix(in oklab, var(--night-current) 66%, black));
  --river-foam: light-dark(color-mix(in oklab, var(--glacial-blue) 70%, var(--foam-mist)), color-mix(in oklab, var(--powder-aqua) 70%, var(--glacial-blue)));
  --river-glint: light-dark(color-mix(in oklab, var(--foam-mist) 86%, var(--glacial-blue)), color-mix(in oklab, var(--foam-mist) 50%, var(--glacial-blue)));
  --river-milk: light-dark(color-mix(in oklab, var(--powder-aqua) 60%, var(--glacial-blue)), color-mix(in oklab, var(--river-teal) 62%, var(--slate-blue)));
  --river-ripple-light: light-dark(var(--powder-aqua), var(--river-teal));
  --river-ripple-dark: light-dark(var(--night-current), color-mix(in oklab, var(--night-current) 58%, black));
  --river-name: var(--foam-mist);                                     /* his name in the water */
  --river-name-edge: color-mix(in oklab, var(--night-current) 82%, transparent);
  --river-meadow-a: light-dark(#d5d8b6, #1d3d42);                     /* dry ridges, thin grass */
  --river-meadow-b: light-dark(#bccdaa, #183840);                     /* grass */
  --river-meadow-c: light-dark(#93b08f, #13323b);                     /* swales and old channels */
  --river-soil: light-dark(#cfc3a4, #2b4347);
  --river-floor: light-dark(#4e7663, #0f2b33);                        /* the ground under the wood */
  --river-tree-a: light-dark(#709a79, #25534f);
  --river-tree-b: light-dark(#54816b, #1d4749);
  --river-tree-c: light-dark(#90aa76, #2e5d52);
  --river-tree-light: light-dark(#b8ca93, #5f9090);                   /* the lit side of a crown; by night the moon on it */
  --river-tree-shade: light-dark(#274f46, #0c252e);
  --river-sand-dry: light-dark(#efe6cf, #62737a);
  --river-sand-wet: light-dark(#c9b993, #3f5258);
  --river-gravel: light-dark(#a9a18e, #37494f);
  --river-reed: light-dark(#87a172, #27514b);
  --river-scarp: light-dark(#7f705a, #1f3338);
  --river-log: light-dark(#cfc5ae, #6f8389);
  --river-shadow: light-dark(color-mix(in oklab, var(--night-current) 58%, black), color-mix(in oklab, var(--night-current) 24%, black));

  /* type: one family, two axes */
  --font: "Bahnschrift", sans-serif;
  --wght-text: 400;
  --wght-strong: 600;
  --wdth-text: 100%;
  --wdth-tight: 87.5%;
  --size-small: 0.9375rem;
  --size-text: 1.0625rem;
  --size-head: 1.3125rem;                  /* a heading inside a page (h3 of A1) */
  --size-title: 1.75rem;                   /* the title of a page (h2 of A1) */
  --size-mail: clamp(1.0625rem, 0.7rem + 1.5vw, 1.5rem);
  --size-lead: clamp(1.375rem, 0.9rem + 1.5vw, 2.0625rem);
  --lh-text: 1.5;
  --lh-loose: 1.7;
  --lh-lead: 1.36;
  --lh-title: 1.35;
  --lh-head: 1.3;
  --measure: 40rem;

  /* space */
  --s1: 0.375rem;
  --s2: 0.75rem;
  --s3: 1.25rem;
  --s4: 2rem;
  --s5: 3.5rem;
  --s6: 6rem;

  /* layout: the left bank of the stream is the one rule of the page */
  --bank: 6.25%;
  --tick: 1.25rem;
  --col-when: 7.75rem;
  --band-h: 4.5rem;                        /* the still river under the menu of every page but the home page */
  --hit: 2.75rem;                          /* 44 px: the smallest target for a finger */

  /* shape */
  --radius-in: 2px;
  --radius-out: 5px;
  --stroke: 1px;
  --ring: 2px;
  --bank-stroke: 1.5px;

  /* motion. Hover and focus change colour only (--dur-fast). The change of theme is the one larger
     motion (the owner's words of 2026-11-14): theme.js reads --dur-theme and --ease-theme for the
     circle that opens from the toggle, and the sun turns into the moon in --dur-icon. */
  --dur-fast: 120ms;
  --dur-icon: 420ms;
  --dur-theme: 520ms;
  --dur-live: 300ms;                       /* the moving river fades in over its still picture */
  --ease-live: linear;
  --ease-out: cubic-bezier(0.2, 0, 0, 1);
  --ease-theme: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);

  /* river art: the land fades into the page at the top and bottom, and at the sides on a very wide screen */
  --fade-edge: linear-gradient(to bottom, transparent, black 7%, black 93%, transparent);
  --fade-sides: linear-gradient(to right, transparent, black 5%, black 95%, transparent);
}
/* site.css: every rule of the site outside the token block. The tokens (section 1) are in
   tokens.css, which the layout loads before this file. Every colour, font, radius, duration
   and easing used here is a token.

   2. Base                        7. Records: rows, entries, small text
   3. The page, its rule, menu    8. About
   4. The river: hero and band    9. Projects
   5. Home                       10. Contact and the notice in the footer
   6. A reach: page title on the bank, content in the water
                                 11. Publications
                                 12. The menu (round 4, arrangement 1)
                                 13. Day and night: the theme toggle and the change of theme */

/* ---------------------------------------------------------------
   2. Base
   --------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scrollbar-color: var(--ink-2) var(--ground);
  scroll-padding-top: var(--s3);
}
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font);
  font-weight: var(--wght-text);
  font-stretch: var(--wdth-text);
  font-size: var(--size-text);
  line-height: var(--lh-text);
  font-kerning: normal;
  caret-color: var(--focus);
}
::selection { background: var(--bed); color: var(--on-bed); }
h1, h2, h3, p, ul, ol, dl, dd, figure, table { margin: 0; }
ul, ol { padding: 0; list-style: none; }
h1, h2, h3 { font-weight: var(--wght-strong); line-height: var(--lh-head); text-wrap: balance; }
p, figcaption, caption { text-wrap: pretty; }
img { display: block; max-width: 100%; height: auto; }
cite { color: var(--ink); }
a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: var(--stroke);
  text-underline-offset: 0.2em;
  text-decoration-color: var(--link-line);
}
@media (hover: hover) and (pointer: fine) {
  a { transition: text-decoration-color var(--dur-fast) var(--ease-out); }
  a:hover { text-decoration-color: var(--link-hover); }
}
:focus-visible {
  outline: var(--ring) solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--radius-in);
}
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.skip {
  position: absolute;
  z-index: 5;
  top: var(--s2);
  left: var(--s3);
  padding: var(--s1) var(--s2);
  background: var(--ground);
  transform: translateY(-400%);
}
.skip:focus { transform: none; }

/* His name, wherever it stands on the site, is set on the bed colour. */
.me {
  padding: 0.05em 0.3em;
  border-radius: var(--radius-in);
  background: var(--bed);
  color: var(--on-bed);
  font-weight: var(--wght-strong);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ---------------------------------------------------------------
   3. The page, its one rule (the left bank) and the menu
   --------------------------------------------------------------- */
.page {
  position: relative;
  max-width: 112rem;
  margin-inline: auto;
}
.page::before {
  content: "";
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  left: var(--bank);
  width: var(--stroke);
  background: var(--rule);
  pointer-events: none;
}

/* The menu is the same on every page: his name (the way home), then the twelve pages.
   Its rules are in section 12, at the end of this file. */

/* ---------------------------------------------------------------
   4. The river: the hero of the home page (the only moving part of the
      site, src/scripts/hero-river.js) and the still band of the other pages
   --------------------------------------------------------------- */
/* The box shows a still picture of the scene (public/hero/still-*.webp, by theme and width);
   hero-river.js draws the moving water on the canvas above it, and the letters are the SVG
   above both. The canvas shows only once the script has drawn it (class is-live). */
.river-art {
  position: relative;
  aspect-ratio: 16 / 7;
  max-height: 78vh;
  overflow: hidden;
  background-color: var(--ground);
  background-image: url("/hero/still-day.webp");
  background-size: cover;
  background-position: center;
  -webkit-mask-image: var(--fade-edge);
  mask-image: var(--fade-edge);
}
:root[data-theme="dark"] .river-art { background-image: url("/hero/still-night.webp"); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .river-art { background-image: url("/hero/still-night.webp"); }
}
.river-art > canvas,
.river-art > svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.river-art > canvas {
  opacity: 0;
  transition: opacity var(--dur-live) var(--ease-live);
}
.river-art.is-live > canvas { opacity: 1; }
/* the letters carry a thin dark edge of the same width on every screen, so foam never eats their outline */
.river-name path {
  fill: var(--river-name);
  stroke: var(--river-name-edge);
  stroke-width: 2px;
  stroke-linejoin: round;
  paint-order: stroke;
  vector-effect: non-scaling-stroke;
}
@media (max-width: 40rem) {
  .river-name path { stroke-width: 1.5px; }
  .river-art {
    aspect-ratio: 10 / 7;
    max-height: none;
    background-image: url("/hero/still-day-small.webp");
  }
  :root[data-theme="dark"] .river-art { background-image: url("/hero/still-night-small.webp"); }
}
@media (max-width: 40rem) and (prefers-color-scheme: dark) {
  :root:not([data-theme]) .river-art { background-image: url("/hero/still-night-small.webp"); }
}
@media (prefers-reduced-motion: reduce) {
  .river-art > canvas { transition: none; }
}

/* the band: a narrow reach of a river, drawn once and never moving (RiverBand.astro) */
.r-water { fill: var(--water); fill-rule: evenodd; }
.r-line {
  fill: none;
  stroke-width: var(--stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.r-bank { stroke: var(--shore); stroke-width: var(--bank-stroke); }
.t-slow { stroke: var(--trace-slow); }
.t-mid { stroke: var(--trace-mid); }
.t-fast { stroke: var(--trace-fast); }
.band { height: var(--band-h); overflow: hidden; }
.band > svg { display: block; width: 100%; height: 100%; }

@media (min-width: 112rem) {
  .river-art {
    -webkit-mask-image: var(--fade-edge), var(--fade-sides);
    mask-image: var(--fade-edge), var(--fade-sides);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
  }
  .band {
    -webkit-mask-image: var(--fade-sides);
    mask-image: var(--fade-sides);
  }
}

/* ---------------------------------------------------------------
   5. Home: the lead sentence, the note on the art with its pause
      button, and the way into the site
   --------------------------------------------------------------- */
.statement {
  max-width: 27em;
  font-size: var(--size-lead);
  line-height: var(--lh-lead);
  text-wrap: balance;
}
.flow { margin-top: var(--s4); }
.flow p {
  max-width: 24rem;
  color: var(--ink-2);
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
}
.btn {
  margin-top: var(--s2);
  padding: var(--s1) var(--s2);
  border: var(--stroke) solid var(--ink-2);
  border-radius: var(--radius-out);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--size-small);
  cursor: pointer;
}
.btn[hidden] { display: none; }
@media (hover: hover) and (pointer: fine) {
  .btn { transition: background-color var(--dur-fast) var(--ease-out); }
  .btn:hover { background-color: var(--wash); }
}
@media (pointer: coarse) {
  .btn, .masthead a { display: inline-flex; align-items: center; min-height: 2.75rem; }
}
@media (prefers-reduced-motion: reduce) {
  a, .btn { transition: none; }
}

/* the way into the site: one row for each page, its name on the left */
.rows.ways { gap: var(--s3); }
.ways a { justify-self: start; font-weight: var(--wght-strong); }
@media (pointer: coarse) {
  .ways > li { align-items: baseline; }
  .ways a { padding-block: var(--s2); }
}

/* ---------------------------------------------------------------
   6. A reach: the title of the page on the bank, its content in the water
   --------------------------------------------------------------- */
.reach { padding: var(--s5) var(--s3) var(--s5) calc(var(--bank) + var(--tick)); }
.lede { padding-top: var(--s3); }
.station { margin-bottom: var(--s3); }
.station h1,
.station h2 { position: relative; font-size: var(--size-title); overflow-wrap: break-word; }
.station h1::before,
.station h2::before {
  content: "";
  position: absolute;
  top: 0.65em;
  left: calc(-1 * var(--tick));
  width: calc(var(--tick) - var(--s1));
  height: var(--stroke);
  background: var(--rule);
}
@media (min-width: 62rem) {
  .reach {
    display: grid;
    grid-template-columns: var(--bank) minmax(0, 4fr) minmax(0, 10fr) var(--bank);
    padding-inline: 0;
  }
  .reach > .station,
  .reach > .flow {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    padding: 0 var(--s3) 0 var(--tick);
  }
  .reach > .water,
  .reach > .statement { grid-column: 3; grid-row: 1; }
  .station h1,
  .station h2 { position: sticky; top: var(--s3); }
}

.water h2 { font-size: var(--size-head); }
.water h3 { font-size: var(--size-text); }
.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--s2); }

/* ---------------------------------------------------------------
   7. Records: a date or a label on the left, the entry on the right
   --------------------------------------------------------------- */
.rows { display: grid; gap: var(--s4); max-width: 52rem; }
.rows > li,
.rows > div {
  display: grid;
  grid-template-columns: var(--col-when) minmax(0, 1fr);
  column-gap: var(--s3);
}
.when { color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* a definition list (DefinitionList): every dd of a row stands in the right column */
.rows > div > dd { grid-column: 2; }
.rows > div > dd + dd { margin-top: var(--s1); }
@media (max-width: 30rem) {
  .rows > li,
  .rows > div { grid-template-columns: minmax(0, 1fr); }
  .rows > div > dd { grid-column: auto; }
}
.entry-title { font-weight: var(--wght-strong); line-height: var(--lh-title); }
.byline {
  margin-top: var(--s1);
  color: var(--ink-2);
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
  line-height: var(--lh-loose);
}
.venue {
  color: var(--ink-2);
  font-size: var(--size-small);
  font-variant-numeric: tabular-nums;
}
.entry-text { margin-top: var(--s1); }
/* a shorter list (RecordList and DefinitionList with tight), and titled groups of records */
.rows.tight { gap: var(--s2); }
.group + .group { margin-top: var(--s5); }
.group > h2 + .rows { margin-top: var(--s3); }
.intro { max-width: var(--measure); margin-bottom: var(--s4); color: var(--ink-2); }
.meta {
  color: var(--ink-2);
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
}

/* ---------------------------------------------------------------
   8. About
   --------------------------------------------------------------- */
.about { display: grid; gap: var(--s4); }
@media (min-width: 40rem) {
  .about { grid-template-columns: minmax(0, 15rem) minmax(0, var(--measure)); align-items: start; }
}
.portrait {
  width: 100%;
  max-width: 15rem;
  border-radius: var(--radius-out);
  outline: var(--stroke) solid var(--rule-soft);
  outline-offset: calc(-1 * var(--stroke));
}
.path { margin-top: var(--s5); }
.path .rows { margin-top: var(--s3); gap: var(--s2); }

/* ---------------------------------------------------------------
   9. Projects
   --------------------------------------------------------------- */
.project + .project { margin-top: var(--s6); }
.project > * + * { margin-top: var(--s3); }
.project > h2 + .meta { margin-top: var(--s1); }
.project > p { max-width: var(--measure); }
.plate { max-width: 56rem; }
.plate img { width: 100%; border-radius: var(--radius-out); }
.plate figcaption,
caption {
  max-width: var(--measure);
  color: var(--ink-2);
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
  text-align: left;
}
.plate figcaption { margin-top: var(--s2); }
.table-wrap { max-width: 46rem; overflow-x: auto; }
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
  font-variant-numeric: tabular-nums;
}
caption { caption-side: top; padding-bottom: var(--s2); }
th, td {
  padding: var(--s1) var(--s2) var(--s1) 0;
  border-bottom: var(--stroke) solid var(--rule-soft);
  text-align: left;
  vertical-align: top;
  font-weight: var(--wght-text);
}
thead th { border-bottom-color: var(--rule); font-weight: var(--wght-strong); }
.num { padding-right: var(--s3); text-align: right; }
.slot {
  max-width: var(--measure);
  padding: var(--s4) var(--s3);
  border: var(--stroke) dashed var(--rule);
  border-radius: var(--radius-out);
  color: var(--ink-2);
}

/* ---------------------------------------------------------------
   10. Contact and the notice in the footer
   --------------------------------------------------------------- */
.mail { font-size: var(--size-mail); overflow-wrap: anywhere; }
.contact .rows { margin-top: var(--s4); gap: var(--s2); }
.contact .rows a { overflow-wrap: anywhere; }
.colophon { color: var(--ink-2); font-size: var(--size-small); }
.colophon p { max-width: var(--measure); }

/* ---------------------------------------------------------------
   11. Publications: the year rail, the year sections and the cards
   --------------------------------------------------------------- */

/* the year rail: a row of years under the title on a phone;
   on a wide screen a list that stays in view on the left bank, one
   tick on the rule of the page for each year */
.year-rail { margin-top: var(--s2); }
.year-rail ul { display: flex; flex-wrap: wrap; column-gap: var(--s3); }
.year-rail a {
  position: relative;
  display: inline-block;
  padding-block: var(--s1);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  text-decoration-line: none;
}
.year-rail a:hover,
.year-rail a:focus-visible { color: var(--ink); text-decoration-line: underline; }
.year-rail a[aria-current] { color: var(--ink); }
@media (min-width: 62rem) {
  .pin { position: sticky; top: var(--s3); }
  .year-rail { margin-top: var(--s4); }
  .year-rail ul { display: block; }
  .year-rail a { display: block; }
  .year-rail a::before {
    content: "";
    position: absolute;
    top: 50%;
    left: calc(-1 * var(--tick));
    width: calc(var(--tick) - var(--s1));
    height: var(--stroke);
    background: var(--rule);
  }
  .year-rail a[aria-current]::before { background: var(--current); }
}

/* the years: a heading with the number of papers and a line to the right edge, then the cards */
.years { display: flex; flex-direction: column; gap: var(--s5); }
.year-head {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin-bottom: var(--s3);
}
.year-head h2 { font-variant-numeric: tabular-nums; }
.year-head::after {
  content: "";
  flex: 1;
  align-self: center;
  height: var(--stroke);
  background: var(--rule-soft);
}

/* the cards: two columns on a phone, up to five in the widest page */
.papers {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(11rem, calc(50% - var(--s3))), 1fr));
  gap: var(--s4) var(--s3);
}
.papers > li { min-width: 0; }
.card { display: block; text-decoration-line: none; overflow-wrap: break-word; }

/* the first page of the paper: every sheet has one size (3 to 4), the page keeps
   its own proportions inside it, and its white takes the tint --sheet of the theme */
.sheet {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border: var(--stroke) solid var(--rule-soft);
  border-radius: var(--radius-in);
  background: var(--sheet);
  isolation: isolate;
}
.sheet img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}
/* a paper without a first page on file: the same sheet, set in type */
.sheet.is-type {
  padding: var(--s2);
  background: var(--wash);
  color: var(--ink-2);
  font-size: var(--size-small);
  font-stretch: var(--wdth-tight);
  line-height: var(--lh-head);
}
.sheet.is-type cite,
.sheet.is-type b { display: block; }
.sheet.is-type b { margin-top: var(--s2); color: var(--ink); font-weight: var(--wght-strong); }
/* a long title stops at a whole line with an ellipsis, never half a line at the foot of the sheet
   (seen at 375 px, 2026-11-14); the full title is printed under the sheet */
.sheet.is-type b {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  overflow: hidden;
}
@media (min-width: 48rem) {
  .sheet.is-type b { -webkit-line-clamp: 7; line-clamp: 7; }
}

/* Projects (Card with fit="cover"): wider cards, a 4 to 3 frame that the image fills,
   with no tint; a card that is not a link has no underline under its title */
.papers.is-wide { grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr)); }
.sheet.is-cover { aspect-ratio: 4 / 3; }
.sheet.is-cover img { object-fit: cover; mix-blend-mode: normal; }
.card.is-still .card-title { text-decoration-line: none; }

.card-title {
  display: block;
  margin-top: var(--s2);
  font-size: var(--size-small);
  font-weight: var(--wght-strong);
  font-stretch: var(--wdth-tight);
  line-height: var(--lh-title);
  text-decoration-line: underline;
  text-decoration-thickness: var(--stroke);
  text-underline-offset: 0.2em;
  text-decoration-color: var(--link-line);
}
.card .venue,
.card .meta { display: block; margin-top: var(--s1); font-stretch: var(--wdth-tight); }
.card:focus-visible .sheet { border-color: var(--focus); }

/* hover and focus change colour only */
@media (hover: hover) and (pointer: fine) {
  .year-rail a { transition: color var(--dur-fast) var(--ease-out); }
  .sheet { transition: border-color var(--dur-fast) var(--ease-out); }
  .card-title { transition: text-decoration-color var(--dur-fast) var(--ease-out); }
  a.card:hover .sheet { border-color: var(--link-hover); }
  a.card:hover .card-title { text-decoration-color: var(--link-hover); }
}
@media (pointer: coarse) {
  .year-rail a { display: inline-flex; align-items: center; min-height: 2.75rem; }
}
@media (prefers-reduced-motion: reduce) {
  .year-rail a,
  .sheet,
  .card-title { transition: none; }
}

/* ---------------------------------------------------------------
   12. The menu. Round 4, arrangement 1, "everything visible" (the
       owner's decision of 14 November 2026; mockup round4/menu-1):
       his name (the way home), then the twelve pages in three lists.
       The first list is about him, the second is his work and the
       third is Contact. The lists sit in one details element, which
       is closed in the HTML. No script is needed.
         under 48rem   his name and a "Menu" control on one line. The
                       control opens the lists, one page on a line
         from 48rem    no control. The lists are two rows under his
                       name, with Contact at the end of the second row.
                       The rows show although the element is closed
                       (::details-content). A browser without that
                       pseudo-element keeps the control, which opens
                       the rows as on a phone
         from 75rem    his name stands over the titles of the pages and
                       the two rows stand over their content (the
                       columns of section 6)
       The page that is open has a line under its name, and the list it
       belongs to is marked as well. Hover and focus change one colour.
       Nothing here moves and nothing fades.
   --------------------------------------------------------------- */
.masthead {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding: var(--s2) var(--s3) var(--s2) calc(var(--bank) + var(--tick));
}
.masthead a {
  display: inline-block;
  padding-block: var(--s1);
  border-bottom: var(--ring) solid transparent;
  text-decoration-color: transparent;
  transition: none;
}
.masthead a:hover,
.masthead a:focus-visible { text-decoration-color: var(--link-hover); }
.masthead a[aria-current="page"] { border-bottom-color: var(--current); text-decoration-color: transparent; }
.masthead > .home { justify-self: start; align-self: start; }
.menu > summary {
  width: fit-content;
  min-height: 2.75rem;
  margin-inline-start: auto;
  padding: calc((2.75rem - var(--lh-text) * 1em) / 2 - var(--stroke)) var(--s2);
  border: var(--stroke) solid var(--ink-2);
  border-radius: var(--radius-out);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .menu > summary:hover { background-color: var(--wash); }
}

/* a finger: every name in the menu is at least 44 px high and wide */
@media (pointer: coarse) {
  .masthead a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.75rem;
    min-height: 2.75rem;
  }
}

/* under 48rem: his name and the "Menu" control share one line, and the lists open under them.
   His name, the control and each page of the list are 44 px high: one line of text (1.5em)
   with the same padding above and below it, less the border where there is one. */
@media not all and (min-width: 48rem) {
  .masthead > .home,
  .masthead > .menu { grid-area: 1 / 1; }
  .masthead > .home {
    position: relative;
    z-index: 1;
    min-height: 2.75rem;
    padding-block: calc((2.75rem - var(--lh-text) * 1em) / 2 - var(--ring));
    border-top: var(--ring) solid transparent;
  }
  .menu-rows { padding-top: var(--s2); }
  .menu-rows ul + ul { margin-top: var(--s3); }
  .masthead .menu-rows a {
    position: relative;
    display: block;
    min-height: 2.75rem;
    padding-block: calc((2.75rem - var(--lh-text) * 1em) / 2);
    border-bottom: 0;
  }
  .masthead .menu-rows a[aria-current="page"] {
    text-decoration-color: var(--current);
    text-decoration-thickness: var(--ring);
  }
  /* the open list: one tick on the rule of the page for each of its pages, a strong one for the page that is open */
  .menu-rows a::before {
    position: absolute;
    top: calc(50% - var(--stroke) / 2);
    left: calc(-1 * var(--tick));
    width: calc(var(--tick) - var(--s1));
    height: var(--stroke);
    background: var(--rule);
  }
  .menu-rows ul:has(a[aria-current="page"]) a::before { content: ""; }
  .menu-rows a[aria-current="page"]::before {
    content: "";
    top: calc(50% - var(--ring) / 2);
    height: var(--ring);
    background: var(--current);
  }
}

/* from 48rem: everything shows, in two rows; Contact ends the second row */
@media (min-width: 48rem) {
  @supports selector(::details-content) {
    .menu > summary { display: none; }
    .menu::details-content { content-visibility: visible; }
  }
  .menu-rows {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    column-gap: var(--s3);
  }
  .menu-rows ul {
    display: flex;
    flex-wrap: wrap;
    column-gap: var(--s2);
    justify-self: start;
    border-bottom: var(--stroke) solid transparent;
  }
  .menu-rows ul:first-child { grid-column: 1 / -1; }
  .menu-rows ul:last-child { justify-self: end; }
  /* the open list: a line under its row; the line of the open page lies on it */
  .menu-rows ul:has(a[aria-current="page"]) { border-bottom-color: var(--rule); }
  .menu-rows li { margin-bottom: calc(-1 * var(--stroke)); }
}
@media (min-width: 62rem) {
  .masthead { padding-inline-end: var(--bank); }
  .menu-rows ul { column-gap: var(--s3); }
}
@media (min-width: 75rem) {
  .masthead {
    grid-template-columns: var(--bank) minmax(0, 4fr) minmax(0, 10fr) var(--bank);
    padding-inline: 0;
  }
  .masthead > .home { grid-column: 2; margin-inline-start: var(--tick); }
  .masthead > .menu { grid-column: 3; }
}

/* ---------------------------------------------------------------
   13. Day and night (the owner's words of 14 November 2026).
       theme.js sets data-theme on the html element; color-scheme picks
       the day or the night value of every light-dark() token.
       The toggle stands in the nav after the menu, 44 px square:
         under 48rem   on the line of his name, at the right, beside
                       the "Menu" control
         48 to 75rem   on the line of his name, at the right, over
                       the two rows of the menu
         from 75rem    in the right margin, on the line of the menu
       It shows the theme that is on: a sun by day, a moon by night.
       A press turns the one into the other (--dur-icon) while the
       page changes theme: a circle that opens from the toggle (View
       Transitions), else a cross-fade of the colours (.theme-fade),
       and no motion at all under prefers-reduced-motion.
   --------------------------------------------------------------- */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: var(--hit);
  height: var(--hit);
  padding: 0;
  border: var(--stroke) solid transparent;
  border-radius: var(--radius-out);
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.theme-toggle[hidden] { display: none; }
@media (hover: hover) and (pointer: fine) {
  .theme-toggle { transition: background-color var(--dur-fast) var(--ease-out); }
  .theme-toggle:hover { background-color: var(--wash); }
}
.sun-moon { display: block; overflow: visible; }
.sun-core { fill: currentColor; }
.sun-rays { fill: none; stroke: currentColor; stroke-width: 1.75px; stroke-linecap: round; }
.sun-core,
.sun-rays,
.moon-cut {
  transform-box: view-box;
  transform-origin: 12px 12px;
}
/* the icon moves only after a press (.is-pressed, set by theme.js), never when a page opens */
.is-pressed .sun-core { transition: transform var(--dur-icon) var(--ease-spring); }
.is-pressed .sun-rays { transition: transform var(--dur-icon) var(--ease-out), opacity var(--dur-icon) var(--ease-out); }
.is-pressed .moon-cut { transition: transform var(--dur-icon) var(--ease-theme); }
/* night: the disc grows, the rays turn away and fade, and the shadow slides in to leave a crescent */
:root[data-theme="dark"] .sun-core { transform: scale(1.7); }
:root[data-theme="dark"] .sun-rays { transform: rotate(-90deg) scale(0.5); opacity: 0; }
:root[data-theme="dark"] .moon-cut { transform: translate(-7.5px, 5.5px); }

.masthead > .theme-toggle {
  position: relative;
  z-index: 1;
  grid-area: 1 / 1;
  justify-self: end;
  align-self: start;
}
@media not all and (min-width: 48rem) {
  .menu > summary { margin-inline-end: calc(var(--hit) + var(--s2)); }
}
@media (min-width: 48rem) and (not (min-width: 75rem)) {
  .masthead > .home { grid-area: 1 / 1; }
  .masthead > .menu { grid-area: 2 / 1; }
}
@media (min-width: 75rem) {
  .masthead > .home { grid-row: 1; }
  .masthead > .menu { grid-row: 1; }
  .masthead > .theme-toggle { grid-area: 1 / 4; justify-self: center; }
}

/* the change of theme: the circle replaces the default cross-fade of a view transition */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
/* without View Transitions: every colour fades to its new value */
:root.theme-fade,
:root.theme-fade *,
:root.theme-fade *::before,
:root.theme-fade *::after {
  transition:
    background-color var(--dur-theme) var(--ease-theme),
    color var(--dur-theme) var(--ease-theme),
    border-color var(--dur-theme) var(--ease-theme),
    outline-color var(--dur-theme) var(--ease-theme),
    text-decoration-color var(--dur-theme) var(--ease-theme),
    fill var(--dur-theme) var(--ease-theme),
    stroke var(--dur-theme) var(--ease-theme);
}
@media (prefers-reduced-motion: reduce) {
  .theme-toggle,
  .is-pressed .sun-core,
  .is-pressed .sun-rays,
  .is-pressed .moon-cut { transition: none; }
}
