@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-latin-400.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/ibm-plex-mono-latin-500.woff2") format("woff2");
}

/* Themes. Tokyo Night is the default; the `theme` command switches and the
   choice is remembered. Dim text is a little brighter than the original comment
   colour of each theme because here it carries real content. No body is pure
   black: light text on #000 shimmers. */

:root {
  color-scheme: dark;
  --desk: #0e0f17;
  --desk-glow: #181a2b;
  --win: #1a1b26;
  --bar-top: #212331;
  --bar-bottom: #1c1d29;
  --status: #16161e;
  --line: rgba(192, 202, 245, 0.08);
  --bevel: rgba(192, 202, 245, 0.08);
  --edge: rgba(0, 0, 0, 0.7);
  --shadow: 0 34px 80px -30px rgba(0, 0, 0, 0.9);
  --fg: #c0caf5;
  --bright: #e6eaff;
  --dim: #7d84ab;
  --faint: #292e42;
  --accent: #7aa2f7;
  --warn: #e0af68;
  --green: #9ece6a;
  --blue: #7dcfff;
  --red: #f7768e;
  --light-off: #3b4261;
  --select: rgba(51, 70, 124, 0.8);
}

:root[data-theme="storm"] {
  --desk: #151826;
  --desk-glow: #1e2236;
  --win: #24283b;
  --bar-top: #2b3047;
  --bar-bottom: #262b3f;
  --status: #1f2335;
  --dim: #8a92ba;
  --faint: #2f344d;
  --light-off: #444b6a;
}

:root[data-theme="day"] {
  color-scheme: light;
  --desk: #c9cedc;
  --desk-glow: #dcdfe9;
  --win: #e1e2e7;
  --bar-top: #d8dbe6;
  --bar-bottom: #ced2df;
  --status: #d0d5e3;
  --line: rgba(55, 96, 191, 0.16);
  --bevel: rgba(255, 255, 255, 0.7);
  --edge: rgba(30, 40, 80, 0.22);
  --shadow: 0 34px 70px -34px rgba(30, 40, 90, 0.42);
  --fg: #3760bf;
  --bright: #1e3a8a;
  --dim: #55629a;
  --faint: #c4c8da;
  --accent: #2e7de9;
  --warn: #8c6c3e;
  --green: #587539;
  --blue: #007197;
  --red: #c8264f;
  --light-off: #b7bccd;
  --select: rgba(46, 125, 233, 0.22);
}

:root[data-theme="carbon"] {
  --desk: #08090b;
  --desk-glow: #101319;
  --win: #14161b;
  --bar-top: #23262d;
  --bar-bottom: #1b1e24;
  --status: #101216;
  --line: rgba(255, 255, 255, 0.075);
  --bevel: rgba(255, 255, 255, 0.09);
  --edge: rgba(0, 0, 0, 0.65);
  --fg: #cfd3da;
  --bright: #f3f5f8;
  --dim: #7f858f;
  --faint: #2b2f37;
  --accent: #e2a86b;
  --warn: #e2a86b;
  --green: #8cc29a;
  --blue: #86acde;
  --red: #e58f82;
  --light-off: #3c4048;
  --select: rgba(226, 168, 107, 0.3);
}

:root[data-theme="paper"] {
  color-scheme: light;
  --desk: #e9e6df;
  --desk-glow: #f3f1ec;
  --win: #fcfbf8;
  --bar-top: #efece6;
  --bar-bottom: #e3e0d9;
  --status: #f1eee8;
  --line: rgba(0, 0, 0, 0.1);
  --bevel: rgba(255, 255, 255, 0.9);
  --edge: rgba(0, 0, 0, 0.16);
  --shadow: 0 34px 70px -34px rgba(60, 45, 20, 0.45);
  --fg: #2e3036;
  --bright: #0f1012;
  --dim: #71757d;
  --faint: #dcd8d0;
  --accent: #a3561a;
  --warn: #a3561a;
  --green: #2f7d4a;
  --blue: #2c5c9a;
  --red: #b3412f;
  --light-off: #cfcbc3;
  --select: rgba(163, 86, 26, 0.22);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  transition: background-color 0.25s ease, color 0.25s ease;
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.25rem max(0.75rem, env(safe-area-inset-right)) 1.25rem max(0.75rem, env(safe-area-inset-left));
  background: radial-gradient(120% 90% at 50% 0%, var(--desk-glow), var(--desk) 62%);
  background-color: var(--desk);
  color: var(--fg);
  font: 400 13px/1.6 "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-ligatures: none;
  font-feature-settings: "zero" 1;
  -webkit-font-smoothing: antialiased;
}

