/* Science — shared styles.
 *
 * One stylesheet for every page. **The page is dark and blue-toned, always.**
 * There is one set of tokens, declared once on :root, and they are the only
 * values any page surface ever takes. There is no light variant, no
 * `prefers-color-scheme` branch and no toggle.
 *
 * Two things about that, because both are decisions rather than defaults.
 *
 * **Why one theme and not two.** A second theme is only correct if *every*
 * token is redefined with it. A token defined inside a media query but read
 * outside one renders one theme's text on the other theme's ground, and this
 * file has been in that state before. Half a theme is worse than none, so
 * there is one, completely, and the contrast numbers below are a full audit
 * of it rather than a sample of one half.
 *
 * **Why blue.** The code ground is `--code-bg`, `#0b0f1a`, a blue-black
 * chosen when "Science Neon" was built, and the palette was designed to sit
 * on it. The page ground used to be a teal-black with a cyan accent, which
 * put the loudest thing on the page in the same hue family as `--c-type`,
 * so a link and a type name competed. A slate-navy page in the same family
 * as the listings harmonises instead, and the accent moves out of the code
 * palette's way: `--accent` is a desaturated periwinkle at 219°, where
 * `--c-type` is an electric cyan at 190°, and the two never share a ground.
 *
 * **The two grounds were swapped, and the listing is now the raised one.**
 * The page is a near-black grey and `--code-bg` is the violet the page itself
 * held an hour ago, so a listing reads as a panel **laid on** the page rather
 * than inset into it — an editor pane on a desktop, which is the other
 * convention and the one asked for here.
 *
 * `--code-bg` sits **1.22:1 above `--paper`**, and that is tighter than the
 * 1.29:1 the inset arrangement had. It is tight for a reason worth stating
 * rather than hiding: a ground light enough to carry the syntax palette is
 * fairly high on the ramp, so a *grey* page has to go nearly to black before
 * it separates at all, and past about #141416 there is nothing left to
 * spend. **`--code-frame` therefore does more work here than it did before**,
 * and it was lifted to #3f4670 — 2.03:1 against the page and 1.66:1 against
 * the listing — because at this separation the boundary does not survive
 * with the border removed, where under the old arrangement it did.
 *
 * **The syntax palette had to move for the first time, by one colour.** Every
 * one of its ten hues is measured against `--code-bg`, and lifting that
 * ground from a near-black to a mid tone cost each of them about a fifth of
 * its contrast. Nine survived; `--c-com`, already the tightest at 4.84:1,
 * fell below the floor and is now `#8d98ba` at 5.25:1 — **the same grey-blue
 * family it always was, lifted rather than re-hued**, because the ground it
 * sits on is blue again. `--c-pun` was lifted with it. The tightest pairing
 * in a listing is now `--c-key` at 4.62:1, which is the number to watch if
 * this ground is ever lightened further.
 *
 * **Three legible levels.** `--surface` (a card, a chip inside a callout) is
 * 1.51:1 above the page and `--sunk` (an inline `code` chip) is 1.99:1 above
 * it. Both now sit *between* the page and the listing rather than on the far
 * side of it, which is the one thing the swap costs: under the old
 * arrangement an inline chip could not be mistaken for a fragment of a block
 * because it was on the opposite side of the page's tone. Here it is told
 * apart by hue — the chips are neutral grey and the listing is violet — and
 * that is a weaker signal than a tonal one, so `--sunk` is kept deliberately
 * grey rather than tinted toward the code ground.
 *
 * **Nothing outside a code block is decorated.** No gradient, no glow, no
 * animation. Dark is not a licence to be loud: the rails are flat 3px tabs,
 * the rules are hairlines, and the only saturated colour on the page is
 * inside a `pre`.
 */
