/*
 * The `hidden` attribute must win. The browser's own `[hidden] { display: none }` lives in the user-agent
 * stylesheet, so any author rule setting `display` beats it however unspecific that rule is: an element
 * carrying `hidden` still paints if some other selector gives it a display value. This rule restores the
 * attribute's meaning for the whole document.
 *
 * A test asserting `element.hidden` cannot catch the failure this prevents, because the attribute is set
 * correctly and it is the paint that ignores it. Assert computed display instead.
 */
[hidden] {
    display: none !important;
}

:root {
    color-scheme: light dark;

    --bg: #ffffff;
    --fg: #1b1b1f;
    --muted: #6b6b73;
    --line: #dcdce2;
    --surface: #f6f6f8;
    --accent: #1f6feb;
    --accent-fg: #ffffff;
    --danger: #c0392b;
    --ok: #1a7f37;
    --ok-bg: #e6f4ea;
    --warn: #9a6700;
    --warn-bg: #fff4d6;
    --error: #b42318;
    --error-bg: #fde8e6;

    --plot-bg: #ffffff;
    --plot-grid-major: #cfcfd6;
    --plot-grid-minor: #ebebf0;
    --plot-axis: #55555e;
    --plot-text: #33333a;
    --plot-font: 12px system-ui, -apple-system, "Segoe UI", sans-serif;

    --series-1: #1f6feb;
    --series-2: #b3561d;
    --series-3: #1a7f37;
    --series-4: #6f42c1;
    --plot-reference: #8a8a94;
    --plot-band-caution: rgba(227, 179, 65, 0.16);
    --plot-band-danger: rgba(180, 35, 24, 0.14);
    --plot-cursor: #9a9aa4;
    --plot-ghost: #c2c2cc;
    --series-5: #0f7d8f;
    --series-6: #a83a7a;
    --flash: rgba(31, 111, 235, 0.18);

    /*
     * The mark, from the brand kit (data/brand/README.md). It is drawn on the page background
     * rather than on its own tile, so on light the disc is ink with a cream surround and on dark
     * the two trade places. The cap is signal orange in both, and nothing else may use that orange.
     */
    --mark-disc: #17171a;
    --mark-ring: #f6f5f2;
    --mark-cone: #34343a;
    --mark-cap: #ff5a1f;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #121215;
        --fg: #e8e8ec;
        --muted: #9a9aa4;
        --line: #33333c;
        --surface: #1b1b20;
        --accent: #58a6ff;
        --accent-fg: #0b0b0e;
        --danger: #f08a7d;
        --ok: #4ec27a;
        --ok-bg: #12301c;
        --warn: #e3b341;
        --warn-bg: #3a2c08;
        --error: #ff7b72;
        --error-bg: #3d1512;

        /* The disc and the surround trade places; the cap does not move. */
        --mark-disc: #f6f5f2;
        --mark-ring: #17171a;
        --mark-cone: #d8d6d0;

        --plot-bg: #17171b;
        --plot-grid-major: #3a3a44;
        --plot-grid-minor: #26262e;
        --plot-axis: #9a9aa4;
        --plot-text: #c8c8d0;

        --series-1: #58a6ff;
        --series-2: #ff9e64;
        --series-3: #4ec27a;
        --series-4: #bc8cff;
        --plot-reference: #7a7a86;
        --plot-band-caution: rgba(227, 179, 65, 0.14);
        --plot-band-danger: rgba(255, 123, 114, 0.14);
        --plot-cursor: #7a7a86;
        --plot-ghost: #4a4a56;
        --series-5: #3fc4d8;
        --series-6: #ff8ac4;
        --flash: rgba(88, 166, 255, 0.24);
    }
}

/*
 * The column is a flex column so the footer sits at the bottom of the window on a short page and
 * below the content on a long one. A footer that floats halfway up a nearly empty page reads as the
 * page having failed to load the rest.
 */
body {
    margin: 0;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    background: var(--bg);
    color: var(--fg);
    font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

main {
    flex: 1 0 auto;
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    padding: 24px;
    box-sizing: border-box;
}

/*
 * The workspace is the one page whose usefulness genuinely grows with the window: a wider plot column
 * is more of the curve on screen, at more pixels per octave. Prose pages keep the 1280px cap, because
 * a 2000px line of text is harder to read, not easier: width is only worth taking where something
 * uses it.
 *
 * Canvases already follow their container (a ResizeObserver in canvas-layer.js, which also re-scales
 * for devicePixelRatio), so the plots redraw at the new size rather than stretching.
 */
main:has(.workspace) {
    max-width: 2400px;
}

a {
    color: var(--accent);
}

h1 {
    margin: 0 0 8px;
    font-size: 24px;
}

h2 {
    margin: 0 0 8px;
    font-size: 18px;
}

.muted {
    color: var(--muted);
    margin: 0 0 16px;
}

.top-nav {
    border-bottom: 1px solid var(--line);
    background: var(--bg);
}

/* The same column the content and the footer use, so the three line up down the page. */
.nav-inner {
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 1280px;
    margin: 0 auto;
    padding: 9px 24px;
    box-sizing: border-box;
}

/* On a narrow screen the links scroll sideways rather than squeezing the account strip into two
   lines: min-width lets this shrink, and the strip beside it does not. */
.nav-links {
    display: flex;
    align-items: center;
    gap: 2px;
    min-width: 0;
    margin-inline-start: 14px;
    overflow-x: auto;
    scrollbar-width: none;
}

.nav-links::-webkit-scrollbar {
    display: none;
}

.top-nav a {
    color: var(--fg);
    text-decoration: none;
}

.nav-links a {
    padding: 6px 11px;
    border-radius: 7px;
    color: var(--muted);
    font-size: 14px;
    white-space: nowrap;
}

.nav-links a:hover,
.nav-links a:focus-visible {
    background: var(--surface);
    color: var(--fg);
}

.nav-links a[aria-current="page"] {
    background: var(--surface);
    color: var(--fg);
    font-weight: 600;
}

.top-nav .brand {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 2px;
}

/*
 * Mark and wordmark are two elements rather than one lockup file so the word can drop away on a
 * narrow screen. The proportions are the kit's: the mark is 1.118x the wordmark's type size, and
 * the gap between them is 0.26x that size, which at a 26px mark is 6px and a 16.6px word.
 */
.brand-mark {
    width: 26px;
    height: 26px;
    flex: none;
}

.brand-word {
    height: 16.6px;
    width: auto;
    flex: none;
    color: var(--fg);
}

.footer-mark {
    width: 17px;
    height: 17px;
    margin-inline-end: 7px;
    vertical-align: -3px;
}

/* The workspace runs to the window edges, so its bar should too. */
body:has(main .workspace) .nav-inner {
    max-width: 2400px;
}

@media (max-width: 560px) {
    .nav-inner {
        padding-inline: 16px;
    }

    .brand-word {
        display: none;
    }

    .nav-links {
        margin-inline-start: 4px;
    }
}

.page-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    margin-bottom: 16px;
}

.actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.button {
    display: inline-block;
    padding: 6px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--surface);
    color: var(--fg);
    font: inherit;
    text-decoration: none;
    cursor: pointer;
}

.button.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-fg);
}

.button.danger {
    color: var(--danger);
}

.button.small {
    padding: 2px 8px;
    font-size: 13px;
}

.button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.cards {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.card {
    display: flex;
    flex-direction: column;
    min-width: 200px;
    padding: 20px;
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--fg);
    text-decoration: none;
}

.card strong {
    font-size: 32px;
}

.filters {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}

.filters input[type="search"] {
    flex: 1;
    max-width: 360px;
}

input,
select,
textarea {
    box-sizing: border-box;
    max-width: 100%;
    font: inherit;
    color: var(--fg);
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 6px 8px;
}

/*
 * Every field holding a quantity is monospaced with a slashed zero and fixed-width digits.
 *
 * This is not decoration. These fields carry numbers a reader copies onto a cutting list or into
 * another tool, and in a proportional face 0 and O are a glance apart while 1 and l are worse. Menlo
 * leads the stack because its zero is slashed outright; `slashed-zero` then asks any other font that
 * ships the feature for the same thing. `tabular-nums` keeps a digit from changing width as it changes
 * value, so dragging a slider does not make the number jitter.
 */
input[type="number"],
input[inputmode="decimal"] {
    font-family: Menlo, ui-monospace, SFMono-Regular, Consolas, "DejaVu Sans Mono", monospace;
    font-variant-numeric: slashed-zero tabular-nums;
    /* Monospace runs large beside the UI face at the same nominal size. */
    font-size: 0.92em;
}

table.data {
    width: 100%;
    border-collapse: collapse;
}

table.data th,
table.data td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: top;
}

table.data th {
    font-weight: 600;
    white-space: nowrap;
}

table.data .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

table.data th button {
    all: unset;
    cursor: pointer;
}

table.data th button.active:after {
    content: " ▲";
    font-size: 10px;
}

table.data th button.active[aria-sort="descending"]:after {
    content: " ▼";
}

.pager {
    display: flex;
    gap: 4px;
    margin-top: 12px;
}

.pager button {
    padding: 4px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--surface);
    color: var(--fg);
    font: inherit;
    cursor: pointer;
}

.pager button.active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-fg);
}

.badge {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--accent-fg);
    font-size: 12px;
    font-weight: 600;
    vertical-align: middle;
}

.notes {
    white-space: pre-wrap;
}

.param-set {
    margin: 0 0 24px;
    padding: 16px;
    border: 1px solid var(--line);
    border-radius: 8px;
}

.param-set.primary {
    border-color: var(--accent);
}

.param-set > header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.provenance {
    margin: 0;
    flex-basis: 100%;
    color: var(--muted);
}

.param-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px 16px;
    margin: 0 0 12px;
}

.param-grid .param dt {
    color: var(--muted);
    font-size: 13px;
}

.param-grid .param dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.param-grid .param.derived dd,
.param-grid .param.estimated dd {
    font-style: italic;
}

.param-grid .param dd small {
    font-style: normal;
    color: var(--muted);
}

.param-grid .param.estimated dd small {
    color: var(--warn);
}

[data-learn] {
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

.callout {
    padding: 8px 12px;
    border-radius: 6px;
    margin: 0 0 12px;
}

.callout.ok {
    background: var(--ok-bg);
    color: var(--ok);
}

.callout.ok a {
    color: inherit;
}

.curve-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 6px 0 0;
}

.curve-row .swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex: none;
}

.curve-row .provenance {
    flex-basis: auto;
    font-size: 13px;
}

.callout.warning {
    background: var(--warn-bg);
    color: var(--warn);
}

.consistency {
    margin-top: 12px;
    border: 1px solid var(--line);
    border-left: 4px solid var(--line);
    border-radius: 8px;
    padding: 12px 16px;
}

.consistency.pass {
    border-left-color: var(--ok);
}

.consistency.warning {
    border-left-color: var(--warn);
}

.consistency.error {
    border-left-color: var(--error);
}

.consistency > header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
}

.consistency .status {
    color: var(--muted);
}

.consistency.pass .status {
    color: var(--ok);
}

.consistency.warning .status {
    color: var(--warn);
}

.consistency.error .status {
    color: var(--error);
}

.consistency table.checks tr.warning td {
    background: var(--warn-bg);
}

.consistency table.checks tr.error td {
    background: var(--error-bg);
}

