/* Breakpoints. A custom property cannot go in a media query, so these are written out where they are used, and a test
   fails on a width that is not on this list. Phone is below 768, tablet is 768 to 1023, desktop is from 1024.
   767   phone: the masthead's theme switch shares the title's row; ledger rows stack; the footer's columns pair up;
         folds, portraits, About's frames and case cards take their compact look; tabs tighten
   768   tablet: the masthead puts the switch in its own column; paired boxes go side by side; ledger rows and the
         footer go to a row; figure strips run in one row
   1024  desktop: the island panels sit in two columns and the just-landed tiles go nine across (below it they are a sideways-scrolling row of 124px tiles); the footer brand sits
         beside its columns; the masthead shows the site note beside the title (below it every page, the island
         included, keeps the note in the "i" hint)
   The island canvas is sized by its own frame (container queries at 611px and 844px of frame width, from the
   script's geometry). Sized by their own content, with no named width: the species cards (150px), the guest list, the case members, the
   reader chips, the fluid wordmark, title, chart height and portrait clamps, and the leaderboard's filter row. */
/* Fonts are self-hosted (SIL OFL), latin subset: Instrument Serif, Instrument Sans, JetBrains Mono. */
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/instrument-serif-latin-400-normal.5eb09b5ac0.woff2) format("woff2");
}
@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/instrument-serif-latin-400-italic.5a51946dff.woff2) format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/instrument-sans-latin-wght-normal.2ee17598a9.woff2) format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/instrument-sans-latin-wght-italic.77210cdde0.woff2) format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url(fonts/jetbrains-mono-latin-wght-normal.18be452724.woff2) format("woff2");
}
@font-face {
  font-family: "Instrument Serif Fallback";
  src: local("Georgia"), local("Iowan Old Style"), local("Palatino Linotype");
  size-adjust: 76.4%;
}

/* Each colour that changes with the theme is written once, light value then dark value, as
   `var(--if-light, LIGHT) var(--if-dark, DARK)`. In the light theme --if-dark is an empty value (so its half drops
   out) and --if-light is unset (so its fallback shows); the dark theme, forced or from the system, swaps the two.
   That is all the two dark blocks below say. light-dark() would do it in one function, but it needs Chrome 123, Safari
   17.5 or Firefox 120, and this stylesheet already works back to Chrome 111 and Safari 16.2. */
