@import url('./surface-layers.css');
/* A commit changes no geometry. Shared by parts, formats and inline parameters in both themes. */
[data-commit-cue], [data-commit-cue] > .field, [data-commit-cue] > .table-cell-value { animation: field-commit 450ms ease-out; }
@keyframes field-commit {
    from { background-color: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
    to { box-shadow: inset 0 0 0 1px transparent; }
}
@media (prefers-reduced-motion: reduce) {
    [data-commit-cue], [data-commit-cue] > .field, [data-commit-cue] > .table-cell-value { animation: none; background-color: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }
}

/* ============================================================================================
   Panel Optimizer — interface.

   Every colour comes from a variable so light and dark both stay legible; hardcoding them is what
   left text almost black on a dark background.

   The rules the screen is built to, and what each one is for:

   - Solid graphite chrome frames the work; colour marks actions, selection and verdicts.
   - Every control answers a press on pointer-*down*, within ~100 ms. A control that only responds
     on release reads as dead.
   - Nothing is a keyboard trap and nothing is invisible to the keyboard: every interactive thing
     carries a :focus-visible ring.
   - Motion is critically damped by default — it settles, it does not bounce. Bounce is reserved for
     something the user threw.
   - Sizes are in rem so the browser's own text size scales the layout with the text.
   - Tracking is size-specific: large text is tightened, small text is opened up. One fixed
     letter-spacing is wrong somewhere.
   - prefers-reduced-motion / -transparency / -contrast are all honoured, and none of them removes
     feedback — they replace it with a quieter equivalent.
   ============================================================================================ */

/* The light palette, and the default. Which one is in force is decided by theme.js, which sets
   `data-theme` on <html> before the first paint — from the OS preference, or from the choice the
   user made with the theme button. There is no `prefers-color-scheme` rule below on purpose: the
   dark palette is written once, and both routes into it go through that one attribute. */
:root {
    /* Semantic roles shared by the graphite light and dark themes. */
    --chrome-bg: #2d3142; --header-bg: #2d3142;
    --chrome-text: #ffffff; --chrome-ink: #ffffff; --chrome-muted: #bfc0c0;
    --chrome-hover: #3a3f55; --chrome-active-bg: #4f5d75;
    --chrome-active-text: #ffffff; --header-text: #ffffff;
    --header-muted: #bfc0c0; --header-control-hover: #3a3f55; --header-button-bg: #2d3142;
    --header-button-text: #ffffff; --header-quiet-text: #ffffff; --tab-selected: #ef8354;
    --action-bg: #ef8354; --action-hover: #e0703f; --action-hover-text: #22252f; --action-text: #2d3142;
    --variant-bg: #f1f1f2;
    --variant-selected-bg: #fdebe3; --variant-edge: #d3693a;
    --variant-shadow: none;
    --variant-selected-text: #2d3142; --variant-selected-muted: #4f5d75;
    --variant-selected-good: #2c7751; --variant-selected-bad: #c0392b;
    --header-status-text: #ffffff; --header-status-warn: #ffc96b;
    --header-count-text: #ffffff; --header-count-bad: #ff8a80;
    --header-close-text: #ffffff;
    --rail-primary-text: #2d3142; --map-grain: #f8fbff;
    --map-part-fill: #08274e; --map-selection: #ffc25e; --map-selection-edge: #ffd277;
    --row-selection-bg: #fdebe3;
    --row-selection-cell-bg: #fdebe3;
    --row-selection-shadow: inset 3px 0 0 var(--selection-edge);
    --row-selection-text: #2d3142; --row-selection-text-soft: #4f5d75;
    --row-selection-muted: #4f5d75; --row-selection-panel: #ffffff;
    --row-selection-hover: #f1f1f2; --row-selection-accent: #4f5d75;
    --row-selection-good: #2c7751; --row-selection-bad: #c0392b;
    --map-label: #f8fbff; --map-piece-label: #f8fbff;
    --edge-fallback: #4f5d75; --mirror-preview: #4f5d75;

    color-scheme: light;

    /* --- surfaces ------------------------------------------------------------------------- */
    --bg: #f1f1f2;
    --panel: #ffffff;
    --panel-2: #f1f1f2;
    --panel-3: #e4e6ea;
    --border: #d8d9db;
    --border-soft: #d8d9db;
    --hairline: #d8d9db;

    /* Solid graphite surfaces; no decorative glass or shadows. */
    --glass: #ffffff;
    --glass-edge: transparent;
    --glass-blur: none;
    --scrim: rgba(0, 0, 0, .18);
    --overlay: rgba(0, 0, 0, .46);
    --overlay-strong: rgba(0, 0, 0, .56);

    /* --- ink ------------------------------------------------------------------------------ */
    --text: #2d3142;
    --text-soft: #4f5d75;
    --muted: #4f5d75;

    /* --- accent and verdicts ---------------------------------------------------------------- */
    --accent: #4f5d75;
    --accent-hover: #2d3142;
    --accent-text: #ffffff;
    --accent-soft: #f1f1f2;
    --accent-soft-text: #2d3142;
    --ring: #2d3142;

    --good: #2c7751;
    --good-bg: #e6f2ec;
    --bad: #c0392b;
    --bad-bg: #fbeaea;
    --warn: #8a5a00;
    --warn-bg: #fff4d6;

    /* --- the drawings ----------------------------------------------------------------------- */
    --sheet: #d8e1eb;
    --sheet-edge: #6c819a;
    --part-fill: #08274e;
    --part-edge: #d4b16d;
    /* Only cutting maps use the owner’s intelliDivide reference; workspace colours stay graphite/coral. */
    --offcut: #e0f2e9;
    --offcut-edge: #3c8067;
    /* The middle grade: big enough to report as an offcut, under the business band, so the order is
       still charged for it. Neither money back nor money burnt — it stays the neutral it always was,
       and the green is reserved for board that actually returns. */
    --offcut-plain: #e6eff8;
    --offcut-plain-edge: #607f9f;
    --panel-face: #f1f1f2;
    --panel-edge: #4f5d75;
    --ink: #2d3142;
    --pending: #4f5d75;
    --diagram-line: #4f5d75;
    --canvas-grid: #f1f1f2;
    --canvas-grid-dot: #9aa0ab;
    --raised-edge: transparent;

    /* --- shape, depth, rhythm --------------------------------------------------------------- */
    --r-none: 0;
    --r-xs: 4px;
    --r-sm: 6px;
    --r-md: 10px;
    --r-lg: 14px;
    --r-full: 999px;

    --icon-sm: 14px;
    --icon-md: 16px;
    --icon-lg: 20px;
    --icon-stroke: 1.5;

    --sh-1: none;
    --sh-2: none;
    /* A bigger surface reads as thicker: more blur, deeper shadow than a chip. */
    --sh-3: none;
    --sh-popover: none;
    --sh-dialog: none;
    --sh-drawer: none;

    /* --- spacing and major layers ---------------------------------------------------------- */
    --sp-0_5: 1px; --sp-1: 2px; --sp-1_5: 3px; --sp-2: 4px;
    --sp-2_5: 5px; --sp-3: 6px; --sp-3_5: 7px; --sp-4: 8px;
    --sp-4_5: 9px; --sp-5: 10px; --sp-5_5: 11px; --sp-6: 12px;
    --sp-6_5: 13px; --sp-7: 14px; --sp-7_5: 15px; --sp-8: 16px;
    --sp-8_5: 17px; --sp-9: 18px; --sp-10: 20px; --sp-11: 22px;
    --sp-12: 24px; --sp-14: 28px; --sp-15: 30px; --sp-16: 32px;
    --sp-17: 34px; --sp-18: 36px; --sp-20: 40px; --sp-31: 62px; --sp-32: 64px;

    /* --- type ------------------------------------------------------------------------------- */
    --t-xs: .75rem;
    --t-sm: .8125rem;
    --t-md: .875rem;
    --t-base: .9375rem;
    --t-lg: 1rem;
    --t-xl: 1.25rem;

    /* --- motion ----------------------------------------------------------------------------- */
    /* Critically damped: reaches the target and stops. The house default. */
    --ease: cubic-bezier(.32, .72, 0, 1);
    /* A little overshoot, and only for something that was thrown or dropped. */
    --ease-bounce: cubic-bezier(.34, 1.32, .64, 1);
    --t-press: 90ms;
    --t-1: 150ms;
    --t-2: 260ms;
    /* Графит и коралл: semantic chrome, action, selection and drawing roles. */
    --map-selection-keyline: transparent;
    --map-selection-keyline-width: 0px;
    --map-focus-ring: #ffc25e;
    --map-inspector-focus-outline: 2px solid var(--map-focus-ring);
    --chrome-icon: #bfc0c0;
    --chrome-active-icon: #ffffff;
    --chrome-selected-icon: #ffffff;
    --chrome-focus-ring: #bfc0c0;
    --paper: #ffffff;
    --paper-ink: #121821;
    --paper-border: #587aa7;
    --paper-selection: #354964;
    --paper-selection-fill: #eef2f6;
    --contrast-border: #2d3142;
    --contrast-muted: #2d3142;

    /* Owner palette 14.10. AA corrections measured in theme-coral/contrast.json. */
    --field-border: #858b96; --selection-edge: #d3693a;
    --menu-marker: #ef8354; --chrome-edge: #2d3142; --tab-text: #2d3142;
    --offcut-text: #27435a; --map-waste-fill: #d0d7df; --map-waste-edge: #718294; --map-waste-text: #31475e; --issue-shadow: #0002; --issue-popover-shadow: #0003;
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --bg: #22252f;
    --panel: #2d3142;
    --panel-2: #22252f;
    --panel-3: #3a3f52;
    --border: #4a5368;
    --border-soft: #4a5368;
    --hairline: #4a5368;

    --glass: #2d3142;
    --glass-edge: transparent;
    --scrim: rgba(0, 0, 0, .5);

    --text: #ffffff;
    --text-soft: #bfc0c0;
    --muted: #bfc0c0;

    --accent: #bfc0c0;
    --accent-hover: #ffffff;
    --accent-text: #2d3142;
    --accent-soft: #3a3f52;
    --accent-soft-text: #ffffff;
    --ring: #ffffff;

    --good: #7fd1a0;
    --good-bg: #23372b;
    --bad: #ff8a80;
    --bad-bg: #442b2b;
    --warn: #ffc96b;
    --warn-bg: #3d3220;

    --sheet: #304562;
    --sheet-edge: #7f9dbb;
    --part-fill: #08274e;
    --part-edge: #d4b16d;
    /* Cutting maps retain navy material and white labels in the dark theme. */
    --offcut: #214b42;
    --offcut-edge: #7ac8ac;
    --offcut-plain: #2b4664;
    --offcut-plain-edge: #86a4c6;
    --panel-face: #3a3f52;
    --panel-edge: #a3acc0;
    --ink: #ffffff;
    --pending: #bfc0c0;
    --diagram-line: #bfc0c0;
    --canvas-grid: #22252f;
    --canvas-grid-dot: #7d869b;

    --sh-1: none;
    --sh-2: none;
    --sh-3: none;
    --sh-popover: none;
    --sh-dialog: none;
    --sh-drawer: none;
    /* Графит и коралл: semantic chrome, action, selection and drawing roles. */
    --glass-blur: none;
    --raised-edge: transparent;
    --variant-shadow: none;
    --action-bg: #ef8354;
    --action-hover: #e0703f;
    --action-text: #2d3142;
    --map-selection: #ffc25e; --map-selection-edge: #ffd277;
    --mirror-preview: #bfc0c0;
    --edge-fallback: #a3acc0;
    --map-part-fill: #08274e;
    --map-label: #f8fbff;
    --map-piece-label: #f8fbff;
    --chrome-bg: #2d3142;
    --chrome-text: #ffffff;
    --chrome-muted: #bfc0c0;
    --chrome-hover: #3a3f55;
    --chrome-active-bg: #3c4258;
    --chrome-active-text: #ffffff;
    --header-bg: #2d3142;
    --header-text: #ffffff;
    --header-muted: #bfc0c0;
    --header-button-bg: #2d3142;
    --header-button-text: #ffffff;
    --header-control-hover: #3a3f55;
    --tab-selected: #ef8354;
    --variant-bg: #2d3142;
    --variant-selected-bg: #4a3a3c;
    --variant-edge: #ef8354;
    --chrome-ink: #ffffff;
    --header-quiet-text: #ffffff;
    --variant-selected-text: #ffffff;
    --variant-selected-muted: #bfc0c0;
    --variant-selected-good: #7fd1a0;
    /* Owner15.10: fitted against the five22% dark philosophy tints, retaining
       red metric meaning at>=4.5:1. Evidence: owner-1510/philosophy-colours.json. */
    --variant-rank-error-lift:35%;
    --variant-selected-bad:color-mix(in srgb,var(--bad),var(--text) var(--variant-rank-error-lift));
    --row-selection-bg: #4a3a3c;
    --row-selection-cell-bg: #4a3a3c;
    --row-selection-shadow: inset 3px 0 0 var(--selection-edge);
    --rail-primary-text: #2d3142;
    --map-grain: #f8fbff;
    --header-close-text: #ffffff;
    --header-status-text: #ffffff;
    --header-count-text: #ffffff;
    --header-status-warn: #ffc96b;
    --header-count-bad: #ff8a80;
    --map-selection-keyline: transparent;
    --map-selection-keyline-width: 0px;
    --row-selection-text: #ffffff;
    --row-selection-text-soft: #bfc0c0;
    --row-selection-muted: #bfc0c0;
    --row-selection-panel: #2d3142;
    --row-selection-hover: #3a3f52;
    --row-selection-accent: #bfc0c0;
    --row-selection-good: #7fd1a0;
    --row-selection-bad: #ff8a80;
    --map-focus-ring: #ffc25e;
    --map-inspector-focus-outline: 2px solid var(--map-focus-ring);
    --contrast-border: #ffffff;
    --contrast-muted: #bfc0c0;

    --field-border: #7d869b; --selection-edge: #ef8354;
    --chrome-edge: #4a5368; --tab-text: #ffffff; --offcut-text: #e2f0fb; --map-waste-fill: #394b61; --map-waste-edge: #8797ab; --map-waste-text: #e2edf7;
}

* { box-sizing: border-box; }

html { font-size: 100%; }               /* the browser's own text size is the base */
/* Keep the map stationary when a dialog locks the Windows page scrollbar. */
html:has(.project-shell.map-active) { scrollbar-gutter: stable; }

body {
    font-family: system-ui, "Segoe UI Variable Text", "Segoe UI", -apple-system, sans-serif;
    font-optical-sizing: auto;
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-size: var(--t-base);
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
    /* The chrome floats over the content, so the page keeps its own scroll and the bar stays put. */
    overflow-y: scroll;
}

h1, h2, h3, h4 { letter-spacing: -.012em; }   /* tighten as type grows */

button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }

.ui-icon {
    width: var(--icon-md); height: var(--icon-md); flex: none; display: block;
    fill: none; stroke: currentColor; stroke-width: var(--icon-stroke);
    stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.btn.sm .ui-icon { width: var(--icon-sm); height: var(--icon-sm); }
.btn.icon .ui-icon, .icon-btn .ui-icon { width: var(--icon-md); height: var(--icon-md); }

/* Nothing is invisible to the keyboard. One ring, everywhere, and never on a mouse press. */
:focus-visible {
    outline: 2px solid var(--ring);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

::selection { background: var(--accent-soft); color: var(--accent-soft-text); }

/* ============================================================================================
   THE CONTROL SYSTEM

   One family. Everything you can press is a `.btn`; everything you can type in is a `.field`; a
   run of related controls is a `.btn-group`. They share one height, one radius, one type size and
   one set of state rules, so a control that looks the same behaves the same wherever it appears.

   This replaced ten different button treatments living on one screen — five heights (16, 26, 27,
   28, 29 px), three radii (0, 5, 6) and four paddings. That is what "no system" looks like when you
   measure it, and it is why the editor read as a pile of unrelated widgets.

   Variants, and what each one means:
     (none)     do this
     .primary   the one thing this bar is for — at most one per bar
     .quiet     available, not asking
     .on        a mode that is currently in force
     .danger    destroys something
     .icon      a square button whose glyph is the whole label
     .sm        the same button in a tighter row
   ============================================================================================ */

/* Fluent 2 CSS port, @fluentui/react-button 9.11.1 (Microsoft Corporation).
 Source: https://unpkg.com/@fluentui/react-button@9.11.1/lib/components/Button/useButtonStyles.styles.js
 Token source: @fluentui/tokens 1.0.0-alpha.24.
 Taken: radiusMedium=4px, strokeThin=1px, strokeThick=2px; heights24/32/40;
 horizontal S/M/L=8/12/16px; icon20/20/24; icon gap XS/SNudge=4/6px;
 durationFaster=100ms; curveEasyEase=cubic-bezier(.33,0,.67,1).
 Colours map to the owner Graphite/Coral tokens. Disabled uses Fluent neutral
 colours #f0f0f0/#bdbdbd/#e0e0e0 (light), #141414/#5c5c5c/#424242 (dark).
 Focus is a 2px inset stroke, preserving bounds and neighbours. Small toolbar
 contexts and header use24px; dialogs/menus use32px. Large is explicit40px.
 Owner15.10 keeps existing app font sizes/weights and uses Fluent small8px
 horizontal padding in every context to preserve available work area.
 MIT License

Copyright (c) Microsoft Corporation.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

NOTE: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license

 */
:root {
 --compact-map-line:12px; /* Preserves both12px/11px labels in1010x563; resume2 compact map evidence. */
 --ctl-h:32px; --ctl-h-sm:24px; --ctl-pad-x:12px; --ctl-gap:8px /* Named minimum separation and surface gutter, owner15.10. */;
 --fluent-radius:4px; --fluent-duration:100ms; --fluent-curve:cubic-bezier(.33,0,.67,1);
 --button-h:32px; --button-pad:8px; --button-pad-y:5px; --button-icon:20px; --button-gap:6px; --button-disabled-bg:#f0f0f0; --button-disabled-ink:var(--text-soft); --button-disabled-stroke:#e0e0e0;
}
html[data-theme=dark] { --button-disabled-bg:#141414; --button-disabled-ink:var(--text-soft); --button-disabled-stroke:#424242; }
:where(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]) { font:inherit; }
/* Legacy aliases retain test selectors. Context is the size; role is the appearance. */
:is(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]) {
 display:inline-flex; align-items:center; justify-content:center; box-sizing:border-box;
 height:var(--button-h); min-height:var(--button-h); flex-shrink:0;
 gap:var(--button-gap); padding:var(--button-pad-y) var(--button-pad); margin:0;
 border:1px solid var(--button-stroke,var(--border)); border-radius:var(--fluent-radius);
 background:var(--button-bg,var(--panel)); color:var(--button-ink,var(--text));
 cursor:pointer; white-space:nowrap; box-shadow:none; transform:none; opacity:1;
 transition:background-color var(--fluent-duration) var(--fluent-curve),color var(--fluent-duration) var(--fluent-curve),border-color var(--fluent-duration) var(--fluent-curve),box-shadow var(--fluent-duration) var(--fluent-curve);
}
:is(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]):hover:not(:disabled) { background:var(--button-hover,var(--panel-2)); color:var(--button-hover-ink,var(--button-ink,var(--text))); border-color:var(--button-stroke,var(--border)); box-shadow:none; }
:is(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]):active:not(:disabled) { background:var(--button-pressed,var(--panel-3)); color:var(--button-hover-ink,var(--button-ink,var(--text))); transform:none; }
:is(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]):disabled { background:var(--button-disabled-role-bg,var(--button-disabled-bg)); color:var(--button-disabled-ink); border-color:var(--button-disabled-role-stroke,var(--button-disabled-stroke)); border-style:solid; opacity:1; cursor:not-allowed; box-shadow:none; }
:is(.btn,.icon-btn,.link,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]):focus-visible { outline:2px solid var(--ring); outline-offset:-2px; box-shadow:inset 0 0 0 2px var(--ring); }
.btn.primary,.rail-action.primary { --button-bg:var(--action-bg); --button-ink:var(--action-text); --button-hover-ink:var(--action-hover-text); --button-disabled-role-bg:var(--button-disabled-bg); --button-disabled-role-stroke:transparent; --button-hover:var(--action-hover); --button-pressed:var(--action-hover); --button-stroke:transparent; }
/* Subtle is the single toolbar/table/menu action appearance. */
:is(.btn.quiet,.btn.icon,.icon-btn,.rail-action,.navigator-icon,.navigator-quick-add,.navigator-operation-menu,.navigator-modes button,.seg,.machine-settings-tab,.menu-item,.command-menu button,.table-command-popover button,.navigator-menu-popover button,.toast-close,.issue-indicator,.table-cell-value,.help-tip-button,.map-menu-popover button,.cs-machine-menu-body button,[data-popup-active] button,.machining-count,.rail-tool,.rail-edge,summary[aria-label]),
:is(.table-toolbar,.navigator-tools,.map-toolbar,.bulk-action-bar,.rack-actions) .btn:not(.primary) { --button-bg:transparent; --button-stroke:transparent; --button-hover:var(--panel-2); --button-pressed:var(--panel-3); --button-disabled-role-bg:transparent; --button-disabled-role-stroke:transparent; }
.link { --button-bg:transparent; --button-stroke:transparent; --button-hover:transparent; --button-pressed:transparent; --button-ink:var(--accent); --button-disabled-role-bg:transparent; --button-disabled-role-stroke:transparent; }
.link:hover { text-decoration:underline; }
.btn.danger,.link.danger,.navigator-icon.danger { --button-ink:var(--bad); }
:is(.btn.on,.seg.active,.navigator-modes button.active,.machine-settings-tab[aria-selected=true]) { --button-bg:var(--row-selection-bg); --button-hover:var(--row-selection-hover); --button-ink:var(--row-selection-text); --button-stroke:transparent; }
:is(.btn.icon,.icon-btn,.navigator-icon,.navigator-operation-menu) { width:var(--button-h); min-width:var(--button-h); padding:var(--button-pad-y); }
:is(.btn,.icon-btn,.navigator-icon,.rail-action) .ui-icon { width:var(--button-icon); height:var(--button-icon); flex:none; }
.btn.large { --button-h:40px; --button-pad:8px; --button-pad-y:8px; --button-icon:24px; }
.btn.large:has(.ui-icon) { --button-pad-y:7px; }
/* Disabled paint is shared by ordinary controls and card-shaped command buttons.
   Appearances explicitly choose their disabled background/stroke, never opacity. */
