/* The forms drawn behind the fold are intonation contours, which is what the
 * dissertation measures. They are motivated rather than ornamental.
 *
 * The home page opens on a plum fold that carries the name, one line of
 * placement and the portrait, and nothing else. Below it the ground changes
 * hard to lilac paper and the page becomes a record. Every other page keeps the
 * rail and the footer and drops the fold.
 *
 * Colour never carries meaning alone: the current page is marked by a rule and
 * by weight, links stay underlined, and the accent is a mark rather than a fill.
 */

*, *::before, *::after { box-sizing: border-box; }
html { overflow-x: clip; -webkit-text-size-adjust: 100%; }
body { overflow-x: clip; margin: 0; }
h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img { max-width: 100%; height: auto; display: block; }

body {
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--text-base);
  line-height: 1.62;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--color-mark); }

a {
  color: var(--color-accent);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
}
a:hover { text-decoration-thickness: var(--rule-thick); }
a:active { color: var(--color-ink); }
:focus-visible { outline: var(--rule-thick) solid var(--color-focus); outline-offset: 3px; }
[aria-disabled="true"], :disabled { opacity: 0.55; cursor: not-allowed; }
em, i { font-style: italic; }

.skip {
  position: absolute; left: var(--space-xs); top: var(--space-xs);
  transform: translateY(-250%);
  background: var(--color-accent); color: var(--color-accent-ink);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--text-sm); text-decoration: none;
  z-index: var(--z-sticky);
}
.skip:focus { transform: none; }

.vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Small-caps apparatus. */
.mark, .defs dt, .mast__affil, .mast__lang {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  font-size: var(--text-xs);
  color: var(--color-muted);
}
/* Field separators are decided here, never in the markup. A comma joins fields
   inside one record; the footer note is three separate statements and takes a
   middot so they are not spliced into one sentence. */
.f + .f::before { content: ", "; }
.mark + .mark::before { content: " / "; color: var(--color-rule); }
.foot__note .f { display: block; }
.foot__note .f + .f::before { content: none; }

/* N3 · side rail ---------------------------------------------------------- */

.mast {
  background: var(--color-slab);
  color: var(--color-slab-ink);
}
.mast__inner {
  display: grid;
  gap: var(--space-sm) var(--space-lg);
  padding: var(--space-md) var(--page-gutter);
  align-items: baseline;
  grid-template-areas: "name icons" "nav nav" "lang lang";
  grid-template-columns: minmax(0, 1fr) auto;
}
.mast__portrait { display: none; }
.mast__name  { grid-area: name; }
.mast__nav   { grid-area: nav; }
.mast__lang  { grid-area: lang; }
.mast__icons { grid-area: icons; justify-self: end; }
.mast__affil { display: none; }

.mast__name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-md);
  line-height: 1.06;
  overflow-wrap: anywhere;
  min-width: 0;
}
.mast__name a { color: inherit; text-decoration: none; }
.mast__name a:hover { text-decoration-line: underline; }

.mast__nav ul {
  display: flex; flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
  align-items: baseline;
}
.mast__nav a {
  white-space: nowrap;
  font-size: var(--text-sm);
  font-weight: 400;
  color: color-mix(in oklch, var(--color-slab-ink) 84%, transparent);
  text-decoration-line: none;
  line-height: 1.2;
  padding-block-end: var(--space-3xs);
  border-block-end: var(--rule-thick) solid transparent;
  transition: color var(--dur-short) var(--ease-out);
}
.mast__nav a:hover { color: var(--color-slab-ink); border-block-end-color: var(--color-slab-rule); }
.mast__nav a[aria-current="page"] {
  color: var(--color-slab-ink);
  font-weight: 700;
  border-block-end-color: var(--color-accent);
}
.mast__lang { color: color-mix(in oklch, var(--color-slab-ink) 70%, transparent); }
.mast__lang a { color: inherit; }
.mast__icons { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); }
.mast__icons a {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 2.75rem; min-block-size: 2.75rem;
  color: color-mix(in oklch, var(--color-slab-ink) 84%, transparent);
  text-decoration: none;
}
.mast__icons a:hover { color: var(--color-accent); }

/* Under 26rem the five icon targets leave the name a column too narrow to set
   in, and it breaks one letter per line. Everything takes its own row. */