:root {
  --if-dark: ;
  --paper: var(--if-light, #ffffff) var(--if-dark, #0b0f19);
  --ink: var(--if-light, #111827) var(--if-dark, #f3f4f6);
  --panel: var(--if-light, #f1f3f6) var(--if-dark, #161c2a);
  --muted: var(--if-light, #5b6472) var(--if-dark, #9aa4b5);
  --alert: var(--if-light, #c81e4a) var(--if-dark, #ff7d96);
  --ok: var(--if-light, #0f766e) var(--if-dark, #5fd3c4);
  --soft: var(--if-light, rgba(17, 24, 39, 0.16)) var(--if-dark, rgba(243, 244, 246, 0.18));
  --water: var(--if-light, #86c5d0) var(--if-dark, #16233f);
  --shadow: rgba(20, 24, 20, 0.22);
  --card-paper: #f3f4f6;
  --card-soft: #c5cad3;
  --display: "Instrument Serif", "Instrument Serif Fallback", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
    serif;
  --body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --data: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
  box-sizing: border-box;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --if-light: ;
    --if-dark: initial;
  }
}
:root[data-theme="dark"] {
  --if-light: ;
  --if-dark: initial;
}
/* Sizes, layers and timings already in use, named by their value. Only values that repeat on a scale are here: the
   odd ones (13.5px and 14.5px type, 7px and 18px spacing and the like) stay literal until they are folded onto it. */
:root {
  --space-2: 2px;
  --space-4: 4px;
  --space-6: 6px;
  --space-8: 8px;
  --space-10: 10px;
  --space-12: 12px;
  --space-14: 14px;
  --space-16: 16px;
  --space-20: 20px;
  --space-24: 24px;
  --space-32: 32px;
  --space-40: 40px;
  --space-48: 48px;
  --space-64: 64px;
  --text-10: 10px;
  --text-11: 11px;
  --text-12: 12px;
  --text-13: 13px;
  --text-14: 14px;
  --text-15: 15px;
  --text-16: 16px;
  --text-17: 17px;
  --text-18: 18px;
  --text-19: 19px;
  --text-20: 20px;
  --text-22: 22px;
  --text-24: 24px;
  --text-26: 26px;
  --text-28: 28px;
  --text-30: 30px;
  --text-32: 32px;
  --text-34: 34px;
  --z-2: 2;
  --z-5: 5;
  --z-10: 10;
  --z-20: 20;
  --z-50: 50;
  --z-100: 100;
  --z-200: 200;
  --dur-120: 120ms;
  --dur-150: 0.15s;
  --dur-180: 0.18s;
  --dur-400: 0.4s;
  --dur-800: 0.8s;
  /* Names by role, for the layout notes: each is defined on a number from the scale above, so changing one moves every
     place that plays the role. Spacing first: under the tabs, the title, a section, a subsection, a lead, a heading, a label,
     a block, columns, and a pair of boxes. */
  --gap-under-tabs: var(--space-14);
  --title-gap: var(--space-10);
  --title-icon-gap: var(--space-8);
  --gap-section: var(--space-32);
  --gap-subsection: var(--space-20);
  --gap-lead: var(--space-20);
  --gap-heading: var(--space-10);
  --gap-label: var(--space-8);
  --gap-block: var(--space-10);
  --gap-columns: var(--space-40);
  --gap-pair: var(--space-24);
  /* Boxes: the border every box and control wears (full, thin and dashed), the rule between rows, the padding inside a card, the gap between
     cards, the padding of a row, the padding of a table cell, and the least height of anything you can press. */
  --line: 2px solid var(--ink);
  --line-soft: 1px solid var(--soft);
  --line-thin: 1px solid var(--ink);
  --line-dashed: 2px dashed var(--ink);
  --card-pad: var(--space-12) var(--space-14);
  --card-gap: var(--space-12);
  --row-pad: var(--space-10) var(--space-14);
  --cell-pad: var(--space-6) var(--space-10);
  --tap: 44px;
  /* Portraits are 22 by 16 frame pixels. These are the widths inside the 2px border, so each frame pixel is a whole
     number of CSS pixels: 2, 3 and 4 to a pixel (48, 70 and 92px outside), 5 for a feature (114px outside), 8 for the
     species page (180px outside), and 1 for a dot in the Alignment chart on a phone (26px outside). */
  --mug-xs: 22px;
  --mug-s: 44px;
  --mug-m: 66px;
  --mug-l: 88px;
  --mug-xl: 110px;
  --mug-xxl: 176px;
  /* Type by role. Each is defined on a size from the scale above: titles, card titles, body, compact and small text, captions, labels, caps, data and figures (and the figure row). */
  --text-title: clamp(32px, 8vw, 38px);
  --text-heading: var(--text-28);
  --text-subheading: var(--text-24);
  --text-card-title: var(--text-22);
  --text-body: var(--text-16);
  --text-small: var(--text-14);
  --text-compact: var(--text-15);
  --text-caption: var(--text-13);
  --text-label: var(--text-12);
  --text-caps: var(--text-11);
  --text-data: var(--text-13);
  --text-figure: var(--text-32);
  --text-figure-row: var(--text-28);
  --text-wordmark: 76px;
  --text-wordmark-small: clamp(30px, 11.5vw, 60px);
  --text-tagline: clamp(20px, 5.4vw, 26px);
  /* The page frame and how wide running text goes. The masthead, tab row and footer are the page width less a gutter
     each side. */
  --page-width: 1204px;
  --page-gutter: var(--space-16);
  --measure: 34em;
}
@media (min-width: 768px) {
  :root {
    --page-gutter: var(--space-24);
  }
}
html {
  scroll-padding-top: calc(env(safe-area-inset-top, 0px) + 56px);
  scrollbar-gutter: stable;
}
html:has(body.full) {
  scrollbar-gutter: auto;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--text-body) / 1.45 var(--body);
}
body.full {
  overflow: hidden;
}
/* The frame every page shares: the masthead, the tab row, the page and the footer sit in one 1180px column. */
header.mast,
.navbar .tabs {
  width: min(calc(var(--page-width) - 2 * var(--page-gutter)), calc(100% - 2 * var(--page-gutter)));
  margin-left: auto;
  margin-right: auto;
}
body > main {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0 var(--page-gutter) var(--space-24);
}

/* The masthead scrolls away. Only the tab row under it sticks. */
.mast {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--space-4) var(--space-12);
  margin-top: var(--space-16);
  margin-bottom: var(--space-6);
  padding-bottom: var(--space-10);
  border-bottom: var(--line);
}
.mast .title {
  grid-area: title;
}
.mast .theme-toggle {
  grid-area: theme;
  justify-self: end;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  min-height: 0;
  padding: 0;
}
.theme-toggle .theme-icon {
  display: none;
  grid-area: 1 / 1;
}
:root[data-theme-choice="light"] .theme-icon[data-icon="light"],
:root[data-theme-choice="dark"] .theme-icon[data-icon="dark"],
:root:not([data-theme-choice="light"]):not([data-theme-choice="dark"]) .theme-icon[data-icon="system"] {
  display: block;
}
@media (min-width: 768px) {
  .mast {
    grid-template-areas: "title sim theme";
    align-items: start;
  }
  .mast .sim {
    align-self: start;
    white-space: nowrap;
  }
}
.mast .wordmark {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--text-wordmark);
  line-height: 0.95;
  letter-spacing: -0.01em;
}
.mast .wordmark a {
  color: var(--ink);
  text-decoration: none;
}
.mast .sub {
  margin: var(--space-6) 0 0;
  font-family: var(--display);
  font-style: italic;
  font-size: var(--text-tagline);
  line-height: 1.2;
  position: relative;
}
.mast .mast-note {
  display: none;
  color: var(--muted);
}
.mast .sim {
  grid-area: sim;
  justify-self: end;
  margin: 0;
  font-size: var(--text-caption);
  line-height: 1.35;
  color: var(--alert);
  font-weight: 600;
}
.mast .sim[hidden] {
  display: none;
}
/* Phone widths: the switch shares the title's row, right-aligned, and the wordmark shrinks to fit beside it. */
@media (max-width: 767px) {
  .mast {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "sim" "title";
    row-gap: 0;
  }
  .mast .sim {
    margin-bottom: var(--space-4);
  }
  .mast .theme-toggle {
    grid-area: title;
    align-self: start;
    position: relative;
    /* Above the title, which shares this cell and comes later in the page. */
    z-index: var(--z-2);
  }
  .mast .theme-toggle::after {
    content: "";
    position: absolute;
    inset: -2px;
  }
  .mast .wordmark {
    display: flex;
    align-items: center;
    min-height: 40px;
    padding-right: 52px;
    font-size: var(--text-wordmark-small);
  }
}
/* Full desktop width: the title, the site note as plain text, and the switch in one row. The note takes what the title
   and the switch leave, and the "i" hint is hidden (display: none) so the note is read out once. The simulated marker
   drops to a second row under the note and the switch, and only takes room when it is shown. */
@media (min-width: 1024px) {
  .mast {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "title note theme";
    column-gap: var(--gap-columns);
  }
  .mast .mast-note {
    display: block;
    grid-area: note;
    max-width: var(--measure);
    margin: var(--space-8) 0 0;
    font-size: var(--text-compact);
    font-weight: 400;
    line-height: 1.5;
    text-align: left;
  }
  .mast .sub .hint {
    display: none;
  }
  .mast .sim {
    grid-area: auto;
    grid-column: 2 / -1;
    grid-row: 2;
  }
}
.mast a:focus-visible,
.navbar a:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}

.navbar {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: var(--z-5);
  margin: 0 0 var(--gap-under-tabs);
  padding: var(--space-6) 0;
  background: var(--paper);
}
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
}
.tabs a {
  display: inline-flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: 0 var(--space-4);
  border: var(--line);
  background: var(--paper);
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}
.tabs a[aria-current="page"] {
  background: var(--ink);
  color: var(--paper);
}
@media (max-width: 767px) {
  .tabs {
    gap: var(--space-4);
  }
}

.stage {
  margin: 0;
}
.glass {
  container-type: inline-size;
  position: relative;
  overflow: hidden;
  border: var(--line);
  box-shadow: 4px 4px 0 var(--ink);
  background: var(--water);
  line-height: 0;
}
canvas {
  display: block;
  width: 100%;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
}
#island {
  /* The height the script sets, so the canvas has it at first paint: 336 under 611 island pixels, 355 from there, and
     twice both from 844px of frame, where the script draws two device pixels to each island pixel. In a window too short
     for that the frame is as tall as the window allows, down to 336px, and the script crops the scene from the top.
     The 150px is the tab row, the gap and the ticker. */
  height: 336px;
  image-rendering: crisp-edges;
  image-rendering: pixelated;
  outline: none;
}
#island:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: -5px;
}
@container (min-width: 611px) {
  #island {
    height: 355px;
  }
}
@container (min-width: 844px) {
  #island {
    height: clamp(336px, 100dvh - 150px, 672px);
  }
}

