/* ARENA notebook — a Courses section opened IN the app.
   Markup built by practice/arena-notebook.js.

   🔴 THIS SHEET IS AN EXTENSION, NOT A SECOND NOTEBOOK STYLE. The cells, the
   toolbar, the banner, the Run gutter and the output block are all the `.nbv-*`
   rules in notebook-view.css — Seth asked for "a view that is like our other
   notebooks thing", and the way to keep that true a month from now is for the
   two surfaces to share the rules rather than to look alike by coincidence.
   So this file must be linked AFTER notebook-view.css, and holds only what the
   ARENA surface has and the lesson notebooks do not:

     - the section header (chapter / number / description / provenance)
     - a Colab setup cell, which is read-only rather than runnable
     - images, which upstream prose is full of and authored lessons never have
*/

/* ---- the faces ----------------------------------------------------------- */

/* 🔴 WE DO NOT SHIP LESSWRONG'S BODY FONT, AND CANNOT. Their prose face is
   `warnock-pro`, a commercial Adobe face served from LessWrong's OWN Typekit
   kit (themes/globalStyles/externalStyles.ts). It renders on their domain and
   on localhost; pointing this app at that kit would be spending someone else's
   font licence, and would 403 the day it left localhost anyway.

   So the body takes THEIR OWN FALLBACK CHAIN instead — the list that sits
   behind warnock-pro in themes/defaultPalette.ts `serifStackBody` — with URW
   Palladio (P052) added, because that is the metric-compatible Palatino clone
   Linux actually has and Palatino is the first thing they fall back to.

   Headings get ET Book, which IS what they use for headings (`headerStack` =
   ETBookRoman + that same chain) and which is MIT-licensed, so it is vendored
   in fonts/ rather than hotlinked. Nothing in this file is their code. */

@font-face {
  font-family: "ETBookRoman";
  font-display: swap;
  font-style: normal;
  font-weight: 400;
  src: url("fonts/et-book-roman-line-figures.woff") format("woff");
}

@font-face {
  font-family: "ETBookRoman";
  font-display: swap;
  font-style: normal;
  font-weight: 700;
  src: url("fonts/et-book-bold-line-figures.woff") format("woff");
}

@font-face {
  font-family: "ETBookRoman";
  font-display: swap;
  font-style: italic;
  font-weight: 400;
  src: url("fonts/et-book-display-italic-old-style-figures.woff") format("woff");
}

/* 🔴 THE NOTEBOOK TAKES EVERYTHING RIGHT OF THE CONTENTS PANE. Seth,
   2026-09-22: "go with the collab format where the code and text take up all
   the space on the right for the notebooks for the full width on the right".

   `--anb-pane-w` is written onto #page-arena-notebook by practice/arena-
   notebook-nav.js — the pane's width while it is docked, 0px when it is
   folded or overlaying a narrow window, unset when there is no pane at all.
   The pane reads the same token for its own width, so the two edges are one
   number and cannot overlap or open a gap.

   🪦 What this replaces: a 682px column centred in the window, `--anb-nudge`
   pushing it 100px right, and a hover overlay living in the margin that
   centring left. Every one of those was a way of keeping a floating tree off
   the prose; a docked pane beside it needs none of them. */
.arena-notebooks-container {
  box-sizing: border-box;
  margin-left: var(--anb-pane-w, 0px);
  max-width: none;
  padding: 0 clamp(4px, 2vw, 24px);
}

/* 🔴 THE PAGE KEEPS ITS OWN SIDE PADDING (`.page`, 20px). A code block grows
   rightward up to the PAGE's padding edge — practice/notebook-cells.js reads
   `paddingRight` off it — so zeroing it here let every wide fence run to the
   window's edge and under the scrollbar, and the page scrolled sideways. The
   container adds the rest of the gutter on top of it. */

/* Focus mode hides the pane (practice/exercise-timer.js), so the notebook
   takes its room back rather than leaving a blank strip where it was. */
#page-arena-notebook.dd-nb-focus .arena-notebooks-container {
  margin-left: 0;
}

/* ---- the section header -------------------------------------------------- */

.arena-nb-head {
  border-bottom: 1px solid var(--border);
  margin: 0 auto 18px;
  padding-bottom: 16px;
}

