/*
 * Thermal Architect
 *
 * The look is meant to get out of the way. An engineering tool is read for
 * hours at a time by someone comparing numbers, so the rules it follows are:
 *
 *   One accent. Teal marks what is actionable and what has been solved, and
 *   nothing else. Everywhere a colour carries meaning it carries exactly one:
 *   warm for a thermal part, teal for a fluid one, violet for a board.
 *
 *   Numbers are monospaced and tabular, always, so a column of them lines up
 *   on the decimal point and can be scanned rather than read.
 *
 *   Units are visible but subordinate. An engineer needs to know a figure is
 *   in kelvin per watt; they do not need it shouting.
 *
 *   Flat. No gradients, no shadows doing work a rule could do, no rounding
 *   past what a panel needs. Depth is reserved for things that genuinely float
 *   above the page: a dragged node, a modal.
 */

:root {
    /* Neutrals. A single ramp, cool enough not to look beige next to the teal
       and warm enough not to look like a spreadsheet. */
    --ink:        #171b21;
    --ink-mid:    #3d4551;
    --ink-soft:   #5b6472;
    --ink-faint:  #687180;      /* 4.9:1 on white, 4.6:1 on --field: AA for the small text it carries */
    --rule:       #e1e5ea;
    --rule-firm:  #c7cdd6;
    --panel:      #ffffff;
    --shell:      #e3e7ec;
    --field:      #f6f8fa;
    --canvas:     #eef0f3;
    --grid:       #cfd5dd;

    /* The accent, and the three domain marks. */
    --brand:      #0d6e66;
    --brand-deep: #095049;
    --brand-pale: #e0efed;
    --warm:       #c2521f;      /* thermal parts */
    --cool:       #3f7fd6;      /* boundaries */
    --board:      #6d46a6;      /* PCBs */
    --danger:     #a92218;
    --ok:         #1b6b40;

    --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;
    --sans: 'Inter', 'Segoe UI Variable Text', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;

    --topbar-h: 50px;

    /* Text on a filled control (a primary button, a toast, a tooltip). */
    --on-fill:    #fff;
    /* Translucent panel colour, as "R G B" for rgb(var(--glass) / alpha). */
    --glass:      255 255 255;
    color-scheme: light;

    /* The light theme's remaining colours, named so the dark theme can
       restate them. Generated from the literals they replaced. */
    --c-008a7c: #008a7c;
    --c-12161b: #12161b;
    --c-2e7d4f: #2e7d4f;
    --c-2f5b9a: #2f5b9a;
    --c-3b2a0c: #3b2a0c;
    --c-3f8c84: #3f8c84;
    --c-5b3a00: #5b3a00;
    --c-5f3a91: #5f3a91;
    --c-5f9e97: #5f9e97;
    --c-6b2a8a: #6b2a8a;
    --c-6b2a8a33: #6b2a8a33;
    --c-6b5a8a: #6b5a8a;
    --c-6e4a00: #6e4a00;
    --c-6fa8a2: #6fa8a2;
    --c-7b4fb5: #7b4fb5;
    --c-7d1a14: #7d1a14;
    --c-7d8492: #7d8492;
    --c-7fb1ab: #7fb1ab;
    --c-8a4b0f: #8a4b0f;
    --c-8c3a14: #8c3a14;
    --c-94a89b: #94a89b;
    --c-9aa1ad: #9aa1ad;
    --c-9aa3ae: #9aa3ae;
    --c-9fe0d8: #9fe0d8;
    --c-a9adb6: #a9adb6;
    --c-b0643a: #b0643a;
    --c-b3261e: #b3261e;
    --c-b5d6c2: #b5d6c2;
    --c-b9c0c8: #b9c0c8;
    --c-c2521f: #c2521f;
    --c-c98500: #c98500;
    --c-c98a2c: #c98a2c;
    --c-c9d8f2: #c9d8f2;
    --c-ccd3dc: #ccd3dc;
    --c-cfe3d6: #cfe3d6;
    --c-d9dde3: #d9dde3;
    --c-d9e6dd: #d9e6dd;
    --c-dde6e0: #dde6e0;
    --c-dfeaf9: #dfeaf9;
    --c-e3f1e8: #e3f1e8;
    --c-e4f1e9: #e4f1e9;
    --c-e5f2ea: #e5f2ea;
    --c-e6c98a: #e6c98a;
    --c-e6c9c6: #e6c9c6;
    --c-e7b7b2: #e7b7b2;
    --c-e9ebef: #e9ebef;
    --c-e9edf1: #e9edf1;
    --c-ecd3a6: #ecd3a6;
    --c-ece3f6: #ece3f6;
    --c-edf2fb: #edf2fb;
    --c-edf4ef: #edf4ef;
    --c-eef0f3: #eef0f3;
    --c-eef3fb: #eef3fb;
    --c-eef7ef: #eef7ef;
    --c-f0cfcc: #f0cfcc;
    --c-f0d9bb: #f0d9bb;
    --c-f4f9f6: #f4f9f6;
    --c-f6f7f9: #f6f7f9;
    --c-f8e3e1: #f8e3e1;
    --c-fbe6da: #fbe6da;
    --c-fbeceb: #fbeceb;
    --c-fbf4ec: #fbf4ec;
    --c-fdf3df: #fdf3df;
    --c-fdf3e7: #fdf3e7;
    --c-fdf3e8: #fdf3e8;
    --c-fdf3ee: #fdf3ee;
    --c-fdf5f4: #fdf5f4;
    --c-fdf8f1: #fdf8f1;
    --c-fffaf7: #fffaf7;
}

/* ---------------------------------------------------------------- dark theme

   Follows the system unless the reader chose (View → Theme, saved in this
   browser): data-theme="light" or "dark" on <html> wins either way. The two
   blocks are the same list; CSS has no way to share it between a media query
   and an attribute selector. */
:root[data-theme="dark"] {
    color-scheme: dark;
    --ink:        #e4e8ee;
    --ink-mid:    #c5ccd6;
    --ink-soft:   #a6aeba;
    --ink-faint:  #8f98a5;      /* 5.6:1 on --panel */
    --rule:       #2b3139;
    --rule-firm:  #3b434e;
    --panel:      #1a1e24;
    --shell:      #111418;
    --field:      #222830;
    --canvas:     #15181d;
    --grid:       #262c34;
    --brand:      #3bb3a5;
    --brand-deep: #5fcabd;
    --brand-pale: #173a36;
    --warm:       #e27b4b;
    --cool:       #6aa2ee;
    --board:      #a688dc;
    --danger:     #f2776c;
    --ok:         #55c287;
    --amber:      #e8a54a;
    --amber-pale: #3a2c12;
    --ok-pale:    #16301f;
    --bad-pale:   #3a1a18;
    --on-fill:    #0e1114;
    --glass:      26 30 36;

    /* Every other colour of the light theme, at a dark ground's lightness. */
    --c-008a7c: #8cf2e8;
    --c-12161b: #d6dbe1;
    --c-2e7d4f: #91ccaa;
    --c-2f5b9a: #5b86c5;
    --c-3b2a0c: #eee1c8;
    --c-3f8c84: #6bb6af;
    --c-5b3a00: #f7dfb6;
    --c-5f3a91: #8b66bb;
    --c-5f9e97: #97bdb9;
    --c-6b2a8a: #9a4bc0;
    --c-6b2a8a33: #9a4bc033;
    --c-6b5a8a: #988bb0;
    --c-6e4a00: #f5dba5;
    --c-6fa8a2: #a7c7c3;
    --c-7b4fb5: #a98fcb;
    --c-7d1a14: #e39995;
    --c-7d8492: #adb1b9;
    --c-7fb1ab: #aecbc8;
    --c-8a4b0f: #e6b68a;
    --c-8c3a14: #e1a487;
    --c-94a89b: #b7c3bb;
    --c-9aa1ad: #b7bbc3;
    --c-9aa3ae: #b6bcc3;
    --c-9fe0d8: #316861;
    --c-a9adb6: #575a62;
    --c-b0643a: #cb9475;
    --c-b3261e: #d9564f;
    --c-b5d6c2: #385443;
    --c-b9c0c8: #454b52;
    --c-c2521f: #dc845b;
    --c-c98500: #f4b02c;
    --c-c98a2c: #d9b072;
    --c-c9d8f2: #2a3a55;
    --c-ccd3dc: #31373f;
    --c-cfe3d6: #3a4d40;
    --c-d9dde3: #3a3e44;
    --c-d9e6dd: #37443b;
    --c-dde6e0: #37413a;
    --c-dfeaf9: #1f2f45;
    --c-e3f1e8: #2b3e31;
    --c-e4f1e9: #2b3d32;
    --c-e5f2ea: #293c31;
    --c-e6c98a: #7a622e;
    --c-e6c9c6: #472c29;
    --c-e7b7b2: #562c28;
    --c-e9ebef: #2e3137;
    --c-e9edf1: #2b3137;
    --c-ecd3a6: #614b24;
    --c-ece3f6: #312440;
    --c-edf2fb: #1c273a;
    --c-edf4ef: #28342c;
    --c-eef0f3: #2a2d33;
    --c-eef3fb: #1c2739;
    --c-eef7ef: #243526;
    --c-f0cfcc: #522f2c;
    --c-f0d9bb: #513b1f;
    --c-f4f9f6: #222f27;
    --c-f6f7f9: #24262c;
    --c-f8e3e1: #432421;
    --c-fbe6da: #4a2d1d;
    --c-fbeceb: #3c1e1c;
    --c-fbf4ec: #3b2d1c;
    --c-fdf3df: #483819;
    --c-fdf3e7: #422f18;
    --c-fdf3e8: #412d18;
    --c-fdf3ee: #3c2418;
    --c-fdf5f4: #361b18;
    --c-fdf8f1: #392b18;
    --c-fffaf7: #392011;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --ink:        #e4e8ee;
        --ink-mid:    #c5ccd6;
        --ink-soft:   #a6aeba;
        --ink-faint:  #8f98a5;      /* 5.6:1 on --panel */
        --rule:       #2b3139;
        --rule-firm:  #3b434e;
        --panel:      #1a1e24;
        --shell:      #111418;
        --field:      #222830;
        --canvas:     #15181d;
        --grid:       #262c34;
        --brand:      #3bb3a5;
        --brand-deep: #5fcabd;
        --brand-pale: #173a36;
        --warm:       #e27b4b;
        --cool:       #6aa2ee;
        --board:      #a688dc;
        --danger:     #f2776c;
        --ok:         #55c287;
        --amber:      #e8a54a;
        --amber-pale: #3a2c12;
        --ok-pale:    #16301f;
        --bad-pale:   #3a1a18;
        --on-fill:    #0e1114;
        --glass:      26 30 36;

        /* Every other colour of the light theme, at a dark ground's lightness. */
        --c-008a7c: #8cf2e8;
        --c-12161b: #d6dbe1;
        --c-2e7d4f: #91ccaa;
        --c-2f5b9a: #5b86c5;
        --c-3b2a0c: #eee1c8;
        --c-3f8c84: #6bb6af;
        --c-5b3a00: #f7dfb6;
        --c-5f3a91: #8b66bb;
        --c-5f9e97: #97bdb9;
        --c-6b2a8a: #9a4bc0;
        --c-6b2a8a33: #9a4bc033;
        --c-6b5a8a: #988bb0;
        --c-6e4a00: #f5dba5;
        --c-6fa8a2: #a7c7c3;
        --c-7b4fb5: #a98fcb;
        --c-7d1a14: #e39995;
        --c-7d8492: #adb1b9;
        --c-7fb1ab: #aecbc8;
        --c-8a4b0f: #e6b68a;
        --c-8c3a14: #e1a487;
        --c-94a89b: #b7c3bb;
        --c-9aa1ad: #b7bbc3;
        --c-9aa3ae: #b6bcc3;
        --c-9fe0d8: #316861;
        --c-a9adb6: #575a62;
        --c-b0643a: #cb9475;
        --c-b3261e: #d9564f;
        --c-b5d6c2: #385443;
        --c-b9c0c8: #454b52;
        --c-c2521f: #dc845b;
        --c-c98500: #f4b02c;
        --c-c98a2c: #d9b072;
        --c-c9d8f2: #2a3a55;
        --c-ccd3dc: #31373f;
        --c-cfe3d6: #3a4d40;
        --c-d9dde3: #3a3e44;
        --c-d9e6dd: #37443b;
        --c-dde6e0: #37413a;
        --c-dfeaf9: #1f2f45;
        --c-e3f1e8: #2b3e31;
        --c-e4f1e9: #2b3d32;
        --c-e5f2ea: #293c31;
        --c-e6c98a: #7a622e;
        --c-e6c9c6: #472c29;
        --c-e7b7b2: #562c28;
        --c-e9ebef: #2e3137;
        --c-e9edf1: #2b3137;
        --c-ecd3a6: #614b24;
        --c-ece3f6: #312440;
        --c-edf2fb: #1c273a;
        --c-edf4ef: #28342c;
        --c-eef0f3: #2a2d33;
        --c-eef3fb: #1c2739;
        --c-eef7ef: #243526;
        --c-f0cfcc: #522f2c;
        --c-f0d9bb: #513b1f;
        --c-f4f9f6: #222f27;
        --c-f6f7f9: #24262c;
        --c-f8e3e1: #432421;
        --c-fbe6da: #4a2d1d;
        --c-fbeceb: #3c1e1c;
        --c-fbf4ec: #3b2d1c;
        --c-fdf3df: #483819;
        --c-fdf3e7: #422f18;
        --c-fdf3e8: #412d18;
        --c-fdf3ee: #3c2418;
        --c-fdf5f4: #361b18;
        --c-fdf8f1: #392b18;
        --c-fffaf7: #392011;

    }
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* `display` on a class beats the `hidden` attribute's own display:none, which
   has caught this stylesheet twice: a closed modal that stayed laid out as an
   invisible full-screen click trap, and the transient's parameters showing in
   steady-state mode because .field-row is a grid. One rule, once, rather than
   remembering to pair every display with a [hidden] of its own. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--shell);
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
}

.mono, td.num, th.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- top bar */

.topbar {
    height: var(--topbar-h);
    background: var(--panel);
    border-bottom: 1px solid var(--rule);
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 14px;
}

.brand { display: flex; align-items: center; gap: 9px; }

.mark rect { fill: none; stroke: var(--ink); stroke-width: 1.5; }
.mark .mark-flow { stroke: var(--brand); stroke-width: 1.5; stroke-linecap: round; }

.wordmark {
    font-size: 14px;
    letter-spacing: -.012em;
    color: var(--ink);
    white-space: nowrap;
}
.wordmark strong { font-weight: 650; }

/* The document title, the way a desktop application shows one: the name of
   the thing you have open, and its state, directly under the application's
   own name. It is an input, not a label - renaming costs one click. */
.doc {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding-left: 14px;
    border-left: 1px solid var(--rule);
    min-width: 0;
}

.doc input {
    font: inherit;
    font-size: 13.5px;
    font-weight: 500;
    width: 210px;
    padding: 4px 7px;
    border: 1px solid transparent;
    border-radius: 4px;
    background: none;
    color: var(--ink);
}
.doc input:hover { border-color: var(--rule); }
.doc input:focus { border-color: var(--rule-firm); background: var(--panel); outline: none; }

.model-state {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ink-faint);
    white-space: nowrap;
}
.model-state.solved { color: var(--brand); }
.model-state.stale  { color: var(--warm); }

/* Where the model is kept: this browser, or the project (history.js). Quiet
   unless something needs doing. */
.save-state {
    font-size: 11px;
    color: var(--ink-faint);
    white-space: nowrap;
    cursor: default;
}
.save-state.pending { color: var(--ink-soft); }
.save-state.warn    { color: var(--warm); font-weight: 600; }
.save-state:empty   { display: none; }

.grow { margin-left: auto; }

.toolbar { display: flex; align-items: center; gap: 8px; }
.tool-rule { width: 1px; height: 20px; background: var(--rule); }

/* File operations as a welded group of icon buttons, the way every desktop
   application puts them: four glyphs everyone already knows, in the width
   their labels would have taken for one of them. */
.tool-group {
    display: flex;
    align-items: center;
    gap: 2px;
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 28px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 5px;
    background: none;
    color: var(--ink-mid);
}

.icon-btn svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.35;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.icon-btn:hover:not(:disabled) {
    background: var(--field);
    border-color: var(--rule-firm);
    color: var(--ink);
}
.icon-btn:disabled { opacity: .4; }
.icon-btn.small { width: 24px; height: 22px; }
.icon-btn.small svg { width: 13px; height: 13px; }

.toolbar select {
    padding: 6px 8px;
    max-width: 150px;
}

button, .toolbar select, .pcb-tools select {
    font: inherit;
    font-size: 13px;
    padding: 6px 12px;
    border-radius: 5px;
    border: 1px solid var(--rule-firm);
    background: var(--panel);
    color: var(--ink-mid);
    cursor: pointer;
}

/* Buttons only: a select's background is its arrow and divider (below), and
   the shorthand here reset their repeat and size, tiling the 7 px arrow
   across the whole control on hover. */
button:hover:not(:disabled) {
    background: var(--field);
    border-color: var(--ink-faint);
    color: var(--ink);
}
button:disabled { opacity: .45; cursor: default; }

button.primary {
    background: var(--brand);
    border-color: var(--brand);
    color: var(--on-fill);
    font-weight: 600;
}
button.primary:hover:not(:disabled) { background: var(--brand-deep); border-color: var(--brand-deep); color: var(--on-fill); }

/* A visible focus ring is not decoration here. This is a tool driven with the
   keyboard as much as the mouse, and losing your place in it is expensive. */
:where(button, a, input, select, textarea, .chip):focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}
/* Buttons carry their own borders and backgrounds in many places; the ring
   above has no specificity, so restate it where it must win. */
button:focus-visible, button.primary:focus-visible, .apage button:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------- tooltips

   The explanations that used to sit permanently under every control. See
   ui.js for why these are positioned from script rather than from CSS: a tip
   on something inside a scrolling panel has to escape that panel's clip. */

.tip-bubble {
    position: fixed;
    z-index: 90;
    max-width: 268px;
    padding: 7px 10px;
    border-radius: 5px;
    background: var(--ink);
    color: var(--on-fill);
    font-size: 12px;
    line-height: 1.45;
    box-shadow: 0 6px 18px rgba(23,27,33,.22);
    pointer-events: none;      /* never swallow the click it is sitting over */
}
.tip-bubble[hidden] { display: none; }

/* The arrow. Flips with the bubble, which flips when there is no room above. */
.tip-bubble::after {
    content: "";
    position: absolute;
    left: 50%;
    margin-left: -5px;
    border: 5px solid transparent;
    border-top-color: var(--ink);
    top: 100%;
}
.tip-bubble.below::after {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--ink);
}

/* The "what is this" affordance, for explanations with no natural host. */
.tip-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    padding: 0;
    margin-left: 5px;
    border: 1px solid var(--rule-firm);
    border-radius: 50%;
    background: none;
    color: var(--ink-faint);
    font-family: var(--sans);
    font-size: 9.5px;
    font-weight: 700;
    font-style: italic;
    line-height: 1;
    vertical-align: 1px;
    cursor: help;
}
.tip-mark:hover:not(:disabled) {
    background: none;
    border-color: var(--ink-soft);
    color: var(--ink-soft);
}

/* ---------------------------------------------------------------- frame */

.frame {
    --left-w: 260px;
    --right-w: 320px;
    height: calc(100% - var(--topbar-h));
    display: grid;
    grid-template-columns: var(--left-w) 0 minmax(360px, 1fr) 0 var(--right-w);
    grid-template-rows: minmax(0, 1fr) 24px;
    background: var(--rule);
    column-gap: 0;
}

.side, .stage {
    background: var(--panel);
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.stage { background: var(--canvas); }

/* A panel header reads as a title bar: small, set in caps, and the same on
   every panel, so the eye finds the boundaries between them without a rule
   having to shout. */
.panel-head {
    flex: none;
    height: 32px;
    padding: 0 8px 0 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-soft);
    border-bottom: 1px solid var(--rule);
    background: var(--field);
}

.head-actions { display: flex; align-items: center; gap: 1px; }

/* What is selected, beside the Properties title. Not uppercase: it is a value,
   not a label, and it changes every time you click something. */
.props-kind {
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-faint);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.panel-body { padding: 12px; overflow-y: auto; flex: 1; min-height: 0; }

.hint { color: var(--ink-soft); font-size: 12.5px; line-height: 1.5; }

/* ------------------------------------------------- segmented controls

   One question, a few answers, one of them on. Used for the analysis mode and
   for which domain the insert palette is showing. Both replace a stack of
   controls that were all live at once. */

.seg {
    display: flex;
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    overflow: hidden;
    background: var(--field);
}

.seg-btn {
    flex: 1 1 0;
    min-width: 0;
    font: inherit;
    font-size: 12px;
    padding: 6px 4px;
    border: 0;
    border-right: 1px solid var(--rule-firm);
    border-radius: 0;
    background: none;
    color: var(--ink-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.seg-btn:last-child { border-right: 0; }
.seg-btn:hover:not(.on) { background: var(--panel); color: var(--ink); border-color: var(--rule-firm); }

.seg-btn.on {
    background: var(--panel);
    color: var(--ink);
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--brand);
}

/* ------------------------------------------------- right rail

   Two panels, not one scroll. The run controls stay put while the properties
   below them scroll, because what you are about to run and what you are
   editing are different questions and the first must not scroll away. */

.side.rail-right { display: flex; flex-direction: column; min-height: 0; }


.solve { width: 100%; padding: 9px 12px; font-size: 13.5px; }

.props {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--rule);
}

/* ---------------------------------------------------------------- parts */

/* One line each. The sentence that used to sit under every name is a tooltip
   now: read once on the first day, then pure width for the next year. */
.chip {
    display: block;
    width: 100%;
    padding: 7px 10px;
    margin-bottom: 6px;
    border: 1px solid var(--rule-firm);
    border-left: 3px solid var(--cool);
    border-radius: 5px;
    background: var(--panel);
    cursor: grab;
    text-align: left;
    touch-action: none;
}

.chip:hover { background: var(--field); border-color: var(--ink-soft); border-left-color: var(--cool); }
.chip.component { border-left-color: var(--warm); }
.chip.component:hover { border-left-color: var(--warm); }
.chip strong { display: block; font-size: 12.5px; font-weight: 600; line-height: 1.3; }
.chip span { display: block; color: var(--ink-soft); font-size: 11px; margin-top: 1px; }

details.tips { margin-top: 14px; border-top: 1px solid var(--rule); padding-top: 12px; }
details.tips summary { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); cursor: pointer; }
details.tips summary::marker { color: var(--ink-faint); }
details.tips p { margin-top: 9px; }

/* ---------------------------------------------------------------- canvas */

.canvas-wrap {
    position: relative;
    background: var(--canvas);
    background-image: radial-gradient(circle, var(--grid) 1px, transparent 1px);
    background-size: 22px 22px;
    overflow: hidden;
    cursor: grab;
    touch-action: none;
    flex: 1;
    min-height: 0;
}

.canvas-wrap.panning { cursor: grabbing; }

#world { position: absolute; inset: 0; transform-origin: 0 0; }

#wires { position: absolute; left: -3000px; top: -3000px; width: 8000px; height: 8000px; overflow: visible; pointer-events: none; }
#wires .hit { stroke: transparent; stroke-width: 18; fill: none; pointer-events: stroke; cursor: pointer; }
#wires .wire { stroke: var(--c-9aa1ad); stroke-width: 2.5; fill: none; stroke-linecap: round; }
#wires .wire.selected { stroke: var(--brand); stroke-width: 3.5; }
#wires .wire.solved { stroke: var(--c-7d8492); }
#wires text { font-family: var(--mono); font-size: 11px; fill: var(--ink-soft); text-anchor: middle; paint-order: stroke; stroke: var(--canvas); stroke-width: 4px; }
#wires text.flow { fill: var(--ink); font-weight: 600; }
#wires text.reverses { fill: var(--warm); font-size: 10px; font-weight: 600; }
#wires .arrow { fill: var(--ink); stroke: var(--canvas); stroke-width: 1.5; paint-order: stroke; }

#draft-wire { stroke: var(--brand); stroke-width: 2.5; stroke-dasharray: 6 5; fill: none; }

.node {
    position: absolute;
    width: 172px;               /* the script positions links against this width */
    padding: 10px 12px;
    border-radius: 6px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-top: 3px solid var(--warm);
    box-shadow: 0 1px 3px rgba(29,34,41,.14);
    cursor: grab;
    user-select: none;
    touch-action: none;
}

.node.boundary { border-top-color: var(--cool); }
.node.selected { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-pale), 0 1px 3px rgba(29,34,41,.14); }
.node.link-target { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-pale); }
.node.dragging { cursor: grabbing; box-shadow: 0 8px 18px rgba(29,34,41,.2); }

