/**
 * CyberChef - The Cyber Swiss Army Knife
 *
 * @copyright Crown Copyright 2016-2026
 * @license Apache-2.0
 *
 *   Copyright 2016-2026 Crown Copyright
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * Design tokens — "lab bench": instrument-panel industrial.
 *
 * The governing idea is a two-channel signal palette: cyan means data entering
 * the bench, amber means data leaving it. At 400px there is no room for labels
 * everywhere, so hue carries the meaning instead. Colour here is semantic, not
 * decorative — nothing is tinted to look nice.
 *
 * Bench (dark) is the default; Paper (light) is authored separately rather than
 * derived, because glow reads as material on graphite and as a smudge on paper.
 */

:root {
    color-scheme: dark light;

    /* Signal channels — hue is meaning */
    --hue-in: 222; /* data entering  */
    --hue-out: 78; /* data leaving   */
    --hue-ok: 148; /* clean bake     */
    --hue-detect: 308; /* inferred, not asserted */
    --hue-err: 27; /* operation threw */

    /* Type — mono carries the data, grotesque carries the chrome */
    --font-data: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    --font-ui: ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif;

    --text-micro: 0.6875rem; /* 11px — tracked small-caps labels */
    --text-meta: 0.75rem;
    --text-ui: 0.8125rem;
    --text-data: 0.875rem;
    --text-lead: 1.0625rem;
    --text-readout: 1.75rem;

    --track-micro: 0.09em;
    --leading-data: 1.45;

    /* Spacing — roles, not a t-shirt scale. Deliberately uneven. */
    --space-hair: 2px;
    --space-tight: 4px;
    --space-chip: 5px 9px 6px;
    --space-pane: 10px 12px 14px;
    --space-gutter: 12px;
    --space-bay: 18px;
    --rail-h: 36px;

    /* Radii — non-uniform on purpose; hard where it reads as an instrument */
    --radius-panel: 3px;
    --radius-chip: 2px;
    --radius-sheet: 11px 11px 0 0;
    --radius-pill: 999px;

    /* Motion — mechanical snap, no bounce */
    --dur-tick: 90ms;
    --dur-swap: 180ms;
    --dur-sweep: 320ms;
    --ease-mech: cubic-bezier(0.2, 0.9, 0.25, 1);
    --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

    /* Texture — 3% scanline, recessed surfaces only */
    --texture-scan: repeating-linear-gradient(
        0deg,
        oklch(100% 0 0 / 0.028) 0 1px,
        transparent 1px 3px
    );
}

/* ── Bench (dark) — the default ─────────────────────────────────── */
:root,
:root[data-theme="bench"] {
    --surface-shell: oklch(16.5% 0.013 262);
    --surface-pane: oklch(20.5% 0.015 262);
    --surface-raised: oklch(25.5% 0.017 262);
    --surface-inset: oklch(12.5% 0.011 262);
    --surface-scrim: oklch(10% 0.01 262 / 0.72);

    --ink-hi: oklch(94% 0.008 250);
    --ink: oklch(78% 0.01 250);
    --ink-lo: oklch(62% 0.012 250);

    --line-hi: oklch(34% 0.016 262);
    --line: oklch(27% 0.013 262);

    --ch-in: oklch(79% 0.115 var(--hue-in));
    --ch-out: oklch(83% 0.14 var(--hue-out));
    --ch-ok: oklch(80% 0.145 var(--hue-ok));
    --ch-detect: oklch(76% 0.12 var(--hue-detect));
    --ch-err: oklch(70% 0.17 var(--hue-err));
    --ch-in-dim: oklch(79% 0.115 var(--hue-in) / 0.16);
    --ch-out-dim: oklch(83% 0.14 var(--hue-out) / 0.16);

    --shadow-inset:
        inset 0 1px 0 oklch(0% 0 0 / 0.5),
        inset 0 -1px 0 oklch(100% 0 0 / 0.045);
    --glow-active:
        0 0 0 1px oklch(83% 0.14 var(--hue-out) / 0.55),
        0 0 20px -7px oklch(83% 0.14 var(--hue-out) / 0.8);
}