.arena-nb-chapter {
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.arena-nb-title {
  font-size: 26px;
  line-height: 1.25;
  margin: 6px 0 8px;
}

.arena-nb-desc {
  color: var(--text);
  font-size: 15px;
  margin: 0 0 10px;
}

/* Where the page came from, and what it is not. A learner who has been graded
   on every other surface in this app has to be told, once and in plain words,
   that this one is not scoring them. */
.arena-nb-origin {
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.6;
  margin: 0;
}

.arena-nb-origin code {
  font-size: 11.5px;
  word-break: break-all;
}

/* ---- disclosures --------------------------------------------------------- */

/* ARENA writes both its hints and its solutions as <details>, and the summary
   is the only thing saying which one you are about to open. It gets the weight
   the lesson notebooks give a problem header for the same reason: it is what a
   scrolling learner is aiming at. */
.arena-nb-details > summary {
  cursor: pointer;
  font-weight: 600;
  padding: 8px 0;
}

.arena-nb-details[open] > summary {
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}

/* ---- a Colab setup cell -------------------------------------------------- */

/* A magic cell runs like any other (the sandbox kernel is real IPython); the
   note above its source is the only thing that marks it. Kept slightly muted
   so the notebook still opens on prose, not on a setup block. */
.arena-nb-magic .nbv-src code {
  color: var(--muted);
}

/* ---- images -------------------------------------------------------------- */

/* Upstream sizes its images with a `width` attribute for a 1200px Colab
   column; the attribute is dropped at compile time and the column decides
   here. `height: auto` is what keeps a wide diagram from being squashed
   rather than scaled once max-width bites. */
.nbv-md img {
  border-radius: 6px;
  display: block;
  height: auto;
  margin: 12px 0;
  max-width: 100%;
}

/* A long URL in upstream prose (papers, Streamlit pages, raw GitHub) must wrap
   rather than push the whole column sideways on a phone. */
.nbv-md a {
  overflow-wrap: anywhere;
}

/* Same for any unbroken run in a paragraph. 0.0's Linear Algebra cell carries
   upstream's `<img src = "https://lh3.googleusercontent.com/…">` as escaped
   TEXT, one 1500px word, and it gave the whole page a horizontal scrollbar
   once the column went full width (2026-09-22). `break-word` only breaks a
   word that cannot fit, so ordinary prose wraps exactly as before. */
#page-arena-notebook .nbv-md p {
  overflow-wrap: break-word;
}

/* Text cells render normally until double-clicked, then become plain Markdown
   editors. Ctrl/Cmd+Enter saves; Escape cancels; blur saves. */
#page-arena-notebook .arena-nb-md-rendered {
  cursor: text;
  min-height: 20px;
}

#page-arena-notebook .arena-nb-md-editor {
  background: var(--surface);
  border: 1px solid var(--info);
  border-radius: 4px;
  box-sizing: border-box;
  color: var(--white);
  /* 🔴 THE RAW SOURCE SCALES WITH WHAT IT RENDERS INTO. Left at a flat 14px
     this editor opened as a speck under 25px prose — you would be reading the
     Markdown for a heading at half the size of the heading. Same token as the
     column: --anb-zoom in this file, and nowhere else. */
  font: calc(14px * var(--anb-zoom, 1)) / 1.55 ui-monospace, SFMono-Regular,
    Consolas, monospace;
  min-height: 180px;
  padding: 12px;
  resize: vertical;
  width: 100%;
}

#page-arena-notebook .arena-nb-md-editor:focus {
  box-shadow: 0 0 0 2px rgb(var(--info-rgb) / 0.18);
  outline: none;
}

/* Cell controls stay quiet until needed. They cover only cell chrome, never
   alter notebook prose or code metrics. */
#page-arena-notebook .nbv-cell {
  position: relative;
}

.arena-nb-cell-tools {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  display: flex;
  gap: 2px;
  opacity: 0;
  padding: 2px;
  pointer-events: none;
  position: absolute;
  right: 5px;
  top: 5px;
  transition: opacity 80ms ease;
  z-index: 3;
}

.nbv-cell:hover > .arena-nb-cell-tools,
.nbv-cell:focus-within > .arena-nb-cell-tools {
  opacity: 1;
  pointer-events: auto;
}