@media (min-width: 640px) {
  body {
    font-size: 14px;
    padding-top: 2rem;
    padding-bottom: 2rem;
  }
}

::selection {
  background: var(--select);
}

/* The window */

.win {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 46rem;
  height: min(40rem, calc(100vh - 2.5rem));
  height: min(40rem, calc(100dvh - 2.5rem));
  overflow: hidden;
  border-radius: 12px;
  background: var(--win);
  box-shadow: 0 0 0 1px var(--edge), var(--shadow);
  animation: appear 0.4s ease both;
}

@keyframes appear {
  from { opacity: 0; }
}

.titlebar {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 14px;
  background: linear-gradient(var(--bar-top), var(--bar-bottom));
  box-shadow: inset 0 1px 0 var(--bevel), inset 0 -1px 0 var(--line);
  border-radius: 12px 12px 0 0;
  user-select: none;
}

.lights {
  display: inline-flex;
  gap: 8px;
}

.lights i {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.22);
  transition: background-color 0.2s ease;
}

.lights i:nth-child(1) { background: #ff5f57; }
.lights i:nth-child(2) { background: #febc2e; }
.lights i:nth-child(3) { background: #28c840; }

/* Absolutely centred so the lights never push the title off centre. */
.title {
  position: absolute;
  inset-inline: 80px;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--dim);
  /* Same face as the terminal: a system UI font renders differently on every OS. */
  font: 500 12px/1 "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  transition: opacity 0.2s ease;
}

/* A window that lost focus: grey lights, quieter title, hollow cursor. */
.win.inactive .lights i {
  background: var(--light-off);
}

.win.inactive .title {
  opacity: 0.6;
}

@media (min-width: 720px) {
  .win {
    height: min(31rem, calc(100vh - 4rem));
    height: min(31rem, calc(100dvh - 4rem));
  }
}

.win-small {
  height: auto;
  min-height: 14rem;
}

/* On pages without the script nothing is armed, so nothing may stay hidden. */

/* Panes, as in a tmux window: about and build side by side, the shell below.
   One gutter, one key column width, and every gap is a whole row. */

.panes {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 0.6fr) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
}

.pane {
  min-width: 0;
  padding: 16px 20px;
}

.pane-about {
  border-right: 1px solid var(--line);
}

.pane-about,
.pane-build {
  border-bottom: 1px solid var(--line);
}

.pane-shell {
  grid-column: 1 / -1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  cursor: text;
  /* Scrolled rows fade out under the pane edge instead of being cut mid-row. */
  -webkit-mask-image: linear-gradient(transparent, #000 17px);
  mask-image: linear-gradient(transparent, #000 17px);
}

.pane-shell::-webkit-scrollbar,
.panes::-webkit-scrollbar {
  display: none;
}

/* On a phone the panes stack and the whole stack scrolls, so an open keyboard
   never squeezes the shell to nothing. */
@media (max-width: 719px) {
  .panes {
    display: block;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
  }

  .pane-about {
    border-right: 0;
  }

  .pane-shell {
    min-height: 12rem;
    overflow: visible;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* Pane header: a title row, then a rule that occupies exactly one row. */

.head {
  display: flex;
  gap: 1ch;
  margin: 0;
  overflow: hidden;
  color: var(--bright);
  font-size: 1em;
  font-weight: 500;
  white-space: nowrap;
}

.head .sigil {
  color: var(--dim);
  font-weight: 400;
}

.rule {
  display: flex;
  align-items: center;
  height: 1.6em;
}

.rule::before {
  content: "";
  flex: 1;
  border-top: 1px solid var(--faint);
}

/* Key and value rows: the same 10 cell key column in every pane and output. */

.kv {
  display: grid;
  grid-template-columns: 10ch minmax(0, 1fr);
  margin: 0;
}

.kv .k {
  color: var(--dim);
}

.kv .v {
  margin: 0;
  overflow-wrap: anywhere;
}

.kv .v b {
  color: var(--bright);
  font-weight: 500;
}

@media (min-width: 720px) {
  .kv.two {
    grid-template-columns: 10ch minmax(0, 1fr) 10ch minmax(0, 1fr);
    column-gap: 2ch;
  }
}

.out .kv .k {
  color: var(--bright);
  font-weight: 500;
}

.out .kv .v {
  color: var(--dim);
}

/* Steps */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

.step {
  display: grid;
  grid-template-columns: 2ch 10ch minmax(0, 1fr) auto;
  align-items: baseline;
}

.step .mark { color: var(--dim); }
.step.done .mark { color: var(--green); }
.step .name { color: var(--fg); }

.step .desc {
  overflow: hidden;
  color: var(--dim);
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: opacity 0.35s ease;
}

.step .desc.swap {
  opacity: 0;
}

.step .time {
  padding-left: 2ch;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.step.run .name { color: var(--bright); }
.step.run .time { color: var(--warn); }

.step.run .mark::before {
  content: "";
  display: inline-block;
  width: 0.72em;
  height: 0.72em;
  border: 1.5px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: turn 0.8s linear infinite;
}

@keyframes turn {
  to { transform: rotate(360deg); }
}

/* Shell. One font size throughout, as in a real terminal: emphasis is weight
   and brightness, never size. */

.out p {
  margin: 0;
}

.ln,
.prompt {
  display: flex;
  align-items: baseline;
  gap: 1ch;
}

.out .echo {
  margin-top: 1.6em; /* exactly one row */
}

.out .echo:first-child {
  margin-top: 0;
}

.out .res {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.out .res.err { color: var(--red); }
.out .res.dim, .dim { color: var(--dim); }

.out b {
  color: var(--bright);
  font-weight: 500;
}

/* A quiet prompt: only the sigil and the directory carry colour. */

.ps1 {
  flex: none;
  white-space: nowrap;
  user-select: none;
}

.ps1 .uh { color: var(--dim); }
.ps1 .cwd { color: var(--blue); }
.ps1 .sigil { color: var(--green); }

@media (max-width: 519px) {
  .ps1 .uh {
    display: none;
  }
}

.cursor {
  background: var(--fg);
  color: var(--win);
  white-space: pre;
  animation: blink 1.1s steps(1) infinite;
}

@keyframes blink {
  50% {
    background: transparent;
    color: inherit;
  }
}

.typedwrap {
  white-space: pre;
}

.probe {
  position: absolute;
  visibility: hidden;
  white-space: pre;
}

a {
  color: var(--fg);
  text-decoration: underline dotted var(--dim);
  text-underline-offset: 0.28em;
}

a:hover {
  color: var(--bright);
  text-decoration: underline solid var(--accent);
}

a::after {
  content: " \2197";
  color: var(--dim);
}

:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Input line: the real input is invisible and sits on top of a drawn command
   line, so the cursor can be a terminal block instead of a thin caret. */

.prompt {
  position: relative;
  margin-top: 1.6em; /* exactly one row */
}

.cmdline {
  flex: 1;
  min-width: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.ghost {
  color: var(--dim);
  opacity: 0.75;
}

.prompt input {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font: inherit;
  font-size: 16px; /* below 16px iOS zooms the page on focus */
  opacity: 0;
  cursor: text;
}

.prompt.typing .cursor {
  animation: none;
}

.prompt:not(.focus) .cursor,
.win.inactive .prompt .cursor {
  animation: none;
  background: transparent;
  color: inherit;
  box-shadow: inset 0 0 0 1px var(--dim);
}

.prompt.locked .ghost,
.prompt[hidden] {
  display: none;
}

/* tmux status line */

.status {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2ch;
  height: 26px;
  padding: 0 14px;
  background: var(--status);
  box-shadow: inset 0 1px 0 var(--line);
  color: var(--dim);
  font-size: 0.86em;
  white-space: nowrap;
  user-select: none;
}

.status .session { color: var(--accent); }
.status .active { color: var(--fg); }

.status-right {
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 419px) {
  .status .host {
    display: none;
  }
}

/* Intro. theme.js arms it before first paint; without JavaScript nothing is
   hidden and the page is simply complete. Opacity only, no transforms on text.
   Only the build pane animates: who this is can be read from the first frame. */

.js-anim .step,
.js-anim:not(.playing) .typed {
  opacity: 0;
}

.js-anim .step.in {
  opacity: 1;
  transition: opacity 0.3s ease;
}

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