/* Leaf default theme, vendored into each page directory by `page init` and served
 * at /theme.css. Four tiers, cheapest first: tokens, element styles for plain
 * semantic HTML, class idioms (one rule + one catalog line each), and
 * element-widgets (lf-* tags rendered entirely by CSS). Customization follows
 * the same cascade: override a token, then a widget's rule. `page init` appends
 * user and project theme files after these defaults.
 *
 * Every surface rides a color token, so the dark palette is exactly one more
 * token block — nothing else in this file (or the runtime, which styles its UI
 * from the same tokens) knows about color schemes.
 *
 * Three voices, because the page already has three kinds of words and the norms
 * turn on telling them apart. What the page *says* is set in a text serif: prose
 * a user reads closely and points at. What the page *labels* — an eyebrow, a
 * column heading, a chip, the headings across a table, a metric's caption — is
 * apparatus, set in the UI sans at small sizes with tracking, so it reads as
 * machinery around the argument rather than as part of it. What it *shows* is mono:
 * code, diffs, trees, timestamps. The runtime's own chrome takes the same sans
 * (.lf-ui reads --sans), which is what finally makes "this is not the document"
 * a difference you can see rather than a claim resting on size and color. It
 * was invisible while document and chrome were the one system face.
 *
 * The serif is stacked, not shipped. theme.css is inlined whole into every
 * `version export` and parsed by `version check` on every version, so a webfont
 * would have to arrive as a base64 blob in both — and referenced by URL instead
 * it silently falls back in exactly the medium (a copy, mailed on) that has no
 * server to ask. Charter and Iowan Old Style ship on macOS, Georgia everywhere
 * else; each is a screen serif with a large x-height, which is the property that
 * matters at 17px.
 *
 * The stylesheet uses declarations as open selectors too. A box that draws a frame
 * declares `--lf-frame: 1` in the rule that draws it. Style queries use that custom
 * property to trim child margins and to bound wide content. A project box then receives
 * the same behavior without joining a tag list. `main` hands wide room back to its
 * contents explicitly because it is the outer page frame.
 *
 * `main` declares `--lf-column: 1` in the same rule, claiming that its `max-width` is
 * the readable column. The file lint measures every fixed pixel width against that
 * number, so a package or page setting a column of its own claims it in the rule that
 * sets it; a width with no claim beside it is a width and nothing more.
 *
 * Where the fact belongs to the registry rather than to the rule that draws the box,
 * `markDeclared` paints it and the selector reads the paint. The lists that ask whether
 * a suggestion slot or a variant holds block content invert HTML's phrasing content,
 * which answers "block" for every custom element, so they exclude `[data-lf-inline]`
 * rather than the tags that declare `x-inline`. The affordance rules that draw a choose
 * group as a control exclude the descendants of `[data-lf-exhibit]` for the same reason,
 * asking in CSS the question `quoted()` asks in JavaScript. A tag name in a shared list
 * is a closed vocabulary wherever it appears, and one layer's tag written into another
 * layer's stylesheet is that plus a leak.
 *
 * Live pages reserve conversation room at the wide layout's existing floors, so the
 * first comment and the last resolution leave the document column in place.
 * `--thread-card-floor` bounds an inline card when the remaining margin is too narrow;
 * the card then covers the page rather than becoming an unreadable sliver. */

/* Ordinary action controls use `.lf-btn`, whose shared theme rules also enter declared
   shadow trees. Packages may set placement and density, but keep its shape, border,
   hover, and disabled treatment. Margin Buttons, reaction chips, and status labels retain
   their own forms.

   Typography is presentation, not passage permission. A chip or code annotation may look
   like apparatus and still be a page word the reader can quote.

   Which question a floor asks belongs to the posture it grants. A floor asking how much
   room is left beside a panel or tray is a container query on `lf-shell`: 1152 and 1416
   for the sidebar and sidenote strips, 1208 and 1472 for the thread's beside posture. The
   living margin's 900 asks the window instead, because it is half of a pair — `@media
   screen and (max-width: 899px)` stops drawing the margin at all, and a marker's presence
   is not something a container can be asked about without the answer depending on the
   strip the marker is asking for. Both halves of such a pair ask the same medium, or a
   panel narrowing `body` under the floor withdraws the strip while the window keeps the
   markers on screen with nothing reserved for them.

   Text may break at any character needed to keep the page inside its column.
   `overflow-wrap` is inherited from the page. Any token that must remain one unit, such
   as a small badge or key chip, declares `white-space: nowrap` locally. Test long
   identifiers and paths, not only ordinary prose.

   A wide widget reads the room declared by `x-wide`:

   - `box` fills the available box and clamps its contents there;
   - `drawing` may size from its source up to the room available to it.

   `markDeclared` exposes this declaration and CSS computes room after chrome strips and
   claimed margins. A drawing inside a framed box uses that box's room, not the outer
   page's. Size the widget's box with `contain: inline-size` where its contents would
   otherwise make the box itself wider.

   Every box that frames authored block flow declares `--lf-frame: 1` where the frame is
   drawn. The declaration may belong to a nested-state selector or a generated internal
   box rather than the tag's base rule. Widgets with `x-content: prose` or `items` can
   admit authored flow; data-only, empty, and inline widgets do not automatically owe a
   frame declaration.

   The shared style query trims the outer margins of the first and last non-generated
   children inside a frame. It ignores `GENERATED` because a positioned pick mark or
   clipped spoken word must not become the visible content edge. A transparent wrapper
   that lets a grandchild's margin collapse through it declares the frame at the wrapper
   level only when it is the boundary responsible for that flow.

   Put a layout grant in a selector strong enough to override the withheld base rule. Put
   a standalone-only affordance guard in `:where(html:not(.lf-copy))` so the guard does
   not add specificity to every rule inside it.

   The live-page scrolling and chrome reservations stay under the live guard. A copy with
   no panel uses an ordinary centered document and must not retain room for absent runtime
   furniture.

   Print asks a stricter question than export because nothing on paper is interactive.
   `data-lf-offer` identifies injected controls to remove, while `data-lf-said` preserves
   a decision word the page speaks through a control and `data-lf-echo` a name a control
   copies off the row it routes to. What the two word markers keep is the word and not the
   shape: a control that survives paper gives up its ground, corner, border, underline,
   marker and pointer hand, because nothing on a sheet can answer the press they promise.
   Colour stays, being part of what the control says.

   Paper opens what a page puts behind a gesture, for the same reason: a settled group's
   cards, an inactive tab's panel, and a shut `<details>` all print open. A page that
   means a disclosure to stay shut on paper says so in its own stylesheet. `paperWords`
   compares the screen and print readings across the whole page. `coveredWords` runs again
   in print. A wrong offer/said declaration is fixed where the label is created, not by
   naming its widget in print CSS. */

:root {
  color-scheme: light dark;
  /* The document is warm paper. Code uses a white editor canvas and quiet gray chrome
     to keep source visually distinct from document fields. */
  --paper: #faf9f5;  --ink: #1c1b18;  --muted: #6f6a60;  --rule: #e7e3d9;
  /* The accent marks where the machinery points — a link, the active milestone,
     a focus ring — and so has to stay hue-distinct from the
     three semantic colors it appears beside. That rules out the warm end: a clay
     accent sits a few degrees from --warn, and an accent ring beside a warning dot
     would be a distinction the reader has to measure. Ink blue keeps the link and
     focus conventions and reads as ink on ivory rather than as UI. */
  --accent: #2f5480; --ok: #3f7d4e;   --warn: #b4741a;   --danger: #b4402f;
  --r: 6px;
  --sp-1: 4px; --sp-2: 8px; --sp-3: 16px; --sp-4: 24px;
  /* The smallest box the layer offers a reader to aim at, on either axis. One token
     rather than a number in each rule, and one token rather than two floors and a media
     query in each of them: what changes between a mouse and a finger is this length and
     nothing else, so the query belongs here where it is asked once. A control that has
     to be a fixed size under a finger — a margin Button, the key line's More — still
     says so where it is written; this is the floor, not the size. */
  --aim-floor: 24px;
  /* --rail has no authored value: the shared margin measures its widest target item
     after content modules have contributed their controls, then states that width on
     the root. The rule that spends it is beside .lf-margin-item below. */
  /* A sidenote's strip: a column of text plus its gutter, chosen rather than measured
     off anything the way --rail is. The 360px it leaves the note sets about fifty-six
     characters of --t-5 serif. The rule that spends it is beside aside.sidenote below.
     Half of it is also how far off the window's centre the column comes to sit, the
     column centring in what the strip leaves — so this number is the page's axis as
     much as the note's measure, and the two are set together on purpose. It held 216px
     while the strip was on the left, which put a note at thirty characters: a measure
     short enough that one sentence took four lines, and an axis close enough to centre
     that the arrangement read as a centred page with something in the margin rather
     than as a page with a margin. */
  --note: 384px;
  /* A page thread uses a wider reading card than an authored sidenote. The margin
     includes the marker and the gutter between it and the 460px conversation. */
  --thread-card: 460px;
  /* The narrowest that card is still a conversation. The card's width is whatever room
     is left to the right of the marker it is measured from, and a page whose margin is
     narrower than this has no margin to draw a thread in: the card comes off the marker
     and stands over the page rather than shrinking to a column a word wide. 320px is
     what the margin's other card already stands at, so the floor is the narrowest
     reading surface this layer ships rather than a second opinion about one. The rule
     that spends it is beside .lf-margin-preview, and placeThreadPreview reads it to
     decide where the card can still be placed beside its source. */
  --thread-card-floor: 320px;
  --thread-margin: 520px;
  /* A compact left margin for page-level wayfinding or reference. Unlike a sidenote,
     which annotates one block at its own height, a sidebar may remain beside the reader
     while the document moves, so the whole left edge is spoken for wherever it is in
     margin form. Its 240px box plus the ordinary 24px gutter is enough for short link
     labels without making a second prose column. The rule beside aside.sidebar spends
     it; the shell's container query decides when the page can afford it. */
  --sidebar: 264px;
  /* The measure, and the gutter main sets it in. Named because three rules now want
     main's width: the element itself, the strip arithmetic beside aside.sidenote, and
     the room a copy states for itself. A second copy of 720 would be a release behind
     the first. */
  --col: 720px;
  --col-pad: 24px;
  /* How wide a widget that lays its content out into the width it is given (x-wide:
     box) may stand — one number for the whole vocabulary, because a set of widths is
     what makes mixed measures read as a design rather than as an accident, and a width
     per widget is how a page becomes a ransom note. Unmistakably wider than the column
     on purpose: a near miss reads as a column that failed to line up, where half as much
     again reads as a figure. --lf-room, the other half of the pair, is resolved by CSS
     from the shell and its claimed strips, so a widget stands clear of both. A drawing
     (x-wide: drawing) is not held to this number, its width being
     its own; the rule beside the two below says what it is held to instead. */
  --wide: 1080px;
  /* The ladder, body at --t-4. Measured on Charter at 17px: 7.9px a character, so
     the column below holds about 74 of them. These are the prose's hierarchy; a size
     that has to fit something states its own number where it is set — a code block
     against the characters it takes across, a step badge against its disc. */
  --t-6: 11.5px; --t-5: 14px; --t-4: 17px; --t-3: 20px; --t-2: 24px; --t-1: 31px;
  --code-size: 12.5px; --code-line: 19px;
  --serif: Charter, "Bitstream Charter", "Iowan Old Style", Georgia, ui-serif, serif;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  --card: #fffefb;   /* raised surfaces: cards, panels, controls */
  --field: #f4f1e8;  /* tinted fields: details, callouts, notes */
  /* The ink every raised surface casts its shadow in. One per scheme, because the two
     grounds want opposite amounts of it and a shadow written once as rgba(0,0,0,α) can
     only be right about one of them: at .12 over the light paper a menu lifts 10 L*, and
     the same declaration over the dark paper lifts 1.4 — which is a drop shadow that is
     in the stylesheet and not on the screen. Nine of the layer's twelve were written that
     way. The dark value is as far as the medium goes: the paper is already at L* 8.3, so
     black takes it to 3.0 and no further, and the WCAG ratio is the wrong instrument down
     there (1.11:1 for an edge the eye reads perfectly well).

     Depth is geometry here and nowhere else. The alphas that were spread .12–.24 across
     the sites are gone, because a shadow's spread and offset already say how high a thing
     is and a second dial saying the same thing is a second dial to keep in step: a card
     in the hand is 0 8px 24px against its resting 0 2px 8px, which is the whole
     difference and enough of one. */
  --shade: rgb(0 0 0 / .14);
  --code-bg: #f6f8fa; --pre-bg: #fff; --code-chrome: #f6f8fa;
  --code-ink: #24292f; --code-muted: #57606a; --code-border: #d0d7de;
  --chip: #eeeade;   /* neutral chip */
  /* Secondary interface ink, held to 4.5:1 against the page surfaces it lands on.
     Code owns a near-neutral value because its canvas no longer follows paper. */
  --ink-2: #3c3934;  --muted-2: #6d6960; --border-2: #d5cfc2;
  /* The banner's translucent backdrop is the paper it floats over, so it is derived
     rather than restated: a project that overrides --paper gets a backdrop that
     follows it, where a second hex kept the default ivory behind a recoloured page,
     and the dark block has one fewer token to hold in step. */
  --veil: color-mix(in srgb, var(--paper) 93.3%, transparent);
  /* Comments use violet so their marks remain distinct from links, focus, and the
     semantic status colors. One hue at three strengths says posted, hovered, and
     active without changing meaning between page and code surfaces. */
  --mark: #dfd1ed66; --mark-hover: #dfd1edb3; --mark-strong: #dfd1ed; --mark-ink: #4a3b7d;
  /* The draft's wash, relative to the accent so one definition serves both schemes; the
     passage highlight (marks.css) and a draft's element mark (chrome.css) read it. */
  --mark-pending: color-mix(in srgb, var(--accent) 20%, transparent);
  /* A reaction's wash: the same hue one step under the resting mark, so a passage
     someone reacted to reads as touched and a passage someone commented on reads as
     annotated, and the two never look alike side by side. */
  --react: #dfd1ed40;
  /* The "you are here" ring: where the reader is standing, wherever they are
     standing. The decision they are in wears it ([data-lf-ask], leaf.js), as do the
     runtime's own controls, which is where a reader backing out of the panel lands.
     One band for one fact — stated apart,
     the same ring was free to become three, and a reader would have had to learn
     that a blue rectangle on the banner and a blue rectangle down the page meant
     the same thing. The gap is what the ring wants outside a box that stands on
     its own; a control packed into a list states its own inset instead.

     The width is a token of its own because the ring is drawn outside the box it
     names, so a scroll region has to reserve room for it: a shorthand cannot be
     read back in a calc, and the number was therefore being retyped wherever the
     room was worked out. --here-ring is composed from it, --here-ring-room adds
     the gap to it, and every control that insets its ring by one width negates
     it, so there is still one place the band's thickness is decided. */
  --here-ring-w: 2px;
  --here-ring: var(--here-ring-w) solid var(--accent); --here-ring-gap: 3px;
  --here-ring-room: calc(var(--here-ring-w) + var(--here-ring-gap));
  --status-trace-w: 1.5px;
  --status-trace-ink: color-mix(in srgb, var(--ink-2) 42%, var(--paper));
  /* A keyboard address chip's box: the line box, which is a ratio of the font, plus
     the ring drawn around it (chrome.css dresses one). It is a token for the
     reason the ring's width is — a box somebody else holds room for has to be read
     back in a calc, and the option that holds a column for one is in another layer's
     stylesheet entirely. Written as a number there, the column stayed at the size the
     chip was when it was measured, and a package redeclaring the ladder grows the chip
     into whatever the column was holding beside it. */
  --lf-key-box: calc(round(var(--t-6) * 1.478 + 2px, 1px));
  --ok-tint: #dfeddf;     --ok-ink: #2f6b40;
  --warn-tint: #f7ecd2;   --warn-ink: #8a5a12;
  --danger-tint: #f7e0da; --danger-ink: #9c3526;
  --add-tint: #e4efe0; --del-tint: #f7e2dc; --hi-tint: #fff8c5;
  /* Six syntax roles are enough to find structure without turning evidence into a
     paint box. Unmapped scopes keep the inherited code ink. Each role clears 4.5:1
     on the code canvas and semantic line tints; the render gate checks the result. */
  --syn-comment: #696458; --syn-keyword: #a3372c; --syn-string: #1d4f6b;
  --syn-number: #2f5480;  --syn-name: #6b4a9e;    --syn-type: #8a5a12;

  /* Series colors, for a chart's marks. Five, and the sixth is refused rather than
     drawn: these are the most a reader can hold apart, and a palette that runs out and
     starts again tells them two series are one. They are their own family rather than
     --accent, --ok, --warn and --danger reused, because those four say something on this
     page — a decision's link, a passing check, a warning — and a bar wearing one would
     be making that claim about a number.
     Not chosen by eye. The first attempt at this line was, and its blue and its plum
     came out 0.3 apart under deuteranopia — the same color, to a reader who has no way
     to tell us. So the steps are stepped to clear the measurable floors: every pair
     (not merely the neighbors, since a stacked bar puts any two of them edge to edge)
     at least 8 apart in OKLab ΔE×100 under simulated protanopia and deuteranopia, at
     least 15 apart under ordinary vision, chroma above the point where a hue reads as
     gray, and 3:1 against the paper they sit on. Worst pair here is 9.5 and 17.8, which
     leaves a little room to move one without having to re-derive the set. The floors are
     a test rather than a note asking to be remembered
     (test_the_series_palette_clears_the_floors_it_claims_to), and it counts the steps
     against $series.steps in the same breath, that being what a chart refuses a sixth
     series against. */
  --series-1: #4589d2; --series-2: #b77114; --series-3: #25966a;
  --series-4: #6c489a; --series-5: #8c2d2a;
}
/* The other half of --aim-floor, and the whole of what a coarse pointer changes about how
   small a control may be. Every rule that states the floor reads the token, so a control
   joins both answers by joining one of them. */
@media (pointer: coarse) { :root { --aim-floor: 44px; } }
/* Which here ring this is, said by the rule that draws it. An outline carries no word
   for which of the layer's rules put it there — so a reader that had to know worked it
   back from the selectors, matching the layer's own rules against the document by hand.
   To ask `querySelectorAll` anything it first had to resolve nesting, join `@scope`
   roots onto their descendants and split `:host(...)` on a matched paren, and it had
   been wrong at each of them in turn: an unresolved `&` throws, and a throw there reads
   exactly like a rule nothing on the page matches, which is the whole of why the joined
   group's own ring was invisible to the gate that watches it. None of that was a fact
   about rings. It was the cost of asking the stylesheet a question the browser had
   already answered.

   The rule says which ring it is instead, in the same declaration that draws it, the
   way a box already says where it draws its frame (--lf-frame). Readers ask the
   composed page, and get a truer answer than the matching gave: the cascade hands the
   name to whichever rule won the outline, so what is credited is the ring the reader is
   looking at rather than every rule whose selector reached the element.

   Registered rather than reset, because the reset --lf-frame needs is a rule of its own
   and this wants none: a name left to inherit would put a thread's ring on every word
   inside it. Typed as one identifier, so a value that is no name — a shadow channel's,
   under a property somebody else spelled the same way, which is how this one came to be
   spelled out in full — falls back to `none` rather than reading as one.

   Naming is not how the layer says a ring is there; the outline is, and nothing the
   product ships reads this. What holds the layer to naming what it draws is the corpus
   floor, in the suite, which divides by these names and credits what the page paints. */
@property --lf-here-ring {
  syntax: "<custom-ident>";
  inherits: false;
  initial-value: none;
}

/* The dark page keeps its warm ground. Code remains on a near-neutral dark canvas so it
   stays distinct from the surrounding document in either color scheme. */
@media (prefers-color-scheme: dark) {
  :root {
    --paper: #191815;  --ink: #e8e4db;  --muted: #a09889;  --rule: #34312b;
    --accent: #8fb0d8; --ok: #7fb98c;   --warn: #d8a95c;   --danger: #d98b7a;

    --card: #201e1a; --field: #232019;
    /* Four times the light alpha, for a fifth of the effect: 5.3 L* off the paper and
       7.5 off a card, against the 1.4 the light value bought here. */
    --shade: rgb(0 0 0 / .55);
    --code-bg: #2b2b29; --pre-bg: #1b1b1a; --code-chrome: #222220;
    --code-ink: #e8e7e3; --code-muted: #9b9992; --code-border: #3b3a37;
    --chip: #2d2922;
    --ink-2: #c9c3b6; --muted-2: #988f7f; --border-2: #453f36;
    --mark: #6152a059; --mark-hover: #6152a079; --mark-strong: #6152a099; --mark-ink: #9d8fd6;
    --react: #6152a036;
    --ok-tint: #1d2b1f;     --ok-ink: #97cca3;
    --warn-tint: #322715;   --warn-ink: #e2bb75;
    --danger-tint: #35211b; --danger-ink: #e0a091;
    --add-tint: #1b2a1c; --del-tint: #33201b; --hi-tint: #342d14;
    --syn-comment: #a59d8e; --syn-keyword: #e59a8c; --syn-string: #9dc4dd;
    --syn-number: #a8c4e2;  --syn-name: #c3a8de;    --syn-type: #dcb27e;
    /* Stepped against this ground rather than lightened from the light set: the band a
       mark has to sit in over a brown-black is a different band, and the five above
       leave it at both ends. Same hues, same floors, checked the same way (worst pair
       9.2 and 17.2). */
    --series-1: #2b8ecd; --series-2: #ce7600; --series-3: #50a069;
    --series-4: #7a4faf; --series-5: #b13d54;
  }
}

/* ---------- elements ---------- */

/* A box that draws an inset shows it twice — above what it holds and below it — and what
 * a child's outer margin does at that edge decides whether the two are the same number.
 * Out on the page that margin collapses through its parent and is spent between blocks;
 * inside a box that draws something at the edge, or that establishes a formatting context
 * of its own, it cannot get out, and the room the child reserved for a neighbour it hasn't
 * got is painted as the box's own inset instead. So a card stating 16px came out 16 over
 * its title and 29 under its last paragraph, and the difference moved with what the author
 * wrote: the same card ending in a run of words was even. An inset that is a fact about
 * the content is an inset the box did not state, and it is the whole of the marking on a
 * quotation, where 16px of bar ran past the exhibit at each end.
 *
 * `margin-trim` is the property for this and Chrome hasn't got it (151: `CSS.supports`
 * says no, and the declaration lays nothing out), so the trim is written here — and the
 * half worth thinking about is who writes it. A list of the boxes that frame what they
 * hold is the closed list the norms forbid: a layer's stylesheet can only name that
 * layer's own, so a project's card is outside it and the failure is a silent 13px rather
 * than an error. A box says so itself instead, in the same declaration where it draws the
 * frame, and the trim finds it through a style query. `--lf-frame` inherits, so the reset
 * inside is what holds the claim to the box's own children: a grandchild's margin is
 * between blocks, where it belongs, and a nested frame outranks the reset by being a
 * selector rather than `*`.
 *
 * Which child is at the edge is a question about the page's own blocks, and `:first-child`
 * is the DOM's answer to it. The two are the same only where no module has written
 * anything: a pick mark is appended and positioned out of the flow, a quiet word is
 * clipped and inserted after the title, and each of them takes the trim off the block the
 * reader can actually see — so a settled option kept 13px under its last paragraph and a
 * block change kept 13 over its first, in exactly the widgets that build the most chrome.
 * The generated markers are the same pair the anchor pass reads (`GENERATED`, leaf.js),
 * because it is the same question: which of these words are the page's. That also
 * dissolves the specimen's two arrangements into one, its "quoted ·" note being a
 * generated child on a live page and a pseudo-element on a page carrying no script.
 *
 * What the trim cannot reach is a first or last child that hands its own children's
 * margins on rather than reserving room itself — a boxless one, whose margin the rule
 * has nowhere to land, and a bare wrapper, through which a grandchild's margin collapses
 * to the frame's edge unchanged. The answer is the same sentence one level in: that box
 * declares the frame too, which is why `.facts` does. Reaching a level further from out
 * here is the fix that suggests itself and is worse, since the same selector over a
 * padded grandchild closes up that box's own first line. `version check --render` is what
 * says when a box hasn't declared (TRAPPED_MARGINS), because a trapped margin renders
 * perfectly and reads as a number somebody chose. */
@container style(--lf-frame: 1) {
  :nth-child(1 of :not(.lf-ui, [data-lf-gen])) { margin-block-start: 0; }
  :nth-last-child(1 of :not(.lf-ui, [data-lf-gen])) { margin-block-end: 0; }
  * { --lf-frame: 0; }
}

/* A run with nothing to break on breaks anyway rather than painting outside the box that
 * was holding it — this page's subject is code, so its prose carries paths, identifiers
 * and shas, and there is no width at which one of them can't be longer. It reaches
 * everything by inheritance and does nothing anywhere a line already can't wrap, so the
 * widgets that scroll instead (lf-board, lf-diff, pre) are untouched; a metric's headline
 * was the one with no width to spare at all, and a twelve-character value ran 287px out
 * of a 138px card and across whatever the grid had put beside it. */
/* Margin features claim named strips instead of overwriting page padding themselves.
 * A static copy must subtract exactly the room its padding reserved; the live page can
 * measure its final box, but both still need one shared answer. The right side hosts
 * sidenotes, suggestion controls, and the living map's inline conversations. They occupy
 * the same strip and are collision-laid-out rather than summed, so the page reserves only
 * the widest claim.
 * The left still has one claimant: aside.sidebar writes --strip-l directly. */
body { margin: 0; background: var(--paper); color: var(--ink);
       font: var(--t-4)/1.6 var(--serif); overflow-wrap: break-word;
       --lf-shell-inset-left: 0px;
       container: lf-shell / inline-size; }
/* Authored HTML is the page's useful initial condition, so it paints from stylesheet
 * parse while JavaScript upgrades widgets and reads the standing log. Presentation is a
 * semantic boundary, not a paint gate: until the first read has applied (or established
 * the offline fallback), Leaf suppresses arrival transitions and withholds authored
 * dialogs and popovers. Those top-layer elements can otherwise escape their ancestors'
 * stacking and inertness; ordinary prose, links, scrolling, and layout stay available.
 *
 * The anonymous layer is first in the merged theme, so these important declarations
 * outrank every later layer and unlayered stylesheet declaration without reserving a
 * named layer custom CSS could append to. Inline importance ranks higher still, so the
 * version gate refuses it on the protected top-layer properties below. */
@layer {
  @media screen {
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]),
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]) > main,
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]) > main *,
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]) .lf-ui {
      transition: none !important;
    }
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]) > main :is(dialog, [popover]) {
      visibility: hidden !important;
      opacity: 0 !important;
      transition: none !important;
      interactivity: inert !important;
    }
    html:has(script[type="module"][src="/examples/feature-gallery/leaf.js"])
      body:not([data-lf-presented]) > main :is(dialog, [popover])::backdrop {
      visibility: hidden !important;
      opacity: 0 !important;
      transition: none !important;
    }
  }
}
/* Positioned so it is the containing block for anything a widget hangs in the
 * page margin (lf-suggestion's controls): `left: 100%` then means the column's
 * right edge, and `anchor()` reaches the anchor names declared inside it.
 *
 * 720px is stated as a number and not as a token, because `version check` reads
 * this very declaration to find the column it measures every pinned width
 * against (_column_width). A var() there is a value the parser can't resolve, so
 * the gate would quietly fall back to its 780px default and start passing pages
 * that overflow by 60px. The column is one number, and this is where it is said.
 *
 * It is the text's own width and not the box's: nothing sets border-box here, so the
 * padding stands outside the 720px rather than inside it, and `version check` reading
 * this number is reading the column the words get. Charter sets about 7.35 of them to
 * the pixel at 17px, so a line here runs around ninety characters.
 *
 * That is long by the measure a book is set to, and it is left alone on purpose. What
 * makes a long line hard is the sweep back to find the next one, and both of the things
 * that cost are missing: the leading is 1.6, which is what buys a long measure back, and
 * a page here is prose interleaved with boards, diffs and cards rather than a column of
 * text, so four consecutive full-width lines is a lot. The reader who works in these
 * pages was asked and doesn't want them narrower.
 *
 * If that ever changes, the floor is not taste. A code block is this column less its
 * padding, and holding the 80 characters `pre` is written for puts the column at about
 * 640px — so prose set to a book's measure and evidence set to source's cannot both come
 * out of one column, and the way to have both would be two of them rather than a smaller
 * number here. Widgets that want width already scroll (lf-board, lf-diff, pre). */
main {
  --strip-l: 0px;
  --lf-thread-beside: 0;
  --strip-r: max(var(--claim-note, 0px), var(--claim-rail, 0px),
    var(--claim-map, 0px), var(--lf-claim-right, 0px));
  --lf-shift: calc((var(--strip-l) - var(--strip-r)) / 2);
  --lf-room: max(0px, calc(100cqi - var(--strip-l) - var(--strip-r)
    - 2 * var(--col-pad)));
  width: min(var(--col), var(--lf-room));
  max-width: var(--col);
  margin: 0 auto;
  padding: 72px var(--col-pad) 96px;
  /* A workspace changes the shell's responsive state in one layout pass. The runtime
   * then carries this final column from its old horizontal position to its new one
   * through --lf-shell-motion-x. Keeping that presentation offset out of the shell's
   * inline size prevents container-query postures from appearing and disappearing in
   * the middle of the motion. A static copy has no runtime registration and reads the
   * zero fallback. */
  left: calc(var(--lf-shift) + var(--lf-shell-motion-x, 0px));
  position: relative;
  --lf-frame: 1;
  --lf-column: 1;
}
/* Evidence that is wider than the argument about it. The column above is the measure
 * prose is read at, and a board's columns or a diagram's graph are as wide as what they
 * hold — so a page carrying one was a cramped board, or a page whose every paragraph had
 * been widened to suit its widest exhibit. Neither is a choice a page should have to
 * make, and the tradition this borrows from doesn't: Distill sets text at l-body and
 * figures at l-page, Tufte holds the column and lets a figure go fullwidth. What keeps it
 * reading as design is that the prose axis never moves and there is one wider width, so
 * an exhibit that fills its box is either in the column or at --wide and never at a
 * number of its own. A drawing fills no box, its width being the size it was drawn at,
 * and the rules below say what its box is instead.
 *
 * Which widgets those are is the registry's to say (x-wide) and not this file's: a rule
 * naming lf-board would work perfectly for lf-board and do nothing at all for the
 * twelfth widget, which is the failure the whole vocabulary is arranged against. The
 * runtime marks what the registry declares, so this reaches a widget nobody has written
 * yet — and marks the element itself, which is what carries the width into an exported
 * copy, a file that runs no script and keeps the markup.
 *
 * The exhibit grows out of the column rather than being sized against the page: each
 * margin gives what it has, up to half of the one width, and the box takes whatever it is
 * given by having no width of its own. That is the floor for free — a margin with nothing
 * to give gives nothing, and a widget nobody has stated a room for is exactly the column,
 * which is the layout the page already had. It is what makes an estimate safe to state,
 * too: a room read short can only fail to widen an exhibit, never narrow one below the
 * measure its own page is set to.
 *
 * A margin has something to give only if nothing is standing in it, and on most pages here
 * something is. A suggestion's controls hang beside the column and a sidenote is read out
 * there, and both hang off the column rather than out of the strip reserved for them —
 * they have to, being level with the line they belong to, while the column centres in
 * what the strip leaves. So the reservation and the occupancy are at different places on
 * the page, and a widget grown to the reservation is drawn over the occupancy: measured,
 * a board stood 134px over the accept and reject controls of the change above it, and 34px
 * over a note. Whoever claims a margin says so where it claims it, in the layer that
 * claims it, and this rule reads the two sides separately so a claim costs that side only.
 *
 * A claimed side is why the exhibit is not centred on the column. Growing by the smaller
 * of the two would be centred and would be nothing at all, since every claim here leaves
 * its side a gutter: five of the seven shipped examples that carry a wide widget also
 * carry a claim, so the axis is what a symmetric rule would have cost the feature. An edge
 * flush with the column is an alignment the page already has. An axis-setting sidenote
 * makes the page asymmetric before the exhibit arrives. A sidebar instead borrows the
 * existing gutter and moves the column only when the remaining room runs short.
 *
 * Screen only. Paper has no window to take room from and a printed page is the column's
 * width, so leaving the rule out of print is the whole of what paper needs. On screen,
 * `body` is the size container. Its inline size already excludes any standing Leaf
 * workspace, and `main` subtracts the page's own two margin claims from that one browser
 * reading. A live page and a standalone copy therefore use the same arithmetic. */