:root {
  /* The page. A neutral grey ramp: --paper is the ground, --surface is a
   * card, --sunk is an inline code chip, --rule is a hairline.
   *
   * **The page and the listing traded places.** The ground was a slate navy,
   * then a violet charcoal; it is a near-black grey now, and the violet it
   * used to be is the *listing's* ground, taken back toward blue. So the violet did not leave the
   * page so much as move behind the code, which is where the argument for
   * choosing it applies most: the syntax palette's three loudest hues are a
   * pink, a purple and a cyan, and they sit on a violet as one decision where
   * on a neutral ground they sit as an accident.
   *
   * On --paper: --ink 15.73:1, --muted 10.11:1, --faint 8.05:1, --accent
   * 8.74:1, --old 9.21:1. Every one is higher than it was, because the ground
   * went nearly to black and none of the foregrounds moved.
   *
   * **--accent is a green, and the constraint it has to clear is the syntax
   * palette rather than the page.** The listing's ground is a blue-violet, so
   * an accent near blue or cyan competes with --c-type across the boundary,
   * and the lilac it used to be sat in the listing's own hue family. A green
   * is outside both.
   *
   * The collision it *could* have had is --c-fn, the function green. They are
   * separated deliberately and on two axes: 132° against 151°, and 48%
   * saturation against 76%. Same family, and no reader will mistake a link
   * for a call — which is the test, since the two appear within a line of
   * each other whenever prose names a function.
   *
   * It is 10.19:1 on the page. The brief was "a little neon, barely" and that
   * is what the saturation figure is: the full-neon version of this hue is
   * already in the palette and is the thing to stay away from.
   *
   * Darkening the page walks it toward the listing, and near black the
   * luminance differences compress, so there is no ground below about
   * #1a2233 that keeps a listing visible as a separate surface at all. This
   * is the darkest ground on that ramp that still reads as two surfaces.
   *
   * --code-frame was lifted with it, from #1b2440, which had fallen to
   * 1.03:1 against the new ground — an invisible border, and the border is
   * half of what separates a block from the page once the fills are this
   * close. It is 1.33:1 against the page and 1.72:1 against the listing now,
   * so it reads from both sides.
   *
   * The tightest foreground that carries navigation is --faint on --paper at
   * 7.01:1 — the sidebar's group headings, checked rather than assumed
   * because it is the pairing that failed the last time this palette moved. */
  --paper:#141416; --surface:#212125; --sunk:#2a2a2f; --ink:#f0f0f3;
  --muted:#c2c2ca; --faint:#adadb8; --rule:#37373e;
  --accent:#6fd684; --accent-soft:#1b2a20; --old:#e7ad96; --old-soft:#3a2b24;
  /* Reserved, and read by nothing today. These three have never been read by
   * a rule in this file; they are re-toned with the rest rather than left as
   * the old teal, so that a future rule reaching for one gets a colour that
   * belongs to this palette. */
  --deep:#0e0e10; --deep-ink:#f0f0f3; --deep-rule:#141416;
  /* Syntax — "Science Neon". Declared once and never redefined, because
   * every code surface on this site is dark whatever the page does. That is
   * the decision that makes the palette possible: a neon hue survives on
   * #0b0f1a and dies on paper, and a palette asked to do both ends up
   * doing neither. The editor's light theme is the one place a readable
   * variant is needed, and it lives in editors/vscode/.
   *
   * Not one value here moved when the page went blue, and that is the point
   * of having declared them once: the listing's ground is fixed, so the
   * listing's colours are fixed, and re-toning the page could not reach
   * them. Every value below is measured against --code-bg and clears 4.5:1
   * there; the tightest is --c-com at 4.84. */
  --code-bg:#1f2540; --code-ink:#dfe4f2; --code-frame:#3f4670;
  --c-key:#e85aa8; --c-ctl:#e85aa8; --c-type:#4de8ff; --c-fn:#3dfca0;
  --c-str:#f6ff6b; --c-num:#c77dff; --c-par:#ffa23c; --c-op:#e85aa8;
  --c-com:#8d98ba; --c-res:#ff6e6e; --c-pun:#9ba6c4;
  /* The block rail, kept separate from the syntax palette above on purpose:
   * these five paint a flat 3px tab on the left of a `pre`, never a gradient,
   * so the block kinds stay tellable apart without competing with the tokens
   * inside them. Declared once, like the rest of the code chrome.
   *
   * The rail is decoration, not information: a removed-syntax block is also
   * captioned and struck through, and a shell block also carries its `$`.
   * Nothing on this site is told apart by rail colour alone, which is why
   * these five are allowed to sit between 2.4:1 and 3.2:1 against the
   * listing behind them.
   *
   * **Two of them were lifted when the listing's ground was.** `--rail-code`
   * and `--rail-legacy` were the two nearest the old near-black, and against
   * the mid-tone ground they fell to 1.86:1 and 2.00:1 — below the range this
   * paragraph states, which is the sort of thing that goes unnoticed because
   * nothing *fails*, the tab simply stops being visible. They are #5470a8 and
   * #697489 now, at 3.05:1 and 3.19:1, and the range above is a claim this
   * file is checked against rather than a description of what happened to be
   * true once. */
  --rail-code:#5470a8; --rail-shell:#2f6b52; --rail-err:#a34848; --rail-legacy:#697489;
  /* A fifth, for a listing in *another* language. `rationale.html` sets the
   * same program side by side in Python, Rust, Go, Java and JavaScript, and
   * those blocks were rendering with no rail at all — so they read as "not
   * Science" by *absence*, which looks like a gap rather than a decision.
   *
   * It is a violet and not the grey, though grey is the obvious neutral: grey
   * is already --rail-legacy, and that one means "syntax this language
   * removed". A reader who has learned one grey rail as "do not write this"
   * would meet a second grey rail on a correct Python program. The note above
   * says nothing here is told apart by rail colour alone — true, and the
   * cost of a collision is still a reader re-reading a caption to find out
   * which kind of not-Science they are looking at. */
  --rail-foreign:#6b5a8a;
  /* Layout, not colour. The masthead is `position: sticky` at `top: 0`, so
   * every other sticky thing on the page and every anchor jump has to clear
   * it. It was cleared by nothing: the sidebar stuck at 1.5rem and a section
   * jumped to 1.5rem, both of which land *under* a 77px bar. One number,
   * declared here and overridden once at the width where the bar gets
   * shorter, so the two readers of it cannot drift apart. */
  --top-h: 4.85rem;
  --sans:"IBM Plex Sans",ui-sans-serif,system-ui,sans-serif;
  --serif:"IBM Plex Serif",Georgia,"Times New Roman",serif;
  --mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
}
/* There was a `@media (prefers-color-scheme: dark)` block and a
 * `[data-theme="dark"]` block here, each redefining thirteen of the tokens
 * above for a second theme. Both are gone: the values they held are now the
 * values on :root, re-toned to blue, and there is no second set. Nothing
 * sets `data-theme`, so the attribute selector would match nothing even if
 * it had stayed. Thirty-odd rules in this file read `--paper`, `--surface`,
 * `--sunk`, `--rule`, `--ink`, `--muted`, `--faint`, `--accent` and `--old`;
 * every one of them has exactly one value to read, on every machine.
 *
 * `color-scheme` is declared dark so the browser's own chrome agrees — the
 * scrollbar, form controls, and the frame the browser paints before this
 * stylesheet lands. Without it a reader gets a white scrollbar beside a navy
 * page and a white flash on first paint, which is the half-flipped result
 * this file exists to avoid. */
:root { color-scheme: dark; }

* { box-sizing: border-box; }
body { background: var(--paper); color: var(--ink); font-family: var(--sans);
  font-size: 16px; line-height: 1.6; margin: 0; -webkit-text-size-adjust: 100%; }

/* The side gutter. 20px on a laptop, 16px once the viewport is narrow enough
 * that twenty is a measurable fraction of the line. Declared as a rule rather
 * than left to the 20px, because at 320px a pair of 20px gutters is an eighth
 * of the screen. */
