/* /Components/AppHeader.razor.rz.scp.css */
.appbar[b-brfcfbdjdi] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex: none;
    height: 2.75rem;
    padding: 0 0.625rem;
    background: var(--rf-chrome);
    border-bottom: 1px solid var(--rf-border);
}

.brand[b-brfcfbdjdi] {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    flex: none;
}

.brand-mark[b-brfcfbdjdi] {
    width: 1.375rem;
    height: 1.375rem;
}

.brand-mark-dim[b-brfcfbdjdi] {
    fill: var(--rf-faint);
}

.brand-mark-lit[b-brfcfbdjdi] {
    fill: var(--rf-accent);
}

.brand-mark-window[b-brfcfbdjdi] {
    fill: none;
    stroke: var(--rf-accent);
    stroke-width: 2.1;
}

.brand-name[b-brfcfbdjdi] {
    color: var(--rf-text);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.brand-name-accent[b-brfcfbdjdi] {
    color: var(--rf-accent);
}

/* Set off from the wordmark by a rule rather than by distance, since the two are read
   together and the bar is too shallow for vertical separation to do it. */
.appbar-note[b-brfcfbdjdi] {
    margin: 0;
    padding-left: 0.75rem;
    border-left: 1px solid var(--rf-border);
    color: var(--rf-muted);
    font-size: 0.75rem;
    white-space: nowrap;
}

.appbar-spacer[b-brfcfbdjdi] {
    flex: 1;
    min-width: 0.25rem;
}

/* A round glyph button, the shape this family gives to the things that open over the
   workbench rather than change it. */
.appbar-icon[b-brfcfbdjdi] {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid var(--rf-border);
    border-radius: 999px;
    background: transparent;
    color: var(--rf-muted);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
}

.appbar-icon:hover[b-brfcfbdjdi] {
    background: var(--rf-chrome-hover);
    color: var(--rf-text);
}

/* The tagline is the first thing to go: it is reassurance, and the controls beside it are
   the app. */
@media (max-width: 76.79rem) {
    .appbar[b-brfcfbdjdi] {
        gap: 0.5rem;
    }

    .appbar-note[b-brfcfbdjdi] {
        display: none;
    }
}
/* /Components/BlockPalette.razor.rz.scp.css */
.pal[b-y36k7yslyb] {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    min-width: 0;
}

/* The groups down the side rather than across the top: the band above the diagram is short,
   and a row of tabs plus a row of blocks is two lines where this is one. */
.pal-tabs[b-y36k7yslyb] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    flex: none;
}

.pal-tab[b-y36k7yslyb] {
    padding: 0.125rem 0.4375rem;
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    color: var(--rf-faint);
    font: inherit;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
}

.pal-tab:hover[b-y36k7yslyb] {
    color: var(--rf-text);
}

.pal-tab.is-on[b-y36k7yslyb] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent-wash);
    color: var(--rf-accent);
}

.pal-blocks[b-y36k7yslyb] {
    display: flex;
    align-items: flex-start;
    gap: 0.25rem;
    flex: 1;
    flex-wrap: wrap;
    min-width: 0;
}

/* The block shows its own syntax rather than a name for it, which is the whole of what
   makes the palette teach: you click "one or more" and see a + arrive in the box. */
.pal-block[b-y36k7yslyb] {
    padding: 0.1875rem 0.4375rem;
    border: 1px solid var(--rf-border);
    border-radius: 5px;
    background: var(--rf-chrome-2);
    color: var(--rf-text);
    font-size: 0.75rem;
    white-space: nowrap;
    cursor: pointer;
}

.pal-block:hover[b-y36k7yslyb] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent-wash);
}

/* A block that goes round something rather than in it. */
.pal-block.is-wrap[b-y36k7yslyb] {
    color: var(--rf-n-group);
}
/* /Components/Explainer.razor.rz.scp.css */
.ex[b-r0nf45cfnv] {
    padding: 0.375rem 0.5rem 0.75rem;
}

.ex-empty[b-r0nf45cfnv] {
    margin: 1.5rem 0.5rem;
    color: var(--rf-faint);
    font-size: 0.8125rem;
    line-height: 1.5;
}

.ex-list[b-r0nf45cfnv] {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Nesting is shown by a rule down the left rather than by indentation alone: at four or
   five levels deep the indent alone stops being countable, and the rules make the columns
   line up so a reader can see which rows belong to the same group. */
.ex-row[b-r0nf45cfnv] {
    display: grid;
    grid-template-columns: 5.5rem auto 1fr;
    align-items: baseline;
    gap: 0 0.5rem;
    margin-left: calc(var(--depth, 0) * 0.75rem);
    padding: 0.25rem 0.375rem 0.25rem 0.5rem;
    border-left: 2px solid color-mix(in srgb, var(--node, var(--rf-border)) 40%, transparent);
    border-radius: 0 4px 4px 0;
    cursor: pointer;
}

.ex-row:hover[b-r0nf45cfnv] {
    background: var(--rf-chrome-2);
}

/* Pointed at from the editor or the diagram. The same accent wash the other panels use for
   the same thing. */
.ex-row.is-lit[b-r0nf45cfnv] {
    background: var(--rf-accent-wash);
    border-left-color: var(--rf-accent);
}

/* What kind of thing this row is, in the node's own colour: the column a reader scans
   rather than reads. */
.ex-what[b-r0nf45cfnv] {
    min-width: 0;
    overflow: hidden;
    color: var(--node, var(--rf-muted));
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-align: right;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}

/* The characters themselves, so the row can be found in the box above without counting. */
.ex-src[b-r0nf45cfnv] {
    padding: 0.0625rem 0.3125rem;
    border-radius: 3px;
    background: var(--rf-chrome-2);
    color: var(--node, var(--rf-text));
    font-size: 0.75rem;
    white-space: pre;
}

.ex-row.is-lit .ex-src[b-r0nf45cfnv] {
    background: var(--rf-pane);
}

.ex-says[b-r0nf45cfnv] {
    min-width: 0;
    color: var(--rf-muted);
    font-size: 0.75rem;
    line-height: 1.45;
}

.ex-row.is-lit .ex-says[b-r0nf45cfnv] {
    color: var(--rf-text);
}

/* Below about a tablet the three columns will not fit, so the sentence drops under the
   label and the source rather than being squeezed to two words a line. */
@media (max-width: 63.99rem) {
    .ex-row[b-r0nf45cfnv] {
        grid-template-columns: 4.5rem auto;
    }

    .ex-says[b-r0nf45cfnv] {
        grid-column: 1 / -1;
        margin-top: 0.125rem;
    }
}
/* /Components/FlagStrip.razor.rz.scp.css */
.fl[b-5nljw6767o] {
    display: flex;
    align-items: center;
    gap: 0.1875rem;
    flex: none;
}

/* Square rather than pill-shaped, and the same monospace the pattern is in, because that is
   what a flag looks like where it is written - after the closing slash of /.../gi. */
.fl-chip[b-5nljw6767o] {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border: 1px solid var(--rf-border);
    border-radius: 5px;
    background: var(--rf-chrome-2);
    color: var(--rf-faint);
    font-family: var(--rf-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
}

.fl-chip:hover[b-5nljw6767o] {
    border-color: var(--rf-border);
    background: var(--rf-chrome-hover);
    color: var(--rf-text);
}

.fl-chip.is-on[b-5nljw6767o] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent);
    color: var(--rf-accent-ink);
}