/* Controls and windows that float over the island. */
.hud {
  position: absolute;
  top: 8px;
  display: flex;
  gap: var(--space-8);
  flex-wrap: wrap;
  line-height: 1.4;
}
.hud-tools {
  left: 8px;
}
.hud-feed {
  right: 8px;
  justify-content: flex-end;
}
.hud button.sq {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  min-width: 36px;
  height: 36px;
  min-height: 36px;
  padding: 0;
}
.hud button.sq svg {
  display: block;
}
.hud button:disabled {
  opacity: 0.45;
  cursor: default;
}
.hud button,
.card,
.feed {
  box-shadow: 3px 3px 0 var(--ink);
}
@media (max-width: 767px) {
  .glass.has-card .hud-tools,
  .glass.has-card .hud-feed {
    display: none;
  }
}
.badge {
  display: inline-block;
  min-width: 24px;
  margin-left: var(--space-6);
  padding: 0 5px;
  background: var(--alert);
  color: var(--paper);
  text-align: center;
  font-family: var(--data);
  font-size: var(--text-data);
  font-weight: 600;
}
.badge[hidden] {
  display: none;
}
.feed {
  position: absolute;
  top: 62px;
  right: 8px;
  width: min(350px, calc(100% - 16px));
  max-height: calc(100% - 70px);
  overflow: auto;
  line-height: 1.4;
  background: var(--panel);
  border: var(--line);
  padding: var(--space-10) var(--space-12);
}
.feed[hidden],
.card[hidden] {
  display: none;
}
.feed:focus-visible,
.card:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: -5px;
}
.feed .head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-12);
  margin-bottom: var(--space-8);
}
.feed h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--text-heading);
  line-height: 1.1;
}
.feed ol,
.card .lately {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--line);
}
.feed li,
.card .lately li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0 var(--space-10);
  align-items: start;
  padding: var(--space-6) 0;
  border-bottom: var(--line-soft);
}
.feed time,
.card .lately time {
  font-family: var(--data);
  font-size: var(--text-13);
  line-height: 1.7;
  color: var(--muted);
}
.feed .who,
.card .lately .who {
  overflow-wrap: anywhere;
  font-weight: 600;
}
.feed .req,
.card .lately .req {
  display: block;
  color: var(--muted);
  font-family: var(--data);
  font-size: var(--text-13);
  font-weight: 400;
}
.tag {
  border: 1px solid currentColor;
  padding: 1px var(--space-6);
  font-family: var(--data);
  font-size: var(--text-label);
  font-weight: 600;
  line-height: 1.5;
  text-transform: uppercase;
  white-space: nowrap;
}
.tag.bad {
  color: var(--alert);
}
.tag.good {
  color: var(--ok);
}