/* `padding-inline`, never the `padding` shorthand: the shorthand would let a
 * later rule that only meant to set a vertical value zero the sides, and a
 * zeroed side gutter is the single failure this whole file is guarding
 * against. Vertical padding on a page section is set with `padding-block`
 * everywhere below for the same reason.
 *
 * `max()` against the safe-area insets because the pages ask for
 * `viewport-fit=cover`: on a notched phone held sideways the inset is ~44px
 * and a flat 16px would put the first character under the camera cutout.
 * `max()` means the gutter is *at least* 16px at every width and grows only
 * where the hardware takes the space. */
.wrap { max-width: 62rem; margin: 0 auto;
  padding-inline: max(20px, env(safe-area-inset-left, 0px))
                  max(20px, env(safe-area-inset-right, 0px)); }
@media (max-width: 30rem) {
  .wrap { padding-inline: max(16px, env(safe-area-inset-left, 0px))
                          max(16px, env(safe-area-inset-right, 0px)); }
}

/* The documentation runs wider than the landing page, because it has a
 * sidebar and the landing page does not. At 62rem a 15rem sidebar and its
 * gutter left the code column 43rem, which is narrower than the listings in
 * it — so every example scrolled sideways inside its own box. Prose does not
 * widen with it: `p` is capped at 44rem regardless, so the extra width goes
 * to the code and the tables, which are the things that wanted it. */
.wrap.wide { max-width: 84rem; }

/* Anything that legitimately exceeds its column scrolls inside its own box
 * rather than taking the page with it. This class was already on two tables
 * in the reference and had no rule behind it at all, which is exactly the
 * horizontal scroll it was named to prevent. */
.scroller { overflow-x: auto; margin: 0 0 1.5rem; }
.scroller > table { margin-bottom: 0; }

/* Tables had no styling whatsoever: browser defaults, collapsed to content
 * width, with no rule between rows. */
table { width: 100%; border-collapse: collapse; margin: 0 0 1.5rem;
  font-size: 0.92rem; }
th, td { text-align: left; padding: 0.5rem 1rem 0.5rem 0;
  border-bottom: 1px solid var(--rule); vertical-align: baseline; }
th { font-family: var(--mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--faint);
  border-bottom-color: var(--ink); white-space: nowrap; }
tbody tr:last-child td { border-bottom: none; }

/* ---- top bar ---- */
/* The masthead stays put. Every language's documentation does this, for the
 * sidebar's reason: a reference is navigated, and a way back to the index that
 * has scrolled off the top is not a way back.
 *
 * Sticky on `.top` itself rather than on a full-bleed wrapper, because the two
 * pages nest their headers differently and one CSS rule that works on both
 * beats an HTML change to each. The rule under it therefore runs to the
 * content width, which reads as deliberate.
 *
 * Opaque, not blurred: a translucent bar over a listing in this palette smears
 * the text behind it, and at 3rem tall there is nothing to see through. */
.top { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 20;
  background: var(--paper);
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding-block: 1.5rem; flex-wrap: wrap; }
.mark { display: flex; align-items: baseline; gap: 0.55rem; }
.mark .glyph { font-family: var(--mono); font-size: 1.15rem; font-weight: 600;
  color: var(--accent); letter-spacing: -0.04em; }
.mark .name { font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink); font-weight: 500; }
.top nav { display: flex; gap: 1.4rem; flex-wrap: wrap; }
.top nav a { font-family: var(--mono); font-size: 0.76rem; color: var(--muted);
  text-decoration: none; }
.top nav a:hover, .top nav a:focus-visible { color: var(--accent); }

/* ---- hero ---- */
.hero { padding-block: 3rem 3.5rem; border-bottom: 1px solid var(--rule); }
h1 { font-size: clamp(2.5rem, 6.8vw, 4rem); font-weight: 600; letter-spacing: -0.035em;
  line-height: 1.03; margin: 0 0 1.4rem; text-wrap: balance; max-width: 22ch; }
h1 em { font-style: normal; color: var(--accent); }
.deck { font-family: var(--serif); font-size: 1.15rem; line-height: 1.55;
  color: var(--muted); max-width: 44rem; margin: 0 0 2.25rem; }
.deck strong { color: var(--ink); font-weight: 500; }

.install { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
/* `min-width: 0` because a flex item's automatic minimum is its content's
 * min-content width, and a listing's min-content width is its longest line.
 * The `overflow-x: auto` on `pre` already zeroes it in every browser that
 * implements that carve-out; this says so rather than relying on it. */
.install pre { margin: 0; flex: 1 1 22rem; min-width: 0; }
.btn { font-family: var(--mono); font-size: 0.82rem; text-decoration: none;
  padding: 0.7em 1.2em; border-radius: 3px; border: 1px solid var(--accent);
  background: var(--accent); color: var(--paper); white-space: nowrap; }
.btn.ghost { background: none; color: var(--accent); }
.btn:hover, .btn:focus-visible { opacity: 0.85; }

/* ---- sections ---- */
section { padding-block: 4rem; border-bottom: 1px solid var(--rule); }
section:last-of-type { border-bottom: none; }
h2 { font-size: 1.7rem; font-weight: 600; letter-spacing: -0.022em; margin: 0 0 0.5rem; }
/* `h1` asks for this on its own line already. The other two headings want it
 * for the same reason and want it most at 360px, where a 1.7rem heading is
 * three words a line and an unbalanced break leaves one word alone on the
 * last. `pretty` on running text is the cheaper cousin: it only fixes the
 * last line, which is the orphan a narrow column produces constantly. */
h2, h3 { text-wrap: balance; }
p, .deck, .lede, .standfirst, .doc .sub, .strip dd, .bet p { text-wrap: pretty; }
.lede { font-family: var(--serif); color: var(--muted); max-width: 44rem; margin: 0 0 2rem; font-size: 1.02rem; }
h3 { font-family: var(--mono); font-size: 0.76rem; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted); margin: 2.25rem 0 0.75rem; }
p { max-width: 44rem; }
p.note { font-family: var(--serif); font-size: 0.95rem; color: var(--muted); margin: 0.85rem 0 0; }
/* Links inside prose. The site's other links all live in a nav, a card or the
 * footer and are styled there; these are the first in running text, and
 * without a rule they would render in the browser's default blue on paper. */
