/* Deck styling for slides.md — loaded by the <link> tag on the title slide.
   Lives outside the markdown so the deck source stays readable; colloquium
   only inlines `custom_css:` from the frontmatter, and a <link> in the slide
   body is the one hook that takes an external sheet. */

/* Local body font (not on Google Fonts): prefer the installed copy,
   fall back to the files in ../fonts so exports stay portable. */
@font-face {
  font-family: "GothamNicolas";
  src: local("GothamNicolas"),
       url("../fonts/GothamNicolas-Regular.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "GothamNicolas";
  src: local("GothamNicolas Bold"), local("GothamNicolas-Bold"),
       url("../fonts/GothamNicolas-Bold.otf") format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
/* ------------------------------------------------------------------ tokens

   The deck's palette and its one unit of vertical space, in one place, so a
   change of mind is one edit rather than twenty-two.

   Sizes are deliberately *not* here.  A hand-drawn figure is an `<svg>` with a
   `viewBox` and `width: 100%`, so `20px` inside it means 20 *canvas units*, and
   the browser then scales the canvas to fit whatever column the figure sits in
   -- a 1180-unit canvas is 0.98 of its authored size in the full slide body and
   0.47 in half of a two-column slide.  A single token therefore cannot mean one
   size on screen and one size relative to the plot at the same time, and it is
   the second that matters: each figure's type is tuned to be proportionate
   inside its own plot box.  Forcing the *rendered* size uniform instead (one
   token times a per-figure scale factor) does close the 12-to-20px spread, and
   it makes the narrower figures' labels crowd their plots, because the plot box
   does not grow with the type.  So every figure keeps its own sizes.

   The two exceptions below are read by assets/plot.js: Chart.js defaults to
   12px Helvetica and cannot see this stylesheet at all, so that file copies
   them into `Chart.defaults` to keep the six chart figures in the same
   typographic family as the hand-drawn ones. */
:root {
  --colloquium-font-body: "GothamNicolas", "Helvetica Neue", Arial, sans-serif;
  /* The theme's own stylesheet calls this --colloquium-heading; sixteen rules
     in this file ask for --colloquium-title, which nothing has ever defined,
     so every one of them was invalid at computed-value time and quietly fell
     back to `inherit`.  Naming it here is what makes them do what they say. */
  --colloquium-title: var(--colloquium-heading);

  /* The deck's three accents.  One quantity, one colour, everywhere: the navy
     of the "trained" series in the capacity chart is the navy of the number
     quoting it in the prose beside it. */
  --deck-navy: #0f3460;
  --deck-red: #c0392b;
  --deck-green: #27ae60;
  --deck-orange: #e67e22;
  /* A lighter blue, only for the "model" half of the model-vs-data pair: it
     sits next to --deck-red as a role, not as a series. */
  --deck-blue: #2980b9;
  --deck-blue-tint: #9ac7e2;
  --deck-navy-tint: #b6c3d1;
  /* Pale washes of the three accents, for a filled cell or a called-out box.
     The red one was written twice, in two figures, under no shared name. */
  --deck-navy-wash: #dce5ef;
  --deck-red-wash: #f4dede;
  --deck-green-wash: #dcefe3;

  /* The gap between a figure and the prose around it, and the one the spacer
     divs in slides.md use.  It is the one dimension that is shared: it is
     measured in the slide's own em, not in any figure's canvas units. */
  --deck-gap: 1.5em;

  /* The two greys the chart legends and assets/plot.js need: a dashed
     guide that is a reading aid rather than data, and the halo a marker
     punches in the line behind it. */
  --fig-guide: #9ca3af;
  /* The halo a marker punches in the line behind it.  The deck had two values
     for this, #fcfcfb in the SVGs and --colloquium-bg (#ffffff) in .pf-point;
     the slide background is white, so white is the one that is right. */
  --fig-surface: var(--colloquium-bg);

  /* Read by assets/plot.js, which copies them into Chart.defaults so the six
     Chart.js figures are typographically the same family as the hand-drawn
     ones.  The hand-drawn figures do *not* take their sizes from here: a
     figure is an svg scaled to fit its column, so one size in canvas units is
     a different size on screen in each of them, and the per-figure values are
     tuned to be proportionate inside their own plot box.  Trying to make the
     *rendered* size uniform instead made the type crowd the narrower plots. */
  --fig-text: 22px;
  --fig-small: 20px;
  --fig-exp: 0.72em;   /* raised exponents, the deck's one already-uniform size */
  --fig-math: 1.05em;  /* italic maths variables inside a figure */
  /* The italic-maths face, as a token and not only as the rule below.  A canvas
     cannot read a rule, and assets/plot.js draws the charts' in-plot notes on
     one, so this is the one place the deck needs the family by name. */
  --fig-math-family: "Latin Modern Math", "Cambria Math", Georgia, serif;

  --fig-data-width: 2.2;
  --fig-hair-width: 1.5;
  --fig-dash: 6 5;
  --fig-point: 2.8;

  /* The lab scoreboard's colour axis, light to dark over 0-100 % of the budget
     spent on the hero run.  Read twice: by the CSS gradient of the colourbar in
     figures/hero-board.md, and by assets/hero-board.js, which interpolates
     between these same two values for the dots -- one ramp, one definition, so
     the bar cannot end up saying something the plot does not. */
  --hero-share-lo: var(--deck-blue-tint);
  --hero-share-hi: var(--deck-navy);
}


/* Every figure's root element.  The seven figure families below each used to
   repeat this quartet and pick its own top margin; one rule means one answer,
   and the gap is the same one the prose uses. */
.matmul-fig,
.zipf-fig,
.embed-fig,
.sphere-fig,
.plot-fig,
.wbuild-fig,
.llmarch-fig {
  display: block;
  width: 100%;
  height: auto;
  margin: var(--deck-gap) auto;
  font-family: var(--colloquium-font-body);
}

/* Italic maths inside a figure.  Was three byte-identical rules, .zf-var,
   .sf-var and .pf-var, one per figure family. */
.fig .fig-var,
.fig .pf-var,
.fig .sf-var,
.fig .zf-var {
  font-family: var(--fig-math-family);
  font-style: italic;
  font-size: var(--fig-math);
}

.highlight-red { color: var(--deck-red); font-weight: 600; }
.highlight-blue { color: var(--deck-blue); font-weight: 600; }
.highlight-green { color: var(--deck-green); font-weight: 600; }
/* Same navy as the "trained" series in the capacity chart, so the number in
   the text reads as belonging to that line. */
.highlight-navy { color: var(--deck-navy); font-weight: 600; }

/* Part I FLOP intuition. The first figure expands a single row-vector dot
   product before generalising it to an m by n matrix; the second uses the
   same three accents for the three equally-sized matrix multiplications in
   training. */

.matmul-fig text { fill: var(--colloquium-text); }
.matmul-fig .mm-label { fill: var(--colloquium-muted); font-size: 18px; }
.matmul-fig .mm-bracket {
  fill: none;
  stroke: var(--colloquium-title);
  stroke-width: 2.2;
  stroke-linecap: round;
}
.matmul-fig .mm-grid rect {
  fill: var(--colloquium-code-bg);
  stroke: var(--colloquium-border);
  stroke-width: 1.2;
}
.matmul-fig .mm-highlight-grid rect { stroke-width: 1.5; }
.matmul-fig .mm-pair-a { fill: var(--deck-navy-wash); stroke: var(--deck-navy); }
.matmul-fig .mm-pair-b { fill: var(--deck-red-wash); stroke: var(--deck-red); }
.matmul-fig .mm-pair-c { fill: var(--deck-green-wash); stroke: var(--deck-green); }
.matmul-fig .mm-num, .matmul-fig .mm-output { font-size: 20px; font-variant-numeric: tabular-nums; }
.matmul-fig .mm-output { fill: var(--colloquium-title); font-weight: 700; }
.matmul-fig .mm-op { fill: var(--colloquium-muted); font-size: 28px; }
.matmul-fig .mm-chip { stroke-width: 1.5; }
.matmul-fig .mm-zero { fill: var(--colloquium-code-bg); stroke: var(--colloquium-border); }
.matmul-fig .mm-product { font-size: 20px; font-weight: 700; }
.matmul-fig .mm-caption { fill: var(--colloquium-muted); font-size: 17px; }
.matmul-fig .mm-plus { fill: var(--colloquium-muted); font-size: 25px; }
.matmul-fig .mm-result { fill: var(--colloquium-title); font-size: 23px; font-weight: 700; }
.matmul-fig .mm-divider,
.matmul-fig .mm-general-line { stroke: var(--colloquium-border); stroke-width: 1.5; }
.matmul-fig .mm-concrete { fill: var(--colloquium-muted); font-size: 18px; }
.matmul-fig .mm-count { fill: var(--colloquium-title); font-size: 23px; font-weight: 700; }
.matmul-fig .mm-general-note { fill: var(--colloquium-muted); font-size: 18px; }
.matmul-fig .mm-concrete-bottom { fill: var(--colloquium-text); font-size: 20px; }
.matmul-fig .mm-law { fill: var(--colloquium-title); font-size: 28px; font-weight: 700; }

/* Training-compute slide (10): three hairline-topped columns, one per matmul,
   with the running total as a plain centered sentence underneath.  The cards are
   sized by their own content -- no min-height -- so the slide still has room for
   the conclusion and the side note below the figure. */
.training-flops {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 0.75em;
  row-gap: 0.55em;
  align-items: stretch;
  margin: 0.25em 0 0.45em;
}
.training-flops .tf-card {
  position: relative;
  padding: 0.75em 0.7em 0.5em;
  border: 0;
  border-top: 3px solid var(--tf-accent);
  border-radius: 0;
  text-align: center;
  background: transparent;
}
.training-flops .tf-card + .tf-card { border-left: 1px solid var(--colloquium-border); }
.training-flops .tf-forward { --tf-accent: var(--deck-navy); }
.training-flops .tf-backward { --tf-accent: var(--deck-red); }
.training-flops .tf-learn { --tf-accent: var(--deck-green); }
.training-flops .tf-step {
  position: absolute;
  top: 0.4em;
  left: 0.6em;
  display: grid;
  place-items: center;
  width: 1.55em;
  height: 1.55em;
  border-radius: 50%;
  color: white;
  background: var(--tf-accent);
  font-size: 0.66em;
  font-weight: 700;
}
.training-flops .tf-title { color: var(--colloquium-title); font-size: 0.88em; font-weight: 700; }
.training-flops .tf-purpose { color: var(--colloquium-muted); font-size: 0.57em; margin: 0.15em 0 0.35em; }
.training-flops .tf-equation {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.8em;
  margin-top: 0.2em;
  color: var(--colloquium-title);
  font-size: 0.76em;
}
.training-flops .tf-equation .katex { color: inherit; }
.training-flops .tf-cost {
  margin-top: 0.2em;
  color: var(--tf-accent);
  font-size: 0.68em;
  font-weight: 700;
}
.training-flops .tf-cost .katex { color: inherit; }
/* Card 3 spells out where its two FLOPs come from, so its line is longer and
   sits a size down from the other two. */
.training-flops .tf-cost-small { font-size: 0.58em; }
/* The total is a sentence, not a badge: ordinary body text, centered. */
.training-flops .tf-total {
  grid-column: 1 / -1;
  margin-top: 0.15em;
  text-align: center;
}

/* The capacity slide is the only chart in the deck, and its column is half
   the slide rather than the theme's assumed full width, so the plot gives
   back a little of the default 400px height. */
.colloquium-chart-container { height: 380px; }

/* Stand-in legend above that chart (emitted by scripts/capacity_sweep.py): one
   thin line plus its marker per series, so the keys look like the curves
   instead of Chart.js's filled boxes.  The colours stay inline in the glyphs --
   they come from the data. */
.cap-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2em 1.5em;
  justify-content: center;
  font-size: 0.7em;
  line-height: 1.3;
}

.cap-legend span.legend-note {
  display: inline;
  color: var(--colloquium-muted);
  font-size: 0.9em;
}
.cap-legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}