/* Expanded: the island takes the whole window. */
body.full .stage {
  position: fixed;
  inset: 0;
  z-index: var(--z-20);
  display: flex;
  flex-direction: column;
  margin: 0;
  background: var(--paper);
  padding: calc(var(--space-8) + env(safe-area-inset-top, 0px)) var(--space-8)
    calc(var(--space-8) + env(safe-area-inset-bottom, 0px));
}
body.full .glass {
  flex: 1;
  min-height: 0;
  box-shadow: none;
}
body.full #island {
  height: 100%;
  aspect-ratio: auto;
}
body.full .ticker {
  margin-top: var(--space-8);
}

/* Night watch: the island and nothing else. The one control left is the contract button, which shows on touch or
   movement and goes after a few seconds. It is not clickable while hidden, so a tap there reaches the island. */
.hud button[hidden] {
  display: none;
}
body.watch .stage {
  padding: 0;
}
body.watch .glass {
  border: 0;
}
body.watch .ticker,
body.watch #bell,
body.watch #watch {
  display: none;
}
body.watch .hud-tools:not(.awake):not(:focus-within) {
  opacity: 0;
  pointer-events: none;
}
body.watch .hud-tools {
  transition: opacity var(--dur-400);
}
@media (prefers-reduced-motion: reduce) {
  body.watch .hud-tools {
    transition: none;
  }
}

.ticker {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  margin-top: var(--space-14);
  background: var(--ink);
  color: var(--paper);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-12);
  min-height: 52px;
}
.ticker p {
  margin: 0;
  flex: 1;
  min-width: 0;
  /* One line: a long line is cut with an ellipsis and never makes the bar taller. */
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* On a phone the line has room for 14 to 27 characters of one line, so it takes two. The two lines are held whether or
   not the second is used, so the bar does not change height as the sentence does. */
@media (max-width: 767px) {
  .ticker p {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    min-height: 2.9em;
    white-space: normal;
  }
}
button {
  font-family: var(--body);
  font-size: var(--text-body);
  font-weight: 500;
  color: var(--ink);
  background: var(--paper);
  border: var(--line);
  min-height: var(--tap);
  padding: 0 var(--space-14);
  cursor: pointer;
}
.ticker button {
  border-color: var(--paper);
}
button:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}