.arena-nb-cell-tools button {
  background: transparent;
  border: 0;
  border-radius: 3px;
  color: var(--muted);
  cursor: pointer;
  font: 500 calc(11px * var(--anb-zoom, 1)) / 1.2 Inter, ui-sans-serif,
    system-ui, sans-serif;
  padding: 4px 5px;
}

.arena-nb-cell-tools button:hover {
  background: rgb(var(--info-rgb) / 0.14);
  color: var(--info);
}

/* 🔴 A TOUCH SCREEN IS NOT A NARROW SCREEN. These controls were revealed by
   `:hover`/`:focus-within` alone, with a `max-width: 700px` phone fallback —
   so a 1024px tablet, which can do neither, got a cell it could not reorder,
   convert or delete, and nothing on screen said why. `hover: none` asks the
   real question. The width rule stays as well: a phone that reports hover
   (some do, wrongly) still needs the controls out. Found by codex, 2026-09-03. */
@media (hover: none), (max-width: 700px) {
  .arena-nb-cell-tools {
    opacity: 1;
    pointer-events: auto;
  }
}

/* ---- the reading column -------------------------------------------------- */

/* SETH: "I want the text size to be the same for the middle part ... I want
   everything to be the same in terms of broad things, aside from obviously the
   fact that my notebook can run code cells in it."

   So the prose here is set to LessWrong's own measure, taken with
   tools/visual-diff (`capture.py lw`, then `diff.py lw ours`) rather than
   guessed: a 682px column of 18.2px text on a 26px line, headings at
   36.4 / 26 / 20.8 with their tighter 1.21 leading. Ours was 16px on 880px —
   about 110 characters a line, which is half again the measure anything is
   meant to be read at.

   🔴 THE CODE CELLS KEEP THE OLD WIDTH. They are the one thing this surface
   has that a post does not: an 80-column line of PyTorch, a run gutter and an
   output block do not fit in a 682px prose measure. So the prose narrows and
   the runnable cells break back out to 880px, which is why the rules below are
   scoped to `#page-arena-notebook` — the lesson notebooks share `.nbv-*` and
   are not this document. */

/* 🔴 SUPERSEDED FOR THIS PAGE, 2026-09-22: the column is the whole right
   pane now (see `.arena-notebooks-container` above). The 682px measure is
   still the lesson notebooks' — it lives in notebook-view.css and is theirs;
   this only lifts it here. */
#page-arena-notebook .nbv-cells,
#page-arena-notebook .arena-nb-head {
  max-width: none;
}

/* 🔴 CODE IS IN THE COLUMN, NOT BESIDE IT. It used to break out by 99px each
   side to 880px, and that is what put the runnable cells further left than the
   prose above them — under the contents tree, and visibly unaligned. Seth,
   2026-09-03: "make it such that the body text is aligned with the code blocks
   ... aligned on both the left and the right". At 1.4x the column is ~955px,
   which is wider than the 880px the breakout was buying anyway. That is now
   just `.nbv-cells { max-width: calc(682px * var(--anb-zoom, 1)) }` above.

   🪦 The grey fill was dropped here at the same time, as a page override of a
   filled rule in notebook-view.css — which left the same element tinted on two
   surfaces and hairlined on this one. The rectangle is the shared rule now;
   only the hints disclosure still needs saying, because it is not `.nbv-code`
   and so is not covered by it. */
#page-arena-notebook .nbv-cell.nbv-hints {
  background: transparent;
}

/* ---- LessWrong's typography, measured ------------------------------------ */

/* SETH, 2026-09-02, with our page and theirs open side by side: "I really like
   the font that they use along with the text sizing and the headers and all
   that other stuff. So, you could copy that exactly."

   Every number below was READ OFF A RENDER, not guessed. ~/Applications/
   lw-toc-local mounts their real FixedPositionToC / MultiToCLayout components
   over one of our notebooks, and tools/visual-diff reads the computed styles
   back out of it. What that comparison showed is worth writing down, because
   it is not what the screenshots suggested: THE SIZES WERE ALREADY EXACT on
   both sides — 36.4 / 26 / 20.8 / 18.2px, rail labels 15.1 / 14.3px, rail rows
   at the same x. The three things that actually differed were the family, the
   heading WEIGHT (we were bold, they are 400) and the palette.

   🔴 THE LINE-HEIGHTS ARE PIXELS, NOT RATIOS. Theirs come out of a 13px rem
   root; ours is 16px. A ratio copied across those two roots is a different
   number of pixels, which is how this drifted the first time. */

