﻿/* The workbench: the shell, the app bar, the three panes, the operation bar and the
   status bar, one section per part of the page. Only the shell pages (the workbench
   and /not-found) load this. */

/* ==== Shell ================================================================= */

:root {
    --sf-statusbar-h: 1.5rem;
}

.sf-shell {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--sf-bg);
    color: var(--sf-text);
    font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-size: 0.875rem;
}

/* Below tablet width two lists cannot sit side by side, so swap them for a notice. */
.sf-too-small {
    display: none;
}

@media (max-width: 921.58px) {
    .sf-shell {
        display: none;
    }

    .sf-too-small {
        position: fixed;
        inset: 0;
        display: grid;
        place-items: center;
        padding: 2rem;
        background: var(--sf-bg);
        color: var(--sf-text);
        font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
        text-align: center;
    }

    .sf-too-small-inner {
        max-width: 26rem;
    }

    .sf-too-small-mark {
        width: 2.25rem;
        height: 2.25rem;
        margin-bottom: 1rem;
        fill: none;
        stroke: var(--sf-accent);
        stroke-width: 1.6;
    }

    .sf-too-small h1 {
        font-size: 1.125rem;
        font-weight: 600;
        letter-spacing: -0.01em;
        margin-bottom: 0.5rem;
    }

    .sf-too-small p {
        color: var(--sf-muted);
        font-size: 0.9375rem;
        line-height: 1.5;
        margin: 0;
    }
}

/* ==== App bar =============================================================== */

.appbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex: none;
    height: 2.75rem;
    padding: 0 0.625rem;
    background: var(--sf-chrome);
    border-bottom: 1px solid var(--sf-border);
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    flex: none;
    padding-right: 0.25rem;
}

.brand-mark {
    width: 1.25rem;
    height: 1.25rem;
    fill: none;
    stroke: var(--sf-muted);
    stroke-width: 1.6;
}

.brand-mark-flex {
    stroke: var(--sf-accent);
}

.brand-name {
    color: var(--sf-text);
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.brand-name-accent {
    color: var(--sf-accent);
}

.appbar-spacer {
    flex: 1;
}

@media (max-width: 1228.78px) {
    .appbar {
        gap: 0.5rem;
    }
}

/* ==== Theme switch ========================================================== */

.theme-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex: none;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--sf-border);
    border-radius: 999px;
    background: transparent;
    color: var(--sf-muted);
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.theme-btn:hover:not(:disabled) {
    background: var(--sf-chrome-hover);
    color: var(--sf-text);
}

.theme-btn:disabled {
    cursor: default;
    opacity: 0.6;
}

/* The label is the first thing to go when the chrome tightens - the glyph on its
   own still says which way the switch will move. */
@media (max-width: 1228.78px) {
    .theme-btn-label {
        display: none;
    }
}

/* ==== Panes ================================================================= */

.pane {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    background: var(--sf-pane);
}

/* Each pane carries its own hue, used only for the hairline under the header and
   the focus rule - enough to tell the panes apart without colouring the lists
   themselves, which is where the user is actually reading. */
.pane-left {
    --pane-hue: var(--sf-side-left);
}

.pane-right {
    --pane-hue: var(--sf-side-right);
}

.pane-result {
    --pane-hue: var(--sf-side-result);
}

.pane-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: none;
    padding: 0.3125rem 0.5rem 0.3125rem 0.625rem;
    background: var(--sf-pane-alt);
    border-bottom: 1px solid var(--sf-border-soft);
    box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--pane-hue) 35%, transparent);
}

.pane-title {
    margin: 0;
    color: var(--sf-text);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.11em;
    text-transform: uppercase;
}

.pane-meta {
    color: var(--sf-muted);
    font-size: 0.6875rem;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.pane-head-spacer {
    flex: 1;
    min-width: 0.5rem;
}

.pane-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex: none;
}