@media (max-width: 26rem) {
  .mast__inner {
    grid-template-areas: "name" "icons" "nav" "lang";
    grid-template-columns: minmax(0, 1fr);
  }
  .mast__icons { justify-self: start; }
}

/* From 60rem the bar becomes a fixed rail down the left edge and the page is
   inset to clear it. Below that width it stays in the flow as a band, which is
   also what keeps the Spanish navigation from overflowing: seven destinations
   set vertically never compete for a single line. */
@media (min-width: 60rem) {
  .mast {
    position: fixed; inset-block: 0; inset-inline-start: 0;
    inline-size: var(--rail);
    z-index: var(--z-sticky);
  }
  .mast__inner {
    block-size: 100%;
    grid-template-areas: "name" "lang" "nav" "icons" "affil";
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto 1fr auto auto;
    align-content: start; align-items: start;
    padding: var(--space-lg) var(--space-md);
    gap: var(--space-md);
    overflow-y: auto;
  }
  .mast__nav { align-self: center; }
  .mast__nav ul { flex-direction: column; gap: var(--space-2xs); }
  .mast__nav a { display: block; }
  .mast__lang { justify-self: start; }
  .mast__affil {
    display: block; grid-area: affil;
    color: color-mix(in oklch, var(--color-slab-ink) 60%, transparent);
    line-height: 1.5;
  }
  .mast__affil .f + .f::before { content: ""; display: block; }
  body { padding-inline-start: var(--rail); }
}

/* The fold ---------------------------------------------------------------- */

.fold {
  position: relative;
  background: var(--color-slab);
  color: var(--color-slab-ink);
  overflow: hidden;
  display: grid;
  /* Two columns at every width. The figure is cut out, so it can share the fold
     with the name instead of becoming a block the reader has to scroll past. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.52fr);
  column-gap: var(--space-lg);
  align-items: end;
  padding: var(--space-xl) var(--page-gutter) 0;
}
.fold__curves {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%;
  pointer-events: none; opacity: 0.42;
}
.fold__type { position: relative; padding-block-end: var(--space-xl); }
.fold__name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-name);
  line-height: 0.93;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
  min-width: 0;
}
.fold__name span { display: block; }
.fold__name span:first-child { font-weight: 800; }
.fold__stand {
  margin-block-start: var(--space-lg);
  max-width: 38ch;
  font-size: var(--text-md);
  line-height: 1.45;
  color: color-mix(in oklch, var(--color-slab-ink) 86%, transparent);
}
.fold__portrait { position: relative; justify-self: end; align-self: end; inline-size: 100%; }
.fold__portrait img, .fold__portrait .placeholder {
  inline-size: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  object-position: center 30%;
}
/* The portrait is cut out, so its own ground would show through as a panel.
   Only the placeholder carries one. */
.fold__portrait .placeholder { background: var(--color-slab-2); }
.fold__portrait .placeholder {
  background-image: repeating-linear-gradient(-45deg,
    color-mix(in oklch, var(--color-slab-ink) 9%, transparent) 0 1px,
    transparent 1px 14px);
  outline: var(--rule-hair) solid var(--color-slab-rule);
  outline-offset: -1px;
}

@media (min-width: 60rem) {
  .fold {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.85fr);
    column-gap: var(--space-3xl);
    padding-block: var(--space-2xl) 0;
  }
  .fold__type { padding-block-end: var(--space-3xl); }
}

/* Below the phone breakpoint the name needs the full width, so the figure
   shrinks to a corner piece rather than a column. */
@media (max-width: 30rem) {
  .fold { grid-template-columns: minmax(0, 1fr) minmax(0, 0.42fr); column-gap: var(--space-sm); }
  .fold__stand { font-size: var(--text-base); }
}

/* The hard colour change that ends the fold. */
/* The fold ends on a change of ground. No stroke is drawn across it. */

/* Document furniture ------------------------------------------------------ */

main { padding-block-end: var(--space-3xl); }
.doc { max-width: 82rem; margin-inline: auto; padding: var(--space-2xl) var(--page-gutter) 0; }
.doc--home { max-width: none; padding-block-start: var(--space-3xl); }
.doc--home > .sec { max-width: 82rem; margin-inline: auto; }

