/* ansi direction: Ship 16, the site's own ANSI theme. Mirrors tools/pixel.py. */
@font-face {
  font-family: "Departure Mono";
  src: url("https://cdn.jsdelivr.net/gh/rektdeckard/departure-mono@main/public/assets/DepartureMono-Regular.woff2")
    format("woff2");
  font-display: swap;
}

:root {
  --c0: #1c1a27;
  --c1: #e65a48;
  --c2: #3fae5a;
  --c3: #e2a52b;
  --c4: #2f63cc;
  --c5: #c45cc4;
  --c6: #25b2c0;
  --c7: #d4ccb8;
  --c8: #5f5a75;
  --c9: #ff7a68;
  --c10: #86d873;
  --c11: #ffd462;
  --c12: #79a4ff;
  --c13: #f590e8;
  --c14: #7fe3ec;
  --c15: #fbf8f1;

  --ink: var(--c0);
  --paper: var(--c15);
  /* the grounds, light to dark as the page descends */
  --sky-high: #a9d3ea;
  --sky: #cfe7f3;
  --haze: #e4f2f8;
  --sea: #1f4fa8;
  --deep: #14306b;
  --wall: #252232;
  --hold: #1c1a27;
  --seabed: #0f1a38;
  --muted-light: #4a4660;
  --muted-dark: #b9b3c9;
  /* the focus ring is ink on light grounds and bright cyan on dark ones */
  --ring: var(--ink);

  /* one type scale for reading text, +2px a step; the pixel face has its own steps (.p11 to .p66, multiples of 11) */
  --t-sm: 14px; /* captions, side notes, small print */
  --t-md: 16px; /* interface text, lists, navigation, secondary copy */
  --t-base: 18px; /* body */
  --t-lg: 20px; /* the intro to a section, a lede */
  --t-xl: 22px; /* the hero's lede */
  --code-sm: 13px; /* tight code: diagrams, keycaps in a table */
  --code-md: 14px; /* code and terminals */

  --pixel: "Departure Mono", ui-monospace, monospace;
  --read: "Atkinson Hyperlegible Next", system-ui, sans-serif;
  --code: ui-monospace, "SF Mono", Menlo, "Cascadia Mono", "DejaVu Sans Mono", monospace;
  /* one art pixel. every sprite on every page is a whole number of these */
  --px: 4px;
  --bar-h: 60px;
  --gut: 56px; /* side margin of every page container */
  --edge: max(
    var(--gut),
    calc(50% - 664px)
  ); /* where the 1328px page column starts, as a padding on a full-width bar */
}

* {
  box-sizing: border-box;
}
html {
  scroll-behavior: auto;
  -webkit-text-size-adjust: 100%;
  scrollbar-color: var(--c8) var(--ink);
}
body {
  margin: 0;
  font: var(--t-base)/1.55 var(--read);
  color: var(--ink);
  background: var(--paper);
}
::selection {
  background: var(--c6);
  color: var(--ink);
}
p,
li {
  text-wrap: pretty;
}
a {
  color: inherit;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 2px;
}
a:focus-visible,
button:focus-visible,
summary:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 3px;
}
img.px,
svg.px {
  image-rendering: pixelated;
  display: block;
}
code,
pre,
kbd {
  font-family: var(--code);
}
:target {
  scroll-margin-top: var(--bar-h);
}