.node-name { font-weight: 600; font-size: 13px; line-height: 1.3; overflow-wrap: anywhere; }
.node-meta { font-family: var(--mono); font-size: 10.5px; color: var(--ink-soft); margin-top: 3px; }

.node-temp {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 15px;
    font-weight: 600;
    margin-top: 7px;
    padding: 3px 7px;
    border-radius: 4px;
    background: var(--c-eef0f3);
    color: var(--ink-faint);
    display: inline-block;
}

.port {
    position: absolute;
    top: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    border-radius: 50%;
    background: var(--panel);
    border: 2.5px solid var(--brand);
    cursor: crosshair;
    touch-action: none;
}

.port-right { right: -8px; }
.port-left  { left: -8px; }

.port:hover { background: var(--brand); }
.node.boundary .port { border-color: var(--cool); }
.node.boundary .port:hover { background: var(--cool); }

.empty-canvas {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    color: var(--ink-soft);
    text-align: center;
    padding: 20px;
    pointer-events: none;
}

.empty-canvas strong { font-size: 15px; color: var(--ink); font-weight: 600; }
.empty-canvas span { font-size: 13px; }

.zoom-controls {
    position: absolute;
    right: 12px;
    bottom: 12px;
    display: flex;
    gap: 4px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    padding: 3px;
    box-shadow: 0 1px 4px rgba(29,34,41,.12);
}

.zoom-controls button { padding: 4px 10px; border: 0; background: none; }
.zoom-controls button:hover { background: var(--field); }

/* ---------------------------------------------------------------- forms */

/* ------------------------------------------------- property groups

   The inspector used to be one flat stack - name, type, capacitance, load,
   profile, four profile parameters, a chart and a delete button, all at the
   same level with a rule somewhere in the middle. Nothing said which fields
   belonged together, so every visit meant reading all of them. */

.pgroup { margin-bottom: 14px; }

.pgroup h3 {
    margin: 0 0 8px;
    padding-bottom: 5px;
    border-bottom: 1px solid var(--rule);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.pgroup .field:last-child,
.pgroup .field-row:last-child { margin-bottom: 0; }
/* Inside a pair the row carries the spacing, not its fields: the rule above
   caught the second field of every pair and dropped it 10px below the first. */
.pgroup .field-row { margin-bottom: 10px; }
.pgroup .field-row > .field { margin-bottom: 0; }
.pgroup .field-row:last-child { margin-bottom: 0; }

/* Which two things a link joins. A heading, not a sentence: it is the first
   thing you check and it used to cost three lines of prose. */
.ends {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 13px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.35;
    overflow-wrap: anywhere;
}
.ends span {
    font-weight: 400;
    font-size: 11px;
    color: var(--ink-faint);
    text-transform: uppercase;
    letter-spacing: .06em;
}

/* Destructive actions at the bottom, behind a rule, where nothing else is. */
.props-foot {
    display: flex;
    gap: 6px;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--rule);
}
.props-foot button { flex: 1; font-size: 12.5px; }
.props-foot button.danger { color: var(--danger); border-color: var(--c-e6c9c6); }
.props-foot button.danger:hover:not(:disabled) { background: var(--c-fbeceb); border-color: var(--danger); }

.field { margin-bottom: 10px; }
.field label { display: block; font-size: 12px; color: var(--ink-soft); margin-bottom: 3px; }

/* A label that carries an explanation says so, quietly. */
.field label[data-tip] {
    cursor: help;
    text-decoration: underline dotted var(--rule-firm);
    text-underline-offset: 3px;
}
.field label[data-tip]:hover { color: var(--ink); text-decoration-color: var(--ink-faint); }

.field input, .field select, .field textarea {
    width: 100%;
    padding: 5px 7px;
    border: 1px solid var(--rule-firm);
    border-radius: 2px;
    font-size: 13px;
    font-family: inherit;
    background: var(--panel);
    color: var(--ink);
}

.field textarea { font-family: var(--mono); font-size: 12px; resize: vertical; line-height: 1.5; }
.field input[type=number] { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-soft); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.field input:not([type=checkbox]):not([type=radio]) { height: 28px; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; align-items: end; }

.load-preview {
    border: 1px solid var(--rule);
    border-radius: 5px;
    padding: 8px 10px 6px;
    background: var(--field);
    margin-bottom: 11px;
}

.load-preview svg { width: 100%; height: 54px; display: block; }
.load-caption { font-family: var(--mono); font-size: 10.5px; color: var(--ink-soft); margin-top: 5px; }

.section-rule { border: 0; border-top: 1px solid var(--rule); margin: 14px 0 13px; }

.run-row { display: flex; gap: 8px; }
.run-row button { flex: 1; }

/* Read-only key/value rows in the inspector: what a board or a port IS, as
   against the fields that change it. Written by the board inspectors and never
   given a style, so they ran together as "Size120.0 x 90.0 x 1.60 mm" - the
   label and the value indistinguishable, which is the one thing a readout has
   to get right. */
.rows {
    margin-bottom: 12px;
    border-top: 1px solid var(--rule);
}

.rows .row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 10px;
    padding: 7px 0;
    border-bottom: 1px solid var(--rule);
}

.rows .k {
    font-size: 12px;
    color: var(--ink-soft);
    min-width: 0;
}

/* The qualifier under a label - "in plane / through" - is part of the label,
   not a second row, so it drops beneath it rather than pushing the value out. */
.rows .k small {
    display: block;
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--ink-faint);
}

.rows .v {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 12px;
    color: var(--ink);
    text-align: right;
    white-space: nowrap;
}

.link-note {
    font-family: var(--mono);
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--ink-soft);
    background: var(--field);
    border-radius: 5px;
    padding: 9px 10px;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- drawer */

.drawer {
    grid-column: 1 / -1;
    background: var(--panel);
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.drawer-bar {
    flex: none;
    height: 38px;
    display: flex;
    align-items: stretch;
    gap: 2px;
    padding: 0 8px 0 4px;
    border-bottom: 1px solid var(--rule);
    background: var(--field);
    position: relative;
}

.drawer-grip {
    position: absolute;
    top: -3px;
    left: 0;
    right: 0;
    height: 7px;
    cursor: ns-resize;
}

.drawer-tab {
    border: 0;
    background: none;
    border-radius: 0;
    border-bottom: 2px solid transparent;
    padding: 0 14px;
    font-size: 13px;
    color: var(--ink-soft);
    cursor: pointer;
}

.drawer-tab:hover:not(:disabled) { background: transparent; color: var(--ink); }

.drawer-tab[aria-selected='true'] {
    color: var(--ink);
    font-weight: 600;
    border-bottom-color: var(--brand);
}

.drawer-tab .dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--brand);
    margin-left: 6px;
    vertical-align: 1px;
    visibility: hidden;
}

.drawer-tab.fresh .dot { visibility: visible; }

.drawer-toggle {
    margin-left: auto;
    align-self: center;
    border: 0;
    background: none;
    color: var(--ink-soft);
    font-size: 12.5px;
    padding: 4px 8px;
}

.drawer-body {
    overflow-y: auto;
    padding: 16px 18px 22px;
    height: 300px;
    min-height: 0;
}

.drawer.shut .drawer-body { display: none; }
.drawer.shut .drawer-grip { cursor: default; }

.dock-panel { display: none; }
.dock-panel.on { display: block; }

/* results only has content once the network has been solved */
#results.dock-panel.on:not(.visible) { display: none; }
#results.dock-panel.on:not(.visible) ~ .dock-blank { display: flex; }

.dock-blank {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    text-align: center;
    color: var(--ink-soft);
    padding: 26px 20px;
}

.dock-blank strong { font-size: 14px; color: var(--ink); font-weight: 600; }
.dock-blank span { font-size: 13px; }

/* ---------------------------------------------------------------- tables and status */

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th { text-align: left; font-weight: 600; color: var(--ink-soft); font-size: 12px; padding: 6px 12px 6px 0; border-bottom: 1px solid var(--rule-firm); }
td { padding: 7px 12px 7px 0; border-bottom: 1px solid var(--rule); }
/* Numbers keep their unit on the same line, and adjacent number columns keep
   a gap: in a narrow pane "-4.77 W" wrapped and "12.41 °C0.00 W" ran together. */
td.num { text-align: right; padding-right: 0; padding-left: 14px; white-space: nowrap; }
th.num { text-align: right; padding-right: 0; padding-left: 14px; }
td.reversed { color: var(--warm); font-weight: 600; }

/* A column whose meaning is not obvious from its name says so, quietly. */
th[data-tip] {
    cursor: help;
    text-decoration: underline dotted rgb(var(--glass) / .55);
    text-underline-offset: 3px;
}
#mat-list th[data-tip] { text-decoration-color: var(--rule-firm); }

.status {
    font-size: 13px;
    padding: 10px 13px;
    border-radius: 5px;
    margin-bottom: 14px;
    display: none;
    line-height: 1.5;
    border-left: 3px solid transparent;
}

.status.visible { display: block; }
.status.ok { background: var(--c-edf4ef); color: var(--ok); border-left-color: var(--ok); }
.status.bad { background: var(--c-fbeceb); color: var(--danger); border-left-color: var(--danger); }

.warn-list {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(0,0,0,.08);
    font-size: 13px;
    line-height: 1.5;
}

.warn-list div + div { margin-top: 4px; }

.results-grid { display: grid; grid-template-columns: minmax(300px, 1fr) minmax(340px, 1.3fr); gap: 30px; align-items: start; }
.chart-title { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); margin-bottom: 8px; }
#chart { width: 100%; height: 260px; }
#load-chart { width: 100%; height: 150px; }
#chart .axis, #load-chart .axis { stroke: var(--rule-firm); stroke-width: 1; }
#chart .tick, #load-chart .tick { font-family: var(--mono); font-size: 10px; fill: var(--ink-faint); }
#chart .trace, #load-chart .trace { fill: none; stroke-width: 2; stroke-linejoin: round; }
.legend { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; font-size: 12.5px; }
.legend span { display: flex; align-items: center; gap: 6px; color: var(--ink-soft); }
.legend span.legend-more { color: var(--ink-faint); font-style: italic; }
.swatch { width: 14px; height: 3px; border-radius: 2px; }

/* ---------------------------------------------------------------- studies */

.mode-row { display: inline-flex; gap: 0; margin-bottom: 12px; border: 1px solid var(--rule-firm); border-radius: 5px; overflow: hidden; }

.mode {
    font: inherit;
    font-size: 13px;
    padding: 7px 16px;
    border: 0;
    border-right: 1px solid var(--rule-firm);
    border-radius: 0;
    background: var(--panel);
    color: var(--ink-soft);
    cursor: pointer;
}

.mode:last-child { border-right: 0; }
.mode:hover:not(.active) { background: var(--field); color: var(--ink); }

.mode.active {
    background: var(--brand-pale);
    color: var(--ink);
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--brand);
}

.study-grid {
    display: grid;
    grid-template-columns: minmax(290px, 360px) minmax(0, 1fr);
    gap: 30px;
    margin-top: 14px;
    align-items: start;
}

.form-block { margin-bottom: 18px; }
.form-block:empty { margin: 0; }

.block-title {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--ink-soft);
    margin-bottom: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--rule);
}

.param-row {
    border: 1px solid var(--rule);
    border-radius: 5px;
    padding: 12px 12px 3px;
    margin-bottom: 10px;
    background: var(--field);
}

.link-button {
    border: none;
    background: none;
    color: var(--brand);
    font-family: inherit;
    font-size: 13px;
    padding: 2px 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.link-button:hover { color: var(--brand-deep); background: none; }
.link-button.remove { color: var(--danger); margin-bottom: 10px; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }

.stat { border: 1px solid var(--rule); border-radius: 5px; padding: 9px 11px; background: var(--field); }
.stat span { display: block; font-size: 11.5px; color: var(--ink-soft); margin-bottom: 2px; }
.stat strong { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 14px; }

.opt-result {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    margin-top: 12px;
    padding: 11px 13px;
    border-radius: 5px;
    background: var(--brand-pale);
    border-left: 3px solid var(--brand);
}

.opt-label { font-size: 12.5px; color: var(--ink-soft); }
.opt-value { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; font-size: 15px; }

.table-scroll { overflow-x: auto; }
table.heatmap td.cell { color: #fff; font-weight: 600; text-align: center; padding: 7px 10px; }
table.heatmap th { white-space: nowrap; }

.advisor .status { margin-bottom: 14px; }
.advisor svg { width: 100%; display: block; }

/* ---------------------------------------------------------------- Engineer Advisor */

.advisor-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 10px 24px;
}
.advisor-brand { display: flex; flex-direction: column; gap: 2px; max-width: 62ch; }
.advisor-brand strong {
    font-size: 15px;
    letter-spacing: .01em;
    color: var(--ink);
}
.advisor-brand strong::before {
    content: "";
    display: inline-block;
    width: 8px; height: 8px;
    margin-right: 8px;
    border-radius: 2px;
    background: var(--brand);
    vertical-align: 1px;
}
.advisor-brand span { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; }
.advisor .mode-row { margin-bottom: 0; flex-wrap: wrap; }
.advisor .mode { padding: 7px 13px; }

.status.busy { display: block; background: var(--field); color: var(--ink-soft); border-left: 3px solid var(--rule-firm); }

.static-field {
    font-size: 12.5px;
    color: var(--ink-soft);
    padding: 7px 0;
}
.field.grow { flex: 1; min-width: 0; }
.change-row, .term-row {
    border-top: 1px dashed var(--rule-firm);
    padding-top: 8px;
    margin-top: 4px;
}
.term-row { display: flex; gap: 8px; align-items: flex-end; }
.term-row .field { margin-bottom: 8px; }
.term-row .field:not(.grow) { width: 96px; flex: none; }
.change-now { font-size: 11.5px; color: var(--ink-faint); margin: -4px 0 8px; font-family: var(--mono); }
.scenario-foot { display: flex; justify-content: space-between; padding: 4px 0 8px; }
.sub-modes { margin-bottom: 14px; }

/* results */

.kpi-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin-bottom: 18px;
}
.kpi {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 10px 12px;
    background: var(--panel);
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.kpi span { font-size: 11.5px; color: var(--ink-soft); }
.kpi strong {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 18px;
    font-weight: 600;
    color: var(--ink);
    overflow-wrap: anywhere;
}
.kpi small { font-size: 11.5px; color: var(--ink-soft); overflow-wrap: anywhere; }
.kpi.good { border-left: 3px solid var(--ok); }
.kpi.bad { border-left: 3px solid var(--danger); }

.advisor-section { margin: 0 0 22px; }
.advisor-section h4 {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin: 0 0 10px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--rule);
}
.advisor-section .hint { font-size: 12px; margin-top: 8px; max-width: 80ch; }

.bar-rows, .diverge-rows, .tornado { display: grid; gap: 6px; }
.bar-row, .diverge-row, .t-row {
    display: grid;
    grid-template-columns: minmax(120px, 34%) minmax(0, 1fr) minmax(92px, auto);
    align-items: center;
    gap: 10px;
    font-size: 12.5px;
}
.bar-row.clickable { cursor: pointer; }
.bar-row.clickable:hover .bar-label { color: var(--brand-deep); text-decoration: underline; }
.bar-label { color: var(--ink-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track, .diverge-track, .t-track {
    position: relative;
    height: 14px;
    background: var(--field);
    border-radius: 3px;
}
.bar-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 0 4px 4px 0; }
.bar-value {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    color: var(--ink);
    text-align: right;
    white-space: nowrap;
}
.bar-value small { color: var(--ink-faint); margin-left: 4px; font-size: 11px; }
.diverge-zero {
    position: absolute;
    left: 50%;
    top: -3px; bottom: -3px;
    width: 1px;
    background: var(--ink-faint);
}
.diverge-fill, .t-seg { position: absolute; top: 2px; bottom: 2px; border-radius: 3px; }
.diverge-error { grid-column: span 2; color: var(--danger); font-size: 12px; }
.tornado-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12px; color: var(--ink-soft); margin-bottom: 10px; }
.tornado-legend i { display: inline-block; width: 12px; height: 8px; border-radius: 2px; margin-right: 6px; }
.tornado-legend .muted { color: var(--ink-faint); font-family: var(--mono); }

.stack-up { list-style: none; margin: 0; padding: 0; }
.stack-up li { display: grid; gap: 4px; }
.stack-node {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 6px 10px;
    border: 1px solid var(--rule);
    border-radius: 5px;
    background: var(--panel);
    font-size: 12.5px;
}
.stack-node span { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink-mid); }
.stack-drop {
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    padding: 4px 10px 4px 22px;
    font-size: 12px;
    color: var(--ink-soft);
    border-left: 2px solid var(--rule-firm);
    margin-left: 14px;
}
.stack-bar { display: block; height: 8px; border-radius: 0 4px 4px 0; background: var(--warm); }
.stack-via { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stack-dt { font-family: var(--mono); color: var(--ink); }

.path-list { display: grid; gap: 6px; }
.path-row {
    border: 1px solid var(--rule);
    border-radius: 5px;
    padding: 7px 10px;
    font-size: 12.5px;
    background: var(--panel);
    cursor: default;
}
.path-row.hot { border-left: 3px solid var(--warm); }
.path-row:hover { border-color: var(--brand); background: var(--brand-pale); }
.path-head { display: grid; grid-template-columns: 76px minmax(0, 1fr) 60px; gap: 10px; align-items: center; }
.path-heat, .path-dt { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.path-dt { text-align: right; color: var(--ink-soft); }
.path-share { height: 6px; background: var(--field); border-radius: 3px; position: relative; }
.path-share span { position: absolute; left: 0; top: 0; bottom: 0; background: var(--c-008a7c); border-radius: 3px; }
.path-steps { margin-top: 4px; color: var(--ink-mid); line-height: 1.5; }
.path-steps span { color: var(--ink-faint); margin: 0 3px; }

.rec-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.rec {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 11px 12px;
    background: var(--panel);
    display: flex;
    flex-direction: column;
    gap: 7px;
}
.rec header { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.rec h5 { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink); }
.rec-share { font-size: 11px; font-family: var(--mono); color: var(--warm); white-space: nowrap; }
.rec p { margin: 0; font-size: 12px; line-height: 1.5; color: var(--ink-soft); }
.rec-numbers { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.rec-numbers div { display: flex; flex-direction: column; }
.rec-numbers span { font-size: 10.5px; color: var(--ink-faint); }
.rec-numbers strong { font-family: var(--mono); font-size: 14px; color: var(--ink); font-variant-numeric: tabular-nums; }
.rec-numbers .meets strong { color: var(--ok); }
.rec-numbers .short strong { color: var(--danger); }
.rec .link-button { align-self: flex-start; }

.advisor-actions { display: flex; gap: 12px; align-items: center; margin: 8px 0 14px; }
.check-inline { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--ink-mid); cursor: pointer; }
.check-inline input { width: auto; }
.advisor-notes { margin-top: 12px; padding: 9px 12px; border-left: 3px solid var(--rule-firm); background: var(--field); }
.advisor-notes p { margin: 0; font-size: 12px; color: var(--ink-soft); line-height: 1.5; }

table.advisor-table { font-size: 12.5px; }
table.advisor-table th, table.advisor-table td { padding: 6px 10px; }
table.advisor-table td.changes { font-size: 11.5px; color: var(--ink-soft); font-family: var(--mono); }
table.advisor-table td.cooler { color: var(--cool); font-weight: 600; }
table.advisor-table td.hotter { color: var(--warm); font-weight: 600; }
table.advisor-table tr.baseline td { background: var(--field); font-weight: 500; }
table.advisor-table tr.clickable { cursor: pointer; }
table.advisor-table tr.clickable:hover td { background: var(--brand-pale); }
table.advisor-table tr.knee td { font-weight: 600; }
table.advisor-table td.bad { color: var(--danger); }
.badge { font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.badge.good { background: var(--c-e3f1e8); color: var(--ok); }
.badge.bad { background: var(--c-f8e3e1); color: var(--danger); }

.chart-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; margin-bottom: 18px; }
.study-chart { background: var(--panel); }
.study-chart.narrow { max-width: 720px; }
.advisor svg .axis { stroke: var(--rule-firm); stroke-width: 1; }
.advisor svg .grid { stroke: var(--rule); stroke-width: 1; }
.advisor svg .tick { font-family: var(--mono); font-size: 10px; fill: var(--ink-faint); }
.advisor svg .axis-label { font-size: 11px; fill: var(--ink-soft); }
.advisor svg .trace { fill: none; stroke-width: 2; stroke-linejoin: round; }
.advisor svg .limit { stroke: var(--warm); stroke-width: 1.5; stroke-dasharray: 5 4; }
.advisor svg .limit-label { font-size: 10.5px; fill: var(--warm); font-weight: 600; }

.pareto-wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(210px, 260px);
    grid-template-areas: "chart detail" "legend detail";
    gap: 6px 18px;
    margin-bottom: 18px;
}
#pareto-chart { grid-area: chart; }
.pareto-legend { grid-area: legend; display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--ink-soft); }
.pareto-legend .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; }
.dot.front { background: var(--c-008a7c); }
.dot.other { background: var(--c-b9c0c8); }
.dot.infeasible { background: transparent; border: 1.5px solid var(--c-b9c0c8); }
.dot.knee { background: transparent; border: 2px solid var(--warm); }
.dot.base { background: var(--ink); border-radius: 1px; transform: rotate(45deg); }
.pareto-detail { grid-area: detail; border: 1px solid var(--rule); border-radius: 6px; padding: 10px 12px; align-self: start; }
.pareto-detail h5 { margin: 0 0 8px; font-size: 12.5px; }
.pareto-detail .rows { margin-bottom: 10px; }
.pareto-detail .row { padding: 4px 0; }
.pareto-detail .k { font-size: 11.5px; }
.pareto-detail .v { font-size: 12px; }
.detail-actions { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
#pareto-chart .pt { cursor: pointer; }
#pareto-chart .pt.front { fill: var(--c-008a7c); stroke: #fff; stroke-width: 1.5; }
#pareto-chart .pt.other { fill: var(--c-b9c0c8); }
#pareto-chart .pt.infeasible { fill: none; stroke: var(--c-b9c0c8); stroke-width: 1.2; }
#pareto-chart .pt.selected { stroke: var(--ink); stroke-width: 2.5; }
#pareto-chart .pt:hover { r: 6; }
#pareto-chart .front-line { fill: none; stroke: var(--c-008a7c); stroke-width: 1.5; stroke-opacity: .55; }
#pareto-chart .knee-ring { fill: none; stroke: var(--warm); stroke-width: 2; pointer-events: none; }
#pareto-chart .base-mark { fill: var(--ink); stroke: #fff; stroke-width: 1.5; cursor: pointer; }

@media (max-width: 1100px) {
    .pareto-wrap { grid-template-columns: 1fr; grid-template-areas: "chart" "legend" "detail"; }
}

/* the diagnosis on the canvas */
#wires .wire.advisor-share { stroke-linecap: round; }
.canvas-wrap.advisor-focus #wires .wire.advisor-dim,
#canvas.advisor-focus #wires .wire.advisor-dim { opacity: .2; }
#wires .wire.advisor-path { stroke: var(--brand) !important; stroke-width: 5 !important; }
#world .node.advisor-hot { box-shadow: 0 0 0 3px var(--warm), 0 1px 3px rgba(29,34,41,.14); }
#world .node.advisor-path { box-shadow: 0 0 0 3px var(--brand); }

/* ---------------------------------------------------------------- materials */

.tag {
    display: inline-block;
    font-size: 11px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--c-e9ebef);
    color: var(--ink-soft);
    vertical-align: middle;
}

.tag.warm { background: var(--c-fbe6da); color: var(--warm); }
.tag.cool { background: var(--c-dfeaf9); color: var(--cool); }

#mat-list { max-height: 300px; overflow-y: auto; border: 1px solid var(--rule); border-radius: 5px; }
#mat-list table { font-size: 12.5px; }
#mat-list th { position: sticky; top: 0; background: var(--panel); z-index: 1; padding-left: 10px; }
#mat-list td { padding-left: 10px; }
tr.mat-row { cursor: pointer; }
tr.mat-row:hover td { background: var(--field); }
tr.mat-row.selected td { background: var(--brand); color: var(--on-fill); }
tr.mat-row.selected .tag { background: rgb(var(--glass) / .25); color: var(--on-fill); }

.pcm-note {
    font-size: 12.5px;
    color: var(--ink-soft);
    line-height: 1.5;
    margin-top: 8px;
    border-left: 2px solid var(--rule-firm);
    padding-left: 10px;
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 1100px) {
    .results-grid, .study-grid { grid-template-columns: 1fr; gap: 22px; }
}


@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ==========================================================================
   System hierarchy: tree sidebar, subsystem frames, template library
   ========================================================================== */

.side.rail-left { min-width: 0; }

.head-action {
    border: 0;
    background: none;
    padding: 3px 7px;
    font-size: 12px;
    color: var(--brand);
    border-radius: 4px;
}

.head-action:hover:not(:disabled) { background: var(--brand-pale); border: 0; }

