/* ===========================================================================
   FINOpti V12 — web chrome (stage 2)
   ---------------------------------------------------------------------------
   The shell around the document: app header, command bar, document tabs,
   Explorer / Properties docks, splitters and status bar. Ported from
   design_handoff_v12_web (v11.css shell + v12.css web chrome).

   Scoped to [data-ui="v12"] like the rest of the system. This file is only
   loaded by /v2 — the classic app never sees it.
   =========================================================================== */

[data-ui="v12"] { --hdr: 58px; }

html, body { height: 100%; }
body:has(> #root > .web) { margin: 0; overflow: hidden; }

[data-ui="v12"].web {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--win);
  overflow: hidden;
}

/* ------------------------------------------------------------ app header -- */
[data-ui="v12"] .webhdr {
  height: var(--hdr);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  background: var(--srf);
  border-bottom: 1px solid var(--bd);
  flex: none;
  min-width: 0;
}
[data-ui="v12"] .wbrand { display: flex; align-items: center; gap: 10px; flex: none; }
[data-ui="v12"] .wbrand .bm {
  width: 32px; height: 32px; border-radius: 7px;
  background: var(--acc); color: var(--ac-ink); display: grid; place-items: center;
}
[data-ui="v12"] .wbrand .bn {
  font-family: var(--d); font-size: 17px; font-weight: 600; letter-spacing: -.01em;
}
[data-ui="v12"] .wbrand .bn i { font-style: normal; color: var(--acc); }

[data-ui="v12"] .jobsel,
[data-ui="v12"] .searchw {
  display: flex; align-items: center; gap: 9px;
  height: 40px; padding: 0 12px;
  border: 1px solid var(--bd-2); border-radius: var(--r);
  background: var(--srf); color: var(--ink);
  min-width: 0; cursor: pointer; font-family: var(--f);
}
[data-ui="v12"] .jobsel { max-width: 300px; }
[data-ui="v12"] .jobsel:hover,
[data-ui="v12"] .searchw:hover { background: var(--srf-3); }
[data-ui="v12"] .jobsel b { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
[data-ui="v12"] .jobsel span {
  font-size: 12.5px; color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
[data-ui="v12"] .searchw { flex: 0 1 300px; color: var(--ink-3); font-size: 13.5px; }
[data-ui="v12"] .searchw .grow { text-align: left; }

[data-ui="v12"] .hbtn {
  width: 40px; height: 40px; border-radius: var(--r);
  display: grid; place-items: center;
  color: var(--ink-2); background: transparent;
  border: 1px solid transparent; flex: none; cursor: pointer;
}
[data-ui="v12"] .hbtn:hover { background: var(--srf-3); border-color: var(--bd); }
[data-ui="v12"] .hbtn.on { background: var(--acc-soft); border-color: var(--acc-line); color: var(--acc-2); }
/* The workspace trigger carries a label and a language tag, so it sizes to its
   content instead of the 40px icon square (v12_roles.jsx:305). */
[data-ui="v12"] .hbtn.wide {
  width: auto; padding: 0 10px;
  display: flex; align-items: center; gap: 7px;
}

[data-ui="v12"] .kbd {
  font-family: var(--m); font-size: 11px; color: var(--ink-4);
  border: 1px solid var(--bd-2); border-radius: 4px;
  padding: 1px 5px; flex: none;
}

[data-ui="v12"] .avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--acc); color: var(--ac-ink);
  display: grid; place-items: center;
  font-size: 13px; font-weight: 600; flex: none;
  border: none; cursor: pointer;
}

@media (max-width: 1080px) {
  [data-ui="v12"] .searchw { flex: 0 0 40px; padding: 0; justify-content: center; }
  [data-ui="v12"] .searchw .grow, [data-ui="v12"] .searchw .kbd { display: none; }
  /* the role label goes before the icon does — the tag still says the language */
  [data-ui="v12"] .hbtn.wide span:not(.tag) { display: none; }}
@media (max-width: 860px) {
  [data-ui="v12"] .jobsel span { display: none; }
  [data-ui="v12"] .wbrand .bn { display: none; }}

