/* ============================================================================
   custom_base.css — custom_clean's baseline stylesheet (shipped here).

   Renders nbconvert's markup with the look of the site's earlier
   lab-template exports, measured from a reference page (1440px viewport):
   white page, full-width content, ONE uniform content column — every
   cell's text starts ~104px from the left edge (empty markdown-cell
   prompts are hidden and reserve their gutter via .text_cell_render's
   left padding; code cells via the 76px prompt column) — 14px/1.6 body
   text, 500-weight headings on the lab size scale (h1 2.0736em ... h6
   0.83333em), 13px code on #f5f5f5 with an #e0e0e0 border, inline code
   as the lab's grey #eee chip, In[]/Out[]
   prompt columns, and the lab's full vertical rhythm: cells padded 5px,
   5px input→output gap, headings 1.2em/0.8em (0.6em first-child,
   0.4em last-child), p 0/1em, lists 1em/1em with 2em indent, code and
   output text on the 1.3077 code line-height, stdout/execute_result
   text starting on the ONE common text edge (~104px) like every other
   text on the page (user rule — see the output_text block below).

   Provenance — measured, not asserted (reproduce: python verify_custom_css.py):
   this file is not a byte-copy of nbconvert's classic static/style.css.
   It is written against the DOM nbconvert emits, so most selectors target
   markup nbconvert also targets; the typography/layout values above are
   lab-export parity, not classic's. verify_custom_css.py prints the exact
   overlap numbers; README.md quotes them — if they differ, one of the two
   is stale.

   Every selector below targets either markup that nbconvert itself emits
   (.border-box-sizing, #notebook, #notebook-container, .rendered_html, ...)
   or custom_clean's own custom-* hooks (#custom-toc and friends).

   This file is a plain shipped file — edit freely; custom.css (same
   folder) is reserved for your rules and is never overwritten.
   ========================================================================== */

/* ---------- base ---------- */
html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background-color: #ffffff;
  color: rgba(0, 0, 0, 0.87);
  font-family: system-ui, -apple-system, blinkmacsystemfont, "Segoe UI",
    helvetica, arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
    "Segoe UI Symbol";
  font-size: 14px;
  line-height: 1.6;
  overflow: visible;
  padding: 8px 0;
}
.border-box-sizing {
  box-sizing: border-box;
}
a {
  color: #1155cc;
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

/* ---------- footnote jump-mark anchors: landing context ---------- */
/* jump_marks.py's footnote scheme navigates to empty inline anchors:
   <a name="fn_NN"> (definitions at the bottom) and <a name="abs_MM">
   (group anchors at the referencing paragraphs). Fragment navigation
   normally glues the target line to the very top of the viewport —
   after a jump you see the target but NONE of the text around it.
   scroll-margin-top pushes the landing point down by 3 body text lines
   (3 x 22.4px at 14px/1.6 = 67.2 -> 67px), so the lines ABOVE the anchor
   stay visible in both jump directions: a reference click (#fn_NN) keeps
   the preceding footnotes / the "Fußnoten:" line in view, a back-link
   click (#abs_MM) keeps the tail of the text before the referencing
   paragraph in view. Scoped to exactly the two name prefixes the helper
   emits — extra anchors (bsp_01, ...) and the heading/pilcrow anchors
   keep landing exactly at the top. scroll-margin participates ONLY in
   scroll-into-view (hash jumps / fragment navigation): no layout effect,
   no effect on ordinary links, and it applies retroactively to every
   page generated before this rule existed. Set it to 0 to restore the
   glued-to-top landing. Near the very end of the document the browser
   clamps at max scroll before the offset can apply (measured on the live
   Tokens page: fn_09 keeps its landing unchanged in both engines).
   Verify: python3 scripts/fn_scroll_check.py                         */
a[name^="fn_"],
a[name^="abs_"] {
  scroll-margin-top: 67px;
}

/* ---------- footnote jump flash (classes set/removed by custom_toc.js) ---------- */
/* After a footnote jump the optional script (js/custom_toc.js, section 2)
   marks the landing spot so the eyes find it: the footnote number marker
   and, where one exists, the word the marker hangs on. The whole timing
   lives in ONE CSS animation — the classes are mere triggers, so a JS
   failure can never leave a stuck highlight: ~5.9 s hold, then a ~1.3 s
   fade to transparent; the script unwraps its word spans right after
   (7.86 s), leaving the DOM exactly as it was. Without the script nothing
   flashes and the page is unchanged (the jump marks need no JS).
   Color: the turquoise of the site's own MindMap deep-link highlight
   (jmnode.jump-highlight in the MindMap viewer's css/kristall_style.css:
   #40e0d0 background + 0 0 10px rgba(0,139,139,0.7) glow), so a green
   MindMap arrow jump and a footnote back-link read as the same kind of
   event (user request: consistency). The MindMap also sets a dark-cyan
   border on its node boxes — NOT reproduced here: a border widens an
   inline box and nudges the surrounding line; the glow is box-shadow,
   which paints outside the line box and cannot shift layout. Durations:
   the ~5.9 s hold keeps the approved ~6 s visibility; ONLY the fade
   doubles, ~0.7 s -> ~1.3 s (6.6 s -> 7.26 s total — user request:
   "the fade to take 2 as long"; the fade-out, not the hold). The keyframe
   split sits at 81.8% = 5.94 s / 7.26 s, so the hold is byte-identical
   to the original and the fade exactly twice as long.
   Dark chip (P-003 R8, owner directive: "the color is perceived
   different on the background and is too light with light letters, we
   need to darken it in darkmode"): under the dark palettes the chip's
   letters are rgba(255,255,255,0.87), which collapses against #40e0d0
   to ~1.5:1 contrast (light mode's dark ink sits at ~11.5:1) — the
   same turquoise reads far too light there. The two dark blocks below
   therefore swap ONLY the animation-name to a second keyframe,
   custom-fn-flash-dark, whose ONLY change is the hold background:
   #006d6d — same turquoise hue, ~5.1:1 under the light letters, still
   ~2.7:1 above the #1e1e1e page plus the glow halo. The glow color
   rgba(0,139,139,0.7) is byte-identical in BOTH keyframes (standing
   directive: the glowing effect's color never changes), as are the
   fade endpoint and every timing. Light mode keeps the untouched
   custom-fn-flash bytes. (The MindMap's own jmnode.jump-highlight has
   no dark treatment and keeps #40e0d0 in dark — divergence registered
   as an open candidate, not changed without a directive.) */
@keyframes custom-fn-flash {
  0%, 81.8% {
    background-color: #40e0d0;
    box-shadow: 0 0 10px rgba(0,139,139,0.7);
  }
  100% {
    background-color: transparent;
    box-shadow: 0 0 10px rgba(0,139,139,0);
  }
}
/* dark-state twin: identical except the hold background (see the comment
   above) — referenced only by the two dark blocks at the file tail */
@keyframes custom-fn-flash-dark {
  0%, 81.8% {
    background-color: #006d6d;
    box-shadow: 0 0 10px rgba(0,139,139,0.7);
  }
  100% {
    background-color: transparent;
    box-shadow: 0 0 10px rgba(0,139,139,0);
  }
}
.fn-flash-word {
  animation: custom-fn-flash 7.26s ease-out forwards;
  border-radius: 2px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.fn-flash-mark {
  animation: custom-fn-flash 7.26s ease-out forwards;
  border-radius: 2px;
  /* chip the digit without shifting the line */
  padding: 0 1px;
  margin: 0 -1px;
}

/* ---------- page layout ---------- */
div#notebook {
  overflow: visible;
  border-top: none;
}
div#notebook-container {
  box-sizing: border-box;
  width: 99%;
  max-width: none;
  margin: 0 auto;
  /* top padding 10px = the lab's --jp-notebook-padding; with body's 8px this
     puts the first heading at the same y as the reference export (35px). */
  padding: 10px 2ex 4ex 2ex;
  background-color: #ffffff;
}
@media print {
  body {
    margin: 0;
  }
  div.cell {
    display: block;
    page-break-inside: avoid;
  }
  div.output_wrapper {
    display: block;
    page-break-inside: avoid;
  }
  div.output {
    display: block;
    page-break-inside: avoid;
  }
}