.skip {
  position: absolute;
  left: 8px;
  top: -80px;
  z-index: 100;
  background: var(--c11);
  color: var(--ink);
  font-weight: 700;
  padding: 10px 16px;
}
.skip:focus {
  top: 8px;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
code {
  font-size: 0.88em;
  padding: 1px 5px;
  background: color-mix(in srgb, currentColor 13%, transparent);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone; /* a chip that wraps keeps its padding on both lines */
  overflow-wrap: anywhere;
} /* and a long path breaks rather than poke out of a phone's column */
.term code,
.bar code {
  background: none;
  padding: 0;
  font-size: inherit;
}

/* the pixel voice: sizes are multiples of 11px so Departure Mono lands on its grid */
.pixel {
  font-family: var(--pixel);
  font-weight: 400;
  letter-spacing: 0;
}
.p22 {
  font-size: 22px;
  line-height: 33px;
}
.p33 {
  font-size: 33px;
  line-height: 44px;
}
.p44 {
  font-size: 44px;
  line-height: 55px;
}
.p66 {
  font-size: 66px;
  line-height: 77px;
}
.p11 {
  font-size: 11px;
  line-height: 22px;
}

/* an art sprite or tile: --w and --h are in art pixels, set per element */
.art {
  width: calc(var(--w) * var(--px));
  height: calc(var(--h) * var(--px));
  max-width: none;
}
.tile {
  background-repeat: repeat-x;
  image-rendering: pixelated;
  background-size: calc(var(--tw) * var(--px)) calc(var(--th) * var(--px));
  height: calc(var(--th) * var(--px));
}

/* a drawn loop: a sheet of --n frames, each --w by --h art pixels, stepped one frame per --dt.
   frame 0 is the still pose, so with motion off (or before the sheet loads) the page reads the same.
   every loop has its own length and pace, so none of them move in time with another. */
.act {
  display: block;
  flex: none;
  max-width: none;
  width: calc(var(--w) * var(--px));
  height: calc(var(--h) * var(--px));
  background: no-repeat 0 0 / calc(var(--w) * var(--n) * var(--px)) calc(var(--h) * var(--px));
  image-rendering: pixelated;
  animation: act calc(var(--n) * var(--dt)) steps(var(--n)) var(--lag, 0s) infinite;
}
@keyframes act {
  to {
    background-position-x: calc(var(--w) * var(--n) * var(--px) * -1);
  }
}
.act.off {
  animation-play-state: paused;
} /* site.js pauses a loop while it is off screen */
/* the deck crew: 36 by 28 frames, a little wider and taller than the 28 by 24 crewmate so there is room to pace and for smoke */
.a-error {
  --w: 36;
  --h: 28;
  --n: 6;
  --dt: 0.3s;
  --lag: -0.5s;
  background-image: url("../art/crew-lookout-error-loop.svg");
}
.a-blocked {
  --w: 36;
  --h: 28;
  --n: 8;
  --dt: 0.34s;
  --lag: -1.1s;
  background-image: url("../art/crew-navigator-blocked-loop.svg");
}
.a-working {
  --w: 36;
  --h: 28;
  --n: 8;
  --dt: 0.24s;
  --lag: -0.7s;
  background-image: url("../art/crew-deckhand-working-loop.svg");
}
.a-unseen {
  --w: 36;
  --h: 28;
  --n: 10;
  --dt: 0.36s;
  --lag: -2.2s;
  background-image: url("../art/crew-cook-unseen-loop.svg");
}
.a-idle {
  --w: 36;
  --h: 28;
  --n: 41;
  --dt: 0.22s;
  --lag: -3.4s;
  background-image: url("../art/crew-captain-idle-loop.svg");
}
/* the crewmates beside the notes in the docs: 28 by 24, mostly at rest */
.a-clipboard {
  --w: 28;
  --h: 24;
  --n: 14;
  --dt: 0.45s;
  --lag: -1.3s;
  background-image: url("../art/crew-deckhand-clipboard-loop.svg");
}
.a-point {
  --w: 28;
  --h: 24;
  --n: 16;
  --dt: 0.4s;
  --lag: -4.2s;
  background-image: url("../art/crew-navigator-point-loop.svg");
}
.a-reach {
  --w: 28;
  --h: 24;
  --n: 16;
  --dt: 0.42s;
  --lag: -2.6s;
  background-image: url("../art/crew-cook-reach-loop.svg");
}

/* the captain with his clipboard, beside the blog's heading: the same long rests and short burst as the others */
.a-log {
  --w: 28;
  --h: 24;
  --n: 14;
  --dt: 0.45s;
  --lag: -4.6s;
  background-image: url("../art/crew-captain-clipboard-loop.svg");
}

/* lists with a pixel bullet: a square on the same grid as the headings' squares */
.doc ul,
.needs,
.notyet ul {
  list-style: none;
  padding-left: 0;
}
.doc li,
.needs li,
.notyet li {
  position: relative;
  padding-left: 24px;
}
.doc li::before,
.needs li::before,
.notyet li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0.58em;
  width: 8px;
  height: 8px;
  background: var(--sea);
}
.needs li::before {
  background: var(--c14);
}