.consistency .efficiency {
    margin: 12px 0 0;
}

.editor fieldset {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 12px 16px 16px;
    margin: 0 0 16px;
}

.editor legend {
    font-weight: 600;
    padding: 0 6px;
}

.editor-columns {
    display: grid;
    /* minmax(0, ...) on both tracks: a long <select> option otherwise sets a min-content width the track
       cannot shrink below, and the column spills over its neighbor. */
    grid-template-columns: minmax(0, 380px) minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}

.editor fieldset > label {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr);
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.editor fieldset > label > select,
.editor fieldset > label > input,
.editor fieldset > label > textarea {
    min-width: 0;
}

.editor fieldset > label.check {
    grid-template-columns: auto 1fr;
    justify-content: start;
}

.control {
    display: flex;
    align-items: center;
    gap: 6px;
}

.control {
    min-width: 0;
}

.control input {
    flex: 1;
    width: 100%;
    min-width: 0;
}

.control .unit {
    color: var(--muted);
    /* Just wide enough for the longest unit shown ("mm"), leaving the rest of the column to the number. */
    min-width: 24px;
}

.param-inputs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 8px 16px;
}

.param-input {
    display: grid;
    grid-template-columns: 70px 1fr;
    align-items: center;
    gap: 6px;
    padding: 4px 0;
}

.param-input .label small {
    display: block;
    color: var(--muted);
    font-size: 11px;
    line-height: 1.2;
}

.param-input .status {
    grid-column: 2;
    font-size: 12px;
    color: var(--muted);
    min-height: 1.2em;
}

.param-input.derived input,
.param-input.estimated input {
    font-style: italic;
    color: var(--muted);
}

.param-input.estimated .status {
    color: var(--warn);
}

.param-input.given input {
    font-style: normal;
    color: var(--fg);
}

.editor label.invalid input,
.editor label.invalid select,
.param-input.invalid input {
    border-color: var(--error);
}

.toolbar {
    margin-top: 12px;
}

.error-box {
    background: var(--error-bg);
    color: var(--error);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 16px;
}

.error-box p {
    margin: 0;
}

.workspace {
    display: grid;
    /*
     * The side columns grow with the window but stop well short of the middle's share: a 500px wide
     * field for a box volume is no better than a 320px one, whereas the plots keep paying for every
     * pixel. So both sides are clamped, and everything above their ceiling goes to the curves.
     */
    grid-template-columns: clamp(320px, 22vw, 420px) minmax(0, 1fr) clamp(280px, 20vw, 380px);
    gap: 20px;
    align-items: start;
}

/* Below 1400px the design list folds under the plots (SPEC.md, "The design workspace"). */
@media (max-width: 1400px) {
    .workspace {
        grid-template-columns: 300px minmax(0, 1fr);
    }

    .workspace-designs {
        grid-column: 1 / -1;
    }
}

.workspace-controls,
.workspace-designs {
    position: sticky;
    top: 16px;
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: 8px;
}

.workspace-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    margin-bottom: 8px;
}

.workspace-header h1 {
    margin: 0;
}

.project-title {
    /* Wide enough that the name and the two status lines under it read as sentences rather than
       breaking mid-phrase; the toolbar drops to its own row before this gets squeezed. */
    min-width: 280px;
    flex: 1;
}

.project-name {
    font-size: 22px;
    font-weight: 600;
    border: 1px solid transparent;
    background: transparent;
    padding: 2px 6px;
    width: 100%;
    max-width: 420px;
    /* Pulled back by its own padding and border so the name's first letter sits on the same vertical
       line as the "Project" label above it and the contents line below, rather than 7px right of both. */
    margin-left: -7px;
}

.project-name:hover {
    border-color: var(--line);
}

.share-link {
    display: block;
    margin-top: 4px;
    word-break: break-all;
    font-size: 13px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Sits directly above the picker it narrows, and reads as its peer rather than a footnote to it. */
.driver-filter {
    margin-bottom: 10px;
}

.control-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

label.stacked {
    display: flex;
    flex-direction: column;
    gap: 3px;
    font-size: 13px;
    color: var(--muted);
    margin-bottom: 10px;
}

label.stacked select {
    color: var(--fg);
    font-size: 15px;
}

.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 6px 0 12px;
}

.tab {
    /* Five enclosures share a 320px column, and "Double tuned" is twice the width of "Sealed".
       Growing from a common basis keeps them one row of even tabs instead of one tab bursting
       out of the strip. */
    flex: 1 1 0;
    min-width: 0;
    white-space: nowrap;
    padding: 6px 6px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--surface);
    color: var(--fg);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.tab.active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-fg);
}

.parameter {
    margin-bottom: 10px;
}

.parameter label {
    display: grid;
    /* The right column holds the number and its unit. It needs to fit the widest value these fields
       accept, such as a net volume of 137.5 L, with the unit alongside. */
    grid-template-columns: 1fr 132px;
    align-items: center;
    gap: 8px;
}

.parameter .name {
    font-size: 13px;
    color: var(--muted);
}

.parameter input[type="range"] {
    width: 100%;
    margin-top: 2px;
    padding: 0;
}

.port-solution {
    margin: 8px 0 0;
    padding: 8px 10px;
    background: var(--surface);
    border-radius: 6px;
    font-size: 13px;
    color: var(--muted);
}

.cursor-readout {
    margin: 0 0 4px 62px;
    min-height: 1.4em;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
    font-size: 13px;
}

.designs-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}

.designs-header h2 {
    margin: 0;
    font-size: 16px;
}

.design-list {
    list-style: none;
    margin: 0 0 10px;
    padding: 0;
}

.design {
    display: grid;
    grid-template-columns: 12px 1fr;
    gap: 8px;
    align-items: center;
    padding: 6px;
    border: 1px solid transparent;
    border-radius: 6px;
    cursor: pointer;
}