/* ---------- table of contents ---------- */
#custom-toc {
  box-sizing: border-box;
  width: 99%;
  max-width: none;
  margin: 8px auto 20px auto;
  padding: 12px 18px;
  border: 1px solid #e3e3e3;
  border-radius: 6px;
  background-color: #fafafa;
  font-size: 14px;
}
#custom-toc .custom-toc-title {
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 6px;
}
#custom-toc .custom-toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
#custom-toc .custom-toc-list li {
  margin: 2px 0;
}
#custom-toc .custom-toc-l1 {
  padding-left: 0;
}
#custom-toc .custom-toc-l2 {
  padding-left: 1.4em;
}
#custom-toc .custom-toc-l3 {
  padding-left: 2.8em;
  font-size: 13.5px;
}
#custom-toc .custom-toc-l4 {
  padding-left: 4.2em;
  font-size: 13px;
}
#custom-toc .custom-toc-l5 {
  padding-left: 5.6em;
  font-size: 12.5px;
}
#custom-toc .custom-toc-active > a {
  font-weight: 700;
}

/* ---------- TOC as a right-hand sidebar ----------
   On wide screens the TOC leaves the document flow: the page becomes a
   two-column grid (content | toc), the box sticks below the viewport top
   and scrolls with the reader. Bold marks ONLY the section currently in
   view (the scroll-spy's .custom-toc-active, rule above). Below the
   breakpoint — and on portrait screens — the TOC stays the full-width
   block on top of the document.
   P-004 fix (2026-11-06): the grid is gated on the toc's EXISTENCE — a
   page without a toc renders single-column at every width, no reserved
   and empty 22rem column. Two SEPARATE rules on purpose: in engines
   without :has() one unknown selector would drop the whole rule, so
   main.has-toc (set by js/custom_toc.js) must stand alone as the
   fallback; together they cover first paint, no-JS and old engines.
   P-004 R10 (2026-11-06): sticky top = the box's NATURAL offset — body
   padding-top (8px) + the box's own margin-top (10px) = 18px. A smaller
   sticky top lets the box ride up the first few pixels of scrolling
   (owner: "when I start scrolling the box moves a little up, that must
   not happen") — with top == the natural offset the box is born pinned
   and scroll start cannot move it. max-height follows the same
   arithmetic: 18px top + box + 20px bottom margin = 100vh. */
