/* Critters Admin portal styles. */

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: #1a1a1a;
    background: #f5f5f7;
}

/* Environment banner. Non-dismissible and sticky by design: an operator with several
   tabs open must be able to tell environments apart without focusing the window, so it
   is always at the very top of the viewport regardless of scroll position. Shared between
   the Blazor portal (EnvironmentBanner.razor) and the anonymous login page, which cannot
   render the Razor component directly and instead reuses these classes on plain HTML. */
.admin-environment-banner {
    position: sticky;
    top: 0;
    z-index: 1000;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.6rem 1rem;
    font-weight: 600;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
}

.admin-environment-banner__label {
    text-transform: uppercase;
}

.admin-environment-banner__operator {
    font-weight: 400;
    opacity: 0.9;
}

.admin-environment-banner--info {
    background: #0d5ba5;
    color: #ffffff;
}

.admin-environment-banner--warning {
    background: #a86400;
    color: #ffffff;
}

.admin-environment-banner--danger {
    background: #b3141a;
    color: #ffffff;
    border-bottom: 4px solid #7a0d11;
}

/* Portal shell */
.admin-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.admin-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
    background: #ffffff;
    border-bottom: 1px solid #d9d9df;
}

.admin-nav__brand {
    font-weight: 700;
}

.admin-nav__signout {
    margin: 0;
}

.admin-nav__signout button {
    padding: 0.4rem 0.9rem;
    border: 1px solid #b3141a;
    border-radius: 4px;
    background: #ffffff;
    color: #b3141a;
    font-weight: 600;
    cursor: pointer;
}

.admin-nav__signout button:hover {
    background: #b3141a;
    color: #ffffff;
}

.admin-content {
    flex: 1;
    padding: 1rem;
}

/* Interaction definitions list/detail (quest/dialogue editor plumbing proof page) */
.admin-table {
    border-collapse: collapse;
    width: 100%;
}

.admin-table th,
.admin-table td {
    text-align: left;
    padding: 0.4rem 0.75rem;
    border-bottom: 1px solid #d9d9df;
}

.admin-error {
    color: #7a0d11;
    background: #fbe4e4;
    border: 1px solid #b3141a;
    border-radius: 4px;
    padding: 0.6rem 0.8rem;
}

.admin-validate-ok {
    color: #0a5c1f;
    background: #e5f6e9;
    border: 1px solid #1f8a3d;
    border-radius: 4px;
    padding: 0.6rem 0.8rem;
}

/* Login page (plain HTML, served outside the Blazor circuit) */
.admin-login-shell {
    display: flex;
    justify-content: center;
    padding: 2rem 1rem;
}

.admin-login-card {
    width: 100%;
    max-width: 360px;
    background: #ffffff;
    border: 1px solid #d9d9df;
    border-radius: 8px;
    padding: 1.5rem;
}

.admin-login-card h1 {
    font-size: 1.25rem;
    margin-top: 0;
}

.admin-login-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin-bottom: 1rem;
}