/* terminal surfaces: the only place state glyphs are drawn */
.term {
  background: var(--ink);
  color: var(--c7);
  font: var(--code-md)/1.45 var(--code);
  border-radius: 0;
  border: 2px solid var(--ink);
}
.term pre {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  scrollbar-color: var(--c8) transparent;
}
.s-working {
  color: var(--c3);
}
.s-blocked {
  color: var(--c1);
}
.s-unseen {
  color: var(--c6);
}
.s-idle {
  color: var(--c2);
}
.s-error {
  color: var(--c5);
}
.dim {
  color: var(--muted-dark);
}
/* a little shell and toml colouring, in the terminal's own colours */
.t-prompt {
  color: var(--muted-dark);
  user-select: none;
}
.t-c {
  color: var(--muted-dark);
}
.t-s {
  color: var(--c10);
}
.t-k {
  color: var(--c12);
}
.t-h {
  color: var(--c11);
}
.t-n {
  color: var(--c13);
}

/* a keycap, for the docs and the keys table */
kbd {
  font: var(--code-md)/1.2 var(--code);
  background: var(--ink);
  color: var(--c15);
  padding: 2px 7px 3px;
  box-shadow: 0 3px 0 var(--c8);
  white-space: nowrap;
  display: inline-block;
  margin-bottom: 3px;
}

/* a copyable command block: the text never runs under the copy button */
.cmd {
  position: relative;
  padding: 16px 18px;
}
.cmd pre {
  font-size: var(--code-md);
  padding-right: 54px;
}
.cmd .copy {
  position: absolute;
  top: 10px;
  right: 10px;
}
pre[tabindex]:focus-visible {
  outline: 3px solid var(--c14);
  outline-offset: 4px;
}
/* code that scrolls sideways shows a dithered edge on the side with more to see; the ink patch hides it at the end of the scroll */
pre[tabindex] {
  background:
    linear-gradient(var(--ink), var(--ink)) local 100% 0 / 8px 100% no-repeat,
    repeating-conic-gradient(var(--c8) 0 25%, transparent 0 50%) scroll 100% 0 / 8px 8px repeat-y;
}

/* the copy button on a command (and the landing's recording controls, which share its keycap) */
.copy,
.reel-btn {
  font: 11px/22px var(--pixel);
  background: var(--c6);
  color: var(--ink);
  border: 0;
  padding: 2px 10px 3px;
  cursor: pointer;
  box-shadow: 0 2px 0 color-mix(in srgb, var(--c6) 60%, var(--ink));
  transition: background-color 0.12s;
}
@media (hover: hover) {
  .copy:hover,
  .reel-btn:hover {
    background: var(--c14);
  }
}
@media (pointer: coarse) {
  .cmd .copy::after {
    content: "";
    position: absolute;
    inset: -9px -6px;
  } /* a 44px target around the keycap */
}
.copy:active,
.reel-btn:active {
  transform: translateY(2px);
  box-shadow: none;
}
.copy.done {
  background: var(--c10);
}
.copy:focus-visible {
  outline-color: var(--c14);
}

/* the always-visible bar, plain links first */
.bar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--ink);
  color: var(--c7);
  --ring: var(--c14);
}
.bar-in {
  display: flex;
  align-items: center;
  gap: 28px;
  width: min(1328px, calc(100% - 2 * var(--gut)));
  margin: 0 auto;
  min-height: 52px;
}
.bar a {
  text-decoration: none;
}
.bar .home {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--c15);
}
/* the mark: 72 art pixels drawn at 44 (36 on a phone, where it is crisp at twice the density), so the crew still read; it rocks a little on the swell
   when you point at it or Tab to it, and the sprite is still when motion is reduced */