@media (min-width: 80em) {
  main:has(> #custom-toc) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 22rem;
    column-gap: 24px;
    align-items: start;
  }
  main.has-toc {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 22rem;
    column-gap: 24px;
    align-items: start;
  }
  #custom-toc {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    /* 8px body padding-top + 10px margin-top = the natural offset; the
       box is born pinned — scroll start cannot move it (P-004 R10). */
    top: 18px;
    width: auto;
    max-width: none;
    margin: 10px 0 20px 0;
    max-height: calc(100vh - 38px);
    overflow-y: auto;
  }
  div#notebook {
    grid-column: 1;
    grid-row: 1;
  }
  div#notebook-container {
    width: 100%;
  }
}

/* ---------- cells ---------- */
div.cell {
  margin: 0;
  padding: 0;
  outline: none;
}
/* lab cell padding (--jp-cell-padding) for the vertical rhythm between cells */
div.text_cell {
  padding: 5px 0;
}
div.text_cell_render {
  /* lab-export parity: markdown text sits in the SAME content column as
     code (~104px from the left edge at any viewport). The empty prompt
     div of a text cell is hidden below; the 81px gutter it needs is built here as left padding
     (81px ≈ the code cells' 76px prompt column + the pre's ~5px inset). Right padding 20px mirrors the lab's rendered-HTML rule.
     No top/bottom padding here — the lab builds the vertical rhythm purely
     from margins (first-child headings 0.6em, p 0/1em, last-child 0.5em). */
  padding: 0 20px 0 81px;
  outline: none;
  resize: none;
  width: inherit;
  border-style: none;
}
div.text_cell .prompt {
  display: none;
}
div.code_cell {
  padding: 5px 0;
}
div.input {
  padding: 0;
}
div.input_area {
  border: 1px solid #e0e0e0;
  border-radius: 3px;
  background: #f5f5f5;
  /* code lines never wrap (see div.input_area pre) — so on narrow screens
     the input box gets a left-right scrollbar instead of clipping them */
  overflow-x: auto;
  overflow-y: hidden;
}
div.inner_cell {
  min-width: 0;
}

/* ---------- prompt columns ---------- */
div.prompt {
  /* lab prompt metrics: 64px content + 2x5px padding + 2x1px transparent
     border = the same 76px prompt column (input code areas start at ~99px,
     their text at ~105px); 13px/1.3077 like the lab's InputPrompt. */
  min-width: 64px;
  padding: 5px;
  border: 1px solid transparent;
  margin: 0;
  font-family: "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
  font-size: 13px;
  line-height: 1.3077;
  text-align: right;
  color: #666666;
  float: left;
}
div.input_prompt {
  color: #38629a;
}
div.output_prompt {
  color: #b05a3a;
}
div.output_wrapper {
  position: relative;
}
/* the lab puts a fixed 5px gap between a cell's input and its outputs */
div.code_cell div.output_wrapper {
  margin-top: 5px;
}
div.output {
  min-width: 0;
}
div.output_area {
  /* definite-width row (lab output-area layout): table-layout fixed gives
     the subarea cell the REMAINING column width instead of letting it
     expand with its widest non-wrapping content — long stdout lines wrap
     inside the column instead of widening the whole page. */
  display: table;
  width: 100%;
  table-layout: fixed;
  padding: 0;
  page-break-inside: avoid;
}
div.output_area .prompt {
  float: none;
  display: table-cell;
  /* lab-parity Out prompt = the In prompt's box: 64px content + 2x5px
     padding + 2x1px border = 76px total, so "Out [N]:" ends where
     "In [N]:" ends (text right edge ~93px) and the execute_result
     content column starts at ~99px.
     Rows WITHOUT a result (display_data/stream) carry an EMPTY prompt
     cell — the :empty rule below strips its padding and border, leaving
     the lab's bare 64px prompt-width column; that is the column that
     keeps display_data content (and the brat svg's 12px inset) at 87px,
     so the svg's blue frame lands on the 99px code column.
     vertical-align: top = the reference's prompt alignment (measured
     .jp-OutputArea-prompt: va top, pad 5px, border-top 1px). Alignment
     between prompt text and output text comes from MATCHING 6px insets
     (here 5px padding + 1px border; the execute_result cell below carries
     the same), never from table baseline alignment: Firefox sizes a
     baseline-shifted cell's row WITHOUT the shift and then lets the
     shifted content overflow the row — the missing bottom-line bug. With
     top-aligned prompts the subarea always defines the row baseline
     unshifted, so the row is exactly its content in every engine. */
  vertical-align: top;
  min-width: 0;
  width: 64px;
}
div.output_area .prompt:empty {
  /* the reference strips its EMPTY output prompt cells
     (.jp-OutputArea-prompt:empty { padding: 0; border: 0 }): bare 64px
     column, content at 87px. The old "64px total" rule had wrongly
     applied that number to the Out [N] rows as well — moving "Out [4]:"'
     text 9px left of "In [N]:" and its content column to 87px instead
     of the reference's 99px. */
  padding: 0;
  border: 0;
}
div.output_subarea {
  /* lab .jp-RenderedHTMLCommon output cell: no left padding, 20px right
     (measured 0/20px) — the 20px are what keeps the brat svg's right
     border inside the cell: brat's JS pins the svg width to the column
     width via inline style, so the 12px inset + 2px borders overhang the
     content edge by 14px and need that right padding as slack. */
  padding: 0.4em 20px 0.2em 0;
  /* NO scroll container on output cells, on either axis. The old
     overflow-x: auto computed overflow-y to auto (CSS Overflow: visible
     next to auto computes to auto), making every output cell a vertical
     scroll container — and Firefox sizes the table row WITHOUT the cells'
     baseline-alignment shift, then clips what shifts out: the bottom
     ~6-8px of a text output's last line vanished at every zoom level
     (measured, scripts/outrow_clip_ff.py: scrollH 278 vs clientH 272,
     pre.bottom - cell.bottom = +6px at zoom 1.0). Chromium includes the
     shift and never clipped — engine-dependent, hence easy to miss.
     Outputs now simply grow as big as their content needs (the lab's own
     "vertical never" policy). Text outputs wrap (white-space: pre-wrap),
     so horizontal overflow cannot arise for them; a genuinely
     non-wrapping wide output now widens the page instead of growing an
     in-cell scrollbar — accepted for now, revisit if it ever bites. The
     brat widget row keeps its explicit overflow policy from
     custom_brat.css (:has() rule — horizontal scroll, vertical hidden). */
  overflow: visible;
  display: table-cell;
}
div.output_stream,
div.output_text {
  text-align: left;
}
/* stdout/stderr/execute_result text: 13px mono on the 1.3077 line-height.
   USER RULE: their glyphs start on the page's ONE common text edge (the
   paragraph/In-code column, measured 104.2px at 1440) — deliberately
   diverging from the lab reference, whose RenderedText cells carry a 2ch
   inset plus a 6px pre margin that put stdout glyphs at ~108.8px and
   execute_result glyphs at ~120.8px, i.e. visibly right of every other
   text (user screenshot, red freehand line; measured before/after:
   scripts/outcol_check.py on the real live Tokens.html markup).
   The two row types start at DIFFERENT columns — execute_result after the
   76px Out prompt box (cell at ~99.2px), stream and any bare display_data
   text row after the bare 64px empty-prompt column (cell at ~87.2px) — so
   the cell itself carries the inset that lands its glyphs on the common
   edge: 17px here for the 87.2px rows, 5px for execute_result below
   (matching the In row's visual inset: 1px input border + 4px pre
   padding). The old 2ch+6px scheme is gone — the pre sits at margin 0. */