/* ----------------------------------------------------------- command bar -- */
[data-ui="v12"] .cmdwrap {
  display: flex; align-items: center;
  background: var(--srf); border-bottom: 1px solid var(--bd);
  flex: none; padding-right: 6px;
}
[data-ui="v12"] .cmdbar {
  flex: 1; min-width: 0;
  height: 44px; display: flex; align-items: center; gap: 2px;
  padding: 0 8px; overflow-x: auto; scrollbar-width: none;
}
[data-ui="v12"] .cmdbar::-webkit-scrollbar { display: none; }
[data-ui="v12"] .cmd {
  display: flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 10px;
  border: 0; border-radius: var(--r-s);
  background: transparent; color: var(--ink);
  font-family: var(--f); font-size: 13px; white-space: nowrap; flex: none; cursor: pointer;
}
[data-ui="v12"] .cmd:hover { background: var(--srf-3); }
[data-ui="v12"] .cmd:active { background: var(--bd); }
[data-ui="v12"] .cmd svg { color: var(--acc); }
[data-ui="v12"] .cmd.pri { background: var(--acc); color: var(--ac-ink); }
[data-ui="v12"] .cmd.pri svg { color: var(--ac-ink); }
[data-ui="v12"] .cmd.pri:hover { background: var(--acc-2); }
[data-ui="v12"] .csep { width: 1px; height: 22px; background: var(--bd); margin: 0 6px; flex: none; }
[data-ui="v12"] .ovbtn {
  width: 34px; height: 34px; border: 0; background: transparent;
  color: var(--ink-2); font-size: 16px; line-height: 1; flex: none; justify-content: center;
  border-radius: var(--r-s); cursor: pointer;
}
[data-ui="v12"] .ovbtn:hover { background: var(--srf-3); }

/* --------------------------------------------------------- document tabs -- */
[data-ui="v12"] .tabrow {
  display: flex; align-items: flex-end;
  background: var(--win); border-bottom: 1px solid var(--bd);
  flex: none; padding-right: 4px;
}
[data-ui="v12"] .tabstrip {
  flex: 1; min-width: 0;
  height: 36px; display: flex; align-items: flex-end; gap: 2px;
  padding: 0 6px; overflow-x: auto; scrollbar-width: none;
}
[data-ui="v12"] .tabstrip::-webkit-scrollbar { display: none; }
[data-ui="v12"] .dtab {
  display: flex; align-items: center; gap: 8px;
  height: 32px; padding: 0 8px 0 11px;
  border-radius: var(--r) var(--r) 0 0;
  font-size: 13px; color: var(--ink-2); background: transparent;
  white-space: nowrap; flex: none; max-width: 230px; cursor: pointer;
}
[data-ui="v12"] .dtab:hover { background: var(--srf-3); }
[data-ui="v12"] .dtab.on {
  background: var(--srf); color: var(--ink); font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--bd), 0 1px 0 var(--srf);
}
[data-ui="v12"] .dtab .x {
  width: 18px; height: 18px; border-radius: var(--r-xs);
  display: grid; place-items: center; color: var(--ink-4); font-size: 11px;
}
[data-ui="v12"] .dtab .x:hover { background: var(--bd); color: var(--ink); }

/* ----------------------------------------------------- docks + splitters -- */
[data-ui="v12"] .workspace {
  flex: 1; min-height: 0; display: flex; align-items: stretch; background: var(--win);
}
[data-ui="v12"] .dock {
  background: var(--srf); display: flex; flex-direction: column;
  min-height: 0; flex: none; overflow: hidden;
}
[data-ui="v12"] .dock.left { border-right: 1px solid var(--bd); }
[data-ui="v12"] .dock.right { border-left: 1px solid var(--bd); }
[data-ui="v12"] .dockhd {
  height: 34px; display: flex; align-items: center; gap: 8px;
  padding: 0 10px; border-bottom: 1px solid var(--bd);
  font-size: 12px; font-weight: 600; color: var(--ink-3); flex: none;
}
[data-ui="v12"] .dockbody { flex: 1; min-height: 0; overflow: auto; }
[data-ui="v12"] .split {
  width: 4px; cursor: col-resize; background: transparent; flex: none; position: relative;
}
[data-ui="v12"] .split:hover::after,
[data-ui="v12"] .split.drag::after {
  content: ""; position: absolute; inset: 0 1px; background: var(--acc);
}

/* ------------------------------------------------------------------ tree -- */
[data-ui="v12"] .tree { padding: 4px 0; font-size: 13px; }
[data-ui="v12"] .tnode {
  display: flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 8px;
  white-space: nowrap; cursor: default; color: var(--ink);
}
[data-ui="v12"] .tnode:hover { background: var(--srf-3); }
[data-ui="v12"] .tnode.sel { background: var(--acc-soft); color: var(--acc-2); }
[data-ui="v12"] .tnode.sel .tsub { color: var(--acc-2); }
[data-ui="v12"] .tw {
  width: 16px; flex: none; display: grid; place-items: center;
  color: var(--ink-3); font-size: 10px;
}
[data-ui="v12"] .tsw {
  width: 11px; height: 11px; border: 1px solid rgba(0,0,0,.25);
  border-radius: 2px; flex: none;
}
[data-ui="v12"] .tnode .tsub {
  margin-left: auto; font-family: var(--m); font-size: 11px; color: var(--ink-4);
}

/* ------------------------------------------------------------- documents -- */
[data-ui="v12"] .docarea {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  min-height: 0; background: var(--win);
}
[data-ui="v12"] .docbody {
  flex: 1; min-height: 0; overflow: auto; background: var(--srf); position: relative;
}

