/* /Common/Components/Actions/ActionDetailOverlay.razor.rz.scp.css */
/* Width and content padding are Modal's now — this overlay asks for them with
   Size="ModalSize.Compact" PadContent="false" instead of reaching past the owner.

   Overlay never prints (was a dead .compare-page .action-detail-dialog rule
   in CompareLayout.razor.css — wrong scope). */
@media print {
    [b-zaneg5zuka] .modal-dialog--compact {
        display: none !important;
    }
}

.action-detail-content[b-zaneg5zuka] {
    padding: 1rem;
}

.action-detail-meta[b-zaneg5zuka] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.75rem;
}

.action-meta-tag[b-zaneg5zuka] {
    background: var(--card-actions-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.15rem 0.5rem;
    font-size: 0.85rem;
    color: var(--text-color);
}

.action-detail-description[b-zaneg5zuka] {
    color: var(--text-color);
    line-height: 1.5;
    margin: 0;
}
/* /Common/Components/Actions/ActionRow.razor.rz.scp.css */
/* No `.action-name-field` rule: the name row is a <FormField>, so the div is
   FormField's and a rule here matched nothing. It asks for
   `form-group--grow` now — the variant lives with the element. */
/* /Common/Components/Actions/ContentActionPanel.razor.rz.scp.css */
/* .action-nav-strip/.action-primary-strip moved to DetailToolbar.razor.css —
   this component renders .action-strip, never those two. */
/* ── Action Panel: Combined Strip ── */
.action-strip[b-042d2r89y8] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
    flex-wrap: wrap;
}

/* .action-group moved to ActionGroup.razor.css (rung 2): this component and
   DetailToolbar both defined it identically, and both render the component now. */

/* ── Layout Strip (Row 3) ── */
.action-layout-strip[b-042d2r89y8] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
    flex-wrap: wrap;
}

/* Moved from the former StatBlockToolbar.razor.css: this component renders the
   fieldset, so the rules never matched from there (they were written as
   `.stat-block-toolbar .layout-toggle`, and the subject element is ours). */
.layout-toggle[b-042d2r89y8] {
    display: flex;
    gap: 0.75rem;
    align-items: center;
}

.layout-toggle label[b-042d2r89y8] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    cursor: pointer;
    font-family: var(--font-body);
    color: var(--text-color);
    font-size: 0.875rem;
}

.layout-toggle input[type="radio"][b-042d2r89y8] {
    cursor: pointer;
    accent-color: var(--radio-accent);
}

/* ── Queue Button / Badge ── */
.queue-btn[b-042d2r89y8] {
    position: relative;
}

.queue-badge[b-042d2r89y8] {
    position: absolute;
    top: -0.375rem;
    right: -0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.25rem;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1;
    border-radius: 999px;
    background-color: var(--radio-accent);
    color: var(--on-primary-text);
}
/* /Common/Components/Actions/FoePreviewOverlay.razor.rz.scp.css */
/* Modal chrome (.modal-backdrop/.modal-dialog/.preview-header/.preview-close-btn)
   is owned by Modal.razor, and so is the tall scrolling shape this overlay used
   to impose through ::deep: it asks for Size="ModalSize.Preview" PadContent="false".
   Only the preview's own content box lives here. */

.preview-content[b-lbzbrnsz3a] {
    overflow-y: auto;
    padding: 1rem;
    flex: 1;
}

.detail-link[b-lbzbrnsz3a] {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.5rem;
    color: var(--text-muted);
    border-radius: 4px;
}

.detail-link:hover[b-lbzbrnsz3a] {
    color: var(--text-color);
    background: var(--card-actions-bg);
}
/* /Common/Components/Actions/ListToolbar.razor.rz.scp.css */
/* A list page's quiet tool row under its heading: btn-nav-link links, wrapping at
   phone width. The negative margins cancel the links' own padding so the first icon
   lines up with the h1 and the text sits evenly between heading and presets. */
.list-tools[b-o1llnu3b7c] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin: 0.5rem 0 -0.5rem -0.6rem;
}

/* touch-target-min sets min-height on the content box; border-box keeps the link at 44px. */
.list-tool[b-o1llnu3b7c] {
    box-sizing: border-box;
}
/* /Common/Components/Collections/AddToCollectionModal.razor.rz.scp.css */
/* ── Add-to-Collection modal ── */
[b-ju2d2bky16] .collection-modal {
    max-width: 420px;
    width: 90%;
}

.collection-modal-header[b-ju2d2bky16] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
}

.collection-modal-header h4[b-ju2d2bky16] {
    margin: 0;
    font-family: var(--font-header);
    color: var(--text-color);
    font-size: 1.1rem;
}

.collection-modal-close[b-ju2d2bky16] {
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-muted);
    padding: 0 0.25rem;
    border-radius: 4px;
    transition: color 0.15s, background 0.15s;
}

.collection-modal-close:hover[b-ju2d2bky16] {
    color: var(--text-color);
    background: var(--editor-highlight-bg);
}

/* ── Modal: collection option list ── */
.collection-options[b-ju2d2bky16] {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin-bottom: 1rem;
    max-height: 280px;
    overflow-y: auto;
}

.collection-option[b-ju2d2bky16] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--card-border);
    border-radius: 6px;
    background: var(--card-bg);
    transition: background 0.15s;
}

.collection-option:hover[b-ju2d2bky16] {
    background: var(--editor-highlight-bg);
}

.collection-option--active[b-ju2d2bky16] {
    border-color: var(--accent-color);
    background: color-mix(in srgb, var(--accent-color) 10%, var(--card-bg));
}

.collection-option-name[b-ju2d2bky16] {
    flex: 1;
    font-size: 0.95rem;
    color: var(--text-color);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Modal: new collection inline form ── */
/* The button row is the shared <ButtonRow> component now. */

.collection-new-form[b-ju2d2bky16] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem;
    background: var(--editor-highlight-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    margin-top: 0.5rem;
}

.collection-new-btn[b-ju2d2bky16] {
    width: 100%;
    margin-top: 0.25rem;
}
/* /Common/Components/CombatProfile/PowerModifierEditor.razor.rz.scp.css */
.power-modifier-suggestion[b-2vpacdut3t] {
    margin-top: 0.5rem;
}
/* /Common/Components/CombatProfile/SignalBadgeRow.razor.rz.scp.css */
/* Moved out of an inline <style> block in SignalBadgeRow.razor (see
   SignalEditor.razor.css). Every class is rendered here — rung 1. */

.signal-badge-row[b-tradityl3l] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
}

.signal-badge[b-tradityl3l] {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.625rem;
    border: 1px solid var(--card-border);
    border-radius: 999px;
    background: var(--card-bg);
    color: var(--text-color);
    font-size: 0.78rem;
    font-weight: 500;
    line-height: 1.4;
    cursor: help;
    transition: border-color 0.15s ease, background-color 0.15s ease;
    outline: none;
}

.signal-badge:hover[b-tradityl3l],
.signal-badge:focus-visible[b-tradityl3l] {
    border-color: var(--accent-color);
    background: var(--editor-highlight-bg);
}

.signal-badge-tooltip[b-tradityl3l] {
    position: absolute;
    bottom: calc(100% + 0.4rem);
    left: 50%;
    transform: translateX(-50%) scale(0.92);
    z-index: 10;
    min-width: max-content;
    max-width: 16rem;
    padding: 0.35rem 0.6rem;
    border-radius: 0.35rem;
    background: var(--card-border);
    color: var(--color-white);
    font-size: 0.72rem;
    font-weight: 400;
    line-height: 1.3;
    text-align: center;
    white-space: normal;
    word-break: keep-all;
    overflow-wrap: anywhere;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.signal-badge:hover .signal-badge-tooltip[b-tradityl3l],
.signal-badge:focus .signal-badge-tooltip[b-tradityl3l],
.signal-badge:active .signal-badge-tooltip[b-tradityl3l] {
    opacity: 1;
    transform: translateX(-50%) scale(1);
}

.signal-icon[b-tradityl3l] {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
}

.signal-label[b-tradityl3l] {
    white-space: normal;
    word-break: keep-all;
    overflow-wrap: anywhere;
}

@media (min-width: 641px) {
    .signal-badge[b-tradityl3l] {
        padding: 0.25rem 0.7rem;
        font-size: 0.8rem;
    }

    .signal-icon[b-tradityl3l] {
        width: 1.05rem;
        height: 1.05rem;
    }
}
/* /Common/Components/CombatProfile/SignalEditor.razor.rz.scp.css */
/* Moved out of an inline <style> block in SignalEditor.razor: that markup emits
   a global, unscoped stylesheet once per component instance. Every class below
   is rendered by this component's own template (ladder rung 1). */

.signal-editor[b-5z91a64vvt] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.signal-editor-row--custom[b-5z91a64vvt] {
    border-left: 3px solid var(--accent-color);
    padding-left: 0.5rem;
}

.signal-editor-indicator[b-5z91a64vvt] {
    color: var(--accent-color);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

@media (min-width: 641px) {
    .signal-editor[b-5z91a64vvt] {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    }
}
/* /Common/Components/CombatProfile/StaleBadge.razor.rz.scp.css */
/* Moved out of an inline <style> block in StaleBadge.razor (see
   SignalEditor.razor.css). All three classes are rendered here — rung 1. */

.stale-badge[b-0c8sec7q7n] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.stale-badge-pill[b-0c8sec7q7n] {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.625rem;
    border: 1px solid var(--color-gold);
    border-radius: 999px;
    background: var(--editor-highlight-bg);
    color: var(--color-gold);
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1.4;
    white-space: nowrap;
}

.stale-badge-refresh[b-0c8sec7q7n] {
    padding: 0.25rem 0.625rem;
    border: 1px solid var(--card-border);
    border-radius: 0.25rem;
    background: var(--card-bg);
    color: var(--text-color);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.4;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.stale-badge-refresh:hover[b-0c8sec7q7n] {
    border-color: var(--color-gold);
    background: var(--editor-highlight-bg);
    color: var(--color-gold);
}

@media (min-width: 641px) {
    .stale-badge[b-0c8sec7q7n] {
        flex-wrap: nowrap;
    }

    .stale-badge-pill[b-0c8sec7q7n],
    .stale-badge-refresh[b-0c8sec7q7n] {
        font-size: 0.8rem;
    }
}
/* /Common/Components/CombatProfile/TacticalDirective.razor.rz.scp.css */
/* Moved out of an inline <style> block in TacticalDirective.razor (see
   SignalEditor.razor.css). The stat-block cards render <TacticalDirective>
   rather than hand-rolling `.tactical-directive`, so the class has one owner
   and the cards' own sizing reaches it with ::deep (rung 3). */

/* No `color` here on purpose: the directive inherits it. On the hub/detail pages
   that inherits `--text-color` from the page, which is what the old rule spelled
   out; inside a stat-block card it inherits the card's own ink (`.foe-card-frame`
   sets #1a1a1a on cream). Declaring `var(--text-color)` washed the print card's
   line out to near-invisible — the old inline <style> block hid that, because it
   only reached the DOM when a TacticalDirective instance was rendered, and the
   card hand-rolled the div instead. */
.tactical-directive[b-d8h9di3hze] {
    display: block;
    font-size: 0.92rem;
    line-height: 1.4;
    white-space: nowrap;
    text-wrap: wrap;
}

.tactics-separator[b-d8h9di3hze] {
    opacity: 0.8;
    margin: 0 0.2em;
}

.tactics-text[b-d8h9di3hze] {
    font-weight: 400;
}

/* Same reasoning as above: the print variant inherits its ink from the sheet it
   is printed on, and the role word inherits from the directive. */
.tactical-directive-print[b-d8h9di3hze] {
    white-space: normal;
}

@media (min-width: 641px) {
    .tactical-directive[b-d8h9di3hze] {
        font-size: 1rem;
    }
}

/* ── Stat-block sizing (driven by the Compact parameter, ladder rung 1) ──
   Reclaimed from MonsterContent.razor.css and AdversaryContent.razor.css, which
   both shrank the directive inside `.tactical-signals-section` through ::deep
   and so took font-size and line-height off this file on every card.

   The two systems disagreed, and the disagreement is real: D&D's card pins the
   line at 0.85rem, Daggerheart's lets it take the card's own 12pt. That is one
   variant with a handed-down size, not two ::deep rules — AdversaryContent sets
   --tactical-directive-size: 1em on the section it renders.

   Placed after the @media block on purpose: both selectors are (0,1,0), so
   source order is what keeps 1rem from winning back above 641px. */
.tactical-directive--compact[b-d8h9di3hze] {
    font-size: var(--tactical-directive-size, 0.85rem);
    line-height: 1.3;
}
/* /Common/Components/CombatProfile/TacticalRoleEditor.razor.rz.scp.css */

.role-suggestion-chips[b-8ejp7riw99] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
/* /Common/Components/ContentSearchPreview.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentSearchPreview.razor.css — scoped styles
   Dissolved from wwwroot/css/foe-list.css
   ═══════════════════════════════════════════ */

.search-preview-wrapper[b-ufzr8xsqj7] {
    position: relative;
    flex: 1;
    max-width: 400px;
}

/* The panel shell (.multiselect-panel) is owned by DropdownPanel (rung 2);
   only this component's size/scroll overrides stay here. The wrapper prefix
   keeps (0,3,0) over DropdownPanel's own (0,2,0) rule regardless of bundle
   order. */
.search-preview-wrapper[b-ufzr8xsqj7]  .search-preview-panel {
    width: 100%;
    min-width: 240px;
    max-height: 320px;
    overflow-y: auto;
}

.search-preview-options[b-ufzr8xsqj7] {
    display: flex;
    flex-direction: column;
}

.search-preview-item[b-ufzr8xsqj7] {
    display: block;
    padding: 0.6rem 0.75rem;
    color: var(--text-color);
    text-decoration: none;
    border-bottom: 1px solid var(--card-border);
    transition: background-color 0.15s;
}

.search-preview-item:hover[b-ufzr8xsqj7],
.search-preview-item:focus[b-ufzr8xsqj7] {
    background: var(--hover-bg);
}

.search-preview-item:last-child[b-ufzr8xsqj7] {
    border-bottom: none;
}

.search-preview-title[b-ufzr8xsqj7] {
    font-size: 0.9rem;
    font-family: var(--font-body);
}

.search-preview-loading[b-ufzr8xsqj7],
.search-preview-empty[b-ufzr8xsqj7] {
    padding: 0.75rem;
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}

@media (max-width: 768px) {
    .search-preview-wrapper[b-ufzr8xsqj7] {
        max-width: none;
    }
}
/* /Common/Components/CrSuggestionPanel.razor.rz.scp.css */
/* The panel box is the shared <InsetPanel> (rung 2): this file and
   EncounterAssessmentPanel stated the same five declarations under two names. */

.cr-suggestion-placeholder[b-p04iu2oe90] {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin: 0;
}

.cr-suggestion-values[b-p04iu2oe90] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    margin-bottom: 0.5rem;
}

.cr-suggestion-item[b-p04iu2oe90] {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.cr-suggestion-label[b-p04iu2oe90] {
    font-size: 0.75rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.cr-suggestion-value[b-p04iu2oe90] {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-color);
}

.cr-suggestion-item--suggested .cr-suggestion-value[b-p04iu2oe90] {
    color: var(--accent-color);
}

.cr-suggestion-meta[b-p04iu2oe90] {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 0.5rem;
}

.cr-suggestion-apply[b-p04iu2oe90] {
    width: fit-content;
}

.cr-suggestion-partial-note[b-p04iu2oe90] {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin: 0.25rem 0;
    font-style: italic;
}
/* /Common/Components/Display/ContentAttribution.razor.rz.scp.css */
.content-attribution-url[b-7soiva2tz6] {
    display: block;
}

.content-attribution--muted a[b-7soiva2tz6] {
    color: var(--text-muted);
    text-decoration: underline;
}
/* /Common/Components/Display/ContentConnectionsHubCard.razor.rz.scp.css */
/* Reclaimed from EntityHub's `::deep .linked-foes-list` (rung 3 -> rung 1): the
   chip row is this component's own markup now, so the hub no longer reaches it. */
.linked-foes-list[b-tg0cn8nzha] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
/* /Common/Components/Display/ContentPortrait.razor.rz.scp.css */
/* The frame. Its glyph arrives as the inline --portrait-glyph (an url()); every
   modifier below only sets the custom properties the parts read. The frame keeps
   the box an uploaded picture will fill; the marks sit on it, outside the picture. */
.content-portrait[b-g173jh1n2b] {
    --portrait-size: 64px;
    --portrait-scale: 0.75;
    --portrait-rim: var(--card-border);
    --portrait-rim-width: 1px;
    --portrait-ink: var(--text-color);
    position: relative;
    display: inline-block;
    flex: 0 0 auto;
    inline-size: var(--portrait-size);
    block-size: var(--portrait-size);
    border: var(--portrait-rim-width) solid var(--portrait-rim);
    border-radius: 20%;
    background: var(--bg-input);
    /* The marks grow with the frame, capped so they stay chips on the large slots. */
    font-size: min(calc(var(--portrait-size) * 0.22), 0.9rem);
    line-height: 1;
}

.content-portrait--inline[b-g173jh1n2b] {
    --portrait-size: 44px;
}

.content-portrait--hero[b-g173jh1n2b] {
    --portrait-size: 72px;
}

@media (min-width: 769px) {
    .content-portrait--card[b-g173jh1n2b] {
        --portrait-size: 96px;
    }

    .content-portrait--hero[b-g173jh1n2b] {
        --portrait-size: 160px;
    }
}

/* Card size: a round plate in an ink ring with a paper halo; the rank sets the
   ring weight, the tone sets the ring colour. */
.content-portrait--card[b-g173jh1n2b] {
    --portrait-rim: var(--text-color);
    --portrait-rim-width: 2px;
    border-radius: 50%;
    box-shadow: 0 0 0 3px var(--bg-input), 0 0 0 4px rgba(var(--line-rgb), 0.5);
}

/* The picture: fills the frame and clips like an `object-fit: cover` image would. */
.portrait-picture[b-g173jh1n2b] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: inherit;
}

/* ─── Scale: how much of the box's height the glyph fills (a monster's size) ─── */
.content-portrait--scale-tiny[b-g173jh1n2b] { --portrait-scale: 0.45; }
.content-portrait--scale-small[b-g173jh1n2b] { --portrait-scale: 0.6; }
.content-portrait--scale-large[b-g173jh1n2b] { --portrait-scale: 0.88; }
.content-portrait--scale-huge[b-g173jh1n2b] { --portrait-scale: 1; }
/* Larger than the box: cropped by the picture layer, as a close-up photo would be. */
.content-portrait--scale-gargantuan[b-g173jh1n2b] { --portrait-scale: 1.25; }

.portrait-glyph[b-g173jh1n2b] {
    flex: none;
    block-size: calc(100% * var(--portrait-scale));
    aspect-ratio: 1;
    background-color: var(--portrait-ink);
    -webkit-mask-image: var(--portrait-glyph);
    mask-image: var(--portrait-glyph);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* Cluster (swarm, horde): the glyph three times, smaller, two in front and one behind. */
.content-portrait--cluster .portrait-glyph[b-g173jh1n2b] {
    -webkit-mask-image: var(--portrait-glyph), var(--portrait-glyph), var(--portrait-glyph);
    mask-image: var(--portrait-glyph), var(--portrait-glyph), var(--portrait-glyph);
    -webkit-mask-position: 0 100%, 100% 100%, 50% 0;
    mask-position: 0 100%, 100% 100%, 50% 0;
    -webkit-mask-size: 55%, 55%, 55%;
    mask-size: 55%, 55%, 55%;
}

/* ─── Rank: the rim by band (CR band, tier, level range), gold at the top ─── */
.content-portrait--rank-1[b-g173jh1n2b] {
    --portrait-rim-width: 2px;
}

.content-portrait--rank-2[b-g173jh1n2b] {
    --portrait-rim: var(--color-copper);
    --portrait-rim-width: 2px;
}

.content-portrait--rank-3[b-g173jh1n2b] {
    --portrait-rim: var(--color-gold-dark);
    --portrait-rim-width: 3px;
}

.content-portrait--rank-4[b-g173jh1n2b] {
    --portrait-rim: var(--color-gold);
    --portrait-rim-width: 4px;
}

/* ─── Tone: an NPC's or faction's attitude, in the difficulty badges' status colours ─── */
.content-portrait--tone-hostile[b-g173jh1n2b] {
    --portrait-rim: var(--difficulty-hard-bar);
    --portrait-rim-width: 2px;
}

.content-portrait--tone-indifferent[b-g173jh1n2b] {
    --portrait-rim: var(--color-warning);
    --portrait-rim-width: 2px;
}

.content-portrait--tone-friendly[b-g173jh1n2b] {
    --portrait-rim: var(--color-success);
    --portrait-rim-width: 2px;
}

/* ─── Corner marks: solid chips, readable over any picture ─── */
.portrait-badge[b-g173jh1n2b] {
    position: absolute;
    inset-block-end: -0.35em;
    inset-inline-end: -0.35em;
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: min(calc(var(--portrait-size) * 0.42), 2.5rem);
    block-size: min(calc(var(--portrait-size) * 0.42), 2.5rem);
    border: 1px solid var(--portrait-rim);
    border-radius: 50%;
    background: var(--card-bg);
}

.portrait-badge[b-g173jh1n2b]::before {
    content: "";
    inline-size: 70%;
    block-size: 70%;
    background-color: var(--text-color);
    -webkit-mask: var(--portrait-badge) center / contain no-repeat;
    mask: var(--portrait-badge) center / contain no-repeat;
}

.portrait-count[b-g173jh1n2b] {
    position: absolute;
    inset-block-start: -0.4em;
    inset-inline-end: -0.4em;
    padding: 0.15em 0.3em;
    border-radius: 0.6em;
    background: var(--accent-color);
    color: var(--on-accent-text);
    font-family: var(--font-header);
    font-weight: 700;
    white-space: nowrap;
}

.portrait-pips[b-g173jh1n2b] {
    position: absolute;
    inset-block-end: 0.3em;
    inset-inline-start: 50%;
    display: flex;
    gap: 0.25em;
    padding: 0.2em 0.3em;
    border-radius: 0.6em;
    background: var(--card-bg);
    transform: translateX(-50%);
}

.portrait-pip[b-g173jh1n2b] {
    inline-size: 0.5em;
    block-size: 0.5em;
    border-radius: 50%;
    background: var(--portrait-ink);
}
/* /Common/Components/Display/CreatorBadge.razor.rz.scp.css */
.creator-badge[b-tlecfn4ouk] {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: normal;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

/* Pill styling when rendered inside a card footer (the .card-footer-creator
   wrapper is CardContent's markup; the span here carries this file's scope). */
.card-footer-creator .creator-badge[b-tlecfn4ouk] {
    background: var(--filter-tag-bg);
    color: var(--filter-tag-color);
    padding: 0.2rem 0.5rem;
    border-radius: 4px;
    font-size: 0.75rem;
    font-family: var(--font-header);
    white-space: nowrap;
}

/* The inline tier chip is TierBadge (Compact) now — it owns the geometry and
   the tier colour table that used to be duplicated here and in
   AuthStatus.razor.css. */
/* /Common/Components/Display/CrossLinkSection.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CrossLinkSection.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)

   .linked-foe-backlink-toggle deliberately stays in base.css: the Monster/
   Adversary LinkedFoesSection components render it too, so it is genuine
   multi-renderer (rung 4) debt, not this component's to own.
   ═══════════════════════════════════════════ */

.linked-foe-search-results[b-tzbsf910b9] {
    border: 1px solid var(--card-border);
    border-radius: 6px;
    overflow: hidden;
    margin-top: 0.5rem;
    margin-bottom: 1rem;
}

.linked-foe-result[b-tzbsf910b9] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--card-border);
    background: var(--card-bg);
}

.linked-foe-result:last-child[b-tzbsf910b9] {
    border-bottom: none;
}

.linked-foe-result:hover[b-tzbsf910b9] {
    background: var(--editor-highlight-bg);
}

.linked-foe-result-name[b-tzbsf910b9] {
    color: var(--text-color);
    font-size: 0.9rem;
}

.linked-foe-result-name small[b-tzbsf910b9] {
    color: var(--text-muted);
    margin-left: 0.5rem;
}

.cross-link-message[b-tzbsf910b9] {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-top: 0.5rem;
}

@media screen and (max-width: 768px) {
    .linked-foe-result[b-tzbsf910b9] { display: flex; gap: 0.5rem; align-items: center; }
    .linked-foe-result-name[b-tzbsf910b9] { flex: 1; min-width: 0; overflow-wrap: break-word; word-break: break-word; }
}
/* /Common/Components/Display/ExternalCreditLine.razor.rz.scp.css */
.external-credit[b-5z08dz20l9] {
    margin: 0.25rem 0 0;
    font-size: 0.9rem;
    color: var(--text-muted);
    overflow-wrap: anywhere;
}

.external-credit-name[b-5z08dz20l9],
.external-credit a[b-5z08dz20l9] {
    font-weight: 600;
    color: var(--text-color);
}

.external-credit a[b-5z08dz20l9] {
    text-decoration: underline;
    text-decoration-color: var(--accent-color);
    text-underline-offset: 0.15em;
}

.external-credit a:hover[b-5z08dz20l9],
.external-credit a:focus-visible[b-5z08dz20l9] {
    color: var(--accent-color);
}
/* /Common/Components/Display/FeaturedAvailabilityBadge.razor.rz.scp.css */
/* The icon is the icon component's own <svg>, not this component's element, so
   these rules reach it with ::deep (rung 3). Written bare, they compiled
   against this component's scope id, matched nothing, and the icon rendered
   at its default size. */
.featured-availability-badge[b-ytkku3z8ed] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-height: 1.375rem;
    font-size: 0.75rem;
    line-height: 1;
    font-weight: 600;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    background-color: color-mix(in srgb, var(--color-warning) 18%, transparent);
    color: var(--warning-ink, var(--color-warning));
    border: 1px solid color-mix(in srgb, var(--color-warning) 45%, transparent);
    white-space: nowrap;
    animation: featured-pulse-b-ytkku3z8ed 2.5s ease-in-out infinite;
}

.featured-availability-badge[b-ytkku3z8ed]  .featured-availability-badge__icon {
    flex: none;
    width: 0.875rem;
    height: 0.875rem;
    fill: currentColor;
}

@media (prefers-reduced-motion: reduce) {
    .featured-availability-badge[b-ytkku3z8ed] {
        animation: none;
    }
}

@keyframes featured-pulse-b-ytkku3z8ed {
    0%, 100% {
        box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-warning) 40%, transparent);
    }
    50% {
        box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--color-warning) 0%, transparent);
    }
}
/* /Common/Components/Display/InfoComponent.razor.rz.scp.css */
.info-component[b-kwklu1yyvz] {
    border: 1px solid var(--card-border);
    border-radius: 6px;
    background: var(--card-bg);
    overflow: hidden;
}

.info-header[b-kwklu1yyvz] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.15s;
}

.info-header:hover[b-kwklu1yyvz] {
    background: var(--editor-highlight-bg);
}

.info-header:active[b-kwklu1yyvz] {
    background: var(--accent-color);
}

.info-icon[b-kwklu1yyvz] {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--accent-color);
    color: var(--on-accent-text);
    font-size: 0.85rem;
    font-weight: 600;
}

.info-title[b-kwklu1yyvz] {
    flex: 1;
    font-weight: 500;
    color: var(--text-color);
    font-size: 0.9rem;
}

.info-toggle-indicator[b-kwklu1yyvz] {
    flex-shrink: 0;
    font-weight: 600;
    color: var(--text-muted);
    font-size: 1.1rem;
    width: 18px;
    text-align: center;
}

.info-content[b-kwklu1yyvz] {
    max-height: 500px;
    overflow: hidden;
    transition: max-height 0.3s ease-out;
    padding: 0 0.75rem;
}

.info-component.collapsed .info-content[b-kwklu1yyvz] {
    max-height: 0;
    padding: 0;
}

.info-content p[b-kwklu1yyvz],
.info-content ul[b-kwklu1yyvz],
.info-content table[b-kwklu1yyvz] {
    margin-bottom: 0.6rem;
}

.info-content p[b-kwklu1yyvz] {
    margin: 0.4rem 0;
    font-size: 0.875rem;
    color: var(--text-color);
    line-height: 1.5;
}

.info-content h4[b-kwklu1yyvz] {
    margin: 0.6rem 0 0.3rem;
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.info-content strong[b-kwklu1yyvz] {
    color: var(--text-color);
}
/* /Common/Components/Display/MultilineText.razor.rz.scp.css */
/* Newlines become line breaks; runs of spaces still collapse as in normal text. */
.multiline-text[b-buu34h4k9c] {
    white-space: pre-line;
}
/* /Common/Components/Display/PortraitHeading.razor.rz.scp.css */
/* The portrait keeps its own size (ContentPortrait owns it); the block takes the rest of the row
   and may shrink, so a long name wraps beside the portrait instead of pushing it onto a row of its own. */
.portrait-heading[b-yp7l7fq3yk] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.portrait-heading-block[b-yp7l7fq3yk] {
    flex: 1 1 auto;
    min-inline-size: 0;
}

@media (min-width: 769px) {
    .portrait-heading[b-yp7l7fq3yk] {
        gap: 1.25rem;
    }
}
/* /Common/Components/Display/QrCodeImage.razor.rz.scp.css */
.qr-code[b-6cjii27ero] {
    display: block;
    flex: none;
    width: 7rem;
    height: 7rem;
    background: white;
}
/* /Common/Components/Display/TierBadge.razor.rz.scp.css */
/* Patreon tier badge. Owns both the markup and these rules (ladder rung 2):
   AuthStatus and CreatorBadge each carried their own copy of the tier colour
   table, with three of the five values identical and hardcoded in both files. */

.tier-badge[b-fhun7nbx11] {
    font-size: 0.75rem;
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.tier-free[b-fhun7nbx11] {
    background: var(--tier-badge-free-bg);
    color: var(--tier-badge-free-text);
}

.tier-supporter[b-fhun7nbx11] {
    background: var(--tier-badge-supporter-bg);
    color: var(--tier-badge-supporter-text);
}

.tier-curator[b-fhun7nbx11] {
    background: var(--tier-badge-curator-bg);
    color: var(--tier-badge-curator-text);
}

.tier-insider[b-fhun7nbx11] {
    background: var(--tier-badge-insider-bg);
    color: var(--tier-badge-insider-text);
}

.tier-creator[b-fhun7nbx11] {
    background: var(--tier-badge-creator-bg);
    color: var(--tier-badge-creator-text);
}

/* ── Compact variant (rendered inline inside CreatorBadge) ── */

.tier-badge--compact[b-fhun7nbx11] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.6rem;
    padding: 0.1rem 0.3rem;
    border-radius: 3px;
    font-weight: 600;
    line-height: 1;
}

/* The compact creator badge keeps the muted gold treatment it shipped with,
   rather than the standard badge's purple gradient. */
.tier-badge--compact.tier-creator[b-fhun7nbx11] {
    background: color-mix(in srgb, var(--color-warning) 18%, transparent);
    color: var(--color-warning);
    border: 1px solid color-mix(in srgb, var(--color-warning) 45%, transparent);
}

/* ::deep: the icon is slotted in by the caller, so it carries the caller's
   scope id, not ours (rung 3). */
[b-fhun7nbx11] .tier-badge__icon {
    flex: none;
    width: 1rem;
    height: 1rem;
    object-fit: contain;
}
/* /Common/Components/Display/TooltipMarker.razor.rz.scp.css */
/* Tooltip Marker Component Styles */
.tooltip-marker[b-wgrsn1hcpm] {
    position: absolute;
    z-index: 100;
}

.marker-badge[b-wgrsn1hcpm] {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--color-gold);
    color: var(--on-primary-text);
    font-weight: 700;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: help;
    box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.3);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    border: 2px solid rgba(var(--highlight-rgb), 0.3);
}

.marker-badge:hover[b-wgrsn1hcpm] {
    transform: scale(1.15);
    box-shadow: 0 4px 12px rgba(var(--shadow-rgb), 0.4);
}

/* Tooltip content - hidden by default */
.tooltip-content[b-wgrsn1hcpm] {
    position: absolute;
    min-width: 200px;
    max-width: 280px;
    padding: 10px 12px;
    background: var(--nav-bg);
    color: var(--nav-text);
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.4);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
    pointer-events: none;
    z-index: 1000;
    font-size: 0.9rem;
    line-height: 1.4;
}

.tooltip-marker:hover .tooltip-content[b-wgrsn1hcpm] {
    opacity: 1;
    visibility: visible;
}

.tooltip-title[b-wgrsn1hcpm] {
    font-weight: 700;
    font-size: 0.95rem;
    margin-bottom: 4px;
    /* --marker-title-color lets a host re-tint the title without reaching in:
       the admin guide sets it on its Daggerheart theme wrapper, where the title
       runs gold. It used to take `color` off this file with
       `.guide-page.dh-theme ::deep .tooltip-title`. */
    color: var(--marker-title-color, var(--nav-border));
}

.tooltip-description[b-wgrsn1hcpm] {
    color: var(--nav-text);
    font-size: 0.85rem;
}

/* Position: top (tooltip appears above marker) */
.tooltip-top .tooltip-content[b-wgrsn1hcpm] {
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(5px);
}

.tooltip-top:hover .tooltip-content[b-wgrsn1hcpm] {
    transform: translateX(-50%) translateY(0);
}

.tooltip-top .tooltip-content[b-wgrsn1hcpm]::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 8px solid transparent;
    border-top-color: var(--nav-bg);
}

/* Position: bottom (tooltip appears below marker) */
.tooltip-bottom .tooltip-content[b-wgrsn1hcpm] {
    top: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(-5px);
}

.tooltip-bottom:hover .tooltip-content[b-wgrsn1hcpm] {
    transform: translateX(-50%) translateY(0);
}

.tooltip-bottom .tooltip-content[b-wgrsn1hcpm]::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 8px solid transparent;
    border-bottom-color: var(--nav-bg);
}

/* Position: left (tooltip appears to the left of marker) */
.tooltip-left .tooltip-content[b-wgrsn1hcpm] {
    right: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%) translateX(5px);
}

.tooltip-left:hover .tooltip-content[b-wgrsn1hcpm] {
    transform: translateY(-50%) translateX(0);
}

.tooltip-left .tooltip-content[b-wgrsn1hcpm]::after {
    content: '';
    position: absolute;
    left: 100%;
    top: 50%;
    transform: translateY(-50%);
    border: 8px solid transparent;
    border-left-color: var(--nav-bg);
}

/* Position: right (tooltip appears to the right of marker) */
.tooltip-right .tooltip-content[b-wgrsn1hcpm] {
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%) translateX(-5px);
}

.tooltip-right:hover .tooltip-content[b-wgrsn1hcpm] {
    transform: translateY(-50%) translateX(0);
}

.tooltip-right .tooltip-content[b-wgrsn1hcpm]::after {
    content: '';
    position: absolute;
    right: 100%;
    top: 50%;
    transform: translateY(-50%);
    border: 8px solid transparent;
    border-right-color: var(--nav-bg);
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .tooltip-content[b-wgrsn1hcpm] {
        min-width: 160px;
        max-width: 220px;
        font-size: 0.85rem;
    }

    .marker-badge[b-wgrsn1hcpm] {
        width: 20px;
        height: 20px;
        font-size: 0.75rem;
    }
}
/* /Common/Components/Editing/BacklinkToggle.razor.rz.scp.css */
.linked-foe-backlink-toggle[b-vw6j2fyfxd] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0.15rem 0.4rem;
    border: 1px solid var(--card-border);
    border-radius: 4px;
    background: var(--card-bg);
    user-select: none;
}

.linked-foe-backlink-toggle input[type="checkbox"][b-vw6j2fyfxd] {
    accent-color: var(--accent-color);
    cursor: pointer;
}

.linked-foe-backlink-toggle:has(input:checked)[b-vw6j2fyfxd] {
    border-color: var(--accent-color);
    color: var(--text-color);
}

.linked-foe-backlink-toggle.disabled[b-vw6j2fyfxd] {
    opacity: 0.5;
    cursor: not-allowed;
}

.linked-foe-backlink-toggle.disabled input[b-vw6j2fyfxd] {
    cursor: not-allowed;
}

@media screen and (max-width: 768px) {
    .linked-foe-backlink-toggle[b-vw6j2fyfxd] { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
}
/* /Common/Components/Editing/ContentEditorShell.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentEditorShell.razor.css — editor form chrome
   Reclaimed from base.css (ladder rung 3): every rule here used to be
   `.foe-editor <descendant>` in the global layer, styling form controls the
   four pages (MonsterEdit, AdversaryEdit, EnvironmentEdit, MonsterImport)
   slot in as ChildContent. The shell's own root carries the scope attribute
   here; the slotted children do not, so every descendant rule needs ::deep.
   ═══════════════════════════════════════════ */

/* Own-root padding. Reclaimed from MonsterEdit.razor.css / AdversaryEdit.razor.css,
   which both carried an identical bare `.foe-editor { padding }` (+ these same two
   media variants) under a "Shared foe-editor base (page template)" comment. That
   selector is the shell's own root once .foe-editor moves here — a scoped bare
   selector in either page's own file can no longer reach it (the div now carries
   ContentEditorShell's scope attribute, not the page's), so leaving it behind would
   silently drop the padding on MonsterEdit/AdversaryEdit. Centralizing it here
   also applies it to EnvironmentEdit/MonsterImport, which never had it — a
   deliberate, reported deviation from strict no-behavior-change; see task-1-report.md. */
.foe-editor[b-mydw8d6z9z] {
    padding: 2rem;
}

@media (max-width: 768px) {
    .foe-editor[b-mydw8d6z9z] {
        padding: 1rem;
    }
}

@media (max-width: 480px) {
    .foe-editor[b-mydw8d6z9z] {
        padding: 0.75rem;
    }
}

/* The page heading. MonsterEdit and AdversaryEdit each carried this rule under
   the identical `.foe-editor h2` selector; the heading is slotted, so it needs
   ::deep from here (rung 3) exactly the way HeroSection reaches its h1. Same
   deviation as the padding above: EnvironmentEdit and MonsterImport render an
   h2 into this shell and never had a rule for it, so their heading now picks up
   the header font, colour and spacing the other two always had. */
/* Spacing only: base.css gives every h1–h6 the header font and --text-color
   already, and restating them here just took the properties off rung 4 at a
   specificity nothing else could answer. */
[b-mydw8d6z9z] h2 {
    margin-bottom: 1.5rem;
}

/* The field row itself is `Common/Components/UI/FormField.razor` now (rung 2).
   This file used to carry the whole row — `.form-group`, its label, its hint
   small and its `> button` — through ::deep, because 117 of the 127 rows in
   the app hand-wrote the div instead of rendering FormField. They all render
   it now, so those rules moved to FormField's own scoped sheet, where they are
   rung-1 rules on markup that component authors.

   The input skin went with them, and did not come back: `background-color:
   var(--card-bg)` here (plus byte-identical copies in EncounterBuilder and
   FoePickerLayout) was the only reason inputs on the editor pages read dark
   navy while the same `.form-control` elsewhere read parchment. base.css owns
   the element vocabulary — one look, one rung-4 rule. */

/* The editor-page look of PublicVisibilityToggle — panel frame, label colour,
   accent checkbox, muted help line — is `.privacy-toggle--editor` in that
   component's own sheet now, behind its InEditorPage parameter. It lived here
   as `.foe-editor ::deep .privacy-toggle` at (0,3,0), chosen precisely because
   it outranks the owner; a parameter cannot tie with anything, so the ranking
   game is over. Every toggle inside this shell passes InEditorPage. */

[b-mydw8d6z9z] .text-muted {
    color: var(--text-muted) !important;
}

[b-mydw8d6z9z] .form-text {
    color: var(--text-muted) !important;
}

[b-mydw8d6z9z] .form-hint {
    color: var(--text-muted);
    font-size: 0.9rem;
    font-style: italic;
    margin-bottom: 1rem;
}

/* Form Row grid moved to Common/Components/UI/FormRow.razor.css (Task 2,
   editor-chrome rung-2 plan): FormRow now authors the `.form-row` div
   itself, so the grid sizing dropped from this file's rung-3 ::deep to a
   rung-1 bare scoped selector there — see the ownership-decision comment
   at the top of that file. */

/* Action editors: gone from this file entirely (2026-08-21). The
   `.feature-editor` half of the old selector list had already become
   FeatureEditor's `.feature-editor--editor`; the `.action-editor` half stayed
   only because six components (ActionRow, SpellRow, and the monster traits /
   reactions / legendary / lair-action sections) hand-rolled the div and there
   was no owner to hand it to. There was: the card those six were missing is
   FeatureEditor, and all six render <FeatureEditor InEditorPage="true"> now.
   The five declarations are stated once, in that component's own sheet, at
   rung 2 — so this shell no longer reaches for them at rung 3. */

/* Form Actions moved to Common/Components/UI/FormActions.razor.css (Task 4,
   editor-chrome rung-2 plan): FormActions now authors the `.form-actions` div
   itself, so this dropped from this file's rung-3 ::deep to a rung-1 bare
   scoped selector there — see the ownership-decision comment at the top of
   that file. */

/* `.required` moved to FormField.razor.css: the asterisk is rendered by
   FormField's `Required` parameter now, not hand-written by three pages. */

/* Validation summary box. Consolidated from identical dead copies in
   MonsterEdit.razor.css / AdversaryEdit.razor.css, where they were written as
   `.foe-editor .validation-summary-errors` — the <ValidationSummary> markup
   comes from the framework component, so the page scope id is never on it and
   the rules matched nothing. base.css styles `.invalid` and
   `.validation-message`, but nothing styled this box. */
[b-mydw8d6z9z] .validation-summary-errors {
    background: var(--editor-highlight-bg);
    border: 1px solid var(--focus-color);
    border-radius: 4px;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    color: var(--focus-color);
}

[b-mydw8d6z9z] .validation-summary-errors ul {
    margin: 0;
    padding-left: 1.25rem;
}
/* /Common/Components/Editing/EditPreviewToggle.razor.rz.scp.css */
/* A segmented control: one bordered group, the pressed half filled.
   In a fixed-height flex column (the encounter builder) overflow: hidden would let it
   shrink to nothing and stretch across: keep its height and width. */
.edit-preview-toggle[b-8srjb4n5em] {
    display: inline-flex;
    flex-shrink: 0;
    align-self: flex-start;
    margin-bottom: 1.25rem;
    border: 1px solid var(--input-border);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.edit-preview-toggle--inline[b-8srjb4n5em] {
    align-self: center;
    margin-bottom: 0;
}

.edit-preview-option[b-8srjb4n5em] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    min-width: 44px;
    padding: 0 1rem;
    border: none;
    background: var(--control-glass-bg, var(--bg-input));
    color: var(--text-color);
    font: inherit;
    cursor: pointer;
}

.edit-preview-option + .edit-preview-option[b-8srjb4n5em] {
    border-left: 1px solid var(--input-border);
}

.edit-preview-option[aria-pressed="true"][b-8srjb4n5em] {
    background: var(--editor-highlight-bg);
    color: var(--heading-accent);
    font-weight: 600;
}

.edit-preview-option:focus-visible[b-8srjb4n5em] {
    outline: none;
    box-shadow: inset 0 0 0 3px var(--focus-shadow);
}
/* /Common/Components/Editing/EntityReferenceSection.razor.rz.scp.css */
.entity-reference-section[b-1gugufwpne] {
    display: flex;
    flex-direction: column;
}

/* The slot's controls (a "New …" button, one or more pickers) stack with room between them. */
.entity-reference-picker[b-1gugufwpne] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    max-width: 320px;
}

.entity-reference-unavailable[b-1gugufwpne] {
    font-size: 0.8rem;
    font-style: italic;
    color: var(--text-muted);
}

.entity-reference-beat-hint[b-1gugufwpne] {
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* Full width on a narrow hub card: the hub lets its buttons break mid-word, so a
   squeezed button read "REMO VE". The chip gives way instead. */
.entity-reference-remove[b-1gugufwpne] {
    flex-shrink: 0;
}
/* /Common/Components/Editing/ExternalCreditFields.razor.rz.scp.css */
.url-input[b-a6x9h7ahip] {
    display: flex;
    gap: 0.25rem;
    align-items: center;
}

.url-input input[b-a6x9h7ahip] {
    flex: 1;
    min-width: 0;
}

.credit-separator[b-a6x9h7ahip] {
    width: 100%;
    margin: 0.5rem 0;
    border: none;
    border-top: 1px solid var(--card-border);
}
/* /Common/Components/Editing/FeatureEditor.razor.rz.scp.css */
/* Bordered card around one feature/action entry. Reclaimed from base.css
   (ladder rung 4 -> 2): five components rendered this same div, so the class
   was global only because the markup was duplicated.

   The editor pages ask for their own frame with InEditorPage. ContentEditorShell
   used to impose it with `.foe-editor ::deep .feature-editor` at (0,3,0), which
   outranked every declaration below and left this file describing a card that
   rendered nowhere the shell was on screen. */

.feature-editor[b-pycuph4lri] {
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.75rem;
    margin-bottom: 0.75rem;
    background: var(--card-bg);
}

/* Reclaimed from ContentEditorShell — and, since 2026-08-21, the only statement of
   this card anywhere. Six components (ActionRow, SpellRow, MonsterTraitsSection,
   MonsterReactionsSection, MonsterLegendarySection, MonsterLairActionsSection)
   hand-rolled a `.action-editor` div with these same five declarations, which the
   shell had to reach with `.foe-editor ::deep .action-editor`. They render
   <FeatureEditor InEditorPage="true"> now, so the shell's rule is deleted and the
   five declarations live here once. */
.feature-editor--editor[b-pycuph4lri] {
    background: var(--feature-editor-bg);
    padding: 1rem;
    margin-bottom: 1rem;
    border-radius: 4px;
    border: 1px solid var(--feature-editor-border);
}
/* /Common/Components/Editing/LanguageToggle.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   LanguageToggle.razor.css — content-language select chrome
   Ownership decision (Task 7, editor-chrome rung-2 plan): moved verbatim from
   base.css, which carried this as "TranslationSection atom + EnvironmentEdit's
   own copy". Both renderers are gone now — LanguageToggle authors the wrapper
   div and its label directly (bare scoped selectors, rung 1), but the <select>
   itself is rendered by Microsoft's <InputSelect>, a different component, so it
   never carries this component's scope attribute — same reasoning already
   documented in EncounterBuilder.razor.css. That rule needs ::deep (rung 3).
   ═══════════════════════════════════════════ */

.language-toggle[b-ki9vim1gvp] {
    margin-bottom: 1.25rem;
}

.language-toggle--inline[b-ki9vim1gvp] {
    margin-bottom: 0;
}

.language-toggle-row[b-ki9vim1gvp] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.language-toggle-hint[b-ki9vim1gvp] {
    margin: 0.5rem 0 0;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.language-toggle label[b-ki9vim1gvp] {
    font-weight: 600;
    color: var(--text-color);
    font-size: 0.95rem;
}

.language-toggle[b-ki9vim1gvp]  .form-select {
    max-width: 280px;
    width: auto;
    min-height: 44px;
}
/* /Common/Components/Editing/LinkedFoeChip.razor.rz.scp.css */
/* Reclaimed from base.css (ladder rung 4 -> 2). The comment there called five
   renderers "legitimate rung-4 debt because they have no common wrapper" — the
   ladder's answer to that is a shared component, which is what this is. */

.linked-foe-chip[b-cx8ticjd9p] {
    display: inline-block;
    background: var(--accent-color);
    color: var(--on-accent-text);
    border-radius: 4px;
    padding: 0.3rem 0.75rem;
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    transition: opacity 0.15s;
}

.linked-foe-chip:hover[b-cx8ticjd9p] {
    opacity: 0.85;
    text-decoration: none;
    color: var(--on-accent-text);
}
/* /Common/Components/Editing/LinkedFoeEditList.razor.rz.scp.css */
/* Reclaimed from base.css (ladder rung 4 -> 2): LinkedFoesSection and
   EnvironmentEdit rendered the same wrapper div around the same row shape. */

.linked-foes-edit-list[b-leceetkwnq] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

/* ::deep: the rows are slotted in by the caller (rung 3). */
[b-leceetkwnq] .linked-foe-edit-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
/* /Common/Components/Editing/LinkedFoesSection.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   LinkedFoesSection.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 1).

   This class was legitimately global while the Monster and Adversary
   linked-foe sections were separate components rendering the same badge.
   Merging them into this single generic component dropped it to one
   renderer, so it belongs here now.
   ═══════════════════════════════════════════ */

.linked-foe-private-badge[b-dk3rngh67n] {
    display: inline-block;
    font-size: 0.75rem;
    padding: 0.1rem 0.45rem;
    border-radius: 4px;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    color: var(--text-muted);
}
/* /Common/Components/Editing/PreviewModeBanner.razor.rz.scp.css */
/* A status strip, not a card: no glass. */
.preview-mode-banner[b-owr5o7ss3z] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin-bottom: 1.25rem;
    padding: 0.5rem 0.75rem;
    background: var(--editor-highlight-bg);
    border: 1px solid var(--accent-color);
    border-radius: 6px;
    color: var(--text-color);
}

.preview-mode-banner-icon[b-owr5o7ss3z] {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--accent-color);
}

.preview-mode-banner-text[b-owr5o7ss3z] {
    flex: 1 1 14rem;
}

/* The login keeps its size when the message wraps. */
.preview-mode-banner-login[b-owr5o7ss3z] {
    flex-shrink: 0;
}
/* /Common/Components/Editing/PublicVisibilityToggle.razor.rz.scp.css */
/* Reclaimed from base.css: .privacy-toggle had three renderers only because the
   two raw-input pages could not use VisibilitySection's InputCheckbox. This
   component renders a plain input, so it is the single owner of the shape. */
/* The two declarations below the border were `.form-group`'s while this
   component wrapped itself in one. It owns its root now, so it states them
   itself rather than borrowing a field row's box model. */
.privacy-toggle[b-18jyd3bair] {
    background-color: var(--privacy-toggle-bg);
    border: 2px solid var(--border-light);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    margin-bottom: 1rem;
}

.privacy-toggle .checkbox-label[b-18jyd3bair] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    cursor: pointer;
    margin-bottom: 0.5rem;
    font-weight: 600;
    font-size: 1.05rem;
}

.privacy-toggle .form-text[b-18jyd3bair] {
    font-style: italic;
}

/* ── Editor-page variant (driven by InEditorPage, ladder rung 1) ──
   Reclaimed from ContentEditorShell's `.foe-editor ::deep .privacy-toggle` family,
   which sat at (0,3,0) and so owned the panel — border and all — on the five
   shell pages while this file described a box nobody there saw. The inner
   rules stay under the variant rather than becoming bare: they were only ever
   applied inside the shell, and lifting them to the base rule would repaint
   the toggle in the encounter builder too. */
.privacy-toggle--editor[b-18jyd3bair] {
    background-color: var(--privacy-toggle-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    padding: 1rem;
}

.privacy-toggle--editor .checkbox-label[b-18jyd3bair] {
    color: var(--text-color);
}

.privacy-toggle--editor .checkbox-label input[type="checkbox"][b-18jyd3bair] {
    accent-color: var(--accent-color);
}

.privacy-toggle--editor .form-text[b-18jyd3bair],
.privacy-toggle--editor .text-muted[b-18jyd3bair] {
    color: var(--text-muted) !important;
    margin-top: 0.5rem;
    display: block;
}

.privacy-toggle--plain[b-18jyd3bair] {
    background-color: transparent;
    border: none;
    margin-bottom: 0;
}
/* /Common/Components/Editing/TagCustomInput.razor.rz.scp.css */
.tag-custom-input-wrap[b-92xzybbbos] {
    position: relative;
    margin-top: 0.5rem;
}

.tag-custom-input[b-92xzybbbos] {
    width: 100%;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--card-border);
    border-radius: 6px;
    background: var(--card-bg);
    color: var(--text-color);
    font-size: 0.85rem;
}

.tag-custom-input:focus[b-92xzybbbos] {
    outline: none;
    border-color: var(--focus-color);
    box-shadow: var(--focus-shadow);
}

.tag-autocomplete-dropdown[b-92xzybbbos] {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 100;
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 0 0 6px 6px;
    box-shadow: 0 4px 8px rgba(var(--shadow-rgb), 0.15);
}

.tag-autocomplete-dropdown li[b-92xzybbbos] {
    padding: 0.4rem 0.6rem;
    font-size: 0.85rem;
    color: var(--text-color);
    cursor: pointer;
}

.tag-autocomplete-dropdown li:hover[b-92xzybbbos] {
    background: var(--editor-highlight-bg);
}
/* /Common/Components/Features/FeatureSuggestionPanel.razor.rz.scp.css */
/* .feature-suggestion-info moved to FullConversionWizard.razor.css — that page
   renders it, this component never has, so the rules could not match here. */

/* ========================================
   Feature Suggestion Panel (MonsterFeatureSuggestionPanel / AdversaryFeatureSuggestionPanel)
   ======================================== */
/* Anchor: positions the absolute dropdown relative to this element */
.suggestion-anchor[b-6ulng4a3hw] {
    position: relative;
    display: inline-block;
}

/* Floating dropdown panel */
.suggestion-panel[b-6ulng4a3hw] {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 200;
    width: 380px;
    max-width: 90vw;
    max-height: 60vh;
    overflow-y: auto;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.25);
    padding: 0.5rem;
}

@media (max-width: 768px) {
    .suggestion-panel[b-6ulng4a3hw] {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        top: auto;
        width: 100%;
        max-width: none;
        border-radius: 1rem 1rem 0 0;
        max-height: 70vh;
        box-shadow: 0 -4px 16px rgba(var(--shadow-rgb), 0.25);
    }
}

.suggestion-search[b-6ulng4a3hw] {
    position: relative;
    display: flex;
    align-items: center;
}

.suggestion-search input.form-control[b-6ulng4a3hw] {
    padding-right: 2rem;
}

.suggestion-search .btn-clear[b-6ulng4a3hw],
.suggestion-search .search-spinner[b-6ulng4a3hw] {
    position: absolute;
    right: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    width: 1.5rem;
    height: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.suggestion-search .btn-clear:hover[b-6ulng4a3hw] {
    color: var(--text-color);
}

.suggestion-item[b-6ulng4a3hw] {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--card-border);
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.25rem 0.5rem;
}

.suggestion-item:last-child[b-6ulng4a3hw] {
    border-bottom: none;
    padding-bottom: 0;
}

.suggestion-item .btn-link[b-6ulng4a3hw] {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font-size: 0.85rem;
    color: var(--color-copper);
    text-decoration: underline;
    cursor: pointer;
}

.suggestion-item .btn-link:hover[b-6ulng4a3hw] {
    color: var(--color-copper-light);
}

.suggestion-header[b-6ulng4a3hw] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    width: 100%;
}

.suggestion-name[b-6ulng4a3hw] {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--text-color);
}

.suggestion-badges[b-6ulng4a3hw] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.add-suggestion[b-6ulng4a3hw] {
    margin-left: auto;
    flex-shrink: 0;
}

/* Substituted name highlight */
.name-sub[b-6ulng4a3hw] {
    background: color-mix(in srgb, var(--accent-color) 20%, transparent);
    text-decoration: underline dotted var(--accent-color);
    border-radius: 3px;
    padding: 0 2px;
    cursor: default;
    position: relative;
}

.name-sub[b-6ulng4a3hw]::after {
    content: attr(data-original);
    position: absolute;
    bottom: calc(100% + 4px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--card-bg);
    color: var(--text-muted);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 2px 6px;
    font-size: 0.75rem;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
    z-index: 10;
}

.name-sub:hover[b-6ulng4a3hw]::after {
    opacity: 1;
}

/* ── Reclaimed from base.css (ladder rung 1) ── */
.suggestion-empty[b-6ulng4a3hw] {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}
/* /Common/Components/FilterPresetPanel.razor.rz.scp.css */
/* The icon is the icon component's own <svg>, not this component's element, so
   these rules reach it with ::deep (rung 3). Written bare, they compiled
   against this component's scope id, matched nothing, and the icon rendered
   at its default size. */
/* znk.digital.FoeForge.Client/Components/Shared/FilterPresetPanel.razor.css */
.preset-panel[b-1qfbgd104t] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 1rem;
}

.preset-list[b-1qfbgd104t] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.preset-chip[b-1qfbgd104t] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    border-bottom: 2px solid transparent;
    padding: 0 0.25rem;
    font-size: 0.85rem;
    transition: border-color 0.15s;
}

.preset-active[b-1qfbgd104t] {
    border-bottom-color: var(--rubric);
}

.preset-name[b-1qfbgd104t] {
    background: none;
    border: none;
    color: var(--text-color);
    cursor: pointer;
    padding: 0;
    min-height: 44px;
    font: inherit;
}

.preset-delete[b-1qfbgd104t] {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0 0.15rem;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.6;
}

.preset-delete:hover[b-1qfbgd104t] {
    opacity: 1;
    color: var(--text-color);
}

.preset-save[b-1qfbgd104t] {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border-radius: 999px;
    padding: 0.35rem 0.75rem;
    font-weight: 600;
    font-size: 0.85rem;
}

.preset-save[b-1qfbgd104t]  .preset-save-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

.preset-save-label[b-1qfbgd104t] {
    white-space: nowrap;
}

.preset-prompt-overlay[b-1qfbgd104t] {
    position: fixed;
    inset: 0;
    background: var(--modal-backdrop-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.preset-prompt-dialog[b-1qfbgd104t] {
    background: var(--card-bg);
    border: 2px solid var(--card-border);
    border-radius: 8px;
    padding: 1.5rem;
    width: 90%;
    max-width: 320px;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.preset-prompt-dialog label[b-1qfbgd104t] {
    font-family: var(--font-header);
    color: var(--text-color);
    font-weight: 600;
}

.preset-prompt-actions[b-1qfbgd104t] {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
}

@media (max-width: 768px) {
    .preset-panel[b-1qfbgd104t] {
        gap: 0.35rem;
    }
    .preset-chip[b-1qfbgd104t] {
        font-size: 0.8rem;
    }
}
/* /Common/Components/FoePicker/FoePickerLayout.razor.rz.scp.css */
/* Search input with the optional Filters toggle beside it, on every width. */
.foe-picker-search-row[b-4w3ahvlyvx] {
    display: flex;
    gap: 0.5rem;
    align-items: stretch;
}

.foe-picker-search-row[b-4w3ahvlyvx]  .search-input {
    flex: 1 1 auto;
    min-width: 0;
}

/* Search status messages */
.search-loading[b-4w3ahvlyvx],
.search-empty[b-4w3ahvlyvx] {
    padding: 1rem;
    text-align: center;
    color: var(--text-muted);
    font-style: italic;
}

/* Sort header over the results (Sortable): on phones two 44px buttons in a
   row; from 769px they sit over the name and CR/tier columns of the rows. */
.search-sort-header[b-4w3ahvlyvx] {
    display: flex;
    gap: 0.5rem;
    padding: 0 0.5rem;
    border-bottom: 1px solid var(--card-border);
}

.sort-header-button[b-4w3ahvlyvx] {
    min-height: 44px;
    padding: 0;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

.sort-header-button[aria-pressed="true"][b-4w3ahvlyvx],
.sort-header-button:hover[b-4w3ahvlyvx] {
    color: var(--text-color);
}

@media (min-width: 769px) {
    .search-sort-header[b-4w3ahvlyvx] {
        display: grid;
        grid-template-columns: var(--foe-result-columns);
        column-gap: 0.5rem;
    }

    .sort-header-button[b-4w3ahvlyvx] {
        min-height: 2rem;
        justify-self: start;
    }

    .foe-picker-filters-toggle[b-4w3ahvlyvx] {
        min-width: 2.25rem;
        min-height: 0;
    }
}
/* /Common/Components/Layout/BrushLandscape.razor.rz.scp.css */
/* Sticks to the top of the scroll and takes no room, like PageBackdrop; the
   picture is one screen high, pinned right. --wash-rgb is the ink of the
   mountains (tokens.css, per mode). */
.brush-landscape[b-l8v7yd0c64] {
    position: sticky;
    top: 0;
    height: 0;
    z-index: -1;
    pointer-events: none;
}

svg[b-l8v7yd0c64] {
    position: absolute;
    inset: 0 0 auto 0;
    width: 100%;
    height: 100svh;
}

.wash-stop[b-l8v7yd0c64] {
    stop-color: rgb(var(--wash-rgb));
}

.far[b-l8v7yd0c64] {
    fill: url(#brush-mist);
    opacity: 0.55;
}

.near[b-l8v7yd0c64] {
    fill: url(#brush-mist);
    opacity: 0.8;
}

.ground[b-l8v7yd0c64] {
    fill: rgb(var(--wash-rgb));
    opacity: 0.25;
}

.sun[b-l8v7yd0c64] {
    fill: var(--rubric);
    opacity: 0.55;
}
/* /Common/Components/Layout/LegalPageLayout.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   LegalPageLayout.razor.css — legal-page chrome
   Reclaimed from base.css (ladder rung 2)

   The document body is authored by the consuming page, so everything below
   the root uses ::deep. That also covers the layout's own <h1>, since
   ::deep places the scope attribute on .legal-page and matches any
   descendant — the pages each carry a second <h1> for their English
   translation section.
   ═══════════════════════════════════════════ */

.legal-page[b-8r5asy1qhq] {
    max-width: 800px;
    margin: 0 auto;
    padding: 2rem 1rem;
    color: var(--text-color);
}

/* --accent-color is the legal pages' one deliberate departure from base.css's
   heading colour; the header font is base.css's and is not restated. */
[b-8r5asy1qhq] h1 {
    color: var(--accent-color);
    margin-bottom: 2rem;
}

/* The section box moved to Common/Components/Layout/LegalSection.razor.css:
   LegalSection now authors the `<section class="legal-section">` element
   itself, so the box and its heading/address rules dropped from this file's
   rung-3 ::deep to rung 1/3 in the component that owns the markup. */

[b-8r5asy1qhq] .legal-divider {
    border: none;
    border-top: 2px solid var(--card-border);
    margin: 3rem 0 2rem;
}

[b-8r5asy1qhq] .lang-note {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-family: var(--font-body);
    font-weight: 400;
}

@media (max-width: 768px) {
    .legal-page[b-8r5asy1qhq] {
        padding: 1rem 0.5rem;
    }
}
/* /Common/Components/Layout/LegalSection.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   LegalSection.razor.css — one boxed section of a legal document
   Reclaimed from LegalPageLayout.razor.css (ladder rung 3 -> rung 2).
   The three legal pages hand-rolled `<section class="legal-section">` 30+
   times and LegalPageLayout reached every one of them with ::deep. The
   section is now its own component, so the box itself is a bare rung-1
   selector here; only the document body inside it is slotted, which is what
   the three ::deep rules below reach.

   Written as `.legal-section ::deep h2` rather than bare `::deep h2` on
   purpose: the compiled selector keeps the (0,2,1) specificity the
   `.legal-page ::deep .legal-section h2` rule had, so nothing about which
   rule wins changes.
   ═══════════════════════════════════════════ */

.legal-section[b-hmitqqmjj7] {
    margin-bottom: 2rem;
    padding: 1.5rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
}

/* --accent-color, not --text-color: the section title is the one heading in the
   app that reads as accent, which is why the colour is stated here at all. The
   header font is base.css's and is not restated. */
.legal-section[b-hmitqqmjj7]  h2 {
    color: var(--accent-color);
    font-size: 1.3rem;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--card-border);
}

.legal-section[b-hmitqqmjj7]  h3 {
    font-size: 1.1rem;
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
}

.legal-section[b-hmitqqmjj7]  address {
    font-style: normal;
    line-height: 1.6;
}

@media (max-width: 768px) {
    .legal-section[b-hmitqqmjj7] {
        padding: 1rem;
    }
}
/* /Common/Components/Layout/PageBackdrop.razor.rz.scp.css */
/* Sits behind the page content: rendered first in MainLayout's `.main-content`
   (positioned, isolated), so z-index -1 stays above the page background. The
   band takes no room (height 0) and sticks to the top of the scroll; its art
   layer is one screen high (the column's height on desktop) and the picture in
   it is 15% taller, moved up by --page-backdrop-shift as the page scrolls
   (page-parallax.js). Mobile first: the small variant (the right-hand part a
   phone shows), the full image from 769px; only the image in use is
   downloaded.

   The art is toned sepia (--art-filter) and faded with masks, so it dissolves
   into the paper ground of the column instead of a flat page colour; the
   blend (--ground-blend, as the ground) sits on the band, whose stacking context composites
   against that ground. The mask layers are custom properties so each variant
   and mode swaps only the part it changes: `down` (the fade at the bottom),
   `across` (the fade from the left) and `place` (where the art sits). */
.page-backdrop[b-6jn822lxhw] {
    --page-backdrop-art: var(--page-backdrop-image-small);
    --page-backdrop-near: 40%;
    --page-backdrop-far: 88%;
    --page-backdrop-down: linear-gradient(to bottom, var(--color-black) 60%, transparent);
    --page-backdrop-across: linear-gradient(90deg,
            transparent 0%,
            transparent 18%,
            color-mix(in srgb, var(--color-black) var(--page-backdrop-near), transparent) 42%,
            color-mix(in srgb, var(--color-black) var(--page-backdrop-far), transparent) 70%,
            var(--color-black) 100%);
    --page-backdrop-place: right calc(-1 * var(--page-backdrop-shift, 0px)) / auto 115%;
    position: sticky;
    top: 0;
    height: 0;
    z-index: -1;
    pointer-events: none;
    mix-blend-mode: var(--ground-blend);
}

.page-backdrop-art[b-6jn822lxhw] {
    position: absolute;
    inset: 0 0 auto 0;
    height: 100svh;
    background: var(--page-backdrop-art) var(--page-backdrop-place) no-repeat;
    filter: var(--art-filter);
    mask-image: var(--page-backdrop-down), var(--page-backdrop-across);
    mask-composite: intersect;
}

/* Light mode: the art is softened toward the pale page, like a print on paper. */
.light-mode .page-backdrop[b-6jn822lxhw] {
    --page-backdrop-near: 22%;
    --page-backdrop-far: 70%;
}

@media (min-width: 769px) {
    .page-backdrop[b-6jn822lxhw] {
        --page-backdrop-art: var(--page-backdrop-image);
    }

    .page-backdrop-art[b-6jn822lxhw] {
        height: 100cqh;
    }
}
/* /Common/Components/MultiSelectDropdown.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   MultiSelectDropdown.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 1)
   ═══════════════════════════════════════════ */

/* Full width on phones, like the selects beside it in a stacked filter drawer
   (FilterGroup goes 100% below 769px); capped beside them on wider screens. */
.multiselect-dropdown[b-a17oo63ucc] {
    position: relative;
}

@media (min-width: 769px) {
    .multiselect-dropdown[b-a17oo63ucc] {
        max-width: 150px;
    }
}

/* Reclaimed from BuilderSearchPanel, which widened the control with
   `::deep .multiselect-dropdown` and so owned its max-width inside that column. */
.multiselect-dropdown--full[b-a17oo63ucc] {
    max-width: 100%;
    width: 100%;
}

/* The `.filter-group` rules that used to sit here are gone with the Label
   parameter: this component no longer composes that class onto its root, and
   every labelled caller wraps it in <FilterGroup>, which owns the shape. */

.multiselect-trigger[b-a17oo63ucc] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    /* Matches base.css's native <select>: same surface, border, padding, size and
       corners. The two sit beside each other in every filter drawer. */
    padding: 0.375rem 0.75rem;
    font-size: 1rem;
    background-color: var(--bg-input);
    border: 1px solid var(--input-border);
    border-radius: 0.375rem;
    font-family: var(--font-body);
    cursor: pointer;
    color: var(--text-color);
    gap: 0.5rem;
    text-align: left;
}

.multiselect-trigger:hover[b-a17oo63ucc] {
    border-color: var(--focus-color);
}

.multiselect-trigger:focus[b-a17oo63ucc] {
    border-color: var(--focus-color);
    box-shadow: 0 0 0 0.2rem var(--focus-shadow);
    outline: none;
}

.multiselect-value[b-a17oo63ucc] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}

.multiselect-chevron[b-a17oo63ucc] {
    flex-shrink: 0;
    font-size: 0.8rem;
    transition: transform 0.2s ease;
    opacity: 0.7;
}

.multiselect-chevron.open[b-a17oo63ucc] {
    transform: rotate(180deg);
}

.multiselect-search[b-a17oo63ucc] {
    padding: 0.5rem;
    border-bottom: 1px solid var(--card-border);
}

/* Skin deliberately absent: the element carries `class="form-control"` and
   base.css owns what a control looks like. Re-stating background, border and
   colour here is what made this search box the one input in the app that did
   not follow --bg-input; only the size differs, so only the size is here. */
.multiselect-search input[b-a17oo63ucc] {
    width: 100%;
    padding: 0.35rem 0.5rem;
    font-size: 0.85rem;
}

.multiselect-search input:focus[b-a17oo63ucc] {
    border-color: var(--focus-color);
    outline: none;
    box-shadow: 0 0 0 0.15rem var(--focus-shadow);
}

.multiselect-dropdown input[type="checkbox"][b-a17oo63ucc] {
    appearance: auto;
    -webkit-appearance: auto;
    position: static;
    display: inline-block;
    width: 1rem;
    height: 1rem;
    border: 1px solid var(--input-border);
    border-radius: 2px;
    background: var(--bg-input);
    cursor: pointer;
    flex-shrink: 0;
    vertical-align: middle;
    transition: none;
}

.multiselect-dropdown input[type="checkbox"][b-a17oo63ucc]::before {
    display: none;
    content: none;
}

.multiselect-dropdown input[type="checkbox"]:checked[b-a17oo63ucc] {
    background: var(--bg-input);
    border-color: var(--focus-color);
    accent-color: var(--focus-color);
}

.multiselect-dropdown input[type="checkbox"]:checked[b-a17oo63ucc]::before {
    display: none;
    content: none;
}

.multiselect-dropdown input[type="checkbox"]:focus-visible[b-a17oo63ucc] {
    outline: 2px solid var(--focus-color);
    outline-offset: 2px;
}

.multiselect-dropdown input[type="checkbox"]:disabled[b-a17oo63ucc] {
    opacity: 0.5;
    cursor: not-allowed;
}

.multiselect-dropdown input[type="checkbox"]:disabled[b-a17oo63ucc]::before {
    display: none;
}

.multiselect-options[b-a17oo63ucc] {
    max-height: 240px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.multiselect-option[b-a17oo63ucc] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.6rem;
    cursor: pointer;
    font-size: 0.9rem;
    color: var(--text-color);
    font-family: var(--font-body);
    transition: background 0.15s ease;
    flex-shrink: 0;
}

.multiselect-option:hover[b-a17oo63ucc] {
    background: var(--filter-tag-bg);
}

.multiselect-option.selected[b-a17oo63ucc] {
    background: var(--editor-highlight-bg);
}

.multiselect-option input[type="checkbox"][b-a17oo63ucc] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--focus-color);
    cursor: pointer;
    flex-shrink: 0;
    margin: 0;
}

.single-select-option[b-a17oo63ucc] {
    width: 100%;
    background: none;
    border: none;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

/* The option row and its detail line are this component's own markup, so this
   is a bare rule (rung 1). It was `::deep .single-select-option .result-detail`:
   `result-detail` is FoeSearchResultItem's class, a different span on a
   different surface that this rule never touched, and borrowing the name made
   the dropdown look like a second renderer of that component's shape. The span
   is `option-detail` now — this component's own name for its own element. */
.single-select-option .option-detail[b-a17oo63ucc] {
    font-size: 0.75rem;
    opacity: 0.7;
}
/* /Common/Components/Owned/OwnedEntityDisplayLayout.razor.rz.scp.css */
.owned-display-toolbar[b-lgwdyztz9c] {
    width: 100%;
}

.owned-display-hub[b-lgwdyztz9c] {
    width: 100%;
    margin-top: 1rem;
}
/* /Common/Components/Owned/OwnedEntityEditLayout.razor.rz.scp.css */
/* Capped like the other compact content pages (Guide.razor, EncounterBuilderLanding.razor):
   ContentEditorShell's .page-width alone runs up to 1800px, and a form this small reads as
   a wall of full-width single-line inputs at that size without its own cap. */
.owned-editor[b-lefz6kh797] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    max-width: 900px;
    margin: 0 auto;
    /* The form sits on one glass panel over the page art (GlassLayer blurs it),
       like EntityCard's .card-item; solid elsewhere. */
    position: relative;
    padding: 1rem;
    border-radius: 8px;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
}

@media (min-width: 769px) {
    .owned-editor[b-lefz6kh797] {
        padding: 1.5rem;
    }
}
/* /Common/Components/Owned/OwnedEntityListLayout.razor.rz.scp.css */
/* The heading row: the slotted h1 (its margin is ListPage's) and the create button. It wraps, so
   at phone width a long heading ("D&D 5e Adventures") pushes the button onto its own line
   instead of past the viewport. */
.owned-list-header[b-y5nf8u36t0] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

/* The heading row's buttons stay together; the group wraps as a unit below the heading. */
.owned-list-actions[b-y5nf8u36t0] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* The empty state's create button carries the longest label on the page; `.btn` keeps it on
   one line, which at 375px ran it past the viewport. */
.owned-list-create-first[b-y5nf8u36t0] {
    max-width: 100%;
    white-space: normal;
}
/* /Common/Components/Spells/SpellRow.razor.rz.scp.css */
/* Was an inline style="flex-grow: 1": the spell name takes the slack left by
   the fixed-size damage, school and uses fields beside it in the same row. */
/* No `.spell-name-field` rule: the div is FormField's, so a rule here matched
   nothing. The name field asks for `form-group--grow` now. */
.spell-row-remove[b-nc9en45z06] {
    display: inline-flex;
    gap: 0.4rem;
    align-items: center;
    white-space: nowrap;
}

/* No `.spell-row-toggles` rule here any more. It reached FormRow's own root
   div through ::deep, which only worked while this file's scope id sat on an
   ancestor of it — the hand-rolled `.action-editor` div. That div is
   <FeatureEditor> now, so the anchor is gone and the rule would have died
   silently. It is `.form-row--toggles` in FormRow.razor.css instead: a bare
   scoped rule on the element FormRow authors (rung 3 -> rung 1). */

/* The checkbox-field variant lives in FormField.razor.css: `.form-group--checkbox`
   is FormField's own class, reached through its `Class` parameter, and both
   renderers of it are the two toggles in this file. Styling it from here meant
   four ::deep rules restating the owner's own selector. */

/* No `.spell-row-remove .btn-label { display: none }` at (max-width: 480px)
   here. Every SpellRow renders inside MonsterSpellcastingSection's
   `.spell-section`, which hides the label on every spell button at that same
   breakpoint with the same value — so this rule decided nothing while claiming
   `display` on a class four components render. Deleted rather than duplicated
   (working rule 4). The real end state is a shared button-label component at
   rung 2; that is a wider extraction than this paydown.
   The narrow-screen half of the toggles row moved to FormRow.razor.css with
   the rest of that modifier. */
/* /Common/Components/StatBlock/FoeStatBlockFrame.razor.rz.scp.css */
/* The on-screen stat-block frame — the nine declarations both stat-block roots
   stated identically, plus the per-system palette every StatBlock* chrome
   component reads through --fsb-*.

   The palette hangs off the modifier classes rather than the .dnd-theme / .dh-theme
   wrappers in tokens.css, for the reason written out in FoeCardFrame.razor.css:
   surfaces render these blocks with no theme wrapper in the document, and every
   --mm-* / --dh-* token is declared on :root precisely so they still paint. */

.foe-stat-block-frame[b-zey5vdl4wg] {
    background: var(--fsb-bg);
    color: var(--fsb-ink);
    padding: 1rem 1.25rem;
    border: 2px solid var(--fsb-border);
    border-radius: var(--fsb-radius);
    font-family: var(--font-body);
    font-size: 0.95rem;
    line-height: 1.45;
    column-count: var(--column-count, 2);
    column-gap: 1.5rem;
    break-inside: avoid;
    /* No max-width: the inline width is Columns × 320px + gaps, and squeezing it
       to the viewport on narrow screens crushed the columns to unreadable slivers.
       The width is authoritative; ContentDisplayLayout's .foe-stat-block scrolls
       horizontally instead. Block-level auto margins resolve to 0 when the box is
       wider than its container, so nothing is clipped on the left. */
    margin: 0 auto 1.5rem;
    box-sizing: border-box;
}

.foe-stat-block-frame--dnd5e[b-zey5vdl4wg] {
    --fsb-bg: var(--stat-block-bg);
    --fsb-ink: var(--stat-block-text);
    --fsb-border: var(--stat-block-rule);
    --fsb-radius: 0;

    /* `--mm-font-header`, not `--font-header`: the app's heading face is the
       rebrand's, and this is D&D chrome that keeps its own. */
    --fsb-heading-font: var(--mm-font-header);
    --fsb-label-variant: normal;
    --fsb-label-colon: "";

    /* Read by <StatBlockRule> and <StatBlockSectionTitle>, which carry no system
       knowledge of their own. */
    --fsb-chrome-rule: var(--stat-block-rule);
    --fsb-chrome-text: var(--stat-block-text);
}

.foe-stat-block-frame--daggerheart[b-zey5vdl4wg] {
    --fsb-bg: var(--dh-bg-light);
    --fsb-ink: var(--dh-text-header);
    --fsb-border: var(--dh-accent-teal);
    --fsb-radius: 6px;

    --fsb-heading-font: var(--dh-font-header);
    --fsb-label-variant: small-caps;
    --fsb-label-colon: ":";

    --fsb-chrome-rule: var(--dh-accent-teal);
    --fsb-chrome-text: var(--dh-text-header);
}

/* Cover-style touches, on screen only (docs/daggerheart-visual-style-plan.md,
   phase 4). The values above stay what print reads; this block re-declares a
   few of the same custom properties under `@media screen`, so a printed detail
   page is untouched.

   Daggerheart: antique gold rules and section underlines (--sb-rule-gold) under
   violet section titles (--dh-bg-medium, 8.26:1 on --dh-bg-light), the rules
   drawn with pointed ends. D&D: the crimson rule tapers to the right like the
   printed manual's, section titles take the same crimson (6.77:1 on the
   parchment), and gold bars close the block top and bottom. */
@media screen {
    .foe-stat-block-frame--dnd5e[b-zey5vdl4wg] {
        --fsb-chrome-text: var(--mm-accent-red-light);
        --fsb-rule-shape: polygon(0 0, 100% 50%, 0 100%);
        border-block: 5px solid var(--sb-rule-gold);
    }

    .foe-stat-block-frame--daggerheart[b-zey5vdl4wg] {
        --fsb-chrome-rule: var(--sb-rule-gold);
        --fsb-chrome-text: var(--dh-bg-medium);
        --fsb-rule-shape: polygon(0 50%, 6px 0, calc(100% - 6px) 0, 100% 50%, calc(100% - 6px) 100%, 6px 100%);
    }
}
/* /Common/Components/StatBlock/StatBlockFeature.razor.rz.scp.css */
.fsb-feature[b-tva7ccqrjs] {
    margin-bottom: 0.35rem;
    break-inside: avoid;
}

.fsb-feature-name[b-tva7ccqrjs] {
    font-weight: 700;
    color: var(--fsb-ink);
}

.fsb-meta[b-tva7ccqrjs] {
    font-style: italic;
    font-size: 0.9em;
}
/* /Common/Components/StatBlock/StatBlockFooter.razor.rz.scp.css */
.stat-block-footer[b-79plolf534] {
    font-size: 0.75rem;
    color: var(--text-muted);
    text-align: right;
    margin-top: 0.5rem;
    padding-top: 0.25rem;
    border-top: 1px solid var(--border-color);
    opacity: 0.85;
}
/* /Common/Components/StatBlock/StatBlockLabel.razor.rz.scp.css */
/* font-variant and the trailing colon arrive from the frame: Daggerheart renders
   small-caps labels ending in a colon, D&D renders neither, and both are values
   rather than a second rule. --fsb-label-colon is "" for D&D, so the ::after
   generates nothing there. */
.fsb-label[b-q3bnlwkspe] {
    font-weight: 700;
    font-variant: var(--fsb-label-variant, normal);
    color: var(--fsb-ink);
}

.fsb-label[b-q3bnlwkspe]::after {
    content: var(--fsb-label-colon, "");
}
/* /Common/Components/StatBlock/StatBlockLine.razor.rz.scp.css */
.fsb-line[b-irtv98iya0] {
    margin-bottom: 0.2rem;
}
/* /Common/Components/StatBlock/StatBlockName.razor.rz.scp.css */
.fsb-name[b-pssclz4g4n] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--fsb-heading-font);
    font-size: 1.5rem;
    margin: 0 0 0.2rem;
    color: var(--fsb-ink);
    text-transform: uppercase;
}

.fsb-name-portrait[b-pssclz4g4n] {
    display: flex;
    flex-shrink: 0;
}

@media (min-width: 1100px) {
    .fsb-name-portrait[b-pssclz4g4n] {
        display: none;
    }
}
/* /Common/Components/StatBlock/StatBlockRule.razor.rz.scp.css */
.stat-block-rule[b-cmsdqqpwvy] {
    height: 4px;
    background: var(--fsb-chrome-rule);
    margin: 0.4rem 0;
    border-radius: 2px;
}

/* The frame hands the shape down with the colour, screen only: the printed rule
   stays the flat bar above. */
@media screen {
    .stat-block-rule[b-cmsdqqpwvy] {
        clip-path: var(--fsb-rule-shape);
    }
}
/* /Common/Components/StatBlock/StatBlockSectionTitle.razor.rz.scp.css */
.stat-block-section-title[b-ajz47wvmyv] {
    font-variant: small-caps;
    font-size: 1.1rem;
    border-bottom: 1px solid var(--fsb-chrome-rule);
    margin: 0.5rem 0 0.3rem;
    color: var(--fsb-chrome-text);
    break-after: avoid-column;
}
/* /Common/Components/StatBlock/StatBlockSubtitle.razor.rz.scp.css */
.fsb-subtitle[b-wmwlohsf0q] {
    font-style: italic;
    margin: 0 0 0.4rem;
    color: var(--fsb-ink);
}
/* /Common/Components/Systems/Daggerheart/DaggerheartBonusOptions.razor.rz.scp.css */
/* ── Reclaimed from base.css (ladder rung 1) ── */
.budget-note[b-un25log12u] {
    color: var(--text-muted);
    font-size: 0.85em;
}
/* /Common/Components/Systems/Daggerheart/DaggerheartDifficultyBudget.razor.rz.scp.css */


/* /Common/Components/UI/ActionDivider.razor.rz.scp.css */
@media screen and (max-width: 768px) {
    .action-divider[b-6sigdjhkv5] {
        display: none;
    }
}
/* /Common/Components/UI/ActionGroup.razor.rz.scp.css */
/* Moved verbatim from ContentActionPanel.razor.css and DetailToolbar.razor.css,
   which defined this class identically (ladder rung 2). */

.action-group[b-t819zibrvp] {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    flex-wrap: wrap;
    max-width: 100%;
}
/* /Common/Components/UI/ActionMenu.razor.rz.scp.css */
/* The panel opens below the trigger, right-aligned, above the page-wide backdrop (z-index 105). */
.action-menu[b-mcwq1t3c1k] {
    position: relative;
    display: inline-flex;
}

.action-menu__panel[b-mcwq1t3c1k] {
    position: absolute;
    top: 100%;
    right: 0;
    z-index: 110;
    display: flex;
    flex-direction: column;
    min-width: 12rem;
    padding: 0.25rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(var(--shadow-rgb), 0.25);
}
/* /Common/Components/UI/ActionMenuItem.razor.rz.scp.css */
.action-menu-item[b-zci27vzl0o] {
    width: 100%;
    gap: 0.5rem;
    white-space: nowrap;
    color: var(--text-color);
}
/* /Common/Components/UI/ActiveFilterChips.razor.rz.scp.css */
.filter-label[b-cx93lwiz97] {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}
/* /Common/Components/UI/AdventureUsageHubCard.razor.rz.scp.css */
.adventure-usage-beats[b-433nzg4eap] {
    margin-left: 0.5rem;
    color: var(--text-muted);
    font-size: 0.85rem;
}
/* /Common/Components/UI/AttackBonusSuggestionChips.razor.rz.scp.css */
.atk-suggestion-chips[b-jouqixwzq4] {
    list-style: none;
    padding: 0;
}
/* /Common/Components/UI/Badge.razor.rz.scp.css */
.badge[b-nhp15io5wj] {
    display: inline-block;
    padding: 0.15em 0.5em;
    border-radius: 4px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

.badge-featured[b-nhp15io5wj] {
    background-color: var(--color-gold);
    color: var(--on-primary-text);
}

.badge-scheduled[b-nhp15io5wj] {
    background-color: var(--color-copper);
    color: var(--on-primary-text);
}

.badge-info[b-nhp15io5wj] {
    background: var(--badge-role-bg);
    color: var(--badge-role-text);
}

.badge-type[b-nhp15io5wj] {
    background: var(--badge-type-bg);
    color: var(--badge-type-text);
}

.badge-system[b-nhp15io5wj] {
    background-color: var(--accent-color);
    color: var(--on-accent-text);
}

.badge-lang[b-nhp15io5wj] {
    background-color: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--card-border);
}

.badge-neutral[b-nhp15io5wj] {
    background-color: transparent;
    color: var(--text-muted);
}
/* /Common/Components/UI/BrandIcon.razor.rz.scp.css */
.brand-icon[b-n0g2y636sx] {
    display: block;
    flex-shrink: 0;
}

.brand-icon__frame[b-n0g2y636sx] {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.2;
}

.brand-icon__field[b-n0g2y636sx] {
    fill: var(--spine-accent);
}

.brand-icon__letter[b-n0g2y636sx] {
    fill: var(--spine);
    font-family: var(--font-header);
    font-size: 27px;
}
/* /Common/Components/UI/ButtonRow.razor.rz.scp.css */
/* Was `.collection-form-actions`, defined identically in three scoped files
   (AddToCollectionModal, CollectionList, CollectionDetail) because all three
   hand-rolled the same row (ladder rung 2). */

.button-row[b-jksmehxq3s] {
    display: flex;
    gap: 0.75rem;
}
/* /Common/Components/UI/CardActionButtons.razor.rz.scp.css */
/* ponytail: display:contents makes this wrapper transparent to the parent's
   flex layout, so the buttons inside participate in .card-actions' flex row
   exactly as they did before the CardActionButtons split. Without this, the
   wrapper becomes a single flex item and the buttons stack inside it. */
.card-action-buttons[b-zb029wyn3c] {
    display: contents;
}

/* action-icon is deliberately not styled here. The svg is rendered by the icon
   child components, so it carries their scope id — a bare selector for it would
   compile with this component's scope attribute and match nothing. CardActions
   owns the sizing with a deep rule (ladder rung 3) and is the only renderer of
   this component. */
/* /Common/Components/UI/CardActions.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardActions.razor.css — scoped styles
   Moved from ContentListLayout.razor.css ::deep
   ═══════════════════════════════════════════ */

.card-actions[b-et195vntz1] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 1rem;
    background: var(--card-actions-bg);
    border-top: 1px dotted rgba(var(--line-rgb), 0.6);
}

/* action-icon is rendered by child components
   (CardActionButtons / icon components), so needs ::deep */
.card-actions[b-et195vntz1]  .action-icon {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
}

/* ─── List mode overrides ───
   ponytail: moved to ContentListLayout.razor.css — .card-grid--list is the
   ContentListLayout ancestor of CardActions, so a ::deep rule here can't match. */



/* ── List mode (driven by the ListView parameter, ladder rung 1) ──
   Moved from ContentListLayout.razor.css. The desktop block stays gated behind
   min-width: 769px so its min/max-width don't leak past the mobile override. */
@media (min-width: 769px) {
    .card-actions--list[b-et195vntz1] {
        border-top: none;
        border-left: 1px solid var(--card-border);
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        /* centre/0.35rem, not flex-start/0.3rem: CardGrid's
           `.card-grid--list ::deep .card-actions` outranked this block at
           (0,3,0), so those were the values that rendered. The ::deep rule is
           gone; the rendered values come home with it rather than the ones
           this file was quietly losing with. */
        align-items: center;
        align-content: center;
        justify-content: flex-end;
        gap: 0.35rem;
        padding: 0.5rem;
        width: 126px;
        min-width: 126px;
        max-width: 126px;
        box-sizing: border-box;
    }

    .card-actions--list button[b-et195vntz1] {
        flex: 0 0 auto;
    }

    /* .btn-icon-only keeps ::deep because CardActionButtons renders it. */
    .card-actions--list[b-et195vntz1]  .btn-icon-only {
        padding: 0.375rem;
    }
}

@media (max-width: 768px) {
    .card-actions--list[b-et195vntz1] {
        border-left: none;
        border-top: 1px solid var(--card-border);
        width: 100%;
        justify-content: stretch;
        gap: 0.75rem;
        padding: 0.75rem 1rem;
        flex-wrap: wrap;
        overflow: hidden;
    }
}
/* /Common/Components/UI/CardConditionGrid.razor.rz.scp.css */
/* The column count is FoeCardFrame's to decide: it drops to two on a narrow
   screen unless the card is pinned to the printable width, and `.fixed-width` is
   that component's class. It arrives as a custom property rather than through a
   ::deep rule, which would outrank this file on the property it owns. */
.status-grid[b-9gg3jseqlq] {
    display: grid;
    grid-template-columns: repeat(var(--foe-card-condition-columns, 4), 1fr);
    gap: 2px;
    margin: 4px 0;
}

.status-grid label[b-9gg3jseqlq] {
    display: flex;
    align-items: center;
    cursor: pointer;
    white-space: nowrap;
}

.status-grid label .checkbox[b-9gg3jseqlq] {
    border: 1px solid var(--foe-card-condition-border);
    height: 1em;
    width: 1em;
    margin-right: 8px;
}

.status-grid label.mark-immune[b-9gg3jseqlq] {
    text-decoration: line-through;
    color: var(--foe-card-condition-immune-color);
}

.status-grid label.mark-immune .checkbox[b-9gg3jseqlq] {
    display: none;
}

.status-grid label.mark-immune[b-9gg3jseqlq]::before {
    content: "";
    background-image: url('/lib/shield.svg');
    margin-right: 8px;
    height: 1em;
    width: 1em;
    background-size: 1em;
}

@media print {
    .status-grid label .checkbox[b-9gg3jseqlq] {
        border: 2px solid black !important;
        min-height: 1em;
        min-width: 1em;
        display: inline-block;
        box-sizing: border-box;
    }

    .status-grid label.mark-immune[b-9gg3jseqlq]::before {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}
/* /Common/Components/UI/CardContent.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardContent.razor.css — scoped styles
   Moved from ContentListLayout.razor.css ::deep
   ═══════════════════════════════════════════ */

.card-content[b-20mgfcgr1i] {
    padding: 1.5rem;
    padding-top: 1.75rem;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    flex: 1;
}

.card-content h3[b-20mgfcgr1i] {
    margin: 0 0 0.5rem 0;
    color: var(--text-color);
    font-family: var(--font-label);
    letter-spacing: 0.03em;
}

.card-content h3[b-20mgfcgr1i]::first-letter {
    color: var(--rubric);
}

.card-header-row[b-20mgfcgr1i] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.card-header-row h3[b-20mgfcgr1i] {
    margin: 0;
    flex: 1 1 auto;
    min-width: 0;
}

/* The thumbnail sits left of the title in both views. */
.card-portrait[b-20mgfcgr1i] {
    display: flex;
    flex: 0 0 auto;
}

.card-header-row .ownership-badge[b-20mgfcgr1i] {
    font-size: 0.65rem;
    padding: 0.15rem 0.4rem;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-family: var(--font-header);
    white-space: nowrap;
}

.card-type[b-20mgfcgr1i] {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin-bottom: 0.75rem;
    font-style: italic;
}

.card-type-inline[b-20mgfcgr1i] {
    display: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
    white-space: nowrap;
}

/* ─── Theme tags ─── */
.card-tags[b-20mgfcgr1i] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.5rem;
    width: 100%;
}
/* .card-tag moved to CardTag.razor.css (rung 2) with the markup. */

/* ─── List mode overrides ───
   ponytail: these were moved to ContentListLayout.razor.css. .card-grid--list is
   rendered by ContentListLayout (ancestor of CardContent), so a ::deep rule here
   can never match — the scope attribute lands on the wrong side of the
   ancestor/descendant relationship. ContentListLayout owns the list-mode layout. */

/* ─── Responsive: ≤480px ─── */
@media (max-width: 480px) {
    .card-content[b-20mgfcgr1i] {
        padding: 1rem;
        padding-top: 1.25rem;
        min-width: 0;
        overflow-wrap: break-word;
    }

    .card-content h3[b-20mgfcgr1i] {
        min-width: 0;
        overflow-wrap: break-word;
    }

    .card-header-row[b-20mgfcgr1i] {
        min-width: 0;
    }

    .card-header-row h3[b-20mgfcgr1i] {
        min-width: 0;
    }

    .card-type[b-20mgfcgr1i] {
        overflow-wrap: break-word;
    }
}

/* ── Reclaimed from base.css (ladder rung 1) ── */
.card-header-row .ownership-badge[b-20mgfcgr1i] {
    font-size: 0.65rem;
    padding: 0.15rem 0.4rem;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-family: var(--font-header);
    white-space: nowrap;
}

/* base.css also carried a `.card-type-inline` block. It was dead there — this
   file's scoped rule at the top outranked it — so it is NOT reclaimed here.
   Resurrecting it would have overridden that rule's font-size (0.85 -> 0.9rem). */

/* ── Reclaimed from base.css (ladder rung 1) ── */
/* The .card-footer-creator base rule moved to CardFooterCreator.razor.css
   (rung 2) with the markup; the list-mode layout below stays here. */

/* The Description slot renders <CardTeaserDescription> for its default, so the
   .card-teaser-description rule lives only in that component's scoped file
   (rung 2). A caller-supplied DescriptionClass renders a bare div this file
   deliberately does not style — the variant class is the caller's to own. */

/* ── List mode (driven by the ListView parameter, ladder rung 1) ──
   Moved from ContentListLayout.razor.css, which reached these elements with
   ::deep on the .card-grid--list ancestor. */
/* Teaser cards (tier-gated previews): compact chrome. Placed before the list
   block so a teaser card in list mode keeps the list layout on
   equal-specificity ties. */
.card-content--teaser[b-20mgfcgr1i] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem;
}

.card-content--list[b-20mgfcgr1i] {
    /* Handed down to CardStatsShell, which owns .card-stats and its
       margin-bottom. This file used to take the property from it with
       `.card-content--list ::deep .card-stats`. */
    --card-stats-margin-bottom: 0;
    flex: 1;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1.5rem;
    padding: 0.75rem 1rem 0.75rem 1.25rem;
}

/* teaser card stacks vertically; stretch keeps the description within the card
   width so the line-clamp engages and footer badges stay visible */
.card-content--list.card-content--teaser[b-20mgfcgr1i] {
    align-items: stretch;
}

.card-content--list h3[b-20mgfcgr1i] {
    margin: 0;
    white-space: nowrap;
}

.card-content--list .card-header-row[b-20mgfcgr1i] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    flex: 1 1 100%;
}

.card-content--list .card-header-row h3[b-20mgfcgr1i] {
    margin: 0;
    flex: 0 1 auto;
    min-width: 0;
}

.card-content--list .card-header-row .card-type-inline[b-20mgfcgr1i] {
    margin-right: 0;
}

/* ::deep: the badges are rendered by the Badge child component, so its root
   element carries Badge's scope id, not ours (rung 3). */
.card-content--list .card-header-row[b-20mgfcgr1i]  .badge-scheduled,
.card-content--list .card-header-row[b-20mgfcgr1i]  .badge-featured {
    margin-left: auto;
}

.card-content--list .card-type[b-20mgfcgr1i] {
    display: none;
}

.card-content--list .card-type-inline[b-20mgfcgr1i] {
    display: inline;
    margin-right: 0.5rem;
}

/* The list-mode footer row is CardFooterCreator's own
   `.card-footer-creator--list` now: the Footer slot renders that component
   with ListView, so the rule no longer reaches past its owner. */

.card-content--list .card-tags[b-20mgfcgr1i] {
    flex: 0 0 100%;
    margin-top: 0.5rem;
}

@media (max-width: 768px) {
    .card-content--list[b-20mgfcgr1i] {
        padding: 1rem;
    }
}

/* These targets are rendered by CHILD components of CardContent
   (FeaturedAvailabilityBadge, Badge, CreatorBadge) or by the page-supplied
   CardStats fragment, so they stay at ladder rung 3. */
.card-content--list .card-header-row[b-20mgfcgr1i]  .featured-availability-badge {
    margin-left: auto;
}

.card-content--list .card-header-row[b-20mgfcgr1i]  .featured-availability-badge ~ .badge-featured {
    margin-left: 0;
}

/* The pill treatment for the footer badge was a byte-identical copy of
   CreatorBadge's own `.card-footer-creator .creator-badge` rule — dead, since
   it could only ever restate what the owner already paints. Deleted rather
   than rehoused (working rule 4), along with its twin in the 480px block. */

/* The base.css narrow-screen .card-content rule is already covered by the
   @media block above — nothing to reclaim here. */
/* /Common/Components/UI/CardDescriptionStat.razor.rz.scp.css */
/* Reclaimed from base.css `.encounter-desc` (ladder rung 2). Its font-size and
   colour are not repeated here: they were the same values CardStatsShell's
   `::deep .stat` already sets at (0,2,0), which outranked the global rule at
   (0,1,0) at every one of the seven render sites — so the global rule only ever
   contributed the italic. */

.card-description[b-33xch9hf2c] {
    font-style: italic;
}
/* /Common/Components/UI/CardEmphasis.razor.rz.scp.css */
/* The two declarations both card sheets stated for their own row's `strong`.
   The colour arrives as a custom property: FoeCardFrame declares the per-system
   default, and a card row that wants a different ink re-declares the property on
   the row element, which is nearer than the frame and so wins for everything
   inside it without any specificity contest. */
.card-emphasis[b-eh067ezn19] {
    font-weight: 700;
    color: var(--foe-card-emphasis-color);
}
/* /Common/Components/UI/CardFooterCreator.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardFooterCreator.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)
   ═══════════════════════════════════════════ */

.card-footer-creator[b-5rgr4ppxnc] {
    border-top: 1px solid rgba(var(--shadow-rgb), 0.15);
    margin-top: auto;
    padding-top: 4px;
    text-align: right;
    opacity: 0.75;
}

/* ── List mode (driven by the ListView parameter, ladder rung 1) ──
   Reclaimed from CardContent's `.card-content--list ::deep .card-footer-creator`,
   which took margin-top and text-align off this file on every list card. */
.card-footer-creator--list[b-5rgr4ppxnc] {
    flex: 0 0 100%;
    margin-left: auto;
    margin-top: 0.25rem;
    text-align: right;
}
/* /Common/Components/UI/CardGrid.razor.rz.scp.css */
/* Card grid. Reclaimed from base.css (ladder rung 4 -> 2): seven components
   rendered the same wrapper, so the class was global only because the markup
   was duplicated. The list-mode block uses ::deep because the cards and their
   contents are slotted in by the caller (rung 3). */

.card-grid[b-aef5173zk5] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 1.5rem;
}

.card-grid--list[b-aef5173zk5] {
    grid-template-columns: 1fr;
    gap: 0.5rem;
}

@media (max-width: 480px) {
    .card-grid[b-aef5173zk5] {
        grid-template-columns: 1fr;
        gap: 1rem;
    }
}

/* ── List mode is the cards' own variant, not this file's reach ──
   The .card-content rules went home to CardContent on 2026-08-16; the card box
   and the actions column followed on 2026-08-17. Everything that used to sit
   here as `.card-grid--list ::deep .X` now lives in X's own sheet behind a
   ListView parameter — EntityCard's `.card-item--list` (box, stripe, hover)
   and CardActions' `.card-actions--list` (the 126px column). Those ::deep
   rules compiled to (0,3,0) against each owner's (0,2,0), so this file owned
   the whole list-mode card and neither owner's sheet described what rendered.
   This component styles its own grid root and nothing else. */
/* /Common/Components/UI/CardNameLine.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardNameLine.razor.css — scoped styles (ladder rung 2)
   The one statement of the selector-card name line. Was three copies:
   `.selectable-card .card-name` and `.selected-card .card-name` in
   ContentCardSelectorLayout.razor.css, `.foe-search-selector .result-card
   .card-name` in ContentSearchSelectorLayout.razor.css.
   ═══════════════════════════════════════════ */

.card-name[b-ir10882cyj] {
    /* The three declarations all three hosts agreed on. */
    font-weight: 600;
    color: var(--text-color);
    font-family: var(--font-header);

    /* Per-host geometry, handed down rather than reached back into with
       ::deep. `unset` is the no-op fallback: inherit for the inherited
       properties, initial for the rest. */
    margin-bottom: var(--card-name-margin-bottom, unset);
    flex: var(--card-name-flex, unset);
    padding-right: var(--card-name-padding-right, unset);
    /* One token, not two: the only host that wants wrapping wants the same
       value for both properties, and two names for one value is the alias
       NoBlockDeclaresTwoTokensWithTheSameValue exists to reject. */
    overflow-wrap: var(--card-name-wrap, unset);
    word-break: var(--card-name-wrap, unset);
}
/* /Common/Components/UI/CardSectionDivider.razor.rz.scp.css */
.section-divider[b-117a3cdhwj] {
    border-top: var(--foe-card-divider-rule, none);
    margin: 6px 0;
    height: 2px;
    background: var(--foe-card-divider-bg);
}
/* /Common/Components/UI/CardStatsShell.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardStatsShell.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 1 + rung 3)
   ═══════════════════════════════════════════ */

/* The shell's own root div. Slotted shapes vary: stat components
   (MonsterCardStats/EncounterCardStats/AdversaryCardStats) render their
   stat rows inside this shell, selector pages pass raw text fragments with
   no inner .card-stats div — both get their chrome from this bare rule. */
.card-stats[b-idvcrgl4ro] {
    display: flex;
    gap: 1rem;
    /* The list-mode row wants no gap under the stats. The shell is slotted in
       by the page's CardStats fragment (a RenderFragment<T>, so no call site
       can pass a flag down), and CardContent used to take the property with
       `.card-content--list ::deep .card-stats`. It hands the value down as a
       custom property instead — the same mechanism PrintSheet uses for its
       --eprint-* palette. A token handed down is not a collision. */
    margin-bottom: var(--card-stats-margin-bottom, 0.75rem);
    flex-wrap: wrap;
}

/* stat spans live in the slotted content, so they are a ::deep hook
   (rung 3). */
.card-stats[b-idvcrgl4ro]  .stat {
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* The description row is <CardDescriptionStat>, which owns its own italic at
   rung 1. The `::deep .stat.encounter-desc` rule that used to live here went
   with it. */
/* /Common/Components/UI/CardSubtype.razor.rz.scp.css */
.card-subtype[b-l1vcq66doc] {
    font-style: italic;
    color: var(--foe-card-subtype-color);
    margin-bottom: 3px;
}

.card-subtype--push-right[b-l1vcq66doc] {
    margin-left: auto;
}
/* /Common/Components/UI/CardTag.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardTag.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)
   ═══════════════════════════════════════════ */

.card-tag[b-nnnd6kwiv1] {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.5rem;
    border-radius: 4px;
    font-size: 0.7rem;
    font-family: var(--font-header);
    font-weight: 600;
    text-transform: uppercase;
    background: var(--filter-tag-bg);
    color: var(--filter-tag-color);
    white-space: nowrap;
}
/* /Common/Components/UI/CardTeaserDescription.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CardTeaserDescription.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)
   ═══════════════════════════════════════════ */

.card-teaser-description[b-jxqkmvk7h5] {
    color: var(--text-muted);
    font-size: 0.875rem;
    line-height: 1.4;
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* /Common/Components/UI/CardTitleRow.razor.rz.scp.css */
.card-title-row[b-o5pwpjjoz1] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: var(--foe-card-title-align, center);
    flex-direction: var(--foe-card-title-direction, row);
    justify-content: space-between;
    padding-bottom: 4px;
    border-bottom: var(--foe-card-title-rule-width, 2px) solid var(--foe-card-title-rule);
    margin-bottom: 4px;
    font-family: var(--foe-card-heading-font);
}

.card-header-right[b-o5pwpjjoz1] {
    display: flex;
    align-self: var(--foe-card-header-right-align, auto);
}

/* The name is written into the Left slot by the card, so the element belongs to
   the card and this rule needs ::deep to reach it. Both cards stated it
   identically apart from the colour, which is now the one token. It also reaches
   the `strong`s inside the Daggerheart threshold box, exactly as
   `.card-title-row strong` did in that sheet before the move. */
.card-title-row[b-o5pwpjjoz1]  strong {
    font-weight: 700;
    margin-right: 6px;
    color: var(--foe-card-title-strong-color);
    font-size: 1.1em;
}

@media print {
    /* Both sheets forced the rule to black on paper in plain mode. `!important`
       came with the rule; it beats the inline-free cascade only because the
       browser's own print sheet can lighten borders. */
    .foe-card-frame.print-plain .card-title-row[b-o5pwpjjoz1] {
        border-color: black !important;
    }
}
/* /Common/Components/UI/CardTrackingRow.razor.rz.scp.css */
.tracking-row[b-watl9b8a40] {
    margin-bottom: var(--foe-card-tracking-row-gap, 4px);
}

.tracking-group[b-watl9b8a40] {
    display: flex;
    align-items: center;
    gap: var(--foe-card-tracking-group-gap, 6px);
    flex-wrap: var(--foe-card-tracking-group-wrap, nowrap);
}

.tracking-label[b-watl9b8a40] {
    font-weight: 700;
    font-size: 0.9em;
    color: var(--foe-card-tracking-label-color);
    min-width: var(--foe-card-tracking-label-min, 0);
    white-space: var(--foe-card-tracking-label-wrap, normal);
}
/* /Common/Components/UI/ClearFiltersButton.razor.rz.scp.css */
/* Moved from base.css when this button became a component: the two rules only ever
   described this element, and rung 1 beats a global utility. */
.clear-filters[b-ebo6kpzadk] {
    align-self: flex-end;
    margin-left: auto;
}

@media (max-width: 768px) {
    .clear-filters[b-ebo6kpzadk] {
        width: 100%;
        margin-left: 0;
    }
}
/* /Common/Components/UI/CollapsibleFormSection.razor.rz.scp.css */
/* Collapsible header chrome only. The `.form-section` box (background, border,
   accent stripe) and the shared `h3` heading typography moved to
   FormSection.razor.css (Task 3, editor-chrome rung-2 plan) — this component
   now wraps `<FormSection>` and slots its own clickable header in as
   ChildContent, so only what's unique to *this* header (the pointer cursor,
   the flex layout, the toggle icon) stays here. `h3.form-section-toggle` is
   this component's own markup — a bare scoped selector reaches it directly,
   no `::deep` needed. */

.form-section-toggle[b-pff3tq5lxq] {
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    user-select: none;
}

.form-section-toggle:hover[b-pff3tq5lxq] {
    opacity: 0.8;
}

.section-toggle-icon[b-pff3tq5lxq] {
    margin-left: auto;
    padding-left: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-muted);
    flex-shrink: 0;
}
/* /Common/Components/UI/CollapsiblePanel.razor.rz.scp.css */
/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.scenario-panel[b-2ba7tjahjq] {
    position: relative;
    border: 1px solid var(--card-glass-border, var(--card-border));
    border-radius: 6px;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
}

.scenario-toggle[b-2ba7tjahjq] {
    width: 100%;
    padding: 0.75rem 1rem;
    background: var(--editor-highlight-bg);
    border: none;
    border-radius: 6px;
    color: var(--text-color);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    transition: background-color 0.15s;
}

.scenario-toggle:hover[b-2ba7tjahjq] {
    background: color-mix(in srgb, var(--editor-highlight-bg) 80%, var(--accent-color) 20%);
}

.scenario-content[b-2ba7tjahjq] {
    padding: 1rem;
}

/* Only reachable with KeepContentMounted — otherwise the body is not rendered. */
.scenario-content.collapsed[b-2ba7tjahjq] {
    display: none;
}
/* /Common/Components/UI/CompareActionItem.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CompareActionItem.razor.css — one clickable action in a compare cell
   Reclaimed from CompareLayout.razor.css (ladder rung 3 -> rung 1).
   The <li> and its name / meta / average spans were the same shape in
   MonsterCompareRows and AdversaryCompareRows; CompareLayout reached all
   four with ::deep. The item now authors every element it styles.
   ═══════════════════════════════════════════ */

.compare-action-item[b-mrourneu7e] {
    cursor: pointer;
    padding: 0.2rem 0.35rem;
    border-radius: 3px;
    border: 1px solid var(--card-border);
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    align-items: baseline;
    font-size: 0.85rem;
    background: var(--card-bg);
}

.compare-action-item:hover[b-mrourneu7e] {
    background: var(--editor-highlight-bg);
}

.compare-action-name[b-mrourneu7e] {
    font-weight: 600;
    color: var(--text-color);
}

.compare-action-meta[b-mrourneu7e] {
    color: var(--text-muted);
    font-size: 0.8rem;
}

.compare-action-avg[b-mrourneu7e] {
    font-weight: 700;
    color: var(--accent-color);
    margin-left: auto;
}

@media print {
    .compare-action-item[b-mrourneu7e] {
        cursor: default;
        border: none;
        padding: 0.1rem 0;
    }
}
/* /Common/Components/UI/CompareActionList.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   CompareActionList.razor.css — the <ul> of a compare cell's actions
   Reclaimed from CompareLayout.razor.css (ladder rung 3 -> rung 1).
   Monster/AdversaryCompareRows hand-rolled the list and CompareLayout
   reached it with ::deep; the list now owns its own element.
   ═══════════════════════════════════════════ */

.compare-action-list[b-rw9zk0d4bb] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}
/* /Common/Components/UI/CompareHeaderRow.razor.rz.scp.css */
/* Compare table header row — owned here so the rules land in this component's
   scope. Previously lived in CompareLayout.razor.css targeting page-rendered
   markup, where the scope attribute never matched. */
th[b-rnbepowb07] {
    background: var(--card-actions-bg);
    font-weight: 600;
    white-space: nowrap;
}

/* No `th.compare-row-label` rule: the label cell is rendered as a <td> by
   MonsterCompareRows and AdversaryCompareRows twenty-two times over as well as
   by the <th> here, so CompareLayout styles all of them from the table context
   it owns — and it already states this rule's colour and min-width verbatim.
   Keeping a copy here only outranked the layout with the same values. */

.compare-foe-name[b-rnbepowb07] {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text-color);
}

.compare-foe-subtitle[b-rnbepowb07] {
    font-size: 0.8rem;
    color: var(--text-muted);
    display: block;
}

.compare-remove-btn[b-rnbepowb07] {
    margin-top: 0.3rem;
    font-size: 0.75rem;
    padding: 0.15rem 0.4rem;
}

@media print {
    .compare-remove-btn[b-rnbepowb07] {
        display: none !important;
    }
}
/* /Common/Components/UI/CompareLayout.razor.rz.scp.css */
/* dissol: app.css Compare block → CompareLayout.razor.css (Task 9) */
.compare-page[b-0fyi0ayv26] {
    padding: 1rem;
}

.compare-table-scroll[b-0fyi0ayv26] {
    overflow-x: scroll;
    -webkit-overflow-scrolling: touch;
}

.compare-table[b-0fyi0ayv26] {
    width: 100%;
    border-collapse: collapse;
    min-width: 480px;
}

@media (max-width: 600px) {
    .compare-page[b-0fyi0ayv26] {
        padding: 0.5rem;
    }
}

@media print {
    @page {
        size: landscape;
    }

    .compare-page .compare-table-scroll[b-0fyi0ayv26] {
        overflow: visible;
    }

    .compare-page .compare-table[b-0fyi0ayv26] {
        min-width: unset;
    }
}

/* Header-row chrome (.compare-foe-name/-subtitle, .compare-remove-btn, thead th)
   is owned by CompareHeaderRow.razor.css; row cells are owned below via ::deep
   because the StatRows fragment is authored by the consuming page. */

/* ── Row cells, authored in the StatRows fragment (ladder rung 3) ──
   Moved from base.css; one definition for both systems' row components. */
[b-0fyi0ayv26] .compare-table td {
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--card-border);
    text-align: left;
    vertical-align: top;
    color: var(--text-color);
    background: var(--card-bg);
}

/* ── Row label column ── */
[b-0fyi0ayv26] .compare-row-label {
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    background: var(--card-actions-bg);
    min-width: 120px;
}

/* ── Even-row alternating background ── */
[b-0fyi0ayv26] .compare-table tbody tr:nth-child(even) td:not(.compare-row-label) {
    background: var(--editor-highlight-bg);
}

/* ── Stat highlighting ── */
[b-0fyi0ayv26] .compare-table td.compare-stat--highest {
    color: var(--compare-stat-highest);
    font-weight: 700;
}

[b-0fyi0ayv26] .compare-table td.compare-stat--lowest {
    color: var(--compare-stat-lowest);
    font-weight: 600;
}

/* ── Damage note (no actions) ── */
[b-0fyi0ayv26] .compare-damage-note {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-style: italic;
}


/* ── Action list ──
   Moved to Common/Components/UI/CompareActionList.razor.css and
   CompareActionItem.razor.css: the <ul>, the clickable <li> and its
   name / meta / average spans are now authored by those two components, so
   every one of those rules is a rung-1 bare selector in the file that owns
   the markup instead of a rung-3 ::deep reach from here. */

/* /Common/Components/UI/ContentCardSelectorLayout.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentCardSelectorLayout.razor.css — one copy for both card selectors
   (was duplicated verbatim in Monster/AdversarySelector.razor.css)
   Dissolved from wwwroot/css/foe-selector.css
   ═══════════════════════════════════════════ */

.card-selector-page[b-s7m454hfns] {
    padding: 1.5rem;
}

.card-selector-page h1[b-s7m454hfns] {
    margin-bottom: 0.5rem;
    font-family: var(--font-header);
}

.card-selector-page > p[b-s7m454hfns] {
    color: var(--text-muted);
    margin-bottom: 1.5rem;
}

.selector-container[b-s7m454hfns] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
}

/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.available-cards[b-s7m454hfns],
.selection-area[b-s7m454hfns] {
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    padding: 1rem;
    position: relative;
}

.available-cards[b-s7m454hfns]::before,
.selection-area[b-s7m454hfns]::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--accent-stripe);
    border-radius: 8px 8px 0 0;
}

.available-cards h2[b-s7m454hfns],
.selection-area h2[b-s7m454hfns] {
    font-size: 1.25rem;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid var(--accent-color);
    font-family: var(--font-header);
    color: var(--text-color);
}

/* The field itself is <SearchBox FullWidth> now. This file used to hand-roll
   SearchBox's markup — same div, same input — and then re-skin it here, which
   is the copy the ladder exists to stop: two components each maintaining half a
   search field, under one class name that a third (ContentSearchSelectorLayout)
   reached into through ::deep. All that is left is where the field sits. */
.selector-search[b-s7m454hfns] {
    margin-bottom: 1rem;
}

.card-list[b-s7m454hfns] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-height: 500px;
    overflow-y: auto;
}

.selectable-card[b-s7m454hfns] {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.75rem;
    cursor: grab;
    transition: all 0.2s ease;

    /* The name line is <CardNameLine> (rung 2). Its bottom gap is this card's
       business, so it travels down as a custom property. */
    --card-name-margin-bottom: 0.25rem;
}

.selectable-card:hover[b-s7m454hfns] {
    border-color: var(--focus-color);
    box-shadow: 0 2px 4px var(--selectable-hover-shadow);
}

.selectable-card:active[b-s7m454hfns] {
    cursor: grabbing;
}

.selectable-card .card-info[b-s7m454hfns] {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}

.selector-item--gated[b-s7m454hfns] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.25rem;
}

.drop-zone[b-s7m454hfns] {
    min-height: 300px;
    max-height: 500px;
    overflow-y: auto;
    background: var(--card-bg);
    border: 2px dashed var(--card-border);
    border-radius: 4px;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    transition: all 0.2s ease;
}

.drop-zone.drag-over[b-s7m454hfns] {
    border-color: var(--drop-zone-active-border);
    background: var(--drop-zone-active-bg);
}

.drop-hint[b-s7m454hfns] {
    color: var(--text-muted);
    text-align: center;
    margin: auto;
    font-size: 1.1rem;
    font-style: italic;
}

.selected-card[b-s7m454hfns] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.5rem 0.75rem;

    /* The name is the row's growing cell; <CardNameLine> reads the value. */
    --card-name-flex: 1;
}

.selected-card .card-info[b-s7m454hfns] {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}

.btn-remove[b-s7m454hfns] {
    background: var(--remove-btn-gradient);
    color: var(--on-danger-text);
    border: 1px solid var(--remove-btn-border);
    border-radius: 4px;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    transition: all 0.2s ease;
}

.btn-remove:hover[b-s7m454hfns] {
    background: var(--remove-btn-hover);
}

.selection-actions[b-s7m454hfns] {
    display: flex;
    gap: 1rem;
    margin-top: 1rem;
    justify-content: flex-end;
}

/* Touch drag-and-drop for mobile */
.selectable-card.touch-holding[b-s7m454hfns] {
    background: var(--drop-zone-active-bg);
    transform: scale(1.02);
}

.selectable-card.touch-dragging-source[b-s7m454hfns] {
    opacity: 0.4;
}

.touch-drag-ghost[b-s7m454hfns] {
    position: fixed;
    z-index: 10000;
    pointer-events: none;
    opacity: 0.85;
    transform: translate(-50%, 0) rotate(2deg);
    background: var(--card-bg);
    border: 2px solid var(--focus-color);
    border-radius: 4px;
    padding: 0.75rem;
    box-shadow: 0 8px 24px rgba(var(--shadow-rgb), 0.4);
}

.drop-zone.touch-drop-target[b-s7m454hfns] {
    border-color: var(--drop-zone-active-border);
    background: var(--drop-zone-active-bg);
    transform: scale(1.02);
}

@media (max-width: 900px) {
    .selector-container[b-s7m454hfns] {
        grid-template-columns: 1fr;
    }
}
/* /Common/Components/UI/ContentDisplayLayout.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentDisplayLayout.razor.css — scoped styles
   Layout container for foe display pages
   ═══════════════════════════════════════════ */

.foe-toolbar[b-d6obpaocl8] {
    margin-bottom: 0;
}

.foe-credit[b-d6obpaocl8] {
    margin-bottom: 0.5rem;
}

.foe-stat-row[b-d6obpaocl8] {
    margin-bottom: 1.5rem;
    /* On desktop MainLayout makes `.content` a fixed-height flex column. A flex
       item holding a scroll container would be shrunk to the leftover viewport
       height and the stat block would scroll inside it instead of running its
       full height (mobile has no flex column, hence the difference). Never
       shrink — the page scrolls instead. */
    flex-shrink: 0;
}

.foe-stat-block[b-d6obpaocl8] {
    /* Stat blocks carry a fixed Columns × 320px width so the columns stay
       readable. When that exceeds the viewport, scroll the slot instead of
       letting the stat block shrink its columns. */
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

/* The hero portrait shows only beside the stat block, from 1100px. */
.foe-portrait-aside[b-d6obpaocl8] {
    display: none;
}

@media (min-width: 1100px) {
    .foe-stat-row[b-d6obpaocl8] {
        display: flex;
        justify-content: center;
        align-items: flex-start;
        gap: 1.5rem;
    }

    /* Sized by the stat block's own width; may shrink below it (min-width: 0)
       so the slot scrolls rather than pushing the aside off the row. */
    .foe-stat-block[b-d6obpaocl8] {
        flex: 0 1 auto;
        min-width: 0;
    }

    .foe-portrait-aside[b-d6obpaocl8] {
        display: block;
        flex-shrink: 0;
    }
}

/* A scroll container clips at page boundaries — never scroll on paper. */
@media print {
    .foe-stat-block[b-d6obpaocl8] {
        overflow-x: visible;
    }
}

.foe-hub-content[b-d6obpaocl8] {
    margin-top: 1rem;
}

/* Shared max-width container for detail-page content */
.foe-toolbar[b-d6obpaocl8],
.foe-stat-row[b-d6obpaocl8],
.foe-hub-content[b-d6obpaocl8] {
    width: 100%;
}
/* /Common/Components/UI/ContentListLayout.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentListLayout.razor.css — scoped styles
   Dissolved from wwwroot/css/foe-list.css
   ═══════════════════════════════════════════ */

/* This component used to render the whole list shell and styled every part of
   it here. It now composes ListPage, SearchFilterContainer, SearchRow,
   FilterRow, CardGrid and EntityCard, each of which owns its own rules —
   .foe-list, .search-filter-container, .filter-row, .card-grid* and
   .card-item* were removed from this file because the elements they target no
   longer carry this component's scope attribute. */

/* ─── Active filters (container only; chip classes owned by ActiveFilterChips components) ─── */
.active-filters[b-3kvl4cvl92] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    margin-bottom: 1rem;
}
/* /Common/Components/UI/ContentPrintPreviewLayout.razor.rz.scp.css */
/* Print-preview chrome — one copy for both systems (was duplicated in
   Monster/AdversaryPrintPreview.razor.css, 295 lines each, differing only in
   the header font and one shadow tint; both now come from tokens.css). */
.print-preview-page[b-nanzj5x89g] {
    padding: 1rem;
}

.action-bar[b-nanzj5x89g] {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.5rem;
    padding: 1rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    flex-wrap: wrap;
}

/* Print mode selector styling */
/* The print-style picker is the shared <PrintSelector>. */

/* No `select:focus` rule: base.css owns focus styling for every form element
   (rung 4) and this repeated it verbatim. */

/* The scale controls sit in a <PrintControlGroup> (rung 2): the row, its label
   and the divider were the same declarations the print-style picker and the
   toggle bar stated, under three different class names. What stays here is the
   presets and the slider this layout renders itself. */

.scale-presets[b-nanzj5x89g] {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.btn-scale-preset[b-nanzj5x89g] {
    padding: 0.25rem 0.6rem;
    background-color: var(--card-bg);
    border: 1px solid var(--accent-color);
    border-radius: 4px;
    font-family: var(--font-body);
    font-size: 0.85rem;
    color: var(--accent-color);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.15s, color 0.15s;
}

.btn-scale-preset:hover[b-nanzj5x89g] {
    background-color: var(--accent-color);
    color: var(--on-primary-text);
}

.scale-manual[b-nanzj5x89g] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.scale-manual input[type="range"][b-nanzj5x89g] {
    width: 100px;
    accent-color: var(--accent-color);
    cursor: pointer;
}

.scale-manual .scale-value[b-nanzj5x89g] {
    font-family: var(--font-body);
    font-size: 0.9rem;
    color: var(--text-muted);
    min-width: 3rem;
    text-align: right;
}

.page-info[b-nanzj5x89g] {
    margin-left: auto;
    color: var(--text-muted);
    font-style: italic;
}

.loading-text[b-nanzj5x89g],
.empty-text[b-nanzj5x89g] {
    text-align: center;
    padding: 2rem;
    color: var(--text-muted);
    font-style: italic;
}

.empty-text a[b-nanzj5x89g] {
    color: var(--accent-color);
}

/* The off-screen measuring pass: cards are rendered at the page's printable
   width so JS can read their real heights before packing. Taken out of the flow
   and hidden rather than `display: none`, which would give every card a height
   of zero. Was an inline style attribute — rung 0. The number used to be a
   literal 194mm with a comment telling the next reader to keep it in step with
   .print-page; it is the same token those rules use now, so it cannot drift. */
.measuring-container[b-nanzj5x89g] {
    position: absolute;
    visibility: hidden;
    width: var(--print-printable-width);
}

/* The pages scroll sideways here, not on the document, when the viewport is
   narrower than a sheet. A block container on purpose: a flex centre line would
   clip the left edge of an over-wide page, while the pages' own `margin: auto`
   degrades to 0 and keeps every millimetre reachable. */
.print-pages[b-nanzj5x89g] {
    overflow-x: auto;
}

/* The sheet at 1:1 on every display — same tokens the packing algorithm
   measured against, so a page that fits in the preview fits on the paper. */
.print-page[b-nanzj5x89g] {
    width: var(--print-page-width);
    min-height: var(--print-page-height);
    margin: 0 auto 2rem auto;
    padding: var(--print-page-margin);
    background: white;
    box-shadow: 0 2px 8px var(--print-card-shadow);
    box-sizing: border-box;
    /* An outline, not a border: a border would take 2px off the 194mm content
       box and clip the right edge of a card pinned to the printable width. */
    outline: 1px solid var(--card-border);
}

/* One card per row, as PrintLayoutCalculator packs them (CardGap = 8mm). Not
   <CardGrid>: its auto-fill columns are narrower than a card pinned to the
   printable width, so the cards overlapped. Reads the scale the page sets
   inline as --card-scale. `zoom`, not `transform: scale`: print fragmentation
   follows the layout box, and a transform leaves it unscaled, so a scaled page
   was cut where the full-size cards would have ended. */
.print-card-stack[b-nanzj5x89g] {
    display: flex;
    flex-direction: column;
    gap: var(--print-page-margin);
    zoom: var(--card-scale, 1);
}

.print-card--restricted[b-nanzj5x89g] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    min-height: var(--print-placeholder-height);
    padding: 1rem;
    text-align: center;
    background: var(--card-bg);
    border: 2px dashed var(--card-border);
    border-radius: 8px;
}

.print-card--restricted h3[b-nanzj5x89g] {
    margin: 0;
    font-family: var(--font-header);
    color: var(--text-color);
}

.print-card--restricted p[b-nanzj5x89g] {
    margin: 0;
    color: var(--text-muted);
    font-style: italic;
}

/* Print styles */
@media print {
    @page {
        size: A4 portrait;
        margin: 0;
    }

    body[b-nanzj5x89g] {
        margin: 0;
        padding: 0;
        background: white;
    }

    .no-print[b-nanzj5x89g] {
        display: none !important;
    }

    .print-preview-page[b-nanzj5x89g] {
        padding: 0;
        background: white;
    }

    .print-page[b-nanzj5x89g] {
        width: var(--print-page-width);
        height: var(--print-page-height);
        margin: 0;
        padding: var(--print-page-margin);
        box-shadow: none;
        outline: none;
        page-break-after: always;
        page-break-inside: avoid;
    }

    .print-page:last-child[b-nanzj5x89g] {
        page-break-after: auto;
    }
}

/* Screen preview styling. One rule for every width now: the page used to stretch
   to 100% of the (up to 1400px) content column above 769px, which is far wider
   than the printable width the cards were measured at — the preview lied about
   where the page ended. */
@media screen {
    .print-page[b-nanzj5x89g] {
        outline: 1px solid var(--card-border);
        max-height: var(--print-page-height);  /* lock page to the sheet: the preview never shows more than one sheet holds */
        overflow: hidden;   /* content always fits (guaranteed by packing algorithm); this only guards a mis-measure */
    }
}

/* Responsive action bar */
@media (max-width: 768px) {
    .action-bar[b-nanzj5x89g] {
        flex-direction: column;
        align-items: stretch;
    }

    /* The `.print-mode-selector` block that sat here was dead: PrintSelector
       renders that div, so this file's copy carried the wrong scope id and the
       divider never turned horizontal. It is that component's `--bordered`
       variant now. */
    .page-info[b-nanzj5x89g] {
        margin-left: 0;
        text-align: center;
    }
}

/* The display-options bar is the shared <PrintDisplayOptions> component
   (rung 2): this layout and SinglePrintPreview shipped it verbatim. The
   toggles themselves are owned by ToggleOption.razor.css. */
/* /Common/Components/UI/ContentSearchSelectorLayout.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ContentSearchSelectorLayout.razor.css — chrome for the search-and-select pages.
   Was duplicated in MonsterCompareSelector / AdversayCompareSelector /
   ConversionSelector (448/448/431 lines, ~99% identical); this component now
   renders that DOM, so the rules live here once.
   ═══════════════════════════════════════════ */
/* ═══════════════════════════════════════════
   
   Dissolved from wwwroot/css/foe-selector.css
   ═══════════════════════════════════════════ */

.foe-search-selector[b-zocq70ycsl] {
    padding: 1rem;
}

/* --- Search bar (sticky) --- */
.foe-search-selector .search-bar[b-zocq70ycsl] {
    display: flex;
    gap: 1rem;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 1rem;
    position: sticky;
    top: 0;
    background: var(--page-bg);
    z-index: 10;
    padding: 0.75rem 0;
}

/* No `.search-box` rule: its sizing is SearchBox's own business (rung 1), and
   stating it here took flex, min-width and max-width off the component that
   renders the element — including the narrow-screen full-width variant, which
   is a `@media` block in SearchBox.razor.css now. */

/* Width only: the select's look is base.css's (rung 4), as for every other select. */
.foe-search-selector .search-bar .type-filter-inline[b-zocq70ycsl] {
    min-width: 150px;
}

.foe-search-selector .search-bar .filters-toggle-btn[b-zocq70ycsl] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    color: var(--text-color);
    cursor: pointer;
    white-space: nowrap;
}

.foe-search-selector .search-bar .filters-toggle-btn:hover[b-zocq70ycsl] {
    border-color: var(--focus-color);
}

.foe-search-selector .search-bar .filters-toggle-btn .filter-badge[b-zocq70ycsl] {
    background: var(--accent-color);
    color: var(--on-accent-text);
    border-radius: 50%;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
}

/* --- Filter drawer (collapsible) ---
   The whole drawer — surface, closed state and the open row layout — is
   <FilterDrawer>'s now. This file used to set `display: flex` on
   `.filter-drawer--open`, taking the property off the component that renders
   the element, and the gap and wrap with it. */



/* --- Results grid --- */
.foe-search-selector .results-grid[b-zocq70ycsl] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1.5rem;
    margin-bottom: 1rem;
    overflow: hidden;
}

/* --- Result cards --- */
/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.foe-search-selector .result-card[b-zocq70ycsl] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    border-radius: 8px;
    padding: 1rem;
    min-width: 0;
    overflow-wrap: break-word;
    cursor: pointer;
    transition: all 0.2s ease;
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, 0 1px 3px rgba(var(--shadow-rgb), 0.15));

    /* The name line is <CardNameLine> (rung 2). What is specific to this tile —
       the gap under the name, the padding that clears the checkbox overlay, and
       the long-name break rules — is handed down, not reached into. */
    --card-name-margin-bottom: 0.5rem;
    --card-name-padding-right: 2rem;
    --card-name-wrap: break-word;
}

.foe-search-selector .result-card:hover[b-zocq70ycsl] {
    border-color: var(--focus-color);
    box-shadow: 0 2px 8px var(--focus-shadow);
}

.foe-search-selector .result-card .checkbox-overlay[b-zocq70ycsl] {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 2;
}

.foe-search-selector .result-card .checkbox-overlay input[type="checkbox"][b-zocq70ycsl],
.foe-search-selector .result-card .checkbox-overlay input[type="radio"][b-zocq70ycsl] {
    appearance: auto;
    -webkit-appearance: auto;
    width: 1.25rem;
    height: 1.25rem;
    accent-color: var(--accent-color);
    cursor: pointer;
    border: initial;
    border-radius: initial;
    background: initial;
    box-shadow: none;
    transition: none;
    vertical-align: middle;
}

.foe-search-selector .result-card .checkbox-overlay input[type="checkbox"][b-zocq70ycsl]::before,
.foe-search-selector .result-card .checkbox-overlay input[type="radio"][b-zocq70ycsl]::before {
    content: none;
}

.foe-search-selector .result-card.selected[b-zocq70ycsl] {
    border-color: var(--accent-color);
    background: var(--accent-tint);
    box-shadow: inset 0 0 0 1px var(--accent-color);
}

.foe-search-selector .result-card[b-zocq70ycsl]  .card-stats {
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* --- Bottom bar (selected state) --- */
.foe-search-selector .selected-bar[b-zocq70ycsl] {
    display: flex;
    gap: 1rem;
    align-items: center;
    padding: 0.75rem 1rem;
    background: var(--card-bg);
    border-top: 1px solid var(--card-border);
    position: sticky;
    bottom: 0;
    z-index: 20;
}

.foe-search-selector .selected-bar .count-badge[b-zocq70ycsl] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    color: var(--text-color);
    cursor: pointer;
}

.foe-search-selector .selected-bar .count-badge[b-zocq70ycsl]::before {
    content: '🛡';
}

.foe-search-selector .selected-bar .action-btn[b-zocq70ycsl] {
    margin-left: auto;
    padding: 0.5rem 1rem;
    background: var(--accent-color);
    color: var(--on-accent-text);
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-weight: 600;
}

.foe-search-selector .selected-bar .action-btn:disabled[b-zocq70ycsl] {
    opacity: 0.5;
    cursor: not-allowed;
}

.foe-search-selector .selected-bar .clear-btn[b-zocq70ycsl] {
    padding: 0.5rem;
    background: transparent;
    border: 1px solid var(--card-border);
    border-radius: 4px;
    color: var(--text-muted);
    cursor: pointer;
}

.foe-search-selector .selected-bar .clear-btn:hover[b-zocq70ycsl] {
    border-color: var(--focus-color);
    color: var(--text-color);
}

/* --- Mobile selection drawer (bottom sheet) --- */
.foe-search-selector .mobile-selection-drawer[b-zocq70ycsl] {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: var(--card-bg);
    border-top: 1px solid var(--card-border);
    border-radius: 12px 12px 0 0;
    padding: 1rem;
    z-index: 30;
    max-height: 50vh;
    overflow-y: auto;
    box-shadow: 0 -4px 12px rgba(var(--shadow-rgb), 0.3);
}

.foe-search-selector .mobile-selection-drawer.open[b-zocq70ycsl] {
    display: block;
}

.foe-search-selector .mobile-selection-drawer .drawer-handle[b-zocq70ycsl] {
    width: 40px;
    height: 4px;
    background: var(--text-muted);
    border-radius: 2px;
    margin: 0 auto 1rem;
}

.foe-search-selector .mobile-selection-drawer .selected-chips[b-zocq70ycsl] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.foe-search-selector .mobile-selection-drawer .selected-chip[b-zocq70ycsl] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: var(--accent-tint);
    border: 1px solid var(--accent-color);
    border-radius: 16px;
    font-size: 0.9rem;
    color: var(--text-color);
}

.foe-search-selector .mobile-selection-drawer .selected-chip .remove-chip[b-zocq70ycsl] {
    cursor: pointer;
    font-weight: 600;
    color: var(--text-muted);
}

.foe-search-selector .mobile-selection-drawer .drawer-actions[b-zocq70ycsl] {
    display: flex;
    gap: 1rem;
    justify-content: flex-end;
}

/* Pagination is the <Pagination> atom — it styles itself (Pagination.razor.css). */

/* --- Responsive: mobile-first, breakpoints at 768px and 480px --- */
@media (max-width: 768px) {
    .foe-search-selector[b-zocq70ycsl] {
        padding: 0.5rem;
    }

    .foe-search-selector .search-bar[b-zocq70ycsl] {
        flex-direction: column;
        align-items: stretch;
    }

    .foe-search-selector .search-bar .type-filter-inline[b-zocq70ycsl] {
        width: 100%;
    }

    /* The drawer's narrow-screen stacking went with the rest of its layout,
       into FilterDrawer.razor.css. */


    .foe-search-selector .results-grid[b-zocq70ycsl] {
        grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
        gap: 1rem;
    }

    .foe-search-selector .selected-bar[b-zocq70ycsl] {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        padding: 0.75rem;
    }

    .foe-search-selector .mobile-selection-drawer.open[b-zocq70ycsl] {
        display: block;
    }
}

@media (max-width: 480px) {
    .foe-search-selector .results-grid[b-zocq70ycsl] {
        grid-template-columns: 1fr 1fr;
    }

    .foe-search-selector .result-card[b-zocq70ycsl] {
        padding: 0.75rem;
    }

    .foe-search-selector .result-card .checkbox-overlay input[type="checkbox"][b-zocq70ycsl] {
        width: 1.25rem;
        height: 1.25rem;
    }
}

/* ── Reclaimed from base.css (ladder rung 3: authored in a supplied fragment / child) ──
   ::deep sits directly after `.foe-search-selector`: the drawer element itself is
   rendered by <FilterDrawer>, so it carries that component's scope id, not ours.
   Scoping on `.filter-drawer` would put our id on an element we do not render. */
/* `min-width: 150px` was a copy of the value FilterGroup already states on its
   own root, so it decided nothing — deleted rather than moved into a variant
   (working rule 4). `flex` is a property the owner does not set: how a slot
   shares the drawer's row is this layout's business. */
.foe-search-selector[b-zocq70ycsl]  .filter-drawer .filter-group {
    flex: 1;
}
.foe-search-selector[b-zocq70ycsl]  .filter-drawer .filter-group label {
    display: block;
    margin-bottom: 0.25rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}
/* No `.filter-drawer .filter-group input` rule: nothing renders one. Every
   filter drawer in the app slots selects and chip rows into <FilterGroup>, so
   this was five declarations of input skin reaching an element that does not
   exist — and it would have restated base.css's element vocabulary at
   (0,3,1) if it ever did. Element subjects are guarded by
   CssElementCollisionTests now. */
/* `.range-inputs` left on 2026-08-20: the flex row was a ::deep rule for a
   class this layout does not render and two components did. Both render
   <RangeFilterGroup> now, which owns the rule at rung 1. */
/* The narrow-screen `width: 100%` on the slotted group was the same copy:
   FilterGroup states it in its own @media block. Deleted, not moved. */
/* /Common/Components/UI/CountdownTrack.razor.rz.scp.css */
.countdown-track[b-v7t55n90ft] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.countdown-track__box[b-v7t55n90ft] {
    width: 1.5rem;
    height: 1.5rem;
    border: 2px solid var(--eprint-value, var(--text-color));
    border-radius: 0.2rem;
    background: transparent;
}
/* /Common/Components/UI/DaggerheartBudgetBreakdown.razor.rz.scp.css */
/* Daggerheart budget breakdown rows — moved from base.css + DaggerheartDifficultyBudget.razor.css
   with the markup (ladder rung 1). */
.difficulty-breakdown[b-b7ehwuo1ik] {
    margin-top: 0.6rem;
    font-size: 0.8rem;
    color: var(--text-color);
}

.breakdown-row[b-b7ehwuo1ik] {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.15rem 0;
    gap: 0.5rem;
}

.breakdown-spent[b-b7ehwuo1ik] {
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.breakdown-formula[b-b7ehwuo1ik] {
    color: var(--text-muted);
    font-weight: 400;
}

.breakdown-divider[b-b7ehwuo1ik] {
    border-top: 1px solid var(--card-border);
    margin: 0.3rem 0;
}

.breakdown-thresholds[b-b7ehwuo1ik] {
    color: var(--text-muted);
    flex-wrap: wrap;
}

.breakdown-adj span:first-child[b-b7ehwuo1ik] {
    color: var(--text-muted);
}

.adj-positive[b-b7ehwuo1ik] { color: var(--difficulty-easy-bar); font-weight: 600; }
.adj-negative[b-b7ehwuo1ik] { color: var(--difficulty-hard-bar); font-weight: 600; }
/* /Common/Components/UI/DetailToolbar.razor.rz.scp.css */
/* Strip chrome, owned by the component that renders it. Values moved verbatim
   from ContentActionPanel.razor.css, which defined them for markup it never renders
   (it renders .action-strip) while four other components hand-wrote the DOM. */
.action-nav-strip[b-16o6dk23ex] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-bottom: 0.75rem;
    flex-wrap: wrap;
}

.action-primary-strip[b-16o6dk23ex] {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.75rem;
    flex-wrap: wrap;
}

/* .action-group moved to ActionGroup.razor.css (rung 2) with the markup —
   ContentActionPanel carried a byte-identical copy of this rule. */
/* /Common/Components/UI/DiceOption.razor.rz.scp.css */
.wizard-dice-option[b-ohpkrupc23] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-color);
    font-size: 0.9rem;
}

.wizard-dice-avg[b-ohpkrupc23] {
    color: var(--text-muted);
    font-size: 0.8em;
}
/* /Common/Components/UI/DifficultyBadge.razor.rz.scp.css */
.difficulty-value[b-9qptcdq6z4] {
    font-weight: 700;
    font-size: 0.9rem;
    padding: 0.1rem 0.5rem;
    border-radius: 3px;
}

/* Reclaimed from EncounterCardStats' `.alternate-match-badge ::deep
   .difficulty-value`, which took font-size and padding off this file on every
   encounter card that shows an alternate match. */
.difficulty-value--compact[b-9qptcdq6z4] {
    font-size: 0.75rem;
    padding: 0.1rem 0.4rem;
}
/* /Common/Components/UI/DifficultyBar.razor.rz.scp.css */
.difficulty-bar[b-33usbh2mgf] {
    height: 6px;
    background: var(--card-border);
    border-radius: 3px;
    overflow: hidden;
}

.difficulty-bar-fill[b-33usbh2mgf] {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s ease;
}

.difficulty-bar-fill.difficulty-trivial[b-33usbh2mgf],
.difficulty-bar-fill.difficulty-easy[b-33usbh2mgf],
.difficulty-bar-fill.difficulty-low[b-33usbh2mgf] {
    background: var(--difficulty-easy-bar);
}

.difficulty-bar-fill.difficulty-medium[b-33usbh2mgf],
.difficulty-bar-fill.difficulty-moderate[b-33usbh2mgf],
.difficulty-bar-fill.difficulty-standard[b-33usbh2mgf] {
    background: var(--difficulty-moderate-bar);
}

.difficulty-bar-fill.difficulty-high[b-33usbh2mgf] {
    background: var(--difficulty-hard-bar);
}

.difficulty-bar-fill.difficulty-hard[b-33usbh2mgf] {
    background: var(--difficulty-hard-bar);
}

.difficulty-bar-fill.difficulty-deadly[b-33usbh2mgf],
.difficulty-bar-fill.difficulty-overwhelming[b-33usbh2mgf] {
    background: var(--difficulty-deadly-bar);
}
/* /Common/Components/UI/DifficultyChip.razor.rz.scp.css */
.difficulty-badge[b-dvhszhcf5i] {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.15rem 0.5rem;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Palette. Both former renderers (BuilderDifficultyMeter, EncounterBuilder) carried
   an identical copy of these rules. */
.difficulty-badge.difficulty-trivial[b-dvhszhcf5i],
.difficulty-badge.difficulty-easy[b-dvhszhcf5i],
.difficulty-badge.difficulty-low[b-dvhszhcf5i] { background: var(--difficulty-easy-bg); color: var(--difficulty-easy-text); }
.difficulty-badge.difficulty-medium[b-dvhszhcf5i],
.difficulty-badge.difficulty-moderate[b-dvhszhcf5i],
.difficulty-badge.difficulty-standard[b-dvhszhcf5i] { background: var(--difficulty-moderate-bg); color: var(--difficulty-moderate-text); }
.difficulty-badge.difficulty-high[b-dvhszhcf5i] { background: var(--difficulty-hard-bg); color: var(--difficulty-hard-text); }
.difficulty-badge.difficulty-hard[b-dvhszhcf5i] { background: var(--difficulty-hard-bg); color: var(--difficulty-hard-text); }
.difficulty-badge.difficulty-deadly[b-dvhszhcf5i],
.difficulty-badge.difficulty-overwhelming[b-dvhszhcf5i] { background: var(--difficulty-deadly-bg); color: var(--difficulty-deadly-text); }

/* The environment-mismatch warning chip. Not a difficulty tier — "harsh" is this
   app's own term, rendered as Label.EnvironmentWarningMismatch ("Harsh
   Environment"). Uses the moderate/amber pair because it warns rather than rates. */
.difficulty-badge.difficulty-harsh[b-dvhszhcf5i] { background: var(--difficulty-moderate-bg); color: var(--difficulty-moderate-text); }
/* /Common/Components/UI/DifficultyDescription.razor.rz.scp.css */
.difficulty-description[b-h5sqwamdrq] {
    font-size: 0.8rem;
    color: var(--text-color);
    margin-bottom: 0.4rem;
}
/* /Common/Components/UI/DifficultyReadout.razor.rz.scp.css */
.difficulty-row[b-cmtjssaeqz] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.25rem;
}

.difficulty-label[b-cmtjssaeqz] {
    font-size: 0.85rem;
    color: var(--text-color);
    font-weight: 600;
}
/* /Common/Components/UI/DifficultyScale.razor.rz.scp.css */
.difficulty-scale[b-fq2ga582wl] {
    font-size: 0.8rem;
    color: var(--text-color);
}

.difficulty-scale-head[b-fq2ga582wl] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.5rem;
    margin-bottom: 0.4rem;
}

.difficulty-scale-label[b-fq2ga582wl] {
    font-weight: 600;
}

.difficulty-scale-value[b-fq2ga582wl] {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

.difficulty-scale-meter[b-fq2ga582wl] {
    position: relative;
    height: 12px;
}

.difficulty-scale-track[b-fq2ga582wl] {
    position: absolute;
    inset: 0;
    border-radius: 6px;
    overflow: hidden;
    background: var(--card-border);
}

/* Bands: dimmed, the current one at full strength. The difficulty-<label> class
   is composed at runtime from the band's label. */
.difficulty-scale-band[b-fq2ga582wl] {
    position: absolute;
    top: 0;
    bottom: 0;
    opacity: 0.35;
}

.difficulty-scale-band--current[b-fq2ga582wl] {
    opacity: 1;
}

.difficulty-scale-band.difficulty-trivial[b-fq2ga582wl],
.difficulty-scale-band.difficulty-easy[b-fq2ga582wl],
.difficulty-scale-band.difficulty-low[b-fq2ga582wl] {
    background: var(--difficulty-easy-bar);
}

.difficulty-scale-band.difficulty-moderate[b-fq2ga582wl],
.difficulty-scale-band.difficulty-standard[b-fq2ga582wl] {
    background: var(--difficulty-moderate-bar);
}

.difficulty-scale-band.difficulty-hard[b-fq2ga582wl] {
    background: var(--difficulty-hard-bar);
}

.difficulty-scale-band.difficulty-overwhelming[b-fq2ga582wl] {
    background: var(--difficulty-deadly-bar);
}

.difficulty-scale-tick[b-fq2ga582wl] {
    position: absolute;
    top: -3px;
    bottom: -3px;
    border-left: 1px dashed var(--text-color);
    opacity: 0.6;
}

.difficulty-scale-pointer[b-fq2ga582wl] {
    position: absolute;
    top: -4px;
    bottom: -4px;
    width: 4px;
    border-radius: 2px;
    background: var(--text-color);
    box-shadow: 0 0 0 1px var(--card-bg);
    transform: translateX(-50%);
    transition: left 0.3s ease;
}

.difficulty-scale-markers[b-fq2ga582wl] {
    position: relative;
    height: 1.1rem;
    margin-top: 0.2rem;
}

.difficulty-scale-marker[b-fq2ga582wl] {
    position: absolute;
    transform: translateX(-50%);
    font-size: 0.7rem;
    color: var(--text-muted);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* /Common/Components/UI/DisplayPage.razor.rz.scp.css */
/* The detail-page wrapper, the display-side sibling of ListPage. EnvironmentDisplay
   and SinglePrintPreview each carried a byte-identical copy of these rules
   (ladder rung 2: same DOM shape in two components means extract the component,
   not duplicate the CSS). Caller-specific sizing — SinglePrintPreview's narrow
   -screen padding — stays with the caller, reached with ::deep. */

.foe-display[b-2r9sul941v] {
    padding: 2rem;
}

@media print {
    .foe-display[b-2r9sul941v] {
        padding: 0;
        max-width: none;
    }
}

/* SinglePrintPreview's narrow-screen sizing. It cannot live in that component:
   this wrapper is the outermost element it renders, so there is no ancestor
   carrying its scope id for a ::deep rule to hang off. It travels as a modifier
   class instead. */
@media screen and (max-width: 768px) {
    .foe-display--compact[b-2r9sul941v] {
        padding: 0.25rem;
        max-width: 100%;
    }
}
/* /Common/Components/UI/DropdownBackdrop.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   DropdownBackdrop.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)
   ═══════════════════════════════════════════ */

.dropdown-backdrop[b-a47eijpzod] {
    position: fixed;
    inset: 0;
    z-index: 105;
}

/* Nav variant: SystemNav's sidebar dropdown sits at z-index 1000, so its
   backdrop must cover the rest of the UI above the generic 105 layer. */
.dropdown-backdrop--nav[b-a47eijpzod] {
    z-index: 999;
}
/* /Common/Components/UI/DropdownPanel.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   DropdownPanel.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 2)
   ═══════════════════════════════════════════ */

.multiselect-panel[b-ao0ehsqaqr] {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    min-width: 220px;
    /* --bg-input, not --card-bg: this panel IS an option list, and the native
       <option> popup a plain <select> opens is painted --bg-input by base.css.
       A filter drawer shows both side by side. */
    background: var(--bg-input);
    border: 1px solid var(--input-border);
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.2);
    z-index: 110;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Reclaimed from BuilderSearchPanel's `::deep .multiselect-panel`, which took
   min-width off this file inside the builder's narrow column. Its `left: 0` is
   not here: this rule already sets it to the same value, so that declaration
   decided nothing and is deleted rather than moved (working rule 4). */
.multiselect-panel--full[b-ao0ehsqaqr] {
    right: 0;
    min-width: 0;
    max-width: 100%;
    width: auto;
}
/* /Common/Components/UI/EditorActions.razor.rz.scp.css */
/* Save is the row's main action: quiet like the rest, set apart by the accent colour. */
.editor-save[b-lkoox961zy] {
    color: var(--heading-accent);
    font-weight: 600;
}
/* /Common/Components/UI/EmptyState.razor.rz.scp.css */
.empty-state[b-ssy6866wtu] {
    text-align: center;
    padding: 3rem 1.5rem;
    color: var(--text-muted);
    font-size: 1.1rem;
}

@media (min-width: 641px) {
    .empty-state[b-ssy6866wtu] {
        padding: 4rem 2rem;
    }
}

/* ::deep: callers slot in their own heading/copy (ContentBundleList,
   ContentBundleDisplay, …), so those elements carry the caller's scope id.
   Reclaimed from base.css `.empty-state h3` / `.empty-state p`. */
/* Spacing only — the header font and --text-color are base.css's word on every
   heading in the app (rung 4). */
[b-ssy6866wtu] h3 {
    margin: 0 0 0.5rem 0;
}

[b-ssy6866wtu] p {
    color: var(--text-muted);
    margin: 0 0 1.5rem 0;
}
/* /Common/Components/UI/EntityCard.razor.rz.scp.css */
/* Card shell. Reclaimed from base.css (ladder rung 4 -> 2): six components
   rendered `<div class="card-item">` around their own body markup. */

.card-item[b-13mc5nqxx7] {
    border: 1px solid var(--card-glass-border, var(--card-border));
    border-radius: var(--radius-md);
    overflow: hidden;
    /* Glass where the theme declares it (GlassLayer blurs the art behind; sheen,
       rim and float shadow carry the look on the plain page); solid elsewhere. */
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    /* Muted text stays readable over the art showing through (tokens.css). */
    --text-muted: var(--card-glass-muted);
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, var(--elevation-1));
    transition: transform var(--transition-base), box-shadow var(--transition-base);
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

/* Keyboard focus lands on the inner link; lift the whole card and ring it so
   tab-through is as legible as hover. */
.card-item:focus-within[b-13mc5nqxx7] {
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--focus-ring), var(--elevation-2);
}

.card-item[b-13mc5nqxx7]::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--accent-stripe);
}

.card-item:hover[b-13mc5nqxx7] {
    transform: translateY(-4px);
    box-shadow: var(--card-glass-rim, 0 0 transparent), 0 4px 12px var(--hover-shadow);
}

/* ── Deckled folio (grid view): the torn edge and the glass are GlassLayer's;
   the card keeps no box of its own, only room for the torn strip. ── */
.card-item--deckled[b-13mc5nqxx7] {
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    padding-bottom: 12px;
}

.card-item--deckled[b-13mc5nqxx7]::before {
    content: none;
}

.card-item--deckled:hover[b-13mc5nqxx7],
.card-item--deckled:focus-within[b-13mc5nqxx7] {
    box-shadow: none;
}

.card-item--deckled:focus-within[b-13mc5nqxx7] {
    outline: 2px solid var(--focus-color);
    outline-offset: -4px;
}

/* ── List mode (driven by the ListView parameter, ladder rung 1) ──
   Reclaimed from CardGrid.razor.css, which set all of this through
   `.card-grid--list ::deep .card-item` at (0,3,0) and so owned the card box
   whenever a page switched to list view. */
@media (min-width: 769px) {
    .card-item--list[b-13mc5nqxx7] {
        display: flex;
        flex-direction: row;
        align-items: stretch;
        /* A row, not a floating tile — no resting lift, only the glass rim.
           Focus-within still rings it for keyboard users. */
        box-shadow: var(--card-glass-rim, none);
    }

    .card-item--list[b-13mc5nqxx7]::before {
        top: 0;
        bottom: 0;
        right: auto;
        width: 4px;
        height: auto;
        border-radius: 8px 0 0 8px;
    }

    .card-item--list:hover[b-13mc5nqxx7] {
        transform: none;
        box-shadow: var(--card-glass-rim, none);
    }
}

@media (max-width: 768px) {
    .card-item--list[b-13mc5nqxx7] {
        flex-direction: column;
    }

    .card-item--list[b-13mc5nqxx7]::before {
        width: auto;
        height: 4px;
        top: 0;
        bottom: auto;
        right: 0;
        border-radius: 8px 8px 0 0;
    }
}
/* /Common/Components/UI/EntityHub.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   EntityHub.razor.css — hub chrome, defined once
   Reclaimed from base.css (ladder rungs 2 + 3)

   Everything except .entity-hub itself is authored inside the consuming
   hub component, so it carries that consumer's scope and needs ::deep.

   .linked-foe-chip stays in base.css: Monster/AdversaryLinkedFoesSection
   and EnvironmentEdit render it outside any .entity-hub.
   ═══════════════════════════════════════════ */

.entity-hub[b-y3mxjnwioq] {
    margin-top: 2rem;
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

/* The card box, its <h4> and its body paragraphs moved to
   Common/Components/UI/HubCard.razor.css: HubCard now authors the
   `<div class="hub-card"><h4>` itself, so those dropped from this file's
   rung-3 ::deep to rung 1 there. `.hub-section` stays here — the hub sections
   are authored by the consuming hub component, not by HubCard. */

/* `.hub-section` is <HubSection>'s own element now (rung 2), so its min-width
   lives in that component's sheet rather than being reached from here. */

/* The hint line and the tag chips are <HubHint>, <HubTagList> and <HubTag> now
   (rung 2). They were styled here with ::deep on markup this component's
   CONSUMERS render — MonsterHubContent, AdversaryHubContent and, outside any
   .entity-hub at all, EncounterDisplay, which carried its own byte-identical
   copies. Ownership was inverted: a Common component theming three slices' DOM,
   with neither side's file readable on its own. */

/* The linked-foe chip row went to <ContentConnectionsHubCard> with the markup
   (rung 3 -> rung 1): both hubs render that component now. */

/* The tighter row spacing inside the cross-link section is FormField's
   `form-group--tight` variant, passed by CrossLinkSection. It used to be set
   from here, which took margin-bottom off the component that renders the
   element — the collision CssPropertyCollisionTests exists to catch. */

@media screen and (max-width: 768px) {
    .entity-hub[b-y3mxjnwioq] { grid-template-columns: minmax(0, 1fr); }
    /* `.btn` is a global utility rendered by the slotted content, not by
       HubCard — tuning it inside this grid is this component's job. */
    [b-y3mxjnwioq] .hub-card .btn { white-space: normal; word-break: break-word; }
    [b-y3mxjnwioq] .cross-link-section .form-group .form-control { width: 100%; max-width: 100%; }

    /* The `.hub-section-group` narrow-screen rules moved to
       MonsterHubContent.razor.css: that component renders the grid and states
       its grid-template-columns, so setting the same property from here took
       it off the owner. Adversary renders no .hub-section-group at all. */
}
/* /Common/Components/UI/FilterDrawer.razor.rz.scp.css */
.filter-drawer[b-svum9o6gxe] {
    display: none;
    padding: 1rem;
    background-color: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    margin-bottom: 1rem;
}

/* The open drawer is a wrapping row. Reclaimed from ContentSearchSelectorLayout,
   which set `display: flex` on this very class through ::deep at (0,3,0) — the
   layout's comment even explained that it could not put `display` on the base
   selector without pinning the drawer open, which is the sign the rule belonged
   to the owner. This component has one consumer, so the `display: block` that
   used to sit here never rendered anywhere; the row layout it lost to comes
   home instead of being restated from outside. */
.filter-drawer--open[b-svum9o6gxe] {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

@media (max-width: 768px) {
    .filter-drawer--open[b-svum9o6gxe] {
        flex-direction: column;
    }
}
/* /Common/Components/UI/FilterGroup.razor.rz.scp.css */
/* One labelled filter control. Reclaimed from base.css (ladder rung 4 -> 2):
   seven components rendered this div, 41 times between them.
   The label and control are slotted in by the caller, hence ::deep (rung 3).

   MultiSelectDropdown keeps an equivalent rule on its own root: it composes
   `filter-group` onto the element it renders itself, so it is rung 1 there. */

.filter-group[b-uxv0tmojom] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 150px;
}

[b-uxv0tmojom] label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-color);
    font-family: var(--font-header);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* Only the affordance, never the skin. `base.css` owns what a select looks like
   — padding, font, background, border, radius — for every form element in the
   app (rung 4), and this file used to restate all five with different values.
   `::deep select` compiles to `[b-filtergroup] select` (0,1,1) against
   `.form-control`'s (0,1,0), so the filter dropdowns silently won and were the
   only form controls in the app rendering on `--card-bg`. Same defect the
   FormField lane deleted from ContentEditorShell, EncounterBuilder and
   FoePickerLayout; this one hid behind an element selector, where the
   class-keyed collision guard could not see it. `CssElementCollisionTests`
   reads element subjects now. */
[b-uxv0tmojom] select {
    cursor: pointer;
}

/* No `select:focus` rule: base.css owns focus styling for every form element
   (rung 4) and this repeated it verbatim. */

@media (max-width: 768px) {
    .filter-group[b-uxv0tmojom] {
        width: 100%;
    }
}
/* /Common/Components/UI/FilterRow.razor.rz.scp.css */
/* Reclaimed from base.css (ladder rung 4 -> 2): ContentListLayout and
   ContentBundleList rendered the same row. */

.filter-row[b-ei8he7258f] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-end;
    justify-content: space-between;
    padding: 1rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    margin-bottom: 1rem;
}

@media (max-width: 768px) {
    .filter-row[b-ei8he7258f] {
        flex-direction: column;
        max-height: 70vh;
        overflow-y: auto;
    }
}
/* /Common/Components/UI/FilterTag.razor.rz.scp.css */
.filter-tag[b-t36ngmtdud] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.25rem 0.5rem;
    background: var(--filter-tag-bg);
    color: var(--filter-tag-color);
    border-radius: 4px;
    font-size: 0.8rem;
    font-family: var(--font-header);
    font-weight: 600;
}

.filter-tag button[b-t36ngmtdud] {
    background: none;
    border: none;
    color: var(--filter-tag-color);
    cursor: pointer;
    padding: 0 0.25rem;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
}

.filter-tag button:hover[b-t36ngmtdud] {
    opacity: 1;
}
/* /Common/Components/UI/FoeCardFrame.razor.rz.scp.css */
/* Printed stat-block card frame — the five rule blocks that opened both
   MonsterContent.razor.css and AdversaryContent.razor.css unchanged apart from
   the root class name and the tokens each read.

   The per-system values arrive through the modifier classes below rather than
   through the .dnd-theme / .dh-theme wrappers in tokens.css. Those wrappers were
   the other candidate and would keep this sheet free of --mm-* / --dh-* names,
   but OgRenderLayout renders these cards with no theme wrapper anywhere in the
   document — every --mm-* / --dh-* token is declared on :root precisely so that
   surface still paints — so hanging the card palette off the wrapper would
   leave the OG images unpainted. The modifier keeps the values on the element
   itself, which is where they were before. */

.foe-card-frame--dnd5e[b-w4o1nkkm5s] {
    --foe-card-bg: var(--mm-bg-parchment);
    --foe-card-border: var(--mm-text-header);
    --foe-card-border-ornate: var(--mm-text-header);
    --foe-card-accent: var(--mm-accent-red);
    --foe-card-ink: var(--mm-text-primary);
    --foe-card-note-line: var(--mm-accent-red);

    /* The chrome palette, read by the Card* components this frame wraps. The
       font is `--mm-font-header`, not `--font-header`: this card prints in its
       own system's face whatever heading face the app is wearing. */
    --foe-card-heading-font: var(--mm-font-header);
    --foe-card-title-strong-color: var(--mm-text-header);
    --foe-card-emphasis-color: var(--mm-text-header);
    --foe-card-subtype-color: var(--mm-text-header);
    --foe-card-tracking-label-color: var(--mm-text-header);
    --foe-card-divider-color: var(--mm-accent-red);
    --foe-card-pip-border: var(--mm-text-header);
    --foe-card-condition-border: var(--mm-text-header);
    --foe-card-condition-immune-color: var(--mm-text-secondary);
    --foe-card-tracking-row-gap: 4px;
    --foe-card-tracking-group-gap: 6px;
    --foe-card-tracking-group-wrap: wrap;
    --foe-card-tracking-label-min: 0;
    --foe-card-tracking-label-wrap: nowrap;
}

.foe-card-frame--daggerheart[b-w4o1nkkm5s] {
    --foe-card-bg: var(--dh-bg-light);
    --foe-card-border: var(--dh-border-purple);
    --foe-card-border-ornate: var(--dh-bg-dark);
    --foe-card-accent: var(--dh-accent-gold);
    --foe-card-ink: var(--dh-text-primary);
    --foe-card-note-line: var(--dh-border-purple);
    --foe-card-pip-border: var(--dh-accent-teal-dark);
    --foe-card-pip-border-alt: var(--dh-accent-gold);

    --foe-card-heading-font: var(--dh-font-header);
    --foe-card-title-strong-color: var(--dh-text-header);
    --foe-card-emphasis-color: var(--dh-text-header);
    --foe-card-subtype-color: var(--dh-card-header-text);
    --foe-card-tracking-label-color: var(--dh-bg-dark);
    --foe-card-divider-color: var(--dh-accent-teal);
    --foe-card-condition-border: var(--dh-border-purple);
    --foe-card-condition-immune-color: var(--dh-text-primary);
    --foe-card-tracking-row-gap: 6px;
    --foe-card-tracking-group-gap: 8px;
    --foe-card-tracking-group-wrap: nowrap;
    --foe-card-tracking-label-min: 80px;
    --foe-card-tracking-label-wrap: normal;
}

.foe-card-frame[b-w4o1nkkm5s] {
    /* Read by StatBlockNotesArea's .note-line. */
    --statblock-note-line: var(--foe-card-note-line);

    /* Chrome values that are the same in both systems, or that depend on the
       print mode rather than the system. Both cards stated every one of these
       twice before the Card* chrome components took the shapes. */
    --foe-card-title-rule: var(--foe-card-accent);
    --foe-card-title-rule-width: 2px;
    --foe-card-title-direction: row;
    --foe-card-title-align: center;
    --foe-card-divider-bg: linear-gradient(90deg, transparent 0%, var(--foe-card-divider-color) 15%, var(--foe-card-divider-color) 85%, transparent 100%);
    --foe-card-divider-rule: none;
    --foe-card-condition-columns: 4;
    width: 100%;
    box-sizing: border-box;
    background: var(--foe-card-bg);
    border: 2px solid var(--foe-card-border);
    border-radius: 2px;
    padding: 12px;
    line-height: 1.3;
    font-size: var(--print-body-size);
    font-family: var(--font-body);
    position: relative;
    color: var(--foe-card-ink);
}

/* Ornate mode styling (default) */
.foe-card-frame.print-ornate[b-w4o1nkkm5s] {
    /* The one chrome value ornate mode changes: both cards thickened the title
       rule to 3px and restated its colour, which was already the accent. */
    --foe-card-title-rule-width: 3px;
    background: var(--foe-card-bg);
    border: 3px solid var(--foe-card-border-ornate);
    border-top-width: 4px;
    border-bottom-width: 4px;
}

/* Tapered accent line decorations for ornate mode */
.foe-card-frame.print-ornate[b-w4o1nkkm5s]::before,
.foe-card-frame.print-ornate[b-w4o1nkkm5s]::after {
    content: '';
    position: absolute;
    left: 8px;
    right: 8px;
    height: 2px;
    background: linear-gradient(90deg, transparent 0%, var(--foe-card-accent) 15%, var(--foe-card-accent) 85%, transparent 100%);
}

.foe-card-frame.print-ornate[b-w4o1nkkm5s]::before {
    top: 6px;
}

.foe-card-frame.print-ornate[b-w4o1nkkm5s]::after {
    bottom: 6px;
}

/* Plain mode styling */
.foe-card-frame.print-plain[b-w4o1nkkm5s] {
    background: white;
    border: 2px solid var(--foe-card-ink);
    color: var(--foe-card-ink);
    --statblock-note-line: var(--foe-card-ink);

    /* Plain mode's chrome palette. Every value below was stated twice — once per
       card sheet under `.foe-card-frame--dnd5e.print-plain` and once under
       `--daggerheart` — and the two were the same declaration reading each
       system's name for the same colour. */
    --foe-card-title-rule: var(--foe-card-ink);
    --foe-card-heading-font: Georgia, serif;
    --foe-card-title-strong-color: var(--foe-card-ink);
    --foe-card-subtype-color: var(--print-text);
    --foe-card-divider-bg: none;
    --foe-card-divider-rule: 1px solid var(--print-rule-strong);
    --foe-card-condition-border: var(--foe-card-ink);
    --foe-card-condition-immune-color: var(--print-text-soft);
}

/* --foe-card-emphasis-color is deliberately absent from the plain-mode block
   above, unlike its title-row sibling. Plain mode drops the D&D lead-in runs to
   ink and leaves the Daggerheart ones on --dh-text-header, and the D&D half
   cannot be stated here anyway: that card's info row re-declares the property to
   maroon on the row element, which is nearer than this frame and would keep
   winning. MonsterContent states the plain-mode ink on the two rows it owns, in
   the one rule that always carried it. The Daggerheart non-flip is the
   pre-existing behaviour, preserved rather than tidied for the same reason as
   the tracking label below. */

/* Plain mode does NOT reset the Daggerheart tracking label: only the D&D sheet
   ever overrode that colour, so the adversary card keeps `--dh-bg-dark` on white
   paper where the monster card drops to ink. Preserved rather than collapsed —
   the divergence predates the extraction and changing it would change print
   output. It is a one-line fix here if it turns out to be unintended. */
.foe-card-frame--dnd5e.print-plain[b-w4o1nkkm5s] {
    --foe-card-tracking-label-color: var(--foe-card-ink);
}

/* Plain print mode drops the decorative palette to ink the printer can be
   trusted with. Both card sheets stated this per pip class before <PipTracker>. */
.foe-card-frame--dnd5e.print-plain[b-w4o1nkkm5s] {
    --foe-card-pip-border: var(--mm-text-primary);
}

.foe-card-frame--daggerheart.print-plain[b-w4o1nkkm5s] {
    --foe-card-pip-border: var(--dh-text-primary);
    --foe-card-pip-border-alt: var(--dh-text-primary);
}

/* The .notes-area::before/::after halves of this selector list were dead — no
   rule ever gave that element a pseudo-element — and dropped with the move. */
.foe-card-frame.print-plain[b-w4o1nkkm5s]::before,
.foe-card-frame.print-plain[b-w4o1nkkm5s]::after {
    display: none;
}

/* The A4 printable width — 210mm of paper less the 8mm the page frame pads on
   each side — held on every display, so the preview breaks lines where the
   printer does. Auto margins centre it in a wider viewport and resolve to 0 in
   a narrower one, which leaves the left edge reachable; the ancestor that owns
   the scroll (SinglePrintPreview's `.stat-block-scroll-wrapper`,
   ContentDisplayLayout's `.foe-stat-block`) supplies the scrollbar.

   Centring used to be D&D-only. That was a divergence nobody chose: the
   Daggerheart card sat hard left of the same preview. Both centre now. */
.foe-card-frame.fixed-width[b-w4o1nkkm5s] {
    width: var(--print-printable-width);
    margin: 0 auto;
}

/* The narrow-screen reflow of the chrome. It belongs here rather than in each
   Card* component because the condition is this frame's: a card pinned to the
   printable width keeps its desktop shape at every viewport, and `.fixed-width`
   is this component's class. Handing the values down as custom properties keeps
   that out of ::deep — a ::deep rule would also outrank the component that owns
   the property, which is the ladder's documented blind spot. */
@media screen and (max-width: 768px) {
    .foe-card-frame:not(.fixed-width)[b-w4o1nkkm5s] {
        --foe-card-title-direction: column;
        --foe-card-title-align: flex-start;
        --foe-card-tracking-group-wrap: wrap;
        --foe-card-condition-columns: 2;
    }

    /* The one place the two cards genuinely disagreed: the D&D badge strip hugs
       the right edge, the Daggerheart threshold box fills the width. */
    .foe-card-frame--dnd5e:not(.fixed-width)[b-w4o1nkkm5s] {
        --foe-card-header-right-align: flex-end;
    }

    .foe-card-frame--daggerheart:not(.fixed-width)[b-w4o1nkkm5s] {
        --foe-card-header-right-align: stretch;
    }
}

/* Print-specific styles */
@media print {
    .foe-card-frame[b-w4o1nkkm5s] {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* Plain mode print - minimal ink */
    .foe-card-frame.print-plain[b-w4o1nkkm5s] {
        background: white !important;
        border: 2px solid black !important;
    }

    /* Ornate mode print - system themed */
    .foe-card-frame.print-ornate[b-w4o1nkkm5s] {
        background: var(--foe-card-bg) !important;
    }
}
/* /Common/Components/UI/FoePreviewLink.razor.rz.scp.css */
/* Reclaimed verbatim from base.css (ladder rung 2) — search-row preview links. */
.foe-preview-link[b-8fxa30vo2j] {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-align: left;
    font-weight: 600;
    color: var(--text-color);
    text-decoration: underline;
    text-decoration-style: dotted;
    text-decoration-color: var(--text-muted);
    display: block;
    white-space: nowrap;
}

.foe-preview-link:hover[b-8fxa30vo2j] {
    color: var(--accent-color);
    text-decoration-color: var(--accent-color);
}
/* /Common/Components/UI/FoeSearchResultItem.razor.rz.scp.css */
/* Search/suggestion row chrome (ladder rung 2). Phones: name over CR/tier ·
   type, "+" at 44px on the right. From 769px: one line in the columns of
   --foe-result-columns (tokens.css), which FoePickerLayout's sort header
   shares. */
.search-result-item[b-4squ6i39re] {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
        "title title add"
        "rank detail add";
    align-items: center;
    column-gap: 0.5rem;
    row-gap: 0.1rem;
    padding: 0.5rem;
    border-bottom: 1px solid var(--card-border);
}

.search-result-item:last-child[b-4squ6i39re] {
    border-bottom: none;
}

.result-title[b-4squ6i39re] {
    grid-area: title;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
}

/* The name keeps its full width; the title scrolls sideways instead. */
.result-name[b-4squ6i39re] {
    flex-shrink: 0;
}

.result-rank[b-4squ6i39re] {
    grid-area: rank;
    white-space: nowrap;
    font-size: 0.8rem;
    color: var(--text-color);
}

.result-detail[b-4squ6i39re] {
    grid-area: detail;
    min-width: 0;
    font-size: 0.8rem;
    color: var(--text-color);
}

/* Row-local add button — scoped to the row so it does not resize every
   icon-only nav button in the app. */
.search-result-item > button.btn-nav-link.btn-icon-only[b-4squ6i39re] {
    grid-area: add;
    width: 44px;
    height: 44px;
    padding: 0;
    font-size: 1.2rem;
    line-height: 1;
    border-radius: 50%;
}

@media (min-width: 769px) {
    .search-result-item[b-4squ6i39re] {
        grid-template-columns: var(--foe-result-columns);
        grid-template-areas: "title rank detail add";
        padding: 0.25rem 0.5rem;
    }

    .result-title[b-4squ6i39re] {
        flex-wrap: nowrap;
    }

    .result-detail[b-4squ6i39re] {
        white-space: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }

    .search-result-item > button.btn-nav-link.btn-icon-only[b-4squ6i39re] {
        width: 2rem;
        height: 2rem;
    }
}
/* /Common/Components/UI/FormActions.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   FormActions.razor.css — form-actions button row
   Ownership decision (Task 4, editor-chrome rung2 plan): this used to live in
   ContentEditorShell.razor.css as `::deep .form-actions` (Task 1's reclaim of the
   global `.foe-editor .form-actions` rule). Now that FormActions authors the
   `.form-actions` div itself, the rule no longer needs to reach through a
   slotted child — it drops from the shell's rung-3 ::deep to rung 1: a bare
   scoped selector on FormActions's own root. Values copied verbatim from
   ContentEditorShell.razor.css.
   ═══════════════════════════════════════════ */
/* Mobile-first (AGENTS.md): the bar is sticky at the bottom on narrow screens so the
   Save/Cancel row is always reachable, and settles into a normal inline row at
   >=769px with the desktop values carried over verbatim from the pre-2026-08 rule
   (display:flex; gap:1rem; justify-content:flex-start; padding:2rem 0).

   This replaced `@media (max-width: 768px) { display: none }`, which required every
   adopter to supply its own mobile fallback. Two of the four never did, leaving their
   Save/Import buttons unreachable. `position: sticky` keeps the bar in normal flow, so
   it occupies its own space and cannot cover the last form control — no container
   padding reservation is needed. */
.form-actions[b-vpe3fb9hcr] {
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    justify-content: flex-start;
    padding: 1rem;
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    border-radius: 8px;
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
}

/* Glass like the FormSections above it; solid elsewhere. The fill is a layer after
   GlassLayer, not the bar's background: sticky makes the bar a stacking context, which
   would paint GlassLayer (z-index -1) over its own background and darken it. */
.form-actions[b-vpe3fb9hcr]::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
}

/* "Saved" after a save that keeps the editor open. */
.form-actions-saved[b-vpe3fb9hcr] {
    align-self: center;
    color: var(--text-muted);
}

@media (min-width: 769px) {
    /* Inline row on desktop; relative (not static) so GlassLayer stays inside it. */
    .form-actions[b-vpe3fb9hcr] {
        position: relative;
        z-index: auto;
        padding: 1rem 1.5rem;
        margin-bottom: 1.5rem;
    }

    /* A toolbar row: the card hugs its icon buttons. */
    .form-actions--compact[b-vpe3fb9hcr] {
        gap: 0.25rem;
        padding: 0.25rem 0.5rem;
        margin-bottom: 0;
    }

    /* Inside a glass panel: a plain row on the panel's own glass (no second blur). */
    .form-actions--inset[b-vpe3fb9hcr] {
        --card-glass-blur: none;
        padding: 0;
        margin-bottom: 0;
        border: none;
        box-shadow: none;
    }

    .form-actions--inset[b-vpe3fb9hcr]::after {
        content: none;
    }
}
/* /Common/Components/UI/FormCard.razor.rz.scp.css */
.form-card[b-mb4tf9rs4i] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1.25rem;
    /* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    margin-bottom: 1.5rem;
}
/* /Common/Components/UI/FormField.razor.rz.scp.css */
/* The field row, owned once (ladder rung 1). Before this file was the only
   owner, the same look was stated three times: `.form-group { margin-bottom }`
   in base.css, the flex/label/help rules here, and a byte-identical
   `::deep .form-group` set in ContentEditorShell.razor.css that served the 117
   rows which hand-wrote the div instead of rendering this component. */
.form-group[b-uelryfxn0i] {
    display: flex;
    flex-direction: column;
    margin-bottom: 1rem;
}

.form-group label[b-uelryfxn0i] {
    font-weight: 600;
    margin-bottom: 0.5rem;
    color: var(--text-color);
    font-family: var(--font-body);
}

/* Variants, each reached through the `Class` parameter (working rule 3).
   They used to be written by the component that wanted them —
   `.movement-speeds .form-group` in MonsterMovementSection,
   `.form-row.stretch-vertical .form-group` in MonsterBasicInfoSection — which
   worked only while those sections authored the div themselves. Neither
   section renders an element of its own, so neither has a scope anchor to
   reach it with ::deep; the variant belongs to this component's parameter. */
.form-group--narrow[b-uelryfxn0i] {
    max-width: 150px;
}

@media (max-width: 768px) {
    .form-group--narrow[b-uelryfxn0i] {
        max-width: none;
    }
}

/* The only cell in its FormRow, so it takes the whole row rather than the
   grid's first track. Three callers wrote this as a bare `.action-name-field`
   / `.reaction-name-field` / `.legendary-name-field` rule in their OWN sheets
   after the rung-0 inline-style sweep — but the div is FormField's, so those
   rules compiled against the caller's scope id and matched nothing. Three name
   fields silently stopped growing. The variant belongs here, where the element
   is. */
.form-group--grow[b-uelryfxn0i] {
    flex-grow: 1;
}

/* A field standing on its own below a row of options rather than inside one:
   AttackConfigEditor's two custom-attack fields and EncounterAutoFillPanel's two
   tag pickers. Both wrote the margin as a bare rule in their own sheet, against
   an element they do not author. */
.form-group--spaced[b-uelryfxn0i] {
    margin-top: 0.75rem;
}

/* Tighter row spacing, used by CrossLinkSection inside the hub's cross-link box. */
.form-group--tight[b-uelryfxn0i] {
    margin-bottom: 0.5rem;
}

/* The checkbox field: label and box on one line, the label set small and
   uppercase. Reclaimed from SpellRow.razor.css, which reached its own two
   fields with four ::deep rules; the two selectors it had (one qualified with
   the row class) applied to the same two elements, so they merge into one. */
.form-group--checkbox[b-uelryfxn0i] {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    min-width: 4.2rem;
    gap: 0.4rem;
    margin-bottom: 0;
}

.form-group--checkbox label[b-uelryfxn0i] {
    margin-bottom: 0;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    white-space: nowrap;
    line-height: 1;
}

/* The required marker: rendered by this component, so it is styled here.
   It used to be `::deep .required` in ContentEditorShell, reaching the three pages
   that hand-wrote the asterisk. */
.required[b-uelryfxn0i] {
    color: var(--focus-color);
    font-weight: bold;
}

.form-help[b-uelryfxn0i] {
    margin-top: 0.25rem;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* A control slotted as ChildContent carries the caller's scope id, not this
   component's, so anything below the label needs ::deep from here. */
[b-uelryfxn0i] > button {
    align-self: flex-start;
}

/* Hint text a caller slots itself (`<small class="form-text text-muted">`)
   rather than passing as HelpText. Rung 3 from the component that owns the
   row — this replaces ContentEditorShell's `::deep .form-group small`, which
   reached the same elements but only on the four editor pages, so the same
   hint rendered differently in the builder and the bundle editor. */
[b-uelryfxn0i] small {
    margin-top: 0.25rem;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
}
/* /Common/Components/UI/FormRow.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   FormRow.razor.css — form-row grid chrome
   Ownership decision (Task 2, editor-chrome rung-2 plan): this grid sizing
   used to live in ContentEditorShell.razor.css as `::deep .form-row` (Task 1's
   reclaim of the global `.foe-editor .form-row` rules). Now that FormRow
   authors the `.form-row` div itself, the sizing no longer depends on being
   inside the editor shell — every breakpoint here keys off viewport width
   alone, nothing reads `.foe-editor`/`page-width` — so it drops one rung
   further, to rung 1: a bare scoped selector on FormRow's own root, strictly
   better than the shell's ::deep (rung 3). Values below are copied verbatim
   from ContentEditorShell.razor.css.

   The `:has()` variant targets `.form-group` elements, which are slotted
   ChildContent authored by the calling section component, not by FormRow —
   so that rule keeps `::deep`, scoped from FormRow's own `.form-row` root.
   ═══════════════════════════════════════════ */
.form-row[b-hscq4dba48] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin-bottom: 1rem;
}

/* The toggles row: a wrapping flex line of checkbox fields rather than the
   grid, tighter under the row above it. Written as SpellRow's
   `::deep .spell-row-toggles` until 2026-08-21, when SpellRow's own root div
   became <FeatureEditor> and took the scope id that rule anchored on with it.
   The class lands on FormRow's own root (<FormRow Class="form-row--toggles">),
   so it belongs here as a bare scoped rule — rung 1, the same place
   `.form-group--checkbox` sits in FormField's sheet. Declared after the base
   `.form-row` so it wins the display/margin ties at equal specificity. */
.form-row--toggles[b-hscq4dba48] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 0.25rem;
    align-items: center;
}

@media (min-width: 769px) {
    .form-row[b-hscq4dba48] {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .form-row[b-hscq4dba48] {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.form-row[b-hscq4dba48]  .form-group:has(textarea),
.form-row[b-hscq4dba48]  .form-group:has(input[type="text"][placeholder*="Description"]) {
    grid-column: 1 / -1;
}

/* minmax(0, …) like the desktop tracks: a bare 1fr keeps its content's
   min-content width, so one wide child (the CR suggestion strip) widened the
   column past the card and every field in the row overflowed with it. */
@media (max-width: 768px) {
    .form-row[b-hscq4dba48] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 480px) {
    /* One column: each FormField's own bottom margin spaces the stack, so a
       grid row-gap or row margin on top would double it against fields
       standing outside a row. */
    .form-row[b-hscq4dba48] {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 0;
        margin-bottom: 0;
    }

    .form-row--toggles[b-hscq4dba48] {
        margin-bottom: 0;
    }
}
/* /Common/Components/UI/FormSection.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   FormSection.razor.css — form-section box chrome
   Ownership decision (Task 3, editor-chrome rung-2 plan): `CollapsibleFormSection`
   used to author the `.form-section` div itself. Four pages (MonsterEdit,
   AdversaryEdit, EnvironmentEdit, MonsterImport) also hand-rolled the same div,
   some collapsible (identical duplicate markup), some with a plain/no header —
   a genuine structural difference, not just "always open". Rather than fork the
   CSS or bolt a `Collapsible` flag onto a component whose rendered shape those
   pages don't share, the box itself is extracted here: `CollapsibleFormSection`
   now wraps `<FormSection>` and slots its own clickable header in as
   ChildContent; the four pages render `<FormSection>` directly with whatever
   header (plain h3, h4, or none) their content actually has.

   The box background/border/shadow and the accent stripe are this component's
   own root — bare scoped selectors. The heading typography is shared by every
   header shape (CollapsibleFormSection's own `h3.form-section-toggle` *and* a
   page's plain `<h3>`), and every one of those is ChildContent authored by
   someone else, so it needs `::deep` (rung 3) rather than a bare selector.
   Values below are copied verbatim from the CollapsibleFormSection.razor.css
   this replaces.
   ═══════════════════════════════════════════ */

/* Glass on the page art, like EntityCard's .card-item; solid elsewhere.
   Positioned for GlassLayer and the accent stripe. */
.form-section[b-dyqm6jwx6m] {
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    padding: 1.5rem;
    margin-bottom: 1.5rem;
    border-radius: 8px;
    border: 1px solid var(--card-glass-border, var(--card-border));
    position: relative;
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, 0 2px 4px var(--section-shadow));
}

.form-section[b-dyqm6jwx6m]::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--accent-stripe);
    border-radius: 8px 8px 0 0;
}

/* The rule underlines the section title; the header font and --text-color come
   from base.css's heading rule (rung 4) and were restated here for no gain. */
.form-section[b-dyqm6jwx6m] >  h3 {
    margin-top: 0;
    margin-bottom: 1rem;
    border-bottom: 2px solid var(--accent-color);
    padding-bottom: 0.5rem;
}
/* /Common/Components/UI/GlassLayer.razor.rz.scp.css */
/* z-index -1 drops the layer under the card's own background, into the nearest
   stacking context (MainLayout's .content), above PageBackdrop. */
.glass-layer[b-60054qq5c4] {
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    backdrop-filter: var(--card-glass-blur, none);
}

.glass-layer--deckled[b-60054qq5c4] {
    border-radius: 0;
    background: var(--card-glass-bg, var(--card-bg));
    -webkit-mask: var(--deckle-mask);
    mask: var(--deckle-mask);
}
/* /Common/Components/UI/HeroSection.razor.rz.scp.css */
/* Moved verbatim from Home.razor.css and Supporters.razor.css, which defined
   both of these identically (ladder rung 2). */

.hero[b-7wuii5v8g7] {
    text-align: center;
    margin-bottom: 3rem;
}

/* ::deep: the heading is written in the caller's markup, so it carries the
   caller's scope id, not ours (rung 3). Each page's responsive `.hero h1`
   override compiles to `.hero h1[b-page]` at (0,2,1) and still beats this
   rule's (0,1,1), so the per-page mobile sizing is unaffected. */
[b-7wuii5v8g7] h1 {
    font-size: 2.5rem;
    margin-bottom: 0.5rem;
}

/* The raised initial: base.css already inks h1::first-letter in --rubric.
   Inline, not floated: a float in the centred hero leaves a gap after it. */
[b-7wuii5v8g7] h1::first-letter {
    font-size: 1.6em;
    line-height: 0.8;
}
/* /Common/Components/UI/HubCard.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   HubCard.razor.css — one titled card inside an EntityHub
   Reclaimed from EntityHub.razor.css (ladder rung 3 -> rungs 1/3).
   Monster/AdversaryHubContent hand-rolled `<div class="hub-card"><h4>…</h4>`
   eight times and EntityHub reached all of them with ::deep. HubCard now
   authors the box and its heading, so those are bare rung-1 selectors here;
   only the card body is slotted.

   `.hub-card ::deep p` rather than bare `::deep p`: the compiled selector
   keeps the (0,2,1) specificity `.entity-hub ::deep .hub-card p` had.
   ═══════════════════════════════════════════ */

.hub-card[b-h0d8vzb3i9] {
    /* Positioned for GlassLayer; glass like EntityCard's .card-item. */
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    /* Muted text stays readable over the art showing through (tokens.css). */
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    padding: 1.25rem 1.5rem;
}

.hub-card h4[b-h0d8vzb3i9] {
    margin: 0 0 0.75rem 0;
    color: var(--text-color);
    font-family: var(--font-header), serif;
    font-size: 1rem;
    border-bottom: 1px solid var(--divider-accent, var(--card-border));
    padding-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.hub-card[b-h0d8vzb3i9]  p {
    margin: 0;
    color: var(--text-color);
    line-height: 1.6;
}

@media screen and (max-width: 768px) {
    .hub-card[b-h0d8vzb3i9] { min-width: 0; overflow-wrap: break-word; }
    /* `.hub-section` wraps its own long words — the rule went with the markup
       when the sections became <HubSection>. */
    .hub-card[b-h0d8vzb3i9]  p { overflow-wrap: break-word; word-break: break-word; }
}
/* /Common/Components/UI/HubGroup.razor.rz.scp.css */
.hub-group[b-nha86z43sl] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
}

.hub-group__title[b-nha86z43sl] {
    margin: 1rem 0 0;
    color: var(--text-color);
    font-family: var(--font-header), serif;
    font-size: 1.25rem;
}

/* Collapsible variant: the title becomes a full-width disclosure button. */
.hub-group__toggle[b-nha86z43sl] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: 44px;
    margin: 1rem 0 0;
    padding: 0;
    background: none;
    border: none;
    color: var(--text-color);
    text-align: left;
    cursor: pointer;
}

.hub-group__toggle .hub-group__title[b-nha86z43sl] {
    margin: 0;
}
/* /Common/Components/UI/HubHeading.razor.rz.scp.css */
/* Moved from AdventureDisplay.razor.css when the NPC page needed the same heading row. */
.hub-heading[b-da3nl2q2iv] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem 1rem;
}

.hub-heading h1[b-da3nl2q2iv] {
    margin: 0;
}

.hub-heading-subtitle[b-da3nl2q2iv] {
    flex-basis: 100%;
    margin: 0;
    color: var(--text-muted);
}
/* /Common/Components/UI/HubHint.razor.rz.scp.css */
/* Reclaimed from EntityHub.razor.css (`::deep .additional-hint`).

   The !important stays, and it is not specificity theatre: HubCard styles the
   paragraphs inside its slot with `.hub-card ::deep p` — (0,2,1) once compiled,
   against this rule's (0,2,0) — and that rule sets `margin: 0`. Without the
   flag the hint loses its bottom margin and the controls below it ride up. */

.additional-hint[b-ovflfzn70a] {
    color: var(--text-muted);
    font-size: 0.875rem;
    font-style: italic;
    margin-bottom: 0.75rem !important;
}
/* /Common/Components/UI/HubSection.razor.rz.scp.css */
.hub-section[b-a89vr70ten] {
    min-width: 0;
}

/* Spans the hub's section grid — the tactical-signals block. */
.hub-section--full[b-a89vr70ten] {
    grid-column: 1 / -1;
}

/* Long unbroken names and generated directives must not push the card wide.
   Reclaimed from HubCard.razor.css, which reached this element with ::deep. */
@media screen and (max-width: 768px) {
    .hub-section[b-a89vr70ten] {
        overflow-wrap: break-word;
        word-break: break-word;
    }
}
/* /Common/Components/UI/HubStack.razor.rz.scp.css */
/* Moved from AdventureDisplay.razor.css (`.adventure-overview`) when the NPC page needed it too. */
.hub-stack[b-x3xnikobfh] {
    display: grid;
    gap: 1rem;
}
/* /Common/Components/UI/HubTag.razor.rz.scp.css */
/* Reclaimed from EntityHub.razor.css (`::deep .additional-tag`), which styled a
   chip three slice components render. The role and tooltip variants came from
   MonsterHubContent.razor.css, whose bare rules stopped matching once the span
   moved here — they are this component's parameters now. */

.additional-tag[b-866y2kk8qp] {
    background: var(--editor-highlight-bg);
    color: var(--text-color);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.2rem 0.6rem;
    font-size: 0.8rem;
}

.additional-tag-role[b-866y2kk8qp] {
    background: var(--accent-color);
    color: var(--on-accent-text);
    border-color: var(--accent-color);
    font-weight: 600;
}

.tooltip-target[b-866y2kk8qp] {
    position: relative;
    cursor: help;
    border-bottom: 1px dashed var(--text-muted);
}

.tooltip-target[b-866y2kk8qp]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    padding: 0.35rem 0.6rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    font-size: 0.8rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
    z-index: 1000;
}

.tooltip-target:hover[b-866y2kk8qp]::after {
    opacity: 1;
}
/* /Common/Components/UI/HubTagList.razor.rz.scp.css */
/* Reclaimed from EntityHub.razor.css (`::deep .additional-tags`) and from the
   byte-identical copy EncounterDisplay carried for its own row. */

.additional-tags[b-e6dreye1dr] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
/* /Common/Components/UI/HubTextSection.razor.rz.scp.css */
/* The GM writes paragraphs; keep them. */
.hub-text[b-1d77j3hnaz] {
    white-space: pre-line;
}
/* /Common/Components/UI/InfoSectionLabel.razor.rz.scp.css */
.info-section-label[b-lc51brclkf] {
    font-weight: 600;
    color: var(--text-muted);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 0.75rem;
    margin-bottom: 0.25rem;
}
/* /Common/Components/UI/InsetPanel.razor.rz.scp.css */
.inset-panel[b-q25s7tkzyt] {
    margin-top: 0.5rem;
    padding: 0.75rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
}

/* On the page art the art shows through; card fill elsewhere. */
.inset-panel--translucent[b-q25s7tkzyt] {
    background: var(--control-glass-bg, var(--card-bg));
    backdrop-filter: blur(6px);
}
/* /Common/Components/UI/ListEmptyState.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   ListEmptyState.razor.css — scoped styles
   Moved from ContentListLayout.razor.css ::deep
   ═══════════════════════════════════════════ */

/* The empty branch renders <EmptyState>, which owns `.empty-state` and the
   ::deep h3/p chrome the slotted heading and copy pick up. The copy that used
   to sit here had drifted (flat 4rem 2rem, no breakpoint, no font-size) and
   left the h3/p unstyled on list pages. */

.no-results[b-oa0uj1toac] {
    text-align: center;
    padding: 2rem;
    color: var(--text-muted);
}

/* base.css also carried a `.no-results` block. It was dead there — the scoped
   rule above outranked it — so it is NOT reclaimed here. Resurrecting it would
   have overridden that rule's padding (2rem -> 2rem 1rem). */
/* /Common/Components/UI/ListPage.razor.rz.scp.css */
/* Shell shared by every list route (Monsters, Adversaries, Environments,
   Encounters, ContentBundles, FeaturedFeed). Reclaimed from base.css
   (ladder rung 4 -> 2): all six pages hand-rolled the same two divs, which is
   why .foe-list and .list-header were global. */

.foe-list[b-gmlzxlvf6w] {
    padding: 2rem;
}

.list-header[b-gmlzxlvf6w] {
    margin-bottom: 1.5rem;
}

/* ::deep: the heading is slotted in by the page (rung 3). */
.list-header[b-gmlzxlvf6w]  h1 {
    margin: 0;
}

@media (max-width: 480px) {
    .foe-list[b-gmlzxlvf6w] {
        padding: 1rem;
    }
}
/* /Common/Components/UI/ListSearchControls.razor.rz.scp.css */
/* The icon is the icon component's own <svg>, not this component's element, so
   these rules reach it with ::deep (rung 3). Written bare, they compiled
   against this component's scope id, matched nothing, and the icon rendered
   at its default size. */
/* ═══════════════════════════════════════════
   ListSearchControls.razor.css — scoped styles
   Moved from ContentListLayout.razor.css ::deep
   ═══════════════════════════════════════════ */

.view-toggle[b-jbnw3lxmpe]  .view-icon {
    width: 1.2rem;
    height: 1.2rem;
    display: block;
}

/* Filters + view-toggle read as plain words (the icon, for the view toggle)
   at the right of the search rule; the open filter panel is the word
   underlined in the rubric. margin-left:auto opens the gap that groups them
   right. */
.filter-toggle[b-jbnw3lxmpe] {
    margin-left: auto;
}

.filter-toggle[b-jbnw3lxmpe],
.view-toggle[b-jbnw3lxmpe] {
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: none;
    padding: 0.3rem 0.25rem;
    color: var(--text-color);
    transition: border-color var(--transition-fast),
                color var(--transition-fast);
}

.filter-toggle:hover[b-jbnw3lxmpe],
.view-toggle:hover[b-jbnw3lxmpe] {
    background: none;
}

.filter-toggle:focus-visible[b-jbnw3lxmpe],
.view-toggle:focus-visible[b-jbnw3lxmpe] {
    outline: none;
    box-shadow: var(--focus-ring);
}

.filter-toggle[aria-expanded="true"][b-jbnw3lxmpe] {
    border-bottom-color: var(--rubric);
}

@media (max-width: 768px) {
    /* Column layout: the group-right margin does nothing useful, and the
       view-toggle keeps its own right-edge alignment. */
    .filter-toggle[b-jbnw3lxmpe] {
        margin-left: 0;
    }

    .view-toggle[b-jbnw3lxmpe] {
        align-self: flex-end;
    }
}
/* /Common/Components/UI/LoadErrorState.razor.rz.scp.css */
.load-error-state[b-b61dzkyh81] {
    text-align: center;
    padding: 3rem 1.5rem;
}

.load-error-message[b-b61dzkyh81] {
    color: var(--danger-ink);
    font-size: 1.1rem;
    margin: 0;
}

.load-error-details[b-b61dzkyh81] {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin: 0.5rem 0 0 0;
    word-break: break-word;
}

.load-error-retry[b-b61dzkyh81] {
    margin-top: 1rem;
}
/* /Common/Components/UI/LoadingState.razor.rz.scp.css */
.loading-state[b-z4rxxut4f0] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 2rem 1rem;
    color: var(--text-muted);
}

.loading-spinner[b-z4rxxut4f0] {
    position: relative;
    width: 2.5rem;
    height: 2.5rem;
}

.loading-spinner-ring[b-z4rxxut4f0] {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid var(--border-color);
    border-top-color: var(--color-gold);
    animation: loading-spin-b-z4rxxut4f0 1s linear infinite;
}

.loading-message[b-z4rxxut4f0] {
    font-family: var(--font-header), serif;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.5px;
    color: var(--text-header);
}

@keyframes loading-spin-b-z4rxxut4f0 {
    to {
        transform: rotate(360deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .loading-spinner-ring[b-z4rxxut4f0] {
        animation: none;
        border-top-color: var(--border-color);
        opacity: 0.5;
    }
}
/* /Common/Components/UI/Modal.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   Modal.razor.css — scoped styles
   Reclaimed from base.css (ladder rung 1)
   ═══════════════════════════════════════════

   The whole modal chrome is Modal-owned: `.modal-backdrop`, `.modal-dialog`,
   the preview-header/close-button pair and `.modal-content` / `.modal-actions`.
   ActionDetailOverlay and FoePreviewOverlay render <Modal> now, so nothing
   else hand-rolls this DOM. */

.modal-backdrop[b-8stxpnpqps] {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--modal-backdrop-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.modal-dialog[b-8stxpnpqps] {
    background: var(--card-bg);
    border: 2px solid var(--card-border);
    border-radius: 8px;
    max-width: 500px;
    width: 90%;
    box-shadow: 0 4px 24px rgba(var(--shadow-rgb), 0.3);
}

/* The plain title (no close button). Header, body and footer each carry
   their own padding, mobile-first, so no caller has to pad the chrome. */
.modal-title[b-8stxpnpqps] {
    margin: 0;
    padding: 1rem 1rem 0;
    font-family: var(--font-header);
    color: var(--text-color);
}

/* Overlay header row — rendered by Modal when ShowCloseButton + Title are set. */
.preview-header[b-8stxpnpqps] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--card-border);
    flex-shrink: 0;
}

.preview-header h3[b-8stxpnpqps] {
    margin: 0;
    font-family: var(--font-header);
    color: var(--text-color);
}

.preview-header-actions[b-8stxpnpqps] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.preview-close-btn[b-8stxpnpqps] {
    background: none;
    border: none;
    font-size: 1.2rem;
    cursor: pointer;
    color: var(--text-muted);
    padding: 0.25rem 0.5rem;
    line-height: 1;
    border-radius: 4px;
}

.preview-close-btn:hover[b-8stxpnpqps] {
    color: var(--text-color);
    background: var(--card-actions-bg);
}

.modal-content[b-8stxpnpqps] {
    padding: 1rem;
}

/* Variants. Reclaimed from ActionDetailOverlay and FoePreviewOverlay, which set
   them through ::deep and so outranked this file on every one. */
.modal-dialog--compact[b-8stxpnpqps] {
    max-width: 480px;
}

.modal-dialog--preview[b-8stxpnpqps] {
    max-width: 780px;
    width: 95%;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
}

.modal-content--flush[b-8stxpnpqps] {
    padding: 0;
}

.modal-dialog--preview .modal-content[b-8stxpnpqps] {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}

/* Footer: stacked full-width buttons on a phone (flex items stretch across
   a column), a right-aligned row from 481px. */
.modal-actions[b-8stxpnpqps] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0 1rem 1rem;
}

@media (min-width: 481px) {
    .modal-title[b-8stxpnpqps] {
        padding: 1.5rem 1.5rem 0;
    }

    .modal-content[b-8stxpnpqps] {
        padding: 1.5rem;
    }

    .modal-content--flush[b-8stxpnpqps] {
        padding: 0;
    }

    .modal-actions[b-8stxpnpqps] {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 1rem;
        padding: 0 1.5rem 1.5rem;
    }
}
/* /Common/Components/UI/Pagination.razor.rz.scp.css */
.pagination-container[b-pkci9m38ga] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.5rem;
    padding: 1rem 0;
}

.pagination-info[b-pkci9m38ga] {
    color: var(--text-muted);
    font-size: 0.9rem;
    text-align: center;
}

.pagination[b-pkci9m38ga] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    list-style: none;
    padding: 0;
    margin: 0;
    gap: 0.25rem;
}

.page-item[b-pkci9m38ga] {
    margin: 0;
}

.page-link[b-pkci9m38ga] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    height: 2.25rem;
    padding: 0 0.5rem;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text-color);
    font-size: 0.85rem;
    cursor: pointer;
    transition: all 0.2s ease;
    border-radius: 4px;
}

.page-link:hover:not(:disabled)[b-pkci9m38ga] {
    background: var(--accent-color);
    color: var(--page-bg);
    border-color: var(--accent-color);
}

.page-item.active .page-link[b-pkci9m38ga] {
    background: var(--accent-color);
    color: var(--page-bg);
    border-color: var(--accent-color);
    font-weight: bold;
}

.page-item.disabled .page-link[b-pkci9m38ga] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

@media (min-width: 576px) {
    .page-link[b-pkci9m38ga] {
        min-width: 2.5rem;
        height: 2.5rem;
        padding: 0 0.75rem;
        font-size: 0.9rem;
    }
}
/* /Common/Components/UI/PatreonLogo.razor.rz.scp.css */
.patreon-logo[b-ld12xwipg6] {
    object-fit: contain;
}
/* /Common/Components/UI/PipTracker.razor.rz.scp.css */
/* The four pip trackers, side by side for the first time.

   They drifted before they were one component: 4px against 3px gaps, 12px
   against 14px pips, one that does not wrap and one that reserves centring.
   Every one of those is preserved here — this extraction changes no pixel — but
   they are now visible together, which is the precondition for anyone deciding
   whether the differences were ever intended. */

.pip-track[b-vukbhstovk] {
    display: flex;
    flex-wrap: wrap;
}

.pip-track--resistance[b-vukbhstovk] { gap: 4px; align-items: center; }
.pip-track--concentration[b-vukbhstovk] { flex-wrap: nowrap; align-items: center; }
.pip-track--hit-points[b-vukbhstovk] { gap: 3px; }
.pip-track--stress[b-vukbhstovk] { gap: 3px; }

/* Border colour arrives from FoeCardFrame, which knows the system and the print
   mode; this component knows neither.

   No box-sizing here on purpose. All four original screen rules were content-box
   and there is no universal reset in base.css, so border-box would shrink every
   pip by its border — 2px, and 3px for concentration. Only the @media print block
   below declares it, exactly as the two print rules it replaced did. */
.pip[b-vukbhstovk] {
    border: 1px solid var(--foe-card-pip-border);
    background: transparent;
}

.pip--resistance[b-vukbhstovk] {
    width: 12px;
    height: 12px;
    transform: rotate(45deg);
}

.pip--concentration[b-vukbhstovk] {
    width: 14px;
    height: 14px;
    border-width: 1.5px;
    border-radius: 50%;
}

.pip--hit-points[b-vukbhstovk] {
    width: 14px;
    height: 14px;
}

.pip--stress[b-vukbhstovk] {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border-color: var(--foe-card-pip-border-alt, var(--foe-card-pip-border));
}

/* On paper the pips must survive a printer that drops light borders and any
   background graphics setting. Both card sheets stated this per pip class; it is
   one rule now. */
@media print {
    .pip--resistance[b-vukbhstovk] {
        border: 2px solid black !important;
        min-width: 12px;
        min-height: 12px;
    }

    .pip--hit-points[b-vukbhstovk],
    .pip--stress[b-vukbhstovk] {
        border: 2px solid black !important;
        min-width: 14px;
        min-height: 14px;
        display: inline-block;
        box-sizing: border-box;
    }
}
/* /Common/Components/UI/PlainList.razor.rz.scp.css */
.plain-list[b-xcxsa63wc8] {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
/* /Common/Components/UI/PreviewSection.razor.rz.scp.css */
/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.preview-section[b-r8p502eept] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 4px;
    padding: 0.75rem;
}

.preview-section h4[b-r8p502eept] {
    margin: 0 0 0.5rem;
    font-size: 0.9rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Slotted paragraphs carry the caller's scope id. */
.preview-section[b-r8p502eept]  p {
    margin: 0.25rem 0;
    font-size: 0.875rem;
    color: var(--text-color);
}
/* /Common/Components/UI/PrintChecklist.razor.rz.scp.css */
.print-checklist[b-0bn6jwxcmq] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.5rem;
}

.print-checklist__item[b-0bn6jwxcmq] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.print-checklist__box[b-0bn6jwxcmq] {
    font-size: 1.1em;
    line-height: 1;
}
/* /Common/Components/UI/PrintControlGroup.razor.rz.scp.css */
.print-control-group[b-x2sjmginp2] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.print-control-group--wide[b-x2sjmginp2] {
    gap: 0.75rem;
}

.print-control-group--bordered[b-x2sjmginp2] {
    padding: 0 1rem;
    border-left: 1px solid var(--card-border);
}

.print-control-group > label:first-child[b-x2sjmginp2] {
    font-family: var(--font-header);
    font-weight: 600;
    color: var(--text-color);
    white-space: nowrap;
}

/* The divider turns horizontal once the action bar has stacked. */
@media (max-width: 768px) {
    .print-control-group--bordered[b-x2sjmginp2] {
        border-left: none;
        border-top: 1px solid var(--card-border);
        padding: 1rem 0 0 0;
        justify-content: center;
    }
}
/* /Common/Components/UI/PrintMetaField.razor.rz.scp.css */
.eprint-meta-label[b-7w9r6p85sj] {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--eprint-label, var(--text-muted));
    font-weight: 600;
}

.eprint-meta-value[b-7w9r6p85sj] {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--eprint-value, var(--text-color));
}

/* The difficulty colour coding for the encounter sheet's ValueClass. It lived in
   EncounterContent.razor.css until 2026-08-18 and was dead there in both halves:
   the compound half (`.eprint-meta-value.eprint-difficulty-hard`) named an
   element this component renders, so it compiled against EncounterContent's
   scope id, and the bare half named a class nothing renders at all — the token
   only ever arrives here, through ValueClass. The encounter print sheet has been
   printing its difficulty in the default value colour for as long as the split
   existed.

   It is the same blind spot AGENTS.md records for a class handed to a child
   through `Class="…"`, one step further along: the guard for that case keys on
   the handed token, and these rules put it in a compound whose key class is the
   receiving component's own. */
.eprint-meta-value.eprint-difficulty-trivial[b-7w9r6p85sj] { color: var(--text-muted); }
.eprint-meta-value.eprint-difficulty-easy[b-7w9r6p85sj] { color: var(--color-success); }
.eprint-meta-value.eprint-difficulty-low[b-7w9r6p85sj] { color: var(--color-success); }
.eprint-meta-value.eprint-difficulty-standard[b-7w9r6p85sj] { color: var(--print-difficulty-moderate); }
.eprint-meta-value.eprint-difficulty-moderate[b-7w9r6p85sj] { color: var(--print-difficulty-moderate); }
.eprint-meta-value.eprint-difficulty-hard[b-7w9r6p85sj] { color: var(--print-difficulty-hard); }
.eprint-meta-value.eprint-difficulty-high[b-7w9r6p85sj] { color: var(--print-difficulty-hard); }
.eprint-meta-value.eprint-difficulty-overwhelming[b-7w9r6p85sj] { color: var(--print-difficulty-overwhelming); }
/* /Common/Components/UI/PrintMetaItem.razor.rz.scp.css */
.eprint-meta-item[b-egwipiggda] {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

/* The tags variant: a row that pushes itself to the end of the meta row.
   The class arrives from the caller but lands on this component's div, so the
   rule belongs here — the environment sheet used to reach it with ::deep. */
.eprint-meta-item.eprint-meta-tags[b-egwipiggda] {
    align-items: center;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-left: auto;
}
/* /Common/Components/UI/PrintMetaRow.razor.rz.scp.css */
.eprint-meta-row[b-untq0fa2t8] {
    display: flex;
    gap: 2rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    padding: 0.75rem 1rem;
    background-color: var(--eprint-panel-bg, var(--card-bg));
    border: 1px solid var(--eprint-panel-border, var(--card-border));
    border-radius: 6px;
}

@media print {
    .eprint-meta-row[b-untq0fa2t8] {
        margin-bottom: 0.75rem;
        padding: 0.4rem 0.75rem;
        gap: 1rem;
    }
}
/* /Common/Components/UI/PrintSection.razor.rz.scp.css */
.eprint-section[b-69jc3zgy4q] {
    margin-bottom: 1.5rem;
}

.eprint-section-inline[b-69jc3zgy4q] {
    margin-bottom: 1rem;
}

.eprint-section-title[b-69jc3zgy4q] {
    font-family: var(--print-font-header), serif;
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--eprint-heading, var(--text-color));
    border-bottom: 1px solid var(--eprint-heading-rule, var(--card-border));
    padding-bottom: 0.3rem;
    margin: 0 0 0.75rem;
}

@media print {
    .eprint-section[b-69jc3zgy4q] {
        margin-bottom: 0.75rem;
    }

    .eprint-section-title[b-69jc3zgy4q] {
        margin-bottom: 0.4rem;
        font-size: 0.95rem;
    }
}
/* /Common/Components/UI/PrintSelector.razor.rz.scp.css */
/* The row, its label and the divider are <PrintControlGroup>'s (rung 2). The
   select's look is base.css's, like every other select in the app (rung 4); its
   own card-coloured skin made the print bar the odd one out. Only the
   affordance stays here. */
.print-select[b-15b63h0j7c] {
    cursor: pointer;
}
/* /Common/Components/UI/PrintSheet.razor.rz.scp.css */
/* The sheet is shown at the true printable width — A4 portrait, 210mm — on every
   display, so the preview and the paper break lines in the same places. It never
   reflows to the viewport: a wider viewport centres it (margin-inline: auto), a
   narrower one scrolls it sideways inside the caller's scroll wrapper. `auto`
   margins on a child wider than its container resolve to 0 rather than clipping
   the left edge, so the whole sheet stays reachable. `page-width` used to sit on
   this root and is gone: a 1400px content container has nothing to say about a
   sheet whose width is fixed by the paper. */
.eprint-sheet[b-2w6yb9gwht] {
    width: var(--print-page-width);
    margin-inline: auto;
    box-sizing: border-box;
    padding: 2rem;
    font-family: var(--font-body), serif;
    color: var(--text-color);
}

/* ── Plain mode: monochrome, for a printer with no colour to spare ── */
.eprint-sheet.print-plain[b-2w6yb9gwht] {
    background: var(--color-white);
    color: var(--text-primary);

    --eprint-heading: var(--text-primary);
    --eprint-header-rule: var(--text-primary);
    --eprint-heading-rule: var(--print-rule);
    --eprint-badge-bg: var(--text-primary);
    --eprint-badge-text: var(--color-white);
    --eprint-panel-bg: var(--color-white);
    --eprint-panel-border: var(--print-rule);
    --eprint-value: var(--text-primary);
    --eprint-label: var(--print-text-muted);
    --eprint-chip-bg: var(--color-white);
    --eprint-chip-border: var(--print-rule);
    --eprint-chip-text: var(--print-text-muted);
    --eprint-footer-text: var(--print-text-muted);
    --eprint-soft-rule: var(--print-rule);
}

/* ── Ornate – D&D 5e (parchment / red) ── */
.eprint-sheet.print-ornate.eprint-dnd[b-2w6yb9gwht] {
    background: var(--mm-bg-parchment);
    color: var(--text-primary);

    --eprint-heading: var(--mm-text-header);
    --eprint-header-rule: var(--mm-text-header);
    --eprint-heading-rule: var(--mm-accent-red);
    --eprint-badge-bg: var(--mm-accent-red);
    --eprint-badge-text: var(--mm-bg-parchment);
    --eprint-panel-bg: var(--mm-print-row-tint);
    --eprint-panel-border: var(--mm-text-header);
    --eprint-value: var(--text-primary);
    --eprint-label: var(--mm-print-label);
    --eprint-chip-bg: var(--mm-print-panel-bg);
    --eprint-chip-border: var(--mm-accent-red);
    --eprint-chip-text: var(--mm-text-header);
    --eprint-footer-text: var(--mm-text-header);
    --eprint-soft-rule: var(--mm-print-rule-soft);
}

/* ── Ornate – Daggerheart (lavender / purple) ── */
.eprint-sheet.print-ornate.eprint-dh[b-2w6yb9gwht] {
    background: var(--dh-bg-light);
    color: var(--text-primary);

    --eprint-heading: var(--dh-bg-dark);
    --eprint-header-rule: var(--dh-bg-dark);
    --eprint-heading-rule: var(--dh-accent-gold);
    --eprint-badge-bg: var(--dh-bg-dark);
    --eprint-badge-text: var(--dh-bg-light);
    --eprint-panel-bg: var(--dh-print-row-tint);
    --eprint-panel-border: var(--dh-border-purple);
    --eprint-value: var(--text-primary);
    --eprint-label: var(--dh-print-label);
    --eprint-chip-bg: var(--dh-print-panel-bg);
    --eprint-chip-border: var(--dh-border-purple);
    --eprint-chip-text: var(--dh-bg-dark);
    --eprint-footer-text: var(--dh-bg-dark);
    --eprint-soft-rule: var(--dh-print-rule-soft);
}

@media print {
    /* On paper the page box already is A4: let the sheet fill it instead of
       repeating the 210mm, which would overflow whatever margin the UA adds. */
    .eprint-sheet[b-2w6yb9gwht] {
        width: auto;
        margin-inline: 0;
        padding: 0.5rem;
        max-width: 100%;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    /* Plain mode on paper: headings, values and the footer go true black.
       Ornate needs nothing — print-color-adjust carries its colours through. */
    .eprint-sheet.print-plain[b-2w6yb9gwht] {
        --eprint-heading: var(--color-black);
        --eprint-value: var(--color-black);
        --eprint-footer-text: var(--color-black);
    }
}
/* /Common/Components/UI/PrintSheetFooter.razor.rz.scp.css */
.eprint-footer[b-tfxp413kb9] {
    margin-top: 1rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--eprint-chip-border, var(--card-border));
    font-size: 0.75rem;
    color: var(--eprint-footer-text, var(--text-muted));
    text-align: right;
}

@media print {
    .eprint-footer[b-tfxp413kb9] {
        margin-top: 0.5rem;
    }
}
/* /Common/Components/UI/PrintSheetHeader.razor.rz.scp.css */
.eprint-header[b-l83br0fjxl] {
    border-bottom: 2px solid var(--eprint-header-rule, var(--card-border));
    padding-bottom: 1rem;
    margin-bottom: 1.25rem;
}

.eprint-title[b-l83br0fjxl] {
    font-family: var(--print-font-header), serif;
    font-size: 2rem;
    margin: 0;
    color: var(--eprint-heading, var(--text-color));
}

.eprint-subtitle[b-l83br0fjxl] {
    margin: 0.25rem 0 0;
    color: var(--eprint-label, var(--text-muted));
    font-weight: 600;
}

.eprint-description[b-l83br0fjxl] {
    margin: 0.5rem 0 0;
    color: var(--eprint-label, var(--text-muted));
    font-style: italic;
}

@media print {
    .eprint-header[b-l83br0fjxl] {
        padding-bottom: 0.5rem;
        margin-bottom: 0.5rem;
    }
}
/* /Common/Components/UI/PrintSubsection.razor.rz.scp.css */
.eprint-subsection[b-57gdyv5rxx] {
    margin-bottom: 1rem;
}

.eprint-subsection:last-child[b-57gdyv5rxx] {
    margin-bottom: 0;
}

@media print {
    .eprint-subsection[b-57gdyv5rxx] {
        margin-bottom: 0.4rem;
    }
}
/* /Common/Components/UI/PrintSubsectionTitle.razor.rz.scp.css */
.eprint-subsection-title[b-s80ylydf8n] {
    font-family: var(--font-body), serif;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--eprint-label, var(--text-muted-on-light-bg));
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 0 0 0.5rem;
    padding-bottom: 0.25rem;
    border-bottom: 1px solid var(--eprint-soft-rule, var(--card-border));
}

@media print {
    .eprint-subsection-title[b-s80ylydf8n] {
        margin-bottom: 0.25rem;
    }
}
/* /Common/Components/UI/PrintSystemBadge.razor.rz.scp.css */
.eprint-system-badge[b-mizu9q67hs] {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.2rem 0.6rem;
    border-radius: 4px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    background-color: var(--eprint-badge-bg, var(--accent-color));
    color: var(--eprint-badge-text, var(--on-accent-text));
}
/* /Common/Components/UI/PrintTagList.razor.rz.scp.css */
.eprint-tags[b-jtnacfz9y2] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.eprint-tag[b-jtnacfz9y2] {
    font-size: 0.8rem;
    padding: 0.2rem 0.6rem;
    background-color: var(--eprint-chip-bg, var(--card-bg));
    border: 1px solid var(--eprint-chip-border, var(--card-border));
    border-radius: 12px;
    color: var(--eprint-chip-text, var(--text-muted));
}
/* /Common/Components/UI/PrintTitleRow.razor.rz.scp.css */
.eprint-title-row[b-pnco5w974v] {
    display: flex;
    align-items: baseline;
    gap: 1rem;
}
/* /Common/Components/UI/RangeFilterGroup.razor.rz.scp.css */
/* Moved here from ContentSearchSelectorLayout's `.foe-search-selector ::deep
   .filter-drawer .range-inputs`, which reached a class it did not render.
   No `.range-inputs select` rule: both selects are bare elements and base.css
   owns the element vocabulary. */
.range-inputs[b-jg1puwfsta] {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}
/* /Common/Components/UI/ReadAloudBox.razor.rz.scp.css */
/* On paper a box of read-aloud text is one unit the GM reads out, so a page break never splits
   it — it moves whole to the next page instead (only text taller than a page can still break). */
@media print {
    .read-aloud-box[b-92hz38dd5g] {
        break-inside: avoid;
        page-break-inside: avoid;
    }
}

.read-aloud-box[b-92hz38dd5g] {
    margin: 0;
    padding: 0.75rem 1rem;
    border-left: 4px solid var(--eprint-heading-rule, var(--accent-color));
    border-radius: 4px;
    background: var(--eprint-panel-bg, var(--editor-highlight-bg));
    color: var(--eprint-value, var(--text-color));
    font-style: italic;
    line-height: 1.6;
    white-space: pre-line;
    overflow-wrap: anywhere;
}
/* /Common/Components/UI/RosterDetail.razor.rz.scp.css */
/* Reclaimed verbatim from base.css (ladder rung 2) — roster detail line. */
.roster-detail[b-p0663mlhyc] {
    font-size: 0.8rem;
    color: var(--text-color);
}

/* Reclaimed from EncounterDisplay's `.roster-display-item ::deep .roster-detail`,
   which took font-size and color off this file on the display page. */
.roster-detail--display[b-p0663mlhyc] {
    font-size: 0.85rem;
    color: var(--text-muted);
}
/* /Common/Components/UI/ScrollBody.razor.rz.scp.css */
.scroll-body[b-8ogk8el8uf] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}
/* /Common/Components/UI/SearchBox.razor.rz.scp.css */
/* The debounced search field, box and all. Two things used to be wrong here and
   both were invisible to the guards because `.search-box` was four different
   shapes under one name — this component, a hand-rolled copy in
   ContentCardSelectorLayout, and a bare token on two <input> elements that no rule
   anywhere could reach.

   1. The skin was stated twice, on the wrapper AND on the input, so the field
      drew a box inside a box; both copies restated `.form-control` from
      base.css with different values. The input carries `.form-control`, which
      is rung 4's word on what a text field looks like, so neither copy is here
      any more.
   2. `.search-box:focus` sat on a <div>, which never takes focus. Gone with it;
      base.css owns focus for the input.

   What is left is sizing, which is genuinely this component's: it is a flex
   child in every search bar that renders it. */

.search-box[b-itw9gawilc] {
    flex: 1;
    min-width: 200px;
    max-width: 400px;
}

/* FullWidth: the card selector stacks the field above a list rather than
   sitting it in a row, so the 400px cap is wrong there. A parameter, not a
   ::deep override from the caller — ContentSearchSelectorLayout used to reach in
   for exactly these three declarations. */
.search-box--full[b-itw9gawilc] {
    max-width: none;
    width: 100%;
}

/* Below the search bar's breakpoint every caller stacks, so the cap goes. */
@media (max-width: 768px) {
    .search-box[b-itw9gawilc] {
        max-width: none;
        width: 100%;
    }
}
/* /Common/Components/UI/SearchFilterContainer.razor.rz.scp.css */
/* Reclaimed from base.css (ladder rung 4 -> 2): ContentListLayout,
   ContentBundleList and CollectionList rendered the same wrapper. Transparent,
   so the page art shows behind the controls; it scrolls away with the page. */
.search-filter-container[b-n89qow1o9p] {
    margin-bottom: 2rem;
    padding: 0.75rem 0;
}
/* /Common/Components/UI/SearchInput.razor.rz.scp.css */
/* The search field's ink rule: no box, no fill, a 1.5px rule underneath that
   turns rubric on focus. Every search field renders this component instead of
   restating the skin. The doubled class beats base.css's `.form-control:focus`
   regardless of bundle order. */
.search-input.form-control[b-7znhujup8z] {
    background: none;
    backdrop-filter: none;
    border: 0;
    border-bottom: 1.5px solid var(--text-color);
    border-radius: 0;
    box-shadow: none;
}

.search-input.form-control:focus[b-7znhujup8z] {
    background: none;
    border-bottom-color: var(--rubric);
    box-shadow: none;
}
/* /Common/Components/UI/SearchRow.razor.rz.scp.css */
/* Reclaimed from base.css (ladder rung 4 -> 2): four components rendered
   this row. */

.search-row[b-o78n8hbxzo] {
    display: flex;
    gap: 1rem;
    align-items: center;
    margin-bottom: 1rem;
}

@media (max-width: 768px) {
    .search-row[b-o78n8hbxzo] {
        /* ponytail: release keeps the search-row as a column on mobile so
           the search input and "SHOW FILTERS" button each take full width.
           The view-toggle sits at the right edge of its row, below
           "SHOW FILTERS", as a small icon. Earlier this rule collapsed
           to a column AND made the view-toggle a full-width pill — we
           revert the full-width pill but keep the column direction. */
        flex-direction: column;
        align-items: stretch;
    }
}
/* /Common/Components/UI/SinglePrintPreview.razor.rz.scp.css */
/* SinglePrintPreview.razor.css - styles for the single print preview shell */

/* `.foe-display` is owned by <DisplayPage>; the narrow-screen and print
   variants live there too (this component renders the wrapper as its root, so
   no ::deep rule here could reach it). */

.single-print-actions[b-9iv27yfle3] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    justify-content: flex-start;
    margin-bottom: 1.5rem;
}

/* The print-style picker is the shared <PrintSelector>. */

/* No `select:focus` rule: base.css owns focus styling for every form element
   (rung 4) and this repeated it verbatim. */

/* Scroll wrapper only. The preview's width belongs to whatever it wraps, and
   both of those already own it at rung 1: <FoeCardFrame> sizes `.fixed-width`
   to the 194mm A4 printable width, <PrintSheet> sizes itself to the 210mm
   sheet. Nothing here restates a paper measurement — an override from this
   wrapper would outrank the owner (`.stat-block-scroll-wrapper[b-x] .frame
   .fixed-width` is 0,4,0 against the owner's 0,3,0) and quietly become the real
   card width.

   A block container, not flex: a flex centre line clips the left edge of a
   child wider than the box, while the owners' `margin: 0 auto` degrades to 0
   and keeps every millimetre reachable. Wider viewport → centred; narrower →
   sideways scroll here rather than on the document. Same idiom as
   ContentDisplayLayout's `.foe-stat-block`.

   The viewport-width blocks that used to live here are gone — they stretched
   the card to 100% above 769px and reflowed its internals below 768px, so the
   preview showed a layout on screen that no printer ever emits. Two `::deep`
   selectors went with them: `.stat-block` and `.dh-stat-block` render only on
   the display pages (MonsterDisplay, AdversaryDisplay), never inside this
   wrapper, and MonsterStatBlock writes its width as an inline style anyway. */
.stat-block-scroll-wrapper[b-9iv27yfle3] {
    display: block;
    overflow-x: auto;
}

/* The display-options bar is the shared <PrintDisplayOptions> component. */

@media print {
    .no-print[b-9iv27yfle3] {
        display: none !important;
    }

    .stat-block-scroll-wrapper[b-9iv27yfle3] {
        overflow-x: visible;
        display: block;
    }
}

/* base.css also carried a `.display-options` bar. It was dead there, and the
   bar is a component now — so it is NOT reclaimed here. The toggles
   themselves are owned by ToggleOption.razor.css. */
/* /Common/Components/UI/SpellGroup.razor.rz.scp.css */
.spell-group[b-g45v9hcb17] {
    background: var(--feature-editor-bg);
    padding: 0.75rem;
    margin-bottom: 1rem;
    border-radius: 4px;
    border: 1px solid var(--feature-editor-border);
}

.spell-group-header[b-g45v9hcb17] {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.5rem;
    align-items: flex-end;
    margin-bottom: 0.75rem;
    padding: 0.5rem;
    background: var(--card-bg);
    border-radius: 4px;
    border: 1px solid var(--feature-editor-border);
}

[b-g45v9hcb17] .form-group--compact {
    flex: 1 1 auto;
    margin-bottom: 0;
    min-width: 4.5rem;
}

[b-g45v9hcb17] .form-group--compact label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 0.2rem;
}

/* No `.form-group--compact input` rule: both compact fields slot an
   <InputNumber class="form-control">, and base.css already gives .form-control
   `width: 100%`. The rule restated it one specificity level up, where it also
   covered any checkbox a caller might slot in — base.css sizes those. */

@media (max-width: 480px) {
    .spell-group-header[b-g45v9hcb17] {
        flex-wrap: wrap;
    }
}
/* /Common/Components/UI/StatBlockNotesArea.razor.rz.scp.css */
/* The write-in notes strip at the foot of both stat-block cards. MonsterContent
   and AdversaryContent rendered byte-identical markup and defined .notes-area
   with a byte-identical body; only the rule line's colour differed, which each
   card now supplies through --statblock-note-line. */
.notes-area[b-aohuvk7x1x] {
    margin-top: 4px;
    position: relative;
}

/* Was an inline style attribute on the <strong> in both cards. */
.notes-area strong[b-aohuvk7x1x] {
    position: absolute;
    left: 0;
    bottom: 0;
}

.note-line[b-aohuvk7x1x] {
    border-bottom: 1px solid var(--statblock-note-line);
    height: 2rem;
    margin-bottom: 3px;
}
/* /Common/Components/UI/SuggestionItem.razor.rz.scp.css */
/* Reclaimed verbatim from base.css (ladder rung 2) — suggestion desc/source lines. */
.suggestion-desc[b-ebuocy0ode] {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin: 0.1rem 0 0;
    line-height: 1.4;
    width: 100%;
}

.suggestion-source[b-ebuocy0ode] {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-style: italic;
    width: 100%;
}
/* /Common/Components/UI/SuggestionLoading.razor.rz.scp.css */
/* Reclaimed verbatim from base.css (ladder rung 2) — suggestion loading line. */
.suggestion-loading[b-knbggoabd7] {
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}
/* /Common/Components/UI/SystemBadge.razor.rz.scp.css */
.system-badge[b-1yg84yxja0] {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.2rem 0.6rem;
    border-radius: 4px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.system-badge.dnd[b-1yg84yxja0] {
    background: var(--color-gold);
    color: var(--on-primary-text);
}

.system-badge.dh[b-1yg84yxja0] {
    background: var(--color-copper);
    color: var(--on-primary-text);
}
/* /Common/Components/UI/TabSet.razor.rz.scp.css */
/* The row fades out at an edge that has more tabs behind it, so a clipped tab reads as "scroll".
   Browsers without scroll-driven animations show the plain clipped row. */
@property --fade-start {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@property --fade-end {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@keyframes tab-list-fade-b-hno4dpok54 {
    0% { --fade-start: 0px; --fade-end: 1.75rem; }
    8% { --fade-start: 1.75rem; }
    92% { --fade-end: 1.75rem; }
    100% { --fade-start: 1.75rem; --fade-end: 0px; }
}

/* Mobile-first: one row of tabs that scrolls sideways; the focused tab scrolls into view. */
.tab-list[b-hno4dpok54] {
    display: flex;
    flex-shrink: 0; /* overflow-x makes it shrinkable in a flex column: tall panel content would draw over it */
    gap: 0.375rem;
    overflow-x: auto;
    scrollbar-width: thin;
    padding: 2px 2px 0.5rem;
}

@supports (animation-timeline: scroll()) {
    .tab-list[b-hno4dpok54] {
        animation: tab-list-fade-b-hno4dpok54 linear both;
        animation-timeline: scroll(self inline);
        mask-image: linear-gradient(to right, transparent, currentColor var(--fade-start), currentColor calc(100% - var(--fade-end)), transparent);
    }
}

.tab[b-hno4dpok54] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: 0.5rem 1rem;
    border: 1px solid var(--input-border);
    border-radius: 6px;
    background: var(--control-glass-bg, var(--bg-input));
    color: var(--text-color);
    font: inherit;
    white-space: nowrap;
    cursor: pointer;
}

.tab:hover[b-hno4dpok54] {
    border-color: var(--accent-color);
}

.tab:focus-visible[b-hno4dpok54] {
    outline: 2px solid var(--focus-color);
    outline-offset: 2px;
}

.tab[aria-selected="true"][b-hno4dpok54] {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: var(--on-accent-text);
}

.tab-error[b-hno4dpok54] {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--focus-color);
}

.tab[aria-selected="true"] .tab-error[b-hno4dpok54] {
    background: var(--on-accent-text);
}

/* Underlined: the builder's phone tab bar look, on the tab list. */
.tab-list--underlined[b-hno4dpok54] {
    gap: 0;
    padding: 0;
    border-bottom: 1px solid var(--card-border);
}

.tab-list--underlined .tab[b-hno4dpok54] {
    flex: 1 0 auto;
    justify-content: center;
    min-height: 0;
    padding: 0.625rem 0.5rem;
    border: none;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.85rem;
    font-weight: 600;
}

.tab-list--underlined .tab:hover[b-hno4dpok54] {
    background: rgba(var(--highlight-rgb), 0.05);
    color: var(--text-color);
}

.tab-list--underlined .tab[aria-selected="true"][b-hno4dpok54] {
    background: rgba(var(--highlight-rgb), 0.05);
    border-bottom-color: var(--accent-color);
    color: var(--accent-color);
}

/* StackOnPhones: phones get no tab list and every panel, the page picks what shows. */
.tab-list--from-desktop[b-hno4dpok54] {
    display: none;
}

.tab-panels--stacked[b-hno4dpok54]  [role="tabpanel"][hidden] {
    display: block;
}

@media (min-width: 769px) {
    .tab-list--from-desktop[b-hno4dpok54] {
        display: flex;
    }

    .tab-panels--stacked[b-hno4dpok54]  [role="tabpanel"][hidden] {
        display: none;
    }
}
/* /Common/Components/UI/TagChip.razor.rz.scp.css */
.tag-chip[b-1hvotkekz2] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.8rem;
    background: var(--card-bg);
    color: var(--text-color);
    border: 1px solid var(--card-border);
}

/* Display variant (<span>, no Selected/OnClick) - verbatim from the original
   atom (git show 119880e3:.../TagChip.razor.css), before an earlier round of
   this task widened `.tag-chip`'s shared base to match the toggle sites and
   silently reshaped this look too. The only real consumer is
   FeaturedFeed.razor's Text-only <TagChip> (predates this task; see the
   component's doc comment). Qualified :not(.tag-chip--selected) - see the
   toggle-family rule below for why a selected span is excluded here. */
span.tag-chip:not(.tag-chip--selected)[b-1hvotkekz2] {
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    font-family: var(--font-header);
    font-weight: 600;
}

/* Toggle-family sizing - verbatim from the retired base.css `.tag-chip`
   block (same commit). Applies to every <button> (the four theme-tag toggle
   sites: TagsSection, FullConversionWizard, QuickConversionView,
   EnvironmentEdit) AND to a *selected* <span>
   (QuickConversionView's readonly zone specifically): that readonly chip was
   a hand-rolled <span class="tag-chip tag-active"> styled by base.css's
   single, unscoped `.tag-chip` rule before this task - it never went through
   this atom's own scoped CSS, so its real pre-existing look (including
   cursor: pointer) was already this "toggle" look despite being a <span>. A
   plain span-vs-button element split would silently shrink it back to the
   atom's tiny heading-font look, which it never had - confirmed by reading
   both the retired base.css `.tag-chip` block and the QuickConversionView's
   own scoped .tag-active override at git show 119880e3. */
button.tag-chip[b-1hvotkekz2], .tag-chip--selected[b-1hvotkekz2] {
    padding: 0.25rem 0.6rem;
    border-radius: 12px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s ease;
}

.tag-chip--selected[b-1hvotkekz2] {
    background: var(--accent-color);
    color: var(--on-accent-text);
    border-color: var(--accent-color);
}

.tag-chip--selected:hover[b-1hvotkekz2] {
    opacity: 0.85;
}

/* Unselected *interactive* (toggle button) state - values carried over
   verbatim from the old base.css `.tag-inactive` (see
   git show 119880e3:.../base.css) rather than dropped when that class name
   was retired. Qualified to `button.tag-chip` specifically: the retired
   `.tag-inactive` only ever appeared on the four hand-rolled toggle
   <button>s, never on a display <span>. FeaturedFeed.razor renders a
   Text-only, Selected/OnClick-less <TagChip> (a pre-existing consumer, not
   introduced by this task) that must keep its plain, unmuted look - an
   unqualified `.tag-chip:not(.tag-chip--selected)` would incorrectly catch
   that span too. */
button.tag-chip:not(.tag-chip--selected)[b-1hvotkekz2] {
    background: var(--bg-input);
    color: var(--text-muted);
}

button.tag-chip:not(.tag-chip--selected):hover[b-1hvotkekz2] {
    border-color: var(--accent-color);
    color: var(--text-color);
}

.tag-chip-remove[b-1hvotkekz2] {
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    padding: 0 0.25rem;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
}

.tag-chip-remove:hover[b-1hvotkekz2] {
    opacity: 1;
}
/* /Common/Components/UI/TagGrid.razor.rz.scp.css */
/* Tag chip container. Reclaimed from base.css (ladder rung 4 -> 2): four
   components rendered an identical bare `<div class="tag-grid">` around a set
   of <TagChip>, which is a shared component, not a global class. */

.tag-grid[b-6iaw4ogqlp] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.75rem;
    margin-top: 0.25rem;
    max-height: 4.5rem;
    overflow-y: auto;
    padding-right: 0.25rem;
}

@media (max-width: 480px) {
    .tag-grid[b-6iaw4ogqlp] {
        max-height: 6rem;
    }
}

/* Read-only variant (QuickConversionView's collapsed tag list): reclaimed
   verbatim from QuickConversionView.razor.css. It restates the layout the base
   rule already sets — kept as shipped rather than "cleaned up". */
.tag-grid-readonly[b-6iaw4ogqlp] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
/* /Common/Components/UI/TierGateTeaser.razor.rz.scp.css */
.foe-teaser-view[b-f0mtyvm4gf] {
    max-width: 42rem;
    margin: 2rem auto;
    padding: 1.5rem;
    text-align: center;
}

.foe-teaser-description[b-f0mtyvm4gf] {
    color: var(--text-muted);
    font-size: 1rem;
    line-height: 1.6;
    margin: 1rem 0;
}
/* /Common/Components/UI/ToggleChip.razor.rz.scp.css */
.toggle-chip[b-siqyzuxvx4] {
    padding: 0.35rem 0.75rem;
    border-radius: 16px;
    border: 1px solid var(--card-border);
    font-family: var(--font-body);
    font-size: 0.9rem;
    cursor: pointer;
    transition: all 0.15s ease;
}

.toggle-chip:hover[b-siqyzuxvx4] {
    transform: scale(1.05);
}

.toggle-chip--neutral[b-siqyzuxvx4] {
    background: var(--card-bg);
    color: var(--text-muted);
    border-color: var(--card-border);
}

.toggle-chip--active[b-siqyzuxvx4] {
    background: linear-gradient(135deg, var(--color-success), var(--color-success-light));
    color: var(--on-success-text);
    border-color: var(--color-success-dark);
    font-weight: 600;
}

.toggle-chip--resist[b-siqyzuxvx4] {
    background: linear-gradient(135deg, var(--resist-badge-start), var(--resist-badge-end));
    color: white;
    border-color: var(--resist-badge-border);
    font-weight: 600;
}

.toggle-chip--immune[b-siqyzuxvx4] {
    background: linear-gradient(135deg, var(--defense-badge-start), var(--defense-badge-end));
    color: white;
    border-color: var(--defense-badge-border);
    font-weight: 600;
}

.toggle-chip--vulnerable[b-siqyzuxvx4] {
    background: linear-gradient(135deg, var(--mm-accent-red), var(--immune-badge-end));
    color: white;
    border-color: var(--mm-accent-maroon);
    font-weight: 600;
}

/* Editing in place: the chip holds an input, so it stops behaving like a button. */
.toggle-chip--editing[b-siqyzuxvx4] {
    color: var(--text-color);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: text;
}

.toggle-chip--editing:hover[b-siqyzuxvx4] {
    transform: none;
}
/* /Common/Components/UI/ToggleOption.razor.rz.scp.css */
.toggle-option[b-wpg86m1iyq] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    font-family: var(--font-body);
    color: var(--text-color);
    white-space: nowrap;
}

.toggle-option span[b-wpg86m1iyq] {
    font-size: 0.9rem;
}
/* /Common/Components/UI/TypeBadge.razor.rz.scp.css */
/* Moved verbatim from Home.razor.css and FeaturedFeed.razor.css, which defined
   this class identically (ladder rung 2). */

.type-badge[b-b2pjvmhay3] {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    background: var(--filter-tag-bg);
    color: var(--filter-tag-color);
    border-radius: 3px;
    font-size: 0.75rem;
    font-family: var(--font-header);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
}
/* /Common/Components/UI/WarningRow.razor.rz.scp.css */
/* Merged from EncounterAssessmentPanel.razor.css (.assessment-warning,
   .warning-icon, .warning-text, .severity-*) and EncounterAutoFillPanel.razor.css
   (.autofill-warning-item, .warning-icon, .warning-text) — ladder rung 2. */

.warning-row[b-c5g9fbyyap] {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    font-size: 0.8rem;
    padding: 0.25rem 0;
}

.warning-icon[b-c5g9fbyyap] {
    flex-shrink: 0;
    line-height: 1.3;
}

.warning-text[b-c5g9fbyyap] {
    flex: 1;
}

/* The padded box variant: the auto-fill panel's linked-foe warnings. */
.warning-row--boxed[b-c5g9fbyyap] {
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-radius: 4px;
    font-size: 0.85rem;
    color: var(--on-warning-text);
    background: color-mix(in srgb, var(--color-warning) 15%, transparent);
    border: 1px solid var(--color-warning-dark);
}

.warning-row--boxed .warning-icon[b-c5g9fbyyap] {
    color: var(--color-warning-dark);
    line-height: normal;
}

.warning-row--boxed .warning-text[b-c5g9fbyyap] {
    min-width: 0;
}

/* Severity modifiers, passed in through Class. They must live here: the row
   carries this component's scope id, so the same rules in the calling panel's
   sheet would compile to `.severity-critical[b-panel]` and match nothing. */
.severity-info[b-c5g9fbyyap] {
    color: var(--text-muted);
}

.severity-caution[b-c5g9fbyyap] {
    color: var(--difficulty-moderate-text);
}

.severity-critical[b-c5g9fbyyap] {
    color: var(--difficulty-hard-text);
    font-weight: 600;
}
/* /Common/Components/UI/WizardActions.razor.rz.scp.css */
.wizard-actions[b-of20ssshdf] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
}
/* /Common/Components/UI/WizardError.razor.rz.scp.css */
/* Colour lives here, not on a `text-danger` utility: that class was a Bootstrap
   remnant with no rule left anywhere, so the error text rendered in body colour. */
.wizard-error[b-tj0p10tmbu] {
    margin-top: 0.5rem;
    color: var(--danger-ink);
}
/* /Common/Components/UI/WizardHint.razor.rz.scp.css */
.wizard-hint[b-2i6upfvz25] {
    color: var(--text-muted);
    font-size: 0.875rem;
    margin-bottom: 1rem;
}
/* /Common/Components/UI/WizardOptionsRow.razor.rz.scp.css */
.wizard-dice-options[b-zdn2fp88fr] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}
/* /Common/Components/UI/WizardPreviewSummary.razor.rz.scp.css */
.wizard-preview-summary[b-vp3qkk7a0m] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

@media (max-width: 600px) {
    .wizard-preview-summary[b-vp3qkk7a0m] {
        grid-template-columns: 1fr;
    }
}
/* /Common/Components/UI/WizardPreviewTable.razor.rz.scp.css */
.wizard-preview-table[b-r4j2a7u343] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

/* The rows are slotted, so they carry the caller's scope id — reach them with ::deep. */
.wizard-preview-table[b-r4j2a7u343]  th,
.wizard-preview-table[b-r4j2a7u343]  td {
    padding: 0.4rem 0.75rem;
    text-align: left;
    border-bottom: 1px solid var(--card-border);
    color: var(--text-color);
}

.wizard-preview-table[b-r4j2a7u343]  th {
    width: 180px;
    font-weight: 600;
    color: var(--text-muted);
}
/* /Common/Components/UI/WizardStepCard.razor.rz.scp.css */
/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.wizard-step[b-9v99tr5h5v] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 1.25rem;
    margin-bottom: 1rem;
}

.wizard-step h3[b-9v99tr5h5v] {
    margin: 0 0 1rem;
    font-size: 1.05rem;
    color: var(--text-color);
}
/* /Common/Components/UI/WriteInLines.razor.rz.scp.css */
.write-in-lines[b-ajp0fmoph7] {
    margin-bottom: 0.75rem;
}

.write-in-label[b-ajp0fmoph7] {
    font-weight: 600;
    color: var(--eprint-value, var(--text-color));
    margin-bottom: 0.15rem;
}

.write-in-hint[b-ajp0fmoph7] {
    font-style: italic;
    font-size: 0.85em;
    color: var(--eprint-label, var(--text-muted));
    margin-bottom: 0.2rem;
}

.write-in-line[b-ajp0fmoph7] {
    border-bottom: 1px solid var(--eprint-soft-rule, var(--card-border));
    height: 1.6rem;
}

.write-in-line + .write-in-line[b-ajp0fmoph7] {
    margin-top: 0.4rem;
}

@media print {
    .write-in-line[b-ajp0fmoph7] {
        height: 1.3rem;
    }
}
/* /Common/Layout/LanguageSwitcher.razor.rz.scp.css */
.language-switcher[b-3asnmxd61x] {
    position: relative;
    display: inline-block;
}

.language-switcher-trigger[b-3asnmxd61x] {
    appearance: none;
    -webkit-appearance: none;
    background: rgba(var(--highlight-rgb), 0.1);
    border: 1px solid rgba(var(--highlight-rgb), 0.2);
    border-radius: 6px;
    color: var(--nav-text);
    font-family: var(--font-body), serif;
    font-size: 0.85rem;
    padding: 0.4rem 0.6rem;
    cursor: pointer;
    line-height: 1.4;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}

.language-switcher-trigger:hover[b-3asnmxd61x] {
    border-color: rgba(var(--highlight-rgb), 0.3);
    background-color: rgba(var(--highlight-rgb), 0.15);
}

.language-switcher-trigger:focus[b-3asnmxd61x] {
    outline: none;
    border-color: var(--nav-border);
    box-shadow: 0 0 0 0.15rem var(--focus-shadow);
}

.language-label[b-3asnmxd61x] {
    white-space: nowrap;
}

.language-chevron[b-3asnmxd61x] {
    font-size: 0.8rem;
    transition: transform 0.2s ease;
    opacity: 0.7;
}

.language-chevron.open[b-3asnmxd61x] {
    transform: rotate(180deg);
}

.language-dropdown[b-3asnmxd61x] {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 100%;
    background: var(--dropdown-bg);
    border: 1px solid var(--dropdown-border);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(var(--shadow-rgb), 0.3);
    z-index: 1000;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.language-option[b-3asnmxd61x] {
    background: transparent;
    border: none;
    color: var(--dropdown-text);
    font-family: var(--font-body), serif;
    font-size: 0.85rem;
    padding: 0.5rem 0.75rem;
    cursor: pointer;
    text-align: left;
    transition: background-color 0.15s ease;
    white-space: nowrap;
}

.language-option:hover[b-3asnmxd61x] {
    background-color: rgba(var(--highlight-rgb), 0.1);
}

.language-option.selected[b-3asnmxd61x] {
    background-color: rgba(var(--color-gold-rgb), 0.25);
    color: var(--accent-color);
}

@media (max-width: 480px) {
    .language-switcher-trigger[b-3asnmxd61x] {
        padding: 0.3rem 0.4rem;
        font-size: 0.8rem;
        gap: 0.2rem;
    }

    .language-chevron[b-3asnmxd61x] {
        font-size: 0.7rem;
    }
}
/* /Common/Layout/MainLayout.razor.rz.scp.css */
.page[b-2w1iv9ewib] {
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    background: var(--page-bg);
    color: var(--text-color);
    font-family: var(--font-body);
    transition: background-color 0.3s ease;
}

/* Desktop screens: pin header/footer and scroll only main content. Screen only:
   A4 paper is wider than 769px, and the 100svh lock printed one sheet. */
@media screen and (min-width: 769px) {
    .page[b-2w1iv9ewib] {
        height: 100svh;
        min-height: 100svh;
        overflow: hidden;
    }

    .page-body[b-2w1iv9ewib] {
        flex: 1 1 auto;
        min-height: 0;
        overflow: hidden;
    }

    /* A size container: the page art (PageBackdrop) is as tall as this
       scrolling column (100cqh). */
    .main-content[b-2w1iv9ewib] {
        overflow-y: auto;
        height: 100%;
        container-type: size;
        display: flex;
        flex-direction: column;
    }

    .main-content .content[b-2w1iv9ewib] {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }
}

.top-bar[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.5rem 1rem;
    background: var(--nav-bg);
    box-shadow: inset 0 -2px 0 rgba(var(--ink-pale-rgb), 0.12), 0 3px 10px rgba(var(--shadow-rgb), 0.25);
    color: var(--nav-text);
    gap: 1rem;
    overflow-x: clip;
}

.brand-and-hamburger[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

.brand[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: inherit;
}

.brand:hover[b-2w1iv9ewib] {
    opacity: 0.9;
}

.brand-text[b-2w1iv9ewib] {
    font-family: var(--font-header);
    font-size: 1.2rem;
    color: var(--nav-text);
    letter-spacing: 0.5px;
}

.brand-text__accent[b-2w1iv9ewib] {
    font-family: var(--font-label);
    color: var(--spine-accent);
}

.nav-center[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex: 1;
    justify-content: center;
}

.header-right[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 1;
    min-width: 0;
}

/* Hamburger button — hidden on desktop, shown on mobile */
.hamburger-btn[b-2w1iv9ewib] {
    display: none;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--nav-text);
    cursor: pointer;
    padding: 0.375rem;
    border-radius: 6px;
    transition: background 0.15s ease;
    flex-shrink: 0;
}

.hamburger-btn:hover[b-2w1iv9ewib] {
    background: rgba(var(--highlight-rgb), 0.1);
}

/* ── Sidebar layout ───────────────────────────────────── */

.page-body[b-2w1iv9ewib] {
    display: flex;
    flex: 1;
    position: relative;
}

.sidebar[b-2w1iv9ewib] {
    width: 220px;
    flex-shrink: 0;
    background: var(--sidebar-bg);
    border-right: 3px double var(--card-border);
    display: flex;
    flex-direction: column;
    transition: width 0.2s ease;
    /* overflow: visible keeps the SystemNav dropdown from being clipped */
    overflow: visible;
    z-index: 50;
    color: var(--side-ink);
}

/* Inner sticky wrapper — nav sticks while sidebar background fills full content height */
.sidebar-nav[b-2w1iv9ewib] {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    overflow: visible;
    /* Takes the height left above the toggle button; the sub-nav scrolls within it. */
    flex: 1 1 auto;
    min-height: 0;
}

.sidebar--collapsed[b-2w1iv9ewib] {
    width: 56px;
}

.sidebar-system[b-2w1iv9ewib] {
    padding: 0.625rem 0.5rem;
    border-bottom: 1px solid var(--side-border);
    overflow: visible;
}

/* Sidebar collapse toggle button
   — sticky so it tracks the viewport bottom while scrolling,
     and naturally stops when the sidebar ends (at the footer's top) */
.sidebar-toggle-btn[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: 0.625rem;
    background: transparent;
    border: none;
    border-top: 1px solid var(--side-border);
    color: inherit;
    cursor: pointer;
    transition: background 0.15s ease;
    flex-shrink: 0;
    opacity: 0.7;
    position: sticky;
    bottom: 0;
    margin-top: auto;
    z-index: 51;
}

.sidebar-toggle-btn:hover[b-2w1iv9ewib] {
    background: var(--side-active-bg);
    opacity: 1;
}

/* Overlay for mobile sidebar */
.sidebar-overlay[b-2w1iv9ewib] {
    position: fixed;
    inset: 0;
    background: rgba(var(--shadow-rgb), 0.5);
    z-index: 149;
}

/* ── Main content ─────────────────────────────────────── */

.main-content[b-2w1iv9ewib] {
    flex: 1;
    min-width: 0;
    /* Positioned and isolated for PageBackdrop, which sits behind the content
       at z-index -1 and sticks to the top of this column's scroll. */
    position: relative;
    isolation: isolate;
    /* The ground: page colour under a grain and a mottle, below the page art. */
    background: var(--paper-noise), var(--paper-mottle), var(--page-bg);
    background-blend-mode: var(--ground-blend);
}

.main-content--locked[b-2w1iv9ewib] {
    overflow-y: hidden;
}

/* Positioned and isolated for the glass cards' blur layer (GlassLayer), which
   sits behind each card at z-index -1, above the page art. */
.content[b-2w1iv9ewib] {
    position: relative;
    isolation: isolate;
    padding: 1rem 2rem;
}

/* ── Global nav (non-system pages) ─────────────────────── */

.global-nav[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.5rem 1rem;
    background: var(--nav-bg);
    border-bottom: 1px solid rgba(var(--ink-pale-rgb), 0.12);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}

.global-nav[b-2w1iv9ewib]::-webkit-scrollbar {
    display: none;
}

.global-nav-link[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
    border-radius: var(--radius-sm);
    color: var(--nav-text-muted);
    text-decoration: none;
    font-size: 0.875rem;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease;
    flex-shrink: 0;
}

.global-nav-link:hover[b-2w1iv9ewib] {
    background: rgba(var(--highlight-rgb), 0.08);
    color: var(--nav-text);
}

.global-nav-link.active[b-2w1iv9ewib] {
    background: rgba(var(--ink-pale-rgb), 0.12);
    color: var(--spine-accent);
    font-weight: 600;
}

.global-nav-link svg[b-2w1iv9ewib] {
    flex-shrink: 0;
}

@media (max-width: 768px) {
    .global-nav[b-2w1iv9ewib] {
        padding: 0.375rem 0.75rem;
        gap: 0.125rem;
    }

    .global-nav-link[b-2w1iv9ewib] {
        padding: 0.375rem 0.5rem;
        font-size: 0.8125rem;
    }
}

/* ── Footer ───────────────────────────────────────────── */

.site-footer[b-2w1iv9ewib] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    padding: 1rem 2rem;
    background: var(--nav-bg);
    font-size: 0.85rem;
    color: var(--nav-text-muted);
    position: relative;
    z-index: 0;
}

.site-footer a[b-2w1iv9ewib] {
    color: var(--spine-accent);
    text-decoration: none;
    transition: opacity 0.2s ease;
}

.site-footer a:hover[b-2w1iv9ewib] {
    opacity: 0.8;
    text-decoration: underline;
}

.footer-links[b-2w1iv9ewib] {
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
    justify-content: center;
}

/* ── Responsive ───────────────────────────────────────── */

@media (max-width: 768px) {
    .hamburger-btn[b-2w1iv9ewib] {
        display: flex;
    }

    .top-bar[b-2w1iv9ewib] {
        padding: 0.5rem 0.75rem;
        gap: 0.5rem;
    }

    .header-right[b-2w1iv9ewib] {
        gap: 0.375rem;
    }

    .content[b-2w1iv9ewib] {
        padding: 1rem;
    }

    .brand-text[b-2w1iv9ewib] {
        font-size: 1rem;
    }

    /* Sidebar becomes a fixed overlay on mobile */
    .sidebar[b-2w1iv9ewib] {
        position: fixed;
        top: 0;
        left: -220px;
        height: 100svh;
        max-height: 100svh;
        width: 220px !important; /* always full-width on mobile */
        z-index: 150;
        transition: left 0.25s ease;
        /* The drawer covers the page, so it is opaque: the tint over the page colour. */
        background: linear-gradient(var(--sidebar-bg), var(--sidebar-bg)), var(--page-bg);
    }

    /* Inside a fixed sidebar, the inner nav fills the container normally */
    .sidebar-nav[b-2w1iv9ewib] {
        position: static;
    }

    .sidebar--mobile-open[b-2w1iv9ewib] {
        left: 0;
    }

    /* Force expanded sidebar on mobile regardless of desktop collapsed preference */
    .sidebar--collapsed[b-2w1iv9ewib] {
        width: 220px !important;
    }
}

@media (max-width: 480px) {
    .brand-text[b-2w1iv9ewib] {
        display: none;
    }

    .header-right[b-2w1iv9ewib] {
        gap: 0.25rem;
    }
}

@media print {
    .top-bar[b-2w1iv9ewib],
    .sidebar[b-2w1iv9ewib],
    .site-footer[b-2w1iv9ewib] {
        display: none !important;
    }

    .main-content[b-2w1iv9ewib] {
        background: none;
    }

    .content[b-2w1iv9ewib] {
        padding: 0;
    }
}



/* ── Shell chrome (reclaimed from base.css, ladder rung 1).
   #blazor-error-ui's .dismiss/.reload stay global — wwwroot/index.html
   renders that banner too, outside CSS isolation.

   base.css also carried `.page` and `.content` blocks. Both were DEAD there:
   Blazor scoping appends an attribute selector, so this file's `.page[b-xxx]`
   (0,2,0) outranked the global `.page` (0,1,0). Moving them here would have
   resurrected them as later-in-source duplicates of the real rules at the top
   of this file — `.page` would have replaced `background: var(--page-bg)` with
   the light `var(--bg-main)`, killing the dark theme, and `.content` would have
   overridden the mobile and print padding resets. They were deleted, not moved.
   Only the `.brand` breakpoint below was genuinely live and is kept. ── */
@media (max-width: 640px) {
    .brand[b-2w1iv9ewib] {
        justify-content: center;
    }
}
/* /Common/Layout/OgRenderLayout.razor.rz.scp.css */
/* `position`/`display`/`transform-origin` reclaimed from the <style> block in
   OgRenderLayout.razor — js/og-render.js scales `.og-render-content`, so the
   origin has to stay top-left. The box metrics were already here and always
   outranked that block, which only ever contributed those three declarations. */

.og-render-frame[b-63gp2l3gd6] {
    width: 1200px;
    height: 630px;
    overflow: hidden;
    position: relative;
}

.og-render-content[b-63gp2l3gd6] {
    width: 1200px;
    height: 630px;
    overflow: hidden;
    display: inline-block;
    transform-origin: top left;
}

.og-render-content[b-63gp2l3gd6]  > * {
    width: 100%;
    height: 100%;
}
/* /Common/Layout/SystemNav.razor.rz.scp.css */
.system-nav[b-ua26uufg3h] {
    position: relative;
    /* merged from MainLayout.razor.css ::deep */
    width: 100%;
}

.system-switcher[b-ua26uufg3h] {
    position: relative;
}

.current-system[b-ua26uufg3h] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    background: rgba(var(--ink-rgb), 0.06);
    border: 1px solid var(--side-border);
    border-radius: var(--radius-sm);
    color: inherit;
    cursor: pointer;
    transition: all 0.2s ease;
    /* merged from MainLayout.razor.css ::deep — the nav only ever renders
       inside the sidebar, so the sidebar's overrides win outright */
    width: 100%;
    box-sizing: border-box;
    font-size: 0.875rem;
}

.current-system:hover[b-ua26uufg3h] {
    background: var(--side-active-bg);
    border-color: var(--card-border);
}

.system-icon[b-ua26uufg3h] {
    font-size: 1.1rem;
}

.dropdown-arrow[b-ua26uufg3h] {
    font-size: 0.8rem;
    transition: transform 0.2s ease;
    opacity: 0.7;
}

.dropdown-arrow.open[b-ua26uufg3h] {
    transform: rotate(180deg);
}

.system-dropdown[b-ua26uufg3h] {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 220px;
    background: var(--dropdown-bg);
    border: 1px solid var(--dropdown-border);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(var(--shadow-rgb), 0.3);
    z-index: 1000;
    overflow: hidden;
}

.system-option[b-ua26uufg3h] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    color: var(--dropdown-text);
    text-decoration: none;
    transition: background 0.15s ease;
}

.system-option:hover[b-ua26uufg3h] {
    background: rgba(var(--ink-rgb), 0.06);
}

.system-option.active[b-ua26uufg3h] {
    background: rgba(var(--ink-rgb), 0.12);
}

.system-option .system-name[b-ua26uufg3h] {
    flex: 1;
}

.check-mark[b-ua26uufg3h] {
    color: var(--accent-color);
    font-weight: bold;
}

.single-system[b-ua26uufg3h] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    /* merged from MainLayout.razor.css ::deep */
    font-size: 0.875rem;
}

/* ── Sidebar adaptations (driven by the Collapsed parameter, ladder rung 1) ──
   Moved from MainLayout.razor.css ::deep. SystemNav is only ever rendered
   inside MainLayout's .sidebar-system, so the ancestor selector was redundant. */

/* Collapsed: hide system name in the trigger button only, not in the dropdown */
.system-nav--collapsed .current-system .system-name[b-ua26uufg3h] {
    display: none;
}

.system-nav--collapsed .dropdown-arrow[b-ua26uufg3h] {
    display: none;
}

.system-nav--collapsed .current-system[b-ua26uufg3h] {
    justify-content: center;
    padding: 0.5rem;
    font-size: 1rem;
}

/* Show abbreviated system indicator in collapsed mode */
.system-nav--collapsed .current-system[b-ua26uufg3h]::after {
    content: '⇅';
    font-size: 0.9rem;
    opacity: 0.8;
}

/* Mobile forces the sidebar expanded, so the collapsed treatment is undone. */
@media (max-width: 768px) {
    .system-nav--collapsed .current-system .system-name[b-ua26uufg3h] {
        display: inline;
    }

    .system-nav--collapsed .dropdown-arrow[b-ua26uufg3h] {
        display: inline;
    }

    .system-nav--collapsed .current-system[b-ua26uufg3h] {
        justify-content: flex-start;
        padding: 0.5rem 0.75rem;
        font-size: 0.875rem;
    }

    .system-nav--collapsed .current-system[b-ua26uufg3h]::after {
        content: none;
    }
}
/* /Common/Layout/SystemSubNav.razor.rz.scp.css */
.sub-nav[b-v2yws29681] {
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: 0.5rem 0;
    color: var(--side-ink);
    gap: 0.125rem;
    /* Scrolls when the viewport is too short, so the sidebar's toggle button is never covered. */
    min-height: 0;
    overflow-y: auto;
}

/* ponytail: NavLink is a component, so its <a> output does NOT receive this
   file's scope attribute. ::deep keeps the rule scoped to .sub-nav descendants
   (the <a> rendered by <NavLink>) without leaking globally. */
[b-v2yws29681] .sub-nav-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    margin: 0 0.5rem;
    width: calc(100% - 1rem);
    color: inherit;
    text-decoration: none;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    transition: background 0.15s ease;
    position: relative;
    white-space: nowrap;
    box-sizing: border-box;
}

[b-v2yws29681] .sub-nav-link:hover {
    background: rgba(var(--ink-rgb), 0.05);
}

[b-v2yws29681] .sub-nav-link:active {
    background: var(--side-active-bg);
}

[b-v2yws29681] .sub-nav-link.active {
    background: var(--side-active-bg);
    font-weight: 600;
}

[b-v2yws29681] .sub-nav-link.active::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--rubric);
}

.sub-nav-icon[b-v2yws29681] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    flex-shrink: 0;
}

.sub-nav-icon svg[b-v2yws29681] {
    width: 100%;
    height: 100%;
}

.sub-nav-text[b-v2yws29681] {
    font-weight: 500;
    letter-spacing: 0.02em;
    overflow: hidden;
    text-overflow: ellipsis;
}

.print-badge[b-v2yws29681] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.3rem;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
    border-radius: 999px;
    background: var(--radio-accent);
    color: var(--on-primary-text);
    flex-shrink: 0;
    margin-left: auto;
}

/* Each group is a list (the foe tools' nested one too); headings and groups stack with the nav's own gap. */
.sub-nav-group[b-v2yws29681] {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.sub-nav-group-heading[b-v2yws29681] {
    margin: 0.75rem 1.25rem 0.25rem;
    font-family: var(--font-label);
    font-size: 0.85rem;
    letter-spacing: 0.08em;
    opacity: 0.75;
}

/* Foe tools nest under the foe entry. */
.sub-nav-children[b-v2yws29681] {
    margin-top: 0.125rem;
    padding-left: 1.25rem;
}

[b-v2yws29681] .sub-nav-link--child {
    font-size: 0.8125rem;
}

/* ── Collapsed state ─────────────────────────────────
   Desktop only: the mobile drawer always uses the expanded layout. */

@media (min-width: 769px) {
    .sub-nav--collapsed[b-v2yws29681]  .sub-nav-link {
        justify-content: center;
        padding: 0.6rem;
        gap: 0;
        margin: 0 auto;
        width: calc(100% - 0.75rem);
    }

    .sub-nav--collapsed .sub-nav-text[b-v2yws29681] {
        display: none;
    }

    /* Badge becomes a small corner dot in collapsed mode */
    .sub-nav--collapsed .print-badge[b-v2yws29681] {
        position: absolute;
        top: 4px;
        right: 4px;
        min-width: 1rem;
        height: 1rem;
        font-size: 0.6rem;
        padding: 0 0.15rem;
        margin-left: 0;
    }

    .sub-nav--collapsed .sub-nav-children[b-v2yws29681] {
        padding-left: 0;
    }

    /* The heading collapses to a thin divider; its text stays as the group's accessible name. */
    .sub-nav--collapsed .sub-nav-group-heading[b-v2yws29681] {
        height: 0;
        overflow: hidden;
        margin: 0.375rem 0.75rem;
        border-top: 1px solid var(--side-border);
    }
}
/* /Common/Layout/ThemeSwitcher.razor.rz.scp.css */
/* The icon is the icon component's own <svg>, not this component's element, so
   these rules reach it with ::deep (rung 3). Written bare, they compiled
   against this component's scope id, matched nothing, and the icon rendered
   at its default size. */
.theme-toggle[b-8ihhtt1vf9] {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    transition: background-color 0.2s ease;
}

.theme-toggle:hover[b-8ihhtt1vf9] {
    background-color: rgba(var(--highlight-rgb), 0.1);
}

.theme-toggle[b-8ihhtt1vf9]  .theme-icon {
    width: 1.25rem;
    height: 1.25rem;
    color: var(--nav-text);
    transition: color 0.2s ease;
}

.theme-toggle:hover[b-8ihhtt1vf9]  .theme-icon {
    color: var(--nav-border);
}
/* /Features/Admin/Guide.razor.rz.scp.css */
/* Guide Page Styles */
.guide-page[b-u00pr71w0j] {
    max-width: 900px;
    margin: 0 auto;
    padding: 2rem 1rem;
    transition: background-color 0.3s ease;
}

.guide-header[b-u00pr71w0j] {
    text-align: center;
    margin-bottom: 2rem;
}

.guide-header h1[b-u00pr71w0j] {
    font-size: 2rem;
    margin-bottom: 0.5rem;
    background: linear-gradient(135deg, var(--color-gold), var(--color-gold-light));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.guide-intro[b-u00pr71w0j] {
    font-size: 1.1rem;
    color: var(--text-muted);
}

/* System Tabs */
.system-tabs[b-u00pr71w0j] {
    display: flex;
    justify-content: center;
    gap: 1rem;
    margin-bottom: 2rem;
}

.tab-button[b-u00pr71w0j] {
    padding: 0.75rem 1.5rem;
    font-family: var(--font-header);
    font-size: 1rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border: 2px solid var(--border-color);
    border-radius: 6px;
    background: var(--card-bg);
    color: var(--text-color);
    cursor: pointer;
    transition: all 0.2s ease;
}

.tab-button:hover[b-u00pr71w0j] {
    border-color: var(--color-gold);
    background: var(--editor-highlight-bg);
}

.tab-button.active[b-u00pr71w0j] {
    border-color: var(--color-gold);
    background: var(--color-gold);
    color: var(--on-primary-text);
}

/* Demo Section */
.demo-section[b-u00pr71w0j] {
    margin-bottom: 3rem;
}

.card-container[b-u00pr71w0j] {
    display: flex;
    justify-content: center;
    padding: 1rem;
}

.annotated-card[b-u00pr71w0j] {
    position: relative;
    display: inline-block;
}

/* `.with-background` and `.notes-area` are not in this list any more: both
   owners (MonsterContent, StatBlockNotesArea) already set `position: relative`
   on markup they render, so those two selectors restated the owner's value and
   decided nothing. The rest of the list is real — it makes room for the
   annotation callouts over card internals nobody else positions. */
.annotated-card[b-u00pr71w0j]  .header-left,
.annotated-card[b-u00pr71w0j]  .abilities-row,
.annotated-card[b-u00pr71w0j]  .info-item,
.annotated-card[b-u00pr71w0j]  .status-grid,
.annotated-card[b-u00pr71w0j]  .threshold-box,
.annotated-card[b-u00pr71w0j]  .pip-track--hit-points,
.annotated-card[b-u00pr71w0j]  .pip-track--stress,
.annotated-card[b-u00pr71w0j]  .section-label,
.annotated-card[b-u00pr71w0j]  .card-subtype {
    position: relative;
}

/* Legend Section */
.legend-section[b-u00pr71w0j] {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 1.5rem;
}

.legend-section h2[b-u00pr71w0j] {
    text-align: center;
    margin-bottom: 1.5rem;
    font-size: 1.3rem;
    color: var(--text-color);
}

.legend-grid[b-u00pr71w0j] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
}

.legend-item[b-u00pr71w0j] {
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem;
    background: var(--card-actions-bg);
    border-radius: 6px;
    border: 1px solid var(--border-light);
}

.legend-number[b-u00pr71w0j] {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--color-gold);
    color: var(--on-primary-text);
    font-weight: 700;
    font-size: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.legend-content[b-u00pr71w0j] {
    flex: 1;
}

.legend-content strong[b-u00pr71w0j] {
    display: block;
    margin-bottom: 0.25rem;
    color: var(--text-color);
    font-size: 0.95rem;
}

.legend-content p[b-u00pr71w0j] {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1.4;
}

/* Theme-specific adjustments for D&D */
.guide-page.dnd-theme .tab-button.active[b-u00pr71w0j] {
    background: var(--color-gold);
    border-color: var(--color-gold);
    color: var(--on-primary-text);
}

.guide-page.dnd-theme .legend-number[b-u00pr71w0j] {
    background: var(--color-gold);
    color: var(--on-primary-text);
}

/* Neither the marker badge nor the tooltip title is re-themed here for D&D:
   TooltipMarker already paints the badge gold on --on-primary-text and the
   title on --nav-border, so both rules restated the owner's own values. */

/* Theme-specific adjustments for Daggerheart */
.guide-page.dh-theme .tab-button.active[b-u00pr71w0j] {
    background: var(--nav-bg);
    border-color: var(--nav-bg);
    color: var(--nav-text);
}

.guide-page.dh-theme .legend-number[b-u00pr71w0j] {
    background: var(--color-gold);
    color: var(--on-primary-text);
}

/* The badge rule was the same dead copy as the D&D one. The title colour is a
   genuine per-theme difference, so it is handed down as a custom property on
   this page's own root rather than reaching into TooltipMarker — the mechanism
   PrintSheet uses for its --eprint-* palette. A token handed down is not a
   collision; a ::deep rule setting `color` would be. */
.guide-page.dh-theme[b-u00pr71w0j] {
    --marker-title-color: var(--color-gold);
}

/* Responsive adjustments */
@media (max-width: 768px) {
    .guide-header h1[b-u00pr71w0j] {
        font-size: 1.5rem;
    }

    .guide-intro[b-u00pr71w0j] {
        font-size: 1rem;
    }

    .system-tabs[b-u00pr71w0j] {
        flex-direction: column;
        align-items: center;
    }

    .tab-button[b-u00pr71w0j] {
        width: 100%;
        max-width: 280px;
    }

    .card-container[b-u00pr71w0j] {
        overflow-x: auto;
        padding: 0.5rem;
    }

    .annotated-card[b-u00pr71w0j] {
        transform: scale(0.7);
        transform-origin: top center;
    }

    .legend-grid[b-u00pr71w0j] {
        grid-template-columns: 1fr;
    }

    .legend-section[b-u00pr71w0j] {
        padding: 1rem;
    }
}

@media (max-width: 480px) {
    .annotated-card[b-u00pr71w0j] {
        transform: scale(0.55);
    }
}
/* /Features/Admin/Statistics.razor.rz.scp.css */
.statistics-page[b-5cr60r9j4k] {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem 1rem;
}

.statistics-page h1[b-5cr60r9j4k] {
    text-align: center;
    font-size: 2rem;
    margin-bottom: 2rem;
}

.stats-section[b-5cr60r9j4k] {
    margin-bottom: 2rem;
}

.stats-section h2[b-5cr60r9j4k] {
    font-size: 1.3rem;
    margin-bottom: 1rem;
    color: var(--text-color);
}

.stats-grid[b-5cr60r9j4k] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 1rem;
    margin-bottom: 1rem;
}

.stat-card[b-5cr60r9j4k] {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1.5rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
}

.stat-value[b-5cr60r9j4k] {
    font-size: 2rem;
    font-weight: bold;
    color: var(--accent-color);
}

.stat-label[b-5cr60r9j4k] {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin-top: 0.25rem;
}

.stats-table[b-5cr60r9j4k] {
    width: 100%;
    border-collapse: collapse;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    overflow: hidden;
}

.stats-table th[b-5cr60r9j4k],
.stats-table td[b-5cr60r9j4k] {
    padding: 0.75rem 1rem;
    text-align: left;
    border-bottom: 1px solid var(--card-border);
}

.stats-table th[b-5cr60r9j4k] {
    background: rgba(var(--shadow-rgb), 0.2);
    color: var(--text-color);
    font-weight: 600;
}

.stats-table td[b-5cr60r9j4k] {
    color: var(--text-muted);
}

.stats-table tbody tr:last-child td[b-5cr60r9j4k] {
    border-bottom: none;
}
/* /Features/Admin/Tracking.razor.rz.scp.css */
.tracking-container[b-yyzij0tmhf] {
    display: grid;
    grid-template-columns: 320px 1fr;
    gap: 1.5rem;
    padding: 1rem;
    max-width: 1400px;
    margin: 0 auto;
}

.tracking-user-list[b-yyzij0tmhf] {
    border: 1px solid var(--card-border);
    border-radius: 8px;
    background: var(--card-bg);
    padding: 1rem;
    max-height: 80vh;
    overflow-y: auto;
}

.tracking-user-list h3[b-yyzij0tmhf] {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    color: var(--text-color);
}

.tracking-user-item[b-yyzij0tmhf] {
    display: flex;
    flex-direction: column;
    padding: 0.5rem 0.75rem;
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s;
}

.tracking-user-item:hover[b-yyzij0tmhf] {
    background: var(--editor-highlight-bg);
}

.tracking-user-item.selected[b-yyzij0tmhf] {
    background: var(--accent-color);
    color: var(--on-accent-text);
}

.tracking-user-name[b-yyzij0tmhf] {
    font-weight: 600;
    font-size: 0.9rem;
}

.tracking-auth-badge[b-yyzij0tmhf] {
    margin-right: 0.3rem;
}

.tracking-user-meta[b-yyzij0tmhf] {
    font-size: 0.78rem;
    color: var(--text-muted);
}

.tracking-user-item.selected .tracking-user-meta[b-yyzij0tmhf] {
    color: var(--on-accent-text);
    opacity: 0.8;
}

.tracking-pagination[b-yyzij0tmhf] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 0.75rem;
    font-size: 0.85rem;
}

.tracking-pagination button[b-yyzij0tmhf] {
    padding: 0.3rem 0.6rem;
    border-radius: 4px;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text-color);
    cursor: pointer;
}

.tracking-pagination button:disabled[b-yyzij0tmhf] {
    opacity: 0.4;
    cursor: default;
}

.tracking-journey[b-yyzij0tmhf] {
    border: 1px solid var(--card-border);
    border-radius: 8px;
    background: var(--card-bg);
    padding: 1rem;
}

.tracking-journey h3[b-yyzij0tmhf] {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    color: var(--text-color);
}

.tracking-date-filter[b-yyzij0tmhf] {
    display: flex;
    gap: 1rem;
    margin-bottom: 1rem;
    font-size: 0.85rem;
}

.tracking-date-filter input[b-yyzij0tmhf] {
    padding: 0.25rem 0.4rem;
    border: 1px solid var(--card-border);
    border-radius: 4px;
    background: var(--card-bg);
    color: var(--text-color);
}

.tracking-timeline[b-yyzij0tmhf] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.tracking-event[b-yyzij0tmhf] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: baseline;
    padding: 0.4rem 0.5rem;
    border-left: 3px solid var(--accent-color);
    font-size: 0.85rem;
}

.tracking-event-time[b-yyzij0tmhf] {
    color: var(--text-muted);
    font-size: 0.78rem;
    min-width: 130px;
}

.tracking-event-type[b-yyzij0tmhf] {
    font-weight: 600;
    color: var(--text-color);
}

.tracking-event-entity[b-yyzij0tmhf] {
    color: var(--accent-color);
}

.tracking-event-system[b-yyzij0tmhf] {
    font-size: 0.75rem;
    padding: 0.1rem 0.4rem;
    border-radius: 3px;
    background: var(--editor-highlight-bg);
    color: var(--text-muted);
}

.tracking-event-meta[b-yyzij0tmhf] {
    font-size: 0.78rem;
    color: var(--text-muted);
    font-style: italic;
}
/* /Features/Adventures/AdventureBeatEdit.razor.rz.scp.css */
/* The add/remove buttons of the read-aloud, dialogue and outcome lists carry
   long labels ("Add read-aloud text", longer in German); `.btn` keeps its label
   on one line, which ran past the card on a phone. */
.beat-list-button[b-ce302zd0q1] {
    white-space: normal;
}
/* /Features/Adventures/AdventureClueList.razor.rz.scp.css */
.adventure-clue[b-8o91azgemw] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.25rem 0.75rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--card-border);
}

.adventure-clue:last-child[b-8o91azgemw] {
    padding-bottom: 0;
    border-bottom: none;
}

.adventure-clue__text[b-8o91azgemw] {
    flex: 1 1 12rem;
    min-width: 0;
    margin: 0;
    overflow-wrap: anywhere;
}

.adventure-clue__actions[b-8o91azgemw] {
    display: flex;
    margin-left: auto;
}

.adventure-clue__found[b-8o91azgemw] {
    flex-basis: 100%;
}
/* /Features/Adventures/AdventureCountdownList.razor.rz.scp.css */
.adventure-countdown[b-hh5h74fe18] {
    display: grid;
    gap: 0.5rem;
    min-width: 0;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--card-border);
}

.adventure-countdown:last-child[b-hh5h74fe18] {
    padding-bottom: 0;
    border-bottom: none;
}
/* /Features/Adventures/AdventureIntroBanner.razor.rz.scp.css */
/* The box is InsetPanel's; this sheet places the text and the dismiss button inside it. */
.adventure-intro[b-dt5c6lsyyb] {
    margin-bottom: 1rem;
}

/* Phone width: text, then the button below it. */
.adventure-intro-body[b-dt5c6lsyyb] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
}

.adventure-intro-text[b-dt5c6lsyyb] {
    margin: 0;
}

@media (min-width: 768px) {
    .adventure-intro-body[b-dt5c6lsyyb] {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
    }
}
/* /Features/Adventures/AdventureItemHeader.razor.rz.scp.css */
/* One line at any width: the title takes the room left and wraps inside itself; badge and actions keep their size. */
.adventure-item-header[b-cozx48k1va] {
    display: flex;
    align-items: center;
    gap: 0.25rem 0.75rem;
}

.adventure-item-header__title[b-cozx48k1va] {
    flex: 1 1 0;
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
}

.adventure-item-header__actions[b-cozx48k1va] {
    display: flex;
    flex: none;
}

/* The title links to the editor; it keeps the heading's colour, the underline marks it as a link. */
.adventure-item-header__title a[b-cozx48k1va] {
    color: inherit;
}
/* /Features/Adventures/AdventureList.razor.rz.scp.css */
.template-pick[b-shyyjq93yy] {
    white-space: normal;
}
/* /Features/Adventures/AdventureOgCard.razor.rz.scp.css */
/* Sized for the fixed 1200×630 OG frame: px type, no breakpoints. A long name (2 lines) and
   hook (3 lines) are clamped, and nothing shrinks, so the worst case still fits above the footer. */
.adventure-og-card[b-b0e47bniqo] {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 52px 72px 44px;
    background: var(--card-bg);
    border-top: 14px solid var(--accent-color);
    color: var(--text-color);
    font-family: var(--font-body);
    overflow: hidden;
}

.adventure-og-card__head[b-b0e47bniqo] {
    display: flex;
    align-items: center;
    gap: 18px;
}

.adventure-og-card__kicker[b-b0e47bniqo] {
    font-family: var(--font-header);
    font-size: 26px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.adventure-og-card__system[b-b0e47bniqo] {
    padding: 2px 16px;
    border: 2px solid var(--accent-color);
    border-radius: var(--radius-pill);
    font-size: 22px;
    font-weight: 700;
}

.adventure-og-card__name[b-b0e47bniqo] {
    margin: 0;
    font-family: var(--font-header);
    flex-shrink: 0;
    font-size: 64px;
    line-height: 1.15;
    color: var(--text-color);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

.adventure-og-card__facts[b-b0e47bniqo] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 32px;
    margin: 0;
    font-size: 28px;
    font-weight: 600;
}

.adventure-og-card__hook[b-b0e47bniqo] {
    margin: 0;
    font-size: 30px;
    line-height: 1.35;
    flex-shrink: 0;
    font-style: italic;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}

.adventure-og-card__foot[b-b0e47bniqo] {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* One row of chips; whatever does not fit is cut rather than wrapped onto the credit line. */
.adventure-og-card__tags[b-b0e47bniqo] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    max-height: 46px;
    margin: 0;
    padding: 0;
    list-style: none;
    overflow: hidden;
}

.adventure-og-card__tag[b-b0e47bniqo] {
    padding: 4px 16px;
    border: 2px solid var(--card-border);
    border-radius: var(--radius-pill);
    font-size: 22px;
    color: var(--text-color);
}

.adventure-og-card__tag--tone[b-b0e47bniqo] {
    background: var(--card-border);
}

.adventure-og-card__credit[b-b0e47bniqo] {
    display: flex;
    justify-content: space-between;
    gap: 24px;
    margin: 0;
    font-size: 24px;
    color: var(--text-muted);
}

.adventure-og-card__brand[b-b0e47bniqo] {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-header);
    letter-spacing: 0.06em;
}
/* /Features/Adventures/AdventurePrintPreview.razor.rz.scp.css */
/* The reference material (the linked encounters and environments in full) follows the session
   sheet and opens on its own page. */
.adv-print-refs[b-uisqhognie] {
    break-before: page;
    page-break-before: always;
}

/* Within it the sheets pack onto shared pages to save paper, but a page break never splits a
   single encounter or environment — each is kept whole (only one taller than a page can still
   be forced to break, which no rule can help). */
.adv-print-ref[b-uisqhognie] {
    break-inside: avoid;
    page-break-inside: avoid;
}

/* The per-page margin of this handout is an injected `@page` rule (adventure-print.js), not CSS:
   the shared bundle's global `@page { margin: 0 }` serves the foe-card prints, and only `@page`
   gives a forced-break page a reliable top margin across browsers. These rules only decide where
   the pages break; the margin lands on every one of them, the overflow pages included. */
@media print {
    /* The whole Story Beats section opens on a fresh page, so the first beat starts its own page
       like the rest — carrying its heading with it rather than orphaning it on the intro page. */
    .adv-print-beats[b-uisqhognie] {
        break-before: page;
        page-break-before: always;
    }

    /* Every later beat opens its own page too, so a beat is never split across the fold and the
       page it vacates ends in natural whitespace. The preview keeps its continuous flow. */
    .adv-print-beat + .adv-print-beat[b-uisqhognie] {
        break-before: page;
        page-break-before: always;
    }
}

/* The reader's "page breaks: off" choice: every forced break above is dropped and the sheets run on in sequence. */
.adv-print-continuous .adv-print-refs[b-uisqhognie],
.adv-print-continuous .adv-print-beats[b-uisqhognie],
.adv-print-continuous .adv-print-beat + .adv-print-beat[b-uisqhognie] {
    break-before: auto;
    page-break-before: auto;
}

.adv-print-place[b-uisqhognie] {
    font-style: italic;
    color: var(--eprint-label, var(--text-muted));
}

/* Cheat sheet: one compact line per beat. */
.adv-print-beat-lines[b-uisqhognie] {
    margin: 0;
    padding-left: 1.25rem;
}

.adv-print-beat-lines > li[b-uisqhognie] {
    margin-bottom: 0.4rem;
}

.adv-print-beat-lines .adv-print-place[b-uisqhognie] {
    margin-left: 0.5rem;
}

.adv-print-text[b-uisqhognie] {
    margin: 0;
    white-space: pre-line;
    overflow-wrap: anywhere;
}
/* /Features/Adventures/AdventureStartChecklist.razor.rz.scp.css */
.start-checklist__step[b-hvn1t8bn3i] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-color);
}

.start-checklist__step--done[b-hvn1t8bn3i] {
    color: var(--text-muted);
    text-decoration: line-through;
}

.start-checklist__mark[b-hvn1t8bn3i] {
    display: inline-flex;
    justify-content: center;
    width: 1.25rem;
    flex-shrink: 0;
}

/* The link is the tap target, so it carries the 44px height, not the row. */
.start-checklist__link[b-hvn1t8bn3i] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
}
/* /Features/Adventures/BeatEncounterSummary.razor.rz.scp.css */
.beat-encounter[b-ixtzrf9eee] {
    margin: 0.25rem 0;
}
/* /Features/Adventures/BeatEnvironmentFeatures.razor.rz.scp.css */
/* The type tag reads its ink from --env-feature-muted; on paper that is the sheet's label colour. */
.beat-env[b-47fwujqapp] {
    --env-feature-muted: var(--eprint-label, var(--text-muted));

    margin: 0.25rem 0 0.5rem;
}

.beat-env__text[b-47fwujqapp] {
    display: block;
    font-size: 0.9rem;
}
/* /Features/Adventures/BeatList.razor.rz.scp.css */
.beat-list[b-4s53w435pj] {
    color: var(--eprint-value, var(--text-color));
    line-height: 1.6;
    overflow-wrap: anywhere;
}

.beat-list ul[b-4s53w435pj] {
    margin: 0;
    padding-left: 1.25rem;
}

.beat-list--compact[b-4s53w435pj] {
    line-height: 1.35;
}

.beat-list--compact li[b-4s53w435pj] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* /Features/Adventures/BeatNarrative.razor.rz.scp.css */
.beat-text[b-4ldix2l0p0] {
    margin: 0;
    color: var(--eprint-value, var(--text-color));
    line-height: 1.6;
    white-space: pre-line;
    overflow-wrap: anywhere;
}
/* /Features/Adventures/CountdownPrint.razor.rz.scp.css */
.countdown-print[b-rw808kz6hv] {
    margin-bottom: 0.5rem;
    color: var(--eprint-value, var(--text-color));
    overflow-wrap: anywhere;
}

.countdown-print p[b-rw808kz6hv] {
    margin: 0 0 0.25rem;
}
/* /Features/Adventures/DialogueList.razor.rz.scp.css */
.dialogue-line[b-vsx8j4xwb2] {
    padding-left: 0.75rem;
    border-left: 3px solid var(--card-border);
    overflow-wrap: anywhere;
}

.dialogue-line__cue[b-vsx8j4xwb2] {
    display: block;
    color: var(--text-muted);
    font-style: italic;
}
/* /Features/Adventures/ReadAloudBlockList.razor.rz.scp.css */
.read-aloud-block__cue[b-5qoyqckcyz] {
    display: block;
    color: var(--eprint-label, var(--text-muted));
    font-style: italic;
    overflow-wrap: anywhere;
}
/* /Features/Adventures/StoryBeatList.razor.rz.scp.css */
/* The outline: numbered in the title, so the list drops its own markers. */
.story-beats[b-ma1vbmyy81] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 1rem;
}

.story-beat[b-ma1vbmyy81] {
    display: grid;
    gap: 0.5rem;
    min-width: 0;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--card-border);
}

.story-beat:last-child[b-ma1vbmyy81] {
    padding-bottom: 0;
    border-bottom: none;
}

/* Carries .story-beat: HubCard's `.hub-card ::deep p` (0,2,1) would otherwise repaint it in --text-color. */
.story-beat .story-beat__meta[b-ma1vbmyy81] {
    color: var(--text-muted);
    font-style: italic;
}
/* /Features/Adversaries/AdversaryActiveFilterChips.razor.rz.scp.css */
/* /Features/Adversaries/AdversaryContent.razor.rz.scp.css */
/* Daggerheart Adversary Card - Purple/Gold/Teal Theme.

   The card frame itself (base box, print-ornate / print-plain, the accent-line
   pseudo-elements and .fixed-width) moved to
   Common/Components/UI/FoeCardFrame.razor.css with the root div — ladder rung 2,
   the same five blocks opened MonsterContent.razor.css. The rules below still
   live here because their subject is an element AdversaryContent renders; only
   the ancestor compound was renamed.

   The card *chrome* followed on 2026-08-18: the title row, the subtype line, the
   section divider, the tracker rows and the condition grid are <CardTitleRow>,
   <CardSubtype>, <CardSectionDivider>, <CardTrackingRow> and
   <CardConditionGrid>, with the per-system values declared once as --foe-card-*
   properties on FoeCardFrame. `.section-label` stays here: this card is its only
   renderer, so it is rung 1 rather than a shared shape. */

.threshold-box[b-9xo2czpkgw] {
    border: 2px solid var(--dh-accent-gold);
    padding: 4px 10px;
    text-align: center;
    background: rgba(var(--dh-accent-gold-rgb), 0.15);
    border-radius: 4px;
}

.foe-card-frame--daggerheart.print-ornate .threshold-box[b-9xo2czpkgw] {
    border-color: var(--dh-accent-gold);
    background: rgba(var(--dh-accent-gold-rgb), 0.2);
}

.foe-card-frame--daggerheart.print-plain .threshold-box[b-9xo2czpkgw] {
    border-color: var(--dh-text-primary);
    background: transparent;
}

.threshold-label[b-9xo2czpkgw] {
    font-size: 0.75em;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--dh-bg-dark);
    font-weight: 600;
}

.threshold-values[b-9xo2czpkgw] {
    display: flex;
    gap: 12px;
    font-size: 1.1em;
    font-weight: 600;
    color: var(--dh-text-header);
}

.combat-stats[b-9xo2czpkgw] {
    position: relative;
}

.info-line[b-9xo2czpkgw] {
    line-height: 1.3;
    margin-bottom: 2px;
}

.info-line strong[b-9xo2czpkgw] {
    font-weight: 700;
    min-width: 45px;
    display: inline-block;
    color: var(--dh-bg-dark);
}

.foe-card-frame--daggerheart.print-plain .info-line strong[b-9xo2czpkgw] {
    color: var(--dh-text-primary);
}

.foe-card-frame--daggerheart.print-plain .info-line.description[b-9xo2czpkgw],
.foe-card-frame--daggerheart.print-plain .attack-description[b-9xo2czpkgw] {
    color: var(--print-text-strong);
}

/* One selector where there were two: the `strong` half named an element
   <CardEmphasis> owns now, and a rule of this sheet's could not reach it any
   more. The row hands the same ink to it as a custom property instead. */
.foe-card-frame--daggerheart.print-plain .feature-line.fear-feature[b-9xo2czpkgw] {
    color: var(--dh-text-primary);
    --foe-card-emphasis-color: var(--dh-text-primary);
}

.info-line.description[b-9xo2czpkgw] {
    font-style: italic;
    color: var(--dh-card-text);
    margin-bottom: 4px;
}

.fear-features[b-9xo2czpkgw] {
    position: relative;
}

.section-label[b-9xo2czpkgw] {
    font-weight: 700;
    margin: 3px 0 2px 0;
    text-transform: uppercase;
    font-family: var(--foe-card-heading-font);
    color: var(--dh-bg-dark);
    font-size: 0.9em;
    letter-spacing: 0.5px;
}

.foe-card-frame--daggerheart.print-plain .section-label[b-9xo2czpkgw] {
    color: var(--dh-text-primary);
}

.attack-block[b-9xo2czpkgw] {
    margin-bottom: 4px;
}

.attack-line[b-9xo2czpkgw] {
    margin-bottom: 2px;
}

.attack-line strong[b-9xo2czpkgw] {
    color: var(--dh-text-header);
}

.attack-description[b-9xo2czpkgw] {
    font-style: italic;
    color: var(--dh-card-text);
    font-size: 0.95em;
}

.feature-line[b-9xo2czpkgw] {
    line-height: 1.3;
    margin-bottom: 2px;
}

/* `.feature-line strong` is gone. Weight 700 plus an ink was the rule
   MonsterContent also wrote for `.ability-stat strong` and `.info-item strong`,
   which is a decision written twice inside a registered sheet pair rather than a
   coincidence; the run is <CardEmphasis> now (ladder rung 2). The plain
   Daggerheart feature name needs nothing here — FoeCardFrame's
   --foe-card-emphasis-color is already --dh-text-header for this system, in both
   print modes, exactly as this rule was. */

.feature-line.fear-feature[b-9xo2czpkgw] {
    color: var(--dh-card-accent-text);
    --foe-card-emphasis-color: var(--dh-card-accent-text);
}

/* Tracking Section */
.tracking-section[b-9xo2czpkgw] {
    margin: 8px 0;
}

/* .notes-area / .note-line moved to Common/Components/UI/StatBlockNotesArea
   (ladder rung 2); see the matching note in MonsterContent.razor.css. The rule
   colour stays here as the custom property the component reads. */

/* Mobile responsive styles. The title row's reflow, the tracker group's wrap and
   the condition grid's column count left with their components — FoeCardFrame
   declares all three as custom properties under the same `:not(.fixed-width)`
   condition, because that class is its own. */
@media screen and (max-width: 768px) {
    .foe-card-frame--daggerheart:not(.fixed-width) .threshold-box[b-9xo2czpkgw] {
        width: 100%;
    }
}

/* The 1.3 leading is <TacticalDirective Compact>'s now. This card's type scale
   differs from the D&D one — the directive takes the card's own 12pt rather
   than a pinned rem value — so the size is handed down as a custom property on
   the section this file renders. `1em` is the card's size, which is what the
   old `font-size: inherit` bought; a token handed down is not a collision.

   `margin-bottom` stays reachable: the component sets no margin, and the gap
   under the line is this card's spacing. */
.tactical-signals-section[b-9xo2czpkgw] {
    --tactical-directive-size: 1em;
}

.tactical-signals-section[b-9xo2czpkgw]  .tactical-directive {
    margin-bottom: 2px;
}
/* /Features/Adversaries/AdversaryEdit.razor.rz.scp.css */
/* Adversary-Specific Editor Styles (Daggerheart) */

/* ── Shared foe-editor base (page template) ──
   The .foe-editor bare-selector padding rule that used to live here moved to
   ContentEditorShell.razor.css (task 1 of the editor-chrome-rung2 plan): once the
   page's outer div is rendered by that shared component, a scoped rule in this
   file can no longer reach it (it carries the shell's scope attribute, not
   this file's). Everything below still targets elements this file renders
   directly as ContentEditorShell's ChildContent, so it is unaffected. */
/* `.foe-editor h2` left this file 2026-08-17: MonsterEdit stated it
   identically, and the heading is slotted content, so it is ContentEditorShell's
   `::deep h2` now (rung 3). */

/* .foe-editor .form-section (+ ::before, h3, h3.form-section-toggle, hover,
   .section-toggle-icon, h4) removed (Task 3, editor-chrome rung-2 plan): dead
   since AdversaryEdit stopped hand-rolling any .form-section div — the last
   one (author notes) now renders through CollapsibleFormSection/FormSection,
   which own this chrome. The h3/.section-toggle-icon this rule targeted is
   now authored by CollapsibleFormSection, so the page's scope attribute is
   never on it. */

/* .foe-editor .validation-message / .validation-summary-errors / .invalid removed:
   all three elements come from framework components (<ValidationMessage>,
   <ValidationSummary>, EditForm field classes), so this page's scope id is never
   on them and the rules matched nothing. base.css owns .validation-message and
   .invalid; the summary box moved to ContentEditorShell.razor.css as a ::deep rule. */

/* ========================================
   Scaling Dialog
   ======================================== */
.scaling-dialog-overlay[b-9xq0at9u1u] {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(var(--shadow-rgb), 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.scaling-dialog[b-9xq0at9u1u] {
    background-color: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 8px;
    padding: 1.5rem;
    max-width: 500px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
}

.scaling-dialog h3[b-9xq0at9u1u] {
    margin-top: 0;
}

.scaling-preview[b-9xq0at9u1u] {
    margin: 1rem 0;
}

/* Moved back from AdversaryCombatProfileSection.razor.css: the scaling table is
   rendered by this page's scaling dialog, not by the section component, so the
   rules could not match there. */
.scaling-comparison[b-9xq0at9u1u] {
    width: 100%;
    border-collapse: collapse;
}

.scaling-comparison th[b-9xq0at9u1u],
.scaling-comparison td[b-9xq0at9u1u] {
    padding: 0.5rem;
    text-align: left;
    border-bottom: 1px solid var(--card-border);
}

.scaling-comparison th[b-9xq0at9u1u] {
    font-weight: bold;
}

@media (max-width: 480px) {
    .scaling-comparison[b-9xq0at9u1u] {
        font-size: 0.85rem;
    }

    .scaling-comparison th[b-9xq0at9u1u],
    .scaling-comparison td[b-9xq0at9u1u] {
        padding: 0.4rem;
    }
}

.scaling-info-banner[b-9xq0at9u1u] {
    background-color: color-mix(in srgb, var(--color-gold) 20%, transparent);
    border: 1px solid var(--color-gold);
    border-radius: 4px;
    padding: 0.75rem;
    margin: 1rem 0;
    color: var(--text-color);
}

.scaling-warning-banner[b-9xq0at9u1u] {
    background-color: color-mix(in srgb, var(--color-danger) 20%, transparent);
    border: 1px solid var(--color-danger);
    border-radius: 4px;
    padding: 0.75rem;
    margin: 1rem 0;
    color: var(--text-color);
}

.scaling-warning-banner ul[b-9xq0at9u1u] {
    margin: 0.5rem 0;
    padding-left: 1.5rem;
}

.warning-options[b-9xq0at9u1u] {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.dialog-actions[b-9xq0at9u1u] {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1rem;
}

/* The encounter-check status line. It was called `.loading-spinner` until
   2026-08-18, which is LoadingState's root class and a ring animation — this is
   three declarations of centred muted text with no spinner in it. The old
   comment argued the collision was harmless, and it was; the name still made
   every reader check. */
.encounter-check-status[b-9xq0at9u1u] {
    text-align: center;
    padding: 1rem;
    color: var(--text-muted);
}
/* /Features/Adversaries/AdversaryStatBlock.razor.rz.scp.css */
/* ========================================
   Daggerheart Classic Stat Block
   ======================================== */
.foe-stat-block-frame .dh-description[b-3dx3lhk3ah] {
    font-style: italic;
    margin: 0 0 0.4rem;
}

.foe-stat-block-frame .dh-stats-row[b-3dx3lhk3ah] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 1.5rem;
    margin-bottom: 0.3rem;
    break-inside: avoid;
}

/* /Features/Adversaries/AdversaryTypeOrnament.razor.rz.scp.css */
/* The stat block's chrome colour, handed down by FoeStatBlockFrame: antique
   gold on screen (--sb-rule-gold, 3.79:1 on --dh-bg-light). Print never shows
   the glyph (`no-print`). */
.adversary-type-ornament[b-wtgj90fqqo] {
    color: var(--fsb-chrome-rule);
    vertical-align: -0.125em;
    margin-inline-end: 0.3em;
}
/* /Features/Adversaries/Sections/AdversaryActionsSection.razor.rz.scp.css */

/* moved from AdversaryEdit.razor.css — this section renders these */
.scaling-info-section-banner[b-foqp4kyjqj] {
    background-color: color-mix(in srgb, var(--color-gold) 15%, transparent);
    border-left: 4px solid var(--color-gold);
    padding: 0.75rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-color);
}

.info-icon[b-foqp4kyjqj] {
    font-size: 1.2rem;
}
/* /Features/Adversaries/Sections/AdversaryCombatProfileSection.razor.rz.scp.css */
/* Adversary-specific combat profile styles (05b: system-specific, owned by this section) */

/* .scaling-comparison moved back to AdversaryEdit.razor.css — the scaling
   dialog table is that page's markup, not this section's. */

/* moved from AdversaryEdit.razor.css — this section renders it */
.btn-scale-adversary[b-vmbsyypeyt] {
    margin-left: 0.5rem;
}
/* /Features/Adversaries/Sections/AdversaryExperiencesSection.razor.rz.scp.css */
/* Experience Suggestions (sole consumer) */
.foe-editor .experience-suggestions[b-e2a3ce543h] {
    margin-top: 0.5rem;
    color: var(--text-muted);
}
/* /Features/Auth/AuthStatus.razor.rz.scp.css */
.auth-status[b-mwq0sqrm2q] {
    display: flex;
    align-items: center;
}

.user-info[b-mwq0sqrm2q] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 1;
    min-width: 0;
}

.user-avatar[b-mwq0sqrm2q] {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
}

.user-name[b-mwq0sqrm2q] {
    font-size: 0.9rem;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The badge itself is the shared TierBadge component now — it owns its
   geometry and the tier colour table (was duplicated in CreatorBadge.razor.css). */

.patreon-login[b-mwq0sqrm2q] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.patreon-icon[b-mwq0sqrm2q] {
    font-weight: bold;
    font-size: 1rem;
}

/* The Patreon mark is the shared <PatreonLogo>. */

@media (max-width: 768px) {
    .user-name[b-mwq0sqrm2q] {
        display: none;
    }

    .user-info[b-mwq0sqrm2q] {
        gap: 0.375rem;
    }
}

@media (max-width: 480px) {
    /* ::deep: TierBadge authors the element, so it carries that component's
       scope id; hiding it on narrow layouts is this header's concern (rung 3). */
    [b-mwq0sqrm2q] .tier-badge {
        display: none;
    }

    .login-text[b-mwq0sqrm2q] {
        display: none;
    }

    .patreon-login[b-mwq0sqrm2q] {
        padding: 0.375rem;
        gap: 0.25rem;
    }
}

/* ── Reclaimed from base.css (ladder rung 1) ── */
@media (max-width: 640px) {
    .user-name[b-mwq0sqrm2q] {
        display: none;
    }
}
/* /Features/Auth/PatreonGate.razor.rz.scp.css */
.patreon-gate[b-9ak36lu6y3] {
    position: relative;
    display: block;
}

.patreon-gate.restricted[b-9ak36lu6y3] {
    overflow: hidden;
    cursor: pointer;
}

/* Dim restricted content */
.patreon-gate.restricted .patreon-gate-content[b-9ak36lu6y3] {
    opacity: 0.45;
    pointer-events: none;
    user-select: none;
}

/* Overlay - hidden by default */
.patreon-gate-overlay[b-9ak36lu6y3] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    background: rgba(var(--shadow-rgb), 0.85);
    color: var(--color-white);
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    border-radius: 6px;
    opacity: 0;
    transition: opacity 0.2s ease;
    z-index: 10;
    white-space: nowrap;
    padding: 0 0.75rem;
}

.patreon-gate-overlay.align-left[b-9ak36lu6y3] {
    justify-content: flex-start;
}

.patreon-gate-overlay img[b-9ak36lu6y3] {
    flex-shrink: 0;
}

.patreon-gate-overlay.align-left span[b-9ak36lu6y3] {
    margin-left: .5em;
}

/* Desktop: show on hover */
.patreon-gate.restricted:hover .patreon-gate-overlay[b-9ak36lu6y3] {
    opacity: 1;
}

/* Mobile: show on tap via toggle class */
.patreon-gate.overlay-visible .patreon-gate-overlay[b-9ak36lu6y3] {
    opacity: 1;
}

.patreon-gate-overlay:hover[b-9ak36lu6y3],
.patreon-gate-overlay:focus[b-9ak36lu6y3] {
    color: var(--color-patreon);
}
/* /Features/Auth/SubscribeCta.razor.rz.scp.css */
.subscribe-cta[b-752qazhup5] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    border-radius: 0.5rem;
    background: var(--color-patreon);
    /* Fixed Patreon brand button text color — not a theme surface, same exemption class as PatreonGate overlay */
    color: var(--color-white);
    font-weight: 600;
    text-decoration: none;
    min-height: 44px;
}

.subscribe-cta__tier[b-752qazhup5] { font-weight: 700; }
/* /Features/Auth/TierGateBadge.razor.rz.scp.css */
.tier-gate-badge[b-tkeqrvbchf] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: 0.25rem;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

/* --tier-*-bg were never defined anywhere, so these always rendered their
   fallbacks; the literals below are exactly what shipped. This gate badge uses
   a different palette from TierBadge (--tier-badge-*) on purpose — inlining the
   values keeps that explicit instead of pointing at tokens that do not exist. */
.tier-gate-badge.tier-insider[b-tkeqrvbchf] { background: var(--tier-gate-insider); color: var(--color-white); }
.tier-gate-badge.tier-curator[b-tkeqrvbchf] { background: var(--tier-gate-curator); color: var(--color-white); }
.tier-gate-badge.tier-supporter[b-tkeqrvbchf] { background: var(--tier-gate-supporter); color: var(--color-white); }

.tier-gate-badge svg[b-tkeqrvbchf] { width: 0.875rem; height: 0.875rem; flex-shrink: 0; }
/* /Features/Collections/CollectionDetail.razor.rz.scp.css */
/* Collection badges (05b) */
.visibility-badge[b-itaa0am1ir] {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    background: var(--accent-color);
    color: var(--on-accent-text);
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
}

.visibility-badge--private[b-itaa0am1ir] {
    background: var(--text-muted);
    color: var(--card-bg);
}

.entry-kind-badge[b-itaa0am1ir] {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
    border: 1px solid var(--card-border);
    color: var(--text-muted);
    background: var(--editor-highlight-bg);
}

.entry-kind-badge--encounter[b-itaa0am1ir] {
    background: var(--accent-color);
    color: var(--on-accent-text);
    border-color: var(--accent-color);
}

/* ── Collection detail: edit form ── */
/* The form card is the shared <FormCard> (rung 2): this page and the other
   collections page stated the same eight declarations under two names. */

/* The button row is the shared <ButtonRow> component now. */

/* ── Collection detail: header ── */
.collection-detail[b-itaa0am1ir] {
    padding: 1.5rem 2rem;
}

.collection-header[b-itaa0am1ir] {
    margin-bottom: 1.5rem;
}

.collection-title-row[b-itaa0am1ir] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.5rem;
}

.collection-title-row h1[b-itaa0am1ir] {
    margin: 0;
    font-family: var(--font-header);
}

.collection-badges[b-itaa0am1ir] {
    display: flex;
    gap: 0.4rem;
}

.collection-actions[b-itaa0am1ir] {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.collection-entries-section h2[b-itaa0am1ir] {
    font-family: var(--font-header);
    color: var(--text-color);
    margin: 0 0 1rem;
    font-size: 1.15rem;
    border-bottom: 1px solid var(--card-border);
    padding-bottom: 0.5rem;
}

/* ── Reclaimed from base.css (ladder rung 1) ── */
.action-icon-btn[b-itaa0am1ir] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.3rem 0.45rem;
}

@media (max-width: 768px) {
    .card-grid--list .card-actions .action-icon-btn[b-itaa0am1ir] {
        min-width: 44px;
        min-height: 44px;
    }
}
/* /Features/Collections/CollectionList.razor.rz.scp.css */
/* ── Collections: Page Layout ── */
.collections-page[b-bacn48bz88] {
    padding: 2rem;
}

.collections-header[b-bacn48bz88] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1.5rem;
}

.collections-header h1[b-bacn48bz88] {
    margin: 0;
    font-family: var(--font-header);
}

/* ── Collection create form ── */
/* The form card is the shared <FormCard> (rung 2): this page and the other
   collections page stated the same eight declarations under two names. */

/* The button row is the shared <ButtonRow> component now. */

.collection-form-error[b-bacn48bz88] {
    color: var(--danger-ink);
    font-size: 0.875rem;
    margin: 0;
}
/* /Features/ContentBundles/ContentBundleDisplay.razor.rz.scp.css */
/* ContentBundle detail view (phase 07) — these classes were previously
   unstyled: no matching rules existed anywhere in app.css/base.css. */

.foe-detail[b-2uylxpzexh] {
    padding: 1rem;
}

.detail-header[b-2uylxpzexh] {
    margin-bottom: 1.5rem;
}

.detail-header-row[b-2uylxpzexh] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.detail-header-row h1[b-2uylxpzexh] {
    font-family: var(--font-header), serif;
    margin: 0;
}

.detail-meta[b-2uylxpzexh] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 0.5rem;
    color: var(--text-muted);
}

.detail-meta .scaling-notes[b-2uylxpzexh] {
    font-style: italic;
}

.detail-section[b-2uylxpzexh] {
    margin: 1.5rem 0;
}

.detail-section h2[b-2uylxpzexh] {
    font-family: var(--font-header), serif;
    color: var(--text-color);
    font-size: 1.15rem;
    margin: 0 0 0.5rem;
}

.narrative-hooks[b-2uylxpzexh] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.narrative-hook[b-2uylxpzexh] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 0.75rem 1rem;
}

.narrative-hook h3[b-2uylxpzexh] {
    font-size: 0.95rem;
    color: var(--text-color);
    margin: 0 0 0.35rem;
}

.narrative-hook p[b-2uylxpzexh] {
    color: var(--text-muted);
    margin: 0;
}

.encounter-list[b-2uylxpzexh] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.encounter-item[b-2uylxpzexh] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 0.5rem 1rem;
}

.encounter-number[b-2uylxpzexh] {
    color: var(--text-muted);
    font-weight: 600;
}

.encounter-link[b-2uylxpzexh] {
    color: var(--accent-color);
}

.detail-actions[b-2uylxpzexh] {
    margin-top: 2rem;
}
/* /Features/Conversion/AttackConfigEditor.razor.rz.scp.css */
/* No `.wizard-custom-damage` rule: the div is FormField's. Both fields ask for
   `form-group--spaced` now. */
/* /Features/Conversion/ConversionSuggestionChips.razor.rz.scp.css */
.feature-suggestions[b-d3xmzydomh] {
    margin-bottom: 1.25rem;
    padding: 0.75rem 1rem;
    border: 1px dashed var(--card-border);
    border-radius: 6px;
    background: var(--editor-highlight-bg);
}

.feature-suggestions-label[b-d3xmzydomh] {
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin: 0 0 0.5rem;
}

.feature-suggestion-chip[b-d3xmzydomh] {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--card-border);
}

.feature-suggestion-chip:last-child[b-d3xmzydomh] {
    border-bottom: none;
    padding-bottom: 0;
}

.feature-suggestion-info[b-d3xmzydomh] {
    flex: 1;
    min-width: 0;
}

.feature-suggestion-info strong[b-d3xmzydomh] {
    color: var(--text-color);
    font-size: 0.95rem;
}

.feature-suggestion-reason[b-d3xmzydomh] {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-left: 0.25rem;
}

.feature-suggestion-desc[b-d3xmzydomh] {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin: 0.2rem 0 0;
    line-height: 1.4;
}

.feature-suggestion-actions[b-d3xmzydomh] {
    display: flex;
    gap: 0.4rem;
    flex-shrink: 0;
    align-items: flex-start;
    padding-top: 0.1rem;
}
/* /Features/Conversion/ConversionWizardHeader.razor.rz.scp.css */
.wizard-header[b-gf24u08t3x] {
    margin-bottom: 1rem;
}

.wizard-header h2[b-gf24u08t3x] {
    margin: 0;
    color: var(--text-color);
}

.wizard-subtitle[b-gf24u08t3x] {
    color: var(--text-muted);
    margin: 0.25rem 0 0;
    font-size: 0.95rem;
}

.wizard-attribution[b-gf24u08t3x] {
    margin: 0.4rem 0 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.wizard-attribution a[b-gf24u08t3x] {
    color: var(--accent-color);
    text-decoration: underline;
    text-underline-offset: 2px;
}
/* /Features/Conversion/ExperienceListEditor.razor.rz.scp.css */
.experience-list[b-3geus2t6xg] {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.experience-entry[b-3geus2t6xg] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--text-color);
    font-size: 0.9rem;
}
/* /Features/Conversion/FullConversionWizard.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   FullConversionWizard.razor.css — scoped styles

   The wizard chrome shared with QuickConversionView (header, step card, hint,
   dice options, experience list, preview table/summary, actions, error,
   suggestion chips) lives in the components both views render. Only the
   step-progress nav and the role guidance table are authored here.
   ═══════════════════════════════════════════ */

.conversion-wizard[b-gp2ou0z80n] {
    padding: 1rem;
}

/* Step progress nav */
/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.wizard-progress[b-gp2ou0z80n] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 1.5rem;
    padding: 0.5rem;
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
}

.wizard-progress-step[b-gp2ou0z80n] {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1;
    min-width: 60px;
    padding: 0.3rem 0.25rem;
    background: transparent;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-muted);
    font-size: 0.7rem;
    transition: background 0.15s;
}

.wizard-progress-step .step-num[b-gp2ou0z80n] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--card-border);
    color: var(--text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    margin-bottom: 0.2rem;
    transition: background 0.15s, color 0.15s;
}

.wizard-progress-step.done .step-num[b-gp2ou0z80n] {
    background: var(--color-copper);
    color: var(--on-primary-text);
}

.wizard-progress-step.active .step-num[b-gp2ou0z80n] {
    background: var(--accent-color);
    color: var(--on-accent-text);
}

.wizard-progress-step.active[b-gp2ou0z80n] {
    color: var(--text-color);
}

.wizard-progress-step:hover .step-num[b-gp2ou0z80n] {
    background: var(--accent-color);
    color: var(--on-accent-text);
}

.wizard-progress-step .step-name[b-gp2ou0z80n] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 70px;
}

@media (max-width: 600px) {
    .wizard-progress-step .step-name[b-gp2ou0z80n] {
        display: none;
    }
}

/* Type/tier guidance table (Preview step InfoComponent) */
.info-role-table[b-gp2ou0z80n] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

.info-role-table th[b-gp2ou0z80n],
.info-role-table td[b-gp2ou0z80n] {
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--card-border);
    text-align: left;
}

.info-role-table th[b-gp2ou0z80n] {
    background: var(--editor-highlight-bg);
    font-weight: 600;
}
/* /Features/Conversion/QuickConversionView.razor.rz.scp.css */
/* ═══════════════════════════════════════════
   QuickConversionView.razor.css — scoped styles

   The wizard chrome this view used to re-declare (header, step card, hint,
   dice options, experience list, preview table/summary, actions, error) now
   lives in the shared components both conversion views render. Only the
   quick-mode zone layout is authored here.
   ═══════════════════════════════════════════ */

.quick-zone[b-y5u2vik0vn] {
    margin-bottom: 1.5rem;
}

.quick-zone-manual h3[b-y5u2vik0vn] {
    color: var(--text-color);
    border-bottom: 1px solid var(--card-border);
    padding-bottom: 0.5rem;
    margin-bottom: 1rem;
}

.quick-zone-auto[b-y5u2vik0vn] {
    border: 1px solid var(--card-border);
    border-radius: 6px;
    padding: 0;
}

.quick-zone-auto summary[b-y5u2vik0vn] {
    padding: 0.75rem 1rem;
    cursor: pointer;
    font-weight: 600;
    color: var(--text-color);
    list-style: none;
}

.quick-zone-auto summary[b-y5u2vik0vn]::before {
    content: "▶ ";
    font-size: 0.75em;
}

.quick-zone-auto[open] summary[b-y5u2vik0vn]::before {
    content: "▼ ";
}

.quick-auto-section[b-y5u2vik0vn] {
    padding: 1rem;
    border-top: 1px solid var(--card-border);
}

.quick-auto-section-header[b-y5u2vik0vn] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.75rem;
}

.quick-auto-section-header h4[b-y5u2vik0vn] {
    margin: 0;
    color: var(--text-color);
}

/* .tag-grid-readonly moved to TagGrid.razor.css — that component authors the div. */
/* /Features/Encounters/BattlemapReference.razor.rz.scp.css */
.battlemap-ref[b-gytv55k2tc] {
    border: 1px dashed var(--card-border);
    border-radius: 6px;
    padding: 0.75rem;
    display: grid;
    gap: 0.5rem;
}

.battlemap-body[b-gytv55k2tc] {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
    justify-content: space-between;
}

.battlemap-credit[b-gytv55k2tc] {
    display: grid;
    gap: 0.15rem;
    min-width: 0;
    overflow-wrap: anywhere;
}

.battlemap-creator[b-gytv55k2tc] {
    font-weight: 600;
}

.battlemap-host[b-gytv55k2tc],
.battlemap-url[b-gytv55k2tc] {
    color: var(--text-muted);
    font-size: 0.9rem;
}

.battlemap-figure[b-gytv55k2tc] {
    margin: 0;
}

.battlemap-figure img[b-gytv55k2tc] {
    display: block;
    max-width: 100%;
    height: auto;
}

.battlemap-figure figcaption[b-gytv55k2tc] {
    margin-top: 0.25rem;
    color: var(--text-muted);
    font-size: 0.85rem;
}

.battlemap-ref-print[b-gytv55k2tc] {
    border-color: var(--print-rule);
    break-inside: avoid;
}

.battlemap-ref-print .battlemap-host[b-gytv55k2tc],
.battlemap-ref-print .battlemap-url[b-gytv55k2tc],
.battlemap-ref-print .battlemap-figure figcaption[b-gytv55k2tc] {
    color: var(--print-text-muted);
}
/* /Features/Encounters/Builder/BuilderDetails.razor.rz.scp.css */
/* Headed groups, one under the other, each with a rule under it. */
.details-group[b-arlmqrc9by] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--card-border);
}

.details-group:last-child[b-arlmqrc9by] {
    border-bottom: none;
}

.details-group-title[b-arlmqrc9by] {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--accent-color);
}

.party-picker[b-arlmqrc9by] {
    align-self: flex-start;
    width: auto;
    max-width: 100%;
    min-width: 12rem;
    min-height: 44px;
}

.party-composition-summary[b-arlmqrc9by] {
    color: var(--text-muted);
    font-size: 0.85rem;
}

@media (min-width: 769px) {
    .party-picker[b-arlmqrc9by] {
        min-height: 2.25rem;
    }
}

.battlemap-preview[b-arlmqrc9by] {
    display: block;
    max-width: 100%;
    max-height: 10rem;
    margin-top: 0.5rem;
}
/* /Features/Encounters/Builder/BuilderHeader.razor.rz.scp.css */
/* Mobile-first: the name fills the first line, badge and language share the second;
   the save actions join the row from 769px (phones use the summary bar). */
.builder-header[b-b1co6g0aup] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    margin-bottom: 0.75rem;
}

.header-name-input[b-b1co6g0aup] {
    flex: 1 1 100%;
    min-width: 0;
}

/* The name is the page title. */
.encounter-title-input[b-b1co6g0aup] {
    font-family: var(--font-header), serif;
    font-size: 1.25rem;
    font-weight: 600;
    min-height: 44px;
}

.header-spacer[b-b1co6g0aup] {
    flex: 1 1 0;
}

.header-actions[b-b1co6g0aup] {
    display: none;
}

@media (min-width: 769px) {
    .header-name-input[b-b1co6g0aup] {
        flex: 0 1 36rem;
        min-width: 12rem;
    }

    .encounter-title-input[b-b1co6g0aup] {
        font-size: 1.5rem;
    }

    .header-actions[b-b1co6g0aup] {
        display: block;
    }
}
/* /Features/Encounters/Builder/BuilderPartyLine.razor.rz.scp.css */
/* One wrapping line: icon · size × level/tier · actions (pushed right).
   Controls 44px on phones, compact from 769px. */
.party-line[b-3yivv5a4ne] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
}

.party-line-icon[b-3yivv5a4ne] {
    display: inline-flex;
    color: var(--text-muted);
}

.party-line .form-control[b-3yivv5a4ne],
.party-line .form-select[b-3yivv5a4ne] {
    min-height: 44px;
}

.party-size[b-3yivv5a4ne],
.party-level[b-3yivv5a4ne] {
    width: 4.5rem;
}

.party-line-times[b-3yivv5a4ne] {
    color: var(--text-muted);
}

.party-line-field[b-3yivv5a4ne] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
    color: var(--text-muted);
}

.party-line-actions[b-3yivv5a4ne] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

@media (min-width: 769px) {
    .party-line .form-control[b-3yivv5a4ne],
    .party-line .form-select[b-3yivv5a4ne] {
        min-height: 2.25rem;
    }
}
/* /Features/Encounters/Builder/BuilderRoster.razor.rz.scp.css */
/* The roster inside the encounter column's Roster tab; the column's glass card and
   its scrolling tab body belong to EncounterBuilder and TabSet. Mobile-first: every
   control 44px, one line per entry on every width. */

.roster-empty[b-0nsd2160y9] {
    margin: 0.75rem 0 0;
    padding: 0.75rem;
    text-align: center;
    color: var(--text-muted);
    border: 1px dashed var(--card-border);
    border-radius: 6px;
}

.roster-list[b-0nsd2160y9] {
    margin-top: 0.25rem;
    container-type: inline-size;
}

.roster-group[b-0nsd2160y9] {
    margin-top: 0.25rem;
}

.roster-group-header[b-0nsd2160y9] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin: 0.25rem 0.25rem 0.1rem;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
}

.roster-group-name[b-0nsd2160y9] {
    margin: 0;
    font-size: inherit;
    font-family: inherit;
    font-weight: 600;
    color: inherit;
}

.roster-group-points[b-0nsd2160y9] {
    font-variant-numeric: tabular-nums;
}

/* Narrow column (a small phone, or the desktop column at its narrowest): the name
   takes the first line, the controls the second. From 18rem one line per entry. */
.roster-item[b-0nsd2160y9] {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
        "main main main main"
        "qty . lock remove";
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem;
    border-bottom: 1px solid var(--card-border);
}

.roster-item:last-child[b-0nsd2160y9] {
    border-bottom: none;
}

/* The row places its children. */
.roster-item > .qty-stepper[b-0nsd2160y9] {
    grid-area: qty;
}

.roster-item > .roster-item-main[b-0nsd2160y9] {
    grid-area: main;
}

.roster-item > .lock-btn[b-0nsd2160y9] {
    grid-area: lock;
}

.roster-item > .remove-btn[b-0nsd2160y9] {
    grid-area: remove;
}

@container (min-width: 18rem) {
    .roster-item[b-0nsd2160y9] {
        grid-template-areas: "qty main lock remove";
    }
}

/* Name + CR/tier on one line; what does not fit scrolls sideways, without a scrollbar. */
.roster-item-main[b-0nsd2160y9] {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    min-width: 0;
    white-space: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
}

/* Roster name button lives in <FoePreviewLink> (Class="roster-entry-name"), so
   it carries the atom's scope id — reach it via ::deep (ladder rung 3).

   The modifier used to be called `roster-name`, which is also the class
   EncounterDisplay puts on the roster line of its own printed sheet. Two
   unrelated shapes under one name: this rule could never reach that line, but
   it did claim font-weight and color on the name of the class, which is what
   the collision guard reported. They are separate names now. */
[b-0nsd2160y9] .roster-entry-name {
    flex-shrink: 0;
    font-weight: 600;
    color: var(--text-color);
}

.qty-stepper[b-0nsd2160y9] {
    display: flex;
    align-items: center;
    gap: 0.15rem;
}

.qty-btn[b-0nsd2160y9],
.lock-btn[b-0nsd2160y9],
.remove-btn[b-0nsd2160y9] {
    width: 44px;
    height: 44px;
    padding: 0;
    line-height: 1;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.qty-display[b-0nsd2160y9] {
    min-width: 1.5rem;
    text-align: center;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--text-color);
}

/* Quiet like a nav link: unlocked stays muted until hover or focus, locked (filled
   lock) carries the accent colour. */
.lock-btn:focus-visible[b-0nsd2160y9] {
    color: var(--text-color);
}

.lock-btn--on[b-0nsd2160y9],
.lock-btn--on:hover[b-0nsd2160y9],
.lock-btn--on:focus-visible[b-0nsd2160y9] {
    color: var(--accent-color);
}

.roster-item-locked[b-0nsd2160y9] {
    background-color: var(--editor-highlight-bg);
    border-left: 3px solid var(--accent-color);
}

.encounter-entry--gated[b-0nsd2160y9] {
    display: inline-flex;
    align-items: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

@media (min-width: 769px) {
    .qty-btn[b-0nsd2160y9],
    .lock-btn[b-0nsd2160y9],
    .remove-btn[b-0nsd2160y9] {
        width: 28px;
        height: 28px;
    }
}
/* /Features/Encounters/Builder/BuilderSearchPanel.razor.rz.scp.css */
/* Form-control chrome is NOT repeated here: EncounterBuilder — this
   component's only renderer — owns it via `::deep .form-control` /
   `::deep .form-select` (ladder rung 3), and every input/select below
   carries one of those classes. A bare `input`/`select` rule here would
   also be dead, since no element in this template is unclassed. */

/* FoePicker search results (rendered by child DnD/DaggerheartFoePicker) */
[b-qxlkufx6yn] .foe-picker {
    margin-bottom: 0.75rem;
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

[b-qxlkufx6yn] .foe-search {
    margin-bottom: 0.75rem;
}

[b-qxlkufx6yn] .search-results {
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

/* The dropdowns in this column ask for their own full-width variant now
   (`<MultiSelectDropdown FullWidth>`, which forwards to DropdownPanel). These
   two rules took max-width and min-width off the components that render those
   elements; the values live in their sheets. */

.builder-search-panel[b-qxlkufx6yn] {
    /* Glass on the page art; the panel holds the GlassLayer and lets its
       ScrollBody scroll, so the blur does not scroll away with the content. */
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: hidden;
    min-width: 0;
    box-sizing: border-box;
    min-height: 0;
}

/* ── Mobile: hide by default; the drawer contract is EncounterBuilder's ──
   This panel only hides itself here. What an *active* mobile panel looks like
   (`.builder-panel.mobile-active`) is stated once, by EncounterBuilder — it
   renders the tab bar, holds ActiveMobileTab and hands `mobile-active` down as
   ActiveClass, so it owns the structural context (ladder rung 3). */
@media (max-width: 768px) {
    .builder-search-panel[b-qxlkufx6yn] {
        display: none;
    }
}
/* /Features/Encounters/Builder/BuilderSuggestions.razor.rz.scp.css */
/* One wrapping row: label · chips · Add all · dismiss. */
.suggested-allies[b-bmznztjpbk] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.375rem;
    margin-top: 0.5rem;
    font-size: 0.8rem;
}

.suggested-allies-label[b-bmznztjpbk] {
    color: var(--text-muted);
}

.ally-chip[b-bmznztjpbk] {
    border: 1px solid var(--card-border);
    border-radius: 999px;
    min-height: 44px;
}

.ally-chip:disabled[b-bmznztjpbk] {
    opacity: 0.6;
    text-decoration: line-through;
}

.suggested-allies-add-all[b-bmznztjpbk] {
    min-height: 44px;
}

.suggested-allies-dismiss[b-bmznztjpbk] {
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
}

@media (min-width: 769px) {
    .ally-chip[b-bmznztjpbk],
    .suggested-allies-add-all[b-bmznztjpbk],
    .suggested-allies-dismiss[b-bmznztjpbk] {
        min-height: 2rem;
    }

    .suggested-allies-dismiss[b-bmznztjpbk] {
        min-width: 2rem;
    }
}
/* /Features/Encounters/Builder/EncounterFilterModal.razor.rz.scp.css */
/* Headed groups one under the other; the dialog's own padding frames them. */
.filter-section[b-yvzvac8vju] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.filter-section + .filter-section[b-yvzvac8vju] {
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--card-border);
}

.filter-section-title[b-yvzvac8vju] {
    margin: 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-color);
}
/* /Features/Encounters/EncounterAssessmentPanel.razor.rz.scp.css */
.assessment-hint[b-pogkm4b9wh] {
    display: block;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.assessment-intent-selector[b-pogkm4b9wh] {
    display: flex;
    gap: 0.4rem;
    margin: 0.5rem 0;
    flex-wrap: wrap;
}

.intent-pill[b-pogkm4b9wh] {
    padding: 0.25rem 0.7rem;
    border: 1px solid var(--card-border);
    border-radius: 999px;
    background: var(--card-bg);
    color: var(--text-color);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
    line-height: 1.4;
}

.intent-pill:hover[b-pogkm4b9wh] {
    border-color: var(--accent-color);
    background: var(--editor-highlight-bg);
}

.intent-pill.intent-active[b-pogkm4b9wh] {
    background: var(--accent-color);
    color: var(--on-primary-text);
    border-color: var(--accent-color);
}

.assessment-archetype-selector[b-pogkm4b9wh] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.assessment-archetype-selector label[b-pogkm4b9wh] {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 600;
    white-space: nowrap;
}

.assessment-archetype-selector select[b-pogkm4b9wh] {
    max-width: 180px;
}

.assessment-verdict[b-pogkm4b9wh] {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    padding: 0.75rem;
}

.assumption-note[b-pogkm4b9wh] {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-top: 0.3rem;
    font-style: italic;
}

.lethality-badge[b-pogkm4b9wh] {
    display: inline-block;
    font-weight: 700;
    font-size: 0.85rem;
    padding: 0.15rem 0.6rem;
    border-radius: 3px;
    margin-bottom: 0.4rem;
}

.lethality-safe[b-pogkm4b9wh] {
    background: var(--difficulty-easy-bg);
    color: var(--difficulty-easy-text);
}

.lethality-risky[b-pogkm4b9wh] {
    background: var(--difficulty-moderate-bg);
    color: var(--difficulty-moderate-text);
}

.lethality-dangerous[b-pogkm4b9wh] {
    background: var(--difficulty-hard-bg);
    color: var(--difficulty-hard-text);
}

.lethality-lethal[b-pogkm4b9wh] {
    background: var(--difficulty-hard-text);
    color: var(--color-white);
}

.assessment-summary[b-pogkm4b9wh] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.assessment-warnings[b-pogkm4b9wh] {
    margin-top: 0.5rem;
}

/* The warning line is <WarningRow>: its row, icon and text rules moved into
   WarningRow.razor.css, and the severity modifiers went with them — they land
   on WarningRow's div, so they could only ever have worked from its sheet
   (ladder rung 2). The detail marker below is slotted content this panel
   renders itself, so it stays. */

.warning-detail[b-pogkm4b9wh] {
    cursor: help;
    opacity: 0.7;
    flex-shrink: 0;
}

.assessment-mismatch[b-pogkm4b9wh] {
    margin-top: 0.5rem;
    padding: 0.4rem 0.6rem;
    background: rgba(var(--difficulty-moderate-bar-rgb), 0.12);
    border: 1px solid rgba(var(--difficulty-moderate-bar-rgb), 0.3);
    border-radius: 4px;
    font-size: 0.8rem;
    color: var(--difficulty-moderate-text);
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.mismatch-icon[b-pogkm4b9wh] {
    flex-shrink: 0;
}

.details-toggle[b-pogkm4b9wh] {
    display: block;
    width: 100%;
    margin-top: 0.4rem;
    font-size: 0.78rem;
}

/* The details box is the shared <InsetPanel> (rung 2). */

.detail-section[b-pogkm4b9wh] {
    margin-bottom: 0.75rem;
}

.detail-section:last-child[b-pogkm4b9wh] {
    margin-bottom: 0;
}

.detail-section h5[b-pogkm4b9wh] {
    font-family: var(--font-header), serif;
    font-size: 0.85rem;
    color: var(--text-color);
    margin: 0 0 0.3rem;
}

.detail-help[b-pogkm4b9wh] {
    cursor: help;
    font-size: 0.75rem;
    opacity: 0.6;
}

.detail-help:hover[b-pogkm4b9wh] {
    opacity: 1;
}

.detail-row[b-pogkm4b9wh] {
    display: flex;
    justify-content: space-between;
    font-size: 0.8rem;
    padding: 0.15rem 0;
    color: var(--text-muted);
}

.detail-row span:last-child[b-pogkm4b9wh] {
    font-weight: 600;
    color: var(--text-color);
}

.detail-row.tone-good span:last-child[b-pogkm4b9wh] {
    color: var(--assessment-positive);
}

.detail-row.tone-warn span:last-child[b-pogkm4b9wh] {
    color: var(--difficulty-moderate-text);
}

.detail-row.tone-bad span:last-child[b-pogkm4b9wh] {
    color: var(--assessment-negative);
    font-weight: 700;
}

.tone-note[b-pogkm4b9wh] {
    font-style: italic;
    font-weight: 400;
    opacity: 0.85;
    margin-left: 0.25rem;
}

.detail-spark[b-pogkm4b9wh] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding-top: 0.3rem;
}

.assessment-empty[b-pogkm4b9wh] {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-style: italic;
    padding: 0.5rem 0;
}

@media (max-width: 768px) {
    .assessment-intent-selector[b-pogkm4b9wh] {
        gap: 0.3rem;
    }

    .intent-pill[b-pogkm4b9wh] {
        font-size: 0.75rem;
        padding: 0.2rem 0.55rem;
    }

    .assessment-summary[b-pogkm4b9wh] {
        font-size: 0.75rem;
    }
}
/* /Features/Encounters/EncounterAutoFillPanel.razor.rz.scp.css */
/* No box of its own: the row sits at the top of the builder's Roster tab,
   inside the encounter column's glass card. */

/* One row: Generate/Fill (+ Regenerate) · difficulty, quiet
   nav-link buttons; wraps when it does not fit. 44px controls on phones. */
.autofill-bar[b-2cke95nw8j] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Shrinks on a narrow screen so the main button's label wraps instead of overflowing. */
.autofill-actions[b-2cke95nw8j] {
    display: flex;
    flex: 0 1 auto;
    min-width: 0;
    gap: 0.25rem;
}

.autofill-actions button[b-2cke95nw8j] {
    min-height: 44px;
}

/* The main action: still colourless, but outlined in the heading accent with an
   icon, so it reads as a button and not as a label. */
.autofill-main[b-2cke95nw8j] {
    color: var(--heading-accent);
    font-weight: 600;
    border: 1px solid var(--heading-accent);
}

.autofill-actions .autofill-regenerate[b-2cke95nw8j] {
    flex: 0 0 auto;
    min-width: 44px;
    padding: 0;
}

.autofill-difficulty[b-2cke95nw8j] {
    flex: 1 1 8rem;
    width: auto;
    min-width: 0;
    min-height: 44px;
}

.autofill-panel + .autofill-panel[b-2cke95nw8j] {
    margin-top: 0.75rem;
}

.autofill-message[b-2cke95nw8j] {
    padding-top: 0.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
    font-style: italic;
}

.autofill-warnings[b-2cke95nw8j] {
    padding-top: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* The row itself is <WarningRow Boxed="true"> — its box chrome, icon and text
   rules moved into WarningRow.razor.css (ladder rung 2). Only the foe name,
   which this panel slots into the row, is still ours. */

.warning-foe-name[b-2cke95nw8j] {
    font-weight: 600;
}

@media (min-width: 769px) {
    .autofill-actions button[b-2cke95nw8j],
    .autofill-difficulty[b-2cke95nw8j] {
        min-height: 2.25rem;
    }

    .autofill-actions .autofill-regenerate[b-2cke95nw8j] {
        min-width: 2.25rem;
    }
}
/* /Features/Encounters/EncounterBuilder.razor.rz.scp.css */
/* ========================================
   Encounter Builder Styles
   ======================================== */

/* Inputs take their look from the element vocabulary in base.css (rung 4).
   The `--card-bg` re-skin that used to sit here was one of three copies of the
   same six declarations (FoePickerLayout, ContentEditorShell were the others) and
   was the only reason inputs in the builder read dark against the parchment
   inputs on every other page. Only the select's arrow gap is local. */
[b-yhc4wpm1ox] .form-select {
    padding-right: 2.25rem;
}

/* No padding of its own: the page's content padding is the one level around the grid. */
.encounter-builder[b-yhc4wpm1ox] {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

/* The edit/preview wrapper leaves the layout to its children (the page-fill flex column)
   and hides them while the preview shows; [hidden] alone loses to display: contents. */
.builder-edit[b-yhc4wpm1ox] {
    display: contents;
}

.builder-edit[hidden][b-yhc4wpm1ox] {
    display: none;
}

/* The print sheet keeps its paper width: it scrolls inside the page-fill column. */
.builder-preview[b-yhc4wpm1ox] {
    overflow: auto;
    min-height: 0;
    flex: 1 1 auto;
}

/* Mobile-first: the message on its own line, the buttons wrap under it; from 769px
   one row. */
.draft-recovery-banner[b-yhc4wpm1ox] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem 0.75rem;
    padding: 0.75rem;
    background: var(--card-bg);
    border: 2px solid var(--accent-color);
    border-radius: 6px;
    margin-bottom: 1rem;
}
.draft-recovery-banner p[b-yhc4wpm1ox] {
    margin: 0;
    flex: 1 1 100%;
}

/* The quiet nav-link buttons of the rest of the app; the main action (recover,
   save) set apart only by the heading accent, as EditorActions' Save. */
.builder-main-action[b-yhc4wpm1ox] {
    color: var(--heading-accent);
    font-weight: 600;
}

/* Phones: one column, the mobile tabs pick the drawer. From 769px the encounter
   column (38%) beside the foe list (62%). */
.builder-layout[b-yhc4wpm1ox] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    margin-bottom: 1rem;
    min-height: 0;
    flex: 1 1 auto;
}

/* The encounter column: one glass card on the page art (GlassLayer blurs it);
   it does not scroll itself, the TabSet's body does. */
.builder-encounter-panel[b-yhc4wpm1ox] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.encounter-party[b-yhc4wpm1ox] {
    flex-shrink: 0;
}

.encounter-difficulty[b-yhc4wpm1ox] {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.encounter-tabs[b-yhc4wpm1ox] {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* ── Responsive ── */

@media (max-width: 768px) {
    /* Mobile tab bar */
    .mobile-tabs[b-yhc4wpm1ox] {
        display: flex;
        gap: 0;
        background: var(--nav-bg);
        border-bottom: 1px solid var(--card-border);
        border-radius: 6px 6px 0 0;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .mobile-tab[b-yhc4wpm1ox] {
        flex: 1 0 auto;
        padding: 0.625rem 0.5rem;
        background: transparent;
        border: none;
        color: var(--text-muted);
        font-size: 0.85rem;
        font-weight: 600;
        cursor: pointer;
        text-align: center;
        transition: color 0.15s, background 0.15s, border-bottom 0.15s;
        border-bottom: 3px solid transparent;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.25rem;
    }

    .mobile-tab:hover[b-yhc4wpm1ox] {
        background: rgba(var(--highlight-rgb), 0.05);
        color: var(--text-color);
    }

    .mobile-tab-active[b-yhc4wpm1ox] {
        color: var(--accent-color);
        border-bottom-color: var(--accent-color);
        background: rgba(var(--highlight-rgb), 0.05);
    }

    .roster-count-badge[b-yhc4wpm1ox] {
        background: var(--accent-color);
        color: var(--on-accent-text);
        font-size: 0.7rem;
        padding: 0.1rem 0.35rem;
        border-radius: 999px;
        font-weight: 700;
        line-height: 1;
    }

    /* Mobile panel visibility — show only the active panel.

       The encounter column hides itself (its own markup, rung 1);
       BuilderSearchPanel does the same in its own sheet. The *active* drawer
       contract is stated once, here, and reaches both roots through the
       shared `builder-panel` marker class they render. This component owns the
       structural context — it renders the tab bar, holds ActiveMobileTab, and
       hands `mobile-active` down to the search panel as ActiveClass — so the
       contract is its business (ladder rung 3).

       Ranks (0,4,0) against each panel's own root rules. */
    .builder-encounter-panel[b-yhc4wpm1ox] {
        display: none;
    }

    /* The encounter column serves every phone tab but Search: Roster shows the party line, the
       difficulty and the Roster tab, each other tab only its own panel. */
    .builder-encounter-panel:not(.mobile-show-roster) .encounter-party[b-yhc4wpm1ox],
    .builder-encounter-panel:not(.mobile-show-roster) .encounter-difficulty[b-yhc4wpm1ox],
    .builder-encounter-panel:not(.mobile-show-roster) .encounter-roster[b-yhc4wpm1ox],
    .builder-encounter-panel:not(.mobile-show-configure) .encounter-details[b-yhc4wpm1ox],
    .builder-encounter-panel:not(.mobile-show-scenario) .encounter-scenario[b-yhc4wpm1ox] {
        display: none;
    }

    .builder-layout[b-yhc4wpm1ox]  .builder-panel.mobile-active {
        display: flex;
        box-sizing: border-box;
        width: 100%;
        max-width: 100%;
        padding: 0.75rem;
        min-height: 0;
        max-height: none;
        overflow-y: auto;
    }

    /* A label wider than its third of a narrow screen breaks instead of clipping. */
    .mobile-tab[b-yhc4wpm1ox] {
        white-space: nowrap;
    }

    /* Mobile sticky summary bar */
    .builder-mobile-actions[b-yhc4wpm1ox] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.5rem;
        padding: 0.5rem 0.75rem;
        background: var(--nav-bg);
        border-top: 1px solid var(--card-border);
        position: sticky;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 20;
    }

    .mobile-summary[b-yhc4wpm1ox] {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.5rem;
        flex: 1;
        min-width: 0;
    }

    .mobile-foe-count[b-yhc4wpm1ox] {
        font-weight: 700;
        font-size: 0.85rem;
        color: var(--text-color);
    }

    .mobile-foe-count-empty[b-yhc4wpm1ox] {
        color: var(--text-muted);
        font-style: italic;
        font-weight: 400;
    }

    .mobile-actions-right[b-yhc4wpm1ox] {
        display: flex;
        gap: 0.5rem;
        flex-shrink: 0;
    }

    .mobile-actions-right .btn-icon-only[b-yhc4wpm1ox] {
        padding: 0;
    }

}

/* ── Desktop: hide mobile-only elements ── */
@media (min-width: 769px) {
    .builder-layout[b-yhc4wpm1ox] {
        grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
        margin-bottom: 0;
    }

    .draft-recovery-banner[b-yhc4wpm1ox] {
        flex-wrap: nowrap;
        padding: 0.75rem 1rem;
    }

    .draft-recovery-banner p[b-yhc4wpm1ox] {
        flex: 1 1 auto;
    }

    .mobile-tabs[b-yhc4wpm1ox] {
        display: none;
    }

    .builder-mobile-actions[b-yhc4wpm1ox] {
        display: none;
    }
}

/* ── Pulse animation for mobile foe count ── */
@keyframes mobile-pulse-b-yhc4wpm1ox {
    0% { transform: scale(1); }
    50% { transform: scale(1.15); }
    100% { transform: scale(1); }
}

.mobile-foe-count.pulse[b-yhc4wpm1ox] {
    animation: mobile-pulse-b-yhc4wpm1ox 0.3s ease;
}

/* ── Extra-small phone refinements ── */
@media (max-width: 480px) {
    .mobile-tab[b-yhc4wpm1ox] {
        padding: 0.5rem 0.25rem;
        font-size: 0.8rem;
    }

    .mobile-foe-count[b-yhc4wpm1ox] {
        font-size: 0.8rem;
    }

    .builder-mobile-actions[b-yhc4wpm1ox] {
        padding: 0.375rem 0.5rem;
        gap: 0.375rem;
    }

    .mobile-actions-right[b-yhc4wpm1ox] {
        gap: 0.25rem;
    }

    .builder-mobile-actions .btn-sm[b-yhc4wpm1ox] {
        padding: 0.25rem 0.5rem;
        font-size: 0.75rem;
    }
}

/* moved from MainLayout.razor.css — EncounterBuilder renders .page-fill, so the
   rule needs this component's scope. */
@media (min-width: 769px) {
    .page-fill[b-yhc4wpm1ox] {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }
}
/* /Features/Encounters/EncounterBuilderLanding.razor.rz.scp.css */
.seo-landing-page[b-appht39h89] {
    max-width: 900px;
    margin: 0 auto;
    padding: 2rem 1rem;
    line-height: 1.7;
}

.seo-hero[b-appht39h89] {
    text-align: center;
    padding: 3rem 1rem;
}

.seo-hero h1[b-appht39h89] {
    font-family: var(--font-header);
    font-size: 2.2rem;
    margin-bottom: 1rem;
}

.seo-hero-subtitle[b-appht39h89] {
    font-size: 1.2rem;
    color: var(--text-secondary);
    margin-bottom: 2rem;
}

.seo-cta[b-appht39h89] {
    display: inline-block;
    padding: 0.8rem 2rem;
    background: var(--accent-color);
    color: var(--on-accent-text);
    text-decoration: none;
    border-radius: 6px;
    font-weight: 600;
    margin: 0.5rem;
    transition: background 0.2s;
}

.seo-cta:hover[b-appht39h89] {
    background: var(--color-gold-dark);
}

.seo-cta-secondary[b-appht39h89] {
    background: transparent;
    border: 2px solid var(--accent-color);
}

.seo-cta-secondary:hover[b-appht39h89] {
    background: var(--accent-color);
}

.seo-steps[b-appht39h89] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1.5rem;
    margin: 2rem 0;
}

/* Glass on the page art (GlassLayer blurs it); solid elsewhere. */
.seo-step[b-appht39h89] {
    position: relative;
    padding: 1.5rem;
    border-radius: 8px;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
}

.seo-step h3[b-appht39h89] {
    margin-bottom: 0.75rem;
}

.seo-faq-item[b-appht39h89] {
    margin: 1.5rem 0;
    padding: 1rem;
    border-left: 3px solid var(--accent-color);
}

.seo-cta-section[b-appht39h89] {
    text-align: center;
    padding: 3rem 1rem;
}

.seo-cta-group[b-appht39h89] {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 1.5rem;
}

.seo-content[b-appht39h89] {
    margin-bottom: 2rem;
}

.seo-content h2[b-appht39h89] {
    font-family: var(--font-header);
    margin-bottom: 1rem;
}

.seo-content ul[b-appht39h89] {
    list-style: disc;
    padding-left: 1.5rem;
    margin: 1rem 0;
}
/* /Features/Encounters/EncounterCardStats.razor.rz.scp.css */
/* ── Card internals ───────────────────────────────
   Ported from EncounterList.razor.css.
   .card-type and .card-teaser-description were dead here (EncounterCardStats
   renders neither element — the type line comes from CardContent's CardType
   param, the teaser moved to CardTeaserDescription) and were deleted; the
   remaining rules are authored by this component. */

/* Alternate-composition match badge */
.alternate-match-badge[b-qeecw4c06o] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* The smaller badge is <DifficultyBadge Compact> now: font-size and padding are
   properties that component states on its own root. */

.alternate-match-label[b-qeecw4c06o] {
    white-space: nowrap;
}
/* /Features/Encounters/EncounterContent.razor.rz.scp.css */
/* Ported from encounter-builder.css — EncounterContent renders the print sheet */

/* The sheet frame and its print-mode palette are <PrintSheet>; the chrome —
   header, meta row, sections, subsection titles, footer, badges — is the
   shared <Print*> component family, coloured through PrintSheet's --eprint-*
   custom properties. What stays here is EncounterContent's own markup: the
   roster table, the budget row, the embedded environment block and the item
   rows, including their per-print-mode theming. */

.eprint-budget-row[b-wzsa6ab7z1] {
    display: flex;
    gap: 0.5rem;
    align-items: baseline;
    margin: -0.75rem 0 1rem;
    padding: 0.5rem 1rem;
    background-color: rgba(var(--shadow-rgb), 0.02);
    border: 1px solid var(--card-border);
    border-top: none;
    border-radius: 0 0 6px 6px;
    font-size: 0.8rem;
}

.eprint-budget-label[b-wzsa6ab7z1] {
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.eprint-budget-values[b-wzsa6ab7z1] {
    color: var(--text-color);
}

.eprint-environment-header[b-wzsa6ab7z1] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
}

.eprint-environment-name[b-wzsa6ab7z1] {
    font-family: var(--print-font-header), serif;
    font-size: 1.05rem;
    margin: 0;
    color: var(--text-color);
}

.eprint-environment-summary[b-wzsa6ab7z1] {
    margin: 0 0 0.5rem;
    color: var(--text-muted);
    font-style: italic;
}

/* The feature stack is <EnvironmentFeatureList> (2026-08-21) — the same four
   declarations were also `.env-summary-features` in
   EncounterEnvironmentSummary.razor.css. The feature name and description
   below stay here: this component renders them, and their per-print-mode
   colours live at the bottom of this file. */

.eprint-env-feature-name[b-wzsa6ab7z1] {
    font-family: var(--print-font-header), serif;
    font-weight: 700;
    color: var(--text-color);
    font-size: 0.95rem;
}

.eprint-env-feature-desc[b-wzsa6ab7z1] {
    margin: 0.15rem 0 0;
    font-size: 0.88rem;
    color: var(--text-color);
}

/* Roster table */
.eprint-roster-table[b-wzsa6ab7z1] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.eprint-roster-table th[b-wzsa6ab7z1] {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    padding: 0.3rem 0.5rem;
    border-bottom: 2px solid var(--card-border);
}

.eprint-roster-table td[b-wzsa6ab7z1] {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--card-border);
    color: var(--text-color);
}
.eprint-col-left[b-wzsa6ab7z1]  { text-align: left; }
.eprint-col-center[b-wzsa6ab7z1] { text-align: center; }
.eprint-col-right[b-wzsa6ab7z1]  { text-align: right; }

.eprint-roster-total td[b-wzsa6ab7z1] {
    font-weight: 700;
    border-top: 2px solid var(--card-border);
    border-bottom: none;
}

.eprint-threshold-note[b-wzsa6ab7z1] {
    font-size: 0.78rem;
    color: var(--text-muted);
    padding: 0.3rem 0.5rem;
    margin-top: 0.25rem;
    border-top: 1px dashed var(--card-border);
}

/* Alternate compositions */

/* Theme tags */

/* Notes lines */

/* Footer */
/* ── Print mode: Plain ── */
/* No per-mode background/colour rules here: the sheet root is <PrintSheet>'s
   element (this file hands it `Class="encounter-print-sheet"`), and PrintSheet
   states the same three declarations on `.eprint-sheet.print-*` where the scope
   id actually lands. These were dead copies, not overrides. The
   `.encounter-print-sheet …` rules further down are different: their subject is
   an .eprint-* element this component renders, and the sheet class is only an
   ancestor there. */

/* The difficulty colour coding moved to PrintMetaField.razor.css on 2026-08-18.
   It was dead in both halves here: this page hands the modifier down as
   <PrintMetaField ValueClass="eprint-difficulty-…">, so the span wearing it is
   that component's and carries that component's scope id, and the bare
   `.eprint-difficulty-*` half named a class no markup in the repo renders. The
   sheet printed its difficulty in the default value colour throughout. */

/* ── Print media ── */
@media print {
    .encounter-print-actions[b-wzsa6ab7z1] { display: none !important; }

    /* Plain mode: enforce black text for reliable printing. Ornate needs
       nothing — print-color-adjust: exact carries its colours through. */
    .encounter-print-sheet.print-plain .eprint-roster-table td[b-wzsa6ab7z1],
    .encounter-print-sheet.print-plain .eprint-roster-table th[b-wzsa6ab7z1] { color: black; }

    .encounter-print-sheet.print-plain .eprint-notes-line[b-wzsa6ab7z1] { border-bottom: 1px solid var(--print-rule); }

    /* Tighten spacing for single-page fit. The header, meta row, sections,
       subsection titles and footer compact themselves — the rules live with
       the shared <Print*> chrome. */
    .eprint-roster-table td[b-wzsa6ab7z1] { padding: 0.2rem 0.4rem; }
    .eprint-roster-table th[b-wzsa6ab7z1] { padding: 0.2rem 0.4rem; }
}

/* Print item rows (shared by objectives and effects) */
.eprint-item-row[b-wzsa6ab7z1] {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.2rem 0 0.2rem 0.5rem;
    margin-bottom: 0.3rem;
    font-size: 0.88rem;
    color: var(--text-color-on-light-bg);
}

.eprint-item-row:last-child[b-wzsa6ab7z1] {
    margin-bottom: 0;
}

.eprint-item-bullet[b-wzsa6ab7z1] {
    font-size: 0.65rem;
    width: 1.2rem;
    text-align: center;
    flex-shrink: 0;
    color: var(--text-muted-on-light-bg);
}

.eprint-item-icon[b-wzsa6ab7z1] {
    font-size: 0.85rem;
    width: 1.2rem;
    text-align: center;
    flex-shrink: 0;
}

/* The item's inline content run is <ScenarioItemContent> (2026-08-21) — the
   same six declarations were also `.scenario-item-content` in
   EncounterDisplay.razor.css. The row, bullet, icon and the name/description/
   meta typography stay here: they are this sheet's own, and their values
   differ from the screen's. */

.eprint-item-name[b-wzsa6ab7z1] {
    color: var(--text-color-on-light-bg);
    flex-shrink: 0;
}

.eprint-item-desc[b-wzsa6ab7z1] {
    color: var(--text-muted-on-light-bg);
    flex: 1;
}

.eprint-item-meta[b-wzsa6ab7z1] {
    color: var(--text-muted-on-light-bg);
    font-size: 0.78rem;
    font-style: italic;
}

/* Per-print-mode theming of the parts EncounterContent renders itself — the
   roster table, the notes lines and the embedded environment block. The
   sheet chrome takes its colours from PrintSheet's --eprint-* palette
   instead, so nothing below reaches into another component. */
.encounter-print-sheet.print-plain .eprint-roster-table th[b-wzsa6ab7z1] {
    border-bottom-color: var(--text-primary);
    color: var(--print-text-muted);
}

.encounter-print-sheet.print-plain .eprint-roster-table td[b-wzsa6ab7z1] {
    border-bottom-color: var(--print-rule);
    color: var(--text-primary);
}

.encounter-print-sheet.print-plain .eprint-roster-total td[b-wzsa6ab7z1] {
    border-top-color: var(--text-primary);
}

.encounter-print-sheet.print-plain .eprint-notes-line[b-wzsa6ab7z1] {
    border-bottom-color: var(--print-rule);
}

.encounter-print-sheet.print-plain .eprint-environment-name[b-wzsa6ab7z1],
.encounter-print-sheet.print-plain .eprint-env-feature-name[b-wzsa6ab7z1] {
    color: var(--text-primary);
}

.encounter-print-sheet.print-plain .eprint-env-feature-desc[b-wzsa6ab7z1] {
    color: var(--text-primary);
}

.encounter-print-sheet.print-plain .eprint-environment-summary[b-wzsa6ab7z1] {
    color: var(--print-text-muted);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-roster-table th[b-wzsa6ab7z1] {
    border-bottom-color: var(--mm-text-header);
    color: var(--mm-print-label);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-roster-table td[b-wzsa6ab7z1] {
    border-bottom-color: var(--mm-accent-red);
    color: var(--text-primary);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-roster-total td[b-wzsa6ab7z1] {
    border-top-color: var(--mm-text-header);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-notes-line[b-wzsa6ab7z1] {
    border-bottom-color: var(--mm-accent-red);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-environment-name[b-wzsa6ab7z1] {
    color: var(--mm-text-header);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-env-feature-name[b-wzsa6ab7z1] {
    color: var(--mm-text-header);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-env-feature-desc[b-wzsa6ab7z1] {
    color: var(--text-primary);
}

.encounter-print-sheet.print-ornate.eprint-dnd .eprint-environment-summary[b-wzsa6ab7z1] {
    color: var(--mm-print-label);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-roster-table th[b-wzsa6ab7z1] {
    border-bottom-color: var(--dh-bg-dark);
    color: var(--dh-print-label);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-roster-table td[b-wzsa6ab7z1] {
    border-bottom-color: var(--dh-border-purple);
    color: var(--text-primary);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-roster-total td[b-wzsa6ab7z1] {
    border-top-color: var(--dh-bg-dark);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-notes-line[b-wzsa6ab7z1] {
    border-bottom-color: var(--dh-border-purple);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-environment-name[b-wzsa6ab7z1] {
    color: var(--dh-bg-dark);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-env-feature-name[b-wzsa6ab7z1] {
    color: var(--dh-bg-dark);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-env-feature-desc[b-wzsa6ab7z1] {
    color: var(--text-primary);
}

.encounter-print-sheet.print-ornate.eprint-dh .eprint-environment-summary[b-wzsa6ab7z1] {
    color: var(--dh-print-label);
}

.encounter-print-sheet.print-plain .eprint-notes-line[b-wzsa6ab7z1] { border-bottom: 1px solid var(--print-rule); }
/* /Features/Encounters/EncounterDisplay.razor.rz.scp.css */
/* Readout chrome (.difficulty-row/-label/-value) is owned by
   DifficultyBadge/DifficultyReadout (Common/Components/UI); the difficulty-<label>
   palette stays global in base.css (class composed at runtime). */
/* Ported from encounter-builder.css — EncounterDisplay renders these classes
   directly (not inside .encounter-builder), so it needs its own scoped copy. */
.encounter-display[b-l4jmk2azc5] {
    padding: 1rem;
}

.encounter-header[b-l4jmk2azc5] {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin: 1rem 0;
}

.encounter-header h1[b-l4jmk2azc5] {
    font-family: var(--font-header), serif;
    margin: 0;
}

.encounter-description[b-l4jmk2azc5] {
    color: var(--text-muted);
    font-style: italic;
    margin: .5rem 0;
}

/* Every section box on the page: glass on the page art (GlassLayer blurs it),
   solid elsewhere, like EntityCard's .card-item. */
.encounter-party-info[b-l4jmk2azc5],
.encounter-difficulty-section[b-l4jmk2azc5],
.encounter-scenario-section[b-l4jmk2azc5],
.encounter-roster-section[b-l4jmk2azc5],
.encounter-environment-section[b-l4jmk2azc5],
.encounter-battlemap-section[b-l4jmk2azc5],
.encounter-alternates-section[b-l4jmk2azc5],
.additional-section[b-l4jmk2azc5] {
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 6px;
    padding: 1rem;
    margin: .5rem 0;
}

.encounter-party-info[b-l4jmk2azc5] {
    display: flex;
    gap: 2rem;
    padding: 0.75rem 1rem;
}

.encounter-difficulty-section h3[b-l4jmk2azc5] {
    font-size: 1rem;
    margin: 0 0 0.5rem;
}

/* One section-heading rule for every section this page renders; it used to be
   stated five times, each copy also restating the font and colour base.css
   already gives every heading. */
.encounter-scenario-section h3[b-l4jmk2azc5],
.encounter-environment-section h3[b-l4jmk2azc5],
.encounter-battlemap-section h3[b-l4jmk2azc5],
.encounter-roster-section h3[b-l4jmk2azc5],
.encounter-alternates-section h3[b-l4jmk2azc5],
.additional-section h3[b-l4jmk2azc5] {
    font-size: 1.1rem;
    margin: 0 0 0.75rem;
}

.encounter-scenario-section h4[b-l4jmk2azc5] {
    font-family: var(--font-header), serif;
    color: var(--text-muted);
    font-size: 0.9rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: 0 0 0.5rem;
    padding-bottom: 0.25rem;
    border-bottom: 1px solid var(--card-border);
}

.scenario-objectives[b-l4jmk2azc5],
.scenario-effects[b-l4jmk2azc5] {
    margin-bottom: 1rem;
}

.scenario-objectives:last-child[b-l4jmk2azc5],
.scenario-effects:last-child[b-l4jmk2azc5] {
    margin-bottom: 0;
}

.scenario-item-row[b-l4jmk2azc5] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--card-border);
    font-size: 0.95rem;
    color: var(--text-color);
}

.scenario-item-row:last-child[b-l4jmk2azc5] {
    border-bottom: none;
}

.scenario-item-bullet[b-l4jmk2azc5],
.scenario-item-icon[b-l4jmk2azc5] {
    font-size: 0.85rem;
    width: 1.5rem;
    text-align: center;
    flex-shrink: 0;
    color: var(--text-muted);
}

/* The item's inline content run is <ScenarioItemContent> (2026-08-21) — the
   same six declarations were also `.eprint-item-content` in
   EncounterContent.razor.css. The row, bullet/icon and the name/description/
   meta typography stay here; the print sheet's values for them differ. */

.scenario-item-name[b-l4jmk2azc5] {
    font-weight: 600;
    color: var(--text-color);
    flex-shrink: 0;
}

.scenario-item-desc[b-l4jmk2azc5] {
    color: var(--text-muted);
    flex: 1;
}

.scenario-item-meta[b-l4jmk2azc5] {
    color: var(--text-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* Environment summary chrome lives in EncounterEnvironmentSummary.razor.css */

.roster-display-item[b-l4jmk2azc5] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--card-border);
}

.roster-display-item:last-child[b-l4jmk2azc5] {
    border-bottom: none;
}

.roster-display-item .roster-name[b-l4jmk2azc5] {
    font-weight: 600;
    flex: 1;
}

.roster-display-item a.roster-name[b-l4jmk2azc5] {
    color: var(--text-color);
    text-decoration: none;
}

.roster-display-item a.roster-name:hover[b-l4jmk2azc5] {
    color: var(--accent-color);
    text-decoration: underline;
}

.roster-display-item .roster-qty[b-l4jmk2azc5] {
    font-weight: 700;
    color: var(--color-gold);
    min-width: 30px;
}

.encounter-meta[b-l4jmk2azc5] {
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* ── Alternate party compositions ── */

.alternates-intro[b-l4jmk2azc5] {
    color: var(--text-muted);
    font-size: 0.9rem;
    font-style: italic;
    margin: 0 0 0.75rem;
}

.alternates-grid[b-l4jmk2azc5] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 0.75rem;
}

.alternate-item[b-l4jmk2azc5] {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.75rem;
    background: var(--editor-highlight-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
}

.alternate-party[b-l4jmk2azc5] {
    font-size: 0.9rem;
    color: var(--text-color);
    font-weight: 600;
}

.alternate-budget[b-l4jmk2azc5] {
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* ── Theme tags ── */

/* The theme-tag row is <HubTagList> / <HubTag> now (rung 2). This file carried
   the same declarations EntityHub carried for the two hub pages — one shape,
   three renderers, two sheets — so they went with the markup. */

/* ── List page description ── */

/* ── Builder-specific responsive/tags/panels moved to EncounterBuilder.razor.css ── */

/* ========================================
   Encounter Print Sheet
   ======================================== */

/* The roster line's size and colour are <RosterDetail InDisplayRoster>'s now.
   They were reached from here with ::deep, which took both properties off the
   component that renders the span. */

/* base.css also carried `.additional-tags` / `.additional-tag`. They were dead
   there, and they are not here either: the chips are <HubTag>/<HubTagList>. */
/* /Features/Encounters/EncounterEnvironmentSummary.razor.rz.scp.css */
/* Environment summary block (encounter detail + builder).
   Moved from EncounterDisplay.razor.css, where the rules targeted this
   component's markup and never matched its scope. */
.env-summary-header[b-t11t63ng3o] {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.25rem;
}

.env-summary-name[b-t11t63ng3o] {
    font-family: var(--font-header), serif;
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-color);
    margin: 0;
}

a.env-summary-name[b-t11t63ng3o] {
    text-decoration: none;
}

a.env-summary-name:hover[b-t11t63ng3o] {
    color: var(--accent-color);
    text-decoration: underline;
}

.env-summary-type[b-t11t63ng3o] {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    border: 1px solid var(--card-border);
    border-radius: 3px;
    padding: 0.05rem 0.4rem;
}

.env-summary-stats[b-t11t63ng3o] {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.env-summary-text[b-t11t63ng3o] {
    margin: 0 0 0.5rem;
    color: var(--text-muted);
    font-style: italic;
}

/* The feature stack is <EnvironmentFeatureList> (2026-08-21) — the same four
   declarations were also `.eprint-env-features` in EncounterContent.razor.css. */

.env-summary-feature p[b-t11t63ng3o] {
    margin: 0.15rem 0 0;
    font-size: 0.85rem;
    color: var(--text-color);
}
/* /Features/Encounters/EncounterPartyConfig.razor.rz.scp.css */
.composition-chips[b-7uxc8h9t9q] {
    margin-top: 0.5rem;
}

.composition-chips label[b-7uxc8h9t9q] {
    display: block;
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
}

.chips-row[b-7uxc8h9t9q] {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.composition-chip[b-7uxc8h9t9q] {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.3rem 0.6rem;
    border-radius: 999px;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text-color);
    cursor: pointer;
    font-size: 0.8rem;
    transition: background 0.15s, border-color 0.15s;
    user-select: none;
}

.composition-chip:hover[b-7uxc8h9t9q] {
    border-color: var(--accent-color);
}

.chip-healer[b-7uxc8h9t9q] {
    border-color: var(--role-healer);
    color: var(--role-healer);
}

.chip-caster[b-7uxc8h9t9q] {
    border-color: var(--role-caster);
    color: var(--role-caster);
}

.chip-phys[b-7uxc8h9t9q] {
    border-color: var(--role-physical);
    color: var(--role-physical);
}

.composition-chip-dec[b-7uxc8h9t9q] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid var(--card-border);
    background: var(--card-bg);
    color: var(--text-muted);
    font-size: 0.9rem;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}

.composition-chip-dec:hover:not(:disabled)[b-7uxc8h9t9q] {
    border-color: var(--accent-color);
}

.composition-chip-dec:disabled[b-7uxc8h9t9q] {
    opacity: 0.3;
    cursor: default;
}

@media (max-width: 768px) {
    .composition-chip[b-7uxc8h9t9q] {
        min-width: 44px;
        min-height: 44px;
        padding: 0.5rem 0.75rem;
    }

    .composition-chip-dec[b-7uxc8h9t9q] {
        min-width: 44px;
        min-height: 44px;
        padding: 0.5rem 0.75rem;
    }
}
/* /Features/Encounters/EncounterScenarioPanel.razor.rz.scp.css */
/* ========================================
   Encounter Scenario Panel
   ======================================== */

.scenario-setting[b-o1nvuhyjs7] {
    margin-bottom: 1.5rem;
}

.scenario-setting label[b-o1nvuhyjs7] {
    display: block;
    font-weight: 600;
    margin-bottom: 0.5rem;
    color: var(--text-color);
}

.scenario-section[b-o1nvuhyjs7] {
    margin-bottom: 1.5rem;
}

.scenario-section:last-child[b-o1nvuhyjs7] {
    margin-bottom: 0;
}

.scenario-section-header[b-o1nvuhyjs7] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.scenario-section-header h4[b-o1nvuhyjs7] {
    margin: 0;
    font-size: 1rem;
    color: var(--text-color);
}

.scenario-section-actions[b-o1nvuhyjs7] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.clear-all-btn[b-o1nvuhyjs7] {
    color: var(--text-muted);
    text-decoration: none;
    padding: 0.25rem 0.5rem;
}

.clear-all-btn:hover[b-o1nvuhyjs7] {
    color: var(--danger-ink);
    text-decoration: underline;
}

/* Scenario items (objectives and effects) */
.scenario-item[b-o1nvuhyjs7] {
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem;
    background: var(--editor-highlight-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}

.scenario-item-body[b-o1nvuhyjs7] {
    flex: 1;
    min-width: 0;
}

.scenario-item-header[b-o1nvuhyjs7] {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    align-items: flex-start;
}

.scenario-item-title[b-o1nvuhyjs7] {
    flex: 1;
    font-weight: 600;
    color: var(--text-color);
    word-break: break-word;
}

.scenario-item-actions[b-o1nvuhyjs7] {
    display: flex;
    gap: 0.25rem;
    flex-shrink: 0;
}

.scenario-item-edit-row[b-o1nvuhyjs7] {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    align-items: flex-start;
}

.scenario-item-edit-row .form-control[b-o1nvuhyjs7] {
    flex: 1;
}

.scenario-item-edit-row .form-control.name-input[b-o1nvuhyjs7] {
    flex: 0 0 40%;
}

.scenario-item-edit-row textarea.form-control[b-o1nvuhyjs7] {
    min-height: 60px;
    resize: vertical;
}

.scenario-item-desc[b-o1nvuhyjs7] {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin: 0.25rem 0;
    line-height: 1.4;
}

/* Trigger configuration */
.trigger-row[b-o1nvuhyjs7] {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.5rem;
    align-items: flex-start;
    flex-wrap: wrap;
}

.trigger-row .form-control[b-o1nvuhyjs7] {
    flex: 1;
    min-width: min(150px, 100%);
}

.trigger-row .trigger-type-select[b-o1nvuhyjs7] {
    flex: 0 1 auto;
    min-width: min(140px, 100%);
}

.trigger-row .trigger-preset-select[b-o1nvuhyjs7],
.trigger-row .trigger-freetext-input[b-o1nvuhyjs7] {
    flex: 1;
    min-width: min(200px, 100%);
}

.trigger-label[b-o1nvuhyjs7] {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
    display: block;
}

.trigger-display[b-o1nvuhyjs7] {
    font-size: 0.875rem;
    color: var(--text-color);
    padding: 0.4rem 0.6rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    display: inline-block;
}

/* Custom add forms */
.scenario-custom-add[b-o1nvuhyjs7] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.75rem;
    background: var(--card-bg);
    border: 1px dashed var(--card-border);
    border-radius: 6px;
    margin-top: 0.75rem;
}

.scenario-custom-add .form-control[b-o1nvuhyjs7] {
    flex: 1;
    min-width: min(200px, 100%);
}

.scenario-custom-add textarea.form-control[b-o1nvuhyjs7] {
    flex: 1 0 100%;
    min-height: 60px;
    resize: vertical;
}

.scenario-custom-add button[b-o1nvuhyjs7] {
    align-self: flex-start;
}

/* Suggestion list styling (extends existing) */
.suggestion-item.suggestion-added[b-o1nvuhyjs7] {
    opacity: 0.6;
}

.suggestion-item.suggestion-added .suggestion-info strong[b-o1nvuhyjs7] {
    color: var(--text-muted);
}

/* Relevance matching tags */
.suggestion-matches[b-o1nvuhyjs7] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.25rem;
}

.suggestion-matches-label[b-o1nvuhyjs7] {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.suggestion-match-tag[b-o1nvuhyjs7] {
    font-size: 0.7rem;
    padding: 0.1rem 0.4rem;
    background: var(--editor-highlight-bg);
    color: var(--accent-color);
    border: 1px solid var(--accent-color);
    border-radius: 10px;
    font-weight: 500;
}

/* Edit mode toggle button */
.btn-edit[b-o1nvuhyjs7] {
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    background: transparent;
    border: 1px solid var(--card-border);
    color: var(--text-muted);
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s;
}

.btn-edit:hover[b-o1nvuhyjs7] {
    border-color: var(--accent-color);
    color: var(--accent-color);
}

.btn-edit.active[b-o1nvuhyjs7] {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: var(--on-accent-text);
}

/* Reorder buttons */
.btn-reorder[b-o1nvuhyjs7] {
    padding: 0.2rem 0.35rem;
    font-size: 0.75rem;
    background: transparent;
    border: 1px solid var(--card-border);
    color: var(--text-muted);
    border-radius: 4px;
    cursor: pointer;
    line-height: 1;
    min-width: 1.5rem;
}

.btn-reorder:hover:not(:disabled)[b-o1nvuhyjs7] {
    border-color: var(--accent-color);
    color: var(--accent-color);
    background: var(--editor-highlight-bg);
}

.btn-reorder:disabled[b-o1nvuhyjs7] {
    opacity: 0.3;
    cursor: not-allowed;
}

/* Empty state */
.scenario-empty[b-o1nvuhyjs7] {
    font-size: 0.875rem;
    color: var(--text-muted);
    font-style: italic;
    padding: 0.5rem 0;
}

/* Error state */
.suggestion-error[b-o1nvuhyjs7] {
    font-size: 0.875rem;
    color: var(--danger-ink);
    padding: 0.75rem;
    background: var(--color-danger-bg);
    border: 1px solid var(--color-danger);
    border-radius: 4px;
}

/* Trigger badges */
.trigger-badge[b-o1nvuhyjs7] {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8rem;
    padding: 0.25rem 0.5rem;
    border-radius: 12px;
    font-weight: 500;
    border: 1px solid transparent;
}

.trigger-badge-always[b-o1nvuhyjs7] {
    background: rgba(var(--difficulty-easy-bar-rgb), 0.15);
    color: var(--difficulty-easy-bar);
    border-color: rgba(var(--difficulty-easy-bar-rgb), 0.3);
}

.trigger-badge-preset[b-o1nvuhyjs7] {
    background: rgba(var(--color-info-rgb), 0.15);
    color: var(--color-info);
    border-color: rgba(var(--color-info-rgb), 0.3);
}

.trigger-badge-custom[b-o1nvuhyjs7] {
    background: rgba(var(--color-purple-rgb), 0.15);
    color: var(--color-purple);
    border-color: rgba(var(--color-purple-rgb), 0.3);
}

.trigger-icon[b-o1nvuhyjs7] {
    font-size: 0.75rem;
    line-height: 1;
}

/* Form-control chrome is NOT repeated here: EncounterBuilder is this
   component's only renderer and owns it via `::deep .form-control` /
   `::deep .form-select` (ladder rung 3). Every input/select/textarea in this
   template carries one of those classes, so the bare element selectors this
   block used to carry matched nothing anyway. */

/* ── Builder Scenario tab overrides ──

   The panel sits in the encounter column's Scenario tab (`.encounter-scenario`,
   EncounterBuilder); on phones that tab is the Configure drawer
   (`.mobile-show-configure`). Until 2026-10-24 both were `.builder-sidebar`.

   The `.scenario-panel` and `.scenario-content` width caps that opened this
   block were dead and are deleted rather than repaired: CollapsiblePanel renders
   both elements, so these rules compiled against this file's scope id and never
   matched. The panel was never width-capped in the old sidebar either. */

.encounter-scenario .scenario-section-header[b-o1nvuhyjs7],
.encounter-scenario .scenario-item-edit-row[b-o1nvuhyjs7],
.encounter-scenario .scenario-custom-add[b-o1nvuhyjs7],
.encounter-scenario .trigger-row[b-o1nvuhyjs7] {
    flex-wrap: wrap;
}

.encounter-scenario .scenario-item-edit-row .form-control[b-o1nvuhyjs7],
.encounter-scenario .scenario-custom-add .form-control[b-o1nvuhyjs7],
.encounter-scenario .scenario-custom-add textarea.form-control[b-o1nvuhyjs7],
.encounter-scenario .trigger-row .form-control[b-o1nvuhyjs7],
.encounter-scenario .trigger-row .trigger-type-select[b-o1nvuhyjs7],
.encounter-scenario .trigger-row .trigger-preset-select[b-o1nvuhyjs7],
.encounter-scenario .trigger-row .trigger-freetext-input[b-o1nvuhyjs7] {
    flex: 1 1 100%;
    min-width: 0;
    width: 100%;
}

.encounter-scenario .scenario-item-edit-row .form-control.name-input[b-o1nvuhyjs7] {
    flex: 1 1 100%;
}

.encounter-scenario .suggestion-item[b-o1nvuhyjs7],
.encounter-scenario .suggestion-info[b-o1nvuhyjs7] {
    min-width: 0;
    max-width: 100%;
}

/* ── Mobile scenario overrides ── */
@media (max-width: 768px) {
    .mobile-show-configure .scenario-item-edit-row[b-o1nvuhyjs7],
    .mobile-show-configure .scenario-custom-add[b-o1nvuhyjs7],
    .mobile-show-configure .trigger-row[b-o1nvuhyjs7] {
        flex-direction: column;
    }

    .mobile-show-configure .scenario-item-edit-row .form-control[b-o1nvuhyjs7],
    .mobile-show-configure .scenario-custom-add .form-control[b-o1nvuhyjs7],
    .mobile-show-configure .scenario-custom-add textarea.form-control[b-o1nvuhyjs7],
    .mobile-show-configure .trigger-row .form-control[b-o1nvuhyjs7],
    .mobile-show-configure .trigger-row .trigger-type-select[b-o1nvuhyjs7],
    .mobile-show-configure .trigger-row .trigger-preset-select[b-o1nvuhyjs7],
    .mobile-show-configure .trigger-row .trigger-freetext-input[b-o1nvuhyjs7] {
        flex: 1 1 auto;
        width: 100%;
        min-width: 0;
    }

    .mobile-show-configure .scenario-section-header[b-o1nvuhyjs7] {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
    }

    .mobile-show-configure .scenario-section-actions[b-o1nvuhyjs7] {
        width: 100%;
        justify-content: flex-start;
        flex-wrap: wrap;
    }

    .mobile-show-configure .scenario-suggestion-list[b-o1nvuhyjs7] {
        max-height: 40vh;
        overflow-y: auto;
    }
}
/* /Features/Encounters/EnvironmentFeatureList.razor.rz.scp.css */
/* Stated once for both surfaces. Was `.env-summary-features` in
   EncounterEnvironmentSummary.razor.css and `.eprint-env-features` in
   EncounterContent.razor.css, identical in both. */
.env-feature-list[b-ae7qasll6v] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 0.5rem;
}
/* /Features/Encounters/ScenarioItemContent.razor.rz.scp.css */
/* Stated once for both surfaces. Was `.scenario-item-content` in
   EncounterDisplay.razor.css and `.eprint-item-content` in
   EncounterContent.razor.css, identical in both. */
.scenario-item-content[b-18isroiepa] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.35rem;
    flex: 1;
    min-width: 0;
}
/* /Features/Environments/EnvironmentContent.razor.rz.scp.css */
/* Environment card display styles */
.env-card[b-8xqdw0zept] {
    margin-bottom: 1.5rem;
    padding: 1.5rem 2rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    color: var(--text-color);
}

.env-card__header[b-8xqdw0zept] {
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--card-border);
    padding-bottom: 0.75rem;
}

.env-card__header h2[b-8xqdw0zept] {
    margin: 0 0 0.35rem;
    font-size: 1.6rem;
    color: var(--text-color);
}

.env-card__meta[b-8xqdw0zept] {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.env-card__cr[b-8xqdw0zept],
.env-card__tier[b-8xqdw0zept],
.env-card__type[b-8xqdw0zept] {
    display: inline-block;
}

.env-card__description[b-8xqdw0zept],
.env-card__atmosphere[b-8xqdw0zept],
.env-card__impulses[b-8xqdw0zept],
.env-card__difficulty[b-8xqdw0zept],
.env-card__dc[b-8xqdw0zept] {
    margin: 0.6rem 0;
    color: var(--text-color);
}

.env-card__linked[b-8xqdw0zept],
.env-card__features[b-8xqdw0zept] {
    margin-top: 1.25rem;
}

.env-card__linked h3[b-8xqdw0zept],
.env-card__features h3[b-8xqdw0zept] {
    margin: 0 0 0.5rem;
    font-size: 1.1rem;
    color: var(--accent-color);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.env-card__features h4[b-8xqdw0zept] {
    margin: 0.75rem 0 0.25rem;
    font-size: 0.95rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.env-card__linked ul[b-8xqdw0zept] {
    list-style: disc;
    padding-left: 1.5rem;
    margin: 0;
    color: var(--text-color);
}

.env-card__linked li[b-8xqdw0zept] {
    margin-bottom: 0.25rem;
}

.env-feature[b-8xqdw0zept] {
    margin-bottom: 1rem;
    padding: 0.75rem;
    background: var(--editor-highlight-bg);
    border-radius: 4px;
}

.env-feature strong[b-8xqdw0zept] {
    display: block;
    margin-bottom: 0.25rem;
    color: var(--text-color);
}

/* `env-feature__type` and `env-feature__questions` left this sheet on 2026-08-22: they are
   <EnvironmentFeatureTypeTag> and <EnvironmentFeatureQuestions>, shared with the print sheet,
   which stated the same rules under `env-pprint-feature__*`. This card takes their defaults. */
.env-feature p[b-8xqdw0zept] {
    margin: 0 0 0.5rem;
    color: var(--text-color);
}

.env-card__tags[b-8xqdw0zept] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--card-border);
}
/* /Features/Environments/EnvironmentDisplay.razor.rz.scp.css */
/* Environment Display — the `.foe-display` wrapper and its print variant are
   owned by <DisplayPage>. `.no-print` is handled globally by print.css:29; the
   elements here are rendered by DetailToolbar, outside this component's scope. */

/* /Features/Environments/EnvironmentFeatureQuestions.razor.rz.scp.css */
.env-feature-questions[b-f2rk5i16nq] {
    list-style: none;
    padding-left: 0.5rem;
    margin: var(--env-feature-questions-margin, 0.5rem 0 0);
    border-left: 2px solid var(--env-feature-rule, var(--accent-color));
}

.env-feature-questions li[b-f2rk5i16nq] {
    margin-bottom: var(--env-feature-question-gap, 0.2rem);
    color: var(--env-feature-muted, var(--text-muted));
    font-size: var(--env-feature-question-size, 0.9rem);
}
/* /Features/Environments/EnvironmentFeatureTypeTag.razor.rz.scp.css */
.env-feature-type[b-ndimn2g9vx] {
    font-weight: normal;
    font-size: 0.85rem;
    color: var(--env-feature-muted, var(--text-muted));
}
/* /Features/Environments/EnvironmentList.razor.rz.scp.css */
/* All rules moved to ContentListLayout.razor.css (::deep) and ListSearchControls.razor.css.
   Empty file kept for Blazor build system. */
/* /Features/Environments/EnvironmentPrintContent.razor.rz.scp.css */
/* ── Environment print sheet ──
   The frame, the print-mode palette and the sheet chrome belong to <PrintSheet>
   and the shared <Print*> components. What stays here is the markup this
   component renders itself: the atmosphere/impulses callout, the feature blocks
   and the linked-foe list, plus their per-mode theming (the mode classes sit on
   PrintSheet's div, which is a plain ancestor of these elements). */

/* Atmosphere / Impulses callout */
.env-pprint-callout[b-bcfwintrep] {
    margin: 0;
    padding: 0.5rem 0.75rem;
    border-left: 3px solid var(--accent-color);
    background: var(--editor-highlight-bg);
    border-radius: 0 4px 4px 0;
    color: var(--text-color-on-light-bg);
    font-style: italic;
}

/* Feature blocks.
   The four custom properties are the print sheet's paper values for <EnvironmentFeatureTypeTag>
   and <EnvironmentFeatureQuestions>, which take the on-screen card's defaults otherwise. They sit
   on this block and NOT on `.env-print-sheet`: that class is handed to <PrintSheet Class="…">, so
   the element wearing it carries PrintSheet's scope id and a rule whose SUBJECT is that class
   matches nothing here. The mode selectors below work because isolation stamps the subject only —
   the descendant they end on is this file's own element. */
.env-pprint-feature[b-bcfwintrep] {
    --env-feature-muted: var(--text-muted-on-light-bg);
    --env-feature-questions-margin: 0;
    --env-feature-question-gap: 0.15rem;
    --env-feature-question-size: 0.85rem;

    margin-bottom: 0.85rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--card-border);
}

.env-pprint-feature:last-child[b-bcfwintrep] {
    border-bottom: none;
    margin-bottom: 0;
    padding-bottom: 0;
}

.env-pprint-feature__name[b-bcfwintrep] {
    display: block;
    margin-bottom: 0.2rem;
    color: var(--text-color-on-light-bg);
    font-size: 0.95rem;
}

.env-pprint-feature__desc[b-bcfwintrep] {
    margin: 0 0 0.4rem;
    color: var(--text-color-on-light-bg);
    font-size: 0.9rem;
}

/* Linked foes list */
.env-pprint-linked[b-bcfwintrep] {
    list-style: disc;
    padding-left: 1.5rem;
    margin: 0;
    color: var(--text-color-on-light-bg);
    font-size: 0.9rem;
}

.env-pprint-linked li[b-bcfwintrep] {
    margin-bottom: 0.2rem;
}

/* ── Plain mode ── */
.env-print-sheet.print-plain .env-pprint-callout[b-bcfwintrep] {
    border-left-color: var(--print-rule);
    background: white;
    color: var(--text-primary);
}

.env-print-sheet.print-plain .env-pprint-feature[b-bcfwintrep] {
    border-bottom-color: var(--print-rule-light);
}

.env-print-sheet.print-plain .env-pprint-feature__name[b-bcfwintrep],
.env-print-sheet.print-plain .env-pprint-feature__desc[b-bcfwintrep],
.env-print-sheet.print-plain .env-pprint-linked[b-bcfwintrep] {
    color: var(--text-primary);
}

.env-print-sheet.print-plain .env-pprint-feature[b-bcfwintrep] {
    --env-feature-muted: var(--print-text-muted);
    --env-feature-rule: var(--print-rule);
}

/* ── Ornate – D&D 5e (parchment / red) ── */
.env-print-sheet.print-ornate.eprint-dnd .env-pprint-callout[b-bcfwintrep] {
    border-left-color: var(--mm-accent-red);
    background: var(--mm-print-row-tint);
    color: var(--text-primary);
}

.env-print-sheet.print-ornate.eprint-dnd .env-pprint-feature[b-bcfwintrep] {
    border-bottom-color: var(--mm-print-rule-soft);
}

.env-print-sheet.print-ornate.eprint-dnd .env-pprint-feature__name[b-bcfwintrep] {
    color: var(--text-primary);
}

.env-print-sheet.print-ornate.eprint-dnd .env-pprint-feature[b-bcfwintrep] {
    --env-feature-muted: var(--mm-print-label);
    --env-feature-rule: var(--mm-accent-red);
}

/* ── Ornate – Daggerheart (lavender / purple) ── */
.env-print-sheet.print-ornate.eprint-dh .env-pprint-callout[b-bcfwintrep] {
    border-left-color: var(--dh-border-purple);
    background: var(--dh-print-row-tint);
    color: var(--text-primary);
}

.env-print-sheet.print-ornate.eprint-dh .env-pprint-feature[b-bcfwintrep] {
    border-bottom-color: var(--dh-print-rule-soft);
}

.env-print-sheet.print-ornate.eprint-dh .env-pprint-feature__name[b-bcfwintrep] {
    color: var(--text-primary);
}

.env-print-sheet.print-ornate.eprint-dh .env-pprint-feature[b-bcfwintrep] {
    --env-feature-muted: var(--dh-print-label);
    --env-feature-rule: var(--dh-border-purple);
}

/* ── Print media ── */
@media print {
    /* The single-page compaction of the meta row, sections, section titles and
       footer is the components' own @media print rule now — identical values,
       stated once. */
    .env-pprint-feature[b-bcfwintrep] { margin-bottom: 0.5rem; padding-bottom: 0.5rem; }
}
/* /Features/Environments/EnvironmentPrintPreview.razor.rz.scp.css */
/* /Features/Factions/FactionPrintContent.razor.rz.scp.css */
.faction-print-card[b-gtwtuq2llp] {
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--eprint-soft-rule, var(--card-border));
}

.faction-print-card:last-child[b-gtwtuq2llp] {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}
/* /Features/Home/FeaturedFeed.razor.rz.scp.css */
/* .type-badge moved to TypeBadge.razor.css (rung 2) with the markup: this page
   and the other one defined it identically, and both render <TypeBadge> now. */

/* .system-tag rules deleted: Home.razor renders the element (Home.razor.css:314
   owns the live copy); this component never has, so they could not match. */

.load-more-container[b-xi8d0fmpb4] {
    display: flex;
    justify-content: center;
    margin-top: 2rem;
}

.load-more-container button[b-xi8d0fmpb4] {
    min-width: 160px;
}
/* /Features/Home/Home.razor.rz.scp.css */
.home-page[b-a051tvhaq3] {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem 1rem;
}

/* .hero and its base `.hero h1` moved to HeroSection.razor.css (rung 2):
   this page and the other one defined both identically, and both render
   <HeroSection> now. The responsive `.hero h1` override further down stays
   here — its subject <h1> is written in this file. */

.tagline[b-a051tvhaq3] {
    font-size: 1.2rem;
    color: var(--text-muted);
    max-width: 600px;
    margin: 0 auto;
}

.features[b-a051tvhaq3] {
    margin-bottom: 3rem;
}

.features h2[b-a051tvhaq3] {
    text-align: center;
    margin-bottom: 1.5rem;
    font-size: 1.5rem;
    color: var(--text-color);
}

/* Every card on Home is glass over the page art (GlassLayer blurs it, the sheen,
   rim and float shadow carry the look; tokens.css), positioned for the layer. */
.card[b-a051tvhaq3] {
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 2rem;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 2px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: var(--text-color);
    transition: transform var(--transition-base),
                border-color var(--transition-base),
                box-shadow var(--transition-base);
    text-align: center;
}

.card:hover[b-a051tvhaq3] {
    transform: translateY(-4px);
    border-color: var(--accent-color);
    box-shadow: var(--card-glass-rim, 0 0 transparent), 0 8px 30px rgba(var(--shadow-rgb), 0.3);
}

/* These cards are links — give the keyboard the same affordance as hover. */
.card:focus-visible[b-a051tvhaq3] {
    outline: none;
    transform: translateY(-4px);
    border-color: var(--accent-color);
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--focus-ring);
}

.card a[b-a051tvhaq3] {
    text-decoration: none;
}

.support-cta .support-buttons[b-a051tvhaq3] {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

.support-cta .btn-bmc[b-a051tvhaq3] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    border-radius: 8px;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.2s ease;
    border: 2px solid transparent;
    background: linear-gradient(135deg, var(--brand-kofi-light), var(--brand-kofi));
    /* Fixed Buy Me a Coffee brand button text color — not a theme surface, same exemption class as PatreonGate overlay */
    color: var(--brand-kofi-text);
}

.support-cta .btn-bmc:hover[b-a051tvhaq3] {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(var(--brand-kofi-rgb), 0.3);
}

.support-cta .btn-patreon[b-a051tvhaq3] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    border-radius: 8px;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.2s ease;
    border: 2px solid transparent;
    background: linear-gradient(135deg, var(--brand-patreon), var(--brand-patreon-dark));
    /* Fixed Patreon brand button text color — not a theme surface, same exemption class as PatreonGate overlay */
    color: var(--color-white);
}

.support-cta .btn-patreon:hover[b-a051tvhaq3] {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(var(--brand-patreon-rgb), 0.3);
}

/* .type-badge moved to TypeBadge.razor.css (rung 2) with the markup: this page
   and the other one defined it identically, and both render <TypeBadge> now. */

.featured-preview-footer[b-a051tvhaq3] {
    display: flex;
    gap: 1rem;
    justify-content: center;
    margin-top: 1.5rem;
    flex-wrap: wrap;
}

.btn-featured-dnd[b-a051tvhaq3],
.btn-featured-dh[b-a051tvhaq3] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    border-radius: 8px;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.2s ease;
    border: 2px solid transparent;
}

.btn-featured-dnd[b-a051tvhaq3] {
    background: rgba(var(--system-dnd-rgb), 0.15);
    color: var(--system-dnd-accent);
    border-color: rgba(var(--system-dnd-rgb), 0.4);
}

.btn-featured-dnd:hover[b-a051tvhaq3] {
    background: rgba(var(--system-dnd-rgb), 0.25);
    border-color: var(--system-dnd-accent);
    transform: translateY(-2px);
}

.btn-featured-dh[b-a051tvhaq3] {
    background: rgba(var(--system-dh-rgb), 0.15);
    color: var(--system-dh-accent);
    border-color: rgba(var(--system-dh-rgb), 0.4);
}

.btn-featured-dh:hover[b-a051tvhaq3] {
    background: rgba(var(--system-dh-rgb), 0.25);
    border-color: var(--system-dh-accent);
    transform: translateY(-2px);
}

.support-cta[b-a051tvhaq3] {
    position: relative;
    text-align: center;
    margin-top: 2rem;
    padding: 1.5rem;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    color: var(--text-color);
}

.support-cta h2[b-a051tvhaq3] {
    color: var(--text-color);
}

.support-cta p[b-a051tvhaq3] {
    margin-bottom: 1rem;
    color: var(--text-muted);
}

.guide-cta[b-a051tvhaq3] {
    position: relative;
    text-align: center;
    margin-bottom: 2rem;
    padding: 1.5rem;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    color: var(--text-color);
}

.guide-cta h2[b-a051tvhaq3] {
    color: var(--text-color);
    margin-bottom: 0.5rem;
}

.guide-cta p[b-a051tvhaq3] {
    margin-bottom: 1rem;
    color: var(--text-muted);
}

.features-grid[b-a051tvhaq3] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1.5rem;
}

.feature[b-a051tvhaq3] {
    position: relative;
    text-align: center;
    padding: 1.5rem;
    border-width: 1px;
    border-radius: var(--radius-md);
    color: var(--text-color);
}

.feature h3[b-a051tvhaq3] {
    font-size: 1.1rem;
    margin-bottom: 0.5rem;
    color: var(--text-color);
}

.feature p[b-a051tvhaq3] {
    color: var(--text-muted);
    font-size: 0.9rem;
}

.system-tag[b-a051tvhaq3] {
    display: inline-block;
    padding: 0.15rem 0.5rem;
    margin-top: 0.5rem;
    border-radius: 10px;
    font-size: 0.75rem;
    font-weight: 600;
    background: rgba(var(--highlight-rgb), 0.08);
    color: var(--text-muted);
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.system-tag.dnd-theme[b-a051tvhaq3] {
    background: rgba(var(--system-dnd-rgb), 0.2);
    color: var(--system-dnd-accent);
}

.system-tag.dh-theme[b-a051tvhaq3] {
    background: rgba(var(--system-dh-rgb), 0.2);
    color: var(--system-dh-accent);
}

/* Loading is the shared <LoadingState> component, which brings its own
   centring and padding. */

/* Tier comparison cards */
.tier-table[b-a051tvhaq3] {
    margin-top: 2rem;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

.tier-card[b-a051tvhaq3] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1.25rem 1rem;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 2px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 12px;
    text-align: center;
    gap: 0.5rem;
}

.tier-card-header[b-a051tvhaq3] {
    font-weight: 700;
    font-size: 1rem;
}

.tier-card-price[b-a051tvhaq3] {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--text-muted);
}

.tier-card-name[b-a051tvhaq3] {
    font-style: italic;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.tier-card-desc[b-a051tvhaq3] {
    font-size: 0.8rem;
    line-height: 1.4;
    color: var(--text-secondary);
    margin-top: auto;
}

.tier-free .tier-card-header[b-a051tvhaq3] { color: var(--text-muted); }
.tier-supporter .tier-card-header[b-a051tvhaq3] { color: var(--tier-badge-supporter-bg); }
.tier-curator .tier-card-header[b-a051tvhaq3] { color: var(--tier-badge-curator-bg); }
.tier-insider .tier-card-header[b-a051tvhaq3] { color: var(--tier-insider-heading); }

@media (max-width: 768px) {
    .hero h1[b-a051tvhaq3] {
        font-size: 1.8rem;
    }

    .tagline[b-a051tvhaq3] {
        font-size: 1rem;
    }

    .tier-table[b-a051tvhaq3] {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 480px) {
    .support-cta .support-buttons[b-a051tvhaq3] {
        flex-direction: row;
        justify-content: center;
        flex-wrap: wrap;
        gap: 0.75rem;
    }

    .support-cta .btn-bmc[b-a051tvhaq3],
    .support-cta .btn-patreon[b-a051tvhaq3] {
        display: inline-flex;
        align-items: center;
        gap: 0.4rem;
        padding: 0.5rem 0.875rem;
        font-size: 0.85rem;
    }

    .featured-preview-footer[b-a051tvhaq3] {
        flex-direction: row;
        justify-content: center;
        flex-wrap: wrap;
        gap: 0.75rem;
    }

    .btn-featured-dnd[b-a051tvhaq3],
    .btn-featured-dh[b-a051tvhaq3] {
        display: inline-flex;
        align-items: center;
        gap: 0.4rem;
        padding: 0.5rem 0.875rem;
        font-size: 0.85rem;
    }

    .guide-cta[b-a051tvhaq3] {
        padding: 1rem;
    }

    .guide-cta .btn[b-a051tvhaq3] {
        padding: 0.5rem 0.875rem;
        font-size: 0.85rem;
        white-space: normal;
        line-height: 1.3;
    }

    .home-page[b-a051tvhaq3] {
        padding: 1rem 0.75rem;
    }

    .hero h1[b-a051tvhaq3] {
        font-size: 1.5rem;
    }

    .tagline[b-a051tvhaq3] {
        font-size: 0.9rem;
    }

    .tier-table[b-a051tvhaq3] {
        grid-template-columns: 1fr;
    }

    .tier-card[b-a051tvhaq3] {
        padding: 1rem 0.75rem;
    }
}
/* /Features/Home/HomeSystemCards.razor.rz.scp.css */
.system-cards[b-19c99o2q7m] {
    margin-bottom: 3rem;
}

.system-cards h2[b-19c99o2q7m] {
    text-align: center;
    margin-bottom: 1.5rem;
    font-size: 1.5rem;
}

.system-cards-grid[b-19c99o2q7m] {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

/* Glass over Home's art (GlassLayer blurs it; tokens.css), in the card's
   own system theme. Positioned for the GlassLayer. */
.system-card[b-19c99o2q7m] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2rem;
    text-align: center;
    text-decoration: none;
    color: var(--text-color);
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 2px solid var(--rubric);
    border-radius: var(--radius-lg);
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    transition: transform var(--transition-base),
                border-color var(--transition-base),
                box-shadow var(--transition-base);
}

/* A link: the keyboard gets the same lift as hover, with the focus ring. */
.system-card:hover[b-19c99o2q7m],
.system-card:focus-visible[b-19c99o2q7m] {
    color: var(--text-color);
    transform: translateY(-4px);
    border-color: var(--accent-color);
    box-shadow: var(--card-glass-rim, 0 0 transparent), 0 8px 30px var(--hover-shadow);
}

.system-card:focus-visible[b-19c99o2q7m] {
    outline: none;
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--focus-ring);
}

.system-card h3[b-19c99o2q7m] {
    margin: 0;
    font-size: 1.5rem;
    color: var(--heading-accent, var(--text-color));
}

.system-card p[b-19c99o2q7m] {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.95rem;
}

.system-card-action[b-19c99o2q7m] {
    margin-top: 0.5rem;
    color: var(--accent-color);
    font-weight: 600;
    font-size: 0.9rem;
}

@media (min-width: 769px) {
    .system-cards-grid[b-19c99o2q7m] {
        grid-template-columns: 1fr 1fr;
    }
}

@media (prefers-reduced-motion: reduce) {
    .system-card[b-19c99o2q7m],
    .system-card:hover[b-19c99o2q7m],
    .system-card:focus-visible[b-19c99o2q7m] {
        transition: none;
        transform: none;
    }
}
/* /Features/Home/Supporters.razor.rz.scp.css */
.supporters-page[b-m45gu63z2q] {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem 1rem;
}

/* Hero */
/* .hero and its base `.hero h1` moved to HeroSection.razor.css (rung 2):
   this page and the other one defined both identically, and both render
   <HeroSection> now. The responsive `.hero h1` override further down stays
   here — its subject <h1> is written in this file. */

.intro-text[b-m45gu63z2q] {
    font-size: 1.15rem;
    color: var(--text-muted);
    max-width: 600px;
    margin: 0 auto;
}

/* States: loading is the shared <LoadingState> component, empty is <EmptyState>.
   The `.loading-state` selector that used to open this block was left with a
   trailing comma when the empty-state rule went, so it silently joined
   `.tier-group` below. */

/* Tier groups */
.tier-group[b-m45gu63z2q] {
    margin-bottom: 3rem;
}

.tier-section-label[b-m45gu63z2q] {
    font-size: 1.4rem;
    text-align: center;
    margin-bottom: 1.5rem;
    color: var(--text-color);
}

.tier-block[b-m45gu63z2q] {
    margin-bottom: 2rem;
}

.tier-heading[b-m45gu63z2q] {
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 0.35rem 1rem;
    border-radius: 6px;
    display: inline-block;
    margin-bottom: 1rem;
    color: var(--color-white);
    font-weight: 600;
}

.tier-heading.tier-insider[b-m45gu63z2q] {
    background: var(--tier-badge-insider-bg);
    color: var(--tier-badge-insider-text);
}

.tier-heading.tier-curator[b-m45gu63z2q] {
    background-color: var(--tier-badge-curator-bg);
}

.tier-heading.tier-supporter[b-m45gu63z2q] {
    background-color: var(--tier-badge-supporter-bg);
}

.tier-heading.tier-free[b-m45gu63z2q] {
    background-color: var(--tier-badge-free-bg);
}

/* Supporter grid */
.supporter-grid[b-m45gu63z2q] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
}

.supporter-card[b-m45gu63z2q] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: calc(25% - 1.125rem);
    min-width: 0;
    text-align: center;
}

/* Avatar */
.avatar-wrapper[b-m45gu63z2q] {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    margin-bottom: 0.5rem;
}

.avatar[b-m45gu63z2q] {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.avatar-placeholder[b-m45gu63z2q] {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--color-white);
}

.avatar-placeholder.tier-insider[b-m45gu63z2q] {
    background: var(--tier-badge-insider-bg);
    color: var(--tier-badge-insider-text);
}

.avatar-placeholder.tier-curator[b-m45gu63z2q] {
    background-color: var(--tier-badge-curator-bg);
}

.avatar-placeholder.tier-supporter[b-m45gu63z2q] {
    background-color: var(--tier-badge-supporter-bg);
}

.avatar-placeholder.tier-free[b-m45gu63z2q] {
    background-color: var(--tier-badge-free-bg);
}

.supporter-name[b-m45gu63z2q] {
    font-size: 0.9rem;
    color: var(--text-color);
    line-height: 1.3;
    word-break: break-word;
}

/* Former supporters section */
.former-section[b-m45gu63z2q] {
    opacity: 0.5;
    filter: grayscale(0.8);
}

/* Responsive: tablet */
@media (max-width: 768px) {
    .supporter-card[b-m45gu63z2q] {
        width: calc(33.333% - 1rem);
    }
}

/* Responsive: mobile */
@media (max-width: 480px) {
    .hero h1[b-m45gu63z2q] {
        font-size: 2rem;
    }

    .intro-text[b-m45gu63z2q] {
        font-size: 1rem;
    }

    .supporter-card[b-m45gu63z2q] {
        width: calc(50% - 0.75rem);
    }
}

/* Responsive: small mobile */
@media (max-width: 360px) {
    .supporter-card[b-m45gu63z2q] {
        width: 100%;
    }
}
/* /Features/Home/WriteOption.razor.rz.scp.css */
/* One Write hub tile: icon above the label, glass on the page art (GlassLayer blurs it). */
.write-option[b-qlrq1c2i6o] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    width: 100%;
    min-height: 9rem;
    padding: 1.25rem 1.5rem;
    position: relative;
    background: var(--card-glass-sheen, none), var(--card-glass-bg, var(--card-bg));
    --text-muted: var(--card-glass-muted);
    border: 1px solid var(--card-glass-border, var(--card-border));
    box-shadow: var(--card-glass-rim, 0 0 transparent), var(--card-glass-shadow, none);
    border-radius: 8px;
    cursor: pointer;
    font-family: var(--font-header);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--text-color);
    text-align: left;
    transition: background 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.write-option:hover[b-qlrq1c2i6o],
.write-option:focus[b-qlrq1c2i6o] {
    border-color: var(--focus-color);
    box-shadow: var(--card-glass-rim, 0 0 transparent), 0 2px 8px var(--hover-shadow);
    outline: none;
}

.write-option:focus-visible[b-qlrq1c2i6o] {
    border-color: var(--focus-color);
    box-shadow: 0 0 0 0.2rem var(--focus-shadow);
}

.write-option:active[b-qlrq1c2i6o] {
    box-shadow: none;
    transform: translateY(1px);
}

.write-option-icon[b-qlrq1c2i6o] {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 3rem;
    height: 3rem;
    font-size: 2.25rem;
    color: var(--color-gold);
}

.write-option-text[b-qlrq1c2i6o] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.write-option-desc[b-qlrq1c2i6o] {
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 400;
    color: var(--text-muted);
}

.write-option-lock[b-qlrq1c2i6o] {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
}

.write-option--locked .write-option-label[b-qlrq1c2i6o] {
    color: var(--text-muted);
}

@media (min-width: 600px) {
    .write-option--lead[b-qlrq1c2i6o] {
        grid-column: 1 / -1;
        flex-direction: row;
        align-items: center;
        gap: 1.25rem;
    }
}
/* /Features/Home/WritePage.razor.rz.scp.css */
/* Write Hub Page */
.write-hub[b-hr6kc68dwo] {
    padding: 3rem 1rem;
    max-width: 1200px;
    margin: 0 auto;
}

@media (min-width: 600px) {
    .write-hub[b-hr6kc68dwo] {
        padding: 3rem 2rem;
    }
}

.write-hub-header[b-hr6kc68dwo] {
    text-align: center;
    margin-bottom: 2.5rem;
}

.write-hub-header h1[b-hr6kc68dwo] {
    margin: 0 0 0.5rem;
    font-family: var(--font-header);
}

.write-hub-subtitle[b-hr6kc68dwo] {
    margin: 0;
    color: var(--text-muted);
    font-size: 1.1rem;
}

/* Mobile-first tile grid; the tiles are WriteOption. */
.write-hub-options[b-hr6kc68dwo] {
    display: grid;
    grid-template-columns: 1fr;
    grid-auto-rows: 1fr;
    gap: 1rem;
}

@media (min-width: 600px) {
    .write-hub-options[b-hr6kc68dwo] {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 1024px) {
    .write-hub-options[b-hr6kc68dwo] {
        grid-template-columns: repeat(3, 1fr);
    }
}
/* /Features/Monsters/MonsterActiveFilterChips.razor.rz.scp.css */
/* /Features/Monsters/MonsterCompareRows.razor.rz.scp.css */
/* Shared cell chrome lives in base.css (both row components render it).
   Only the monster-only speed list is scoped here. */
/* ── Speed list ── */
.compare-speed-list[b-ql4rop6mro] {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.9rem;
}
/* /Features/Monsters/MonsterContent.razor.rz.scp.css */
/* Monster Card - D&D Monster Manual Theme.

   The card frame itself (base box, print-ornate / print-plain, the accent-line
   pseudo-elements and .fixed-width) moved to
   Common/Components/UI/FoeCardFrame.razor.css with the root div — ladder rung 2,
   the same blocks opened AdversaryContent.razor.css. The rules below still
   live here because their subject is an element MonsterContent renders; only the
   ancestor compound was renamed.

   The card *chrome* followed on 2026-08-18, for the same reason and by the same
   route: the title row, the subtype line, the section divider, the tracker rows
   and the condition grid were the same shapes in both card sheets under two token
   vocabularies, so they are <CardTitleRow>, <CardSubtype>, <CardSectionDivider>,
   <CardTrackingRow> and <CardConditionGrid> now, with the per-system values
   declared once as --foe-card-* properties on FoeCardFrame.

   `.section-label` went at the same time and was not rehoused: this file styled
   it in eight declarations plus a plain-mode override, and MonsterContent.razor
   has never rendered the class. Dead on both counts (working rule 4). */

/* Spacer divs between the HP, AC and initiative badges. These were inline
   style="width:16px" / style="width:8px" — rung 0, which no guard reads. A
   flex `gap` on the title row's right slot cannot replace them: the two gaps
   differ. */
.header-stat-gap[b-m6cwwe536a] {
    width: 16px;
}

.header-stat-gap--narrow[b-m6cwwe536a] {
    width: 8px;
}

.with-background[b-m6cwwe536a] {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    width: 62px;
}

.with-background img[b-m6cwwe536a] {
    position: absolute;
    top: 0;
    left: 0;
}

.abilities-row[b-m6cwwe536a] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 0;
    border-bottom: 1px solid var(--mm-accent-red);
    margin-bottom: 3px;
}

.foe-card-frame--dnd5e.print-ornate .abilities-row[b-m6cwwe536a] {
    border-bottom-color: var(--mm-accent-red);
}

.foe-card-frame--dnd5e.print-plain .abilities-row[b-m6cwwe536a] {
    border-bottom-color: var(--mm-text-primary);
}

/* `.ability-stat strong` is gone: weight 700 plus an ink was the same rule this
   sheet wrote twice (here and for `.info-item`) and AdversaryContent wrote a
   third time for `.feature-line strong`. The run is <CardEmphasis> now (ladder
   rung 2) and takes FoeCardFrame's --foe-card-emphasis-color, which is this
   card's --mm-text-header. The row itself needed no other declaration and gets
   none; it is still named by the plain-mode rule further down. */

.save-bonus[b-m6cwwe536a] {
    font-weight: 600;
    margin-left: 1px;
}

/* Info section - flexible horizontal layout */
.info-section[b-m6cwwe536a] {
    display: flex;
    flex-wrap: wrap;
    column-gap: 6px;
    row-gap: 1px;
    line-height: 1.3;
    margin-bottom: 2px;
}

.info-item[b-m6cwwe536a] {
    white-space: nowrap;

    /* The lead-in label's ink, read by the <CardEmphasis> this row renders. The
       abilities row takes the frame's default; this one has always used the
       maroon instead, so it re-declares the property on itself. */
    --foe-card-emphasis-color: var(--mm-accent-maroon);
}

/* Separator between inline items (not before wide items or after last inline) */
.info-item:not(.info-item-wide):not(:has(~ .info-item:not(.info-item-wide)))[b-m6cwwe536a]::after {
    content: none;
}

.info-item:not(.info-item-wide):not(:last-child):not(:has(+ .info-item-wide))[b-m6cwwe536a]::after {
    content: "|";
    color: var(--mm-accent-red);
    margin-left: 6px;
}

.foe-card-frame--dnd5e.print-plain .info-item:not(.info-item-wide)[b-m6cwwe536a]::after {
    color: var(--print-text-soft);
}

/* Wide items (actions, reactions) get their own line */
.info-item-wide[b-m6cwwe536a] {
    flex-basis: 100%;
    white-space: normal;
}

/* Plain mode drops both lead-in inks to the card's text colour. The same one
   rule as before over the same two rows — it named the two `strong` subjects
   while this sheet owned them, and names the two rows that hand the ink down
   now that <CardEmphasis> owns the element. */
.foe-card-frame--dnd5e.print-plain .info-item[b-m6cwwe536a],
.foe-card-frame--dnd5e.print-plain .ability-stat[b-m6cwwe536a] {
    --foe-card-emphasis-color: var(--mm-text-primary);
}

/* .notes-area / .note-line moved to Common/Components/UI/StatBlockNotesArea
   (ladder rung 2) — the same markup and the same rule bodies also sat in
   AdversaryContent.razor.css. Only the rule colour was ever card-specific, so it
   stays here as the custom property the component reads. */

/* Mobile responsive styles. The title row's reflow and the condition grid's
   column count left with their components — FoeCardFrame declares both as
   custom properties under the same `:not(.fixed-width)` condition, because that
   class is its own. */
@media screen and (max-width: 768px) {
    .foe-card-frame--dnd5e:not(.fixed-width) .abilities-row[b-m6cwwe536a] {
        flex-wrap: wrap;
    }

    .foe-card-frame--dnd5e:not(.fixed-width) .info-item[b-m6cwwe536a] {
        white-space: normal;
    }
}

/* Print-specific styles */
@media print {
    .foe-card-frame--dnd5e.print-plain .abilities-row[b-m6cwwe536a] {
        border-color: black !important;
    }

    .with-background img[b-m6cwwe536a] {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

/* The card's type scale for the directive — 0.85rem on a 1.3 leading — is
   <TacticalDirective Compact>'s now; those two properties are the component's
   own, and setting them from here took them off it. The card had inherited 1.3
   from `.foe-card-frame--dnd5e`, which is what the variant states outright.

   What is left are two properties the component does not set, on an element it
   renders — rung 3, no collision. */
.tactical-signals-section[b-m6cwwe536a]  .tactical-directive {
    font-style: italic;
    opacity: 0.8;
}
/* /Features/Monsters/MonsterEdit.razor.rz.scp.css */
/* Monster-Specific Editor Styles (D&D 5e) */

/* ── Shared foe-editor base (page template) ──
   The .foe-editor bare-selector padding rule that used to live here moved to
   ContentEditorShell.razor.css (task 1 of the editor-chrome-rung2 plan): once the
   page's outer div is rendered by that shared component, a scoped rule in this
   file can no longer reach it (it carries the shell's scope attribute, not
   this file's). Everything below still targets elements this file renders
   directly as ContentEditorShell's ChildContent, so it is unaffected. */
/* `.foe-editor h2` left this file 2026-08-17: AdversaryEdit stated it
   identically, and the heading is slotted content, so it is ContentEditorShell's
   `::deep h2` now (rung 3). */

/* .foe-editor .form-section (+ ::before, h3, h3.form-section-toggle, hover,
   .section-toggle-icon, h4) removed (Task 3, editor-chrome rung-2 plan): dead
   since MonsterEdit stopped hand-rolling any .form-section div — the last one
   (movement-speeds) now renders through CollapsibleFormSection/FormSection,
   which own this chrome. The h3/.section-toggle-icon this rule targeted is
   now authored by CollapsibleFormSection, so the page's scope attribute is
   never on it. */

/* .foe-editor .validation-message / .validation-summary-errors / .invalid removed:
   all three elements come from framework components (<ValidationMessage>,
   <ValidationSummary>, EditForm field classes), so this page's scope id is never
   on them and the rules matched nothing. base.css owns .validation-message and
   .invalid; the summary box moved to ContentEditorShell.razor.css as a ::deep rule. */
/* /Features/Monsters/MonsterHubContent.razor.rz.scp.css */
/* The sections themselves are <HubSection> (rung 2). What is left here is the
   grid that lays them out, which this component does render. */
.hub-section-group[b-n0bjtfgf0u] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(8rem, 100%), 1fr));
    gap: 0.75rem;
    align-items: start;
}

/* `hub-section--tactical-signals` is gone: the block asks for
   <HubSection FullWidth>, and the variant lives in HubSection's own sheet. */

/* Reclaimed from EntityHub.razor.css, which set grid-template-columns on this
   grid with ::deep and so took the property off the file that renders it. */
@media screen and (max-width: 768px) {
    .hub-section-group[b-n0bjtfgf0u] {
        grid-template-columns: 1fr;
    }

    .hub-section-group[b-n0bjtfgf0u]  .hub-section:not(:last-child) {
        border-bottom: 1px solid var(--card-border);
        padding-bottom: 0.75rem;
    }
}

/* The role chip and the tooltip chip are <HubTag Role> / <HubTag Tooltip> now,
   and their rules went to that component's sheet: the span carries HubTag's
   scope id, so a bare rule here would no longer match it. */
/* /Features/Monsters/MonsterImport.razor.rz.scp.css */
.json-paste-area[b-stjfsd73l4] {
    font-family: monospace;
    font-size: 0.85rem;
    resize: vertical;
}

/* ── Import status banners (reclaimed from base.css, ladder rung 1) ── */
.alert[b-stjfsd73l4] {
    padding: 0.75rem 1.25rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
    border-radius: 0.375rem;
}

.alert-warning[b-stjfsd73l4] {
    color: var(--text-primary);
    background: var(--color-warning-light);
    border-color: var(--color-warning-dark);
}

.alert-success[b-stjfsd73l4] {
    color: var(--on-success-text);
    background: var(--color-success);
    border-color: var(--color-success-dark);
}

.alert-danger[b-stjfsd73l4] {
    color: var(--on-danger-text);
    background: var(--color-danger);
    border-color: var(--color-danger-dark);
}

.import-actions[b-stjfsd73l4] {
    display: flex;
    gap: 0.5rem;
}
/* /Features/Monsters/MonsterReferenceCard.razor.rz.scp.css */
/* A monster reference's card: HubCard owns the box and title; this file only the column of its body. */

.monster-reference-card[b-531k57gtyp] {
    max-width: 900px;
}

.reference-body[b-531k57gtyp] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.reference-link[b-531k57gtyp] {
    align-self: flex-start;
}
/* /Features/Monsters/MonsterStatBlock.razor.rz.scp.css */
.foe-stat-block-frame .sb-abilities[b-s5vwrs8p9w] {
    display: flex;
    justify-content: flex-start;
    gap: 0.5rem;
    margin: 0.3rem 0;
    break-inside: avoid;
}

.foe-stat-block-frame .sb-ability[b-s5vwrs8p9w] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 2.5rem;
}

.foe-stat-block-frame .sb-ability .sb-abbr[b-s5vwrs8p9w] {
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--fsb-ink);
}

.foe-stat-block-frame .sb-ability .sb-score[b-s5vwrs8p9w] {
    font-weight: 700;
    font-size: 1rem;
    color: var(--fsb-ink);
}

.foe-stat-block-frame .sb-ability .sb-mod[b-s5vwrs8p9w] {
    font-size: 0.85rem;
    color: var(--fsb-ink);
}

/* /Features/Monsters/Sections/MonsterAbilityScoresSection.razor.rz.scp.css */
/* Ability Scores & Saves Grid — moved from MonsterEdit.razor.css ::deep */
.ability-grid[b-mno9nq24ru] {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 1rem;
}

@media (max-width: 900px) {
    .ability-grid[b-mno9nq24ru] {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (max-width: 500px) {
    .ability-grid[b-mno9nq24ru] {
        grid-template-columns: repeat(2, 1fr);
    }
}

.ability-group[b-mno9nq24ru] {
    display: flex;
    flex-direction: column;
    align-items: center;
    background: var(--editor-highlight-bg);
    border: 1px solid var(--card-border);
    border-radius: 6px;
    padding: 0.75rem;
}

/* `--mm-font-header`, not `--font-header`: this is D&D chrome that keeps its own
   face whatever heading face the app is wearing. */
.ability-group > label[b-mno9nq24ru] {
    font-weight: 700;
    color: var(--text-color);
    font-family: var(--mm-font-header);
    font-size: 0.9rem;
    margin-bottom: 0.25rem;
}

.ability-group .ability-score[b-mno9nq24ru] {
    width: 100%;
    text-align: center;
    font-size: 1.1rem;
    font-weight: 600;
}

.ability-group .ability-mod[b-mno9nq24ru] {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin: 0.25rem 0 0.5rem 0;
}

.ability-group .save-input[b-mno9nq24ru] {
    width: 100%;
    border-top: 1px solid var(--card-border);
    padding-top: 0.5rem;
    margin-top: 0.25rem;
}

.ability-group .save-input label[b-mno9nq24ru] {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-color);
    display: block;
    text-align: center;
    margin-bottom: 0.25rem;
}

.ability-group .save-input input[b-mno9nq24ru] {
    width: 100%;
    text-align: center;
    font-size: 0.95rem;
}

.ability-group .save-input input[b-mno9nq24ru]::placeholder {
    color: var(--text-muted);
}
/* /Features/Monsters/Sections/MonsterBasicInfoSection.razor.rz.scp.css */
/* Alignment Selector — moved from MonsterEdit.razor.css ::deep */
.alignment-selector[b-ve04xzrhva] {
    position: relative;
}

.alignment-display[b-ve04xzrhva] {
    width: 100%;
    background-color: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    padding: 0.5rem;
    font-family: var(--font-body);
    text-align: left;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: var(--text-color);
}

.alignment-display:hover[b-ve04xzrhva] {
    border-color: var(--focus-color);
}

.alignment-display:focus[b-ve04xzrhva] {
    border-color: var(--focus-color);
    box-shadow: 0 0 0 0.2rem var(--focus-shadow);
    outline: none;
}

.dropdown-arrow[b-ve04xzrhva] {
    font-size: 0.7rem;
    color: var(--text-muted);
}

.alignment-grid-popup[b-ve04xzrhva] {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 100;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(var(--shadow-rgb), 0.15);
    padding: 0.5rem;
    margin-top: 2px;
}

.alignment-grid[b-ve04xzrhva] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
    margin-bottom: 4px;
}

.alignment-cell[b-ve04xzrhva] {
    padding: 0.5rem 0.25rem;
    border: 1px solid var(--card-border);
    border-radius: 4px;
    background: var(--card-bg);
    font-family: var(--font-body);
    font-size: 0.85rem;
    cursor: pointer;
    transition: all 0.15s ease;
    text-align: center;
    color: var(--text-color);
}

.alignment-cell:hover[b-ve04xzrhva] {
    background: var(--editor-highlight-bg);
    border-color: var(--focus-color);
}

.alignment-cell.selected[b-ve04xzrhva] {
    background: linear-gradient(135deg, var(--color-gold), var(--color-gold-dark));
    color: var(--on-primary-text);
    border-color: var(--color-gold-dark);
    font-weight: 600;
}

.alignment-cell.unaligned[b-ve04xzrhva] {
    width: 100%;
    background: var(--card-bg);
    color: var(--text-muted);
    font-style: italic;
}

.alignment-cell.unaligned:hover[b-ve04xzrhva] {
    background: var(--editor-highlight-bg);
}

.alignment-cell.unaligned.selected[b-ve04xzrhva] {
    background: linear-gradient(135deg, var(--color-secondary-dark), var(--color-secondary));
    color: var(--on-secondary-text);
}

@media (max-width: 480px) {
    .alignment-grid-popup[b-ve04xzrhva] {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 90vw;
        z-index: 200;
        right: auto;
    }
}

.inline-form-control[b-ve04xzrhva] {
    display: flex;
    width: 100%;
    justify-content: flex-start;
    gap: 1em;
    align-items: baseline;
}
/* /Features/Monsters/Sections/MonsterDefensesSection.razor.rz.scp.css */
/* Damage & Condition Grids — moved from MonsterEdit.razor.css ::deep.
   The chips themselves are <ToggleChip> (rung 2): this file and
   MonsterSkillsSection stated the same pill under three class names, with the
   selected states differing only in which gradient tokens they named. */
.damage-type-grid[b-z1adtmincf] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.condition-grid[b-z1adtmincf] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
/* /Features/Monsters/Sections/MonsterMovementSection.razor.rz.scp.css */
/* The speed fields' width is FormField's `form-group--narrow` variant now.
   This section renders no element of its own — every child is a component —
   so it has no scope id to anchor a ::deep rule to, and the old
   `.movement-speeds .form-group` selector matched only while the div was
   written here. */
/* /Features/Monsters/Sections/MonsterSkillsSection.razor.rz.scp.css */
/* Skill Grid — moved from MonsterEdit.razor.css ::deep */
.skill-grid[b-zkmurok0ig] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* The chips are <ToggleChip> (rung 2): the skills, damage and condition grids
   stated one seven-declaration pill under three names. What stays here is the
   inline bonus input this section renders inside the editing chip. */

.skill-grid .skill-bonus-inline[b-zkmurok0ig] {
    width: 38px;
    text-align: center;
    border: none;
    border-bottom: 1px solid var(--card-border);
    border-radius: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    padding: 0;
    margin: 0;
    -moz-appearance: textfield;
    appearance: textfield;
}

.skill-grid .skill-bonus-inline:focus[b-zkmurok0ig] {
    outline: none;
    border-color: transparent;
    border-bottom-color: var(--accent-color);
    box-shadow: none;
}

.skill-grid .skill-bonus-inline[b-zkmurok0ig]::-webkit-outer-spin-button,
.skill-grid .skill-bonus-inline[b-zkmurok0ig]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

@media (max-width: 480px) {
    .skill-grid .skill-bonus-inline[b-zkmurok0ig] {
        width: 48px;
    }
}
/* /Features/Monsters/Sections/MonsterSpellcastingSection.razor.rz.scp.css */
/* Spell Section Toolbar */
.spell-section .btn[b-tg9fpcp0oq] {
    display: inline-flex;
    gap: 0.4rem;
    align-items: center;
    white-space: nowrap;
}

/* the mobile .btn-label hide moved to base.css — the buttons it targets are
   rendered by SpellSlotLevelGroup, not by this section. */

/* ── Reclaimed from base.css (ladder rung 3: authored in a supplied fragment / child) ── */
/* Buttons come from SpellSlotLevelGroup / SpellRow. */
@media (max-width: 480px) {
    .spell-section[b-tg9fpcp0oq]  .btn .btn-label {
        display: none;
    }
}
/* /Features/Npcs/NpcPrintContent.razor.rz.scp.css */
.npc-print-card[b-cvt89inrr9] {
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--eprint-soft-rule, var(--card-border));
}

.npc-print-card:last-child[b-cvt89inrr9] {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

.npc-print-subtitle[b-cvt89inrr9] {
    margin: 0 0 0.5rem;
    font-style: italic;
    color: var(--eprint-label, var(--text-muted));
}
/* /Features/Parties/PartyEditor.razor.rz.scp.css */
.members-section[b-6mzba9n9m3] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.members-header[b-6mzba9n9m3] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-weight: 600;
}

.member-row[b-6mzba9n9m3] {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.4fr) minmax(0, 1fr) auto;
    gap: 0.5rem;
    align-items: center;
}

.member-remove[b-6mzba9n9m3] {
    line-height: 1;
}

/* A managed-class member has no name field (its name already shows in the
   class dropdown). The row itself drops to 3 tracks rather than either
   leaving the vacated column empty (looked like a layout bug) or letting the
   class select span it (grew far wider than its short option text needed). */
.member-row--no-name[b-6mzba9n9m3] {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
}

.party-derived-footer[b-6mzba9n9m3] {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--card-border);
}

.derived-summary[b-6mzba9n9m3] {
    font-weight: 600;
    color: var(--text-color);
}

.party-editor-error[b-6mzba9n9m3] {
    margin: 0;
    color: var(--danger-ink);
    font-size: 0.85rem;
}

@media (max-width: 600px) {
    .member-row[b-6mzba9n9m3] {
        grid-template-columns: 1fr 1fr;
    }
}
/* /Features/QuickDraft/QuickDraftPage.razor.rz.scp.css */
/* A short form page: one column capped at 900px; the TabSet's FormSection is the glass card. */
.quick-draft[b-5zsc5ts1z8] {
    max-width: 900px;
    margin: 0 auto;
    padding: 1.5rem 1rem;
}

.quick-draft h1[b-5zsc5ts1z8] {
    margin: 0 0 0.5rem;
    font-family: var(--font-header);
}

.quick-draft-intro[b-5zsc5ts1z8] {
    margin: 0 0 1.5rem;
    color: var(--text-muted);
}

@media (min-width: 769px) {
    .quick-draft[b-5zsc5ts1z8] {
        padding: 3rem 2rem;
    }
}
/* /Features/SessionZero/SessionZeroSheet.razor.rz.scp.css */
.sz-safety-tool[b-l30218ws0s] {
    margin: 0 0 0.6rem;
}

.sz-lines-veils-table[b-l30218ws0s] {
    width: 100%;
    border-collapse: collapse;
    margin-top: 0.5rem;
}

.sz-lines-veils-table th[b-l30218ws0s],
.sz-lines-veils-table td[b-l30218ws0s] {
    border: 1px solid var(--eprint-panel-border, var(--card-border));
    padding: 0.4rem;
    text-align: left;
}

.sz-lines-veils-table td[b-l30218ws0s] {
    height: 1.8rem;
}

.sz-worksheet-page[b-l30218ws0s] {
    break-before: page;
    page-break-before: always;
}

.sz-section-toggles[b-l30218ws0s] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.sz-worksheet-count[b-l30218ws0s] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.sz-worksheet-input[b-l30218ws0s] {
    width: 4rem;
}