/* The lab scoreboard (figures/hero-board.md).  Its canvas is built in the
   browser rather than by colloquium, so it is not a .colloquium-chart-container
   and has to state its own height: Chart.js sizes a maintainAspectRatio:false
   canvas from its box, and a box with no height collapses to nothing.
   assets/hero-board.js pins the canvas to this box exactly (see `pin` there), so
   these are the plot's real dimensions and not a starting point Chart.js may
   revise.  470 is what fits between the heading and the footer with the
   colourbar row below it; the width is the slide's wide column, which is the
   point -- a horizontal plot uses the space the slide actually has. */
.hero-board-plot {
  height: 470px;
  width: 100%;
}

/* Colourbar over status line, both centred under the plot.  Side by side was
   the first try and it wrapped: the plot sits in the wide column of a 5/2 row,
   so the pair has ~815 deck units to share, and the two labels together want
   more than that at this size. */
.hero-board-foot {
  margin-top: 0.35em;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15em;
  font-size: 0.7em;
  color: var(--colloquium-muted);
}

.hero-bar {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
}

/* The gradient is the plot's ramp, not a decoration: same two tokens the dots
   are interpolated between. */
.hero-bar i {
  display: inline-block;
  width: 120px;
  height: 0.62em;
  border-radius: 1px;
  background: linear-gradient(to right, var(--hero-share-lo), var(--hero-share-hi));
}