.admin-login-field input {
    padding: 0.6rem;
    font-size: 1rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

.admin-login-submit {
    width: 100%;
    padding: 0.7rem;
    font-size: 1rem;
    font-weight: 600;
    border: none;
    border-radius: 4px;
    background: #0d5ba5;
    color: #ffffff;
    cursor: pointer;
}

.admin-login-error {
    background: #fbe4e4;
    color: #7a0d11;
    border: 1px solid #b3141a;
    border-radius: 4px;
    padding: 0.6rem 0.8rem;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

/* Quest/dialogue condition tree editor (Docs/CritterAdmin/Quest-Editor-Plan.md §1). The tree is
   read as an outline of boolean logic, not a form - every nesting level gets its own left rule so
   an author can tell at a glance which group a leaf belongs to, no matter how deep. */

.admin-detail-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

.admin-summary {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 0.75rem;
    row-gap: 0.15rem;
    max-width: 32rem;
}

.admin-summary dt {
    font-weight: 600;
    color: #55555f;
}

.admin-summary dd {
    margin: 0;
    /* The content hash is a 64-character unbroken hex string - without this, its <code> forces
       the grid's 1fr column past the viewport at narrow widths (a grid track still sizes to its
       content's min-content width by default, unbroken text having a very wide one). */
    min-width: 0;
    overflow-wrap: anywhere;
}

.admin-dirty-badge {
    display: inline-block;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    background: #a86400;
    color: #ffffff;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.admin-step-picker {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 1rem 0;
}

.admin-step-picker label {
    font-weight: 600;
}

.step-picker-select {
    flex: 1;
    max-width: 28rem;
    padding: 0.4rem 0.5rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
    font-size: 0.95rem;
}

.cond-section {
    margin: 1.5rem 0;
}

.cond-section h2 {
    margin-bottom: 0.2rem;
}

.cond-section-hint {
    margin-top: 0;
    color: #55555f;
    font-size: 0.85rem;
}

/* One visual language for every level: a badge for what kind of node this is, a left rule that
   deepens with nesting, and a hint of what the badge means. Combinator groups and the page's own
   Prerequisites/Requirement roots share these classes so indentation reads consistently from the
   very top of the tree. */
.cond-group {
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #ffffff;
    margin: 0.6rem 0;
}

.cond-group-root {
    border-style: dashed;
}

.cond-group-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    background: #f0f0f4;
    border-bottom: 1px solid #d9d9df;
    border-radius: 6px 6px 0 0;
}

.cond-children {
    padding: 0.6rem 0.7rem 0.6rem 1rem;
    margin-left: 0.6rem;
    border-left: 3px solid #c7c7d1;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.cond-node {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #fbfbfd;
}

.cond-badge {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 4px;
    background: #0d5ba5;
    color: #ffffff;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
}

.cond-badge-not {
    background: #7a3d9c;
}

.cond-badge-unknown {
    background: #6b6b76;
}

.cond-combinator-select {
    padding: 0.15rem 0.4rem;
    border-radius: 4px;
    border: 1px solid #0d5ba5;
    background: #0d5ba5;
    color: #ffffff;
    font-weight: 700;
    font-size: 0.8rem;
    text-transform: uppercase;
}

.cond-group-hint {
    color: #55555f;
    font-size: 0.85rem;
}

.cond-leaf-fields {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.cond-remove {
    margin-left: auto;
    width: 1.6rem;
    height: 1.6rem;
    line-height: 1.4rem;
    padding: 0;
    border: 1px solid #b3141a;
    border-radius: 50%;
    background: #ffffff;
    color: #b3141a;
    font-weight: 700;
    cursor: pointer;
    flex-shrink: 0;
}

.cond-remove:hover {
    background: #b3141a;
    color: #ffffff;
}

.cond-empty {
    color: #77777f;
    font-style: italic;
    padding: 0.3rem 0;
}

.cond-add {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.cond-add-select {
    padding: 0.35rem 0.5rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

.cond-add-hint {
    color: #77777f;
    font-size: 0.8rem;
    font-style: italic;
}

.cond-unknown {
    background: #fff8e5;
    border-color: #a86400;
}

.cond-unknown-text {
    color: #6b4c00;
    font-size: 0.9rem;
}

.cond-nofrom {
    color: #6b4c00;
    font-size: 0.9rem;
    font-style: italic;
}

.leaf-label {
    font-weight: 600;
    color: #55555f;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* Every typed leaf form's own input/select (e.g. InvokeNpcConditionCheckForm's condition-key
   dropdown) uses this class. Unconstrained, a <select> sizes to its widest <option> - some
   interop keys are long enough to push the condition tree past the viewport at narrow widths. */
.leaf-field {
    min-width: 0;
    max-width: 100%;
}

/* Shared by every typed leaf form's own field rows - conditions (QuestCooldownConditionForm and
   others) already used these class names before any of them existed here. */
.leaf-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.3rem 0;
}

.leaf-checkbox {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.9rem;
    cursor: pointer;
}

.leaf-hint {
    color: #77777f;
    font-size: 0.8rem;
    font-style: italic;
}

.leaf-unit {
    color: #55555f;
    font-size: 0.85rem;
}

/* RolledRange editor */
.range-editor {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.range-mode {
    padding: 0.3rem 0.4rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

.range-num {
    width: 6rem;
    padding: 0.3rem 0.4rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

.range-sep {
    color: #55555f;
}

.range-rollkey {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.range-rollkey label {
    color: #55555f;
    font-size: 0.8rem;
}

.range-key {
    width: 9rem;
    padding: 0.3rem 0.4rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

/* Requirements (Requirement.Condition plus Requirement.TaskDescription). Distinct from the
   Prerequisites root list because each row is a wrapper object, not a bare condition - it carries
   its own player-facing text and its own add/remove control. */
.cond-requirement {
    border: 1px solid #d9d9df;
    border-radius: 6px;
    padding: 0.6rem 0.7rem;
    margin: 0.6rem 0;
    background: #ffffff;
}

.cond-requirement-desc-field {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin-bottom: 0.6rem;
}

.cond-requirement-desc-hint {
    color: #77777f;
    font-size: 0.8rem;
    font-style: italic;
}

.cond-requirement-desc-input {
    width: 100%;
    max-width: 32rem;
    padding: 0.4rem 0.5rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
}

.cond-requirement-remove-btn {
    padding: 0.4rem 0.8rem;
    border: 1px solid #b3141a;
    border-radius: 4px;
    background: #ffffff;
    color: #b3141a;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
}

.cond-requirement-remove-btn:hover {
    background: #b3141a;
    color: #ffffff;
}

/* Publish / validate actions */
.admin-actions {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: 1rem 0;
}

.admin-btn {
    padding: 0.5rem 1rem;
    border: 1px solid #55555f;
    border-radius: 4px;
    background: #ffffff;
    color: #1a1a1a;
    font-weight: 600;
    cursor: pointer;
}

.admin-btn:hover {
    background: #ececf0;
}

.admin-btn-primary {
    border-color: #0d5ba5;
    background: #0d5ba5;
    color: #ffffff;
}

.admin-btn-primary:hover {
    background: #0a4a87;
}

.admin-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.admin-error-list {
    margin: 0.4rem 0;
    padding-left: 1.5rem;
}

.admin-conflict {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0.6rem 0;
}

/* Read-only JSON view. Never an editable control - <pre> holds text, not a <textarea>. */
.admin-json-view {
    margin: 1.5rem 0;
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #ffffff;
}

.admin-json-view summary {
    cursor: pointer;
    padding: 0.6rem 0.8rem;
    font-weight: 600;
}

.admin-json-pre {
    margin: 0;
    padding: 0.8rem;
    border-top: 1px solid #d9d9df;
    background: #f5f5f7;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    font-size: 0.8rem;
    overflow-x: auto;
    max-width: 100%;
}

/* Pass 2a: per-Step fields and Replies (Docs/CritterAdmin/Quest-Editor-Plan.md §2). Reuses
   leaf-label/cond-empty/cond-remove/admin-btn from the Pass 1 condition editor above so both
   sections read as one visual language rather than two different editors bolted together. */

.step-fields {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    max-width: 40rem;
}

.step-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.step-field-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
}

.step-field-hint {
    margin: 0;
    color: #77777f;
    font-size: 0.8rem;
    font-style: italic;
}

.step-checkbox {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
}

.reply-field-input {
    padding: 0.4rem 0.5rem;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
    font-size: 0.9rem;
    min-width: 0;
    max-width: 100%;
}

.reply-field-wide {
    width: 100%;
    max-width: 32rem;
}

.dialogue-pool {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    max-width: 32rem;
}

.dialogue-pool-row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.dialogue-pool-input {
    flex: 1;
    min-width: 0;
}

/* Replies (Step.Replies) - the core value of Pass 2a: an interop-heavy NPC like
   WorldPizzaOrganization has nothing else worth looking at on its Step, so these cards are what
   finally explains why the Step exists. */
.reply-list {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
}

.reply-card {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #ffffff;
    padding: 0.8rem 0.9rem;
}

.reply-card-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 0.5rem;
}

.reply-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    min-width: 0;
}

.reply-field-id-input {
    width: 6rem;
}

.reply-field-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
}

.reply-returns-entry {
    align-self: center;
}

.reply-linkaction {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.reply-lint-warning {
    margin: 0;
    padding: 0.5rem 0.7rem;
    background: #fff8e5;
    border: 1px solid #a86400;
    border-radius: 4px;
    color: #6b4c00;
    font-size: 0.85rem;
}

/* Document-level fields (Docs/CritterAdmin/Quest-Editor-Research.md §1) - Title/Description/
   ImagePath, the four dialogue pools, and the Repeatable/optional-step-count controls. Reuses
   step-field/step-field-row/step-field-hint/step-checkbox/reply-field-input/reply-field-wide/
   leaf-label from the Pass 2a Step editor above so the two "fields on a thing" sections read as
   one visual language; only the layout wrappers below (doc-*) are new. */
.doc-mode-note {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 1rem;
}

.admin-mode-badge {
    display: inline-block;
    padding: 0.2rem 0.55rem;
    border-radius: 4px;
    background: #ececf0;
    color: #1a1a1a;
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.admin-mode-hint {
    color: #55555f;
    font-size: 0.85rem;
}

.doc-fields {
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    max-width: 40rem;
    margin-bottom: 1.2rem;
}

.doc-field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.doc-field-error {
    margin: 0;
    padding: 0.3rem 0.6rem;
    font-size: 0.8rem;
}

.doc-description-input {
    min-height: 4.5rem;
    font-family: inherit;
    resize: vertical;
}

.doc-pools {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-bottom: 1.2rem;
}

.doc-pool {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.doc-offer-controls {
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    max-width: 40rem;
}

/* Pass 2b: effect editing (Docs/CritterAdmin/Quest-Editor-Plan.md §2) - Step.Rewards and a
   StepReply's own Effects. Effects are a flat list, never nested, so this reuses the Pass 1
   cond-node/cond-badge/cond-add/cond-remove classes directly rather than defining a parallel set -
   a Reward and a condition read as the same visual language. */
.effect-list {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.imperative-editor {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    flex: 1;
}

.imperative-field-input,
.imperative-datemath-input {
    min-width: 16rem;
}

.range-shared-hint {
    color: #0d5ba5;
    font-size: 0.8rem;
    font-style: italic;
}

/* Pass 3: dialogue flow graph (Docs/CritterAdmin/Quest-Editor-Plan.md §3), rendered by Mermaid
   (DialogueGraphView.razor / MermaidDialogueGraphSource.cs) - Mermaid owns the SVG it produces
   internally, so there is no per-node/per-edge CSS here. The scroll wrapper is the overflow
   boundary: the rendered SVG is never shrunk, so a wide diagram scrolls inside this box exactly
   the way admin-json-pre already scrolls wide JSON, instead of ever pushing the page's own width. */
.dg-graph-scroll {
    overflow-x: auto;
    max-width: 100%;
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #fbfbfd;
    margin-bottom: 0.75rem;
    padding: 0.5rem;
}

.dg-mermaid-container svg {
    display: block;
}

.dg-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.9rem;
    margin-bottom: 1.2rem;
    font-size: 0.8rem;
    color: #55555f;
}

.dg-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

/* Colors are set inline from MermaidDialogueGraphSource's constants (DialogueGraphView.razor) so
   the legend can never drift from what Mermaid's own linkStyle output actually draws. */
.dg-legend-swatch {
    display: inline-block;
    width: 1.4rem;
    height: 0;
    border-top-width: 3px;
    border-top-style: solid;
}

.dg-legend-dotted { border-top-style: dotted; }
.dg-legend-dashed { border-top-style: dashed; }

/* Quest-mode Steps are an unordered set with no edges (Docs/CritterAdmin/
   Quest-Editor-Research.md §1.1) - a scrollable compact list/board, not a canvas. Pappy Snacky (33
   Steps) is the real-content stress test for this view; the fixed max-height keeps it from
   dominating the page the way 33 full-size cards would. */
.item-picker {
    position: relative;
    display: inline-block;
    min-width: 18rem;
    max-width: 100%;
}

.item-picker-input {
    width: 100%;
}

.item-picker-results {
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    margin: 0.15rem 0 0;
    padding: 0;
    list-style: none;
    max-height: 16rem;
    overflow-y: auto;
    background: #ffffff;
    border: 1px solid #b3b3bb;
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}

.item-picker-option {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.35rem 0.6rem;
    cursor: pointer;
}

.item-picker-option:hover {
    background: #eaf3fb;
}

.item-picker-option-id {
    color: #8a8a94;
    font-size: 0.78rem;
    flex-shrink: 0;
}

.item-picker-more {
    padding: 0.35rem 0.6rem;
    color: #55555f;
    font-size: 0.8rem;
    font-style: italic;
}

.editor-split {
    display: grid;
    grid-template-columns: minmax(260px, 360px) minmax(0, 1fr);
    gap: 1.2rem;
    align-items: start;
}

/* The flow list pins below the sticky environment banner (~2.6rem tall) and scrolls internally,
   so it stays beside the editor no matter how long either the variant list or the editor gets. */
.editor-split-nav {
    position: sticky;
    top: 3rem;
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
}

.editor-split-detail {
    min-width: 0;
}

@media (max-width: 820px) {
    .editor-split {
        grid-template-columns: 1fr;
    }

    .editor-split-nav {
        position: static;
        max-height: none;
        overflow-y: visible;
    }
}

.qm-group {
    border: 1px solid #d9d9df;
    border-radius: 6px;
    background: #fbfbfd;
    margin-bottom: 0.8rem;
    overflow: hidden;
}

.qm-group-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2rem 0.6rem;
    padding: 0.5rem 0.7rem;
    background: #ececf0;
    border-bottom: 1px solid #d9d9df;
}

.qm-group-title {
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: 0.78rem;
}

.qm-group-meta {
    color: #55555f;
    font-size: 0.8rem;
}

.qm-group-hint {
    margin: 0;
    padding: 0.4rem 0.7rem;
    color: #55555f;
    font-size: 0.8rem;
    font-style: italic;
    border-bottom: 1px solid #ececf0;
}

.qm-inert {
    color: #7a4a00;
}

.qm-warning {
    padding: 0.5rem 0.7rem;
    margin-bottom: 0.8rem;
    border-radius: 6px;
    color: #7a0d11;
    background: #fbe4e4;
    border: 1px solid #b3141a;
    font-size: 0.85rem;
}

.qm-group .qm-row:last-child {
    border-bottom: none;
}

.effect-direction {
    flex-shrink: 0;
    font-size: 0.72rem;
    padding: 0.1rem 0.45rem;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.effect-direction-gain {
    background: #e5f6e9;
    color: #0a5c1f;
}

.effect-direction-cost {
    background: #fbe4e4;
    color: #7a0d11;
}

.effect-direction-sideeffect {
    background: #ececf0;
    color: #55555f;
}

.qm-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.7rem;
    border-bottom: 1px solid #ececf0;
    cursor: pointer;
}

.qm-row:last-child {
    border-bottom: none;
}

.qm-row:hover {
    background: #ececf0;
}

.qm-row-selected {
    background: #eaf3fb;
}

.qm-row-id {
    font-weight: 700;
    flex-shrink: 0;
}

.qm-row-summary {
    color: #55555f;
    font-size: 0.85rem;
    flex: 1;
    min-width: 0;
}


/* Mobile: moderators triage from phones, so the nav stacks and touch targets stay large. */
@media (max-width: 600px) {
    .admin-environment-banner {
        font-size: 0.85rem;
        padding: 0.5rem 0.75rem;
    }

    .admin-nav {
        flex-direction: column;
        align-items: stretch;
    }

    .admin-nav__signout button {
        width: 100%;
        padding: 0.6rem;
    }

    .admin-content {
        padding: 0.75rem;
    }

    /* Deep trees are the whole point of this editor, so indentation must shrink rather than
       disappear - the left rule per level stays as the "which group am I in" cue at any width,
       it just costs fewer pixels per level. */
    .cond-children {
        margin-left: 0.3rem;
        padding: 0.5rem 0.4rem 0.5rem 0.6rem;
    }

    .cond-node,
    .cond-group-head {
        padding: 0.45rem 0.5rem;
    }

    .cond-remove {
        margin-left: 0;
    }

    .admin-summary {
        grid-template-columns: 1fr;
    }

    .admin-summary dt {
        margin-top: 0.3rem;
    }

    .step-picker-select {
        max-width: 100%;
    }

    .admin-step-picker {
        flex-direction: column;
        align-items: stretch;
    }

    .admin-btn {
        width: 100%;
    }

    .range-num {
        width: 4.5rem;
    }

    .range-key {
        width: 100%;
    }

    .reply-field-wide,
    .step-fields,
    .doc-fields,
    .doc-offer-controls {
        max-width: 100%;
    }

    .imperative-field-input,
    .imperative-datemath-input {
        min-width: 0;
        width: 100%;
    }

    .reply-card-head {
        flex-wrap: wrap;
    }

    .reply-field-id-input {
        width: 100%;
    }

    /* The SVG itself never shrinks (dg-graph-scroll's own overflow-x:auto is what keeps it off
       the page at any width) - only the legend below it, a plain flex row, needs to wrap tighter. */
    .dg-legend {
        gap: 0.5rem 0.8rem;
    }

    .qm-row {
        flex-wrap: wrap;
    }
}

/* User directory row badges (Dev / Inactive) - small pills next to the username, same shape as
   admin-mode-badge/cond-badge but colored to read as status rather than a category label. */
.user-badge {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.45rem;
    border-radius: 4px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.user-badge-dev {
    background: #0d5ba5;
    color: #ffffff;
}

.user-badge-inactive {
    background: #ececf0;
    color: #55555f;
}

/* Wraps the user detail page's Privileges & Economy (mints Cash, flips Active/Dev) and Reset
   Password sections - the same amber caution tone as cond-unknown/reply-lint-warning, so these
   read as deliberate, powerful actions rather than ordinary profile fields. */
.admin-danger-section {
    border: 1px solid #a86400;
    border-radius: 6px;
    background: #fff8e5;
    padding: 0.8rem 1rem 0.2rem;
}

.admin-danger-section h2 {
    color: #6b4c00;
}