html .project-shell.project-shell button:disabled { opacity:1; background:var(--button-disabled-role-bg,var(--button-disabled-bg)); color:var(--button-disabled-ink); border-color:var(--button-disabled-role-stroke,var(--button-disabled-stroke)); }
html .project-shell.project-shell button:disabled .ui-icon { color:var(--button-disabled-ink); }
.btn-group { display:inline-flex; align-items:center; gap:0; padding:0; border:0; background:transparent; }
.btn-group > :is(.btn,select,.field) { border-radius:var(--r-none); }
.btn-group > :first-child { border-radius:var(--fluent-radius) var(--r-none) var(--r-none) var(--fluent-radius); }
.btn-group > :last-child { border-radius:var(--r-none) var(--fluent-radius) var(--fluent-radius) var(--r-none); }
.btn-group > :only-child { border-radius:var(--fluent-radius); }
.btn-group > :is(.btn,select,.field) + :is(.btn,select,.field) { border-left-width:0; }
.btn-group .field { padding:0 var(--ctl-gap); }
.btn-group .field > input[type=number] { width:3.75rem; border:0; background:none; padding:0; height:auto; }

/* The label above a group of controls, in every bar that has one. */
.ctl-label {
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em;
    color: var(--muted); font-weight: 600; white-space: nowrap;
}

/* ============================================================================================
   Fields — a label welded to its input, at the same height as a button so a row of mixed
   controls sits on one line.
   ============================================================================================ */

:root { --field-hover:var(--accent); --field-bg:var(--panel); --field-ink:var(--text); }
.workflow-header { --field-border:var(--chrome-muted); --field-hover:var(--header-text); --field-bg:var(--header-bg); --field-ink:var(--header-text); }
input:not([type]), input[type=number], input[type=text], input[type=search], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=date], input[type=time], input[type=datetime-local], select, textarea {
    height: var(--ctl-h); padding: 0 var(--sp-3_5);
    border: 1px solid var(--field-border); border-radius: var(--r-sm);
    background: var(--field-bg); color: var(--field-ink); font-size: var(--t-md);
    font-variant-numeric: tabular-nums;
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
input:not([type]):hover, input[type=number]:hover, input[type=text]:hover, input[type=search]:hover, select:hover, textarea:hover { border-color: var(--field-hover); }
input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--field-hover); }
textarea { height:auto; padding:var(--sp-3_5); }
input[readonly], textarea[readonly], output, .fixed-value, .parameter-readonly { border:0; background:transparent; box-shadow:none; }
.workflow-header :is(input,select,textarea):focus-visible { outline-color:var(--chrome-focus-ring); }
input:disabled, select:disabled, textarea:disabled { color:var(--text-soft); cursor:not-allowed; opacity:1; background:var(--panel-2); border-style:dashed; }
[aria-invalid="true"] { border-color:var(--bad); outline:1px solid var(--bad); outline-offset:-1px; }

input[type=checkbox] { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; height: auto; }

.field { display: inline-flex; align-items: center; gap: var(--sp-2_5); white-space: nowrap; }
.field > .field-label { font-size: var(--t-sm); color: var(--muted); }
.field > input[type=number] { width: 5rem; text-align: right; }
.field > select { max-width: 11rem; }
.field > .fixed-value { font-weight: 600; color: var(--text); }

/* ============================================================================================
   The app bar — one band, not three. File on the left, where you are in the middle, what you can
   make on the right. It floats: content scrolls beneath it through the blur.
   ============================================================================================ */

.appbar {
    position: sticky; top: 0; z-index: var(--z-chrome);
    display: flex; align-items: center; gap: var(--sp-5);
    padding: var(--sp-4) var(--sp-7); min-height: 58px;
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border-bottom: 1px solid var(--hairline);
    box-shadow: inset 0 1px 0 var(--glass-edge);
}
.appbar-group { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.appbar-group.right { margin-left: auto; }

/* Shop destinations and open-order steps use normal flow so neither can cover file actions. */
.appbar .shop-nav, .order-bar .order-nav, .page .stock-nav {
    position: static; transform: none; width: auto; order: initial; flex-wrap: wrap;
}
.appbar { flex-wrap: wrap; }
.workflow-header { position: sticky; top: 0; z-index: var(--z-chrome); background: var(--panel); }
.workflow-header .appbar { position: static; }
.workflow-header .banner { margin: 0; }
.workflow-header .calculation-blocker { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-6); margin:0; padding:var(--sp-3) var(--sp-6); font-size:12px; }
.workflow-header .calculation-blocker .btn { flex:none; }
.order-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4) var(--sp-9);
    flex-wrap: wrap; padding: var(--sp-4) var(--sp-7); background: var(--panel); border-bottom: 1px solid var(--hairline); }
.order-identity { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; flex-wrap: wrap; }
.order-identity .file-name { max-width: 38ch; }
.stock-nav { display: inline-flex; margin-bottom: var(--sp-7); }
[hidden] { display: none !important; }
.production-actions, .shop-settings { max-width: 800px; }
.production-actions fieldset { border: 0; padding: var(--sp-7); min-width: 0; margin: 0; }
.shop-settings .rack-actions { justify-content: space-between; margin-bottom: var(--sp-6); }
.page .plan-side { position: static; max-height: none; }
.plan-side > div { display: flex; flex-direction: column; gap: var(--sp-5); }

/* The open file, named plainly. Truncated from the left would hide the extension, so it ellipsises
   at the end and carries the whole path in its title. */
.file-name {
    color: var(--text-soft); font-size: var(--t-md); font-weight: 500;
    max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding: 0 var(--sp-2);
}

/* Where am I — a segmented control, centred, so the answer is in the same place on every screen. */
.segmented {
    display: flex; gap: var(--sp-1); padding: var(--sp-1);
    background: var(--panel-3); border-radius: var(--r-sm);
    position: absolute; left: 50%; transform: translateX(-50%);
}




.segmented .seg .count { color: var(--muted); font-variant-numeric: tabular-nums; margin-left: var(--sp-2); }
.segmented .seg.active .count { color: var(--muted); }

/* Centring it only works while there is room on both sides of it. Below that it takes its turn in
   the row rather than sitting on top of the buttons. */
@media (max-width: 1180px) {
    .appbar { flex-wrap: wrap; }
    .segmented { position: static; transform: none; order: 3; width: 100%; }
    .segmented .seg { flex: 1 1 0; justify-content: center; }
}

/* Something is happening, and it says what. */
.working { display: inline-flex; align-items: center; gap: var(--sp-3_5); color: var(--muted); font-size: var(--t-md); }
.spinner {
    width: 13px; height: 13px; flex: none; border-radius: var(--r-full);
    border: 2px solid var(--border); border-top-color: var(--accent);
    animation: spin 700ms linear infinite;
}

/* A long calculation is its own state, not a tiny hint in the toolbar. */
.planning-screen {
    position: fixed; inset: 0; z-index: var(--z-blocking); display: grid; place-items: center;
    padding: var(--sp-12); background: color-mix(in srgb, var(--bg) 82%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(120%);
    backdrop-filter: blur(18px) saturate(120%);
}
.planning-card {
    max-height:calc(100dvh - 2 * var(--sp-12)); overflow:auto;
    width: min(440px, 100%); text-align: center; padding: var(--sp-17) var(--sp-18) var(--sp-15);
    color: var(--text); background: var(--panel); border: 1px solid var(--border-soft);
    border-radius: calc(var(--r-lg) + 4px); box-shadow: var(--sh-3);
    animation: planning-arrive 260ms var(--ease) both;
}
.planning-card h1 { margin: var(--sp-8_5) 0 var(--sp-4); font-size: clamp(1.3rem, 3vw, 1.7rem); line-height: 1.15; letter-spacing: -.018em; }
.planning-card p { margin: 0 auto; max-width: 36ch; color: var(--text-soft); line-height: 1.5; }
.planning-mark { display: flex; justify-content: center; align-items: end; gap: var(--sp-2_5); height: 28px; }
.planning-mark span {
    width: 7px; height: 15px; border-radius: var(--r-full); background: var(--accent);
    animation: planning-bars 900ms ease-in-out infinite alternate;
}
.planning-mark span:nth-child(2) { height: 25px; animation-delay: -300ms; }
.planning-mark span:nth-child(3) { height: 19px; animation-delay: -600ms; }
.planning-progress { height: 4px; margin: var(--sp-12) 0 var(--sp-6); overflow: hidden; border-radius: var(--r-full); background: var(--panel-3); }
.planning-progress span {
    display: block; height: 100%; border-radius: inherit; background: var(--accent);
    transition: width var(--t-2) var(--ease);
}
.planning-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6); margin-bottom: var(--sp-5); color: var(--text-soft); font-size: var(--t-sm); }
.planning-note { color: var(--muted); font-size: var(--t-sm); }
@keyframes planning-arrive { from { opacity: 0; transform: scale(.975); } to { opacity: 1; transform: scale(1); } }
@keyframes planning-bars { to { transform: scaleY(.55); opacity: .55; } }
@keyframes planning-progress { from { transform: translateX(-8%); } to { transform: translateX(174%); } }
@keyframes spin { to { transform: rotate(360deg); } }

/* ============================================================================================
   Menus — a floating panel, dismissed by clicking anywhere else.
   ============================================================================================ */

