/* Illuminate — one stylesheet for the landing page, the guides and the
   sandboxes. Cream paper, black rules, square corners, one typeface.

   Colour is used for exactly two things and it means the same thing on every
   page: blue is a plan, rust is a price. The pair was checked with a
   colour-vision simulator rather than by eye, and stays clearly separated
   under protanopia, deuteranopia and tritanopia in both schemes. */

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

:root {
  --paper: #fffff8;
  --panel: #ffffff;
  --ink: #000000;
  --ink2: #404040;
  --muted: #707070;
  --rule: #000000;
  --rule-soft: #C0BDAD;
  --plan: #1B4F9C;
  --price: #B4341F;
  --ok: #2E6B33;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --paper: #1a1816;
  --panel: #221f1d;
  --ink: #e8e6e0;
  --ink2: #a8a599;
  --muted: #787366;
  --rule: #e8e6e0;
  --rule-soft: #4a4540;
  --plan: #4A87CC;
  --price: #C25A42;
  --ok: #4E8F55;
  color-scheme: dark;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* Two faces from one superfamily, so they share proportions and colour.
   Mono carries the identity -- the bar, headings, contents, figures, code,
   anything that is data. Serif carries the reading, because several thousand
   words of monospace is tiring in a way that has nothing to do with taste. */
:root {
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --text-face: "IBM Plex Serif", Iowan Old Style, Georgia, serif;
}

body {
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.6;
  letter-spacing: -0.01em;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: background-color 0.2s ease, color 0.2s ease;
}

a { color: inherit; }
*:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* --- the bar ------------------------------------------------------------ */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.5rem;
  border-bottom: 2px solid var(--rule);
  position: sticky;
  top: 0;
  background: var(--paper);
  z-index: 10;
}

.brand {
  font-weight: 600;
  letter-spacing: 0.14em;
  text-decoration: none;
  font-size: 14px;
}

.toggle {
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.1em;
  font-weight: 500;
  padding: 0.35rem 0.85rem;
  height: 32px;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--rule);
  border-radius: 0;
  cursor: pointer;
}
.toggle:hover { background: var(--panel); }

/* --- prose -------------------------------------------------------------- */

main { flex: 1 0 auto; }

/* the guide pages put a chapter list beside the prose. The pair is centred as
   a unit rather than the prose being centred and the list hung off it, so the
   text stays in the same place whether or not the list is showing. */
.withtoc {
  flex: 1 0 auto;
  display: grid;
  /* min(42rem, 100%), not minmax(0, 42rem): a track whose maximum is a fixed
     length does not shrink to fit a smaller container, it overflows it. That
     is what made narrow viewports -- and so browser zoom -- scroll sideways
     instead of reflowing. */
  grid-template-columns: 14rem min(42rem, 100%);
  gap: 3.5rem;
  justify-content: center;
  align-items: start;
  padding: 0 1.5rem;
}
/* A grid item defaults to min-width:auto, which means it refuses to shrink
   below its own content -- so one wide table or code block sets a floor for
   the whole page and the layout jams instead of reflowing. Overriding it is
   what lets narrow viewports, and therefore browser zoom, work at all. */
.withtoc > * { min-width: 0; }
/* max-width:100% rather than none. The column already gets its width from the
   grid track, so `none` looks harmless -- but it lets a child that cannot wrap
   (a code block is `white-space: pre`) push the column out to the width of its
   longest line and drag the page sideways with it. Capping at the track width
   makes the code block scroll inside itself, which is what it is for. */
.withtoc .prose { padding-left: 0; padding-right: 0; max-width: 100%; }

.toc {
  position: sticky;
  top: 4.6rem;
  align-self: start;
  padding: 3rem 0 2rem;
  max-height: calc(100vh - 6rem);
  overflow-y: auto;
  font-size: 0.82rem;
  line-height: 1.4;
}
.toc-label {
  text-transform: uppercase;
  letter-spacing: 0.13em;
  font-size: 0.66rem;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 0.9rem;
}
.toc ol { list-style: none; margin: 0; padding: 0; }
.toc li { margin: 0; }
.toc a {
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  gap: 0.2rem;
  padding: 0.42rem 0;
  text-decoration: none;
  border: 0;
  color: var(--muted);
  border-left: 2px solid transparent;
  padding-left: 0.7rem;
  margin-left: -0.7rem;
}
.toc a:hover { color: var(--ink); }
.toc-num { color: var(--rule-soft); }
.toc a.current {
  color: var(--ink);
  border-left-color: var(--plan);
  font-weight: 500;
}
.toc a.current .toc-num { color: var(--plan); }

@media (max-width: 1060px) {
  .withtoc { grid-template-columns: min(42rem, 100%); }
  .toc { display: none; }
}

.prose {
  max-width: 42rem;
  margin: 0 auto;
  padding: 3rem 1.5rem 5rem;
  font-family: var(--text-face);
  font-size: 1.115rem;
  line-height: 1.68;
  letter-spacing: 0;
}