/* ── Paper (light) — warm instrument label, not white ────────────── */
:root[data-theme="paper"] {
    --surface-shell: oklch(95.5% 0.008 92);
    --surface-pane: oklch(98% 0.006 92);
    --surface-raised: oklch(100% 0 0);
    --surface-inset: oklch(92% 0.01 92);
    --surface-scrim: oklch(30% 0.02 262 / 0.34);

    --ink-hi: oklch(24% 0.02 262);
    --ink: oklch(38% 0.018 262);
    --ink-lo: oklch(50% 0.016 262);

    --line-hi: oklch(82% 0.012 92);
    --line: oklch(88% 0.01 92);

    --ch-in: oklch(48% 0.135 var(--hue-in));
    --ch-out: oklch(52% 0.13 var(--hue-out));
    --ch-ok: oklch(48% 0.135 var(--hue-ok));
    --ch-detect: oklch(47% 0.15 var(--hue-detect));
    --ch-err: oklch(48% 0.18 var(--hue-err));
    --ch-in-dim: oklch(48% 0.135 var(--hue-in) / 0.11);
    --ch-out-dim: oklch(52% 0.13 var(--hue-out) / 0.11);

    --shadow-inset: inset 0 1px 2px oklch(30% 0.02 92 / 0.14);
    --glow-active:
        0 0 0 1px var(--ch-out),
        0 2px 0 0 var(--ch-out-dim);
}

/*
 * There is deliberately no `prefers-color-scheme` block. "Follow the OS" is
 * resolved in src/popup/theme.ts, which always writes a concrete `data-theme`,
 * so each palette is defined exactly once above. The bare `:root` on the dark
 * block is the pre-hydration default.
 *
 * `color-scheme` must follow the chosen theme rather than the OS: scrollbars,
 * form controls and ::backdrop read it, and an OS-light scrollbar against the
 * bench palette reads as a rendering bug.
 */
:root[data-theme="bench"] {
    color-scheme: dark;
}

:root[data-theme="paper"] {
    color-scheme: light;
}

@media (prefers-reduced-motion: reduce) {
    :root {
        --dur-tick: 1ms;
        --dur-swap: 1ms;
        --dur-sweep: 1ms;
    }
}

/* ── Shell ──────────────────────────────────────────────────────── */
*,
*::before,
*::after {
    box-sizing: border-box;
}

body {
    margin: 0;
    /* Chrome caps action popups at 800×600; 400×580 leaves breathing room. */
    inline-size: 400px;
    block-size: 580px;
    display: grid;
    grid-template-rows: var(--rail-h) 1fr auto;
    overflow: hidden;
    background: var(--surface-shell);
    color: var(--ink);
    font-family: var(--font-ui);
    font-size: var(--text-ui);
}

/* ── The web surface ────────────────────────────────────────────────
   The same bundle served as a page, where the viewport is whatever the
   visitor's device happens to be rather than a popup we chose the size of.

   A separate class from `as-panel`, deliberately: that one is what
   `isPanel()` reads, and inheriting it would switch on panel-only UI —
   the pick-mode strip and the first-run explainer — for a surface that
   can do neither. */
html.as-web {
    block-size: 100%;
    overflow: hidden;
}

body.as-web {
    inline-size: 100%;
    /* `dvh` before the fallback would leave nothing for browsers without
       it; after, it wins where supported. This matters on phones: `vh` is
       computed against the *largest* viewport, so a 100vh layout sits
       partly under the URL bar until the user scrolls. */
    block-size: 100vh;
    block-size: 100dvh;

    /* A 400px-wide bench stretched across a tablet is worse than one that
       stays legible and centres. Line length, not screen width, is what
       makes a text tool readable. */
    max-inline-size: 720px;
    margin-inline: auto;
}