.hero-bar em { font-style: normal; }

/* The status line only ever carries a failure now (assets/hero-board.js says
   why), so it takes no room at all while the sheet is answering. */
.hero-status { color: var(--colloquium-text); }

.hero-status:empty { display: none; }

.hero-status--bad { color: var(--deck-red); }

/* The form's QR (figures/hero-qr.md, written by scripts/hero_board.py --qr).
   Sized here rather than in the SVG so the generated fragment stays a bare
   matrix.  200px is what the narrow column beside the scoreboard has room for
   next to its two lines of prose; checked by decoding it back out of a 1600x900
   render of the slide, which is a harder read than any projector. */
.hero-qr-box {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 0.5em;
}

.hero-qr-box svg.hero-qr {
  width: 100%;
  max-width: 200px;
  height: auto;
  shape-rendering: crispEdges;   /* a QR module is a pixel, not a shape to smooth */
}

/* The stand-in shown until the QR has been generated: visibly unfinished, so a
   deck built before the form exists cannot look finished. */
.hero-qr-box--empty {
  flex-direction: column;
  width: 100%;
  max-width: 200px;
  aspect-ratio: 1 / 1;
  border: 2px dashed var(--colloquium-border);
  color: var(--colloquium-muted);
  font-size: 0.8em;
  text-align: center;
}

.hero-qr-box--empty span { font-family: var(--colloquium-font-mono); font-size: 0.8em; }

/* Chinchilla slide: the mockup's three horizontal bands (premise,
   equation/interpretation, evidence/conclusion) are colloquium `===` rows, the
   last two split `row-columns: 1/1`.  Only the trimmings live here. */
.chin-slide .katex-display { margin: 0.2em 0; }
/* Band two is one display equation against a one-line gloss: centre the gloss
   on the equation rather than letting it hang from the top of the row. */
.chin-slide .colloquium-row:nth-child(2) { align-items: center; }
.chin-independence { color: var(--colloquium-muted); }
.chin-story p { margin-bottom: 0.62em; }
.chin-story .katex-display { margin: 0.35em 0 0.55em; }

/* A typographic matrix rather than a boxed or shaded table. */
.fit-matrix {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  align-items: baseline;
  margin-top: 0.55em;
  border-top: 1px solid var(--colloquium-border);
  border-bottom: 1px solid var(--colloquium-border);
  font-size: 0.8em;
}
.fit-matrix > div { padding: 0.42em 0.35em; }
.fit-matrix > div:nth-child(n+4) { border-top: 1px solid var(--colloquium-border); }
.fit-matrix .fm-head { color: var(--colloquium-muted); font-size: 0.88em; }
.fit-matrix .fm-label, .fit-matrix .fm-value { font-weight: 700; }
.fit-matrix .fm-red { color: var(--deck-red); }
.fit-matrix .fm-navy { color: var(--deck-navy); }
.fit-matrix .fm-value { font-variant-numeric: tabular-nums; }

/* Bold text picks up the theme's dark blue title. */
.slide strong,
.slide b {
  color: var(--colloquium-title);
}
/* Except on a filled background, where the theme has already set the whole
   box's ink and bold has to keep it -- navy bold on the navy accent box is
   invisible.  The theme says this itself, but at the same specificity as the
   rule above, and this sheet is a <link> in the body, so it loads last and
   wins; the exception has to be restated here to give it back. */
.slide .colloquium-box--accent strong,
.slide .colloquium-box--accent b,
.slide .colloquium-box--accent em,
.slide .colloquium-box--accent a,
.slide--section-break strong,
.slide--section-break b {
  color: inherit;
}

/* "Simplifying language modeling": the model's explicit next-token
   distribution vs. the data's implicit one, each in its own accent.
   Extra specificity so bold inside these spans keeps the role colour
   instead of falling back to the navy `.slide strong` rule. */
.slide .tok-model, .slide .tok-model strong, .slide strong.tok-model {
  color: var(--deck-blue);
}
.slide .tok-data, .slide .tok-data strong, .slide strong.tok-data {
  color: var(--deck-red);
}

/* Centered, code-like example block: candidate next tokens in a single
   black column, one probability column per source (model, then data). */
.tok-example {
  display: flex;
  align-items: flex-start;
  gap: 1.5em;
  width: fit-content;
  max-width: 100%;
  margin: 0.6em auto;
  padding: 0.8em 1.6em;
  background: var(--colloquium-code-bg);
  border-radius: 8px;
  font-family: var(--colloquium-font-mono);
  font-size: 0.78em;
  line-height: 1.55;
}

/* The context, underlined and labelled underneath. */
/* Drop the context down by exactly one column-header line (the header is set
   at the body size of the block, so 1em of text at 1.55 line-height plus its
   0.45em bottom margin) so it sits on the first token row rather than in the
   middle of the stack. */