div.output_subarea.output_text {
  padding: 0 0 0 17px;
  /* 13px so the mono cell's own insets resolve exactly; see above */
  font-size: 13px;
  font-family: "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
}
/* execute_result rows: the lab gives .jp-OutputArea-executeResult a
   deterministic 6px top inset (padding-top 5px + 1px transparent
   border-top, measured on the reference: pad "5px 0px 0px 15.6533px",
   borderT 1px) so the result's first line sits on the same baseline as
   the Out [N] prompt's text, whose own box contributes the same 6px
   (5px padding + 1px border, see the prompt rule). Stream/display rows
   get no inset — their empty prompts are stripped to 0. This replaces
   the old implicit alignment (table baseline shift +6px) with the
   reference's explicit one; the row height is identical (278px for the
   16-line Out [4] list) but no longer engine-dependent. */
div.output_subarea.output_execute_result {
  padding-top: 5px;
  border-top: 1px solid transparent;
  /* left: this row starts after the 76px Out prompt box (cell ~99.2px,
     NOT the 87.2px stream column) — 5px = the In row's visual inset
     (1px input border + 4px pre padding) lands its glyphs on the same
     common text edge (~104.2px) as everything else. Overrides the 17px
     of the .output_text rule above (execute_result rows match both). */
  padding-left: 5px;
}
div.output_area .output_text pre {
  margin: 0;
  padding: 0;
  line-height: 1.3077;
  word-break: break-all;
}
/* markdown ``` code blocks: the lab renders them bare (no margin, no
   padding, no box) — mono text on the page background */
.rendered_html pre {
  margin: 0;
  padding: 0;
}
div.output_stderr {
  background: #fdd;
}
div.output_error {
  background: #fdd;
  border: 1px solid #ebb;
  border-radius: 3px;
  margin: 2px 0;
}
div.output_latex,
div.output_markdown,
div.output_html {
  text-align: left;
}
div.output_png img,
div.output_jpeg img,
div.output_svg img {
  max-width: 100%;
  height: auto;
  vertical-align: middle;
}
div.output_png img.unconfined,
div.output_jpeg img.unconfined,
div.output_svg img.unconfined {
  max-width: none;
}

