/* fun-refactor — one stylesheet, no external requests.
   The type does the work: this is a tool for people who read diffs, so the page is
   set like something meant to be read, with the terminal voice kept for terminals.

   The palette is the one the mainframe manuals were printed in: a flat grey scale, one
   saturated blue that means "you can act on this", and square corners everywhere. Any
   colour that is not the blue is carrying information — a confidence tier, a diff line —
   so there is nothing left over to decorate with. */

:root {
  color-scheme: light dark;

  --ink: #161616;
  --ink-soft: #525252;
  --ink-faint: #6f6f6f;
  --paper: #f4f4f4;
  --paper-raised: #ffffff;
  --rule: #c6c6c6;
  --rule-soft: #e0e0e0;

  /* One blue, and a darker one for the pressed state. Nothing else is blue. */
  --accent: #0043ce;
  --accent-soft: #002d9c;
  --btn-ink: #ffffff;
  --exact: #0e6027;
  --weak: #8e6a00;
  --refuse: #a2191f;

  --term-bg: #161616;
  --term-ink: #f4f4f4;
  --term-dim: #8d8d8d;
  /* The terminal is dark whichever way the page is, so it cannot borrow the page's
     blue: `#0043ce` on `#161616` is a shape and not a colour. */
  --term-accent: #78a9ff;

  --measure: 34rem;
  --wide: 74rem;

  /* Named first where it happens to be installed, never fetched: a stylesheet that
     reaches for a font is a stylesheet that fails offline. */
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --serif: ui-serif, Georgia, Cambria, "Times New Roman", serif;

  --step: 0.25rem;
  /* Square. A rounded corner is a decision about mood; this palette has none to make. */
  --radius: 0;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #f4f4f4;
    --ink-soft: #c6c6c6;
    --ink-faint: #8d8d8d;
    --paper: #161616;
    --paper-raised: #262626;
    --rule: #393939;
    --rule-soft: #262626;
    --accent: #78a9ff;
    --accent-soft: #a6c8ff;
    --btn-ink: #161616;
    --exact: #42be65;
    --weak: #f1c21b;
    --refuse: #ff8389;
    --term-bg: #0b0b0b;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ink: #f4f4f4;
  --ink-soft: #c6c6c6;
  --ink-faint: #8d8d8d;
  --paper: #161616;
  --paper-raised: #262626;
  --rule: #393939;
  --rule-soft: #262626;
  --accent: #78a9ff;
  --accent-soft: #a6c8ff;
  --btn-ink: #161616;
  --exact: #42be65;
  --weak: #f1c21b;
  --refuse: #ff8389;
  --term-bg: #0b0b0b;
}

:root[data-theme="light"] {
  color-scheme: light;
  --ink: #161616;
  --ink-soft: #525252;
  --ink-faint: #6f6f6f;
  --paper: #f4f4f4;
  --paper-raised: #ffffff;
  --rule: #c6c6c6;
  --rule-soft: #e0e0e0;
  --accent: #0043ce;
  --accent-soft: #002d9c;
  --btn-ink: #ffffff;
  --exact: #0e6027;
  --weak: #8e6a00;
  --refuse: #a2191f;
  --term-bg: #161616;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------------------------------------------------------------- structure */

.shell { max-width: var(--wide); margin: 0 auto; padding: 0 1.5rem; }
.prose { max-width: var(--measure); }
.prose.wide { max-width: 48rem; }

section { padding: 4.5rem 0; border-top: 1px solid var(--rule-soft); }
section:first-of-type { border-top: 0; }

/* ------------------------------------------------------------------- header */

header.top {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--rule-soft);
}

.top-inner {
  max-width: var(--wide);
  margin: 0 auto;
  padding: 0.75rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.wordmark {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.wordmark span { color: var(--accent); }

nav.top-nav { display: flex; gap: 1.25rem; margin-left: auto; align-items: center; flex-wrap: wrap; }
nav.top-nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.9rem;
  padding-bottom: 2px;
  border-bottom: 1.5px solid transparent;
}
nav.top-nav a:hover { color: var(--ink); }
nav.top-nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--accent); }

.theme-toggle {
  background: none;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
  border-radius: var(--radius);
  width: 2rem;
  height: 2rem;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  display: grid;
  place-items: center;
}
.theme-toggle:hover { color: var(--ink); border-color: var(--ink-faint); }

