/* KerfMate styles: "Workshop Slate" (DECISIONS.md, Phase 3).
   Colours are variables; dark mode follows the device unless the user picks one. */

:root {
  --font: system-ui, -apple-system, 'Segoe UI', Roboto, 'Noto Sans', 'Noto Sans Sinhala', 'Noto Sans Tamil', sans-serif;
  --bg: #f4f5f7; --surface: #ffffff; --surface-2: #f8f9fb; --fg: #1d2430; --muted: #5b6573; --line: #dde1e7;
  --bar: #243041; --bar-fg: #f2f4f7; --chip: #36455b;
  --primary: #2f5d8a; --primary-hover: #264d73; --on-primary: #fff;
  --accent: #d98e2b; --on-accent: #1d2430;
  --tag: #e9eef5; --tag-fg: #2f5d8a;
  --ok-bg: #e8f5ec; --ok-fg: #1e6b3a; --warn-bg: #fff4e0; --warn-fg: #7a4a00; --err-bg: #fdeceb; --err-fg: #a12a1f;
  --part: #e2c79d; --part-line: #8a6a3a; --board: #faf6ee; --trim: #d9dce2; --free: #faf6ee;
  --focus: #9a5b0f; --accent-text: #9a5b0f;   /* darker amber for text and focus rings (AA contrast) */
  --radius: 10px;
  --tap: 44px;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #12161d; --surface: #1b212b; --surface-2: #171c25; --fg: #e8ecf1; --muted: #9aa5b4; --line: #2c3542;
    --bar: #0c1016; --chip: #243041; --primary: #7fb0e0; --primary-hover: #9cc3ea; --on-primary: #0c1016;
    --accent: #e3a04a; --accent-text: #e3a04a; --focus: #e3a04a; --tag: #243041; --tag-fg: #a9c9ea;
    --ok-bg: #16301f; --ok-fg: #9adbb0; --warn-bg: #3a2a10; --warn-fg: #ffd08a; --err-bg: #3a1714; --err-fg: #ffb4ab;
    --part: #735634; --part-line: #e2c79d; --board: #262019; --trim: #353b45; --free: #262019;
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --bg: #12161d; --surface: #1b212b; --surface-2: #171c25; --fg: #e8ecf1; --muted: #9aa5b4; --line: #2c3542;
  --bar: #0c1016; --chip: #243041; --primary: #7fb0e0; --primary-hover: #9cc3ea; --on-primary: #0c1016;
  --accent: #e3a04a; --accent-text: #e3a04a; --focus: #e3a04a; --tag: #243041; --tag-fg: #a9c9ea;
  --ok-bg: #16301f; --ok-fg: #9adbb0; --warn-bg: #3a2a10; --warn-fg: #ffd08a; --err-bg: #3a1714; --err-fg: #ffb4ab;
  --part: #735634; --part-line: #e2c79d; --board: #262019; --trim: #353b45; --free: #262019;
  color-scheme: dark;
}
/* Scripts that need more line height (Phase 6 sets lang on <html>). */
:root:lang(si), :root:lang(ta), :root:lang(hi) { --lh: 1.7; }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 16px/var(--lh, 1.5) var(--font);
  padding-bottom: env(safe-area-inset-bottom);
}
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; scroll-behavior: auto !important; } }