.doc__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-display);
  line-height: 1.02;
  letter-spacing: -0.015em;
  overflow-wrap: anywhere;
  min-width: 0;
  margin-block-end: var(--space-sm);
}
.doc__intro {
  max-width: var(--measure);
  color: var(--color-muted);
  padding-block-end: var(--space-md);
  margin-block-end: var(--space-2xl);
}

.sec { margin-block-start: var(--space-2xl); }
/* Only a section that directly follows the page intro loses its top margin.
   The CV puts an identity block between the two, and zeroing it there ran the
   Education heading into the email row. */
.doc__intro + .sec { margin-block-start: 0; }
.doc--home > .sec:first-of-type { margin-block-start: 0; }
.sec__title {
  font-weight: 700;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  line-height: 1.2;
  color: var(--color-muted);
  padding-block-end: var(--space-2xs);
  border-block-end: var(--rule-hair) solid var(--color-rule);
  margin-block-end: var(--space-lg);
}

/* The profile prose, justified. */
.prose, .intro__prose { max-width: var(--measure); }
.prose > * + *, .intro__prose > * + * { margin-block-start: var(--space-md); }
.prose p, .intro__prose p { text-align: justify; text-justify: inter-word; hyphens: auto; }

@media (min-width: 60rem) {
  .intro__prose {
    max-width: none;
    columns: 2;
    column-gap: var(--space-3xl);
  }
  .intro__prose p { max-width: var(--measure); break-inside: avoid; }
  .intro__prose > * + * { margin-block-start: 0; }
}

/* The field is a centred column of justified text at the same size as the four
   methods below it, which sit in a 2x2 grid. Its name sits above the paragraph
   rather than leading it; that, and nothing else, marks it apart. */
.field {
  max-width: 58ch;
  margin-inline: auto;
  margin-block-end: var(--space-xl);
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
}
.field .line__title { display: block; text-align: center; margin-block-end: var(--space-2xs); }
.field .line__title::after { content: none; }

/* The four methods read as four paragraphs, each led by its name in bold. One
   size for all of them. */
.lines { display: grid; gap: var(--space-lg); }
.lines > div { max-width: none; }
.line__title {
  display: inline;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: inherit;
  line-height: inherit;
  overflow-wrap: anywhere;
}
.line__title::after { content: "."; }
.lines p {
  display: inline;
  color: var(--color-ink);
}
.lines > div {
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
}
@media (min-width: 60rem) {
  .lines { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-lg) var(--space-2xl); }
}

.group { margin-block-start: var(--space-2xl); }
.group:first-of-type { margin-block-start: 0; }
.group__year {
  font-family: var(--font-display);
  font-weight: 500; font-size: var(--text-xl);
  line-height: 1;
  margin-block-end: var(--space-md);
  max-width: 4ch;
}

.entries { display: grid; gap: var(--space-xl); max-width: var(--measure-wide); }
/* Records carry no left rule. A full-height hairline beside every entry reads
   as a margin the page does not have; the space between entries does the work. */
.entry__t, .entry__title {
  font-weight: 600; font-size: var(--text-md); line-height: 1.25;
  overflow-wrap: anywhere; min-width: 0;
}
.entry__cite a { color: var(--color-ink); text-decoration-color: var(--color-rule); }
.entry__cite a:hover { color: var(--color-accent); text-decoration-color: currentColor; }
.entry__meta, .entry__detail { color: var(--color-muted); font-size: var(--text-sm); }
.entry__marks { margin-block-start: var(--space-2xs); }
/* An invited talk or a poster is a label on the record, so it is set apart from
   the thematic marks beside it. A tinted chip, no border, no rule. */
.mark--kind {
  background: var(--color-paper-3);
  color: var(--color-ink);
  padding: 0.15em 0.5em;
}
.mark--kind + .mark::before { content: ""; padding-inline-start: var(--space-2xs); }

/* Publications keep the citation at reading size; the title inside it is the
   only thing that grows. */
.entry__cite { font-size: var(--text-base); line-height: 1.55; }
/* A talk and a publication are the same kind of record and read at the same
   size; the talk title was a step larger and made the two pages disagree. */