p a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
p a:hover, p a:focus-visible { text-decoration: none; }

/* ---- code ---- */
/* The listing is darker than the page, not lighter, and that is what makes it
 * read as inset rather than as a panel laid on top. `--code-bg` and the ten
 * syntax tokens are declared once on :root and read here; nothing redefines
 * them, so there is nothing that could flip half of them. */
pre { position: relative; font-family: var(--mono); font-size: 0.83rem; line-height: 1.7;
  background: var(--code-bg); color: var(--code-ink);
  border: 1px solid var(--code-frame); border-left: 0; border-radius: 0 3px 3px 0;
  padding: 1.1rem 1.25rem; margin: 0 0 1.25rem; overflow-x: auto; tab-size: 4; }

/* The left rail is the one piece of ornament, and it is deliberately quiet:
 * a single flat 3px bar per block kind, never a gradient. A gradient rail reads
 * as decoration competing with the listing; a flat one reads as a tab colour,
 * which is what a reference manual uses. Painted as a background layer rather
 * than a border so it runs down the block's full height however tall it
 * grows. The hue still tells the block kinds apart — this one for Science
 * source — but none of them glow or shift. */
/* No shadow. There was a `0 1px 2px rgba(0,0,0,0.30)` here, and on a page
 * this dark it is a black shadow on a near-black ground: it renders nothing
 * and costs a composited layer. The block is separated from the page by
 * being darker than it and by `--code-frame`, which are the two things that
 * actually do the work. */
/* **The rail is a one-stop gradient, and it has to be.** It was written
 * `background: var(--rail-code) left / 3px 100% no-repeat, var(--code-bg)`,
 * and that put a *colour* in a non-final background layer, which only the
 * last layer may carry. Every block on the site lost its ground.
 *
 * The reason it was not caught by reading the rule is worth keeping, because
 * it is the opposite of what a reader expects. An invalid value written
 * literally is a parse error: the declaration is thrown away and the earlier
 * `pre { background: var(--code-bg) }` still applies, so the block keeps its
 * ground and merely loses its rail. An invalid value produced by `var()` is
 * not — substitution happens at computed-value time, far past parsing, so the
 * declaration *wins the cascade* and then computes to the property's initial
 * value. For `background` that is `transparent`. The rule that looked like it
 * added a rail was removing the ground instead, and it did so only because the
 * colour arrived through a variable.
 *
 * `linear-gradient(C, C)` is an image, so it is legal in any layer, and a
 * two-stop gradient between one colour and itself is flat — which is what the
 * note above demands. The cost is one gratuitous-looking gradient per block
 * kind; the alternative is a fifth pair of variables holding the same four
 * colours pre-wrapped. */
pre[data-science] {
  background:
    linear-gradient(var(--rail-code), var(--rail-code)) left / 3px 100% no-repeat,
    var(--code-bg);
}
/* A block kept only for comparison: the syntax it shows has been removed from
 * the language. Marked three ways at once — a caption above it, a grey rail
 * instead of the live one, and a strike through the words that no longer
 * exist — because a reader skimming will miss any one of them on its own, and
 * mistaking a removed form for a live one is the expensive mistake here. No
 * new palette entry: the rail and the strike both reuse the comment grey,
 * which already means "not the code". */
/* This rule used to carry `box-shadow: none` to cancel the shadow the live
 * block had. The live block no longer has one, so the cancellation named a
 * property nothing sets, and it is gone with it. */
pre[data-science][data-legacy] {
  background:
    linear-gradient(var(--rail-legacy), var(--rail-legacy)) left / 3px 100% no-repeat,
    var(--code-bg);
}
.rm { color: var(--c-com); text-decoration: line-through; }
.legend { font-family: var(--mono); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--old); margin: 0 0 0.5rem; }

pre.shell {
  background:
    linear-gradient(var(--rail-shell), var(--rail-shell)) left / 3px 100% no-repeat,
    var(--code-bg);
}
pre.shell .p { color: #7080a4; } pre.shell .c { color: #3dfca0; }
pre.err {
  background:
    linear-gradient(var(--rail-err), var(--rail-err)) left / 3px 100% no-repeat,
    var(--code-bg);
}
/* A listing in another language. Same ground and same frame as a Science
 * block, because the point of the comparison is that the two are read
 * together — a foreign block on a different ground would be a different
 * *kind* of thing on the page, when it is the same kind carrying a different
 * language. Only the rail differs, and `rationale.html` names the language in
 * the caption above each one, so the rail is the second signal and never the
 * only one. */
pre.foreign {
  background:
    linear-gradient(var(--rail-foreign), var(--rail-foreign)) left / 3px 100% no-repeat,
    var(--code-bg);
}
/* The copy button. Appears on hover and on keyboard focus, sits inside the
 * block's padding so it never covers the first line, and reports what it did
 * in words rather than an animation. */
.copy { position: absolute; top: 0.55rem; right: 0.55rem; z-index: 1;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--code-ink); background: var(--code-bg);
  border: 1px solid var(--code-frame); border-radius: 3px;
  padding: 0.25rem 0.5rem; cursor: pointer; opacity: 0; transition: opacity 0.12s;
  /* **The block scrolls and the button used to go with it.** `position:
   * absolute` inside an `overflow-x: auto` box is positioned against the
   * padding box's *scroll* origin, so on a phone — where nearly every listing
   * on this site is wider than the screen — the first sideways swipe carried
   * the button off the left edge and it could not be got back without
   * scrolling home. `--scroll-x` is set by `assets/highlight.js` on the
   * block's scroll event and the button cancels it out, so the button is
   * pinned to the *visible* top-right corner at any scroll offset.
   *
   * On the `translate` property rather than inside `transform`, because
   * `transform` is transitioned below with everything else on the site and a
   * 140ms ease on a value that changes every scroll frame is a button that
   * swims. `translate` composes with `transform` and is not transitioned. */
  translate: var(--scroll-x, 0px) 0; }