/* ------------------------------------------------------------ status bar -- */
[data-ui="v12"] .statusbar {
  height: 26px; display: flex; align-items: center;
  background: var(--srf); border-top: 1px solid var(--bd);
  font-size: 12px; color: var(--ink-3); flex: none; padding: 0 4px;
}
[data-ui="v12"] .sseg {
  padding: 0 10px; display: flex; align-items: center; gap: 6px;
  white-space: nowrap; height: 100%;
}
[data-ui="v12"] .sseg + .sseg { border-left: 1px solid var(--bd); }
[data-ui="v12"] .sseg b {
  color: var(--ink); font-weight: 600; font-family: var(--m); font-size: 11.5px;
}

/* ---------------------------------------------------------------------------
   Existing pages inside a docked pane.
   The classic pages were written for a full-width viewport with their own
   sidebar; in a ~700px document pane their fixed grid tracks starve. Until each
   screen is rebuilt (stages 3+) let them degrade rather than scroll sideways.
   --------------------------------------------------------------------------- */
[data-ui="v12"] .docbody > .app-root,
/* v11.css:210 + :221 — a document inside the pane is tighter than a
   standalone page, and steps back up on a wide screen. Both values are the
   design's; the horizontal was 18px here, which is nobody's number. */
[data-ui="v12"] .docbody > .page { padding: 16px 16px 28px; max-width: none; }
@media (min-width: 1500px) {
  [data-ui="v12"] .docbody > .page { padding: 20px 22px 32px; }
  [data-ui="v12"] .docbody .cols { grid-template-columns: minmax(0, 1fr) 330px; }}
[data-ui="v12"] .docbody { container-type: inline-size; }
@container (max-width: 980px) {
  [data-ui="v12"] .docbody .cols { grid-template-columns: minmax(0, 1fr); }
  [data-ui="v12"] .docbody .rgrid-2,
  [data-ui="v12"] .docbody .rgrid-3 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
  [data-ui="v12"] .docbody .table-wrap { overflow-x: auto; }}

/* ---------------------------------------------------------------------------
   The sheet drawing (stage 3)
   --------------------------------------------------------------------------- */
[data-ui="v12"] .v2canv {
  position: relative;
  flex: 1; min-height: 0;
  display: grid; place-items: center;
  padding: 14px;
  background: var(--bg-2, #eaeaea);
  overflow: auto;
}
:root[data-theme="dark"] [data-ui="v12"] .v2canv { background: #1a1a1a; }
[data-ui="v12"] .v2canv::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(0,0,0,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,.05) 1px, transparent 1px);
  background-size: 16px 16px;
}
[data-ui="v12"] .v2sheet {
  position: relative;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,.16));
  max-width: 100%;
}
[data-ui="v12"] .v2tile { cursor: pointer; }
[data-ui="v12"] .v2tile:hover rect { fill-opacity: .42; }
[data-ui="v12"] .v2cut { stroke-width: 1.2; stroke-dasharray: 5 3; }
[data-ui="v12"] .v2empty {
  flex: 1; display: grid; place-items: center;
  color: var(--ink-4); font-size: 13px;
}
[data-ui="v12"] .v2thumb {
  border: 1px solid var(--bd-2); border-radius: var(--r-s);
  background: var(--board); display: block;
}
[data-ui="v12"] .v2thumb.on { border-color: var(--acc); box-shadow: 0 0 0 1px var(--acc); }
[data-ui="v12"] .v2tip {
  position: fixed; z-index: 250; pointer-events: none;
  min-width: 150px; padding: 8px 10px;
  background: var(--srf); border: 1px solid var(--bd-2);
  border-radius: var(--r); box-shadow: var(--sh-3);
  font-size: 12px;
}
[data-ui="v12"] .v2tip .t { font-family: var(--m); font-weight: 600; margin-bottom: 4px; }
[data-ui="v12"] .v2tip .r { display: flex; gap: 10px; color: var(--ink-3); }
[data-ui="v12"] .v2tip .r b { margin-left: auto; color: var(--ink); font-family: var(--m); font-weight: 600; }

/* zoom dock under the drawing */
[data-ui="v12"] .v2dock {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; border-top: 1px solid var(--bd); background: var(--srf);
  flex: none; overflow-x: auto; scrollbar-width: none;
}
[data-ui="v12"] .v2dock::-webkit-scrollbar { height: 0; }
[data-ui="v12"] .v2dock > * { flex: none; }

/* --------------------------------------------------- cutting-plan document -- */
[data-ui="v12"] .v2plan { height: 100%; display: flex; flex-direction: column; min-height: 0; }
[data-ui="v12"] .v2mattabs {
  display: flex; gap: 6px; padding: 8px 10px;
  border-bottom: 1px solid var(--bd); background: var(--srf-2); flex: none;
}
[data-ui="v12"] .v2sw { width: 10px; height: 10px; border-radius: 2px; flex: none; }
[data-ui="v12"] .v2sheetbar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-bottom: 1px solid var(--bd); background: var(--srf); flex: none;
}
[data-ui="v12"] .v2canvbox { flex: 1; min-height: 0; display: flex; }