input[type=search] {
    width: 100%;
    font: inherit;
    font-size: 13px;
    padding: 6px 9px;
    border: 1px solid var(--rule-firm);
    border-radius: 5px;
    background: var(--panel);
    color: var(--ink);
    appearance: none;
}

input[type=search]:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-pale); }

.rail-tools { flex: none; padding: 9px 10px; border-bottom: 1px solid var(--rule); }

/* ---------------------------------------------------------------- tree */

.tree {
    flex: 1 1 auto;
    min-height: 90px;
    overflow: auto;
    padding: 5px 0 12px;
}

/* An assembly browser, not a list.

   Rows are full-bleed and square - a selected row is a band across the panel
   the way a CAD tree selects, not a floating pill - and each level of nesting
   draws a guide rule down the page so a deep subsystem can be followed by eye
   back to its parent. The rules are a repeating gradient clipped to the row's
   own indent, which is why every level has to indent by the same step:
   --tree-step here, STEP in hierarchy.js. */

/* The guide is a shade firmer than a panel rule: it has to be followable
   down forty rows without being read as a border. */
.tree { --tree-step: 14px; --tree-root: 8px; --tree-guide: var(--c-ccd3dc); }

.tr {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 8px 3px 0;
    cursor: default;
    font-size: 12.5px;
    line-height: 1.4;
    white-space: nowrap;
    padding-left: var(--pad, 8px);

    /* One rule per level of nesting, drawn only across the part of the indent
       that nesting actually produced: a top-level row gets none, a row three
       deep gets three. See STEP and ROOT_PAD in hierarchy.js. */
    background-image: repeating-linear-gradient(
        to right, var(--tree-guide) 0 1px, transparent 1px var(--tree-step));
    background-size: calc(var(--pad, 0px) - var(--tree-root)) 100%;
    background-position: calc(var(--tree-root) + 5px) 0;
    background-repeat: no-repeat;
}

.tr:hover { background-color: var(--field); }

.tr.sel {
    background-color: var(--brand-pale);
    box-shadow: inset 2px 0 0 var(--brand);
}
.tr.sel .nm { font-weight: 600; }
.tr.drop { box-shadow: inset 0 0 0 1px var(--brand); background-color: var(--brand-pale); }
.tr.dim { opacity: .45; }

/* The divider above the ungrouped nodes: a rule with a caption on it, the way
   a browser separates the assembly from the loose parts. */
.tree-sep {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 7px 0 3px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
}
.tree-sep::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--rule);
    margin-right: 8px;
}

.tr .nm { overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.tr .meta { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 11px; color: var(--ink-faint); flex: none; }
.tr.leaf .nm { color: var(--ink-soft); }
.tr.leaf.sel .nm { color: var(--ink); }

.twist {
    flex: none;
    width: 15px;
    height: 15px;
    border: 0;
    background: none;
    padding: 0;
    color: var(--ink-faint);
    font-size: 9px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 3px;
}

.twist:hover:not(:disabled) { background: transparent; color: var(--ink); border: 0; }
.twist svg { transition: transform .12s ease; }
.tr.shut .twist svg { transform: rotate(-90deg); }

.dot { flex: none; width: 9px; height: 9px; border-radius: 2px; }

.kind { flex: none; width: 3px; height: 13px; border-radius: 2px; background: var(--warm); margin-left: 3px; }
.kind.boundary { background: var(--cool); }

.tree-empty { padding: 14px 10px; font-size: 12.5px; color: var(--ink-faint); line-height: 1.5; }

/* Only while something is being dragged. A permanent dashed box explaining a
   gesture nobody is making is the clearest kind of clutter there is. */
.tree-root-drop {
    display: none;
    margin: 6px 8px 0;
    padding: 6px 8px;
    border: 1px dashed var(--rule-firm);
    border-radius: 5px;
    font-size: 11.5px;
    color: var(--ink-faint);
    text-align: center;
}
.tree.dragging .tree-root-drop { display: block; }

.tree-root-drop.drop { border-color: var(--brand); color: var(--brand); background: var(--brand-pale); }

/* ---------------------------------------------------------------- insert */

.insert {
    flex: none;
    display: flex;
    flex-direction: column;
    /* Three palette sections need most of the rail. The tree above gives up the
       difference: it stays useful when short, where a palette whose third group
       is below the fold does not - a part you cannot see is a part you do not
       know the tool has. */
    max-height: 68%;
    border-top: 1px solid var(--rule);
}

.insert-head {
    width: 100%;
    border: 0;
    border-bottom: 1px solid var(--rule);
    border-radius: 0;
    padding: 0 14px;
    cursor: pointer;
    color: var(--ink-soft);
}

.insert-head svg { transition: transform .12s ease; }
.insert.shut .insert-head svg { transform: rotate(-90deg); }
.insert.shut .insert-fixed, .insert.shut .insert-body { display: none; }

/* One domain's controls at a time, so the palette is a row of chips and not a
   wall. See the domain switch above it. */
.insert-fixed { flex: none; padding: 9px 10px 10px; }
.insert-fixed .seg { margin-bottom: 9px; }
.insert-body { overflow: auto; padding: 8px 10px 12px; }

/* A line in the palette that is a setting rather than a part: which piping the
   next run will be, which fluid is in it. Label on the left, control on the
   right, so it reads as a setting and not as another thing to place. */
.insert-line {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}

.insert-label {
    flex: none;
    width: 42px;
    font-size: 11px;
    color: var(--ink-soft);
}

.insert-line select { flex: 1; min-width: 0; font-size: 12.5px; padding: 5px 7px; }
.insert-line .connector-row { flex: 1; margin: 0; }

/* Templates are a library you reach for now and then, not a palette you work
   from, so they live behind a disclosure that is shut when the page loads. */
.tpl-drop {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    border-top: 1px solid var(--rule);
}

.tpl-drop > summary {
    flex: none;
    height: 30px;
    display: flex;
    align-items: center;
    gap: 3px;
    padding: 0 12px;
    font-size: 11.5px;
    color: var(--ink-soft);
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.tpl-drop > summary::-webkit-details-marker { display: none; }
.tpl-drop > summary:hover { background: var(--field); color: var(--ink); }

/* The disclosure arrow, drawn rather than inherited, so it turns with the
   state and matches the one on the Insert header. */
.tpl-drop > summary::before {
    content: "";
    width: 0; height: 0;
    margin-right: 4px;
    border: 4px solid transparent;
    border-left-color: currentColor;
    transition: transform .12s ease;
}
.tpl-drop[open] > summary::before { transform: rotate(90deg) translateX(-1px); }

.tpl-drop:not([open]) { flex: none; }
.tpl-drop #tpl-search { margin-bottom: 8px; }

.chip-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }

/* The board is one part, not a pair, so it gets the row to itself rather than
   sitting in a half-width box beside nothing. */
.chip-group.board .chip-row { grid-template-columns: 1fr; }
.chip-row .chip { margin: 0; padding: 7px 9px; }
.chip-row .chip strong { font-size: 12.5px; line-height: 1.25; }

.tpl-note { font-size: 11.5px; color: var(--ink-faint); line-height: 1.45; margin: 8px 2px 2px; }

.tpl-cat {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--ink-faint);
    padding: 10px 2px 4px;
}

.tpl {
    display: block;
    width: 100%;
    text-align: left;
    border: 1px solid var(--rule);
    border-radius: 5px;
    background: var(--panel);
    padding: 7px 9px;
    margin-bottom: 5px;
    cursor: grab;
    touch-action: none;
}

.tpl:hover { background: var(--field); border-color: var(--ink-soft); }
.tpl strong { display: block; font-size: 12.5px; font-weight: 600; }
.tpl span { display: block; font-size: 11px; color: var(--ink-soft); margin-top: 1px; white-space: normal; }
.tpl .tpl-kill { float: right; color: var(--ink-faint); font-size: 11px; }
.tpl:hover .tpl-kill { color: var(--danger); }

.tpl-ghost {
    position: fixed;
    z-index: 40;
    pointer-events: none;
    background: var(--ink);
    color: var(--on-fill);
    font-size: 12px;
    padding: 5px 10px;
    border-radius: 5px;
    box-shadow: 0 6px 18px rgba(29,34,41,.3);
}

/* ---------------------------------------------------------------- frames */

/* z-index 0 makes this a stacking context, so frames stay behind nodes and wires */
#group-layer { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

.gframe {
    position: absolute;
    border: 1px solid var(--gcol, var(--c-9aa1ad));
    border-radius: 8px;
    background: var(--gfill, rgba(0,0,0,.03));
    pointer-events: none;
}

.gframe.sel { border-width: 2px; }

.gframe-head {
    position: absolute;
    top: -1px;
    left: -1px;
    transform: translateY(-100%);
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 280px;
    padding: 3px 9px;
    border: 1px solid var(--gcol, var(--c-9aa1ad));
    border-bottom: 0;
    border-radius: 6px 6px 0 0;
    background: var(--panel);
    color: var(--gtext, var(--ink));
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
    cursor: grab;
    pointer-events: auto;
    user-select: none;
}

.gframe-head:hover { background: var(--field); }
.gframe-head.moving { cursor: grabbing; }
.gframe-head .count { font-family: var(--mono); font-weight: 400; color: var(--ink-faint); }

/* ---------------------------------------------------------------- group inspector */

.insp-title {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 12px;
}

.insp-title .dot { width: 10px; height: 10px; }

.btn-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.btn-row button { flex: 1 1 auto; font-size: 12.5px; padding: 6px 10px; }
.btn-row button.danger { color: var(--danger); border-color: var(--c-e6c9c6); }
.btn-row button.danger:hover:not(:disabled) { background: var(--c-fbeceb); border-color: var(--danger); }

@media (max-width: 900px) {
    .insert { max-height: none; }
    .tree { max-height: 320px; }
}

/* ------------------------------------------------------- fluid systems */

/* The palette is split so the two domains read as two domains. They are not
   interchangeable: a wire between a thermal node and a fluid node is refused,
   because heat crosses between them through a component's wall rather than
   along anything the user draws. Colour carries that distinction everywhere -
   sidebar, node cards, wires - so it is learned once. */

.chip-group[hidden] { display: none; }

.chip.fluid { border-left-color: var(--brand); }
.chip.fluid:hover { border-left-color: var(--brand); }

.connector-row {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 12px;
}

.connector {
    padding: 4px 9px;
    font-size: 11.5px;
    font-family: inherit;
    color: var(--ink-soft);
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 999px;
    cursor: pointer;
}

.connector:hover { border-color: var(--ink-soft); color: var(--ink); }

.connector.armed,
.connector[aria-checked="true"] {
    background: var(--brand-pale);
    border-color: var(--brand);
    color: var(--brand-deep);
    font-weight: 600;
}

.fluid-working { margin-bottom: 4px; }

/* Fluid node cards. The top edge carries the colour, as the thermal ones do,
   and a reservoir gets the heavier one because it is the thing that fixes the
   network's pressure level. */
.node.fluid { border-top-color: var(--brand); }
.node.fluid.reservoir { border-top-color: var(--brand-deep); border-top-width: 4px; }

/* ---- devices ----

   A pump is an object, so it is drawn as one: a box with a port on each side.
   The ports sit half outside the box on purpose, so it reads as piping meeting
   the device rather than as two dots printed on it.

   Scoped to #world. An unscoped `.device` rule also matched the palette chips,
   absolutely positioning all four of them at the same point so that only the
   last was clickable - every attempt to place a pump produced a compressor. A
   canvas rule has no business reaching into the sidebar. */

#world .device {
    position: absolute;
    width: 180px;               /* DEVICE_W in builder.js */
    height: 96px;               /* DEVICE_H */
    box-sizing: border-box;
    padding: 8px 14px;
    border-radius: 6px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-left: 4px solid var(--brand);
    box-shadow: 0 1px 3px rgba(29,34,41,.14);
    cursor: grab;
    user-select: none;
    touch-action: none;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
}

#world .device.selected {
    border-color: var(--brand);
    box-shadow: 0 0 0 2px var(--brand-pale), 0 1px 3px rgba(29,34,41,.14);
}
#world .device.dragging { cursor: grabbing; box-shadow: 0 8px 18px rgba(29,34,41,.2); }
#world .device.unsupported { border-left-color: var(--warm); background: var(--c-fffaf7); }

#world .device-name { font-weight: 600; font-size: 13px; line-height: 1.25; }

/* Two lines rather than one truncated one. A pump's defining numbers are its
   shutoff head and its free delivery; showing "70 kPa shutoff - 0.08..." tells
   you less than nothing, because the figure that got cut is the one you were
   looking for. The clamp is still there for a third line, which no device
   currently produces and which would push the card out of shape if one did. */
#world .device-meta {
    font-family: var(--mono);
    font-size: 9.5px;
    line-height: 1.35;
    color: var(--ink-soft);
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    line-clamp: 1;
}
#world .device-flow {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 10.5px;
    line-height: 1.35;
    font-weight: 600;
    color: var(--brand-deep);
    min-height: 0;
}
#world .device-flow:empty { display: none; }

/* ---- ports ----

   Small, because they are a feature of a device rather than a thing in their
   own right, and because making them node-sized would suggest they can be
   dragged around independently, which they cannot. */

#world .port-node {
    position: absolute;
    width: 18px;
    height: 18px;
    box-sizing: border-box;
    border-radius: 50%;
    background: var(--panel);
    border: 2.5px solid var(--brand);
    box-shadow: 0 1px 2px rgba(29,34,41,.18);
    cursor: crosshair;
    touch-action: none;
    z-index: 2;
}

#world .port-node.outlet { background: var(--brand); }
#world .port-node:hover { border-color: var(--brand-deep); transform: scale(1.18); }
#world .port-node.selected { box-shadow: 0 0 0 3px var(--brand-pale); }
#world .port-node.link-target {
    border-color: var(--brand-deep);
    box-shadow: 0 0 0 4px var(--brand-pale);
    transform: scale(1.25);
}

#draft-wire.fluid { stroke: var(--c-6fa8a2); stroke-width: 3; }

/* Piping is dashed, heat is solid: the one rule that makes a coupled model
   legible, because a loop of piping and a chain of heat paths otherwise look
   the same. Ducts are drawn heavier than pipes. Once solved, the dashes move
   the way the fluid does. */
#wires .wire.fluid {
    stroke: var(--c-5f9e97); stroke-width: 3; stroke-dasharray: 9 6;
    stroke-linecap: butt; stroke-linejoin: round;
}
#wires .wire.fluid.duct { stroke-width: 5; stroke-dasharray: 12 6; stroke: var(--c-7fb1ab); }
#wires .wire.fluid.selected { stroke: var(--brand); stroke-width: 4; }
#wires .wire.fluid.duct.selected { stroke-width: 6; }
#wires .wire.fluid.flowing { animation: fluid-flow 1.1s linear infinite; }
#wires .wire.fluid.flowing.reverse { animation-direction: reverse; }
@keyframes fluid-flow { to { stroke-dashoffset: -30; } }
@media (prefers-reduced-motion: reduce) {
    #wires .wire.fluid.flowing { animation: none; }
}
#wires .arrow.fluid { fill: var(--brand-deep); }
#wires text.port-tag { fill: var(--brand-deep); font-size: 10px; font-weight: 600; }

/* Where heat crosses from a wall into a stream: a solid line in the thermal
   colour, with a dot on the fluid end. */
#wires .coupling { stroke: var(--warm); stroke-width: 2.2; fill: none; stroke-linecap: round; }
#wires .coupling-end { fill: var(--warm); stroke: var(--canvas); stroke-width: 1.5; }
#wires text.coupling-tag { fill: var(--warm); font-size: 10px; font-weight: 600; }

/* ---- fluid devices, beyond the basic box ---- */

#world .device-glyph {
    position: absolute;
    top: 6px;
    right: 8px;
    color: var(--brand);
    line-height: 0;
    pointer-events: none;
}
#world .device.unsupported .device-glyph { color: var(--warm); }
#world .device .device-name { padding-right: 20px; }

/* Two streams in one box: the rows are drawn by an SVG behind the text, and
   the name sits in the middle band between them. */
#world .device.two-sided {
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 0 18px;
    border-left-width: 1px;
    border-top: 4px solid var(--brand);
}
#world .device.two-sided .device-name { padding-right: 0; }
#world .device.two-sided .device-meta { -webkit-line-clamp: 1; line-clamp: 1; }
#world .device.two-sided > :not(.device-streams):not(.device-glyph) { position: relative; z-index: 1; }
#world .device-streams {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    overflow: visible;
}
#world .device-streams .stream { stroke-width: 2; stroke-dasharray: 5 4; fill: none; }
#world .device-streams .stream.hot { stroke: var(--warm); }
#world .device-streams .stream.cold { stroke: var(--cool); }
#world .device-streams .head { stroke: none; stroke-dasharray: none; }
#world .device-streams .head.hot { fill: var(--warm); }
#world .device-streams .head.cold { fill: var(--cool); }
#world .device-streams .stream-label {
    font-family: var(--mono);
    font-size: 9px;
    fill: var(--ink-soft);
    letter-spacing: .04em;
    text-transform: uppercase;
}

.node.fluid.source { border-top-color: var(--cool); border-top-width: 4px; }

/* ---- fluid inspector ---- */

/* Solved values for a fluid component run long - "2.80 L/s · 2.795 kg/s",
   a film correlation - so the value column wraps rather than overrunning. */
.rows.fluid-rows .row { grid-template-columns: auto minmax(0, 1fr); }
.rows.fluid-rows .v { white-space: normal; overflow-wrap: anywhere; }

.field.check label {
    display: flex;
    gap: 7px;
    align-items: flex-start;
    font-size: 12px;
    color: var(--ink-mid);
    line-height: 1.4;
    cursor: pointer;
}
.field.check input { width: auto; margin-top: 2px; }

.hint.size-facts {
    margin: -4px 0 10px;
    font-family: var(--mono);
    font-size: 10.5px;
    line-height: 1.5;
}

.curve-chart {
    display: block;
    width: 100%;
    max-width: 100%;
    height: auto;
    margin: 4px 0 2px;
    background: var(--field);
    border: 1px solid var(--rule);
    border-radius: 4px;
}
.curve-chart .axis { stroke: var(--rule-firm); stroke-width: 1; }
.curve-chart .tick { font-family: var(--mono); font-size: 8.5px; fill: var(--ink-faint); }
.curve-chart .machine-curve { stroke: var(--brand); stroke-width: 2; fill: none; }
.curve-chart .system-curve { stroke: var(--ink-soft); stroke-width: 1.3; stroke-dasharray: 4 3; fill: none; }
.curve-chart .bep { stroke: var(--ok); stroke-width: 1; stroke-dasharray: 2 3; }
.curve-chart .duty-point { fill: var(--warm); stroke: #fff; stroke-width: 1.5; }

/* ---- the run panel's machine and device tables ---- */

.fluid-table {
    width: 100%;
    margin-top: 9px;
    border-collapse: collapse;
    font-size: 11px;
    line-height: 1.45;
}
.fluid-table th {
    text-align: left;
    font-weight: 600;
    font-size: 10px;
    letter-spacing: .04em;
    color: var(--ink-faint);
    border-bottom: 1px solid var(--rule-firm);
    padding: 2px 4px 3px 0;
}
.fluid-table td {
    padding: 3px 4px 3px 0;
    border-bottom: 1px solid var(--rule);
    vertical-align: top;
    color: var(--ink-mid);
}
.fluid-table .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fluid-table td.off { color: var(--warm); font-weight: 600; }

/* The conservation readout after a coupled solve. A flow solve that did not
   close is not a slightly worse answer, so it is shown rather than hidden, and
   it changes colour when it needs reading. */
.fluid-summary {
    margin-top: 14px;
    padding: 11px 12px;
    border: 1px solid var(--rule-firm);
    border-left: 3px solid var(--brand);
    border-radius: 5px;
    background: var(--field);
}

.fluid-summary.unsettled { border-left-color: var(--warm); }

.fluid-summary h3 {
    margin: 0 0 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

/* A grid rather than space-between, so the value column can shrink and wrap
   instead of running off the panel. "3.5e-11 of the stream" lost its last two
   words to the edge of a 312px inspector, which turned a conservation figure
   into a number with no scale attached - the one thing that makes it readable. */
.fluid-line {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 4px 10px;
    font-size: 11.5px;
    line-height: 1.55;
    padding: 2px 0;
}

.fluid-line span:first-child { color: var(--ink-soft); }
.fluid-line span:last-child {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    text-align: right;
    overflow-wrap: anywhere;
}

.fluid-summary .caveats {
    margin: 9px 0 0;
    padding-left: 16px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--ink-soft);
}

p.caveat {
    margin: -4px 0 12px;
    padding: 8px 10px;
    border-left: 3px solid var(--warm);
    border-radius: 3px;
    background: var(--c-fdf3ee);
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--ink-soft);
}

.kind.fluid { background: var(--c-6fa8a2); }
.kind.fluid.reservoir { background: var(--brand-deep); }

.tag-fluid {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--brand-pale);
    color: var(--brand-deep);
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 600;
    vertical-align: 1px;
}

/* ------------------------------------------------------ boards */

.chip.pcb { border-left-color: var(--c-7b4fb5); }
.chip.pcb:hover { border-left-color: var(--c-7b4fb5); }

/* The board on the sandbox: one object, whatever the mesh turns out to be.
   Scoped to #world for the same reason the device rules are - an unscoped
   canvas rule reaches into the sidebar and stacks the palette chips. */
#world .board-object {
    position: absolute;
    width: 256px;               /* BOARD_W in pcb.js */
    height: 96px;               /* BOARD_H */
    box-sizing: border-box;
    /* One declaration, not a shorthand after a longhand. Written as
       `padding-right: 52px` followed by `padding: 10px 13px`, the shorthand
       silently reset the right padding to 13 and the board's name ran under the
       Edit button. */
    padding: 11px 50px 11px 12px;
    border-radius: 6px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-left: 4px solid var(--c-7b4fb5);
    box-shadow: 0 1px 3px rgba(29,34,41,.14);
    cursor: grab;
    user-select: none;
    touch-action: none;
    display: flex;
    align-items: center;
    gap: 11px;
}

/* The board's own picture, to its real aspect ratio. See drawBoardThumb. */
#world .board-thumb {
    position: relative;
    flex: none;
    border: 1px solid var(--c-a9adb6);
    border-radius: 2px;
    background: var(--c-dde6e0);
    overflow: hidden;
}
#world .board-thumb.solved { border-color: var(--c-7b4fb5); }
#world .board-thumb .pcb-field { opacity: 1; }

#world .thumb-part {
    position: absolute;
    box-sizing: border-box;
    background: rgba(23,27,33,.72);
    border: 1px solid rgb(var(--glass) / .45);
    border-radius: 1px;
}
#world .thumb-part.interface { background: rgba(13,110,102,.8); }
/* Parts on the bottom face: the thumbnail shows the top, so they are outlines. */
#world .thumb-part.far { background: none; border: 1px dashed rgba(23,27,33,.8); }

#world .board-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }

#world .board-object.selected {
    border-color: var(--c-7b4fb5);
    box-shadow: 0 0 0 2px var(--c-ece3f6), 0 1px 3px rgba(29,34,41,.14);
}
#world .board-object.dragging { cursor: grabbing; box-shadow: 0 8px 18px rgba(29,34,41,.2); }

#world .board-name {
    font-weight: 600;
    font-size: 13px;
    line-height: 1.25;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
#world .board-meta {
    font-family: var(--mono);
    font-size: 9.5px;
    color: var(--ink-soft);
    line-height: 1.35;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}
#world .board-peak {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--c-5f3a91);
}
#world .board-peak:empty { display: none; }

#world .board-edit {
    position: absolute;
    top: 7px; right: 8px;
    padding: 2px 8px;
    font-size: 10.5px;
    font-family: inherit;
    border: 1px solid var(--rule-firm);
    border-radius: 4px;
    background: var(--panel);
    color: var(--ink-soft);
    cursor: pointer;
}
#world .board-edit:hover { border-color: var(--c-7b4fb5); color: var(--c-5f3a91); }

#world .port-node.board { border-color: var(--c-7b4fb5); background: var(--panel); }
#world .port-node.board:hover { border-color: var(--c-5f3a91); }

/* ---- the designer ---- */

.modal-shade {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(29,34,41,.42);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

/* `display` on a class beats the `hidden` attribute's own display:none, so a
   closed modal stayed laid out: invisible, full-screen, and swallowing every
   click on the page behind it. Anything given a display needs this alongside. */
.modal-shade[hidden] { display: none; }

.modal {
    display: flex;
    flex-direction: column;
    width: min(1280px, 100%);
    height: min(820px, 100%);
    background: var(--panel);
    border-radius: 10px;
    box-shadow: 0 24px 60px rgba(29,34,41,.32);
    overflow: hidden;
}

.modal-head {
    position: relative;
    padding: 15px 20px 13px;
    border-bottom: 1px solid var(--rule);
    background: var(--field);
}
.modal-head h2 { margin: 0; font-size: 15px; font-weight: 600; }
.modal-head p { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-soft); }