.ico { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ---------------------------------------------------------------- top bar and tabs */
.topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 10px;
  padding: 8px max(12px, env(safe-area-inset-left)); padding-top: max(8px, env(safe-area-inset-top));
  background: var(--bar); color: var(--bar-fg);
}
.logo { width: 32px; height: 32px; border-radius: 8px; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; flex: none; }
.brand { font-weight: 700; font-size: 18px; white-space: nowrap; }
.project-name {
  flex: 1; min-width: 0; max-width: 360px; background: transparent; border: 1px solid transparent; border-radius: 8px;
  color: var(--bar-fg); padding: 6px 8px; min-height: 40px;
}
.project-name::placeholder { color: #b7c0cc; }
.project-name:hover, .project-name:focus { border-color: #4a5a71; background: rgba(255,255,255,.06); }
.chip { font-size: 13px; padding: 4px 10px; border-radius: 99px; background: var(--chip); white-space: nowrap; }
.topbar .spacer { flex: 1; }
.iconbtn {
  min-width: var(--tap); min-height: var(--tap); display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 0; background: transparent; color: inherit; border-radius: 8px; cursor: pointer; padding: 0 8px;
}
.iconbtn:hover { background: rgba(127,127,127,.15); }

.tabs { position: sticky; top: 56px; z-index: 15; display: flex; background: var(--surface); border-bottom: 1px solid var(--line); }
.tabs button {
  flex: 1; min-height: 48px; border: 0; background: transparent; font-weight: 600; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.tabs button[aria-selected="true"] { color: var(--primary); box-shadow: inset 0 -3px 0 var(--primary); }
.tabs .count { font-size: 12px; background: var(--tag); color: var(--tag-fg); border-radius: 99px; padding: 1px 7px; }

/* ---------------------------------------------------------------- layout */
.work { max-width: 1600px; margin: 0 auto; padding: 12px max(12px, env(safe-area-inset-left)) 96px; display: grid; gap: 12px; }
.pane { display: grid; gap: 12px; align-content: start; min-width: 0; }
/* Phones and tablets: one pane at a time (tabs). */
.work[data-tab="sheets"] #pane-parts, .work[data-tab="sheets"] #pane-results,
.work[data-tab="parts"] #pane-sheets, .work[data-tab="parts"] #pane-results,
.work[data-tab="results"] #pane-sheets, .work[data-tab="results"] #pane-parts { display: none; }
/* Computers: inputs left, results right. */
@media (min-width: 1024px) {
  .tabs { display: none; }
  /* Inputs get most of the width (the parts grid needs it); results keep a steady column. */
  .work { grid-template-columns: minmax(0, 1fr) clamp(340px, 30vw, 540px); grid-template-rows: auto auto auto 1fr; align-items: start; padding-bottom: 24px; }
  .work #pane-parts, .work #pane-results { display: grid !important; }
  /* Left column order: sheet types, then parts, then "More options" (so it never pushes the parts down).
     The Sheets panel's two blocks become separate grid items for this. */
  .work #pane-sheets { display: contents !important; }
  #pane-sheets > .sheets-card { grid-column: 1; grid-row: 1; }
  #pane-sheets > .basics-card { grid-column: 1; grid-row: 2; }
  #pane-parts { grid-column: 1; grid-row: 3; }
  #pane-sheets > details.more { grid-column: 1; grid-row: 4; }
  #pane-results { grid-column: 2; grid-row: 1 / span 4; position: sticky; top: 68px; max-height: calc(100vh - 80px); overflow: auto; padding-right: 2px; }
  /* One line per sheet type. */
  .stock-grid { grid-template-columns: minmax(150px, 2fr) repeat(5, minmax(70px, 1fr)) auto !important; }
  .stock-grid .stock-remove { display: inline-flex; align-self: end; }
  .sheets-card .stock-actions:not(:has(input)) { display: none; }
  .stock-grid .field.full { grid-column: auto; }
  /* A little tighter so the basic grid fits without sideways scrolling at 1280 px. */
  .work table.grid td.c-name { min-width: 120px; }
  .work table.grid td.c-cut { min-width: 84px; }
}
/* When the parts grid does scroll sideways, the row number and name stay in view. */
table.grid .rownum, table.grid .c-name { position: sticky; background: var(--surface); z-index: 1; }
table.grid .rownum { left: 0; }
table.grid .c-name { left: 28px; }
table.grid thead th:nth-child(-n+2) { position: sticky; background: var(--surface); z-index: 1; }
table.grid thead th:first-child { left: 0; }
table.grid thead th:nth-child(2) { left: 28px; }

/* ---------------------------------------------------------------- cards and controls */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; min-width: 0; }
.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.card-head h2 { font-size: 15px; margin: 0; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); flex: 1; }
.btn {
  min-height: var(--tap); padding: 0 14px; border-radius: 8px; border: 1px solid var(--line); background: var(--surface);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 6px; font-weight: 500; text-decoration: none; color: var(--fg);
}
.btn:hover { border-color: var(--muted); }
.btn.primary { background: var(--primary); color: var(--on-primary); border-color: var(--primary); font-weight: 600; }
.btn.primary:hover { background: var(--primary-hover); }
.btn.accent { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 700; }
.btn.accent:hover { filter: brightness(1.06); }
.btn.link { border: 0; background: transparent; color: var(--primary); padding: 0 6px; font-weight: 600; }
.btn.danger { color: var(--err-fg); }
.btn.big { min-height: 52px; font-size: 17px; width: 100%; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* "Continue with Google / Facebook": the colours their brand rules ask for, in light and dark mode. */
.btn.social { gap: 12px; font-weight: 600; font-size: 16px; }
.btn.social svg { flex: none; }
.btn.google { background: #fff; color: #1f1f1f; border-color: #747775; }
.btn.google:hover { background: #f2f2f2; border-color: #747775; }
.btn.facebook { background: #1877f2; color: #fff; border-color: #1877f2; }
.btn.facebook:hover { background: #166fe5; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn.google { background: #131314; color: #e3e3e3; border-color: #8e918f; }
}
:root[data-theme="dark"] .btn.google { background: #131314; color: #e3e3e3; border-color: #8e918f; }
.row-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.muted { color: var(--muted); }
.small { font-size: 14px; }
.num { font-variant-numeric: tabular-nums; }

input.cell, select.cell {
  width: 100%; min-height: 40px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-2);
}
input.cell:focus, select.cell:focus { background: var(--surface); border-color: var(--primary); outline: none; box-shadow: 0 0 0 2px var(--primary); }
input.cell.bad { border-color: var(--err-fg); background: var(--err-bg); }
input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--primary); }
label.field { display: grid; gap: 4px; font-size: 14px; color: var(--muted); }
label.field > input, label.field > select { color: var(--fg); font-size: 16px; }
.check { display: inline-flex; align-items: center; gap: 8px; min-height: var(--tap); cursor: pointer; }

/* Editable tables (sheets grid, parts grid, offcuts). They scroll inside their own box. */
.table-wrap { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
table.grid { width: 100%; border-collapse: separate; border-spacing: 0 4px; min-width: 560px; }
table.grid th { text-align: left; font-size: 13px; font-weight: 600; color: var(--muted); padding: 0 4px; white-space: nowrap; }
table.grid td { padding: 0 2px; vertical-align: middle; }
table.grid td.act { width: 1%; white-space: nowrap; }
table.grid .w-num { width: 88px; }
table.grid .w-qty { width: 64px; }
table.grid .rownum { width: 28px; color: var(--muted); font-size: 13px; text-align: right; padding-right: 6px; }

/* Parts as cards (narrow screens). */
.pcards { display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr); }   /* a long part name is cut with "…", it never widens the page */
.pcard { display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); min-height: 56px; cursor: pointer; text-align: left; width: 100%; }
.pcard .main { flex: 1; min-width: 0; }
.pcard .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pcard .meta { font-size: 14px; color: var(--muted); }
.pcard.bad { border-color: var(--err-fg); }

.form-grid { display: grid; gap: 12px; grid-template-columns: 1fr 1fr; }
.form-grid .full { grid-column: 1 / -1; }

.empty { text-align: center; padding: 20px 12px; color: var(--muted); display: grid; gap: 10px; justify-items: center; }
.empty strong { color: var(--fg); font-size: 17px; }

/* More options */
details.more { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
details.more > summary { list-style: none; cursor: pointer; min-height: var(--tap); padding: 10px 12px; display: flex; align-items: center; gap: 8px; font-weight: 600; }
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary .ico { transition: transform .15s; }
details.more[open] > summary .ico { transform: rotate(90deg); }
details.more .body { padding: 4px 12px 14px; display: grid; gap: 14px; }
/* "More options": grouped settings rows (label left, compact control right). */
.set-groups { display: grid; gap: 14px 24px; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); align-items: start; }
.set-group h3 { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; margin: 0 0 2px; }
.set-row { border-bottom: 1px solid var(--line); padding: 4px 0; }
.set-group .set-row:last-child { border-bottom: 0; }
.set-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: var(--tap); }
.set-label { flex: 1 1 120px; min-width: 0; display: flex; align-items: center; gap: 8px; }
.set-label label { cursor: pointer; }
.set-row .help-text { margin: 4px 0 6px; }
.set-num { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.set-num input.cell { width: 88px; text-align: right; }
.set-num .unit { color: var(--muted); font-size: 13px; min-width: 2.2em; }
select.set-select { width: auto; max-width: 100%; flex: none; margin-left: auto; }
input.set-text { width: 88px; flex: none; text-transform: uppercase; }
input.switch { appearance: none; -webkit-appearance: none; flex: none; width: 46px; height: 28px; border-radius: 14px; background: var(--line); position: relative; cursor: pointer; margin: 0; transition: background .15s; }
input.switch::after { content: ''; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: left .15s; }
input.switch:checked { background: var(--primary); }
input.switch:checked::after { left: 21px; }
input.switch:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.set-line > input.switch { order: 2; }
.tape-cards { display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); margin: 6px 0 4px; }
.tape-card { border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); padding: 8px; display: grid; gap: 6px; }
.tape-top { display: flex; gap: 6px; align-items: center; }
.tape-fields { display: grid; gap: 8px; grid-template-columns: 1fr 1fr auto; align-items: end; }
.tape-default { min-height: 40px; }
.tape-field { display: grid; gap: 2px; font-size: 13px; color: var(--muted); }
.tape-field .set-num input.cell { width: 100%; color: var(--fg); }
.tape-field .set-num { display: flex; }
.help-btn { min-width: 28px; min-height: 28px; border-radius: 50%; border: 1px solid var(--line); background: var(--surface); color: var(--muted); cursor: pointer; font-weight: 700; font-size: 13px; padding: 0; position: relative; }
.help-btn::after { content: ''; position: absolute; inset: -8px; }   /* a bigger invisible touch area */
.help-text { font-size: 14px; color: var(--muted); background: var(--surface-2); border-radius: 6px; padding: 8px 10px; margin: 0; }
.changed-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); margin-left: 4px; }

