.docbuilder-designer {
    min-height: 400px;
}

.docbuilder-designer .mud-paper {
    height: 100%;
}

.docbuilder-block-preview {
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 6px;
    padding: 12px;
    margin-bottom: 8px;
    cursor: pointer;
}

.docbuilder-block-preview.active {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 2px rgba(63, 81, 181, 0.12);
}

.docbuilder-block-preview .block-type {
    font-size: 0.75rem;
    text-transform: uppercase;
    color: var(--mud-palette-grey-600);
}

.docbuilder-block-preview .block-content {
    font-size: 0.95rem;
    color: var(--mud-palette-text-primary);
}

.docbuilder-field-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    margin: 4px;
    border-radius: 999px;
    background-color: rgba(63, 81, 181, 0.08);
    color: var(--mud-palette-primary);
    font-size: 0.75rem;
    cursor: pointer;
}

.docbuilder-outline-list {
    list-style: decimal inside;
    padding-left: 1rem;
}

.docbuilder-outline-list li {
    margin-bottom: 4px;
}

.docbuilder-preview-frame {
    border: 1px solid rgba(0,0,0,0.12);
    border-radius: 8px;
    padding: 24px;
    max-height: 600px;
    overflow-y: auto;
    background-color: white;
}

/* -------------------------------------------------------------------------
   Canvas Editor v2 — rich text read-only display (Sprint 02)
   ------------------------------------------------------------------------- */

.canvas-lab-rich-island {
    border: 1px solid #d4d4d8;
    border-radius: 6px;
    padding: 6px 8px;
    background: #fafafa;
    font-family: ui-sans-serif, system-ui, sans-serif;
}

.canvas-lab-rich-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}

.canvas-lab-rich-chip {
    font-size: 0.62rem;
    padding: 1px 8px;
    border-radius: 9999px;
    background: #ede9fe;
    color: #5b21b6;
    border: 1px solid #c4b5fd;
    line-height: 1.4;
    letter-spacing: 0.02em;
}

.canvas-lab-rich-body {
    line-height: 1.5;
    color: #18181b;
    word-break: break-word;
}

.canvas-lab-rich-body--paragraph {
    font-size: 11pt;
}

.canvas-lab-rich-body--heading {
    font-weight: 700;
    line-height: 1.25;
}

.canvas-lab-rich-body--heading-1 { font-size: 1.7rem; }
.canvas-lab-rich-body--heading-2 { font-size: 1.45rem; }
.canvas-lab-rich-body--heading-3 { font-size: 1.25rem; }
.canvas-lab-rich-body--heading-4 { font-size: 1.1rem; }
.canvas-lab-rich-body--heading-5 { font-size: 1rem; }
.canvas-lab-rich-body--heading-6 { font-size: 0.92rem; text-transform: uppercase; letter-spacing: 0.05em; }

.canvas-lab-rich-body--quote {
    border-left: 3px solid #c4b5fd;
    padding-left: 12px;
    margin: 0;
    color: #3f3f46;
    font-style: italic;
}

.canvas-lab-quote-caption {
    margin-top: 4px;
    font-size: 0.75rem;
    color: #71717a;
}

.canvas-lab-rich-body strong { font-weight: 700; }
.canvas-lab-rich-body em { font-style: italic; }
.canvas-lab-rich-body u { text-decoration: underline; }
.canvas-lab-rich-body s { text-decoration: line-through; color: #6b7280; }

.canvas-lab-rich-body .canvas-lab-mark-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 0.92em;
    background: #f1f5f9;
    border: 1px solid #e2e8f0;
    border-radius: 3px;
    padding: 0 4px;
}

.canvas-lab-rich-body .canvas-lab-mark-link {
    color: #4338ca;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* -------------------------------------------------------------------------
   ProseMirror Inline Editing V1 (per-block paragraph / heading / quote)
   ------------------------------------------------------------------------- */

.canvas-inline-editor {
    border: 1px solid #d4d4d8;
    border-radius: 6px;
    padding: 6px 8px;
    background: #ffffff;
    font-family: ui-sans-serif, system-ui, sans-serif;
}

.canvas-inline-editor--readonly {
    background: #fafafa;
    opacity: 0.85;
}

.canvas-inline-editor-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}

.canvas-inline-editor-btn {
    font-size: 0.78rem;
    padding: 2px 8px;
    border-radius: 4px;
    background: #f4f4f5;
    color: #3f3f46;
    border: 1px solid #d4d4d8;
    cursor: pointer;
    line-height: 1.3;
}