@media screen {
  [data-lf-wide] {
    /* Half the surplus, because a side may only ever have half: the other half is the
       other side's whether or not it is taken, so a claim never makes the free side
       wider than it would have been on a page with no claim at all. */
    --lf-grow: max(0px, calc((var(--lf-reach) - 100%) / 2));
    --lf-grow-l: var(--lf-grow);
    --lf-grow-r: var(--lf-grow);
    max-width: none;
    margin-left: calc(-1 * var(--lf-grow-l));
    margin-right: calc(-1 * var(--lf-grow-r));
    /* The box's width is the room's and never its content's — that is the whole
     * contract above — and this is where layout is told so. Without it the content's
     * minimum is what every shrink-to-fit holder is floored at, and the row-form
     * option is one: a table box hugging its label hugged a 985px graph instead,
     * grew past the joined group's border, and the group's clip cut the exhibit off
     * with nothing reported. Size containment zeroes the box's say in any ancestor's
     * intrinsic width; what it holds already scrolls. */
    contain: inline-size;
  }
  /* The two kinds of wide widget differ in one thing, how far the box may reach, and that
   * follows from what decides their width. A box (a board) lays its columns out into
   * whatever it is given, so the width is a choice, and the choice is the one number
   * above. A drawing (a diagram's graph) is the size its renderer drew it at, and the box
   * around it is nothing but the clip: capped at that number it showed the left 1080px of
   * a 1533px sequence diagram on a window with room for the whole of it — cut off, with
   * an overlay scrollbar the platform hides until it is used as the only sign that there
   * was more. So a drawing's box reaches the room, and the number the vocabulary shares
   * is a promise about boxes that fill it, and a drawing is not one — what shows of it is
   * the drawing, at its own size, whatever its box.
   *
   * Then the drawing has to be *placed* in a box that is now most of the window, and
   * centring it in the box is the wrong answer on any page with a claim, since the box
   * has grown one way and its centre is off the column's axis by half the growth: a
   * 466px graph on a page with a rail came out 241px left of the prose it explains on a
   * 1920 window, hanging into the free margin with nothing out there to explain. What
   * reads right is the alignment a board already has: on the column's axis wherever the
   * drawing fits between the claimed edges, flush with the column on the claimed side and
   * out into the free margin when it needs the room, and scrolling only when even the
   * room is short. Block layout cannot say that — a block wider than its holder starts at
   * the holder's start, whatever the margins — so the box is a row. A spacer at each end
   * carries the room that side has and the other gave up, so at most one of the two is
   * ever wider than nothing, and each gives way before anything else does. The drawing
   * between them centres while the three fit and starts at the box's edge once they
   * don't. Every child at its own size, none squeezed to make the row fit, and the box
   * scrolls what is left over. What the row holds is the drawing and the two spacers: a
   * widget declaring x-says as well as x-wide: drawing is refused at the registry door,
   * the word the layer would write here being an item beside the drawing rather than a
   * line above it.
   *
   * The spacers read --lf-grow, and read it differently from the box: its `100%` is the
   * holder of whatever reads it, which for the box is the column and for a spacer is the
   * row the box became. Read there, the growth on a free side is half of what the box
   * fell short of the room by — nothing on a page with no claim, since the box took the
   * whole room, and half of what the claimed side declined on a page with one, the claimed
   * side itself reading the 0px its claim wrote. Twice that is the spacer, on exactly the
   * side that should have one. */
  [data-lf-wide="box"] { --lf-reach: min(var(--wide), var(--lf-room, 0px)); }
  [data-lf-wide="drawing"] {
    --lf-reach: var(--lf-room, 0px);
    display: flex;
    justify-content: safe center;
    overflow-x: auto;
  }
  [data-lf-wide="drawing"]::before, [data-lf-wide="drawing"]::after {
    content: ""; flex: 0 1 auto;
  }
  [data-lf-wide="drawing"]::before { width: calc(2 * var(--lf-grow-l)); }
  [data-lf-wide="drawing"]::after  { width: calc(2 * var(--lf-grow-r)); }
  [data-lf-wide="drawing"] > * { flex: none; }
  /* A widget whose upgrade failed is showing the message and the source it choked on
   * (failSoft), and prose is the column's. The room it declared was for the drawing it
   * did not manage to make, so a parse error came out as a red slab across the whole
   * window with its message set on one 1600px line — the degrade path, which is the
   * worst place to be shouting. `.lf-error` is the layer's own word for this rather than
   * any widget's, so the next widget to fail soft is covered by having failed.
   *
   * The box is the message's holder here and not a clip, so the message fills it and
   * wraps. Both halves of that are said: a flex item is floored at its own content's
   * minimum unless told otherwise, and the source it holds is a `pre` that never wraps,
   * so the box came out as wide as the longest line — 854px of it in a 720px column,
   * scrolling, on the first real diagram source anyone fed it. The `pre` scrolls inside
   * the message instead, which is what a `pre` does everywhere else on the page. */
  [data-lf-wide]:has(> .lf-error) { --lf-room: 0px; }
  [data-lf-wide="drawing"] > .lf-error { flex: auto; min-width: 0; }
  /* A box that draws one of its own is a box a wide widget stays inside. The room is the
   * page's to give, and inside a disclosure or a callout the page is not what holds the
   * widget — a board that took the window from inside a <details> hung out over both
   * edges of the frame it was filed under, which reads as a broken page rather than as a
   * wide exhibit. Stated as no room rather than as an exception to the rule above, so the
   * widget falls back to the floor that rule already has and fills its holder exactly.
   *
   * A box declares that it frames what it holds in the rule where it draws the frame
   * (`--lf-frame`), and the room is the second thing the layer reads out of that one
   * declaration: whoever draws a box gets both by saying one thing, in the layer that
   * draws it, and a project's card is covered the day it says it. Two lists of tags said
   * it before, one here and one in packages/default/theme.css, and a list beside a declaration is
   * a copy of it — every tag in them declared the frame, five boxes that declared were in
   * neither, and `figure`, which draws no box at all, was withholding the room.
   *
   * `--lf-room` inherits, so one rule at a box's own children reaches a widget however
   * deep inside it sits, and `--lf-frame` is reset one level in (above), so no box
   * answers for its grandparent's frame.
   *
   * The column declares the frame too — it is a padded box like any other and its first
   * line wants the trim — so it hands the room straight back to what it holds. That is
   * the whole difference between the page and a box on it, and the gate says it the same
   * way, by walking up no further than `main`.
   *
   * A transparent wrapper declares nothing: a section and a tab's panel are the page's
   * own flow, and an exhibit breaking out through one is the point. What says so when a
   * box that draws has not declared is `version check --render`, which measures every
   * wide element against the nearest ancestor that draws one. It could not see through a
   * scroll container until a diagram in a board card was drawn 332px across the next
   * column, and four widgets letting a diagram out were found the day it could. */
  @container style(--lf-frame: 1) { * { --lf-room: 0px; } }
  main > * { --lf-room: inherit; }
}
@media screen and (max-width: 640px) {
  main { padding-top: 28px; padding-bottom: 72px; }
}
/* The headings are the body serif at weight, size and spacing — one voice, four
 * volumes — rather than a display face over a text face. A page whose subject is
 * a decision and whose furniture is diffs and boards has enough going on; the
 * hierarchy it needs is the one that survives being skimmed, which is size and
 * air, not contrast of family. */
h1 { font-size: var(--t-1); line-height: 1.16; letter-spacing: -0.014em;
     margin: 0 0 12px; text-wrap: balance; }
h2 { font-size: var(--t-2); line-height: 1.25; letter-spacing: -0.008em;
     margin: 48px 0 12px; text-wrap: balance; }
h3 { font-size: var(--t-3); line-height: 1.3; margin: 32px 0 8px;
     text-wrap: balance; }
p { margin: 13px 0; }
ul, ol { margin: 10px 0; padding-left: 24px; }
li { margin: 6px 0; }
a { color: var(--accent); text-underline-offset: 2px;
    text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent); }
a:hover { text-decoration-color: currentColor; }
/* lf-shadow:start */
.lf-external-mark { display: inline-block; width: .75em; height: .75em;
                    margin-inline-start: .24em; vertical-align: .03em;
                    fill: none; stroke: currentColor; stroke-width: 1.5;
                    stroke-linecap: round; stroke-linejoin: round;
                    overflow: visible; user-select: none; -webkit-user-select: none; }
/* lf-shadow:end */
hr { border: none; border-top: 1px solid var(--rule); margin: 40px 0; }
/* An identifier breaks where it must. A test name or a path is one word to the line
 * breaker, and a word a box cannot hold is either drawn past the box or holds the
 * box to its own width — in a table cell the latter: a column of 79-character test
 * names beside a column of prose held its column at 583px of the 720px measure, the
 * prose was squeezed to 118px and a few words a line, and the table ran 3174px tall
 * and scrolled 83px sideways for the rest. `anywhere` rather than `break-word`
 * because only `anywhere` counts the break when a box's minimum is measured, and a
 * table's columns are sized from exactly that: with it the same table stood
 * 112/352/256 and 1047px tall, scrolling nothing. On code and not on every cell,
 * because a cell's minimum is its longest word, and that is what keeps a column of
 * row names from being squeezed under the prose beside it — with every cell
 * breakable the same table's row names measured 55px. The minimum is what every
 * shrinking box is sized from, so a flex item or a grid track holding a long name
 * hands room to its neighbour the same way (a flex item measured 691px to 359px).
 * A block (pre) wraps nothing, so this reaches nothing there. */
code { background: var(--code-bg); border-radius: 4px; padding: 1px 5px;
       font-size: 82%; font-family: var(--mono); overflow-wrap: anywhere;
       box-decoration-break: clone; -webkit-box-decoration-break: clone; }
/* A code block is sized by how many characters it takes across, which is why its size
 * is off the serif ladder above. At --code-size, the column keeps comfortably more
 * than the 80 characters most source is written to.
 *
 * The size and leading are tokens because plain blocks, upgraded widgets, and the diff's
 * shadow tree must keep one density through upgrade. */
pre { background: var(--pre-bg); border: 1px solid var(--code-border); border-radius: var(--r);
      padding: 12px 14px; overflow-x: auto; font-size: var(--code-size);
      line-height: var(--code-line); font-family: var(--mono); color: var(--code-ink);
      font-variant-ligatures: none; }
pre code { background: none; padding: 0; font-size: 100%; }
/* Syntax roles. The runtime writes these into any code block that names a language —
   a <pre><code class="language-*"> or a lf-code with `language` — having collapsed the
   tokenizer's scopes into six of leaf's own first. Styled at document level like
   the marks, because they land on the page's own elements; one attribute rather than
   six classes, so the shared class vocabulary doesn't widen at all. A tokenizer swap
   costs one table in leaf.js and no page that has already shipped. */
[data-lf-syn="cm"] { color: var(--syn-comment); font-style: italic; }
[data-lf-syn="kw"] { color: var(--syn-keyword); }
[data-lf-syn="st"] { color: var(--syn-string); }
[data-lf-syn="nu"] { color: var(--syn-number); }
[data-lf-syn="fn"] { color: var(--syn-name); }
[data-lf-syn="ty"] { color: var(--syn-type); }
/* A diff's own lines take the tints lf-diff and lf-suggestion already carry, so an
   added line reads the same whichever of the three drew it. Ink only: these spans
   cover a line's text and not its box, and a background would print as a ragged
   half-width band. */
[data-lf-syn="ins"] { color: var(--ok-ink); }
[data-lf-syn="del"] { color: var(--danger-ink); }
blockquote { margin: 18px 0; padding: 2px 18px; border-left: 2px solid var(--rule);
             color: var(--muted); font-style: italic; --lf-frame: 1; }
figure { margin: 22px 0; }
figcaption { font-size: var(--t-6); color: var(--muted); margin-top: 8px; }
img, svg, video { max-width: 100%; height: auto; }
/* A table's columns hold what is in them, and the space between two of them is
 * one gutter wide. `width: 100%` bought the opposite: the browser's auto layout
 * spreads leftover width across every column, so a four-column survey on the
 * 720px measure ran 149/122/267/182 over content 95px and 52px wide, and the eye
 * crossed 124px of nothing to get from an attribute to its values.
 *
 * display:block is what buys it back, and a wide table's answer with it. The
 * grid inside a block box shrink-wraps, so a table takes the measure only when
 * its content asks for it, wraps its cells when the content asks for more, and
 * scrolls inside itself — like pre, like lf-board — when even the wrapping
 * can't fit. Nothing narrower does all three: overflow on a table box is
 * ignored outright, and a table that spills lands in the margin where a
 * suggestion's controls hang, having scrolled the page by nothing the render
 * gate can see at its own viewport width.
 *
 * The third case is reached through the second: a table scrolls once every
 * column is at its minimum, and a column's minimum is its longest unbreakable
 * run — so whatever wraps in a scrolling table wraps at a word a line, beside a
 * name that could not break (an identifier has nowhere to break until the rule
 * at `code` above gives it one) or because there are more columns than the
 * measure holds. `version check --render` refuses a table that scrolls with a
 * cell in it wrapped (SQUEEZED_TABLES) and leaves the third case to a table with
 * nothing left to wrap.
 *
 * Two things the display change could have cost, both measured rather than
 * assumed, and neither charged: Chrome's accessibility tree keeps table,
 * rowgroup, row, columnheader and cell through it, with or without an explicit
 * role, and a long table still breaks across printed pages, since a page box
 * fragments an overflow block rather than clipping it. What paper does lose is
 * a table too wide to wrap, which it loses either way — the same trade pre and
 * lf-board already make, and the reason not to write a print rule undoing this
 * one. */
table { display: block; overflow-x: auto; border-collapse: collapse;
        font-size: var(--t-5); margin: 18px 0; font-variant-numeric: tabular-nums; }
caption { text-align: left; font-size: var(--t-6); color: var(--muted);
          margin-bottom: 6px; }
th, td { text-align: left; padding: 8px 14px; border-bottom: 1px solid var(--rule);
         vertical-align: top; --lf-frame: 1; }
/* The padding is a gutter, and the columns at the two ends have no neighbour to
   keep away from: 10px of it there set every table's first word 10px right of
   the prose above it, and stopped the last column short of the same edge. */
tr > :first-child { padding-left: 0; }
tr > :last-child { padding-right: 0; }
/* Which kind of header a th is, asked of the author's own word for it rather
   than of where it sits: a header row written without a <thead> is still column
   headings, and `scope="row"` is what a row's name needs said anyway. Each rule
   says which kind it is for, so neither resets the other — a row's name is the
   page's words in the page's face, and shouting it in 11.5px small caps is what
   one rule for both did. */
th:not([scope="row"]) { font-size: var(--t-6); text-transform: uppercase;
     letter-spacing: .06em; color: var(--muted); font-weight: 600;
     border-bottom-color: var(--border-2); }
th[scope="row"] { font-weight: 600; }
details { background: var(--field); border: 1px solid var(--rule);
          border-radius: var(--r); padding: 8px 14px; margin: 18px 0; --lf-frame: 1; }
summary { cursor: pointer; font-weight: 600; font-size: var(--t-5); }
details pre { margin: 10px 0 6px; }
dl { margin: 10px 0; }
dt { font-weight: 600; }
dd { margin: 0 0 8px 0; }

/* The apparatus voice, said once per layer. Every label, caption, chip, badge and
 * column heading on the page is the page pointing at its own content rather than
 * saying something — so it takes the UI sans at a small size, usually tracked, and
 * the serif is left to carry what there is to read. Listing them in one rule is the
 * point: what counts as apparatus is a judgement, and a judgement made in twenty
 * places is twenty chances to answer it differently. This rule is the layer's own
 * words — the idioms and the fail-soft box; a package theme
 * (packages/default/theme.css, or any selected package's) states the same rule for the
 * words its widgets wear.
 *
 * This is a look, not a permission — the anchoring norm's distinction exactly. A
 * chip a widget says (data-lf-said) is still the page's words and still something
 * a user can select and quote; it is set in the sans because it reads as
 * machinery, not because it is the runtime's.
 *
 * Nothing a widget builds through `offer` belongs here, and the first draft had
 * four of them (a row's `for` reference, the settled row's count and Δ, a tab's
 * Δ). Those wear lf-ui, which already answers in the same face — so the rule was
 * inert, and it said the wrong thing where anyone read it: that the runtime's own
 * chrome is the page pointing at its content. This list is the page's words.
 *
 * Figures are part of the voice, because apparatus is where the page's quantities
 * live and a quantity here is one that moves — a task's done fraction, a metric's
 * value, a badge's count, each rewritten in place by a report the reader never
 * asked for. The sans sets its digits to their own widths, so a rewrite resizes the
 * box the number is set in — a chip is a filled pill, so that edge is visible on its
 * own — and moves whatever stands after it, which for a metric is the delta riding
 * against its value. Measured in this stack, `1,412` and `1,398` stand 4.6px apart at
 * --t-2 and `11,111` and `41,208` 15.5px, all four identical once the figures are
 * tabular. That is the movement CLAUDE.md's "Layout and motion" forbids,
 * in the form the norm calls worst — arriving on a poll, with no gesture behind it to
 * explain where the line went.
 *
 * The serif is left out because it needs nothing: Charter already sets every digit
 * to one width, so the same four strings measure identically with the property and
 * without it, and stating it there would be a declaration that could never be
 * wrong and never do anything. */
.eyebrow, .tag, figcaption, caption, th:not([scope="row"]), .facts dt,
.lf-error {
  font-family: var(--sans); font-variant-numeric: tabular-nums; }

/* The pill a small label rides in. These numbers are a contract across layers: the
 * default-package widgets' chips (lf-chip, a milestone's attribute row) restate them in
 * packages/default/theme.css so a band of chips and an inline .tag stand the same height —
 * they drifted four pixels apart once, when the inline label padded itself and
 * nobody had decided that. A wearer keeps only where it sits, and a tint of its
 * own where the tint is the point. */
.tag {
  display: inline-block; font-size: var(--t-6); line-height: 1.6; padding: 0 8px;
  border-radius: 999px; background: var(--chip); color: var(--ink-2); }

/* Pressable, said once per layer, and the pill above is what it is said against. A
 * chip that opens a section and a badge that counts something were the same object at
 * rest — one ground, one ink, one corner, one size — and the only page that said which
 * was which said it in prose. The reader had to press one to find out.
 *
 * The marker is the runtime's own, not a new one: `offer` and `selectableOffer` write
 * data-lf-offer on everything a widget builds to be worked, and three passes already
 * asked it before this one (print, the drag guard, the render gate). So the hand, the ground under the
 * aim, and the here ring are stated once against that attribute rather than restated by
 * each widget's rules — which is what makes them a layer fact. A widget family that
 * joins tomorrow wears all three with its entry and its module, having written no CSS,
 * and a family that wants its own says so in its own theme rules, which come after this
 * file in the merged sheet and outrank it at equal specificity.
 *
 * .tag takes none of it, and needs no exclusion to be left out: no `offer` made it. That
 * is the line the rule draws — not "does this look like a control" but "did a widget
 * build this to be worked", which is a fact the runtime holds rather than a judgement
 * a stylesheet re-makes.
 *
 * The ground and not the ink, because ink is what a widget spends on its own meaning:
 * an operation's press is inked by whether it is live, a pick's mark by whether it is
 * taken. A wash toward the ink leaves both of those readable and reads the same way on
 * the paper-white palette and the dark one — the joined option group's own answer to
 * this question, arrived at there for the same reason (packages/default/theme.css).
 *
 * An inset shadow rather than a background, because it composes instead of competing.
 * `background` is the one property a control's own dress is written in, and every layer
 * writes it: a chip states a fill, chrome's .lf-btn swaps one on hover, a package restates
 * both. A shared rule setting `background` has to out-specify all of them to be seen and
 * then wins against the ones that should have won — the aim wash landed on nothing at
 * all against `.lf-command-facts > [role="button"]`, which ties it exactly. The shadow is
 * painted over whatever fill the control wears, so the chip keeps its ground, the .lf-btn
 * keeps its swap, and both deepen by the same amount under the pointer. It is inset, so
 * it paints inside the padding box, follows the corner the control already has, and adds
 * nothing outside a rectangle the movement tests are watching.
 *
 * A spent press keeps its shape and gives up its opacity. That is the layer's one cue
 * for "there is nothing left to do here", and it is stated with the hand it withdraws so
 * the two cannot come apart: a one-shot request that had been answered still wore the
 * full-strength border of a live one and differed only in ink, which greyscale drops and
 * a reader scanning a column of eight of them never sees. Chrome's own .lf-btn says the
 * same pair for the same reason (chrome.css); this reaches the controls that are
 * not one.
 *
 * The ring is the fallback rather than the rule: every control with a ring of its own
 * outranks this, and what is left is the controls that were wearing the platform's
 * outline or, where a widget had restyled them, nothing at all. Named like every other
 * ring the layer draws, so the corpus floor can credit it (--lf-here-ring, above).
 *
 * Every rule here is written to be outranked. The value guard sits in :where() so it
 * costs nothing, which leaves each rule at the weight of the thing it is answering — the
 * ring at a plain attribute and a state, so lf-option's own pick ring and chrome's .lf-btn
 * ring both still win and keep their names. A floor is only a floor if what is built on
 * it comes out on top.
 *
 * The value and not the bare attribute, because `offer` writes two different facts into
 * one dataset key: "button" for a press it built, the role for a `selectableOffer`, and
 * the empty string for everything else it makes — the draft's controls row, its history
 * disclosure, its edit box, a generated form. Those are chrome a widget injected, not
 * things to press, and the bare attribute put the hand on a textarea and a wrapper div.
 * The distinction is the one `offer` already draws; this reads it rather than keeping a
 * list of the tags and roles that count, so a role a widget reaches for next year is a
 * pressable the day its module names it.
 *
 * Inside the shadow markers, because a widget declaring x-shadow builds its controls in
 * a tree the document's stylesheet does not reach, and a floor that stopped at the light
 * DOM would be a floor the newest kind of widget is the one to fall through. The slice is
 * copied into each declared root rather than moved out of this file, so one statement
 * dresses both sides and there is no second copy to drift. */
/* lf-shadow:start */
[data-lf-offer]:where(:not([data-lf-offer=""])) { cursor: pointer; }
[data-lf-offer]:where(:not([data-lf-offer=""])):hover:where(:not([aria-disabled="true"], :disabled)) {
  box-shadow: inset 0 0 0 100px color-mix(in srgb, var(--ink) 7%, transparent); }
[data-lf-offer]:where(:not([data-lf-offer=""])):is([aria-disabled="true"], :disabled) {
  cursor: default; opacity: .55; }
[data-lf-offer]:where(:not([data-lf-offer=""])):is(:focus-visible, .lf-focus-visible) {
  outline: var(--here-ring); --lf-here-ring: pressable;
  outline-offset: var(--here-ring-gap); }
/* lf-shadow:end */

/* ---------- class idioms ---------- */

.eyebrow { font-size: var(--t-6); letter-spacing: .1em; text-transform: uppercase;
           color: var(--muted); font-weight: 500; margin: 0 0 10px; }
/* An eyebrow and the heading below it are one title: the heading level's large top
   margin belongs before the pair, while the eyebrow's bottom margin owns the small gap
   inside it. The contents map may put its zero-height fragment target between the two;
   generated navigation must not change the authored rhythm. */
.eyebrow:has(+ h2), .eyebrow:has(+ .lf-toc-target + h2) { margin-top: 48px; }
.eyebrow:has(+ h3), .eyebrow:has(+ .lf-toc-target + h3) { margin-top: 32px; }
.eyebrow + :is(h2, h3),
.eyebrow + .lf-toc-target + :is(h2, h3) { margin-top: 0; }
/* The one paragraph a reader is guaranteed to read, so it is set as one: larger
   than the body, looser, and in the ink the body isn't. */
.lede { color: var(--ink-2); font-size: var(--t-3); line-height: 1.5;
        margin: 0 0 10px; }
/* Riding in a line of prose is all this adds to the pill above. */
.tag { vertical-align: middle; }
/* A tinted field with a hairline border — never a left-accent bar. What sits in it is the
   page's own prose at the page's own size, so the tint is the whole of the marking and
   this says nothing about size at all. It held 16px once, a pixel under the body around it
   for a difference no reader could see; stating --t-4 instead was the same number in a
   token, true and inert, and a second place the body's size had to be kept. */
.callout { background: var(--field); border: 1px solid var(--rule);
           border-radius: var(--r); padding: 12px 16px; margin: 18px 0; --lf-frame: 1; }
/* A sidebar is page-level supporting material rather than an annotation on one block:
   local navigation, a compact legend, or stable reference facts. In ordinary flow it is
   simply an aside where it was authored. On a roomy screen its box moves into the left
   strip and sticks beneath Leaf's banner, so it remains useful through a long page. The
   negative left margin and the right gutter sum with its width to zero, leaving the
   prose's line boxes untouched; the shell's left claim is the room the box uses.

   The claim is page-wide because a sticky box may occupy any height while the reader
   scrolls. A wide exhibit therefore gives up its left growth while the sidebar stands;
   subtracting the strip from --lf-room alone still lets symmetric growth cross the
   gutter. A sidebar and a sidenote together wait for 1416px of shell, the ordinary
   1152px margin floor plus the sidebar's 264px; granting both at the ordinary floor
   shrank the prose to 504px. The paired number is held to those two tokens in
   test_the_sidebar_and_note_floor_is_their_sum. Paper gets only the base in-flow form,
   and therefore neither a sticky box nor an empty margin.

   Direct-child margins are trimmed because a sidebar is a placement wrapper, not a
   second rhythm around what it holds. This keeps an lf-toc's quiet spine and makes the
   class equally usable around a nav, facts list, or short prose aside. Only the first
   direct sidebar child of main takes the margin. The catalog asks for one page-level
   wrapper, but leaving an accidental second one in flow is safer than laying two sticky
   boxes over each other. */
aside.sidebar { display: flow-root; margin: var(--sp-4) 0 30px; }
aside.sidebar > :first-child { margin-top: 0; }
aside.sidebar > :last-child { margin-bottom: 0; }
@media screen {
  @container lf-shell (min-width: 1152px) {
  html:not(.lf-copy)
    main:has(> aside.sidebar):not(:has(aside.sidenote)) {
    --strip-l: var(--sidebar);
    /* Keep the reading column on the page's axis while both margin residents fit in
       its existing gutters. If they need more room, spend the outer page edges and
       shift only far enough to keep each resident on screen before narrowing prose. */
    --lf-sidebar-edge: clamp(0px,
      calc((100cqi - var(--strip-l) - var(--strip-r) - var(--col)) / 2),
      var(--col-pad));
    --lf-room: max(0px, calc(100cqi - var(--strip-l) - var(--strip-r)
      - 2 * var(--lf-sidebar-edge)));
    --lf-gutter: calc((100cqi - min(var(--col), var(--lf-room))) / 2);
    --lf-shift: calc(
      max(0px, var(--strip-l) + var(--lf-sidebar-edge) - var(--lf-gutter))
      - max(0px, var(--strip-r) + var(--lf-sidebar-edge) - var(--lf-gutter)));
    & [data-lf-wide] { --lf-grow-l: 0px; }
  }
  html:not(.lf-copy) main:not(:has(aside.sidenote))
    > aside.sidebar:nth-child(1 of aside.sidebar) {
    float: left; clear: left; position: sticky;
    --lf-sidebar-posture: margin;
    top: calc(var(--lf-banner-h, 0px) + var(--sp-4));
    width: calc(var(--sidebar) - var(--sp-4));
    max-height: calc(100vh - var(--lf-banner-h, 0px) - 2 * var(--sp-4));
    overflow-y: auto;
    margin: 0 var(--sp-4) var(--sp-4) calc(-1 * var(--sidebar));
  }
  }
  @container lf-shell (min-width: 1416px) {
  html:not(.lf-copy)
    main:has(> aside.sidebar):has(aside.sidenote) {
    --strip-l: var(--sidebar);
    & [data-lf-wide] { --lf-grow-l: 0px; }
  }
  html:not(.lf-copy) main:has(aside.sidenote)
    > aside.sidebar:nth-child(1 of aside.sidebar) {
    float: left; clear: left; position: sticky;
    --lf-sidebar-posture: margin;
    top: calc(var(--lf-banner-h, 0px) + var(--sp-4));
    width: calc(var(--sidebar) - var(--sp-4));
    max-height: calc(100vh - var(--lf-banner-h, 0px) - 2 * var(--sp-4));
    overflow-y: auto;
    margin: 0 var(--sp-4) var(--sp-4) calc(-1 * var(--sidebar));
  }
  }
}
/* What the margin is for is in the catalog beside the class; this is why it is the right
   margin, what shares it, and what the strip costs.

   The right is where a reader's eye leaves the line, which is where marginalia has been
   set for as long as there has been marginalia, and the left is where the eye returns to
   start the next one — so a note there sits in the return path of every line of the
   column beside it. The page reads as one axis rather than two because of it: the column
   hangs off the strip, the strip is half the distance the column sits off the window's
   centre, and both are the one number above.

   What else stands out there is the loop's, and it is not asked to move. A suggestion's
   accept and reject controls hang level with the change they decide, a note hangs level
   with the block it annotates, and both are pinned by the flow, so neither can step
   aside for the other: where a page puts them level, the controls are drawn over the
   note's first line. That is a decision rather than a defect. The alternatives were each
   worse — a rail stacked past the note puts the press the whole width of a note away
   from the change it settles, and a note that dodged would be marginalia that moves when
   a change lands near it — and the overlap costs one line of a note that is read where
   it stands, against a control that is read where it is reached for. `version check
   --render` is told, in the one place it can be told: chrome a widget hangs out of the
   flow may cover the page's words (coveredWords, in render-checks/standalone.js), which
   is the exemption the runtime's own floating layer already had, said for whoever owns
   the float.

   The composer opens out there too and covers a note whole while it stands, which is a
   box the reader summoned and dismisses. The panel takes that side of the window
   entirely, and the note does not give way to it: both the strip and the column come out
   of the box the panel leaves, so a note moves exactly as far as the paragraph it
   annotates and no further.

   The strip is a claim on the shell, so the column centres in what is left rather than
   hanging the note in whatever the centring happened to leave over. A panel or tray
   narrows that named container, and the same query therefore returns the note to flow
   only when the page itself no longer has room.

   The breakpoint below is that same width asked of the window; under it the strip would
   come out of the column's own width. Under it, and on paper, the note is a small
   indented block where it was written. Paper has no margin to hang one in — 768px is 8
   inches at 96 to the inch, against 8.5 for Letter and 8.27 for A4 before either takes a
   page margin — and cannot drop the note either, the words being the page's own, which
   the render gate holds it to by reading both media. */
aside.sidenote { font-size: var(--t-5); line-height: 1.45; color: var(--muted);
                 margin: 12px 0 12px var(--sp-4); }