/* ---------- code / monospace ---------- */
pre,
code,
kbd,
samp {
  font-family: menlo, consolas, "DejaVu Sans Mono", monospace;
}
pre {
  font-size: 13px;
  margin: 0.2em 0;
  padding: 0.5em 0.4em;
  line-height: 1.3077;
  background: transparent;
  border: none;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: inherit;
}
div.input_area pre {
  /* the lab's editor pre (.cm-editor.cm-s-jupyter .highlight pre):
     padding 5px 4px, margin 0 — code text starts at 104px, the SAME
     column as markdown text, and an n-line box is n x 17px + 10px + border,
     exactly like the reference */
  margin: 0;
  padding: 5px 4px;
  white-space: pre;
}
code {
  /* shared baseline for ALL code elements: mono font, body size, bare box —
     the grey chip lives on :not(pre) > code below */
  font-size: inherit;
  background: transparent;
  border-radius: 0;
  padding: 0;
}
:not(pre) > code {
  /* inline code chip (`` `PPK_1` `` etc.) — CORRECTED reading of the
     reference: the lab exports' own css carries
       .jp-RenderedHTMLCommon :not(pre) > code {
         background-color: var(--jp-layout-color2);   = --md-grey-200 = #eee
         padding: 1px 5px; }
     on top of the shared pre/code rule (border: 0, line-height 1.3077,
     white-space pre-wrap). An earlier version of this file mis-read the
     reference as "bare mono" and left the backtick look out of the
     exports entirely — user request put it back. Grey fill, and — Task
     37, user: "put the border just like the bigger code (cell) blocks
     have one" — the SAME border as the div.input_area cell boxes:
     1px solid #e0e0e0. Fenced ``` blocks (pre > code) stay bare below.

     box geometry — deliberate deviations from the lab's 1px 5px /
     1.3077 (user request: "the grey box is too big especially on x
     axis" and "the letters are higher on y axis than the text they
     are embedded in"):
     - padding 1px 3px (Task 36 retune of Task 35's 0 2px 1px, user:
       "top and bottom padding back to 1px and the x padding to only
       drop to 6 instead of 4"): 6px total x-padding keeps the chip
       clearly narrower than the lab's 10px; the 1px bottom gives
       descenders and underscores air. line-height stays normal, so
       the extra top padding grows the grey UPWARD only — the box
       top lands at ascent + 1px, flush with the surrounding text's
       own font box (measured: chromium 0px above it, firefox 1px
       below it), and the box's LOWER edge stays exactly where the
       no-top-padding version had it.
     - line-height normal instead of 1.3077: the fixed 17px line added
       ~1px of synthetic half-leading ABOVE the glyphs and the 1px top
       padding pushed further, so the grey box rose above the
       surrounding text's own font box and the chip floated high in
       the line (guide-line screenshots in
       scripts/cssflow/chip_geom*.png). normal makes the grey hug the
       mono font's own ascent/descent on every platform. Measured on
       both engines (scripts/chip_geometry_probe.py): the grey no
       longer pokes above the surrounding text's box, and the grey
       over the glyph tops is exactly the requested 1px padding. The
       font-size deviation below is UNTOUCHED — the approved 13px
       letter size stays.
     - display inline-block (Task 36, user: "keep the lower edges of
       text on one line" — the narrower chips had reflowed the live
       Tokens page so the SECTION 0 chip broke at its internal space
       onto the next line): an inline-block is ATOMIC — a chip that
       does not fit the rest of the line moves to the next line WHOLE
       instead of splitting at a space, so a chip's text never
       continues on a second line. If a chip were ever wider than the
       whole column it would wrap internally (pre-wrap) rather than
       overflow horizontally. Baseline geometry is unchanged: the
       inline-block's baseline is its own text baseline, so letters
       stay on the shared baseline and the box keeps the exact
       ascent+1 / descent+1 shape of the inline version.

     font-size — deliberate deviation from the lab (user request, "the
     text in backticks is bigger than the other text, that MUST stop"):
     at the inherited 14px the chip matches the body's nominal size, but
     mono glyphs (larger x-height, fixed advance width) read distinctly
     bigger than the surrounding sans text. 0.9286em = 13px on the 14px
     body — the size every OTHER code on the page already uses (pre,
     prompt column, stdout/execute_result), so inline code now sits at
     the page's one code size and clearly below the body text; in em, so
     a chip inside a heading keeps scaling with the heading (h2 ≈ 22.5px).
     Measured before/after: scripts/code_size_check.py (14px -> 13.0px,
     parent p stays exactly 14px, no line-height change). */
  display: inline-block;
  font-size: 0.9286em;
  background-color: #eeeeee;
  border: 1px solid #e0e0e0;
  border-radius: 0;
  padding: 1px 3px;
  line-height: normal;
  white-space: pre-wrap;
}
pre code {
  /* block code inside a fenced ``` pre stays bare mono on the page */
  background: transparent;
  padding: 0;
  border-radius: 0;
}
div.highlight {
  background: transparent;
}

/* ---------- rendered markdown typography ---------- */
.rendered_html {
  color: rgba(0, 0, 0, 0.87);
}
/* heading scale: font sizes stay the lab's --jp-content-font-sizeN steps
   on the 14px body (h1 ≈ 29px ... h6 ≈ 12px), weight 500, line-height 1.
   Margins are a DELIBERATE user-requested deviation from the lab rhythm
   (tighter heading gaps): top 0.6em / bottom 0.4em instead of the lab's
   1.2em/0.8em, 0.3em for first-child headings (lab: 0.6em). Margins are
   in each heading's own em, so absolute px scale with the heading level
   (h1 top ≈ 17px, h3 top ≈ 12px). Halving both values keeps the lab's
   top:bottom ratio; adjust here if a tighter/looser rhythm is wanted. */