/* /Components/LibraryOverlay.razor.rz.scp.css */
.library:not([open])[b-sxuf6vbrzy] {
    display: none;
}

/* A fixed height rather than a cap this content grows up to: a `<dialog>` recentres itself
   in the viewport whenever its box changes size, so with only `max-height` here, filtering
   down to a handful of cards would shrink the dialog and drag the search box and chips up
   the screen with it - jarring on every keystroke and every chip click. Fixed height means
   only `.library-body` below ever scrolls, and the chrome above it never moves. */
.library[b-sxuf6vbrzy] {
    width: min(76rem, 94vw);
    height: 86vh;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--rf-border);
    border-radius: 10px;
    background: var(--rf-pane);
    color: var(--rf-text);
    font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-size: 0.875rem;
}

.library[b-sxuf6vbrzy]::backdrop {
    background: rgba(4, 7, 10, 0.62);
}

.library-head[b-sxuf6vbrzy] {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    flex: none;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--rf-border);
    background: var(--rf-pane-alt);
}

.library-title[b-sxuf6vbrzy] {
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.library-sub[b-sxuf6vbrzy] {
    margin: 0 auto 0 0;
    color: var(--rf-muted);
    font-size: 0.75rem;
}

.library-close[b-sxuf6vbrzy] {
    display: grid;
    place-items: center;
    flex: none;
    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid transparent;
    border-radius: 6px;
    background: none;
    color: var(--rf-muted);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
}

.library-close:hover[b-sxuf6vbrzy] {
    border-color: var(--rf-border);
    background: var(--rf-chrome-hover);
    color: var(--rf-text);
}

.library-body[b-sxuf6vbrzy] {
    flex: 1;
    min-height: 0;
    overflow: auto;
    padding: 1rem;
}

.library-filters[b-sxuf6vbrzy] {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.library-search[b-sxuf6vbrzy] {
    flex: 1 1 14rem;
    min-width: 10rem;
    padding: 0.375rem 0.625rem;
    border: 1px solid var(--rf-border);
    border-radius: 6px;
    background: var(--rf-chrome-2);
    color: var(--rf-text);
    font: inherit;
    font-size: 0.8125rem;
}

.library-search:focus-visible[b-sxuf6vbrzy] {
    border-color: var(--rf-accent-dim);
    outline: none;
}

.library-chips[b-sxuf6vbrzy] {
    display: flex;
    gap: 0.375rem;
    flex-wrap: wrap;
}

.chip[b-sxuf6vbrzy] {
    padding: 0.1875rem 0.625rem;
    border: 1px solid var(--rf-border);
    border-radius: 999px;
    background: var(--rf-chrome-2);
    color: var(--rf-muted);
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.chip:hover[b-sxuf6vbrzy] {
    background: var(--rf-chrome-hover);
    color: var(--rf-text);
}

.chip.is-on[b-sxuf6vbrzy] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent-wash);
    color: var(--rf-accent);
}

.library-empty[b-sxuf6vbrzy] {
    margin: 2rem 0;
    color: var(--rf-muted);
    font-size: 0.8125rem;
    text-align: center;
}

/* Columns rather than a grid: cards differ in height by a line or two, and a grid leaves
   its short rows trailing space where a column flow simply packs the next card in. */
.library-cards[b-sxuf6vbrzy] {
    columns: 23rem;
    column-gap: 1rem;
}

.library-card[b-sxuf6vbrzy] {
    break-inside: avoid;
    margin-bottom: 1rem;
    padding: 0.6875rem 0.8125rem;
    border: 1px solid var(--rf-border-soft);
    border-radius: 8px;
    background: var(--rf-pane-alt);
}

.library-card-head[b-sxuf6vbrzy] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.4375rem;
}

.library-card-head h3[b-sxuf6vbrzy] {
    margin: 0;
    color: var(--rf-text);
    font-size: 0.8125rem;
    font-weight: 600;
}

.library-category[b-sxuf6vbrzy] {
    flex: none;
    color: var(--rf-faint);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* The pattern itself, coloured exactly as the editor colours it - so a card is already
   saying which piece is a group and which is a set, before it has been loaded. */
.library-pattern[b-sxuf6vbrzy] {
    margin: 0 0 0.4375rem;
    padding: 0.3125rem 0.4375rem;
    border-radius: 5px;
    background: var(--rf-chrome-2);
    font-size: 0.8125rem;
    line-height: 1.4;
    overflow-wrap: break-word;
    word-break: break-word;
}

.library-pattern span[b-sxuf6vbrzy] {
    color: var(--node, var(--rf-text));
}

.library-pattern .n-group[b-sxuf6vbrzy],
.library-pattern .n-repeat[b-sxuf6vbrzy],
.library-pattern .n-anchor[b-sxuf6vbrzy] {
    font-weight: 600;
}

/* The flags, set off from the pattern the way they are in the languages that write them
   after a closing slash. */
.library-flags[b-sxuf6vbrzy] {
    margin-left: 0.5ch;
    padding: 0 0.3125rem;
    border-radius: 3px;
    background: var(--rf-accent-wash);
    color: var(--rf-accent) !important;
    font-size: 0.75rem;
    font-weight: 700;
}

.library-says[b-sxuf6vbrzy] {
    margin: 0 0 0.3125rem;
    color: var(--rf-text);
    font-size: 0.8125rem;
    line-height: 1.4;
}

.library-desc[b-sxuf6vbrzy] {
    margin: 0;
    color: var(--rf-muted);
    font-size: 0.75rem;
    line-height: 1.45;
}

.library-card-actions[b-sxuf6vbrzy] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.625rem;
}