@media screen {
  @container lf-shell (min-width: 1152px) {
  main:has(aside.sidenote) {
    --claim-note: var(--note);
    /* The whole strip is the claim, even where a centred column already leaves enough
       room to paint the note. The strip is the page's axis as well as the note's measure:
       reserving it is what makes the arrangement read as a column with a right margin
       rather than a centred column with something left over beside it.

       An exhibit and a note both want the right margin, and only one of them can have it
       at a given height. The note hangs a gutter off the column while the strip comes out
       of the far edge of the page, so a board grown to the strip is drawn over the note it
       stands level with.

       The collision is a fact about one height, so the answer is stated at that height. A
       wide widget that would have been drawn over a note drops below it and then takes the
       whole margin; one no note reaches keeps its place and grows both ways, which is the
       layout a page with no note at all already has. Refusing the margin page-wide answers
       the same collision by never having it, and charges every exhibit on the page for a
       note somewhere above it: measured, one note near the top of a page held a diagram
       977px below it to the column's own width and clipped 286px of it away, with the
       margin beside the diagram empty the whole time.

       `clear` says this and the browser already knows how: the note is a float, floats have
       a flow of their own, and clearing one is how a block declines to share its band. It
       needs no measurement, so an exported copy that runs no script gets the same answer as
       the live page. Inside the rule with the strip it claims, because they are one
       condition — a cramped page has handed the strip back and its notes are indented
       blocks in the flow, so there is no float out there to clear and no margin to take.

       Only the note. The rail claims this side too for a suggestion's controls, which
       are positioned rather than floated, so `clear` cannot see them; the module that
       hangs them measures the same collision instead, and the rule beside
       .lf-sug-actions spends its answer.

       Every wide element, including one inside a box that withheld the room from it. A
       widget with no room has no negative margin and could not have reached the note, so
       clearing buys it nothing and costs it the drop — 11px, measured, for a diagram in a
       disclosure level with a note. Asking which elements have room needs the element's
       own value and a style query answers for its container, so the alternative is a
       second reading of the room rather than a tighter rule. */
    & [data-lf-wide] { clear: right; }
  }
  /* The pull reaches the page's margin through any box between that doesn't clip, which
     is a section, a tab panel, a disclosure. Through one that does — a choose group, a
     board, a table — the note is drawn nowhere at all, and the reader is the only party
     who loses it: checkVisibility() is true of a clipped box, so screen and paper agree,
     and the copy withholds the clip and shows the words the live page dropped. Scoping
     the float to what it may float out of would answer that and cost the cases that
     work, a tab panel clipping nothing, so MISPLACED_BOXES carries a reading for it and
     the version is refused at handover instead.

     No margin-top. The float lands at the foot of the preceding block's bottom margin,
     so it comes out level with the block it precedes wherever that block's own top
     margin is the smaller of the two — every text block here, within three pixels — and
     sits above one that carries more room over it than the block before it left, which
     is what a heading does. A margin-top matched per neighbour would be this file's own
     margins restated in a second table free to disagree with the first. Aligning the
     two first baselines would want about 4px besides, and that is an ascent difference
     between two faces at two sizes — a fact about Charter that DejaVu answers
     differently, for a shift nobody can see across a 24px gutter. `clear` is what
     stacks a second note under the first rather than over it.

     The in-flow form above is the whole fallback. The shell query grants the margin on
     both a live page and a script-free copy, with no runtime state to mirror. */
  main aside.sidenote {
    float: right; clear: right; width: calc(var(--note) - var(--sp-4));
    margin: 0 calc(-1 * var(--note)) 12px 0; }
  }
}
.facts { display: grid; grid-template-columns: max-content 1fr; align-items: baseline;
         gap: var(--sp-1) var(--sp-3); margin: 14px 0; }
.facts dt { color: var(--muted); font-weight: 400; font-size: var(--t-5); }
.facts dd { margin: 0; }
@media screen and (max-width: 640px) {
  /* A long term must not spend most of a phone's line on the first column and leave
     its explanation as a one-word ribbon. Stack each fact while the reading column is
     narrow; later terms keep the ordinary block rhythm through the row gap. */
  .facts { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .facts dd + dt { margin-top: var(--sp-2); }
}
/* A column of quantities lines up on its last digit — the comparison a table of
   numbers is there for, and one tabular figures alone don't make. Said per cell,
   heading included, because which column holds quantities is the author's to
   declare: "60" and "60 sessions" are one shape and two different things, and a
   pass that read the text would be guessing at the difference. */
th.num, td.num { text-align: right; }
ol.steps { list-style: none; counter-reset: step; padding-left: 0; }
ol.steps > li { counter-increment: step; position: relative; padding-left: 34px;
                margin: 10px 0; }
/* The step's own number, off the ladder for the reason the ladder states: it is set
   against a 21px disc rather than against the prose, so it is a fit and says so here. The
   apparatus rung would fill the disc; the room is what is scarce, as it is for the pick
   mark's ✓ and the keyboard address's digit. */
ol.steps > li::before { content: counter(step); position: absolute; left: 0;
                        top: 2px; width: 21px; height: 21px; border-radius: 50%;
                        background: var(--accent); color: var(--card); font-size: 12px;
                        font-weight: 600; display: grid; place-items: center; }

/* The three durable-state bands below are the whole of what says a decision has moved
   without the reader touching it, and each is the only carrier of its own fact. They were
   washed toward the paper — 40%, 50% and 55% of their token — which put them at 1.94:1,
   1.98:1 and 1.94:1 against the light paper: under the 3:1 a band drawn instead of a word
   has to clear, and a band nobody sees is a state nobody has been told about. Each is
   mixed to that floor instead, with room: 3.59:1, 3.37:1 and 3.25:1 light, 4.51:1, 5.64:1
   and 7.15:1 dark.

   Three percentages rather than one, because the three tokens sit at different luminance
   against the same paper and a shared percentage would buy each of them a different
   visibility — the fault this is fixing. Light is the binding scheme for all three.

   None of them goes to the token whole, and that is the accent's constraint speaking for
   all three: a restated band at 2px solid --accent is the here ring, glyph for glyph, and
   the layer's ring reading tells one outline from another by its resolved colour
   (test_the_ring_reading_tells_a_ring_from_the_layers_other_outlines). A band that became
   the ring would be credited as one on a box the keyboard can never light.

   Something a version restated: it rewrote words the user had decided on, so
   the runtime dropped what they recorded and is asking again. Without the tint,
   a decision undone looks exactly like one never made — the user would find
   it by rereading sixty drafts. Why it was undone belongs in the changelog note,
   where a version explains itself. The runtime sets this, from the log; the
   author's word is `restated` on the element. */
[data-lf-restated] { outline: 2px solid color-mix(in srgb, var(--accent) 70%, transparent);
                     outline-offset: 3px; border-radius: 2px; }

/* Effective state supplied by the reader log instead of authored input — a moved
   card, an edited draft, a pick the source did not mark. For recorded state, the
   runtime compares the log's fold with captured authored facets in one shared pass;
   a recordless decision remains reader-supplied while its holder stands. Green, the
   reader's color: the outline says who constructed the visible state; work receipts
   separately say whether anything remains to process or complete. */
[data-lf-reader-override] { outline: 2px solid color-mix(in srgb, var(--ok) 82%, transparent);
                    outline-offset: 3px; border-radius: 2px; }

/* A worker's standing report: this element's state arrived through the log
   (`leaf report`) and no version has answered it yet. Provisional news
   rather than a decision — amber and dashed, so it never reads as the user's
   green, and it clears the moment a version absorbs or overrules the report
   (the note's `settles` targets of kind `report`). The runtime sets this from the log; the
   answering version's word is `overruled` on the element, or simply writing
   the reported state. */
[data-lf-reported] { outline: 2px dashed color-mix(in srgb, var(--warn) 92%, transparent);
                     outline-offset: 3px; border-radius: 2px; }

/* The shared boxes of a registry-declared widget conversation. The widget places it.
   The same Thread view may be seated inside an x-thread-surface shadow tree, so this
   whole vocabulary is carried through the shadow extraction boundary. */
/* lf-shadow:start */
/* A thread mark's accessibility control lives beside the datum it names. The chrome
   stylesheet states this contract for light DOM; repeat it in the shared shadow slice
   because document selectors cannot cross into a declared widget tree. Its transparent
   pixel remains a real pointer target, while keyboard focus gives it the same visible
   skip-link face as the document copy. */
.lf-mark-note { appearance: none; box-sizing: border-box; position: absolute;
          width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden;
          border: 0; background: none; color: inherit; font: inherit;
          user-select: none; -webkit-user-select: none; opacity: 0; }
.lf-mark-note:is(:focus-visible, .lf-focus-visible) { position: fixed; z-index: 9050;
          top: calc(var(--lf-banner-h) + 6px); left: 8px;
          width: auto; height: auto; padding: 6px 10px; overflow: visible; opacity: 1;
          border: 1px solid var(--accent); border-radius: var(--r); background: var(--card);
          color: var(--ink); box-shadow: 0 8px 24px var(--shade); }
.lf-conversation { display: none; margin-top: var(--sp-2); overflow-wrap: anywhere; }
.lf-conversation-thread { min-width: 0; font-family: var(--sans); font-size: var(--t-5);
          line-height: var(--lf-ui-lh); color: var(--ink); overflow-wrap: anywhere; }
.lf-say { display: none; align-items: flex-end;
          gap: var(--sp-2); margin-top: var(--sp-2); }
.lf-conversation-thread > .lf-say:not([hidden]) { display: flex; }
.lf-say textarea { flex: 1; min-width: 0; }
.lf-conversation-thread > .lf-say { flex-direction: column; align-items: stretch; }
.lf-conversation-actions, .lf-conversation-resolved { display: flex;
          align-items: center; justify-content: space-between; gap: var(--sp-2); }
.lf-conversation-actions .lf-resolve { margin-left: auto; }
.lf-conversation > .lf-say { margin-top: 0; }
.lf-conversation-thread + .lf-conversation-thread {
          border-top: 1px solid var(--rule); margin-top: var(--sp-3); padding-top: var(--sp-3); }
.lf-conversation-msg { margin: var(--sp-2) 0; }
.lf-conversation-head { display: flex; align-items: baseline; gap: var(--sp-2);
          font-size: var(--t-6); }
.lf-conversation-msg.claude .lf-conversation-head b { color: var(--accent); }
.lf-conversation-head time { color: var(--muted-2); }
.lf-conversation-head .lf-edited { color: var(--muted-2); }
.lf-conversation-body { margin-top: 2px; }
.lf-conversation-body > :first-child { margin-top: 0; }
.lf-conversation-body > :last-child { margin-bottom: 0; }
.lf-drawing-reference { display: block; margin-top: 2px; color: var(--muted-2);
          font: 500 var(--t-6)/1.35 var(--sans); }
.lf-conversation-open { margin-top: var(--sp-2); }
.lf-conversation-resolved { margin-top: var(--sp-2); color: var(--ok); }
.lf-conversation-summary { padding: 8px 10px; color: var(--ok); cursor: pointer;
          font-weight: 600; }
.lf-conversation-thread[open] > .lf-conversation-summary { margin-bottom: var(--sp-2);
          border-bottom: 1px solid var(--rule); }
.lf-conversation-thread > .lf-conversation-summary[hidden] { display: none; }
.lf-conversation-thread .lf-btn { font: inherit; }
.lf-conversation-thread textarea { box-sizing: border-box; padding: 8px 10px;
          border: 1px solid var(--border-2); border-radius: 6px; background: var(--card);
          color: inherit; font: inherit; resize: none; field-sizing: content;
          max-height: 50vh; overflow-y: auto; }
.lf-conversation-thread :is(.lf-btn, textarea, summary):is(:focus-visible, .lf-focus-visible) {
          outline: var(--here-ring); outline-offset: 1px; --lf-here-ring: conversation; }
@media print {
  .lf-conversation-thread,
  .lf-conversation-thread :is(.lf-conversation-msg, .lf-conversation-resolved) {
          display: block !important; }
  .lf-conversation-thread :is(.lf-say, button, .lf-receipt), .lf-mark-note {
          display: none !important; }
}
/* A reaction chip and its trigger wear the chrome's pill face. That face is written in
   the chrome stylesheet, which no declared shadow root sees, so a widget's own thread
   outlet drew the platform's button instead: on the dark scheme its ButtonFace grey put
   the muted word at 1.86:1. Repeated here with the reset it needs, the way .lf-mark-note
   above repeats its own. */
.lf-pill { appearance: none; margin: 0; padding: 0 8px; white-space: nowrap;
          border: 1px solid var(--border-2); border-radius: 999px;
          background: var(--card); color: var(--ink-2);
          font: inherit; font-size: var(--t-6); line-height: 1.7; }
.lf-pill:is(button, [role="button"]) { cursor: pointer; }
.lf-pill:is(button, [role="button"]):hover { background: var(--chip); }
.lf-pill:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring);
          --lf-here-ring: pill; outline-offset: 1px; }