.menu { position: relative; }
.menu-scrim { position: fixed; inset: 0; z-index: var(--z-menu-scrim); background: transparent; }
.menu-panel {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: var(--z-popover);
    min-width: 268px; padding: var(--sp-3_5);
    /* Opaque, not --glass. Chrome is a material the work scrolls under and may be translucent; a
       menu is a surface you read, and at --glass's 72 % the page read straight through it — the
       "68 PIECES PLACED" tile and the comparison table's own numbers showed between the menu's
       items. A blur cannot fix that: it softens what is behind, it does not stop it being read. */
    background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: var(--sh-3);
    /* Anchored to the control that opened it, and it materialises rather than merely fading:
       a real surface arriving. */
    transform-origin: top right;
    animation: none;
}
@keyframes menu-in {
    from { opacity: 0; transform: scale(.94) translateY(-4px); }
    to { opacity: 1; transform: none; }
}
.menu-panel .menu-item {
    display: flex; align-items: center; gap: var(--sp-4); width: 100%; text-align: left;
    background: none; border: 0; border-radius: var(--r-sm); padding: var(--sp-3_5) var(--sp-4_5);
    font-size: var(--t-md); color: var(--text); cursor: pointer;
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.menu-panel .menu-item:hover:not(:disabled) { background: var(--panel-2); }
.menu-panel .menu-item:active:not(:disabled) { transform: none; }
.menu-panel .menu-item:disabled { color: var(--muted); cursor: not-allowed; }
.menu-panel .menu-item .glyph { width: 18px; text-align: center; opacity: .8; flex: none; }
.menu-panel .menu-sep { height: 1px; background: var(--hairline); margin: var(--sp-3) var(--sp-2); }
.menu-panel .menu-head {
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em;
    color: var(--muted); padding: var(--sp-3_5) var(--sp-4_5) var(--sp-1_5);
}
.menu-panel .menu-field {
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
    padding: var(--sp-2) var(--sp-4_5) var(--sp-3_5); font-size: var(--t-sm); color: var(--text-soft);
}
.menu-panel .menu-field select { flex: 1 1 auto; min-width: 0; }
.menu-panel .menu-note { padding: var(--sp-2) var(--sp-4_5) var(--sp-3); font-size: var(--t-xs); color: var(--muted); }

/* ============================================================================================
   Page shell
   ============================================================================================ */

.page { padding: var(--sp-7); }
.empty {
    margin: clamp(var(--sp-14), 6vh, var(--sp-32)) auto; max-width: 34rem; text-align: center;
    color: var(--muted); font-size: var(--t-lg);
}
.empty .empty-title { display: block; color: var(--text); font-size: var(--t-xl); font-weight: 600; margin-bottom: var(--sp-3); }
.empty.compact, .card .empty { margin: var(--sp-11) auto; font-size: var(--t-base); }
.muted { color: var(--muted); }
.hint { color: var(--muted); font-size: var(--t-sm); }
.section-help, .field-help { display: flex; align-items: center; gap: var(--sp-3); color: var(--muted); font-size: var(--t-sm); }

/* Explanations stay one click away without becoming permanent paragraphs. */
.help-tip { position: relative; display: inline-flex; align-items: center; flex: none; vertical-align: middle; }
.help-tip-button {
    display: grid; place-items: center; width: var(--sp-12); height: var(--sp-12); padding: 0;
    border: 1px solid var(--border); border-radius: var(--r-full); background: var(--panel-2);
    color: var(--muted); font-size: var(--t-xs); font-weight: 700; line-height: 1; cursor: help;
}
.help-tip-button:hover, .help-tip-button[aria-expanded="true"] { color: var(--accent); border-color: var(--accent); }
.command-tooltip {
    pointer-events:none;
    /* Measure text independently of the previous hint's left coordinate. */
    position:fixed; z-index:var(--z-tooltip); width:max-content; max-width:calc(100vw - 16px);
    padding:var(--sp-3) var(--sp-5); border:1px solid var(--border);
    border-radius:var(--r-sm); background:var(--panel); color:var(--text);
    box-shadow:var(--sh-3); font-size:var(--t-sm); line-height:1.4;
    overflow-wrap:anywhere;
}
/* Only overflowing labels need pointer input for their scroll area. */
.command-tooltip[tabindex="0"] { pointer-events:auto; }
.command-tooltip[hidden] { display:none; }
.help-tip-popover {
    position: absolute; z-index: var(--z-tooltip); left: 50%; bottom: calc(100% + 8px); width: min(300px, calc(100vw - 32px));
    transform: translateX(-50%); padding: var(--sp-4_5) var(--sp-5_5); border: 1px solid var(--border);
    border-radius: var(--r-md); background: var(--panel); color: var(--text-soft); box-shadow: var(--sh-3);
    font-size: var(--t-sm); font-weight: 400; line-height: 1.45; text-align: left; text-transform: none;
    letter-spacing: normal; white-space: normal; pointer-events: auto;
}
/* Interop measures the hidden box, then exposes its first frame beside the anchor. */
.help-tip-popover:not([data-positioned="true"]) { visibility:hidden; }
/* A hint about something that did not work. Muted is the wrong colour for "your saw is missing". */
.hint.bad { color: var(--bad); }

/* ============================================================================================
   Messages. An error is a failure; a notice is a thing that worked. They looked identical before —
   "cutting plan written" arrived in the same red box as "file could not be read".
   ============================================================================================ */

.banner {
    display: flex; align-items: flex-start; gap: var(--sp-4_5);
    margin: 0 0 var(--sp-6); padding: var(--sp-4_5) var(--sp-6); border-radius: var(--r-md);
    font-size: var(--t-md);
    background: var(--panel); border: 1px solid var(--border);
}
.banner .banner-glyph { flex: none; line-height: 1.4; }
.banner.bad { background: var(--bad-bg); color: var(--bad); border-color: transparent; }
.banner.warn { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.banner .banner-action { margin-left: auto; flex: none; }
.banner.geometry-error { display: grid; grid-template-columns: auto minmax(0, 1fr); }
.banner.geometry-error .geometry-error-copy { min-width: 0; overflow-wrap: anywhere; }
.banner.geometry-error .geometry-error-actions {
    grid-column: 2; display: flex; flex-wrap: wrap; gap: var(--sp-2);
    margin-left: 0;
}

.toast {
    position: fixed; left: 50%; bottom: 22px; z-index: var(--z-toast);
    display: flex; align-items: center; gap: var(--sp-5);
    max-width: min(46rem, calc(100vw - 32px));
    padding: var(--sp-4_5) var(--sp-7); border-radius: var(--r-full);
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--hairline); box-shadow: var(--sh-3);
    font-size: var(--t-md); color: var(--text);
    /* It arrives from below, where it lives — enter and exit share one path. */
    animation: none;
}
@keyframes toast-in {
    from { opacity: 0; transform: translate(-50%, 14px) scale(.96); }
    to { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
.toast { transform: translateX(-50%); }
.toast.warn { color: var(--warn); }
.toast .toast-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================================================
   The layout screen: what to cut on the left, what that produced on the right.

   Before this the screen was five full-width bands stacked on top of each other — 463 px of chrome
   on an 860 px window before the first board appeared, and 6 279 px of stacked materials under it
   with no way to reach one. The choice and its settings now live in a column that stays put, and
   the plan takes the rest of the window.
   ============================================================================================ */

.plan { display: flex; gap: var(--sp-7); align-items: flex-start; }
.plan-side {
    flex: 0 0 302px; min-width: 0;
    display: flex; flex-direction: column; gap: var(--sp-5);
    position: sticky; top: 66px;
    max-height: calc(100vh - 80px); overflow-y: auto;
    scrollbar-gutter: stable;
}
.plan-main { flex: 1 1 auto; min-width: 0; }

/* Too narrow for a column beside the plan, so it goes above it — and then it must not become a
   screenful of its own. Stacked in one column at 900 px the controls came to 926 px and put the
   first board 1 399 px down the page; laid out across the width they come to about a third of that. */
@media (max-width: 1080px) {
    .plan { flex-direction: column; }
    .plan-side {
        flex: none; width: 100%; position: static; max-height: none;
        display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
        align-items: start;
    }
    /* The three philosophies read across rather than down when there is width to spare. */
    .plan-side .strategies { flex-direction: row; flex-wrap: wrap; }
    .plan-side .strategies .strategy { flex: 1 1 13rem; }
}

.card {
    background: var(--panel); border: 1px solid var(--border-soft);
    border-radius: var(--r-lg); box-shadow: var(--sh-1);
}
.card > .card-head {
    display: flex; align-items: baseline; gap: var(--sp-4); padding: var(--sp-5) var(--sp-6_5) 0;
}
.card-title {
    font-size: var(--t-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .07em;
    color: var(--muted); margin: 0;
}
.card-body { padding: var(--sp-5) var(--sp-6_5) var(--sp-6); }
.table-scroll-x {
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
}
/* Shared table viewport: leave the final row above the horizontal scrollbar/footer.
   Padding belongs to the scroll content, so rows and the outer viewport keep their height.
   Sticky headers and their viewports share the measured height in each component.
   Other table viewports have no sticky header. Card bodies retain their larger inset. */
:is(.table-scroll,.table-scroll-x,.catalogue-table-scroll,.navigator-table,.source-scroll) {
    --table-scroll-end-space: var(--ctl-gap);
    --table-sticky-header-height: 0px;
    padding-block-end: var(--table-scroll-end-space);
    scroll-padding-block: var(--table-sticky-header-height) var(--table-scroll-end-space);
}
.card-body.table-scroll-x { --table-scroll-end-space: var(--sp-6); }
/* The header is one paint layer above positioned/sticky body cells (parts: layers2/3).
   Keep this stacking context on the row group: individual sticky cells, including
   frozen columns, cannot fall behind a later body cell. Geometry stays unchanged. */
table {
    --table-header-surface: var(--panel);
    --table-header-layer: 4;
}
table thead { position:relative; z-index:var(--table-header-layer); }
table thead th { background-color:var(--table-header-surface); }
.reissue-table-scroll {
    max-height: 320px;
    margin-top: var(--sp-6);
    overflow-y: auto;
    overscroll-behavior-y: contain;
}
.card.empty-section > .card-head {
    align-items: center; min-height: 42px; padding: var(--sp-4_5) var(--sp-6_5);
}
.card.empty-section > .card-head .hint { margin-left: auto; text-align: right; }

.package-card .card-head { justify-content: space-between; }
.package-card .summary-value { color: var(--text-soft); font-size: var(--t-sm); text-align: right; }
.package-settings { display: grid; grid-template-columns: minmax(0, 1fr) 138px; align-items: center; gap: var(--sp-4) var(--sp-5); }
.package-settings > label { color: var(--text-soft); font-size: var(--t-sm); }
.package-settings .field-note, .package-settings .package-machine { grid-column: 1 / -1; }
.package-settings .field-note { margin: calc(-1 * var(--sp-1)) 0 var(--sp-0_5); }
.package-machine { width: fit-content; }
.package-explanation { line-height: 1.42; }
.package-result {
    grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3) var(--sp-5); margin-top: var(--sp-1_5); padding-top: var(--sp-4_5); border-top: 1px solid var(--hairline);
    color: var(--muted); font-size: var(--t-xs);
}
.package-result b { color: var(--text); font-size: var(--t-sm); }

/* --- the philosophy chooser ----------------------------------------------------------------
   A shop picks its philosophy once and lives with it, so the three are stacked and each one says
   in words what it costs against the default. */
.strategies { display: flex; flex-direction: column; gap: var(--sp-3); }
.strategy {
    display: grid; grid-template-columns: 26px minmax(0,1fr); align-items: start; gap: var(--sp-1_5) var(--sp-4_5);
    width: 100%; min-width:0; white-space:normal; text-align: left; cursor: pointer;
    background: var(--panel-2); color: var(--text-soft);
    border: 1px solid transparent; border-radius: var(--r-md);
    padding: var(--sp-4_5) var(--sp-5_5); font-size: var(--t-md); line-height: 1.35;
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.strategy:hover:not(:disabled) { background: var(--panel-3); color: var(--text); }
.strategy:active:not(:disabled) { transform: none; }
.strategy:disabled { opacity:1; cursor:progress; background:var(--button-disabled-bg); color:var(--button-disabled-ink); border-color:var(--button-disabled-stroke); --muted:var(--button-disabled-ink); }
.strategy:disabled :is(.name,.cost,.variant-symbol) { color:var(--button-disabled-ink); }
.strategy .glyph { grid-row: span 2; font-size: var(--t-xl); line-height: 1.15; text-align: center; }
.strategy .name { min-width:0; overflow-wrap:anywhere; font-weight: 600; color: var(--text); }
.strategy .cost { grid-column: 2; color: var(--muted); font-size: var(--t-sm); }
.strategy.active {
    background: var(--accent-soft); color: var(--accent-soft-text); border-color: var(--accent);
}
.strategy.active .name { color: var(--accent-soft-text); }
.strategy.active .cost { color: var(--accent-soft-text); opacity: .8; }

/* --- disclosures: settings, edge banding ---------------------------------------------------- */
.disclosure > summary {
    display: flex; align-items: center; gap: var(--sp-4); cursor: pointer;
    padding: var(--sp-5) var(--sp-6_5); list-style: none;
    font-size: var(--t-md); font-weight: 600; color: var(--text);
    border-radius: var(--r-lg);
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary:hover { background: var(--panel-2); }
.disclosure > summary::before {
    content: "›"; flex: none; width: 10px; color: var(--muted); font-size: var(--t-lg);
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.disclosure[open] > summary::before { transform: rotate(90deg); }
/* What is inside, said on the outside — so it need not be opened to be read. */
.disclosure .summary-value {
    margin-left: auto; color: var(--muted); font-weight: 400; font-size: var(--t-sm);
    font-variant-numeric: tabular-nums; text-align: right;
}
.disclosure .disclosure-body { padding: var(--sp-1) var(--sp-6_5) var(--sp-6); animation: none; }
@keyframes reveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* Settings read as a form, one row per thing, label left and value right — a control sits next to
   what it changes and the eye runs down a single edge. */
.field-grid { display: grid; grid-template-columns: 1fr auto; gap: var(--sp-3_5) var(--sp-5); align-items: center; }
.field-grid > label { font-size: var(--t-md); color: var(--text-soft); }
.field-grid input[type=number] { width: 6.5rem; text-align: right; }
.field-grid select { max-width: 11rem; }
.field-grid .field-wide { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--sp-3_5); font-size: var(--t-md); color: var(--text-soft); }
/* Prose across both columns. NOT .field-wide: that one is a flex row built for a checkbox and its
   label, and a sentence put in it is torn into one flex item per inline chunk — a note with a <b>
   in the middle came out as three columns with the bold word stranded in its own. Nothing in a DOM
   measurement catches that; it took a screenshot. */
.field-grid .field-note {
    grid-column: 1 / -1; display: block;
    font-size: var(--t-sm); color: var(--muted); line-height: 1.5;
}
.field-grid .field-sep { grid-column: 1 / -1; height: 1px; background: var(--hairline); margin: var(--sp-1_5) 0; }

/* ============================================================================================
   A modal, for settings that belong to the machine rather than to the order. One at a time, so
   there is no stacking to manage and no z-index ladder to keep straight.
   ============================================================================================ */
.scrim {
    position: fixed; inset: 0; z-index: var(--z-dialog);
    /* Opaque enough to stop the plan being read through the dialog — the same mistake the Output
       menu made at --glass, where the tiles behind it showed through the items. */
    background: var(--overlay);
}
html.modal-open, body.modal-open { overflow: hidden; overscroll-behavior: none; }
.dialog {
    position: fixed; z-index: var(--z-dialog-surface);
    /* Pinned near the top rather than centred vertically. Centred, the shell grows and shrinks around
       its middle as the tabs change height, so the tab strip itself slid ~190 px between "In general"
       and "Physical package limit" — you reach for the tab you just left and it has moved. The tabs are the one
       thing in here that must not move. */
    top: 72px; left: 50%; transform: translateX(-50%);
    display: flex; flex-direction: column;
    width: min(680px, calc(100vw - 32px));
    max-height: calc(100vh - 104px);
    max-height: calc(100dvh - 104px);
    overflow: hidden;
    background: var(--panel); color: var(--text);
    border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--sh-2);
}
/* A dialog that holds a table of the order's own rows needs the width of one. */
.dialog.wide { width: min(1000px, calc(100vw - 32px)); }
.dialog.machine-settings-dialog {
    top: 32px;
    width: min(1120px, calc(100vw - 32px));
    max-height: calc(100vh - 64px);
    max-height: calc(100dvh - 64px);
}
.machine-settings-dialog > .dialog-body { display:flex; min-height:0; overflow:hidden; padding:0; }
.machine-settings-form { display:flex; flex-direction:column; flex:1; min-height:0; }
.machine-settings-inline {
    display: flex; flex-direction: column; width: 100%; min-width: 0;
    border: 1px solid var(--border); border-radius: var(--r-lg);
    background: var(--panel); color: var(--text);
    margin-bottom: var(--sp-4); overflow: hidden;
}
.field-grid > .machine-settings-placement { grid-column: 1 / -1; min-width: 0; }
.machine-settings-inline .dialog-body { max-height: none; overflow: visible; }
.machine-settings-dialog .field-grid, .machine-settings-inline .field-grid {
    grid-template-columns: minmax(10rem, 1fr) minmax(7rem, 10rem)
                           minmax(10rem, 1fr) minmax(7rem, 10rem);
    column-gap: var(--sp-7);
}
.machine-settings-dialog .field-grid > input,
.machine-settings-dialog .field-grid > select,
.machine-settings-inline .field-grid > input,
.machine-settings-inline .field-grid > select { width: 100%; max-width: none; }
.machine-settings-dialog .field-grid .field-note,
.machine-settings-dialog .field-grid .field-sep,
.machine-settings-dialog .field-grid .field-wide,
.machine-settings-inline .field-grid .field-note,
.machine-settings-inline .field-grid .field-sep,
.machine-settings-inline .field-grid .field-wide { grid-column: 1 / -1; }
.machine-settings-bands { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-6); }
.dialog-section-help { display:flex; justify-content:flex-end; min-height:28px; margin-bottom: var(--sp-4); }
.machine-settings-bands .band-card { margin-bottom: 0; min-width: 0; }
/* Each card contains one label/value pair per row; the dialog's four-column
   grid would give each half-width card the minimum width of the whole form. */
.machine-settings-bands .field-grid { grid-template-columns: minmax(0, 1fr) minmax(7rem, 10rem); }
.band-toggle { display:inline-flex; align-items:center; gap:var(--sp-3); }
.machine-settings-dialog .gap-list { columns: 2 26rem; column-gap: var(--sp-14); }
.machine-settings-dialog .gap-list > * { break-inside: avoid; }
.machine-settings-dialog .post-settings-summary,
.machine-settings-inline .post-settings-summary { margin: 0 0 var(--sp-4); font-weight: 700; }
.machine-settings-dialog .post-settings-notice,
.machine-settings-inline .post-settings-notice {
    margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
    border-left: 3px solid var(--danger, var(--bad)); background: var(--panel-2);
}
.post-settings-section + .post-settings-section { margin-top: var(--sp-6); }
.post-settings-section > h3 { padding: var(--sp-3) 0; border-bottom: 1px solid var(--border); }
.machine-settings-dialog .post-setting-row,
.machine-settings-inline .post-setting-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 24rem);
    gap: var(--sp-2) var(--sp-6); align-items: center;
    padding: var(--sp-2) 0; border-bottom: 1px solid var(--hairline);
}
.machine-settings-dialog .post-field-state,
.machine-settings-inline .post-field-state { display: inline-block; margin-left: var(--sp-2); color: var(--text-soft); font-size: var(--t-sm); }
.machine-settings-dialog .post-field-state[data-status="Работает"],
.machine-settings-inline .post-field-state[data-status="Работает"] { color: var(--good); }
.machine-settings-dialog .post-field-state[data-status="Не проверено"],
.machine-settings-inline .post-field-state[data-status="Не проверено"] { color: var(--warn); }
.machine-settings-dialog .post-setting-row > :is(input, select),
.machine-settings-inline .post-setting-row > :is(input, select) { width: 100%; max-width: 100%; min-width: 0; }
.machine-settings-dialog .post-setting-row[data-value-kind="boolean"] > select,
.machine-settings-inline .post-setting-row[data-value-kind="boolean"] > select { width: 8rem; }
@media (max-width: 540px) {
    .machine-settings-dialog .field-grid.post-setting-row,
    .machine-settings-inline .field-grid.post-setting-row { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 820px) {
    .dialog.machine-settings-dialog { top: 16px; max-height: calc(100dvh - 32px); }
    .machine-settings-dialog .field-grid, .machine-settings-inline .field-grid { grid-template-columns: minmax(10rem, 1fr) minmax(7rem, 10rem); }
    .machine-settings-bands { grid-template-columns: 1fr; }
    .machine-settings-dialog .gap-list { columns: 1; }
}
.dialog-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--sp-6_5) var(--sp-7) var(--sp-4_5); border-bottom: 1px solid var(--hairline);
    flex: none;
}
.dialog-title { margin: 0; font-size: var(--t-lg); font-weight: 600; }

/* The app bar's tab strip is centred by absolute positioning; in here it is just a row. */
.segmented.dialog-tabs {
    position: static; transform: none; left: auto;
    order: initial; width: auto; flex: none;
    margin: var(--sp-5) var(--sp-7) 0; overflow-x: auto; scrollbar-width: none;
}
.segmented.dialog-tabs::-webkit-scrollbar { display: none; }

/* One scroll owner per modal. The shell, title and actions stay still; only the body scrolls. */
.dialog-body {
    padding: var(--sp-7); overflow-y: auto; min-height: 0;
    overscroll-behavior: contain; scrollbar-gutter: stable;
    scroll-padding-block: var(--sp-6);
}
.dialog.variant-comparison-dialog { width:calc(100vw - 24px); max-width:1600px; }
.variant-comparison-dialog .dialog-body { padding:var(--sp-4); scrollbar-gutter:auto; }
.new-order-dialog .dialog-body { min-height: 140px; }
.dialog-lead { margin-bottom: var(--sp-6); }
.dialog-note { margin-top: var(--sp-7); padding-top: var(--sp-5_5); border-top: 1px solid var(--hairline); }
.dialog-foot {
    display: flex; align-items: center; gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-7); border-top: 1px solid var(--hairline);
    flex: none;
}
.dialog-foot .hint { flex: 1; min-width: 0; }
.dialog-foot .bad { color: var(--bad); }

/* Centred overlays use the same fixed-header / single-scroll-owner contract as .dialog,
   without inheriting .dialog's fixed positioning. Component styles own only width and content. */
.overlay-dialog-shell {
    display: flex; flex-direction: column;
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px);
    overflow: hidden;
}
.overlay-dialog-head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6);
    padding: var(--sp-6_5) var(--sp-8) var(--sp-5); border-bottom: 1px solid var(--hairline);
    flex: none;
}
.overlay-dialog-head > :is(h2, h3) { margin: 0; }
.overlay-dialog-body {
    min-height: 0; padding: var(--sp-7) var(--sp-8); overflow-y: auto;
    overscroll-behavior: contain; scrollbar-gutter: stable;
    scroll-padding-block: var(--sp-6);
}
.overlay-dialog-foot {
    display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-8); border-top: 1px solid var(--hairline);
    flex: none;
}

@media (max-height: 700px) {
    .dialog {
        top: 16px;
        max-height: calc(100vh - 32px);
        max-height: calc(100dvh - 32px);
    }
    .dialog-body, .new-order-dialog .dialog-body { min-height: 0; }
}

/* Label design is a three-step workspace: add information, place it directly on the physical label,
   then tune the selected item. The old two-column form mixed all three and made coordinates the
   apparent primary workflow. */
.dialog.label-editor { width: min(1220px, calc(100vw - 24px)); top: 54px; max-height: calc(100vh - 72px); }
.label-editor-head { padding: var(--sp-8) var(--sp-9) var(--sp-6); }
.label-editor-head .hint { margin-top: var(--sp-1); }
.label-document-bar {
    display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-9);
    padding: var(--sp-5_5) var(--sp-9) var(--sp-6_5); background: var(--panel); border-bottom: 1px solid var(--hairline);
}
.label-document-bar label, .label-toolbox label, .label-inspector label {
    display: flex; flex-direction: column; gap: var(--sp-2); color: var(--muted); font-size: var(--t-sm);
}
.label-name-field { flex: 1; max-width: 360px; }
.label-size-fields { display: flex; align-items: center; gap: var(--sp-3_5); color: var(--muted); font-size: var(--t-sm); }
.label-size-fields > span:first-child { margin-right: var(--sp-1_5); font-weight: 600; color: var(--text-soft); }
.label-size-fields label { display: grid; grid-template-columns: 68px auto; align-items: center; gap: var(--sp-2_5); }
.label-size-fields small { white-space: nowrap; color: var(--muted); }
.label-size-times { color: var(--muted); }