/* ------------------------------------------------------------- tool strip -- */
/* README §3.4: ONE row, scrolls sideways, never steals height from the sheet.
   `flex: none` + `overflow-x: auto` is what enforces that — the row keeps its
   own height and pushes its overflow sideways instead of wrapping onto a
   second line and eating the drawing. */
[data-ui="v12"] .v2tools {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px; border-top: 1px solid var(--bd); background: var(--srf-2);
  flex: none; overflow-x: auto; scrollbar-width: none;
}
[data-ui="v12"] .v2tools::-webkit-scrollbar { height: 0; }
[data-ui="v12"] .v2tools > * { flex: none; }
[data-ui="v12"] .v2tools .grow { flex: 1 0 12px; }

/* pickable row (saw chooser) */
[data-ui="v12"] .v2pick {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 10px; margin-bottom: 6px; cursor: pointer;
  border: 1px solid var(--bd-2); border-radius: var(--r-s); background: var(--srf);
  font: inherit; color: inherit;
}
[data-ui="v12"] .v2pick:hover { border-color: var(--ink-4); }
[data-ui="v12"] .v2pick[data-on="1"] { border-color: var(--acc); background: var(--acc-soft); }
[data-ui="v12"] .v2pick-t { display: block; font-size: 13.5px; font-weight: 600; }

/* acknowledgement — a deliberate, readable tick, not a hairline checkbox:
   this is the last gate before metal moves. */
[data-ui="v12"] .v2ack {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 7px 0; cursor: pointer; font-size: 13px; line-height: 1.5;
  color: var(--ink-2);
}
[data-ui="v12"] .v2ack-b {
  width: 15px; height: 15px; flex: none; margin-top: 2px; border-radius: 3px;
  border: 1px solid var(--ink-4); background: var(--srf);
  /* the tick paints in --ac-ink so it stays readable on the dark theme's
     light accent when the box is checked */
  display: grid; place-items: center; font-size: 10px; color: var(--ac-ink);
}
[data-ui="v12"] .v2ack-b[data-on="1"] { border-color: var(--acc); background: var(--acc); }

/* ----------------------------------------------------------------- panels -- */
/* Segmented tab strip: buttons welded into one control, so it reads as a
   single switch rather than six loose buttons. */
[data-ui="v12"] .v2seg {
  display: flex; border: 1px solid var(--bd-2); border-radius: var(--r-s); overflow: hidden;
}
[data-ui="v12"] .v2seg > .btn {
  border: 0; border-radius: 0; background: transparent; color: var(--ink-2);
}
[data-ui="v12"] .v2seg > .btn + .btn { border-left: 1px solid var(--bd-2); }
/* The active member is TINTED, not filled. A solid accent block inside a
   bordered segmented control reads as a mis-shaped pill — the fill has square
   corners where the control's are round, and two of them side by side look
   like a rendering fault. The design's own .btn.on is a soft accent wash with
   an accent hairline, which says "selected" without fighting the container's
   shape; the segmented control just inherits it. */
[data-ui="v12"] .v2seg > .btn.on {
  background: var(--acc-soft); color: var(--acc-2);
  box-shadow: inset 0 0 0 1px var(--acc-line);
}

/* the strip above a panel's body: status tag, explanation, actions */
[data-ui="v12"] .v2panbar {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 10px 13px; border-bottom: 1px solid var(--bd);
}
[data-ui="v12"] .v2pangrid,
[data-ui="v12"] .v2repgrid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(296px, 1fr)); gap: 14px;
}
[data-ui="v12"] .v2repgrid { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); padding: 13px; }
[data-ui="v12"] .v2labgrid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); gap: 10px;
}
/* proportion bar for the cut-time breakdown */
[data-ui="v12"] .v2bar {
  height: 6px; border-radius: 3px; background: var(--srf-3, var(--bd)); overflow: hidden;
}
[data-ui="v12"] .v2bar > i { display: block; height: 100%; background: var(--acc); }

/* -------------------------------------------------------------- free mode -- */
/* The design's Free Mode is 244 / 1fr / 268 with a 14px gutter
   (v12_ext.jsx:307). The rails here were 340 and 260 — 88px wider in total —
   which is what pushed the whole layout past its own collapse threshold on an
   ordinary window. */
[data-ui="v12"] .v2free {
  display: grid; grid-template-columns: 244px minmax(0, 1fr) 268px; gap: 14px;
  min-height: 0; align-items: start;
}
[data-ui="v12"] .v2freemid {
  display: flex; flex-direction: column; min-width: 0;
  border: 1px solid var(--bd); border-radius: var(--r-s); background: var(--srf);
  height: 640px;
}
/* Two lines per part: name + actions, then a labelled 4-across field grid
   (the design's layout, v12_ext.jsx:326). The single-line version packed five
   unlabelled inputs at 58/44px — unusable for 4-digit millimetre values. */