.design.active {
    border-color: var(--accent);
    background: var(--surface);
}

/* Taken off the plots but still in the project: dimmed, so its state is visible without reading a button. */
.design.off-plots .swatch,
.design.off-plots .design-label {
    opacity: 0.45;
}

.design .swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
}

.design-label {
    border: 1px solid transparent;
    background: transparent;
    padding: 2px 4px;
    min-width: 0;
}

.design-label:hover {
    border-color: var(--line);
}

.design-actions {
    grid-column: 2;
    display: flex;
    /* Wrapping, because the panel is a fixed 280px column above 1400px and four verbs do not fit on
       one line there. Without this the row's min-content is the sum of all four buttons, the grid
       track cannot shrink below it, and the whole row hangs out over the panel's edge. */
    flex-wrap: wrap;
    gap: 4px;
    min-width: 0;
}

.small {
    font-size: 12px;
}

.plot {
    position: relative;
    width: 100%;
    /*
     * Height follows width, or the extra room a wide window buys turns every curve into a letterbox
     * strip: at 1500px across, a 210px plot is more than seven to one, and a 3 dB feature stops being
     * visible as one. The ceiling keeps the stack of plots scrollable on a tall screen.
     */
    height: clamp(210px, 14vw, 300px);
}

.plot + .plot {
    margin-top: 6px;
}

.plot-surface {
    cursor: crosshair;
    touch-action: none;
}

.plot-surface.panning {
    cursor: grabbing;
}

.plot-legend {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
    margin: 2px 0 0 60px;
    font-size: 12px;
    color: var(--muted);
}

.plot-legend span:before {
    content: "";
    display: inline-block;
    width: 14px;
    height: 2px;
    margin-right: 5px;
    vertical-align: middle;
    background: currentColor;
}

.vented-only[hidden] {
    display: none;
}

.plot canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

/* --- Validation page ---------------------------------------------------- */

.callout.error {
    background: var(--error-bg);
    color: var(--error);
}

.lede {
    font-size: 17px;
    line-height: 1.5;
    max-width: 68ch;
    margin: 0 0 24px;
}

.validation-section {
    margin: 0 0 36px;
}

.validation-section h2 {
    margin: 0 0 4px;
}

.validation-section > .muted {
    max-width: 78ch;
    margin: 0 0 12px;
}

.validation-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.validation-table th,
.validation-table td {
    text-align: left;
    padding: 6px 10px;
    border-bottom: 1px solid var(--line);
    vertical-align: top;
}

.validation-table th {
    font-weight: 600;
    color: var(--muted);
    border-bottom-color: var(--fg);
    white-space: nowrap;
}

.validation-table td.name {
    max-width: 34ch;
}

/* Hashes and measured values are compared by eye, so they line up in a mono face. */
.validation-table td:not(.name):not(.verdict) {
    font-variant-numeric: tabular-nums;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 13px;
    white-space: nowrap;
}

.validation-table td.verdict {
    font-weight: 600;
    white-space: nowrap;
}

.validation-table tr.pass td.verdict {
    color: var(--ok);
}

.validation-table tr.fail td.verdict {
    color: var(--error);
}

.validation-table tr.fail td {
    background: var(--error-bg);
}

/* --- Analytics ------------------------------------------------------------ */

.analytics-note {
    max-width: 78ch;
    line-height: 1.5;
}

.analytics-audience {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin: 4px 0 18px;
}

.analytics-audience .label {
    font-weight: 600;
    margin-right: 2px;
}

.analytics-audience .small {
    margin-left: 6px;
}

.analytics-totals {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 14px;
    margin: 20px 0 28px;
}

.analytics-totals > div {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 14px 16px;
    background: var(--surface);
}

.analytics-totals dt {
    color: var(--muted);
    font-size: 13px;
}

.analytics-totals dd {
    margin: 4px 0 0;
    font-size: 26px;
    font-variant-numeric: tabular-nums;
}

.analytics-section {
    margin-bottom: 36px;
}

.analytics-section h2 {
    font-size: 17px;
    margin: 0 0 12px;
}

.analytics-split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 28px;
}

/* One row per day: label, a bar as wide as that day was busy, then the two numbers. */
.day-bars {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 3px;
}

.day-bars li {
    display: grid;
    grid-template-columns: 5.5rem 1fr 4rem 4rem;
    align-items: center;
    gap: 10px;
    font-variant-numeric: tabular-nums;
    font-size: 13px;
}

.day-bars .day {
    color: var(--muted);
}

.day-bars .bar {
    height: 14px;
    border-radius: 3px;
    background: linear-gradient(to right, var(--accent) var(--fill), var(--surface) var(--fill));
    border: 1px solid var(--line);
}

.day-bars .count {
    text-align: right;
}

.day-bars .visitors {
    text-align: right;
    color: var(--muted);
}

/* --- Legal pages and the footer ------------------------------------------- */

.legal {
    max-width: 68ch;
    margin: 0 auto;
    padding-bottom: 56px;
    line-height: 1.6;
}

.legal h1 {
    font-size: clamp(24px, 3vw, 32px);
    margin: 8px 0 12px;
}

.legal h2 {
    font-size: 19px;
    margin: 34px 0 8px;
}

.legal > .lede {
    font-size: 18px;
    color: var(--muted);
    margin: 0 0 24px;
}

.legal ul {
    padding-left: 20px;
}

.legal li {
    margin-bottom: 8px;
}

.legal-list dt {
    font-weight: 600;
    margin-top: 12px;
}

.legal-list dd {
    margin: 4px 0 0;
    color: var(--muted);
}