/* 🔴 :root, FOR THE SAME REASON variables.css IS. These are token
   declarations, and a token only reaches an element at or BELOW the one that
   declares it. `body` paints the page and the contents rail is
   `position: fixed`, so both sit outside #page-arena-notebook — declaring
   these on the page left the rail and the whole surround on the dark theme's
   --bg while the reading column alone turned white. app.js sets the attribute
   when this page opens and clears it when it closes, so nothing else in the
   app sees these. */
:root[data-arena-notebook] {
  /* 🔴 EVERY MEASUREMENT BELOW IS LESSWRONG'S REAL ONE, TIMES THIS.

     Seth read their post at 140% browser zoom, liked it at that size, and
     reported ours as "much smaller than what it actually is on the website".
     Measuring both at a matched viewport settled it: their column really is
     682px of 18.2px text on a 26px line and ours already matched it exactly —
     the 40% was his zoom, not their design. So the LW numbers stay written in
     the source as the numbers they measured to, and this multiplies them.
     Seth, 2026-09-03: "make it 140% larger actually. I think that's better."

     🔴 CHANGE THE SIZE HERE AND NOWHERE ELSE. Retuning by editing the pixel
     values would destroy the provenance — every one of them was read off a
     render, and a hand-scaled copy can no longer be checked against theirs.
     The fallback is 1, so without this attribute the sheet is still their
     measure.

     🔴 IT WAS 1.4 AND IT IS 1 AGAIN (Seth, 2026-09-22: "make it
     resized such that it's much more aligned with the size of the lessons
     ... because I like the way the lessons look more"). A lesson page sets no
     zoom, so it renders the measured sheet at 1; this page multiplying it by
     1.4 was the ONLY reason the two surfaces looked like different products
     — same measurements, same faces, same palette, one knob apart. Matching
     the lessons therefore means this number and nothing else: 25.48px prose
     and code in a 954.8px column become 18.2px in 682px, which is what a
     lesson already renders and what LessWrong actually measures at. */
  --anb-zoom: 1;

  /* 🪦 --anb-measure, --anb-code-size and --anb-code-lh WERE DECLARED HERE,
     and then briefly at :root in styles/practice/notebook-view.css, and now
     nowhere: a custom property is substituted where it is DECLARED, so a token
     derived from --anb-zoom freezes at whichever zoom its own block had and
     the surfaces that set a different one silently keep the root's number. The
     measurements are written out at each point of use instead. See the note at
     the top of that file. This page still sets the zoom and nothing else. */

  /* 🪦 --lw-serif / --lw-header WERE DECLARED HERE. They are
     --prose-font / --prose-heading in styles/variables.css now, because this
     stopped being the only page set in them: Seth, 2026-09-10, asked the
     practice split's problem panel and the lesson pages for "the same font as
     the notebook", so the face had to outlive this attribute. Same list, same
     provenance — see the note in variables.css. */
}

/* ── LessWrong's palette — THE LIGHT THEME ONLY ────────────────────────────
   🪦 THIS PAGE USED TO BE LIGHT IN EVERY THEME. variables.css handed
   `:root[data-arena-notebook]` the whole light palette, so a learner on the
   dark theme who opened a notebook got a white screen. Seth, 2026-09-10: "if
   it's in dark mode, both the notebook and the coding interface or whatever
   should be in dark mode. And then if it's in light mode, it should just have
   what it currently has."

   "What it currently has" is this block, and it is unchanged — their three
   greys and their hairline, over the light palette. It just has to ASK for the
   light theme now instead of forcing it.

   --bg becomes --surface, so the page and the topbar are the same white and
   the bar reads as LessWrong's does: a hairline rule rather than a panel.
   --accent-text is the label hover in the rail, which they take to
   full-strength text rather than to a brand colour. */