/* --------------------------------------------------------------- typography */

h1, h2, h3 { line-height: 1.15; letter-spacing: -0.02em; margin: 0 0 0.75rem; font-weight: 620; }
h1 { font-size: clamp(2.2rem, 5.5vw, 3.4rem); max-width: 20ch; }
/* The hero sets its own measure: at the body's 34rem the intended two-line break
   strands a word, and a headline that breaks badly reads as a mistake. */
h1.prose { max-width: 16ch; }
h2 { font-size: clamp(1.5rem, 3vw, 2rem); margin-top: 0; }
h3 { font-size: 1.15rem; margin-top: 2.5rem; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  margin: 0 0 1rem;
}

.lede { font-size: 1.2rem; color: var(--ink-soft); }
p { margin: 0 0 1.1rem; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

.note {
  font-size: 0.9rem;
  color: var(--ink-faint);
  border-left: 2px solid var(--rule);
  padding-left: 1rem;
}

/* -------------------------------------------------------------------- terminal */

.term {
  background: var(--term-bg);
  color: var(--term-ink);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.6;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--term-bg) 70%, var(--rule));
}

.term-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  color: var(--term-dim);
  font-size: 0.72rem;
}
.dot { width: 10px; height: 10px; border-radius: 50%; background: #525252; }
.term-title { margin-left: 0.5rem; }

.term-body { padding: 1rem 1.1rem; overflow-x: auto; }
.term-body pre { margin: 0; white-space: pre; font: inherit; }

.term .cmd { color: #fff; }
.term .cmd::before { content: "$ "; color: var(--term-accent); }
.term .exact { color: #42be65; }
.term .weak { color: #f1c21b; }
.term .refuse { color: #ff8389; }
.term .add { color: #42be65; }
.term .del { color: #ff8389; }
.term .dim { color: var(--term-dim); }

/* ---------------------------------------------------------------- components */

.grid { display: grid; gap: 1.25rem; }
@media (min-width: 720px) { .grid.two { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .grid.three { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.4rem;
}
.card h3 { margin-top: 0; font-size: 1rem; }
.card p:last-child { margin-bottom: 0; }

.stat { border-left: 2px solid var(--accent); padding-left: 1rem; }
.stat .num {
  font-family: var(--mono);
  font-size: 1.9rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  display: block;
  line-height: 1.1;
}
.stat .what { font-size: 0.9rem; color: var(--ink-soft); }

.pills { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0; margin: 0; list-style: none; }
.pills li {
  font-family: var(--mono);
  font-size: 0.78rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.15rem 0.7rem;
  color: var(--ink-soft);
}

.btn {
  display: inline-block;
  font-size: 0.92rem;
  padding: 0.6rem 1.15rem;
  border-radius: var(--radius);
  text-decoration: none;
  border: 1px solid var(--accent);
  background: var(--accent);
  /* Fixed, not the page's paper: the blue is light in the dark theme and dark in the
     light one, and a label that followed the page would vanish into one of them. */
  color: var(--btn-ink);
  font-weight: 500;
}
.btn.ghost { background: none; color: var(--ink); border-color: var(--rule); }
.btn.ghost:hover { border-color: var(--ink-faint); }
.btn-row { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 1.75rem; }

code:not(pre code) {
  font-family: var(--mono);
  font-size: 0.86em;
  background: var(--rule-soft);
  padding: 0.1em 0.35em;
  border-radius: var(--radius);
}

/* Tables scroll on their own so the page never does. */
.scroll-x { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
th, td { text-align: left; padding: 0.5rem 0.9rem 0.5rem 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
th { font-weight: 600; color: var(--ink-soft); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; }
td code { white-space: nowrap; }

.tier-exact { color: var(--exact); font-family: var(--mono); font-size: 0.85em; }
.tier-weak { color: var(--weak); font-family: var(--mono); font-size: 0.85em; }
.tier-refuse { color: var(--refuse); font-family: var(--mono); font-size: 0.85em; }

/* ------------------------------------------------------------------- footer */

footer {
  border-top: 1px solid var(--rule-soft);
  padding: 2.5rem 0 3.5rem;
  color: var(--ink-faint);
  font-size: 0.85rem;
}
footer a { color: var(--ink-soft); }
.footer-inner { display: flex; gap: 2rem; flex-wrap: wrap; justify-content: space-between; }

/* -------------------------------------------------------------------- demo */

.demo-layout { display: grid; gap: 1.5rem; }
@media (min-width: 940px) { .demo-layout { grid-template-columns: 15rem 1fr; align-items: start; } }

.steps { list-style: none; margin: 0; padding: 0; position: sticky; top: 5rem; }
.steps li { margin-bottom: 0.3rem; }
.steps button {
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-left: 2px solid var(--rule);
  color: var(--ink-faint);
  padding: 0.4rem 0 0.4rem 0.85rem;
  cursor: pointer;
  font: inherit;
  font-size: 0.86rem;
  line-height: 1.35;
}
.steps button:hover { color: var(--ink-soft); }
.steps button[aria-selected="true"] { color: var(--ink); border-left-color: var(--accent); font-weight: 500; }
.steps .n { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-faint); margin-right: 0.4rem; }

.demo-controls { display: flex; gap: 0.6rem; align-items: center; margin-top: 1rem; flex-wrap: wrap; }
.demo-controls button {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  color: var(--ink);
  border-radius: var(--radius);
  cursor: pointer;
}
.demo-controls button:hover { border-color: var(--ink-faint); }
.demo-caption { font-size: 0.95rem; color: var(--ink-soft); margin-top: 1.1rem; min-height: 3.2em; }

.recorded {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.1rem 0.6rem;
}

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

/* ------------------------------------------------ catalogue and translation */

.filters { display: flex; gap: 0.5rem; margin-bottom: 2rem; flex-wrap: wrap; }
.filters button {
  font: inherit;
  font-size: 0.9rem;
  background: none;
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.3rem 0.9rem;
  cursor: pointer;
}
.filters button:hover { color: var(--ink-soft); border-color: var(--ink-faint); }
.filters button[aria-selected="true"] {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}

.catalog-layout { display: grid; gap: 2rem; }
@media (min-width: 62rem) {
  .catalog-layout { grid-template-columns: 15rem 1fr; }
  .catalog-index { position: sticky; top: 5rem; align-self: start; max-height: 80vh; overflow-y: auto; }
}
.catalog-index ol { list-style: none; margin: 0; padding: 0; counter-reset: entry; }
.catalog-index li { counter-increment: entry; margin-bottom: 0.35rem; }
.catalog-index a {
  display: block;
  font-size: 0.9rem;
  color: var(--ink-faint);
  text-decoration: none;
  border-left: 2px solid transparent;
  padding: 0.1rem 0 0.1rem 0.7rem;
}
.catalog-index a::before {
  content: counter(entry);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--rule);
  margin-right: 0.45rem;
}
.catalog-index a:hover { color: var(--ink); border-left-color: var(--accent); }

.entry { margin-bottom: 3.5rem; scroll-margin-top: 5rem; }
.entry h3 { margin: 0 0 0.35rem; font-size: 1.15rem; }
.entry-intent { margin: 0 0 0.6rem; color: var(--ink-soft); max-width: var(--measure); }
/* What the move preserves. The definition of a refactoring is that something does not
   change, so the sentence naming it gets the same weight as the sentence naming the
   change. */
.entry-invariant {
  margin: 0 0 0.7rem;
  padding: 0.5rem 0.75rem;
  border-left: 3px solid var(--rule);
  color: var(--ink-soft);
  max-width: var(--measure);
  font-size: 0.94rem;
}
.entry-invariant strong { color: var(--ink); }
.sources {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}
.sources li { font-family: var(--mono); }
.sources .kind { margin-left: auto; }

.pane-tabs { margin-left: auto; display: flex; gap: 0.15rem; }
.pane-tabs button {
  font: inherit;
  font-size: 0.75rem;
  background: none;
  color: var(--term-dim);
  border: 0;
  border-radius: var(--radius);
  padding: 0.15rem 0.55rem;
  cursor: pointer;
}
.pane-tabs button:hover { color: var(--term-ink); }
.pane-tabs button[aria-selected="true"] { color: var(--term-ink); background: rgba(255,255,255,0.09); }

.specimen-cmd {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.6rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-soft);
  overflow-x: auto;
}
.specimen-cmd code { white-space: pre; }
.specimen-cmd code::before { content: "$ "; color: var(--accent); }
.specimen-cmd .copy {
  font: inherit;
  margin-left: auto;
  flex: none;
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink-faint);
  padding: 0.1rem 0.5rem;
  cursor: pointer;
}
.specimen-cmd .copy:hover { color: var(--ink); border-color: var(--ink-faint); }

.recipe-pair { display: grid; gap: 1.25rem; }
@media (min-width: 68rem) { .recipe-pair { grid-template-columns: 22rem 1fr; align-items: start; } }
.recipe-source {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-left: 2px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  margin: 0;
  overflow-x: auto;
  font-size: 0.8rem;
  line-height: 1.5;
}
.grammar {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  overflow-x: auto;
  font-size: 0.82rem;
}

/* The two sides of a crossing, side by side. Same question, two documents. */
.contract-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 1.25rem;
}
.contract-columns h4 { margin: 0 0 0.5rem; font-size: 0.95rem; color: var(--ink-soft); }
.op-list { list-style: none; margin: 0; padding: 0; font-size: 0.9rem; }
.op-list li { padding: 0.15rem 0.4rem; }
/* The same two colours the diff panes use, so a reader who has scrolled past one
   recognises the other. */
.op-list li.del { background: color-mix(in srgb, #ff8389 18%, transparent); }
.op-list li.add { background: color-mix(in srgb, #42be65 18%, transparent); }

/* ------------------------------------------------------- the types tutorial
 *
 * A reading page with a panel that answers questions about what it is reading.
 * The panel is fixed because the code it describes is long: scrolling to a symbol
 * and then scrolling back to read about it would be the whole page's worth of work.
 */

.has-panel main {
  margin-right: 25vw;
}

#panel {
  position: fixed;
  top: 0;
  right: 0;
  width: 25vw;
  height: 100vh;
  overflow-y: auto;
  border-left: 1px solid var(--rule);
  background: var(--paper-raised);
  padding: 5.5rem 1.5rem 2rem;
  z-index: 5;
}

.panel-title {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  margin: 0 0 1rem;
}

.panel-hint {
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.panel-name {
  font-family: var(--mono);
  font-size: 1.15rem;
  color: var(--accent);
  margin: 0 0 1rem;
  word-break: break-word;
}

.panel-fields {
  margin: 0;
  font-size: 0.9rem;
}

.panel-fields dt {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 1rem;
}

.panel-fields dd {
  margin: 0.15rem 0 0;
  font-family: var(--mono);
  line-height: 1.5;
  word-break: break-word;
}

.panel-type {
  color: var(--exact);
}

/* A symbol you can ask about. It has to sit in the text without moving it, so no
 * padding and no border — only a colour and an underline that appears on approach. */
.sym {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  border-bottom: 1px dotted var(--rule);
}

.sym:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.sym.on {
  background: var(--accent-soft);
  color: var(--accent);
}

.stage {
  margin: 4rem 0;
  padding-top: 2rem;
  border-top: 1px solid var(--rule-soft);
}

.stage-head h2 {
  margin-top: 0.25rem;
}

.kills {
  border-left: 3px solid var(--exact);
  padding-left: 1rem;
  margin: 1.25rem 0;
}

.kills-label {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--exact);
  display: block;
}

.score {
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.side-by-side {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  margin-top: 1.5rem;
}

.pane {
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  overflow: hidden;
}

.pane-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.78rem;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
}

.pane-head .tag {
  color: var(--ink-faint);
  letter-spacing: 0.06em;
}

.pane .code {
  margin: 0;
  padding: 0.9rem;
  overflow-x: auto;
  font-size: 0.78rem;
  line-height: 1.65;
}

.scoreboard {
  width: 100%;
  font-size: 0.88rem;
}

.scoreboard .num {
  text-align: right;
  font-family: var(--mono);
  width: 5.5rem;
}

.scoreboard .bar {
  width: 40%;
  padding: 0.4rem 0.75rem;
}

.scoreboard .bar span {
  display: inline-block;
  height: 0.6rem;
  vertical-align: middle;
}

.bar-declared {
  background: var(--exact);
}

.bar-inferred {
  background: var(--weak);
}

.bar-unknown {
  background: var(--rule);
}

/* One column, and the panel below and not beside, once there is no room for two.
 * A 25vw panel on a phone is a column of single words. */
@media (max-width: 1100px) {
  .has-panel main {
    margin-right: 0;
  }

  #panel {
    position: static;
    width: auto;
    height: auto;
    border-left: 0;
    border-top: 1px solid var(--rule);
    padding: 2rem 1.5rem;
  }

  .side-by-side {
    grid-template-columns: 1fr;
  }
}

/* ------------------------------------------------- the type-safety tutorial */

.ts-toc {
  margin: 1.5rem 0 0;
  padding-left: 1.5rem;
  columns: 2 22rem;
  column-gap: 3.5rem;
}
.ts-toc li { margin: 0.35rem 0; break-inside: avoid; }
.ts-progress { margin-right: 0.6rem; accent-color: var(--accent); }

.ts-example { margin: 1.5rem 0; }

.ts-example-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.ts-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  align-items: start;
}

@media (max-width: 820px) {
  .ts-pair { grid-template-columns: 1fr; }
}

.ts-pane { min-width: 0; }

.ts-pane-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
  border: 1px solid var(--rule-soft);
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  padding: 0.3rem 0.75rem;
  background: var(--raised);
}

.ts-pane pre {
  margin: 0;
  padding: 0.75rem;
  border: 1px solid var(--rule-soft);
  border-radius: 0 0 6px 6px;
  background: var(--sunken);
  overflow-x: auto;
  font-size: 0.8rem;
  line-height: 1.5;
}

.ts-badge {
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
}
.ts-badge.accepted {
  color: var(--exact);
  border: 1px solid var(--exact);
  background: color-mix(in srgb, var(--exact) 10%, transparent);
}
.ts-badge.rejected {
  color: var(--refuse);
  border: 1px solid var(--refuse);
  background: color-mix(in srgb, var(--refuse) 10%, transparent);
}
.ts-badge.runs {
  color: var(--accent);
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.ts-solution { margin: 1rem 0; }
.ts-solution summary { cursor: pointer; font-weight: 600; }
.ts-solution[open] summary { margin-bottom: 0.5rem; }

.ts-next { margin-top: 2rem; font-weight: 600; }
.ts-next a::after { content: " →"; }

/* Wide tables scroll inside their own box; the page never scrolls sideways. */
.table-scroll { overflow-x: auto; }
.ts-page .table-scroll table { min-width: 44rem; }
.ts-page th, .ts-page td { padding: 0.55rem 1rem 0.55rem 0.4rem; }
.ts-page tr:nth-child(even) td { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.ts-page tr:hover td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.ts-missing { color: var(--refuse); font-weight: 600; }

.ts-diff-added { color: var(--exact); }
.ts-diff-removed { color: var(--refuse); }
.ts-diff-meta { color: var(--ink-faint); }

/* One improvement: predecessor, the diff between them, the improved version,
   and any call the checker now rejects. */
.ts-block {
  margin: 1.5rem 0 2.5rem;
  border: 1px solid var(--rule-soft);
  border-radius: 12px;
  padding: 1rem 1.25rem 1.25rem;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.06);
}

.ts-block-head { margin-bottom: 0.5rem; }

.ts-block-head h4 { margin: 0; font-size: 1.05rem; }

/* Centred on the border between the Python and the TypeScript pane. */
.ts-block-controls {
  display: flex;
  justify-content: center;
  margin-bottom: 0.5rem;
}

.ts-view-code[hidden],
.ts-view-diff[hidden] { display: none; }

.ts-diff-button {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.3rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--raised);
  color: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.ts-diff-button:hover,
.ts-diff-button[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }

.ts-row { margin: 1rem 0; }
.ts-row-label { font-size: 0.9rem; margin-bottom: 0.4rem; color: var(--ink-soft); }
.ts-row-label strong { color: var(--ink); }
.ts-diff-row[hidden] { display: none; }

/* The code colours, in both themes' variables. */
.tok-kw { color: var(--accent); }
.tok-str { color: var(--exact); }
.tok-com { color: var(--ink-faint); }
.tok-num { color: var(--weak); }

/* The tutorial's examples are two code panes side by side, and the site's shell
   width was sized for prose. The page takes 90% of the screen; paragraphs keep
   their measure so the text stays readable. */
.ts-page .shell { max-width: 90vw; }
.ts-page .prose { max-width: none; }

/* ------------------------------------------------------------- type-safety quiz */

.ts-quiz-card {
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: 1rem 1.25rem 1.25rem;
  margin: 2.5rem 0 1rem;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.06);
}
.ts-quiz-question { font-weight: 600; margin: 0.25rem 0 1rem; }
.ts-quiz-controls { display: flex; gap: 0.75rem; justify-content: center; margin: 1.25rem 0 0.5rem; }
.ts-quiz-button {
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.45rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--raised);
  color: inherit;
  cursor: pointer;
}
.ts-quiz-reveal p {
  margin: 0.75rem 0 0;
  padding: 0.6rem 0.9rem;
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border-radius: 0 6px 6px 0;
}
.ts-quiz-button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.ts-quiz-button:disabled { opacity: 0.45; cursor: default; }
.ts-quiz-reveal { margin-top: 0.75rem; }
.ts-quiz-reveal .ts-quiz-next { display: block; margin: 0.75rem auto 0; }

.ts-checker-words { margin: 0.75rem 0 0.25rem; }
.ts-checker-words summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
}
.ts-checker-words[open] summary { margin-bottom: 0.5rem; }
.ts-checker-words pre { white-space: pre-wrap; }

::highlight(ts-same-text) {
  background-color: color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 2px;
}

/* --------------------------------------------------------- notebook cells */

.ts-block, .ts-example, .ts-quiz, .ts-quiz-card { max-width: 1100px; margin-left: auto; margin-right: auto; }

.ts-block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.ts-lang-toggle {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: 999px;
  overflow: hidden;
  flex: none;
}
.ts-lang-toggle button {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.25rem 0.9rem;
  border: none;
  background: var(--raised);
  color: var(--ink-soft);
  cursor: pointer;
}
.ts-lang-toggle button + button { border-left: 1px solid var(--rule); }
.ts-lang-toggle button[aria-pressed="true"] {
  background: var(--sunken);
  color: var(--accent);
}

.ts-cell-button {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.2rem 0.8rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--raised);
  color: inherit;
  cursor: pointer;
}
.ts-cell-button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.ts-cell-button:disabled { opacity: 0.45; cursor: default; }

/* The page is about the checker, so the check button leads the row. */
.ts-cell-button[data-action="check"] {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--rule));
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

.ts-edit-link {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.2rem 0.8rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--raised);
  color: inherit;
  text-decoration: none;
}
.ts-edit-link:hover { border-color: var(--accent); color: var(--accent); }

.ts-run-out {
  margin: 0;
  padding: 0.6rem 0.75rem 0.6rem 1rem;
  border: 1px solid var(--rule-soft);
  border-top: none;
  border-radius: 0 0 6px 6px;
  border-left: 3px solid var(--rule);
  background: var(--raised);
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 0.8rem;
  white-space: pre-wrap;
  color: var(--ink-soft);
}
.ts-cell:has(.ts-run-out:not([hidden])) pre { border-radius: 0; }
.ts-run-ok { border-left-color: var(--accent); color: var(--ink); }
.ts-run-err { border-left-color: #c4483e; color: var(--ink); }

/* ------------------------------------------------------------ editable cells */

.ts-editor { position: relative; }
.ts-editor pre { overflow: hidden; }
.ts-editor-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0.75rem;
  border: 1px solid transparent;
  border-radius: 0 0 6px 6px;
  background: transparent;
  color: transparent;
  caret-color: var(--ink);
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre;
  overflow: auto;
  resize: none;
  outline: none;
  tab-size: 8;
}
.ts-editor pre code { tab-size: 8; }
.ts-editor:focus-within pre { border-color: var(--accent); }

.ts-cell-buttons { display: inline-flex; gap: 0.5rem; }
.ts-reset-button {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.2rem 0.8rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--raised);
  color: var(--ink-soft);
  cursor: pointer;
}
.ts-reset-button:hover { border-color: var(--accent); color: var(--accent); }

.ts-mantras {
  margin: 3.5rem auto 1rem;
  max-width: 1100px;
  text-align: center;
  border-top: 1px solid var(--rule-soft);
  padding-top: 2rem;
}
.ts-mantras p {
  margin: 0.4rem 0;
  font-weight: 600;
  font-size: 1.05rem;
}

.ts-epigraph {
  margin: 0 0 1.5rem;
  padding-left: 1rem;
  border-left: 3px solid var(--rule);
}
.ts-epigraph p { margin: 0; font-style: italic; color: var(--ink-soft); }
.ts-epigraph cite { display: block; margin-top: 0.3rem; font-size: 0.85rem; color: var(--ink-faint); font-style: normal; }