[data-ui="v12"] .v2partrow {
  display: block; padding: 7px 8px;
  border: 1px solid var(--bd-2); border-radius: var(--r-s); cursor: pointer;
}
[data-ui="v12"] .v2partrow.on { border-color: var(--acc); background: var(--acc-soft); }
[data-ui="v12"] .v2partrow-hd { display: flex; align-items: center; gap: 6px; min-width: 0; }
[data-ui="v12"] .v2partrow-fields {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 6px; margin-top: 6px;
}
[data-ui="v12"] .v2partrow-fields label { display: block; min-width: 0; }
[data-ui="v12"] .v2partrow-fields .lab { display: block; margin-bottom: 2px; font-size: 10.5px; }
[data-ui="v12"] .v2partrow-fields .inp { width: 100%; min-width: 0; }
[data-ui="v12"] .v2partrow .inp { padding: 4px 6px; font-size: 12.5px; }
/* The palette is dense by nature — keep its controls touchable anyway. */
[data-ui="v12"] .v2partrow .btn.sm { padding: 4px 8px; }

/* The design collapses at 1040px (v12_ext.jsx:216), not 1180. At 1180 the
   rails stacked BELOW the board on any window with the Explorer dock open —
   a 1440px window leaves a 1177px pane — so the palette the on-screen hint
   tells you to "pick a part on the left" from was off the bottom of the page.
   When it does collapse, the rails' cards flow into columns rather than one
   long ribbon, as the design does. */
@container (max-width: 1040px) {
  [data-ui="v12"] .v2free { grid-template-columns: minmax(0, 1fr); }
  [data-ui="v12"] .v2freemid { height: 520px; order: -1; }
  [data-ui="v12"] .v2railL,
  [data-ui="v12"] .v2railR {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    align-items: start;
  }}

/* ------------------------------------------------- customers · templates -- */
[data-ui="v12"] .v2custcols {
  display: grid; grid-template-columns: minmax(0, 1fr) 344px; gap: 14px; align-items: start;
}
[data-ui="v12"] .v2ordrow {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 13px; border-bottom: 1px solid var(--bd); cursor: pointer;
}
[data-ui="v12"] .v2ordrow:hover { background: var(--srf-2); }
[data-ui="v12"] .v2tplgrid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(296px, 1fr)); gap: 14px;
}
@container (max-width: 1000px) {
  [data-ui="v12"] .v2custcols { grid-template-columns: minmax(0, 1fr); }}

/* --------------------------------------------------------------- cut mode -- */
/* A floor screen: the board gets the space, the numbers are readable at
   arm's length, and the two controls the operator hits hundreds of times a
   job are 64px tall. @media, not @container — this fills the document pane
   but its rail must not shrink with it. */
[data-ui="v12"] .v2play { height: 100%; display: flex; flex-direction: column; min-height: 0; }
[data-ui="v12"] .v2playbar {
  display: flex; align-items: center; gap: 9px; flex: none;
  padding: 9px 12px; border-bottom: 1px solid var(--bd); background: var(--srf);
}
[data-ui="v12"] .v2done { margin: auto 0; text-align: center; }
[data-ui="v12"] .v2done-h { font-size: 22px; font-weight: 700; color: var(--ok); margin-bottom: 6px; }
/* the current cut, drawn heavy so it reads across the shop */
[data-ui="v12"] .v2cut.now { stroke-dasharray: none; }

/* The design steps the cockpit's side columns down as the window narrows
   (v7.css:200-201: 236/300 under 1400, 200/268 under 1160). Those are VIEWPORT
   queries; here they are CONTAINER queries on the document pane, because the
   pane is what the columns actually have to fit inside — with both docks open
   a 1440px window leaves the cockpit about 930px, and a viewport query would
   still be handing out full-width tracks.

   These fill a gap the design leaves: its own steps are viewport queries, so
   in a docked pane they never fire, and below a 900px pane it jumps straight
   to stacking. Between 900 and 1160 the cockpit would otherwise still be
   handing 272px and 344px to the side rails and leaving ~330px for the
   drawing. */
@container (max-width: 1160px) {
  [data-ui="v12"] .nest { grid-template-columns: 236px minmax(0, 1fr) 300px; }}
@container (max-width: 1000px) {
  [data-ui="v12"] .nest { grid-template-columns: 200px minmax(0, 1fr) 268px; gap: 10px; padding: 10px; }}
/* No stacking rule here on purpose. The DESIGN already stacks the cockpit
   below a 900px document pane, with !important, and its version is the more
   complete one — it clamps the inner .nscroll rather than the .ncol, so the
   drawing column keeps its 340px. An extra max-height on .ncol here would
   fight that and squash the last column to 190px. Verified: closing the
   Properties dock on a 1440px window gives a 1186px pane and the design's
   full 272px / 1fr / 344px cockpit. */