.pane-editor {
    flex: 1;
    min-height: 0;
    min-width: 0;
    padding: 0.5rem 0.75rem;
    border: 0;
    outline: 0;
    resize: none;
    background: transparent;
    color: var(--sf-text);
    font-family: 'JetBrains Mono', 'Cascadia Mono', 'Consolas', ui-monospace, monospace;
    font-size: 0.8125rem;
    line-height: 1.55;
    tab-size: 8;
    white-space: pre;
    overflow: auto;
}

.pane-editor::placeholder {
    color: var(--sf-faint);
}

.pane-editor:focus-visible {
    box-shadow: inset 2px 0 0 var(--pane-hue);
}

.pane-footer {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: none;
    flex-wrap: wrap;
    padding: 0.375rem 0.625rem;
    background: var(--sf-pane-alt);
    border-top: 1px solid var(--sf-border-soft);
    color: var(--sf-muted);
    font-size: 0.75rem;
}

/* ==== Operation glyphs ====================================================== */

.op-icon {
    width: 1.25rem;
    height: 1.25rem;
    flex: none;
}

/* The region the operation returns. `currentColor` throughout, so the whole glyph
   follows the button's own state - selected, hovered or at rest - with no rule
   here having to know about any of them. */
.op-icon-fill {
    fill: currentColor;
}

/* The circles the fill is not in: enough to show which two sets are being talked
   about without competing with the answer. */
.op-icon-edge {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.1;
    opacity: 0.55;
}

.op-icon-line {
    fill: none;
    stroke: currentColor;
    stroke-width: 2.2;
    stroke-linecap: round;
}

/* ==== Workbench ============================================================= */

/* Pane sizes are bare `fr` values so a drag just moves budget between neighbours;
   js/panes.js rewrites these custom properties during a drag. They must stay free
   of any `minmax()` floor - with a floor in the track, grid subtracts the floors
   before distributing the remainder, so sizes stop being proportional to the
   custom properties and the arithmetic in panes.js no longer holds. The minimum
   pane size is clamped in JS instead.

   The starting proportions are `var()` fallbacks rather than declarations on these
   elements, because a remembered layout is applied to <html> before first paint
   (see the inline script in the page head) and a declaration here would shadow what it inherits. */
.sf {
    position: relative;
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-rows: var(--sf-size-lists, 5fr) auto var(--sf-size-result, 4fr);
    background: var(--sf-bg);
}

/* The two lists and the operation bar under them are one resizable track: the bar
   belongs to the question, not to the answer, and giving it its own track would
   let a drag squeeze it out of existence. */
.sf-lists {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
}

.sf-lr {
    flex: 1;
    min-height: 0;
    min-width: 0;
    display: grid;
    grid-template-columns: var(--sf-size-left, 1fr) auto var(--sf-size-right, 1fr);
}

/* One handle style for both axes: a gutter in the shell colour, hairlined on both
   sides, with a short grip in the middle. Which axis a handle serves is decided by
   its box - see panes.js - so the media query below only restyles it, it never has
   to tell the script anything. */
.sf-split {
    position: relative;
    display: grid;
    place-items: center;
    background: var(--sf-bg);
    touch-action: none;
}

.sf-split::after {
    content: "";
    display: block;
    border-radius: 999px;
    background: var(--sf-faint);
    opacity: 0.5;
}

.sf-lr > .sf-split {
    width: 9px;
    border-inline: 1px solid var(--sf-border);
    cursor: col-resize;
}

.sf-lr > .sf-split::after {
    width: 3px;
    height: 2rem;
}

.sf > .sf-split {
    height: 9px;
    border-block: 1px solid var(--sf-border);
    cursor: row-resize;
}

.sf > .sf-split::after {
    width: 2rem;
    height: 3px;
}

.sf-split:hover,
.sf-split:focus-visible {
    background: var(--sf-accent-wash);
    border-color: var(--sf-accent-dim);
    outline: none;
}

.sf-split:hover::after,
.sf-split:focus-visible::after,
.sf-split.is-dragging::after {
    background: var(--sf-accent);
    opacity: 1;
}

.sf-split.is-dragging {
    background: var(--sf-accent-wash);
    border-color: var(--sf-accent);
}