.modal-close {
    position: absolute;
    top: 12px; right: 14px;
    width: 28px; height: 28px;
    border: 0; border-radius: 5px;
    background: none;
    font-size: 20px; line-height: 1;
    color: var(--ink-soft);
    cursor: pointer;
}
.modal-close:hover { background: var(--shell); color: var(--ink); }

.modal.narrow { width: min(1040px, 100%); height: min(680px, 100%); }

/* The report options: two columns, sized to their content rather than to the
   board designer's full-screen frame. */
.modal.report-modal { width: min(860px, 100%); height: auto; max-height: 100%; }
.report-body {
    flex: 1; min-height: 0; overflow-y: auto;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
}
.report-col { padding: 16px 20px; display: flex; flex-direction: column; gap: 4px; }
.report-col + .report-col { border-left: 1px solid var(--rule); }
.report-col textarea { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; font-size: 12.5px; }
.report-detail-note { margin: 6px 0 0; font-size: 12px; color: var(--ink-soft); line-height: 1.45; min-height: 3.2em; }

.report-sections-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px;
    font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.linkish { border: 0; background: none; padding: 2px 4px; font-size: 12px; color: var(--brand); cursor: pointer;
    text-transform: none; letter-spacing: 0; }
.linkish:hover:not(:disabled) { background: none; text-decoration: underline; color: var(--brand-deep); }

.report-sections { display: grid; gap: 2px; }
.report-section {
    display: grid; grid-template-columns: 18px 1fr; column-gap: 8px; align-items: start;
    padding: 6px 8px; border-radius: 5px; cursor: pointer;
}
.report-section:hover { background: var(--field); }
.report-section input { margin: 2px 0 0; }
.report-section b { font-weight: 600; font-size: 13px; }
.report-section small { grid-column: 2; font-size: 11.5px; color: var(--ink-soft); line-height: 1.4; }
.report-section.unavailable { cursor: default; opacity: .55; }
.report-section.unavailable:hover { background: none; }

.report-transient { margin: 6px 0 0 34px; }
.report-summary { font-size: 12px; color: var(--ink-soft); min-width: 0; }
.report-summary.bad { color: var(--danger); }

/* The Report page: the options beside the report as it will come out. */
.report-page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
    gap: 18px;
    align-items: start;
    max-width: 1180px;
}
.report-page[hidden] { display: none; }
.report-form {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    border: 1px solid var(--rule); border-radius: 8px; background: var(--panel);
}
.report-form .optional { color: var(--ink-faint); font-weight: 400; margin-left: 4px; }
.report-outline {
    position: sticky; top: 0;
    border: 1px solid var(--rule); border-radius: 8px; background: var(--field);
    padding: 12px 14px;
}
.report-outline-head { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 8px; }
.ro-title { font-weight: 650; font-size: 14px; line-height: 1.3; }
.ro-meta { font-size: 12px; color: var(--ink-soft); margin: 2px 0 10px; }
.ro-list { margin: 0 0 4px 18px; padding: 0; display: grid; gap: 6px; font-size: 12.5px; }
.ro-list small { display: block; color: var(--ink-soft); font-size: 11.5px; line-height: 1.35; }
/* Always in reach, however long the section list: the foot sticks to the
   bottom of the page as it scrolls. */
.report-foot {
    grid-column: 1 / -1;
    position: sticky; bottom: 0; z-index: 2;
    display: flex; align-items: center; gap: 12px;
    padding: 10px 0 12px;
    background: var(--panel);
    border-top: 1px solid var(--rule);
}
.report-foot .report-summary { flex: 1; }
.report-foot .primary { flex: none; min-width: 150px; }
.report-page .report-transient { margin: 6px 0 0; }
@container (max-width: 980px) {
    .report-page { grid-template-columns: minmax(0, 1fr); }
    .report-outline { position: static; }
}
@container (max-width: 720px) {
    .report-form { grid-template-columns: minmax(0, 1fr); }
    .report-col + .report-col { border-left: 0; border-top: 1px solid var(--rule); }
}

.modal-body {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: 290px 1fr 290px;
}

/* The material library: find on the left, read on the right. */
.modal-body.two-up { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }

.mat-side, .mat-detail {
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 16px 18px;
}
.mat-side { border-right: 1px solid var(--rule); }
.mat-detail { overflow-y: auto; }

/* The list takes whatever height is left, rather than the modal growing a
   scrollbar around a list that has one of its own. */
.grow-scroll { flex: 1 1 auto; min-height: 90px; overflow: auto; }
.mat-side #mat-list { max-height: none; }

.pcb-panel {
    overflow-y: auto;
    padding: 14px 16px 20px;
    border-right: 1px solid var(--rule);
}
.modal-body > .pcb-panel:last-child { border-right: 0; border-left: 1px solid var(--rule); }

.pcb-panel h3 {
    margin: 16px 0 9px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
}
.pcb-panel h3:first-child { margin-top: 0; }

.pcb-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }

.pcb-derived {
    margin: -2px 0 10px;
    font-size: 11px;
    line-height: 1.5;
    color: var(--ink-soft);
}
.pcb-derived.bad { color: var(--danger); }

.pcb-edge {
    display: grid;
    grid-template-columns: 52px 1fr;
    gap: 6px;
    align-items: center;
    margin-bottom: 6px;
    font-size: 12px;
}
.pcb-edge:has(input) { grid-template-columns: 52px 1fr 1fr; }
.pcb-edge:has(.pcb-edge-t) { grid-template-columns: 52px 1fr 1fr 1fr; }
.pcb-edge span { color: var(--ink-soft); text-transform: capitalize; }
.pcb-edge select, .pcb-edge input { width: 100%; }

/* the board itself */

.pcb-stage { display: flex; flex-direction: column; min-width: 0; }

.pcb-tools {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--rule);
}
.pcb-hint { font-size: 11.5px; color: var(--ink-faint); }

.pcb-canvas {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(circle at 1px 1px, var(--grid) 1px, transparent 0) 0 0 / 18px 18px,
        var(--canvas);
}

.pcb-board {
    position: relative;
    background: var(--c-d9e6dd);
    border: 1px solid var(--c-94a89b);
    border-radius: 3px;
    box-shadow: 0 2px 10px rgba(29,34,41,.18);
}

.pcb-field {
    position: absolute;
    inset: 0;
    image-rendering: pixelated;   /* cell boundaries are real, not artefacts */
    opacity: .92;
}

.pcb-part {
    position: absolute;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(29,34,41,.82);
    border: 1px solid var(--c-12161b);
    border-radius: 2px;
    color: #fff;
    font-size: 9px;
    font-family: var(--mono);
    overflow: hidden;
    cursor: grab;
    touch-action: none;
}
.pcb-part.interface { background: rgba(13,110,102,.85); border-color: var(--brand-deep); }
.pcb-part.selected { outline: 2px solid var(--c-7b4fb5); outline-offset: 1px; z-index: 2; }

/* A part on the face not being viewed: present, but through the board. Dashed
   and see-through so the field under it stays readable, and still selectable
   so it can be moved or flipped without changing the view. */
.pcb-part.far {
    background: rgba(29,34,41,.14);
    border: 1px dashed rgba(18,22,27,.75);
    color: var(--c-12161b);
}
.pcb-part.interface.far { background: rgba(13,110,102,.14); border-color: var(--brand-deep); }

.pcb-face { flex: none; width: 128px; }
.pcb-add-region { width: auto; flex: none; }
.pcb-tools > button, .pcb-tools > select { flex: none; white-space: nowrap; }
.pcb-tools > .grow { flex: 1 1 0; min-width: 0; }
.pcb-tools .pcb-hint { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Regions: what the board is made of, drawn under the parts that sit on it. */
.pcb-region {
    --via-dot: rgba(120, 84, 22, .85);
    position: absolute;
    box-sizing: border-box;
    cursor: grab;
    touch-action: none;
    font-family: var(--mono);
    font-size: 8.5px;
    color: var(--c-3b2a0c);
    overflow: hidden;
}
.pcb-region span {
    position: absolute; top: 1px; left: 2px;
    padding: 0 2px; border-radius: 2px;
    background: rgb(var(--glass) / .72);
    white-space: nowrap; pointer-events: none;
}
.pcb-region.vias { background-color: rgba(214, 178, 94, .22); border: 1px solid rgba(120, 84, 22, .8); }
.pcb-region.pour { background: rgba(196, 122, 58, .38); border: 1px solid rgba(150, 82, 26, .9); }
.pcb-region.keepout {
    border: 1px dashed var(--c-b3261e);
    background: repeating-linear-gradient(45deg, rgba(179,38,30,.16) 0 4px, transparent 4px 8px);
    color: var(--c-7d1a14);
}
.pcb-region.far { opacity: .32; }
.pcb-region.selected { outline: 2px solid var(--c-7b4fb5); outline-offset: 1px; z-index: 1; }

.pcb-region-list { display: grid; gap: 4px; margin-bottom: 6px; }
.pcb-region-list .hint { margin: 0; }
.pcb-region-list button {
    display: flex; align-items: center; gap: 7px;
    width: 100%; padding: 4px 8px; font-size: 12px; text-align: left;
    border: 1px solid var(--rule); border-radius: 4px; background: var(--field);
}
.pcb-region-list button.on { border-color: var(--c-7b4fb5); box-shadow: inset 2px 0 0 var(--c-7b4fb5); }
.pcb-region-list button span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcb-region-list button small { color: var(--ink-faint); font-size: 10.5px; }
.pcb-region-list i { width: 12px; height: 9px; border-radius: 2px; flex: none; }
.pcb-region-list .vias i { background: radial-gradient(circle, rgba(120,84,22,.9) 1px, transparent 1.4px) 0 0 / 4px 4px, rgba(214,178,94,.35); border: 1px solid rgba(120,84,22,.8); }
.pcb-region-list .pour i { background: rgba(196,122,58,.6); border: 1px solid rgba(150,82,26,.9); }
.pcb-region-list .keepout i { border: 1px dashed var(--c-b3261e); background: repeating-linear-gradient(45deg, rgba(179,38,30,.3) 0 2px, transparent 2px 4px); }

.pcb-kind {
    font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
    color: var(--ink-faint); margin-bottom: 8px;
}
.pcb-figures { margin-top: 10px; display: grid; gap: 4px; }
.pcb-figures .row { display: flex; justify-content: space-between; gap: 10px; font-size: 11.5px; }
.pcb-figures .k { color: var(--ink-soft); flex: none; }
.pcb-figures .v { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; }
.pcb-part span { padding: 0 2px; white-space: nowrap; }

/* A part too small to hold its own name wears it above instead. Clipped inside
   a 6 mm standoff, "Standoff" came out as "tandof" - centred, so cut at both
   ends - which reads as a different component rather than as a truncation. */
.pcb-part.tagged { overflow: visible; }
.pcb-part.tagged span {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 2px;
    padding: 0 3px;
    border-radius: 2px;
    background: rgb(var(--glass) / .86);
    color: var(--ink);
    font-size: 9px;
    line-height: 1.35;
    pointer-events: none;
}

.pcb-foot {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 8px 14px;
    border-top: 1px solid var(--rule);
}

/* A mesh that could not be built as asked says so here. Warm, because the
   peak temperature is the first casualty and it is the number people read. */
.pcb-mesh strong {
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 3px;
    background: var(--c-fbe6da);
    color: var(--warm);
    font-family: var(--sans);
    font-size: 10.5px;
    font-weight: 600;
    cursor: help;
}
.pcb-mesh.starved strong { background: var(--c-fbeceb); color: var(--danger); }

.pcb-mesh {
    flex: 1;
    min-width: 0;
    font-family: var(--mono);
    font-size: 11px;
    color: var(--ink-soft);
    min-height: 16px;
}

/* The field's colour scale. Without it the map says where the hot part is,
   which the person already knew, and nothing about how much hotter. */
.pcb-scale {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: none;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 10.5px;
    color: var(--ink-soft);
}
.pcb-scale[hidden] { display: none; }
.pcb-scale i {
    display: block;
    width: 150px;
    height: 9px;
    border-radius: 2px;
    border: 1px solid var(--rule-firm);
}

.modal-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 18px;
    border-top: 1px solid var(--rule);
    background: var(--field);
}

.pcb-problems { font-size: 11.5px; color: var(--danger); line-height: 1.45; }
.modal-foot .grow { flex: 1; }
.modal-foot button[disabled] { opacity: .45; cursor: not-allowed; }

.tr.grp.board .dot.board { background: var(--c-7b4fb5); }
.kind.board { background: var(--c-7b4fb5); }

/* ------------------------------------------------ chrome and affordances */

.empty-keys {
    margin-top: 10px;
    font-size: 11.5px;
    color: var(--ink-faint);
}

kbd {
    display: inline-block;
    min-width: 18px;
    padding: 1px 5px;
    border: 1px solid var(--rule-firm);
    border-bottom-width: 2px;
    border-radius: 4px;
    background: var(--panel);
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--ink-mid);
    text-align: center;
}

/* Floats over the canvas rather than opening a dialog: it is a reference, not
   a task, and a modal would make you dismiss it before using what it says. */
.shortcuts {
    position: absolute;
    right: 16px;
    bottom: 58px;
    z-index: 8;
    padding: 13px 16px 15px;
    border: 1px solid var(--rule-firm);
    border-radius: 7px;
    background: var(--panel);
    box-shadow: 0 8px 24px rgba(23,27,33,.14);
}

.shortcuts h3 {
    margin: 0 0 9px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

.shortcuts dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 5px 12px;
    margin: 0;
    font-size: 12px;
}
.shortcuts dt { margin: 0; }
.shortcuts dd { margin: 0; color: var(--ink-soft); }

/* ------------------------------------------------- thermodynamics (Results)

   A fluid system's states, drawn the three ways an engineer checks them on
   paper. Same chart grammar as the advisor: recessive axes, one teal trace,
   the dome in grey, device spans as faint bands with their names above. */
.thermo { margin-top: 22px; border-top: 1px solid var(--rule); padding-top: 16px; }
.results-grid[hidden] + .thermo, .thermo:first-child { margin-top: 0; border-top: 0; padding-top: 0; }
.thermo-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-bottom: 14px; }
.thermo-head h3 { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); }
.thermo-head .seg { flex: 0 1 auto; }
.thermo-head .seg-btn { flex: 0 0 auto; padding: 4px 10px; }
.thermo-fluid { font-size: 12.5px; font-weight: 600; }
.thermo-facts { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-left: auto; font-size: 12px; color: var(--ink-soft); }
.thermo-facts b { font-family: var(--mono); font-weight: 600; color: var(--ink); }
.thermo-profiles { margin-bottom: 10px; }
.thermo-diagram-row { display: grid; grid-template-columns: minmax(320px, 1.1fr) minmax(300px, 1fr); gap: 18px; align-items: start; }
@media (max-width: 1100px) { .thermo-diagram-row { grid-template-columns: 1fr; } }
.thermo-diagram-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.thermo-diagram-bar .seg { flex: 0 0 auto; }
.thermo-diagram-bar .seg-btn { flex: 0 0 auto; padding: 3px 10px; font-size: 11.5px; }
.thermo-diagram-bar .hint { font-size: 11.5px; margin: 0; }
.thermo-chart { width: 100%; display: block; background: var(--panel); }
.thermo-chart .axis { stroke: var(--rule-firm); stroke-width: 1; }
.thermo-chart .grid { stroke: var(--rule); stroke-width: 1; }
.thermo-chart .tick { font-family: var(--mono); font-size: 10px; fill: var(--ink-faint); }
.thermo-chart .axis-label { font-size: 10.5px; fill: var(--ink-soft); }
.thermo-chart .band { fill: var(--c-008a7c); fill-opacity: .07; }
.thermo-chart .band-label { font-size: 9.5px; fill: var(--ink-soft); }
.thermo-chart .trace { fill: none; stroke: var(--c-008a7c); stroke-width: 2; stroke-linejoin: round; }
.thermo-chart .dot { fill: var(--c-008a7c); stroke: var(--panel); stroke-width: 2; }
.thermo-chart .hit { fill: transparent; cursor: default; }
.thermo-chart g:hover .dot { r: 5.5; }
.thermo-chart .value-label { font-family: var(--mono); font-size: 10px; fill: var(--ink); }
.thermo-chart .station-num { font-family: var(--mono); font-size: 9.5px; fill: var(--ink-soft); }
.thermo-chart .dome { fill: var(--c-9aa3ae); fill-opacity: .08; stroke: var(--c-9aa3ae); stroke-width: 1.5; }
.thermo-chart .critical { fill: var(--c-9aa3ae); }
.thermo-table-wrap { max-height: 340px; overflow: auto; }
table.thermo-table { font-size: 12px; }
table.thermo-table th, table.thermo-table td { padding: 4px 8px; }
table.thermo-table td.idx { color: var(--ink-faint); width: 2em; }
table.thermo-table td.low { color: var(--danger); font-weight: 600; }
table.thermo-table .muted { color: var(--ink-faint); font-size: 11px; }
table.thermo-table thead th { position: sticky; top: 0; background: var(--panel); }

/* ------------------------------------------------- fluid states on the canvas */
.node-temp.fluid-state { display: inline-flex; padding: 0; background: none; overflow: hidden;
    border: 1px solid var(--rule-firm); font-size: 11.5px; max-width: 100%; }
.node-temp.fluid-state span { padding: 3px 6px; white-space: nowrap; }
.node-temp.fluid-state .t { color: #fff; }
.node-temp.fluid-state .p { color: var(--ink); background: var(--field); }

#world .port-state {
    position: absolute;
    z-index: 3;
    pointer-events: none;
    display: flex;
    flex-direction: column;
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-size: 9.5px;
    line-height: 1.25;
    color: var(--ink-soft);
    background: rgb(var(--glass) / .94);
    border: 1px solid var(--rule);
    border-left: 3px solid var(--tick, var(--ink-faint));
    border-radius: 2px;
    padding: 1px 4px 1px 3px;
    white-space: nowrap;
}
#world .port-state b { font-weight: 600; color: var(--ink); }
/* sat outside the box, above the pipe it opens onto */
#world .port-state[data-side="left"]  { transform: translate(calc(-100% - 7px), calc(-100% - 8px)); }
#world .port-state[data-side="right"] { transform: translate(7px, calc(-100% - 8px)); }
#world .port-state[data-side="up"]    { transform: translate(11px, calc(-100% - 6px)); }
#world .port-state[data-side="down"]  { transform: translate(11px, 6px); }

.zoom-controls button.toggle { font-family: var(--mono); font-size: 11.5px; border-left: 1px solid var(--rule); border-radius: 0 3px 3px 0; }
.zoom-controls button.toggle[aria-pressed="true"]:not(:disabled) { color: var(--brand-deep); background: var(--brand-pale); font-weight: 600; }
.zoom-controls button.toggle:disabled { color: var(--ink-faint); }

/* ------------------------------------------------- dropdowns

   Drawn as a CAD combo box rather than a web form control: square, dense,
   with the arrow in a narrow button segment of its own behind a hairline,
   and a small solid triangle instead of a chevron. Every select in the app
   gets the same one, wherever it sits.

   Where the browser can style the open list too (appearance: base-select,
   Chromium 135 on), the list matches: square, tight rows, a filled band on
   the chosen item, no checkmark column. Elsewhere the native list opens
   from the same closed control. */

select, .toolbar select, .pcb-tools select, .field select, .insert-line select, .pcb-edge select {
    -webkit-appearance: none;
    appearance: none;
    font-family: var(--sans);
    font-size: 12.5px;
    line-height: 1.2;
    height: 26px;
    padding: 0 27px 0 7px;
    border: 1px solid var(--rule-firm);
    border-radius: 2px;
    color: var(--ink);
    background-color: var(--panel);
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath d='M0 0h7L3.5 4z' fill='%233d4551'/%3E%3C/svg%3E"),
        linear-gradient(var(--rule-firm), var(--rule-firm)),
        linear-gradient(var(--field), var(--field));
    background-repeat: no-repeat;
    background-size: 7px 4px, 1px 100%, 19px 100%;
    background-position: right 6px center, right 19px center, right 0 center;
    cursor: default;
    text-overflow: ellipsis;
    white-space: nowrap;
    box-shadow: none;
}
.field select { height: 28px; font-size: 13px; }
select:hover:not(:disabled), .toolbar select:hover, .pcb-tools select:hover, .field select:hover {
    border-color: var(--ink-faint);
    background-color: var(--panel);
    background-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath d='M0 0h7L3.5 4z' fill='%23171b21'/%3E%3C/svg%3E"),
        linear-gradient(var(--ink-faint), var(--ink-faint)),
        linear-gradient(var(--c-e9edf1), var(--c-e9edf1));
    background-repeat: no-repeat;
    background-size: 7px 4px, 1px 100%, 19px 100%;
    background-position: right 6px center, right 19px center, right 0 center;
    color: var(--ink);
}
select:focus, .field select:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
select:disabled { color: var(--ink-faint); background-color: var(--field); }

@supports (appearance: base-select) {
    select, .toolbar select, .pcb-tools select, .field select, .insert-line select, .pcb-edge select,
    ::picker(select) { appearance: base-select; }

    select, .toolbar select, .pcb-tools select, .field select, .insert-line select, .pcb-edge select {
        display: inline-flex;
        align-items: center;
        overflow: hidden;
    }
    .field select { display: flex; }
    /* The arrow segment stays the background drawing above: the content box
       ends before it, so a long choice in a narrow column is cut short under
       the hairline instead of pushing the arrow out of sight, which is what
       the built-in picker icon does. */
    select::picker-icon { display: none; }
    select:open, .field select:open {
        background-image:
            url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='4' viewBox='0 0 7 4'%3E%3Cpath d='M0 4h7L3.5 0z' fill='%23095049'/%3E%3C/svg%3E"),
            linear-gradient(var(--brand), var(--brand)),
            linear-gradient(var(--brand-pale), var(--brand-pale));
    }
    select:open { border-color: var(--brand); }
    select > button { all: unset; }
    select selectedcontent { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

    ::picker(select) {
        border: 1px solid var(--ink-faint);
        border-radius: 2px;
        background: var(--panel);
        box-shadow: 0 6px 18px rgba(23, 27, 33, .18);
        padding: 2px 0;
        margin: 1px 0;
        max-height: min(360px, 60vh);
        min-width: anchor-size(width);
        font-family: var(--sans);
    }
    select option {
        font-size: 12.5px;
        padding: 3px 10px 3px 9px;
        min-height: 22px;
        line-height: 16px;
        color: var(--ink);
        gap: 6px;
        white-space: nowrap;
    }
    select option::checkmark { display: none; }
    select option:hover, select option:focus-visible { background: var(--brand-pale); outline: none; }
    select option:checked { background: var(--brand); color: var(--on-fill); }
    select option:disabled { color: var(--ink-faint); }
    select option:checked:disabled { background: var(--field); color: var(--ink-faint); }
    select optgroup { font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
                      color: var(--ink-faint); padding: 4px 0 0; }
    select optgroup legend { padding: 3px 9px 2px; }
    select optgroup option { text-transform: none; letter-spacing: 0; font-weight: 400; padding-left: 16px; }
    select optgroup + optgroup, select option + optgroup { border-top: 1px solid var(--rule); margin-top: 2px; }
}

/* ------------------------------------------------- TIMs, heat pipes, vapor chambers */
.seg.tim-mode { margin-bottom: 10px; }
.tim-readout { font-family: var(--mono); font-size: 11.5px; color: var(--ink); }
.curve-chart .curve-point { fill: var(--brand); }
/* On the canvas: a heat pipe is drawn as the tube it is, a vapor chamber as a
   broad band, a TIM as a short dense line. */
#wires .wire.kind-heat_pipe { stroke: var(--c-b0643a); stroke-width: 5; stroke-linecap: round; }
#wires .wire.kind-vapor_chamber { stroke: var(--c-b0643a); stroke-width: 8; stroke-opacity: .55; }
#wires .wire.kind-tim { stroke: var(--c-7d8492); stroke-width: 3; stroke-dasharray: 1 3; stroke-linecap: round; }
#wires .wire.kind-heat_pipe.selected, #wires .wire.kind-vapor_chamber.selected,
#wires .wire.kind-tim.selected { stroke: var(--brand); stroke-opacity: 1; }

/* ---- shape factors and spreading resistances (shapes.js) ---- */
.seg.geo-k { margin: 4px 0 10px; }
.geo-formula {
    font-family: var(--mono); font-size: 12px; color: var(--ink);
    background: var(--field); border: 1px solid var(--rule); border-radius: 4px;
    padding: 6px 8px; margin: 0 0 6px; overflow-x: auto; white-space: nowrap;
}
.geo-readout { font-family: var(--mono); font-size: 11.5px; color: var(--ink); overflow-wrap: anywhere; }
.geo-readout.error { color: var(--danger); }
.geo-source { font-style: italic; }
.geo-plan {
    display: block; width: 100%; max-width: 100%; height: auto; margin: 2px 0 10px;
    background: var(--field); border: 1px solid var(--rule); border-radius: 4px;
}
.geo-plan .plan-plate { fill: var(--c-d9dde3); stroke: var(--ink-faint); stroke-width: 1; }
.geo-plan .plan-source { fill: var(--warm); fill-opacity: .8; stroke: var(--warm); }
.geo-plan .plan-source.off { fill: var(--danger); stroke: var(--danger); }
.geo-plan .tick { font-family: var(--mono); font-size: 9px; fill: var(--ink-faint); }
.geo-plan .plan-warn { fill: var(--danger); }
#wires .wire.kind-shape_factor { stroke-dasharray: 8 3 2 3; }
#wires .wire.kind-spreading { stroke-width: 3.5; stroke-dasharray: 10 3; }
.geo-note { margin-bottom: 8px; }

/* ---- level of detail: what the canvas shows at each zoom (applyTransform) ---- */
.canvas-wrap[data-lod="far"] #wires text,
.canvas-wrap[data-lod="far"] .port-state,
.canvas-wrap[data-lod="mid"] #wires text:not(.flow):not(.reverses):not(.coupling-tag) { display: none; }
.canvas-wrap[data-lod="far"] #wires g:hover text,
.canvas-wrap[data-lod="far"] #wires g.selected text,
.canvas-wrap[data-lod="mid"] #wires g:hover text,
.canvas-wrap[data-lod="mid"] #wires g.selected text { display: inline; }
.canvas-wrap[data-lod="far"] .node .node-meta { display: none; }
/* Hovering a run lifts it, so you can follow one line through a busy corridor. */
#wires g:hover .wire { stroke-width: 3.5; }
#wires g:hover .coupling { stroke-width: 2.5; }

/* ---- fluid in the model tree ---- */
/* A device is a thing with a flow through it, so its marker is a ring rather
   than the bar a node carries: machines round, heat-transfer devices square. */
.kind.devmark {
    width: 9px; height: 9px; margin-left: 0; border-radius: 50%;
    background: transparent; border: 2px solid var(--c-3f8c84);
}
.kind.devmark.dev-heat_exchanger, .kind.devmark.dev-chiller,
.kind.devmark.dev-cold_plate, .kind.devmark.dev-heater { border-radius: 2px; border-color: var(--c-b0643a); }
.kind.devmark.dev-valve, .kind.devmark.dev-fitting { border-radius: 2px; transform: rotate(45deg) scale(.85); }
.tr .dot.circuit { background: transparent; border: 2px solid var(--c-3f8c84); border-radius: 50%; width: 10px; height: 10px; }
.tr.grp.circuit .nm { color: var(--ink-mid); }

/* ---- the fluid strip in the right rail: status only, detail in Results ---- */
.fluid-summary { padding: 9px 11px; }
.fluid-summary .fs-line { display: flex; align-items: center; gap: 7px; font-size: 12.5px; }
.fluid-summary .fs-line strong { font-weight: 600; color: var(--ink); }
.fluid-summary .fs-state { margin-left: auto; font-size: 11.5px; color: var(--ok); text-align: right; }
.fluid-summary.unsettled .fs-state { color: var(--warm); font-weight: 600; }
.fluid-summary .fs-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); flex: none; }
.fluid-summary.unsettled .fs-dot { background: var(--warm); }
.fluid-summary .fs-sub { margin-top: 3px; font-family: var(--mono); font-size: 10.5px; color: var(--ink-faint); }
.fluid-summary .fs-warn { color: var(--warm); font-weight: 600; }
.fluid-summary .link-button { margin-top: 5px; font-size: 11.5px; }