/* -------------------------------------------------------------- settings -- */
[data-ui="v12"] .v2setcols {
  display: grid; grid-template-columns: 214px minmax(0, 1fr); gap: 14px; align-items: start;
}
[data-ui="v12"] .v2setnav {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  padding: 7px 13px; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--ink-2);
}
[data-ui="v12"] .v2setnav:hover { background: var(--srf-2); }
[data-ui="v12"] .v2setnav.on { background: var(--acc-soft); color: var(--acc); font-weight: 600; }
/* label left, control right — the design's one repeated row primitive */
[data-ui="v12"] .v2setrow {
  display: grid; grid-template-columns: minmax(0, 180px) minmax(0, 1fr);
  gap: 12px; align-items: center;
  padding: 9px 13px; border-bottom: 1px solid var(--bd);
}
[data-ui="v12"] .v2setrow:last-child { border-bottom: 0; }
@container (max-width: 860px) {
  [data-ui="v12"] .v2setcols { grid-template-columns: minmax(0, 1fr); }
  [data-ui="v12"] .v2setrow { grid-template-columns: minmax(0, 1fr); }}

/* --------------------------------------------------------------- console -- */
/* The KPI cell's stacking is the design's own: .cell .v and .cell .sub carry
   position:relative + z-index:2, and .cell .spark sits at z-index:1 along the
   bottom. Nothing to add here. */

/* job queue row (still used by the batch screen; the console renders .jrow) */
[data-ui="v12"] .v2jrow {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: 34px minmax(0, 1.4fr) minmax(0, 1.1fr) 74px 128px 104px;
  padding: 8px 12px; border-bottom: 1px solid var(--bd); cursor: pointer; min-height: 44px;
}
[data-ui="v12"] .v2jrow:hover { background: var(--acc-soft); }
[data-ui="v12"] .v2jrow.sel { background: var(--acc-soft); box-shadow: inset 2px 0 0 var(--acc); }
[data-ui="v12"] .v2jrow:last-of-type { border-bottom: 0; }
[data-ui="v12"] .v2jref { font-size: 13.5px; font-weight: 600; }
[data-ui="v12"] .v2jsel {
  width: 26px; height: 26px; display: grid; place-items: center; flex: none;
  border: 1px solid var(--bd-2); border-radius: var(--r-xs);
  font-family: var(--m); font-size: 11px; color: var(--ink-3); background: var(--srf);
}
[data-ui="v12"] .v2jsel[data-on="1"] { background: var(--acc); border-color: var(--acc); color: var(--ac-ink); }
[data-ui="v12"] .v2bulk {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; border-top: 1px solid var(--bd); background: var(--srf-2);
}

/* Inside a narrow document pane the fixed tracks cannot fit; fall back to a
   wrapping flex row rather than letting the grid overflow (v11.css:246-255). */
@container (max-width: 780px) {
  [data-ui="v12"] .v2jrow { display: flex; flex-wrap: wrap; gap: 6px 12px; }
  [data-ui="v12"] .v2jrow > div { min-width: 0; }
  [data-ui="v12"] .yv { flex: 1 1 140px; }}

/* --------------------------------------------------------------- reports -- */
[data-ui="v12"] .v2repcols {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 14px; align-items: start;
}
@container (max-width: 1000px) {
  [data-ui="v12"] .v2repcols { grid-template-columns: minmax(0, 1fr); }}

/* ----------------------------------------------------------------- batch -- */
[data-ui="v12"] .v2batchcols {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start;
}
@container (max-width: 1000px) {
  [data-ui="v12"] .v2batchcols { grid-template-columns: minmax(0, 1fr); }}

/* ------------------------------------------------------------ production -- */
[data-ui="v12"] .v2prodcols {
  display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 14px; align-items: start;
}
[data-ui="v12"] .v2stations {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 14px;
  align-items: start;
}
[data-ui="v12"] .v2station.drop { border-color: var(--acc); box-shadow: inset 0 0 0 1px var(--acc); }
[data-ui="v12"] .v2trayjob {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-bottom: 1px solid var(--bd); cursor: grab;
}
[data-ui="v12"] .v2trayjob:hover { background: var(--srf-2); }
[data-ui="v12"] .v2order {
  margin: 8px; padding: 9px 10px; cursor: grab;
  border: 1px solid var(--bd-2); border-radius: var(--r-s); background: var(--srf-2);
}
[data-ui="v12"] .v2order.cutting { border-color: var(--acc); background: var(--acc-soft); }
[data-ui="v12"] .v2orderact {
  display: flex; align-items: center; gap: 4px; margin-top: 8px; flex-wrap: wrap;
}
[data-ui="v12"] .v2fin {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-top: 1px solid var(--bd); background: var(--srf-2);
}
@container (max-width: 900px) {
  [data-ui="v12"] .v2prodcols { grid-template-columns: minmax(0, 1fr); }}