/* The two scrolling regions are capped in absolute pixels for a fixed
   popup. On a page they should take a share of whatever height exists —
   a 667px iPhone SE and a 1024px tablet want very different numbers. */
body.as-web .tool-rail { max-block-size: clamp(72px, 18dvh, 168px); }
body.as-web .arg-drawer { max-block-size: clamp(96px, 24dvh, 260px); }

/* Touch, not a mouse. Coarse pointers need a bigger target than a 26px
   chip, and this is the honest signal for "is this a finger" — far more
   reliable than guessing from width. */
@media (pointer: coarse) {
    body.as-web .tool-chip { min-block-size: 34px; }
    body.as-web button { min-block-size: 34px; }
}

/* iOS Safari zooms the whole page when a focused field's text is below
   16px, and never zooms back out. Any smaller value here costs the user
   a pinch on every single input. */
@media (pointer: coarse) {
    body.as-web #input,
    body.as-web #output {
        font-size: 16px;
    }
}

/* Short and wide — a phone on its side, where the chrome above and below
   leaves very little for the panes. */
@media (orientation: landscape) and (max-height: 480px) {
    body.as-web .tool-rail { max-block-size: 56px; }
    body.as-web .arg-drawer { max-block-size: 84px; }
}

/* The side panel runs the same bundle but is user-resizable. */
body.as-panel {
    inline-size: 100%;
    block-size: 100vh;
}

:focus-visible {
    outline: 2px solid var(--ch-in);
    outline-offset: 2px;
}

/* ── Header ─────────────────────────────────────────────────────── */
.bench-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: var(--space-gutter);
    border-block-end: 1px solid var(--line-hi);
    /* Scanline texture marks the chrome as a different material to the panes. */
    background: var(--texture-scan), var(--surface-pane);
}

.wordmark {
    margin: 0;
    font-size: var(--text-micro);
    font-weight: 600;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-hi);
}

.wordmark-mark {
    color: var(--ch-out);
}

.wordmark-link {
    color: inherit;
    text-decoration: none;
    transition: color var(--dur-tick) linear;
}

.wordmark-link:hover {
    color: var(--ch-in);
    text-decoration: underline;
}

.wordmark-link:focus-visible {
    outline: 2px solid var(--ch-in);
    outline-offset: 2px;
}

.header-actions {
    display: flex;
    gap: var(--space-tight);
}

/* ── Buttons ────────────────────────────────────────────────────── */
.ghost-button,
.icon-button {
    padding: var(--space-chip);
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-raised);
    color: var(--ink);
    font: inherit;
    font-size: var(--text-micro);
    font-weight: 500;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    cursor: pointer;
    transition:
        transform var(--dur-tick) var(--ease-mech),
        color var(--dur-tick) linear,
        box-shadow var(--dur-tick) var(--ease-mech);
}

.icon-button {
    border-color: transparent;
    background: transparent;
    color: var(--ink-lo);
}

.ghost-button:hover,
.icon-button:hover {
    transform: translateY(-1px);
    color: var(--ink-hi);
}

.ghost-button:active,
.icon-button:active {
    transform: translateY(0) scale(0.975);
}

/*
 * The one filled button in the UI. Adding a tool is the popup's core loop, so
 * it gets the only solid fill — everything else is a hairline or bare text.
 */
.accent-button {
    flex-shrink: 0;
    padding: var(--space-chip);
    border: 1px solid var(--ch-out);
    border-radius: var(--radius-chip);
    background: var(--ch-out-dim);
    color: var(--ch-out);
    font: inherit;
    font-size: var(--text-micro);
    font-weight: 600;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    cursor: pointer;
    transition:
        transform var(--dur-tick) var(--ease-mech),
        box-shadow var(--dur-tick) var(--ease-mech);
}

.accent-button:hover {
    transform: translateY(-1px);
    box-shadow: var(--glow-active);
}

.accent-button:active {
    transform: translateY(0) scale(0.975);
}

/* Grab, when the page can never be read. */
.icon-button[data-grab-state="blocked"] {
    opacity: 0.4;
    cursor: not-allowed;
}