/* ---- the Results drawer's views ---- */
.results-nav { margin: 0 0 14px; max-width: 420px; }
.rpane-off { display: none !important; }
#results .thermo { margin-top: 0; border-top: 0; padding-top: 0; }

/* Fluid system detail: balances beside the machine and device tables, across
   the drawer's width where a table has room to be a table. */
.fluid-results {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 8px 28px;
    align-items: start;
}
.fluid-results:empty { display: none; }
.fluid-results h3 {
    margin: 0 0 6px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
    text-transform: uppercase; color: var(--ink-faint);
}
.fluid-balances { padding: 10px 12px; border: 1px solid var(--rule); border-left: 3px solid var(--brand); border-radius: 5px; background: var(--field); }
.fluid-balances.unsettled { border-left-color: var(--warm); }
.fluid-balances .caveats { margin: 8px 0 0; padding-left: 16px; font-size: 11.5px; line-height: 1.5; color: var(--ink-soft); }
.fluid-results .fluid-table { margin-top: 0; font-size: 12px; }
.fluid-results .fluid-table th { font-size: 10.5px; }
.fluid-summary .fs-line strong { white-space: nowrap; }

/* Long inspector explanations: two lines until clicked (builder.js, HINT_FOLD). */
#inspector p.hint.folded {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden; cursor: pointer; position: relative;
}
#inspector p.hint.folded:not(.open)::after {
    content: "more"; position: absolute; right: 0; bottom: 0; padding-left: 18px;
    background: linear-gradient(to right, transparent, var(--panel) 40%);
    color: var(--brand); font-size: 11px;
}
#inspector p.hint.folded.open { display: block; -webkit-line-clamp: unset; }
#inspector p.hint.folded:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* ---- heat pipes and vapor chambers (twophase.js) ---- */
.tp-ends { margin: 0 0 8px; font-size: 12.5px; color: var(--ink-mid); line-height: 1.45; }
.tp-ends .hint { display: block; margin-top: 2px; }
.seg.tp-level, .seg.tp-input { margin-bottom: 10px; }
.field-row.three { grid-template-columns: 1fr 1fr 1fr; }
.pgroup .field-row.three > .field { margin-bottom: 0; }
.tp-orient { display: block; width: 100%; max-width: 100%; height: auto; margin: -2px 0 10px;
             background: var(--field); border: 1px solid var(--rule); border-radius: 4px; }
.tp-orient .tp-pipe { stroke: var(--c-b0643a); stroke-width: 7; stroke-linecap: round; }
.tp-orient .tp-evap { fill: var(--warm); stroke: #fff; stroke-width: 1.5; }
.tp-orient .tp-cond { fill: var(--cool); stroke: #fff; stroke-width: 1.5; }
.tp-orient .tp-g { stroke: var(--ink-faint); stroke-width: 1.5; fill: none; }
.tp-orient .tick { font-family: var(--mono); font-size: 9px; fill: var(--ink-faint); }
.tp-orient .tp-words { font-size: 10.5px; fill: var(--ink-mid); font-weight: 600; }
.tp-orient .tp-words.bad { fill: var(--warm); }
.tp-curve { border-left: 3px solid var(--swatch); padding-left: 8px; margin-bottom: 8px; }
.tp-curve textarea { width: 100%; font-family: var(--mono); font-size: 12px; padding: 5px 7px;
                     border: 1px solid var(--rule-firm); border-radius: 2px; resize: vertical; }
.tp-curve-tools { display: flex; align-items: flex-end; justify-content: flex-end; }
.tp-curve-tools .link-button.remove { margin-bottom: 4px; }
#tp-addcurve { margin: 0 0 10px; }
details.tp-advanced { margin: 4px 0 10px; border: 1px solid var(--rule); border-radius: 4px; padding: 6px 9px; }
details.tp-advanced > summary { cursor: pointer; font-size: 12px; color: var(--ink-mid); }
details.tp-advanced[open] > summary { margin-bottom: 8px; }
.tp-chart-box { margin: 6px 0 10px; }
.tp-chart-seg { margin-bottom: 6px; max-width: 260px; }
.curve-chart.tp-chart { display: block; width: 100%; height: auto; }
.curve-chart .grid { stroke: var(--rule); stroke-width: 0.6; }
.curve-chart .tp-line { fill: none; stroke-width: 2; stroke-linejoin: round; }
.curve-chart .tp-envelope { fill: none; stroke: var(--ink); stroke-opacity: .13; stroke-width: 9; stroke-linejoin: round; stroke-linecap: round; }
.curve-chart .tp-qmax { stroke: var(--warm); stroke-width: 1.2; stroke-dasharray: 4 3; }
.tp-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 11px; color: var(--ink-soft); margin-top: 4px; }
.tp-legend i { display: inline-block; width: 12px; height: 3px; border-radius: 2px; margin-right: 5px; vertical-align: middle; }
.tp-legend i.env { height: 7px; background: var(--ink); opacity: .18; }
.tp-legend i.op { width: 8px; height: 8px; border-radius: 50%; background: var(--warm); }
.tp-results { margin-top: 6px; }
.tp-state { display: flex; align-items: baseline; gap: 8px; padding: 7px 10px; border-radius: 4px;
            border-left: 3px solid var(--ok); background: var(--field); margin-bottom: 8px; }
.tp-state strong { font-family: var(--mono); font-size: 14px; }
.tp-state span { font-size: 12px; color: var(--ink-soft); }
.tp-state.edge { border-left-color: var(--c-c98500); }
.tp-state.bad { border-left-color: var(--danger); }
.tp-state.bad span { color: var(--danger); font-weight: 600; }
.tp-limits { width: 100%; border-collapse: collapse; font-size: 11.5px; margin: 8px 0; }
.tp-limits th { text-align: left; font-size: 10px; font-weight: 600; color: var(--ink-faint);
                border-bottom: 1px solid var(--rule-firm); padding: 2px 4px 3px 0; }
.tp-limits td { padding: 3px 4px 3px 0; border-bottom: 1px solid var(--rule); color: var(--ink-mid); }
.tp-limits .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tp-limits tr.gov td { color: var(--ink); font-weight: 600; }
.tp-limits .sw { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 6px; }
.tp-limits .basis { font-size: 10px; padding: 0 5px; border-radius: 8px; background: var(--shell); color: var(--ink-soft); white-space: nowrap; }

/* ---------------------------------------------------------------- Calibration */

.calibration .advisor-head { align-items: flex-start; }
.cal-steps { display: flex; flex-wrap: wrap; gap: 4px; }
.cal-step {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 5px 11px 5px 6px; border: 1px solid var(--rule-firm); border-radius: 999px;
    background: var(--panel); color: var(--ink-mid); font-size: 12.5px; cursor: pointer;
}
.cal-step .n {
    display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 50%;
    background: var(--field); color: var(--ink-soft); font: 600 11px/1 var(--mono);
}
.cal-step.done .n { background: var(--brand-pale); color: var(--brand-deep); }
.cal-step.on { border-color: var(--brand); color: var(--ink); background: var(--brand-pale); }
.cal-step.on .n { background: var(--brand); color: var(--on-fill); }
.cal-step:disabled { opacity: 0.45; cursor: not-allowed; }
.cal-step:hover:not(:disabled):not(.on) { border-color: var(--ink-faint); }

.cal-grid { display: grid; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); gap: 28px; align-items: start; }
.cal-grid.wide { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 1100px) { .cal-grid, .cal-grid.wide { grid-template-columns: 1fr; gap: 20px; } }
.cal-out .run-row, .cal-grid .run-row { margin-top: 14px; }
.cal-next { flex: 0 1 auto !important; }
.cal-intro { max-width: 70ch; display: grid; gap: 12px; justify-items: start; }

.cal-exp { padding: 8px 10px; border: 1px solid var(--rule); border-radius: 6px; margin-bottom: 8px; display: grid; gap: 3px; }
.cal-exp.on { border-color: var(--brand); background: var(--brand-pale); }
.cal-exp-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cal-exp-head select { width: auto; }
.cal-exp small { color: var(--ink-soft); font-size: 11.5px; }
.cal-exp .link-button.remove { justify-self: start; margin: 0; font-size: 11.5px; }
.cal-exp-name { font-weight: 600; color: var(--ink); }

label.check { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink-mid); margin: 6px 0; cursor: pointer; }
label.check input { width: auto; }
.cal-map { width: 100%; font-size: 12.5px; }
.cal-map td { padding: 4px 6px 4px 0; vertical-align: middle; }
.cal-map input[type=number] { width: 70px; }
.cal-pre { margin: 10px 0; border-top: 1px solid var(--rule); padding-top: 8px; }
.cal-pre summary { cursor: pointer; font-weight: 600; font-size: 12.5px; color: var(--ink-mid); }
.cal-log { margin: 4px 0 0 18px; font-size: 12px; color: var(--ink-soft); line-height: 1.55; }
.cal-picker { margin-bottom: 8px; max-width: 560px; }

.cal-chart { position: relative; max-width: 820px; }
.cal-chart .legend .swatch.dashed { background: none !important; border-top: 2px dashed var(--ink-faint); height: 0; }
.cal-chart .legend .swatch.dot { width: 7px; height: 7px; border-radius: 50%; }
.cal-chart .legend .swatch.band { height: 9px; opacity: 0.3; }
.advisor svg .cal-cross { stroke: var(--ink-faint); stroke-width: 1; stroke-dasharray: 3 3; }
.cal-hit { cursor: crosshair; }
.cal-tip {
    position: absolute; z-index: 5; pointer-events: none; min-width: 150px;
    background: var(--panel); border: 1px solid var(--rule-firm); border-radius: 6px;
    box-shadow: 0 4px 14px rgba(23, 27, 33, 0.12); padding: 7px 9px;
    display: grid; gap: 3px; font-size: 11.5px; color: var(--ink-mid);
}
.cal-tip span { display: flex; align-items: center; gap: 6px; }
.cal-tip b { font-family: var(--mono); font-weight: 600; color: var(--ink); }

.pill {
    display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: 999px;
    font-size: 11px; font-weight: 600; background: var(--field); color: var(--ink-soft);
    border: 1px solid var(--rule); white-space: nowrap;
}
.pill.good { background: var(--c-edf4ef); color: var(--ok); border-color: var(--c-cfe3d6); }
.pill.warn { background: var(--c-fdf3e7); color: var(--c-8a4b0f); border-color: var(--c-f0d9bb); }
.pill.bad { background: var(--c-fbeceb); color: var(--danger); border-color: var(--c-f0cfcc); }
.cal-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

.cal-params { width: 100%; font-size: 12.5px; border-collapse: collapse; }
.cal-params th, .cal-params td { padding: 6px 10px; vertical-align: top; }
.cal-params th:first-child, .cal-params td:first-child { padding-left: 0; }
.cal-params th { white-space: nowrap; }
.cal-params td small, .cal-params th small, .cal-bounds td small { display: block; color: var(--ink-faint); font-size: 11px; font-weight: 400; }
.cal-params td.num, .cal-params th.num { text-align: right; font-family: var(--mono); }
.cal-bounds { font-size: 12.5px; }
.cal-bounds th, .cal-bounds td { padding: 5px 8px 5px 0; text-align: left; }
.cal-bounds input, .cal-bounds select { width: 96px; }
.cal-bounds input, .cal-map input[type=number] {
    padding: 5px 7px; border: 1px solid var(--rule-firm); border-radius: 5px;
    background: var(--field); font: 12.5px var(--mono); color: var(--ink);
}
.cal-bounds input:focus, .cal-map input:focus { border-color: var(--brand); background: var(--panel); }

.cal-finding { border-left: 3px solid var(--rule-firm); padding: 6px 10px; margin-bottom: 10px; background: var(--field); border-radius: 0 6px 6px 0; }
.cal-finding.bad { border-left-color: var(--danger); }
.cal-finding.warn { border-left-color: var(--c-c98a2c); }
.cal-finding-head { display: flex; align-items: center; gap: 8px; }
.cal-finding p { margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-mid); }
.cal-finding p.evidence { font-family: var(--mono); font-size: 11.5px; color: var(--ink-soft); }

.cal-verdict { display: flex; gap: 12px; padding: 12px 14px; border-radius: 8px; border: 1px solid var(--rule); margin-bottom: 18px; }
.cal-verdict .icon { flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; font-weight: 700; color: var(--on-fill); background: var(--ink-faint); }
.cal-verdict strong { font-size: 15px; }
.cal-verdict ul { margin: 6px 0 0 18px; font-size: 12.5px; color: var(--ink-mid); line-height: 1.5; }
.cal-verdict.good { border-color: var(--c-cfe3d6); background: var(--c-f4f9f6); }
.cal-verdict.good .icon { background: var(--ok); }
.cal-verdict.warn { border-color: var(--c-f0d9bb); background: var(--c-fdf8f1); }
.cal-verdict.warn .icon { background: var(--c-c98a2c); }
.cal-verdict.bad { border-color: var(--c-f0cfcc); background: var(--c-fdf5f4); }
.cal-verdict.bad .icon { background: var(--danger); }
.cal-answer { font-size: 13.5px; line-height: 1.55; max-width: 70ch; }
.cal-audit { display: grid; grid-template-columns: max-content 1fr; gap: 3px 14px; font-size: 12.5px; }
.cal-audit dt { color: var(--ink-soft); }
.cal-audit .mono { font-family: var(--mono); }
.calibration details summary { cursor: pointer; font-size: 12.5px; color: var(--ink-mid); margin-top: 8px; }

.cal-heat { display: grid; gap: 2px; font-size: 11.5px; max-width: 560px; }
.cal-heat span { padding: 5px 4px; }
.cal-heat .h { text-align: center; color: var(--ink-soft); font-family: var(--mono); }
.cal-heat .rl { color: var(--ink-mid); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-heat .c { text-align: center; font-family: var(--mono); border-radius: 3px; }
.cal-heat .c.diag { background: repeating-linear-gradient(45deg, var(--field), var(--field) 4px, var(--rule) 4px, var(--rule) 5px); }

.cal-group { margin-bottom: 12px; }
.cal-group-name { font-size: 11.5px; font-weight: 600; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
.cal-pick { display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 8px; padding: 3px 0; font-size: 12.5px; cursor: pointer; }
.cal-pick input { width: auto; }
.cal-pick small { color: var(--ink-faint); font-family: var(--mono); font-size: 11px; }
.cal-pick .info { font-style: normal; color: var(--ink-faint); border: 1px solid var(--rule-firm); border-radius: 50%; width: 16px; height: 16px; display: grid; place-items: center; font-size: 10px; }
.cal-chosen { margin-left: 18px; font-size: 12.5px; line-height: 1.7; }
.cal-chosen small { color: var(--ink-faint); font-family: var(--mono); }
.cal-recs { margin-left: 20px; font-size: 13px; line-height: 1.55; display: grid; gap: 6px; }
.cal-actions { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------------------------------------------------------------- 4.9: correlations, sinks, boiling */

.phys-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; }
.phys-fields .field { min-width: 0; }
.phys-readout { margin-top: 10px; padding: 10px 12px; border: 1px solid var(--rule); border-radius: 6px; background: var(--field); }
.phys-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 6px; font-size: 12px; color: var(--ink-soft); }
.phys-head strong { font-family: var(--mono); font-size: 14px; color: var(--ink); }
.phys-row { display: flex; justify-content: space-between; font-size: 12.5px; padding: 2px 0; }
.phys-row strong { font-family: var(--mono); }
.phys-row strong.warn, td.warn { color: var(--warm); }
.phys-grid { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; font-size: 12px; margin: 6px 0; }
.phys-grid strong { font-family: var(--mono); text-align: right; }
.phys-warn { margin: 6px 0 0 16px; font-size: 11.5px; color: var(--c-8a4b0f); line-height: 1.45; }
.phys-readout .hint.mono { font-family: var(--mono); font-size: 11px; }
.phys-chart { width: 100%; max-width: 320px; display: block; background: var(--panel); }
.phys-chart .axis { stroke: var(--rule-firm); }
.phys-chart .grid { stroke: var(--rule); }
.phys-chart .tick { font-family: var(--mono); font-size: 9px; fill: var(--ink-faint); }
.phys-chart .axis-label { font-size: 10px; fill: var(--ink-soft); }
.sink-picture { margin: 4px 0 8px; }
.sink-svg { width: 100%; max-width: 260px; display: block; background: var(--panel); border: 1px solid var(--rule); border-radius: 5px; }
.layer-row { border: 1px solid var(--rule); border-radius: 6px; padding: 6px 8px; margin-bottom: 4px; }
.layer-head { display: flex; gap: 8px; align-items: center; }
.layer-head input { flex: 1; font-weight: 600; }
.layer-iface { padding: 0 8px 4px; border-left: 3px solid var(--warm); margin: 0 0 4px 10px; }
.modal-body.enc-body { display: block; overflow: auto; padding: 8px 20px 16px; }
.enc-card .table-scroll { overflow-x: auto; }
.enc-table input, .enc-title input, .layer-head input {
    padding: 4px 6px; border: 1px solid var(--rule-firm); border-radius: 5px;
    background: var(--field); font: 12.5px var(--mono); color: var(--ink);
}
.enc-title input, .layer-head input { font-family: inherit; font-weight: 600; }
.enc-card { border: 1px solid var(--rule); border-radius: 8px; padding: 10px 12px; margin: 10px 0; }
.enc-card h3 { font-size: 13px; margin-bottom: 6px; }
.enc-title { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.enc-title input { flex: 1; font-weight: 600; }
.enc-table { font-size: 12px; border-collapse: collapse; }
.enc-table th, .enc-table td { padding: 3px 5px; text-align: left; white-space: nowrap; }
.enc-table input[type=number] { width: 72px; }
.enc-table .fcell { width: 56px; }
.enc-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin-top: 6px; }

/* ---------------------------------------------------------------- advanced disclosures (ui.js) */

details.adv { margin: 10px 0 4px; border-top: 1px dashed var(--rule-firm); }
details.adv > summary {
    list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
    padding: 8px 0 6px; font-size: 11.5px; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--ink-soft);
}
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::before {
    content: ""; width: 6px; height: 6px; border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform 0.12s;
}
details.adv[open] > summary::before { transform: rotate(45deg); }
details.adv > summary:hover, details.adv > summary:focus-visible { color: var(--brand); }
details.adv > .adv-body { padding: 2px 0 6px; }

/* UX pass: link inspectors */
.lsec { margin: 12px 0 4px; }
.lsec-title {
    margin: 0 0 6px; padding-bottom: 3px; border-bottom: 1px solid var(--rule);
    font-size: 11.5px; font-weight: 600; color: var(--ink-mid);
}
.layer-row details.adv { margin: 4px 0 0; }
.layer-row details.adv > summary { padding: 5px 0 3px; }
.enc-card .lsec:first-of-type { margin-top: 8px; }
.enc-body > details.adv { margin-top: 14px; }