.library-found[b-sxuf6vbrzy] {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    color: var(--rf-faint);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.library-use[b-sxuf6vbrzy] {
    flex: none;
    padding: 0.25rem 0.6875rem;
    border: 1px solid var(--rf-accent-dim);
    border-radius: 6px;
    background: var(--rf-accent-wash);
    color: var(--rf-accent);
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
}

.library-use:hover[b-sxuf6vbrzy] {
    background: var(--rf-accent);
    color: var(--rf-accent-ink);
}

@media (max-width: 63.99rem) {
    .library[b-sxuf6vbrzy] {
        width: 96vw;
        height: 92vh;
    }

    .library-body[b-sxuf6vbrzy] {
        padding: 0.75rem;
    }

    .library-sub[b-sxuf6vbrzy] {
        display: none;
    }
}
/* /Components/MatchList.razor.rz.scp.css */
.ml[b-os89kx52e7] {
    padding: 0.5rem;
}

.ml-empty[b-os89kx52e7],
.ml-error[b-os89kx52e7] {
    margin: 1rem 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.5;
}

.ml-empty[b-os89kx52e7] {
    color: var(--rf-faint);
}

.ml-error[b-os89kx52e7] {
    padding: 0.5rem 0.625rem;
    border: 1px solid color-mix(in srgb, var(--rf-danger) 40%, transparent);
    border-radius: 6px;
    background: var(--rf-danger-wash);
    color: var(--rf-text);
}

.ml-list[b-os89kx52e7] {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 0.375rem;
}

.ml-item[b-os89kx52e7] {
    padding: 0.375rem 0.5rem;
    border: 1px solid var(--rf-border-soft);
    border-radius: 6px;
    background: var(--rf-pane-alt);
    cursor: pointer;
}

.ml-item:hover[b-os89kx52e7] {
    border-color: var(--rf-border);
}

/* The one being traced by the other panel. */
.ml-item.is-picked[b-os89kx52e7] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent-wash);
}

.ml-head[b-os89kx52e7] {
    display: flex;
    align-items: baseline;
    gap: 0.4375rem;
}

/* The match's number, in a fixed-width tab so a column of them lines up however many
   there are. */
.ml-n[b-os89kx52e7] {
    flex: none;
    min-width: 1.25rem;
    padding: 0.0625rem 0.25rem;
    border-radius: 3px;
    background: var(--rf-chrome-2);
    color: var(--rf-faint);
    font-size: 0.625rem;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    text-align: center;
}

.ml-item.is-picked .ml-n[b-os89kx52e7] {
    background: var(--rf-accent);
    color: var(--rf-accent-ink);
}