.entry--talk .entry__title { font-size: var(--text-base); }
.entry--pub .entry__t, .entry__cite .entry__t { font-size: inherit; font-weight: 600; }
/* The CV is one size from top to bottom. A title, a fact, a citation and a
   bullet are all the same kind of thing on this page; weight and colour do the
   distinguishing, never size. */
.p-cv .entries { gap: var(--space-lg); }
.p-cv .entry__title,
.p-cv .entry__cite,
.p-cv .entry__meta,
.p-cv .entry__detail,
.p-cv .entry__when,
.p-cv .bullets { font-size: var(--text-base); }
.p-cv .entry__cite { line-height: 1.55; }
.p-cv .entry__when { letter-spacing: 0.04em; text-transform: none; font-weight: 400; }
.sec__sub {
  font-weight: 600; font-size: var(--text-xs);
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--color-neutral);
  margin-block: var(--space-xl) var(--space-md);
}
.sec__title + .sec__sub { margin-block-start: 0; }

/* One fact per line rather than a comma run. */
.entry__meta--stack .f { display: block; }
.entry__meta--stack .f + .f::before { content: none; }

/* Teaching and service share one record shape: the dates take their own
   column so a record reads as a record instead of as a string. */
.entry--teach { display: grid; gap: var(--space-2xs); }
.entry__when {
  font-weight: 600; font-size: var(--text-xs);
  letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--color-muted);
}
.entry__dates { display: block; letter-spacing: 0.06em; text-transform: none; }
.entry__body > * + * { margin-block-start: var(--space-2xs); }
.entry__body .entry__detail { margin-block-start: var(--space-xs); }
@media (min-width: 40rem) {
  .entry--teach { grid-template-columns: 8.5rem minmax(0, 1fr); gap: var(--space-lg); }
}

/* Bullets on the CV read as a list, one step down from the post they sit under. */
.bullets {
  list-style: disc;
  padding-inline-start: 1.1em;
  margin-block-start: var(--space-xs);
  display: grid; gap: var(--space-2xs);
  font-size: var(--text-sm);
  color: var(--color-muted);
  max-width: var(--measure);
}
.bullets li { list-style: inherit; }
.bullets li::marker { color: var(--color-rule); }

/* An aside in her voice, set apart from the record by measure and by size. */
.aside {
  max-width: 52ch;
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin-block-end: var(--space-2xl);
}

/* Reading lists: APA references with a hanging indent, at the size of the rest
   of the page. The DOI sits under its reference rather than inside the run of
   the sentence. */
.reading {
  display: grid; gap: var(--space-md);
  max-width: var(--measure-wide);
  margin-block-end: var(--space-xl);
}
.reading__item {
  padding-inline-start: 1.6em;
  text-indent: -1.6em;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.reading__doi { display: block; text-indent: 0; font-size: var(--text-sm); color: var(--color-muted); }
.reading__doi:hover { color: var(--color-accent); }
.reading--links .reading__item { padding-inline-start: 0; text-indent: 0; }
.course__meta { margin-block-end: var(--space-xl); }
/* The intro and the course facts are one statement, and the two closing notes
   are one block: both pairs sit closer than a section break. */
.p-course_mq .doc__intro { padding-block-end: 0; margin-block-end: var(--space-lg); }
.p-course_mq .aside { margin-block-end: var(--space-lg); }
.p-course_mq .sec__sub { margin-block: var(--space-lg) var(--space-sm); }
.p-course_mq .materials { margin-block: var(--space-xs) var(--space-lg); }

.materials { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-md);
  margin-block: var(--space-xs) var(--space-lg); }
.materials a { font-size: var(--text-sm); }

/* Outreach sits after the research list, separated by a rule rather than a year. */
.sec--outreach { margin-block-start: var(--space-4xl); }
.peer-note { color: var(--color-muted); font-size: var(--text-sm); margin-block-start: var(--space-lg); }

.defs { display: grid; gap: var(--space-sm); max-width: var(--measure); }
.defs > div { display: grid; gap: var(--space-3xs); }
@media (min-width: 40rem) {
  .defs > div { grid-template-columns: 7rem minmax(0, 1fr); gap: var(--space-lg); align-items: baseline; }
}
.defs dd { margin: 0; }