/* Bigger grab target on touch devices; the gutter keeps its weight because the
   extra width is padding in the shell colour. */
@media (pointer: coarse) {
    .sf-lr > .sf-split {
        width: 17px;
    }

    .sf > .sf-split {
        height: 17px;
    }
}

/* The operation bar. */
.sf-ops {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    flex: none;
    flex-wrap: wrap;
    padding: 0.375rem 0.625rem;
    background: var(--sf-chrome-2);
    border-block: 1px solid var(--sf-border);
}

.sf-ops-spacer {
    flex: 1;
    min-width: 0.5rem;
}

.op-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4375rem;
    padding: 0.25rem 0.625rem 0.25rem 0.4375rem;
    border: 1px solid var(--sf-border);
    border-radius: 6px;
    background: var(--sf-pane);
    color: var(--sf-muted);
    font: inherit;
    font-size: 0.8125rem;
    white-space: nowrap;
    cursor: pointer;
}

.op-btn:hover {
    border-color: var(--sf-accent-dim);
    color: var(--sf-text);
}

/* The chosen comparison. Filled rather than outlined: this is the one control on
   screen whose state the result is entirely explained by, so it should be
   readable from across the room. */
.op-btn.is-on {
    background: var(--sf-accent);
    border-color: var(--sf-accent);
    color: var(--sf-accent-ink);
    font-weight: 600;
}

.op-btn.is-on:hover {
    background: var(--sf-accent-bright);
    border-color: var(--sf-accent-bright);
}

/* Small ghost buttons in the pane header bars and beside the pills. */
.pane-btn {
    padding: 0.1875rem 0.4375rem;
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    color: var(--sf-muted);
    font: inherit;
    font-size: 0.75rem;
    white-space: nowrap;
    cursor: pointer;
}

.pane-btn:hover:not(:disabled) {
    background: var(--sf-chrome-hover);
    border-color: var(--sf-border);
    color: var(--sf-text);
}

.pane-btn:disabled {
    cursor: default;
    opacity: 0.55;
}

/* Result shaping: pressed pills rather than one-shot buttons, because these stay
   on across a recalculation. */
.pill {
    padding: 0.1875rem 0.5rem;
    border: 1px solid var(--sf-border);
    border-radius: 999px;
    background: transparent;
    color: var(--sf-muted);
    font: inherit;
    font-size: 0.75rem;
    white-space: nowrap;
    cursor: pointer;
}

.pill:hover {
    border-color: var(--sf-accent-dim);
    color: var(--sf-text);
}

.pill.is-on {
    background: var(--sf-accent-wash);
    border-color: var(--sf-accent-dim);
    color: var(--sf-accent);
}

.opt {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex: none;
    color: var(--sf-muted);
    font-size: 0.75rem;
    cursor: pointer;
    user-select: none;
}

.opt input {
    width: 0.875rem;
    height: 0.875rem;
    margin: 0;
    accent-color: var(--sf-accent);
}

.statusbar {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex: none;
    box-sizing: border-box;
    /* Fixed, so the privacy sheet can sit exactly on top of it. */
    height: var(--sf-statusbar-h);
    padding: 0 0.75rem;
    background: var(--sf-chrome);
    border-top: 1px solid var(--sf-border);
    color: var(--sf-muted);
    font-size: 0.6875rem;
}

.statusbar-item {
    font-variant-numeric: tabular-nums;
}

.statusbar-spacer {
    flex: 1;
}

.statusbar-note {
    color: var(--sf-faint);
    white-space: nowrap;
}

/* Something the user asked for did not happen. Muted rather than red: nothing on
   screen is wrong, there is just another way to get at it. */