.lf-react-trigger { color: var(--muted); }
.lf-react-palette { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.lf-react-open > .lf-react-trigger { display: none; }
.lf-react-strip:not(.lf-react-open) > .lf-react-palette:not(:has(> [aria-pressed="true"])) {
          display: none; }
.lf-react { display: inline-flex; align-items: center; justify-content: center; gap: 4px;
          min-width: 26px; }
.lf-react > .lf-react-word { display: none; }
.lf-react[aria-pressed="true"] > .lf-react-word { display: inline; }
.lf-react[aria-pressed="true"] { background: var(--chip); }
.lf-react[aria-busy="true"] { opacity: .55; }
.lf-react-strip { display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
          margin-top: 6px; }
.lf-react-palette > .lf-react:not(.lf-margin-button, [aria-pressed="true"]) { color: var(--muted);
          border-color: transparent; background: transparent; }
.lf-react-palette > .lf-react:not(.lf-margin-button, [aria-pressed="true"]):is(:hover, :focus-visible,
          .lf-focus-visible, [aria-busy="true"]),
.lf-react-open .lf-react-palette > .lf-react:not(.lf-margin-button, [aria-pressed="true"]) {
          color: var(--ink-2); border-color: var(--border-2); background: var(--chip); }
/* Where a subject has no page edge of its own, one receipt grows beneath the reader
   move it acknowledges: Sent, Picked up, then Active when an explicit work claim names
   that subject. This is the panel-local and frozen-conversation fallback; page targets
   present the same projection through their existing margin Button. The state wraps;
   the age and the explicit silence word do not. A phase change is a change of words
   and of the Active ink, with no motion: the line answers a question the reader
   already asked, and a tint that replays is a flash.
   The shadow markers carry the same rule into any declared tree an authored subject
   is staged into; they remain ordinary comments in the document stylesheet. */
.lf-receipt { display: flex; gap: 6px; align-items: flex-end; clear: both;
  width: 100%; box-sizing: border-box; grid-column: 1 / -1;
  margin: var(--sp-2) 0 0; padding: 3px 8px; font-size: var(--t-6); color: var(--muted);
  border: 1px solid var(--border-2); border-radius: 6px;
  background: color-mix(in srgb, var(--field) 72%, transparent); }
.lf-receipt-state { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.lf-receipt.is-active .lf-receipt-state { color: var(--accent); }
.lf-receipt .lf-receipt-quiet { flex: none; color: var(--warn-ink);
  background: var(--warn-tint); border-radius: 3px; padding: 0 4px; white-space: nowrap; }
.lf-receipt time { color: var(--muted-2); white-space: nowrap; }
/* The runtime's mark on a static box whose computed overflow scrolls (reachScrollers,
 * for what escaped such a box and why the mark is read from the composed page rather
 * than declared here beside each overflow), so no rule in this file or a package's
 * states a position for its scroller's sake. Inside the shadow markers because the
 * sweep enters every declared tree, and a diff's lines scroll in one. No offsets:
 * relative moves nothing. */
[data-lf-holds] { position: relative; }
/* lf-shadow:end */
@media screen {
  html:not(.lf-copy) {
    /* :not([hidden]), because a caller may take the box behind a collapse (a settled
       group takes it with its options) — the display here would outrank the
       attribute's own hiding. */
    .lf-conversation:not([hidden]) { display: block; }
    .lf-say:not([hidden]) { display: flex; }
  }
}

/* lf-suggestion / lf-old / lf-new: a proposed change to content the user has seen. The
 * wrapper takes the form its content takes — inline among the words for a change of a
 * phrase, block around the slots for one of whole paragraphs — so a suggestion sits
 * mid-sentence or wraps whole sections without disturbing either flow, and either way
 * the change is one box. The slots carry the marks. A decision is the end of the matter
 * visually: the settled slot loses every mark and reads as ordinary prose, and a
 * suggestion with nothing left to show disappears.
 *
 * It generated no box at all once (display: contents), which is this same reading of
 * "follow the content" with the box left out — and a box is what anything asking where
 * the change is has to have. An element generating none measures (0,0) at the document's
 * origin, which is not a degenerate answer but a wrong one, naming the top of the page.
 * Four consumers met that separately and each worked around it where it stood: the ring
 * had nothing to hang on, the Ask walk's travel centred the document, a container's edge
 * rule reached past the wrapper to the slots, and the widget prepends a span to itself
 * for its controls to anchor from. None of the first three arises here now. The fourth
 * outlived the reason it was written for and earns its place on another: what a widget
 * builds for itself is what it can rely on, and which form this wrapper takes is a
 * stylesheet's to say — a layer restyling it boxless would take the controls off the
 * page altogether (see lf-suggestion.js). A wrapper that draws nothing still has to be
 * somewhere.
 *
 * Having a box also puts the wrapper in front of the render gate's floors, and the
 * width floor is written for widgets that reserve a region. This one's box is its
 * content's in both forms, words included — a one-word swap is ~30px and correct — so
 * the entry declares x-inline, which is the key that names whose floor is whose. */
lf-suggestion { display: inline; }
lf-old, lf-new { border-radius: 3px; padding: 0 3px; }
/* --ink-2, not --muted: the strike and the tint already say retired, and muted on
 * the del tint reads 4.31:1 at body size — under the 4.5 the contrast sweep holds
 * every reader-facing word to. The corpus's first inline delete is what surfaced it. */
lf-old { background: var(--del-tint); color: var(--ink-2);
         text-decoration: line-through; text-decoration-color: var(--danger); }
lf-new { background: var(--add-tint); }
/* The words that moved, deepened against the slot's own tint: the module's ranges
 * through the highlight registry (lf-suggestion.js #emphasize), so no node is
 * wrapped and a dead copy simply keeps the whole-slot tints. Layout-free
 * properties only, which is all ::highlight() may carry. */
::highlight(lf-sug-del) { background-color: color-mix(in srgb, var(--danger) 30%, transparent); }
::highlight(lf-sug-ins) { background-color: color-mix(in srgb, var(--ok) 26%, transparent); }
/* Which form a slot takes is asked of the platform's own closed set, inverted: any
 * child that is not phrasing content makes the slot a block. Enumerating the block
 * side named every shipped widget in the integrated layer — the closed list the norms
 * forbid, silently inline for the first project-layer widget staged in a slot, whose
 * fold then dropped it in the frame of the press. Phrasing is the list that cannot
 * grow: a custom element is never in it, so a block widget from any layer is covered
 * unnamed. The marker at the end is the other direction's residue, and the inversion's
 * one wrong answer: an inline widget is a custom element too. Which widgets those are is
 * the registry's to say (x-inline) and a stylesheet cannot read it, so the runtime paints
 * the declaration where a selector can reach it (data-lf-inline, leaf.js markDeclared).
 * Four widget names stood here instead, one of them a standard chip's — a shipped tag in
 * the integrated theme, and the layer that most needed the answer, a project's own, was
 * the one layer it could never be given for. What the tag list bought that the marker
 * does not is the page that never runs the runtime: unpainted, an inline widget in a
 * slot reads as block there. No shipped script-free page stages one, and the price of
 * keeping that case was the closed list itself.
 *
 * In :where(), because :not() and :has() both take the specificity of the most specific
 * thing inside them, and a bare attribute selector is a whole class-column above the type
 * names it stands among. The list is a question about the content, not a claim on the
 * cascade, and the answer wearing a class column outranked the marks that answer over it:
 * this rule's own block display beat [data-lf-retired]'s `display: none`, so a decided
 * suggestion kept the slot it had just retired on the page. :where() zeroes that argument
 * and leaves the list weighing what the tag names weighed.
 *
 * The platform half is that set quoted whole, `link` and `meta` included, which no
 * slot will ever hold and which render nothing if one does. Quoting it whole is what
 * makes it checkable: the test states HTML's phrasing content once and holds both
 * copies to it, where a set filtered by what seemed worth keeping could only ever be
 * checked against itself — which is the check the two copies were already giving each
 * other, and it cannot see a name dropped from both.
 *
 * The block form's room is above the slot rather than around it, so a run of changes
 * reads as a stack. That was once the only room the slots could ask for: while the
 * wrapper was boxless they were the flow's own boxes, their outer margins were what a
 * container read at its own edge, and a quoted change stood 10px inside the gutter
 * marking it with nothing able to reach it — a rule for the specimen's last child found
 * the suggestion, and the suggestion had no box. The wrapper is that box now, and the
 * room stays on one side because it is the better answer anyway: it costs the pair
 * nothing, the gap between two slots and between two suggestions being the second one's
 * either way. Nor does it cost the prose around a change: collapsing already took the
 * larger of this 10px and the 13px a paragraph reserves, so the side that went was one
 * no reader ever saw.
 *
 * Both slots take the block form together, the wrapper being what asks the question:
 * what the reader is deciding is one change, not two halves with their own layouts. A
 * paragraph replaced by a phrase used to render as a full-width struck field with a
 * three-word pill under it, which is what a suggestion looks like when each slot
 * answers for itself.
 *
 * The padding then frames what the slot holds, so the slot says so: a block change is a
 * whole paragraph in a tinted field, and the 2px it states came out 15 at each end on
 * every one in the corpus. */
lf-suggestion:has(> :is(lf-old, lf-new) > :not(a, abbr, area, audio, b, bdi, bdo, br,
    button, canvas, cite, code, data, datalist, del, dfn, em, embed, i, iframe, img,
    input, ins, kbd, label, link, map, mark, math, meta, meter, noscript, object,
    output, picture, progress, q, ruby, s, samp, script, select, slot, small, span,
    strong, sub, sup, svg, template, textarea, time, u, var, video, wbr,
    :where([data-lf-inline]))) {
  display: block;
  & > :is(lf-old, lf-new) {
    display: block; padding: 2px 10px; margin-top: 10px; --lf-frame: 1; }
}
/* Decided: the surviving slot is plain prose, the other one gone. The retired one is
 * folded away by the widget rather than dropped in a frame (lf-suggestion.js), and the
 * survivor gives up its padding over the same span — a block slot's 10px is the sentence
 * the reader is looking at stepping sideways, which is the jerk the fold is there to
 * remove, only smaller. Declared on the slot rather than on the decided state, because a
 * transition is read from the state the element is leaving; the reduced-motion guard at
 * the foot of this file takes it with everything else.
 *
 * Padding alone. The tint going is paint, which a state change may do freely, and a
 * transitioned background is the thing the choose group's own comment above warns
 * about: the tokens themselves move when the reader's system flips to dark, so every
 * slot on the page would animate from one palette to the other for a change nobody
 * made. */
lf-old, lf-new { transition: padding .22s ease; }
lf-suggestion[data-lf-state] > :is(lf-old, lf-new) {
  background: none; color: inherit; text-decoration: none; padding: 0; }
/* A slot the standing decision retired, marked by the runtime from the registry's own
 * relation (data-lf-retired, leaf.js renderRetired). One rule for every family, so a
 * holder a project declares hides what a settlement removes the day it declares it —
 * the by-name pair that stood here was the closed list wearing CSS's clothes. A
 * module's fold outranks this with its inline display for the length of the motion,
 * and an exported copy keeps marker and rule with no module behind them. What no
 * relation can say stays the family's own, like the emptied wrapper below. */
[data-lf-retired] { display: none; }
lf-suggestion[data-lf-state="accept"]:not(:has(lf-new)),
lf-suggestion[data-lf-state="reject"]:not(:has(lf-old)) { display: none; }
/* A pending suggestion still has to say it is proposed when generated controls are
 * absent. On screen the ✓/✗ row carries that fact and this word stays clipped for
 * whoever is listening. A static copy and paper expose the word #voice already writes
 * in each slot, so the proposal remains distinguishable from settled content without
 * adding another label or moving it elsewhere.
 *
 * The page the markup describes is the base, and the live page's clipped version goes
 * inside the screen guard. `user-select` is not touched: this is the runtime's reading
 * of the paint rather than authored prose, so copying a published paragraph must not
 * carry the word with it.
 *
 * inline-block, because lf-old is struck and CSS runs a decoration through every
 * in-flow inline descendant — a descendant cannot cancel it, and `text-decoration:
 * none` here is inert. Unclipped as a plain inline, the one word saying the change has
 * *not* been made was itself painted struck in the deletion's red, which is the reading
 * this whole rule exists to prevent. An atomic inline is where the line stops. */
lf-suggestion:not([data-lf-state]) > :is(lf-old, lf-new) > .lf-quiet {
  position: static; width: auto; height: auto; overflow: visible; clip-path: none;
  display: inline-block; margin-right: 5px; }
@media screen {
  html:not(.lf-copy) lf-suggestion:not([data-lf-state]) > :is(lf-old, lf-new) > .lf-quiet {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); margin-right: 0; }
}
/* A suggestion's contribution is an unpositioned group inside the shared target cluster.
 * Its only theme rules are the semantics of the decision controls; placement, docking,
 * packing, and the focus-ring allowance belong to .lf-margin-item below. */
.lf-sug-actions { display: inline-flex; align-items: center; gap: 4px;
    white-space: nowrap; }
/* The living margin is a retained projection with one cluster per page target. Its
 * primary Button, optional `…`, and the secondary Buttons that ellipsis unfolds share
 * one host. One packing pass keeps the clusters clear, docks each whole unit when the
 * margin is too narrow, and tells wide exhibits which occupied bands they must yield. */
.lf-living-margin { position: absolute; z-index: 2; pointer-events: none; }
.lf-living-margin[hidden] { display: none; }
.lf-margin-toolbar { position: absolute; inset: 0; }
.lf-margin-item { position: absolute; z-index: 2; left: 100%; margin-left: 22px;
    display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
    padding-right: var(--here-ring-room); pointer-events: auto; }
.lf-margin-item:is(:hover, :focus-within) { z-index: 3; }
.lf-margin-item::before { content: ""; position: absolute; right: 100%; top: 16px;
    width: 18px; border-top: 1px solid var(--border-2); opacity: 0;
    pointer-events: none; }
.lf-margin-item:is(:hover, :focus-within)::before { opacity: 1; }
.lf-margin-item:has(.lf-margin-button[data-lf-behavior="status"]:hover)::before {
    border-color: var(--status-trace-ink); border-width: var(--status-trace-w); }
.lf-margin-item.lf-waiting { display: none; }
/* display, because the item is inline-flex where it hangs and absolute position is what
 * blockifies it there. Left inline-level once docked, the row joins whatever line box
 * its perch sits on: a change inside a card perches on an inline element, so the ✓/✗
 * landed on the last line of the sentence it decides, straddling the words instead of
 * standing under them. A docked row is a line of its own wherever it comes to rest.
 *
 * fit-content keeps that line the width of the controls standing in it, the box the row
 * had in the margin: a block-level row stretched to the column would take presses across
 * the whole width of a line the reader is trying to select in (pointer-events above). */
.lf-margin-item.lf-docked { position: static; display: flex; width: fit-content;
    max-width: 100%; margin: 2px 0 12px; flex-wrap: wrap; white-space: normal; }
.lf-margin-item.lf-docked::before { display: none; }
.lf-margin-options { display: inline-flex; align-items: center; gap: 4px;
    white-space: nowrap; }
.lf-margin-options[hidden] { display: none; }
.lf-margin-item.lf-docked .lf-margin-options { flex-wrap: wrap; white-space: normal; }
/* The word stays in the DOM and out of the paint: a reaction reads as the same
 * circular, glyph-only status before the runtime's stylesheet arrives, and a widget
 * rebuilding its own control reads the word back off the span. What names the control
 * is the aria-label `marginButton` writes, not that word — the runtime style below
 * turns the span into transient hover and focus chrome, and it rides into a static copy
 * with the rest of the sheet, so in a file the word is hidden in every medium too. */
.lf-margin-button > :is(.lf-margin-button-space, .lf-margin-button-label) {
  display: none;
}
.lf-margin-reactions { display: inline-flex; align-items: center; gap: 4px;
    white-space: nowrap; }
.lf-margin-reactions > .lf-react-trigger { display: none; }
.lf-margin-reactions > .lf-react-palette { display: inline-flex; align-items: center;
    gap: 4px; flex-wrap: nowrap; }
.lf-margin-reactions .lf-react[aria-busy="true"] { opacity: .55; }
.lf-margin-marker { color: var(--muted); pointer-events: auto; }
.lf-margin-reading-option { position: relative; }
.lf-margin-more { letter-spacing: .04em; }
.lf-margin-marker[hidden] { display: none; }
/* A marker reporting a status is excluded here as it is from the runtime's press
 * styles: neither the pointer nor the keyboard gives inert status an interactive accent
 * treatment. The focus outline still says where the Page-map walk has landed. */
.lf-margin-marker:not([data-lf-behavior="status"]):is(:hover, :focus-visible, [aria-expanded="true"]),
.lf-margin-more:is(:hover, :focus-visible, [aria-expanded="true"]) {
    border-color: var(--accent); color: var(--ink); background: var(--paper); }
.lf-margin-change { color: var(--accent); }
.lf-margin-comment { color: var(--mark-ink); }
.lf-margin-ask { color: var(--warn-ink); }
.lf-margin-activity { color: var(--accent); }
.lf-margin-count { position: absolute; top: -7px; right: -7px; min-width: 16px;
    height: 16px; padding: 0 3px; box-sizing: border-box; border-radius: 999px;
    border: 1px solid var(--paper); background: var(--ink); color: var(--paper);
    font: 600 10px/14px var(--sans); text-align: center; }
.lf-margin-target { outline: var(--here-ring); --lf-here-ring: margin-target;
    outline-offset: calc(-1 * var(--here-ring-w)); }
/* The one floor that asks the window rather than the page's own box, because it is the
 * half of a pair: below it the rule further down stops drawing the living margin at all,
 * and that rule is a media query because a marker's presence is not a thing a container
 * can be asked about without the answer depending on the strip the marker is asking for.
 * Two readings of one 900 is the page showing markers it has reserved no room for — the
 * panel narrowing body under the floor took the strip away while the window kept the
 * markers, and every row docked beside an empty rail. The floors below stay container
 * queries: those ask how much room is left beside the panel, which is the question the
 * runtime's old cramped veto asked, and the answer moves with the panel by design. */
@media screen and (min-width: 900px) {
  :root[data-lf-rail] main {
    /* The floor is the generated marker: 32px of glyph hanging 22px off the column,
       with the shared focus-ring room at the outer edge. Claim all three, or opening a
       side panel leaves that last band past body's room and the layout hides the
       marker. Over that floor stands the widest stable contribution the shared layout
       has measured, which is wider wherever a contributed control takes the marker's
       place. What the condition reads is stated with the rest of the claim below. */
    --claim-rail: max(calc(54px + var(--here-ring-room)), var(--rail, 0px));
  }
}
@media screen {
  /* A live page can receive its first comment at any moment. Reserve conversation
     room before that gesture so sending and resolving never move the passage.
     1208px leaves the 640px evidence floor, 520px margin, and two 24px gutters.
     Static copies need the strip only where they carry a thread marker. */
  @container lf-shell (min-width: 1208px) {
  body:has(
      :where(.lf-chrome, .lf-margin-item .lf-margin-marker[data-lf-kinds~="comment"])
    ) > main:where(:not(:has(> aside.sidebar))) {
    --claim-map: var(--thread-margin);
    --lf-thread-beside: 1;
  }
  }
  /* A page-level sidebar claims another 264px on the opposite side. Wait for
     that strip too: 1208 + 264 = 1472, so the same 640px document floor holds
     when both contextual surfaces stand. */
  @container lf-shell (min-width: 1472px) {
  body:has(
      :where(.lf-chrome, .lf-margin-item .lf-margin-marker[data-lf-kinds~="comment"])
    ) > main:where(:has(> aside.sidebar)) {
    --claim-map: var(--thread-margin);
    --lf-thread-beside: 1;
  }
  }
}
@media screen and (max-width: 899px) {
  .lf-living-margin, .lf-margin-marker.lf-margin-button { display: none; }
}
/* A file cannot dock. The runtime's packing pass measured the rail once, at the width
 * the page was exported at, and left with the scripts; the record a copy keeps stands
 * in an absolute seat hung off the right of its target. Where the rail is not drawn —
 * under the floor above, and on paper — that seat is off the page box: an 800px window
 * put the record 115px past its own edge and grew the document to reach it, and a
 * sheet narrower than the export simply loses it. So a copy takes the shape the
 * runtime gives a margin too narrow to stand in (.lf-margin-item.lf-docked above),
 * on the medium's terms rather than on a measurement it can no longer make.
 *
 * Not the rows the same pass withheld. `lf-waiting` says the target is not shown — a
 * widget inside a shut fold is the reachable case — and that rule is one class less
 * specific than this one, so a shape taken on the medium's terms would also be the
 * only thing standing a record beside a passage the file was folding away when
 * exported. Paper later unfolds that passage through CSS, but a script-free copy
 * cannot rerun the packing pass; changing the serialized `lf-waiting` reading belongs
 * to the live and copied layouts together, not to this export override. */
@media screen and (max-width: 899px), print {
  html.lf-copy .lf-margin-item:not(.lf-waiting) { position: static; display: flex;
      width: fit-content;
      max-width: 100%; margin: 2px 0 12px; flex-wrap: wrap; white-space: normal; }
  html.lf-copy .lf-margin-item::before { display: none; }
}
@media (pointer: coarse) {
  .lf-margin-item { margin-left: 10px; }
}
@media print {
  .lf-living-margin, .lf-margin-marker.lf-margin-button { display: none !important; }
}
/* lf-shadow:start */
@media print {
  /* A shut disclosure on paper is a summary and a stub: the words are in the document,
     nothing on the sheet says they are there, and there is no press to open them with.
     Six of them printed that way on the corpus, one of them holding 3270px of an exact
     source. The layer already takes this line for the other two ways a page puts
     content behind a gesture — a settled group's cards and an inactive tab both print
     open (packages/default) — and <details> was the one that was missed.

     `::details-content` is what the browser hides the body with, so it is what says
     otherwise; the marker goes because paper has nothing to turn. A page that means a
     disclosure to stay shut on paper says so in its own stylesheet, at a weight this
     does not contest. */
  details:not([open])::details-content { content-visibility: visible; }
  details > summary { list-style: none; }
  details > summary::-webkit-details-marker { display: none; }
}
/* lf-shadow:end */
/* A page that can grow a page-edge Button reserves this strip at load. The runtime says
 * so on the root (data-lf-rail) and never takes it back, so durable apparatus never hangs
 * in accidental leftover space and the reader never buys the room for it with a gesture.
 * The claim's width is the widest stable width the shared layout has measured, over a
 * floor of the generated marker's own fitting, and it is monotonic for the page's life:
 * neither settling an action nor taking it back moves the column under the reader.
 * Temporary reaction choices borrow the available RHS and dock the complete item if they
 * do not fit; they do not enlarge this claim. Below the breakpoint the whole item docks
 * into flow.
 *
 * This is a claim rather than the strip itself because a sidenote may claim the same side;
 * body spends the wider claim, not their sum. The condition is what the page declares,
 * because both readings of the margin's own contents fail. Asking whether an item docked
 * feeds the reservation decision back into itself. Asking whether an item stands there at
 * all put the reflow on the gesture that raised the first one, and a second reflow on the
 * gesture that took it back. */
@media screen and (min-width: 900px) {
  /* And the right margin is spoken for where a row hangs in it, so a wide widget level
     with one grows to the left alone. The row hangs 22px off the column and the strip is
     reserved out of the far side of the page, which are not the same place once the
     column centres in what is left: a board grown to the strip stood 134px over these
     controls at a laptop's width. Refusing the side page-wide answered that collision by
     never having it, and charged every exhibit on the page for a row somewhere above it —
     measured, one change near the top of a page held a board 1400px below it to the
     column's width with 345px of margin standing empty beside it. The collision is a fact
     about one height, the same fact `clear` states for a sidenote on the left; a row is
     positioned rather than floated, so no layout rule can see it, and the shared margin
     layout marks the exhibits whose bands a row reaches (data-lf-yield) here.
     Said beside the reservation because they are the two halves of taking a margin, and a
     page that reserves one without saying so is a page whose exhibits are drawn over its
     own apparatus. A copy runs no script and keeps the marks it was exported with, the
     way it keeps the rail its decided rows reserved. */
  [data-lf-wide][data-lf-yield~="r"] { --lf-grow-r: 0px; }
}

/* Where a widget upgrade fails, it fails soft into this box. */
.lf-error { border: 1px solid var(--danger); background: var(--danger-tint);
            color: var(--danger-ink); border-radius: var(--r); padding: 8px 12px;
            font-size: var(--t-5); white-space: normal; --lf-frame: 1; }
.lf-error pre { margin: 8px 0 0; white-space: pre; }

/* A live-version transition is a paint boundary, not motion. The old pixels remain
 * while the replacement upgrades and replays, then the restored reading lands in one
 * frame rather than cross-fading text under the reader's eyes. */
html.lf-versioning::view-transition-group(root),
html.lf-versioning::view-transition-old(root),
html.lf-versioning::view-transition-new(root) {
  animation-duration: .01ms !important;
}

/* Reduced motion: one global guard covers every animation and transition in the
 * theme and the injected layers (!important outranks inline styles, so
 * JS-driven transitions stop too). JS-driven motion goes through the runtime's
 * motion() and the live motion readings, which answer the same preference themselves.
 *
 * The two halves are not written alike, because a duration is a way of keeping
 * an animation and no way at all of keeping a transition. An animation is
 * declared and named, and `animationend` is how the layer knows one has run —
 * the thread list takes `grow` off a card that way — so the near-zero duration
 * keeps that event and spends no time on it. A transition is declared by
 * nobody: `transition-property` is `all` until something says otherwise, so a
 * duration on every element makes a transition out of every property that
 * changes, on every element, and none of them is a transition this theme
 * wrote. Nothing listens for `transitionend`, so they were kept for no one and
 * were not free: a running transition's animated value is what the platform
 * reports for the property, so for the frames one of these took, every reading
 * of a box's style — the render gate's included — was told the value the
 * property was leaving rather than the one on screen. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition: none !important;
  }
}

/* Ordinary action buttons share their face across document and shadow trees.
 * Packages may adjust placement and density; margin Buttons and reaction chips
 * retain their separate forms. */
/* lf-shadow:start */
.lf-btn { padding: 4px 10px; border: 1px solid var(--border-2); border-radius: 6px; background: var(--card); cursor: pointer; white-space: nowrap; color: var(--ink); display: inline-block; }
.lf-btn:hover { background: var(--chip); }
.lf-btn.primary { background: var(--accent); border-color: var(--accent); color: var(--paper); }
.lf-btn.primary:hover { filter: brightness(.92); }
/* Two selectors, two mechanisms, one look: the platform's own on the banner's real
   buttons, and the attribute wireInput sets, which is the only one a span press can
   wear. */
.lf-btn:disabled, .lf-btn[aria-disabled="true"] { opacity: .55; cursor: default; }
.lf-btn.primary:is(:disabled, [aria-disabled="true"]) {
          opacity: 1; color: var(--muted); background: var(--paper);
          border-color: var(--border-2); filter: none; }
.lf-btn.on { border-color: var(--accent); color: var(--accent); background: var(--chip); }
/* Draw mode takes page-widget presses before their controls can act. This rule is in
   the shared slice because document selectors do not cross a declared shadow root. */
:host-context(body.lf-drawing):host-context(main) * { cursor: crosshair !important; }
:host-context(body.lf-drawing):host-context(main) .lf-conversation,
:host-context(body.lf-drawing):host-context(main) .lf-conversation * {
  cursor: auto !important; }
/* lf-shadow:end */
/* Leaf's default package: broadly useful content rules concatenated after the kernel
 * theme by `page init`. These widgets reach a page through the same package route as
 * selected, user, and project contributions. Tokens, elements, idioms, and the
 * suggestion family are the kernel theme's; this file carries only what the default
 * package's widgets wear. */

/* ---------- element-widgets ---------- */

/* lf-gloss: the prose stays prose, and its dotted underline is the whole visible
 * affordance. The underline is deliberately quieter than a link — this phrase goes
 * nowhere — while the top-layer card uses the page's ordinary paper, ink, and rule
 * rather than inventing a tooltip palette. Static copies and paper put the explanation
 * after the phrase, where they can honour its words. */
lf-gloss { display: inline; }
/* The no-script rendering of x-says. Once the runtime writes the selectable span, that
 * span takes over; a static exported copy keeps the span and gives it the same inline
 * fallback below. */
lf-gloss[tip]::after { content: " (" attr(tip) ")"; color: var(--muted); }
lf-gloss:has(> [data-lf-said="tip"])::after { content: none; }
@media screen {
  html:not(.lf-copy) lf-gloss {
    text-decoration-line: underline;
    text-decoration-style: dotted;
    text-decoration-color: var(--accent);
    text-decoration-thickness: 1px;
    text-underline-offset: .18em;
    cursor: help;
  }
}
.lf-gloss-mark {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  opacity: 0; pointer-events: none;
}
lf-gloss:has(> .lf-gloss-mark:is(:focus-visible, .lf-focus-visible)) {
  outline: var(--here-ring); --lf-here-ring: gloss-mark;
  outline-offset: calc(-1 * var(--here-ring-w));
}
.lf-gloss-popover {
  position: fixed; inset: auto; position-area: block-end center;
  position-try-fallbacks: flip-block, flip-inline;
  box-sizing: border-box;
  width: max-content; max-width: min(22rem, calc(100vw - 24px));
  margin: 8px 0; padding: 10px 13px 11px;
  border: 1px solid var(--border-2);
  border-radius: var(--r); background: var(--card); color: var(--ink);
  box-shadow: 0 10px 28px var(--shade);
  font-family: var(--serif); font-size: var(--t-5); line-height: 1.45;
  text-align: left; white-space: normal;
  overflow-wrap: anywhere;
}
.lf-gloss-popover::backdrop { background: transparent; }
html.lf-copy lf-gloss > .lf-gloss-popover {
  display: inline; position: static; width: auto; max-width: none;
  margin: 0; padding: 0; border: 0; background: none; color: var(--muted);
  box-shadow: none; font: inherit;
}
html.lf-copy lf-gloss > .lf-gloss-popover::before { content: " ("; }
html.lf-copy lf-gloss > .lf-gloss-popover::after { content: ")"; }
@media print {
  lf-gloss > .lf-gloss-popover {
    display: inline; position: static; width: auto; max-width: none;
    margin: 0; padding: 0; border: 0; background: none; color: var(--muted);
    box-shadow: none; font: inherit;
  }
  lf-gloss > .lf-gloss-popover::before { content: " ("; }
  lf-gloss > .lf-gloss-popover::after { content: ")"; }
}

/* Every attribute the registry marks x-says is written twice here. The runtime
 * renders the value as real text (renderSaid, in a span carrying data-lf-said),
 * because a pseudo-element paints glyphs that live in no text node — a user
 * can read them and can never select or comment on them. The pseudo-element
 * stays as the same words for a page carrying no script at all and stands down where
 * the runtime got there, asked by :has() and placed later in the cascade, so the two
 * are never both on. A word the theme puts in front of a value stays a pseudo either
 * way ("quoted ·"): that one is the theme's word about the page's, and only the page's
 * is worth quoting. There is one of those left. The
 * other went with the attribute it named: the theme wrote "effort" in front of
 * `effort` because it knew the name, and a decision's facets are the author's to
 * name, so they are markup (lf-chip) rather than an attribute rendered into text.
 *
 * Every rule here names the attribute it styles, because data-lf-said is the wider
 * claim that these words are the page's — a widget's own label wears it bare
 * (relabel) — and a rule matching it bare styles whatever a widget says next. The
 * chosen-option mark is a direct child of lf-option and came out as a chip band
 * at the head of the card. */

/* The apparatus voice, for this package's words: the kernel theme states the same
 * rule for the page's idioms, and every package restates it for the labels its own
 * widgets wear. One rule per package, because what counts as apparatus is a judgement,
 * and a judgement made per
 * widget is a dozen chances to answer it differently.
 *
 * Figures come with the face, and this package is where that earns its keep: the
 * numbers a report moves between versions are all here — a task's done fraction, a
 * metric's value, a tree's badge — and in the sans's own figures each rewrite resizes
 * the pill the number is set in, and moves whatever stands after it. The integrated
 * theme's copy of this rule carries the measurement and the norm it answers. */
.lf-chips span, .lf-tree-badge, .lf-shotcap, lf-metric,
lf-specimen::before, lf-specimen > [data-lf-said="label"], lf-column::before,
lf-column > [data-lf-said="label"], lf-tab::before,
.lf-state, .lf-heard, .lf-cold,
lf-chip {
  font-family: var(--sans); font-variant-numeric: tabular-nums; }

/* The pill this package's chips ride in — the kernel theme's .tag numbers,
 * restated so a band of chips and an inline label stand the same height. */
lf-chip, .lf-chips span {
  display: inline-block; font-size: var(--t-6); line-height: 1.6; padding: 0 8px;
  border-radius: 999px; background: var(--chip); color: var(--ink-2); }

/* A card is a marking — a border, a fill — and what stands inside it is the page's own
 * words at the page's own size, so it states no size. lf-option, lf-variant and lf-card
 * each stated 15px instead, two of them with a 16px title over it: a pixel of hierarchy no
 * reader could see, over a body off the ladder entirely, which nothing here was ever
 * fitted or measured against. The
 * `.facts` rail is where that showed — apparatus at --t-5 is meant to read as subordinate
 * to the case beside it, and against a 15px case it was one pixel smaller than the prose
 * it stood next to. Unlike the voice above, this is not a judgement a layer restates:
 * there is one ladder and every layer reads the same tokens. */

/* lf-options / lf-option: the theme is most of the widget — the module adds the
 * pick, the reference, and the option the reader writes, and without it these rules still
 * draw the whole thing.
 *
 * Which of two forms a group takes is a fact about its options rather than an
 * attribute saying so: an option that leads with a <strong> title argues its own
 * case, so a group holding one stacks into full-width cards read down the page;
 * and a group whose options are bare labels is a question *about* the page rather
 * than a set of them, and reads as a list of compact rows, each naming the
 * block it is about (`for`). Every rule below that only makes sense for one
 * form says which — a card's `.facts` rail docks right, a question
 * row's reference rides in its line — and none is an override of another.
 *
 * There was a third form: a group whose every option was terse laid them across,
 * a grid of ~13rem cards. Options are alternatives to weigh against each other,
 * which is a reading down, and the grid's geometry moved with the count besides —
 * four options came out three across with the fourth orphaned under them, every
 * cell stretched as tall as the row's longest argument. A list is the same shape
 * at three options and at six, so adding one is editing a line rather than
 * re-laying the group.
 *
 * The chip band is the one thing no form has to state, because inline-block in
 * front of the title is already both answers: a titled option's <strong> is
 * a block, so the band lands on a line of its own above it, and a bare-label
 * option has no block to push against, so it rides in the row's own line. What
 * came before was two attributes pinned to a card's two corners, and every form
 * paid for that placement — a 40px band reserved above the title, an
 * anchor-positioned offset so the second chip cleared the first, an 11rem
 * reservation in the row-form title. Every one of those numbers was room held
 * for a fixed count of words the theme knew the length of. An author writes as
 * many lf-chip as the decision has facets, so there is no count to lay out for
 * and no width to reserve: they wrap along the band like the words they are. */
/* Whether a group stands as one control is a second axis, across the form it takes: the
 * cards and the rows alike become cells when the group is joined, and both come apart
 * again under `settled`, in an exhibit, in a copy and on paper. The axis is declared here
 * and read by style queries, because half of what decides it — the medium, and the copy's
 * class on the root — cannot be written into a `:not()` at all. Undeclared, the dressing
 * an option wears standing alone arrived on every option and was undone cell by cell, and
 * the undoing was a race the joined block won on class columns: one attribute selector in
 * the card's hover turned it, and a status lost its stripe and grew a ring the group's
 * own clip cut down to a line above the cell. Declared, a rule states the case it is
 * true of and has nothing of the other case to undo. */
/* Row prose must remain prose. A table layout may create an anonymous cell around mixed
   inline content without inserting a wrapper that changes authorship or spacing. Flex
   gaps applied to raw inline children can turn authored spaces into layout gaps and split
   code or emphasis into separate items. Joined answerable rows keep their complete width
   inside the group's border with `box-sizing: border-box`.

   Whether a group is answerable is independent of its form. The presence of `choose`
   gives the whole group a visible control boundary in cards and rows. Each form chooses
   its presentation, not whether the page admits a response.

   A group joined into one control has cells, and its children arrive from every layer:
   the authored options are the author's, while the option the reader writes and the Done
   press are the runtime's. Each brings the spacing it wears standing alone, and the grid
   stretches all of them to the same column whatever they were written as.

   The reader's cell is an add form dressed as an option. It creates and selects a real
   generated option through the same absolute `choose` state as the authored options; it
   is not a conversation seat. What it is for is the answer the menu hasn't got, so it
   takes the cells' fill and their column and states no inset of its own. A cell that
   dresses as apparatus tells the reader to skip it.

   So what every cell owes is said over every child, and only what one kind alone answers
   is said by naming it. Block margins are zeroed for all of them, because the hairline is
   the whole of what separates a cell from the next; the inset each holds its words off
   the frame by is a floor at zero specificity, which any cell with an answer of its own
   outranks. Naming kinds is how three children got their margins reset and the fourth
   kept an 8px band under a line already separating, and how the question got no inset at
   all. Reserved columns the cells share, such as the room a keyboard address stands in,
   are named once and read by everything that opens at them — including the forms the
   frame never reaches, since a settled group reserves the same column on the cards behind
   its disclosure.

   A widget derives its visual form from content when the content already states the
   distinction; do not add a second layout attribute that can disagree with that
   markup. Rules specific to one form include the form predicate in their selector.
   Avoid general rules followed by a reset for the other form; specificity can leave
   the wrong state partially active. A rule stays general only when its effect is true
   in every form. */
lf-options { display: block; margin: 14px 0; --lf-joined: 0;
             container-type: inline-size; }
lf-option { display: block; position: relative; }
/* The submitted draft keeps its line breaks when it becomes an option. Restrict this to
 * generated options: authored markup carries formatting whitespace around its prose. */
lf-option[data-lf-added] { white-space: pre-wrap; }
/* The card dressing is the titled form's, said so rather than painted on every option
 * and reset by the row form: a reset is a guard reading state another rule wrote, and
 * the row form carried four of them for dressing no row ever showed. The same sentence
 * on the joined axis: a titled option is a padded box that frames the author's blocks
 * wherever it stands, and a bordered card on its own ground only.
 *
 * A card's shadow carries two facts that do not answer each other — the ring its status
 * draws and the lift the pointer draws — so each takes a channel of its own. Sharing the
 * property, whichever fact was stated second had to restate the first to keep it, and a
 * status with no copy in the hover rule lost its ring the moment a pointer arrived.
 * Nothing else in this file draws an option's shadow, which is what says a row nobody
 * can press has no edges of its own. */
lf-options:has(> lf-option > strong) > lf-option { padding: var(--sp-3); --lf-frame: 1;
            --lf-ring: 0 0 #0000; --lf-lift: 0 0 #0000;
            box-shadow: var(--lf-ring), var(--lf-lift); }
@container style(--lf-joined: 0) {
  lf-options:has(> lf-option > strong) > lf-option { border: 1px solid var(--rule);
              border-radius: var(--r); background: var(--card); }
}
lf-option > strong { display: block; margin: 0 0 4px; }
/* A chip is an element, so nothing here renders it and nothing declares it words: it is
 * the author's own markup, quotable and diffable like any other content. The pill is the
 * shared one — inline-block there, which is what leaves each form free to decide where
 * the band sits — and what a chip adds is the band: margins that space and wrap a row of
 * them, and a max-width bounding a long one against the card, since the words are the
 * author's and there is no length the theme can assume. */
lf-chip { max-width: 100%; margin: 0 6px 2px 0; }
/* The tint is the author's, per chip. The theme knows the three semantic pairs and
 * nothing about which facet earns one — the pair this replaced tinted `risk` and not
 * `effort`, which was the theme holding an opinion about a word, and the opinion went
 * wrong the moment the author picked the facet. Same bargain lf-metric makes with
 * `direction`. Untoned is the default and should stay the common case: a band where
 * every chip is coloured points at nothing. */
lf-chip[tone="ok"]     { background: var(--ok-tint);     color: var(--ok-ink); }
lf-chip[tone="warn"]   { background: var(--warn-tint);   color: var(--warn-ink); }
lf-chip[tone="danger"] { background: var(--danger-tint); color: var(--danger-ink); }
/* The titled form. A titled option is a card arguing its own case, and the cards
 * stack into full-width rows, read down the page the way a decision record
 * reads — which is how pages stopped growing a comparison table and an "in
 * detail" section outside the widget they decide in. Terse or substantial alike:
 * a case of one sentence reads down the same list a case of three paragraphs
 * does, and block content asks for nothing, it just fills the row the option
 * already has. A `.facts` list at the top of an option docks
 * right at one width wherever the row can spare it, so scalars align down the
 * group like the column of the comparison table this form folds back in, and
 * stacks above the prose where it can't.
 *
 * lf-compare is the same shape without the decision and follows it — for block
 * content only, because an exhibition is looked across where a decision is read
 * down, so terse variants keep their side-by-side grid. Whether a variant holds
 * block content is the platform's closed set inverted, exactly as the suggestion
 * slots ask it: any child that is not phrasing content stacks the group, so a
 * widget from any layer is covered without being named — the enumeration this
 * replaces listed fifteen widgets and would have missed the sixteenth. A test
 * states HTML's phrasing content once and holds both copies of the list to it,
 * so neither can drift from the platform or from the other. The marker at the
 * end is the inversion's one wrong answer, an inline widget being a custom
 * element like any other: the registry says which widgets those are and the
 * runtime paints it where a selector can reach it (data-lf-inline, leaf.js
 * markDeclared), so a chip keeps the grid here by the same declaration that
 * keeps a suggestion inline in a sentence. It is in :where() for the reason the
 * suggestion slots' copy states: an attribute selector inside :not() would lift
 * this whole rule a specificity column and let a layout question outrank the
 * marks painted over it. */
lf-options:has(> lf-option > strong),
lf-compare:has(> lf-variant > :not(a, abbr, area, audio, b, bdi, bdo, br, button, canvas,
    cite, code, data, datalist, del, dfn, em, embed, i, iframe, img, input, ins, kbd,
    label, link, map, mark, math, meta, meter, noscript, object, output, picture,
    progress, q, ruby, s, samp, script, select, slot, small, span, strong, sub, sup,
    svg, template, textarea, time, u, var, video, wbr, :where([data-lf-inline]))) {
  display: block;
  & > :is(lf-option, lf-variant) { display: flow-root; margin: 0 0 var(--sp-2); }
  & > :is(lf-option, lf-variant):last-child { margin-bottom: 0; }
  /* The rail docks right where the row has the width to spare, and stacks above the prose
   * where it hasn't — asked of the row itself, because how much room it has is a fact
   * about the row and not about the window: the page gives 168px up to the margin
   * the moment a change wants deciding, and a viewport wide enough to dock in was still
   * one of those. A rail out of a narrower row leaves the argument three words to the
   * line, so the rail wins the row and the case it was docked beside loses it.
   *
   * What the row must have is therefore the rail, its gutter, and a measure left over for
   * the case, and the threshold says exactly that rather than the sum of it. Both widths
   * are the row's own `em`, the rail being a column carved out of the row and the measure
   * what is left of it. They stood in `rem`, which is the one unit here that answers to
   * nothing: the option's type went from 15px to 17px and the case behind the threshold
   * quietly dropped from about forty-seven characters to forty-one, since the room it was
   * given had never been a fact about the words in it. The measure is around forty-six
   * characters of Charter, which sets about 7.35 of them to the pixel at 17px, and both
   * numbers re-derive the next time the ladder moves.
   *
   * That leaves the rail's type to its own dt and dd, because a font-size on the list
   * would make `em` mean one thing in the width and another in the condition, where the
   * container is the option. The gutter is written out because a custom property is
   * not allowed in a container condition; it is `--sp-3`, and the rail's own margin below
   * is where it is really stated. */
  & > :is(lf-option, lf-variant) { container-type: inline-size; }
  /* The rail declares the frame its option already does, because the trim reaches one
     level and the rail is what stands in that level: a `dt`'s 6px between terms is the
     first term's too, and collapsing hands it to the option, whose padding then paints it
     — so the rail's first line sat 6px below the case docked beside it. Stated here
     rather than under the float, since where the rail stacks the same 6px reaches the
     option through the same collapse. */
  & > :is(lf-option, lf-variant) > .facts { display: block; margin: 0 0 var(--sp-2);
      --lf-frame: 1; }
  @container (min-width: calc(9.5em + 16px + 20em)) {
    & > :is(lf-option, lf-variant) > .facts { float: right; clear: right; width: 9.5em;
        margin: 0 0 var(--sp-2) var(--sp-3); }
  }
  & > :is(lf-option, lf-variant) > .facts dt { color: var(--muted);
      font-size: var(--t-6); text-transform: uppercase; letter-spacing: .05em;
      font-weight: 400; margin-top: 6px; padding: 0; }
  & > :is(lf-option, lf-variant) > .facts dd { font-size: var(--t-5); margin: 0; }
}
/* With `choose`, the group takes the reader's pick by click. What follows is a card
 * standing on its own — a card in a settled group, or any card on paper. A card in a
 * live group is a cell of one control, and the block further down states its pick,
 * hover and mark in those terms. */
/* The rings: a card states its status as a border it already has, so both live with
 * the card form. A row has no border to color and says the same two things with a
 * wash (below), and a card taking a pick has no border either once the group takes it
 * over, so the joined form says both as a bar beside the option's words (further
 * below), in the same channel and under the guard that is true of it. */
@container style(--lf-joined: 0) {
  lf-options:has(> lf-option > strong) > lf-option[chosen] {
                         border-color: var(--ok); --lf-ring: 0 0 0 1px var(--ok); }
}
/* The pick is the group's own gesture rather than a press on any one thing — a click
 * lands anywhere in the option — so nothing here wears the role `version export` strips
 * from a control, and the medium is what has to say it. `choose` is the author's word and
 * stands in every copy of the page; what does not stand is a handler to answer it, so a
 * copy that kept the hand and the lift invited a click on twenty cards and answered none
 * of them. Live pages only, which is where these are true, and the joined shape below is
 * withheld in exactly the same breath for exactly the same reason.
 *
 * Every option lifts on hover, the pick included — clicking it clears it, so it has to
 * keep looking clickable. A ring a card already wears layers under the lift. The joined
 * form answers the same requirement without the lift, because a cell that rose would pull
 * away from the hairlines holding the group together.
 *
 * `:where` around the guard, where the blocks elsewhere in this file spell it plainly, and
 * the difference is what each guard is for. Those grant a layout over a rule that withholds
 * it, so they have to outrank something; this one is the only statement its declarations
 * get, so it needs to outrank nothing.
 *
 * A quoted group is exhibited, not offered, so every rule that says "this takes input" —
 * the hand, the lift, the joined shape, the reserved strips and columns, the hover wash —
 * excludes it where the rule is written (`:not(:where([data-lf-exhibit]) *)`). A block
 * keyed to the exhibit used to unkey these selector by selector instead, and that shape
 * lost twice: a plainly-spelled guard outranked the unkeying (the joined cells kept their
 * hover wash inside an exhibit), and every affordance added after the unkey block was one
 * nobody remembered to unkey. The exclusion travels with the affordance, so the next one
 * carries its own — including the two that can paint nothing inside an exhibit whether
 * they carry it or not. The mark's warmed ring is drawn on a `.lf-pick`, which a quoted
 * option grows only where the document marks it chosen, and the rule excludes `[chosen]`;
 * a chosen row's hover wash is the colour that row already wears at rest. What makes each unobservable is a
 * module's choice or another rule, neither of which is this rule's to rest on, so both
 * carry the exclusion anyway. A flip of either comes back green, and that is the reading
 * to expect rather than a gap to go looking for.
 *
 * The marker rather than the tag. Which widgets quote what they hold is the registry's to
 * say (x-exhibit) and a stylesheet cannot read it, so the runtime paints the declaration
 * where a selector can reach it (data-lf-exhibit, leaf.js markDeclared) and the descendant
 * combinator asks the descendant half of quoted()'s question: does this element stand
 * inside one. quoted() answers for the element itself too, and that half is nobody's
 * here while lf-options is not an exhibit — a layer declaring it one would have to say
 * so in its own rules. Spelled, it was `lf-specimen` ten times over: the tag this package
 * happens to ship, and no answer at all for a project whose exhibit has another name.
 *
 * In :where(), which is the idiom the phrasing lists set (theme.css) and not a contest
 * being won here — nothing in this theme changes hands either way. It keeps the
 * exclusion a question about where the element sits rather than a claim on the cascade,
 * and it does one thing more than it does there: the marker is the only thing inside
 * these :not()s, where in a phrasing list it stands among type names, so each of these
 * ten weighs a type column less than it did with the tag spelled. That direction is the
 * safe one to move in — these rules grant an affordance, so a contest lost withholds it
 * rather than offering what an exhibit cannot take.
 *
 * What the tag bought that the marker does not is the page that never runs the runtime,
 * where nothing paints the mark and a quoted group would keep the whole offer. No shipped
 * page is that page. No shipped authored page does: each reaches the runtime through
 * its Leaf scaffold. A copy and paper are already out by the guards above. */
@media screen {
 :where(html:not(.lf-copy)) {
  lf-options[choose]:not(:where([data-lf-exhibit]) *) > lf-option { cursor: pointer;
                         transition: box-shadow .12s ease, transform .12s ease; }
  @container style(--lf-joined: 0) {
    lf-options[choose]:not(:where([data-lf-exhibit]) *):has(> lf-option > strong)
                         > lf-option:hover {
                           transform: translateY(-1px);
                           --lf-lift: 0 3px 10px var(--shade); }
  }
 }
}
/* The mark the upgrade injects is both the keyboard path and the state. Each form gives
 * that element one place of its own.
 *
 * A live titled card is the whole pointer target, and for a while its open single-pick
 * state drew no mark at all — the joined frame, card divisions, pointer, and aim wash were
 * to carry the offer. A reader who has not hovered sees none of those: a blind drive read
 * three cards, found nothing on them that looked like a control, and chose only after a
 * hover happened to shade one. So the empty ring stands in the state slot at the card's
 * opening edge, the same slot the pick becomes a chip in and the same empty box a
 * multiple-choice card already wears, saying the slot is untaken and where the press
 * lands.
 *
 * The Ask's action address temporarily takes that same opening-edge slot in either arity.
 * The slot is reserved beside the author's chip band and title on every card, so neither
 * a pick nor an address moves or covers the words. A document-only chosen card keeps the
 * compact caption below: it has no live header state or action address. */
lf-options:has(> lf-option > strong) > lf-option[chosen] { padding-bottom: 32px; }
lf-options:has(> lf-option > strong) > lf-option > .lf-pick {
                     position: absolute; left: var(--sp-3); bottom: 9px; }
@media screen {
 html:not(.lf-copy)
 lf-options[choose]:not(:where([data-lf-exhibit]) *):has(> lf-option > strong) {
   --lf-card-state-room: 80px;
   & > :is(lf-option, .lf-another) { padding-inline-start: var(--sp-3); }
   & > lf-option { padding-bottom: var(--sp-3); }
   /* A float is the exclusion, rather than margin on one authored child: every chip and
    * title line that reaches the status band wraps around the same reserved rectangle. */
   & > lf-option::before { content: ""; float: inline-end;
                     width: var(--lf-card-state-room); height: 22px;
                     pointer-events: none; }
   & > lf-option > .lf-pick {
                     left: auto; inset-inline-end: var(--sp-2);
                     top: var(--sp-2); bottom: auto; z-index: 1; }
   & > lf-option[chosen] > .lf-pick {
                     padding: 2px 8px; border-radius: 999px;
                     background: var(--ok); color: var(--card);
                     font-size: var(--t-6); line-height: 1.5;
                     gap: 4px; }
   & > lf-option[chosen] > .lf-pick::before {
                     width: auto; height: auto; border: 0; background: transparent;
                     color: inherit; }
   & > lf-option > .lf-address {
                     inset-inline-start: auto; inset-inline-end: var(--sp-2);
                     top: var(--sp-2); }
   & > lf-option:has(> .lf-address[data-lf-ask-address]) > .lf-pick {
                     opacity: 0; }
 }
}
/* The face is stated here, not left to a class: the mark has two shapes — a press
 * wearing .lf-ui where the group takes picks, a bare span where it doesn't — and only
 * one of them has the class to answer for it, so the one rule both shapes share names
 * the family, size and line itself. */
lf-option .lf-pick { display: inline-flex; align-items: center; gap: 6px;
                     font-family: var(--sans);
                     font-size: var(--t-6); line-height: 1.5;
                     color: var(--muted); }
/* Off the ladder, and stated here because it is a fit rather than a size: the mark is an
 * 11px box whose border leaves 9px of interior, and 8px sets a ✓ five pixels across in it,
 * well clear of the ring. The smallest step on the ladder is 11.5px, which draws it eight
 * across in an advance box a pixel wider than the interior — a tick filling the mark it is
 * inside rather than sitting in it. (The border asks for 1.5px and Chrome uses 1; half a
 * pixel of ring is a paint decision, and the interior is what the glyph gets.) */
lf-option .lf-pick::before { content: ""; width: 11px; height: 11px; flex: none;
                     border: 1.5px solid var(--border-2);
                     display: grid; place-items: center; box-sizing: border-box;
                     font-size: 8px; line-height: 1; color: var(--card); }
/* The mark's corner is how many the group takes: a circle is one of these, a rounded
 * square any of these. It is the difference a reader gets by eye, and it is the one they
 * already have — every platform's radio and checkbox are this pair, and nothing else the
 * group can do says arity. Paint reaches no screen reader, so the mark's own word carries
 * the same distinction for a reader listening, and the module holds the pair together.
 * A `multiple` group was drawing the same circles a single-pick
 * one draws, so the two were identical on screen and the page had to say in prose which
 * question it was asking ("pick the ones worth starting"); a reader who took the shape at
 * its word would pick once and expect the next click to replace it.
 *
 * The shape and not a word, because an offer says nothing (the rule below) — and not the
 * ✓ either, which stays the same glyph in both: the corner answers how many, the tick
 * answers whether this one, and a state that changed both would be one guarantee written
 * twice. Paint inside the mark's own box, so neither arity is a pixel wider than the
 * other and nothing that was reserved has to be re-measured.
 *
 * Each group states its own options' marks, down a child combinator, and neither rule is
 * the other's reset — the two are disjoint, so the base rule above states no corner and
 * every mark takes one of these. Written as a value inherited from the group instead, it
 * would have had to be defended: an option's content model is prose, so a question nests
 * inside another question's option, and the inner group's marks would have taken the
 * outer group's arity for want of a default. Reach only as far as the options the group
 * owns and the case cannot arise. */
lf-options:not([multiple]) > lf-option > .lf-pick::before { border-radius: 50%; }
lf-options[multiple] > lf-option > .lf-pick::before { border-radius: 3px; }
/* Keyed on the selection role rather than on the class, because only one of the mark's
 * two shapes is a control — and the same attribute answers for the medium, `version
 * export` taking it off a control whose handler has gone. So this needs no guard of its
 * own: the hand is on the mark exactly while the mark can take a selection. */
lf-option .lf-pick[role="checkbox"] { cursor: pointer; }
/* An offer says nothing on screen, so its word is not drawn. "Choose one" or "choose any"
 * remains the mark's accessible name because shape reaches no screen reader. A picked
 * row and an inert document mark stay just as terse: their check and tint state the fact.
 * A live titled card is the exception declared in its own layout above, where the picked
 * word becomes a compact header status in room the open state already reserved. */
lf-option .lf-pick:not([data-lf-said]) { font-size: 0; gap: 0; }
/* Warming the ring under the aim, wherever the ring is drawn — a row, a card under
 * `multiple`, and a card in a settled group. A live single-pick card group draws none, so
 * this reaches nothing there and the cell's own hover is the answer instead. The keyboard
 * is an aim like the pointer: inside a joined group the mark's own focus ring is withheld
 * (the group's is the ring, below), so the warmed tick and the wash are what say which
 * mark the next toggle will take. Guarded with the group's other answers to the pointer, and free of
 * specificity for the same reason they are. */
@media screen {
 :where(html:not(.lf-copy)) {
  lf-options[choose]:not(:where([data-lf-exhibit]) *) > lf-option:not([chosen]):is(:hover,
                     :has(> .lf-pick:is(:focus-visible, .lf-focus-visible))) > .lf-pick::before {
                     border-color: var(--muted); }
 }
}
/* Child combinators, for the same reason the corner rules reach only the options the
 * group owns: a question nests inside another question's option, and a descendant rule
 * painted every inner mark with the outer option's state. */
lf-option[chosen] > .lf-pick { color: var(--ok-ink); }
lf-option[chosen] > .lf-pick::before { content: "✓"; border-color: var(--ok);
                     background: var(--ok); }
/* A standalone copy and paper have no live mark, but authored selection is still part
 * of the document. Keep the same compact check without reviving a dead control or its
 * former status caption. */
@media print { lf-option[chosen]::after { content: "✓"; color: var(--ok-ink);
                                        font-family: var(--sans); font-weight: 700; } }
html.lf-copy lf-option[chosen]::after { content: "✓"; color: var(--ok-ink);
                                       font-family: var(--sans); font-weight: 700; }
lf-option .lf-pick:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: options-pick;
                     outline-offset: var(--here-ring-gap); border-radius: 4px; }