.rendered_html h1,
.rendered_html h2,
.rendered_html h3,
.rendered_html h4,
.rendered_html h5,
.rendered_html h6 {
  margin: 0.6em 0 0.4em 0;
  line-height: 1;
  font-weight: 500;
}
.rendered_html h1:first-child,
.rendered_html h2:first-child,
.rendered_html h3:first-child,
.rendered_html h4:first-child,
.rendered_html h5:first-child,
.rendered_html h6:first-child {
  margin-top: 0.3em;
}
.rendered_html h1 {
  font-size: 2.0736em;
}
.rendered_html h2 {
  font-size: 1.728em;
}
.rendered_html h3 {
  font-size: 1.44em;
}
.rendered_html h4 {
  font-size: 1.2em;
}
.rendered_html h5 {
  font-size: 1em;
}
.rendered_html h6 {
  font-size: 0.83333em;
}
/* heading anchor pilcrows: nbconvert's markdown filter emits
   <a class="anchor-link" href="#...">¶</a> inside every heading. The lab
   reference never shows them at all (its inline css: a.anchor-link
   { display: none }) — same here. The links stay in the DOM so their
   hrefs keep working; classic's hover-reveal scheme is gone, so a
   pilcrow can never become visible, not even on heading hover. */
a.anchor-link {
  display: none;
}
/* heading links render as plain text, URL as CSS tooltip: a markdown
   heading like "## [#SchrifttumsLinguistik](https://…)" would otherwise
   paint the global link blue (#1155cc) inside the heading. In the exports
   the link keeps the heading's own color (inherit) and never underlines;
   the URL surfaces only on hover/focus via ::after + attr(href) — pure
   CSS, no JS, no title-attribute post-processing. :not(.anchor-link)
   keeps the hidden pilcrow anchors out of the scheme;
   :not([href="#toc"]) the toc jump-back links (P-004 R11, owner ruling:
   "I never said I want the toc tooltip") — the back-links matter on small
   screens without the space on the right for a toc, and those are touch
   anyway (no hover, no tooltip), so a tooltip on them would only ever
   fire in the narrow-desktop edge case. They keep the heading-text look
   (the first rule below still applies to them) and simply carry no
   ::after; the rubrum's mindmap deep link and every other heading link
   keep their tooltip. Touch devices have no hover: every link stays
   tappable, the tooltip is simply absent there.
   Body links outside headings keep the global a rules unchanged.

   One line, never wrapped (user request): the positioned anchor IS the
   ::after's containing block, so with white-space:normal an absolutely
   positioned tooltip shrink-to-fit inside the HEADING TEXT's own width —
   a URL longer than the heading soft-wrapped into several lines (seen on
   the live exports, e.g. the top heading of test_werte_PPK_aus). nowrap
   makes the one-line width both the min- and the max-content width, so
   the box grows to its full single-line size and overflows the anchor
   and the heading to the right — allowed here: body and #notebook are
   overflow:visible, so nothing clips it; a URL wider than the page only
   widens the horizontal scroll area while it is hovered. No max-width
   cap and no word-break either: both would put the soft wrap back for
   long URLs. */
.rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link) {
  color: inherit;
  text-decoration: none;
  position: relative;
}
.rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link):not([href="#toc"])::after {
  content: attr(href);
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 10;
  display: none;
  padding: 3px 8px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.82);
  color: #ffffff;
  font-family: menlo, consolas, "DejaVu Sans Mono", monospace;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  white-space: nowrap;
  pointer-events: none;
}
.rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link):not([href="#toc"]):hover::after,
.rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link):not([href="#toc"]):focus-visible::after {
  display: block;
}
/* footnote reference tooltips (user request, revised): every reference
   <a href="#fn_NN"><sup>N</sup></a> shows the footnote's own text on
   hover/focus. custom_toc.js reads the text from the definition block at
   view time and builds a <span class="custom-fn-tt"> inside the
   reference carrying ONE head span: THE FIRST MAX 64 CHARACTERS — a
   hard cut. The user's final rule, verbatim: "I want only one line to
   see, even if it breaks correctly, I should not break/wrap at all.
   ONE LINE MAX, ON THAT ONE LINE 60 CHARS MAX", raised by: "I want 63
   chars now, I reworked text and footnote", then: "Want 64 now
   anyways" — so there is NO tail,
   no second line, nothing below: the earlier head + loosely wrapped
   tail build is gone. When the definition runs longer than the window,
   the JS line ends with an ellipsis "…" as the continuation hint
   (user: "ah and if there is more text than the 64, then there have to
   be ... as hint") — a fitting definition gets none. The data-fn-head
   attribute stays on the anchor as
   the data mirror (css hook + tests). Why a real span and not the
   heading tooltips' ::after attr() scheme: the one-line box needs its
   own element for nowrap + overflow hidden + ellipsis clip. Visibility
   is still pure CSS (:hover/:focus-visible on the reference), nothing
   runs at hover time, and the compiled jump-mark anchors in the
   notebook source stay byte-identical. On screens narrower than the
   64-char line the line is ellipsis-CLIPPED (fewer chars, still one
   line) — never wrapped — and the box cap follows the viewport (90vw).
   A geometry pass
   in custom_toc.js keeps the OPEN box on the screen (user: "what ever
   works with the screen"): the default box opens rightward from the
   anchor (left: 0); refs near the right text edge get the flip class
   below (opens leftward from the anchor's right edge); in the remaining
   narrow-viewport corner the script caps the width per element via the
   --custom-fn-maxw custom property (third term of the min() below).
   All decisions are made at build/load/resize — never at hover time.
   Without the script no spans/attributes exist and nothing renders.
   Superscripts inside the definition are rebuilt as real sup elements
   in the line (user: "I reworked the file a bit, but I noticed that the
   Footnote in 18 contain the 20 an in the tooltip the sup is missing")
   — they keep the browser's raised type, no css of its own needed. Sans
   like the prose it previews (the heading tooltip's mono is for URLs);
   visual language otherwise identical. */