.ml-text[b-os89kx52e7] {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    color: var(--rf-text);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ml-at[b-os89kx52e7] {
    flex: none;
    color: var(--rf-faint);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
}

/* The groups. A two-column list rather than a table, because the rows are label-and-value
   and a table would bring borders nobody needs to a card this small. */
.ml-caps[b-os89kx52e7] {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 0.125rem 0.5rem;
    margin: 0.375rem 0 0;
    padding-top: 0.3125rem;
    border-top: 1px dashed var(--rf-border-soft);
}

.ml-caps dt[b-os89kx52e7] {
    color: var(--rf-n-group);
    font-size: 0.6875rem;
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
}

.ml-caps dt.is-absent[b-os89kx52e7] {
    color: var(--rf-faint);
    font-weight: 500;
}

.ml-caps dd[b-os89kx52e7] {
    margin: 0;
    min-width: 0;
    overflow: hidden;
    color: var(--rf-text);
    font-size: 0.75rem;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A group that never matched, and one that matched an empty string. The two look the same
   in every other tool and are not the same thing at all - one is a branch that was not
   taken, the other is a branch that was. */
.ml-absent[b-os89kx52e7] {
    color: var(--rf-faint);
    font-size: 0.6875rem;
    font-style: italic;
}
/* /Components/NodeActions.razor.rz.scp.css */
/* A bar in the diagram pane's header rather than a menu that pops up over the drawing. A
   popup would cover the thing it is about, and what a reader wants while they are clicking
   these is to watch the diagram change underneath. */
.na[b-9kplmxkveb] {
    display: flex;
    align-items: center;
    gap: 0.3125rem;
    min-width: 0;
    flex-wrap: nowrap;
    overflow: hidden;
}

.na-hint[b-9kplmxkveb] {
    color: var(--rf-faint);
    font-size: 0.6875rem;
    white-space: nowrap;
}

/* What is selected, in the pattern's own monospace, so there is no doubt which of three
   similar-looking boxes was clicked. */
.na-name[b-9kplmxkveb] {
    flex: none;
    min-width: 0;
}

.na-name code[b-9kplmxkveb] {
    padding: 0.0625rem 0.3125rem;
    border-radius: 3px;
    background: var(--rf-accent-wash);
    color: var(--rf-accent);
    font-size: 0.75rem;
    white-space: pre;
}

.na-sep[b-9kplmxkveb] {
    flex: none;
    width: 1px;
    height: 0.875rem;
    background: var(--rf-border);
}

.na-label[b-9kplmxkveb] {
    flex: none;
    color: var(--rf-faint);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.na-spacer[b-9kplmxkveb] {
    flex: 1;
    min-width: 0.25rem;
}

/* The one destructive control here, so it is set apart by colour on hover rather than
   sitting in the row looking like the others. */
.na-drop:hover:not(:disabled)[b-9kplmxkveb] {
    border-color: color-mix(in srgb, var(--rf-danger) 45%, transparent);
    background: var(--rf-danger-wash);
    color: var(--rf-danger);
}

.btn.is-on[b-9kplmxkveb] {
    border-color: var(--rf-accent-dim);
    background: var(--rf-accent-wash);
    color: var(--rf-accent);
    font-weight: 600;
}
/* /Components/PatternBox.razor.rz.scp.css */
/* The two layers sit in the same place holding the same text, and every property that could
   move a character by half a pixel has to be identical on both. They are therefore declared
   once, in the one block below that names both elements, and **neither element may set any of
   them on its own** - a rule in a single-element block wins on specificity and silently
   un-pairs the two. `EditorMetricsTests` is what holds this file to that.

   The font is the one that bites hardest. Both elements used to take it from the shared `.mono`
   class, and a `font-family: inherit` on the textarea alone was enough to leave the layer
   monospace and the box proportional: the text the reader could see and the caret they were
   typing with were then in different places, and the tail of a long pattern had no textarea
   underneath it to select at all. */
.box[b-fd6nr7hb34] {
    position: relative;
    border: 1px solid var(--rf-border);
    border-radius: 7px;
    background: var(--rf-chrome-2);
    overflow: hidden;
}

.box:focus-within[b-fd6nr7hb34] {
    border-color: var(--rf-accent-dim);
    box-shadow: 0 0 0 2px var(--rf-accent-wash);
}

.box-layer[b-fd6nr7hb34],
.box-input[b-fd6nr7hb34] {
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: 0.5rem 0.625rem;
    border: 0;
    font-family: var(--rf-mono);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    letter-spacing: 0;
    word-spacing: 0;
    text-indent: 0;
    text-transform: none;
    tab-size: 4;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;

    /* Both reserve room for a scrollbar whether or not one is showing. Without this the
       textarea's content box narrows by a scrollbar's width the moment the pattern gets long
       enough to scroll, its lines then wrap in different places from the layer's, and the
       colour slides off the text below the first wrap. */
    scrollbar-gutter: stable;
}

.box-layer[b-fd6nr7hb34] {
    position: absolute;
    inset: 0;
    overflow: hidden;
    color: var(--rf-faint);
    pointer-events: none;
    user-select: none;
}

/* The box's own text is invisible and its caret is not, so what the reader sees is the
   coloured layer with a real caret moving through it. */
.box-input[b-fd6nr7hb34] {
    position: relative;
    display: block;
    resize: none;
    overflow: auto;
    background: transparent;
    color: transparent;
    caret-color: var(--rf-text);
}

.box-input:focus[b-fd6nr7hb34] {
    outline: none;
}

.box-input[b-fd6nr7hb34]::placeholder {
    color: var(--rf-faint);
}

.box-input[b-fd6nr7hb34]::selection {
    background: var(--rf-accent-dim);
}

/* Every run takes its colour from the --node the .n-* class set, so this one rule covers
   all of them and adding a node kind is a token and a class, not a rule here. */
.box-layer span[b-fd6nr7hb34] {
    color: var(--node, var(--rf-text));
}

/* A group's brackets and a quantifier are structure rather than content, and drawing them
   at full strength makes a pattern read as louder than it is. The weight is what carries
   them instead. */
.box-layer .n-group[b-fd6nr7hb34],
.box-layer .n-repeat[b-fd6nr7hb34],
.box-layer .n-anchor[b-fd6nr7hb34] {
    font-weight: 600;
}

/* What the parser could not read. A wavy underline rather than a red background: the
   characters still have to be readable, and they are still the ones being typed. */
.box-layer .is-broken[b-fd6nr7hb34] {
    text-decoration: underline wavy var(--rf-danger);
    text-underline-offset: 0.2em;
}

/* The part being pointed at somewhere else on the page - a box in the diagram, a row in the
   explanation, the step the trace is stopped on. This is the whole tie between the panels,
   so it is deliberately the strongest mark the box has. */
.box-layer .is-lit[b-fd6nr7hb34] {
    border-radius: 3px;
    background: var(--rf-accent-wash);
    box-shadow: 0 0 0 1px var(--rf-accent-dim);
}

.box-tail[b-fd6nr7hb34] {
    color: transparent;
}

/* /Components/RailDiagram.razor.rz.scp.css */
/* The diagram is as wide as the pattern needs and scrolls sideways rather than wrapping.
   A railroad that wrapped would be lying: along the page is the order the engine reads in,
   and a second row would say the track goes back to the left, which it does not. */
.rail-wrap[b-o65uflqwkr] {
    min-width: 0;
    padding: 0.75rem 0.875rem 1rem;
}

/* Every label in this drawing is rendered by the SvgText component, and a child component's
   elements do not carry this file's scope attribute - so a rule written as `.rail-box text`
   compiles to `.rail-box text[b-xyz]` and matches nothing at all. The labels then fall back to
   SVG's default fill, which is black: invisible on a dark pane, and perfectly fine on a light
   one, which is exactly how this came to be shipped.

   So nothing below targets `text`. `fill`, `font-size`, `font-weight` and `font-family` are all
   inherited in SVG, so they are set on the group instead and the shapes that want something
   different - every `rect` and `path` here - say so themselves. */
.rail[b-o65uflqwkr] {
    display: block;
    overflow: visible;
    color: var(--rf-faint);
    font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, sans-serif;

    /* Dragging across the diagram should not select the words in it. */
    user-select: none;
}

.rail-empty[b-o65uflqwkr] {
    margin: 1.5rem 0;
    color: var(--rf-faint);
    font-size: 0.8125rem;
    text-align: center;
}

/* ── The track ────────────────────────────────────────────────────────────────
   Deliberately quiet. The line is what the eye follows between the boxes, not
   something to look at, and a diagram whose connectors are as strong as its
   contents reads as a circuit board. */
.rail-line[b-o65uflqwkr] {
    fill: none;
    stroke: var(--rf-border);
    stroke-width: 1.5;
    color: var(--rf-faint);
}

/* The way back from a repeat. Drawn thinner and in the repeat's own green, because it is
   the one line on the diagram that goes backwards and it should be recognisable as such
   from across the page. */
.rail-line.is-loop[b-o65uflqwkr] {
    stroke: color-mix(in srgb, var(--rf-n-repeat) 55%, transparent);
    stroke-width: 1.3;
}

/* ── Boxes ────────────────────────────────────────────────────────────────────
   Each takes its hue from the --node the drawing set on it, so one rule covers
   every kind and the palette is the only place the colours live. */
/* The label's colour and size come from here and are inherited by the text inside. */
.rail-box[b-o65uflqwkr] {
    cursor: pointer;
    fill: var(--rf-text);
    font-size: 11px;
    font-weight: 500;
}

.rail-box rect[b-o65uflqwkr],
.rail-box path[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--node) 12%, var(--rf-pane));
    stroke: color-mix(in srgb, var(--node) 55%, transparent);
    stroke-width: 1.3;
}

/* A literal is the one kind of box whose label is the thing itself rather than a name for
   it, so it is set in the same monospace the pattern is. */
.rail-box.is-literal[b-o65uflqwkr] {
    font-family: var(--rf-mono);
    font-size: 10.5px;
}

/* An anchor consumes nothing, and the flag it is drawn as should not look like something
   the text passes through - so it is filled with the page rather than with its own hue. */
.rail-box.is-anchor[b-o65uflqwkr] {
    fill: var(--rf-muted);
    font-size: 10px;
}

.rail-box.is-anchor path[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--node) 8%, var(--rf-pane-alt));
    stroke-dasharray: none;
}