/* The Ask's action keys, worn on the option cells it addresses. The gutter reads status,
 * address, then prose, so each chip starts after the status rule and ends before the
 * cell's words. A card aligns its digit with the top of its content; rows centre theirs. */
lf-option > .lf-address { position: absolute; inset-inline-start: var(--lf-address-start); }
lf-options:has(> lf-option > strong) > lf-option > .lf-address { top: 8px; }
/* The thread multi-question's submit (the module adds it there alone): one press
 * stating the set is whole, since every toggle already reached the agent as it
 * landed. Answered is paint, never a wider word — the pressed control's own line
 * holds still. Keyed on the pressed state the press already wears, because the
 * group's markup is the author's: an `answered` attribute here was the same fact
 * a second time, in a namespace the entry closes (lf-options.js). It held 8px over
 * itself once, from the days a group was options standing apart; the module adds it to a
 * thread question only, every thread question is a live `choose` group, and a live
 * `choose` group is the joined control, whose cells butt. Nothing was left for the margin
 * to detach it from — the grid had been stretching it to the full column all along — so
 * what it drew was a hairline with dead ground under it, on every thread the agent asked
 * a set question in. */
lf-options > .lf-done[aria-pressed="true"] { color: var(--ok-ink);
                     border-color: var(--ok); background: var(--ok-tint); }
/* Its Ask address stands where the rows' do: on the address column, centred on the
 * press, inside the cell rather than hung off its corner. */
lf-options > .lf-done { position: relative; }
lf-options > .lf-done > .lf-address { position: absolute;
                     inset-inline-start: var(--lf-address-start);
                     top: 0; bottom: 0; margin: auto 0; }
/* A group under `choose` is one control, not a set of options standing near each other.
 * Deleting the offer word left the question of what says a decision is waiting, and the
 * answer is the group rather than another thing drawn on every member: a group offers and
 * its members are what is offered, so writing the offer onto each of them was the mistake a
 * dot repeats more quietly than a word did. Cells of one width sharing edges, divided by a
 * hairline instead of a gap, is what a segmented control is made of and all it is made of —
 * repetition at one size says "these are alternatives" before a word is read, and it says
 * it once. The shape appears only where `choose` does, so its presence is the offer.
 *
 * Both forms, because the offer is the group's rather than the layout's: the titled
 * form's cards and the compact list alike become cells of the same control, one per
 * row, and neither states its own answer to "is this answerable". Hence
 * `display: grid` over forms the theme otherwise lays out as blocks — one column, no
 * template stated — so each option is a cell, with the hairline between neighbours
 * drawn below.
 *
 * The list form was left out of this at first, on the reading that a bare-label row is a
 * quiet thing and a border around it would be shouting. What that actually shipped was a
 * question with no visible answer to "which of these can I press": the rows carry no
 * border, no fill and no rule between them (the list rules below), so at rest a `choose`
 * list is three lines of prose with a faint dot column off to the right, and the only thing
 * that ever draws a row's own box is the hover wash — which arrives after the reader has
 * already had to guess where to aim. A reader said so of the shipped page. Whatever the
 * form, the offer has to be visible before the pointer is committed, and that is the same
 * fact this rule was written for.
 *
 * The live page only, which is the same reason twice. On paper nothing can be picked, and
 * an exported copy has had its scripts dropped, so a group drawn as a control in either
 * would be offering what the medium cannot take. Both get the page without the offer by
 * never being handed it rather than by undoing it — the bargain the reader's own cell already
 * makes — so the cards come apart again and wear the rings they print. Not `settled`
 * either, for the same reason in a different medium: a retired decision is a line the
 * user opens, and drawing the group as a control around it would put one box inside
 * another and offer a question nobody is asking. Opened, its cards come back as
 * cards — with their rings, since the ring and the container are the same decision made
 * twice and a group that isn't joined has to say the offer itself. */
/* Every child of a joined control is a cell, and a cell holds its words off the frame.
 * Said once, as the thing that is true of a cell, rather than once per kind the block
 * below expects to find: children arrive here from every layer — the authored options
 * are the author's, while the option the reader writes and the Done press are generated
 * controls. A new kind should inherit the cell floor without being added to a list.
 *
 * At no specificity at all, both guards inside :where(), so it is a floor rather than a
 * rule to fight: a cell with an answer of its own already outranks it — a card's padding,
 * a row's, a button's own — and a cell nobody has dressed lands on it and is right. The
 * reader's own option is the second kind: nothing dresses it, so it opens where the cells
 * open, and the floor is the whole of that rule rather than a copy of it further down.
 * That is also why it is stated out here rather than as `& > *`
 * inside the block: nested there it would carry the block's own two class columns and
 * clobber the form padding it is meant to defer to.
 *
 * Two floors, because they answer two questions. Where the group's words begin is the
 * whole group's, `settled` included: a settled group reserves the same column on the
 * cards behind its disclosure. Room above and below is the frame's, so only the joined
 * control asks for it. */
@media screen {
 :where(html:not(.lf-copy)) {
  :where(lf-options[choose]:not(:where([data-lf-exhibit]) *)) > * {
                     padding-inline-start: var(--lf-address-col); }
  :where(lf-options[choose]:not([settled]):not(:where([data-lf-exhibit]) *)) > * {
                     padding-block: var(--sp-2); padding-inline-end: var(--sp-3); }
 }
}
@media screen {
 html:not(.lf-copy) {
  lf-options[choose]:not([settled]):not(:where([data-lf-exhibit]) *) {
    display: grid; background: var(--card);
    border: 1px solid var(--border-2); border-radius: var(--r); overflow: hidden;
    /* The reader-origin outline would be a second exterior border around this already-
     * framed control. The joined control already shows the effective choice and its
     * state origin remains in the projection; keep the frame visually stable. */
    &[data-lf-reader-override] { outline: none; }
    /* The joined group draws a frame, so it says so, like every box that draws one
     * (--lf-frame, theme.css). Its cells declare their own; this covers what stands
     * beside them. */
    --lf-frame: 1;
    /* And it says which case its cells are in, for the rules that dress an option
     * standing alone (the axis is declared on lf-options, above). */
    --lf-joined: 1;
    /* Cells butt, so nothing brings a block margin into the group: the hairline below is
     * the whole of what separates one from the next, and a margin beside it is a second
     * way to say what the line already says, drawn as a rule floating in a band of
     * nothing. Over every child rather than over the kinds this block goes on to name.
     * The reader's own option and a thread question's Done press each had one for
     * standing alone, and each was written before the group
     * became a grid that stretches every child to the column. Naming them one at a time
     * is how the first two got reset here and the third did not, and the comment that
     * used to stand here called it a float that "does not fill the row" when the grid
     * had been filling it all along. */
    & > * { margin-block: 0; }
    /* A control packed into this group states its own inset (theme.css, --here-ring).
     * The group clips to the frame it draws, so a ring drawn outside a cell's box is
     * drawn into the pixels the frame cuts away: the Done press sits flush on the
     * group's bottom edge and lost the bottom run of its ring there, and the cells lose
     * their side runs the same way. Inset, the ring is inside the box it names and the
     * clip has nothing of it to take. The group's own frame is what stands off the
     * page, which is the gap's job on a box that stands alone. */
    & .lf-btn:is(:focus-visible, .lf-focus-visible) { outline-offset: calc(-1 * var(--here-ring-w)); }
    /* The hairline between neighbours: one line, stated once, on the upper of the
     * two, so a child no rule here names arrives already separated. It is the only
     * border in the group: a cell wears none of its own, and the card's is withheld
     * from a joined group rather than undone in it. The line used to be each
     * cell's own outer shadow, cast into a 1px grid gap: three declarations for
     * one line, every interior line painted twice, and the edges leaning on the
     * group's clip to take the overhang. */
    & > :not(:last-child) { border-bottom: 1px solid var(--rule); }
    /* A cell has no border of its own. Selection gets one quiet ground here; the mark's
     * check is its compact second channel. The vertical status bar that used to sit
     * beside both only repeated the same fact and made green read like focus. */
    & > lf-option { --fill: var(--card); background-color: var(--fill); }
    /* The aim wash. The cell under the pointer and the cell under the keyboard are the
     * same fact to the reader — this one is being weighed — so both wear one paint. It
     * deepens whatever the cell is filled with, rather than lifting it: a cell that
     * rose would pull away from the hairlines that are the whole of what joins the group.
     * One rule for every state, the pick included — clicking that one clears it, so it has
     * to keep answering the pointer. Toward the ink rather than toward black, so the same
     * declaration deepens on paper-white and lightens on the dark palette.
     *
     * The fill is not in the group's transition, and that is the choose block above rather
     * than an omission here: the tokens themselves change when the reader's system flips to
     * dark, so a transitioned background animates every cell of every group from one palette
     * to the other — a page repainting itself over a tenth of a second for a change nobody
     * on it made. It is also how the contrast sweep found this, by reading a cell mid-flip
     * and getting a grey that belongs to neither palette. */
    & > lf-option:is(:hover, :has(> .lf-pick:is(:focus-visible, .lf-focus-visible))) {
                     background: color-mix(in srgb, var(--fill) 92%, var(--ink)); }
    & > lf-option[chosen] { --fill: var(--ok-tint); }
    /* The add form is the group's own child, so joining the group takes it inside the
     * border too, butted against the last cell by the hairline every child shares. It is
     * a cell rather than a footer: it creates the option the reader writes when none of
     * the authored ones is the answer, so it opens at the column their words open at and
     * is filled the way an option nobody has picked is filled.
     *
     * Which is to say nothing is stated here at all, and that is the rule rather than an
     * omission twice over. The floor above is the whole of the inset, so the cell follows
     * the column when the column moves. And an unpicked option paints no fill of its own
     * either — `--fill` is `--card`, which is the group's own background showing through
     * — so a cell that states none is already wearing it, and a copy of the token here
     * would be a second place to change when the group's ground changes.
     *
     * It wore the footer's own clothes instead: `--field`, and a 12px inset that outranked
     * that floor. Both said apparatus, of the one cell in the group that takes an answer
     * the author didn't think of — sunk into a band below the answers, held 18px short of
     * the column every word around it opens at, dressed as the machinery a reader skips. */
    /* The joined control owns focus at row scale. The mark's generic ring stays off and
     * the exact option row draws one inset keyboard ring below; pointer focus draws none.
     * This leaves the permanent group frame as a frame rather than surrounding it with a
     * second border that disappears when the question is answered. */
    & > lf-option > .lf-pick:is(:focus-visible, .lf-focus-visible) { outline: none; }
  }
  /* The runtime's semantic location mark normally rings the whole Decision. Within an
   * options control that makes the permanent frame look like a second, stateful border.
   * Suppress that outer paint while focus is inside this control; keyboard focus is
   * carried by the exact row, while pointer focus needs no extra channel at all. */
  [data-lf-ask]:has(
    lf-options[choose]:not(:where([data-lf-exhibit]) *) :is(:focus, .lf-focus)
  ) { outline: none; }
  lf-options[choose]:not([settled]):not(:where([data-lf-exhibit]) *)
    > lf-option:has(> .lf-pick:is(:focus-visible, .lf-focus-visible)) {
      outline: var(--here-ring); --lf-here-ring: options-row;
      outline-offset: calc(-1 * var(--here-ring-w));
    }
  /* The add field's own outline is off (below), so the row it sits in is the only thing
   * that can answer the keyboard for it — in every group that shows the field, not just
   * the open ones. A settled group opened by its disclosure shows the same cell, and
   * scoped to :not([settled]) this rule left a reader who had Tabbed into it with
   * nothing on screen saying where they were. */
  lf-options[choose]:not(:where([data-lf-exhibit]) *)
    > .lf-another:has(textarea:is(:focus-visible, .lf-focus-visible)) {
      outline: var(--here-ring); --lf-here-ring: options-row;
      outline-offset: calc(-1 * var(--here-ring-w));
  }
  .lf-another { position: relative; display: flex; align-items: center; gap: var(--sp-2); }
  .lf-another:not([hidden]) { min-height: var(--aim-floor); }
  /* The field holds the option before it is recorded, so its words use the document's
   * face just as they will after the module turns them into an lf-option. Add remains a
   * real button with a compact visible word and the full accessible name. Positioned
   * over room the textarea reserves, hiding its empty state changes paint rather than layout. */
  .lf-another textarea { flex: 1; min-width: 0; padding: 0;
                     padding-inline-end: calc(var(--aim-floor) + var(--sp-4));
                     border: 0; outline: none; background: transparent; color: inherit;
                     font: var(--t-4)/1.6 var(--serif); resize: none; }
  .lf-another > .lf-btn { position: absolute; inset-inline-end: var(--sp-1);
                     inset-block-end: var(--sp-1);
                     display: flex; align-items: center; justify-content: center;
                     min-width: var(--aim-floor); height: var(--aim-floor);
                     padding: 0 var(--sp-1);
                     font: 600 var(--t-6)/1 var(--sans); }
  .lf-another > .lf-btn[data-lf-empty] { visibility: hidden; }
  /* The leading column holds the keyboard address and the gap before the option's
   * words. The address starts at the ordinary 8px inset and takes
   * --lf-key-box, so changing the utility type grows the
   * column with the chip. The final 6px keeps the chip off the prose. This room is held
   * before the keyboard address appears, so focusing an option moves nothing.
   *
   * Live pages only: copies and paper receive no keyboard address. The column is named
   * because options and generated cells all begin on it. */
  lf-options[choose]:not(:where([data-lf-exhibit]) *) {
                     --lf-address-start: var(--sp-2);
                     --lf-address-col: calc(var(--lf-address-start) + var(--lf-key-box) + 6px); }
  lf-options[choose]:not(:where([data-lf-exhibit]) *) > lf-option {
                     padding-inline-start: var(--lf-address-col); }
 }
}
html.lf-copy lf-options > .lf-another { display: none; }
/* The row form: a list, so it reads like one. Every row opens at the same column, the
 * mark leads it, and the apparatus that is about somewhere else — the block reference —
 * runs to the line's end.
 *
 * Leading with the mark cost that alignment once: a picked row's mark was wider than an
 * open one's by the word it said, so the labels came out ragged and the eye had nothing
 * straight to run down. That is no longer a fact about the mark. Its word is zero-sized
 * in every state and every form (the base rules above), so the box is 11px whether the
 * row is taken or open, and a column of them is exactly the straight edge the labels
 * were moved to the front for. What the trailing column cost instead was the answer to
 * "which of these did I take": in a full-width group the ticks stood ~620px from the
 * words they belong to, far enough that reading a row and reading its state were two
 * separate looks.
 *
 * A table, because a row is a run of prose with apparatus either side of it, and the
 * anonymous cell a table puts around that run is the only box the words can have while the
 * markup stays the author's. Laid out as flex items they had none: every stretch of a label
 * was an item of its own, so an inline <code> mid-label came out with the row's own 8px gap
 * either side of it and without the space that was written there — a flex item's edge
 * whitespace is trimmed, and the gap had been standing in for it on every label that was
 * one run.
 *
 * An open mark shows its dot and not its word, which is every form's rule rather than this
 * one's. The row form got there first and then argued the wrong reason for keeping the word
 * on a card — that a card has no dots beside it to say it — when a choose group has two to
 * five cards and every one carries a mark. The column was there; it was weak, spread down a
 * tall card, and the answer to that is to strengthen it, which is what both forms now do.
 *
 * The width is stated as the whole box, because another rule pads this one: a row fills its
 * cell, and a live choose group then takes 30px off the same box for the keyboard address
 * (above). Counted outside the 100%, those 30px carried every row past the group, which
 * clips itself, and what went was the last 30px of each line — at the time the column the
 * mark stood in, so the word came out mid-letter, the chosen option lost its tick, and the
 * open ones lost the box to tick. Four of the examples shipped a question that way. The
 * mark leads the row now and is out of that column's way, but the overflow it was the
 * symptom of is not: what the last 30px holds today is the block reference, and a row
 * running past its group still clips. A card is laid out at its own width and absorbs the
 * same padding without being told. */
lf-options:not(:has(> lf-option > strong)) > lf-option {
                     position: relative;
                     display: table; width: 100%; box-sizing: border-box;
                     border-spacing: var(--lf-row-gap) 0;
                     padding: 5px 0; --lf-frame: 1; }
/* The mark's own column, and every child of the group opens after it — the options and
 * the cell the reader writes their own option in alike, because the one thing that makes
 * a list of answers readable is that they all start at the same place.
 *
 * Beside the keyboard address rather than sharing its column: a card is tall enough to
 * hold both in one gutter at different heights, and a row is one line. So the row form
 * adds its own 17px to whatever column the group already opens on, and the mark stands
 * in the room that widening made.
 *
 * Stated twice because the two cases carry different weight, and the group's own column
 * is set at a weight the form has to clear: a live choose group states
 * --lf-address-col on every child, so the form's addition has to outrank that rather
 * than be reset by it. Without `choose` there is no address column and the mark's is
 * the whole of it. */
lf-options:not(:has(> lf-option > strong)) > :is(lf-option, .lf-another) {
                     --lf-pick-col: 17px; --lf-row-gap: var(--sp-2);
                     padding-inline-start: var(--lf-pick-col); }
lf-options[choose]:not(:where([data-lf-exhibit]) *):not(:has(> lf-option > strong))
                     > :is(lf-option, .lf-another) {
                     padding-inline-start: calc(var(--lf-address-col) + var(--lf-pick-col)); }
/* A row's table spacing holds its prose off the mark column. The form has no anonymous
 * table cell to supply that space, so its textarea takes the same named gap. Matching the
 * option's vertical inset makes the draft and the option it becomes one stable row. */
lf-options:not(:has(> lf-option > strong)) > .lf-another:not([hidden]) {
                     gap: 0; padding-block: 5px; padding-inline-end: var(--lf-row-gap); }
lf-options:not(:has(> lf-option > strong)) > .lf-another textarea {
                     margin-inline-start: var(--lf-row-gap); }
/* A cramped row still has three cells: its words, the block reference, and the mark.
 * Separate-border spacing also puts one gap outside each end, and those two empty gaps
 * made the table's minimum 14px wider than its group under Linux's wider apparatus in a
 * page narrowed by the thread panel. Keep the ordinary gutter while there is room and
 * use the compact spacing token when the group's own box is narrow; the cells retain a
 * visible gap without clipping the mark the reader presses. */
@container (max-width: 20rem) {
  lf-options:not(:has(> lf-option > strong)) > :is(lf-option, .lf-another) {
                     --lf-row-gap: var(--sp-1); }
}
/* The row's own ground: a corner to round and a wash to say its status in, both of which
 * are answers to standing alone. A joined row is a cell that butts its neighbours and
 * takes the group's stripe, so it is handed neither rather than having both undone. */
@container style(--lf-joined: 0) {
  lf-options:not(:has(> lf-option > strong)) > lf-option { border-radius: 6px; }
  lf-options:not(:has(> lf-option > strong)) > lf-option[chosen] {
                     background: var(--ok-tint); }
}
/* The wash is this form's whole answer to the pointer, where a card has a lift — so it
 * goes where the lift goes, behind the live-page guard and free of specificity for the
 * reasons stated there. It is also the only thing that ever draws a row's own box, so a
 * copy of a question was a list of bare labels with nothing to say it took an answer,
 * every one of which lit under a pointer that could not give one. */
@media screen {
 :where(html:not(.lf-copy)) {
  @container style(--lf-joined: 0) {
    lf-options[choose]:not(:where([data-lf-exhibit]) *):not(:has(> lf-option > strong))
                     > lf-option:hover { background: var(--chip); }
    lf-options[choose]:not(:where([data-lf-exhibit]) *):not(:has(> lf-option > strong))
                     > lf-option[chosen]:hover { background: var(--ok-tint); }
  }
 }
}
/* The apparatus takes a cell each and claims none of the row's free width, so what is
 * left over goes to the words and the mark ends every row at the same column, whether or
 * not a reference stands beside it. Which is what a row of flex items could not say: the
 * free space had to be handed to whichever part came first, so the column rested on an
 * attribute (`for`) the form does not require, and a row naming no block parked its mark
 * wherever its label happened to end.
 *
 * And each stands on the row rather than on its first line, which is the answer the
 * digit column below already gives: a label long enough to wrap carries the apparatus
 * down with it. The mark turns that from tidiness into a rule — its dot is out of flow
 * and centred on the row (below), so a word left on the baseline of a two-line label
 * sat a line above the tick it belongs to. */
lf-options:not(:has(> lf-option > strong)) > lf-option > .lf-ref {
                     display: table-cell; width: 0; white-space: nowrap;
                     vertical-align: middle; }
/* The mark stands in that column rather than in the table, which is the same answer a
 * card's mark has always had and it is here for the reason the form's own comment above
 * gives twice over: a cell takes its width from what the row happens to hold, so a row
 * naming no block came out eight pixels off its neighbours and carried whatever stood
 * beside it along. As a cell at the line's end that raggedness was the marks'; as a cell
 * at the line's start it was the labels', which is worse, because the labels are what the
 * reader runs their eye down. Out of flow it is neither: the column is the group's, the
 * mark is in it, and the words open at one place on every row.
 *
 * Centred on the row and not on its first line, which is the answer the digit column
 * below gives for the same reason — a label long enough to wrap carries its apparatus
 * down with it, and a word left on the baseline of a two-line label would sit a line
 * above the tick it belongs to. The height is stated because an absolute box given both
 * offsets and no height stretches to fill them. */
lf-options:not(:has(> lf-option > strong)) > lf-option > .lf-pick {
                     position: absolute;
                     inset-inline-start: var(--lf-address-col, 0px);
                     top: 0; bottom: 0; margin: auto 0; height: 11px; }
/* And the digit at the other end of the row takes the same answer, for the same reason: a
 * row is the words in it, so a mark that belongs to the row is centred on the box they
 * fill, and that stays true whatever size they are set at. It is the row and not the first
 * line — a label long enough to wrap carries its digit down with its mark, the two staying
 * level with each other. */
lf-options:not(:has(> lf-option > strong)) > lf-option > .lf-address {
                     top: 0; bottom: 0; margin: auto 0; }
/* The block a row is about (`for`). It points; it never supplies the row's words, so it
 * reads as what it is — an id, written the way the thread panel writes an element
 * anchor — and rides at the line's end with the mark, out of the way of what the row
 * says. */
.lf-ref { font-size: var(--t-6); color: var(--muted); text-decoration: none;
          white-space: nowrap; }
.lf-ref:hover { color: var(--accent); text-decoration: underline; }
/* The conversation's shared rules live with the integrated theme. The group's own
 * placement of it is stated above, in the choose-group block. */
/* Paper takes no input, so the group prints as one that was never choosable: the
 * marks offering a pick go with the rest of the UI, and the one on the card that
 * carries it stays to say which option the page holds. That needs no rule here —
 * the mark's label declares which kind of word it is (lf-options.js), and the
 * runtime hides the offers. Left hidden, a printout would state the decision in
 * the ok ring alone, which greyscale drops. */
/* `settled`: the decision is made and acted on, so the group reads as one line
 * — the disclosure the upgrade builds — with the cards behind it. Unupgraded, and
 * anywhere the disclosure has no handler behind it, every card shows. */
/* The row wears lf-ui, and the chrome face, size and ink it carries are the look; what
 * this states is only the row's own box and weight. (The part of the row naming the
 * chosen card is the page speaking and says so, which anchoring reads over the class —
 * see lf-options.js.) Laid out by the live-page block below; hidden until then, because
 * a button is worth showing only where something will answer it. */
lf-options[settled] > .lf-settled {
              display: none; width: 100%; align-items: baseline;
              min-height: var(--aim-floor);
              gap: var(--sp-2); margin: 0 0 var(--sp-2); padding: 7px 12px;
              font-weight: 600; text-align: left;
              background: var(--field); cursor: pointer;
              border: 1px solid var(--rule); border-radius: var(--r); }
/* Open or closed is the row's own expanded state, which is where the module says it
 * (aria-expanded) — the group wore an `open` attribute for these two rules, and that
 * is authored namespace for a fact no version carries (lf-options.js). */
lf-options[settled] > .lf-settled[aria-expanded="false"] { margin-bottom: 0; }
lf-options[settled] > .lf-settled:hover { border-color: var(--border-2); }
lf-options[settled] > .lf-settled:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: options-settled;
              outline-offset: 1px; }
.lf-settled::before { content: "▸"; color: var(--muted); font-weight: 400; }
.lf-settled[aria-expanded="true"]::before { content: "▾"; }
.lf-settled-count { margin-left: auto; font-weight: 400; font-size: var(--t-6);
                    color: var(--muted); white-space: nowrap; }
.lf-settled-diff { font-weight: 400; font-size: var(--t-6); padding: 0 6px;
                   border-radius: 999px; background: var(--add-tint); color: var(--ok-ink); }
/* The collapse is the whole of what the disclosure's handler does, so it is offered
 * only in the live page and every other medium gets the cards back by never being
 * handed it, rather than by undoing a hide. A page left holding the row elsewhere
 * would state a decision and offer no way to the options it was made among. */
@media screen {
  html:not(.lf-copy) {
    lf-options[settled] > .lf-settled { display: flex; }
    /* until-found keeps the card's own box in flow, and a card is bordered,
     * padded, and (stacked) margined — zero it all, or the collapse leaves a
     * stack of empty boxes behind. A block, because the content-visibility that
     * until-found collapses the box with is containment, and containment passes
     * over a table box without a word: a question row states its layout as a table
     * and stayed on screen under a closed disclosure, reading as a group that had
     * not collapsed at all. */
    lf-options[settled] > lf-option[hidden] { display: block; padding: 0; border: 0;
                                              box-shadow: none; margin: 0; }
    /* The boolean-hidden fallback (no until-found support) hides here, because the
     * display:block above outranks the UA's [hidden] rule. */
    lf-options[settled] > lf-option[hidden]:not([hidden="until-found"]) { display: none; }
  }
}
/* Paper cannot edit the document the way `version export` does, so collapsed cards keep
 * their hidden attribute and the content-visibility it carries is undone here. */
@media print {
  lf-options[settled] > lf-option { content-visibility: visible !important; }
}

/* lf-milestones / lf-milestone: a rail of status dots. The rail and dots are
 * CSS; the chip row (`when`, `tags`) is built by the lf-milestone upgrade. */
lf-milestones { display: block; margin: 14px 0 14px 8px; }
lf-milestone { display: block; position: relative; padding: 0 0 16px 26px;
               border-left: 2px solid var(--rule); --lf-frame: 1; }
lf-milestone:last-child { border-left-color: transparent; padding-bottom: 2px; }
lf-milestone::before { content: ""; position: absolute; left: -7px;
                       top: calc(0.5lh - 7px);
                       width: 10px; height: 10px; border-radius: 50%;
                       background: var(--paper); border: 2px solid var(--muted); }
lf-milestone[status="done"]::before   { background: var(--ok); border-color: var(--ok); }
lf-milestone[status="active"]::before { border-color: var(--accent);
                                        box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
lf-milestone[status="blocked"]::before { background: var(--danger); border-color: var(--danger); }
lf-milestone > strong { display: block; margin: 0 0 2px; }
lf-milestone[status="done"] > strong { color: var(--muted); }
.lf-chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 2px 0 6px; }
/* The status word a reader listening gets wears the runtime's .lf-ui .lf-quiet —
 * real text, clipped on screen where the dot already says it. Which attributes get
 * one is declared (x-paints) and the writing is the runtime's own pass, so
 * lf-event's kind is spoken here too. It was left silent while these two spoke, on
 * the reading that saying it meant giving the timeline its first module and the
 * quoting fence an upgrade brings with it — which was true of the answer being
 * copied and not of the question. A declaration costs neither. */

/* lf-timeline / lf-event: an event log on a rail. The dot is ::after, absolute,
 * colored by kind; the time label is the `at` attribute, said above the title. */
lf-timeline { display: block; margin: 14px 0 14px 8px; }
lf-event { display: block; position: relative; padding: 0 0 16px 26px;
           border-left: 2px solid var(--rule); --lf-frame: 1; }
lf-event:last-child { border-left-color: transparent; padding-bottom: 2px; }
lf-event::after { content: ""; position: absolute; left: -7px; top: 4px;
                  width: 10px; height: 10px; border-radius: 50%;
                  background: var(--paper); border: 2px solid var(--muted); }
lf-event[kind="info"]::after    { background: var(--muted); }
lf-event[kind="action"]::after  { background: var(--accent); border-color: var(--accent); }
lf-event[kind="warning"]::after { background: var(--warn); border-color: var(--warn); }
lf-event[kind="failure"]::after { background: var(--danger); border-color: var(--danger); }
lf-event[at]::before,
lf-event > [data-lf-said="at"] { display: block; font-family: var(--mono);
                       font-size: var(--t-6); color: var(--muted); margin-bottom: 1px; }
lf-event[at]::before { content: attr(at); }
lf-event:has(> [data-lf-said="at"])::before { content: none; }
lf-event > strong { margin-right: 6px; }