.label-editor-body {
    display: grid; grid-template-columns: 240px minmax(390px, 1fr) 250px;
    gap: 0; padding: 0; height: min(560px, calc(100vh - 260px)); min-height: 0; overflow: hidden;
}
.label-toolbox, .label-inspector { overflow-y: auto; min-width: 0; padding: var(--sp-8); }
.label-toolbox { border-right: 1px solid var(--hairline); background: var(--panel); }
.label-inspector {
    display: grid; grid-template-columns: 24px 1fr; align-content: start; gap: var(--sp-6) var(--sp-4);
    border-left: 1px solid var(--hairline); background: var(--panel);
}
.label-inspector > *, .label-inspector label, .label-inspector fieldset { min-width: 0; }
.label-inspector input:not([type="checkbox"]), .label-inspector select { width: 100%; min-width: 0; }
.label-panel { display: grid; grid-template-columns: 24px 1fr; gap: var(--sp-5) var(--sp-4_5); padding-bottom: var(--sp-9); }
.label-panel + .label-panel { padding-top: var(--sp-8_5); border-top: 1px solid var(--hairline); }
.label-section-number {
    display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--r-full);
    background: var(--accent-soft); color: var(--accent-soft-text); font-size: var(--t-sm); font-weight: 700;
}
.label-panel h3, .label-preview-head h3, .label-inspector h3 { margin: 0; font-size: var(--t-base); line-height: 1.3; }
.label-panel p, .label-inspector p { margin: var(--sp-1) 0 0; color: var(--muted); font-size: var(--t-sm); line-height: 1.4; }
.label-panel .wide, .label-inspector .wide { grid-column: 1 / -1; }
.label-block-buttons { display: grid; grid-template-columns: 1fr; gap: var(--sp-3); }
.label-block-buttons .btn { justify-content: flex-start; }
.label-block-buttons .btn span { width: 20px; font-size: var(--t-lg); }
.label-empty { padding: var(--sp-6); border: 1px dashed var(--border); border-radius: var(--r-md); color: var(--muted); font-size: var(--t-sm); text-align: center; }

.label-element-list { max-height: 260px; overflow-y: auto; border-radius: var(--r-md); background: var(--panel-2); }
.label-element-list button {
    display: grid; grid-template-columns: 24px minmax(0, 1fr); align-items: center; gap: var(--sp-4);
    width: 100%; padding: var(--sp-4_5); border: 0; border-bottom: 1px solid var(--hairline);
    background: transparent; color: var(--text); text-align: left; cursor: pointer;
}
.label-element-list button:last-child { border-bottom: 0; }
.label-element-list button:hover { background: var(--panel-2); }
.label-element-list button.active { background: var(--accent-soft); color: var(--accent-soft-text); }
.label-layer-icon { display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--r-sm); background: var(--panel-2); font-weight: 700; }
.label-element-list button.active .label-layer-icon { background: var(--panel); }
.label-element-list strong, .label-element-list small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.label-element-list strong { font-size: var(--t-sm); font-weight: 600; }
.label-element-list small { margin-top: var(--sp-0_5); color: inherit; opacity: .68; font-size: var(--t-xs); }

.label-preview-wrap { display: flex; flex-direction: column; min-width: 0; padding: var(--sp-8) var(--sp-10) var(--sp-9); background: var(--panel-2); }
.label-preview-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--sp-6); margin-bottom: var(--sp-6); }
.label-preview-head span { display: block; margin-top: var(--sp-1); color: var(--muted); font-size: var(--t-sm); }
.label-size-badge { margin: 0 !important; padding: var(--sp-2) var(--sp-4); border: 1px solid var(--border); border-radius: var(--r-full); background: var(--panel); font-variant-numeric: tabular-nums; }
.label-canvas { display: grid; place-items: center; flex: 1; min-height: 0; overflow: hidden; padding: var(--sp-12); border-radius: var(--r-md); background-color: var(--canvas-grid); background-image: radial-gradient(var(--canvas-grid-dot) 1px, transparent 1px); background-size: 12px 12px; }
.label-preview {
    position: relative; width: auto; height: min(100%, 435px); max-width: 100%; overflow: hidden; touch-action: none;
    background: var(--paper); color: var(--paper-ink); border: 1px solid var(--paper-border); border-radius: var(--r-xs);
    box-shadow: var(--sh-3);
}
.label-preview-element {
    position: absolute; min-width: 0; padding: 0; overflow: hidden; white-space: nowrap;
    color: var(--paper-ink); background: transparent; border: 1px solid transparent; text-align: left;
    font-family: Arial, sans-serif; line-height: 1.1; cursor: grab; touch-action: none;
}
.label-preview > svg { display: block; width: 100%; height: 100%; pointer-events: none; }
.document-download { --notice-preferred-width:500px; position: fixed; right: var(--sp-10); bottom: var(--sp-10); z-index: var(--z-drag); width: min(var(--notice-preferred-width), calc(100vw - var(--sp-20))); padding: var(--sp-9); background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--r-md); box-shadow: var(--sh-popover); overflow-wrap: anywhere; }
.document-download p { margin: var(--sp-5) 0; font-size: var(--t-sm); }
.document-download > div { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
.label-preview-element:hover { border-color: var(--paper-selection); background: var(--paper-selection-fill); }
.label-preview-element.selected { border: 2px solid var(--paper-selection); background: var(--paper-selection-fill); z-index: 2; }
.label-preview-element.dragging { cursor: grabbing; box-shadow: var(--sh-2); }
.label-preview-element.kind-logo { display: grid; place-items: center; }
.label-preview-element.kind-logo img { width: 100%; height: 100%; object-fit: contain; image-rendering: auto; }
.label-preview-help { display: flex; justify-content: space-between; gap: var(--sp-6); margin-top: var(--sp-4_5); color: var(--muted); font-size: var(--t-xs); }
.label-preview-help kbd { display: inline-grid; place-items: center; min-width: 18px; height: 18px; margin-right: var(--sp-1); border: 1px solid var(--border); border-radius: var(--r-xs); background: var(--panel); box-shadow: 0 1px 0 var(--border); font-family: inherit; }

.label-inspector-title { min-width: 0; }
.label-inspector > .wide { grid-column: 1 / -1; }
.label-type-row { display: grid; grid-template-columns: 1fr 80px; align-items: end; gap: var(--sp-4); }
.label-type-row .check { flex-direction: row; align-items: center; min-height: 34px; }
.label-geometry { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4_5); margin: var(--sp-1_5) 0 0; padding: var(--sp-5_5); border: 0; border-radius: var(--r-md); background: var(--panel-2); }
.label-geometry legend { padding: 0 var(--sp-2); color: var(--muted); font-size: var(--t-xs); }
.label-inspector-actions { display: flex; justify-content: space-between; gap: var(--sp-4); padding-top: var(--sp-1); }
.label-inspector-empty { grid-column: 1 / -1; align-self: center; padding: var(--sp-20) var(--sp-6); text-align: center; color: var(--muted); }
.label-inspector-empty > span { display: block; margin-bottom: var(--sp-4); font-size: 1.8rem; }
.label-inspector-empty h3 { color: var(--text); }
.logo-file span { color: var(--muted); font-size: var(--t-xs); }
.label-editor-foot { padding: var(--sp-6) var(--sp-9); }

@media (max-width: 1100px) {
    .label-editor-body { display: flex; flex-direction: column; overflow-y: auto; height: calc(100vh - 260px); }
    .label-toolbox { overflow: visible; border-right: 0; border-bottom: 1px solid var(--hairline); }
    .label-preview-wrap { flex: 0 0 500px; min-height: 500px; }
    .label-inspector { flex: none; overflow: visible; border-left: 0; border-top: 1px solid var(--hairline); grid-template-columns: 24px minmax(220px, 1fr) minmax(300px, 1fr); }
    .label-inspector > .wide { grid-column: auto; }
}
@media (max-width: 720px) {
    .label-document-bar { align-items: stretch; flex-direction: column; }
    .label-name-field { max-width: none; }
    .label-editor-body { display: flex; flex-direction: column; overflow-y: auto; }
    .label-toolbox { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .label-preview-wrap { min-height: 470px; }
    .label-inspector { display: grid; grid-template-columns: 24px 1fr; }
    .label-inspector > .wide { grid-column: 1 / -1; }
    .label-preview-help, .label-editor-foot .hint { display: none; }
}

/* A number that is read out of a file, not typed into one. It sits where an input would and is
   deliberately not shaped like one: a box you can click is a promise you can change it. */
.stated {
    display: flex; align-items: baseline; gap: var(--sp-4); justify-content: flex-end;
    font-size: var(--t-md); font-variant-numeric: tabular-nums;
}
.stated .source { color: var(--muted); font-size: var(--t-sm); font-variant-numeric: normal; }

.band-card {
    border: 1px solid var(--hairline); border-radius: var(--r-md);
    padding: var(--sp-5_5) var(--sp-6); margin-bottom: var(--sp-5);
}
.band-card .band-head { display: flex; align-items: center; gap: var(--sp-3_5); margin-bottom: var(--sp-4_5); }

/* What the shop's screen has and ours does not, with what each waits on. */
.gap-list { margin: 0; }
.gap-list dt { font-weight: 600; font-size: var(--t-md); margin-top: var(--sp-6); }
.gap-list dt:first-child { margin-top: 0; }
.gap-list dd {
    margin: var(--sp-1_5) 0 0; font-size: var(--t-sm); color: var(--muted); line-height: 1.5;
}

/* --- the materials of the order, all of them, always ---------------------------------------- */
.material-list { display: flex; flex-direction: column; gap: var(--sp-1_5); }
.material-pick {
    display: grid; grid-template-columns: 1fr auto; gap: var(--sp-0_5) var(--sp-4); width: 100%; text-align: left;
    background: none; border: 1px solid transparent; border-radius: var(--r-md);
    padding: var(--sp-3_5) var(--sp-4_5); cursor: pointer; color: var(--text); font-size: var(--t-md);
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.material-pick:hover { background: var(--panel-2); }
.material-pick:active { transform: none; }
.material-pick.active { background: var(--accent-soft); color: var(--accent-soft-text); }
.material-pick .m-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.material-pick .m-sheets { color: var(--muted); font-variant-numeric: tabular-nums; font-size: var(--t-sm); }
.material-pick .m-sub { grid-column: 1 / -1; color: var(--muted); font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
.material-pick.active .m-sheets, .material-pick.active .m-sub { color: inherit; opacity: .75; }

/* --- totals, as tiles ------------------------------------------------------------------------
   Four numbers a shop reads off the screen at a glance. A sentence in bold was not that. */
.totals { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-bottom: var(--sp-6); }
.tile {
    flex: 1 1 120px; min-width: 108px;
    background: var(--panel); border: 1px solid var(--border-soft); border-radius: var(--r-md);
    box-shadow: var(--sh-1); padding: var(--sp-4) var(--sp-6);
}
.tile .tile-value {
    font-size: var(--t-xl); font-weight: 600; letter-spacing: -.018em;
    font-variant-numeric: tabular-nums; line-height: 1.15;
}
/* The unit is not part of the number. At the value's size and weight "m²" reads as a footnote
   marker hung off the digits rather than as square metres; smaller, lighter and set off, it reads
   as what it is. */
.tile .tile-unit {
    font-size: .55em; font-weight: 500; color: var(--muted); margin-left: .2em;
}
.tile .tile-label {
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
    /* A two-word label broken across two lines makes its tile taller than the rest of the row, and
       the row reads as a mistake. The tile is allowed to be wider instead; the row wraps first. */
    white-space: nowrap;
}
.tile.bad .tile-value { color: var(--bad); }
.tile.good .tile-value { color: var(--good); }

/* --- the philosophies side by side ------------------------------------------------------------
   A row is a philosophy and clicking it adopts that one: the table is the chooser, not a report
   about the chooser. */
.philosophies { width: 100%; border-collapse: collapse; font-size: var(--t-md); }
.philosophies th, .philosophies td { padding: var(--sp-3_5) var(--sp-6); text-align: right; font-variant-numeric: tabular-nums; }
.philosophies th:first-child, .philosophies td:first-child { text-align: left; }
.philosophies th {
    color: var(--muted); font-weight: 600; font-size: var(--t-xs);
    text-transform: uppercase; letter-spacing: .06em; border-bottom: 1px solid var(--hairline);
}
.philosophies tbody tr { cursor: pointer; transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve); }
.philosophies tbody tr:hover { background: var(--panel-2); }
.philosophies tbody tr.chosen { background: var(--accent-soft); color: var(--accent-soft-text); }
.philosophies tbody td { border-bottom: 1px solid var(--border-soft); }
.philosophies .best { font-weight: 700; }

/* A philosophy with no plan for the current settings. Listed rather than dropped, so the table keeps
   saying how many philosophies there are; quiet, so it never competes with a row that has figures. */
.philosophies tbody tr.unplanned { cursor: default; }
.philosophies tbody tr.unplanned:hover { background: transparent; }
.philosophies tbody tr.unplanned td:first-child { color: var(--muted); }
.philosophies .unpriced { color: var(--muted); text-align: left; font-style: italic; }

/* --- the boards ------------------------------------------------------------------------------ */
.material { margin-bottom: var(--sp-7); }
.material > .material-head {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-4) var(--sp-6); margin-bottom: var(--sp-5);
}
.material h3 { margin: 0; font-size: var(--t-lg); font-weight: 600; }
.stat { color: var(--text-soft); font-size: var(--t-md); }
.stat b { color: var(--text); font-variant-numeric: tabular-nums; }

.compare { display: flex; gap: var(--sp-11); flex-wrap: wrap; align-items: flex-start; }
.compare .column { flex: 1 1 420px; min-width: 0; }
.compare .column h4 {
    margin: 0 0 var(--sp-4); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em;
    color: var(--muted); font-weight: 600;
}
.boards { display: flex; flex-wrap: wrap; gap: var(--sp-8); }
.board-wrap { font-size: var(--t-xs); color: var(--muted); }
.board-caption { margin-top: var(--sp-2_5); text-align: center; font-variant-numeric: tabular-nums; }

/* The pills that were everywhere. Kept, but as a label on a thing — never as a message. */
.pill {
    display: inline-block; background: var(--panel-3); color: var(--text-soft);
    border-radius: var(--r-full); padding: var(--sp-0_5) var(--sp-4_5); font-size: var(--t-sm); font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.pill.warn { background: var(--warn-bg); color: var(--warn); }
.pill.bad { background: var(--bad-bg); color: var(--bad); }
.pill.accent { background: var(--accent-soft); color: var(--accent-soft-text); }

.gap { border-radius: var(--r-full); padding: var(--sp-0_5) var(--sp-4_5); font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
.gap.good { background: var(--good-bg); color: var(--good); }
.gap.bad { background: var(--bad-bg); color: var(--bad); }
.ref { color: var(--muted); }

/* ============================================================================================
   The board drawing — unchanged in meaning. Line and fill carry it, so these stay as they were.
   ============================================================================================ */

svg.board { background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-sm); max-width: 100%; }
svg.board .sheet { fill: var(--sheet); stroke: var(--sheet-edge); stroke-width: 1; }
svg.board .part { fill: var(--part-fill); stroke: var(--part-edge); stroke-width: .65; vector-effect: non-scaling-stroke; }
/* Functional outer keyline separates a light amber selection from light map fills.
   Its default width is zero; only the H trial opts in, with no shadow or geometry change. */
svg.board .part[aria-pressed="true"]:not(:focus-visible) { outline: var(--map-selection-keyline-width, 0px) solid var(--map-selection-keyline, transparent); outline-offset: var(--map-selection-keyline-offset, 0px); }
svg.board .part:focus-visible { outline: 2px solid var(--map-focus-ring, var(--ring)); outline-offset: 2px; }
svg.board .grain-arrow { color:var(--map-grain); }
/* Board coming back: not charged to this order, and held out of every fill figure on the screen. */
svg.board .offcut { fill: var(--offcut); stroke: var(--offcut-edge); stroke-width: 0.6; stroke-dasharray: 8 3; }

/* Reported, but the order still pays for it. Same dashed outline — it is still a named rectangle
   the operator lifts out — in the neutral that says nothing about money. */
svg.board .offcut-plain {
    fill: var(--offcut-plain); stroke: var(--offcut-plain-edge); stroke-width: 0.6; stroke-dasharray: 4 3;
}

/* Waste is leftover the rack will not take: a neutral hatch, with
   its area on it. This is what makes a bad board look bad — fill alone cannot, because one usable
   offcut and eleven unusable slivers come to the same percentage. */
svg.board .waste { fill: var(--map-waste-fill); stroke: var(--map-waste-edge); stroke-width: 0.6; stroke-dasharray: 2 2; }
/* The text on a board.
   -------------------
   Every one of these is cut out of its own background rather than haloed in white. The stroke colour
   comes in as an attribute from BoardSvg — the piece's own fill for a part, --offcut for a leftover,
   --map-waste-fill for waste — so the halo is invisible where nothing runs under the text and still keeps it
   clean where a band strip or a neighbour does. A 3 px white outline round every glyph was doing the
   second job by permanently doing the first one badly: a pale smudge around the digits that are the
   whole reason the board is on screen.

   paint-order puts that stroke behind the fill, so the letterforms themselves stay sharp. */
svg.board text {
    paint-order: stroke;
    stroke-width: 2.5px;
    stroke-linejoin: round;
    stroke-linecap: round;
    pointer-events: none;
    text-anchor: middle;
    dominant-baseline: middle;
    font-variant-numeric: tabular-nums;
}

svg.board .waste-label {
    fill: var(--map-waste-text); font-size: 11px; font-weight: 600; letter-spacing: .01em;
}
svg.board .offcut-label,
svg.board .offcut-plain-label {
    /* Was --muted, which on the dark theme's --offcut is about 3.6:1 — under the floor for 11 px.
       Re-measured on both grounds this now sits on: 8.9:1 / 8.6:1 on the green, and unchanged on
       the neutral, which is the colour it was measured against in the first place. */
    fill: var(--offcut-text); font-size: 11px; font-weight: 500; letter-spacing: .01em;
}

/* What becomes of the offcut, under its size. Quieter than the size by weight and size — never by
   opacity, which is how the rest of this drawing keeps its hierarchy legible at arm's length. */
svg.board .offcut-note {
    fill: var(--good); font-size: 10.5px; font-weight: 600; letter-spacing: .01em;
}

/* The per-sheet scorecard under each board. */
.board-score { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); justify-content: center; margin-top: var(--sp-1_5); }
.board-score .score-good { color: var(--good); }
.board-score .score-bad { color: var(--bad); font-weight: 600; }
/* The size, printed on the piece. Dark ink in both themes, because the part fills are the same
   pastels in both — hsl(h 55% 72%), which puts this at better than 10:1 with no halo needed for
   contrast. Tracking is very slightly tight: it is the larger of the two lines. */
svg.board .part-label {
    fill: var(--map-label); font-size: 12px; font-weight: 650; letter-spacing: -.005em;
}

/* The piece number, beside the size. Quieter than the size — the size is what an operator checks a
   panel by, the number is what they look up a label or a program with — but quieter by SIZE AND
   WEIGHT, not by ink and never by transparency. It used to be the size's own colour at 80 % opacity.

   The ink was chosen by measuring, not by eye. Part fills are hsl(h 55% 72%) and HSL lightness is
   not perceptual lightness, so the blue-violet hues come out far darker than the yellows at the same
   72 %. Worst case over the whole hue circle: #3a3d45 gives 3.75:1 — under the floor for 10.5 px —
   and #2b2e35 only just clears it at 4.69. #22242a holds 5.35:1 against every hue a part id can
   produce, and is still a visible step lighter than the size's #15161a (6.23:1 worst). */
svg.board .piece-label {
    fill: var(--map-piece-label); font-size: 10.5px; font-weight: 550; letter-spacing: .025em;
}

/* ============================================================================================
   The rack
   ============================================================================================ */

.rack { display: flex; flex-direction: column; gap: var(--sp-6); }
.rack-actions { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; }
.catalogue-footer {
    display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: flex-start;
    padding-top: var(--sp-6); margin-top: var(--sp-5); border-top: 1px solid var(--hairline);
}
.catalogue-body { overflow: visible; }
.catalogue-table-scroll { overflow-x: auto; }
.catalogue-add { position: relative; }
.catalogue-add > summary { list-style: none; cursor: pointer; }
.catalogue-add > summary::-webkit-details-marker { display: none; }
.catalogue-add[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.catalogue-form {
    position: absolute; z-index: 8; top: calc(100% - 1px); left: 0; width: min(30rem, calc(100vw - 48px));
    max-height: min(70vh, 620px); overflow-y: auto;
    padding: var(--sp-7); background: var(--panel); border: 1px solid var(--hairline);
    border-radius: var(--r-none) var(--r-md) var(--r-md) var(--r-md); box-shadow: var(--sh-3);
}
.row-actions { white-space: nowrap; text-align: right; }
.row-actions .btn + .btn { margin-left: var(--sp-2); }
.switch-row { display: flex; align-items: flex-start; gap: var(--sp-4_5); }
.switch-row label { display: flex; align-items: center; gap: var(--sp-4); font-weight: 500; cursor: pointer; }

@media (max-width: 760px) {
    .catalogue-form { position: fixed; inset: 72px 16px 16px; width: auto; max-height: none; border-radius: var(--r-lg); }
}

/* ============================================================================================
   Parts — the list finds a part, the drawing is the instrument. Everything above the drawing is
   chrome, and chrome was measured at 344 px of a 720 px screen before it was cut back.
   ============================================================================================ */

.parts {
    display: flex; gap: var(--sp-6); align-items: stretch;
    /* Bound to the bar's own height rather than a magic number that breaks when the bar wraps. */
    height: calc(100vh - 58px - 34px); min-height: 26rem;
}
.part-list {
    /* Wide enough that a part's name survives beside its size, number and bands — at 264 px
       "Sredni stoyka" came out as "1 Sredni…", which defeats a list you find things in. */
    flex: 0 0 320px; overflow-y: auto; display: flex; flex-direction: column;
    background: var(--panel); border: 1px solid var(--border-soft); border-radius: var(--r-lg);
    box-shadow: var(--sh-1); scrollbar-gutter: stable;
}
.part-list-actions {
    display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-4);
    border-bottom: 1px solid var(--border-soft); flex: none;
}
.part-search {
    position: sticky; top: 0; z-index: 2;
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4);
    /* A fade where the list runs under the search box, not a rule across it. */
    box-shadow: var(--sh-1);
    font-size: var(--t-sm);
}
.part-search input {
    flex: 1 1 auto; min-width: 0; padding: var(--sp-2_5) var(--sp-4_5); font-size: var(--t-md);
    background: var(--panel-2); border-radius: var(--r-full);
}