.prose h1 {
  font-family: var(--mono);
  font-size: clamp(1.5rem, 4vw, 2.05rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.2;
  margin-bottom: 1.1rem;
}

.prose h2 {
  font-family: var(--mono);
  font-size: 1.16rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 3.6rem 0 1.2rem;
  padding-top: 1.5rem;
  border-top: 2px solid var(--rule);
  scroll-margin-top: 5rem;
}

.prose h2 .num {
  display: inline-block;
  min-width: 2.4rem;
  color: var(--muted);
  font-weight: 500;
}

.prose h3 {
  font-family: var(--mono);
  font-size: 0.98rem;
  font-weight: 600;
  margin: 2.2rem 0 0.7rem;
}

.prose p { margin: 0 0 1.25rem; }
.prose strong { font-weight: 600; }
.prose em { font-style: italic; color: var(--ink2); }

/* the standfirst: the sentence under the title that says what this is */
.prose > p:first-of-type {
  font-size: 1.24rem;
  line-height: 1.5;
  color: var(--ink2);
  margin-bottom: 1.6rem;
}

.prose a {
  text-decoration: none;
  border-bottom: 1px solid var(--rule-soft);
}
.prose a:hover { border-bottom-color: var(--ink); }

.prose ul, .prose ol { margin: 0 0 1.2rem 1.3rem; }
.prose li { margin-bottom: 0.5rem; }

.prose hr {
  border: 0;
  border-top: 2px solid var(--rule);
  margin: 2.6rem 0;
}

.prose code {
  font-family: var(--mono);
  font-size: 0.86em;
  background: var(--panel);
  border: 1px solid var(--rule-soft);
  padding: 0.05em 0.35em;
  font-size: 0.92em;
  white-space: nowrap;
}

.prose pre {
  font-family: var(--mono);
  font-size: 0.86rem;
  background: var(--panel);
  border: 2px solid var(--rule);
  padding: 1rem 1.1rem;
  overflow-x: auto;
  margin: 0 0 1.4rem;
}
.prose pre code { background: none; border: 0; padding: 0; }

.aside {
  border-left: 3px solid var(--price);
  padding: 0.2rem 0 0.2rem 1.1rem;
  margin: 0 0 1.4rem;
  color: var(--ink2);
}
.aside p { margin-bottom: 0.4rem; }
.aside p:last-child { margin-bottom: 0; }

/* the one-line landing a chapter ends on */
.takeaway {
  border: 0;
  border-top: 2px solid var(--rule);
  border-bottom: 2px solid var(--rule);
  padding: 1.1rem 0 1.2rem;
  margin: 2.4rem 0 0;
  color: var(--ink);
}
.takeaway p { margin: 0; font-size: 1.1rem; line-height: 1.55; }
/* the chapter rule immediately after a landing would double its bottom edge */
.takeaway + hr { display: none; }

.takeaway strong:first-child {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 0.55rem;
}

/* how far through the guide the reader is, drawn along the bottom of the bar */
.progress {
  position: absolute;
  left: 0;
  bottom: -2px;
  height: 2px;
  background: var(--plan);
  width: 0;
}
.bar { position: sticky; }

/* --- figures ------------------------------------------------------------ */

/* A rendered figure carries its own cream paper and black ink and cannot
   repaint itself for dark mode, so it is matted instead: the plate keeps the
   light background in both schemes and reads as a plate rather than a bug. */
.plate {
  margin: 1.8rem 0 2rem;
  border: 2px solid var(--rule);
  background: #fffff8;
  padding: 0.6rem;
  line-height: 0;
}
.plate img { width: 100%; height: auto; display: block; }

/* --- tables ------------------------------------------------------------- */

.overflow-x { overflow-x: auto; margin: 0 0 1.6rem; }

table {
  font-family: var(--mono);
  border-collapse: collapse;
  width: 100%;
  font-size: 0.86rem;
  letter-spacing: -0.01em;
}
th, td {
  border-bottom: 1px solid var(--rule-soft);
  padding: 0.5rem 0.7rem;
  text-align: left;
  vertical-align: top;
}
thead th {
  border-bottom: 2px solid var(--rule);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.76rem;
  color: var(--muted);
}

/* --- chapter and topic lists -------------------------------------------- */

.chapters { list-style: none; margin: 1.6rem 0 2.4rem; }
.chapters li { border-bottom: 1px solid var(--rule-soft); margin: 0; }
.chapters a {
  display: block;
  padding: 0.85rem 0 0.35rem;
  text-decoration: none;
  border: 0;
  font-weight: 500;
}
.chapters a:hover { color: var(--plan); }
.chapters .num {
  display: inline-block;
  min-width: 2.6rem;
  color: var(--muted);
  font-weight: 400;
}
.chapters .sub {
  display: block;
  padding: 0 0 0.85rem 2.6rem;
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.5;
}

/* --- sandbox ------------------------------------------------------------ */

.sandbox {
  max-width: 46rem;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}
.sandbox h1 {
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0.8rem 0 0.5rem;
}
.back, .pager a {
  font-size: 0.82rem;
  color: var(--muted);
  text-decoration: none;
  letter-spacing: 0.04em;
}
.back:hover, .pager a:hover { color: var(--ink); }
.lede { color: var(--ink2); margin-bottom: 1.2rem; }
.try {
  border-left: 3px solid var(--plan);
  padding: 0.3rem 0 0.3rem 1rem;
  margin-bottom: 1.6rem;
  color: var(--ink2);
  font-size: 0.94rem;
}

canvas {
  width: 100%;
  height: auto;
  aspect-ratio: 660 / 380;
  display: block;
  border: 2px solid var(--rule);
  background: var(--paper);
}

.controls { margin: 1.4rem 0 0; }
.row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 0.7rem 0;
  flex-wrap: wrap;
}
.row label {
  flex: 0 0 13rem;
  font-size: 0.86rem;
  color: var(--ink2);
}
input[type="range"] { flex: 1 1 8rem; accent-color: var(--plan); }
select {
  font: inherit;
  font-size: 0.86rem;
  padding: 0.25rem 0.4rem;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--rule);
  border-radius: 0;
  /* A select is sized by its longest option and will not shrink below it,
     so one descriptive option label pushed the whole page sideways on a
     phone. flex-basis 0 makes it take its width from the space available
     rather than from its content, and min-width:0 lets that actually
     happen; without both, the option text sets a floor for the page. */
  flex: 1 1 0;
  min-width: 0;
  max-width: 100%;
}
.val {
  flex: 0 0 4.5rem;
  text-align: right;
  font-size: 0.84rem;
  color: var(--ink);
}