.tok-ctx {
  text-align: center;
  margin-top: calc(1em * 1.55 + 0.45em);
}
.tok-ctx-group { display: inline-block; }
.tok-ctx-text {
  display: block;
  padding-bottom: 0.2em;
  border-bottom: 2px solid var(--colloquium-muted);
}
.tok-ctx-label {
  display: block;
  margin-top: 0.2em;
  font-size: 0.8em;
  color: var(--colloquium-muted);
}

/* Token / probability columns. */
.tok-cols { display: flex; justify-content: center; gap: 2.4em; }
/* `model` and `data` head their own probability column, and they are read as
   part of it: same size as the numbers underneath, not a shrunken caption. */
.tok-col-head {
  display: block;
  margin-bottom: 0.45em;
  letter-spacing: 0.04em;
}
.tok-tokens { text-align: left; }
.tok-model, .tok-data { text-align: right; min-width: 3.6em; }

/* Assumption 3: a compact Zipf explainer. The plot is deliberately schematic:
   its job is to make rank, frequency and the long tail legible at a glance.
   The two-column split is colloquium's own (`row-columns: 1/1`), so all that is
   left here is capping the figure so it does not fill its whole half. */
.zipf-fig {
  max-width: 430px;
}
.zipf-fig .zf-axis { stroke: var(--colloquium-muted); stroke-width: 1.8; }
.zipf-fig .zf-guide {
  fill: none;
  stroke: var(--deck-navy);
  stroke-width: 3;
  stroke-linecap: round;
}
.zipf-fig .zf-tick { stroke: var(--colloquium-muted); stroke-width: 1.4; }
.zipf-fig .zf-num { fill: var(--colloquium-muted); font-size: 17px; }
.zipf-fig .zf-label { fill: var(--colloquium-text); font-size: 20px; }
.zipf-fig .zf-note { fill: var(--colloquium-muted); font-size: 17px; }
/* The slope, written the way every other exponent in the deck is written:
   muted grey, horizontal, and nothing but base^exponent.  See
   scripts/chinchilla_svg.py for the note on why none of them are tilted. */
.zipf-fig .zf-law { fill: var(--colloquium-muted); font-size: 20px; }
.zipf-fig .zf-var {
  font-family: "Latin Modern Math", "Cambria Math", Georgia, serif;
  font-style: italic;
  font-size: 1.05em;
}

/* Assumption 2: the only architecture retained by the toy model. */