/* One line per part, not three. Sixty parts at 75 px each is 4.6 m of scrolling. */
/* Picking parts to band in one go. The checkbox sits outside the row button rather than inside it —
   a button inside a button is not a thing, and the row still has to stay clickable for the drawing. */
.part-bulk {
    display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-2) var(--sp-4_5);
    border-bottom: 1px solid var(--border-soft); flex: none;
}
.part-pick-all { display: flex; align-items: center; gap: var(--sp-3); cursor: pointer; font-size: var(--t-sm); color: var(--muted); }

.part-bulk-apply {
    display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-3_5) var(--sp-4_5);
    background: var(--panel-2); border-bottom: 1px solid var(--border-soft); flex: none;
}
.part-bulk-apply .btn-group { flex-wrap: wrap; }
.part-bulk-apply .hint { font-size: var(--t-sm); }

.part-line {
    display: flex; align-items: center; gap: var(--sp-3); padding-left: var(--sp-4_5); flex: none;
    border-bottom: 1px solid var(--border-soft);
}
.part-line .part-pick { flex: none; }

/* The row keeps its own width rules everywhere else, so they are undone here rather than there:
   'width: 100%' beside a checkbox that cannot shrink pushes the piece numbers off the right edge. */
.part-line .part-row { padding-left: 0; border-bottom: 0; flex: 1 1 auto; width: auto; min-width: 0; }

.part-row {
    display: flex; align-items: center; gap: var(--sp-3_5); width: 100%; text-align: left;
    background: none; border: 0; border-bottom: 1px solid var(--border-soft); padding: var(--sp-2_5) var(--sp-4_5);
    font-size: var(--t-md); cursor: pointer; color: var(--text); flex: none;
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.part-row:hover { background: var(--panel-2); }
.part-row.selected { background: var(--accent-soft); color: var(--accent-soft-text); }
.part-row .swatch { width: 10px; height: 10px; border-radius: var(--r-xs); border: 1px solid var(--ink); flex: none; }
.part-row .part-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.part-row .part-size { color: var(--muted); font-variant-numeric: tabular-nums; flex: none; font-size: var(--t-sm); }
.part-row .part-qty { color: var(--muted); flex: none; font-size: var(--t-sm); }
/* The piece number stays: it is how a labelled panel on the bench is traced back to a row. */
.part-row .part-nums { color: var(--muted); flex: none; font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.part-row.selected .part-size, .part-row.selected .part-qty, .part-row.selected .part-nums {
    color: inherit; opacity: .8;
}
.part-row .part-ops { display: none; }

.part-detail {
    flex: 1 1 auto; background: var(--panel); border: 1px solid var(--border-soft);
    border-radius: var(--r-lg); box-shadow: var(--sh-1); padding: var(--sp-5) var(--sp-7); min-width: 0;
    display: flex; flex-direction: column; overflow: hidden;
}

@media (max-width: 1100px) {
    .parts { height: auto; min-height: 0; flex-direction: column; }
    .part-list { flex: 0 0 auto; width: 100%; max-height: min(38vh, 340px); }
    .part-detail { min-height: 620px; overflow: visible; }
    .editor { min-height: 540px; }
}
.part-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-3_5); }
.part-head h3 { margin: 0; font-size: var(--t-lg); font-weight: 600; }
.part-head .stat { margin: 0; }
.part-head-actions { display: flex; align-items: center; gap: var(--sp-2_5); margin-left: auto; }
.part-form select { min-width: 15rem; max-width: 22rem; }
.part-detail h3 { margin: 0 0 var(--sp-2); font-size: var(--t-lg); }

/* ============================================================================================
   The part drawing — a drawing, so line types carry meaning. Unchanged.
   ============================================================================================ */

svg.part-drawing {
    max-width: 100%; height: auto; background: var(--panel);
    border: 1px solid var(--border); border-radius: var(--r-sm);
}
/* Line types carry meaning here, the way they do on a drawing: a continuous thick line is an edge
   the tool makes, a thin one is annotation, dash-dot is an axis, and dashed is something hidden. */
svg.part-drawing .part-body { fill: var(--panel-face); stroke: var(--panel-edge); stroke-width: 1.4; }

/* A hole is a circle with its centre marked. It is not filled in: filled reads as solid material,
   which is the opposite of what a hole is, and it hides the centre a machinist measures to. */
svg.part-drawing .bore { fill: none; stroke: var(--ink); stroke-width: 1.3; }
svg.part-drawing .bore.blind { stroke-width: 1.1; }
svg.part-drawing .bore.edge { stroke: var(--ink); stroke-width: 1.1; stroke-dasharray: 3 2; }
svg.part-drawing .centre { stroke: var(--ink); stroke-width: .7; stroke-dasharray: 5 2 1 2; opacity: .75; }

svg.part-drawing .mill { fill: none; stroke: var(--accent); stroke-opacity: .5; stroke-linecap: round; stroke-linejoin: round; }
svg.part-drawing .mill-line { fill: none; stroke: var(--accent); stroke-width: 1; stroke-dasharray: 3 2; pointer-events: none; }

/* A groove is removed material: hatched, walled, and with the cutter's run as its axis. */
svg.part-drawing .groove { fill: url(#groove-hatch); stroke: var(--ink); stroke-width: 1.1; }
svg.part-drawing .hatch { stroke: var(--panel-edge); stroke-width: 1; }
svg.part-drawing .groove-axis {
    stroke: var(--ink); stroke-width: .7; stroke-dasharray: 5 2 1 2; opacity: .7; pointer-events: none;
}
/* A fault is marked on the feature it is about, so the drawing is the report. */
svg.part-drawing .groove.faulty { stroke: var(--bad); }
svg.part-drawing .fault-mark { fill: none; stroke: var(--bad); stroke-width: 1.6; stroke-dasharray: 3 2; }

/* Picking a feature off the drawing. The target is invisible and larger than the feature, because a
   Ø5 hole at 30 % zoom is under two pixels across and nobody can hit that. */
svg.part-drawing .bore-target { fill: transparent; stroke: none; cursor: pointer; }
svg.part-drawing .bore.picked { fill: var(--accent); stroke: var(--accent); stroke-width: 3; }
svg.part-drawing .bore.blind.picked, svg.part-drawing .bore.edge.picked { fill: var(--accent-soft); }
svg.part-drawing .groove.picked { stroke: var(--accent); }
svg.part-drawing .mill.picked { stroke-opacity: 1; stroke: var(--accent); }
svg.part-drawing .groove, svg.part-drawing .mill { cursor: pointer; }

/* What the drawing cannot show. Stated plainly rather than hidden in a tooltip — the shop must not
   hear about a missing hole from the machine. */
.stat.notice {
    background: var(--bad-bg); color: var(--bad); border-left: 3px solid var(--bad);
    padding: .5rem .7rem; border-radius: var(--r-sm); margin: .35rem 0;
}
.stat.notice ul { margin: .3rem 0 .3rem 1.1rem; padding: 0; }
/* Dimensions: thin continuous lines with arrowheads, extension lines out to them, values above the
   line. Bare ticks and a number floating underneath was not a dimension, it was a caption. */
svg.part-drawing .dim { stroke: var(--muted); stroke-width: .9; fill: none; }
svg.part-drawing .dim-head { fill: var(--offcut-text); stroke: none; }
svg.part-drawing .extension { stroke: var(--muted); stroke-width: .6; opacity: .6; }
svg.part-drawing .dim-text {
    fill: var(--text); font-size: 13px; font-weight: 600; text-anchor: middle; font-variant-numeric: tabular-nums;
}
/* Running dimensions from the datum. Smaller than the overall size, because they are read one at a
   time and there are a lot of them. */
svg.part-drawing .ordinate-text {
    fill: var(--text-soft); font-size: 10.5px; text-anchor: start; font-variant-numeric: tabular-nums;
}
svg.part-drawing .datum { fill: var(--ink); stroke: none; }
svg.part-drawing .datum-text {
    fill: var(--text); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
svg.part-drawing .view-label { fill: var(--muted); font-size: 11px; }
/* Same rule as the board's labels: the halo is the colour of what the text actually sits on. A
   callout is anchored just outside its own hole, so that is the panel FACE, not the page — it was
   haloed in --panel, which is a white smudge on the face's #f7f4ec. */
svg.part-drawing .callout {
    fill: var(--text); font-size: 11px; font-variant-numeric: tabular-nums; letter-spacing: .01em;
    paint-order: stroke; stroke: var(--panel-face); stroke-width: 3px; stroke-linejoin: round;
    pointer-events: none;
}
/* The depth symbol, a size up: at 11 px ISO's ↧ is a vertical stroke and reads as a capital I. */
svg.part-drawing .callout .sym { font-size: 14px; }

/* Ties a pushed-out note back to the hole it belongs to. Thin and quiet — it is a pointer, not a
   feature of the part, and it must never be mistaken for a cut. The note is drawn after it, so the
   note's own halo cuts the line off at the glyphs instead of the line running through them. */
svg.part-drawing .callout-leader {
    stroke: var(--muted); stroke-width: .7; fill: none; pointer-events: none;
}

/* Edge elevations: the panel seen on edge, with drills shown at the depth they reach. */
svg.part-drawing .edge-body { fill: var(--panel-face); stroke: var(--panel-edge); stroke-width: 1; }
svg.part-drawing .elevation-feature { pointer-events: all; fill: none; stroke: var(--ink); stroke-width: 1; cursor: pointer; }
svg.part-drawing .elevation-feature.hidden { stroke-dasharray: 3 2; }
svg.part-drawing .elevation-feature.uncertain { stroke-dasharray: 1 3; }
svg.part-drawing .elevation-feature.picked { stroke: var(--accent); stroke-width: 2; fill: var(--accent-soft); }
svg.part-drawing .elevation-feature.faulty { stroke: var(--bad); }
svg.part-drawing .bore-depth { stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-opacity: .75; }
/* The selection rectangle, an overlay on the drawing rather than part of it — see editor.js.
   Faint enough to read the drawing through it while it is being dragged. */
.editor .drawing-area { position: relative; }
.editor .drawing-area .marquee-box {
    position: absolute; display: none; pointer-events: none;
    background: var(--accent); opacity: .18;
    border: 1px dashed var(--accent); border-radius: var(--r-xs);
}
svg.part-drawing .pending { fill: none; stroke: var(--pending); stroke-width: 1.6; stroke-dasharray: 5 3; }
svg.part-drawing .pending-point { fill: var(--pending); }

/* ============================================================================================
   Machining editor
   ============================================================================================ */

/* Fixed work areas: tools / drawing / inspector. Conditional properties, faults and
   the feature list scroll in the inspector; none can change the canvas rectangle. */
.editor {
    display: grid; flex: 1 1 0; min-height: 0; min-width: 0;
    grid-template-columns: 13rem minmax(0, 1fr) 19rem;
    grid-template-rows: minmax(0, 1fr) var(--ctl-h);
    grid-template-areas: "rail canvas context" "status status status";
    gap: var(--sp-4);
}
.editor .ed-context { grid-area: context; }
.editor .ed-rail { grid-area: rail; }
.editor .ed-canvas { grid-area: canvas; }
.editor .ed-status { grid-area: status; }
.editor .hint { color: var(--muted); font-size: var(--t-sm); }
.ed-context {
    display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-5);
    min-height: 0; min-width: 0; overflow: auto; scrollbar-gutter: stable;
    padding-left: var(--sp-5); border-left: 1px solid var(--hairline);
}
.ed-context .inspector-title { margin: 0; font-size: var(--t-md); font-weight: 600; }
.editor .btn.icon.primary { --button-bg:var(--action-bg); --button-ink:var(--action-text); --button-hover:var(--action-hover); --button-hover-ink:var(--action-hover-text); }
.ed-what { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; gap: var(--sp-4); }
.ed-what > :is(.ctl-label,.band-picker,.pill,.hint) { grid-column: 1 / -1; }
.ed-what > .ctl-label { margin: 0; }
.ed-context .field { display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-2); min-width: 0; white-space: normal; }
.ed-context .field > :is(input,select) { width: 100%; min-width: 0; box-sizing: border-box; }
.ed-context .field > input[type=checkbox] { width: auto; align-self: flex-start; }
.ed-context .field-label { min-height: 1.2em; }
.ed-do { display: flex; flex-wrap: wrap; align-items: end; gap: var(--sp-3); min-width: 0;
    padding-top: var(--sp-5); border-top: 1px solid var(--hairline); }
.ed-context .btn-group { display: flex; flex-wrap: wrap; align-items: end; gap: var(--sp-3); width: 100%; }
.ed-context .btn-group > .field { flex: 1 1 4rem; padding: 0; }
.ed-context .btn-group > .field > input { height: var(--ctl-h); padding: var(--sp-2) var(--sp-3); border: 1px solid var(--border); background: var(--panel); border-radius: var(--fluent-radius); }
.ed-context .btn-group > :is(.btn,select) { border: 1px solid var(--button-stroke,var(--border)); border-radius: var(--fluent-radius); }
.ed-context .btn-group > select { min-width: 0; flex: 1 1 7rem; }
.ed-context .band-picker { min-width: 0; }
.ed-context .band-picker .picker-controls { display: flex; flex-direction: column; align-items: stretch; }
.ed-context .band-picker :is(input,select) { width: 100%; min-width: 0; }
/* Keep procedural help off the work surface; the editor has a help button in its status strip. */
.ed-context .band-picker > small:first-of-type { display: none; }
.ed-context .feature-list { width: 100%; min-height: 0; max-height: 40%; flex: 0 0 auto; margin: 0; }

/* Below this width the two side panels leave no usable drawing. Reserve a lower
   inspector instead; its contents still cannot change either canvas dimension. */
@media (max-width: 850px) {
    .editor {
        grid-template-columns: 13rem minmax(0, 1fr);
        grid-template-rows: 23rem 22rem var(--ctl-h);
        grid-template-areas: "canvas canvas" "rail context" "status status";
        height: calc(45rem + var(--ctl-h) + 2 * var(--sp-4));
        min-height: calc(45rem + var(--ctl-h) + 2 * var(--sp-4));
        flex: none;
    }
}

/* --- the rail --------------------------------------------------------------------------------- */
/* Wide enough for the longest label — "Through hole" — with the same clear space either side that
   every other control has. It was 8.75 rem with a permanently reserved scrollbar gutter, which left
   16 px of dead space on the right and squeezed that one label to 9 px from its edge while the rest
   sat 25–58 px clear. The rail holds a dozen fixed rows and never needs a scrollbar. */
.ed-rail {
    display: flex; flex-direction: column; gap: var(--sp-1);
    width: auto; flex: none; min-height: 0; overflow-y: auto; scrollbar-gutter: stable;
    /* Keep the final history buttons clear of the scroll edge, including fractional 125% pixels. */
    padding-right: var(--sp-5); padding-bottom: var(--sp-4); border-right: 1px solid var(--hairline);
}
.editor .rail-tool, .editor .rail-edge {
    display: flex; align-items: center; justify-content: flex-start; gap: var(--sp-3); width: 100%; text-align: left;
    height: var(--ctl-h); padding: 0 var(--ctl-pad-x); flex: none;
    background: none; border: 1px solid transparent; border-radius: var(--r-sm);
    color: var(--text); font-size: var(--t-md); cursor: pointer;
    transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve);
}
.rail-tool:hover, .rail-edge:hover { background: var(--panel-2); }
.rail-tool:disabled { opacity: .5; cursor: not-allowed; }
.rail-tool:disabled:hover { background: none; }
.rail-tool:active, .rail-edge:active { transform: none; }
/* Exactly one tool is lit at all times, Pick included: a set of modes with none lit says nothing
   about what the next click will do. */