pre:hover .copy, .copy:focus-visible { opacity: 1; }
.copy:hover { border-color: var(--c-type); color: var(--c-type); }
.copy[data-done] { opacity: 1; border-color: var(--c-fn); color: var(--c-fn); }
@media (prefers-reduced-motion: reduce) { .copy { transition: none; } }
/* No hover to reveal it on a touch screen, so it is always there. */
@media (hover: none) { .copy { opacity: 1; } }

code { font-family: var(--mono); font-size: 0.87em; background: var(--sunk);
  padding: 0.1em 0.35em; border-radius: 2px;
  /* An inline chip is usually one identifier and an identifier has no break
   * opportunity in it, so at 360px a chip like `ScienceCompilerOptions` is
   * wider than the column it sits in and hangs out of the callout that holds
   * it. `anywhere` rather than `break-word` because only `anywhere` lowers
   * the element's *min-content* width, which is what a grid track and a flex
   * item measure — `break-word` would still let a chip force a column wide.
   * It breaks nothing that fits: the rule only applies where a line would
   * otherwise overflow. */
  overflow-wrap: anywhere; }
/* A listing is `white-space: pre` and has a scroller of its own; it scrolls
 * rather than wrapping, and that is the whole contract of a code block. */
pre code { background: none; padding: 0; font-size: 1em; overflow-wrap: normal; }
.k  { color: var(--c-key); font-weight: 500; }   /* declaration keyword */
.kc { color: var(--c-ctl); font-weight: 500; }   /* control flow */
.t  { color: var(--c-type); }                    /* type, by capitalisation */
.f  { color: var(--c-fn); }                      /* name followed by `(` */
.s  { color: var(--c-str); }
.n  { color: var(--c-num); }
.pa { color: var(--c-par); font-style: italic; } /* label or field name */
.o  { color: var(--c-op); }
.pu { color: var(--c-pun); }
.r  { color: var(--c-res); text-decoration: underline dotted; }
                                                 /* reserved for a later phase:
                                                    marked structurally, since no
                                                    spare hue reads as "not yet" */
.cm { color: var(--c-com); font-style: italic; }

/* No glow on the code. The palette went through three versions before this
 * one and the glow was the last thing left over from the first: a hue this
 * saturated on a ground this dark is already emissive, and a shadow under it
 * only softens the glyph edges, which is the opposite of what a listing wants.
 * The identity now lives in the rail and in the palette, not in a blur. */
/* A `pre[data-science][data-legacy] span { text-shadow: none }` stood here,
 * cancelling that glow on the removed-syntax block in particular. It named a
 * property no rule in this file sets any more, which is the same dead-weight
 * a half-removed theme leaves behind, so it is gone with the glow. */
.e-code { color: #ff6e6e; font-weight: 600; } .e-hi { color: #ff6e6e; }
/* Pale, not neon: a `help:` line is prose about the fix, not a token, so it
 * does not need the cyan that marks a type in the listing above it. */
.e-help { color: #8ab4c9; }

/* ---- the three bets ---- */
.bets { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 2rem 2.5rem; margin-top: 2rem; }
.bet h3 { margin-top: 0; color: var(--accent); }
.bet p { font-family: var(--serif); font-size: 0.96rem; color: var(--muted); margin: 0; }

/* ---- feature strip ---- */
.strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(13.5rem, 100%), 1fr));
  gap: 1.75rem; margin-top: 1.75rem; }
.strip div { border-top: 2px solid var(--rule); padding-top: 0.8rem; }
.strip dt { font-family: var(--mono); font-size: 0.78rem; color: var(--ink);
  font-weight: 600; margin-bottom: 0.35rem; }
.strip dd { font-family: var(--serif); font-size: 0.92rem; color: var(--muted); margin: 0; }

/* ---- two-up ---- */
.two { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); gap: 1.5rem; }
.two h3 { margin-top: 0; }

/* ---- docs cards ---- */
.docs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 1rem; margin-top: 1.5rem; }
.doc { display: block; border: 1px solid var(--rule); border-radius: 3px;
  padding: 1.05rem 1.2rem; text-decoration: none; background: var(--surface); }
.doc:hover, .doc:focus-visible { border-color: var(--accent); }
.doc .ttl { font-family: var(--mono); font-size: 0.8rem; color: var(--accent);
  font-weight: 500; display: block; margin-bottom: 0.3rem; }
.doc .sub { font-family: var(--serif); font-size: 0.89rem; color: var(--muted); }

footer { padding-block: 2.5rem 4rem; font-family: var(--serif);
  font-size: 0.9rem; color: var(--muted); border-top: 1px solid var(--rule); }
footer code { font-size: 0.82em; }
footer .links { display: flex; gap: 1.4rem; flex-wrap: wrap; margin-bottom: 1rem; }
footer .links a { font-family: var(--mono); font-size: 0.78rem; color: var(--accent); text-decoration: none; }

/* The considered `prefers-reduced-motion` block is at the foot of this file.
 * A blanket `animation: none` used to sit here, which contradicted it: that
 * block uses `1ms` rather than `none` because the `both` fill modes are
 * load-bearing, and `animation-name: none` would have stripped them first. */

/* --- reference-only ------------------------------------------------------ */
.masthead { padding-block: 3.5rem 2rem; position: relative; }
.eyebrow { font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0 0 1rem; }
.standfirst { font-family: var(--serif); font-size: 1.1rem; line-height: 1.55;
  color: var(--muted); max-width: 40rem; margin: 0; }
.standfirst strong { color: var(--ink); font-weight: 500; }
.status { display: flex; flex-wrap: wrap; gap: 0.5rem 1.75rem; padding-block: 1.25rem;
  border-bottom: 1px solid var(--rule); font-family: var(--mono); font-size: 0.78rem; color: var(--muted); }
.status b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.status .dot { display: inline-block; width: 0.5em; height: 0.5em; border-radius: 50%;
  margin-right: 0.45em; vertical-align: 0.05em; }