.rendered_html a[href^="#fn_"][data-fn-head] {
  position: relative;
}
.rendered_html a[href^="#fn_"][data-fn-head] .custom-fn-tt {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 10;
  padding: 3px 8px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.82);
  color: #ffffff;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  /* width: max-content + the max-width cap: max-content is the full
     single-line width (the tooltip is ONE nowrap line — user: "ONE LINE
     MAX, ON THAT ONE LINE 60 CHARS MAX", since raised to 64 chars); the
     cap turns it into "as wide as the line wants, at most one
     screen-friendly width", and on
     narrower screens the ellipsis clip takes over. (Historical: with a
     wrappable tail this also prevented the collapse to a narrow tall
     column, measured firefox 80x453.) */
  width: max-content;
  /* the third min() term is the geometry pass's per-element squeeze cap
     (--custom-fn-maxw), set only in the narrow-viewport corner case;
     without it the var falls back to the 560px cap. box-sizing:
     border-box makes that cap include the 2x8px padding — measured
     defect without it: content-box sizing let every squeezed box run
     16px past its cap and the viewport's right edge. */
  box-sizing: border-box;
  max-width: min(90vw, 560px, var(--custom-fn-maxw, 560px));
  pointer-events: none;
}
/* geometry pass case 2: the reference sits too near the right text edge
   for the default rightward opening — the box opens LEFTWARD from the
   anchor's right edge instead (its right edge pins to the anchor's, and
   the script only assigns the class when the space left of the anchor's
   right edge fits the capped box, so the left edge stays on screen) */
.rendered_html a[href^="#fn_"].custom-fn-tt-flip .custom-fn-tt {
  left: auto;
  right: 0;
}
/* the ONE line — user: "I want only one line to see, even if it breaks
   correctly, I should not break/wrap at all. ONE LINE MAX, ON THAT ONE
   LINE 60 CHARS MAX", raised: "I want 63 chars now, I reworked text and
   footnote", then: "Want 64 now anyways": nowrap makes it ONE line,
   always; when a screen is ever narrower than the 64-char line, overflow
   hidden + text-overflow ellipsis CLIP it (fewer chars, still one line)
   instead of ever wrapping. A sup inside the line keeps its raised type
   (the line box grows a hair with it — still ONE line; deliberately no
   line-height reset here, which would invite the overflow clip to shave
   the raised glyphs). */