/* Contact. The icon never carries the meaning alone: it sits beside its name. */
.profiles { display: grid; gap: var(--space-sm); max-width: var(--measure); }
.profile { display: flex; align-items: baseline; gap: var(--space-sm); flex-wrap: wrap; }
.profile a {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-sm);
  overflow-wrap: anywhere; min-width: 0;
}
.profile__label { color: var(--color-muted); font-size: var(--text-sm); }
/* The label column only earns a fixed width once there is room for it. */
@media (min-width: 30rem) { .profile__label { min-inline-size: 8rem; } }
.profile .ico { flex: none; align-self: center; }
.ico {
  inline-size: 1.15rem; block-size: 1.15rem;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.ico--solid { fill: currentColor; stroke: none; }

.tlink {
  display: inline-flex; align-items: center;
  min-block-size: 2.75rem;
  font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.1em;
  font-size: var(--text-sm);
  color: var(--color-ink);
  text-decoration-line: underline;
  text-decoration-thickness: var(--rule-thick);
  text-decoration-color: var(--color-accent);
  text-underline-offset: 0.4em;
  white-space: nowrap; line-height: 1.4;
}
.tlink:hover { color: var(--color-accent); }
.more { margin-block-start: var(--space-xl); }

/* Ft1 · mast-headed ------------------------------------------------------- */

.foot {
  margin-block-start: var(--space-3xl);
  background: var(--color-slab);
  color: var(--color-slab-ink);
}
.foot__inner {
  max-width: 82rem; margin-inline: auto;
  padding: var(--space-2xl) var(--page-gutter);
  padding-block-end: max(var(--space-2xl), env(safe-area-inset-bottom));
  display: grid; gap: var(--space-md);
  grid-template-columns: minmax(0, 1fr) auto;
}
.foot__inner > p { grid-column: 1; }
.foot__name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-xl); line-height: 1.02;
  overflow-wrap: anywhere; min-width: 0;
}
.foot__reach { font-size: var(--text-md); }
.foot__icons { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm); }
.foot__icons a {
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 2.75rem; min-block-size: 2.75rem;
  color: var(--color-slab-ink); text-decoration: none;
  border: var(--rule-hair) solid var(--color-slab-rule);
}
.foot__icons a:hover { border-color: var(--color-accent); }
/* The colophon carries two sprites, one animation per page, from the PMD Collab
   sheets. A steps() walk across a horizontal strip: no script, no third-party
   request, and they hold on the first frame for anyone who has asked for less
   motion. Frames are cropped to what is drawn, so the two creatures sit at
   comparable heights whatever the animation pads its frames to.

   Each animation declares its frame size and step count; --s is the scale, so a
   narrow viewport shrinks both creatures without touching either strip. Two
   wide animations at full size overflowed a 320px screen.

   Durations come from the sheets' own frame timings, with one exception: rotate
   spins nine frames in 0.3s, which reads as a blur at this scale, and is
   stretched to 1.2s. */
.sprites {
  --s: 3;
  grid-column: 2; grid-row: 1 / span 3;
  align-self: center; justify-self: end;
  display: flex; align-items: flex-end; gap: var(--space-lg);
}
.sprite {
  inline-size: calc(var(--w) * var(--s) * 1px);
  block-size: calc(var(--h) * var(--s) * 1px);
  background-size: calc(var(--w) * var(--s) * var(--steps) * 1px)
                   calc(var(--h) * var(--s) * 1px);
  image-rendering: pixelated;
  background-repeat: no-repeat;
  animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) { .sprite { animation: none; } }
@media (max-width: 40rem) { .sprites { --s: 2; gap: var(--space-md); } }
@media (max-width: 26rem) { .sprites { --s: 1.6; gap: var(--space-sm); } }