/* Grab, when a permission would unlock it — the "inferred" channel, since we
   are guessing that access is what is missing. */
.icon-button[data-grab-state="needsPermission"] {
    color: var(--ch-detect);
}

.link-button {
    padding: 0;
    border: 0;
    background: none;
    color: var(--ch-in);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

/* ── Main layout ────────────────────────────────────────────────── */
.bench-main {
    display: grid;
    /* input : rail : args : output — args collapse to nothing when hidden. */
    grid-template-rows: minmax(90px, 0.9fr) auto auto minmax(120px, 1.1fr);
    gap: var(--space-tight);
    padding: var(--space-tight) var(--space-gutter) var(--space-gutter);
    min-block-size: 0;
}

.pane {
    display: grid;
    grid-template-rows: auto 1fr;
    min-block-size: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-panel);
    background: var(--surface-pane);
}

/* The output pane is the destination, so it reads as raised. */
.pane--output {
    border-color: var(--line-hi);
}

.pane-rail {
    display: flex;
    align-items: center;
    gap: var(--space-tight);
    padding: var(--space-tight) var(--space-tight) var(--space-tight) 10px;
    border-block-end: 1px solid var(--line);
}

.pane-label {
    margin: 0;
    font-size: var(--text-micro);
    font-weight: 600;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-lo);
}

.pane--input .pane-label {
    color: var(--ch-in);
}

.pane--output .pane-label {
    color: var(--ch-out);
}

/*
 * The active tool, shown beside the INPUT label so the pane says what is about
 * to happen to the text. Amber: it names the thing that produces the output.
 * Truncates rather than pushing the rail's buttons off the edge.
 */
.pane-tool {
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ch-out);
}

.pane-tool:empty {
    display: none;
}

.pane-meta {
    flex: 1;
    font-size: var(--text-micro);
    color: var(--ink-lo);
    font-variant-numeric: tabular-nums;
}

/* ── Input ──────────────────────────────────────────────────────── */
.input-field {
    inline-size: 100%;
    block-size: 100%;
    padding: 8px 10px 12px;
    border: 0;
    border-radius: 0 0 var(--radius-panel) var(--radius-panel);
    background: transparent;
    color: var(--ink-hi);
    font-family: var(--font-data);
    font-size: var(--text-data);
    line-height: var(--leading-data);
    resize: none;
}

.input-field:focus {
    outline: none;
    box-shadow: inset 2px 0 0 var(--ch-in);
}

.input-field::placeholder {
    color: var(--ink-lo);
}

/* ── Tool rail — a recessed channel, not another card ───────────── */
.tool-rail {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-tight);
    max-block-size: 84px;
    overflow-y: auto;
    padding: var(--space-sm, 8px);
    border-radius: var(--radius-panel);
    background: var(--surface-inset);
    box-shadow: var(--shadow-inset);
}

.rail-empty {
    margin: 0;
    padding: var(--space-tight);
    font-size: var(--text-micro);
    color: var(--ink-lo);
}

.chip-wrap {
    position: relative;
    display: inline-flex;
}

.chip-remove {
    position: absolute;
    inset-block-start: -5px;
    inset-inline-end: -5px;
    inline-size: 14px;
    block-size: 14px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-pill);
    background: var(--surface-shell);
    color: var(--ink-lo);
    font-size: 10px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transform: scale(0.8);
    transition:
        opacity var(--dur-tick) linear,
        transform var(--dur-tick) var(--ease-mech),
        color var(--dur-tick) linear;
}

.chip-wrap:hover .chip-remove,
.chip-wrap:focus-within .chip-remove {
    opacity: 1;
    transform: scale(1);
}

.chip-remove:hover {
    color: var(--ch-err);
    border-color: var(--ch-err);
}