.callout.warn {
    background: var(--warn-bg);
    color: var(--warn-fg, #a15c00);
    border: 1px solid var(--warn);
}

.site-footer {
    flex: none;
    margin-top: 56px;
    border-top: 1px solid var(--line);
    background: var(--surface);
    color: var(--muted);
    font-size: 13px;
}

/* Lined up with main, so the footer's edges sit under the content's rather than beside them. */
.footer-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px 32px;
    max-width: 1280px;
    margin: 0 auto;
    padding: 20px 24px 26px;
    box-sizing: border-box;
}

.footer-brand {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
    margin: 0;
}

.footer-brand a {
    color: var(--fg);
    font-weight: 600;
    letter-spacing: 0.01em;
    text-decoration: none;
}

.site-footer nav {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
}

.site-footer a {
    color: var(--muted);
    text-decoration: none;
}

.site-footer a:hover,
.site-footer a:focus-visible {
    color: var(--accent);
    text-decoration: underline;
}

.footer-brand a:hover,
.footer-brand a:focus-visible {
    color: var(--accent);
}

/* The workspace fills the window, so a footer band under it would only take plot height. */
main:has(.workspace) + .site-footer {
    margin-top: 24px;
}


/* Deleting an account is not an action to make comfortable. */
.danger-zone {
    border: 1px solid var(--danger);
    border-radius: 10px;
    padding: 16px 18px;
}

.account-section {
    margin-bottom: 32px;
    max-width: 68ch;
}

.account-details {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 6px 18px;
    margin: 0 0 12px;
}

.account-details dt {
    color: var(--muted);
}

.account-details dd {
    margin: 0;
}

/* --- Learning pages ------------------------------------------------------- */

.learn-lede {
    max-width: 68ch;
    color: var(--muted);
    line-height: 1.55;
}

.learn-index {
    list-style: none;
    padding: 0;
    margin: 24px 0 48px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 18px;
}

.learn-index li {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 14px 16px;
    background: var(--surface);
}

.learn-index a {
    font-weight: 600;
}

.learn-index p {
    margin: 6px 0 0;
    color: var(--muted);
    font-size: 14px;
    line-height: 1.45;
}

/* A topic reads as an article, so it gets an article's measure rather than the workspace's. */
.learn-page {
    max-width: 68ch;
    margin: 0 auto;
    padding-bottom: 56px;
}

.learn-page h1 {
    font-size: clamp(24px, 3vw, 34px);
    line-height: 1.15;
    margin: 4px 0 10px;
    text-wrap: balance;
}

.learn-page > .lede {
    font-size: 18px;
    color: var(--muted);
    line-height: 1.5;
    margin: 0 0 28px;
}

.crumbs {
    font-size: 13px;
    color: var(--muted);
    margin-top: 8px;
}

.learn-page .learn-body h2 {
    font-size: 20px;
    margin: 32px 0 10px;
}

.learn-page .learn-body p,
.learn-page .learn-body ul,
.learn-page .learn-body ol {
    margin: 0 0 14px;
}

.learn-page .learn-body li {
    margin-bottom: 6px;
}

.learn-page .learn-body blockquote {
    margin: 0 0 14px;
    padding-left: 14px;
    border-left: 3px solid var(--line);
    color: var(--muted);
}

.learn-page .learn-body code {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 1px 4px;
    font-size: 0.92em;
}

.learn-page .learn-body .tex[data-display="true"] {
    display: block;
    margin: 18px 0;
    text-align: center;
}

.learn-related-page {
    margin-top: 40px;
    border-top: 1px solid var(--line);
    padding-top: 20px;
}

.learn-related-page h2 {
    font-size: 16px;
    margin: 0 0 12px;
}

.learn-related-page ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 10px;
}

.learn-related-page span {
    display: block;
    color: var(--muted);
    font-size: 14px;
}

.learn-back {
    margin-top: 32px;
    color: var(--muted);
    font-size: 14px;
}

.learn-permalink {
    margin-inline-end: auto;
    font-size: 13px;
}

/* --- Landing page --------------------------------------------------------- */

.landing {
    /* Wider than a reading column, narrower than the workspace: the screenshots want room and the
       prose does not. */
    max-width: 1120px;
    margin: 0 auto;
}

.landing h2 {
    font-size: clamp(22px, 2.4vw, 30px);
    line-height: 1.2;
    margin: 0 0 12px;
}

.landing p {
    max-width: 62ch;
    line-height: 1.55;
}

.hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
    gap: 40px;
    align-items: center;
    padding: 24px 0 8px;
}

.hero-eyebrow {
    margin: 0 0 10px;
    color: var(--muted);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.hero h1 {
    font-size: clamp(30px, 4.4vw, 48px);
    line-height: 1.08;
    letter-spacing: -0.02em;
    margin: 0 0 16px;
    text-wrap: balance;
}

.hero .lede {
    font-size: clamp(16px, 1.5vw, 19px);
    color: var(--muted);
    margin: 0 0 24px;
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 14px;
}

.button.large {
    padding: 11px 20px;
    font-size: 16px;
}

.hero-note {
    color: var(--muted);
    font-size: 14px;
    margin: 0;
}

.hero-figure,
.landing-section figure {
    margin: 0;
}

/* The screenshots are real captures of the running application, so they are framed as windows
   rather than bled into the page: a border and a shadow say "this is the tool" without pretending
   to be part of the page around it. */
.landing img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--surface);
    box-shadow: 0 10px 30px rgb(0 0 0 / 12%);
}

.hero-figure figcaption,
.landing-section figcaption {
    color: var(--muted);
    font-size: 13px;
    line-height: 1.5;
    margin-top: 10px;
    max-width: 52ch;
}

.landing-section {
    padding: 44px 0;
    border-top: 1px solid var(--line);
}

.landing-section.split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 36px;
    align-items: center;
}