.dot-on { background: var(--accent); } .dot-wip { background: var(--old); }
.revision { border: 1px solid var(--old); border-left: 3px solid var(--old);
  border-radius: 0 3px 3px 0; background: var(--old-soft); padding: 1rem 1.25rem; margin-block: 2rem 0; }
.revision h2 { font-family: var(--mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--old); margin: 0 0 0.5rem; display: block; }
.revision p { font-family: var(--serif); font-size: 0.95rem; color: var(--ink); margin: 0; max-width: none; }
.revision code { background: var(--surface); }
.cite { font-family: var(--mono); font-size: 0.72rem; font-weight: 400; letter-spacing: 0.04em;
  color: var(--accent); background: var(--accent-soft); padding: 0.15em 0.5em; border-radius: 2px; }
.cite.wip { color: var(--old); background: var(--old-soft); }
.ladder { list-style: none; margin: 0 0 1.25rem; padding: 0; }
.ladder li { display: flex; align-items: baseline; gap: 1rem; padding: 0.4rem 0; border-bottom: 1px solid var(--rule); }
.ladder li:last-child { border-bottom: none; }
.ladder .rung { font-family: var(--mono); font-size: 0.68rem; color: var(--faint);
  width: 1.5rem; flex: none; font-variant-numeric: tabular-nums; }
.ladder .ops { font-family: var(--mono); font-size: 0.85rem; color: var(--ink); }
.ladder .gloss { font-family: var(--serif); font-size: 0.88rem; color: var(--muted);
  margin-left: auto; text-align: right; }
.bank { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0 0 1rem; padding: 0; list-style: none; }
.bank li { font-family: var(--mono); font-size: 0.76rem; padding: 0.2em 0.5em;
  border-radius: 2px; background: var(--accent-soft); color: var(--accent); }
.bank.later li { background: var(--old-soft); color: var(--old); }
.bank.never li { background: var(--sunk); color: var(--muted); }
.callout { border: 1px solid var(--old); border-left: 3px solid var(--old);
  border-radius: 0 3px 3px 0; background: var(--old-soft); padding: 1rem 1.25rem; margin: 0 0 1.5rem; }
.callout h3 { margin: 0 0 0.5rem; color: var(--old); }
.callout p { font-family: var(--serif); font-size: 0.95rem; color: var(--ink); margin: 0; max-width: none; }
.callout code { background: var(--surface); }
/* --- the docs layout ----------------------------------------------------
 *
 * A sticky sidebar beside the prose, which is what every language's
 * documentation settled on and for a reason worth stating: a reference is
 * read by jumping, not by scrolling, and a table of contents that scrolls
 * away is a table of contents you have to scroll back to find.
 *
 * It is one grid declaration and a `position: sticky`. The horizontal strip
 * this replaced needed `overflow-x` and `white-space: nowrap` and still cut
 * the last four sections off the right edge at laptop width. */
.docs { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 0 3.5rem;
  align-items: start; }
.docs > main { min-width: 0; }
/* **`.docs` is two different components sharing one class name.** The landing
 * page uses it for a row of cards; a documentation page uses it for the
 * sidebar-and-prose layout above. The layout rule is further down the file,
 * so it was winning on the landing page too and rendering four cards into a
 * fixed 15rem column and a remainder.
 *
 * Told apart by what is inside rather than by a second class, because the
 * markup belongs to pages this file does not own. If `:has()` is missing the
 * rule is dropped and the landing page falls back to exactly what it renders
 * today, so the failure mode is the current behaviour rather than a new one. */
.docs:has(> .doc) {
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 1rem; align-items: stretch;
}

.sidebar { position: sticky;
  top: calc(env(safe-area-inset-top, 0px) + var(--top-h) + 1rem);
  max-height: calc(100vh - var(--top-h) - 2.5rem);
  overflow-y: auto; overscroll-behavior: contain;
  padding-block: 0.5rem 2rem; }
.sidebar h2 { font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  margin: 1.75rem 0 0.6rem; }
.sidebar h2:first-child { margin-top: 0; }
.sidebar ul { list-style: none; margin: 0; padding: 0; }
.sidebar a { display: block; font-size: 0.87rem; color: var(--muted);
  text-decoration: none; padding: 0.3rem 0 0.3rem 0.85rem; line-height: 1.35;
  border-left: 2px solid var(--rule); }
.sidebar a:hover, .sidebar a:focus-visible { color: var(--accent);
  border-left-color: var(--accent); background: var(--accent-soft); }
/* :target styles the section the URL names, so the sidebar shows where you
 * are without a scroll listener. It is the whole of the "active link"
 * behaviour a framework would ship a hook for. */
.sidebar a.here { color: var(--ink); border-left-color: var(--accent); }

.reference section { border-bottom: none; padding-block: 0 3.5rem;
  scroll-margin-top: calc(var(--top-h) + 1rem); }
/* **Scoped to a section's own heading, and it has to be.** This was
 * `.reference h2`, and `.reference` is on the wrapper around *everything* on
 * a documentation page — the sidebar and the revision note included. At
 * (0,1,1) it ties with `.sidebar h2` and `.revision h2` and, being further
 * down the file, won both: the sidebar's group labels were rendering at 24px
 * as flex containers instead of at 0.68rem as micro-labels, which is most of
 * why the sidebar was three screenfuls tall on a phone, and the revision
 * note's heading was doing the same. `.revision h2` already carried an
 * explicit `display: block` — a cancellation of this rule, written without
 * the cause being found. Every section on every page carries its h2 as a
 * direct child, so this selector reaches exactly what the rule was for. */
.reference section > h2 { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; font-size: 1.5rem; }

/* An anchor beside every section heading, the way every docs site does it:
 * visible on hover, always reachable by keyboard, and a real link so it can
 * be copied from the context menu. */
.reference section > h2 .anchor { font-family: var(--mono); font-size: 0.85rem; font-weight: 400;
  color: var(--faint); text-decoration: none; opacity: 0; transition: opacity 0.12s; }
.reference section > h2:hover .anchor,
.reference section > h2 .anchor:focus-visible { opacity: 1; }
.reference section > h2 .anchor:hover { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .reference section > h2 .anchor { transition: none; }
}