.embed-fig .ef-head { fill: var(--colloquium-title); font-size: 22px; font-weight: 700; }
.embed-fig .ef-context { fill: var(--colloquium-code-bg); stroke: var(--colloquium-border); }
.embed-fig .ef-code { fill: var(--colloquium-text); font-family: var(--colloquium-font-mono); font-size: 13px; }
.embed-fig .ef-arrow { stroke: var(--colloquium-muted); stroke-width: 2; marker-end: url(#ef-arrow); }
.embed-fig marker#ef-arrow path { fill: var(--colloquium-muted); }
.embed-fig .ef-muted { fill: var(--colloquium-muted); font-size: 16px; }
.embed-fig .ef-space { fill: none; stroke: var(--colloquium-muted); stroke-width: 1.6; }
.embed-fig .ef-red { fill: var(--deck-red); }
.embed-fig .ef-green { fill: var(--deck-green); }
.embed-fig .ef-navy { fill: var(--deck-navy); }
.embed-fig .ef-vector { fill: var(--colloquium-text); font-size: 18px; font-style: italic; }
.embed-fig .ef-token, .embed-fig .ef-prob { fill: var(--colloquium-text); font-size: 17px; }
.embed-fig .ef-bar { fill: var(--deck-blue); }

/* Extra half line of air under the title-slide headline
   (theme default is 0.3em at font-size 2.8em). */
.slide--title h1 {
  margin-bottom: calc(0.6em + 18px);
}

/* Remove space between paragraph and bullet points */
.slide p + ul {
  margin-top: -0.5em;   /* 0.8em gap → ~0.4em */
}
.slide p + ol {
  margin-top: -0.5em;   /* 0.8em gap → ~0.4em */
}

/* Increase space after slide titles */
.slide h2 {
  margin-bottom: 1em;
}

/* "Interference" figure: three unit spheres of random embeddings.  One
   arrow = one context embedding, coloured by its correct next token, so
   "several nearby arrows sharing a colour" is exactly the failure mode.
   The drawing is deliberately smaller than the space it has (r = 104 in a
   356-unit viewBox), and the margins spend the surplus as air above and
   below rather than on bigger circles -- the slide has a text line hard
   against the figure on both sides. */

.sphere-fig .sf-sphere {
  fill: none;
  stroke: var(--colloquium-muted);
  stroke-width: 1.5;
}
.sphere-fig .sf-vec {
  stroke-width: 2.4;
  stroke-linecap: round;
}
.sphere-fig .sf-axis {
  stroke: var(--colloquium-muted);
  stroke-width: 1.6;
}
.sphere-fig .sf-navy   { stroke: var(--deck-navy); }
.sphere-fig .sf-red    { stroke: var(--deck-red); }
.sphere-fig .sf-green  { stroke: var(--deck-green); }
.sphere-fig .sf-orange { stroke: var(--deck-orange); }
.sphere-fig text {
  fill: var(--colloquium-text);
  font-size: 22px;
}
.sphere-fig .sf-muted { fill: var(--colloquium-muted); }
.sphere-fig .sf-good { fill: var(--deck-navy); font-weight: 700; }
.sphere-fig .sf-bad { fill: var(--deck-red); font-weight: 700; }
.sphere-fig .sf-small { font-size: 20px; }
/* The interference line ends one slide and opens the next.  Colloquium
   swaps slides with display none/flex, so there is no cross-slide morph
   to hook into; the closest honest effect is to let the line rise into
   its new position as the slide appears.  Disabled for print/capture so
   a static export never catches it mid-flight. */
@keyframes colloquium-carry-up {
  from { opacity: 0; transform: translateY(38px); }
  to   { opacity: 1; transform: translateY(0); }
}
.slide.carry-line .slide-content > p:first-child {
  animation: colloquium-carry-up 0.45s ease-out both;
}
.colloquium-capture .slide.carry-line .slide-content > p:first-child {
  animation: none;
}
@media print {
  .slide.carry-line .slide-content > p:first-child { animation: none; }
}

/* Math-ish italics for the scalars d and h inside the captions. */
.sphere-fig .sf-var {
  font-family: "Latin Modern Math", "Cambria Math", Georgia, serif;
  font-style: italic;
  font-size: 1.05em;
}

/* "From capacity to scaling laws": two schematic plots.  Same palette,
   stroke weights and type sizes as .sphere-fig above, so the two figures
   read as one family. */

.plot-fig .pf-axis {
  fill: none;
  stroke: var(--colloquium-muted);
  stroke-width: 1.6;
}
.plot-fig .pf-curve {
  fill: none;
  stroke: var(--deck-navy);
  stroke-width: 2.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.plot-fig .pf-guide {
  fill: none;
  stroke: var(--colloquium-muted);
  stroke-width: 1.6;
  stroke-dasharray: 6 5;
}
/* Red is reserved for the capacity marker, the one quantity the slide is
   about; the level guide for l stays muted. */
.plot-fig .pf-tick {
  stroke: var(--deck-red);
  stroke-width: 2;
}
/* The same red, run the full height of the left panel: the capacity is the
   line between what the model has stored and what it has not, so the divider
   carries on above the l plateau.  Dashed, like the level guide, so it reads
   as a guide rather than as part of the step. */
.plot-fig .pf-sep {
  stroke: var(--deck-red);
  stroke-width: 1.6;
  stroke-dasharray: 6 5;
}
.plot-fig text {
  fill: var(--colloquium-text);
  font-size: 22px;
}
.plot-fig .pf-muted { fill: var(--colloquium-muted); }
.plot-fig .pf-red { fill: var(--deck-red); }
.plot-fig .pf-navy { fill: var(--deck-navy); font-weight: 700; }
.plot-fig .pf-strong { font-weight: 700; }
.plot-fig .pf-small { font-size: 20px; }
/* Twin-axis version: one grey axis shared by both laws, so the hue lives on
   the lines and in the legend under the plot instead. */
.plot-fig .pf-curve-d { stroke: var(--deck-red); }
.plot-fig .pf-var {
  font-family: "Latin Modern Math", "Cambria Math", Georgia, serif;
  font-style: italic;
  font-size: 1.05em;
}
/* Three-panel recipe comparison (figures/recipe-trends-fig.md).  The deck's
   two-series pair, navy vs red, as in the twin-axis plot above -- one hue per
   method, held across all three panels so the comparison is the same one
   throughout.  Lines are a shade lighter than .pf-curve: there are two of them
   crossing in one small panel, and the dots marking the 500M runs have to stay
   readable on top of them, hence the surface-coloured halo. */
.plot-fig .rt-line {
  fill: none;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.plot-fig .rt-a { stroke: var(--deck-navy); }
.plot-fig .rt-b { stroke: var(--deck-red); }
.plot-fig .rt-dot { stroke: var(--fig-surface); stroke-width: 1.8; }
.plot-fig .rt-fill-a { fill: var(--deck-navy); }
.plot-fig .rt-fill-b { fill: var(--deck-red); }
/* Panel headings: the reading of each panel, so they are text-coloured and
   bold against the muted axis annotation. */
.plot-fig .rt-title { font-size: 21px; font-weight: 700; }

/* Slider under the twin-axis plot.  `input` is in presentation.js's
   click-to-advance ignore list, so dragging it does not change slide. */
.alpha-control {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1em;
  margin-top: 0.1em;
  font-size: 0.68em;
  color: var(--colloquium-muted);
}
.alpha-control input[type="range"] {
  width: 240px;
  accent-color: var(--deck-navy);
}
.alpha-var {
  font-family: "Latin Modern Math", "Cambria Math", Georgia, serif;
  font-style: italic;
  font-size: 1.15em;
}

/* Stepped derivations: one line of maths per `<!-- step -->`, with a short note
   in the column beside it.  The lines are left-aligned rather than each centred
   in its own row, so a `\phantom` on the continuation lines keeps the relation
   symbols under one another the way `aligned` would.  Margins are tighter than
   the theme's 0.8em because a split derivation pays them once per line. */
/* Layout is colloquium's own: one `===` row per line of maths, each split
   `row-columns: 3/2` into equation and note.  What is left here is typography. */
.eq-rows .colloquium-row {
  align-items: center;
}
.eq-rows .katex-display {
  margin: 0.3em 0 0.3em 1.2em;
}
/* KaTeX centres the inner .katex block, so left-aligning has to happen there. */
.eq-rows .katex-display > .katex { text-align: left; }
/* The note is commentary, not part of the derivation, and carries no
   paragraph margins of its own so it stays centred on its equation. */
.eq-rows .text-sm { color: var(--colloquium-muted); }
.eq-rows .text-sm p { margin: 0; }

/* Footnote look, but inside the slide body so a `<!-- step -->` can hold it
   back: colloquium's own footnotes render outside the fragment machinery. */
.slide .inline-footnote {
  font-size: 0.62em;
  line-height: 1.35;
  color: var(--colloquium-muted);
  margin-top: 0.8em;
}
.slide .inline-footnote strong { color: inherit; }

/* Legend labels carrying an exponent (the IsoFLOP slide's compute budgets).
   `.cap-legend span` above is an inline-flex box with a gap, and that rule matches
   nested spans too, so a bare <sup> inside one becomes a flex item: it loses its
   raise and gains the gap, rendering as "10 13". Marking the label as plain inline
   text puts the <sup> back inside an inline box, where it superscripts normally. */
.cap-legend span.num { display: inline; }

/* IsoFLOP slide: the compute legend runs down the left of the figure rather than across
   the top of it, so the pair is no taller than the plot itself.  `.cap-legend` is a
   centred wrapping row by default, which is right everywhere else in the deck. */
.if-row {
  display: flex;
  align-items: center;
  gap: 1.2em;
  margin-top: 0;
}
.if-row > .cap-legend {
  flex: 0 0 auto;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
}
.if-row > .plot-fig {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}

/* isoflop figure */
/* Centring the legend on the figure is not the same as centring it on the plot: the
   SVG box carries ~90 viewBox units of tick labels and axis title below the plot box
   and only 18 above it, so flex centring lands the legend low.  The plot box spans
   y = 18..308 of the 400-unit viewBox, so its middle sits 37 units above the box's
   middle -- about 31 px at the width the figure is laid out at, measured on the ink
   rather than on the line boxes.  A percentage would be the honest unit, but `top: %`
   resolves against a content-sized flex row and drops to auto; the deck scales by
   transform, so a px lift holds at every zoom. */
.if-row > .cap-legend {
  position: relative;
  top: -31px;
}

/* recipe-comparison slide (figures/recipe-trends-fig.md).  Same legend-column
   row as the IsoFLOP and Chinchilla figures, with two adjustments.  The lift is
   smaller: this viewBox is 332 units and its plot box spans y = 60..250, so the
   plot's middle sits only 11 units above the box's middle (against 37 on the
   IsoFLOP figure), which is ~10 px at the width the pair lays out at.  And the
   two keys keep their series' colour and weight -- there are only two of them
   and they are the whole comparison, unlike the six-key ramps elsewhere, where
   the swatch alone does the identifying. */
.rt-row > .cap-legend { top: -10px; }
.rt-row .rt-key-a { color: var(--deck-navy); font-weight: 700; }
.rt-row .rt-key-b { color: var(--deck-red); font-weight: 700; }

/* practice-capacity slide */
/* Two Chart.js panels side by side, each with a legend above the plot and its own
   cited caption below it.  The theme's chart box would push the captions off the
   bottom of the slide, so the box is shortened rather than the type -- this is
   the tallest box that still leaves the captions clear of the footer.  It also
   has to stay under the print cap the theme puts on row images,
   (720px - 2*padding - 96px) * --colloquium-print-row-frac, which is why the
   slide's `rows:` track list gives the figure band the larger share.  A smaller
   share used to silently shrink the exported plots while leaving the on-screen
   canvas alone, so it only showed up in a capture; that was Chart.js sizing a
   responsive canvas off the deck's post-transform width, and assets/plot.js now
   pins every chart to its container's own layout box instead.  The cap still
   applies, but missing it no longer costs resolution invisibly. */
.pc-slide .colloquium-chart-container {
  height: 366px;
  margin: 0.1em 0 0;
}
/* Half-width panels: the default 1.5em between legend keys wraps the right-hand
   legend onto a second line, which would drop its plot below its neighbour's.
   Tighter keys keep both legends one line tall, so the two panels line up.
   0.9em was enough while the left panel named four dataset sizes; it now names
   six plus the 2 bits/param yardstick, seven keys in a 744px column, and needed
   another ~0.3em off the gap to stay on one line.  Both legends tighten together
   so the pair still matches.  If you add an eighth key, expect to reach for the
   font size instead -- the gap has no more room to give. */
.pc-slide .cap-legend {
  margin-top: 0.3em;
  gap: 0.2em 0.6em;
  font-size: 0.66em;
}
/* Same `rows:` de-stretching as `.eq-rows` below: the two bands (lead-in text,
   pair of panels) take their content height and pack at the top instead of
   splitting the slide, so the gap between them is ordinary paragraph spacing. */
.slide.pc-slide .slide-content.colloquium-rows {
  grid-template-rows: none !important;
  grid-auto-rows: min-content;
  align-content: start;
}
/* Each caption names one figure and cites one paper, so it is centred under its
   own plot and kept to a single line's worth of space. */
.pc-slide .pc-caption {
  text-align: center;
  margin-top: 0.3em;
}
.pc-slide .pc-caption p { margin: 0; }

/* Assumption 2 figure, second pass: the embeddings are drawn as arrows on the
   unit circle rather than as scattered dots, so this slide and the later
   "Interference" spheres share one visual language -- same arrow heads, same
   stroke weight, same palette as `.sphere-fig` above.  The coloured tab beside
   each context box is what ties a context to its arrow. */
.embed-fig .ef-vec {
  stroke-width: 2.4;
  stroke-linecap: round;
}
.embed-fig .ef-vec.ef-navy  { stroke: var(--deck-navy); fill: none; }
.embed-fig .ef-vec.ef-red   { stroke: var(--deck-red); fill: none; }
.embed-fig .ef-vec.ef-green { stroke: var(--deck-green); fill: none; }
.embed-fig .ef-fill-navy  { fill: var(--deck-navy); }
.embed-fig .ef-fill-red   { fill: var(--deck-red); }
.embed-fig .ef-fill-green { fill: var(--deck-green); }
/* The bars are the distribution predicted for the first (navy) context, so they
   carry its hue; the non-argmax entries get a tint of the same. */
.embed-fig .ef-navy-light { fill: var(--deck-navy-tint); }

/* theory-capacity slide */
/* The chart column is much shorter than the commentary beside it, so left
   top-aligned it reads as if it had slipped up the slide.  There is no
   per-column `valign` directive -- `valign: center` acts on the slide and
   `.slide-content` already claims the spare height -- so the column itself
   becomes the flex context and centres its own chart. */
.ct-slide .colloquium-grid > .col:first-child {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* eq-rows slides (the two "From capacity to scaling laws" derivations) */
/* `rows:` builds a grid on .slide-content whose bands are stretched to fill the
   whole slide height, so a three-step derivation comes out with a third of the
   slide of dead space between each line.  The rows structure itself has to stay
   -- it is what lets each band carry `row-columns: 3/2` and so pairs every
   equation with its gloss at a readable 40% width -- so only the vertical
   distribution is undone here: the fr-based track list (an inline style, hence
   `!important`) gives way to content-height bands packed at the top, leaving
   the grid's own 0.9em gap as ordinary paragraph spacing. */
.slide.eq-rows .slide-content.colloquium-rows {
  grid-template-rows: none !important;
  grid-auto-rows: min-content;
  align-content: start;
}

/* "Building W" figure (`figures/w-build-fig.md`), on the slide that turns the
   Hebbian sum into a picture.  Three panels read left to right: four contexts,
   the random unit embedding each one gets, and the next token each embedding is
   paired with -- the same left-to-right grammar as `.embed-fig`, and the same
   palette, arrow heads, 2.4 stroke and type sizes as `.embed-fig` and
   `.sphere-fig`, so the figures read as one family; the vectors are shortened
   by 13px so the head's tip, not the line's end, lands on the circle.
   Registration with the next slide: the embedding arrows start at viewBox
   x = 590, which is where the middle sphere of `.sphere-fig` sits, and both
   figures are full-width children of `.slide-content` with a 1180-unit
   viewBox, so that x renders to the same screen pixel on both slides -- click
   forward and the arrows stay put.  The vertical half of that alignment is
   *not* done here: a positive margin-top would collapse with the paragraph
   above (0 and 0.37em measure identically), so the figure carries the offset
   itself, as 9 units of top padding in its viewBox.  Re-measure both slides if
   either one's text above the figure changes. */

.wbuild-fig .wb-head { fill: var(--colloquium-title); font-size: 22px; font-weight: 700; }
.wbuild-fig .wb-context { fill: var(--colloquium-code-bg); stroke: var(--colloquium-border); }
.wbuild-fig .wb-code { fill: var(--colloquium-text); font-family: var(--colloquium-font-mono); font-size: 15px; }
.wbuild-fig .wb-muted { fill: var(--colloquium-muted); font-size: 16px; }
.wbuild-fig .wb-map { stroke: var(--colloquium-muted); stroke-width: 2; marker-end: url(#wb-arrow); }
.wbuild-fig marker#wb-arrow path { fill: var(--colloquium-muted); }
.wbuild-fig .wb-circle { fill: none; stroke: var(--colloquium-muted); stroke-width: 1.6; }
.wbuild-fig .wb-vec { stroke-width: 2.4; stroke-linecap: round; fill: none; }
.wbuild-fig .wb-navy { stroke: var(--deck-navy); }
.wbuild-fig .wb-red  { stroke: var(--deck-red); }
.wbuild-fig .wb-fill-navy { fill: var(--deck-navy); }
.wbuild-fig .wb-fill-red  { fill: var(--deck-red); }
.wbuild-fig .wb-tok { font-size: 24px; font-weight: 700; }

/* loss-step figure: the area-to-point build */
/* The shaded block under the step curve is the loss integral, so it is a fill
   rather than an outline -- light enough that the navy step and the red
   capacity divider still read through it as the figure's foreground. */
.plot-fig .pf-area {
  fill: var(--colloquium-muted);
  fill-opacity: 0.15;
  stroke: none;
}
/* The one L(N) value that block amounts to.  The halo is the slide background,
   not white, so the dot keeps its edge if the deck ever darkens; it matters
   because the N^(1-alpha) line is drawn through this point one step later. */
.plot-fig .pf-point {
  fill: var(--deck-navy);
  stroke: var(--colloquium-bg);
  stroke-width: 2.5;
}

/* The two "Scaling laws" slides: Kaplan's Figure 2, regenerated by
   scripts/kaplan_curves.py into figures/kaplan-{tokens,compute}-fig.md.  The plot
   itself needs nothing beyond `.plot-fig` above; only the legend and the column
   spacing are particular to these slides. */
/* Six ordered model sizes in the single-hue ramp, above a nearly square plot that
   sits in the wider column of a `columns: 3/2` slide.  The default `.cap-legend`
   gap of 1.5em wraps six keys onto two lines at that width, which steals a line of
   plot height, so the keys are pulled closer together and the glyph-to-label gap
   is tightened to match. */
.kap-legend { gap: 0.1em 0.95em; }
.kap-legend span { gap: 0.3em; }
/* The frontier's in-plot label needs no rule of its own: `.pf-muted .pf-strong` is
   already the deck's "a guide, named" pair.  It is deliberately not `.pf-red`, which
   the deck reserves for the one quantity a slide is *about* -- here the frontier is
   the construction, and the curves it envelopes are the measurement. */

/* ===== Chinchilla: the three compute-optimal slides (15-17).
   All three figures are generated by scripts/chinchilla_slides.py and share the
   .plot-fig look of the Part II IsoFLOP slide; only what is new to them lives here. */

/* The Pareto front on slide 15, and the compute-optimal frontier of slide 17's
   contour map, which is the same object arrived at a third way.  Red, like the
   capacity marker in Part II: it is the one quantity the slide is about, and it has to
   read *against* the family of curves it is the envelope of -- in navy it disappears
   into the darkest of them, which is the curve that owns the right-hand end of the
   front.  Solid and heavy because, unlike the power law drawn over it a click later,
   it is a measurement. */
.plot-fig .pf-front {
  fill: none;
  stroke: var(--deck-red);
  stroke-width: 3.2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Slide 15 needs a step that *removes* emphasis: once the front is drawn, the family
   of per-model-size curves it was read off drops back so only the front is left.
   colloquium's fragments only ever reveal, so the beat is an empty <g> whose .visible
   state is read backwards up the tree with :has() -- the curves are earlier siblings,
   and CSS has no previous-sibling combinator. */
.cp-fig .cp-fade { transition: opacity 0.35s ease; }
.cp-fig:has(.cp-dim.visible) .cp-fade { opacity: 0.2; }
/* Capture and print force every fragment visible without adding .visible, so the
   final state has to be spelled out again for both. */
.colloquium-capture .cp-fig .cp-fade { opacity: 0.2; }
@media print {
  .cp-fig .cp-fade { opacity: 0.2; }
}

/* Slide 17's contour map lays lines of constant compute over the fitted iso-loss
   contours.  Both families run the same way across the plane and cross at a shallow
   angle, so the constraint has to be the lighter of the two: `pf-guide`'s weight with
   a finer dash, which reads as a grid rather than as a fit. */
.plot-fig .cp-isoc {
  stroke-width: 1.3;
  stroke-dasharray: 2 5;
}
/* The frontier's own label sits on top of the contours it is tangent to -- there is
   no clear ground beside a line that everything else crosses -- so it is drawn with a
   background-coloured outline under the glyphs.  `paint-order` is what makes that an
   outline rather than a smear over them. */
.plot-fig .cp-halo {
  stroke: var(--fig-surface);
  stroke-width: 5;
  stroke-linejoin: round;
  paint-order: stroke fill;
}

/* Slide 17: the equation and, under it, the five constants fitted here.  The
   constants line is markdown rather than hand-written spans -- `$L_\infty$` inside a
   raw HTML span never reaches KaTeX, it just prints the dollars -- so it needs the
   blank lines around it and gets its margins trimmed here instead. */
.chin-law .katex-display { margin: 0.35em 0 0.45em; }
.chin-consts { margin: -0.1em 0 0.75em; }
.chin-consts p { margin: 0; font-size: 0.86em; text-align: center; }
/* These five numbers are the slide: navy, not the muted grey a caption would get. */
.chin-consts .katex,
.chin-consts .katex * { color: var(--colloquium-title); }

/* "Language model pretraining" (slide 5).  One full-width, left-to-right chain:
   the context, the sequence model, the embedding, the prediction head, the
   next-token distribution, and the observed token the loss compares it against.
   The figure is a single row of nodes, so it lays out very wide and short -- see
   the geometry comment in figures/llm-arch-fig.md; at a full-width column it
   renders at roughly its own viewBox width, which makes the sizes below close to
   real pixels.  Colours are the roles the deck already uses: navy for the
   model's internals, blue for what it predicts, red for anything from the data. */

.llmarch-fig text { fill: var(--colloquium-text); }

/* The four nodes share one caption baseline, 32 units clear of everything above
   it, so these read as one row of names under the figure rather than as text
   crowding it. */
.llmarch-fig .lp-cap { fill: var(--colloquium-muted); font-size: 19px; }
/* What each arrow does: the two model components, named.  Set on two lines in
   the figure -- that is what buys the horizontal air the row needs. */
.llmarch-fig .lp-step { fill: var(--colloquium-title); font-size: 18px; font-weight: 600; }

/* The context, and the rule that its caption hangs off. */
.llmarch-fig .lp-ctx { font-family: var(--colloquium-font-mono); font-size: 22px; }
.llmarch-fig .lp-rule { stroke: var(--colloquium-muted); stroke-width: 1.8; }
.llmarch-fig .lp-arrow { fill: none; stroke: var(--colloquium-muted); stroke-width: 2.2; }
.llmarch-fig marker#lp-head-grey path { fill: var(--colloquium-muted); }

/* The embedding: the circle and one vector on it, as on the "Simplifying
   language modeling" slide -- one vector rather than that figure's three,
   because here there is only one context. */
.llmarch-fig .lp-space { fill: none; stroke: var(--colloquium-muted); stroke-width: 1.6; }
.llmarch-fig .lp-vec { fill: none; stroke: var(--deck-navy); stroke-width: 2.6; }

/* The predicted distribution: candidates and bars, deliberately unlabelled --
   see the figure's header comment. */
.llmarch-fig .lp-tok { font-family: var(--colloquium-font-mono); font-size: 19px; }
.llmarch-fig .lp-bar rect { fill: var(--deck-blue-tint); }
.llmarch-fig .lp-bar rect.lp-bar-top { fill: var(--deck-blue); }

/* The observed token and the loss between it and the prediction: red, the
   deck's accent for anything the data supplies.  The arrow is plain: dashed
   read as "tentative" next to the figure's other, solid arrows, when this one
   is the most concrete relation on the slide. */
.llmarch-fig .lp-obs-box { fill: var(--deck-red-wash); stroke: var(--deck-red); stroke-width: 1.6; }
.llmarch-fig .lp-obs {
  fill: var(--deck-red);
  font-family: var(--colloquium-font-mono);
  font-size: 24px;
  font-weight: 700;
}
.llmarch-fig .lp-xarrow { fill: none; stroke: var(--deck-red); stroke-width: 1.8; }
.llmarch-fig .lp-xlab { fill: var(--deck-red); font-size: 17px; font-weight: 700; }

/* The Chinchilla figures reuse .if-row (legend column, then plot) but their plot box
   sits differently inside its viewBox, so the lift that centres the legend on the
   *plot* rather than on the whole SVG is not the IsoFLOP slide's.  The box spans
   y = 18..350 of a 420-unit viewBox, so its middle is 26 units above the viewBox's --
   about 30 px at the width these figures lay out at.  Also a little tighter: three
   panels need every pixel of width they can get. */
.cp-row { gap: 0.9em; }
.cp-row > .cap-legend { top: -30px; font-size: 0.66em; }
/* Slide 17's figure is one near-square panel in a half-width column: y = 30..508 of
   a 600-unit box, so the lift is smaller and the box is laid out narrower. */
.cp-row-pm > .cap-legend { top: -21px; }

/* The history timeline (figures/history-fig.md) styles itself, in a <style>
   element inside its own SVG, and its citation row is styled inline in
   slides.md.  Both are deliberate departures from "figure styling lives here":
   the type sizes are what keep four columns of text from overlapping, and this
   file is separately cached, so a browser holding an older copy of it rendered
   the figure at `.plot-fig text`'s 22px with the columns on top of each other.
   Geometry and the type that has to fit it now travel in one file. */

/* The narrow column beside the scoreboard: the two ways to submit, over the QR,
   all of it a size down because the plot is what the room is looking at.  The
   column is centred against the plot rather than hung from the top of the slide,
   which with a 470px plot beside ~330px of text and QR is a visible difference.
   `:has()` because the column div is colloquium's, emitted at `|||`, and the
   slide source has no handle on it. */
.hero-side { font-size: 0.8em; }

.slide .col:has(.hero-side) {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* The QR is the second thing in that column, so it gets the gap rather than a
   margin on the prose above it. */
.hero-side + .hero-qr-box { margin-top: 1.2em; }