/* lf-compare / lf-variant: labeled columns; exhibition, not decision.
 *
 * A cell takes its width from the group and its height from what it holds. Stretch is
 * the grid's own default and it draws empty boxes: out of 720px of column a one-sentence
 * variant beside a six-line one came out 278px tall, 190 of that blank under a single
 * line, which reads as a card whose words failed to arrive.
 *
 * That leaves a last row with room to spare — four terse variants come out three across
 * and one under them at a third of the row, seven as 3, 3 and 1. The two ways of filling
 * it both pay in cell width: a wrapped flex line grows its items, and a column count read
 * off the child count is a different width per count. An exhibition is read down its
 * columns as much as across its rows, and a card wider than its peers because it happened
 * to be last says something about that variant that isn't true. So the room stays. */
lf-compare { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
             align-items: start; gap: var(--sp-3); margin: 14px 0; }
lf-variant { display: block; border: 1px solid var(--rule); border-radius: var(--r);
             padding: var(--sp-3); background: var(--card); --lf-frame: 1; }
lf-variant > strong { display: block; margin: 0 0 4px; }

/* lf-metrics / lf-metric: a KPI row. The value leads, said from the attribute;
 * the delta trails and colors by sign × direction — honest coloring, no JS. */
lf-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
             gap: var(--sp-3); margin: 14px 0; }
lf-metric { display: block; border: 1px solid var(--rule); border-radius: var(--r);
            padding: 10px 14px; background: var(--card); font-size: var(--t-6);
            text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
            --lf-frame: 1; }
lf-metric::before,
lf-metric > [data-lf-said="value"] { display: block; font-size: var(--t-2);
                    font-weight: 600; line-height: 1.3; letter-spacing: -0.01em;
                    text-transform: none; color: var(--ink); }
lf-metric::before { content: attr(value); }
lf-metric:has(> [data-lf-said="value"])::before { content: none; }
lf-metric[delta]::after,
lf-metric > [data-lf-said="delta"] { display: inline-block; margin-left: 6px;
                          padding: 0 7px; border-radius: 999px; letter-spacing: 0;
                          text-transform: none; font-size: var(--t-6); line-height: 1.6;
                          background: var(--chip); color: var(--ink-2); }
lf-metric[delta]::after { content: attr(delta); }
lf-metric:has(> [data-lf-said="delta"])::after { content: none; }
lf-metric[direction="up-good"][delta^="+"]::after,
lf-metric[direction="up-bad"][delta^="-"]::after,
lf-metric[direction="up-good"][delta^="+"] > [data-lf-said="delta"],
lf-metric[direction="up-bad"][delta^="-"] > [data-lf-said="delta"]
                    { background: var(--ok-tint); color: var(--ok-ink); }
lf-metric[direction="up-good"][delta^="-"]::after,
lf-metric[direction="up-bad"][delta^="+"]::after,
lf-metric[direction="up-good"][delta^="-"] > [data-lf-said="delta"],
lf-metric[direction="up-bad"][delta^="+"] > [data-lf-said="delta"]
                    { background: var(--danger-tint); color: var(--danger-ink); }

/* lf-board / lf-column / lf-card: the one widget the user edits directly.
 * All presentation is CSS; the lf-board upgrade only wires dragging (grips,
 * dropzones) and reports each drop as a `move` action. Unupgraded it reads as a
 * static board. */
lf-board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(10rem, 1fr);
           gap: var(--sp-2); margin: 14px 0; align-items: stretch; overflow-x: auto; }
lf-column { display: block; background: var(--field); border: 1px solid var(--rule);
            border-radius: var(--r); padding: 8px; min-height: 64px; --lf-frame: 1; }
/* The heading is written by lf-board.js rather than by the x-says pass, because
   it is the list's accessible name as well as its visible words and the pass
   knows nothing about names. Where the upgrade ran, the column carries those
   words as its name and the span is aria-hidden, so they reach the tree once;
   where no script runs at all there is no name either, and the generated copy
   is the whole rendering, audible as well as visible. */
lf-column::before,
lf-column > [data-lf-said="label"] { display: block; font-size: var(--t-6);
            text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
            padding: 2px 4px 8px; }
lf-column::before { content: attr(label); }
lf-column:has(> [data-lf-said="label"])::before { content: none; }
lf-card { display: block; position: relative; background: var(--card);
          border: 1px solid var(--rule); border-radius: var(--r);
          padding: 8px 10px; margin: 0 0 var(--sp-2); --lf-frame: 1; }
/* The column the grip hangs in, spent only where a grip hangs: the module measures its
   own grip's box and states the room (--lf-grip-room, lf-board.js), the same answer the
   pick column already is, so the ladder moving or a platform substituting a different
   glyph re-measures itself. The number this replaces was 34px read out of a browser
   once — and stated unconditionally, so paper, exported copies and quoted boards, none
   of which ever grow a grip, all carried a dead column beside every card. No module, no
   var, no room; the copy keeps the var in the serialized style attribute, which is why
   the rule asks the medium too. */
@media screen {
 :where(html:not(.lf-copy)) {
  lf-card { padding-right: calc(10px + var(--lf-grip-room, 0px)); }
 }
}
lf-card:last-child { margin-bottom: 0; }
lf-card > strong { display: block; margin: 0 0 2px; }
/* The grip is a press, so the keyboard reaches it: Enter grabs, arrows move. It says no
   size, because `offer` builds it wearing .lf-ui and the runtime's own rule sets that
   face's size once for every control in the layer — the 14px stated here was --t-5
   written out a second time, under a selector specific enough to win, so the chrome's
   size would have moved everywhere but on a card's grip. `line-height: 1` stays: .lf-ui
   sets a line of its own, and this glyph wants none. */
lf-card .lf-grip { position: absolute; top: 2px; right: 0; color: var(--muted);
          padding: 8px 10px; cursor: grab;
          min-height: var(--aim-floor); min-width: var(--aim-floor);
          border-radius: 4px; user-select: none;
          -webkit-user-select: none; line-height: 1;
          touch-action: none; /* the handle owns the gesture; scroll stays on the card */ }
lf-card:hover > .lf-grip { color: var(--ink-2); }
lf-card .lf-grip:hover { background: var(--chip); }
/* The ring is inset rather than offset a pixel out, as the layer's other small controls
   have theirs, because this one is flush with its card's edge inside lf-board, which
   scrolls sideways. At the width where three columns reach their 10rem floor the board
   clips a pixel outside the last column's cards, so the ring's right run and both
   corners on that side fell outside the clip while the grip itself stayed whole. An
   inset ring cannot leave the box it names, at any scroll position. */
lf-card .lf-grip:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: card-grip; outline-offset: calc(-1 * var(--here-ring-w));
          color: var(--ink-2); }
/* SortableJS drag states: the in-flow slot, the pressed card, the follower. */
lf-card.lf-ghost { opacity: .4; border-style: dashed; border-color: var(--accent); }
lf-card.lf-lift { box-shadow: 0 2px 8px var(--shade); }
/* (No transform here: Sortable positions the follower with an inline matrix.) */
lf-card.lf-inhand { opacity: 1; cursor: grabbing;
                    box-shadow: 0 8px 24px var(--shade); }
/* lf-tabs / lf-tab: parallel workstreams, one panel on screen at a time. The
 * strip is generated by the upgrade; which tab is open is the reader's view
 * state, so everything here is presentation. On a live page the strip is a
 * typographic index inside the panel's one frame: its closing rule separates the
 * index from the workstream, and the frame answers how far that workstream runs.
 * Unupgraded, and anywhere the strip has no handler behind it, the panels stack
 * as labeled sections. */
lf-tabs { display: block; margin: 14px 0; }
lf-tab { display: block; }
lf-tab::before { content: attr(label); display: block; font-size: var(--t-6);
                 text-transform: uppercase; letter-spacing: .05em;
                 color: var(--muted); margin: 18px 0 8px; }
lf-tabs.lf-rendered > lf-tab { margin-top: 14px; }
/* Laid out by the live-page block below; hidden until then, because a row of
 * buttons is worth showing only where something will answer one. */
.lf-tabstrip { display: none; flex-wrap: wrap; gap: 2px;
               border-bottom: 1px solid var(--border-2); }
.lf-tabstrip .lf-tab-btn { padding: 5px 7px 7px;
               min-height: var(--aim-floor); min-width: var(--aim-floor);
               display: inline-flex; align-items: center; justify-content: center;
               color: var(--muted); cursor: pointer; }
.lf-tabstrip .lf-tab-btn:hover { color: var(--ink-2); }
/* A tab is a span the module gives a role and a tab stop to, so the only mark it wore
 * for the keyboard was the platform's own — beside a strip whose every other control
 * wears the layer's band, which reads as the walk leaving the page. Inset, because the
 * button's foot is on the strip's rule and an outset band would be drawn over it. */
.lf-tabstrip .lf-tab-btn:is(:focus-visible, .lf-focus-visible) {
               outline: var(--here-ring); --lf-here-ring: tab-btn;
               outline-offset: calc(-1 * var(--here-ring-w)); }
/* Every name reserves the same square face; selection paints it without changing any
 * control's measure. */
.lf-tabstrip .lf-tab-btn > [data-lf-said] {
               display: inline-block; padding: 2px 5px; }
.lf-tabstrip .lf-tab-btn[aria-selected="true"] > [data-lf-said] {
               background: var(--card); color: var(--ink); }
.lf-tabdiff { font-size: var(--t-6); font-weight: 400; margin-left: 6px;
              padding: 0 6px; border-radius: 999px;
              background: var(--add-tint); color: var(--ok-ink); }
/* One panel at a time is the whole of what the strip's handler does, so it is
 * offered only in the live page and the rest is what the markup already says.
 * A control whose state the browser owns needs no such block and has none;
 * that is the whole difference between this widget and lf-shot's checkbox. */
@media screen {
  html:not(.lf-copy) {
    /* :where keeps the frame face below the generic edge trim's specificity. */
    :where(lf-tabs.lf-rendered) { margin: var(--sp-4) 0 32px;
      border: 1px solid var(--border-2); border-radius: var(--r);
      background: var(--card); --lf-frame: 1; }
    .lf-tabstrip { display: flex; padding: 8px 8px 0;
      border-radius: calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0;
      background: var(--field); }
    lf-tabs.lf-rendered > lf-tab::before { content: none; } /* the strip carries the label */
    /* Padding belongs only to the panel on screen. An until-found panel keeps a box in
     * flow, so padding on every panel would leave one blank band per preceding tab. */
    lf-tabs.lf-rendered > lf-tab { margin: 0; padding: 0; }
    lf-tabs.lf-rendered > lf-tab:not([hidden]) {
      padding: var(--sp-4); --lf-frame: 1;
    }
    /* A section is the usual one-child wrapper for a self-contained workstream. Let it
     * pass the panel's edge trim through, so its opening heading and closing paragraph
     * spend exactly the panel inset rather than adding collapsed block margins to it. */
    lf-tabs.lf-rendered > lf-tab:not([hidden]) > :only-child { --lf-frame: 1; }
    /* until-found keeps the element's own box in flow; zero it so inactive panels
     * leave no stray gap below the active one. */
    lf-tabs.lf-rendered > lf-tab[hidden] { margin: 0; }
    /* The boolean-hidden fallback (no until-found support) hides here, because the
     * display:block above outranks the UA's [hidden] rule. */
    lf-tabs.lf-rendered > lf-tab[hidden]:not([hidden="until-found"]) { display: none; }
  }
}
/* Paper cannot edit the document the way `version export` does, so inactive panels keep
 * their hidden attribute and the content-visibility it carries is undone here. */
@media print {
  lf-tabs.lf-rendered > lf-tab { content-visibility: visible !important; }
}

/* lf-shot: both frames share one grid cell sized by the taller image, so a flip
 * moves nothing below it. The rail keeps before and after at fixed ends while a short
 * accent rule names the visible state. The transparent native checkbox covers only
 * the frame; the shared margin Button supplies the second control. CSS owns image
 * visibility, keeping image clicks and Space live in script-free exports. Print stacks
 * both. */
lf-shot { display: block; margin: 16px 0; }
lf-shot .lf-shotframe { position: relative; grid-area: 2 / 1;
    border: 1px solid var(--rule); border-radius: 0 0 var(--r) var(--r); overflow: hidden;
    background: var(--card); }
lf-shot:has(.lf-shotframe) { display: grid; }
lf-shot .lf-shotframe img { display: block; width: 100%; height: auto;
    background: var(--card); }
lf-shot .lf-shotframe[data-lf-state="after"] { visibility: hidden; }
lf-shot:has(input:checked) .lf-shotframe[data-lf-state="before"] { visibility: hidden; }
lf-shot:has(input:checked) .lf-shotframe[data-lf-state="after"] { visibility: visible; }
lf-shot .lf-shotrail { display: flex; grid-area: 1 / 1; align-items: center;
    justify-content: space-between; height: 34px; padding: 0 11px;
    border: 1px solid var(--rule); border-bottom: 0;
    border-radius: var(--r) var(--r) 0 0; color: var(--muted);
    background: var(--card); }
lf-shot .lf-shotcap { display: flex; align-items: center; align-self: stretch;
    font-size: var(--t-6); font-weight: 650; text-transform: uppercase;
    letter-spacing: .04em; }
lf-shot .lf-shotcap[data-lf-state="before"],
lf-shot:has(input:checked) .lf-shotcap[data-lf-state="after"] { color: var(--ink);
    box-shadow: inset 0 -2px var(--accent); }
lf-shot:has(input:checked) .lf-shotcap[data-lf-state="before"] {
    color: var(--muted); box-shadow: none; }
/* The image is itself the native target, so a click never forwards focus to a
   distant label or control and scrolls a tall comparison out from under the reader. */
lf-shot > input.lf-shotflip { grid-area: 2 / 1; z-index: 2;
    align-self: stretch; justify-self: stretch; width: 100%; height: 100%;
    min-width: 0; min-height: 0; margin: 0; padding: 0; border: 0;
    appearance: none; opacity: 0; cursor: pointer; }
/* The rail and the frame are one card, so the ring goes round the card. Drawn on the
   frame alone it ran along the rail's foot instead of round anything, and the rail's
   own surface stands where its top run is. lf-shot paints nothing of its own, so the
   radius here is the card's outer corners lent to the outline and reaches nothing
   else. */
lf-shot:has(> input.lf-shotflip:is(:focus-visible, .lf-focus-visible)) { outline: var(--here-ring);
    --lf-here-ring: shot; outline-offset: 1px; border-radius: var(--r); }

@media print {
  lf-shot, lf-shot:has(.lf-shotframe) { display: block; }
  lf-shot > .lf-shotrail { border-bottom: 1px solid var(--rule);
    border-radius: var(--r); margin-bottom: var(--sp-2); }
  lf-shot .lf-shotcap { color: var(--ink) !important; box-shadow: none !important; }
  lf-shot .lf-shotcap[data-lf-state="before"]::after { content: " · top"; }
  lf-shot .lf-shotcap[data-lf-state="after"]::after { content: " · bottom"; }
  lf-shot > input.lf-shotflip { display: none; }
  lf-shot .lf-shotframe { visibility: visible !important; margin-bottom: var(--sp-2);
    border-radius: var(--r); }
}

/* lf-toc: the page's route. In ordinary flow it is a compact, open outline. Its roomy
 * margin form is a reading map: the widget gives each row the length of the section it
 * leads, flex lays those shares down the full available height, and the darker lens on
 * the spine shows the band currently in view. The markers therefore describe the page
 * while every repeated heading is quiet. Pointer entry, keyboard entry, or the go-to
 * chord fades the labels in without changing any row's box. The transparent first layer
 * receives the revealing gesture, then the links become pointer targets when that fade
 * is complete; an unseen label cannot navigate on the gesture that discovers it.
 *
 * The start row repeats the page title in that map, and on paper, where the outline is
 * the one reading of the route and keeps every word the map says; the open outline on
 * screen sits under the title and leaves it out. It is still navigation apparatus, so
 * weight and ink distinguish it within the same sans voice as the section labels. Their common inset then reads as one route rather than two typographic systems.
 * Depth changes only the labels' inset. Every knot stays on the same spine, and every
 * label is limited to two lines and packs around the markers without changing their
 * positions, so prose never distorts the map.
 * The open, paper, and copy forms retain the complete words.
 *
 * The one-pixel sibling target is what leaves native fragment navigation behind in a
 * standalone copy. Its negative end margin gives it no net height, while the real box
 * lets the shared arrival pass align a copied link precisely rather than stopping as
 * soon as a zero-height point enters the viewport. */
lf-toc { display: block; margin: var(--sp-4) 0 30px; }
lf-toc:empty { display: none; }
lf-toc .lf-toc-nav { position: relative; border-left: 1px solid var(--border-2);
                     padding-left: var(--sp-3); color: var(--muted);
                     font: var(--t-5)/1.3 var(--sans); }
lf-toc .lf-toc-heading { margin: 0 0 7px; color: var(--ink-2);
                         font-size: var(--t-6); font-weight: 650;
                         letter-spacing: .08em; text-transform: uppercase; }
lf-toc .lf-toc-start, lf-toc .lf-toc-window { display: none; }
@media print { lf-toc .lf-toc-start { display: block; } }
lf-toc ol { list-style: none; margin: 0; padding: 0; }
lf-toc li { --lf-toc-indent: 0px; margin: 0 0 0 var(--lf-toc-indent); }
lf-toc li[data-lf-depth="1"] { --lf-toc-indent: 10px; }
lf-toc li[data-lf-depth="2"] { --lf-toc-indent: 20px; }
lf-toc li[data-lf-depth="3"] { --lf-toc-indent: 30px; }
lf-toc li[data-lf-depth="4"] { --lf-toc-indent: 40px; }
lf-toc a { display: inline-block; padding: 3px 0; color: inherit;
           text-decoration: none; }
lf-toc a:hover, lf-toc a:focus-visible { color: var(--accent); }

@keyframes lf-toc-enable-links {
  to { pointer-events: auto; }
}

/* The core sidebar states its actual posture after viewport and panel-room decisions.
 * Only a fine-pointer margin form fixes itself into a viewport map; generic sidebars keep
 * their sticky behavior and an in-flow ToC stays open. The shell inset moves the fixed map
 * beside a standing left workspace. */
@media screen and (hover: hover) and (pointer: fine) {
  @container style(--lf-sidebar-posture: margin) {
    lf-toc { position: fixed;
             left: calc(var(--lf-shell-inset-left, 0px) + var(--sp-4));
             top: calc(var(--lf-banner-h, 0px) + var(--sp-4));
             /* The generic sidebar guarantees a 240px map and its gutter. Once the
              * reading column can stay centred with room left over, spend that empty
              * margin on shorter labels until the map reaches 320px. */
             width: clamp(
               calc(var(--sidebar) - var(--sp-4)),
               calc((100cqi - min(var(--col), var(--lf-room))) / 2
                 + var(--lf-shift) - 2 * var(--sp-4)),
               320px);
             height: calc(100vh - var(--lf-banner-h, 0px) - 2 * var(--sp-4));
             margin: 0; }
    body[data-lf-upgraded="1"] lf-toc { transition: left .18s ease; }
    body[data-lf-sizing] lf-toc { transition: none; }
    lf-toc .lf-toc-nav { height: 100%; border: 0; padding: 0;
                         --lf-toc-label-opacity: 0;
                         pointer-events: none; }
    lf-toc .lf-toc-nav::before { content: ""; position: absolute; inset: 0;
                                 z-index: 0; pointer-events: auto; }
    lf-toc .lf-toc-heading { display: none; }
    lf-toc .lf-toc-rows { position: relative; display: flex; height: 100%;
                          flex-direction: column; }
    lf-toc .lf-toc-rows::before { content: ""; position: absolute;
                                  z-index: 0; top: 0; bottom: 0; left: 0; width: 1px;
                                  background: var(--border-2); }
    lf-toc .lf-toc-window { display: block; position: absolute; z-index: 1;
                            top: var(--lf-toc-window-start, 0%);
                            left: 0; width: 1px;
                            height: var(--lf-toc-window-size, 12%);
                            min-height: 14px; border-radius: 2px;
                            background: var(--ink-2); }
    lf-toc .lf-toc-start, lf-toc li { --lf-toc-indent: 0px;
                                      position: relative; z-index: 2; display: block;
                                      flex: var(--lf-toc-span, 1) 1 0px;
                                      min-height: 0; margin: 0; }
    lf-toc ol { display: contents; }
    lf-toc .lf-toc-start::before, lf-toc li::before {
      content: ""; position: absolute; z-index: 2;
      top: 7px; left: -1px; width: 3px; height: 3px; border-radius: 50%;
      background: var(--muted);
    }
    lf-toc :is(.lf-toc-start, li):has(> a[aria-current="location"])::before {
      background: var(--ink-2);
    }
    lf-toc li[data-lf-depth="1"] { --lf-toc-indent: 10px; }
    lf-toc li[data-lf-depth="2"] { --lf-toc-indent: 20px; }
    lf-toc li[data-lf-depth="3"] { --lf-toc-indent: 30px; }
    lf-toc li[data-lf-depth="4"] { --lf-toc-indent: 40px; }
    lf-toc .lf-toc-start a, lf-toc li a {
      position: absolute; z-index: 3; display: -webkit-box;
      top: var(--lf-toc-label-shift, 0px); left: 0; width: 100%;
      overflow: hidden; max-height: 2.6em;
      padding: 0 2px 2px calc(14px + var(--lf-toc-indent));
      line-height: 1.3; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
      opacity: var(--lf-toc-label-opacity); pointer-events: none;
      transition: color .12s ease-out, opacity .24s ease-out;
    }
    lf-toc .lf-toc-start a { color: var(--ink-2); font-weight: 650;
                             line-height: 1.2; max-height: 2.4em; }
    lf-toc li a[aria-current="location"] { color: var(--ink-2); }
    lf-toc a:focus-visible { outline: var(--here-ring); --lf-here-ring: toc-link;
                             outline-offset: calc(-1 * var(--here-ring-w)); }
    lf-toc .lf-toc-nav:is(:hover, :focus-within, body[data-lf-goto] *) {
      --lf-toc-label-opacity: 1;
    }
    lf-toc .lf-toc-nav:is(:hover, :focus-within, body[data-lf-goto] *) a {
      animation: lf-toc-enable-links 0s .24s forwards;
    }
    /* When all labels cannot fit beside the track, the destination under the pointer or
     * keyboard focus reveals on its own. Turning the rail into a second scrollable outline
     * would put the markers and viewport lens in a different coordinate system. */
    lf-toc[data-lf-dense] .lf-toc-rows { overflow: hidden; }
    lf-toc[data-lf-dense] :is(.lf-toc-start, li) {
      min-height: 0; pointer-events: auto;
    }
    lf-toc[data-lf-dense] :is(.lf-toc-start, li) a {
      top: 0;
      max-height: 1.25em; font-size: var(--t-6); line-height: 1.25;
      -webkit-line-clamp: 1;
    }
    lf-toc[data-lf-dense] li:last-child a { top: auto; bottom: 0; }
    lf-toc[data-lf-dense] .lf-toc-nav:is(:hover, :focus-within, body[data-lf-goto] *) a {
      opacity: 0; animation: none; pointer-events: none;
    }
    lf-toc[data-lf-dense] .lf-toc-nav:hover
      :is(.lf-toc-start, li):hover a,
    lf-toc[data-lf-dense] .lf-toc-nav:focus-within a:focus {
      opacity: 1;
      animation: lf-toc-enable-links 0s .24s forwards;
    }
  }
}
@media (prefers-reduced-motion: reduce) {
  lf-toc a { transition: none; }
  @container style(--lf-sidebar-posture: margin) {
    lf-toc .lf-toc-nav:is(:hover, :focus-within, body[data-lf-goto] *) a {
      animation: none; pointer-events: auto;
    }
    lf-toc[data-lf-dense] .lf-toc-nav:is(:hover, :focus-within, body[data-lf-goto] *) a {
      opacity: 0; pointer-events: none;
    }
    lf-toc[data-lf-dense] .lf-toc-nav:hover
      :is(.lf-toc-start, li):hover a,
    lf-toc[data-lf-dense] .lf-toc-nav:focus-within a:focus {
      opacity: 1; pointer-events: auto;
    }
  }
}
@media (forced-colors: active) {
  lf-toc .lf-toc-rows::before,
  lf-toc .lf-toc-start::before, lf-toc li::before {
    forced-color-adjust: none; background: CanvasText;
  }
  lf-toc .lf-toc-window,
  lf-toc :is(.lf-toc-start, li):has(> a[aria-current="location"])::before {
    forced-color-adjust: none; background: Highlight;
  }
}
.lf-toc-target { display: block; width: 1px; height: 0; }

/* lf-ask: a semantic reading and arrival boundary, with no presentation of its own.
 * Block rather than the custom-element default inline so its box begins at the
 * question's opening and reaches around the context and control the standing ring says
 * are one Decision. Child margins keep the same ordinary block rhythm they have in a section. */
lf-ask { display: block; }

/* lf-specimen: quoted material — a widget or section the page exhibits rather
 * than speaks (a sample decision, a demo board). It wears the quotation idiom, a
 * muted left gutter — not the callout's tinted field, and not the left-accent bar
 * that rule forbids: a quotation's gutter marks provenance, an accent bar demands
 * attention. The content itself renders at full fidelity
 * (an exhibit must show the real thing), so the gutter alone says "mention, not
 * use". Input never leaves one: the interactive widgets check quoted() before
 * wiring (lf-options.js, lf-board.js), so a quoted choose group renders as though
 * it never declared `choose` and a quoted board stays the static board the theme
 * already renders.
 *
 * The gutter runs beside the exhibit and nothing else. The note naming it — this
 * theme's "quoted ·" over the author's label — is a word *about* the quoted
 * region rather than a word in it, and it opened the gutter from inside: the marking
 * took in a line the quoted page never said, and the exhibit read as though it came
 * with a heading of its own. Every other reading had it right — the quote search, the
 * diff and the capture all take the note where the file has it, first inside the
 * element — so the one account that was wrong was the one the reader could see.
 *
 * The word over it is the reader's; `lf-specimen` is the author's. A tag names a member
 * of a vocabulary its author picks from and can afford a word to learn, where the note's
 * whole job is telling a reader who has met none of that vocabulary that the page is
 * showing this rather than saying it. The tag keeps its own name because the plain one is
 * spoken for on the other side: a quote here is the passage a comment is made on, and an
 * `lf-quote` would put that mechanism's word on one of the things a page can hold.
 *
 * `display: table` is what stands it outside. A caption box is laid out beyond the
 * table box's border, in flow, so it reserves its own room and wraps like any other
 * run of words — where lifting the note out with absolute positioning would hang the
 * room above the gutter on a number read out of a browser once, and land the note on
 * the paragraph above it the day a label wraps. The exhibit keeps the layout it had:
 * consecutive non-table children are wrapped in one anonymous cell, so what is
 * inside is a block flow whose margins collapse between its blocks exactly as they do
 * out on the page, which is the fidelity an exhibit is for. What a cell cannot do is
 * let the outermost of them collapse *out*, and that is a paragraph of its own below.
 * Nor does the box become a table to anything
 * that reads the page: Chrome types it LayoutTable where it typed the block generic,
 * and stops there — the row and the cell are anonymous boxes and neither reaches the
 * accessibility tree.
 *
 * What the layout costs is a declaration for each thing a block had for free. A table
 * shrink-wraps, so the width is asked for whole and stated border-box, which is what
 * keeps the gutter and the inset inside the column rather than 27px past it. And a
 * table sizes to its content besides, so the board on the how-it-works page came out
 * 523px wide in a 380px column, with the document scrolling sideways to reach what the
 * board's own overflow was holding — which is what `table-layout: fixed` settles, and
 * what test_a_specimen_holds_a_wide_exhibit_inside_the_column holds it to.
 *
 * The bar is a pixel heavier than the 2px it was and the exhibit is set deeper: the
 * bar is the whole of the marking now that the note stands off it, and it is read
 * against content that draws its own boxes — a specimen full of cards is one more line
 * on a page of borders, where a quoted paragraph is the only rule in a column of prose.
 * The note stands 4px off the bar and the theme's own 18px under the paragraph above,
 * because proximity is what says which block a line belongs to, and this line belongs
 * to the exhibit.
 *
 * Beside the exhibit is how far the bar runs as well as where it starts, and the cell is
 * what made that a rule to write rather than something that happens. A block reserves
 * room against the neighbours it expects; a table cell is a margin barrier, so the room
 * the exhibit's outermost blocks reserve cannot collapse out of the marking and is
 * painted as bar instead. Sixteen pixels of it over the first card and under the last,
 * on every specimen in the corpus, held for neighbours that are not there — and the
 * reader who reported it read the top as the loose end, because the note is 4px off the
 * bar and so appears to open it, leaving a marking that begins at a line and then waits
 * twenty pixels for the thing it is marking. So the specimen states no padding of its
 * own and declares the frame, which drops those margins where they abut the marking:
 * what separates a specimen from the prose around it is its own 18px, stated once.
 *
 * The trim that declaration buys is the layer's (theme.css), and the reach is the direct
 * children, which is what a selector has. Nothing about the note is stated here, though
 * it is a child on a live page (`x-says` writes it `before`) and a pseudo-element on one
 * carrying no script: the trim asks for the first child the page itself put there, so
 * both arrangements come out the same and the exhibit's first block is what it lands on.
 *
 * A child that generates no box hands its own margins to the flow and the trim lands on
 * nothing. The one such widget shipped is the suggestion, and it is why the block slot
 * asks for its room above rather than around itself (theme.css) — which leaves one edge
 * rather than two, measured: a suggestion leading a specimen still holds its 10px. Which
 * edge is left follows from the room having to sit on one side, and the other side was
 * worse — stated between siblings, it could not cross the boxless wrapper at all, and two
 * suggestions in a row on a shipped page shut against each other. A box that stands in
 * that position and has one declares the frame itself, one level in, which is the answer
 * `.facts` takes; a suggestion has no box to declare it on. Reaching a level further from
 * out here is the fix that suggests itself, and it
 * trades a silent failure for a worse one: the grandchild whose margin shows is the
 * grandchild of a *boxless* parent, and the same selector over a padded one — a callout
 * leading a specimen — closes up that box's own first line, which is the exhibit
 * rendering at less than full fidelity, the one thing a specimen promises. So no
 * selector reaches the next boxless widget either, and what holds this is a reading of
 * the painted bar against the exhibit's own boxes over every specimen the corpus has
 * (test_the_gutter_runs_beside_the_exhibit_and_no_further) — loud where the rule goes
 * quiet, and what a leading suggestion meets the day one is written. */
lf-specimen { display: table; table-layout: fixed; width: 100%;
              box-sizing: border-box; margin: 18px 0; padding-left: var(--sp-4);
              border-left: 3px solid var(--border-2); --lf-frame: 1; }
lf-specimen::before,
lf-specimen > [data-lf-said="label"] { display: table-caption;
              font-size: var(--t-6); margin-bottom: var(--sp-1);
              letter-spacing: .08em; text-transform: uppercase;
              color: var(--muted); }
lf-specimen::before { content: "quoted"; }
lf-specimen[label]::before { content: "quoted · " attr(label); }
lf-specimen:has(> [data-lf-said="label"])::before { content: none; }
lf-specimen > [data-lf-said="label"]::before { content: "quoted · "; }
/* A quoted choose group renders as one that never declared `choose`. That promise is
 * kept where each pressable look is granted, not undone here: every affordance rule in
 * the lf-options section — the hand, the lift, the joined shape, the reserved strip and
 * address column, the row wash — excludes exhibits in its own selector
 * (`:not(:where([data-lf-exhibit]) *)`, the marker the runtime paints from this entry's
 * x-exhibit), because an unkeying block here lost every contest against a plainly-spelled
 * guard and missed every affordance written after it. The upgrade holds the half no
 * stylesheet can: the click handler (quoted(), lf-options.js). What stays
 * quoted is the document's state — a chosen card's mark and ring — because a mention
 * shows the decision without offering it. */

/* Upgraded widgets: pre-upgrade presentation, so a page degrades readably.
 *
 * The integrated theme's code tokens set the density here too. The authored body
 * inside these widgets is a <pre> that gives up the document's dressing and inherits from
 * here (the rule below), so this is the size such a page is set in until a module
 * runs. */
lf-chart, lf-tree, lf-code { display: block; margin: 14px 0;
             font-family: var(--mono); font-size: var(--code-size);
             line-height: var(--code-line); font-variant-ligatures: none;
             color: var(--code-muted); overflow-x: auto; }