.landing-section.split.reverse > figure {
    order: -1;
}

.landing-list {
    margin: 16px 0 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 10px;
    max-width: 62ch;
}

.landing-list li {
    padding-left: 16px;
    border-left: 3px solid var(--accent);
    line-height: 1.5;
}

.enclosure-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 20px;
    margin-top: 20px;
}

.enclosure-grid article {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 16px;
    background: var(--surface);
}

.enclosure-grid h3 {
    margin: 10px 0 6px;
    font-size: 16px;
}

.enclosure-grid p {
    margin: 0;
    color: var(--muted);
    font-size: 14px;
    line-height: 1.45;
}

/* Drawn in the page's own colour so both themes get a legible diagram from one file. */
.enclosure-icon {
    width: 100%;
    max-width: 120px;
    height: auto;
}

.enclosure-icon .box {
    fill: none;
    stroke: var(--muted);
    stroke-width: 2;
}

.enclosure-icon .cone {
    fill: var(--accent);
    stroke: none;
    opacity: 0.85;
}

.enclosure-icon .cone.passive {
    fill: var(--muted);
    opacity: 0.55;
}

.enclosure-icon .divider,
.enclosure-icon .port {
    fill: none;
    stroke: var(--muted);
    stroke-width: 2;
}

.faq {
    margin: 16px 0 0;
    max-width: 68ch;
}

.faq dt {
    font-weight: 600;
    margin-top: 18px;
}

.faq dd {
    margin: 6px 0 0;
    color: var(--muted);
    line-height: 1.55;
}

.landing-cta {
    text-align: center;
    padding: 52px 0 64px;
    border-top: 1px solid var(--line);
}

.landing-cta p {
    max-width: none;
    color: var(--muted);
    margin: 0 0 20px;
}

@media (max-width: 860px) {
    .hero,
    .landing-section.split {
        grid-template-columns: 1fr;
        gap: 24px;
    }

    .landing-section.split.reverse > figure {
        order: 0;
    }
}

/* --- Accounts ------------------------------------------------------------- */

.top-nav .account {
    flex: none;
    margin-inline-start: auto;
    padding-inline-start: 10px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
}

.account-menu {
    position: relative;
}

.account-trigger {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 5px 8px 5px 10px;
    border: 1px solid transparent;
    border-radius: 7px;
    background: none;
    color: var(--fg);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.account-trigger:hover,
.account-trigger[aria-expanded="true"] {
    border-color: var(--line);
    background: var(--surface);
}

.account-trigger .chevron {
    font-size: 18px;
    line-height: 1;
    color: var(--muted);
}

.account-trigger[aria-expanded="true"] .chevron {
    transform: rotate(180deg);
}

.account-menu-items {
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + 6px);
    z-index: 40;
    min-width: 200px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--bg);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.14);
}

.account-menu-email {
    margin: 4px 10px 6px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--line);
    color: var(--muted);
    font-size: 12px;
    overflow-wrap: anywhere;
}

.account-menu-item {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--fg);
    font: inherit;
    font-size: 13px;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.account-menu-item:hover,
.account-menu-item:focus-visible {
    background: var(--surface);
    color: var(--accent);
}

.account-pages {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 24px;
    max-width: 780px;
}

.account-pages form.stack {
    display: flex;
    flex-direction: column;
    gap: 10px;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 16px;
}

.account-pages h2 {
    margin: 0;
    font-size: 16px;
}

.account-pages .error {
    color: var(--warn-fg, #a15c00);
    margin: 0;
}

/* A contribution nobody has looked at yet. Listed like any other driver, because a reader who can
   see the mark is better served than one who cannot see the driver at all. */
.badge.pending {
    background: var(--warn-bg, #fdf3e3);
    color: var(--warn-fg, #a15c00);
}

/* --- Learning layer ------------------------------------------------------ */

/* The one affordance, used everywhere: a dotted underline and nothing else. No icons, no badges,
   no color. A reader who does not want explanations should not notice the feature exists. */
[data-learn] {
    cursor: help;
}

/* In a table header the label is already a sort button, so the affordance cannot be the label
   itself: it is an info icon beside it. This is the one place the dotted underline is dropped,
   because an underline under an icon reads as a rule rather than as an affordance. */
.learn-mark.icon {
    margin-left: 4px;
    font-size: 0.95rem;
    color: var(--muted);
    text-decoration: none;
    vertical-align: -0.18em;
}

.learn-mark.icon:hover {
    color: var(--accent);
}

[data-learn]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 2px;
}

.learn-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.28);
    display: flex;
    justify-content: flex-end;
    z-index: 60;
}

/* An overlay drawer: it sits above the workspace and never reflows it or resizes a plot. */
.learn-drawer {
    width: min(560px, 100vw);
    background: var(--bg);
    border-left: 1px solid var(--line);
    box-shadow: -8px 0 32px rgba(0, 0, 0, 0.16);
    overflow-y: auto;
    padding: 20px 24px 28px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.learn-drawer > header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
}

.learn-drawer h2 {
    margin: 0 0 4px;
    font-size: 20px;
}

/* Depth 1: the one-sentence definition, always visible in the header. */
.learn-summary {
    margin: 0;
    color: var(--muted);
    font-size: 14px;
    line-height: 1.45;
}

.learn-finding {
    background: var(--surface);
    border-left: 3px solid var(--accent);
    padding: 10px 12px;
    border-radius: 0 4px 4px 0;
    font-size: 14px;
}

/* Depths 2 and 3: the explainer and the reference, reached by scrolling. */
.learn-body {
    font-size: 15px;
    line-height: 1.6;
}

.learn-body h2 {
    font-size: 16px;
    margin: 22px 0 6px;
}