/* -------------------------------------------------------------- quick job -- */
[data-ui="v12"] .v2qjcols {
  display: grid; grid-template-columns: 330px minmax(0, 1fr); gap: 14px; align-items: start;
}
[data-ui="v12"] .v2qjcols .tbl tr.err td { background: color-mix(in srgb, var(--err) 8%, transparent); }
[data-ui="v12"] .v2qjcols .tbl .inp { padding: 3px 6px; font-size: 12.5px; min-height: 26px; }
[data-ui="v12"] .v2qjcols .v2seg .btn.sm { padding: 3px 7px; }
@container (max-width: 1000px) {
  [data-ui="v12"] .v2qjcols { grid-template-columns: minmax(0, 1fr); }}

/* The keyboard contract, stated once above the grid. Nobody discovers
   Enter-copies-the-row-above by accident, and it is the difference between
   typing a 40-row list and clicking through one. */
[data-ui="v12"] .v2qjkeys {
  padding: 7px 13px; border-bottom: 1px solid var(--bd); background: var(--srf-2);
  white-space: normal; overflow: visible; text-overflow: clip;
}
[data-ui="v12"] .v2qjkeys b { font-weight: 650; color: var(--ink-2); }

/* Offcut stock — one card per remainder board, dimensions on top and the
   board's own edge trim under them. */
[data-ui="v12"] .v2qjsw { display: flex; align-items: center; gap: 6px; cursor: pointer; }
[data-ui="v12"] .v2qjsw span { font-size: 12.5px; color: var(--ink-2); }
[data-ui="v12"] .v2qjnote { white-space: normal; overflow: visible; text-overflow: clip; }
[data-ui="v12"] .v2qjoff {
  border: 1px solid var(--bd-2); border-radius: var(--r-s);
  padding: 10px; background: var(--srf-2);
}
[data-ui="v12"] .v2qjoffrow {
  display: grid; grid-template-columns: 1fr 1fr 66px 30px; gap: 7px; align-items: end;
}
[data-ui="v12"] .v2qjofftrim { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
/* ---------------------------------------------------------- export sheet -- */
/* The cockpit's Export menu, as rows rather than a dropdown: the same five
   exits (print, pack, quote, CSV, program) with room to say what each one
   produces. A menu of bare verbs is what made people ask which one gives the
   saw its file. */
[data-ui="v12"] .v2exp { display: grid; gap: 4px; }
[data-ui="v12"] .v2exprow {
  display: grid; gap: 1px; text-align: left; width: 100%;
  padding: 9px 11px; border: 1px solid var(--bd-2); border-radius: var(--r-s);
  background: var(--srf); cursor: pointer; font: inherit; color: var(--ink);
}
[data-ui="v12"] .v2exprow:hover { background: var(--srf-2); border-color: var(--acc); }
[data-ui="v12"] .v2exprow b { font-size: 13px; font-weight: 600; }

/* ------------------------------------------------- tool strip, grouped ---- */
/* The strip carries three kinds of action and used to run them together as one
   undifferentiated row: tools that re-run the engine, one that changes shop
   stock, and the exits that produce paper and machine files. Same buttons,
   read left to right as change-the-plan → stock → what-comes-out, with the one
   irreversible action last so it is never a neighbour of a casual click.
   .csep is the design's own command-bar divider (v12.css), reused here. */
[data-ui="v12"] .v2tools .csep {
  width: 1px; height: 20px; background: var(--bd); margin: 0 4px; flex: none;
}
[data-ui="v12"] .tgrp {
  font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); margin-right: 2px; flex: none;
}
/* The view toggles sit in the drawing's own header, where a segmented control
   has to line up with 28px buttons rather than the 34px default. */
[data-ui="v12"] .nhead .v2seg > .btn { height: 28px; }
[data-ui="v12"] .nhead .csep {
  width: 1px; height: 20px; background: var(--bd); margin: 0 5px; flex: none;
}

/* The strip and its pinned primary action. The row scrolls; the action does
   not — see the note in v2_tools.jsx. */
[data-ui="v12"] .v2toolbar {
  display: flex; align-items: stretch; flex: none;
  border-top: 1px solid var(--bd); background: var(--srf-2); min-width: 0;
}
[data-ui="v12"] .v2toolbar > .v2tools {
  flex: 1 1 auto; min-width: 0; border-top: 0;
}
[data-ui="v12"] .v2tools-pin {
  display: flex; align-items: center; gap: 6px; flex: none;
  padding: 7px 10px 7px 8px;
  /* a hairline and a hint of the surface, so the pinned button reads as
     anchored rather than as the last item of a row that happens to end here */
  border-left: 1px solid var(--bd); background: var(--srf-2);
}

/* The zoom dock belongs to the DRAWING, not to the column. The design anchors
   it 112px off the bottom of its own nest panel; here the panel also carries
   the tool strip and the board reel, so that offset dropped the dock 29px past
   the drawing and straight on top of the pinned Send button (measured). Anchor
   it inside the drawing area instead, where it can only ever overlap the
   board it zooms. */