lf-chart.lf-rendered, lf-tree.lf-rendered, lf-code.lf-rendered {
             font: inherit; color: inherit; overflow: visible; }
/* The authored body, before its module replaces it. Nothing here says white-space: the
   body is a <pre>, which is the whole reason it is one. Everything here undoes the rule
   near the top that dresses a <pre> as evidence the page is showing — a box, a rule, a
   mono face, an inset. This <pre> is not that: it is the widget's own content, about to
   be rendered or edited, inside an element that has already said how it looks and how
   far it stands off. The rendered <pre> a module builds is evidence again, and keeps
   the dressing. */
lf-chart:not(.lf-rendered) > pre,
lf-tree:not(.lf-rendered) > pre, lf-code:not(.lf-rendered) > pre, lf-draft > pre {
             background: none; border: 0; border-radius: 0; padding: 0; margin: 0;
             font: inherit; line-height: inherit; overflow: visible; }
/* Until it has drawn, a drawing's box is not a drawing's box: what stands in it is the
   authored source, which is evidence and reads at the column's width from the column's
   own left edge. Both halves of the drawing rule are wrong for it — the room, since
   there is no drawing to be around, and the row, whose whole job is placing one. The
   rule is written against the `x-wide: drawing` declaration rather than against a tag,
   so it stays here where every page reads it while the one drawing widget shipped today
   travels in the `diagram` package. The runtime marks the element before any module
   imports, so this is not a corner: the renderer is fetched lazily, so every diagram
   spends its loading interval as source centred in most of the window, at an indent set
   by its own longest line — three diagrams, three indents, none of them the column's. A page whose module
   never arrives spends the rest of its life that way. `.lf-rendered` is this package's
   word for a module having replaced its body, so this is the sentence theme.css's
   `.lf-error` rule makes about a failure, said where the word for the other half
   lives. */
[data-lf-wide="drawing"]:not(.lf-rendered) { --lf-room: 0px; display: block; }

/* A chart's colors are all here, and none of them are in its module. Plot leaves every
 * mark `currentColor` unless a color channel says otherwise, and lf-chart never passes
 * one — it gives each series' marks a class and nothing else — so `color` on that class
 * paints the bars, the line and the dots of one series at once. What it buys is that the
 * drawing is painted by the same cascade as the page: a scheme flipped mid-read repaints
 * it, an export opens honestly for a reader whose scheme is not the exporter's, and a
 * project overriding --series-N gets its own charts without touching a widget. A
 * diagram's CSS-variable palette has the same live behavior, but assigns semantic
 * surfaces rather than data series.
 *
 * One font declaration, and the module reads it back. The margins a chart reserves are
 * room for text the browser has not drawn yet, so the module measures the labels on a
 * canvas — and a canvas measures in a font string, which is what --lf-chart-font is.
 * Overriding it keeps that shape: a size in px, then a family. */
lf-chart { --lf-chart-font: var(--t-6) var(--sans); }
/* The box each drawing goes in, so that redrawing for a new width replaces the drawing and
   not the widget's children: by then the runtime may have hung a line of its own on the
   element saying a comment stands here, and that line is a child of the element. */
lf-chart .lf-chart-drawing { display: block; }
lf-chart svg { display: block; font: var(--lf-chart-font); color: var(--muted); }
lf-chart .lf-series-1 { color: var(--series-1); }
lf-chart .lf-series-2 { color: var(--series-2); }
lf-chart .lf-series-3 { color: var(--series-3); }
lf-chart .lf-series-4 { color: var(--series-4); }
lf-chart .lf-series-5 { color: var(--series-5); }
/* The key sits above the drawing, so the colors are named before they are met. Its words
   wear the ink every other label on the page wears, never the series color: a name set in
   its own mark's color is a second, weaker copy of the swatch beside it, and it is the
   half that has to stay legible at 3:1 on paper. */
lf-chart .lf-chart-keys { display: flex; flex-wrap: wrap; gap: 2px var(--sp-3);
             margin-bottom: var(--sp-2); font: var(--lf-chart-font);
             color: var(--muted-2); }
lf-chart .lf-chart-key { display: inline-flex; align-items: center; gap: 6px; }
lf-chart .lf-chart-swatch { width: 9px; height: 9px; border-radius: 2px;
             background: currentColor; flex: none; }

/* lf-tree rendered form: nested lists with hairline guides and change badges. The size is
   the `pre` contract again, and a
   tree's own reason for taking it is that its lines are paths, the same words a code block
   holds, set to the same measure beside them. */
lf-tree.lf-rendered { font-family: var(--mono); font-size: var(--code-size);
                      line-height: var(--code-line); color: var(--code-ink); }
lf-tree ul { list-style: none; margin: 0; padding-left: 0; }
lf-tree ul ul { padding-left: 18px; border-left: 1px solid var(--rule); margin-left: 5px; }
lf-tree li { margin: 3px 0; }
lf-tree .lf-tree-dir { font-weight: 600; }
/* nowrap because the module appends name and badges with no whitespace between them and
 * spaces them by margin, so a line is one word to the breaker: told it may break inside
 * one, it split a two-character badge down the middle and drew half the pill on each
 * line. The name is what breaks now, which is the one of the three that can. */
lf-tree .lf-tree-badge { font-size: var(--t-6); padding: 0 6px; margin-left: 6px;
                         border-radius: 999px; white-space: nowrap; }
lf-tree .lf-tree-badge.add { background: var(--ok-tint); color: var(--ok-ink); }
lf-tree .lf-tree-badge.del { background: var(--danger-tint); color: var(--danger-ink); }

/* lf-code rendered form: numbered lines, hi ranges, notes docked at their line. */
lf-code.lf-rendered pre { counter-reset: lf-code-line; padding: 12px 0; --lf-frame: 1; }
lf-code.lf-rendered pre:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: code-pre-light;
             outline-offset: calc(-1 * var(--here-ring-w)); }
/* The same max-content floor as the shadow slice's line spans: an hi range's tint has
   to run the whole scrolled line, not stop at the fold. */
lf-code .lf-code-line { display: block; padding: 0 14px 0 0;
             width: max-content; min-width: 100%; box-sizing: border-box; }
lf-code .lf-code-line::before { counter-increment: lf-code-line;
             content: counter(lf-code-line); display: inline-block; width: 38px;
             margin-right: 8px; padding-right: 10px; box-sizing: border-box;
             border-right: 1px solid var(--code-border); background: var(--code-chrome);
             text-align: right;
             color: var(--code-muted); font-variant-numeric: tabular-nums; }
lf-code .lf-code-line.hi { background: var(--hi-tint); }
lf-code .lf-code-line.hi::before { border-right-color: var(--warn); }
/* A note is prose about a source line, not another source line. It follows the
   code-review convention: a sans-serif row spanning the source frame, with its text
   aligned to the code after the 46px gutter. Horizontal rules mark the insertion
   without inventing author metadata the note does not carry. Sticky positioning holds
   that row to a horizontal scrollport; unlike a max-content line, its prose still wraps. */
lf-code .lf-code-note { position: sticky; inset-inline-start: 0;
             margin: 5px 0 6px; padding: 7px 14px 8px 46px;
             background: var(--pre-bg); border: 0;
             border-block: 1px solid var(--code-border); border-radius: 0;
             color: var(--code-ink); font-family: var(--sans);
             font-size: var(--t-5); line-height: 1.5; white-space: normal; --lf-frame: 1; }
lf-code lf-note { display: block; }

/* lf-source: captured text with the provenance needed to identify the immutable
   selection. The frame is one evidence object; its caption uses the apparatus face
   without becoming runtime chrome, because the label is captured page data too. */
lf-source { display: block; margin: 14px 0; min-height: 2px; }
lf-source > .lf-source-document {
  margin: 0; border: 1px solid var(--code-border); border-radius: var(--r);
  overflow: hidden; background: var(--pre-bg); --lf-frame: 1;
}
lf-source figcaption {
  padding: 7px 11px; border-bottom: 1px solid var(--rule);
  color: var(--muted); font-family: var(--sans); font-size: var(--t-6);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
lf-source pre { margin: 0; border: 0; border-radius: 0; }
/* A long capture becomes a keyboard-reachable scroller inside the evidence frame.
   Keep its generic focus ring inside that frame: the figure clips at its rounded
   corners, so an outside ring loses a pixel on three sides. */
lf-source pre:is(:focus-visible, .lf-focus-visible) {
  outline-offset: calc(-1 * var(--here-ring-w));
}

/* lf-draft rendered form: a block of text the user owns. The dashed border says
   "editable" and sharpens under the pointer, because the box is the door a press opens
   (lf-draft.js); the ✎ button is the door the keyboard uses. Newlines in a draft are
   content, so the body preserves them. A reader-edited body differing from authored
   text wears the runtime's green data-lf-reader-override mark. Unupgraded, the same
   box shows raw text.

   Reading and editing are one box, not a box inside a box. The two views state their
   shared metrics together — same font (both inherit the page's), same wrapping — and
   the edit box drops everything the runtime's general textarea rule adds around text
   that would move it: the padding and border shifted the words 9px right and 6px down,
   the 64px floor stretched a two-line draft, and inline-block layout left a baseline
   gap under it. So the word under the press stays under the pointer, which is what makes
   the gesture worth aiming. field-sizing (that same rule) does the growing, so the box
   is as tall as its text and no taller — what read mode showed. The affordance moves to
   the host, since a border on the textarea is a border read mode hasn't got: the dashed
   border goes solid and accent for as long as an edit is open.

   The controls are a fixed part of that box rather than something an edit adds to it:
   one row under the text in both views, holding ✎ while reading and Save and Cancel
   while editing, all three the same button, so the row's height is the same in either
   view and nothing under the pointer moves. It cost the ✎ its floating corner. An
   absolute corner costs no height, but then the row replacing it does, and the box grew
   36px the instant a press landed — a gesture aimed at a word, answered by the
   whole block changing shape. The text got the corner's 40px gutter back.

   The box being open is a fact about the screen, so the whole swap is scoped to it and
   the widget's JS writes none of it. Paper drops the box with the other offers, and
   without this scope it dropped the hidden body too and printed a draft as an empty
   frame — the words a page states have to survive a medium that has no box to type in,
   and an unsent edit is not yet among them.

   The ring is inset, which is the metrics above carried out one layer: every word held
   still and the frame around them did not, because an outset ring paints 2px past the
   border on every side with the corners rounding wider to match. A shadow costs no
   layout, so every rect agreed nothing had happened and it took a screenshot diff to
   find. Inside the border there is padding to paint on and nothing of the page's to
   disturb. */
lf-draft { display: block; border: 1px dashed var(--border-2); border-radius: 6px;
           padding: 10px 14px; margin: 12px 0; background: var(--card); }
.lf-draft-body, .lf-draft-edit.lf-ui { white-space: pre-wrap; }
.lf-draft-pencil { opacity: 1; }
/* The one control whose face is deliberately the document's: the box shows the page's
   words in the page's serif, or the word under the press reflows out from under the
   pointer the moment the box opens. Stated unlayered, so it outranks the runtime's layered
   UA-clearing and the chrome face .lf-ui would otherwise put on it. */
.lf-draft-edit.lf-ui { display: block; width: 100%; padding: 0; border: 0; background: none;
           font: inherit; min-height: 0; max-height: none; overflow: hidden; }
.lf-draft-edit.lf-ui:is(:focus, .lf-focus) { box-shadow: none; }
.lf-draft-controls, .lf-draft-history { display: none; }
@media screen {
  html:not(.lf-copy) {
    /* The box is the door (lf-draft.js), so the box answers the pointer: the dashed
       edge it already wears to say "editable" sharpens under the aim, the way the
       layer's own pressables warm their ground. Not the ground here — the reader is
       about to type on it, and the words have to stay the page's words while they
       decide. A quoted draft is an exhibit with no door and gets none of this. */
    lf-draft:not(:where([data-lf-exhibit]) *):not(:has(.lf-draft-edit)):hover {
               border-color: var(--muted); }
    lf-draft:has(.lf-draft-edit) { border-style: solid;
               border-color: color-mix(in srgb, var(--accent) 45%, var(--card));
               box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
    lf-draft:has(.lf-draft-edit:focus-visible) { outline: var(--here-ring);
               --lf-here-ring: draft-editor;
               outline-offset: calc(-1 * (var(--here-ring-w) + var(--here-ring-gap))); }
    lf-draft:has(.lf-draft-edit) > .lf-draft-body,
    lf-draft:has(.lf-draft-edit) .lf-draft-pencil { display: none; }
    .lf-draft-controls { display: flex; }
    .lf-draft-history { display: block; }
  }
}
@media (forced-colors: active) {
  html:not(.lf-copy) lf-draft:has(.lf-draft-edit:focus-visible) {
    outline: 2px solid Highlight; outline-offset: -5px; box-shadow: none;
  }
}
.lf-draft-controls { justify-content: flex-end; gap: 4px; margin-top: 6px; }
.lf-margin-item > .lf-draft-controls {
  align-items: center; justify-content: flex-start; margin-top: 0;
}
.lf-draft-history { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--rule);
                    font-size: var(--t-5); color: var(--ink-2); }
.lf-draft-history > summary { width: max-content; cursor: pointer; color: var(--muted); }
.lf-draft-history > summary:hover { color: var(--ink-2); }
.lf-draft-current { margin: 10px 0; }
.lf-draft-current > strong { display: block; margin-bottom: 4px; }
.lf-draft-revisions { margin: 0; padding-left: 20px; }
.lf-draft-revisions > li { margin: 8px 0; padding-left: 3px; }
.lf-draft-revision-head { display: flex; align-items: center; justify-content: space-between;
                          gap: 8px; margin-bottom: 3px; }
.lf-draft-delta, .lf-draft-snapshot { white-space: pre-wrap; color: var(--ink-2); }
.lf-draft-delta del { background: var(--del-tint); color: var(--danger-ink); }
.lf-draft-delta ins { background: var(--add-tint); color: var(--ok-ink);
                      text-decoration: none; }
.lf-draft-restore { flex: none; font-size: var(--t-6); }
/* The diagram package's presentation. Everything here was in the default package's
 * theme until the diagram renderer left every page carrying a large bundle most never
 * draw with. What moved is the tag's own rules; the declaration-driven half — the
 * `[data-lf-wide="drawing"]` box a drawing stands in — stayed there, because a second
 * drawing widget from a third package reads it too. */

/* Pre-upgrade presentation, so a page degrades readably: the same shape the default
 * package states for its own upgraded widgets, restated here for this tag. The
 * integrated theme's code tokens set the density, and the authored body inside the
 * widget is a <pre> that gives up the document's dressing and inherits from here, so
 * this is the size such a page is set in until the module runs. */
/* The renderer's own custom properties are named --bg, --accent, and so on. Passing
 * `var(--accent)` into its inline `--accent` declaration would be a self-reference and
 * invalidate the value, so these inherited aliases carry Leaf's live palette across
 * that namespace boundary. */
lf-diagram { --lf-diagram-paper: var(--paper); --lf-diagram-ink: var(--ink);
             --lf-diagram-muted: var(--muted); --lf-diagram-accent: var(--accent);
             display: block; margin: 14px 0;
             font-family: var(--mono); font-size: var(--code-size);
             line-height: var(--code-line); font-variant-ligatures: none;
             color: var(--code-muted); overflow-x: auto; }
lf-diagram.lf-rendered { font: inherit; color: inherit; overflow: visible; }
/* The authored body, before the module replaces it. Nothing here says white-space: the
   body is a <pre>, which is the whole reason it is one. Everything here undoes the rule
   that dresses a <pre> as evidence the page is showing — a box, a rule, a mono face, an
   inset. This <pre> is not that: it is the widget's own content, about to be rendered,
   inside an element that has already said how it looks and how far it stands off. The
   rendered SVG a module builds is evidence again, and keeps the dressing. */
lf-diagram:not(.lf-rendered) > pre {
             background: none; border: 0; border-radius: 0; padding: 0; margin: 0;
             font: inherit; line-height: inherit; overflow: visible; }
/* A rendered diagram keeps its natural size rather than scaling a wide flowchart's
 * labels below legibility, so a wide one
 * scrolls in its own box, the same answer a wide table gets, instead of painting over
 * the margin. max-width: none escapes the page-wide svg rule in the kernel theme, which
 * would scale it right back down. Where the runtime has marked the element wide, the
 * kernel's `[data-lf-wide="drawing"]` rule owns the box; these two are for the diagram
 * standing where nothing marks it — a thread's message — and agree with it.
 * Paper cannot scroll, so print restores the fit: width and viewBox stay in the markup,
 * and max-width alone scales the drawing whole. */
lf-diagram.lf-rendered { overflow-x: auto; }
lf-diagram svg { display: block; margin: 0 auto; max-width: none; }
@media print {
  lf-diagram svg { max-width: 100%; }
}
/* The diff package's presentation. Everything here was in the default package's theme
 * until Pierre's 1.7MB left every page carrying a diff renderer most of them never
 * draw with. The document-level rules come first; the shadow-tree block the runtime
 * slices out follows, and every layer may contribute one, so this package's arrives
 * after the kernel's and keeps the same cascade inside the tree as in the document. */

/* Pre-upgrade presentation, so a page degrades readably: the same shape the default
 * package states for its own upgraded widgets, restated here for this tag. The
 * integrated theme's code tokens set the density, and the authored body inside the
 * widget is a <pre> that gives up the document's dressing and inherits from here, so
 * this is the size such a page is set in until the module runs. */
lf-diff { display: block; margin: 14px 0;
          font-family: var(--mono); font-size: var(--code-size);
          line-height: var(--code-line); font-variant-ligatures: none;
          color: var(--code-muted); overflow-x: auto; }
/* The diff renders its evidence inside a shadow tree, so its host keeps the code scale
 * above while giving up only the pre-upgrade colour and overflow. */
lf-diff.lf-rendered { color: inherit; overflow: visible; }
/* The authored body, before the module replaces it. Nothing here says white-space: the
   body is a <pre>, which is the whole reason it is one. Everything here undoes the rule
   that dresses a <pre> as evidence the page is showing — a box, a rule, a mono face, an
   inset. This <pre> is not that: it is the widget's own content, about to be rendered,
   inside an element that has already said how it looks and how far it stands off. The
   rendered <pre> the module builds is evidence again, and keeps the dressing. */
lf-diff:not(.lf-rendered) > pre {
          background: none; border: 0; border-radius: 0; padding: 0; margin: 0;
          font: inherit; line-height: inherit; overflow: visible; }

/* The rules a shadow-rendering widget (x-shadow) carries into its own tree. A selector
   written out here reaches the document and stops dead at a shadow boundary, so these
   are sliced out at load and put back as a <style> the shadow root owns — which is also
   what makes them survive `version export`, since an adopted stylesheet is in no
   element's markup and a copy runs no script to adopt one. They stay in the theme
   because the theme owns the look: a project overriding it overrides these with it,
   and a second copy in a widget module would be a second answer to what a diff
   looks like. Everything inside the markers is written for the shadow tree — :host is
   the widget element itself — so nothing in here matches anything at document level. */
/* lf-shadow:start */
/* `clip` rather than `hidden`, and the difference is the whole of why the file header
   below can pin. Both clip a rounded corner identically; only `hidden` also makes the
   box a scroll container, and a sticky child is held by the nearest scrolling ancestor —
   which would be this box, which never scrolls, so the header stuck to nothing and
   scrolled away with its rows. `:where` scopes the rule without outranking the review
   press's later negative-margin placement. */
:host(.lf-rendered) :where(.lf-diff-file) > details,
:host(.lf-rendered) .lf-diff-rename { margin: 0; padding: 0; overflow: clip;
                              background: var(--pre-bg); border: 1px solid var(--code-border);
                              border-radius: var(--r); }
:host(.lf-rendered) :where(.lf-diff-file) > details > summary,
:host(.lf-rendered) .lf-diff-rename { padding: 7px 10px; font-size: var(--t-5);
                                     font-family: var(--sans); color: var(--code-ink);
                                     background: var(--code-chrome); }
/* The press is out of the summary's flow, so that line holds a column open for it and a
   long path wraps above it rather than running underneath. A copy with no press to make
   room for takes its ordinary inset back. */
.lf-diff-file:has(.lf-diff-review, .lf-diff-reviewed) > details > summary,
.lf-diff-file:has(.lf-diff-review, .lf-diff-reviewed) .lf-diff-rename {
                                     padding-right: calc(var(--lf-diff-press) + 18px); }
.lf-diff-tools { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px;
                 margin: 8px 0; padding: 8px 10px; border: 1px solid var(--code-border);
                 border-radius: var(--r); background: var(--code-chrome);
                 color: var(--code-muted); font: var(--t-6) var(--sans); }
.lf-diff-search-label { flex: 1 1 220px; }
.lf-diff-search { box-sizing: border-box; width: 100%; min-height: 30px; padding: 5px 8px;
                  border: 1px solid var(--code-border); border-radius: calc(var(--r) - 2px);
                  background: var(--pre-bg); color: var(--code-ink); font: inherit; }
.lf-diff-search::placeholder { color: var(--code-muted); opacity: 1; }
.lf-diff-progress { font-variant-numeric: tabular-nums; white-space: nowrap; }
.lf-diff-wrap-label { display: inline-flex; align-items: center; gap: 6px; flex: none;
                      white-space: nowrap; cursor: pointer; }
.lf-diff-wrap { margin: 0; flex: none; cursor: pointer; }
.lf-diff-next, .lf-diff-review { min-height: 30px; font: inherit; }
/* The file's row is a disclosure, and a disclosure is a control, so the review press
   cannot be a descendant of it (lf-diff.js). It is a sibling drawn over the summary
   line instead: a block in the flow ahead of the row, pushed to the right by its auto
   margin, with the row pulled back up over it by a top margin that takes back the
   press's height and the 6px above it, so the row starts where it would without it;
   that is why the height is stated rather than floored, and why the wrapper carries
   the file's spacing and is a block context of its own, so those margins meet nothing
   outside it. The pull is the row's and not the press's because the press pins (below)
   and a sticky box is held inside its containing block by its margin box: a negative
   bottom margin on the press lent it 32px of travel past its file, so at every file
   boundary the header unpinned and the press stayed, over the next file's header and
   that file's own press. 6px and 11px
   are the details' 1px border plus that
   line's own 7px and 10px padding, the top pulled 2px up so the press sits centred on
   the text beside it. The sans is stated because the host this sits in is set in mono,
   and one width for both labels is what makes the column the row holds open exact.
   In the flow rather than absolute because the line pins (below): the summary sticks
   under the banner while its rows go past, and a box placed against the file's top
   stayed there and drifted off the header it belongs to, its column empty and the
   press out of reach for the whole of the file. Positioned, and one level over the
   pinned summary: that one lifts the header over the rows that pass under it, and
   lifted alone it covered the press too, on every file, so a click on "Mark reviewed"
   opened and closed the file instead. */
.lf-diff-file { position: relative; display: flow-root; margin: 8px 0;
                --lf-diff-press: 110px; }
.lf-diff-file:has(.lf-diff-review, .lf-diff-reviewed) > :is(details, .lf-diff-rename) {
                margin-top: -32px; }
.lf-diff-review, .lf-diff-reviewed { display: block; position: relative; z-index: 3;
                                     width: fit-content; height: 26px;
                                     margin: 6px 11px 0 auto;
                                     font-family: var(--sans); }
.lf-diff-review { box-sizing: border-box; width: var(--lf-diff-press);
                  min-height: 26px; padding: 2px 8px;
                  font-size: var(--t-6); }
.lf-diff-reviewed { font-size: var(--t-5); line-height: 26px; }
.lf-diff-review[aria-pressed="true"], .lf-diff-reviewed { color: var(--ok);
                                                         font-weight: 650; }
.lf-diff-filtered { display: none !important; }
.lf-diff-next:is(:focus-visible, .lf-focus-visible),
.lf-diff-wrap:is(:focus-visible, .lf-focus-visible),
.lf-diff-review:is(:focus-visible, .lf-focus-visible),
.lf-diff-search:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring);
                                                        --lf-here-ring: diff-tools;
                                                        outline-offset: 1px; }
/* The file's own row, and the box it opens clips (overflow above), so the ring it wears
   is inset — theme.css's rule for a control packed into something rather than standing
   on its own. Outside, its top run was drawn into the border the details draws and lost
   with it. */
:host(.lf-rendered) .lf-diff-file > details > summary:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: code-summary;
                                            outline-offset: calc(-1 * var(--here-ring-w)); }
/* The file header pins under the banner while its own rows go past, which is the thread
   list's answer to the same question — the name of the part you are reading has to be on
   screen for the whole of it, not only at its start. Forty-six files at thirty-two
   thousand pixels is that list's four-thousand-pixel run with a nought on it: opening one
   file and reading down it left nothing on screen saying which file it was.
   The slot is the banner's own height, said once at :root and inherited through this
   boundary, so the two edges cannot drift apart. Opaque already (the summary's
   background), because the rows pass underneath it.
   Screen only: paper has no banner and no scroll to pin against, and a copy's rows are
   all on the page at once. And only where the module says the page's own scroller is the
   one underneath — inside the panel the pinned slot is the run headings', and a diff in a
   reply scrolls in that list rather than in the document. */
@media screen {
  :host(.lf-rendered[data-lf-diff-pinned]) .lf-diff-file > details > summary { position: sticky;
                              top: var(--lf-banner-h, 0px); z-index: 2; }
  /* The press with it, 5px down: its own 6px less the border the summary's box starts
     inside, which is the distance between the two at rest. */
  :host(.lf-rendered[data-lf-diff-pinned]) .lf-diff-review,
  :host(.lf-rendered[data-lf-diff-pinned]) .lf-diff-reviewed { position: sticky;
                              top: calc(var(--lf-banner-h, 0px) + 5px); }
}
/* The room that header takes, so a landing arrives below it rather than behind it. The
   document declares its banner through scroll-padding-top; this is the rest of the same
   sum, measured because a wrapped path makes it a number no stylesheet can work out
   (paintHeadRoom, lf-diff.js — the thread list writes the same fact under this name for
   its own pinned headings). */
:host(.lf-rendered) [data-line] { scroll-margin-top: var(--lf-head-room, 0px); }
/* The path is evidence — a file's name in the file's own voice — and a shadow tree
   inherits no document rule, so the mono is stated here or it is the UA's. */
.lf-diff-path { font-family: var(--mono); font-size: var(--t-6);
                overflow-wrap: anywhere; }
.lf-diff-stat { color: var(--code-muted); font-weight: 400; margin-left: 8px;
                font-size: var(--t-6); font-variant-numeric: tabular-nums;
                white-space: nowrap; }
:host(.lf-rendered) {
  --diffs-font-family: var(--mono);
  --diffs-font-size: var(--code-size);
  --diffs-line-height: var(--code-line);
  --diffs-bg: var(--pre-bg);
  --diffs-bg-buffer: var(--pre-bg);
  --diffs-bg-context: var(--pre-bg);
  --diffs-bg-context-gutter: color-mix(in srgb, var(--code-ink) 4%, var(--pre-bg));
  --diffs-bg-separator: var(--code-chrome);
  --diffs-fg: var(--code-ink);
  --diffs-fg-number: var(--code-muted);
  /* A changed row's number is drawn in that row's own base by default, which is the
     ink the fill beside it is mixed from: green on green at 4.03:1 in the light
     palette. The tinted-surface inks are the layer's answer to exactly that question
     and keep the number the same statement, legibly. */
  --diffs-fg-number-addition-override: var(--ok-ink);
  --diffs-fg-number-deletion-override: var(--danger-ink);
  --diffs-addition-base: var(--ok);
  --diffs-deletion-base: var(--danger);
  --diffs-bg-addition: color-mix(in srgb, var(--ok) 16%, var(--pre-bg));
  --diffs-bg-deletion: color-mix(in srgb, var(--danger) 16%, var(--pre-bg));
  --diffs-bg-addition-emphasis: color-mix(in srgb, var(--ok) 34%, var(--pre-bg));
  --diffs-bg-deletion-emphasis: color-mix(in srgb, var(--danger) 34%, var(--pre-bg));
}
:host(.lf-rendered) pre { margin: 0; border: none; border-top: 1px solid var(--code-border);
                          border-radius: 0; overflow-x: auto; color: var(--code-ink); }
/* The scroll region's tab stop (lf-diff.js): reachable is only half — focus has to
   show where it landed, or the stop reads as Tab going nowhere. */
:host(.lf-rendered) code[data-code]:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring);
                          --lf-here-ring: code-pre-shadow;
                          outline-offset: calc(-1 * var(--here-ring-w)); }
/* A Thread occupies one additional Pierre subgrid row. The widget inserts a content
   outlet and a paired gutter spacer at the same line index; matching fills and borders
   make them one full-width review row while preserving the renderer's two columns. */
.lf-diff-thread-outlet, .lf-diff-thread-gutter {
                          min-width: 0; border-block: 1px solid var(--rule);
                          background: var(--paper); }
.lf-diff-thread-gutter { border-inline-end: 1px solid var(--rule); }
.lf-diff-thread-outlet { padding: 10px clamp(10px, 2vw, 18px); white-space: normal; }
.lf-diff-thread-outlet > .lf-conversation-thread {
                          max-width: 760px; border: 1px solid var(--border-2);
                          border-radius: 7px; padding: 10px 12px; background: var(--card); }
.lf-diff-thread-outlet > .lf-conversation-thread + .lf-conversation-thread {
                          margin-top: 8px; }
.lf-diff-thread-outlet > details.lf-conversation-thread:not([open]) { padding: 0; }
.lf-diff-thread-outlet > details.lf-conversation-thread:not([open]) > summary {
                          border-radius: inherit; }
/* Soft wrap. A diff line is `white-space: pre` and the box it sits in scrolls sideways,
   so the only way to read the end of a long line is a scrollbar at the foot of the whole
   file — twenty-four thousand pixels below the line, on the patch this was measured on.
   Wrapping trades the diff's column alignment for lines that end where the reader can
   see them, which is why it is the reader's own switch rather than the default.
   The switch is a checkbox and this is a sibling combinator off it, so the state has one
   home and a copy with its scripts dropped still works it; the siblings are the file
   rows, each holding its disclosure and its review press. `anywhere` rather than
   `break-word`: what runs long in a patch is paths, URLs, minified data and prose in
   comments, and the first three offer the line box no break opportunity to find.
   The code box gives up its permanent scrollbar with them, since wrapped rows leave it
   nothing to scroll. */
.lf-diff-tools:has(.lf-diff-wrap:checked) ~ .lf-diff-file [data-line] {
                          white-space: pre-wrap; overflow-wrap: anywhere; }
.lf-diff-tools:has(.lf-diff-wrap:checked) ~ .lf-diff-file code[data-code] {
                          overflow-x: auto; }
/* Pierre owns the line and inline-diff paint. Leaf supplies brighter semantic fills
   through its variables above, and keeps its syntax roles readable on the denser one. */
[data-diff-span] [data-lf-syn="cm"] { color: color-mix(in srgb, var(--syn-comment) 50%, var(--ink)); }
[data-diff-span] [data-lf-syn="kw"] { color: color-mix(in srgb, var(--syn-keyword) 50%, var(--ink)); }
[data-diff-span] [data-lf-syn="st"] { color: color-mix(in srgb, var(--syn-string) 50%, var(--ink)); }
[data-diff-span] [data-lf-syn="nu"] { color: color-mix(in srgb, var(--syn-number) 50%, var(--ink)); }
[data-diff-span] [data-lf-syn="fn"] { color: color-mix(in srgb, var(--syn-name) 50%, var(--ink)); }
[data-diff-span] [data-lf-syn="ty"] { color: color-mix(in srgb, var(--syn-type) 50%, var(--ink)); }
/* Syntax colour is the same statement the document makes, and the tokens are in here
   rather than out there, so the rules come too. The custom properties they read inherit
   through the boundary, which is why only the selectors need repeating. */