/* The buffer at each end: filled rather than outlined, so it reads as the end of the line
   and not as one more thing the text has to match. */
.rail-box.is-terminal[b-o65uflqwkr] {
    cursor: default;
}

.rail-box.is-terminal rect[b-o65uflqwkr] {
    fill: var(--rf-border);
    stroke: none;
}

.rail-box.is-error rect[b-o65uflqwkr] {
    fill: var(--rf-danger-wash);
    stroke: var(--rf-danger);
}

.rail-box:hover rect[b-o65uflqwkr],
.rail-box:hover path[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--node) 24%, var(--rf-pane));
}

/* Pointed at from somewhere else on the page - the editor, the explanation, the trace.
   Same mark in all four panels, which is what makes them read as one thing. */
.rail-box.is-lit rect[b-o65uflqwkr],
.rail-box.is-lit path[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--node) 28%, var(--rf-pane));
    stroke: var(--node);
    stroke-width: 2;
}

/* Clicked, and so holding the editing menu open. */
.rail-box.is-chosen rect[b-o65uflqwkr],
.rail-box.is-chosen path[b-o65uflqwkr] {
    stroke: var(--rf-accent);
    stroke-width: 2;
}

/* ── Frames ───────────────────────────────────────────────────────────────────
   A group's frame is a boundary rather than an object: dashed, unfilled, and
   named on its own top edge so the name never sits on the track. */
.rail-frame[b-o65uflqwkr] {
    cursor: pointer;
    fill: color-mix(in srgb, var(--rf-n-group) 80%, var(--rf-text));
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.rail-frame rect[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--rf-n-group) 5%, transparent);
    stroke: color-mix(in srgb, var(--rf-n-group) 45%, transparent);
    stroke-width: 1.1;
    stroke-dasharray: 4 3;
}

/* The two look-arounds that must *not* match. A frame that means "and none of this" has to
   be distinguishable from one that means the opposite at a glance, so it takes the danger
   colour - the only place on the page that colour is used for something that is not wrong. */
.rail-frame.is-negative[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--rf-danger) 75%, var(--rf-text));
}

.rail-frame.is-negative rect[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--rf-danger) 5%, transparent);
    stroke: color-mix(in srgb, var(--rf-danger) 45%, transparent);
}

.rail-frame:hover rect[b-o65uflqwkr],
.rail-frame.is-lit rect[b-o65uflqwkr] {
    stroke-width: 1.8;
    stroke-dasharray: none;
}

/* ── Tags ─────────────────────────────────────────────────────────────────────
   What is written beside a loop: how many times, and how hard it holds on. */
.rail-tag[b-o65uflqwkr] {
    fill: var(--rf-faint);
    font-size: 9.5px;
    font-weight: 400;
    pointer-events: none;
}

/* The count. The one label on the diagram that carries information rather than naming
   something, so it is the one that gets a chip of its own. */
.rail-tag.is-strong[b-o65uflqwkr] {
    fill: color-mix(in srgb, var(--rf-n-repeat) 90%, var(--rf-text));
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Filled with the pane rather than left transparent, which is the whole point: the loop line
   passes exactly through here, and this is what breaks it behind the digits instead of
   letting it run through them. */
.rail-chip[b-o65uflqwkr] {
    fill: var(--rf-pane);
    stroke: color-mix(in srgb, var(--rf-n-repeat) 35%, transparent);
    stroke-width: 1;
}

/* /Components/SubjectBox.razor.rz.scp.css */
/* Two layers in the same place with identical metrics - see PatternBox.razor.css, which does
   the same thing for the same reason and carries the full explanation. Every property that
   could move a character by half a pixel is declared once, in the block naming both elements,
   and neither element may set any of them on its own. */
.subj[b-jc24i08atz] {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
}

.subj-layer[b-jc24i08atz],
.subj-input[b-jc24i08atz] {
    box-sizing: border-box;
    width: 100%;
    margin: 0;
    padding: 0.5rem 0.625rem;
    border: 0;
    font-family: var(--rf-mono);
    font-size: 0.8125rem;
    font-weight: 400;
    line-height: 1.55;
    letter-spacing: 0;
    word-spacing: 0;
    text-indent: 0;
    text-transform: none;
    tab-size: 4;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;
    scrollbar-gutter: stable;
}

.subj-layer[b-jc24i08atz] {
    position: absolute;
    inset: 0;
    overflow: hidden;
    color: var(--rf-muted);
    pointer-events: none;
    user-select: none;
}

.subj-input[b-jc24i08atz] {
    position: relative;
    display: block;
    flex: 1;
    resize: none;
    overflow: auto;
    background: transparent;
    color: transparent;
    caret-color: var(--rf-text);
}

.subj-input:focus[b-jc24i08atz] {
    outline: none;
}

.subj-input[b-jc24i08atz]::placeholder {
    color: var(--rf-faint);
}

.subj-input[b-jc24i08atz]::selection {
    background: var(--rf-accent-dim);
}

/* A match. The accent rather than one of the node hues, on purpose: a match is the app's
   answer about the text, not a piece of the pattern, and colouring it like one would say
   the two are the same kind of thing. */
.subj-layer mark[b-jc24i08atz] {
    padding: 0.0625rem 0;
    border-radius: 2px;
    background: var(--rf-hit);
    box-shadow: inset 0 -1px 0 var(--rf-hit-edge);
    color: var(--rf-text);
}

/* The one being traced by the panel beside this. */
.subj-layer mark.is-picked[b-jc24i08atz] {
    background: color-mix(in srgb, var(--rf-accent) 34%, transparent);
    box-shadow: 0 0 0 1px var(--rf-accent);
    color: var(--rf-text);
}

/* A match that consumed nothing. There is no width to fill, so it is drawn as a caret
   between two characters - and it has to be drawn as something, because "this pattern
   matches the empty string everywhere" is exactly the answer people fail to notice. */
.subj-layer mark.is-empty[b-jc24i08atz] {
    display: inline-block;
    width: 0;
    padding: 0;
    border-left: 2px solid var(--rf-cursor);
    border-radius: 0;
    background: none;
    box-shadow: none;
}

.subj-tail[b-jc24i08atz] {
    color: transparent;
}
/* /Components/ThemeToggle.razor.rz.scp.css */
.theme-btn[b-5hw48lebv4] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex: none;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--rf-border);
    border-radius: 999px;
    background: transparent;
    color: var(--rf-muted);
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.theme-btn:hover:not(:disabled)[b-5hw48lebv4] {
    background: var(--rf-chrome-hover);
    color: var(--rf-text);
}