.tool-chip {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: var(--space-chip);
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-raised);
    color: var(--ink);
    font: inherit;
    font-size: var(--text-micro);
    font-weight: 500;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    cursor: pointer;
    transition:
        transform var(--dur-tick) var(--ease-mech),
        box-shadow var(--dur-tick) var(--ease-mech),
        color var(--dur-tick) linear;
}

/* The channel tick: a 2px signal bar that carries the in/out hue. */
.tool-chip::before {
    content: "";
    inline-size: 2px;
    block-size: 9px;
    background: var(--ch-in);
    opacity: 0.55;
    transition:
        opacity var(--dur-tick) linear,
        transform var(--dur-tick) var(--ease-mech);
}

.tool-chip:hover {
    transform: translateY(-1px);
    color: var(--ink-hi);
}

.tool-chip:hover::before {
    opacity: 1;
    transform: scaleY(1.35);
}

.tool-chip:active {
    transform: translateY(0) scale(0.975);
}

.tool-chip[aria-checked="true"] {
    border-color: transparent;
    color: var(--ink-hi);
    background: linear-gradient(var(--ch-out-dim), transparent) var(--surface-raised);
    box-shadow: var(--glow-active);
}

.tool-chip[aria-checked="true"]::before {
    background: var(--ch-out);
    opacity: 1;
}

/* ── Argument drawer ────────────────────────────────────────────── */
.arg-drawer {
    display: grid;
    gap: var(--space-tight);
    max-block-size: 148px;
    overflow-y: auto;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: var(--radius-panel);
    background: var(--surface-pane);
}

.arg-drawer[hidden] {
    display: none;
}

.arg-field {
    display: grid;
    gap: 3px;
}

.arg-field--inline {
    align-items: center;
}

.arg-label {
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-lo);
}

.arg-input {
    inline-size: 100%;
    padding: 5px 7px;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-inset);
    color: var(--ink-hi);
    font: inherit;
    font-size: var(--text-meta);
}

.arg-input--mono {
    font-family: var(--font-data);
}

.arg-textarea {
    resize: vertical;
    font-family: var(--font-data);
}

.arg-toggle {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--space-tight);
}

.arg-select--unit {
    inline-size: auto;
    color: var(--ch-out);
}

.arg-switch {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
}

.arg-switch input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.arg-switch-track {
    position: relative;
    inline-size: 26px;
    block-size: 14px;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-pill);
    background: var(--surface-inset);
    transition: background var(--dur-tick) linear;
}

.arg-switch-track::after {
    content: "";
    position: absolute;
    inset-block-start: 1px;
    inset-inline-start: 1px;
    inline-size: 10px;
    block-size: 10px;
    border-radius: var(--radius-pill);
    background: var(--ink-lo);
    transition:
        transform var(--dur-tick) var(--ease-mech),
        background var(--dur-tick) linear;
}

.arg-switch input:checked + .arg-switch-track {
    background: var(--ch-out-dim);
}

.arg-switch input:checked + .arg-switch-track::after {
    transform: translateX(12px);
    background: var(--ch-out);
}

.arg-switch input:focus-visible + .arg-switch-track {
    outline: 2px solid var(--ch-in);
    outline-offset: 2px;
}

.arg-switch-label {
    font-size: var(--text-meta);
    color: var(--ink);
}

.arg-hint,
.arg-note {
    margin: 0;
    font-size: var(--text-micro);
    color: var(--ink-lo);
}

.arg-note--warn {
    color: var(--ch-detect);
}

/* ── Output ─────────────────────────────────────────────────────── */
.output-body {
    display: block;
    min-block-size: 0;
    overflow: auto;
    padding: 8px 10px 12px;
    font-family: var(--font-data);
    font-size: var(--text-data);
    line-height: var(--leading-data);
    color: var(--ink-hi);
}

.output-text {
    margin: 0;
    white-space: pre-wrap;
    word-break: break-word;
    font: inherit;
}

.output-rich table {
    border-collapse: collapse;
    font-size: var(--text-meta);
}

.output-rich td,
.output-rich th {
    padding: 2px 6px;
    border: 1px solid var(--line);
}