.rendered_html a[href^="#fn_"][data-fn-head] .custom-fn-tt-head {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.rendered_html a[href^="#fn_"][data-fn-head]:hover .custom-fn-tt,
.rendered_html a[href^="#fn_"][data-fn-head]:focus-visible .custom-fn-tt {
  display: block;
}
/* lab flow rhythm (measured on the reference export): p margin 0 top /
   1em bottom; lists keep the browser's 1em top, 2em indent, lose their
   bottom margin when nested; li margins 0. */
.rendered_html p {
  margin: 0 0 1em 0;
}
.rendered_html ul,
.rendered_html ol {
  margin: 1em 0;
  padding-left: 2em;
}
.rendered_html ul ul,
.rendered_html ul ol,
.rendered_html ol ul,
.rendered_html ol ol {
  margin-bottom: 0;
}
.rendered_html li {
  margin: 0;
}
.rendered_html hr {
  border: none;
  border-top: 1px solid #dddddd;
  margin: 1em 0;
}
.rendered_html blockquote {
  margin: 1em 2em;
  padding: 0 1em;
  border-left: 5px solid #e0e0e0;
}
.rendered_html img {
  max-width: 100%;
  height: auto;
}
.rendered_html svg {
  /* same cap the lab applies to rendered svg (keeps an oversized brat svg
     from widening the page — it scales down instead) */
  max-width: 100%;
  height: auto;
}
.text_cell_render > img {
  display: block;
  margin: 0 0 1em 0;
}
/* lab's last-child softening: the final block of a markdown cell (and of
   a heading run) sits closer to the cell edge. */
.text_cell_render > :last-child {
  margin-bottom: 0.5em;
}
.rendered_html h1:last-child,
.rendered_html h2:last-child,
.rendered_html h3:last-child,
.rendered_html h4:last-child,
.rendered_html h5:last-child,
.rendered_html h6:last-child {
  margin-bottom: 0.2em;
}
.rendered_html table {
  border-collapse: collapse;
  margin: 0.8em 0;
  font-size: 14px;
}
.rendered_html th,
.rendered_html td {
  border: 1px solid #d5d5d5;
  padding: 5px 9px;
  text-align: left;
  vertical-align: top;
}
.rendered_html th {
  background-color: #f2f2f2;
  font-weight: 600;
}
.rendered_html tbody tr:nth-child(even) {
  background-color: #fafafa;
}

/* ---------- darkmode palettes (P-003 R6) ----------
   Three-state scheme (owner directive): auto = the page follows
   prefers-color-scheme (the @media block below — works without any
   JavaScript), dark/light = manual override via <html data-theme="...">
   set by js/custom_theme.js, persisted per origin. The FAB and the
   color-scheme plumbing live in custom_theme.css; the code-token colors
   are a variable redefinition in custom_pygments.css. The two blocks
   below carry the SAME declarations: one keyed on the manual attribute,
   one for auto + dark system preference. Every rule above is untouched —
   light mode renders exactly as before whenever neither block matches. */

html[data-theme="dark"] body {
  background-color: #1e1e1e;
  color: rgba(255, 255, 255, 0.87);
}
html[data-theme="dark"] a { color: #6699ff; }
html[data-theme="dark"] div#notebook-container { background-color: #1e1e1e; }
html[data-theme="dark"] #custom-toc {
  border-color: #3c3c3c;
  background-color: #252526;
}
html[data-theme="dark"] div.input_area {
  border-color: #3c3c3c;
  background: #252526;
}
html[data-theme="dark"] div.prompt { color: #999999; }
html[data-theme="dark"] div.input_prompt { color: #6f9bd8; }
html[data-theme="dark"] div.output_prompt { color: #d09070; }
html[data-theme="dark"] div.output_stderr { background: rgba(255, 85, 85, 0.12); }
html[data-theme="dark"] div.output_error {
  background: rgba(255, 85, 85, 0.12);
  border-color: rgba(255, 85, 85, 0.4);
}
html[data-theme="dark"] :not(pre) > code {
  background-color: #333333;
  border-color: #4a4a4a;
}
html[data-theme="dark"] .rendered_html { color: rgba(255, 255, 255, 0.87); }
/* the two tooltip schemes invert on dark ground (dark patch + white text
   would sink into the page) */
html[data-theme="dark"] .rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link):not([href="#toc"])::after {
  background: rgba(255, 255, 255, 0.92);
  color: #111111;
}
html[data-theme="dark"] .rendered_html a[href^="#fn_"][data-fn-head] .custom-fn-tt {
  background: rgba(255, 255, 255, 0.92);
  color: #111111;
}
html[data-theme="dark"] .rendered_html hr { border-top-color: #444444; }
html[data-theme="dark"] .rendered_html blockquote { border-left-color: #444444; }
html[data-theme="dark"] .rendered_html th,
html[data-theme="dark"] .rendered_html td { border-color: #454545; }
html[data-theme="dark"] .rendered_html th { background-color: #2d2d2d; }
html[data-theme="dark"] .rendered_html tbody tr:nth-child(even) { background-color: #252526; }
/* the jump flash: darkened chip in dark (see the keyframes above) —
   only the animation-name moves; glow color and timings stay as approved */
html[data-theme="dark"] .fn-flash-word,
html[data-theme="dark"] .fn-flash-mark {
  animation-name: custom-fn-flash-dark;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) body {
    background-color: #1e1e1e;
    color: rgba(255, 255, 255, 0.87);
  }
  html:not([data-theme="light"]) a { color: #6699ff; }
  html:not([data-theme="light"]) div#notebook-container { background-color: #1e1e1e; }
  html:not([data-theme="light"]) #custom-toc {
    border-color: #3c3c3c;
    background-color: #252526;
  }
  html:not([data-theme="light"]) div.input_area {
    border-color: #3c3c3c;
    background: #252526;
  }
  html:not([data-theme="light"]) div.prompt { color: #999999; }
  html:not([data-theme="light"]) div.input_prompt { color: #6f9bd8; }
  html:not([data-theme="light"]) div.output_prompt { color: #d09070; }
  html:not([data-theme="light"]) div.output_stderr { background: rgba(255, 85, 85, 0.12); }
  html:not([data-theme="light"]) div.output_error {
    background: rgba(255, 85, 85, 0.12);
    border-color: rgba(255, 85, 85, 0.4);
  }
  html:not([data-theme="light"]) :not(pre) > code {
    background-color: #333333;
    border-color: #4a4a4a;
  }
  html:not([data-theme="light"]) .rendered_html { color: rgba(255, 255, 255, 0.87); }
  html:not([data-theme="light"]) .rendered_html :is(h1, h2, h3, h4, h5, h6) a:not(.anchor-link):not([href="#toc"])::after {
    background: rgba(255, 255, 255, 0.92);
    color: #111111;
  }
  html:not([data-theme="light"]) .rendered_html a[href^="#fn_"][data-fn-head] .custom-fn-tt {
    background: rgba(255, 255, 255, 0.92);
    color: #111111;
  }
  html:not([data-theme="light"]) .rendered_html hr { border-top-color: #444444; }
  html:not([data-theme="light"]) .rendered_html blockquote { border-left-color: #444444; }
  html:not([data-theme="light"]) .rendered_html th,
  html:not([data-theme="light"]) .rendered_html td { border-color: #454545; }
  html:not([data-theme="light"]) .rendered_html th { background-color: #2d2d2d; }
  html:not([data-theme="light"]) .rendered_html tbody tr:nth-child(even) { background-color: #252526; }
  /* same flash swap as the manual block above (auto + dark system) */
  html:not([data-theme="light"]) .fn-flash-word,
  html:not([data-theme="light"]) .fn-flash-mark {
    animation-name: custom-fn-flash-dark;
  }
}

/* ---------- end of custom_base.css — put your own rules in custom.css ---------- */