/* UX pass: workbench */
.cal-lead { margin: 0 0 12px; font-size: 12.5px; color: var(--ink-mid); max-width: 80ch; }
.field-row.wrap { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.form-block details.adv, .cal-form > details.adv { margin-top: 6px; }
details.adv > .adv-body > .form-block:first-child { margin-top: 0; }
.advisor-section + details.adv, .kpi-row + details.adv, .study-chart + details.adv { margin-top: 14px; }
/* Bounds table: prior, scale and scope columns show while "Advanced" is open. */
.cal-bounds-wrap details.adv { margin: 0 0 6px; }
.cal-bounds-wrap .adv-col { display: none; }
.cal-bounds-wrap:has(> details.adv[open]) .adv-col { display: table-cell; }

/* Fluid picker: concentration box for water mixtures */
.mix-pct { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.mix-pct[hidden] { display: none; }
.mix-pct input { width: 5.5em; flex: none; }
.mix-pct .mix-basis { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.insert-line .mix-pct { margin-top: 4px; }

/* Simulation job tray (ui.js jobTray) */
.job-tray {
    position: fixed; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: 60; width: min(320px, calc(100vw - 32px));
    display: flex; flex-direction: column; gap: 8px;
}
.job-tray[hidden] { display: none; }
.job-row {
    background: var(--panel); border: 1px solid var(--rule-firm); border-radius: 6px;
    box-shadow: 0 6px 20px rgba(23, 27, 33, 0.12); padding: 10px 12px;
}
.job-row-head { display: flex; align-items: baseline; gap: 8px; font-size: 13px; }
.job-label { font-weight: 600; color: var(--ink); }
.job-state { color: var(--ink-soft); font-variant-numeric: tabular-nums; margin-right: auto; }
.job-cancel { font-size: 12px; }
.job-bar { height: 4px; margin-top: 8px; background: var(--rule); border-radius: 2px; overflow: hidden; }
.job-bar i { display: block; height: 100%; background: var(--brand); transition: width 0.25s ease; }
.job-bar.indeterminate i { animation: job-slide 1.2s ease-in-out infinite; }
@keyframes job-slide { 0% { transform: translateX(-100%); } 100% { transform: translateX(300%); } }
@media (prefers-reduced-motion: reduce) {
    .job-bar.indeterminate i { animation: none; opacity: 0.6; width: 100% !important; }
}

/* ---------------------------------------------------------------- accounts */

/* Organization / project, beside the model name: where this work is saved
   and whose plan it runs on. A quiet button until it is empty, when it asks
   to be clicked. */
.context {
    display: flex;
    align-items: baseline;
    gap: 5px;
    max-width: 320px;
    min-width: 0;
    padding: 4px 9px;
    border: 1px solid var(--rule);
    border-radius: 5px;
    background: var(--field);
    font-size: 12.5px;
    color: var(--ink-mid);
}
.context-org { color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px; }
.context-sep { color: var(--ink-faint); }
.context-project { font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.context.empty .context-project { color: var(--warm); }

.account { position: relative; display: flex; align-items: center; margin-left: 4px; }

/* Help: the reference pages, off the toolbar. Shares the account menu's box. */
.help-area { position: relative; display: flex; align-items: center; margin-right: 6px; }
.help-menu { width: 300px; }
.help-menu > a {
    display: flex; flex-direction: column; gap: 1px;
    padding: 7px 10px; border-radius: 5px;
    color: var(--ink); text-decoration: none;
}
.help-menu > a:hover, .help-menu > a:focus-visible { background: var(--field); outline: none; }
.help-menu > a b { font-weight: 600; font-size: 13px; }
.help-menu > a span { font-size: 12px; color: var(--ink-soft); }
.help-version {
    margin-top: 4px; padding: 7px 10px 3px;
    border-top: 1px solid var(--rule);
    font-size: 11.5px; color: var(--ink-faint);
}

.avatar {
    width: 30px; height: 30px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--brand);
    background: var(--brand-pale);
    color: var(--brand-deep);
    font-size: 11.5px;
    font-weight: 650;
    letter-spacing: .02em;
}
.avatar:hover:not(:disabled) { background: var(--brand); border-color: var(--brand); color: var(--on-fill); }

.account-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 70;
    width: 280px;
    display: flex;
    flex-direction: column;
    padding: 6px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 8px;
    box-shadow: 0 14px 36px rgba(29,34,41,.22);
}
.account-menu > button {
    text-align: left;
    border: 0;
    background: none;
    padding: 7px 10px;
    color: var(--ink);
}
.account-menu > button:hover:not(:disabled) { background: var(--field); }
.account-menu > button.menu-quiet { color: var(--ink-soft); border-top: 1px solid var(--rule); border-radius: 0 0 5px 5px; margin-top: 4px; }
.account-who { display: flex; flex-direction: column; padding: 6px 10px 8px; border-bottom: 1px solid var(--rule); }
.account-who b { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; }
.account-who span { font-size: 12px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; }
.account-switch, .account-plan {
    display: flex; flex-direction: column; gap: 4px;
    padding: 8px 10px; border-bottom: 1px solid var(--rule);
    font-size: 12.5px;
}
.account-plan { flex-direction: row; justify-content: space-between; margin-bottom: 4px; }
.account-plan .warn { color: var(--danger); font-weight: 600; }
.account-menu .k, .acct-section h3 {
    font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
    text-transform: uppercase; color: var(--ink-faint);
}

.plan-banner {
    position: fixed;
    top: calc(var(--topbar-h) + 10px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 65;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: min(720px, calc(100% - 32px));
    padding: 8px 8px 8px 16px;
    background: var(--panel);
    border: 1px solid var(--brand);
    border-left-width: 4px;
    border-radius: 6px;
    box-shadow: 0 10px 28px rgba(29,34,41,.18);
    font-size: 13px;
}
.plan-banner.bad { border-color: var(--danger); }
.plan-banner .modal-close { position: static; }

.modal.account-modal { width: min(900px, 100%); height: min(620px, 100%); }
.modal.account-modal.compact { width: min(620px, 100%); height: auto; max-height: 100%; }

.account-body {
    flex: 1; min-height: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
.acct-col { display: flex; flex-direction: column; gap: 8px; padding: 14px 18px; min-height: 0; overflow-y: auto; }
.acct-col + .acct-col { border-left: 1px solid var(--rule); }
.acct-scroll { overflow-y: auto; padding: 4px 20px 12px; }

.acct-head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ink-faint);
}
.acct-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
    font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--ink-mid); }

.acct-list { list-style: none; display: flex; flex-direction: column; gap: 2px; }
.acct-row { display: flex; align-items: center; gap: 6px; border-radius: 6px; }
.acct-row:hover { background: var(--field); }
.acct-row.current { background: var(--brand-pale); }
.acct-row.archived { opacity: .7; }
.acct-pick {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: flex-start;
    border: 0; background: none; padding: 7px 10px; text-align: left;
}
.acct-pick:hover:not(:disabled) { background: none; }
.acct-pick b { font-weight: 600; font-size: 13px; color: var(--ink); max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-pick small { font-size: 11.5px; color: var(--ink-soft); }
.acct-row-actions { display: flex; gap: 2px; padding-right: 6px; }
.linkish.danger { color: var(--danger); }
.acct-empty { padding: 8px 10px; font-size: 12.5px; color: var(--ink-soft); }

.acct-inline { display: flex; gap: 6px; }
.acct-inline input {
    flex: 1; min-width: 0; font: inherit; font-size: 13px;
    padding: 6px 9px; border: 1px solid var(--rule-firm); border-radius: 5px; background: var(--panel);
}
.acct-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.acct-status { font-size: 12.5px; color: var(--ink-soft); }
.acct-status.bad { color: var(--danger); }

.acct-section { display: flex; flex-direction: column; gap: 8px; padding: 14px 0; }
.acct-section + .acct-section { border-top: 1px solid var(--rule); }
.acct-section .hint { font-size: 12.5px; color: var(--ink-soft); }

.plan-name { display: flex; align-items: baseline; gap: 10px; }
.plan-name b { font-size: 18px; font-weight: 650; letter-spacing: -.01em; }
.plan-status { font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
    padding: 2px 7px; border-radius: 10px; background: var(--field); color: var(--ink-soft); }
.plan-status.active, .plan-status.trialing { background: var(--brand-pale); color: var(--brand-deep); }
.plan-status.past_due, .plan-status.unpaid { background: var(--c-fbeceb); color: var(--danger); }
.notice { font-size: 12.5px; padding: 8px 10px; border-radius: 5px; background: var(--field);
    border-left: 3px solid var(--brand); }
.notice.bad { border-left-color: var(--danger); background: var(--c-fbeceb); }

.meter { display: flex; flex-direction: column; gap: 4px; }
.meter-label { display: flex; justify-content: space-between; font-size: 12.5px; }
.meter-track { height: 6px; border-radius: 3px; background: var(--shell); overflow: hidden; }
.meter-fill { height: 100%; border-radius: 3px; background: var(--brand); }
.meter-track.high .meter-fill { background: var(--warm); }

.offer {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 16px; align-items: start;
    padding: 12px; border: 1px solid var(--rule); border-radius: 8px;
}
.offer .offer-features { grid-column: 1; list-style: none; display: flex; flex-wrap: wrap;
    gap: 4px 12px; font-size: 12px; color: var(--ink-mid); }
.offer .offer-features li::before { content: "\2713  "; color: var(--brand); }
.offer button { grid-column: 2; grid-row: 1 / span 2; align-self: center; }

@media (max-width: 720px) {
    .account-body { grid-template-columns: 1fr; }
    .acct-col + .acct-col { border-left: 0; border-top: 1px solid var(--rule); }
    .context { display: none; }
    .offer { grid-template-columns: 1fr; }
    .offer button { grid-column: 1; grid-row: auto; }
}

/* ---------------------------------------------------------------- operating envelope */

.env-grid { grid-template-columns: minmax(360px, 460px) minmax(0, 1fr); }
.env-form .field input, .env-form .field select { width: 100%; }
.env-form .field-row.env-row { grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); margin-bottom: 8px; }
.env-form .env-wide { grid-column: span 2; }

.env-scn-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.env-scn {
    padding: 4px 11px; border-radius: 14px; font-size: 12.5px;
    border: 1px solid var(--rule-firm); background: var(--panel); color: var(--ink-mid);
}
.env-scn.on { background: var(--brand-pale); border-color: var(--brand); color: var(--brand-deep); font-weight: 600; }
.env-scn.off { text-decoration: line-through; color: var(--ink-faint); }
.env-scn-tools { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; margin: 8px 0 2px; }

.env-var, .env-out {
    border: 1px solid var(--rule); border-radius: 6px; background: var(--field);
    padding: 10px 11px 4px; margin-bottom: 10px;
}
.env-var-head { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.env-var-name {
    flex: 1; min-width: 0; font: inherit; font-weight: 600; font-size: 13px;
    padding: 4px 7px; border: 1px solid transparent; border-radius: 4px; background: none;
}
.env-var-name:hover, .env-var-name:focus { border-color: var(--rule-firm); background: var(--panel); outline: none; }
.env-var-key { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); }
.env-var-head select { font-size: 12px; max-width: 150px; }
.env-var-more { display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; margin: 2px 0 6px; }
.env-dist { display: inline-flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.env-dist input { width: 72px; font: inherit; font-size: 12px; padding: 4px 6px; }
.env-dist select { font-size: 12px; }
.env-fixed { align-self: end; padding-bottom: 8px; }
.env-remove { align-self: end; padding-bottom: 6px; }
.env-add-row { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
.env-add-row .hint { flex: 1; min-width: 200px; margin: 0; }
.env-con { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.env-con input { flex: 1; font-family: var(--mono); font-size: 12px; padding: 5px 7px; }
.env-form code { font-family: var(--mono); font-size: 11.5px; background: var(--field); padding: 1px 4px; border-radius: 3px; }

.env-methods { display: grid; gap: 6px; margin-bottom: 10px; }
.env-method {
    display: grid; grid-template-columns: 18px 1fr; gap: 8px; align-items: start;
    padding: 7px 9px; border: 1px solid var(--rule); border-radius: 6px; cursor: pointer;
}
.env-method.on { border-color: var(--brand); background: var(--brand-pale); }
.env-method input { margin-top: 3px; }
.env-method b { display: block; font-size: 13px; font-weight: 600; }
.env-method small { display: block; font-size: 11.5px; color: var(--ink-soft); line-height: 1.4; }

.env-estimate { margin: 4px 0 12px; }
.env-estimate table { font-size: 12px; }
.env-est-total { margin: 8px 0 4px; font-size: 13px; }
.env-warn {
    margin: 6px 0; padding: 6px 9px; font-size: 12.5px; border-radius: 4px;
    background: var(--c-fdf3e8); border-left: 3px solid var(--warm); color: var(--ink);
}
.env-run { margin-bottom: 8px; }
.env-run button[hidden] { display: none; }
.env-progress { margin: 6px 0 14px; }
.env-bar { height: 8px; border-radius: 4px; background: var(--shell); overflow: hidden; }
.env-bar span { display: block; height: 100%; width: 0; background: var(--brand); transition: width .3s ease; }
.env-bar span.indeterminate { animation: env-pulse 1.4s ease-in-out infinite; }
@keyframes env-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .env-bar span { transition: none; animation: none; } }
.env-progress-text { margin-top: 6px; font-size: 12.5px; color: var(--ink-mid); font-variant-numeric: tabular-nums; }

.env-tabs { margin: 0 0 14px; }
.env-bad { color: var(--danger); font-weight: 600; }
tr.env-fail-row td:first-child { box-shadow: inset 3px 0 0 var(--danger); }
tr.env-click { cursor: pointer; }
tr.env-click:hover td { background: var(--field); }
.env-sub { display: block; font-size: 11px; color: var(--ink-faint); font-weight: 400; }
.env-status, .env-basis {
    display: inline-block; padding: 1px 7px; border-radius: 9px; font-size: 11px;
    font-weight: 700; letter-spacing: .04em;
}
.env-status.pass { background: var(--c-e4f1e9); color: var(--ok); }
.env-status.fail { background: var(--c-fbeceb); color: var(--danger); }
.env-basis { font-weight: 600; letter-spacing: 0; background: var(--field); color: var(--ink-mid); border: 1px solid var(--rule); }
.env-basis.search { background: var(--c-edf2fb); color: var(--cool); border-color: var(--c-c9d8f2); }
.env-conclusions { margin: 0; padding-left: 18px; display: grid; gap: 6px; font-size: 13px; line-height: 1.5; max-width: 90ch; }

.env-map-controls { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 10px; }
.env-map-wrap { max-width: 820px; }
#env-map-svg .tick { font-family: var(--mono); font-size: 10px; fill: var(--ink-soft); }
#env-map-svg .axis-label { font-size: 11.5px; fill: var(--ink-mid); }
#env-map-svg .axis { stroke: var(--rule-firm); }
#env-map-svg .limit { stroke: var(--danger); stroke-dasharray: 4 3; stroke-width: 1.5; }
#env-map-svg .limit-label { font-size: 10.5px; fill: var(--danger); }
.env-dot { fill: var(--ink); stroke: #fff; stroke-width: .8; cursor: pointer; }
.env-dot:hover { fill: var(--brand); }
.env-cell-fail { stroke: var(--danger); stroke-width: .8; }
.env-boundary { stroke: var(--ink); stroke-width: 2; stroke-linecap: square; }
.env-hist { max-width: 620px; }

.env-point-tools { display: flex; flex-wrap: wrap; gap: 0; align-items: center; margin-bottom: 10px; }
.env-point-tools .seg-btn { border: 1px solid var(--rule-firm); margin-right: -1px; padding: 5px 10px; font-size: 12px; }
.env-point-tools .seg-btn.on { background: var(--brand-pale); color: var(--brand-deep); }
.env-point-tools .linkish { margin-left: 12px; }
.env-points { max-height: 420px; overflow: auto; }
.env-points td, .env-points th { white-space: nowrap; }
.env-point-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; margin-bottom: 10px; }
.env-point-grid h5 { margin: 0 0 6px; font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.env-kv { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; border-bottom: 1px solid var(--rule); font-size: 12.5px; }
.env-kv b { font-family: var(--mono); font-weight: 600; font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
    .env-grid { grid-template-columns: 1fr; }
}
/* The results stay in view while the definition beside them scrolls. */
.env-grid > .study-output { position: sticky; top: 8px; max-height: calc(100vh - 160px); overflow: auto; }
.env-empty { border: 1px dashed var(--rule-firm); border-radius: 8px; padding: 18px 20px; color: var(--ink-soft); font-size: 13px; line-height: 1.55; max-width: 70ch; }
.env-empty ol { margin: 8px 0 0 18px; }
#env-results .advisor-notes { margin-bottom: 14px; }

/* =========================================================================
   Analyze workspace (4.15)

   Build and Analyze are two views of one model. Analyze trades the model
   tree, the insert palette and the property rail for a navigation rail and a
   full-width page, and keeps the canvas beside it as a heat-coloured view of
   the model, so a diagnosis can still light up the path it is talking about.
   ========================================================================= */

:root {
    --amber:      #9a5b00;
    --amber-pale: #fbf1dc;
    --ok-pale:    #e6f2ea;
    --bad-pale:   #fbeceb;
}

.workspace-switch { flex: none; margin-left: 4px; }
.workspace-switch .seg-btn { flex: none; padding: 5px 16px; font-size: 12.5px; }

/* ---------------------------------------------------------------- navigation */

.analysis-nav {
    background: var(--panel);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 0 16px;
}
.nav-group { padding: 8px 10px 6px; }
.nav-group + .nav-group { border-top: 1px solid var(--rule); }
.nav-group-head {
    display: flex;
    align-items: baseline;
    gap: 7px;
    padding: 2px 8px 5px;
}
.nav-step {
    font-family: var(--mono);
    font-size: 10.5px;
    color: var(--ink-faint);
    min-width: 12px;
}
.nav-group-name {
    font-size: 11px;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-mid);
}
.nav-group-q { display: block; padding: 0 8px 6px 27px; font-size: 11.5px; color: var(--ink-faint); line-height: 1.35; }
.nav-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
    font: inherit;
    font-size: 13px;
    color: var(--ink-mid);
    background: none;
    border: 0;
    border-radius: 5px;
    padding: 6px 8px 6px 27px;
    position: relative;
    cursor: pointer;
}
.nav-item:hover:not(:disabled) { background: var(--field); color: var(--ink); }
.nav-item.on { background: var(--brand-pale); color: var(--ink); font-weight: 600; }
.nav-item.on::before {
    content: "";
    position: absolute;
    left: 0; top: 5px; bottom: 5px;
    width: 3px;
    border-radius: 2px;
    background: var(--brand);
}
.nav-item .nav-label { flex: 1; min-width: 0; }
.nav-item .nav-meta { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); font-weight: 400; }
.nav-dot {
    flex: none;
    width: 8px; height: 8px;
    border-radius: 50%;
    border: 1.5px solid var(--rule-firm);
    background: transparent;
}
.nav-dot.done { background: var(--brand); border-color: var(--brand); }
.nav-dot.pass { background: var(--ok); border-color: var(--ok); }
.nav-dot.fail { background: var(--danger); border-color: var(--danger); }
.nav-dot.margin { background: var(--amber); border-color: var(--amber); }
.nav-dot.stale { background: var(--panel); border-color: var(--amber); }
.nav-foot {
    margin-top: auto;
    padding: 12px 18px 0;
    border-top: 1px solid var(--rule);
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 12px;
    color: var(--ink-soft);
}
.nav-foot label { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.nav-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 11px; color: var(--ink-faint); }
.nav-legend span { display: inline-flex; align-items: center; gap: 4px; }

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

.analysis-page {
    background: var(--panel);
    min-height: 0;
    overflow-y: auto;
    padding: 22px 28px 48px;
}
.apage { display: none; max-width: 1480px; }
.apage.on { display: block; }

.apage-head { margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid var(--rule); }
.apage-head:empty { display: none; }
.apage-crumb {
    font-size: 11px;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--brand);
}
.apage-title { font-size: 20px; font-weight: 650; letter-spacing: -.01em; margin: 2px 0 2px; text-wrap: balance; }
.apage-title:focus { outline: none; }
.apage-title:focus-visible { outline: none; }   /* a place, not a control */
.apage-question { font-size: 14px; color: var(--ink-mid); max-width: 80ch; text-wrap: pretty; }
.apage-about { font-size: 12.5px; color: var(--ink-soft); margin-top: 4px; max-width: 90ch; }
.apage-head-row { display: flex; align-items: flex-start; gap: 20px; justify-content: space-between; flex-wrap: wrap; }
.apage-head .context-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.chip-info {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    padding: 3px 9px;
    border: 1px solid var(--rule);
    border-radius: 999px;
    background: var(--field);
    color: var(--ink-mid);
}
.chip-info b { font-weight: 600; color: var(--ink); }
.chip-info.warn { border-color: var(--c-ecd3a6); background: var(--amber-pale); color: var(--amber); }

.apage-next:empty { display: none; }
.apage-next { margin-top: 28px; max-width: 1480px; }

/* the recommended next step */
.next-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px 16px;
    padding: 12px 16px;
    border-radius: 7px;
    background: var(--brand-pale);
    border: 1px solid color-mix(in srgb, var(--brand) 25%, var(--rule));
}
.next-card .next-tag {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--brand-deep);
}
.next-card .next-text { font-size: 13.5px; color: var(--ink); }
.next-card .next-text small { display: block; font-size: 12px; color: var(--ink-soft); margin-top: 1px; }
.next-card.quiet { background: var(--field); border-color: var(--rule); }
.next-card.quiet .next-tag { color: var(--ink-soft); }

/* ---------------------------------------------------------------- verdicts */

.pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11.5px;
    font-weight: 650;
    padding: 2px 8px;
    border-radius: 999px;
    white-space: nowrap;
    letter-spacing: .01em;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.pass { background: var(--ok-pale); color: var(--ok); }
.pill.fail { background: var(--bad-pale); color: var(--danger); }
.pill.margin { background: var(--amber-pale); color: var(--amber); }
.pill.na, .pill.stale { background: var(--field); color: var(--ink-soft); }

.verdict {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border-radius: 7px;
    border: 1px solid var(--rule);
    border-left-width: 4px;
    margin-bottom: 16px;
    background: var(--field);
}
.verdict.pass { border-left-color: var(--ok); background: var(--ok-pale); }
.verdict.fail { border-left-color: var(--danger); background: var(--bad-pale); }
.verdict.margin { border-left-color: var(--amber); background: var(--amber-pale); }
.verdict-main { font-size: 15px; font-weight: 650; color: var(--ink); }
.verdict-sub { font-size: 12.5px; color: var(--ink-mid); margin-top: 2px; }
.verdict .grow { flex: 1; }

table.req-table td, table.req-table th { vertical-align: middle; }
table.req-table th:last-child, table.req-table td:last-child { padding-left: 16px; }
table.req-table td.num b { font-weight: 650; }
table.req-table tr.fail td.num.value { color: var(--danger); }
table.req-table tr.margin td.num.value { color: var(--amber); }
table.req-table .where { display: block; font-size: 11.5px; color: var(--ink-faint); }
.margin-bar { display: inline-block; width: 70px; height: 5px; border-radius: 3px; background: var(--rule); vertical-align: middle; margin-left: 8px; position: relative; overflow: hidden; }
.margin-bar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; }

/* ---------------------------------------------------------------- check page */

.check-run {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px 16px;
    padding: 12px 14px;
    border: 1px solid var(--rule);
    border-radius: 7px;
    margin-bottom: 18px;
    background: var(--field);
}
.check-run .seg { width: 220px; background: var(--panel); }
.check-run .field { margin-bottom: 0; width: 120px; }
.check-run .field.seg-field { width: auto; }
.check-run .hint { flex: 1 1 260px; margin: 0; }
.check-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
#check-results-slot #results { margin-top: 26px; }
#check-results-slot .results-heading { font-size: 13px; font-weight: 650; color: var(--ink-mid); margin: 28px 0 10px; padding-bottom: 6px; border-bottom: 1px solid var(--rule); }

/* ---------------------------------------------------------------- overview */

.review-model { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 18px; }
.review-list { display: flex; flex-direction: column; border: 1px solid var(--rule); border-radius: 8px; overflow: hidden; margin-top: 18px; }
.review-step {
    display: grid;
    grid-template-columns: 34px minmax(180px, 240px) minmax(0, 1fr) auto;
    gap: 4px 16px;
    align-items: start;
    padding: 14px 16px;
    background: var(--panel);
}
.review-step + .review-step { border-top: 1px solid var(--rule); }
.review-num {
    width: 26px; height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-soft);
    border: 1.5px solid var(--rule-firm);
    background: var(--panel);
}
.review-step.done .review-num { background: var(--brand); border-color: var(--brand); color: var(--on-fill); }
.review-step.pass .review-num { background: var(--ok); border-color: var(--ok); color: var(--on-fill); }
.review-step.fail .review-num { background: var(--danger); border-color: var(--danger); color: var(--on-fill); }
.review-step.margin .review-num, .review-step.stale .review-num { background: var(--amber-pale); border-color: var(--amber); color: var(--amber); }
.review-name { font-size: 14px; font-weight: 650; }
.review-q { font-size: 12.5px; color: var(--ink-soft); line-height: 1.4; }
.review-findings { display: flex; flex-direction: column; gap: 5px; font-size: 13px; color: var(--ink-mid); min-width: 0; }
.review-findings .none { color: var(--ink-faint); }
.review-finding { display: flex; gap: 8px; align-items: baseline; }
.review-finding .tool { flex: none; font-size: 11.5px; color: var(--ink-faint); min-width: 118px; }
.review-finding .stale-note { color: var(--amber); font-size: 11.5px; }
.review-actions { display: flex; flex-direction: column; gap: 5px; align-items: flex-end; }
.review-actions button { padding: 4px 11px; font-size: 12.5px; white-space: nowrap; }

@media (max-width: 1100px) {
    .review-step { grid-template-columns: 34px minmax(0, 1fr); }
    .review-findings, .review-actions { grid-column: 2; align-items: flex-start; }
}

/* ---------------------------------------------------------------- requirements */

.req-editor { display: flex; flex-direction: column; gap: 8px; max-width: 1100px; }
.req-row {
    display: grid;
    grid-template-columns: minmax(170px, 1.5fr) repeat(3, minmax(70px, .55fr)) minmax(120px, .8fr) minmax(130px, 1fr) 28px;
    gap: 10px;
    align-items: end;
    padding: 10px 12px 2px;
    border: 1px solid var(--rule);
    border-radius: 6px;
    background: var(--field);
}
.req-row .field { margin-bottom: 8px; }
.req-row .req-now { font-size: 12px; color: var(--ink-soft); padding-bottom: 12px; min-width: 0; overflow-wrap: anywhere; }
.req-row .req-now b { font-family: var(--mono); font-weight: 600; color: var(--ink); }
.req-row .icon-btn { margin-bottom: 10px; }
.req-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 6px; }
.empty-state {
    border: 1px dashed var(--rule-firm);
    border-radius: 8px;
    padding: 18px 20px;
    max-width: 760px;
    background: var(--field);
}
.empty-state b { display: block; font-size: 14px; margin-bottom: 4px; }
.empty-state p { font-size: 13px; color: var(--ink-mid); margin-bottom: 10px; }
@media (max-width: 1100px) {
    .req-row { grid-template-columns: 1fr 1fr 1fr; }
}

/* ---------------------------------------------------------------- inputs */