:root[data-theme="light"][data-arena-notebook] {
  --bg: var(--surface);
  --text: rgba(0, 0, 0, 0.87);
  --muted: #616161;
  --muted-dim: #757575;
  --border: #e0e0e0;
  --border-strong: #bdbdbd;
  --accent-text: rgba(0, 0, 0, 0.87);
}

/* ── The same page, on a dark theme ────────────────────────────────────────
   Deliberately short. The dark and blue palettes are already a reading
   surface — that is what the Colab greys were built for — so this does NOT
   restate them, it only repeats the ONE structural move the light block makes
   that the theme does not: the rail's hover goes to full-strength text rather
   than to the brand red, so a contents tree does not read as a list of links
   to click.

   Everything else that differed between the two surfaces is a --prose-* token
   in variables.css, declared once per theme like every other colour.

   🔴 `:not([data-theme="light"])` rather than listing dark and blue. A fourth
   theme is "a block in variables.css, an entry in THEMES, and nothing else"
   (theme.js), and naming the themes here would quietly break that promise —
   the new theme would get the light block's greys on a dark page. */
:root:not([data-theme="light"])[data-arena-notebook] {
  --accent-text: var(--white);
}

#page-arena-notebook {
  background: var(--bg);
  color: var(--text);
}

/* The section header is this page's title block, so it follows the headings
   rather than the app's sans chrome — but it is the one heading here that is
   NOT inside a `.nbv-md` cell, so the shared scale in
   styles/practice/notebook-view.css does not reach it and it restates the
   face. Same h2 numbers as that sheet's `.nbv-md h2`. */
#page-arena-notebook .arena-nb-title {
  font-family: var(--prose-heading);
  font-weight: 400;
  font-size: calc(26px * var(--anb-zoom, 1));
  line-height: calc(31.35px * var(--anb-zoom, 1));
}

#page-arena-notebook .arena-nb-desc {
  font-family: var(--prose-font);
  font-size: calc(18.2px * var(--anb-zoom, 1));
  line-height: calc(26px * var(--anb-zoom, 1));
}

/* 🔴 EVERY HEADING ON THIS PAGE IS CENTRED — the section's own title block
   and every `.nbv-md` heading down the notebook. Seth, 2026-09-11: "for the
   different headers within the notebook, instead of being left aligned, they
   should be center aligned, such that they align with the top bar". The tab
   strip in the topbar is centred in the window; a left-aligned heading under
   it reads as a column that starts somewhere else. Body prose stays
   left-aligned — a centred paragraph is a poster.

   Scoped to this page: notebook-view.css's scale is shared with the lesson
   notebooks, and this is the ARENA page's alignment, not theirs. With the
   contents pane docked the column starts right of it, so a centred heading
   is centred in the COLUMN rather than under the tab strip — moving the
   headings off the column they head would be the worse trade. */
#page-arena-notebook .arena-nb-head,
#page-arena-notebook .nbv-md h1,
#page-arena-notebook .nbv-md h2,
#page-arena-notebook .nbv-md h3,
#page-arena-notebook .nbv-md h4 {
  text-align: center;
}

/* ---- the editor layer (practice/notebook-code-edit.js) ------------------- */

/* 🔴 BOTH OF THESE ARE GENERATED CONTENT, AND THAT IS THE POINT. The cell's
   source is read back out of the DOM with `innerText`, so a character drawn
   here as real text would end up in the learner's program — a suggestion they
   never accepted, or a zero-width space Python answers with a SyntaxError.
   `content:` is in neither `innerText` nor `textContent`. See the header of
   practice/notebook-code-edit.js.

   The ghost is the inline completion: dimmed enough to read as "not yours
   yet", solid enough to read. Same token the practice editor's ghost uses,
   so the two surfaces suggest in the same colour. */
.nb-code-ghost::after {
  background: rgb(var(--tint-rgb) / calc(0.05 * var(--tint-k)));
  border-radius: 2px;
  color: var(--code-ghost);
  content: attr(data-ghost);
}

/* Holds a line box open on a trailing newline, which a pre-formatted element
   otherwise gives no height — the blank line you just made with Enter has to
   be somewhere the caret can sit. */
.nb-code-tail::after {
  content: "\200B";
}