.canvas-inline-editor-btn:hover { background: #e4e4e7; }
.canvas-inline-editor-btn:active { background: #d4d4d8; }

.canvas-inline-editor-debug {
    margin-left: auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 0.62rem;
    color: #71717a;
}

.canvas-inline-editor-host {
    line-height: 1.5;
    color: #18181b;
    word-break: break-word;
    min-height: 1.6em;
    outline: none;
}

.canvas-inline-editor-host .ProseMirror {
    outline: none;
    min-height: 1.4em;
}

.canvas-inline-editor-host .ProseMirror p,
.canvas-inline-editor-host .ProseMirror h1,
.canvas-inline-editor-host .ProseMirror h2,
.canvas-inline-editor-host .ProseMirror h3,
.canvas-inline-editor-host .ProseMirror h4,
.canvas-inline-editor-host .ProseMirror h5,
.canvas-inline-editor-host .ProseMirror h6,
.canvas-inline-editor-host .ProseMirror blockquote {
    margin: 0;
}

.canvas-inline-editor--heading-1 .canvas-inline-editor-host { font-size: 1.7rem; font-weight: 700; line-height: 1.25; }
.canvas-inline-editor--heading-2 .canvas-inline-editor-host { font-size: 1.45rem; font-weight: 700; line-height: 1.25; }
.canvas-inline-editor--heading-3 .canvas-inline-editor-host { font-size: 1.25rem; font-weight: 700; line-height: 1.3; }
.canvas-inline-editor--heading-4 .canvas-inline-editor-host { font-size: 1.1rem; font-weight: 700; line-height: 1.3; }
.canvas-inline-editor--heading-5 .canvas-inline-editor-host { font-size: 1rem; font-weight: 700; line-height: 1.4; }
.canvas-inline-editor--heading-6 .canvas-inline-editor-host { font-size: 0.92rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }

.canvas-inline-editor--quote .canvas-inline-editor-host {
    border-left: 3px solid #c4b5fd;
    padding-left: 12px;
    color: #3f3f46;
    font-style: italic;
}

.canvas-inline-editor-host .ProseMirror strong { font-weight: 700; }
.canvas-inline-editor-host .ProseMirror em { font-style: italic; }
.canvas-inline-editor-host .ProseMirror u { text-decoration: underline; }
.canvas-inline-editor-host .ProseMirror a {
    color: #4338ca;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.canvas-inline-editor-host .pm-field-placeholder {
    display: inline-block;
    font-size: 0.85em;
    padding: 0 6px;
    border-radius: 9999px;
    background: #ede9fe;
    color: #5b21b6;
    border: 1px solid #c4b5fd;
    line-height: 1.6;
    margin: 0 1px;
    white-space: nowrap;
}

.canvas-lab-rich-body .canvas-lab-mark-link:hover {
    color: #312e81;
}

.canvas-lab-rich-body .canvas-lab-mark-highlight {
    background: #fef9c3;
    color: inherit;
    padding: 0 2px;
    border-radius: 2px;
}

.canvas-lab-field-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    margin: 0 2px;
    border-radius: 9999px;
    background: rgba(63, 81, 181, 0.10);
    color: #3730a3;
    font-size: 0.78em;
    font-family: ui-sans-serif, system-ui, sans-serif;
    font-weight: 500;
    border: 1px solid rgba(63, 81, 181, 0.25);
    white-space: nowrap;
    vertical-align: baseline;
}

.canvas-lab-field-pill--unresolved {
    background: #fef3c7;
    color: #92400e;
    border-color: #fde68a;
}

/* -------------------------------------------------------------------------- */
/* Editor v2 Right Rail + WYSIWYG sprint — block chrome cleanup (global).     */
/*                                                                            */
/* Goal: in the default operator view, unselected blocks render close to the  */
/* final preview / PDF output. Editor chrome (badges, type chips, dashed lane */
/* outlines, inline-editor toolbar, debug ids) only appears when the block is */
/* selected, or when Developer tools is on (canvas-lab-canvas-scroll--debug). */
/*                                                                            */
/* All selectors anchor on .canvas-lab-canvas-scroll so the right-rail        */
/* inspector previews, palette previews, and any non-canvas surface keep      */
/* their current styling.                                                     */
/*                                                                            */
/* These rules live in the GLOBAL docbuilder stylesheet (not the Blazor       */
/* scoped CanvasEditorLab.razor.css) because the block tree is rendered by    */
/* CanvasEditorLabBlock + CanvasInlineEditor which are separate components    */
/* whose deep descendants are not reachable from the parent's scoped CSS,     */
/* AND because we want the same WYSIWYG cleanup to apply unchanged to the     */
/* V2 document editor (ModernDocumentEditorV2.razor) which reuses the same    */
/* canvas component without its own scoped stylesheet.                        */
/* -------------------------------------------------------------------------- */

/* Chrome that disappears entirely on unselected blocks in WYSIWYG mode.
   display:none (rather than visibility:hidden) so layout matches the eventual
   PDF/preview output exactly and selecting/deselecting does not jitter the
   canvas vertically. */
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-heading-meta,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-card-type-chip,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-card-readonly-badge,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-card-extra-badge,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-card-icon,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-inline-editor-toolbar,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-columns-header,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-column-lane-label,
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-debug-id {
    display: none !important;
}

/* Visual frames become invisible but still occupy layout slots so toggling
   the selection doesn't reflow page breaks. The block frame's existing
   :hover outline (in CanvasEditorLab.razor.css) still gives a subtle hover
   affordance because outlines do not change layout. */
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-readonly-card {
    border-color: transparent;
    background: transparent;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-card-header {
    background: transparent;
    border-color: transparent;
    padding: 2px 0;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-columns {
    border-color: transparent;
    background: transparent;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-lab-column-lane {
    border-color: transparent;
    background: transparent;
    min-height: 0;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame:not(.is-selected) .canvas-inline-editor {
    border-color: transparent;
    background: transparent;
    padding: 0;
}

/* Selected block restores the editor chrome on THE SELECTED block only.
   Hover is intentionally NOT used to reveal chips/labels so pointer movement
   does not flicker the canvas; the block frame outline already gives a
   pointer-driven affordance. */
.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame.is-selected .canvas-lab-readonly-card {
    border-color: #d4d4d8;
    background: #fafafa;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame.is-selected .canvas-lab-card-header {
    background: #f4f4f5;
    border-bottom: 1px solid #e4e4e7;
    padding: 5px 8px;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame.is-selected .canvas-lab-columns {
    border-color: #c7d2fe;
    background: #f8fafc;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame.is-selected .canvas-lab-column-lane {
    border-color: #a5b4fc;
    background: linear-gradient(180deg, #ffffff 0%, #f5f3ff 100%);
    min-height: 48px;
}

.canvas-lab-canvas-scroll:not(.canvas-lab-canvas-scroll--debug)
    .canvas-lab-block-frame.is-selected .canvas-inline-editor {
    border-color: #d4d4d8;
    background: #ffffff;
    padding: 6px 8px;
}

/* Developer-tools boundaries: when devtools is on, paint a faint dashed
   outline on every block + every column lane so structural debugging is
   obvious. Independent of selection. The --debug class is added to the
   scroll container by CanvasEditorLab.razor / ModernDocumentEditorV2.razor
   when their _devTools flag is true. */
.canvas-lab-canvas-scroll--debug .canvas-lab-block-frame {
    outline: 1px dashed color-mix(in srgb, var(--mud-palette-secondary, #7c3aed) 40%, transparent);
    outline-offset: 1px;
}

.canvas-lab-canvas-scroll--debug .canvas-lab-column-lane {
    outline: 1px dotted color-mix(in srgb, #4338ca 35%, transparent);
    outline-offset: 1px;
}

/* -------------------------------------------------------------------------- */
/* Canvas Visual Parity V1 — QuestPDF-led canvas tokens.                      */
/*                                                                            */
/* Source of truth: `ModernDocumentCanvasVisualTokens` in                     */
/* `Application/Features/ModernDocumentBuilder/Canonical/Editor/`.            */
/* Contract document: `src/docs/ModernDocumentBuilder-QuestPdfLedCanvasVisual */
/* Contract.md`. Numeric values mirror the QuestPDF canonical PDF renderers   */
/* under `Infrastructure/Services/Documents/CanonicalPdf/` so the canvas      */
/* matches the final PDF output without inventing browser-only styling.       */
/*                                                                            */
/* These tokens are scoped to `.canvas-lab-canvas-scroll` so they only apply  */
/* to the Editor v2 / V2 document canvas surfaces. Right-rail previews,       */
/* palette tiles, dialog previews, and any non-canvas surface keep their      */
/* existing styling unchanged.                                                */
/* -------------------------------------------------------------------------- */

.canvas-lab-canvas-scroll {
    /* Body / page typography. Defaults match QuestPDF (Helvetica, 11pt, near-black on white). */
    --canon-body-font-family: Helvetica, Arial, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --canon-body-font-size: 11pt;
    --canon-body-line-height: 1.45;
    --canon-text-color: #18181b;
    --canon-background-color: #ffffff;

    /* Paragraph + heading rhythm — matches CanonicalTextBlockRenderer.RenderParagraph / RenderHeading. */
    --canon-paragraph-spacing-bottom: 4pt;
    --canon-heading-spacing-top: 6pt;
    --canon-heading-spacing-bottom: 2pt;
    --canon-heading-font-weight: 700;
    --canon-heading-1-size: calc(var(--canon-body-font-size) + 10pt);
    --canon-heading-2-size: calc(var(--canon-body-font-size) + 6pt);
    --canon-heading-3-size: calc(var(--canon-body-font-size) + 3pt);
    --canon-heading-4-size: calc(var(--canon-body-font-size) + 1pt);

    /* Quote — left rule + italic body + grey caption (matches CanonicalTextBlockRenderer.RenderQuote). */
    --canon-quote-border-color: #c7d2fe;
    --canon-quote-border-width: 2pt;
    --canon-quote-padding-left: 8pt;
    --canon-quote-padding-vertical: 4pt;
    --canon-quote-color: var(--canon-text-color);
    --canon-quote-caption-color: #6b7280;
    --canon-quote-caption-size: calc(var(--canon-body-font-size) - 1pt);

    /* Table — relative columns, optional header row, 0.5pt borders, 4pt cell padding (matches
       CanonicalTableBlockRenderer.Render). */
    --canon-table-border-color: #d4d4d8;
    --canon-table-border-width: 0.5pt;
    --canon-table-cell-padding: 4pt;
    --canon-table-header-bg: #f4f4f5;
    --canon-table-cell-size: calc(var(--canon-body-font-size) - 0.5pt);

    /* List — 20pt marker column, 2pt item spacing (matches CanonicalListBlockRenderer.Render). */
    --canon-list-marker-width: 20pt;
    --canon-list-item-spacing: 2pt;
    --canon-list-spacing-top: 2pt;
    --canon-list-spacing-bottom: 4pt;

    /* Delimiter — 0.5pt rule with 8pt vertical padding (matches CanonicalDelimiterRenderer.Render). */
    --canon-delimiter-color: #a1a1aa;
    --canon-delimiter-thickness: 0.5pt;
    --canon-delimiter-padding-vertical: 8pt;

    /* fieldPlaceholder — 2pt vertical padding, plain body text (matches CanonicalFieldPlaceholderRenderer.Render). */
    --canon-field-placeholder-padding-vertical: 2pt;

    /* Media / Image UX V1 (2026-05-12) — image / logo / imageLayout shapes mirroring the
       canonical QuestPDF renderers. Image: 4pt vertical padding around the figure + 2pt
       gap above the caption (CanonicalImageBlockRenderer). Border: 0.5pt #e2e8f0 (matches
       the renderer). Caption: base-1pt grey. Empty state: muted grey card. ImageLayout:
       slot gap 6pt + 4pt vertical padding (matches the renderer's `Row.Spacing(6f)` and
       `PaddingVertical(2f)` ranges). */
    --canon-image-padding-vertical: 4pt;
    --canon-image-caption-spacing-top: 2pt;
    --canon-image-caption-color: #6b7280;
    --canon-image-caption-size: calc(var(--canon-body-font-size) - 1pt);
    --canon-image-border-color: #e2e8f0;
    --canon-image-border-width: 0.5pt;
    --canon-image-layout-slot-gap: 6pt;
    --canon-image-layout-slot-bg: #fafafa;
    --canon-image-layout-slot-border: #c4b5fd;
    --canon-media-empty-color: #6b7280;
    --canon-media-empty-bg: #f9fafb;
    --canon-media-empty-border: #d1d5db;
}

/* Page body inherits the QuestPDF-led typography. The page shell still has the existing
   shadow + border defined in CanvasEditorLab.razor.css so the surface still reads as paper. */
.canvas-lab-canvas-scroll .canvas-lab-page-body {
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    color: var(--canon-text-color);
}

/* The page shell colour matches the QuestPDF page background. */
.canvas-lab-canvas-scroll .canvas-lab-page-shell {
    background: var(--canon-background-color);
    color: var(--canon-text-color);
}

/* Paragraph / heading / quote — the inline editor host inherits the page typography but the
   per-block size + spacing tokens drive the visual contract. The existing
   `.canvas-inline-editor--heading-N` and `--quote` classes in this file still set the rich-edit
   chrome (border, focus, toolbar); the rules below override their typography only on the canvas. */
.canvas-lab-canvas-scroll .canvas-inline-editor {
    font-family: var(--canon-body-font-family);
    color: var(--canon-text-color);
}

.canvas-lab-canvas-scroll .canvas-inline-editor--paragraph {
    margin-bottom: var(--canon-paragraph-spacing-bottom);
}

.canvas-lab-canvas-scroll .canvas-inline-editor--paragraph .canvas-inline-editor-host {
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    color: var(--canon-text-color);
}

.canvas-lab-canvas-scroll .canvas-inline-editor--heading {
    margin-top: var(--canon-heading-spacing-top);
    margin-bottom: var(--canon-heading-spacing-bottom);
}

/* Heading sizes track the QuestPDF deltas; `font-weight` is set explicitly so we are not
   relying on the browser default for h1..h6 (the host element is a div, not <h*>). */
.canvas-lab-canvas-scroll .canvas-inline-editor--heading-1 .canvas-inline-editor-host {
    font-size: var(--canon-heading-1-size);
    font-weight: var(--canon-heading-font-weight);
    line-height: 1.25;
    text-transform: none;
    letter-spacing: 0;
}

.canvas-lab-canvas-scroll .canvas-inline-editor--heading-2 .canvas-inline-editor-host {
    font-size: var(--canon-heading-2-size);
    font-weight: var(--canon-heading-font-weight);
    line-height: 1.25;
    text-transform: none;
    letter-spacing: 0;
}

.canvas-lab-canvas-scroll .canvas-inline-editor--heading-3 .canvas-inline-editor-host {
    font-size: var(--canon-heading-3-size);
    font-weight: var(--canon-heading-font-weight);
    line-height: 1.3;
    text-transform: none;
    letter-spacing: 0;
}

.canvas-lab-canvas-scroll .canvas-inline-editor--heading-4 .canvas-inline-editor-host,
.canvas-lab-canvas-scroll .canvas-inline-editor--heading-5 .canvas-inline-editor-host,
.canvas-lab-canvas-scroll .canvas-inline-editor--heading-6 .canvas-inline-editor-host {
    font-size: var(--canon-heading-4-size);
    font-weight: var(--canon-heading-font-weight);
    line-height: 1.35;
    /* QuestPDF does not render the legacy "h6 small caps" treatment, so we drop it on canvas
       to match the PDF output. Operators who relied on it can use a level 4 heading. */
    text-transform: none;
    letter-spacing: 0;
}

/* Quote — italic body + 2pt left rule + 8pt left padding mirror the PDF. The rich-edit border
   from `.canvas-inline-editor` is suppressed so unselected quotes look like the PDF. (Selected
   quotes still get the per-selection chrome via the existing chrome rules above.) */
.canvas-lab-canvas-scroll .canvas-inline-editor--quote {
    border-left: var(--canon-quote-border-width) solid var(--canon-quote-border-color);
    padding-left: var(--canon-quote-padding-left);
    padding-top: var(--canon-quote-padding-vertical);
    padding-bottom: var(--canon-quote-padding-vertical);
    border-radius: 0;
    background: transparent;
}

.canvas-lab-canvas-scroll .canvas-inline-editor--quote .canvas-inline-editor-host {
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    font-style: italic;
    color: var(--canon-quote-color);
    border-left: 0;
    padding-left: 0;
}

/* The quote caption (rendered by CanvasEditorLabBlock.razor as `.canvas-lab-quote-caption`)
   should match the PDF caption style: em-dash prefix is supplied by the markup, here we just
   set the typography. */
.canvas-lab-canvas-scroll .canvas-lab-quote-caption {
    margin-top: 2pt;
    font-size: var(--canon-quote-caption-size);
    color: var(--canon-quote-caption-color);
    font-style: normal;
    padding-left: var(--canon-quote-padding-left);
}

/* List — `.canon-list` is the canvas-only container produced by CanvasEditorLabBlock for
   `list` blocks. `.canon-list-item` rows lay marker + content side-by-side using the QuestPDF
   marker-column width. */
.canvas-lab-canvas-scroll .canon-list {
    display: flex;
    flex-direction: column;
    gap: var(--canon-list-item-spacing);
    margin: var(--canon-list-spacing-top) 0 var(--canon-list-spacing-bottom);
    padding: 0;
    list-style: none;
    color: var(--canon-text-color);
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    font-family: var(--canon-body-font-family);
}

.canvas-lab-canvas-scroll .canon-list-item {
    display: flex;
    align-items: flex-start;
    gap: 0;
}

.canvas-lab-canvas-scroll .canon-list-marker {
    flex: 0 0 var(--canon-list-marker-width);
    width: var(--canon-list-marker-width);
    color: var(--canon-text-color);
    font-variant-numeric: tabular-nums;
}

.canvas-lab-canvas-scroll .canon-list-content {
    flex: 1 1 auto;
    min-width: 0;
    word-break: break-word;
}

/* List counter-type warning — surfaces when the canonical block declares an alpha/roman counter
   that QuestPDF cannot reproduce. Visual hint only; the property panel remains the source of
   truth for the underlying value. */
.canvas-lab-canvas-scroll .canon-list-counter-warning {
    margin-top: 4pt;
    font-size: 0.7rem;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fde68a;
    border-radius: 4px;
    padding: 2px 6px;
    display: inline-block;
}

/* List Inline Item Editing V1 (2026-05-12) — `.canon-list--editing` is the selected-state
   editor produced by `CanvasListItemEditor`. Visual layout deliberately mirrors the read-only
   `.canon-list` (same marker column, same line spacing, same font tokens) so the operator sees
   the same shape they will get in the PDF. The per-item input replaces the static
   `.canon-list-content` span; the action buttons render after the input so they don't shift
   the marker / content alignment. Buttons are visible only inside `.canon-list--editing`,
   matching the rule that unselected lists never expose editor chrome. */
.canvas-lab-canvas-scroll .canon-list--editing .canon-list-item--editing {
    align-items: center;
    gap: 4px;
}

.canvas-lab-canvas-scroll .canon-list-item__input {
    flex: 1 1 auto;
    min-width: 0;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: var(--canon-text-color);
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    padding: 1px 4px;
}

.canvas-lab-canvas-scroll .canon-list-item__input:hover {
    border-color: #e4e4e7;
}

.canvas-lab-canvas-scroll .canon-list-item__input:focus {
    outline: none;
    border-color: #6366f1;
    background: #ffffff;
}

.canvas-lab-canvas-scroll .canon-list-item__actions {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-left: 6px;
}

.canvas-lab-canvas-scroll .canon-list-item__btn {
    border: 1px solid #d4d4d8;
    background: #ffffff;
    color: #3f3f46;
    border-radius: 3px;
    padding: 0 6px;
    height: 20px;
    min-width: 20px;
    line-height: 18px;
    font-size: 0.75rem;
    cursor: pointer;
    user-select: none;
}

.canvas-lab-canvas-scroll .canon-list-item__btn:hover:not([disabled]) {
    background: #f4f4f5;
    border-color: #a1a1aa;
}

.canvas-lab-canvas-scroll .canon-list-item__btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

.canvas-lab-canvas-scroll .canon-list-item__btn--danger:hover:not([disabled]) {
    background: #fef2f2;
    border-color: #fecaca;
    color: #b91c1c;
}

.canvas-lab-canvas-scroll .canon-list-add {
    margin-top: 4pt;
}

.canvas-lab-canvas-scroll .canon-list-add-btn {
    border: 1px dashed #a1a1aa;
    background: transparent;
    color: #3f3f46;
    border-radius: 3px;
    padding: 2px 10px;
    font-size: 0.75rem;
    cursor: pointer;
    user-select: none;
}

.canvas-lab-canvas-scroll .canon-list-add-btn:hover {
    background: #f4f4f5;
    border-color: #6366f1;
    border-style: solid;
    color: #1f2937;
}

/* Table — `.canon-table` is the canvas-only `<table>` produced for `table` / `structuredTable`.
   `table-layout: fixed` forces equal relative columns the same way QuestPDF's RelativeColumn
   does. Borders match the 0.5pt PDF rule (rounded to 1 CSS px). Cell padding is 4pt. */
.canvas-lab-canvas-scroll .canon-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    margin: 4pt 0 6pt;
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-table-cell-size);
    color: var(--canon-text-color);
}

.canvas-lab-canvas-scroll .canon-table-cell {
    border: max(1px, var(--canon-table-border-width)) solid var(--canon-table-border-color);
    padding: var(--canon-table-cell-padding);
    vertical-align: top;
    word-break: break-word;
    background: transparent;
}

.canvas-lab-canvas-scroll .canon-table-cell--header {
    background: var(--canon-table-header-bg);
    font-weight: 600; /* SemiBold in QuestPDF */
}

/* Table Grid Editor V1 (2026-05-12) — `.canon-table--editing` is the selected-state grid
   editor produced by `CanvasTableGridEditor`. Visual layout deliberately mirrors the
   read-only `.canon-table` (same column distribution, same border / padding, same fonts)
   so the operator sees the same shape they will get in the PDF. The per-cell input
   replaces the static `<td>` text; the per-row / per-column action bars appear only on
   hover so the unselected resting state stays clean (selection is what already gates the
   editor's mount). */
.canvas-lab-canvas-scroll .canon-table-edit-shell {
    position: relative;
}

.canvas-lab-canvas-scroll .canon-table--editing {
    /* Subtle outline so the operator knows they are editing. The plain `.canon-table` keeps
       its cell borders for the unselected WYSIWYG render. */
    outline: 1px dashed #d4d4d8;
    outline-offset: 2px;
}

.canvas-lab-canvas-scroll .canon-table--editing .canon-table-cell--editing {
    padding: 0;
}

.canvas-lab-canvas-scroll .canon-table-cell__input {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid transparent;
    border-radius: 2px;
    background: transparent;
    color: var(--canon-text-color);
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-table-cell-size);
    line-height: 1.3;
    padding: var(--canon-table-cell-padding);
    margin: 0;
}

.canvas-lab-canvas-scroll .canon-table-cell--header .canon-table-cell__input {
    font-weight: 600;
}

.canvas-lab-canvas-scroll .canon-table-cell__input:hover {
    border-color: #e4e4e7;
}

.canvas-lab-canvas-scroll .canon-table-cell__input:focus {
    outline: none;
    border-color: #6366f1;
    background: #ffffff;
}

.canvas-lab-canvas-scroll .canon-table-edit-col-actions {
    /* Action bars rendered as a regular `<thead>` but stripped of cell chrome so they
       don't look like header cells. */
    background: transparent;
}

.canvas-lab-canvas-scroll .canon-table-edit-col-cell {
    border: 0;
    padding: 0 0 2px;
    background: transparent;
    text-align: center;
    vertical-align: bottom;
}

.canvas-lab-canvas-scroll .canon-table-edit-col-bar {
    display: inline-flex;
    gap: 2px;
    visibility: hidden;
}

.canvas-lab-canvas-scroll .canon-table--editing:hover .canon-table-edit-col-bar,
.canvas-lab-canvas-scroll .canon-table--editing:focus-within .canon-table-edit-col-bar {
    visibility: visible;
}

.canvas-lab-canvas-scroll .canon-table-edit-row-action-spacer {
    border: 0;
    padding: 0;
    width: 0;
    background: transparent;
}

.canvas-lab-canvas-scroll .canon-table-edit-row-actions {
    border: 0;
    padding: 0 0 0 4px;
    background: transparent;
    vertical-align: middle;
    width: 0;
    white-space: nowrap;
}

.canvas-lab-canvas-scroll .canon-table-edit-row-bar {
    display: inline-flex;
    gap: 2px;
    visibility: hidden;
}

.canvas-lab-canvas-scroll .canon-table--editing:hover .canon-table-edit-row-bar,
.canvas-lab-canvas-scroll .canon-table--editing:focus-within .canon-table-edit-row-bar {
    visibility: visible;
}

.canvas-lab-canvas-scroll .canon-table-edit-add-actions {
    display: flex;
    gap: 6px;
    margin-top: 4pt;
}

.canvas-lab-canvas-scroll .canon-table-edit-empty-actions {
    display: flex;
    gap: 6px;
    margin-top: 4pt;
}

/* fieldPlaceholder — plain text block, no chip/pill in normal mode. The dev-tools view (handled
   elsewhere in the chrome rules) still shows the metadata chip when a block is selected. */
.canvas-lab-canvas-scroll .canon-field-placeholder {
    padding: var(--canon-field-placeholder-padding-vertical) 0;
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    color: var(--canon-text-color);
}

.canvas-lab-canvas-scroll .canon-field-placeholder--unbound {
    color: #6b7280;
    font-style: italic;
}

/* Delimiter — match the PDF's 0.5pt #a1a1aa rule with 8pt vertical padding. */
.canvas-lab-canvas-scroll .canon-delimiter {
    border: 0;
    border-top: max(1px, var(--canon-delimiter-thickness)) solid var(--canon-delimiter-color);
    margin: var(--canon-delimiter-padding-vertical) 0;
    background: transparent;
    height: 0;
}

/* -------------------------------------------------------------------------- */
/* Media / Image UX V1 (2026-05-12) — image / logo / imageLayout canvas       */
/* shapes. Scoped to `.canvas-lab-canvas-scroll` so the rules never leak into */
/* the legacy editor (`editor-v2-blocked-panel`), right-rail previews,       */
/* palette tiles, or dialog previews. The canvas mirrors the QuestPDF        */
/* renderers (CanonicalImageBlockRenderer / CanonicalLogoBlockRenderer /     */
/* CanonicalImageLayoutBlockRenderer); the property panel never exposes      */
/* settings the renderer cannot reproduce.                                   */
/* -------------------------------------------------------------------------- */

/* Image block — wrapper aligns the figure (left / center / right); figure carries
   the optional max-width so the alignment wrapper stays full-width. Caption uses
   the same grey + size as the PDF caption (BaseFontSizePt - 1f, #6b7280). */
.canvas-lab-canvas-scroll .canon-image-block {
    padding: var(--canon-image-padding-vertical) 0;
}

.canvas-lab-canvas-scroll .canon-image-figure {
    display: inline-flex;
    flex-direction: column;
}

.canvas-lab-canvas-scroll .canon-image-img {
    display: block;
    max-width: 100%;
    height: auto;
}

.canvas-lab-canvas-scroll .canon-image-img--border {
    border: max(1px, var(--canon-image-border-width)) solid var(--canon-image-border-color);
    padding: 1pt;
    background: var(--canon-background-color);
}

.canvas-lab-canvas-scroll .canon-image-caption {
    margin-top: var(--canon-image-caption-spacing-top);
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-image-caption-size);
    line-height: var(--canon-body-line-height);
    color: var(--canon-image-caption-color);
}

/* Logo block — sized smaller by default (the PDF uses MaxWidth for logos). The
   canvas mirrors that: no maxWidth → natural width; maxWidth → wrapping figure. */
.canvas-lab-canvas-scroll .canon-logo-block {
    padding: 2pt 0;
}

.canvas-lab-canvas-scroll .canon-logo-figure {
    display: inline-flex;
}

.canvas-lab-canvas-scroll .canon-logo-img {
    display: block;
    max-width: 100%;
    height: auto;
}

/* ImageLayout block — slot grids mirror the PDF's `Row.Spacing(6f)` and the
   per-layout sizing. The empty-slot card uses the same muted purple the PDF
   uses for failed slot loads so the canvas reads consistently. */
.canvas-lab-canvas-scroll .canon-image-layout-block {
    padding: 4pt 0;
}

.canvas-lab-canvas-scroll .canon-image-layout-summary {
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-image-caption-size);
    color: var(--canon-image-caption-color);
    margin-bottom: var(--canon-image-layout-slot-gap);
}

.canvas-lab-canvas-scroll .canon-image-layout-grid {
    display: grid;
    gap: var(--canon-image-layout-slot-gap);
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--1 {
    grid-template-columns: 1fr;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--2 {
    grid-template-columns: 1fr 1fr;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--3 {
    grid-template-columns: 1fr 1fr 1fr;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--1-2 {
    /* Large image on the left, two stacked smaller ones on the right. We can't
       perfectly mirror QuestPDF's nested rows in 2-D CSS grid, so we fall back
       to a single row with one large and two stacked smaller slots laid out by
       a nested column flexbox below. */
    grid-template-columns: 1fr 1fr;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--1-2 .canon-image-layout-slot:nth-child(1) {
    grid-row: span 2;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--2-1 {
    grid-template-columns: 1fr 1fr;
}

.canvas-lab-canvas-scroll .canon-image-layout-grid--2-1 .canon-image-layout-slot:nth-child(3) {
    grid-row: span 2;
}

.canvas-lab-canvas-scroll .canon-image-layout-slot {
    display: flex;
    flex-direction: column;
}

.canvas-lab-canvas-scroll .canon-image-layout-slot-img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 180pt;
    object-fit: contain;
    background: var(--canon-background-color);
}

.canvas-lab-canvas-scroll .canon-image-layout-slot-caption {
    margin-top: var(--canon-image-caption-spacing-top);
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-image-caption-size);
    line-height: var(--canon-body-line-height);
    color: var(--canon-image-caption-color);
}

.canvas-lab-canvas-scroll .canon-image-layout-slot--empty .canon-image-layout-slot-empty {
    border: max(1px, var(--canon-image-border-width)) dashed var(--canon-image-layout-slot-border);
    background: var(--canon-image-layout-slot-bg);
    color: #6d28d9;
    font-family: var(--canon-body-font-family);
    font-size: calc(var(--canon-body-font-size) - 2pt);
    padding: 8pt 6pt;
    text-align: center;
    min-height: 60pt;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2pt;
}

.canvas-lab-canvas-scroll .canon-image-layout-slot-empty-title {
    font-weight: 600;
}

.canvas-lab-canvas-scroll .canon-image-layout-slot-empty-hint {
    color: var(--canon-image-caption-color);
}

/* Media empty state — shared between image / logo / imageLayout when nothing is
   configured. Reads as a calm guidance card, not a scary warning, so unselected
   WYSIWYG canvases stay product-grade. */
.canvas-lab-canvas-scroll .canon-media-empty {
    border: 1px dashed var(--canon-media-empty-border);
    background: var(--canon-media-empty-bg);
    color: var(--canon-media-empty-color);
    font-family: var(--canon-body-font-family);
    font-size: var(--canon-body-font-size);
    line-height: var(--canon-body-line-height);
    padding: 12pt 14pt;
    border-radius: 4px;
    min-height: 48pt;
    display: flex;
    flex-direction: column;
    gap: 2pt;
    align-items: flex-start;
    justify-content: center;
}

.canvas-lab-canvas-scroll .canon-image-block--empty .canon-media-empty,
.canvas-lab-canvas-scroll .canon-logo-block--empty .canon-media-empty {
    width: 100%;
    max-width: 320px;
}

.canvas-lab-canvas-scroll .canon-media-empty-title {
    font-weight: 600;
    color: #374151;
    font-size: var(--canon-body-font-size);
}

.canvas-lab-canvas-scroll .canon-media-empty-hint {
    font-size: var(--canon-image-caption-size);
    color: var(--canon-media-empty-color);
}

/* Selected-block + dev-tools overrides: keep the existing chrome cleanup behaviour (declared
   above) authoritative. The new visual blocks `.canon-list`, `.canon-table`,
   `.canon-field-placeholder`, `.canon-delimiter`, `.canon-image-block`, `.canon-logo-block`,
   and `.canon-image-layout-block` are rendered as PDF-shape regardless of selection, so they
   need no additional `:not(.is-selected)` rules — the chrome cleanup CSS suppresses summary
   cards / type chips / debug ids on unselected blocks already. */

/* -------------------------------------------------------------------------- */
/* Editor v2 Shell Polish V1 — independent scrolling shell + compact header.  */
/*                                                                            */
/* Both the template canvas (CanvasEditorLab.razor) and the V2 document       */
/* editor (ModernDocumentEditorV2.razor) wrap their canvas+rail MudGrid in a  */
/* `.canvas-lab-workspace` div. The workspace gets a fixed height computed    */
/* from the viewport and turns its two children into independent scroll       */
/* regions so:                                                                */
/*                                                                            */
/*   - the action bar / banners / metadata card stay above in normal page     */
/*     flow (and never scroll with the canvas)                                */
/*   - the canvas (left) scrolls long documents independently                 */
/*   - the right rail (right) scrolls tall Properties / inspector panels      */
/*     independently and stays visible while the canvas scrolls               */
/*                                                                            */
/* These rules live globally because Blazor scoped CSS only applies to the    */
/* component that owns it, and we want the same behaviour on both editors.    */
/*                                                                            */
/* `Editor v2 Shell Polish V1` (2026-05-12) tightened the viewport offset to  */
/* `180px` (from `220px`) because the page header is now a single compact     */
/* row. The static offset still leaves headroom for the app shell             */
/* (breadcrumbs + global header) and the editor's own action bar so the      */
/* workspace never overflows on standard desktop viewports. Below ~1280px     */
/* viewports the rail stacks under the canvas (the markup uses xs="12") so   */
/* the workspace falls back to natural page flow.                             */
/* -------------------------------------------------------------------------- */
.canvas-lab-workspace {
    display: block;
    height: calc(100vh - 180px);
    min-height: 480px;
}

.canvas-lab-workspace .canvas-lab-canvas-scroll {
    height: 100%;
    min-height: 0;
    margin-bottom: 0;
}

.canvas-lab-workspace .canvas-lab-right-rail {
    /* Override the legacy sticky positioning — inside the workspace the rail
       is sized off the workspace and scrolls independently. */
    position: static;
    top: auto;
    align-self: stretch;
    height: 100%;
    max-height: none;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.canvas-lab-workspace .canvas-lab-right-rail-tabs-paper {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.canvas-lab-workspace .canvas-lab-right-rail-tab-body {
    /* Override the legacy 100vh-based clamp — the workspace height already
       constrains us correctly. */
    max-height: none;
    height: 100%;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Editor v2 Shell Polish V1 — segmented Add / Properties / Document strip.
   These rules live globally so the V2 document editor (which has no scoped
   CSS file) inherits identical look-and-feel from the template canvas.
   Currently only the template canvas mounts the strip; the global selector
   keeps the contract centralised so future surfaces opt in by markup alone. */
.canvas-lab-workspace .canvas-lab-right-rail-segments {
    flex: 0 0 auto;
}

@media (max-width: 1280px) {
    .canvas-lab-workspace {
        height: auto;
        min-height: 0;
    }

    .canvas-lab-workspace .canvas-lab-canvas-scroll {
        height: 70vh;
    }

    .canvas-lab-workspace .canvas-lab-right-rail {
        height: auto;
        max-height: 70vh;
    }
}