.theme-btn:disabled[b-5hw48lebv4] {
    cursor: default;
    opacity: 0.6;
}

/* The label is the first thing to go when the chrome tightens - the glyph on its
   own still says which way the switch will move. */
@media (max-width: 1228.78px) {
    .theme-btn-label[b-5hw48lebv4] {
        display: none;
    }
}

/* /Components/TracePanel.razor.rz.scp.css */
.tr[b-1vqeacx0pj] {
    display: flex;
    flex-direction: column;
    min-height: 0;
    height: 100%;
    padding: 0.5rem;
    gap: 0.4375rem;
}

.tr-empty[b-1vqeacx0pj] {
    margin: 1rem 0.5rem;
    color: var(--rf-faint);
    font-size: 0.8125rem;
    line-height: 1.5;
}

/* ── The tape ─────────────────────────────────────────────────────────────────
   Where in the text the engine is, at this step. One line, and the characters
   this step took shown against the ones around them. */
.tr-tape[b-1vqeacx0pj] {
    flex: none;
    overflow: hidden;
    padding: 0.4375rem 0.5rem;
    border: 1px solid var(--rf-border-soft);
    border-radius: 6px;
    background: var(--rf-chrome-2);
    font-size: 0.8125rem;
    white-space: pre;
    text-overflow: ellipsis;
}

.tr-tape-before[b-1vqeacx0pj],
.tr-tape-after[b-1vqeacx0pj] {
    color: var(--rf-faint);
}

/* What this step did to the text, in the step's own colour - so the tape and the row in the
   list below agree without the reader having to look from one to the other. */
.tr-tape-at[b-1vqeacx0pj] {
    padding: 0.0625rem 0;
    border-radius: 2px;
    box-shadow: inset 0 -2px 0 var(--tone, var(--rf-accent));
    color: var(--rf-text);
    font-weight: 700;
}

/* ── The scrubber ─────────────────────────────────────────────────────────────
   The slider is the panel's main control, not the list: four thousand steps is
   something you drag through, not something you scroll. */
.tr-scrub[b-1vqeacx0pj] {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    flex: none;
}

.tr-step[b-1vqeacx0pj] {
    flex: none;
    padding: 0.0625rem 0.375rem;
    border-color: var(--rf-border);
    font-size: 0.8125rem;
    line-height: 1.2;
}

.tr-range[b-1vqeacx0pj] {
    flex: 1;
    min-width: 0;
    height: 1rem;
    margin: 0;
    accent-color: var(--rf-accent);
    cursor: pointer;
}

.tr-count[b-1vqeacx0pj] {
    flex: none;
    color: var(--rf-faint);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── The counts ───────────────────────────────────────────────────────────────
   The panel's verdict, and the only place in the app that says what a pattern
   costs rather than what it means. */
.tr-facts[b-1vqeacx0pj] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: none;
    flex-wrap: wrap;
}

.tr-fact[b-1vqeacx0pj] {
    color: var(--rf-muted);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
}

.tr-fact b[b-1vqeacx0pj] {
    color: var(--rf-text);
    font-weight: 700;
}

/* Enough backtracking to be worth noticing. Warned rather than errored: a pattern that
   backtracks is not wrong, it is expensive, and the difference matters. */
.tr-fact.is-hot b[b-1vqeacx0pj] {
    color: var(--rf-warn);
}

.tr-cut[b-1vqeacx0pj] {
    flex: none;
    margin: 0;
    padding: 0.375rem 0.5rem;
    border: 1px solid color-mix(in srgb, var(--rf-warn) 40%, transparent);
    border-radius: 6px;
    background: var(--rf-warn-wash);
    color: var(--rf-text);
    font-size: 0.6875rem;
    line-height: 1.45;
}

/* ── The steps ────────────────────────────────────────────────────────────────
   A window around the current step rather than the whole walk - see Window in
   the component. */
.tr-steps[b-1vqeacx0pj] {
    flex: 1;
    min-height: 4rem;
    overflow: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    border: 1px solid var(--rf-border-soft);
    border-radius: 6px;
    background: var(--rf-pane-alt);
}

.tr-row[b-1vqeacx0pj] {
    display: grid;
    grid-template-columns: 0.875rem 1.75rem 1fr;
    align-items: baseline;
    gap: 0 0.375rem;
    padding: 0.125rem 0.375rem 0.125rem calc(0.375rem + (var(--depth, 0) * 0.4375rem));
    border-left: 2px solid transparent;
    color: var(--rf-muted);
    font-size: 0.6875rem;
    line-height: 1.45;
    cursor: pointer;
}

.tr-row:hover[b-1vqeacx0pj] {
    background: var(--rf-chrome-2);
}

/* The step the slider is on. */
.tr-row.is-at[b-1vqeacx0pj] {
    border-left-color: var(--tone, var(--rf-accent));
    background: var(--rf-chrome-2);
    color: var(--rf-text);
}