.learn-body p,
.learn-body ul,
.learn-body ol {
    margin: 0 0 12px;
}

.learn-body li {
    margin: 0 0 4px;
}

.learn-body blockquote {
    margin: 0 0 12px;
    padding-left: 12px;
    border-left: 3px solid var(--line);
    color: var(--muted);
}

.learn-body code {
    background: var(--surface);
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 13px;
}

/* A formula that KaTeX could not render keeps showing its TeX, which is readable enough to be a
   genuine fallback rather than a broken state. */
.learn-body .tex[data-display="true"] {
    display: block;
    overflow-x: auto;
    padding: 10px 0;
}

.learn-drawer > footer {
    margin-top: auto;
    padding-top: 12px;
    border-top: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.learn-related {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    font-size: 13px;
    color: var(--muted);
}

/* The findings count: a quiet line near the plots, never an inline banner. */
.findings-note {
    background: none;
    border: none;
    padding: 2px 0;
    font: inherit;
    font-size: 13px;
    color: var(--muted);
    cursor: pointer;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

.findings-note:hover {
    color: var(--fg);
}

.findings-note.problem {
    color: var(--error);
}

.findings-line {
    margin: 0 0 6px;
    min-height: 18px;
}

/* The uncertainty toggle sits with the findings line: both are commentary on the plots above. */
.uncertainty-row {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    margin: 0 0 8px;
    font-size: 13px;
}

.uncertainty-row .check {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    margin: 0;
    cursor: pointer;
}

#uncertainty-readout strong {
    font-variant-numeric: tabular-nums;
}

.baffle-choice,
.baffle-size {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    margin: 0;
}

.baffle-size {
    flex-wrap: wrap;
    gap: 10px;
}

.baffle-size label {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    margin: 0;
    color: var(--muted);
}

.baffle-size input {
    /* In em of the monospace face these now use: room for a four-digit millimeter and a minus sign. */
    width: 6em;
}

/* --- Verdict and design space -------------------------------------------- */

.verdict {
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 12px 14px;
    margin: 0 0 12px;
    background: var(--surface);
}

.verdict > header {
    margin-bottom: 8px;
}

.verdict header label {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    margin: 0;
    font-size: 13px;
    color: var(--muted);
}

.verdict-text p,
.verdict > p {
    margin: 0 0 6px;
    font-size: 14px;
    line-height: 1.5;
    /* The box sits in the plot column, which is now as wide as the window allows. The plots want
       that width; a sentence does not, so the prose here keeps a readable measure. */
    max-width: 85ch;
}

.verdict-text p:last-child {
    margin-bottom: 0;
}

/* Shorter than the response plots (it is a locator, not a curve to study) but tall enough for the
   rotated y-axis label to fit, which 150px was not: it cut "…(Hz)" off the end. */
.design-space {
    height: 230px;
    margin-top: 10px;
}

/*
 * The enclosure description: the first line of the guidance box, so it leads rather than trails.
 *
 * Qualified with the parent because `.verdict > p` above is more specific than a bare class and would
 * otherwise win the margin, leaving the padding applied but the compensating pull-back not, which sets
 * this paragraph six pixels right of every other one in the box.
 */
.verdict > p.enclosure-note {
    /* Padded so the highlight below reads as a deliberate band rather than a stripe behind the text,
       and pulled back by the same amount so the words stay aligned with the paragraphs under them. */
    margin: 0 0 8px -6px;
    padding: 4px 6px;
    border-radius: 4px;
    font-size: 14px;
    line-height: 1.5;
    max-width: 85ch;
}

/*
 * Changing the enclosure type replaces this paragraph with a different one, and a paragraph that
 * silently becomes a different paragraph is easy to miss. The highlight says "this changed" and then
 * gets out of the way.
 */
@keyframes enclosure-note-flash {
    from { background-color: var(--flash); }
    to { background-color: transparent; }
}

.enclosure-note.flash {
    animation: enclosure-note-flash 2.1s ease-out;
}

/* Anyone who has asked for less motion gets the highlight without the fade doing the talking. */
@media (prefers-reduced-motion: reduce) {
    .enclosure-note.flash {
        animation: enclosure-note-flash 0.01s linear;
    }
}

/* --- Suggested boxes ------------------------------------------------------ */

.suggest-row {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.suggestions {
    display: grid;
    /* As many cards as fit, each wide enough for its figures line to stay on one row. */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
    margin-top: 10px;
}

.suggestion {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--bg);
}

.suggestion.current {
    border-color: var(--accent);
}

/* Still shown, grayed out: which alignments a driver cannot reach is worth knowing. */
.suggestion.unavailable {
    opacity: 0.7;
    border-style: dashed;
}

.suggestion h3 {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    margin: 0;
    font-size: 15px;
}

.suggestion-target {
    font-size: 12px;
    font-weight: 400;
    color: var(--muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.suggestion-figures {
    margin: 0;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
}

.suggestion-why {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: var(--muted);
}

/* --- Summary tiles -------------------------------------------------------- */

.summary-strip {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
    margin: 12px 0 0;
    padding: 0;
}

.summary-strip > div {
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 8px 10px;
    background: var(--bg);
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.summary-strip dt {
    font-size: 12px;
    color: var(--muted);
    margin: 0;
    /* The dotted underline is the learning layer's one affordance; keep it visible here. */
    width: fit-content;
}

/* On a tile the symbol is what a reader looks for once they know the vocabulary, so here it is the
   prominent half of the label rather than the quiet one. Elsewhere .symbol stays as it was. */
.summary-strip .symbol {
    font-size: 15px;
    font-weight: 600;
    opacity: 1;
    color: var(--fg);
}

.summary-strip .learn-mark.icon {
    font-size: 0.85rem;
    vertical-align: -0.12em;
}

.summary-strip dt .trailing {
    white-space: nowrap;
}

.summary-strip dd {
    margin: 0;
    font-size: 18px;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

/* What this kind of speaker usually reaches, so a number is not left without an anchor. */
.summary-strip .usual {
    font-size: 11px;
    color: var(--muted);
    line-height: 1.3;
}

.summary-strip .usual.outside {
    color: var(--warn);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .summary-strip > div {
        background: var(--surface);
    }
}

/* The symbol beside a plain name: present for anyone who wants it, quiet for anyone who does not. */
.symbol {
    font-size: 0.85em;
    opacity: 0.65;
    font-variant-numeric: tabular-nums;
}

.symbol:before {
    content: "· ";
}

/* A disabled control must look disabled. Without this the Delete button on a lone design was
   indistinguishable from a working one, so clicking it looked like a bug rather than a refusal. */
.button:disabled,
.button[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
}

/* The design name is editable; it needs to look it. */
.design-label {
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    padding: 2px 6px;
    font: inherit;
    color: inherit;
    min-width: 0;
    flex: 1;
}

.design-label:hover {
    border-color: var(--line);
    background: var(--bg);
}

.design-label:focus {
    border-color: var(--accent);
    background: var(--bg);
    outline: none;
}

.saved-designs {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
}

.saved-designs h2 {
    font-size: 13px;
    color: var(--muted);
    margin: 0 0 6px;
}

.saved-list {
    list-style: none;
    margin: 0 0 8px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.saved-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
}

.saved-list li a {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.saved-list li.current a {
    font-weight: 600;
}

/* "Project" said out loud. Without a visible label the name field reads as naming a design rather than
   the thing that contains them, which is the distinction the whole panel depends on. */
.project-label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    margin-bottom: 1px;
}

#project-contents {
    margin: 2px 0 0;
}

/* A label that only a screen reader needs: the icon-only action column's header. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.data td.actions-cell {
    width: 1%;
    white-space: nowrap;
    text-align: right;
}

/* Measured curves belong to the driver, so they sit apart from the design list. */
.measured { margin-top: 1rem; border-top: 1px solid var(--rule, #d8d8d8); padding-top: 0.75rem; }
.measured-heading { font-size: 0.95rem; margin: 0 0 0.25rem; }
.measured-list { list-style: none; margin: 0.5rem 0 0; padding: 0; }
.measured-list > li + li { margin-top: 0.6rem; }
.measured-conditions { margin: 0.1rem 0 0 1.55rem; line-height: 1.35; }

/* A record known to be wrong, said where somebody is choosing or building. */
.icon.data-warning { color: var(--warn-fg, #a15c00); font-size: 1rem; cursor: help; }
.callout.warn {
    background: var(--warn-bg, #fff6e5);
    border-left: 3px solid var(--warn-fg, #a15c00);
    padding: 0.5rem 0.7rem;
    margin: 0.5rem 0 0;
}
.callout.warn .icon { color: var(--warn-fg, #a15c00); font-size: 1rem; }

/* Out of production, said on the name rather than in a footnote. */
.badge.discontinued {
    background: var(--warn-bg);
    color: var(--warn);
    border: 1px solid var(--warn);
}

/* Somebody else's published test. Links out, never copies. */
.link-list { list-style: none; margin: 0.6rem 0 0; padding: 0; }
.link-list > li + li { margin-top: 0.7rem; }
.link-line { display: flex; align-items: center; gap: 0.5rem; margin: 0; flex-wrap: wrap; }
.link-line .badge.subtle {
    background: var(--surface);
    color: var(--muted);
    border: 1px solid var(--line);
    font-weight: 500;
}
.link-line .button { margin-inline-start: auto; }
.link-title { margin: 0.1rem 0 0; }

/* A recognized publisher reads as a name; anything else reads as the address it is. The difference is
   the only claim this page makes about a link, so it has to be visible without being an accusation. */
.publisher.known { font-weight: 600; }
.publisher.unknown { font-weight: 400; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; }
.publisher .icon { font-size: 0.9rem; vertical-align: -0.12em; }

.link-form { display: flex; gap: 0.5rem; margin-top: 0.9rem; flex-wrap: wrap; }
.link-form input[type="url"] { flex: 2 1 18rem; }
.link-form input[type="text"] { flex: 1 1 12rem; }

/* The two flag columns on the driver list: narrow, and never the reason the table gets wider. */
table.data th.flag, table.data td.flag { white-space: nowrap; width: 1%; text-align: center; }
table.data td.flag .badge { font-size: 11px; }

/* The warning is behind a button, not a tooltip: a tooltip cannot be reached on a touch screen, and
   this is the one thing on the row that a reader must not miss. */
.flag-button {
    background: none;
    border: 0;
    padding: 0.1rem 0.3rem;
    cursor: pointer;
    line-height: 1;
    border-radius: 4px;
}
.flag-button:hover, .flag-button:focus-visible { background: var(--warn-bg); }
.warning-detail[hidden] { display: none; }
.warning-detail > td { padding: 0 0 0.5rem; }
.warning-detail .callout.warn { margin: 0; }

/* "Somebody has measured this one." A pointer to the tests, not a mark of quality. */
.tested-flag { color: var(--accent); text-decoration: none; line-height: 1; }
.tested-flag:hover { text-decoration: none; opacity: 0.75; }
.tested-flag .icon { font-size: 1.05rem; vertical-align: -0.18em; }

/* Nobody has established whether this is still made. Quieter than the discontinued badge, because it
   is a gap in what we know rather than a fact about the driver, but visible, because the whole point
   of the third state is that it must not read as "confirmed in production". */
.badge.unchecked {
    background: var(--surface);
    color: var(--muted);
    border: 1px dashed var(--line);
    font-weight: 500;
}