/* Sections below the island. */
.home {
  display: grid;
  gap: var(--gap-section) var(--space-16);
  grid-template-columns: minmax(0, 1fr);
  margin-top: var(--gap-section);
}
@media (min-width: 1024px) {
  /* Two columns, two rows: the panels are placed straight into the grid so each row's pair shares a height. The
     hour chart stretches to the height of "At the port" beside it. */
  .home {
    grid-template-columns: minmax(0, 54fr) minmax(0, 46fr);
    grid-template-areas: "port hours" "today day" "landed landed";
    column-gap: var(--gap-columns);
  }
  .home > section {
    min-width: 0;
  }
  .port {
    grid-area: port;
  }
  .today {
    grid-area: today;
    align-self: start;
  }
  .hoursbox {
    grid-area: hours;
  }
  .daybox {
    grid-area: day;
    align-self: start;
  }
  .landedbox {
    grid-area: landed;
  }
  .hoursbox,
  .hoursbox .chart {
    display: flex;
    flex-direction: column;
  }
  .hoursbox .chart,
  .hoursbox .bars.hours {
    flex: 1;
  }
  .hoursbox .bars.hours {
    height: auto;
    min-height: 96px;
  }
}
/* One section heading for the island page: the display serif, as before the panels were redrawn. */
.home h2 {
  font-size: var(--text-heading);
  line-height: 1.1;
}
.fine {
  max-width: var(--measure);
  margin: var(--space-6) 0 var(--gap-block);
  color: var(--muted);
  font-size: var(--text-small);
}
/* A heading with something at its right: the heading, then a link or a figure, on one baseline. */
.headrow {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4) var(--space-12);
  margin: var(--gap-section) 0 var(--gap-heading);
}
.headrow h2 {
  margin: 0;
}
.home .headrow {
  margin-top: 0;
}
main :is(h2, .headrow):has(+ .fine) {
  margin-bottom: var(--space-4);
}
main :is(h2, .headrow) + .fine {
  margin: 0 0 var(--space-12);
  font-size: var(--text-compact);
}
.aside {
  font-family: var(--data);
  font-size: var(--text-label);
  color: var(--muted);
}
/* The read-out above a chart: the bar it reads, and its figures. Today, or the busiest hour, is the red one. */
.readout {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  height: 20px;
  max-width: none;
  margin: var(--space-4) 0 var(--space-6);
  overflow: hidden;
  font-family: var(--data);
  font-size: var(--text-data);
  white-space: nowrap;
}
.readout .sw {
  flex: none;
  width: 10px;
  height: 10px;
  background: var(--muted);
  opacity: 0.4;
}
.readout .sw.now {
  background: var(--alert);
  opacity: 1;
}
.readout .at {
  color: var(--muted);
}
.readout .what {
  font-weight: 600;
}
.headrow .readout {
  margin: 0;
}
/* One row at every width: nine equal tiles across on desktop; narrower, the row scrolls sideways. */
.landed {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-6);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 124px;
  gap: var(--card-gap);
  overflow-x: auto;
}
@media (min-width: 1024px) {
  .landed {
    grid-auto-columns: calc((100% - 8 * var(--card-gap)) / 9);
  }
}
.landed li {
  container-type: inline-size;
  border: var(--line);
  background: var(--panel);
}
.landed li.support {
  border-style: dashed;
}
.landed li.support a {
  display: flex;
  flex-direction: column;
  height: 100%;
  color: inherit;
  text-decoration: none;
}
.landed li.support canvas {
  border-bottom-style: dashed;
}
.landed button {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  width: 100%;
  height: 100%;
  min-height: 0;
  padding: 0;
  border: 0;
  text-align: left;
  background: var(--panel);
}
.landed canvas {
  /* The drawing is a whole number of CSS pixels to a frame pixel, centred on its colour, which fills the tile. */
  box-sizing: content-box;
  width: var(--mug-l);
  aspect-ratio: 22 / 16;
  padding-inline: calc((100% - var(--mug-l)) / 2);
  border-bottom: var(--line);
}
@container (min-width: 110px) {
  .landed canvas {
    width: var(--mug-xl);
    padding-inline: calc((100% - var(--mug-xl)) / 2);
  }
}
.landed .nm {
  display: block;
  padding: var(--space-6) var(--space-8) 0;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.landed .net {
  display: block;
  padding: 1px var(--space-8) 0;
  color: var(--muted);
  font-size: var(--text-caption);
  font-weight: 400;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.landed time,
.landed li.support a::after {
  display: block;
  margin-top: auto;
  padding: var(--space-4) var(--space-8) var(--space-8);
  font-family: var(--data);
  font-size: var(--text-label);
  font-weight: 400;
  color: var(--muted);
}
.landed li.support a::after {
  content: "\00a0";
}

/* Specimen of the day: the species with the most landings so far today. */
.day {
  display: grid;
  grid-template-columns: calc(var(--mug-xl) + 4px) minmax(0, 1fr);
  gap: var(--space-12);
  align-items: start;
  border: var(--line);
  background: var(--panel);
  padding: var(--card-pad);
  line-height: 1.45;
  /* Name, Latin name, order line, the joke on that many lines, the count line. */
  --day-lines: 2;
  min-height: calc(
    2 *
    var(--space-12) +
    4px +
    1.2 *
    var(--text-18) +
    1.15 *
    var(--text-22) +
    3 *
    var(--space-6) +
    (1 + var(--day-lines)) *
    1.45 *
    var(--text-compact) +
    1.45 *
    var(--text-13)
  );
}
@media (max-width: 767px) {
  .day {
    --day-lines: 4;
  }
  .headrow .readout {
    flex-basis: 100%;
  }
}
#tOutOf {
  display: inline-block;
  min-width: 4ch;
}
.day.empty::before {
  content: "";
  box-sizing: content-box;
  width: var(--mug-xl);
  aspect-ratio: 22 / 16;
  border: var(--line-dashed);
}
.day .none {
  margin: 0;
  color: var(--muted);
}
.day canvas {
  box-sizing: content-box;
  width: var(--mug-xl);
  aspect-ratio: 22 / 16;
  border: var(--line);
}
.day h3 {
  margin: 0;
  font-family: var(--body);
  font-size: var(--text-18);
  font-weight: 600;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.day .latin {
  margin: 0;
  font-family: var(--display);
  font-style: italic;
  font-size: var(--text-22);
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.day p {
  margin: var(--space-6) 0 0;
  font-size: var(--text-compact);
}
.day .ord {
  color: var(--muted);
}
.day .meta {
  font-family: var(--data);
  font-size: var(--text-data);
}
.more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  min-height: var(--tap);
  color: var(--ink);
  font-weight: 500;
}
.headrow .more {
  margin: calc(-1 * var(--space-6)) 0;
}
.headrow .more[hidden] {
  visibility: hidden;
}

/* The creature card: a window over the island. */
.card {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  max-height: 64%;
  overflow: auto;
  line-height: 1.35;
  border: var(--line);
  background: var(--panel);
  padding: var(--space-8) var(--space-10);
}
@media (min-width: 768px) {
  .card {
    right: auto;
    bottom: auto;
    top: 52px;
    width: 330px;
    max-height: calc(100% - 60px);
    padding: var(--space-10) var(--space-12);
  }
}
/* A link that sits among the card's buttons and looks like one. */
.btn {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--space-14);
  border: var(--line);
  background: var(--paper);
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}
.btn:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}
button.primary,
.btn.primary {
  padding: 0 var(--space-24);
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
}
button.primary:hover,
.btn.primary:hover {
  background: var(--paper);
  color: var(--ink);
}
.card .head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-10);
}
.card .acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin-top: var(--space-8);
}
.card .mug {
  box-sizing: content-box;
  width: var(--mug-m);
  flex: none;
  aspect-ratio: 22 / 16;
  border: var(--line);
}
.card .who {
  flex: 1;
  min-width: 0;
}
.card h2 {
  margin: 0;
  font-family: var(--body);
  font-weight: 600;
  font-size: var(--text-19);
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.card .held {
  margin: var(--space-8) 0 0;
  border: 2px solid var(--alert);
  padding: var(--space-2) var(--space-8);
  color: var(--alert);
  font-weight: 600;
}
.card .latin {
  margin: 1px 0 0;
  font-family: var(--display);
  font-style: italic;
  font-size: var(--text-20);
  line-height: 1.15;
}
.card dl {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 3px var(--space-12);
  margin: var(--space-10) 0 0;
  padding-top: var(--space-8);
  border-top: 2px dotted var(--ink);
}
.card dt {
  color: var(--muted);
}
.card dd {
  margin: 0;
  overflow-wrap: anywhere;
}
.card dd.req {
  font-family: var(--data);
  font-size: var(--text-13);
  align-self: center;
}

/* A place's panel: the section names, who is there, and nobody. */
.card h3 {
  margin: var(--space-12) 0 var(--space-4);
  padding-top: var(--space-8);
  border-top: 2px dotted var(--ink);
  font-family: var(--body);
  font-size: var(--text-14);
  font-weight: 600;
  color: var(--muted);
}
.card h3 + dl {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.card .none {
  margin: 0;
  color: var(--muted);
}
.card .here {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}
.card .here button {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  min-height: var(--tap);
  padding: var(--space-2) var(--space-10) var(--space-2) var(--space-2);
  border: var(--line);
  background: var(--paper);
  color: var(--ink);
  font-weight: 500;
  cursor: pointer;
}
.card .here canvas {
  width: 44px;
  aspect-ratio: 22 / 16;
}
.card .lately {
  margin-top: 0;
}

.card .route {
  max-height: 224px;
  overflow: auto;
}
.card .route li {
  display: block;
  padding: 0;
}
.card .route li.none {
  padding: var(--space-6) 0;
  color: var(--muted);
  font-family: var(--data);
  font-size: var(--text-13);
}
.card .route .stop {
  display: grid;
  grid-template-columns: 22px auto minmax(0, 1fr) auto;
  gap: 0 var(--space-8);
  align-items: start;
  width: 100%;
  min-height: 36px;
  padding: var(--space-6) var(--space-2);
  border: 0;
  background: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.card .route .stop[aria-pressed="true"] {
  background: var(--soft);
}
.card .route .n {
  min-width: 22px;
  font-weight: 700;
  padding: 0 var(--space-4);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
  font-family: var(--data);
  font-size: var(--text-12);
  line-height: 1.7;
}
.card .route time {
  font-family: var(--data);
  font-size: var(--text-13);
  line-height: 1.7;
  color: var(--muted);
}

.card .sessions {
  list-style: none;
  margin: var(--space-12) 0 0;
  padding: 0;
  border-top: var(--line);
}
.card .sessions li {
  padding: 5px 0;
  font-family: var(--data);
  font-size: var(--text-13);
  border-bottom: var(--line-soft);
  overflow-wrap: anywhere;
}

/* Server-rendered pages (species, method, editions) share this sheet. */
main h1,
main h2,
main h3 {
  font-family: var(--display);
  font-weight: 400;
}
main strong,
main b {
  font-weight: 600;
}
main i,
main em {
  font-family: var(--display);
  font-size: 1.1em;
  /* The serif has one weight, so a bold or italic around it would be drawn by the browser and smear its thin strokes. */
  font-synthesis: none;
}
/* The serif is a display face: its thin stroke needs 20px or more. In small text an italic word is the sans italic. */
:is(.fine, .notes, .data, .tip-body, .split) :is(i, em) {
  font-family: inherit;
  font-size: inherit;
}
main code,
main pre,
main time {
  font-family: var(--data);
  font-size: var(--text-data);
}

/* The footer, the same on the island page as on the server pages. It sits in the masthead's column, under a 2px ink rule. */
body > footer {
  width: min(calc(var(--page-width) - 2 * var(--page-gutter)), calc(100% - 2 * var(--page-gutter)));
  margin: var(--space-16) auto 0;
  padding: var(--space-48) 0 calc(var(--space-48) + env(safe-area-inset-bottom, 0px));
  border-top: var(--line);
  font-size: var(--text-small);
}
body > footer p,
body > footer ul,
body > footer h2 {
  margin: 0;
  padding: 0;
}
body > footer ul {
  list-style: none;
}
body > footer .foot-top a {
  color: var(--ink);
  text-decoration: none;
}
body > footer .foot-top a:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}
body > footer .foot-top a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 2px;
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}
.foot-top {
  display: flex;
  flex-direction: column;
  gap: var(--space-40);
}
.foot-brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
  max-width: 20rem;
}
.foot-name {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  font-family: var(--display);
  font-size: var(--text-20);
  line-height: 1.2;
  color: var(--ink);
}
.foot-name img {
  width: 24px;
  height: 24px;
}
.foot-blurb {
  color: var(--muted);
  line-height: 1.625;
}
.foot-cols {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.foot-cols nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}
.foot-cols ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}
body > footer h2 {
  font: 600 var(--text-label) / 1.33 var(--body);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.foot-note {
  max-width: var(--measure);
  font-size: var(--text-caption);
  color: var(--muted);
}
.foot-legal {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
  margin-top: var(--space-48);
  padding-top: var(--space-24);
  border-top: var(--line-soft);
}
.foot-legal p {
  max-width: var(--measure);
  font-size: var(--text-caption);
  color: var(--muted);
}
body > footer a.codeswhat-pill {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-6) var(--space-14) var(--space-6) var(--space-6);
  border: var(--line-soft);
  border-radius: 9999px;
  background: color-mix(in srgb, var(--paper) 50%, transparent);
  color: var(--muted);
  text-decoration: none;
  transition: border-color var(--dur-150), background-color var(--dur-150);
}
body > footer a.codeswhat-pill:hover {
  border-color: var(--muted);
  background: color-mix(in srgb, var(--paper) 80%, transparent);
}
body > footer a.codeswhat-pill:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}
.codeswhat-pill .coin {
  width: 26px;
  height: 26px;
  border-radius: 9999px;
  box-shadow: 0 0 0 1px var(--soft);
}
:root[data-theme="dark"] .codeswhat-pill .coin {
  filter: invert(1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .codeswhat-pill .coin {
    filter: invert(1);
  }
}
.codeswhat-pill .pill-text {
  font-size: var(--text-label);
  line-height: 1.33;
}
.codeswhat-pill .pill-name {
  font-weight: 600;
  color: var(--ink);
}
.codeswhat-pill .pill-arrow {
  flex: none;
  transition: transform var(--dur-150);
}
.codeswhat-pill:hover .pill-arrow {
  transform: translate(2px, -2px);
}
@media (prefers-reduced-motion: reduce) {
  .codeswhat-pill .pill-arrow {
    transition: none;
  }
}
@media (min-width: 768px) {
  .foot-legal {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}
@media (min-width: 768px) {
  .foot-cols {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--space-40) var(--space-64);
  }
}
@media (min-width: 1024px) {
  .foot-top {
    flex-direction: row;
    justify-content: space-between;
  }
  .foot-cols {
    justify-content: flex-end;
  }
}

/* The one link a script adds to every page. It sits in the footer, so it reads as one of its links. */
a.grown {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  margin-top: var(--space-6);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--text-small);
  line-height: 1.45;
  font-weight: 400;
  text-underline-offset: 2px;
}
a.grown:focus-visible {
  outline: 3px solid var(--alert);
  outline-offset: 2px;
}