.rail-tool.on { background: var(--accent); color: var(--accent-text); font-weight: 600; }
.rail-tool.on .glyph { opacity: 1; }
.rail-tool > .glyph { flex: none; width: 1rem; text-align: center; font-size: var(--t-lg); opacity: .75; }
.rail-tool > span:last-child { white-space: normal; text-align: left; }
.rail-edge > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.rail-label {
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em;
    color: var(--muted); font-weight: 600; padding: var(--sp-5) var(--sp-4) var(--sp-1_5); flex: none;
}
.rail-edge > b { flex: none; width: .75rem; }
.rail-edge > .muted { font-size: var(--t-sm); margin-left: auto; }
.rail-note { font-size: var(--t-xs); color: var(--warn); padding: var(--sp-2) var(--sp-4); flex: none; }
.rail-spacer { flex: 1 1 auto; min-height: 10px; }
.rail-history { align-self: flex-start; flex: none; }

/* --- the canvas, with zoom floating on it ------------------------------------------------------ */
.ed-canvas { position: relative; display: flex; min-height: 0; min-width: 0; }

/* Zoom is about looking rather than doing, so it floats on the drawing the way a map's does,
   instead of taking a row off it. Translucent, because what is underneath still matters. */
.canvas-zoom {
    position: absolute; right: 14px; bottom: 12px; z-index: 3;
    display: flex; align-items: center; gap: var(--sp-1_5); padding: var(--sp-1_5);
    background: var(--glass);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--hairline); border-radius: var(--r-full);
    box-shadow: var(--sh-2);
}
.canvas-zoom .btn { box-shadow: none; border-color: transparent; background: transparent; }
.canvas-zoom .btn:hover:not(:disabled) { background: var(--panel-2); }
.canvas-zoom .btn.on { background: var(--row-selection-bg); color: var(--row-selection-text); }
.canvas-zoom .zoom-value {
    font-size: var(--t-sm); color: var(--text-soft); font-variant-numeric: tabular-nums;
    min-width: 3.1rem; text-align: center;
}

/* --- the status strip -------------------------------------------------------------------------- */
.ed-status {
    display: flex; align-items: center; gap: var(--sp-4); flex-wrap: nowrap;
    min-height: 0; font-size: var(--t-sm); color: var(--muted);
}
.ed-status .coords { font-variant-numeric: tabular-nums; color: var(--text); }
.ed-status .status-right { display: flex; align-items: center; gap: var(--sp-7); margin-left: auto; }
.ed-status .field > select { height: var(--ctl-h-sm); font-size: var(--t-sm); }

.ed-alert {
    display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center;
    background: var(--bad-bg); border-left: 3px solid var(--bad); border-radius: var(--r-sm);
    padding: .35rem .6rem;
}
.ed-alert .link { color: var(--bad); font-size: var(--t-md); text-align: left; }

.editor .fixed-value { color: var(--text); font-weight: 600; }

/* Zoom is only worth having if the far end of a 2.8 m panel can be reached at 200 %, so the drawing
   scrolls inside its own box rather than pushing the page sideways. */
/* The scrollbar gutter is reserved whether or not there is a scrollbar. Without it, fitting the
   drawing to the box is a feedback loop: the drawing grows, a scrollbar appears, the box narrows by
   the scrollbar's width, the drawing is re-fitted smaller, the scrollbar goes, and the page spins. */
.editor .drawing-area {
    cursor: crosshair; overflow: auto; scrollbar-gutter: stable both-edges;
    flex: 1 1 auto; min-height: 0; min-width: 0;
    border: 1px solid var(--border-soft); border-radius: var(--r-md); background: var(--panel-2);
}
.editor .drawing-area.panning { cursor: grabbing; }
/* Centred while it fits, hard against the left once it does not — margin:auto resolves to 0 on an
   element wider than its box, so the same rule does both. */
.editor .drawing-canvas { position: relative; display: inline-block; min-width: 100%; }
.editor .drawing-area svg.part-drawing {
    max-width: none; border: 0; border-radius: var(--r-none); display: block; margin: 0 auto; background: transparent;
}

/* A part carries hundreds of holes, so the list is a panel with its own scrollbar — not something
   that pushes the drawing off the top of the screen. */
.feature-list {
    margin-top: var(--sp-4); flex: 0 0 auto; max-height: 30vh; overflow: auto;
    border: 1px solid var(--border-soft); border-radius: var(--r-md);
}
.feature-list.folded { display: none; }
.feature-list table { border-collapse: collapse; width: 100%; font-size: var(--t-md); color: var(--text); }
.feature-list th {
    position: sticky; top: 0; background: var(--panel); z-index: 1;
    text-align: left; font-weight: 600; color: var(--muted); font-size: var(--t-xs);
    text-transform: uppercase; letter-spacing: .06em; padding: var(--sp-3) var(--sp-4_5); border-bottom: 1px solid var(--hairline);
}
.feature-list td { padding: var(--sp-2) var(--sp-4_5); border-bottom: 1px solid var(--border-soft); font-variant-numeric: tabular-nums; }
.feature-list tbody tr { cursor: pointer; transition: background-color var(--fluent-duration) var(--fluent-curve), color var(--fluent-duration) var(--fluent-curve), border-color var(--fluent-duration) var(--fluent-curve), opacity var(--fluent-duration) var(--fluent-curve), box-shadow var(--fluent-duration) var(--fluent-curve), fill var(--fluent-duration) var(--fluent-curve), stroke var(--fluent-duration) var(--fluent-curve); }
.feature-list tbody tr:hover { background: var(--panel-2); }
.feature-list tr.picked, .feature-list tr.picked:hover { background: var(--accent-soft); }
.feature-list tr.faulty td:last-child { color: var(--bad); }
.feature-list input[type=number] { width: 4.25rem; }
.feature-list .link { padding: 0 var(--sp-2); font-size: var(--t-md); }

/* ============================================================================================
   Edge banding.
   Every band is drawn in the colour the project gives it rather than in a theme colour, because
   that colour is what the operator matches the roll against at the bander — so these carry an
   outline instead, or a dark band vanishes into a dark theme and a pale one into a light one.
   ============================================================================================ */

.edge-swatch, .edge-dot {
    display: inline-block; width: 11px; height: 11px; border-radius: var(--r-xs);
    border: 1px solid var(--ink); flex: none; vertical-align: -1px;
}
.edge-dot { width: 9px; height: 9px; border-radius: var(--r-full); margin-right: var(--sp-1_5); }
.part-row .part-edges { flex: none; display: flex; align-items: center; }

/* The part's four sides, drawn. A banded side is a heavy stroke in its band's own colour, a bare one
   a hairline — so "banded all round" and "banded on the two long sides" are told apart without
   reading anything, which a row of identical dots could never do. */
.edge-map { width: 16px; height: 12px; flex: none; overflow: visible; }
.edge-map line { stroke-width: 1; stroke-linecap: round; }
.edge-map line.banded { stroke-width: 2.5; }
.edge-map line.bare { stroke-dasharray: 1.5 2; }

.edge-tag {
    display: inline-flex; align-items: center; gap: var(--sp-2_5); margin-right: var(--sp-6);
    background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r-sm); padding: var(--sp-1) var(--sp-4);
}

.edge-table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.edge-table th {
    text-align: left; font-weight: 600; color: var(--muted); font-size: var(--t-xs);
    text-transform: uppercase; letter-spacing: .06em; padding: var(--sp-2_5) var(--sp-3); border-bottom: 1px solid var(--hairline);
}
.edge-table td { padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--border-soft); font-variant-numeric: tabular-nums; }
.edge-table td:first-child { display: flex; align-items: center; gap: var(--sp-3); }

/* A band row opens that band's settings: the table is where its metres are read, so it is where a
   figure that looks wrong should be correctable. */
.edge-table tr.clickable { cursor: pointer; }
.edge-table tr.clickable:hover td { background: var(--panel-2); }

/* Choosing a band is done in the context bar like every other selection, so the picker needs no
   island of its own — it is a .btn-group of ordinary buttons. */

/* Banding on a part drawing is identified by its letter only. */
svg.part-drawing .edge-letter {
    font-size: 10px; font-weight: 700; fill: var(--text); text-anchor: middle; dominant-baseline: middle;
    pointer-events: none;
}
svg.part-drawing .edge-letter.editable { pointer-events: all; cursor: pointer; }
svg.part-drawing .edge-letter.editable:focus-visible { outline: 1px solid var(--accent); }

/* ============================================================================================
   Startup and failure, for the browser build. The desktop app has its runtime in the box; a page
   has to fetch it, so it says so rather than showing an empty window while it downloads.
   ============================================================================================ */

.startup { padding: var(--sp-20) var(--sp-12); color: var(--muted); font-size: var(--t-lg); }
#blazor-error-ui {
    display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: var(--z-blocking);
    padding: var(--sp-5) var(--sp-8); background: var(--bad-bg); color: var(--bad);
    border-top: 1px solid var(--bad);
}
#blazor-error-ui .reload { color: inherit; }

/* ============================================================================================
   Accessibility preferences. None of these removes feedback — each replaces it with a quieter
   equivalent, which is what the settings actually ask for.
   ============================================================================================ */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 1ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
        scroll-behavior: auto !important;
    }
    /* The press still answers — it just does it by colour instead of by moving. */
    .btn:active:not(:disabled), .strategy:active, .rail-tool:active, .rail-edge:active,
    .segmented .seg:active, .material-pick:active { transform: none; }
    .btn:active:not(:disabled) { background: var(--panel-3); }
    .spinner { animation: none; border-top-color: var(--accent); opacity: .7; }
    .planning-card, .planning-mark span, .planning-progress span { animation: none; }
    .planning-progress span { width: 100%; opacity: .65; transform: none; }
}

@media (prefers-reduced-transparency: reduce) {
    :root { --glass: var(--panel); --glass-blur: none; --glass-edge: transparent; }
    .appbar, .menu-panel, .toast, .part-search { -webkit-backdrop-filter: none; backdrop-filter: none; }
    .appbar, .menu-panel, .toast, .part-search { background: var(--panel); }
    .planning-screen { background: var(--bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

@media (prefers-contrast: more) {
    :root {
        --border: var(--contrast-border);
        --border-soft: var(--contrast-border);
        --hairline: var(--contrast-border);
        --muted: var(--contrast-muted);
        --glass: var(--panel);
        --glass-blur: none;
    }
    .btn, .tile, .card, .part-list, .part-detail { border-color: var(--border); }
}

@media (forced-colors: active) {
    :root, :root[data-theme="dark"] {
        --chrome-bg: Canvas; --header-bg: Canvas; --chrome-ink: CanvasText; --chrome-text: CanvasText; --chrome-muted: CanvasText;
        --chrome-hover: Canvas; --chrome-active-bg: Highlight; --chrome-active-text: HighlightText;
        --chrome-icon: CanvasText; --chrome-active-icon: CanvasText; --chrome-selected-icon: HighlightText; --chrome-focus-ring: Highlight;
        --header-text: CanvasText; --header-muted: CanvasText; --header-button-bg: Canvas; --header-button-text: CanvasText; --header-quiet-text: CanvasText; --header-control-hover: Canvas;
        --header-status-text: CanvasText; --header-status-warn: CanvasText; --header-count-text: CanvasText; --header-count-bad: LinkText; --header-close-text: CanvasText;
        --action-bg: Highlight; --action-hover: Highlight; --action-text: HighlightText; --action-hover-text: HighlightText; --field-border: CanvasText; --selection-edge: Highlight; --menu-marker: Highlight; --tab-text: CanvasText; --offcut-text: CanvasText; --map-waste-fill: Canvas; --map-waste-edge: CanvasText; --map-waste-text: CanvasText; --map-selection-edge: CanvasText; --rail-primary-text: HighlightText; --tab-selected: Highlight;
        --variant-bg: Canvas; --variant-selected-bg: Canvas; --variant-edge: Highlight; --variant-selected-text: CanvasText; --variant-selected-muted: CanvasText; --variant-selected-good: CanvasText; --variant-selected-bad: LinkText;
        --row-selection-bg: Canvas; --row-selection-cell-bg: Canvas; --row-selection-text: CanvasText; --row-selection-text-soft: CanvasText; --row-selection-muted: CanvasText; --row-selection-panel: Canvas; --row-selection-hover: Canvas; --row-selection-accent: Highlight; --row-selection-good: CanvasText; --row-selection-bad: LinkText;
        --map-label: HighlightText; --map-piece-label: CanvasText; --map-part-fill: Highlight; --map-grain: HighlightText; --map-selection: CanvasText; --map-focus-ring: CanvasText; --map-inspector-focus-outline: 3px solid CanvasText;
        --edge-fallback: CanvasText; --mirror-preview: Highlight; --paper: Canvas; --paper-ink: CanvasText; --paper-border: CanvasText; --paper-selection: Highlight; --paper-selection-fill: Canvas;
        --bg: Canvas; --panel: Canvas; --panel-2: Canvas; --panel-3: Canvas;
        --text: CanvasText; --text-soft: CanvasText; --muted: CanvasText;
        --border: CanvasText; --border-soft: CanvasText; --hairline: CanvasText;
        --glass: Canvas; --glass-edge: CanvasText; --glass-blur: none;
        --accent: Highlight; --accent-hover: Highlight; --accent-text: HighlightText;
        --accent-soft: Canvas; --accent-soft-text: CanvasText; --ring: Highlight;
        --good: CanvasText; --good-bg: Canvas; --bad: LinkText; --bad-bg: Canvas;
        --warn: CanvasText; --warn-bg: Canvas; --pending: CanvasText;
        --sheet: Canvas; --sheet-edge: CanvasText; --part-fill: Highlight;
        --part-edge: HighlightText; --offcut: Canvas; --offcut-edge: CanvasText;
        --offcut-plain: Canvas; --offcut-plain-edge: CanvasText;
        --panel-face: Canvas; --panel-edge: CanvasText; --ink: CanvasText;
        --diagram-line: CanvasText; --canvas-grid: Canvas; --canvas-grid-dot: CanvasText;
        --overlay: Canvas; --overlay-strong: Canvas;
        --sh-1: none; --sh-2: none; --sh-3: none;
        --sh-popover: none; --sh-dialog: none; --sh-drawer: none;
    }
    .btn.primary, .btn.on { forced-color-adjust: none; background: Highlight; color: HighlightText; border-color: Highlight; }
    [aria-invalid="true"], .btn.danger { border-color: LinkText; }
}

@media (prefers-contrast: more) {
    :root[data-theme="dark"] {
        --border: var(--contrast-border);
        --border-soft: var(--contrast-border);
        --hairline: var(--contrast-border);
        --muted: var(--contrast-muted);
    }
}
.manual-drawing-host .drawing-overlay{z-index:var(--z-editor-dialog)}

/* A narrow map can omit the repeated material only while its operation is named above. */
@media (min-width: 851px) and (max-width: 1280px) {
    .project-shell:has(.workspace-structure.collapsed) .map-material-name,
    .project-shell:not(:has(.operation-context.with-material)) .map-material-name { display: block; }
}

/* Reviewed reissue and supplier layout restored after the SaaS merge. */

.reissue-identity { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--sp-4); }

.reissue-identity label { display:grid; gap:var(--sp-2); min-width:0; color:var(--muted); font-size:var(--t-sm); }

.reissue-identity input { width:100%; min-width:0; }

.reissue-list-head { display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4); margin-top:var(--sp-6); }

.reissue-list-head input { width:min(300px,50%); }

.reissue-table-scroll input[aria-label^="Номера повреждённых"] { width:100%; min-width:150px; }

.reissue-outcome { flex:1; min-width:0; color:var(--muted); font-size:var(--t-sm); }

.reissue-empty { color:var(--muted); font-size:var(--t-sm); }
 .reissue-identity { grid-template-columns:1fr; }
 .reissue-list-head { align-items:stretch; flex-direction:column; }
 .reissue-list-head input { width:100%; }

.catalogue-supply-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3) var(--sp-4); margin-top: var(--sp-3); }

.catalogue-supply-form label { display: grid; gap: var(--sp-1); }

.catalogue-supply-form input { width: 100%; min-width: 0; }

.catalogue-supply-form .btn, .catalogue-supply-form .notice { grid-column: 1 / -1; }

    .catalogue-form, .catalogue-supply-form { grid-template-columns: 1fr; }