[data-lf-syn="cm"] { color: var(--syn-comment); font-style: italic; }
[data-lf-syn="kw"] { color: var(--syn-keyword); }
[data-lf-syn="st"] { color: var(--syn-string); }
[data-lf-syn="nu"] { color: var(--syn-number); }
[data-lf-syn="fn"] { color: var(--syn-name); }
[data-lf-syn="ty"] { color: var(--syn-type); }
@media print {
  .lf-diff-tools, .lf-diff-review:not([data-lf-said]) { display: none !important; }
  .lf-diff-file:not(:has([data-lf-said])) > details > summary,
  .lf-diff-file:not(:has([data-lf-said])) .lf-diff-rename { padding-right: 10px; }
  /* The row's pull (above) takes back the press's height, and the press an unreviewed
     file's row is pulled over is gone here: a hidden box has no margins, so a pull on
     the press left with it, but :has() still matches the hidden press, so a pull on the
     row stayed and drew each file's header 24px inside the file before it, the first
     32px above the widget. Guarded as the neighbour rule is: no said word, nothing on
     the sheet to pull over. */
  .lf-diff-file:not(:has([data-lf-said])) > :is(details, .lf-diff-rename) { margin-top: 0; }
  .lf-diff-filtered { display: block !important; }
  /* Paper wraps whether or not the switch was on, because a clipped line on screen is a
     scroll away and a clipped line on paper is gone: forty rows of the walkthrough's
     patch came out cut, the worst by 744px, and one of them was the key line a reader
     would have been reading the page to learn. The switch is not on the sheet to press,
     so the sheet cannot be left holding its answer. */
  [data-line] { white-space: pre-wrap !important; overflow-wrap: anywhere !important; }
  code[data-code] { overflow-x: visible !important; }
}
/* lf-shadow:end */
/* Swipe decks are RFC index cards, not a second app shell: one queue holds the eye,
 * literal verdict rails state the operation, and compact ledgers retain the result. */
lf-swipe-deck {
  --lf-frame: 1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  width: min(100%, 44rem);
  margin: var(--sp-4) auto;
  container-type: inline-size;
}

lf-swipe-pile {
  display: block;
  min-width: 0;
}

lf-swipe-pile[verdict="unseen"] {
  display: grid;
  grid-column: 1 / -1;
  grid-row: 1;
  grid-template: 1fr / 1fr;
  width: min(100%, 34rem);
  margin-inline: auto;
  padding-bottom: 14px;
}

lf-swipe-pile[verdict="unseen"]::before,
lf-swipe-pile[verdict="unseen"]::after {
  content: "";
  display: block;
  box-sizing: border-box;
  grid-area: 1 / 1;
  min-height: 12rem;
  border: 1px solid var(--border-2);
  border-radius: var(--r);
  background: var(--card);
}

lf-swipe-pile[verdict="unseen"]::before {
  z-index: 1;
  transform: translateY(14px) scale(.976);
}

lf-swipe-pile[verdict="unseen"]::after {
  z-index: 2;
  transform: translateY(7px) scale(.988);
}

lf-swipe-pile[verdict="unseen"]:not(:has(> lf-swipe-card:nth-of-type(2)))::after,
lf-swipe-pile[verdict="unseen"]:not(:has(> lf-swipe-card:nth-of-type(3)))::before {
  display: none;
}

lf-swipe-pile[verdict="unseen"] > .lf-swipe-pile-label {
  grid-area: 1 / 1;
  align-self: start;
  z-index: 4;
  width: max-content;
  margin: var(--sp-3) 0 0 var(--sp-3);
}

.lf-swipe-pile-label {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--muted);
  font: 600 var(--t-6)/1.3 var(--sans);
  letter-spacing: .065em;
  text-transform: uppercase;
}

lf-swipe-card {
  --lf-frame: 1;
  display: block;
  box-sizing: border-box;
  min-width: 0;
  padding: var(--sp-3);
  border: 1px solid var(--border-2);
  border-radius: var(--r);
  background: var(--card);
  color: var(--ink-2);
  font-size: var(--t-5);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

lf-swipe-card > :first-child {
  margin-top: 0;
}

lf-swipe-card > :last-child {
  margin-bottom: 0;
}

lf-swipe-card > strong:first-child {
  display: block;
  margin: 0;
  padding-top: var(--sp-4);
  color: var(--ink);
  font: 650 var(--t-3)/1.25 var(--sans);
  letter-spacing: -.008em;
}

lf-swipe-card > strong:first-child:not(:last-child) {
  margin-bottom: var(--sp-2);
}

lf-swipe-pile[verdict="unseen"] > lf-swipe-card {
  grid-area: 1 / 1;
  min-height: 12rem;
  touch-action: pan-y;
  user-select: text;
}

lf-swipe-pile[verdict="unseen"] > lf-swipe-card:first-of-type {
  position: relative;
  z-index: 3;
  cursor: grab;
}

lf-swipe-pile[verdict="unseen"] > lf-swipe-card:nth-of-type(n + 2) {
  visibility: hidden;
}

lf-swipe-pile[verdict="unseen"] > lf-swipe-card:first-of-type:focus-visible {
  outline: var(--here-ring);
  outline-offset: var(--here-ring-gap);
  --lf-here-ring: swipe-card;
}

:is(lf-swipe-deck.lf-swipe-quoted, html.lf-copy lf-swipe-deck)
  lf-swipe-pile[verdict="unseen"] {
  display: block;
  width: auto;
  padding-bottom: 0;
}

:is(lf-swipe-deck.lf-swipe-quoted, html.lf-copy lf-swipe-deck)
  lf-swipe-pile[verdict="unseen"]::before,
:is(lf-swipe-deck.lf-swipe-quoted, html.lf-copy lf-swipe-deck)
  lf-swipe-pile[verdict="unseen"]::after {
  display: none;
}

:is(lf-swipe-deck.lf-swipe-quoted, html.lf-copy lf-swipe-deck)
  lf-swipe-pile[verdict="unseen"]
  > .lf-swipe-pile-label {
  width: auto;
  margin: 0 0 var(--sp-2);
}

:is(lf-swipe-deck.lf-swipe-quoted, html.lf-copy lf-swipe-deck)
  lf-swipe-pile[verdict="unseen"]
  > lf-swipe-card {
  min-height: 0;
  margin-bottom: var(--sp-2);
  transform: none;
  visibility: visible;
  cursor: auto;
}

lf-swipe-deck.lf-swipe-quoted lf-swipe-pile[verdict="pass"],
lf-swipe-deck.lf-swipe-quoted lf-swipe-pile[verdict="keep"] {
  grid-row: 2;
}

lf-swipe-card.lf-swipe-dragging {
  cursor: grabbing;
  transform: translateX(var(--lf-swipe-drag-x));
  user-select: none;
}

.lf-swipe-exit {
  z-index: 100;
  pointer-events: none;
}

.lf-swipe-controls {
  display: grid;
  grid-column: 1 / -1;
  grid-row: 2;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sp-3);
  width: min(100%, 34rem);
  margin: 0 auto;
}

.lf-swipe-pass.lf-ui,
.lf-swipe-keep.lf-ui,
.lf-swipe-undo.lf-ui {
  min-height: max(2.5rem, var(--aim-floor));
  min-width: var(--aim-floor);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-2);
  border-radius: var(--r);
  background: var(--card);
  color: var(--ink-2);
  font: 600 var(--t-5)/1 var(--sans);
  cursor: pointer;
}

.lf-swipe-pass {
  justify-self: start;
}

.lf-swipe-keep {
  justify-self: end;
}

.lf-swipe-undo {
  grid-column: 1 / -1;
  justify-self: center;
}

.lf-swipe-pass:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger-ink);
}

.lf-swipe-keep:hover:not(:disabled),
.lf-swipe-undo:hover:not(:disabled) {
  border-color: var(--ok);
  color: var(--ok-ink);
}

.lf-swipe-pass:disabled,
.lf-swipe-keep:disabled {
  color: var(--muted);
  cursor: default;
  opacity: .55;
}

.lf-swipe-progress {
  color: var(--muted);
  font: var(--t-6)/1.3 var(--mono);
  text-align: center;
  white-space: nowrap;
}

lf-swipe-pile[verdict="pass"],
lf-swipe-pile[verdict="keep"] {
  grid-row: 3;
  min-height: 5rem;
  padding: var(--sp-3);
  border-top: 2px solid var(--rule);
}

lf-swipe-pile[verdict="pass"] > lf-swipe-card,
lf-swipe-pile[verdict="keep"] > lf-swipe-card {
  padding: var(--sp-2) 0;
  border: 0;
  border-top: 1px solid var(--rule);
  border-radius: 0;
  background: transparent;
}

lf-swipe-pile[verdict="pass"] > lf-swipe-card:first-of-type,
lf-swipe-pile[verdict="keep"] > lf-swipe-card:first-of-type {
  border-top: 0;
}

lf-swipe-pile[verdict="pass"] > lf-swipe-card > strong:first-child,
lf-swipe-pile[verdict="keep"] > lf-swipe-card > strong:first-child {
  padding-top: 0;
  font-size: var(--t-5);
}

lf-swipe-pile[verdict="pass"]
  > lf-swipe-card
  > strong:first-child:not(:last-child),
lf-swipe-pile[verdict="keep"]
  > lf-swipe-card
  > strong:first-child:not(:last-child) {
  margin-bottom: var(--sp-1);
}

@container (max-width: 31rem) {
  lf-swipe-deck {
    grid-template-columns: 1fr;
    gap: var(--sp-2);
  }

  lf-swipe-pile[verdict="unseen"],
  .lf-swipe-controls {
    grid-column: 1;
  }

  lf-swipe-pile[verdict="pass"],
  lf-swipe-pile[verdict="keep"] {
    grid-row: auto;
  }

  lf-swipe-deck.lf-swipe-quoted lf-swipe-pile[verdict="pass"],
  lf-swipe-deck.lf-swipe-quoted lf-swipe-pile[verdict="keep"] {
    grid-row: auto;
  }

  .lf-swipe-controls {
    gap: var(--sp-2);
  }

  .lf-swipe-progress {
    white-space: normal;
  }
}

html.lf-copy .lf-swipe-controls {
  display: none;
}

@media print {
  lf-swipe-deck {
    display: block;
    width: auto;
  }

  lf-swipe-pile,
  lf-swipe-pile[verdict="unseen"] {
    display: block;
    width: auto;
    margin: var(--sp-3) 0;
    padding: 0;
  }

  lf-swipe-pile[verdict="unseen"] > .lf-swipe-pile-label {
    width: auto;
    margin: 0 0 var(--sp-2);
  }

  lf-swipe-pile[verdict="unseen"]::before,
  lf-swipe-pile[verdict="unseen"]::after {
    display: none;
  }

  lf-swipe-pile[verdict="unseen"] > lf-swipe-card {
    min-height: 0;
    margin-bottom: var(--sp-2);
    transform: none;
    visibility: visible;
    cursor: auto;
  }

  lf-swipe-card {
    background: transparent;
    break-inside: avoid;
  }
}
/* lf-roster / lf-agent: who is working, and where each of them stands. The rows and
 * the state pill's tints are CSS; everything on the live line — the state word, the
 * `doing` clause, the § reference and the elapsed line — is built by the lf-agent
 * upgrade, because all but the reference move between versions and the elapsed line
 * is computed from the log. Branch evidence comes from the worktree data source.
 *
 * A row and not a card. The reader's question is comparative — which of these five is
 * stuck, which has gone quiet — and a card puts a border between every pair of things
 * being compared, so the eye has to cross one to make each comparison. Hairlines
 * between rows and one shape per row is what a set read across wants, which is the
 * same argument the row form of a choose group makes and the reason a roster stands
 * wide (x-wide): the live line's parts land in the same order at the same place on
 * every row, and an eye runs down any one of them. */
lf-roster { display: block; margin: 14px 0; border-top: 1px solid var(--rule); }
/* The state's column, and then the row's own text beside it. The width is the module's
 * (--lf-state-room, measured from the five words in the face this page is set in); the
 * gap is the theme's. The pill is out of flow so that a row of one line and a row of
 * three both hang their state at the same place — in flow it would be the first word of
 * a paragraph and would sit where that paragraph's first line happened to start. */
lf-agent { display: block; position: relative; padding: 10px 2px 10px
           calc(var(--lf-state-room, 60px) + var(--sp-3));
           border-bottom: 1px solid var(--rule); }
lf-agent > .lf-state { position: absolute; left: 0; top: 12px; }
lf-agent > strong { margin-right: var(--sp-2); }
lf-agent[state="done"] > strong, lf-agent[state="idle"] > strong { color: var(--muted); }
/* The live line: what this worker is doing now, and what the log knows about when it
 * last said so. Wrapping, because `doing` is a free clause and a narrow window is not
 * a reason to lose the rest of the row; the elapsed line takes the free width to its
 * left (margin-left: auto) so it ends every row at the same column and grows leftward
 * into space nothing else has claimed — a fact that gains a character every minute
 * must not be able to move anything, and there is nothing to its right to move. */
.lf-agent-line { display: flex; flex-wrap: wrap; align-items: baseline;
                 gap: var(--sp-1) var(--sp-2); margin-top: 3px; }
/* The elapsed line and the call-out beside it are one statement about freshness, so the
 * free width opens before whichever of them comes first rather than between the two —
 * two auto margins would have split it and stood "quiet" in the middle of the row,
 * apart from the words it qualifies. */
.lf-agent-line .lf-cold, .lf-agent-line .lf-heard { margin-left: auto; }
.lf-agent-line:has(.lf-cold) .lf-heard { margin-left: var(--sp-2); }
.lf-agent-line .lf-heard { padding-left: var(--sp-3); }
/* The clause is the row's content, so it is set in the page's own voice: the reader
 * reads it as a sentence, where everything else on the line is apparatus about it. */
.lf-doing { color: var(--ink-2); }
.lf-heard { color: var(--muted); white-space: nowrap; font-size: var(--t-6); }
/* Silence against a claim of work. The word is the module's and says the whole of it;
 * the tint is the bonus, using the vocabulary's amber for work that needs attention. */
.lf-cold { color: var(--warn-ink); background: var(--warn-tint);
           padding: 0 8px; border-radius: 999px; font-size: var(--t-6); }
/* The state, in the vocabulary's own semantics: green for finished, accent for the one
 * in flight, amber for waiting, red for stuck, and neutral for a worker with nothing to
 * do — which is not a fault and is not tinted as one. */
.lf-state { padding: 0 8px; border-radius: 999px; font-size: var(--t-6);
            white-space: nowrap; background: var(--chip); color: var(--ink-2); }
.lf-state-working { background: color-mix(in srgb, var(--accent) 14%, transparent);
                    color: var(--accent); }
.lf-state-waiting { background: var(--warn-tint); color: var(--warn-ink); }
.lf-state-blocked { background: var(--danger-tint); color: var(--danger-ink); }
.lf-state-done    { background: var(--ok-tint); color: var(--ok-ink); }
.lf-state-reaped  { background: var(--chip); color: var(--ink-2); text-decoration: line-through; }
lf-agent[state="reaped"] > strong { color: var(--ink-2); }

/* lf-tasks / lf-task: a hierarchy of work. The indent guides and status
 * markers are CSS; the chip row (`owner`, `when`, `tags`, and a parent's
 * done-fraction) is built by the lf-task upgrade. The marker vocabulary is
 * the milestone's, plus `review` in the warn tint: finished by its holder and
 * ready to be reviewed. A nested Decision assigns that review. */
lf-tasks, lf-command { display: block; margin: 14px 0; }
lf-task { display: block; position: relative; padding-left: 26px; margin: 8px 0; }
lf-task::before { content: ""; position: absolute; left: 6px; top: 5px;
                  width: 10px; height: 10px; border-radius: 50%;
                  background: var(--paper); border: 2px solid var(--muted); }
lf-task[status="done"]::before    { background: var(--ok); border-color: var(--ok); }
lf-task[status="active"]::before  { border-color: var(--accent);
                                    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent); }
lf-task[status="blocked"]::before,
lf-task[status="stalled"]::before { background: var(--danger); border-color: var(--danger); }
lf-task[status="review"]::before  { background: var(--warn); border-color: var(--warn); }
lf-task > lf-task { margin-left: 11px; border-left: 1px solid var(--rule);
                    --lf-frame: 1; }
lf-task > strong { margin-right: 6px; }
lf-task[status="done"] > strong { color: var(--muted); }

/* Command tree: the plan is canonical; these are projections generated around it. */
lf-command > .lf-command-head { display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-3); align-items: end; margin: 0 0 var(--sp-4); padding: var(--sp-4);
  border: 1px solid var(--rule); border-radius: var(--r); background: var(--paper); }
.lf-command-outcome { display: grid; gap: 2px; }
.lf-command-outcome > strong { font-size: var(--t-3); }
.lf-command-outcome > span { color: var(--muted); font-size: var(--t-6); }
.lf-command-facts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-1); }
.lf-command-facts > a, .lf-command-facts > [role="button"], .lf-command-facts > span,
.lf-stopped-view a, .lf-fleet-view a { border: 0; border-radius: 999px;
  padding: 3px 8px; background: var(--chip); color: var(--ink-2); font: inherit;
  font-size: var(--t-6); cursor: pointer; text-decoration: none; }
.lf-command-facts > span { cursor: default; }
.lf-command-facts > .warn { background: var(--warn-tint); color: var(--warn-ink); }
.lf-command-facts > .danger { background: var(--danger-tint); color: var(--danger-ink); }
.lf-stopped-view, .lf-fleet-view { margin: var(--sp-3) 0; padding: 0 var(--sp-3);
  border-left: 2px solid var(--rule); }
.lf-stopped-view > summary, .lf-fleet-view > summary { color: var(--ink-2); }
.lf-stopped-view ol, .lf-fleet-view ul { margin: var(--sp-2) 0; }
.lf-stopped-view li, .lf-fleet-view li { margin: var(--sp-1) 0; color: var(--muted); }
.lf-stopped-view a, .lf-fleet-view a { padding: 0; background: none;
  color: var(--accent); font-size: inherit; text-align: left; }

lf-command [data-lf-command-goal] { display: grid;
  grid-template-columns: minmax(12rem, 1fr) auto auto;
  column-gap: var(--sp-3); align-items: baseline; }
lf-command [data-lf-command-goal] > strong { grid-column: 1; }
lf-command [data-lf-command-goal] > .lf-task-meta { grid-column: 2 / 4;
  display: flex; align-items: center;
  justify-content: flex-end; gap: var(--sp-1); min-width: max-content; }
.lf-task-meta > span, .lf-task-crew { border: 0; border-radius: 999px; padding: 1px 7px;
  background: var(--chip); color: var(--ink-2); font: inherit; font-size: var(--t-6); }
.lf-task-crew { cursor: pointer; color: var(--accent); }
.lf-task-held { color: var(--warn-ink) !important; background: var(--warn-tint) !important; }
.lf-task-signal { color: var(--accent) !important; }
lf-command [data-lf-command-goal] > :not(strong):not(.lf-task-meta):not([data-lf-command-goal]):not([data-lf-command-worker]):not(.lf-conversation) {
  grid-column: 1 / -1; }
lf-command [data-lf-command-goal] > [data-lf-command-goal],
lf-command [data-lf-command-goal] > [data-lf-command-worker],
lf-command [data-lf-command-goal] > .lf-conversation {
  grid-column: 1 / -1; }
lf-command [data-lf-command-goal] > [data-lf-command-worker] {
  display: none; margin: var(--sp-2) 0 0 12px; }
lf-command [data-lf-command-goal][data-lf-open] > [data-lf-command-worker] { display: block; }
lf-command [data-lf-command-goal][data-lf-held] {
  background: linear-gradient(90deg, var(--warn-tint), transparent 72%); }
html.lf-copy lf-command [data-lf-command-goal] > [data-lf-command-worker] { display: block; }

/* Host operations are a compact command set, distinct from lf-options' replayable
 * document decisions. The prose stays authored and selectable; the trailing press is
 * apparatus, and a linked receipt replaces its availability with a terminal account. */
lf-operations { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--sp-2); margin: var(--sp-3) 0; }
lf-operation { position: relative; display: block; padding: var(--sp-3) 5.5rem var(--sp-3) var(--sp-3);
  border: 1px solid var(--rule); border-radius: var(--r); background: var(--paper);
  --lf-frame: 1; }
lf-operation[data-lf-requested] { background: color-mix(in srgb, var(--accent) 7%, var(--paper)); }
.lf-operation-press { position: absolute; top: var(--sp-3); right: var(--sp-3); }
.lf-operation-status { grid-column: 1 / -1; color: var(--muted); font: var(--t-6) var(--sans); }
.lf-operation-status[data-status="failed"] { color: var(--danger-ink); }
.lf-operation-status[data-status="succeeded"] { color: var(--ok-ink); }

lf-worktree { display: block; margin: var(--sp-2) 0; padding-left: var(--sp-3);
  border-left: 2px solid var(--rule); }
.lf-worktree-snapshot { display: block; }
.lf-worktree-head { display: block; width: 100%; border: 0; padding: var(--sp-1) 0;
  background: none; color: var(--ink-2); font: var(--t-6) var(--mono); text-align: left;
  cursor: pointer; }
.lf-worktree-source { margin: 1px 0 var(--sp-2); color: var(--muted);
  font: var(--t-7) var(--sans); letter-spacing: .055em; text-transform: uppercase; }
.lf-worktree-evidence { margin: var(--sp-2) 0; }
.lf-worktree-evidence > strong { display: block; margin-bottom: var(--sp-1);
  color: var(--muted); font: var(--t-7) var(--sans); letter-spacing: .055em;
  text-transform: uppercase; }
.lf-worktree-evidence > pre { margin: 0; }
html.lf-copy .lf-worktree-head { cursor: default; }
lf-worktree:not([data-lf-open]) .lf-worktree-snapshot > :not(.lf-worktree-head) {
  display: none; }
html.lf-copy lf-worktree:not([data-lf-open]) .lf-worktree-snapshot > :not(.lf-worktree-head) {
  display: block; }

@media print {
  .lf-worktree-head { cursor: default; }
  lf-command [data-lf-command-goal] > [data-lf-command-worker],
  lf-worktree:not([data-lf-open]) .lf-worktree-snapshot > :not(.lf-worktree-head) {
    display: block; }
}

lf-record { display: block; margin: var(--sp-3) 0; }
lf-record > ol { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
lf-record > ol > li { padding: var(--sp-2) 0; border-bottom: 1px solid var(--rule);
  color: var(--muted); font: var(--t-6) var(--mono); overflow-wrap: anywhere; }

@media (max-width: 520px) {
  lf-command > .lf-command-head { grid-template-columns: 1fr; align-items: start; }
  .lf-command-facts { justify-content: flex-start; }
  lf-command [data-lf-command-goal] { grid-template-columns: minmax(0, 1fr); }
  lf-command [data-lf-command-goal] > .lf-task-meta {
    grid-column: 1; justify-content: flex-start; flex-wrap: wrap;
    min-width: 0; margin-top: 2px; }
  lf-command [data-lf-command-goal] > .lf-task-meta > span {
    max-width: 100%; overflow-wrap: anywhere; }
}
/* Pull-request evidence uses the visual language of a change ledger: the branch path
 * and revision form its spine, while the author's own words sit in an inset signed
 * block. Surrounding page prose remains visually independent review analysis. */
lf-pull-request {
  display: block;
  margin: var(--sp-4) 0;
  container-type: inline-size;
}

.lf-pr-card {
  --lf-frame: 1;
  display: grid;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  background: color-mix(in srgb, var(--paper) 94%, var(--accent));
  break-inside: avoid;
}

.lf-pr-head {
  display: grid;
  gap: var(--sp-1);
  min-width: 0;
}

.lf-pr-identity,
.lf-pr-byline,
.lf-pr-route,
.lf-pr-observed {
  margin: 0;
}

.lf-pr-identity {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  color: var(--muted);
  font: var(--t-6) var(--mono);
  overflow-wrap: anywhere;
}

.lf-pr-status {
  flex: none;
  padding: 2px 8px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-2);
  font: var(--t-6) var(--sans);
  text-transform: capitalize;
  white-space: nowrap;
}

.lf-pr-status[data-status="open"],
.lf-pr-status[data-status="merged"] {
  border-color: color-mix(in srgb, var(--ok-ink) 45%, var(--rule));
  background: var(--ok-tint);
  color: var(--ok-ink);
}

.lf-pr-status[data-status="closed"] {
  border-color: color-mix(in srgb, var(--danger-ink) 40%, var(--rule));
  background: var(--danger-tint);
  color: var(--danger-ink);
}

.lf-pr-title {
  display: block;
  color: var(--ink);
  font-size: var(--t-2);
  line-height: 1.16;
  overflow-wrap: anywhere;
}

.lf-pr-byline {
  color: var(--ink-2);
  font: var(--t-6) var(--sans);
}

.lf-pr-route {
  padding-top: var(--sp-2);
  border-top: 1px solid var(--rule);
  color: var(--ink-2);
  font: var(--t-6) var(--mono);
  overflow-wrap: anywhere;
}

.lf-pr-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
  border-block: 1px solid var(--rule);
}

.lf-pr-fact {
  display: grid;
  gap: 2px;
  padding: var(--sp-2);
  border-inline-start: 1px solid var(--rule);
  min-width: 0;
}

.lf-pr-fact:first-child {
  border-inline-start: 0;
}

.lf-pr-fact-name,
.lf-pr-description-label,
.lf-pr-checks-label {
  color: var(--muted);
  font: var(--t-6) var(--sans);
  letter-spacing: .045em;
  text-transform: uppercase;
}

.lf-pr-fact-value {
  color: var(--ink);
  font: var(--t-4) var(--mono);
}

/* The card is already a tint of the accent over the page's paper, so a second
 * translucent accent here stacked into a surface the layer's own --muted ink could not
 * clear: the label and any emphasis inside the author's words read at 4.32:1. The
 * raised-surface token separates the quoted block from the card by going lighter
 * instead, which the accent rule beside it was doing the work of anyway. */
.lf-pr-description {
  padding: var(--sp-3);
  border-inline-start: 3px solid var(--accent);
  background: var(--card);
}

.lf-pr-description-label,
.lf-pr-checks-label {
  margin: 0 0 var(--sp-2);
}

.lf-pr-description-body {
  color: var(--ink);
}

.lf-pr-description-body > :first-child {
  margin-top: 0;
}

.lf-pr-description-body > :last-child {
  margin-bottom: 0;
}

.lf-pr-checks {
  min-width: 0;
}

.lf-pr-check-table {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font: var(--t-6) var(--sans);
}

.lf-pr-check > * {
  padding: 3px 0;
  border-bottom: 1px solid var(--rule);
}

.lf-pr-check:last-child > * {
  border-bottom: 0;
}

.lf-pr-check-name {
  width: 100%;
  padding-inline-end: var(--sp-3);
  color: var(--ink-2);
  font-weight: 400;
  text-align: start;
  overflow-wrap: anywhere;
}

.lf-pr-check-status {
  color: var(--muted);
  text-align: end;
  text-transform: capitalize;
  white-space: nowrap;
}

.lf-pr-check[data-status="passed"] .lf-pr-check-status {
  color: var(--ok-ink);
}

.lf-pr-check[data-status="failed"] .lf-pr-check-status {
  color: var(--danger-ink);
}

.lf-pr-check[data-status="running"] .lf-pr-check-status,
.lf-pr-check[data-status="queued"] .lf-pr-check-status {
  color: var(--warn-ink);
}

.lf-pr-check-empty,
.lf-pr-observed,
.lf-pr-missing {
  color: var(--muted);
  font: var(--t-6) var(--sans);
}

.lf-pr-observed {
  text-align: end;
}

@container (max-width: 34rem) {
  .lf-pr-card {
    padding: var(--sp-3);
  }

  .lf-pr-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .lf-pr-fact:nth-child(3) {
    border-inline-start: 0;
    border-top: 1px solid var(--rule);
  }

  .lf-pr-fact:nth-child(4) {
    border-top: 1px solid var(--rule);
  }
}

@media print {
  .lf-pr-card,
  .lf-pr-description,
  .lf-pr-status {
    background: transparent;
  }
}

/* CallDiff is literal review evidence rather than a second diagram language. Its
 * unchanged rows hold the mental map still while additions and removals carry the
 * same semantic washes as the source diff. */
lf-call-diff {
  --lf-frame: 1;
  display: block;
  max-width: 100%;
  margin: var(--sp-3) 0;
  overflow: hidden;
  border: 1px solid var(--code-border);
  border-radius: var(--r);
  background: var(--pre-bg);
  color: var(--code-ink);
  font-family: var(--mono);
  font-size: var(--code-size);
  font-variant-ligatures: none;
  line-height: var(--code-line);
  container-type: inline-size;
}

.lf-call-tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--code-border);
  background: var(--code-chrome);
  color: var(--code-muted);
  font-family: var(--sans);
}

.lf-call-summary {
  margin: 0;
  font-size: var(--t-6);
}

.lf-call-toggle { flex: none; }

.lf-call-group {
  border-top: 1px solid var(--code-border);
  background: var(--pre-bg);
}

.lf-call-group:first-of-type {
  border-top: 0;
}

.lf-call-group > summary {
  list-style: none;
  cursor: pointer;
}

.lf-call-group > summary::-webkit-details-marker {
  display: none;
}

.lf-call-group > summary::before {
  content: "›";
  align-self: center;
  grid-column: 1;
  grid-row: 1 / span 2;
  color: var(--code-muted);
  font-family: var(--sans);
  font-weight: 700;
  text-align: center;
  transition: transform 120ms ease;
}

.lf-call-group[open] > summary::before {
  transform: rotate(90deg);
}

.lf-call-group-body {
  overflow-x: auto;
  border-top: 1px solid color-mix(in srgb, var(--code-border) 60%, transparent);
}

.lf-call-line {
  display: grid;
  grid-template-columns: 2rem max-content max-content;
  min-width: max-content;
  padding-inline-end: var(--sp-3);
  white-space: pre;
}

.lf-call-group-summary {
  box-sizing: border-box;
  grid-template-columns: 1.25rem 2rem minmax(0, 1fr) max-content;
  grid-template-rows: auto auto;
  width: 100%;
  min-width: 0;
  padding-block: var(--sp-1);
}

.lf-call-group-summary .lf-call-body {
  grid-column: 3;
  grid-row: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.lf-call-group-summary .lf-call-location {
  grid-column: 3 / 5;
  grid-row: 2;
  min-width: 0;
  margin-inline-start: 0;
  overflow: hidden;
  font-size: var(--t-7);
  text-overflow: ellipsis;
}

.lf-call-group-count {
  align-self: center;
  grid-column: 4;
  grid-row: 1;
  margin-inline-start: var(--sp-4);
  color: var(--code-muted);
  font-family: var(--sans);
  font-size: var(--t-7);
  text-align: end;
  white-space: nowrap;
}

.lf-call-line + .lf-call-line {
  border-top: 1px solid color-mix(in srgb, var(--code-border) 45%, transparent);
}

.lf-call-group-body .lf-call-line:first-child {
  border-top: 0;
}

.lf-call-line[data-status="added"] {
  background: color-mix(in srgb, var(--ok) 16%, var(--pre-bg));
}

.lf-call-line[data-status="removed"] {
  background: color-mix(in srgb, var(--danger) 16%, var(--pre-bg));
}

.lf-call-line[data-root] .lf-call-body {
  font-weight: 700;
}

.lf-call-line[data-meta] {
  min-width: 0;
  overflow-x: auto;
  padding-block: var(--sp-1);
  background: var(--code-chrome);
  color: var(--code-muted);
}

.lf-call-marker {
  padding-inline: var(--sp-2);
  color: var(--code-muted);
  text-align: center;
  user-select: none;
}

.lf-call-line[data-status="added"] .lf-call-marker {
  color: var(--ok-ink);
}

.lf-call-line[data-status="removed"] .lf-call-marker {
  color: var(--danger-ink);
}

.lf-call-location {
  margin-inline-start: var(--sp-4);
  color: var(--code-muted);
  text-decoration-color: var(--rule);
  text-underline-offset: 2px;
}

/* Only where there is somewhere to go: a row that names its location without linking it
 * must not answer the pointer as though it did. */
.lf-call-location[href]:hover {
  color: var(--accent);
}

.lf-call-missing,
.lf-call-invalid {
  display: block;
  min-width: 0;
  padding: var(--sp-3);
  color: var(--code-muted);
  font-family: var(--sans);
  white-space: normal;
}

.lf-call-invalid {
  color: var(--danger-ink);
}

@media print {
  lf-call-diff,
  .lf-call-line[data-meta],
  .lf-call-line[data-status="added"],
  .lf-call-line[data-status="removed"] {
    background: transparent;
  }

  .lf-call-tools {
    background: transparent;
  }

  .lf-call-group:not([open]) > .lf-call-group-body {
    display: block;
  }
}

@container (max-width: 34rem) {
  .lf-call-tools {
    align-items: flex-start;
    flex-direction: column;
  }

  .lf-call-group-count {
    display: none;
  }

  .lf-call-group-summary {
    grid-template-columns: 1.25rem 2rem minmax(0, 1fr);
  }

  .lf-call-group-summary .lf-call-location {
    grid-column-end: 4;
  }
}