.inputs-editor { max-width: 1100px; }
.inputs-editor .env-var { margin-bottom: 10px; }
.inputs-editor .field-row.env-row { grid-template-columns: minmax(0, 2.2fr) minmax(90px, .8fr) minmax(110px, .9fr); margin-bottom: 4px; }
.inputs-editor .field-row.env-row.env-range { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.inputs-editor .env-wide { grid-column: auto; }
.inputs-editor .env-range .env-wide { grid-column: 1 / -1; }
.input-roles { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.use-list { display: flex; flex-direction: column; gap: 6px; }
.use-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 10px;
    align-items: center;
    padding: 7px 10px;
    border: 1px solid var(--rule);
    border-radius: 6px;
    background: var(--field);
    font-size: 13px;
}
.use-row.off { opacity: .6; }
.use-row .use-range { font-family: var(--mono); font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.use-row .use-sub { display: block; font-size: 11.5px; color: var(--ink-faint); }
.use-row.blocked { opacity: .55; }
.role-tag { font-size: 10.5px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-faint); margin-left: 6px; }

/* measure picker inside the study forms */
.measure-note { font-size: 12px; color: var(--ink-soft); margin: -4px 0 10px; }
.measure-note b { color: var(--ink); font-weight: 600; }

/* the report page */
.report-contents { display: flex; flex-direction: column; gap: 6px; max-width: 820px; margin: 12px 0 18px; }
.report-line { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 8px; font-size: 13px; color: var(--ink-mid); }
.report-line .tick-mark { color: var(--ok); font-weight: 700; }
.report-line.missing { color: var(--ink-faint); }
.report-line.missing .tick-mark { color: var(--ink-faint); }

/* the Build drawer's link across */
.drawer-link {
    align-self: center;
    margin-left: 12px;
    border: 0;
    background: none;
    color: var(--brand);
    font-size: 12.5px;
    font-weight: 600;
    padding: 4px 8px;
}
.drawer-link:hover:not(:disabled) { background: var(--brand-pale); color: var(--brand-deep); }
.req-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    align-items: center;
    padding: 8px 12px;
    margin-bottom: 12px;
    border: 1px solid var(--rule);
    border-radius: 6px;
    font-size: 12.5px;
    color: var(--ink-mid);
}
.req-strip:empty { display: none; }
.req-strip .grow { flex: 1; }

/* the study pages carry their own header now */
.apage.advisor .advisor-head { display: none; }
.apage.calibration .cal-steps { margin-bottom: 14px; }

table.heatmap td.cell.over { outline: 2px solid var(--danger); outline-offset: -2px; }
.study-output .env-empty:first-child { margin-top: 0; }

/* The page narrows when the model sits beside it: lay the studies out by the
   page's own width, not the window's. */
.analysis-page { container-type: inline-size; }
@container (max-width: 980px) {
    .apage .study-grid, .apage .env-grid { grid-template-columns: minmax(0, 1fr); gap: 22px; }
    .apage .env-grid > .study-output { position: static; max-height: none; }
    .review-step { grid-template-columns: 34px minmax(0, 1fr) auto; }
    .review-step > div:nth-child(2) { grid-column: 2; }
    .review-findings { grid-column: 2 / span 2; grid-row: 2; }
    .review-actions { grid-column: 3; grid-row: 1; flex-direction: row; flex-wrap: wrap; justify-content: flex-end; }
    .req-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .req-row .field:first-child { grid-column: 1 / -1; }
    /* Stacked, a study's settings keep a form's width; the results below
       them still take the page. */
    .apage .study-form { max-width: 600px; }
}
@container (max-width: 700px) {
    .study-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container (max-width: 460px) {
    .study-cards { grid-template-columns: minmax(0, 1fr); }
}
@container (min-width: 981px) {
    .apage .study-grid { grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); }
}

/* Which release this is: what an alpha tester quotes in a bug report. */
.stage-badge {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--amber);
    background: var(--amber-pale);
    border: 1px solid var(--c-ecd3a6);
    border-radius: 4px;
    padding: 1px 6px;
    cursor: default;
}

/* Experimental parts: hidden until switched on, never removed, so a model
   that already has a chiller in it still opens and solves. */
body.no-experimental [data-experimental] { display: none; }
.exp-toggle { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-soft); cursor: pointer; }

/* Recovery of an autosaved model, offered at start (history.js). */
.recover-bar {
    position: absolute;
    top: 14px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 9;
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: calc(100% - 32px);
    padding: 9px 10px 9px 14px;
    border: 1px solid var(--rule-firm);
    border-radius: 7px;
    background: var(--panel);
    box-shadow: 0 8px 24px rgba(23,27,33,.14);
    font-size: 12.5px;
}
.recover-bar span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.recover-bar button { flex: none; }

/* -------------------------------------------------------------------------
   Imported layouts (pcbimport.js)
   ------------------------------------------------------------------------- */

.pcb-tools { flex-wrap: wrap; row-gap: 6px; }
.pcb-view { flex: none; }
.pcb-view .seg-btn { padding: 4px 9px; }

/* A shaped board: the outline is drawn, not the box. */
.pcb-board.shaped { background: transparent; border: 0; box-shadow: none; }
.pcb-outline { position: absolute; inset: 0; overflow: visible; }
.pcb-outline path { fill: var(--c-d9e6dd); stroke: var(--c-94a89b); stroke-width: 1; filter: drop-shadow(0 2px 5px rgba(29,34,41,.18)); }
.pcb-copper { image-rendering: pixelated; opacity: 1; }
.pcb-kmap { opacity: .95; }
.pcb-region-grid { position: absolute; inset: 0; pointer-events: none; }
.pcb-region-grid path { stroke: rgba(23,27,33,.28); stroke-width: .6; fill: none; }

.pcb-part.imp { transform-origin: 50% 50%; cursor: pointer; }
.pcb-part.imp.in-model { background: rgba(194,82,31,.82); border-color: var(--c-8c3a14); }
.pcb-part.imp.needs { background: rgb(var(--glass) / .55); border: 1px dashed var(--c-8c3a14); color: var(--ink); }
.pcb-part.imp.blocked { background: rgba(169,34,24,.18); border: 1.5px solid var(--danger); color: var(--danger); }
.pcb-part.imp.hidden-part { background: rgb(var(--glass) / .3); border: 1px dotted var(--ink-faint); color: var(--ink-faint); }
.pcb-part.imp.faded { opacity: .45; }

/* The import panel under the board */
.pcb-import {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    height: 42%;
    min-height: 180px;
    border-top: 1px solid var(--rule-firm);
    background: var(--panel);
}
.pcb-import.folded { height: auto; min-height: 0; }
.pcb-import.folded .pcb-import-body { display: none; }
.pcb-import.folded #pcb-import-fold svg { transform: rotate(180deg); }
.pcb-import-head { display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-bottom: 1px solid var(--rule); }
.pcb-import-tabs .seg-btn { padding: 4px 10px; white-space: nowrap; }
.pcb-import-status { font-size: 11.5px; color: var(--ink-soft); }
.pcb-import-body { flex: 1; min-height: 0; overflow: auto; padding: 10px 12px 14px; font-size: 12.5px; }

.imp-summary { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.imp-block { border: 1px solid var(--rule); border-radius: 6px; padding: 8px 10px; line-height: 1.5; }
.imp-block h4, .imp-lists h4 { margin: 0 0 4px; font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }
.imp-lists { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 12px; }
.imp-dim { color: var(--ink-soft); font-size: 11.5px; }
.imp-note { margin: 0 0 6px; color: var(--ink-mid); font-size: 11.5px; }
.imp-note.error { color: var(--danger); }
.imp-warn {
    display: block; width: 100%; text-align: left; margin-bottom: 4px;
    background: var(--c-fdf3df); border: 1px solid var(--c-ecd3a6); color: var(--c-6e4a00); font-size: 12px;
}
.imp-warn.error { background: var(--c-fbeceb); border-color: var(--c-e7b7b2); color: var(--danger); }
button.link { background: none; border: 0; padding: 0; color: var(--brand-deep); text-decoration: underline; cursor: pointer; font-size: inherit; }

.imp-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 8px; }
.imp-controls .grow { flex: 1; }
.imp-inline { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--ink-mid); }
.imp-inline input[type=number] { width: 72px; }
#imp-search { width: 180px; }
.imp-filter { background: var(--brand-pale); padding: 5px 9px; border-radius: 5px; margin-bottom: 8px; }
.imp-csv { background: var(--field); border: 1px solid var(--rule); border-radius: 5px; padding: 6px 9px; margin-bottom: 8px; display: flex; flex-wrap: wrap; gap: 10px; }
.imp-csv .warn { color: var(--c-6e4a00); }
.imp-csv.bad { color: var(--danger); }

.imp-table-wrap { overflow: auto; }
.imp-table { border-collapse: collapse; width: 100%; font-size: 12px; }
.imp-table th, .imp-table td { padding: 3px 6px; border-bottom: 1px solid var(--rule); text-align: left; white-space: nowrap; vertical-align: middle; }
.imp-table th { position: sticky; top: 0; background: var(--field); font-weight: 600; color: var(--ink-mid); z-index: 1; }
.imp-table .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.imp-table td.num input { width: 70px; text-align: right; font-family: var(--mono); padding: 2px 4px; }
.imp-table input[data-source="library"] { background: var(--c-eef3fb); }
.imp-table input[data-source="imported"] { background: var(--c-eef7ef); }
.imp-table input.assumed { background: var(--c-fdf3df); border-color: var(--c-ecd3a6); }
.assumed-key { background: var(--c-fdf3df); border: 1px solid var(--c-ecd3a6); padding: 0 4px; border-radius: 3px; }
.imp-table td.part { max-width: 260px; overflow: hidden; }
.imp-table td.part span { display: block; overflow: hidden; text-overflow: ellipsis; }
.imp-table td.part small, .imp-table small { color: var(--ink-faint); display: block; overflow: hidden; text-overflow: ellipsis; }
.imp-table td.ref { font-weight: 600; }
.imp-table tr.on td { background: var(--brand-pale); }
.imp-table tr[data-row] { cursor: pointer; }
.imp-table.stack tr.copper td { background: var(--c-fbf4ec); }
.imp-table td.src { white-space: normal; color: var(--ink-soft); font-size: 11px; max-width: 280px; }
.imp-badge { display: inline-block; padding: 0 6px; border-radius: 9px; font-size: 11px; background: var(--field); color: var(--ink-soft); border: 1px solid var(--rule); }
.imp-badge.error { background: var(--c-fbeceb); color: var(--danger); border-color: var(--c-e7b7b2); font-weight: 600; }
.imp-badge.warn { background: var(--c-fdf3df); color: var(--c-6e4a00); border-color: var(--c-ecd3a6); }
.imp-badge.ok { background: var(--c-e5f2ea); color: var(--ok); border-color: var(--c-b5d6c2); }
.imp-figures { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px 14px; margin: 6px 0 10px; }
.imp-figures div { display: flex; justify-content: space-between; gap: 8px; border-bottom: 1px dotted var(--rule); }
.imp-figures span { color: var(--ink-soft); }
.imp-figures b { font-family: var(--mono); font-weight: 500; }
.imp-part-head { margin-bottom: 8px; }
.imp-part-head span { color: var(--ink-soft); }
.imp-src { color: var(--c-2f5b9a); font-weight: 500; }
/* The stage shares its height between the board and the import panel. */
.pcb-stage { min-height: 0; overflow: hidden; }
.pcb-canvas { overflow: hidden; }
.pcb-view .seg-btn, .pcb-import-tabs .seg-btn { flex: none; min-width: 0; overflow: visible; text-overflow: clip; }
.pcb-view, .pcb-import-tabs { width: auto; }
.pcb-part.imp span { display: inline-block; }
/* With an imported layout the stage needs the width: the side panels narrow. */
.modal-body.importing { grid-template-columns: 240px minmax(0, 1fr) 250px; }
.imp-table td.num input { width: 58px; }

/* IPC-2581 / import review additions: holes, vias, the reduced-order model,
   materials that need assigning, the thermal settings. */
.pcb-holes, .pcb-model { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.pcb-holes circle { fill: rgb(var(--glass) / .9); stroke: var(--c-6b5a8a); stroke-width: 1; }
.pcb-holes circle.mount { stroke: var(--c-6b2a8a); stroke-width: 1.6; }
.pcb-holes circle.standoff { fill: var(--c-6b2a8a); }
.pcb-holes circle { pointer-events: auto; }
.pcb-vias { pointer-events: none; }
.pcb-model path.mesh { stroke: rgba(23,27,33,.32); stroke-width: .5; fill: none; }
.pcb-model path.contact { fill: rgba(194,82,31,.35); stroke: var(--c-8c3a14); stroke-width: 1; }
.imp-summary.review { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.imp-block.bad { border-color: var(--danger); background: rgba(169,34,24,.05); }
.imp-ok { color: var(--c-2e7d4f); font-weight: 600; }
.imp-warn-mark { color: var(--danger); font-weight: 600; }
.imp-settings { border: 1px solid var(--rule); border-radius: 6px; padding: 8px 10px; margin: 10px 0; }
.imp-settings h4 { margin: 0 0 6px; font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }
.imp-settings .imp-controls { flex-wrap: wrap; row-gap: 6px; }
.imp-settings #imp-lump { width: 56px; }
.imp-table tr.unresolved td { background: rgba(169,34,24,.07); }
.imp-table select.imp-assign { max-width: 170px; font-size: 11.5px; }
.imp-table.mount tr.blocked td { background: rgba(169,34,24,.07); }
.imp-table.mount input[type=number] { width: 70px; }
.imp-block button.link, .imp-note button.link { padding: 0; border: 0; background: none; color: var(--accent, var(--c-c2521f)); cursor: pointer; font: inherit; text-decoration: underline; }

/* A board's components in the model tree. */
.kind.part-chip { background: var(--c-c2521f); }
.tr.part.over .meta { color: var(--danger); font-weight: 600; }
.imp-table.stack input[type=number] { width: 62px; }
.imp-table.stack td, .imp-table.stack th { padding-top: 3px; padding-bottom: 3px; vertical-align: middle; }

/* Analyze > Baseline results: the board parts table. */
.board-parts { margin: 10px 0 16px; }
.board-parts h4 { margin: 0 0 6px; font-size: 13px; }
.board-parts h4 .where { font-weight: 400; color: var(--ink-soft); margin-left: 6px; }
.board-parts h4 .bad { color: var(--danger); }
.parts-table tbody tr { cursor: pointer; }
.parts-table tbody tr:hover td { background: var(--field); }
.parts-table .margin-bar { width: 44px; }
.split-bar { display: inline-block; width: 36px; height: 5px; border-radius: 3px; background: var(--c-6b2a8a33); vertical-align: middle; margin-left: 6px; position: relative; overflow: hidden; }
.split-bar i { position: absolute; left: 0; top: 0; bottom: 0; background: var(--c-c2521f); }

/* ==========================================================================
   Kit: menus, command palette, toasts, state badges (kit.js)

   One menu, used by the header, the tree, the canvas and every context menu,
   so a menu looks and behaves the same wherever it opens.
   ========================================================================== */

:root {
    --float-shadow: 0 8px 28px rgba(23, 27, 33, .18), 0 1px 3px rgba(23, 27, 33, .12);
    --row-h: 28px;
}

.kit-menu {
    position: fixed;
    z-index: 120;
    min-width: 200px;
    max-width: 340px;
    max-height: calc(100vh - 12px);
    overflow-y: auto;
    padding: 4px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    box-shadow: var(--float-shadow);
    font-size: 13px;
}
.kit-menu-item {
    display: grid;
    grid-template-columns: 14px minmax(0, 1fr) auto;
    align-items: center;
    gap: 6px;
    width: 100%;
    min-height: var(--row-h);
    padding: 3px 10px 3px 6px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--ink);
    text-align: left;
    font-size: 13px;
}
.kit-menu-item:hover:not(:disabled),
.kit-menu-item:focus-visible { background: var(--brand-pale); color: var(--ink); outline: none; }
.kit-menu-item:disabled { color: var(--ink-faint); opacity: 1; }
.kit-menu-item.danger { color: var(--danger); }
.kit-menu-check { font-size: 11px; color: var(--brand); }
.kit-menu-label small { display: block; font-size: 11px; color: var(--ink-faint); line-height: 1.3; }
.kit-menu-keys { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); white-space: nowrap; padding-left: 14px; }
.kit-menu-sep { height: 1px; margin: 4px 2px; background: var(--rule); }
.kit-menu-heading {
    padding: 6px 8px 2px 26px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-faint);
}

/* ---------------------------------------------------------------- palette */

.kit-palette-shade {
    position: fixed;
    inset: 0;
    z-index: 130;
    background: rgba(23, 27, 33, .18);
    display: flex;
    justify-content: center;
    align-items: flex-start;
    padding-top: 12vh;
}
.kit-palette {
    width: min(620px, calc(100vw - 32px));
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 8px;
    box-shadow: var(--float-shadow);
    display: flex;
    flex-direction: column;
    max-height: 66vh;
    overflow: hidden;
}
.kit-palette-input {
    font: inherit;
    font-size: 15px;
    padding: 12px 14px;
    border: 0;
    border-bottom: 1px solid var(--rule);
    background: var(--panel);
    color: var(--ink);
    outline: none;
}
.kit-palette-list { overflow-y: auto; padding: 4px; }
.kit-palette-group {
    padding: 8px 10px 3px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-faint);
}
.kit-palette-row {
    display: grid;
    grid-template-columns: 96px minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    min-height: 32px;
    padding: 4px 10px;
    border-radius: 5px;
    cursor: pointer;
    font-size: 13px;
}
.kit-palette-row.on { background: var(--brand-pale); }
.kit-palette-kind { font-size: 11px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kit-palette-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kit-palette-title small { margin-left: 8px; font-size: 11.5px; color: var(--ink-soft); }
.kit-palette-keys { font-family: var(--mono); font-size: 11px; color: var(--ink-faint); }
.kit-palette-empty { padding: 18px 14px; color: var(--ink-soft); font-size: 13px; }
.kit-palette-foot {
    display: flex;
    gap: 16px;
    padding: 6px 12px;
    border-top: 1px solid var(--rule);
    background: var(--field);
    font-size: 11px;
    color: var(--ink-faint);
}
.kit-palette-foot kbd, .statusbar kbd {
    font-family: var(--mono);
    font-size: 10.5px;
    padding: 0 4px;
    margin-right: 2px;
    border: 1px solid var(--rule-firm);
    border-radius: 3px;
    background: var(--panel);
}

/* ---------------------------------------------------------------- toasts */

.kit-toast-host {
    position: fixed;
    left: 50%;
    bottom: 40px;
    transform: translateX(-50%);
    z-index: 125;
    pointer-events: none;
}
.kit-toast {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 10px 8px 14px;
    border-radius: 6px;
    background: var(--ink);
    color: var(--on-fill);
    font-size: 13px;
    box-shadow: var(--float-shadow);
    pointer-events: auto;
}
.kit-toast button {
    padding: 3px 9px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--c-9fe0d8);
    background: none;
    border: 1px solid rgb(var(--glass) / .25);
}
.kit-toast button:hover:not(:disabled) { background: rgb(var(--glass) / .1); color: var(--on-fill); border-color: rgb(var(--glass) / .4); }
.kit-toast.warn { background: var(--c-5b3a00); }
.kit-toast.error { background: var(--danger); }

/* ---------------------------------------------------------------- badges */

.kit-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
    color: var(--ink-soft);
}
.kit-badge.current, .kit-badge.ok { color: var(--ok); }
.kit-badge.stale, .kit-badge.warn { color: var(--amber); }
.kit-badge.failed, .kit-badge.error { color: var(--danger); }
.kit-badge.running { color: var(--brand); }

/* ==========================================================================
   The workspace (shell.js)

   Model tree | centre | properties, over a status bar. The centre shows the
   canvas with its results under it, or an analysis; the two side panels stay
   put either way, so the thing an analysis flags can be selected and edited
   without leaving it. Both sides resize and fold; below 1100px they become
   drawers over the centre, which keeps the canvas usable on a laptop.
   ========================================================================== */

.frame > .rail-left   { grid-column: 1; grid-row: 1; }
.frame > #split-left  { grid-column: 2; grid-row: 1; }
.frame > .workarea    { grid-column: 3; grid-row: 1; }
.frame > #split-right { grid-column: 4; grid-row: 1; }
.frame > .rail-right  { grid-column: 5; grid-row: 1; }
.frame > .statusbar   { grid-column: 1 / -1; grid-row: 2; }

.frame.left-shut  { grid-template-columns: 0 0 minmax(360px, 1fr) 0 var(--right-w); }
.frame.right-shut { grid-template-columns: var(--left-w) 0 minmax(360px, 1fr) 0 0; }
.frame.left-shut.right-shut { grid-template-columns: 0 0 minmax(0, 1fr) 0 0; }
.frame.left-shut > .rail-left, .frame.right-shut > .rail-right { display: none; }
.frame.left-shut > #split-left, .frame.right-shut > #split-right { display: none; }

.side.rail-left { border-right: 1px solid var(--rule); }
.side.rail-right { border-left: 1px solid var(--rule); }

/* A splitter is a zero-width column with a grip wider than it, so the
   panels keep their own rules and the grip is easy to catch. */
.splitter {
    position: relative;
    z-index: 6;
    width: 0;
    cursor: col-resize;
    touch-action: none;
}
.splitter::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    left: -4px;
    width: 8px;
}
.splitter:hover::after, .splitter.dragging::after, .splitter:focus-visible::after {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    left: -1px;
    width: 2px;
    background: var(--brand);
}
.splitter:focus-visible { outline: none; }

/* ---------------------------------------------------------------- centre */

.workarea {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    background: var(--panel);
}

.centre-bar {
    flex: none;
    height: 32px;
    display: flex;
    align-items: stretch;
    gap: 2px;
    padding: 0 4px;
    border-bottom: 1px solid var(--rule);
    background: var(--field);
}
.centre-bar .icon-btn { align-self: center; }
.centre-tabs { display: flex; align-items: stretch; gap: 0; margin-left: 4px; }
.centre-tab {
    border: 0;
    border-radius: 0;
    border-bottom: 2px solid transparent;
    background: none;
    padding: 0 14px;
    font-size: 12.5px;
    color: var(--ink-soft);
    white-space: nowrap;
}
.centre-tab:hover:not(:disabled) { background: var(--panel); color: var(--ink); border-color: transparent; border-bottom-color: var(--rule-firm); }
.centre-tab.on { color: var(--ink); font-weight: 600; border-bottom-color: var(--brand); background: var(--panel); }
.centre-tab.on:hover:not(:disabled) { border-bottom-color: var(--brand); }
.centre-tab-sub { font-weight: 400; color: var(--ink-faint); }
.centre-tab-sub:not(:empty)::before { content: " · "; }
.centre-option {
    align-self: center;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--ink-soft);
    padding: 0 8px;
    cursor: pointer;
    white-space: nowrap;
}

.centre-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    position: relative;
}
.centre-body > .stage { flex: 1 1 auto; min-height: 160px; position: relative; }
.centre-body > .drawer { flex: none; border-top: 1px solid var(--rule); }
.centre-body > .analysis-page { flex: 1 1 auto; }

/* An analysis takes the centre; with "Model beside", it shares it. */
body.ws-analyze .centre-body > .stage,
body.ws-analyze .centre-body > .drawer { display: none; }
body.ws-analyze.model-beside .centre-body { flex-direction: row; }
body.ws-analyze.model-beside .centre-body > .stage {
    display: flex;
    flex: 0 0 38%;
    min-width: 260px;
    border-left: 1px solid var(--rule);
    order: 2;
}
body.ws-analyze.model-beside .centre-body > .analysis-page { flex: 1 1 0; min-width: 0; }

/* The left rail: the tree above, Insert or the analyses below. */
body.ws-analyze .rail-left .insert { display: none; }
.rail-left > .analysis-nav {
    flex: 0 1 auto;
    max-height: 62%;
    border-top: 1px solid var(--rule);
    padding: 4px 0 8px;
    overflow-y: auto;
}
.rail-left > .analysis-nav .nav-group { padding: 4px 6px 2px; }
.rail-left > .analysis-nav .nav-group-q { display: none; }
.rail-left > .analysis-nav .nav-item { padding: 4px 8px 4px 27px; font-size: 12.5px; }
.rail-left > .analysis-nav .nav-foot { padding: 8px 14px 0; }
.rail-left > .tree { flex: 1 1 120px; min-height: 80px; }

/* ---------------------------------------------------------------- header */

.run-group { display: flex; align-items: center; gap: 6px; position: relative; }
.solve-split { display: flex; align-items: stretch; }
.solve-split .solve {
    width: auto;
    padding: 5px 14px;
    font-size: 13px;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.solve-split .solve-mode {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 9px;
    font-size: 12px;
    font-weight: 500;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    border-left: 1px solid rgb(var(--glass) / .35);
    white-space: nowrap;
}
.menu-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    white-space: nowrap;
}
.menu-btn[aria-expanded="true"] { background: var(--field); border-color: var(--ink-faint); color: var(--ink); }