.output-error {
    margin: 0;
    color: var(--ch-err);
    white-space: pre-wrap;
}

.output-note {
    margin: var(--space-sm, 8px) 0 0;
    padding-block-start: var(--space-tight);
    border-block-start: 1px solid var(--line);
    font-family: var(--font-ui);
    font-size: var(--text-micro);
    color: var(--ink-lo);
}

/* ── Status bar ─────────────────────────────────────────────────── */
.bench-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-tight);
    min-block-size: 26px;
    padding-inline: var(--space-gutter);
    border-block-start: 1px solid var(--line);
    background: var(--surface-inset);
    box-shadow: var(--shadow-inset);
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    color: var(--ink-lo);
}

.bench-status[data-channel="ok"] #status-line {
    color: var(--ch-ok);
}

.bench-status[data-channel="err"] #status-line {
    color: var(--ch-err);
}

#status-line {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.status-hint {
    flex-shrink: 0;
    color: var(--ink-lo);
    opacity: 0.7;
}

/* ── Pick strip ─────────────────────────────────────────────────── */
/* Replaces the status hint while picking. The mode toggle lives here, not in
   Settings, because here is where it is used. */
.pick-strip {
    display: flex;
    align-items: center;
    gap: var(--space-sm, 8px);
    margin-inline-start: auto;
}

.pick-strip[hidden] {
    display: none;
}

.pick-strip-label {
    flex-shrink: 0;
    color: var(--ch-detect);
    font-weight: 600;
}

.segmented--compact {
    box-shadow: none;
}

/* The strip's segments are buttons rather than radios: they are rebuilt on
   every change, and a radio group would need names kept unique across
   rebuilds for no gain. */
.segment-face--button {
    padding: 3px 8px;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-lo);
    cursor: pointer;
}

.segment-face--button + .segment-face--button {
    border-inline-start: 1px solid var(--line);
}

.segment-face--button:hover {
    color: var(--ink-hi);
}

.segment-face--button[aria-checked="true"] {
    background: var(--ch-out-dim);
    color: var(--ch-out);
}

/* Grab, while a pick is running. */
.icon-button[data-picking="true"] {
    color: var(--ch-detect);
    border-color: var(--ch-detect);
}

.status-link {
    flex-shrink: 0;
    margin-inline-start: auto;
    padding-inline: var(--space-sm, 8px);
    color: var(--ink-lo);
    text-decoration: none;
    transition: color var(--dur-tick) linear;
}

.status-link:hover {
    color: var(--ch-in);
    text-decoration: underline;
}

/* ── Settings sheet ─────────────────────────────────────────────── */
.sheet {
    inline-size: 340px;
    padding: 0;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-panel);
    background: var(--surface-raised);
    color: var(--ink);
}

.sheet::backdrop {
    background: var(--surface-scrim);
}

.sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-tight) var(--space-tight) var(--space-tight) var(--space-gutter);
    border-block-end: 1px solid var(--line);
}

.sheet-body {
    display: grid;
    gap: var(--space-bay);
    padding: var(--space-gutter);
}

.settings-row {
    display: grid;
    gap: var(--space-tight);
}

.settings-hint {
    margin: 0;
    font-size: var(--text-micro);
    line-height: 1.5;
    color: var(--ink-lo);
}

/* ── Segmented picker ───────────────────────────────────────────── */
.settings-choice {
    display: grid;
    gap: var(--space-tight);
    margin: 0;
    padding: 0;
    border: 0;
}

.segmented {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    overflow: hidden;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-inset);
    box-shadow: var(--shadow-inset);
}

.segment {
    cursor: pointer;
}

.segment input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.segment + .segment .segment-face {
    border-inline-start: 1px solid var(--line);
}

.segment-face {
    display: block;
    padding: 5px 0;
    text-align: center;
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-lo);
    transition:
        color var(--dur-tick) linear,
        background var(--dur-tick) linear;
}

.segment:hover .segment-face {
    color: var(--ink-hi);
}