.statusbar-warn {
    min-width: 0;
    overflow: hidden;
    color: var(--sf-text);
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The privacy notice. Faint, like the summary, because it is a standing control rather
   than anything about the comparison - but it stays at every width, which the summary
   does not. The chevron points up to open the sheet and down once it is open. */
.statusbar-link {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    flex: none;
    padding: 0;
    border: 0;
    background: none;
    color: var(--sf-faint);
    font: inherit;
    white-space: nowrap;
    cursor: pointer;
}

.statusbar-link:hover,
.statusbar-link:focus-visible,
.statusbar:has(+ .privacy-sheet:popover-open) .statusbar-link {
    color: var(--sf-text);
}

.statusbar-chevron {
    width: 0.625rem;
    height: 0.625rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform 0.2s ease;
}

.statusbar:has(+ .privacy-sheet:popover-open) .statusbar-chevron {
    transform: rotate(180deg);
}

/* ==== Privacy sheet ========================================================= */

/* Slides up out of the status bar, on the right under the button that opened it. A
   popover, so it lives in the top layer and needs no z-index; the UA's centring and
   border are undone. */
.privacy-sheet {
    position: fixed;
    inset: auto 0.75rem var(--sf-statusbar-h) auto;
    box-sizing: border-box;
    width: min(26rem, calc(100vw - 1.5rem));
    max-height: calc(100vh - var(--sf-statusbar-h) - 3.5rem);
    margin: 0;
    padding: 0.875rem 1rem 0.75rem;
    overflow: auto;
    background: var(--sf-pane);
    border: 1px solid var(--sf-border);
    border-bottom: 0;
    border-radius: 0.5rem 0.5rem 0 0;
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.22);
    color: var(--sf-text);
    font-family: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-size: 0.8125rem;
    line-height: 1.5;

    transform: translateY(100%);
    opacity: 0;
    transition:
        transform 0.22s ease,
        opacity 0.22s ease,
        overlay 0.22s allow-discrete,
        display 0.22s allow-discrete;
}

.privacy-sheet:popover-open {
    transform: none;
    opacity: 1;
}

@starting-style {
    .privacy-sheet:popover-open {
        transform: translateY(100%);
        opacity: 0;
    }
}

/* Clear, so the workbench stays readable behind it - it is a note, not a dialog. */
.privacy-sheet::backdrop {
    background: transparent;
}

.privacy-sheet-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.privacy-sheet-title {
    flex: 1;
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.privacy-sheet-close {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 0.25rem;
    background: none;
    color: var(--sf-muted);
    cursor: pointer;
}

.privacy-sheet-close:hover,
.privacy-sheet-close:focus-visible {
    border-color: var(--sf-border);
    background: var(--sf-chrome-hover);
    color: var(--sf-text);
}

.privacy-sheet-close svg {
    width: 0.75rem;
    height: 0.75rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.privacy-sheet-list {
    margin: 0;
    padding-left: 1.125rem;
    color: var(--sf-muted);
}

.privacy-sheet-list li + li {
    margin-top: 0.4375rem;
}

.privacy-sheet-list strong {
    color: var(--sf-text);
    font-weight: 600;
}

.privacy-sheet-foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-top: 0.75rem;
    padding-top: 0.625rem;
    border-top: 1px solid var(--sf-border-soft);
    font-size: 0.75rem;
}

.privacy-sheet-foot a {
    color: var(--sf-accent);
    text-decoration: none;
}

.privacy-sheet-foot a:hover,
.privacy-sheet-foot a:focus-visible {
    text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
    .privacy-sheet,
    .statusbar-chevron {
        transition: none;
    }
}

/* Narrow enough that five labelled buttons and the two lists cannot both fit:
   the operation bar keeps its glyphs and sheds its words, since the glyph is the
   part that distinguishes them anyway. */
@media (max-width: 1228.78px) {
    .op-btn {
        padding: 0.25rem 0.4375rem;
    }

    .op-btn span {
        display: none;
    }

    .statusbar-note {
        display: none;
    }
}

/* ==== Not found ============================================================= */

.missing {
    flex: 1;
    display: grid;
    place-items: center;
    padding: 2rem;
    text-align: center;
}

.missing h1 {
    margin: 0 0 0.5rem;
    font-size: 1.125rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.missing p {
    margin: 0 0 1rem;
    color: var(--sf-muted);
}

.missing a {
    color: var(--sf-accent);
}