.sprite--idle {
  --w: 26; --h: 25; --steps: 27;
  background-image: url("/static/img/sprite-idle.png");
  animation-name: anim-sprite-idle;
  animation-duration: 0.9s;
  animation-timing-function: steps(27);
}
@keyframes anim-sprite-idle {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--walk {
  --w: 26; --h: 25; --steps: 18;
  background-image: url("/static/img/sprite-walk.png");
  animation-name: anim-sprite-walk;
  animation-duration: 0.6s;
  animation-timing-function: steps(18);
}
@keyframes anim-sprite-walk {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--double {
  --w: 46; --h: 26; --steps: 36;
  background-image: url("/static/img/sprite-double.png");
  animation-name: anim-sprite-double;
  animation-duration: 0.6s;
  animation-timing-function: steps(36);
}
@keyframes anim-sprite-double {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--charge {
  --w: 21; --h: 18; --steps: 10;
  background-image: url("/static/img/sprite-charge.png");
  animation-name: anim-sprite-charge;
  animation-duration: 0.33s;
  animation-timing-function: steps(10);
}
@keyframes anim-sprite-charge {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--withdraw {
  --w: 22; --h: 30; --steps: 24;
  background-image: url("/static/img/sprite-withdraw.png");
  animation-name: anim-sprite-withdraw;
  animation-duration: 0.4s;
  animation-timing-function: steps(24);
}
@keyframes anim-sprite-withdraw {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--sleep {
  --w: 22; --h: 20; --steps: 2;
  background-image: url("/static/img/sprite-sleep.png");
  animation-name: anim-sprite-sleep;
  animation-duration: 1.17s;
  animation-timing-function: steps(2);
}
@keyframes anim-sprite-sleep {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--rotate {
  --w: 22; --h: 26; --steps: 9;
  background-image: url("/static/img/sprite-rotate.png");
  animation-name: anim-sprite-rotate;
  animation-duration: 1.2s;
  animation-timing-function: steps(9);
}
@keyframes anim-sprite-rotate {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-idle {
  --w: 28; --h: 21; --steps: 71;
  background-image: url("/static/img/trubbish-idle.png");
  animation-name: anim-trubbish-idle;
  animation-duration: 1.18s;
  animation-timing-function: steps(71);
}
@keyframes anim-trubbish-idle {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-walk {
  --w: 28; --h: 28; --steps: 12;
  background-image: url("/static/img/trubbish-walk.png");
  animation-name: anim-trubbish-walk;
  animation-duration: 0.4s;
  animation-timing-function: steps(12);
}
@keyframes anim-trubbish-walk {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-double {
  --w: 54; --h: 21; --steps: 36;
  background-image: url("/static/img/trubbish-double.png");
  animation-name: anim-trubbish-double;
  animation-duration: 0.6s;
  animation-timing-function: steps(36);
}
@keyframes anim-trubbish-double {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-charge {
  --w: 29; --h: 21; --steps: 10;
  background-image: url("/static/img/trubbish-charge.png");
  animation-name: anim-trubbish-charge;
  animation-duration: 0.33s;
  animation-timing-function: steps(10);
}
@keyframes anim-trubbish-charge {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-withdraw {
  --w: 18; --h: 22; --steps: 12;
  background-image: url("/static/img/trubbish-withdraw.png");
  animation-name: anim-trubbish-withdraw;
  animation-duration: 0.8s;
  animation-timing-function: steps(12);
}
@keyframes anim-trubbish-withdraw {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-sleep {
  --w: 26; --h: 19; --steps: 2;
  background-image: url("/static/img/trubbish-sleep.png");
  animation-name: anim-trubbish-sleep;
  animation-duration: 1.17s;
  animation-timing-function: steps(2);
}
@keyframes anim-trubbish-sleep {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.sprite--t-rotate {
  --w: 28; --h: 26; --steps: 9;
  background-image: url("/static/img/trubbish-rotate.png");
  animation-name: anim-trubbish-rotate;
  animation-duration: 1.2s;
  animation-timing-function: steps(9);
}
@keyframes anim-trubbish-rotate {
  to { background-position: calc(var(--w) * var(--s) * var(--steps) * -1px) 0; }
}

.foot__note {
  color: color-mix(in oklch, var(--color-slab-ink) 68%, transparent);
  font-size: var(--text-sm);
  max-width: var(--measure-wide);
  margin-block-start: var(--space-lg);
}
.foot a { color: var(--color-slab-ink); }
.foot a:hover { color: var(--color-accent); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

@media print {
  .mast, .skip, .foot__icons, .fold__curves, .fold__portrait { display: none; }
  body { background: var(--color-paper-print); color: var(--color-ink-print); padding-inline-start: 0; }
  .fold, .foot { background: none; color: var(--color-ink-print); }
  a { text-decoration: none; }
}