/* ===================================================================== *
 * Narrow widths
 *
 * Three breakpoints, in one place, largest first, each with one job. They
 * were not in one place before: a `60rem` block sat here and a `30rem` block
 * sat up beside `.wrap`, and between them they had never been checked at a
 * real phone width. The numbers below were measured at 360, 390, 414, 768
 * and 1024.
 *
 *   60rem (960px) - the two-column documentation layout stops fitting.
 *                   The sidebar stops being a column.
 *   48rem (768px) - the masthead's row stops fitting. Touch is assumed
 *                   from here down for anything that is only a hit area.
 *   30rem (480px) - a phone. The gutter narrows and the vertical rhythm,
 *                   which was set for a laptop, is pulled in.
 *
 * Nothing below changes a colour token, a syntax colour, or the resting
 * state of any animation.
 * ===================================================================== */

@media (max-width: 60rem) {
  .docs { display: block; }

  /* **The sidebar becomes a bounded, scrolling block - it does not vanish.**
   * Stacked and unbounded it was measured at 1078px on `syntax.html` at
   * 360px wide: three screenfuls of table of contents standing between the
   * reader and the first sentence of the page, which is worse than no table
   * of contents at all. Bounded, it is one screenful at most and the page
   * starts where the reader expects.
   *
   * Scrolling rather than collapsing because collapsing wants a disclosure
   * control, a control wants an element to hang off, and the markup of these
   * pages is not this file's to change. A bounded scroller needs nothing but
   * a height - and, unlike a collapsed one, it still shows the reader that a
   * contents list exists and roughly how long it is.
   *
   * `min(24rem, 55vh)`: the viewport share keeps it to about half a short
   * phone, and the absolute cap stops it eating a tablet's whole first
   * screen just because the tablet is tall. */
  .sidebar {
    position: static;
    max-height: min(24rem, 55vh);
    overflow-y: auto; overscroll-behavior: contain;
    margin-bottom: 2.5rem;
    padding-block: 0 0.9rem; padding-inline: 0.9rem;
    border: 1px solid var(--rule); border-radius: 3px;
  }
  /* A box that is cut off at a height needs to say it is a box. Without a
   * label a bounded list reads as a rendering fault - as the page having run
   * out rather than the list having been contained. Generated rather than
   * marked up for the reason above, and it is a label rather than a control,
   * so nothing is hidden behind it. Sticky, so it is still there once the
   * reader has scrolled the list. */
  .sidebar::before {
    content: "On this page";
    display: block; position: sticky; top: 0; z-index: 1;
    margin-inline: -0.9rem; padding-block: 0.7rem 0.5rem; padding-inline: 0.9rem;
    background: var(--paper); border-bottom: 1px solid var(--rule);
    font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
    letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint);
  }
  .sidebar .groups { display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
    gap: 0 1.5rem; }
  /* `:first-child` counts elements, and `::before` is not one, so the first
   * group heading still matches the `margin-top: 0` rule above and would sit
   * flush against the label. */
  .sidebar h2:first-child { margin-top: 0.9rem; }

  /* A 0.87rem link with 0.3rem of padding is a 28px target. These are the
   * densest links on the site and the only way through a 120-section
   * reference, so they are the ones that have to be hittable. */
  .sidebar a { padding-block: 0.55rem; }
  footer .links a { display: inline-block; padding-block: 0.4rem; }
  /* The wordmark is a link back to the index on every documentation page and
   * it was a 68x16 target. `inline-block` so the padding has an effect at
   * all, and the baseline an `inline-block` reports is still its last text
   * baseline, so it stays aligned with the glyph beside it in `.mark`. */
  .mark .name a { display: inline-block; padding-block: 0.45rem; }

  /* No hover to reveal it, so the section anchor is always shown - and it is
   * an 8px wide `#`, which is a target nobody hits. The padding is cancelled
   * by an equal negative margin so the heading's baseline does not move. */
  .reference section > h2 .anchor { opacity: 1;
    padding: 0.4rem 0.5rem; margin: -0.4rem -0.3rem; }
}

@media (max-width: 48rem) {
  /* **The masthead is sticky, and at 360px it was 155px of sticky.** The nav
   * wrapped to two rows under the wordmark and took a quarter of the screen
   * with it, permanently, on every page - the one thing a sticky bar must
   * not do. One row now, with the links scrolling sideways in their own box
   * if there are more of them than fit, which is what a tab strip on a phone
   * has always done. */
  .top { flex-wrap: nowrap; gap: 0.75rem; padding-block: 0.85rem; }
  .mark { flex: none; }
  .top nav {
    flex-wrap: nowrap; min-width: 0;
    overflow-x: auto; overscroll-behavior-x: contain;
    gap: 1.1rem; scrollbar-width: none;
  }
  .top nav::-webkit-scrollbar { display: none; }
  .top nav a { white-space: nowrap; padding-block: 0.5rem; }
  /* The travelling bar is kept - on wider screens. It is drawn at
   * `left: -0.75rem`, which inside a scroller of its own is 12px of scroll
   * width per link and a bar drawn over the previous link's last letter.
   * Contained to the layout it was designed for rather than removed. */
  .top nav a::before { display: none; }
  :root { --top-h: 4.25rem; }
}

@media (max-width: 30rem) {
  /* The vertical rhythm was set at a laptop, where 4rem between sections is
   * a breath. On a 640px-tall phone the same 4rem is a tenth of the screen
   * spent twice per section, and the page reads as mostly gaps. */
  section { padding-block: 2.75rem; }
  .hero { padding-block: 2rem 2.5rem; }
  .masthead { padding-block: 2rem 1.5rem; }
  .reference section { padding-block: 0 2.5rem; }
  footer { padding-block: 2rem 3rem; }
  /* 1.25rem of side padding inside a block that is already inside a 16px
   * gutter leaves a 328px screen 288px of code. */
  pre { padding: 0.9rem 1rem; }
  .callout, .revision { padding: 0.9rem 1rem; }

  /* The ladder puts its gloss on the far right of the same row as the rungs.
   * At this width there is no far right, so the gloss takes its own line and
   * reads left like everything else. */
  .ladder li { flex-wrap: wrap; gap: 0.5rem 1rem; }
  .ladder .gloss { margin-left: 0; text-align: left; flex-basis: 100%; }

  .sidebar { max-height: min(20rem, 50vh); }
}

