, [provsql]" */
.wp-config__sp { display: flex; align-items: stretch; gap: 0.3rem; }
.wp-config__sp-input {
flex: 1 1 auto;
font-family: var(--font-mono);
font-size: 0.82rem;
color: var(--purple-700);
border: 1px solid var(--border-soft);
border-radius: 4px;
padding: 0.2rem 0.4rem;
min-width: 0;
}
.wp-config__sp-input:focus {
outline: 2px solid var(--gold-500);
outline-offset: 1px;
}
.wp-config__sp-suffix {
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: rgba(107, 79, 160, 0.12);
color: var(--purple-700);
border-radius: 4px;
padding: 0 0.5rem;
font-family: var(--font-mono);
font-size: 0.78rem;
white-space: nowrap;
}
.wp-config__sp-suffix i { font-size: 0.78em; opacity: 0.75; }
/* The Active switch reuses the same SVG-free pill we ship for the form
toggles; copy the relevant rules so it doesn't depend on .wp-toggle. */
.wp-config__switch {
appearance: none; -webkit-appearance: none;
position: relative;
width: 30px; height: 16px;
border-radius: 999px;
background: var(--border-soft);
border: 1px solid var(--border-soft);
cursor: pointer;
margin: 0;
flex-shrink: 0;
transition: background 0.15s, border-color 0.15s;
}
.wp-config__switch::before {
content: "";
position: absolute;
top: 1px; left: 1px;
width: 12px; height: 12px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 2px rgba(42, 24, 80, 0.25);
transition: left 0.15s;
}
.wp-config__switch:checked {
background: var(--purple-500);
border-color: var(--purple-500);
}
.wp-config__switch:checked::before { left: 15px; }
.wp-config__status {
margin: 0.5rem 0 0;
font-family: var(--font-ui);
font-size: 0.72rem;
color: var(--fg-muted);
}
.wp-config__status.is-error { color: var(--terracotta-500); }
/* ───────── error block (rendered into the result area) ───────── */
/* Errors get a distinctly deeper red than warnings (which use terracotta).
Stronger background tint + crimson border + dark-red text so the block
reads as a stop sign, not just a warmer warning. */
.wp-error {
border: 1px solid #B00020;
border-left: 3px solid #B00020;
background: rgba(176, 0, 32, 0.12);
color: #5A0010;
padding: 0.6rem 0.85rem;
border-radius: 4px;
font-family: var(--font-ui);
font-size: 0.85rem;
margin: 0.4rem 0;
white-space: pre-wrap;
}
.wp-error i { color: #B00020; margin-right: 0.4rem; }
.wp-error code { background: rgba(176, 0, 32, 0.10); color: #5A0010; }
.wp-error code { background: var(--bg-code); }
/* Informational banner: shown when the wrap is silently dropped because
the user's query touches no provenance-tracked relation, plus the
per-NOTICE feed forwarded from psycopg's notice handler.
white-space: pre-wrap preserves embedded newlines that PostgreSQL
uses to format multi-line diagnostics (DETAIL / HINT / context lines). */
.wp-notice {
border: 1px solid var(--gold-500);
border-left: 3px solid var(--gold-500);
background: rgba(232, 184, 75, 0.12);
color: var(--purple-900);
padding: 0.6rem 0.85rem;
border-radius: 4px;
font-family: var(--font-ui);
font-size: 0.85rem;
margin: 0.4rem 0;
white-space: pre-wrap;
}
.wp-notice i { color: var(--gold-700, #B8901E); margin-right: 0.4rem; }
/* Server WARNING (e.g. provsql_warning): orange/terracotta accent. */
.wp-warning {
border: 1px solid var(--terracotta-500);
border-left: 3px solid var(--terracotta-500);
background: rgba(196, 102, 74, 0.08);
color: var(--purple-900);
padding: 0.6rem 0.85rem;
border-radius: 4px;
font-family: var(--font-ui);
font-size: 0.85rem;
margin: 0.4rem 0;
white-space: pre-wrap;
}
.wp-warning i { color: var(--terracotta-500); margin-right: 0.4rem; }
/* Collapsible variant for long diagnostics (parse-tree dumps from
provsql.verbose_level >= 50, full pre/post-rewrite SQL at >= 20). The
summary line keeps the same coloured-banner styling as the parent
.wp-notice / .wp-warning / .wp-error rules; only the disclosure
triangle and the expanded body need bespoke styling. */
.wp-diag--collapsible > summary {
cursor: pointer;
list-style-position: outside;
/* The parent has white-space: pre-wrap so embedded newlines don't
leak from the head line into the summary. */
}
.wp-diag--collapsible > summary:hover { filter: brightness(0.97); }
.wp-diag__body {
margin-top: 0.5rem;
padding-top: 0.5rem;
border-top: 1px dashed currentColor;
opacity: 0.85;
font-family: var(--font-mono);
font-size: 0.78rem;
white-space: pre-wrap;
max-height: 24rem;
overflow: auto;
}
/* Source badge for messages that the C extension emits with the
"ProvSQL: " prefix. Renders as a small purple pill so the origin
is readable at a glance and the prefix doesn't have to clutter the
message text inline. */
.wp-srcbadge {
display: inline-block;
font-family: var(--font-display);
font-style: italic;
font-weight: 600;
font-size: 0.72rem;
letter-spacing: 0.02em;
background: var(--purple-500);
color: #fff;
padding: 0.05rem 0.5rem;
border-radius: 999px;
margin-right: 0.35rem;
vertical-align: 1px;
}
#result-banners:not(:empty) { margin: 0.4rem 0 0.6rem; }
/* ───────── shared site footer (mirrors website + docs) ───────── */
#provsql-site-footer {
position: relative;
text-align: center;
padding: 0.8em 1em;
background: var(--purple-900);
border-top: 2px solid var(--gold-500);
font-family: var(--font-ui);
font-size: 0.85rem;
}
#provsql-site-footer a {
color: rgba(244,240,250,0.85);
text-decoration: none;
}
#provsql-site-footer a:hover { color: var(--gold-500); }
#provsql-site-footer a:visited { color: rgba(244,240,250,0.85); }
#provsql-site-footer .sep {
margin: 0 0.4em;
color: rgba(244,240,250,0.4);
}
#provsql-site-footer .versions {
position: absolute;
right: 1em;
top: 50%;
transform: translateY(-50%);
font-size: 0.75rem;
color: rgba(244,240,250,0.45);
letter-spacing: 0.01em;
}
#provsql-site-footer .versions span:not(:empty) + span:not(:empty)::before {
content: " · ";
color: rgba(244,240,250,0.3);
}
/* "No database picked at launch" banner : wedged between the nav and
the wp-shell grid so it can't be missed but doesn't shift the page
below it once dismissed. */
.wp-db-hint {
margin: 0; padding: 0.6rem 1.5rem;
font-family: var(--font-ui); font-size: 0.85rem;
background: rgba(232, 184, 75, 0.18);
border-bottom: 1px solid var(--gold-500);
color: var(--purple-900);
/* Right-align so the "Pick a database…" button ends up under the
top-right database switcher chip : short visual line of travel
from the prompt to the dropdown. */
text-align: right;
}
.wp-db-hint i { color: var(--gold-700); margin-right: 0.4rem; }
.wp-db-hint code {
font-family: var(--font-mono); font-size: 0.82em;
padding: 0.05rem 0.3rem; background: rgba(0,0,0,0.05);
border-radius: 3px;
}
.wp-db-hint__btn {
margin-left: 0.5rem;
padding: 0.15rem 0.6rem;
border: 1px solid var(--gold-700);
background: #fff;
color: var(--purple-900);
font-family: var(--font-ui); font-size: 0.82rem; font-weight: 600;
border-radius: 4px;
cursor: pointer;
}
.wp-db-hint__btn:hover {
background: var(--gold-500); color: var(--purple-900);
}
/* ───────── shell ───────── */
.wp-shell {
display: grid;
grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
gap: 1.5rem;
/* No outer max-width: on wide screens the schema/result panes get
more horizontal room (more columns visible, less wrapping). The
internal column ratio still keeps the sidebar:main proportions
comfortable; the page padding prevents content from hugging the
viewport edges. */
margin: 0 auto;
padding: 1.5rem;
align-items: start; /* allow the sidebar to be shorter than the result card */
}
@media (max-width: 1080px) {
.wp-shell { grid-template-columns: 1fr; }
}
/* In where mode, pin the source-relations sidebar to the viewport so its
highlighted (terracotta) cells are always visible regardless of how far
the user has scrolled the result table. The sidebar gets its own scroll
pane so its content (potentially many relations) is reachable without
moving the result. The sticky offset clears the sticky nav. */
body.mode-where #sidebar {
position: sticky;
top: 5rem;
max-height: calc(100vh - 6rem);
overflow-y: auto;
}
@media (max-width: 1080px) {
/* Single-column layout: sticky would overlap the result, so disable. */
body.mode-where #sidebar { position: static; max-height: none; }
}
/* ───────── card ───────── */
.wp-card {
background: var(--bg-elevated);
border: 1px solid var(--border-soft);
border-radius: 6px;
padding: 1.75rem 1.75rem 1.5rem;
}
.wp-card__hdr { margin-bottom: 1.25rem; }
.wp-card__title {
font-family: var(--font-display);
font-style: italic;
font-weight: 600;
font-size: 2rem;
margin: 0 0 0.35rem;
color: var(--purple-900);
border-bottom: 2px solid var(--gold-500);
padding-bottom: 0.2em;
display: inline-block;
}
/* Live search_path readout: keeps the user oriented when they're typing
unqualified relation names. Reuses the lead's code chip styling so
schema names render the same as inline-code elsewhere. */
.wp-card__searchpath {
margin: 0.3rem 0 0;
font-size: 0.78rem;
color: var(--fg-muted);
}
.wp-card__searchpath code {
font-family: var(--font-mono);
background: var(--bg-code);
padding: 1px 5px;
border-radius: 3px;
font-size: 0.95em;
color: var(--purple-700);
}
/* Locked-chip rendering for the `provsql` segment of search_path: a
small purple-tinted pill with a lock glyph, to indicate Studio
enforces this entry regardless of the user's configuration. */
.wp-card__sp-locked {
display: inline-flex;
align-items: center;
gap: 0.25rem;
background: rgba(107, 79, 160, 0.12);
color: var(--purple-700);
border-radius: 3px;
padding: 0 6px;
font-size: 0.95em;
}
.wp-card__sp-locked i { font-size: 0.78em; opacity: 0.75; }
/* "Input gates only" toggle at the top of the where-mode sidebar :
filters out provenance-tracked relations whose first row's provsql
token is not an input leaf. */
.wp-rel-filter {
margin: 0 0 0.6rem;
font-family: var(--font-ui);
font-size: 0.75rem;
color: var(--fg-muted);
}
.wp-rel-filter__label {
display: inline-flex;
align-items: center;
gap: 0.35rem;
cursor: pointer;
}
.wp-rel-filter__hint {
color: var(--purple-700);
font-style: italic;
}
/* Relation quick-nav chips at the top of the where-mode sidebar. */
.wp-rel-nav {
display: flex; flex-wrap: wrap; gap: 0.3rem;
margin: 0 0 0.6rem;
padding-bottom: 0.6rem;
border-bottom: 1px dashed var(--border-soft);
}
.wp-rel-nav__btn {
font-family: var(--font-mono);
font-size: 0.75rem;
background: var(--bg-code);
color: var(--purple-700);
border: 1px solid transparent;
padding: 0.18rem 0.55rem;
border-radius: 999px;
cursor: pointer;
transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.wp-rel-nav__btn:hover {
background: var(--purple-500);
color: #fff;
border-color: var(--purple-500);
}
/* ───────── relation block (left) ───────── */
.wp-relation { margin-top: 1.25rem; }
/* Quick-nav targets land on the header (table name + tuple count) rather
than on the section's outer box (which would otherwise put the first
tuple at the visible top because the section's margin-top sits above
the header). scroll-margin-top adds a small breathing gap. */
.wp-relation__hdr { scroll-margin-top: 0.6rem; }
.wp-relation__hdr {
display: flex; align-items: baseline; justify-content: space-between;
border-bottom: 1px solid var(--border-soft);
padding-bottom: 0.4rem;
margin-bottom: 0.5rem;
}
.wp-relation__name {
font-family: var(--font-mono);
font-size: 1.05rem;
font-weight: 500;
margin: 0;
color: var(--purple-700);
}
.wp-relation__meta {
font-family: var(--font-ui);
font-size: 0.76rem;
color: var(--fg-muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.wp-relation__meta code { font-size: 0.95em; color: var(--purple-700); }
/* ───────── tables ───────── */
.wp-table-wrap {
background: var(--bg-canvas);
border: 1px solid var(--border-soft);
border-radius: 4px;
overflow: auto;
}
.wp-table {
width: 100%;
border-collapse: collapse;
font-family: var(--font-ui);
font-size: 0.88rem;
}
.wp-table th, .wp-table td {
padding: 0.5rem 0.75rem;
text-align: left;
border-bottom: 1px solid var(--border-soft);
vertical-align: middle;
}
.wp-table th {
background: var(--bg-elevated);
font-weight: 600;
font-size: 0.74rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--purple-700);
border-bottom: 1px solid var(--border-soft);
position: sticky; top: 0;
}
.wp-table tbody tr:nth-child(even) td { background: rgba(214, 204, 240, 0.18); }
.wp-table tbody tr:hover td { background: rgba(232, 184, 75, 0.12); }
.wp-table tbody tr:last-child td { border-bottom: none; }
/* Right-align numeric and date/time/interval columns. Tabular-nums keeps
digit columns aligned across rows. */
.wp-table th.is-right, .wp-table td.is-right { text-align: right; font-variant-numeric: tabular-nums; }
/* Multi-line text cells (provsql.view_circuit dump, anything with
embedded newlines) : monospaced, whitespace preserved, horizontal
scrollbar on long lines so wide ASCII trees stay legible. The
max-width caps the cell so the rest of the row stays usable. */
.wp-cell-pre {
margin: 0;
font-family: var(--font-mono);
font-size: 0.78rem;
white-space: pre;
max-width: 80ch;
max-height: 24rem;
overflow: auto;
line-height: 1.35;
scrollbar-width: thin;
}
.wp-cell-pre::-webkit-scrollbar { width: 6px; height: 6px; }
.wp-cell-pre::-webkit-scrollbar-thumb { background: var(--border-soft); border-radius: 3px; }
/* Sidebar relation tables: more compact than the result table on the right
so several relations fit at a glance. */
#sidebar .wp-relation { margin-top: 0.85rem; }
#sidebar .wp-relation__hdr { padding-bottom: 0.25rem; margin-bottom: 0.3rem; }
#sidebar .wp-relation__name { font-size: 0.92rem; }
#sidebar .wp-relation__meta { font-size: 0.68rem; }
#sidebar .wp-table { font-size: 0.78rem; }
#sidebar .wp-table th, #sidebar .wp-table td { padding: 0.25rem 0.5rem; }
#sidebar .wp-table th { font-size: 0.66rem; }
/* highlighted cells (where-provenance source).
The toggled state must not change layout metrics (font-weight, padding,
border) or the column widths reflow as the user moves the mouse; keep
only colour + box-shadow (which is outside the box model). */
.wp-table td.is-source {
color: #fff !important;
background: var(--terracotta-500) !important;
box-shadow: inset 0 0 0 2px var(--purple-900);
transition: background 0.12s, color 0.12s;
}
/* hovered result cell mirror */
.wp-table--result td.is-hover {
background: var(--gold-500) !important;
color: var(--purple-900) !important;
}
/* ───────── buttons ───────── */
.wp-btn {
font-family: var(--font-ui);
font-size: 0.85rem;
font-weight: 500;
border: 1px solid var(--purple-500);
background: transparent;
color: var(--purple-500);
padding: 0.4rem 0.8rem;
border-radius: 4px;
cursor: pointer;
transition: background 0.15s, color 0.15s;
display: inline-flex; align-items: center; gap: 0.4rem;
}
.wp-btn:hover { background: var(--purple-500); color: #fff; }
.wp-btn[hidden] { display: none; }
/* Send and Cancel share the slot in the form action bar; pin them to the
same width and center their content so swapping one for the other
doesn't shift the rest of the row. The cancel button is .wp-btn--ghost
for its colour palette but inherits the primary's box (font-size,
padding, weight) so the row height stays put. */
#run-btn, #cancel-btn { min-width: 9.5rem; justify-content: center; }
#cancel-btn {
font-size: 0.85rem;
font-weight: 600;
padding: 0.55rem 1.1rem;
background: var(--terracotta-500);
border-color: var(--terracotta-500);
color: var(--fg-on-dark);
}
#cancel-btn:hover {
background: var(--terracotta-500);
border-color: var(--terracotta-500);
color: var(--fg-on-dark);
filter: brightness(0.9);
}
.wp-btn--primary {
background: var(--gold-500);
border-color: var(--gold-500);
color: var(--purple-900);
font-weight: 600;
padding: 0.55rem 1.1rem;
}
.wp-btn--primary:hover { background: var(--gold-700); border-color: var(--gold-700); color: var(--purple-900); }
.wp-btn--ghost {
background: transparent;
border-color: var(--border-soft);
color: var(--purple-700);
font-size: 0.78rem;
padding: 0.32rem 0.65rem;
}
.wp-btn--ghost:hover { background: var(--bg-code); color: var(--purple-700); border-color: var(--purple-500); }
.wp-btn--ghost[aria-expanded="true"] { background: var(--bg-code); border-color: var(--purple-500); }
/* Past-queries dropdown : pinned to the History button. */
.wp-history { position: relative; display: inline-flex; }
.wp-history__menu {
position: absolute;
/* Open downward over the result section so the menu is always anchored
against the viewport top (where the History button sits): an upward
menu of 60vh would push its top above the viewport when the form is
near the top of the window, hiding the upper entries even though
overflow-y: auto would otherwise let the user scroll to them. */
top: calc(100% + 6px);
right: 0;
margin: 0;
padding: 0.3rem 0;
list-style: none;
background: #fff;
color: var(--purple-900);
border: 1px solid var(--border-soft);
border-radius: 4px;
box-shadow: 0 6px 24px rgba(42, 24, 80, 0.25);
min-width: 320px;
max-width: 540px;
max-height: 40vh;
overflow-y: auto;
z-index: 20;
}
.wp-history__menu[hidden] { display: none; }
.wp-history__menu li {
padding: 0.45rem 0.85rem;
font-family: var(--font-mono);
font-size: 0.78rem;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
border-bottom: 1px solid var(--border-soft);
}
.wp-history__menu li:last-child { border-bottom: none; }
.wp-history__menu li:hover { background: var(--bg-code); }
.wp-history__empty {
padding: 0.6rem 0.85rem;
font-family: var(--font-ui);
font-size: 0.78rem;
color: var(--fg-muted);
font-style: italic;
}
.wp-history__clear {
border-top: 1px solid var(--border-soft);
padding: 0.4rem 0.85rem;
font-family: var(--font-ui);
font-size: 0.72rem;
color: var(--terracotta-500);
cursor: pointer;
text-align: right;
}
.wp-history__clear:hover { background: rgba(196, 102, 74, 0.08); }
/* ───────── editor ───────── */
.wp-form { margin-bottom: 1.5rem; }
.wp-editor {
display: flex;
border: 1px solid var(--border-soft);
border-radius: 4px;
background: var(--bg-canvas);
overflow: hidden;
border-left: 3px solid var(--gold-500);
}
.wp-editor__gutter {
background: var(--bg-code);
color: var(--purple-700);
font-family: var(--font-ui);
font-size: 0.7rem;
letter-spacing: 0.08em;
text-transform: uppercase;
padding: 0.65rem 0.5rem;
border-right: 1px solid var(--border-soft);
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
font-weight: 600;
}
.wp-editor__gutter-action {
background: transparent;
border: 1px solid transparent;
color: var(--fg-muted);
cursor: pointer;
padding: 0.15rem 0.3rem;
border-radius: 3px;
font-size: 0.8rem;
line-height: 1;
}
.wp-editor__gutter-action:hover {
color: var(--terracotta-500);
border-color: var(--border-soft);
background: var(--bg-canvas);
}
.wp-editor__panel {
flex: 1;
position: relative;
min-width: 0;
}
/* Editor + highlighted overlay share identical metrics so glyphs align
exactly. The textarea sits on top with transparent text colour; the
underlying renders the syntax-highlighted version. */
.wp-editor__ta,
.wp-editor__hl {
font-family: var(--font-mono);
font-size: 0.85rem;
line-height: 1.5;
padding: 0.65rem 0.85rem;
margin: 0;
border: none;
white-space: pre-wrap;
word-break: break-word;
overflow-wrap: break-word;
tab-size: 2;
-moz-tab-size: 2;
}
.wp-editor__hl {
position: absolute;
inset: 0;
pointer-events: none;
color: var(--purple-900);
background: transparent;
overflow: auto;
scrollbar-width: none;
}
.wp-editor__hl::-webkit-scrollbar { width: 0; height: 0; }
.wp-editor__hl code { display: block; font: inherit; color: inherit; background: none; }
.wp-editor__ta {
position: relative;
display: block;
width: 100%;
background: transparent;
color: transparent;
-webkit-text-fill-color: transparent;
caret-color: var(--purple-900);
resize: vertical;
outline: none;
}
.wp-editor__ta::selection {
background: rgba(107, 79, 160, 0.25);
}
.wp-editor__ta::placeholder {
color: var(--fg-muted);
-webkit-text-fill-color: var(--fg-muted);
}
/* SQL token colours for the overlay. Colours match the Pygments "default"
style used by the user docs (doc/source/_build/html/_static/pygments.css),
but bold/italic are dropped: any font-weight or font-style change between
the textarea (regular) and the overlay shifts glyph advance widths and
the caret drifts off the displayed text. Colour alone is enough. */
.hl-kw { color: #008000; } /* Keyword (.k) */
.hl-fn { color: #0000FF; } /* Name.Function (.nf) */
.hl-str { color: #BA2121; } /* Literal.String (.s) */
.hl-num { color: #666666; } /* Literal.Number (.m) */
.hl-com { color: #3D7B7B; } /* Comment (.c) */
.hl-op { color: #666666; } /* Operator (.o) */
.wp-form__actions {
display: flex; align-items: center; justify-content: space-between;
flex-wrap: wrap; gap: 0.6rem;
margin-top: 0.7rem;
}
.wp-form__hint {
font-family: var(--font-ui);
font-size: 0.8rem;
color: var(--fg-muted);
display: inline-flex; align-items: center; gap: 0.4rem;
}
.wp-form__hint code { color: var(--purple-700); }
/* GUC toggles in the form-actions row, styled as switches. The native
checkbox keeps semantics + keyboard handling; appearance:none lets us
draw a track + knob via the input itself. */
.wp-toggle {
font-family: var(--font-ui);
font-size: 0.78rem;
color: var(--fg-muted);
display: inline-flex; align-items: center; gap: 0.45rem;
cursor: pointer;
user-select: none;
}
.wp-toggle input[type="checkbox"] {
appearance: none; -webkit-appearance: none;
position: relative;
width: 30px; height: 16px;
border-radius: 999px;
background: var(--border-soft);
border: 1px solid var(--border-soft);
cursor: pointer;
margin: 0;
flex-shrink: 0;
transition: background 0.15s, border-color 0.15s;
}
.wp-toggle input[type="checkbox"]::before {
content: "";
position: absolute;
top: 1px; left: 1px;
width: 12px; height: 12px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 2px rgba(42, 24, 80, 0.25);
transition: left 0.15s, background 0.15s;
}
.wp-toggle input[type="checkbox"]:checked {
background: var(--purple-500);
border-color: var(--purple-500);
}
.wp-toggle input[type="checkbox"]:checked::before { left: 15px; }
.wp-toggle input[type="checkbox"]:focus-visible {
outline: 2px solid var(--gold-500);
outline-offset: 1px;
}
.wp-toggle code { color: var(--purple-700); font-size: 0.95em; }
/* Padlock placeholder: present in the DOM in both modes so the toggle's
horizontal footprint doesn't change when switching mode. Visibility (not
display) toggling keeps the box reserved. */
.wp-toggle__lock { font-size: 0.7em; color: var(--fg-muted); visibility: hidden; }
.wp-toggle.is-locked .wp-toggle__lock { visibility: visible; }
/* Locked state: muted track + padlock icon. Track stays in the "on"
position but uses a desaturated colour to signal it isn't user-editable. */
.wp-toggle.is-locked { cursor: not-allowed; }
.wp-toggle.is-locked input[type="checkbox"] { cursor: not-allowed; }
.wp-toggle.is-locked input[type="checkbox"]:checked {
background: var(--purple-300, #B8A5D6);
border-color: var(--purple-300, #B8A5D6);
}
.wp-toggle.is-locked input[type="checkbox"]::before {
background: #f0e8fa;
box-shadow: none;
}
.wp-toggle.is-locked code { color: var(--fg-muted); font-style: italic; }
/* Provenance-mode selector: segmented three-way switch that replaces
the old where_provenance toggle. The native radios stay in the DOM
(semantics + keyboard), but appearance:none lets us paint the
labels as connected segment buttons. The selected segment uses the
brand purple; the rest are flat ghost buttons. */
.wp-prov-scheme {
display: inline-flex;
align-items: stretch;
border: 1px solid var(--border-soft);
border-radius: 999px;
background: var(--bg-elevated);
padding: 0;
margin: 0;
font-family: var(--font-ui);
font-size: 0.78rem;
overflow: hidden;
}
/* The native