.bar .home .mark {
  width: 44px;
  height: 44px;
}
.bar .home:focus-visible .mark {
  animation: rock 0.8s steps(1) infinite;
}
@media (hover: hover) {
  .bar .home:hover .mark {
    animation: rock 0.8s steps(1) infinite;
  }
}
@keyframes rock {
  50% {
    transform: translateY(2px);
  }
}
.bar nav ul {
  display: flex;
  gap: 22px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--t-md);
}
.bar nav a {
  color: var(--c7);
  display: inline-block;
  padding: 13px 2px;
}
.bar nav a[aria-current] {
  color: var(--c15);
  text-decoration: underline;
}
@media (hover: hover) {
  .bar nav a:hover {
    color: var(--c15);
    text-decoration: underline;
  }
}
.places {
  margin-left: auto;
  position: relative;
  font-size: var(--t-md);
}
.places summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 5px 12px;
  border: 2px solid var(--c8);
  color: var(--c7);
  min-height: 34px;
}
.places summary::-webkit-details-marker {
  display: none;
}
.places[open] summary {
  border-color: var(--c14);
  color: var(--c15);
}
@media (hover: hover) {
  .places summary:hover {
    border-color: var(--c14);
    color: var(--c15);
  }
}
.places summary .lab {
  font: 11px/22px var(--pixel);
  color: var(--muted-dark);
}
.places .here {
  color: var(--c15);
}
.places .caret::before {
  content: "▾";
  color: var(--c14);
}
.places[open] .caret::before {
  content: "▴";
}
.places ol {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 60;
  list-style: none;
  margin: 0;
  padding: 6px;
  background: var(--ink);
  border: 2px solid var(--c14);
  min-width: 360px;
}
.places li a {
  position: relative;
  display: flex;
  gap: 14px;
  padding: 8px 10px 8px 24px;
  color: var(--c7);
  text-decoration: none;
}
@media (hover: hover) {
  .places li a:hover {
    background: #2b2840;
    color: var(--c15);
  }
}
.places li a[aria-current] {
  color: var(--c15);
}
.places li a[aria-current]::before {
  content: "▸";
  color: var(--c14);
  position: absolute;
  left: 8px;
}
.places .nau {
  font: 11px/22px var(--pixel);
  color: var(--c14);
  min-width: 11ch;
}
.places .pl {
  color: inherit;
}

@media (max-width: 899px) {
  :root {
    --bar-h: 90px; /* the bar is two rows here, about 86px with the mark */
    --gut: 28px;
  }
  .bar-in {
    flex-wrap: wrap;
    gap: 0 16px;
    padding-bottom: 6px;
    min-height: 0;
  }
  .bar .home {
    padding: 4px 0;
  }
  .bar .home .mark {
    width: 36px;
    height: 36px;
  }
  .bar .home .wordmark {
    display: none;
  }
  .bar nav ul {
    gap: 14px;
  }
  .bar nav a {
    padding: 7px 2px;
  }
  .places {
    margin-left: 0;
    flex: 1 1 100%;
  }
  .places summary {
    width: 100%;
    padding-block: 3px;
    min-height: 0;
  }
  .places ol {
    left: 0;
    right: 0;
    min-width: 0;
  }
}
@media (max-width: 600px) {
  :root {
    --px: 3px;
    --gut: 20px;
    --bar-h: 92px; /* two rows: the mark, places (or search) and the toggle, then the links */
  }
  /* the links take the second row, so the first holds the mark, the places menu or search, and the toggle */
  .bar-in > nav {
    order: 3;
    flex: 1 1 100%;
  }
  .bar-in > .places,
  .bar-in > .search {
    order: 1;
    min-width: 0;
  }
  .bar-in > .mode {
    order: 2;
  }
  .places summary {
    min-width: 0;
  }
  .places .here {
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

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

/* the install commands keep each line whole and scroll sideways on a narrow screen, so a URL never breaks mid-word */
.cmd pre[tabindex] {
  white-space: pre;
  overflow-x: auto;
}
@media (max-width: 600px) {
  /* on a phone the copy button gets its own strip above the lines, which then scroll sideways clear of it */
  .cmd:has(pre[tabindex]) {
    padding-top: 42px;
  }
  .cmd pre[tabindex] {
    padding-right: 0;
  }
}