[data-ui="v12"] .v2canvbox { position: relative; }
[data-ui="v12"] .v2canvbox > .zoomdock,
[data-ui="v12"] .nest .zoomdock { position: absolute; right: 14px; bottom: 14px; top: auto; }

/* The strip carries six actions plus two dividers in a column that is often
   ~560px. At the design's 6px gap the last button clipped by 15px, and a
   half-visible button reads as broken rather than as "scroll me". */
[data-ui="v12"] .v2tools { gap: 5px; padding-left: 8px; padding-right: 8px; }

/* -------------------------------------------------- cut lines draw in ----- */
/* The design ships @keyframes draw (stroke-dashoffset → 0) for exactly this
   and nothing used it. The cuts now draw themselves in SAW ORDER when a board
   comes up: it is a plan you are meant to read as a sequence, and a static
   web of lines does not say which comes first.

   Animating stroke-dasharray rather than the offset is what keeps the resting
   look intact — the keyframes do not hold their end state, so each line falls
   back to the stylesheet's dashed 5 3 the moment it finishes. With
   pathLength="1" on the element, "0 1" is an undrawn line and "1 0" is a fully
   drawn one whatever its real length. */
@keyframes v2cutdraw { from { stroke-dasharray: 0 1; } to { stroke-dasharray: 1 0; } }
[data-ui="v12"] .v2cut {
  animation: v2cutdraw .42s cubic-bezier(.4, 0, .2, 1) backwards;
  animation-delay: calc(var(--ci, 0) * 22ms);
}
/* The cut being made in Cut mode is the operator's focus — it should be there
   the instant they advance, not draw itself while they wait at the machine. */
[data-ui="v12"] .v2cut.now { animation: none; }
@media (prefers-reduced-motion: reduce) {
  [data-ui="v12"] .v2cut { animation: none; }
}

/* --------------------------------------------- the optimizing overlay ----- */
/* The design's .opt / .optbox / .optlog / .sweep are all in the ported sheet
   already; these are the two pieces it does not define — the spinner glyph in
   the box header, and confining the overlay to the DRAWING rather than the
   page, so the parts list and telemetry stay readable while the engine runs. */
[data-ui="v12"] .ncol.mid > .opt { position: absolute; inset: 0; }
[data-ui="v12"] .v2spin {
  width: 15px; height: 15px; flex: none; border-radius: 50%;
  border: 2px solid var(--acc-line); border-top-color: var(--acc);
  animation: v2spin .7s linear infinite;
}
@keyframes v2spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  [data-ui="v12"] .v2spin { animation-duration: 2.4s; }
  [data-ui="v12"] .opt .sweep { display: none; }
}

/* ------------------------------------------------------ rails, as designed -- */
/* Part index: the grain marker rides on the size line, because grain decides
   whether the engine may turn the piece. */
[data-ui="v12"] .pgrain {
  margin-left: 7px; padding: 0 5px; border-radius: var(--r-xs);
  background: var(--srf-3); border: 1px solid var(--bd);
  font-family: var(--m); font-size: 10px; color: var(--ink-3);
}
[data-ui="v12"] .prow.on .pgrain { background: var(--srf); border-color: var(--acc-line); }

/* Selected part: pinned under the index, so the detail does not scroll away
   from the list it belongs to. */
[data-ui="v12"] .pselbox {
  flex: none; border-top: 1px solid var(--bd); background: var(--srf-2);
  padding: 10px 12px 12px;
}
[data-ui="v12"] .pselbox .spec { padding: 5px 0; font-size: 12px; }
[data-ui="v12"] .pselbox .spec b { font-size: 12px; }

/* Plan ranking bars — the design's .srank, whose middle element is the track. */
[data-ui="v12"] .srank { display: flex; align-items: center; gap: 9px; padding: 4px 0; }
[data-ui="v12"] .srank .n { width: 104px; font-size: 12px; color: var(--ink-2); }
[data-ui="v12"] .srank.best .n { color: var(--acc); font-weight: 600; }
[data-ui="v12"] .srank .p { width: 44px; text-align: right; font-family: var(--m); font-size: 11px; color: var(--ink-3); }
[data-ui="v12"] .srank .grow { min-width: 20px; }

/* Output: the primary exit full width, the four documents two-up beneath. */
[data-ui="v12"] .v2outgrid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 6px;
}
[data-ui="v12"] .v2outgrid .btn { width: 100%; }

/* ----------------------------------------------- overflow menu sections -- */
/* Seventeen unlabelled rows is a list you scan, not one you read — and the
   design groups them. The typography is the design's own menu-section
   treatment (.wsmenu .pgsec: transparent, no rules, tight top padding), so a
   heading here reads the same as a heading in the workspace menu rather than
   introducing a second style for the same idea. The first one loses its top
   margin; a menu should not open with empty space. */
[data-ui="v12"] .menupop .msec {
  padding: 9px 10px 3px; margin-top: 3px;
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4);
}
[data-ui="v12"] .menupop .msec:first-child { margin-top: 0; padding-top: 4px; }