/* Run bar: sticky at the bottom on phones. */
.runbar { display: grid; gap: 8px; }
@media (max-width: 1023.98px) {
  .runbar.floating { position: fixed; left: 0; right: 0; bottom: 0; z-index: 18; padding: 10px max(12px, env(safe-area-inset-left)) max(10px, env(safe-area-inset-bottom));
                     background: var(--surface); border-top: 1px solid var(--line); box-shadow: 0 -4px 12px rgba(0,0,0,.08); }
}
.progress { height: 8px; border-radius: 4px; background: var(--line); overflow: hidden; }
.progress > div { height: 100%; width: 0; background: var(--accent); transition: width .2s; }

/* ---------------------------------------------------------------- results */
.alert { padding: 10px 12px; border-radius: 8px; font-size: 15px; display: grid; gap: 4px; }
.alert.warn { background: var(--warn-bg); color: var(--warn-fg); }
.alert.err { background: var(--err-bg); color: var(--err-fg); }
.alert.ok { background: var(--ok-bg); color: var(--ok-fg); }
.alert ul { margin: 0; padding-left: 18px; }
.stats { display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; }
.stat b { display: block; font-size: 22px; font-variant-numeric: tabular-nums; line-height: 1.2; }
.stat small { color: var(--muted); font-size: 13px; }
/* Totals from a plan that is out of date or leaves pieces out: still readable, clearly not final. */
.stats.doubtful .stat, .card.doubtful { background: repeating-linear-gradient(135deg, var(--surface), var(--surface) 10px, var(--surface-2) 10px, var(--surface-2) 20px); }
.stats.doubtful .stat b { color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }
table.grid tr.bad .rownum { background: var(--err-bg); color: var(--err-fg); font-weight: 700; }
table.list { width: 100%; border-collapse: collapse; font-size: 15px; }
table.list th, table.list td { text-align: left; padding: 8px 6px; border-top: 1px solid var(--line); vertical-align: top; }
table.list th { font-size: 13px; color: var(--muted); font-weight: 600; border-top: 0; }
table.list td.r, table.list th.r { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sheet-card { display: grid; gap: 10px; }
.sheet-card h3 { margin: 0; font-size: 17px; display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.sheet-card h3 .muted { font-size: 14px; font-weight: 400; }
.badge { font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 99px; background: var(--tag); color: var(--tag-fg); white-space: nowrap; display: inline-block; }
.badge.warn { background: var(--warn-bg); color: var(--warn-fg); }
.diagram { width: 100%; height: auto; display: block; touch-action: pinch-zoom; }
.diagram .board { fill: var(--board); }
.diagram .trim { fill: var(--trim); }
.diagram .free { fill: var(--free); }
.diagram .part { fill: var(--part); stroke: var(--part-line); }
.diagram .lbl { fill: var(--fg); font-family: var(--font); }
.diagram .grainline { stroke: var(--part-line); opacity: .25; }
.diagram .cut { stroke: var(--accent); }
.diagram .hl-piece { fill: var(--accent); fill-opacity: .3; stroke: var(--accent); stroke-opacity: .9; }
.diagram .done { opacity: .35; }
.diagram-wrap { overflow: auto; max-height: 75vh; border-radius: 6px; }
.diagram-wrap.zoomed .diagram { width: 200%; }
ol.steps { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
ol.steps li { display: flex; gap: 10px; align-items: flex-start; padding: 8px; border-radius: 8px; background: var(--surface-2); font-size: 15px; }
ol.steps .n { min-width: 30px; height: 30px; border-radius: 50%; background: var(--accent); color: var(--on-accent); display: grid; place-items: center; font-weight: 700; font-size: 14px; flex: none; }
ol.steps li.trim .n { background: var(--trim); color: var(--fg); }
details.sub > summary { cursor: pointer; min-height: var(--tap); display: flex; align-items: center; gap: 6px; font-weight: 600; color: var(--primary); list-style: none; }
details.sub > summary::-webkit-details-marker { display: none; }
.stale { position: sticky; top: 0; z-index: 2; }

/* ---------------------------------------------------------------- dialogs and toast */
dialog.dlg { border: 0; border-radius: 14px; padding: 0; width: min(560px, calc(100vw - 24px)); max-height: calc(100dvh - 24px); background: var(--surface); color: var(--fg); box-shadow: 0 10px 40px rgba(0,0,0,.3); }
dialog.dlg::backdrop { background: rgba(10,14,20,.55); }
.dlg-head { display: flex; align-items: center; gap: 8px; padding: 12px 12px 4px 16px; }
.dlg-head h2 { margin: 0; font-size: 18px; flex: 1; }
.dlg-body { padding: 8px 16px 16px; display: grid; gap: 12px; overflow: auto; }
.dlg-foot { display: flex; gap: 8px; justify-content: flex-end; padding: 0 16px 16px; flex-wrap: wrap; }
.dlg-foot .btn.left { margin-right: auto; }
@media (max-width: 599.98px) {
  dialog.dlg { width: 100vw; max-width: 100vw; margin: auto 0 0; border-radius: 14px 14px 0 0; padding-bottom: env(safe-area-inset-bottom); }
}
.menu-list { display: grid; gap: 2px; }
.menu-list a.btnlike { color: inherit; text-decoration: none; }
.menu-list button, .menu-list label.btnlike, .menu-list a.btnlike { justify-content: flex-start; width: 100%; border: 0; background: transparent; min-height: 48px; padding: 0 10px; border-radius: 8px; display: flex; align-items: center; gap: 10px; cursor: pointer; text-align: left; font-size: 16px; }
.menu-list button:hover, .menu-list label.btnlike:hover, .menu-list a.btnlike:hover { background: var(--surface-2); }
.menu-list hr { border: 0; border-top: 1px solid var(--line); margin: 4px 0; width: 100%; }
.toast { position: fixed; left: 50%; bottom: calc(90px + env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 60; background: var(--fg); color: var(--bg); padding: 10px 16px; border-radius: 8px; max-width: calc(100vw - 32px); font-size: 15px; }
.toast .btn.link { color: inherit; text-decoration: underline; padding-left: 0; padding-right: 0; }

/* ---------------------------------------------------------------- the edge sketch (ui/edgeSketch.js)
   The part with its taped edges thick in the main colour, untaped edges thin and dashed, the first
   size along the top edge and the second along the left edge. Drawn at its own pixel size and only
   made smaller to fit (never bigger), so the numbers stay readable. */
.esk { display: block; max-width: 100%; height: auto; overflow: visible; }
.esk-board { fill: var(--part); }
.esk-tape { stroke: var(--primary); stroke-linecap: square; }
.esk-bare { stroke: var(--muted); stroke-width: 1.5px; stroke-dasharray: 5 4; vector-effect: non-scaling-stroke; }
.esk-tiny .esk-bare { stroke-dasharray: 3 3; }
.esk-num { fill: var(--fg); font-family: var(--font); font-weight: 700; }
.esk-grain line { stroke: var(--part-line); stroke-width: 1.5px; opacity: .45; }
.esk-grain .esk-arrow { stroke-width: 2px; opacity: .9; }
.esk-head { fill: var(--part-line); opacity: .9; }
@media print { .esk-tape { stroke: #000; } .esk-num { fill: #000; } }

/* Edge picker: the choices around the sketch (top above, bottom below, left and right beside it). */
.edge-pick { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
  grid-template-areas: ". top ." "left shape right" ". bottom ."; gap: 8px; align-items: center; }
.edge-pick .top { grid-area: top; }
.edge-pick .left { grid-area: left; }
.edge-pick .shape { grid-area: shape; display: grid; place-items: center; min-width: 0; }
.edge-pick .right { grid-area: right; }
.edge-pick .bottom { grid-area: bottom; }
.edge-pick .field { min-width: 0; overflow-wrap: anywhere; }
/* Phones: the sketch gets the whole width; left and right go in a row under it. */
@media (max-width: 479.98px) {
  .edge-pick { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "top top" "shape shape" "left right" "bottom bottom"; }
}
/* The part form: the sketch under the tape choice. */
.form-sketch { display: grid; place-items: center; padding: 4px 0; }
.form-sketch .esk { max-height: 34vh; width: auto; }
/* Part cards: a small sketch for taped parts (in place of the tape name), always beside the text, so
   a card is no taller than one without tape. The sizes are on the card's first line already: on a
   narrow phone the sketch has no numbers (the tiny one), so the name keeps most of the width. */
.pcard-sketch { flex: none; display: block; }
.pcard-sketch .esk-tiny { display: none; }
@media (max-width: 479.98px) {
  .pcard-sketch .esk-small { display: none; }
  .pcard-sketch .esk-tiny { display: block; }
  /* The sketch above the ">" in one narrow column on the right, so the text keeps the width. */
  .pcard:has(.pcard-sketch) { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; row-gap: 6px; }
  .pcard:has(.pcard-sketch) .main { grid-row: 1 / span 2; }
  .pcard:has(.pcard-sketch) .pcard-sketch { grid-column: 2; align-self: end; }
  .pcard:has(.pcard-sketch) > svg.ico { grid-column: 2; justify-self: center; align-self: start; }
  /* Selecting: the tick box first, the sketch alone on the right (no ">"). */
  .pcard.selectable:has(.pcard-sketch) { grid-template-columns: auto minmax(0, 1fr) auto; }
  .pcard.selectable:has(.pcard-sketch) > input { grid-row: 1 / span 2; align-self: center; }
  .pcard.selectable:has(.pcard-sketch) .pcard-sketch { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
}
/* Parts grid: a tiny sketch button beside the tape choice. */
.tape-cell { display: flex; align-items: center; gap: 4px; }
.sketchbtn { flex: none; min-width: var(--tap); min-height: var(--tap); display: grid; place-items: center; padding: 2px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); cursor: pointer; }
.sketchbtn:hover { border-color: var(--primary); }
/* The marked part under a sheet drawing. */
.pick-sketch { flex: none; display: block; }

/* ---------------------------------------------------------------- cut mode */
.cutmode { position: fixed; inset: 0; z-index: 50; background: var(--bg); display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.cutmode .cm-top { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: var(--bar); color: var(--bar-fg); }
.cutmode .cm-top .title { flex: 1; min-width: 0; font-weight: 700; font-size: 18px; line-height: 1.3; }
.cutmode .cm-sheets { display: flex; justify-content: space-between; gap: 8px; padding: 0 8px; border-bottom: 1px solid var(--line); }
.cutmode .cm-sheets:empty { display: block; border: 0; padding: 0; }
.cutmode .cm-instr { padding: 12px 16px; display: grid; gap: 4px; }
.cutmode .cm-kind { font-size: 15px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--accent-text); }
.cutmode .cm-main { font-size: clamp(20px, 5vw, 30px); font-weight: 600; line-height: 1.25; font-variant-numeric: tabular-nums; }
.cutmode .cm-num { display: block; font-size: clamp(40px, 12vw, 64px); font-weight: 800; line-height: 1.05; }
.cutmode .cm-frees { font-size: 17px; font-weight: 600; color: var(--ok-fg); background: var(--ok-bg); border-radius: 6px; padding: 4px 8px; justify-self: start; }
.cutmode .cm-donecard { grid-row: 3 / span 2; align-content: start; overflow: auto; }
.cutmode .cm-next { font-size: 18px; font-weight: 700; margin-top: 6px; }
.diagram .edge-names text { fill: var(--muted); font-family: var(--font); }
.cutmode .cm-sub { font-size: 18px; color: var(--muted); }
.cutmode .cm-draw { min-height: 0; padding: 0 12px; display: grid; align-items: center; }
.cutmode .cm-draw svg { max-height: 100%; }
.cutmode .cm-nav { display: grid; grid-template-columns: 1fr 2fr; gap: 10px; padding: 12px 16px; }
.cutmode .cm-nav .btn { min-height: 64px; font-size: 20px; }
.cutmode .cm-count { font-size: 15px; color: var(--muted); }

/* ---------------------------------------------------------------- print */
#print-area { display: none; }
@media print {
  :root { color-scheme: light; --fg: #000; --muted: #333; --line: #bbb; --surface: #fff; --bg: #fff;
          --part: #eadbc2; --part-line: #6b5330; --board: #fff; --trim: #ddd; --free: #fff; --accent: #c77712; --tag: #eee; --tag-fg: #000; }
  /* overflow: cut mode hides the page's scrolling while open; printing must still get every page. */
  body { background: #fff; color: #000; padding: 0; overflow: visible !important; }
  body.print-labels > *:not(#print-area), body.print-sheets > *:not(#print-area) { display: none !important; }
  #print-area { display: block; }
  .sheet-print { break-inside: avoid; page-break-inside: avoid; margin-bottom: 8mm; }
  .sheet-print h2 { font-size: 14pt; margin: 0 0 3mm; }
  .sheet-print .diagram { max-height: 120mm; }
  .sheet-print ol.steps li { background: none; padding: 1mm 0; font-size: 10pt; }
  .sheet-print ol.steps .n { min-width: 7mm; height: 7mm; font-size: 9pt; background: #eee; color: #000; }
}
.label-page { display: grid; box-sizing: border-box; break-after: page; page-break-after: always; overflow: hidden; }
.label-page:last-child { break-after: auto; page-break-after: auto; }
/* One part label (ui/labels.js places the QR code, the text lines and the edge drawing in mm).
   Pure black on white: label printers print black dots only, and greys smear. */
.label { position: relative; box-sizing: border-box; overflow: hidden; color: #000; background: #fff; }
.label .ln { position: absolute; white-space: pre; color: #000; }
.label .qr, .label .edge { position: absolute; display: block; overflow: visible; }

/* The floating Optimize bar is only for phones/tablets; computers use the one in the results column. */
@media (min-width: 1024px) { .runbar.floating { display: none; } }
/* Cut mode drawing fills the free space and keeps its proportions. */
.cutmode .cm-draw { position: relative; }
.cutmode .cm-draw svg { position: absolute; inset: 0 12px; width: calc(100% - 24px); height: 100%; }
/* Parts grid: keep every column readable; the table scrolls inside its box when narrow. */
table.grid td.c-name { min-width: 150px; }
table.grid td.c-sel select { min-width: 120px; }
table.grid td.c-label { min-width: 120px; }
/* Hidden screen-reader labels stay inside their scroll box (no page-wide sideways scroll). */
.table-wrap { position: relative; }
table.grid td.w-qty { min-width: 60px; }
table.grid td.w-num { min-width: 84px; }
table.list tr.total td { font-weight: 700; font-size: 16px; }
/* Narrow phones: keep the top bar on one line. */
.chip-short { display: none; }
@media (max-width: 639.98px) {
  .chip-long { display: none; }
  .chip-short { display: inline; }
  .topbar { gap: 6px; }
}
.card-head .btn { flex: none; }
/* Grid children may shrink below their content, so wide tables scroll inside their box. */
.more .body > *, .pane > *, .dlg-body > * { min-width: 0; }
.table-wrap { max-width: 100%; }
/* (?) buttons look small but have a full 44 px touch area. */
table.grid td.c-cut { min-width: 96px; white-space: nowrap; padding: 0 6px; }
/* The status chip is a button: tap it for sign-in / save options. */
button.chip { border: 0; color: inherit; cursor: pointer; min-height: 36px; position: relative; font: inherit; font-size: 13px; }
button.chip::after { content: ''; position: absolute; inset: -4px; }
button.chip.warn { background: #7a4a00; }
button.chip.ok { background: #1e5a36; }

/* Sinhala, Tamil and Hindi: fonts already on the device (no download), and more line height. */
:root:lang(si) { --font: 'Noto Sans Sinhala', 'Nirmala UI', 'Iskoola Pota', 'Sinhala Sangam MN', system-ui, sans-serif; }
:root:lang(ta) { --font: 'Noto Sans Tamil', 'Nirmala UI', 'Latha', 'Tamil Sangam MN', system-ui, sans-serif; }
:root:lang(hi) { --font: 'Noto Sans Devanagari', 'Nirmala UI', 'Mangal', 'Kohinoor Devanagari', system-ui, sans-serif; }
:root:lang(si) body, :root:lang(ta) body, :root:lang(hi) body { line-height: 1.7; }
/* Long words in buttons and tabs may wrap instead of overflowing. */
.btn, .tabs button, .chip, .pcard .name { overflow-wrap: anywhere; }
.btn { text-align: center; line-height: 1.25; padding-top: 4px; padding-bottom: 4px; }
/* Tabs: labels stay on one line (never break inside a word); a bit smaller on tiny phones. */
.tabs button { overflow-wrap: normal; white-space: nowrap; padding: 0 4px; min-width: 0; }
.tabs .count { white-space: nowrap; }
@media (max-width: 379.98px) { .tabs button { font-size: 14px; gap: 4px; } }
/* Part cards: the tape tag moves under the sizes when space is tight. */
.pcard .main { flex: 1 1 auto; }

/* "A new version is ready" note: small, at the bottom, never covering the Optimize bar on phones. */
.update-bar { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(84px + env(safe-area-inset-bottom)); z-index: 40;
  display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 14px; border-radius: 12px; max-width: calc(100vw - 24px);
  background: var(--bar); color: var(--bar-fg); box-shadow: 0 6px 20px rgba(0,0,0,.25); }
@media (min-width: 1024px) { .update-bar { bottom: 20px; } }

/* "KerfMate / by SM Interiors" in the top bar. */
.brand-wrap { display: flex; flex-direction: column; line-height: 1.1; min-width: 0; }
.brand-wrap .by { font-size: 11px; opacity: .8; white-space: nowrap; }
@media (max-width: 399.98px) { .brand-wrap { display: none; } }
/* Numbered cut lines on sheet drawings (same numbers as the cutting order). */
.diagram .cutline { stroke: #c0392b; fill: none; }
.diagram .cutline.trimcut { stroke: #8a929e; }
.diagram .cutno circle { fill: #c0392b; }
.diagram .cutno.trimcut circle { fill: #6b7380; }
.diagram .cutno text { fill: #fff; font-family: var(--font); }
@media print { .diagram .cutno circle { fill: #c0392b !important; } .diagram .cutno text { fill: #fff !important; } }

/* Parts on a sheet, under its drawing (the drawing shows only numbers when it is small). */
.sheet-parts { list-style: none; margin: 6px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(210px, 100%), 1fr)); gap: 2px 12px; font-size: 14px; }
.sheet-parts li { overflow-wrap: anywhere; }
.sheet-parts .muted { font-variant-numeric: tabular-nums; }
@media print { #print-area .diagram text { display: inline !important; } }
/* Cut mode on a phone held sideways: instruction and buttons on the left, drawing on the right. */
@media (max-height: 500px) and (orientation: landscape) {
  .cutmode { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); grid-template-rows: auto auto minmax(0, 1fr) auto; }
  .cutmode .cm-top, .cutmode .cm-sheets { grid-column: 1 / -1; }
  .cutmode .cm-top { padding: 4px 12px; }
  .cutmode .cm-sheets .btn { min-height: 36px; }
  .cutmode .cm-instr { grid-column: 1; grid-row: 3; align-content: center; padding: 6px 16px; }
  .cutmode .cm-main { font-size: clamp(20px, 6vh, 28px); }
  .cutmode .cm-sub { font-size: 15px; }
  .cutmode .cm-draw { grid-column: 2; grid-row: 3 / span 2; padding: 6px 12px; }
  .cutmode .cm-nav { grid-column: 1; grid-row: 4; padding: 6px 16px 10px; }
  .cutmode .cm-nav .btn { min-height: 52px; font-size: 18px; }
}

/* The answers (sheets to buy, estimated cost) get a plywood-coloured edge. */
.stats .stat:first-child, .stats .stat:last-child { border-top: 3px solid var(--accent); }
.stats.doubtful .stat { border-top-color: var(--line); }
/* How-to steps */
.help-steps { margin: 0; padding-left: 22px; display: grid; gap: 8px; }
/* Offcuts: a table on wide screens, one card per offcut on phones. */
.offcut-table { min-width: 620px; }
.offcut-table .o-only { display: none; }
@media (max-width: 599.98px) {
  .offcut-table { min-width: 0 !important; border-spacing: 0; }
  .offcut-table thead { display: none; }
  .offcut-table, .offcut-table tbody, .offcut-table td { display: block; width: auto !important; }
  .offcut-table tr { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px; padding: 10px; margin-bottom: 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); }
  .offcut-table td { padding: 0; min-width: 0 !important; }
  .offcut-table td[data-label]::before { content: attr(data-label); display: block; font-size: 13px; color: var(--muted); }
  .offcut-table .o-mat, .offcut-table .o-note { grid-column: 1 / -1; }
  .offcut-table .o-only { display: inline; }
  .offcut-table .o-grain { align-self: end; }
  .offcut-table .o-del { justify-self: end; align-self: end; order: 8; }
  .offcut-table .o-note { order: 9; }
}
@media (max-height: 500px) and (orientation: landscape) {
  .cutmode .cm-donecard { grid-column: 1 / -1; grid-row: 3; }
}

/* Saw and edge tape card: the kerf row, then the tape types. */
.basics-card .set-row { border-bottom: 0; }
.basics-card .set-group h3 { margin-top: 6px; }

.stock-remove { display: none; }

/* A cut that takes a narrow strip off a thin piece (sequence.js marks it). */
.caution { color: var(--warn-fg); font-weight: 600; }
.cutmode .cm-caution { font-size: 17px; font-weight: 700; color: var(--warn-fg); background: var(--warn-bg); border-radius: 6px; padding: 4px 8px; justify-self: start; }

/* ---------------------------------------------------------------- part screen (QR code on a part label: ui/partView.js) */
/* Covers the whole app, like cut mode. Long names and translations wrap; nothing scrolls sideways. */
.partview { position: fixed; inset: 0; z-index: 55; overflow-y: auto; overscroll-behavior: contain; background: var(--bg); color: var(--fg);
  padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.pv-top { position: sticky; top: 0; z-index: 1; display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; padding-top: max(8px, env(safe-area-inset-top)); background: var(--bar); color: var(--bar-fg); }
.pv-brand { font-weight: 700; font-size: 18px; white-space: nowrap; }
.pv-top .spacer { flex: 1; }
.pv-lang { min-height: var(--tap); max-width: 55%; padding: 6px 8px; border-radius: 8px; border: 1px solid #4a5a71; background: var(--chip); color: var(--bar-fg); }
.pv-body { max-width: 720px; margin: 0 auto; padding: 16px 16px 32px; display: grid; gap: 16px; }
.pv-body > * { min-width: 0; }
.pv-head { display: grid; gap: 6px; }
.pv-kicker { margin: 0; font-size: 13px; font-weight: 600; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); }
.pv-head h1, .pv-problem h1 { margin: 0; }
.pv-head h1:focus, .pv-problem h1:focus { outline: none; }        /* focused only so screen readers start here */
.pv-head h1 { display: grid; gap: 4px; }
.pv-no { font-size: clamp(40px, 13vw, 60px); font-weight: 800; line-height: 1.05; font-variant-numeric: tabular-nums; }
.pv-name { font-size: clamp(22px, 6.5vw, 30px); font-weight: 700; line-height: 1.4; overflow-wrap: anywhere; }
.pv-room { margin: 0; }
.pv-room dd { margin: 0; display: inline-block; max-width: 100%; font-size: 17px; font-weight: 600; padding: 4px 12px; border-radius: 8px;
  background: var(--tag); color: var(--tag-fg); overflow-wrap: anywhere; }
.pv-facts { margin: 0; display: flex; flex-wrap: wrap; gap: 2px 18px; font-size: 15px; }
.pv-facts > div { max-width: 100%; overflow-wrap: anywhere; }
.pv-facts dt { display: inline; color: var(--muted); margin-right: 6px; }
.pv-facts dd { display: inline; margin: 0; font-weight: 600; }
.pv-sizes { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.pv-size { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 14px; display: grid; gap: 2px; align-content: start; min-width: 0; }
.pv-size.main { border-top: 4px solid var(--accent); }
.pv-size .k { font-size: 14px; font-weight: 600; color: var(--muted); }
.pv-size b { font-size: clamp(28px, 8.5vw, 38px); font-weight: 800; line-height: 1.15; overflow-wrap: anywhere; }
.pv-size:not(.main) b { font-size: clamp(22px, 6.5vw, 28px); }
.pv-edges { display: grid; gap: 12px; }
.pv-edges-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; }
.pv-edges-head h2 { margin: 0; font-size: 15px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.pv-count { font-size: 18px; font-weight: 700; }
.pv-count.on { color: var(--primary); }
/* The drawing: edge names around the part (top above, bottom below, the ends at the sides). */
.pv-draw { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2.2fr) minmax(0, 1fr);
  grid-template-areas: ". top ." "left shape right" ". bottom ."; gap: 6px 8px; align-items: center; width: 100%; max-width: 560px; margin: 0 auto; }
.pv-e { display: grid; font-size: 14px; line-height: 1.3; overflow-wrap: anywhere; min-width: 0; color: var(--muted); }
.pv-e-top { grid-area: top; text-align: center; }
.pv-e-bottom { grid-area: bottom; text-align: center; }
/* Above and below the part there is room for the tape and the length on one line (it wraps when not). */
.pv-e-top, .pv-e-bottom { display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline; gap: 0 10px; }
.pv-e-left { grid-area: left; text-align: right; }
.pv-e-right { grid-area: right; text-align: left; }
.pv-e .pv-e-tape { font-weight: 600; }
.pv-e-word { font-size: 13px; font-weight: 600; color: var(--muted); }   /* "Top (720 mm)" (no capitals: "mm" must stay "mm") */
.pv-e.on { color: var(--fg); }
.pv-e.on .pv-e-tape { color: var(--primary); font-weight: 700; font-size: 16px; }
.pv-shape { grid-area: shape; min-width: 0; }
.pv-shape { display: grid; place-items: center; }
.pv-shape .esk { width: 100%; max-height: 50vh; }
.pv-grain-note { margin: 0; text-align: center; }
.pv-problem h1 { font-size: 20px; line-height: 1.35; }
.pv-problem p { margin: 0; }
/* Narrow phones: the drawing gets the whole width; the left and right names go in a row under it
   ("Left (400 mm)" on the left, "Right (400 mm)" on the right). Not too tall, so the edge tape
   answer fits on the first screen after a scan. */
@media (max-width: 479.98px) {
  .pv-draw { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "top top" "shape shape" "bottom bottom" "left right"; gap: 4px 12px; }
  .pv-e { font-size: 13px; hyphens: auto; }
  .pv-e.on .pv-e-tape { font-size: 15px; }
  .pv-e-left { text-align: left; }
  .pv-e-right { text-align: right; }
  .pv-e-word { display: block; }
  .pv-shape .esk { max-height: 28vh; width: auto; }
}

/* A short-link label (#q=): "Finding this part…", where the part is now, and where to go next. */
.pv-finding { margin: 0; font-size: 17px; color: var(--muted); }
.pv-note { margin: 0; }
.pv-actions { display: grid; gap: 10px; }
.pv-body > .pv-kicker { margin-bottom: -8px; }

/* ---------------------------------------------------------------- "Scan a label" (ui/scanner.js) */
.scan-box { position: relative; width: 100%; aspect-ratio: 1; max-height: 60vh; background: #000; border-radius: 8px; overflow: hidden; }
.scan-video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* A square in the middle shows where to hold the QR code. */
.scan-frame { position: absolute; inset: 18%; border: 3px solid #fff; border-radius: 12px; box-shadow: 0 0 0 999px rgba(0, 0, 0, .35); pointer-events: none; }
.scan-status { margin: 0; min-height: 3em; overflow-wrap: anywhere; }
.scan-dlg .dlg-body > .btn { justify-self: start; }

/* ---------------------------------------------------------------- labels dialog: the labels file for a label printer's phone app */
.label-file { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); }
.label-file > .btn { justify-self: start; }
select.cell.tap { min-height: var(--tap); }          /* full-size touch target (the labels dialog's choices) */
.label-file [role="status"]:focus { outline: none; }        /* focused only so screen readers read the progress */
/* Cut mode's "Sheet S2 is cut" screen: the labels button under the list of parts. */
.cutmode .cm-donecard .row-actions { margin-top: 6px; }

/* ---------------------------------------------------------------- labels dialog: printing straight to a Bluetooth label printer (ui/btPrint.js) */
.bt-print { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2); min-width: 0; }
.bt-print h3 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.bt-print p { margin: 0; }
.bt-status { overflow-wrap: anywhere; display: grid; gap: 2px; }
.bt-live { display: grid; gap: 8px; }
.bt-live:empty { display: none; }
.bt-print [role="status"]:focus { outline: none; }
.bt-hint { margin: 0; }
.bt-settings > summary { list-style: none; cursor: pointer; min-height: var(--tap); display: flex; align-items: center; gap: 6px; font-weight: 600; color: var(--primary); }
.bt-settings > summary::-webkit-details-marker { display: none; }
.bt-settings[open] > summary .ico { transform: rotate(90deg); }
.bt-settings .body { display: grid; gap: 12px; padding: 2px 0 4px; }
.bt-settings fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 4px; min-width: 0; }
.bt-settings legend { font-weight: 600; font-size: 15px; padding: 0; margin-bottom: 2px; }
/* A long choice wraps under its own text; the radio stays level with the first line. */
.bt-radio { display: flex; align-items: flex-start; padding: 10px 0; }
.bt-radio input[type="radio"] { width: 22px; height: 22px; margin: 2px 0 0; margin-top: calc((1lh - 22px) / 2); accent-color: var(--primary); flex: none; }
.bt-gap { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: var(--tap); }
.bt-settings fieldset .bt-gap { padding-left: 30px; }        /* under its "Fixed" choice */
.bt-print input.cell { min-height: var(--tap); width: 76px; text-align: center; color: var(--fg); font-size: 16px; }
.bt-nudge { display: grid; gap: 2px; }
.bt-nudge-label { font-size: 14px; color: var(--muted); }
.bt-nudge-ctl { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.bt-nudge-ctl .btn { min-width: var(--tap); padding: 0 10px; }
.bt-nudge-words { min-height: 1.4em; }
.ico.up { transform: rotate(-90deg); }
.ico.down { transform: rotate(90deg); }
.bt-other { display: grid; gap: 6px; }
.bt-first { display: grid; gap: 6px; }            /* "First time with this printer?" and its Test print button */
.bt-baud { margin: 0; }
/* ---------------------------------------------------------------- parts list: find a part, select several (ui/partsPane.js) */
.parts-tools { display: grid; gap: 6px; margin-bottom: 8px; }
.parts-tools:empty { display: none; }
.part-search { display: flex; align-items: center; gap: 6px; max-width: 520px; color: var(--muted); }
.part-search .ico { margin-left: 2px; }
.part-search input.cell { flex: 1; min-width: 0; min-height: var(--tap); font-size: 16px; color: var(--fg); }
.found-count { min-height: 1.2em; }
/* The select bar stays in view under the tabs while the list scrolls. */
.selbar { position: sticky; top: 104px; z-index: 5; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px;
  padding: 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); box-shadow: 0 2px 8px rgba(0,0,0,.08); }
@media (min-width: 1024px) { .selbar { top: 60px; } }
.selbar, .sel-room { margin-bottom: 8px; }
.selbar .sel-count { min-width: 6em; flex: 1 1 auto; overflow-wrap: anywhere; }   /* a long one-word count (Tamil) wraps, never hides under Done */
.selbar > * { min-width: 0; }
/* Phones: two short rows ("2 selected | Done", "Delete 2 parts | Select all"), so the bar does not
   cover the list. Delete is bottom left, away from Done (top right): a thumb aiming for Done does not delete. */
@media (max-width: 599.98px) {
  .selbar { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .selbar .sel-count { order: 1; padding-left: 4px; }
  .selbar .sel-done { order: 2; }
  .selbar .btn.danger { order: 3; }
  .selbar .sel-all { order: 4; }
}
/* A long room name or translation never makes the room choice wider than the list. */
.sel-room { display: flex; min-width: 0; }
.sel-room select.cell { width: auto; min-width: 0; max-width: 100%; min-height: var(--tap); }
/* Grid: the tick box sits in the row-number column, which grows to a full touch target. */
table.grid.selecting .rownum { width: 58px; }
table.grid.selecting .c-name { left: 58px; }
table.grid.selecting thead th:nth-child(2) { left: 58px; }
.selbox { display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px; min-height: var(--tap); min-width: var(--tap); cursor: pointer; }
table.grid tr.selected td, table.grid tr.selected .rownum, table.grid tr.selected .c-name { background: var(--tag); }
/* Cards: the card and its "Where" button side by side; when selecting, the whole card is the tick box. */
.pcard-row { display: flex; gap: 6px; align-items: stretch; min-width: 0; }
.pcard-row > .pcard { flex: 1 1 auto; min-width: 0; }
.pcard.selectable input[type="checkbox"] { flex: none; margin: 0 2px; }
.pcard.selected { border-color: var(--primary); background: var(--tag); }
/* A part found from the results: a clear outline (no animation, as agreed). */
table.grid tr.found td, table.grid tr.found .rownum, table.grid tr.found .c-name { background: var(--warn-bg); }
table.grid tr.found .rownum { box-shadow: inset 4px 0 0 var(--accent); }
table.grid tr:focus { outline: none; }
table.grid tr.found:focus-visible .rownum { outline: 3px solid var(--focus); outline-offset: -3px; }
.pcard-row.found .pcard { border-color: var(--accent-text); box-shadow: 0 0 0 3px var(--accent); }
/* "S2 · #5 +1": where a part is in the results. */
.btn.wherebtn { min-width: var(--tap); padding: 2px 8px; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap;
  flex-direction: column; gap: 0; line-height: 1.25; color: var(--primary); }
.btn.wherebtn .more { font-size: 12px; color: var(--muted); font-weight: 500; }
.btn.wherebtn.missing { color: var(--err-fg); }
.btn.wherebtn.stale-where { border-style: dashed; color: var(--muted); }
table.grid td.c-where { min-width: 96px; }
table.grid td.c-where .btn.wherebtn { flex-direction: row; gap: 4px; min-height: var(--tap); }
.place-list { display: flex; flex-wrap: wrap; gap: 8px; }
/* ---------------------------------------------------------------- results: a part marked on its sheet */
.diagram.pickable .pt { cursor: pointer; }
.diagram .pick { fill: var(--accent); fill-opacity: .35; stroke: var(--accent-text); pointer-events: none; }
.pick-info { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; padding: 8px 10px; border-radius: 8px;
  background: var(--warn-bg); color: var(--fg); border-left: 4px solid var(--accent); }
.pick-info:focus { outline: none; }
.pick-info:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.pick-info .pick-text { flex: 1 1 180px; min-width: 0; overflow-wrap: anywhere; }
/* Part names in the results that jump somewhere: look like text, with a full touch target. */
.partbtn { border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; padding: 0 4px; margin: 0 -4px;
  min-height: var(--tap); border-radius: 6px; overflow-wrap: anywhere; }
.partbtn:hover { background: var(--surface-2); }
.sheet-parts .partbtn { width: calc(100% + 8px); }
.sheet-parts li.picked .partbtn { background: var(--warn-bg); box-shadow: inset 3px 0 0 var(--accent); }
td > .partbtn { color: var(--primary); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.where-list { display: flex; flex-wrap: wrap; gap: 0 10px; }
.where-list .partbtn { margin: 0; color: var(--primary); white-space: nowrap; font-variant-numeric: tabular-nums; }
@media print { .pick-info, .parts-tools { display: none !important; } .diagram .pick { display: none; } }
/* Cut lines and their numbers never catch a tap: a tap there marks the part underneath. */
.diagram .cutlines, .diagram .cutnos { pointer-events: none; }