/* Moving between pages: a browser that can do cross-document view transitions holds the masthead title, the
   tab row and a page's sub-tab row still and cross-fades only what is below them. Others navigate as before. */
@view-transition {
  /* biome-ignore lint/correctness/noUnknownProperty: biome 1.9 does not know the @view-transition descriptor */
  navigation: auto;
}
.mast .title {
  view-transition-name: mast-title;
}
.navbar {
  view-transition-name: main-nav;
}
.subnav {
  view-transition-name: sub-nav;
}
::view-transition-group(*) {
  animation-duration: var(--dur-120);
}
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--dur-120);
}
@media (prefers-reduced-motion: reduce) {
  @view-transition {
    /* biome-ignore lint/correctness/noUnknownProperty: biome 1.9 does not know the @view-transition descriptor */
    navigation: none;
  }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none;
  }
}

/* The i hint lives here, not in pages.css, because the island page loads only this sheet and its masthead has one. */
/* A hint: a small round "i" that shows a short panel on hover, focus and tap, without moving anything. */
.hint {
  display: inline-block;
  vertical-align: middle;
  font-family: var(--body);
  font-size: var(--text-small);
  font-weight: 400;
  line-height: 1.35;
}
main .hint summary,
.mast .hint summary {
  min-height: 0;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  list-style: none;
  cursor: pointer;
}
main .hint summary::-webkit-details-marker,
.mast .hint summary::-webkit-details-marker {
  display: none;
}
main .hint summary:focus-visible,
.mast .hint summary:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
/* A hint wears the pixel circled i in place of the lettered circle: the icon alone, no CSS ring. */
.hint .info-icon {
  display: block;
}
.hint::details-content {
  content-visibility: visible;
  display: contents;
}
.hint .tip {
  display: none;
  position: absolute;
  z-index: var(--z-5);
  top: 100%;
  left: 0;
  width: max-content;
  max-width: min(34ch, calc(100vw - 32px));
  padding-top: var(--space-6);
}
.hint[open] .tip,
.hint:hover .tip,
.hint:focus-within .tip {
  display: block;
}
/* With the site script running (it sets data-hints on the root) a panel is fixed under its icon, centred, and kept
   12px inside the viewport; the script writes --hx, --hy and --hn (the notch's x). Without it the rules above hold. */