.run-popover {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 60;
    width: 300px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    box-shadow: var(--float-shadow);
}
.run-popover .field-row { margin: 0; }

.search-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    width: 190px;
    padding: 4px 6px 4px 9px;
    color: var(--ink-faint);
    background: var(--field);
    border-color: var(--rule);
}
.search-btn svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; }
.search-btn .search-text { flex: 1; text-align: left; font-size: 12.5px; }
.search-keys {
    font-family: var(--mono);
    font-size: 10.5px;
    padding: 0 5px;
    border: 1px solid var(--rule-firm);
    border-radius: 3px;
    background: var(--panel);
    color: var(--ink-soft);
}

/* ---------------------------------------------------------------- status bar */

.statusbar {
    display: flex;
    align-items: stretch;
    gap: 0;
    min-width: 0;
    background: var(--field);
    border-top: 1px solid var(--rule);
    font-size: 11.5px;
    color: var(--ink-soft);
    overflow: hidden;
}
.statusbar .grow { flex: 1; margin: 0; }
.sb-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 0 10px;
    border: 0;
    border-right: 1px solid var(--rule);
    border-radius: 0;
    background: none;
    font-size: 11.5px;
    color: var(--ink-soft);
    white-space: nowrap;
}
.sb-item:empty { display: none; }
button.sb-item:hover:not(:disabled) { background: var(--panel); color: var(--ink); border-color: var(--rule); }
.statusbar .grow + .sb-item { border-left: 1px solid var(--rule); }
.statusbar .sb-item:last-child { border-right: 0; }
.sb-item .num { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--ink); }
.sb-item .kit-badge { font-size: 11px; }

/* ---------------------------------------------------------------- results headline */

.drawer-headline {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
    padding: 0 10px;
    font-size: 12px;
    color: var(--ink-soft);
    overflow: hidden;
    white-space: nowrap;
}
.drawer-headline:empty { display: none; }
.drawer-headline .metric { display: inline-flex; align-items: baseline; gap: 5px; }
.drawer-headline .metric b { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink); }
.drawer-headline button.metric {
    padding: 2px 6px;
    border: 1px solid transparent;
    background: none;
    font-size: 12px;
    color: var(--ink-soft);
}
.drawer-headline button.metric:hover:not(:disabled) { border-color: var(--rule-firm); background: var(--panel); }

/* ---------------------------------------------------------------- narrow windows */

@media (max-width: 1360px) {
    .search-btn { width: auto; }
    .search-btn .search-text { display: none; }
    .wordmark { display: none; }
}

@media (max-width: 1180px) {
    .doc input { width: 150px; }

    #example-picker { max-width: 110px; }
    .toolbar { gap: 5px; }
}

/* Below 1100px the side panels float over the centre as drawers, so the
   canvas keeps the whole width. They open from the centre bar's buttons. */
@media (max-width: 1100px) {
    .frame, .frame.left-shut, .frame.right-shut, .frame.left-shut.right-shut {
        grid-template-columns: 0 0 minmax(0, 1fr) 0 0;
    }
    .frame > .splitter { display: none; }
    .frame > .rail-left, .frame > .rail-right {
        display: none;
        position: relative;
        z-index: 40;
        box-shadow: var(--float-shadow);
    }
    .frame > .rail-left { width: min(300px, 80vw); grid-column: 1 / 4; justify-self: start; }
    .frame > .rail-right { width: min(340px, 85vw); grid-column: 3 / -1; justify-self: end; }
    .frame.left-open > .rail-left, .frame.right-open > .rail-right { display: flex; }
    .doc .model-state { display: none; }
    .topbar { gap: 8px; padding: 0 8px; }
    .brand .stage-badge { display: none; }
}

@media (max-width: 760px) {
    .tool-group[aria-label="Libraries"], .tool-rule, #btn-analyze-menu { display: none; }
    .doc input { width: 110px; }
    .solve-split .solve-mode #solve-mode-label { display: none; }
}

/* The document title stays a title: it gives way before the toolbar does. */
.topbar .doc { flex: 0 1 auto; overflow: hidden; }
.topbar .toolbar { flex: none; }
.statusbar .save-state { font-size: 11.5px; }

/* ---------------------------------------------------------------- outdated results

   Kept on screen after an edit, so the before is there to compare with, and
   marked so they cannot be read as the answer for the model as it is now:
   a banner, greyed tables, grey hatched temperatures on the canvas, and the
   status bar. Never colour alone: each says "outdated" in words too. */

.stale-banner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 10px 8px 14px;
    margin-bottom: 12px;
    border: 1px solid var(--c-e6c98a);
    border-left: 3px solid var(--amber);
    border-radius: 5px;
    background: var(--amber-pale);
    font-size: 13px;
    color: var(--ink);
}
.stale-banner span { flex: 1; }
.stale-banner button { padding: 4px 12px; font-size: 12.5px; flex: none; }
#results.stale .results-grid,
#results.stale .fluid-results,
#results.stale .thermo,
#results.stale .fluid-summary,
#results.stale #status { opacity: .55; }
#world .node-temp.stale {
    background: repeating-linear-gradient(135deg, var(--c-e9ebef) 0 4px, var(--c-f6f7f9) 4px 8px) !important;
    color: var(--ink-soft) !important;
    border: 1px dashed var(--rule-firm);
}
.drawer-headline.stale .metric b { color: var(--ink-soft); }

/* ---------------------------------------------------------------- several at once (modelling.js) */

#world .node.multi-sel, #world .device.multi-sel, #world .multi-sel {
    box-shadow: 0 0 0 2px var(--brand), 0 1px 3px rgba(29, 34, 41, .14);
}
#tree .tr.multi-sel { background: var(--brand-pale); }
.marquee {
    position: absolute;
    z-index: 8;
    border: 1px solid var(--brand);
    background: color-mix(in srgb, var(--brand) 10%, transparent);
    pointer-events: none;
}
.multi-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.multi-head b { font-size: 14px; }
.multi-head span { font-size: 12px; color: var(--ink-soft); }
.multi-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.multi-actions button { flex: 1 1 auto; }

/* A wire's type and resistance before a solve: quieter than a heat flow. */
#wires text.kind { fill: var(--ink-faint); font-family: var(--mono); font-size: 10px; }
.canvas-wrap.lod-low #wires text.kind { display: none; }

/* ---------------------------------------------------------------- unit-aware fields (fields.js) */

input.unit-field { font-family: var(--mono); font-variant-numeric: tabular-nums; }
input.unit-field.invalid,
input.unit-field.invalid:focus {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px var(--bad-pale);
}

/* ---------------------------------------------------------------- the first model */

.empty-actions { display: flex; gap: 8px; margin: 12px 0 6px; pointer-events: auto; }
.empty-actions button { padding: 6px 14px; }
.empty-canvas .empty-keys { font-size: 12px; color: var(--ink-faint); }

.first-model {
    position: absolute;
    left: 12px;
    bottom: 12px;
    z-index: 6;
    width: 270px;
    padding: 10px 12px 8px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(23, 27, 33, .08);
    font-size: 12.5px;
}
.fm-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.fm-head b { font-size: 12.5px; }
.fm-head span { color: var(--ink-faint); font-family: var(--mono); font-size: 11px; }
.fm-close { margin-left: auto; border: 0; background: none; padding: 0 4px; font-size: 16px; line-height: 1; color: var(--ink-faint); }
.first-model ol { list-style: none; display: flex; flex-direction: column; gap: 3px; }
.first-model li { display: flex; align-items: center; gap: 8px; color: var(--ink-mid); }
.first-model li.ok { color: var(--ink-faint); text-decoration: line-through; }
.fm-mark {
    flex: none;
    width: 16px; height: 16px;
    border-radius: 50%;
    border: 1px solid var(--rule-firm);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-family: var(--mono);
}
.first-model li.ok .fm-mark { background: var(--ok); border-color: var(--ok); color: var(--on-fill); }
.first-model .linkish { padding: 0; font-size: 12.5px; text-align: left; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* The shortcut sheet grew with the command registry: two columns, and it
   scrolls rather than running off the top of a short canvas. */
.shortcuts {
    top: 12px;
    bottom: auto;
    max-height: calc(100% - 24px);
    overflow-y: auto;
    width: min(640px, calc(100% - 32px));
    columns: 2 280px;
    column-gap: 24px;
}
.shortcuts h3 { break-after: avoid; }
.shortcuts dl { break-inside: auto; margin-bottom: 12px; }

/* ---------------------------------------------------------------- model health (diagnostics.js) */

.diag-panel {
    position: fixed;
    left: 8px;
    bottom: 30px;
    z-index: 110;
    width: min(460px, calc(100vw - 16px));
    max-height: min(560px, calc(100vh - 100px));
    overflow-y: auto;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 7px;
    box-shadow: var(--float-shadow);
    font-size: 13px;
}
.diag-panel header {
    position: sticky; top: 0;
    display: flex; flex-direction: column; gap: 2px;
    padding: 10px 40px 10px 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--rule);
}
.diag-panel header b { font-size: 13.5px; }
.diag-panel header span { color: var(--ink-soft); font-size: 12px; }
.diag-panel header .modal-close { position: absolute; top: 6px; right: 6px; }
.diag-list { list-style: none; padding: 6px 0; }
.diag-item { display: flex; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--rule); }
.diag-item:last-child { border-bottom: 0; }
.diag-glyph { flex: none; width: 16px; font-size: 12px; line-height: 20px; text-align: center; }
.diag-item.error .diag-glyph { color: var(--danger); }
.diag-item.warn .diag-glyph { color: var(--amber); }
.diag-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.diag-text b { font-weight: 600; color: var(--ink); }
.diag-text > span:not(.sr-only) { color: var(--ink-soft); font-size: 12.5px; }
.diag-fixes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.diag-fixes button { padding: 3px 10px; font-size: 12px; }
.diag-fixes.in-status { margin-top: 8px; }
.diag-ok { padding: 14px; }
.diag-checks { padding: 8px 14px 12px; font-size: 11.5px; color: var(--ink-faint); border-top: 1px solid var(--rule); }
.diag-panel footer { padding: 0 14px 12px; }

/* The object a problem belongs to, marked where it is drawn. */
#world .node.diag-error { box-shadow: 0 0 0 2px var(--danger), 0 1px 3px rgba(29, 34, 41, .14); }
#world .node.diag-warn  { box-shadow: 0 0 0 2px var(--amber), 0 1px 3px rgba(29, 34, 41, .14); }
#world .node.diag-error::after, #world .node.diag-warn::after {
    position: absolute; top: -9px; right: -9px;
    width: 18px; height: 18px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 700; color: var(--on-fill);
}
#world .node.diag-error::after { content: "✕"; background: var(--danger); }
#world .node.diag-warn::after  { content: "!"; background: var(--amber); }
#wire-layer g.diag-error .wire { stroke: var(--danger) !important; stroke-dasharray: 5 3; }
#tree .tr.diag-error .nm::after { content: " ✕"; color: var(--danger); font-size: 11px; }
#tree .tr.diag-warn .nm::after  { content: " ⚠"; color: var(--amber); font-size: 11px; }

/* ---------------------------------------------------------------- canvas views (views.js) */

.view-bar {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 7;
    display: flex;
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    overflow: hidden;
    background: var(--panel);
    box-shadow: 0 1px 3px rgba(23, 27, 33, .06);
}
.view-bar .seg-btn { flex: none; padding: 4px 10px; font-size: 12px; }
.view-bar .seg-btn:disabled { opacity: .45; }
.view-legend {
    position: absolute;
    top: 44px;
    left: 10px;
    z-index: 7;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px;
    font-size: 11.5px;
    font-family: var(--mono);
    color: var(--ink-mid);
    background: var(--panel);
    border: 1px solid var(--rule);
    border-radius: 5px;
}
.view-legend .ramp {
    width: 120px; height: 8px; border-radius: 2px;
    background: linear-gradient(90deg, hsl(214, 62%, 46%), hsl(114, 62%, 43%), hsl(14, 62%, 40%));
}
.view-legend .bars { display: inline-flex; align-items: flex-end; gap: 3px; height: 10px; }
.view-legend .bars i { display: block; width: 14px; background: var(--brand); border-radius: 1px; }
.view-legend .linkish { font-family: var(--sans); font-size: 11.5px; }

/* The transient time slider, at the foot of the canvas left of the zoom. */
.timeline {
    position: absolute;
    left: 12px;
    right: 150px;
    bottom: 12px;
    z-index: 7;
    max-width: 640px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px 4px 4px;
    background: var(--panel);
    border: 1px solid var(--rule-firm);
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(29,34,41,.12);
}
.timeline[hidden] { display: none; }
.timeline .tl-play {
    flex: none; width: 28px; height: 26px; padding: 0;
    border: 0; background: none; font-size: 12px; color: var(--brand);
}
.timeline .tl-play:hover { background: var(--field); }
.timeline .tl-range {
    flex: 1; min-width: 80px; height: 4px; margin: 0;
    appearance: none; -webkit-appearance: none; border-radius: 2px; cursor: pointer;
    border: 0; padding: 0; box-shadow: none;
    background: linear-gradient(90deg, var(--brand) var(--fill, 100%), var(--rule-firm) var(--fill, 100%));
}
.timeline .tl-range::-webkit-slider-thumb {
    -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;
    background: var(--panel); border: 2px solid var(--brand);
}
.timeline .tl-range::-moz-range-thumb {
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--panel); border: 2px solid var(--brand);
}
.timeline .tl-time { flex: none; font: 11.5px var(--mono); color: var(--ink-mid); white-space: nowrap; }
.timeline .tl-end { flex: none; font-size: 11.5px; }
/* Part-way through a run, the slider says so in colour as well as numbers. */
#canvas.scrubbing .timeline { border-color: var(--amber); }
#canvas.scrubbing .timeline .tl-time { color: var(--ink); font-weight: 600; }
.timeline .tl-note { flex: none; font-size: 11px; color: var(--ink-faint); display: none; }
#canvas.scrubbing .timeline .tl-note { display: inline; }
/* The wires' heat flows are the end of the run's; part-way through they step back. */
#canvas.scrubbing #wires text.flow { opacity: .4; }
#chart { cursor: crosshair; }
#chart line.tl-cursor { stroke: var(--amber); stroke-width: 1.5; stroke-dasharray: 4 3; pointer-events: none; }

#canvas.view-temperature #world .node[style*="--tint"] {
    border-color: var(--tint);
    background: color-mix(in srgb, var(--tint) 16%, var(--panel));
}
#canvas.view-flow #wires .wire.thermal,
#canvas.view-drop #wires .wire.thermal { stroke: var(--brand); transition: stroke-width .15s; }
#canvas.view-drop #wires .view-major .wire.thermal { stroke: var(--warm); }
@media (prefers-reduced-motion: reduce) { #canvas #wires .wire.thermal { transition: none; } }

/* Rows that name a part or a link select it (shell.js). */
.locatable { cursor: pointer; }
tr.locatable:hover td, .t-row.locatable:hover .bar-label { background: var(--brand-pale); }

/* ---------------------------------------------------------------- the board view (boardview.js) */

body.ws-board .centre-body > :not(#pcb-modal) { display: none !important; }
body.ws-board .rail-left .insert { display: none; }
.board-view { flex: 1 1 auto; min-height: 0; display: flex; }
.board-view .modal {
    width: 100%;
    height: 100%;
    border-radius: 0;
    box-shadow: none;
}
.board-view .modal-head { padding: 10px 16px 9px; }
.pcb-apply { font-size: 12px; color: var(--ink-soft); }
.pcb-apply.ok::before { content: "✓ "; color: var(--ok); }
.pcb-apply.warn { color: var(--amber); font-weight: 600; }
.pcb-apply.warn::before { content: "⚠ "; }
@media (max-width: 1280px) {
    .board-view .modal-body { grid-template-columns: 250px minmax(0, 1fr) 250px; }
}

/* ---------------------------------------------------------------- the model by role (treeviews.js) */

#tree .role-sep { margin-top: 10px; }
#tree .role-sec .nm { font-size: 11px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-mid); }
#tree .role-row .kind { width: 3px; height: 12px; border-radius: 1px; background: var(--rule-firm); }
#tree .role-row .kind.boundary { background: var(--cool); }
#tree .role-row .kind.load { background: var(--warm); }
#tree .role-row .kind.board-face, #tree .role-row .kind.board-load { background: var(--board); }
#tree .role-row .kind.fluid { background: var(--brand); }
#tree .role-row .kind.material { background: var(--ink-faint); width: 8px; height: 8px; border-radius: 2px; }
#tree .role-row[data-mat] { cursor: grab; }
#tree .role-action .nm { color: var(--brand); }
#wire-layer g.drop-target .wire { stroke: var(--brand) !important; stroke-width: 6px !important; }
.pcb-scale.stale i, .pcb-scale.stale span { opacity: .55; }
.pcb-scale-stale { color: var(--amber); font-size: 11px; font-weight: 600; margin-right: 6px; }
.board-peak.stale { color: var(--amber) !important; }
.stale-word { color: var(--amber); font-weight: 600; }

/* The material library, put to work (treeviews.js). */
.mat-in-model { margin-bottom: 14px; padding: 10px 12px; border: 1px solid var(--rule); border-radius: 6px; background: var(--field); }
.mat-in-model h3 { margin: 0 0 6px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }
.mat-in-model p { font-size: 12.5px; margin: 0 0 4px; }
.mat-uses { display: flex; flex-wrap: wrap; gap: 2px 8px; margin-bottom: 6px; }
.mat-assign { margin-top: 6px; }
.tag.used { background: var(--brand-pale); color: var(--brand-deep); }

/* ---------------------------------------------------------------- analyses home (analysis.js)

   A choice of studies, not a procedure: cards grouped by what they are for,
   set-up and results in one line each, the full review folded at the foot. */

.analysis-strip {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    margin: 4px 0 22px;
}
.strip-item {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    border: 1px solid var(--rule);
    border-radius: 6px;
    background: var(--field);
    font-size: 12.5px;
    min-width: 0;
}
.strip-item b { font-size: 11px; font-weight: 650; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-soft); }
.strip-item span { color: var(--ink-mid); overflow-wrap: anywhere; }
.strip-item .linkish { align-self: flex-start; padding: 0; margin-top: 2px; }

.study-group { margin-bottom: 20px; }
.study-group h2 { font-size: 13px; font-weight: 650; margin: 0 0 8px; color: var(--ink); }
.study-group h2 span { font-weight: 400; color: var(--ink-soft); margin-left: 6px; }
.study-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
/* The home page reads as one column of choices: the strip and the cards
   share three columns and stop at a width where a row is still one glance. */
#page-overview { max-width: 1180px; }
.study-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    text-align: left;
    padding: 11px 13px;
    border: 1px solid var(--rule-firm);
    border-radius: 7px;
    background: var(--panel);
    color: var(--ink);
    font-size: 12.5px;
    min-height: 84px;
}
.study-card:hover:not(:disabled) { border-color: var(--brand); background: var(--panel); box-shadow: 0 1px 4px rgba(13, 110, 102, .12); }
.study-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.study-card-head b { font-size: 13.5px; font-weight: 600; }
.study-card-q { color: var(--ink-soft); line-height: 1.4; }
.study-card-finding { color: var(--ink-mid); font-size: 12px; border-top: 1px solid var(--rule); padding-top: 5px; margin-top: 2px; }
.study-card.fail { border-color: var(--c-e6c9c6); }
.study-card.stale { border-style: dashed; }

.review-fold { margin-top: 26px; border-top: 1px solid var(--rule); padding-top: 12px; }
.review-fold > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink-mid); }
.review-fold > summary span { font-weight: 400; color: var(--ink-faint); margin-left: 6px; font-size: 12px; }
.review-fold[open] > summary { margin-bottom: 12px; }

.apage-about-fold { margin-top: 4px; }
.apage-about-fold > summary { cursor: pointer; font-size: 12px; color: var(--brand); width: max-content; }
.apage-about-fold[open] > summary { margin-bottom: 2px; }

/* Before a study has run: one quiet line rather than a dashed box. */
.study-output .env-empty { border: 0; background: none; padding: 4px 0; max-width: none; }
.study-output .env-empty b { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.study-output .env-empty p, .study-output .env-empty ol { font-size: 12.5px; color: var(--ink-soft); }

@media (max-width: 1100px) { .analysis-strip { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- requirements, hardened (analysis.js) */

/* Two lines: what it is (name, part), then the limit (max, min, margin,
   basis), with the verdict beside both. Eight fields in one line were
   unreadable at the width an analysis page has beside the rails. */
.req-row {
    grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(130px, 1.1fr) 28px;
    align-items: end;
}
.req-row > :nth-child(1) { grid-column: 1 / 3; grid-row: 1; }
.req-row > :nth-child(2) { grid-column: 3 / 5; grid-row: 1; }
.req-row > :nth-child(3) { grid-column: 1; grid-row: 2; }
.req-row > :nth-child(4) { grid-column: 2; grid-row: 2; }
.req-row > :nth-child(5) { grid-column: 3; grid-row: 2; }
.req-row > :nth-child(6) { grid-column: 4; grid-row: 2; }
.req-row > .req-now { grid-column: 5; grid-row: 1 / 3; align-self: center; }
.req-row > [data-rq-del] { grid-column: 6; grid-row: 1; align-self: start; margin-top: 4px; }
.req-row > .req-notes { grid-row: 3; }
.req-row.invalid { border-color: var(--c-e6c9c6); background: var(--bad-pale); }
.req-row .req-now small { display: block; font-size: 11px; color: var(--ink-soft); }
.req-notes { grid-column: 1 / -1; list-style: none; margin: -4px 0 8px; display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.req-notes li::before { margin-right: 6px; }
.req-notes li.err { color: var(--danger); }
.req-notes li.err::before { content: "✕"; }
.req-notes li.warn { color: var(--amber); }
.req-notes li.warn::before { content: "⚠"; }
.req-bad { color: var(--danger); font-weight: 600; }
.req-good { color: var(--ok); font-weight: 600; }
.req-summary { display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: baseline; margin: 0 0 12px; font-size: 13px; color: var(--ink-mid); }
.req-row > * { min-width: 0; }
.req-row .field input, .req-row .field select { width: 100%; min-width: 0; box-sizing: border-box; }
@media (max-width: 760px) {
    .req-row { grid-template-columns: 1fr 1fr 28px; }
    .req-row > :nth-child(n) { grid-column: auto; grid-row: auto; }
    .req-row > .req-now, .req-row > .req-notes { grid-column: 1 / -1; }
}
/* Outranks the older container rule that spans the first field across the row. */
.req-row > .field.req-name { grid-column: 1 / 3; }
@media (max-width: 760px) { .req-row > .field.req-name { grid-column: 1 / -1; } }

/* No model yet, on any study. */
.model-empty .empty-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* Theme switch, at the foot of the help menu. */
.help-theme { display: flex; align-items: center; gap: 0; margin: 6px 10px 2px; font-size: 12px; color: var(--ink-soft); }
.help-theme > span { flex: 1; }
.help-theme .seg-btn { flex: none; padding: 3px 8px; font-size: 12px; border: 1px solid var(--rule-firm); border-radius: 0; margin-left: -1px; background: var(--panel); }
.help-theme .seg-btn:first-of-type { border-radius: 5px 0 0 5px; }
.help-theme .seg-btn:last-of-type { border-radius: 0 5px 5px 0; }
.help-theme .seg-btn.on { background: var(--brand-pale); color: var(--brand-deep); border-color: var(--brand); position: relative; }

/* A temperature written in its scale colour (tempTextStyle in builder.js). */
.temp-text { color: var(--t-light); }
:root[data-theme="dark"] .temp-text { color: var(--t-dark); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .temp-text { color: var(--t-dark); } }


/* -- sign-in screen (account.js; only when the server requires sign-in) --- */
.signin-gate {
    position: fixed;
    inset: 0;
    z-index: 1000;              /* over the workspace and its dialogs; Clerk's own modal sits above */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--shell);
}
.signin-gate[hidden] { display: none; }
.gate-card {
    width: min(400px, 100%);
    padding: 32px 28px 24px;
    background: var(--panel);
    border: 1px solid var(--rule);
    border-radius: 10px;
    text-align: center;
    box-shadow: 0 12px 32px rgb(0 0 0 / 0.08);
}
.gate-card .mark { display: block; margin: 0 auto 10px; }
.gate-card h1 { margin: 0; font-size: 22px; font-weight: 400; }
.signin-gate .wordmark { display: inline; font-size: 22px; }
.gate-lede { margin: 6px 0 22px; color: var(--ink-soft); font-size: 13.5px; }
.gate-actions { display: flex; flex-direction: column; gap: 8px; }
.gate-actions button { width: 100%; height: 38px; font-size: 14px; }
.gate-note { margin: 10px 0 0; color: var(--ink-soft); font-size: 12.5px; line-height: 1.45; }
.gate-note.bad { color: var(--danger); margin-bottom: 12px; }
.gate-home { display: inline-block; margin-top: 22px; color: var(--ink-faint); font-size: 12px; }
.gate-home:hover { color: var(--brand); }