.segment input:checked + .segment-face {
    background: var(--ch-out-dim);
    color: var(--ch-out);
}

.segment input:focus-visible + .segment-face {
    /* Inset, because .segmented clips its overflow. */
    outline: 2px solid var(--ch-in);
    outline-offset: -2px;
}

/* ── First-run explainer ────────────────────────────────────────── */
.intro {
    inline-size: 380px;
    max-inline-size: calc(100vw - 24px);
}

.intro-modes {
    display: grid;
    gap: var(--space-gutter);
}

.intro-mode {
    display: grid;
    gap: var(--space-tight);
    padding: var(--space-pane);
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-panel);
    background: var(--surface-pane);
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
    transition:
        transform var(--dur-tick) var(--ease-mech),
        box-shadow var(--dur-tick) var(--ease-mech),
        border-color var(--dur-tick) linear;
}

.intro-mode:hover {
    transform: translateY(-1px);
    border-color: var(--ch-out);
    box-shadow: var(--glow-active);
}

.intro-mode:active {
    transform: translateY(0) scale(0.99);
}

.intro-mode-name {
    font-size: var(--text-micro);
    font-weight: 600;
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ch-out);
}

.intro-mode-note {
    font-size: var(--text-micro);
    line-height: 1.5;
    color: var(--ink-lo);
}

/*
 * The dioramas.
 *
 * A miniature browser window: chrome strip, toolbar icon, the surface itself,
 * and a cursor. Both run the same 6s loop with the same beats — icon flashes,
 * surface appears, cursor moves into the page — so the eye only has to catch
 * the difference on the last beat: the popup vanishes, the panel does not.
 *
 * Animated properties are transform and opacity only, so the whole thing stays
 * on the compositor.
 */
.diorama {
    position: relative;
    display: block;
    block-size: 88px;
    overflow: hidden;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-inset);
}

/* Content lines, so the area behind the surface reads as a page rather than
   an empty box. Static — only the cursor and the surface animate. */
.diorama::before {
    content: "";
    position: absolute;
    inset-block-start: 22px;
    inset-inline-start: 8px;
    inline-size: 52%;
    block-size: 40px;
    background: repeating-linear-gradient(
        var(--ink-lo) 0 2px,
        transparent 2px 8px
    );
    opacity: 0.35;
}

.diorama-chrome {
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    block-size: 12px;
    background: var(--surface-raised);
    border-block-end: 1px solid var(--line);
}

.diorama-icon {
    position: absolute;
    inset-block-start: 3px;
    inset-inline-end: 8px;
    inline-size: 6px;
    block-size: 6px;
    border-radius: 1px;
    background: var(--ch-out);
    transform-origin: center;
    animation: diorama-press 6s var(--ease-mech) infinite;
}

/*
 * The cursor travels; its dot pulses on each click. Two animations on one
 * element cannot both drive `transform`, so the travel lives on the span and
 * the click pulse on its pseudo-element.
 */
.diorama-cursor {
    position: absolute;
    inset-block-start: 3px;
    inset-inline-end: 7px;
    inline-size: 9px;
    block-size: 9px;
    animation: diorama-cursor 6s var(--ease-mech) infinite;
}

.diorama-cursor::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: var(--ink-hi);
    /* Ringed so it stays visible over both the page and the surface. */
    box-shadow:
        0 0 0 2px var(--surface-inset),
        0 0 0 3px var(--ink-lo);
    animation: diorama-click 6s var(--ease-mech) infinite;
}

.diorama-surface {
    position: absolute;
    background: var(--ch-out-dim);
    border: 1px solid var(--ch-out);
    border-radius: 1px;
}

/* Popup: a small sheet under the icon that goes away on the last beat. */
.diorama--popup .diorama-surface {
    inset-block-start: 16px;
    inset-inline-end: 6px;
    inline-size: 44px;
    block-size: 34px;
    transform-origin: top right;
    animation: diorama-popup 6s var(--ease-mech) infinite;
}