.xnc-parameter-workspace { display:block; flex:1; min-height:0; background:var(--panel); border:1px solid var(--border); border-radius:var(--r-lg); overflow:auto; }
.xnc-parameter-workspace > * { min-width:0; }
.xnc-part-parameters { display:grid; gap:var(--sp-4); padding:var(--sp-5) var(--sp-6); }
.xnc-overview { display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-4); }
.xnc-overview-copy { display:grid; gap:var(--sp-1); min-width:0; }
.xnc-overview-copy strong { overflow-wrap:anywhere; }
.xnc-overview-copy span { color:var(--muted); }
.xnc-overview .btn { flex:none; }
.xnc-machine-actions { display:flex; align-items:end; gap:var(--sp-3); flex-wrap:wrap; }
.xnc-machine-field { display:grid; gap:var(--sp-1); min-width:min(100%, 15rem); color:var(--muted); font-size:var(--t-sm); }
.xnc-machine-field select { width:100%; min-width:0; }
.xnc-parameter-workspace .machining-costs { border-top:1px solid var(--border); padding:var(--sp-5) var(--sp-6); }
.xnc-parameter-workspace .contour-band-assignments { border-top:1px solid var(--border); }
@media (max-width: 700px) {
    .xnc-part-parameters, .xnc-parameter-workspace .machining-costs { padding:var(--sp-4); }
    .xnc-overview { flex-wrap:wrap; }
    .xnc-overview .btn { max-width:100%; }
    .xnc-machine-actions > * { max-width:100%; }
}
/* Shared feedback is outside the workspace flow: an unresolved check never shrinks a grid or map. */
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:0; overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0; }
.issue-status { display:flex; align-items:center; gap:.65rem; min-width:0; height:16px; }
.issue-status .toast { display:inline-flex; gap:.5rem; min-width:0; padding:0; background:none; border:0; box-shadow:none; }
.issue-status .toast-text { flex:0 1 auto; max-width:55ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.issue-status .toast-close { flex:none; }
.issue-indicator { font-weight:700; color:var(--bad); flex:none; white-space:nowrap; }
.issue-toast { --notice-preferred-width:670px; position:fixed; top:0; right:12px; z-index:var(--z-toast); width:min(var(--notice-preferred-width),calc(100vw - 90px)); height:30px; box-sizing:border-box; display:flex; align-items:center; gap:.5rem; padding:var(--sp-1) var(--sp-4); border:1px solid var(--border); border-left:3px solid var(--bad); border-radius:var(--r-md); background:var(--panel); color:var(--text); box-shadow:0 4px 18px var(--issue-shadow); }
.issue-toast>.ui-icon { flex:none; color:var(--bad); }
.issue-toast-text { min-width:0; flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:.82rem; }
.issue-toast .btn { flex:none; }
.issue-popover { position:fixed; top:58px; right:12px; z-index:var(--z-popover); width:min(750px,calc(100vw - 90px)); max-height:calc(100dvh - 80px); display:flex; flex-direction:column; background:var(--panel); color:var(--text); border:1px solid var(--border); border-radius:var(--r-md); box-shadow:0 12px 36px var(--issue-popover-shadow); overflow:hidden; }
.issue-popover>header { display:flex; align-items:center; justify-content:space-between; padding:.65rem .8rem; border-bottom:1px solid var(--border); }
.issue-list { overflow:auto; min-height:0; padding:.25rem .8rem .65rem; overscroll-behavior:contain; }
.issue-row { padding:.55rem 0; border-bottom:1px solid var(--border-soft); }
.issue-row:last-child { border-bottom:0; }
.issue-row-main { display:flex; gap:.55rem; align-items:center; }
.issue-row-main>span { flex:1; min-width:0; font-size:.88rem; overflow-wrap:anywhere; }
.issue-row-main>.ui-icon { flex:none; color:var(--bad); }
.issue-row-main>.btn { flex:none; }
.issue-details { margin-left:1.6rem; font-size:.8rem; color:var(--muted); }
.issue-details>summary { cursor:pointer; width:max-content; padding:.2rem 0; }
.issue-details p { margin:.4rem 0; white-space:pre-wrap; overflow-wrap:anywhere; }
.issue-group-row { padding:var(--sp-2) 0; border-bottom:1px solid var(--border-soft); }
.issue-group-row:last-child { border-bottom:0; }
.issue-group-row>.issue-row-main>span { font-weight:600; }
.issue-group-tools { display:flex; align-items:center; flex-wrap:wrap; gap:var(--sp-2); margin:var(--sp-1) 0 0 var(--sp-6); }
.issue-objects { color:var(--muted); font-size:var(--t-sm); margin-right:auto; }
.issue-group>summary { padding:var(--sp-1) 0; margin-left:var(--sp-6); font-size:var(--t-sm); color:var(--muted); cursor:pointer; }
.issue-group .issue-row { padding:var(--sp-1) 0; }


.issue-indicator { position:static; margin:0; padding:0; border:0; background:transparent; font:inherit; font-weight:700; line-height:16px; height:16px; display:inline-flex; align-items:center; gap:var(--sp-1); overflow:visible; }

.issue-toast,.issue-popover { margin:0; left:auto; bottom:auto; }

/* Status is inline in the reserved header row; it must not inherit the legacy floating toast. */
.issue-status .toast { position:static; inset:auto; transform:none; margin:0; width:auto; z-index:auto; }
.saved-strategies { display:flex !important; flex-wrap:wrap; gap:var(--sp-3); }
.cutting-workspace .result-support .strategies.saved-strategies .strategy { flex:0 1 270px; width:270px; max-width:100%; }
.saved-strategies .variant-metric .missing { font-size:.75rem; font-weight:600; }
.issue-status .toast { height:14px; font-size:11px; line-height:14px; }
.issue-status .toast-close { font:inherit; line-height:14px; min-height:0; height:14px; padding:0; }

/* Queue notification display and pause its timer until blocking chrome closes. */
html.modal-open .issue-toast, html:has(.planning-screen) .issue-toast { visibility:hidden; pointer-events:none; }

/* Shared issue sources have a local surface only inside their owning modal.
   It inherits the dialog layer and inert management; no portal or top-layer exception. */
.issue-local { display:none; }
:is([data-modal-root],dialog,[role="dialog"][aria-modal="true"]) .issue-local {
    display:block; margin:var(--sp-2) 0; padding:var(--sp-2) var(--sp-3);
    border:1px solid var(--border); border-left:3px solid var(--bad);
    border-radius:var(--r-sm); background:var(--panel); color:var(--text);
}
.issue-local-main { display:flex; align-items:center; flex-wrap:wrap; gap:var(--sp-2); }
.issue-local-main>span { flex:1 1 200px; min-width:0; overflow-wrap:anywhere; }
.issue-local-main>.ui-icon { flex:none; color:var(--bad); }
.issue-local.warning { border-left-color:var(--warn); }
.issue-local.warning .ui-icon { color:var(--warn); }
.issue-local .issue-details { max-height:160px; overflow:auto; }

/* Shared anchored surfaces escape scrolling containers, then close before any blocking layer. */
[data-popup-surface] { position:fixed !important; inset:auto; margin:0; z-index:var(--z-popover); box-sizing:border-box; overflow:auto; }
[data-popup-surface][popover]:not(:popover-open) { display:none !important; }
html.modal-open [data-popup-active][data-popup-owned="app"] { visibility:hidden; pointer-events:none; }
[data-popup-inline] { position:static !important; width:auto; max-width:100%; }

/* Existing Warning/Error meaning controls paint only. */
.issue-row.warning .issue-row-main > .ui-icon, .issue-group-row.warning > .issue-row-main > .ui-icon, .issue-indicator.warning { color:var(--warn); }

/* Shared layout primitives: separated groups8px, inner toolbar groups4px,
   padded surfaces8px. These are safety minima, not per-screen nudges. */
html .project-shell.project-shell :is(.project-titlebar,.context-calculation,.appbar-group,.rack-actions,.dialog-actions,.workspace-dialog-actions,.map-toolbar,.table-toolbar,.navigator-tools,.bulk-action-bar) { gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.project-titlebar,.map-toolbar,.table-toolbar,.navigator-tools,.bulk-action-bar) { padding-block:var(--ctl-gap); padding-inline:var(--ctl-gap); }
html .project-shell.project-shell :is(.navigator-actions,.navigator-modes,.bulk-action-group,.bulk-row-actions) { gap:var(--ctl-gap); padding:0; }
html .project-shell.project-shell :is(.table-toolbar,.navigator-tools,.bulk-action-bar) { --button-h:24px; --button-pad:8px; --button-pad-y:3px; --button-gap:4px; }
html .project-shell.project-shell :is(.table-toolbar,.navigator-tools,.bulk-action-bar) :is(.btn,.navigator-icon,.navigator-quick-add,.navigator-operation-menu):has(.ui-icon) { --button-pad-y:1px; }
html .project-shell.project-shell :is(.table-toolbar,.navigator-tools,.bulk-action-bar) :is(input:not([type=checkbox]),select,.field) { height:24px; min-height:24px; }
html .project-shell.project-shell :is(.segmented,.machine-settings-tabs) { gap:var(--ctl-gap); padding:var(--ctl-gap); }
html .project-shell.project-shell .workflow-header { padding-bottom:var(--ctl-gap); }
html .project-shell.project-shell .project-rail { padding-inline:var(--ctl-gap); }
html .project-shell.project-shell .project-rail { gap:var(--ctl-gap); }
html .project-shell.project-shell .project-rail nav { gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.field-grid,.parameter-fields,.material-fields,.material-actions,.material-catalogue,.result-support) { row-gap:var(--ctl-gap); column-gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.table-command-popover,.navigator-menu-popover,.menu-panel,.command-menu) { display:grid; }
html .project-shell.project-shell .project-titlebar .btn.icon:not([data-popup-surface] *) { --button-ink:var(--header-text); --button-disabled-ink:var(--header-muted); --button-hover:var(--chrome-hover); }
html .project-shell.project-shell .btn.icon.rail-toggle { width:auto; min-width:96px; padding:var(--button-pad-y) var(--button-pad); }
html .project-shell.project-shell .project-title { display:flex; gap:var(--sp-2); }
html .project-shell.project-shell .header-status .toast { display:flex; gap:var(--ctl-gap); }
html .project-shell.project-shell .project-title { flex-direction:column; }
html .project-shell.project-shell .header-status { height:32px; }
html .project-shell.project-shell .header-status .toast { height:32px; }
html .project-shell.project-shell .header-status .issue-status { height:32px; gap:var(--ctl-gap); }
html .project-shell.project-shell .header-status .toast { animation:none; transform:none; }
/* Reserve the longest normal Russian save-status phrase so asynchronous saves
   do not resize the adjacent title field. Error text may still take more room. */
html .project-shell.project-shell .project-titlebar { --save-status-width:26ch; }
html .project-shell.project-shell .project-save-state { min-inline-size:var(--save-status-width); }
html .project-shell.project-shell :is(.toast-close,.issue-indicator) { height:32px; min-height:32px; padding:var(--button-pad-y) var(--button-pad); --button-bg:transparent; --button-stroke:transparent; --button-ink:var(--header-text); --button-hover:var(--chrome-hover); }
html .project-shell.project-shell .result-support { display:flex; flex-direction:column; gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.result-options > .card-body,.cs-cutting-column,.cs-cutting-column > form) { display:flex; flex-direction:column; gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.parts-grid,.edge-table,.data-table,.cnc-drill-table,.project-navigator table,.linear-table table,.groove-table table,.general-operation table,.cnc-table-scroll table) { --button-h:24px; --button-pad:8px; --button-pad-y:3px; --button-gap:4px; }
/* Dense table slots, owner15.10:24px Fluent small +2px each side +1px line=29px.
   Cells are slots, not8px-gutter panels; focus remains inset. */
html .project-shell.project-shell :is(.parts-grid,.edge-table,.data-table,.cnc-drill-table,.project-navigator table,.linear-table table,.groove-table table,.general-operation table,.cnc-table-scroll table) td { height:28px; padding-block:var(--sp-1); }
html .project-shell.project-shell .table-cell-value { --button-bg:transparent; --button-hover:var(--panel-2); --button-pressed:var(--panel-3); --button-stroke:transparent; width:100%; justify-content:flex-start; }
html .project-shell.project-shell .help-tip-button { width:var(--button-h); height:var(--button-h); min-height:var(--button-h); padding:0; border-radius:var(--fluent-radius); --button-bg:transparent; --button-stroke:transparent; }
html .project-shell.project-shell .map-toolbar :is(.btn,select) { height:32px; min-height:32px; }
html .project-shell.project-shell .map-context { min-height:32px; padding:var(--ctl-gap); }
html .project-shell.project-shell .map-context select { height:32px; min-height:32px; }
html .project-shell.project-shell :is(.strategy,.map-thumbnail):focus-visible { outline-offset:-2px; }
svg.board .part:focus-visible { outline-offset:-2px; }
html .project-shell.project-shell :is(.rail-create,.rail-work,.rail-bottom,.rail-nav) { gap:var(--ctl-gap); }
html .project-shell.project-shell .project-rail nav, html .project-shell.project-shell .rail-create { min-width:0; grid-template-columns:minmax(0,1fr); }
html .project-shell.project-shell .rail-action { width:100%; min-width:0; height:auto; }
html .project-shell.project-shell:not(.rail-hidden) .rail-action > span { min-width:0; white-space:normal; overflow-wrap:anywhere; }
html .project-shell.project-shell .project-rail .rail-action { --button-ink:var(--chrome-text); --button-hover:var(--chrome-hover); --button-pressed:var(--chrome-active-bg); justify-content:flex-start; }
html .project-shell.project-shell.rail-hidden .rail-action { width:32px; min-width:32px; }
html .project-shell.project-shell :is(.rail-action,.navigator-icon) .ui-icon { width:var(--button-icon); height:var(--button-icon); }
html .project-shell.project-shell :is(.btn,.icon-btn,.navigator-icon,.rail-action,.rail-tool,.rail-edge,summary[aria-label],[data-popup-active] button) .ui-icon { width:var(--button-icon); height:var(--button-icon); }
.project-shell.rail-hidden .rail-action { justify-content:center; padding:var(--button-pad-y); }
html .project-shell.project-shell .project-rail .rail-action.active { --button-bg:var(--chrome-active-bg); --button-ink:var(--chrome-active-text); }
html .project-shell.project-shell :is(.table-command-popover,.navigator-menu-popover,.menu-panel,.command-menu) { padding:var(--ctl-gap); gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.map-menu-popover,.cs-machine-menu-body,[data-popup-active]) { padding:var(--ctl-gap); gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.table-command-popover,.navigator-menu-popover,.menu-panel,.command-menu,.map-menu-popover,.cs-machine-menu-body,[data-popup-active]) { --button-h:32px; --button-pad:8px; --button-pad-y:5px; --button-gap:6px; }
html .project-shell.project-shell :is(.map-menu-popover,.cs-machine-menu-body) { display:grid; }
html .project-shell.project-shell :is(.map-menu-popover,.cs-machine-menu-body) button { width:100%; justify-content:flex-start; --button-bg:transparent; --button-stroke:transparent; }
html .project-shell.project-shell [data-popup-active] button:not(.primary) { --button-bg:transparent; --button-stroke:transparent; }
html .project-shell.project-shell .map-thumbnails { padding:var(--ctl-gap); gap:var(--ctl-gap); }
html .project-shell.project-shell :is(.project-navigator,.map-inspector,.table-scroll,.map-strip):focus-visible { outline-offset:-2px; }
html .project-shell.project-shell :is(.table-command-popover,.navigator-menu-popover,.menu-panel,.command-menu) button { width:100%; justify-content:flex-start; }
html .project-shell.project-shell :is(.machine-settings-grid,.machine-settings-fields,.settings-grid) { gap:var(--ctl-gap); }
html .project-shell.project-shell :is(button,input,select,[role=tab]):focus-visible { outline-width:2px; outline-offset:-2px; }
@media (prefers-reduced-motion:reduce) { *,*::before,*::after { transition:none !important; animation:none !important; } }

html .project-shell.project-shell :is(.machine-output,.machine-output label) { gap:var(--ctl-gap); }

/* One occupied command row switches content on selection; no extra panel or overlay. */
html .project-shell.project-shell .part-command-row { height:calc(var(--ctl-h-sm) + 2 * var(--ctl-gap)); min-height:calc(var(--ctl-h-sm) + 2 * var(--ctl-gap)); flex:none; flex-wrap:nowrap; border:0; border-radius:var(--fluent-radius); }
html .project-shell.project-shell .part-command-row.bulk-action-bar { box-shadow:inset 0 0 0 1px var(--accent); }

/* A summary is a block flex control: inline baselines must not lift menu buttons. */
html .project-shell.project-shell details > summary.btn { display:flex; }

/* Display and edit controls share the row context height; commit cues cannot recenter cells. */
html .project-shell.project-shell .parts-grid .table-cell-editor .field { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }

/* Owner15.10: preserve f518f5b button typography, including responsive app overrides.
   Fluent supplies dimensions/paint/focus/motion; its text scale is not ported. */
.btn { font-size: var(--t-md); font-weight: 500; line-height: 1; }
.btn.primary { font-weight: 600; }
.btn.on { font-weight: 600; }
.btn.icon { font-size: var(--t-lg); }
.btn.sm { font-size: var(--t-sm); }
.link { font-size: var(--t-sm); }
.segmented .seg { font-size: var(--t-md); font-weight: 500; }
.menu-panel .menu-item { font-size: var(--t-md); }
.help-tip-button { font-size: var(--t-xs); font-weight: 700; line-height: 1; }
.label-block-buttons .btn span { font-size: var(--t-lg); }
.rail-tool, .rail-edge { font-size: var(--t-md); }
.rail-tool.on { font-weight: 600; }
.rail-tool > .glyph { font-size: var(--t-lg); }
.rail-edge > .muted { font-size: var(--t-sm); }
.ed-alert .link { font-size: var(--t-md); }
.feature-list .link { font-size: var(--t-md); }
.issue-indicator { font-weight:700; }
.issue-toast .btn { font-size:.75rem; }
.issue-indicator { font:inherit; font-weight:700; line-height:16px; }
.issue-status .toast-close { font:inherit; line-height:14px; }

/* Compact control contexts retain app typography and the original drawing floor.
   Unframed command rows use their parent gap as vertical clearance; surface
   gutters remain 8px at the actual header/panel/map frames. */
html .project-shell.project-shell :is(.project-titlebar,.header-status,.map-toolbar,.map-context,.result-compare-action) { --button-h:var(--ctl-h-sm); --button-pad:8px; --button-pad-y:1px; --button-gap:4px; }
html .project-shell.project-shell .btn.icon.rail-toggle { min-width:0; }
html .project-shell.project-shell :is(.header-status,.header-status .toast,.header-status .issue-status,.toast-close,.issue-indicator) { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }
html .project-shell.project-shell :is(.map-toolbar,.map-context) { padding-block:0; }
html .project-shell.project-shell :is(.map-toolbar,.map-context) :is(.btn,select) { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .map-context { min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .map-inspector { gap:var(--ctl-gap); }

/* Card contents are one command, so their internal rows need no control gutter.
   Compact cards keep the source text/icon sizes and a constant Fluent1px stroke. */
@media(max-width:1100px) {
 html .project-shell.project-shell .result-support .strategies > button { padding-block:0; border-width:1px; row-gap:0; }
 html .project-shell.project-shell .result-support .strategies .name { min-height:20px; }
 html .project-shell.project-shell .map-part { row-gap:0; }
}
html .project-shell.project-shell .result-support { row-gap:0; }

html .project-shell.project-shell .project-titlebar select { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }

/* Fixed small feedback slot: toast lifetime and dialogs cannot resize the
   work surface. The title field and feedback commands form one toolbar group. */
html .project-shell.project-shell .project-title { gap:var(--sp-2); }
@media(max-width:1100px) {
 html .project-shell.project-shell .metrics-only dd { line-height:1; }
 html .project-shell.project-shell .metrics-only dt { line-height:12px; }
}

/* The calculation commands form one toolbar group (Fluent small inner gap). */
html .project-shell.project-shell .context-calculation { gap:var(--sp-2); }

@media(max-width:1100px) {
 html .project-shell.project-shell .metrics-only .result-metrics > div { padding-block:0; }
 html .project-shell.project-shell .strategies .variant-metric b { line-height:1; }
}

@media(max-width:1100px) { html .project-shell.project-shell .map-part { line-height:var(--compact-map-line); } }

/* The persistent operation context is a small toolbar, including its fields/tabs. */
html .project-shell.project-shell .operation-context { --button-h:var(--ctl-h-sm); --button-pad:8px; --button-pad-y:1px; --button-gap:4px; }
html .project-shell.project-shell .operation-context :is(select,.btn,.seg) { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .operation-tabs { min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .map-identity h4 { line-height:13px; }
html .project-shell.project-shell .map-material-name { line-height:11px; }

/* The existing map footer keeps its text-row footprint when a part is selected. */
html .project-shell.project-shell .map-context { min-height:var(--ctl-h); }
@media(max-width:1100px) { html .project-shell.project-shell .map-context { min-height:calc(2 * var(--compact-map-line)); } }

/* ShortRail650:14 commands at32px plus8px group gaps overflow the563px
   native client. Below650px use the library small context instead of hiding
   commands or changing the navigation layout (paired f518 native evidence). */
@media(max-height:650px) {
 html .project-shell.project-shell .project-rail { --button-h:var(--ctl-h-sm); --button-pad-y:1px; --button-gap:4px; }
 html .project-shell.project-shell.rail-hidden .rail-action { width:var(--ctl-h-sm); min-width:var(--ctl-h-sm); }
}


@media(max-width:1100px) { html .project-shell.project-shell .strategies .variant-metric .rank-mark { line-height:1; } }

/* Labelled menu/material summaries are button controls too; keep native selectors. */
html .project-shell.project-shell summary[aria-label] { gap:var(--button-gap); border-radius:var(--fluent-radius); }
html .project-shell.project-shell summary[aria-label]:not(.icon):not(.navigator-operation-menu) { padding:var(--button-pad-y) var(--button-pad); }
html .project-shell.project-shell .cs-machine-menu > summary { width:var(--button-h); min-width:var(--button-h); padding:var(--button-pad-y); }
html .project-shell.project-shell .cs-machine-menu > summary .ui-icon { width:var(--button-icon); height:var(--button-icon); }
html .project-shell.project-shell .operation-context summary[aria-label] { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .operation-context .material-facts > span { padding-inline-start:0; border:0; }
@media(max-width:1100px) { html .project-shell.project-shell .result-support .strategies .name { line-height:1; } }

/* Planner resume2: preserve f518 intrinsic widths in the dense existing
   contexts. These app insets take precedence over the library's8px default;
   text size/weight,24px height,4px radius and Fluent states stay unchanged.
   Basis: paired1010x563 inventory, resume2-f518-browser/narrow-map.json. */
html .project-shell.project-shell .operation-tabs .seg { padding-inline:var(--sp-1); border-inline-width:0; }
html .project-shell.project-shell .project-titlebar .btn.icon.rail-toggle { padding-inline:var(--sp-3); }
html .project-shell.project-shell .map-toolbar { --button-pad:var(--sp-2); }
html .project-shell.project-shell .link { padding:0; border-width:0; }

/* Standalone size aliases; app/dialog/menu contexts remain the size authority. */
.btn.sm { --button-h:var(--ctl-h-sm); --button-pad:8px; --button-pad-y:3px; --button-gap:4px; }
.btn.sm:has(.ui-icon) { --button-pad-y:1px; }
html :is(.project-shell,[role=dialog],.workspace-dialog,[data-popup-active]) .btn.sm { --button-h:inherit; --button-pad:inherit; --button-pad-y:inherit; --button-gap:inherit; }
html .btn[aria-busy=true]:disabled { cursor:progress; }

/* A floating notification owns its frame; its small actions need the same
   surface gutter as every panel. Height follows24px controls + two8px gutters. */
html .project-shell.project-shell .issue-toast { height:auto; min-height:calc(var(--ctl-h-sm) + 2 * var(--ctl-gap) + 2px); padding:var(--ctl-gap); gap:var(--ctl-gap); --button-h:var(--ctl-h-sm); --button-pad:8px; --button-pad-y:1px; --button-gap:4px; }
html .project-shell.project-shell .issue-toast .btn { --button-ink:var(--text); --button-hover-ink:var(--text); --button-hover:var(--panel-2); --button-pressed:var(--panel-3); }
/* The fixed indicator is anchored to its own24px slot, rather than a16px
   baseline shim that lowered it towards the workspace tabs. */

/* Existing compact command/card rows: shared separation, no new wrapping mode. */
html .project-shell.project-shell .context-material,
html .project-shell.project-shell .result-support .strategies { gap:var(--ctl-gap); }

html .project-shell.project-shell :is(.parts-grid,.edge-table,.data-table,.cnc-drill-table,.project-navigator table,.linear-table table,.groove-table table,.general-operation table,.cnc-table-scroll table) td :is(input:not([type=checkbox]):not([type=radio]),select) { height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); padding-block:var(--sp-1); box-sizing:border-box; }
html .project-shell.project-shell td .format-row-actions { gap:var(--sp-2); }

/* The existing search fits the wide selection row; restore it after clear on compact views. */
@media(max-width:1100px) { html .project-shell.project-shell .part-command-row.bulk-action-bar .table-search { display:none; } }
/* Owner15.10: one small Fluent field contract. Padding is horizontal so the
   retained app font always fits the client height. Table editors retain their slots. */
html .project-shell.project-shell :is(input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),select,[role=combobox]) {
    box-sizing:border-box; min-height:24px; padding-block:0; line-height:1.2;
    background:var(--panel); color:var(--text); border-color:var(--field-border); border-radius:var(--fluent-radius);
}
html .project-shell.project-shell input::placeholder,html .project-shell.project-shell textarea::placeholder { color:var(--muted); opacity:1; }
html .project-shell.project-shell .navigator-tools input { background:var(--panel); height:24px; flex:0 0 150px; }
html .project-shell.project-shell .navigator-actions { flex:none; }
html .project-shell.project-shell .navigator-actions > button { flex:none; width:auto; min-width:max-content; white-space:nowrap; }
html .project-shell.project-shell .navigator-tools { flex-wrap:nowrap; }
html .project-shell.project-shell .context-product { flex:none; width:auto; max-width:none; margin-left:0; gap:var(--ctl-gap); }
html .project-shell.project-shell .context-product select { field-sizing:content; width:auto; max-width:260px; min-width:100px; height:24px; text-overflow:ellipsis; }
html .project-shell.project-shell .context-calculation { display:flex; align-items:center; gap:var(--ctl-gap); flex-wrap:wrap; }
html .project-shell.project-shell .project-titlebar { flex-wrap:nowrap; align-items:center; min-height:44px; }
@media(max-width:1050px) {
    /* Global views also expose calculation commands while an order is open. */
    html .project-shell.project-shell:not(.technologist-workspace) .project-titlebar { flex-wrap:wrap; }
}
html .project-shell.project-shell .project-title { display:flex; flex-direction:row; align-items:center; min-width:0; gap:var(--ctl-gap); }
html .project-shell.project-shell .project-name-input { flex:0 1 auto; field-sizing:content; width:auto; min-width:0; max-width:100%; height:32px; background:transparent; color:var(--header-text); border-color:transparent; text-overflow:ellipsis; }
html .project-shell.project-shell .project-name-input:is(:hover,:focus) { border-color:var(--header-muted); }
html .project-shell.project-shell .header-status { flex:none; }
html .project-shell.project-shell .project-save-state { min-inline-size:0; max-width:26ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* One TabList paint contract; identity/selection never changes its geometry. */
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) { background:transparent; border-radius:var(--r-none); }
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) > :is(button,.seg) {
    position:relative; background:transparent; border-color:transparent; box-shadow:none; color:var(--muted); --button-bg:transparent; --button-stroke:transparent; --button-ink:var(--muted); border-radius:var(--r-none);
}
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) > :is(button,.seg)::after {
    content:""; position:absolute; height:3px; border-radius:var(--r-full); inset:auto 8px 0; background:transparent;
}
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) > :is(button,.seg):hover::after { background:var(--accent-soft); }
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) > :is(button,.seg):is(.active,.on,[aria-selected=true],[aria-current=page]) { color:var(--text); --button-ink:var(--text); font-weight:600; background:transparent; box-shadow:none; }
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.dialog-tabs,.navigator-modes) > :is(button,.seg):is(.active,.on,[aria-selected=true],[aria-current=page])::after { background:var(--selection-edge); }
/* Philosophy identity only. Owner-supplied colours, never metric rankings. */
:root { --ph-balanced:#3f6db3; --ph-offcuts:#1f8a7e; --ph-handling:#7656c4; --ph-speed:#a8770f; --ph-material:#a64d79; --ph-tint:12%; }
:root[data-theme=dark] { --ph-balanced:#8fb1ea; --ph-offcuts:#5fcabd; --ph-handling:#b49cf0; --ph-speed:#e3b04f; --ph-material:#e08ab1; --ph-tint:22%; }
[data-philosophy=Balanced] { --philosophy:var(--ph-balanced); }
[data-philosophy=FewestOffcuts] { --philosophy:var(--ph-offcuts); }
[data-philosophy=EasiestHandling] { --philosophy:var(--ph-handling); }
[data-philosophy=FastestProduction] { --philosophy:var(--ph-speed); }
[data-philosophy=LowestMaterialCost] { --philosophy:var(--ph-material); }
html .project-shell.project-shell .strategy .variant-symbol { color:var(--philosophy); }
html .project-shell.project-shell .result-support .strategy[aria-pressed=true] { background:color-mix(in srgb,var(--philosophy) var(--ph-tint),var(--panel)); border-color:transparent; box-shadow:inset 0 0 0 2px var(--philosophy); color:var(--text); }
html .project-shell.project-shell .result-support .strategy[aria-pressed=true]::before { display:none; }
html .project-shell.project-shell .result-support .strategy[aria-pressed=true] .name { font-weight:600; color:var(--text); }
.philosophy-chip { display:inline-flex; align-items:center; gap:var(--sp-2); color:var(--text); }
.philosophy-dot { display:inline-block; flex:none; width:8px; height:8px; border-radius:var(--r-full); background:var(--philosophy); }
/* Compact forms share row pitch and field geometry, not smaller typography. */
html .project-shell.project-shell :is(.cs-operation-context,.groove-parameters,.edge-parameters,.machine-settings-form,.general-operation,.machining-parameters) { --form-field-height:24px; --form-row-gap:var(--sp-2); }
html .project-shell.project-shell :is(.parameter-fields,.field-grid,.material-fields) { row-gap:var(--form-row-gap,var(--sp-4)); align-items:center; }
html .project-shell.project-shell :is(.cs-operation-context,.groove-parameters,.edge-parameters,.machine-settings-form,.general-operation,.machining-parameters) :is(input:not([type=checkbox]):not([type=radio]),select,.inline-parameter) { height:24px; min-height:24px; padding-block:0; }
html .project-shell.project-shell :is(.cs-operation-context,.groove-parameters,.edge-parameters,.machine-settings-form,.general-operation,.machining-parameters) input:is([inputmode=decimal],[type=number]) { width:88px; justify-self:end; text-align:right; }
html .project-shell.project-shell .cs-operation-context { container-type:inline-size; --button-h:var(--ctl-h-sm); --button-pad:var(--ctl-gap); --button-pad-y:var(--sp-0_5); --button-gap:var(--sp-2); }
html .project-shell.project-shell .cs-parameters-layout:not(.compact) { display:grid; grid-template-columns:minmax(0,1fr); gap:var(--sp-6); align-items:start; padding-block:var(--sp-2); }
html .project-shell.project-shell .cs-material-column { display:block; }
html .project-shell.project-shell .cs-cutting-column { display:block; }
html .project-shell.project-shell .cs-parameters-layout :is(h2,h3,summary) { text-align:left; margin-block:var(--sp-2); padding-block:0; min-height:24px; }
html .project-shell.project-shell .cs-parameters-layout :is(.parameter-fields,.field-grid) { grid-template-columns:minmax(0,1fr) minmax(88px,160px) 24px; row-gap:var(--sp-2); }
html .project-shell.project-shell .cs-parameters-layout :is(form,.disclosure-body,.package-settings) { margin:0; padding-block:var(--sp-1); }
html .project-shell.project-shell .cs-cutting-column > form { gap:var(--sp-2); }
html .project-shell.project-shell .cs-parameters-layout .parameter-check { min-height:24px; margin-block:var(--sp-2); }
html .project-shell.project-shell .cs-parameters-layout .help-tip-button { width:var(--ctl-h-sm); height:var(--ctl-h-sm); min-height:var(--ctl-h-sm); }
html .project-shell.project-shell .material-editor:not(.compact) .material-fields { gap:var(--sp-2); }
/* Fixed material labels leave the full field column to long supplier names;
   checked against the1010px Kronospan fixture in OwnerSecondReview. */
html .project-shell.project-shell .material-editor:not(.compact) { --material-label-width:120px; }
html .project-shell.project-shell .material-editor:not(.compact) .material-fields > label { display:grid; grid-template-columns:var(--material-label-width) minmax(88px,1fr) 24px; min-height:24px; gap:var(--sp-2); }
html .project-shell.project-shell .material-editor:not(.compact) .material-fields > .material-name { display:grid; align-items:center; grid-template-columns:var(--material-label-width) minmax(0,1fr); }
html .project-shell.project-shell .material-editor:not(.compact) .material-name input { grid-column:2; }
html .project-shell.project-shell .cs-parameters-layout .material-editor > summary { justify-content:flex-start; }
@container(min-width:1050px) { html .project-shell.project-shell .cs-parameters-layout:not(.compact) { grid-template-columns:repeat(2,minmax(0,1fr)); } html .project-shell.project-shell .cs-cost-column { grid-column:1; grid-row:2; } html .project-shell.project-shell .cs-cutting-column { grid-column:2; grid-row:1 / span 2; } }
@container(min-width:1400px) { html .project-shell.project-shell .cs-parameters-layout:not(.compact) { grid-template-columns:repeat(3,minmax(0,1fr)); } }
@container(min-width:1400px) { html .project-shell.project-shell .cs-cost-column { grid-column:2; grid-row:1; } html .project-shell.project-shell .cs-cutting-column { grid-column:3; grid-row:1; } }
/* Order scope has no selected material/cost columns; common saw settings start at the left. */
html .project-shell.project-shell .cs-parameters-layout.order-scope:not(.compact) { grid-template-columns:minmax(0,1fr); }
html .project-shell.project-shell .cs-parameters-layout.order-scope > :is(.cs-material-column,.cs-cost-column):empty { display:none; }
html .project-shell.project-shell .cs-parameters-layout.order-scope > .cs-cutting-column { grid-column:1; grid-row:auto; }
html .project-shell.project-shell .parameters-output :is(select,.btn) { height:24px; min-height:24px; }
html .project-shell.project-shell .cs-operation-context:not(.compact) { position:relative; }
html .project-shell.project-shell .cs-cutting-heading { display:flex; align-items:center; justify-content:space-between; gap:var(--ctl-gap); }
html .project-shell.project-shell .cs-cutting-heading .cs-machine-menu { margin:0; }
html .project-shell.project-shell .cs-cutting-column > .machine-output { flex-wrap:nowrap; margin-block:var(--sp-2); }
html .project-shell.project-shell .cs-cutting-column > .machine-output label { flex:1; }
html .project-shell.project-shell .cs-cutting-column > .machine-output select { width:100%; max-width:none; flex:1; }
html .project-shell.project-shell .cs-machine-settings { margin-bottom:var(--ctl-gap); }
/* Owner16.10: native before-click frames continued past125ms because the100ms
   Fluent hover/pressed paint restarted on controls revealed under the pointer.
   Disclosures and commands paint immediately; no geometry or pressed animation. */
html .project-shell.project-shell :is(button,summary,[role=button],.project-rail),
html .project-shell.project-shell :is(button,summary,[role=button])::before,
html .project-shell.project-shell :is(button,summary,[role=button])::after { transition:none; }
html .project-shell.project-shell summary:active { background:var(--button-pressed,var(--panel-3)); }
html .project-shell.project-shell .cs-parameters-layout h3 { margin-block:var(--sp-2); padding-block:0; }
html .project-shell.project-shell .cs-parameters-layout .material-editor:not(.compact) > summary { justify-content:flex-start; min-height:24px; margin:0; }
html .project-shell.project-shell .cs-parameters-layout .material-editor:not(.compact) form { padding-block:var(--sp-1); }
html .project-shell.project-shell .cs-parameters-layout :is(h2,h3) { min-height:20px; margin-block:var(--sp-1); }
html .project-shell.project-shell .cs-inline-costs > .field-help { grid-column:1 / -1; }
html .project-shell.project-shell .project-titlebar .project-title input.project-name-input[aria-label] { background:transparent; color:var(--header-text); border-color:transparent; }
html .project-shell.project-shell .project-titlebar .project-title input.project-name-input[aria-label]:is(:hover,:focus) { border-color:var(--header-muted); }
html .project-shell.project-shell .navigator-actions [hidden] { display:none; }
html .project-shell.project-shell :is(.edge-settings-panel,.machining-costs,.cnc-settings) { --form-row-gap:var(--sp-2); }
html .project-shell.project-shell :is(.edge-settings-panel,.machining-costs,.cnc-settings) :is(input:not([type=checkbox]):not([type=radio]),select) { height:24px; min-height:24px; padding-block:0; }
html .project-shell.project-shell :is(.edge-workspace-grid,.machining-rate-grid) { gap:var(--sp-6); }
html .project-shell.project-shell .project-titlebar .project-title input.project-name-input[aria-label] { height:24px; }
html .project-shell.project-shell .header-status :is(.issue-status,.issue-indicator) { height:24px; min-height:24px; }
html .project-shell.project-shell .status-toast { --notice-preferred-width:55ch; position:fixed; z-index:var(--z-toast); display:flex; align-items:center; gap:var(--sp-4); min-height:40px; max-width:min(var(--notice-preferred-width),calc(100vw - 32px)); padding:var(--sp-4); border:1px solid var(--border); border-radius:var(--fluent-radius); background:var(--panel); color:var(--text); box-shadow:var(--sh-popover); transform:none; animation:none; }
html .project-shell.project-shell .status-toast .toast-text { overflow:visible; text-overflow:clip; white-space:normal; overflow-wrap:anywhere; }
html .project-shell.project-shell .status-toast .toast-close { flex:none; height:24px; min-height:24px; padding:0; color:var(--text); --button-ink:var(--text); --button-hover-ink:var(--text); --button-hover:var(--panel-2); }
html.modal-open .status-toast,html:has(.planning-screen) .status-toast { visibility:hidden; pointer-events:none; }
html .project-shell.project-shell .cs-parameters-layout .material-editor:not(.compact) form { padding-top:var(--sp-4); }
html .project-shell.project-shell .cs-parameters-layout .cs-cutting-column { display:block; }
html .project-shell.project-shell .cs-parameters-layout .cs-cutting-column > form { gap:var(--sp-2); margin-top:var(--sp-2); }
html .project-shell.project-shell :is(.edge-settings-panel,.machining-costs,.cnc-settings) input[type=number] { width:88px; justify-self:end; text-align:right; }
html .project-shell.project-shell .machining-rates label { display:grid; grid-template-columns:minmax(0,1fr) 88px; align-items:center; gap:var(--sp-2); }
html .project-shell.project-shell :is(.machine-settings-form,.cnc-settings) .rack-actions { --button-h:var(--ctl-h-sm); --button-pad-y:var(--sp-0_5); }
html .project-shell.project-shell :is([role=tablist],.segmented,.operation-tabs,.navigator-modes) > button { flex:none; white-space:nowrap; }

/* Error and status notifications share a chrome-safe corner; the title issue pill stays clickable. */
html .project-shell.project-shell :is(.issue-toast,.status-toast) { inset:auto var(--sp-8) var(--sp-8) auto; }