:root[data-hints] details.hint.hint .tip {
  position: fixed;
  z-index: var(--z-50);
  top: var(--hy, 0);
  right: auto;
  bottom: auto;
  left: var(--hx, 0);
  max-width: min(34ch, calc(100vw - 24px));
  padding-top: var(--space-8);
}
:root[data-hints] .mast .sub .hint .tip {
  max-width: min(40em, calc(100vw - 24px));
}
:root[data-hints] .tip-body {
  position: relative;
}
:root[data-hints] .tip-body::before {
  content: "";
  position: absolute;
  top: -5px;
  left: calc(var(--hn, 50%) - 5px);
  width: 8px;
  height: 8px;
  border: solid var(--ink);
  border-width: 1px 0 0 1px;
  background: var(--paper);
  transform: rotate(45deg);
}
/* An open panel is painted above its neighbours: its icon's box and the masthead (which holds its own stacking
   context for the view transition and sits before the sticky tab row) rise while it is open. */
.hint:is(:hover, :focus-within, [open]) {
  z-index: var(--z-50);
}
.mast:has(.hint:is(:hover, :focus-within, [open])) {
  position: relative;
  z-index: var(--z-50);
}
.tip-body {
  padding: var(--space-8) var(--space-10);
  border: var(--line-thin);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--text-small);
  font-style: normal;
  font-weight: 400;
  text-align: left;
}
.tip-body p {
  max-width: var(--measure);
  margin: 0 0 var(--space-6);
}
.tip-body p:last-child {
  margin-bottom: 0;
}