.out {
  margin-top: 1.3rem;
  padding: 0.95rem 1.1rem;
  border: 2px solid var(--rule);
  background: var(--panel);
  font-family: inherit;
  font-size: 0.84rem;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-x: auto;
}
.note { margin-top: 1.4rem; font-size: 0.82rem; color: var(--muted); }
.pager {
  margin-top: 2.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule-soft);
  display: flex;
  gap: 1.2rem;
  flex-wrap: wrap;
}

/* landing */

.wide { max-width: 54rem; }

.masthead {
  border-bottom: 2px solid var(--rule);
  padding-bottom: 2.6rem;
}
/* the two-line hed is set by hand, so it needs to stay narrow enough that the
   forced break is the only break */
.masthead h1 {
  font-size: clamp(1.15rem, 2.9vw, 1.85rem);
  line-height: 1.3;
  margin-bottom: 1.2rem;
}
.kicker {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.74rem;
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 1rem;
}
.standfirst { color: var(--ink2); max-width: 42rem; }

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

.guide > * { min-width: 0; }
.guide {
  display: grid;
  grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
  gap: 1.8rem;
  align-items: start;
  padding: 2.2rem 0;
  border-bottom: 2px solid var(--rule);
  margin: 0;
}

/* the preview keeps its cream mat in dark mode, like every other figure */
.guide-figure {
  display: block;
  border: 2px solid var(--rule);
  background: #fffff8;
  padding: 0.4rem;
  line-height: 0;
}
.guide-figure img { width: 100%; height: auto; display: block; }

.guide-body h2 {
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0.15rem 0 0.6rem;
  line-height: 1.2;
}
.guide-body h2 a { text-decoration: none; border: 0; }
.guide-body h2 a:hover { color: var(--plan); }
.guide-body p { color: var(--ink2); margin-bottom: 0.9rem; }

.meta {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.7rem;
  color: var(--muted);
  margin-bottom: 0.4rem !important;
}

.guide-links { display: flex; gap: 1.1rem; font-size: 0.86rem; margin: 0 !important; }
.guide-links a { text-decoration: none; border-bottom: 1px solid var(--rule-soft); }
.guide-links a:hover { border-bottom-color: var(--ink); color: var(--plan); }

.section-label {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem !important;
  font-weight: 500 !important;
  color: var(--muted);
  border: 0 !important;
  padding: 0 !important;
  margin: 2.6rem 0 1.2rem !important;
}

.queue dl { margin: 0; }
.queue dt {
  font-weight: 600;
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule-soft);
}
.queue dt:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
.queue dd { margin: 0.25rem 0 0; color: var(--muted); font-size: 0.92rem; }

.colophon { border-top: 2px solid var(--rule); margin-top: 3rem; }
.colophon p { color: var(--ink2); font-size: 0.94rem; }

@media (max-width: 620px) {
  .guide { grid-template-columns: 1fr; gap: 1.1rem; }
}

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

.foot {
  border-top: 2px solid var(--rule);
  padding: 1.4rem 1.5rem 2.4rem;
  font-size: 0.8rem;
  color: var(--muted);
  text-align: center;
}
.foot a { color: var(--muted); }

@media (max-width: 700px) {
  .row label { flex: 0 0 100%; }
  /* The label is on its own line by now, so the control gets the whole row.
     This is also the only thing that reliably stops a select from setting a
     width floor for the page: Chromium keeps its longest option as the
     min-content contribution whatever min-width says, and an explicit width
     is what overrides that. */
  .row select { width: 100%; flex: none; }
  .prose { padding-top: 2rem; }
}

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