/* Hit areas, keyed to the input device rather than to the width, because a
 * finger is not narrow - it is blunt, and it is just as blunt on a tablet at
 * 1024px. Everything here grows a *target*; nothing here grows a glyph. */
@media (pointer: coarse) {
  .sidebar a { padding-block: 0.6rem; }
  .top nav a { padding-block: 0.55rem; }
  footer .links a { display: inline-block; padding-block: 0.45rem; }
  .mark .name a { display: inline-block; padding-block: 0.5rem; }
  .top nav a { padding-inline: 0.35rem; margin-inline: -0.35rem; }
  /* Both of these grow a target without moving a glyph, for the reason the
   * copy button does below: the anchor is a single `#` and the heading it
   * hangs off has its own baseline, so widening the ink would push the
   * heading around on the one screen size with no room to push it. */
  .reference section > h2 .anchor { position: relative;
    padding: 0.4rem 0.5rem; margin: -0.4rem -0.3rem; }
  .reference section > h2 .anchor::after { content: ""; position: absolute; inset: -8px -12px; }
  /* The copy button is 47x24, and it sits over the first line of the listing,
   * so making the button itself 44px tall would hide two lines instead of
   * one. The target grows and the button does not: an invisible pad on a
   * pseudo-element, which is the one way to have both. */
  .copy::after { content: ""; position: absolute; inset: -10px; }
}
td.mono { font-family: var(--mono); font-size: 0.82rem; }
td.what { font-family: var(--serif); color: var(--muted); }

/* ===================================================================== *
 * Motion
 *
 * **Everything on this page is readable with JavaScript off and motion
 * disabled, and that is the constraint every rule below is written under.**
 * Nothing here is parked at `opacity: 0` waiting for an observer to reveal
 * it: a section that animates in does so *from a visible resting state*, by
 * moving a few pixels, so a reader who never sees the animation never
 * notices it was there. The failure this avoids is the common one — a
 * scroll-reveal that leaves the whole page blank when the observer never
 * fires, which is what a printed page, a reader-mode extension and a
 * thumbnail capture all look like.
 *
 * `prefers-reduced-motion` turns all of it off at the bottom of the file
 * rather than per rule, so there is one place to check and one place to
 * fail.
 * ===================================================================== */

/* A link, a button, a card: one duration and one curve for the whole site,
 * so that two things moving at once do not look like two decisions. 140ms is
 * below the ~200ms at which a transition starts reading as an animation
 * rather than as responsiveness. */
a, .btn, .doc, .bet, nav a, .card {
  transition: color 140ms ease, background-color 140ms ease,
              border-color 140ms ease, transform 140ms ease,
              box-shadow 140ms ease;
}
/* `.copy` was in the list above and is not any more. It keeps the same colour
 * and border curve as everything else, and loses only `transform` — which it
 * never used, and which now shares a compositor with the scroll-pinning
 * `translate` above. Its `opacity: 0.12s` is declared with the rest of it. */
.copy { transition: opacity 0.12s, color 140ms ease, border-color 140ms ease; }

/* A card lifts by one pixel. Not three: a card that jumps announces itself,
 * and these sit in a grid where several are visible at once. */
.doc:hover, .bet:hover, .card:hover {
  transform: translateY(-1px);
  border-color: var(--accent);
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

/* The masthead's rule draws itself once, left to right. It is the only
 * purely decorative motion on the site and it is one second long and does
 * not repeat — a loop would make the page feel like it was still loading. */
@keyframes rule-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* Drawn on the masthead's own bottom rule, through `::after`, rather than on
 * an element added to five files. The selector this replaces — `header .rule,
 * .masthead-rule` — matched nothing on any page, so the animation above was
 * written, documented and never once run.
 *
 * At rest the transform is `none`, which is `scaleX(1)`: with the animation
 * suppressed the rule is simply the line it always was, and nothing is ever
 * parked at zero width waiting for something to start it. */
.masthead::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--ink);
  transform-origin: left center;
  animation: rule-draw 900ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

/* A section arriving. It starts **visible** and 6px low, and settles. With
 * the animation suppressed it is simply where it belongs. */
@keyframes settle { from { transform: translateY(6px); } to { transform: none; } }
section > h2, section > .lede {
  animation: settle 320ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}

/* The anchor a reader just jumped to. A target that only changes colour is
 * easy to miss when the jump lands mid-screen; this fades a tint out over a
 * second, which says "here" without leaving a permanent mark. */
@keyframes target-fade {
  from { background-color: var(--accent-soft); }
  to   { background-color: transparent; }
}
section:target > h2 { animation: target-fade 1200ms ease-out both; }

/* The sidebar's current entry. The bar grows from the top rather than
 * appearing, so moving between entries reads as one thing travelling. */
nav a { position: relative; }
nav a::before {
  content: ""; position: absolute; left: -0.75rem; top: 0; bottom: 0;
  width: 2px; background: var(--accent);
  transform: scaleY(0); transform-origin: top center;
  transition: transform 140ms ease;
}
nav a:hover::before, nav a[aria-current="true"]::before { transform: scaleY(1); }

/* A `pre:hover .copy { transform: translateY(0) }` stood here. It set the
 * identity transform on an element nothing ever translated, so it animated
 * nothing; it is gone with the button's `transform` transition, and the
 * button's scroll-pinning `translate` has the compositor to itself. */

@media (prefers-reduced-motion: reduce) {
  /* One switch for the whole file. `animation-duration: 1ms` rather than
   * `none` because `both` fill modes are load-bearing above — an animation
   * removed outright would drop the end state with it. */
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