.tr-mark[b-1vqeacx0pj] {
    color: var(--tone, var(--rf-faint));
    font-weight: 700;
    text-align: center;
}

.tr-pos[b-1vqeacx0pj] {
    color: var(--rf-faint);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.tr-what[b-1vqeacx0pj] {
    min-width: 0;
}

/* One tone per kind of step, set as a variable so the mark, the left rule and the tape
   above all take it from one place. Green for progress, orange for giving ground, red for
   a dead end - and every one of them also carries its own glyph, because that is a lot of
   meaning to hang on colour alone. */
.tr-row.is-take[b-1vqeacx0pj],
.tr-tape-at.is-take[b-1vqeacx0pj] { --tone: var(--rf-good); }

.tr-row.is-assert[b-1vqeacx0pj],
.tr-tape-at.is-assert[b-1vqeacx0pj] { --tone: var(--rf-n-anchor); }

.tr-row.is-fail[b-1vqeacx0pj],
.tr-tape-at.is-fail[b-1vqeacx0pj] { --tone: var(--rf-danger); }

.tr-row.is-back[b-1vqeacx0pj],
.tr-tape-at.is-back[b-1vqeacx0pj] { --tone: var(--rf-warn); }

.tr-row.is-scan[b-1vqeacx0pj],
.tr-tape-at.is-scan[b-1vqeacx0pj] { --tone: var(--rf-n-any); }

.tr-row.is-done[b-1vqeacx0pj],
.tr-tape-at.is-done[b-1vqeacx0pj] { --tone: var(--rf-accent); }

.tr-row.is-enter[b-1vqeacx0pj],
.tr-tape-at.is-enter[b-1vqeacx0pj] { --tone: var(--rf-n-group); }

/* A backtrack is what the panel exists to show, so it is the one kind of step that is
   readable at a glance in a column of sixty. */
.tr-row.is-back[b-1vqeacx0pj] {
    color: var(--rf-text);
}
/* /Layout/ShellLayout.razor.rz.scp.css */
/* Fixed to the viewport, so the panes divide a known height between them and the page
   itself never scrolls: every pane that can overflow scrolls inside its own box, which is
   what keeps the pattern, its diagram and the text it is being run over all on screen at
   once. Seeing those three change together is the whole app - a diagram you have to scroll
   away from the pattern to see is a diagram of nothing in particular. */
.rf-shell[b-dgg1q1h78r] {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--rf-bg);
    color: var(--rf-text);
    font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-size: 0.875rem;
}

/* On a narrow screen the fixed shell is given up. A pattern band, a diagram, an explanation
   and a test panel inside one viewport height would leave every one of them too short to
   read - so the page scrolls instead, and each pane is as tall as it needs to be. */
@media (max-width: 63.99rem) {
    .rf-shell[b-dgg1q1h78r] {
        position: static;
        min-height: 100dvh;
        overflow: visible;
    }
}
/* /Pages/NotFound.razor.rz.scp.css */
/* Centred in what is left of the shell below the app bar. */
.missing[b-td35cet7h7] {
    flex: 1;
    display: grid;
    place-items: center;
    padding: 2rem;
    text-align: center;
}

.missing h1[b-td35cet7h7] {
    margin: 0 0 0.5rem;
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.missing p[b-td35cet7h7] {
    margin: 0 0 1rem;
    color: var(--rf-muted);
}

.missing a[b-td35cet7h7] {
    color: var(--rf-accent);
    font-size: 0.875rem;
}
/* /Pages/Workbench.razor.rz.scp.css */
/* ── The pattern band ─────────────────────────────────────────────────────────
   Full width and at the top, because it is what the page is about. Everything
   below is a reading of it, and both readings want width more than this does. */
.rf-top[b-eurjz7ton8] {
    flex: none;
    --pane-hue: var(--rf-accent);
    border-bottom: 1px solid var(--rf-border);
}

.rf-band[b-eurjz7ton8] {
    padding: 0.625rem 0.875rem 0.6875rem;
}

/* Everything the app has to say about the pattern above, in a patch of the band that is
   always exactly this tall.

   The height is the point of it. The sentence rewords itself on every keystroke, and
   findings appear and disappear as the pattern changes - turning on a flag adds one - so
   sizing this to its contents moved the palette underneath it and the diagram under that,
   out from under a reader who was aiming at them. Four and a half lines covers the sentence
   and a finding or two; more than that scrolls, which is a scrollbar in one small box
   rather than the whole page shifting. */
.rf-read[b-eurjz7ton8] {
    box-sizing: border-box;
    height: 4.75rem;
    overflow-y: auto;
    margin-top: 0.625rem;
    padding: 0.4375rem 0.5625rem;
    border: 1px solid var(--rf-border-soft);
    border-radius: 6px;
    background: var(--rf-pane-alt);
}

.rf-said[b-eurjz7ton8] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* The sentence. The largest text on the page after the pattern itself. */
.rf-says[b-eurjz7ton8] {
    margin: 0;
    color: var(--rf-text);
    font-size: 1rem;
    line-height: 1.4;
}

.rf-said-spacer[b-eurjz7ton8] {
    flex: 1;
    min-width: 0;
}

.finds[b-eurjz7ton8] {
    margin: 0.375rem 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.75rem;
}

/* A clean pattern has nothing to report, and an empty list should not push a gap. */
.finds:empty[b-eurjz7ton8] {
    margin: 0;
}

/* Hovering a finding lights the characters it is about, which is the whole reason a finding
   carries a span - "this range runs backwards" is worth very little without "this one". */
.find[b-eurjz7ton8] {
    display: flex;
    align-items: baseline;
    gap: 0.4375rem;
    padding: 0.125rem 0.25rem;
    border-radius: 4px;
    color: var(--rf-muted);
    line-height: 1.45;
    cursor: default;
}

.find:hover[b-eurjz7ton8] {
    background: var(--rf-chrome-2);
}

/* The mark is a fixed width so the sentences line up down the left however many findings
   there are and whatever mix of marks they carry. */
.find-mark[b-eurjz7ton8] {
    flex: none;
    width: 0.75rem;
    color: var(--tone, var(--rf-faint));
    font-weight: 700;
    text-align: center;
}

.find-bad[b-eurjz7ton8] {
    --tone: var(--rf-danger);
    color: var(--rf-text);
}

.find-warn[b-eurjz7ton8] {
    --tone: var(--rf-warn);
    color: var(--rf-text);
}

.find-note[b-eurjz7ton8] {
    --tone: var(--rf-faint);
}

/* The builder and the presets on one line: the palette takes what it needs and the presets
   sit at the end of it. */
.rf-build[b-eurjz7ton8] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 0.625rem;
}