/* Panel: a full-height column that stays put. */
.diorama--panel .diorama-surface {
    inset-block-start: 13px;
    inset-inline-end: 0;
    inline-size: 40px;
    inset-block-end: 0;
    border-radius: 0;
    transform-origin: right center;
    animation: diorama-panel 6s var(--ease-mech) infinite;
}

@keyframes diorama-press {
    0%, 8% { transform: scale(1); }
    12% { transform: scale(0.75); }
    18%, 100% { transform: scale(1); }
}

/* Cursor: rests on the icon, clicks, then travels into the page and stays. */
@keyframes diorama-cursor {
    0%, 45% { transform: translate(0, 0); }
    62%, 100% { transform: translate(-56px, 44px); }
}

/* Squashes on each click: once on the icon, once out in the page. */
@keyframes diorama-click {
    0%, 9% { transform: scale(1); }
    12% { transform: scale(0.55); }
    16%, 58% { transform: scale(1); }
    62% { transform: scale(0.55); }
    66%, 100% { transform: scale(1); }
}

@keyframes diorama-popup {
    0%, 12% { opacity: 0; transform: scale(0.7); }
    22%, 58% { opacity: 1; transform: scale(1); }
    /* The click lands in the page — and the popup is gone. */
    68%, 100% { opacity: 0; transform: scale(0.7); }
}

@keyframes diorama-panel {
    0%, 12% { opacity: 0; transform: translateX(100%); }
    /* Same click, same beat — the panel is still there. */
    22%, 100% { opacity: 1; transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
    /* Hold the end state: the difference between the two is still legible. */
    .diorama-icon,
    .diorama-cursor,
    .diorama-surface {
        animation: none;
    }

    .diorama--popup .diorama-surface {
        opacity: 0.35;
    }

    .diorama-cursor {
        transform: translate(-56px, 44px);
    }

    .diorama-cursor::after {
        animation: none;
    }
}

.intro-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-gutter);
    padding-block-start: var(--space-gutter);
    border-block-start: 1px solid var(--line);
}

.settings-about {
    display: grid;
    gap: var(--space-tight);
    padding-block-start: var(--space-gutter);
    border-block-start: 1px solid var(--line);
}

.settings-link {
    color: var(--ch-in);
}

/* ── Picker ─────────────────────────────────────────────────────── */
.picker {
    inline-size: 340px;
    max-block-size: 420px;
    padding: 0;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-panel);
    background: var(--surface-raised);
    color: var(--ink);
}

.picker::backdrop {
    background: var(--surface-scrim);
}

.picker-search {
    display: flex;
    gap: var(--space-tight);
    align-items: center;
    padding: var(--space-tight);
    border-block-end: 1px solid var(--line);
}

.picker-input {
    flex: 1;
    padding: 6px 8px;
    border: 1px solid var(--line-hi);
    border-radius: var(--radius-chip);
    background: var(--surface-inset);
    color: var(--ink-hi);
    font: inherit;
    font-size: var(--text-ui);
}

.picker-results {
    margin: 0;
    padding: var(--space-tight);
    max-block-size: 330px;
    overflow-y: auto;
    list-style: none;
}

.picker-hit {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-tight);
    padding: 6px 8px;
    border-radius: var(--radius-chip);
    cursor: pointer;
}

.picker-hit[aria-selected="true"] {
    background: var(--ch-in-dim);
}

.picker-name {
    font-size: var(--text-ui);
    color: var(--ink-hi);
}

.picker-name .match {
    background: none;
    color: var(--ch-in);
    text-decoration: underline;
}

.picker-category {
    flex-shrink: 0;
    font-size: var(--text-micro);
    letter-spacing: var(--track-micro);
    text-transform: uppercase;
    color: var(--ink-lo);
}

.picker-empty {
    padding: 8px;
    font-size: var(--text-meta);
    color: var(--ink-lo);
}

.picker-empty--error {
    color: var(--ch-err);
}

