/* GENERATED FILE — do not edit directly. Source: studio-widget/src/QuoterraCanvas.css. Rebuild via `npm run build:studio` (repo root). */
/* Document CONTENT (the .paper below) is styled to match Jaring's own General Template
   PDF (routes/pdf/generalPdf.js: Helvetica family, 9.5pt body, black text, justified
   paragraphs, underlined section headers; lib/pdf/helpers.js: letterhead/footer placement
   and page margins) — NOT ported from Document_editor's own visual design.
   Canvas CHROME (toolbar/buttons/panels below) uses this app's own actual brand palette
   (public/index.html's Tailwind color remap: indigo-600 #ba8750 = primary action,
   green-600 #39b54a = save/success, plus stock Tailwind gray/blue) so the tab reads as
   part of this app, not a distinct imported tool. */

.jm-studio-canvas { display: flex; flex-direction: column; gap: 12px; font-family: Arial, Helvetica, sans-serif; color: #111827; }
.jm-studio-canvas * { box-sizing: border-box; }
.jm-studio-canvas button { font: inherit; cursor: pointer; background: #fff; border: 1px solid #d1d5db; border-radius: 6px; padding: 4px 8px; color: #374151; }
.jm-studio-canvas button:hover { background: #f9fafb; }
.jm-studio-canvas select, .jm-studio-canvas input[type="number"] { font: inherit; border: 1px solid #d1d5db; border-radius: 6px; padding: 3px 4px; }

/* ---- Action bar (Edit/Download/Save/Cancel) — always the first thing in the tab ---- */
.jm-studio-canvas .studio-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding-bottom: 4px; }
.jm-studio-canvas .save-state { font-size: 12px; color: #6b7280; margin-right: auto; }
.jm-studio-canvas .save-state-failed { color: #b3261e; font-weight: 600; }
.jm-studio-canvas .btn-primary, .jm-studio-canvas .btn-save { border-radius: 8px; padding: 8px 16px; font-size: 14px; font-weight: 500; color: #fff; border: none; }
.jm-studio-canvas .btn-primary { background: #ba8750; }
.jm-studio-canvas .btn-primary:hover { background: #9e7344; }
.jm-studio-canvas .btn-save { background: #39b54a; }
.jm-studio-canvas .btn-save:hover { background: #309a3f; }
.jm-studio-canvas .btn-cancel { border-radius: 8px; padding: 8px 16px; font-size: 14px; font-weight: 500; background: #fff; border: 1px solid #d1d5db; color: #374151; }
.jm-studio-canvas .btn-cancel:hover { background: #f9fafb; }
.jm-studio-canvas .btn-download { border-radius: 8px; padding: 8px 12px; font-size: 13px; font-weight: 500; background: #fff; }
.jm-studio-canvas .btn-download-pdf { border: 1px solid #a4ddac; color: #309a3f; }
.jm-studio-canvas .btn-download-pdf:hover { background: #f5fbf6; }
.jm-studio-canvas .btn-download-word { border: 1px solid #93c5fd; color: #1d4ed8; }
.jm-studio-canvas .btn-download-word:hover { background: #eff6ff; }
.jm-studio-canvas .btn-download-template { border: 1px solid #d1d5db; color: #374151; }
.jm-studio-canvas .btn-download-template:hover { background: #f9fafb; }

/* ---- Toolbar ---- */
.jm-studio-canvas .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 8px 10px; background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; position: sticky; top: 0; z-index: 20; }
.jm-studio-canvas .tool-group { display: flex; align-items: center; gap: 4px; padding-right: 8px; border-right: 1px solid #e5e7eb; }
.jm-studio-canvas .tool-group:last-of-type { border-right: none; }
.jm-studio-canvas .tool-group label { display: flex; flex-direction: column; font-size: 10px; color: #6b7280; gap: 2px; }
.jm-studio-canvas .tool-group label span { line-height: 1; }
.jm-studio-canvas .spacing-tools input { width: 44px; }
.jm-studio-canvas .size-select input[type="number"] { width: 54px; }
.jm-studio-canvas .select-all-tools button.select-all-active { background: #ba8750; border-color: #ba8750; color: #fff; }
.jm-studio-canvas .select-all-tools button.select-all-active:hover { background: #9e7344; }
.jm-studio-canvas .colour-picker { flex-direction: row !important; align-items: center; gap: 3px; }
.jm-studio-canvas .colour-picker input[type="color"] { width: 20px; height: 20px; padding: 0; border: none; }
.jm-studio-canvas .toolbar-spacer { flex: 1; }
.jm-studio-canvas .insert-wrap { position: relative; }
.jm-studio-canvas .insert-menu { position: absolute; right: 0; top: calc(100% + 4px); background: #fff; border: 1px solid #d1d5db; border-radius: 8px; box-shadow: 0 6px 18px rgba(0,0,0,.12); display: flex; flex-direction: column; min-width: 140px; z-index: 30; }
.jm-studio-canvas .insert-menu button { border: none; border-radius: 0; text-align: left; padding: 8px 12px; }

/* ---- Canvas / page ---- */
.jm-studio-canvas .canvas-area { display: flex; flex-direction: column; gap: 8px; }
.jm-studio-canvas .ruler-wrap { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.jm-studio-canvas .zoom-control { display: flex; align-items: center; gap: 6px; }
/* Shared by both "Adjust Page Zoom:" and "Adjust Document Margins:" — one rule so the two
   can never drift out of sync (same font-size), rather than two separately-maintained
   selectors that happen to match today. */
.jm-studio-canvas .ruler-wrap-label { font-size: 12px; color: #374151; white-space: nowrap; }
.jm-studio-canvas .zoom-control-label { margin-right: 2px; }
/* Extra breathing room specifically between the zoom cluster and this button (on top of
   ruler-wrap's own gap, which still applies between this button and the margins cluster). */
.jm-studio-canvas .orientation-button { display: flex; align-items: center; gap: 5px; white-space: nowrap; margin-left: 24px; }
/* Destructive-tinted border (matches the pattern of colour-coding action intent used by
   .btn-download-pdf/.btn-download-word) so it doesn't read as just another neutral tool.
   Disabled — no pageMap yet, only one page, still probing, or the last page starts
   mid-table (see deleteLastPage/canDeleteLastPage) — falls back to the plain look. */
.jm-studio-canvas .delete-last-page-button { border-color: #f3aca6; color: #b7413e; white-space: nowrap; }
.jm-studio-canvas .delete-last-page-button:hover:not(:disabled) { background: #fdf3f2; }
.jm-studio-canvas .delete-last-page-button:disabled { color: #9ca3af; border-color: #d1d5db; cursor: not-allowed; }
/* Margin sliders stay on one line (Top/Left/Right/Bottom in a row) with a leading label —
   narrower ranges than the old 88px, and full words instead of single-letter abbreviations
   per label, so all four plus the label still fit without wrapping in the ruler-wrap's
   remaining width. */
.jm-studio-canvas .margin-controls { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.jm-studio-canvas .margin-range { width: 56px; }
.jm-studio-canvas .margin-field { display: flex; align-items: center; gap: 3px; font-size: 11px; color: #6b7280; }
.jm-studio-canvas .margin-field > span { white-space: nowrap; }
.jm-studio-canvas .margin-field > b { min-width: 20px; font-weight: 600; color: #374151; text-align: right; }
.jm-studio-canvas .page-stage { display: flex; justify-content: center; padding: 16px 0 40px; background: #f3f4f6; border-radius: 8px; }
.jm-studio-canvas .paper-frame { position: relative; }
.jm-studio-canvas .paper {
  position: absolute; top: 0; left: 0; width: 794px; min-height: 1123px; background: #fff;
  box-shadow: 0 2px 14px rgba(0,0,0,.18); font-size: 9.5pt; line-height: 1.4;
  /* Inter-block spacing tiers — the CSS-px equivalents (×96/72) of the fixed-point spacers
     the PDFKit renderers use (lib/pdf/helpers.js: PDF_LINE_GAP 4pt / PDF_TEXT_GAP 6pt /
     PDF_NORMAL_GAP 8pt / PDF_TABLE_GAP 15pt / PDF_HEADER_GAP 16pt). Every gap between
     document blocks below is expressed as one of these so the on-screen canvas and the
     headless-Chrome PDF match the classic per-qtype PDF's vertical rhythm. Adjust a tier
     here and it moves everywhere at once. */
  --jm-gap-line: 5px;
  --jm-gap-text: 8px;
  --jm-gap-block: 11px;
  --jm-gap-table: 20px;
  --jm-gap-header: 21px;
}
.jm-studio-canvas .paper.landscape { width: 1123px; min-height: 794px; }

/* ---- Restore hidden items-table columns ---- */
.jm-studio-canvas .restore-columns { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.jm-studio-canvas .restore-columns > span { font-size: 12px; color: #6b7280; }
.jm-studio-canvas .restore-columns button { font-size: 12px; padding: 3px 8px; border: 1px dashed #d1d5db; color: #ba8750; }
.jm-studio-canvas .restore-columns button:hover { background: #fcf9f6; border-color: #ba8750; }

/* ---- Sections ---- */
.jm-studio-canvas .document-section { position: relative; }
/* Default gap between two consecutive document sections — the PDFKit renderers' own
   between-block spacer (PDF_NORMAL_GAP 8pt ≈ --jm-gap-block). It collapses with the
   sections' own edge margins, so a boundary that needs a bigger tier (a table gap, the
   letter-opening's header gap) raises it via the block's own margin below; this is the
   floor. A "space:<id>" drag/dock override still wins — it's an inline style. */
.jm-studio-canvas .paper .document-section + .document-section { margin-top: var(--jm-gap-block); }
/* Section controls stay pinned once you click anywhere in a section (QuoterraCanvas.tsx /
   studioShared.tsx set `section-active`) — no longer a hover reveal that flickers as the
   pointer moves. Sizing is 1.5x the original. */
.jm-studio-canvas .document-section.section-active .section-controls { opacity: 1; visibility: visible; pointer-events: auto; }
.jm-studio-canvas .document-section.section-active { outline: 1px dashed #d8c3ad; outline-offset: 3px; }
/* Full-text + icon buttons (Move up/Hide/Duplicate/etc., plus the custom-table row/column
   ops and Insert) don't fit on one inline strip like the old icon-only version — wraps
   onto multiple lines instead of overflowing off the right edge of the viewport. The
   section label and the table-ops sub-group each force their own row via flex-basis:100%.
   Every section's popover is always in the DOM (opacity-only shows/hides it for the fade
   transition) — now that it can be several rows tall, a non-active section's own popover
   can easily sit underneath (or overlap) the one you're looking at. pointer-events:none +
   visibility:hidden keep an invisible popover from ever intercepting a click meant for the
   visible one (a real bug: clicks were landing on the wrong section's buttons — #222). */
.jm-studio-canvas .section-controls { position: absolute; right: -4px; top: -4px; transform: translateX(100%); display: flex; flex-wrap: wrap; gap: 3px; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .1s; background: #fff; border: 1px solid #d1d5db; border-radius: 9px; padding: 4px; z-index: 10; max-width: 280px; }
.jm-studio-canvas .section-controls span.section-controls-label { flex-basis: 100%; font-size: 13px; color: #6b7280; padding: 0 4px 2px; white-space: nowrap; }
.jm-studio-canvas .section-controls button { padding: 3px 7px; font-size: 12px; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
.jm-studio-canvas .section-controls button.is-active { background: #ba8750; color: #fff; border-color: #ba8750; }
/* Custom-table row/column/shading/border ops — only rendered when the active section is a
   user-inserted table block (see editSelectedTable's custom-table guard). Broken onto its
   own row, separated from the section-level buttons above it. */
.jm-studio-canvas .section-controls .table-ops { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 3px; border-top: 1px dashed #e5e7eb; padding-top: 4px; margin-top: 2px; }
.jm-studio-canvas .section-hidden { opacity: .35; }
.jm-studio-canvas .section-hidden-content { pointer-events: none; }
.jm-studio-canvas .space-selected { outline: 1px dashed #ba8750; outline-offset: 2px; }

/* ---- Inter-block spacing (spacing.tsx's <BlockSpacer>) — a thin edit-mode handle above
   AND below any block (one of each, per SectionFrame); drag the grip to grow that edge's
   gap, click to target it for the Before/After dock. Same class/styling either way — only
   the JSX position (before vs. after the section's content) and the grip's title text
   differ per edge. */
.jm-studio-canvas .block-spacer { position: relative; height: 9px; cursor: pointer; }
.jm-studio-canvas .block-spacer::before { content: ""; position: absolute; left: 0; right: 0; top: 4px; border-top: 1px dashed transparent; }
.jm-studio-canvas .block-spacer:hover::before, .jm-studio-canvas .block-spacer-selected::before { border-top-color: #d8c3ad; }
.jm-studio-canvas .block-spacer-grip { position: absolute; left: 50%; top: 1px; width: 34px; height: 7px; margin-left: -17px; border-radius: 4px; background: #e7dccd; cursor: row-resize; opacity: 0; transition: opacity .1s; }
.jm-studio-canvas .block-spacer:hover .block-spacer-grip, .jm-studio-canvas .block-spacer-selected .block-spacer-grip { opacity: 1; }
body.resizing-block-gap, body.resizing-block-gap * { cursor: row-resize !important; user-select: none; }
.jm-studio-canvas.is-preview .block-spacer { display: none; }

/* ---- Letterhead / recipient block ---- */
.jm-studio-canvas .template-letterhead img { max-width: 175px; display: block; margin-bottom: 12px; }
.jm-studio-canvas .letterhead-fallback { font-size: 16pt; margin-bottom: 12px; }
.jm-studio-canvas .template-recipient { font-size: 9.5pt; color: #000; margin-top: 8px; }
.jm-studio-canvas .template-line { margin-bottom: 2px; outline-offset: 2px; }
.jm-studio-canvas .template-line.selected-template-line { outline: 1px dashed #7a8f83; }
.jm-studio-canvas .recipient-attn-block { font-weight: 700; font-style: italic; }
/* The letter-opening run (date / Attn block / address+phone+fax / salutation / RE) —
   generalPdf.js & proposalPdf.js put a full PDF_HEADER_GAP (16pt) between the date line,
   the whole recipient info block, and salutation/RE, while every line *within* that
   recipient info block (Attn/Title/Department/Company/Address/Tel/Fax) sits at natural
   line height with genuinely ZERO gap between them (plain sequential doc.text() calls,
   no spacer). Match that exactly: header gap after the date line and around salutation/
   RE; margin-bottom:0 both inside the Attn block (its own descendant-selector rule below)
   AND on Address/Tel/Fax (.template-recipient-tight, applied directly since those three
   sit outside recipient-attn-block — they must stay regular-weight/non-italic, unlike
   that block's own bold-italic styling) — the generic .template-line 2px default was
   still a visible, if small, gap versus the Attn block's true flush zero. Address/Tel/Fax
   read as one tight block regardless of which of them is actually last; the visual gap
   before "Dear" still lands correctly either way: template-salutation's own margin-top is
   a sibling CSS margin that collapses to the larger value against whichever line precedes
   it. */
.jm-studio-canvas .template-date-line { margin-bottom: var(--jm-gap-header); }
.jm-studio-canvas .recipient-attn-block .template-line,
.jm-studio-canvas .template-recipient-tight { margin-bottom: 0; }
.jm-studio-canvas .template-salutation { margin-top: var(--jm-gap-header); margin-bottom: var(--jm-gap-header); }
.jm-studio-canvas .template-subject { margin-top: var(--jm-gap-header); margin-bottom: var(--jm-gap-header); }
.jm-studio-canvas .template-subject strong { text-decoration: underline; text-transform: uppercase; }
.jm-studio-canvas .format-field-shell.selected-format-field .dynamic-field { outline: 1px dashed #7a8f83; }
.jm-studio-canvas .dynamic-field { display: inline; }

/* ---- Narrative / rich text ---- */
.jm-studio-canvas .editable-copy { display: block; margin: var(--jm-gap-text) 0; text-align: justify; white-space: pre-wrap; }
.jm-studio-canvas [contenteditable="true"] { outline: none; }
.jm-studio-canvas [contenteditable="true"]:focus { box-shadow: 0 0 0 2px rgba(46,125,90,.25); border-radius: 2px; }
/* ---- Exchange Rate Table (matches generalPdf.js's boxed label/rate rows) ---- */
.jm-studio-canvas .rate-table { width: 100%; border-collapse: collapse; margin: var(--jm-gap-block) 0 var(--jm-gap-table); }
.jm-studio-canvas .rate-table td { border: 1px solid #000; padding: 4px 6px; vertical-align: top; }
.jm-studio-canvas .rate-table-header { font-weight: 700; }
.jm-studio-canvas .rate-table-rate { font-weight: 700; width: 140px; }

/* ---- Payable Conditions (matches pdfPayableConditionsBlock) ---- */
.jm-studio-canvas .payable-block h2 { font-size: 9.5pt; font-weight: 700; margin: var(--jm-gap-block) 0 var(--jm-gap-line); }
.jm-studio-canvas .payable-table { width: 100%; border-collapse: collapse; }
.jm-studio-canvas .payable-table td { border: 1px solid #000; padding: 5px 6px; text-align: left; }

/* ---- Items table (matches generalPdf.js's black-border, bold-header look — header
   shade #d5d5d5 == pdfSegGenericTable's '#D5D5D5' / builders.js DX_GREY) ---- */
.jm-studio-canvas .quote-table { width: 100%; border-collapse: collapse; margin: var(--jm-gap-block) 0 var(--jm-gap-table); font-size: 9.5pt; }
.jm-studio-canvas .quote-table th, .jm-studio-canvas .quote-table td { border: 1px solid #000; padding: 5px 6px; vertical-align: top; text-align: left; position: relative; }
.jm-studio-canvas .quote-table th { font-weight: 700; background: #d5d5d5; }
.jm-studio-canvas .quote-table td strong { display: block; }
.jm-studio-canvas .quote-table td span { display: block; font-size: 8.5pt; color: #333; }
/* Est. Quantity/Volume — the value and its unit are one field ("5,253.48 Kg", giVolumeLines
   embeds the unit) and neither is bold (no <strong> wrapper, unlike Unit Price/Total). Each
   dynamicText() call's own wrapper span (.format-field-shell) is a DIRECT child of this td
   for the centred numeric columns (every other column with a sibling span — Description's
   stacked SW Code/HS Code lines — nests it inside a non-td-direct wrapper instead), so
   scoping this inline override to a direct child here can't affect that stacking. Also
   re-inlines the INNER .dynamic-field span, not just the outer shell — the generic
   "td span { display: block }" rule above outranks the standalone top-level
   ".dynamic-field { display: inline }" rule (more classes+tags = higher specificity). */
.jm-studio-canvas .quote-table td.col-center > span.format-field-shell,
.jm-studio-canvas .quote-table td.col-center > span.format-field-shell .dynamic-field { display: inline; }
/* Est. Quantity/Volume, Unit Price, Tax, Total — numeric columns, centered not left-indented. */
.jm-studio-canvas .quote-table th.col-center, .jm-studio-canvas .quote-table td.col-center { text-align: center; }
/* Empty Tax/Duty cell (QuoterraCanvas.tsx's quotationCell) — darker than the header's own
   #d5d5d5 shade so an empty cell reads as clearly "nothing here" at a glance, not a subtle
   tint. Printed blank (no dash) — see lib/pdf/studio/general.js's
   mv(giItemHasNoTax(...) ? '' : ...) gate that feeds this. lib/docx/builders.js's
   dxGeneralItemsTableBlocks uses the same B0B0B0 hex for the matching Word cell shading —
   keep the two in sync. */
.jm-studio-canvas .quote-table td.cell-empty { background: #b0b0b0; }
.jm-studio-canvas .quote-table th { padding-right: 16px; }
.jm-studio-canvas .th-hide { position: absolute; top: 1px; right: 1px; padding: 0 3px; font-size: 10px; line-height: 1.3; border: 1px solid #cfd8d3; border-radius: 3px; background: #fff; opacity: 0; transition: opacity .1s; }
.jm-studio-canvas .quote-table th:hover .th-hide { opacity: 1; }
.jm-studio-canvas .row-resize-handle { position: absolute; left: 0; bottom: -3px; width: 100%; height: 6px; background: transparent; z-index: 3; cursor: row-resize; }
body.resizing-table-column, body.resizing-table-column * { cursor: col-resize !important; user-select: none; }
body.resizing-table-row, body.resizing-table-row * { cursor: row-resize !important; user-select: none; }

/* ---- Resizable tables (tableLayout.tsx's <ResizableTable>): a positioned wrapper with a
   full-height drag handle straddling every internal column border, plus one on the table's
   outer right edge that resizes the whole table. The wrapped table is table-layout:fixed
   and its column grid is set by a <colgroup>. ---- */
.jm-studio-canvas .rtable-wrap { position: relative; }
.jm-studio-canvas .paper .rtable-wrap > table { table-layout: fixed; }
.jm-studio-canvas .col-border-handle { position: absolute; top: 0; height: 100%; width: 9px; transform: translateX(-50%); cursor: col-resize; z-index: 6; }
.jm-studio-canvas .col-border-handle::after { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; transform: translateX(-50%); background: transparent; transition: background .1s; }
.jm-studio-canvas .rtable-wrap:hover .col-border-handle::after { background: rgba(186,135,80,.35); }
.jm-studio-canvas .col-border-handle:hover::after { background: #ba8750; }
/* Whole-table width handle — a thicker bar with a centre grip so it reads differently from
   the thin column-border lines. */
.jm-studio-canvas .table-width-handle { position: absolute; top: 0; height: 100%; width: 12px; transform: translateX(-50%); cursor: ew-resize; z-index: 7; }
.jm-studio-canvas .table-width-handle::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 3px; transform: translateX(-50%); background: transparent; transition: background .1s; }
.jm-studio-canvas .table-width-handle::after { content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 26px; transform: translate(-50%, -50%); border-radius: 3px; background: transparent; border: 1px solid transparent; transition: background .1s, border-color .1s; }
.jm-studio-canvas .rtable-wrap:hover .table-width-handle::before { background: rgba(186,135,80,.35); }
.jm-studio-canvas .rtable-wrap:hover .table-width-handle::after { background: #fff; border-color: #ba8750; }
.jm-studio-canvas .table-width-handle:hover::before { background: #ba8750; }
.jm-studio-canvas .table-width-handle:hover::after { background: #ba8750; border-color: #ba8750; }
.jm-studio-canvas.is-preview .col-border-handle, .jm-studio-canvas.is-preview .table-width-handle, .jm-studio-canvas.is-preview .th-hide { display: none; }
.jm-studio-canvas .product-image-cell { text-align: center; }
.jm-studio-canvas .product-image-wrap { position: relative; }
.jm-studio-canvas .product-image-wrap img { width: 100%; height: 48px; display: block; }
.jm-studio-canvas .image-controls { display: flex; flex-wrap: wrap; gap: 2px; justify-content: center; margin-top: 3px; }
.jm-studio-canvas .image-controls button { padding: 0 4px; font-size: 9px; }
.jm-studio-canvas .image-placeholder-static { font-size: 8.5pt; color: #8a938e; }
.jm-studio-canvas .grand-total-row td { font-weight: 700; border-top: 2px solid #000; }

/* ---- Terms & SST note (matches generalPdf.js's lettered a)/b)/c) convention) ---- */
.jm-studio-canvas .terms-block h2 { font-size: 9.5pt; font-weight: 700; font-style: italic; text-decoration: underline; margin: var(--jm-gap-block) 0 var(--jm-gap-line); }
.jm-studio-canvas .lettered-list { margin: 0; }
/* align-items:baseline + zeroed child margin keeps the marker level with the first line
   of its entry — Settlement's terms render through NarrativeField (.editable-copy, which
   carries margin:10px 0) so without this the number floated 10px above its text; min-width
   on the marker keeps every entry's text starting at the same x for 1.–11. numbering
   (General's a)/b) markers are single-width so this is a no-op there). */
.jm-studio-canvas .lettered-item { display: flex; gap: 8px; margin-bottom: var(--jm-gap-line); align-items: baseline; }
.jm-studio-canvas .lettered-item .editable-copy { margin: 0; }
.jm-studio-canvas .letter-marker { flex-shrink: 0; min-width: 1.7em; }
.jm-studio-canvas .sst-note { font-style: italic; font-size: 9pt; margin: var(--jm-gap-text) 0 0; }
/* generalPdf.js puts a full PDF_HEADER_GAP between the closing paragraph and "Thank you.",
   and another before the signature — the signature's own margin-top carries the second. */
.jm-studio-canvas .thank-you { margin: var(--jm-gap-header) 0 0; }

/* ---- Signature block — name/title only, no captured signature image and no reserved
   wet-ink band: quotations are no longer physically signed, the "This is a system
   generated quotation" note (.signature-note below) covers that now. ---- */
.jm-studio-canvas .signature { margin-top: var(--jm-gap-header); font-size: 9.5pt; }
.jm-studio-canvas .signature-columns { display: flex; justify-content: space-between; }
.jm-studio-canvas .signature-col { width: 45%; }
.jm-studio-canvas .signature-col p { margin: 0 0 2px; }
.jm-studio-canvas .signatory-company { font-weight: 700; }
.jm-studio-canvas .signatory-name { font-weight: 700; }
.jm-studio-canvas .signatory-title { font-weight: 700; font-size: 9pt; }
.jm-studio-canvas .company-stamp { display: block; width: 60px; height: 60px; margin: var(--jm-gap-table) auto 0; }
.jm-studio-canvas .signature-note { margin: var(--jm-gap-table) 0 0; font-size: 7pt; text-align: center; }

/* ---- Footer (matches lib/pdf/helpers.js's pdfDrawFooter exactly — static, no data) ---- */
.jm-studio-canvas .document-footer { margin-top: 32px; padding-top: 6px; border-top: 0.8px solid #000; font-size: 7pt; color: #000; }
.jm-studio-canvas .document-footer p { margin: 2px 0; }
.jm-studio-canvas .document-footer p:nth-child(2) { font-size: 6.5pt; }
.jm-studio-canvas .document-footer-contact { display: flex; justify-content: space-between; }

/* ---- Custom blocks ---- */
.jm-studio-canvas .custom-content-zone { display: block; margin: var(--jm-gap-block) 0; }
.jm-studio-canvas .custom-content-zone.custom-table table.custom-table { width: 100%; border-collapse: collapse; }
.jm-studio-canvas .custom-content-zone table.custom-table td { border: 1px solid #000; padding: 5px 6px; }
.jm-studio-canvas .manual-page-break { border-top: 1px dashed #9aa6a0; text-align: center; margin: 16px 0; }
.jm-studio-canvas .manual-page-break span { background: #eef1ef; font-size: 9px; color: #5a655f; padding: 0 6px; position: relative; top: -8px; }

/* ---- Page boundaries (pageBreakGuides.tsx) — the continuous sheet split into pages at the
   EXACT positions the exported PDF breaks (from a headless render, POST /:id/page-map). The
   break element is tagged `data-jm-page-start` (a data attr — survives React reconciliation,
   unlike a className); the CSS opens a clean white gap and the component floats an
   opaque-white strip + a "Page N" chip into it. ---- */
:root { --jm-page-gap: 44px; }
/* The gap ABOVE a section that starts a page — ::before is in-flow and pushes content down;
   the section's own inter-section margin is cancelled so the gap is exactly --jm-page-gap. */
.jm-studio-canvas .paper .document-section[data-jm-page-start] { margin-top: 0; }
.jm-studio-canvas .paper .document-section[data-jm-page-start]::before {
  content: ""; display: block; height: var(--jm-page-gap); background: #fff;
}
/* A table row that starts a page — rows can't carry a ::before box, so the gap is cell
   padding. A per-cell ::before fills that padding zone with opaque white, poking ±1px into
   neighbours so the vertical divider stubs go too; it starts at top:0 (inside the border
   box) so the row ABOVE keeps its own crisp, table-snapped bottom border at the top of the
   gap. A per-cell ::after draws the table's top edge on the new page just above the resumed
   content — cell-width, so the cells join into a line exactly as wide as the table, not a
   full-content-width rule. Both are on-screen only (hidden in @media print). */
.jm-studio-canvas .paper tr[data-jm-page-start] > td,
.jm-studio-canvas .paper tr[data-jm-page-start] > th { padding-top: var(--jm-page-gap); position: relative; }
.jm-studio-canvas .paper tr[data-jm-page-start] > td::before,
.jm-studio-canvas .paper tr[data-jm-page-start] > th::before {
  content: ""; position: absolute; z-index: 6;
  top: 0; left: -2px; right: -2px; height: calc(var(--jm-page-gap) - 1px);
  background: #fff;
}
.jm-studio-canvas .paper tr[data-jm-page-start] > td::after,
.jm-studio-canvas .paper tr[data-jm-page-start] > th::after {
  content: ""; position: absolute; z-index: 7;
  left: 0; right: 0; top: calc(var(--jm-page-gap) - 1px);
  border-top: 1px solid #000;
}
/* Strip sitting in the gap (absolute inside the scaled .paper, pre-transform coords) —
   carries the "Page N" chip only. The gap fill is CSS-driven (::before above for both a
   section break and a table-row break), so this stays transparent. */
.jm-studio-canvas .pbg-boundary { position: absolute; left: 0; right: 0; height: calc(var(--jm-page-gap) + 1px); pointer-events: none; z-index: 7; }
/* A dotted line runs the full page width at the boundary's vertical center, same red as
   the "Page N" pin below — the pin (a later, position:absolute sibling of this ::before)
   paints on top of it with an opaque background, so the line visually terminates at the
   pin's edges and resumes past it, reading as one guide threading through the pin rather
   than two disconnected marks. */
.jm-studio-canvas .pbg-boundary::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; border-top: 1.5px dotted #b7413e;
}
.jm-studio-canvas .pbg-label {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size: 13px; font-weight: 600; letter-spacing: .02em;
  color: #b7413e; background: #fff; border: 1px solid #e6c3c1; border-radius: 999px; padding: 4px 14px; line-height: 1.5;
}
.jm-studio-canvas .pbg-calculating {
  position: absolute; right: 6px; top: 6px; z-index: 8; font-size: 10px; color: #6b7280;
  background: #fff; border: 1px solid #e5e7eb; border-radius: 999px; padding: 2px 10px; pointer-events: none;
}


/* ---- Spacing dock / preview / misc ---- */
.jm-studio-canvas .spacing-dock { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 8px 12px; background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; font-size: 12px; }
.jm-studio-canvas .spacing-dock label { display: flex; align-items: center; gap: 4px; }
.jm-studio-canvas .spacing-dock output { min-width: 20px; text-align: center; }
.jm-studio-canvas .restore-sections { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.jm-studio-canvas .toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background: #1f2a24; color: #fff; padding: 8px 14px; border-radius: 6px; font-size: 12px; display: flex; align-items: center; gap: 6px; z-index: 50; }

/* ---- Print ---- */
@media print {
  body * { visibility: hidden; }
  .jm-studio-canvas, .jm-studio-canvas .paper, .jm-studio-canvas .paper * { visibility: visible; }
  .jm-studio-canvas .toolbar, .jm-studio-canvas .ruler-wrap, .jm-studio-canvas .spacing-dock, .jm-studio-canvas .studio-actions, .jm-studio-canvas .section-controls, .jm-studio-canvas .toast { display: none !important; }
  /* Editing affordances that live inside .paper — hide from the rendered PDF. The page-gap
     decoration (pbg-*, data-jm-page-start) is on-screen only; the probe returns no map in a
     headless mount so the tags are never set here anyway — hidden defensively. */
  .jm-studio-canvas .col-border-handle, .jm-studio-canvas .table-width-handle, .jm-studio-canvas .th-hide, .jm-studio-canvas .row-resize-handle, .jm-studio-canvas .block-spacer,
  .jm-studio-canvas .pbg-boundary, .jm-studio-canvas .pbg-calculating { display: none !important; }
  .jm-studio-canvas .paper .document-section[data-jm-page-start]::before,
  .jm-studio-canvas .paper tr[data-jm-page-start] > td::before,
  .jm-studio-canvas .paper tr[data-jm-page-start] > th::before,
  .jm-studio-canvas .paper tr[data-jm-page-start] > td::after,
  .jm-studio-canvas .paper tr[data-jm-page-start] > th::after { display: none !important; }
  /* .page-stage is display:flex/justify-content:center for on-screen viewing (centers
     the page in the gray canvas background) — left uncancelled, the printed .paper (now
     width:auto below) sits centered inside that flex box instead of flush against the
     page's own left margin, since it shrink-wraps narrower than the full print area. */
  .jm-studio-canvas .page-stage { display: block; background: none; padding: 0; }
  .jm-studio-canvas .paper-frame { width: auto !important; height: auto !important; }
  /* Padding zeroed — the page margin now comes from Chrome's page.pdf() so it repeats on
     EVERY page (CSS padding on this continuous element only lands on page 1's top and the
     last page's bottom). renderFormattedPdf.js sets it from pageSettings. min-height is
     zeroed too: the 1123px/794px figures (QuoterraCanvas.css:83/97) are a full on-screen
     A4 sheet, purely so a short document still looks like a full page while editing.
     Chrome's per-physical-page printable height is necessarily less than that (margins
     plus HEADER_BAND_CM/FOOTER_BAND_CM eat into it — renderFormattedPdf.js), so leaving
     the forced min-height in place guaranteed a content-free second page — just the
     repeating header/footer bands — for any document shorter than one full sheet. */
  .jm-studio-canvas .paper { position: static; box-shadow: none; transform: none !important; width: auto; padding: 0 !important; min-height: 0 !important; }

  /* The letterhead logo and the company footer print via page.pdf()'s native repeating
     header/footer templates (lib/pdf/renderFormattedPdf.js), reserved in HEADER_BAND_CM /
     FOOTER_BAND_CM of the top / bottom page margin. The in-flow `.template-letterhead` and
     `.document-footer` are on-screen-only — hidden here so they can't render a second time
     (the footer fragmented across the page break as a position:fixed element, since
     Chromium's print path doesn't reliably repeat those). The recipient block below the
     letterhead stays in flow — only the logo repeats. */
  .jm-studio-canvas .template-letterhead,
  .jm-studio-canvas .document-footer { display: none !important; }

  /* ---- Page-break conventions — Chrome (page.pdf()) auto-paginates this continuous
     document; these rules make it break BETWEEN sections rather than through content.
     pageBreakGuides.tsx packs the same sections to predict where the breaks land. ---- */
  /* Whole sections stay together and jump to the next page rather than split... */
  .jm-studio-canvas .document-section { break-inside: avoid; page-break-inside: avoid; }
  /* ...except the ones that legitimately span pages — those break at row boundaries. */
  .jm-studio-canvas .document-section[data-section-id="items"],
  .jm-studio-canvas .document-section[data-section-id="sectionB"],
  .jm-studio-canvas .document-section[data-section-id="groups"] { break-inside: auto; page-break-inside: auto; }
  /* Never split a table row. */
  .jm-studio-canvas .paper tr { break-inside: avoid; page-break-inside: avoid; }
  /* A long expandable row (Section B's per-row formula breakdown) is allowed to split —
     forcing it whole would push a multi-line cell wholesale to the next page. */
  .jm-studio-canvas .tmpl-settlement .settle-b-formula,
  .jm-studio-canvas .tmpl-settlement .settle-b-formula td { break-inside: auto; page-break-inside: auto; }
  /* Keep a heading with the content it introduces. */
  .jm-studio-canvas .paper h2, .jm-studio-canvas .payable-block h2, .jm-studio-canvas .terms-block h2,
  .jm-studio-canvas .settle-section-label, .jm-studio-canvas .rsm-group-heading, .jm-studio-canvas .rsm-sub-bar,
  .jm-studio-canvas .rsm-terms h2, .jm-studio-canvas .mh-title, .jm-studio-canvas .mh-section-title td,
  .jm-studio-canvas .settle-lme-heading, .jm-studio-canvas .mh-lme-line { break-after: avoid; page-break-after: avoid; }
  /* Minimum lines of any paragraph kept together at a page edge. */
  .jm-studio-canvas .editable-copy, .jm-studio-canvas .lettered-item, .jm-studio-canvas .lettered-item *,
  .jm-studio-canvas .rsm-term, .jm-studio-canvas .mh-remarks-body, .jm-studio-canvas .settle-docblock p,
  .jm-studio-canvas .custom-content-zone p { orphans: 3; widows: 3; }
  .jm-studio-canvas .paper img, .jm-studio-canvas .company-stamp,
  .jm-studio-canvas .product-image-wrap { break-inside: avoid; page-break-inside: avoid; }
  /* Repeat a real <thead> on every page a long table spans. */
  .jm-studio-canvas .paper thead { display: table-header-group; }
  /* Manual "Insert > Page break" — on screen it's a dashed marker with a label; in print it
     must actually force a break instead of just being a decorative line (it had no real
     effect on the exported PDF before this). Kept as a zero-height box (not display:none)
     because a display:none element generates no box for break-before to act on. */
  .jm-studio-canvas .manual-page-break { break-before: page; page-break-before: always; border: none; margin: 0; height: 0; overflow: hidden; }
  .jm-studio-canvas .manual-page-break span { visibility: hidden; }
}

/* ============================================================================
   PER-TEMPLATE STYLES — settlement / mhydroxide / rsmrskformula
   Each block is scoped to .paper.tmpl-<name> so it can't affect General's canvas.
   Metrics approximate the matching routes/pdf/<type>Pdf.js renderer; fine-tune
   against a real rendered PDF.
   ============================================================================ */

/* ---- Shared small helpers used by the sibling canvases ---- */
.jm-studio-canvas .paper .rsm-c,
.jm-studio-canvas .paper .mh-c { text-align: center; }
.jm-studio-canvas .paper .mh-r { text-align: right; }

/* ---- RSM / RSK Formula Price ---- */
.jm-studio-canvas .paper.tmpl-rsmrskformula { font-size: 9.5pt; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-box { margin: var(--jm-gap-block) 0 var(--jm-gap-table); }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-box-heading { font-weight: 700; font-size: 9.5pt; margin-bottom: var(--jm-gap-line); }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-table { width: 100%; border-collapse: collapse; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-table td { border: 1px solid #000; padding: 4px 6px; font-size: 9pt; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-table td:first-child { width: 60%; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-rate-value { font-weight: 700; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-group { margin: var(--jm-gap-table) 0; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-group-heading { font-weight: 700; font-size: 10.5pt; text-decoration: underline; margin-bottom: var(--jm-gap-line); }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-sub-bar { font-weight: 700; font-size: 9.5pt; background: #d9d9d9; border: 1px solid #000; padding: 3px 6px; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-formula-table { width: 100%; border-collapse: collapse; margin-top: -1px; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-formula-table th { background: #b0b0b0; border: 1px solid #000; padding: 5px 3px; font-size: 8.5pt; text-align: center; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-formula-table td { border: 1px solid #000; padding: 4px 6px; font-size: 9pt; vertical-align: middle; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-formula-cell { font-size: 8pt; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-terms { margin-top: var(--jm-gap-table); }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-terms h2 { font-size: 9.5pt; font-weight: 700; text-decoration: underline; margin: 0 0 var(--jm-gap-text); }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-term { margin-bottom: var(--jm-gap-text); font-size: 9.5pt; }
/* align-items:baseline + zeroed child margin keeps the number level with the first line
   of its term — the term text renders through NarrativeField (.editable-copy, which
   carries margin:8px 0), so without this the number floated above its text (same bug
   as .lettered-item, see the comment above that rule). */
.jm-studio-canvas .tmpl-rsmrskformula .rsm-term-first { display: flex; gap: 6px; align-items: baseline; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-term-first .editable-copy { margin: 0; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-term-cont { padding-left: 18px; }
.jm-studio-canvas .tmpl-rsmrskformula .rsm-term-num { flex-shrink: 0; width: 16px; }

/* ---- Metal Hydroxide ---- */
.jm-studio-canvas .paper.tmpl-mhydroxide { font-size: 8pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-title { font-size: 9pt; font-weight: 700; margin: 6px 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-info-block { margin: 6px 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-info-line { display: flex; gap: 8px; margin: 2px 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-info-label { width: 130px; flex-shrink: 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-lme-line { margin: var(--jm-gap-block) 0; font-size: 8pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-lme-sep { margin-left: 24px; }
.jm-studio-canvas .tmpl-mhydroxide .mh-rate-table { border-collapse: collapse; width: 75%; margin: var(--jm-gap-block) 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-rate-table td, .jm-studio-canvas .tmpl-mhydroxide .mh-rate-table th { border: 1px solid #000; padding: 3px 6px; font-size: 8pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-rate-group th { font-weight: 700; text-align: right; }
.jm-studio-canvas .tmpl-mhydroxide .mh-rate-group th:first-child { text-align: left; }
.jm-studio-canvas .tmpl-mhydroxide .mh-sampling-table { border-collapse: collapse; width: 100%; margin: var(--jm-gap-block) 0; }
.jm-studio-canvas .tmpl-mhydroxide .mh-sampling-table td, .jm-studio-canvas .tmpl-mhydroxide .mh-sampling-table th { border: 1px solid #000; padding: 3px 5px; font-size: 8pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-sampling-hdr th { font-weight: 700; text-align: center; }
.jm-studio-canvas .tmpl-mhydroxide .mh-returns-table, .jm-studio-canvas .tmpl-mhydroxide .mh-charges-table { border-collapse: collapse; width: 100%; margin: var(--jm-gap-table) 0; border: 1px solid #000; }
.jm-studio-canvas .tmpl-mhydroxide .mh-returns-table td, .jm-studio-canvas .tmpl-mhydroxide .mh-charges-table td { padding: 3px 5px; font-size: 8pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-section-title td { background: #d5d5d5; font-weight: 700; font-size: 7.5pt; text-align: center; }
.jm-studio-canvas .tmpl-mhydroxide .mh-returns-hdr td, .jm-studio-canvas .tmpl-mhydroxide .mh-charges-hdr td { font-weight: 700; text-align: center; border-bottom: 1px solid #000; }
.jm-studio-canvas .tmpl-mhydroxide .mh-total-row td { font-weight: 700; }
.jm-studio-canvas .tmpl-mhydroxide .mh-net-payable { border: 1px solid #000; padding: 6px 8px; margin: var(--jm-gap-table) 0; display: flex; justify-content: space-between; font-size: 9.5pt; font-weight: 700; }
.jm-studio-canvas .tmpl-mhydroxide .mh-remarks { margin: var(--jm-gap-block) 0; font-size: 8.5pt; }
.jm-studio-canvas .tmpl-mhydroxide .mh-remarks-label { margin: 0 0 2px; }
/* Same fix as .rsm-term-first above — zero the NarrativeField's default top margin so the
   "-" prefix stays level with the remarks text instead of floating above it. */
.jm-studio-canvas .tmpl-mhydroxide .mh-remarks-body { display: flex; gap: 3px; align-items: baseline; }
.jm-studio-canvas .tmpl-mhydroxide .mh-remarks-body .editable-copy { margin: 0; }

/* ---- Recovery Settlement ---- */
.jm-studio-canvas .paper.tmpl-settlement { font-size: 9pt; }
.jm-studio-canvas .tmpl-settlement .settle-section { margin: var(--jm-gap-table) 0; }
.jm-studio-canvas .tmpl-settlement .settle-section-label { font-size: 9pt; font-weight: 700; margin-bottom: var(--jm-gap-line); }
.jm-studio-canvas .tmpl-settlement .settle-lme-box { margin: var(--jm-gap-block) 0; }
.jm-studio-canvas .tmpl-settlement .settle-lme-heading { font-weight: 700; font-size: 8.5pt; margin-bottom: var(--jm-gap-line); }
.jm-studio-canvas .tmpl-settlement .settle-a-table { border-collapse: collapse; margin: var(--jm-gap-line) 0; font-size: 8.5pt; width: auto; }
/* Extra separation between the stacked Section A tables (A1 / A2 / A3). Targets the
   ResizableTable wrapper divs (.rtable-wrap), not .settle-a-table itself — each
   SectionATable renders as <div class="rtable-wrap"><table class="settle-a-table">, so
   the <table> elements are never direct siblings of each other and a ".settle-a-table +
   .settle-a-table" selector never matched (confirmed: without this fix the tables only
   ever got the base 5px --jm-gap-line margin, not this tier). Larger than the shared
   --jm-gap-table tier on purpose — this gap looked visually too tight even at 20px. */
.jm-studio-canvas .tmpl-settlement .settle-section > .rtable-wrap + .rtable-wrap { margin-top: 32px; }
.jm-studio-canvas .tmpl-settlement .settle-a-table td, .jm-studio-canvas .tmpl-settlement .settle-a-table th { border: 1px solid #000; padding: 4px 6px; text-align: center; }
.jm-studio-canvas .tmpl-settlement .settle-a-table th { background: #d5d5d5; font-weight: 700; }
.jm-studio-canvas .tmpl-settlement .settle-b-table { border-collapse: collapse; width: 100%; margin: var(--jm-gap-line) 0; font-size: 8pt; }
.jm-studio-canvas .tmpl-settlement .settle-b-table td, .jm-studio-canvas .tmpl-settlement .settle-b-table th { border: 1px solid #000; padding: 3px 4px; text-align: center; vertical-align: top; white-space: pre-line; }
.jm-studio-canvas .tmpl-settlement .settle-b-table th { background: #ececec; font-weight: 700; }
.jm-studio-canvas .tmpl-settlement .settle-b-formula td { text-align: left; font-size: 7.5pt; background: #fafafa; }
.jm-studio-canvas .tmpl-settlement .settle-b-total td { font-weight: 700; }
.jm-studio-canvas .tmpl-settlement .settle-pc-waived { text-decoration: line-through; color: #888; }
.jm-studio-canvas .tmpl-settlement .settle-docblock { margin: var(--jm-gap-block) 0; }
.jm-studio-canvas .tmpl-settlement .settle-docblock h3 { font-size: 9pt; font-weight: 700; margin: 0 0 var(--jm-gap-line); }
.jm-studio-canvas .tmpl-settlement .settle-docblock-table { border-collapse: collapse; width: 100%; font-size: 8.5pt; }
.jm-studio-canvas .tmpl-settlement .settle-docblock-table td, .jm-studio-canvas .tmpl-settlement .settle-docblock-table th { border: 1px solid #000; padding: 3px 6px; }