.rf-presets[b-eurjz7ton8] {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    flex-wrap: wrap;
}

.rf-presets-label[b-eurjz7ton8] {
    flex: none;
    margin-right: 0.125rem;
    color: var(--rf-faint);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* ── The two readings ─────────────────────────────────────────────────────────
   Stacked, so the page reads as three bands: the pattern, what it is, and what it
   does to your text. Both readings then have the full width, which each of them
   uses - the diagram to run along rather than wrap, and the test panel to put the
   text and the answer side by side. */
.rf[b-eurjz7ton8] {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--rf-bg);
}

/* The diagram band gets the larger share. It is the panel people came for, and it is the
   one whose content can be genuinely tall - a pattern with four alternatives is four rows
   of track. */
.rf-shape[b-eurjz7ton8] {
    flex: 3 1 0;
    min-height: 9rem;
    --pane-hue: var(--rf-n-group);
}

/* The current size, between the two steppers. Fixed width so that going from 100% to 90%
   does not shuffle the buttons either side of it under the pointer that is pressing them. */
.rf-zoom-now[b-eurjz7ton8] {
    min-width: 2.75rem;
    font-variant-numeric: tabular-nums;
}

.rf-shape-body[b-eurjz7ton8] {
    flex: 1;
    min-height: 0;
    display: flex;
}

/* The diagram scrolls in both directions inside its own box. Along, because a railroad that
   wrapped would be claiming the track goes back to the left; down, because a deep
   alternation is legitimately tall and shrinking it to fit would make every box unreadable
   rather than making the pattern simpler. */
.rf-rail[b-eurjz7ton8] {
    flex: 1 1 0;
    min-width: 0;
    overflow: auto;
    border-right: 1px solid var(--rf-border-soft);
}

/* The explanation is a column of prose and does not want the width - it wants to be beside
   the diagram, so that hovering one lights the other without either moving. */
.rf-ex[b-eurjz7ton8] {
    flex: none;
    width: 27rem;
    max-width: 42%;
    min-width: 0;
    overflow: auto;
    background: var(--rf-pane-alt);
}

.rf-run[b-eurjz7ton8] {
    flex: 2 1 0;
    min-height: 8rem;
    --pane-hue: var(--rf-accent);
    border-top: 1px solid var(--rf-border);
}

.rf-run-body[b-eurjz7ton8] {
    flex: 1;
    min-height: 0;
    display: flex;
}

/* The text and the answer side by side rather than stacked, because what a reader is doing
   here is changing one and watching the other. Stacked, one of them is always off screen at
   the moment it changes. */
.rf-subject[b-eurjz7ton8] {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    border-right: 1px solid var(--rf-border-soft);
}

.rf-answer[b-eurjz7ton8] {
    flex: 1 1 0;
    min-width: 0;
    overflow: auto;
    background: var(--rf-pane-alt);
}

/* ── Status bar ───────────────────────────────────────────────────────────────── */

.statusbar[b-eurjz7ton8] {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex: none;
    padding: 0.25rem 0.75rem;
    background: var(--rf-chrome);
    border-top: 1px solid var(--rf-border);
    color: var(--rf-muted);
    font-size: 0.6875rem;
}

/* The pattern in the shape most languages write it, slashes and all - so what is on screen
   can be read straight across into code. */
.statusbar-item[b-eurjz7ton8] {
    min-width: 0;
    overflow: hidden;
    font-variant-numeric: tabular-nums;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.statusbar-spacer[b-eurjz7ton8] {
    flex: 1;
}

.statusbar-note[b-eurjz7ton8] {
    min-width: 0;
    overflow: hidden;
    color: var(--rf-faint);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Something the user asked for did not happen. Muted rather than red: nothing on screen is
   wrong, there is just another way to get at it. */
.statusbar-warn[b-eurjz7ton8] {
    min-width: 0;
    overflow: hidden;
    color: var(--rf-text);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Narrow screens ───────────────────────────────────────────────────────────── */

@media (max-width: 86.39rem) {
    .rf-ex[b-eurjz7ton8] {
        width: 22rem;
    }
}

@media (max-width: 76.79rem) {
    .statusbar-note[b-eurjz7ton8] {
        display: none;
    }
}

/* Below about a tablet the page scrolls rather than the panes: nothing divides a fixed
   height any more, so every band is as tall as what is in it, and the two side-by-side
   splits become stacked. */
@media (max-width: 63.99rem) {
    .rf-shape[b-eurjz7ton8],
    .rf-run[b-eurjz7ton8] {
        flex: none;
        min-height: 0;
    }

    .rf-shape-body[b-eurjz7ton8],
    .rf-run-body[b-eurjz7ton8] {
        flex-direction: column;
    }

    .rf-rail[b-eurjz7ton8] {
        max-height: 60vh;
        border-right: 0;
        border-bottom: 1px solid var(--rf-border-soft);
    }

    .rf-ex[b-eurjz7ton8] {
        width: auto;
        max-width: none;
        overflow: visible;
    }

    .rf-subject[b-eurjz7ton8] {
        min-height: 9rem;
        border-right: 0;
        border-bottom: 1px solid var(--rf-border-soft);
    }

    .rf-answer[b-eurjz7ton8] {
        min-height: 12rem;
        overflow: visible;
    }

    /* The page itself scrolls here, and a small box that scrolls inside a page that scrolls
       is worse to use than one that grows - especially under a thumb. It keeps its floor, so
       the common case of a finding appearing still moves nothing. */
    .rf-read[b-eurjz7ton8] {
        height: auto;
        min-height: 4.75rem;
        overflow-y: visible;
    }

    /* One line that scrolls sideways, rather than four lines of chips pushing the diagram
       off the first screen. */
    .rf-presets[b-eurjz7ton8] {
        flex-wrap: nowrap;
        overflow-x: auto;
        padding-bottom: 0.25rem;
    }
}