/* The intro hint after the masthead tagline: upright, centred on the text's x-height, panel under the tagline. */
.mast .sub .hint {
  position: static;
  margin-left: var(--space-8);
  font-style: normal;
  vertical-align: 0.05em;
}
.mast .sub .hint .tip {
  z-index: var(--z-10);
  max-width: min(40em, 100%);
  padding-top: var(--space-8);
}
.mast .sub .hint .tip-body {
  font-family: var(--body);
  font-size: var(--text-small);
  line-height: 1.4;
}

/* Phone: the footer's link columns pair up two by two. */
@media (max-width: 767px) {
  .foot-cols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-10) var(--space-16);
  }
}

/* The Rules ledger rows and share bar live in this sheet because the island page loads only this one. */
.rules {
  margin: 0 0 var(--gap-block);
  padding: 0;
  list-style: none;
  border: var(--line);
  background: var(--panel);
}
.rules > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 var(--space-12);
  padding: var(--card-pad);
  border-top: var(--line-soft);
}
.rules > li:first-child {
  border-top: 0;
}
.rules .where {
  color: var(--muted);
  font-size: var(--text-small);
}
/* The island's compact row (rules compact), as designed: a body-size label in ink and a 20px figure, both grey at zero. */
.rules.compact .where {
  color: var(--ink);
  font-size: var(--text-body);
  line-height: 1.3;
}
.rules.compact {
  margin-bottom: 0;
}
.rules.compact > li {
  padding: var(--row-pad);
}
/* The island's tally rows keep a 20px figure. */
.rules.compact .big .n {
  font-size: var(--text-20);
}
.rules.compact .big.plain .n {
  font-weight: 400;
}
.rules.compact li:has(.big.plain) .where {
  color: var(--muted);
}
.bar {
  display: flex;
  width: 100%;
  height: 8px;
  overflow: hidden;
  border: var(--line);
  background: var(--paper);
}
.bar .k {
  flex: 0 1 auto;
  background: var(--ok);
}
.bar .k.plain {
  background: var(--muted);
}
.bar .b {
  flex: 0 0 auto;
  min-width: 2px;
  background: var(--alert);
}
.rules > li.led {
  grid-template-columns: minmax(0, 1fr) 16rem;
  align-items: start;
}
.rules .rulecol {
  min-width: 0;
}
.rules .rulecol code {
  display: block;
}
.rules .big {
  display: grid;
  justify-items: end;
  gap: var(--space-4);
  align-self: center;
  width: 16rem;
  max-width: 100%;
  justify-self: end;
}
.rules .big .n {
  font-family: var(--data);
  font-size: var(--text-figure-row);
  font-weight: 600;
  line-height: 1;
}
.cap {
  margin: 0;
  color: var(--muted);
  font-family: var(--data);
  font-size: var(--text-label);
  font-weight: 400;
}
.rules .big .cap {
  text-align: right;
}
/* "18 of 578" on one line: today's figure, then the all-time total small and muted beside it. */
.rules .big .n .of {
  color: var(--muted);
  font-size: var(--text-caption);
  font-weight: 400;
}
.rules .big.plain .n {
  color: var(--muted);
}
@media (max-width: 767px) {
  .rules > li.led {
    grid-template-columns: minmax(0, 1fr);
  }
  .rules .big {
    justify-self: stretch;
    justify-items: start;
    width: auto;
    margin-top: var(--space-4);
  }
  .rules .big .cap {
    text-align: left;
  }
}

/* The bar chart (96px chart, red current bar, mono axis) lives in this sheet because the island page loads only this one. */
.chart {
  margin: 0 0 var(--gap-block);
}
.bars {
  display: block;
  width: 100%;
  height: 96px;
  border-bottom: var(--line);
}
.bar-now {
  fill: var(--alert);
}
.bar-now-b {
  fill: var(--alert);
  fill-opacity: 0.55;
}
.bar-a {
  fill: var(--ink);
}
.bar-b {
  fill: var(--muted);
}
.chart .axis {
  display: flex;
  justify-content: space-between;
  margin-top: var(--space-4);
  color: var(--muted);
  font-family: var(--data);
  font-size: var(--text-label);
}
.hoursbox .chart {
  margin-bottom: 0;
}
/* The island's chart is DOM bars, not SVG: the same classes, drawn as backgrounds. */
.hours {
  touch-action: pan-y;
}
.bars.hours {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  align-items: end;
  gap: var(--space-2);
}
.hours i {
  display: block;
  background: var(--ink);
}
.hours i.bar-now {
  background: var(--alert);
}
/* The picked hour: a grey column the full height of the chart behind its bar, which keeps its own colour. */
.bars.hours {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.hours i.sel {
  position: relative;
}
.hours i.sel::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: -1;
  height: 100vh;
  background: var(--muted);
  opacity: 0.4;
}
.hours i.later {
  background: var(--soft);
}
@media (prefers-reduced-motion: no-preference) {
  .bar .k,
  .bar .b {
    transition: width var(--dur-400);
  }
}
