/* Document canvas (YUM-195, round 2) — semantic classes for the canvas surface. App code
   points at these names and never styles anything itself: no inline styles, no utility
   soup. Same token vocabulary as the rest of CDS 1.0.3 (--ink/--surface/--line/--accent).
   The pane sets a 13px/1.4 ambient base below — nothing inside it relied on an explicit
   size before, so anything that forgot to set one (an input, a spreadsheet cell) inherited
   the page's larger default font instead of this working surface's own scale. That gap is
   most of what "fonts too big" meant; every rule below is either that ambient base or an
   explicit override of it, never an inherited accident. */

/* ---- the right-hand dock (YUM-342) --------------------------------------------------
   One column on the right edge holds everything that displays a file: the document canvas
   and the file list, stacked. Its rail carries the switches for both, so the controls sit
   with the things they control. The file SYSTEM (folders/documents) is the opposite edge —
   .tree-drawer, further down. Nothing flips sides any more: right is where files live. */
.right-dock{position:fixed;top:0;right:0;bottom:0;z-index:60;display:flex;align-items:stretch;transition:width 220ms ease}
/* Rail removed 2026-07-28 — Files/Doc controls live in the top nav. Keep class for legacy. */
.right-dock-rail{display:none}
.right-dock-panels{display:flex;flex-direction:row;align-items:stretch;width:0;overflow:hidden;transition:width 220ms ease;min-height:0;border-left:1px solid var(--line)}
/* Drag resize must track the pointer 1:1 — any width transition reads as lag. */
.right-dock.is-resizing,.right-dock.is-resizing .right-dock-panels{transition:none!important}
.yarnball-shell.dock-resizing{transition:none!important}
.yarnball-shell.dock-open{transition:padding-right 220ms ease}
.yarnball-shell.dock-open.dock-resizing{transition:none!important}
/* Open width: files-only is a narrow column; document alone is mid; both together is wider. */
.right-dock.is-open .right-dock-panels{width:min(42vw,720px)}
.right-dock.is-open.is-files-only .right-dock-panels{width:min(22vw,280px)}
/* Doc-only dock needs room for OnlyOffice chrome (Ben 2026-07-31 — was min(48vw,820px) and crushed). */
.right-dock.is-open.is-doc-only .right-dock-panels{width:min(62vw,1040px)}
.right-dock.is-open.is-split .right-dock-panels{width:min(92vw,calc(var(--files-side,280px) + var(--viewer-side,520px) + 10px))}
/* Browsing with nothing chosen: the browser tree, not a document. Must match the shell's
   dock-open:has(.is-browse-empty) reservation below — narrowing only one of the two makes
   the dock overlap the chat instead of fixing the slab. */
.right-dock.is-open.is-browse-empty .right-dock-panels{width:min(28vw,340px)}
.right-dock.is-files-narrow.is-open.is-files-only .right-dock-panels{width:min(18vw,220px)}
.right-dock.is-files-mid.is-open.is-files-only .right-dock-panels{width:min(22vw,280px)}
.right-dock.is-files-wide.is-open.is-files-only .right-dock-panels{width:min(28vw,340px)}
.right-dock.is-files-narrow.is-open.is-split .right-dock-panels{width:min(92vw,calc(var(--files-side,220px) + var(--viewer-side,520px) + 10px))}
.right-dock.is-files-mid.is-open.is-split .right-dock-panels{width:min(92vw,calc(var(--files-side,280px) + var(--viewer-side,520px) + 10px))}
.right-dock.is-files-wide.is-open.is-split .right-dock-panels{width:min(92vw,calc(var(--files-side,340px) + var(--viewer-side,520px) + 10px))}
/* FILES LEFT of the document pane (Ben 2026-07-28). */
.right-dock-panels > .files-drawer{order:1;flex:0 0 min(22vw,280px);width:min(22vw,280px);max-width:340px;border-top:0;border-right:1px solid var(--line);border-left:1px solid var(--line)}
.right-dock.is-files-narrow .right-dock-panels > .files-drawer{flex-basis:var(--files-side,220px);width:var(--files-side,220px)}
.right-dock.is-files-mid .right-dock-panels > .files-drawer{flex-basis:var(--files-side,280px);width:var(--files-side,280px)}
.right-dock.is-files-wide .right-dock-panels > .files-drawer{flex-basis:var(--files-side,340px);width:var(--files-side,340px)}
.right-dock.is-split .right-dock-panels > .files-drawer{flex:0 0 var(--files-side,280px);width:var(--files-side,280px);max-width:none}
.right-dock.is-resizing .right-dock-panels > .files-drawer{flex:0 0 var(--files-side,280px)!important;width:var(--files-side,280px)!important;max-width:none!important}
.right-dock.is-files-only .right-dock-panels > .files-drawer{flex:1 1 auto;width:100%;max-width:none}
.right-dock-panels > .canvas-pane{order:3;flex:1 1 auto;min-width:0}
/* YUM-505: no fat SPLIT slider — thin drag seam only */
.right-dock-panels > .dock-split-ctrl{display:none}
.right-dock-panels > .dock-resize{order:2;flex:0 0 5px;width:5px;min-width:5px;max-width:5px;cursor:col-resize;border:0;background:var(--line);padding:0;margin:0;align-self:stretch;appearance:none;-webkit-appearance:none;border-radius:0}
.right-dock-panels > .dock-resize:hover,.right-dock-panels > .dock-resize:focus-visible{background:var(--accent)}
.right-dock-panels > .dock-resize:focus{outline:none}
.right-dock-panels > .dock-min-strip{order:1;flex:0 0 36px;width:36px;border:0;border-left:1px solid var(--line);background:var(--surface-2);color:var(--ink-2);font-family:var(--mono);font-size:10px;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;writing-mode:vertical-rl;transform:rotate(180deg)}
.dock-pane-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.dock-pane-actions{display:flex;align-items:center;gap:4px}
.files-row-load{min-width:28px;padding:0 6px}
.files-row-load-glyph{font-size:14px;line-height:1;font-weight:700}
.canvas-image{object-fit:contain;max-width:100%;max-height:100%;background:var(--bg)}
.secfact-plain-ev{margin-top:10px}
.secfact-tech{margin-top:8px}
/* Round 3: canvas alone, on a SHORT document (a one-sheet spreadsheet, a short note), left
   a void: .right-dock stretches every flex child (including .right-dock-panels) to the
   dock's full viewport height, and a lone 'auto' grid row inherits that same stretch by
   default — so canvas-pane, however short its content, was always forced to the dock's
   full height, with its own white --surface background filling whatever the content did
   not. align-content:start stops the row claiming that leftover space: canvas-pane now
   sizes to its own content (every one of its editors already caps its own scroll region at
   62-70vh, so a LONG document still fits in one viewport without being clipped by this
   panel's overflow:hidden). What's left below a short pane is the dock's own --bg canvas
   colour, not a blank continuation of the card — it reads as the card ending where its
   content ends, not as missing content. Scoped to canvas-alone so the two-drawers-open
   3fr/2fr split above (a deliberate ratio between two real panels) is untouched. */
.right-dock-panels:has(.canvas-pane):not(:has(.files-drawer)){align-content:start}
/* A switch is a toggle: pressed means the drawer is open, and pressing it again closes it.
   Reads normally, left to right — rotated sideways glyphs (writing-mode:vertical-rl) were
   here before and were themselves a defect; a dense HORIZONTAL control at a slightly wider
   rail width (--dock-rail, below) is what actually reads as one at a glance.
   Round 3: horizontal alone was not enough — at the previous 58px rail, 'CANVAS' (the
   longest of the three labels) measured wider than its own button and wrapped to a second
   line ("CANVA" / "S"). Two ways to fix a clipped label: widen the box, or move to a
   different control shape (e.g. a segmented switch above the canvas content). The switch
   stays: it is the ONE persistent way to open the canvas or the file list before either
   drawer exists, so it has to keep working with nothing open, which rules out a control
   that lives inside content that is not there yet. --dock-rail (below) is widened just
   enough for 'CANVAS' with real margin; white-space:nowrap stops any font/locale fallback
   from ever silently wrapping a label again instead of visibly failing to fit. */
/* No ellipsis: a label that does not fit must be visible as a defect, not silently
   truncated to "CAN…". The rail is sized to the longest label instead. */
.dock-switch{min-height:32px;width:100%;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink-2);font-family:var(--mono);font-size:10px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;line-height:1.15;padding:4px 2px;cursor:pointer;text-align:center;white-space:nowrap}
.dock-switch:hover{border-color:var(--accent);color:var(--ink)}
.dock-switch.is-on{background:var(--ink);border-color:var(--ink);color:var(--surface);font-weight:650}
/* Round 3: the pane and whatever sits to its left (the open tree, or its collapsed reopen
   rail) are a PAIR laid out side by side — canvas.js wraps both in this row so the rail
   never has to fake its position with position:fixed against the whole viewport again. The
   open .tree-drawer stays position:fixed (it deliberately docks to the opposite edge of the
   app, unchanged) and so takes itself out of this row's flow; only the collapsed .canvas-
   rail actually participates as a flex item here. */
.canvas-pane-row{display:flex;align-items:stretch;min-width:0;min-height:0}
/* Item 9 (round 3): the collapsed rail reads as a control — bordered, hoverable, with the
   same chevron the expanded toggle uses, pointing the way it will open. It sits directly
   against the pane's own left edge (no border-right — the pane's own border-left is the
   seam between them) and is exactly as tall as the pane next to it, never the dock's full
   viewport height: a control is only ever as big as the thing it controls. */
/* A tab at the top of the pane's edge, not a full-height strip: centring one 9px label in
   600px of column is what read as an empty gutter. It reopens the tree, so it sits where
   the tree's own header would be. */
.canvas-rail{flex:none;width:auto;min-width:60px;max-width:104px;padding:10px 8px;border:1px solid var(--line);border-right:0;background:var(--surface-2);display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:6px;cursor:pointer;align-self:flex-start;border-bottom-left-radius:var(--r-sm)}
.canvas-rail:hover{border-color:var(--accent);color:var(--ink)}
.canvas-rail .canvas-chevron{transform:rotate(-90deg)}
/* Horizontal, never rotated, never wrapped into a vertical stack of single characters —
   the previous 56px-wide fixed rail was narrower than 'Documents' at any reasonable size,
   which is what actually read as "rotated" even though no writing-mode rule was in play. */
.canvas-rail span:last-child{font-family:var(--mono);font-size:9.5px;letter-spacing:.02em;text-transform:uppercase;color:var(--faint);line-height:1.2;text-align:center;white-space:nowrap}
@media (max-width:900px){.canvas-rail{display:none}}
/* The pane is a panel inside the dock now, not a fixed sheet of its own. */
.canvas-pane{position:relative;min-width:0;min-height:0;flex:1 1 auto;display:grid;grid-template-rows:auto minmax(0,1fr);background:var(--surface);border-left:1px solid var(--line);box-shadow:var(--shadow);font-size:13px;line-height:1.4}
.canvas-pane *{box-sizing:border-box;min-width:0}
/* font-FAMILY only: the `font` shorthand also resets font-size, and at (element+class)
   specificity it outranked every control's own size rule — which silently threw away
   the whole type scale for buttons. */
.canvas-pane button{cursor:pointer;font-family:inherit;font-weight:inherit;touch-action:manipulation}
.canvas-pane :focus-visible{outline:3px solid var(--accent);outline-offset:2px}
/* The shell is a normal flow container, so reserving the room on the shell itself is what
   keeps the composer and every screen clear of the dock — padding on inner surfaces does
   not reach the full-width composer wrapper. */
/* --dock-rail widened from 38px: it now holds horizontal (never rotated) button labels
   ("Canvas"/"Files"/"Full") and needs the room to read normally at a small size. Round 3:
   --tree-rail is gone — the collapsed tree's reopen handle (.canvas-rail, below) is no
   longer a second, separately-reserved strip pinned to the far left of the whole shell; it
   is an in-flow sibling of the pane it controls (.canvas-pane-row, below), so its width
   comes out of the dock's own existing budget instead of a gutter reserved elsewhere. */
/* Dock rail width 0 — controls moved to top nav (2026-07-28). */
.yarnball-shell{--dock-rail:0px;--tree-drawer:260px}
.yarnball-shell.dock-rail{padding-right:var(--dock-rail)}
.yarnball-shell.dock-open{padding-right:calc(min(42vw,720px) + var(--dock-rail))}
.yarnball-shell.dock-open:has(.right-dock.is-files-only){padding-right:calc(min(22vw,280px) + var(--dock-rail))}
.yarnball-shell.dock-open:has(.right-dock.is-doc-only){padding-right:calc(min(62vw,1040px) + var(--dock-rail))}
.yarnball-shell.dock-open:has(.right-dock.is-split){padding-right:calc(min(92vw,calc(var(--files-side,280px) + var(--viewer-side,520px) + 10px)) + var(--dock-rail))}
/* Browsing with nothing picked yet: the pane holds one sentence, so it takes the
   room for one sentence. Declared after the rules above deliberately — same
   specificity, and this state must win over the generic .dock-open width. */
.yarnball-shell.dock-open:has(.right-dock.is-browse-empty){padding-right:calc(min(28vw,340px) + var(--dock-rail))}
.yarnball-shell.tree-open{padding-left:var(--tree-drawer)}
/* Item 9: pop out — a standalone window showing only the document. Nothing is fixed or
   bordered because there is no chat column beside it to reserve room from. */
.canvas-pane.canvas-popout{position:static;width:100%;height:100dvh;border:0;box-shadow:none;transform:none}
.yarnball-shell.canvas-popout{padding:0}

/* ---- full editor + chat right column (Ben 2026-08-01, fixed layout) -----------------
   Shell becomes a CSS grid: top bar full width; left = document editor; right = chat
   main + composer. No position:fixed on chat (that broke into a top-left pill + white void). */
.yarnball-shell.canvas-full.editor-chat-right,
.yarnball-shell.dock-open.canvas-full.editor-chat-right,
.yarnball-shell.dock-rail.canvas-full.editor-chat-right,
.yarnball-app.yarnball-shell.canvas-full.editor-chat-right{
  --chat-side:min(360px,32vw);
  --viewer-side:min(42vw,560px);
  /* !important: must beat .yarnball-shell{display:flex} in _ds_bundle and any cached float layout */
  display:grid!important;
  flex-direction:unset!important;
  grid-template-columns:minmax(0,1fr) var(--chat-side);
  grid-template-rows:auto minmax(0,1fr) auto;
  height:100dvh;
  width:100%;
  max-width:none;
  margin:0;
  padding:0!important;
  padding-right:0!important;
  padding-left:0!important;
  overflow:hidden;
  box-sizing:border-box;
}
/* Kill the old canvas-full floating chat card when editor-chat-right owns the layout */
.yarnball-shell.canvas-full.editor-chat-right .yarnball-main,
.yarnball-shell.canvas-full.editor-chat-right .chat-surface,
.yarnball-shell.canvas-full.editor-chat-right .compwrap{
  position:relative!important;
  left:auto!important;right:auto!important;top:auto!important;bottom:auto!important;
  width:100%!important;
  max-width:none!important;
  max-height:none!important;
  border-radius:0!important;
  box-shadow:none!important;
}
.yarnball-shell.canvas-full.editor-chat-right > .top{
  grid-column:1/-1;
  grid-row:1;
  max-width:none;
  margin:0;
  width:100%;
  box-sizing:border-box;
}
/* Editor occupies left column, rows 2–3 */
.yarnball-shell.canvas-full.editor-chat-right > .right-dock{
  grid-column:1;
  grid-row:2/-1;
  position:relative!important;
  inset:auto!important;
  width:100%!important;
  height:100%!important;
  z-index:2;
  display:flex;
  align-items:stretch;
}
.yarnball-shell.canvas-full.editor-chat-right > .right-dock.is-full{
  left:auto;right:auto;width:100%;
}
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .right-dock-panels{
  width:100%!important;
  height:100%;
  min-height:0;
  flex:1 1 auto;
}
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-pane{
  margin:0;
  width:100%;
  max-width:none;
  height:100%;
  min-height:0;
  box-shadow:none;
  border-left:0;
  display:grid;
  grid-template-rows:auto minmax(0,1fr);
}
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-body,
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-onlyoffice-wrap,
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-onlyoffice-host,
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-onlyoffice-mount{
  min-height:0;
  height:100%;
  flex:1 1 auto;
}
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-onlyoffice-host iframe,
.yarnball-shell.canvas-full.editor-chat-right > .right-dock .canvas-onlyoffice-mount iframe{
  width:100%!important;
  height:100%!important;
  min-height:0;
  border:0;
}
/* Chat column (right): message list + composer as grid rows */
.yarnball-shell.canvas-full.editor-chat-right > .yarnball-main,
.yarnball-shell.canvas-full.editor-chat-right > main.yarnball-main{
  grid-column:2;
  grid-row:2;
  position:relative!important;
  inset:auto!important;
  width:100%!important;
  max-width:none!important;
  height:100%;
  max-height:none;
  overflow:auto;
  margin:0;
  padding:8px 10px;
  border-left:1px solid var(--line);
  background:var(--surface);
  box-sizing:border-box;
  justify-content:flex-start;
}
.yarnball-shell.canvas-full.editor-chat-right > .compwrap{
  grid-column:2;
  grid-row:3;
  position:relative!important;
  inset:auto!important;
  width:100%!important;
  max-width:none!important;
  margin:0;
  padding:6px 8px;
  border-left:1px solid var(--line);
  border-top:1px solid var(--line);
  border-radius:0;
  background:var(--surface);
  box-sizing:border-box;
  z-index:3;
}
.yarnball-shell.canvas-full.editor-chat-right > .queued-msgs{
  grid-column:2;
  grid-row:2;
  align-self:end;
  padding-left:8px;
  padding-right:8px;
  z-index:4;
}
/* Hide chrome that fights the editor grid */
.yarnball-shell.canvas-full.editor-chat-right > .app-footer,
.yarnball-shell.canvas-full.editor-chat-right > footer,
.yarnball-shell.canvas-full.editor-chat-right .chat-float-bar,
.yarnball-shell.canvas-full.editor-chat-right .chat-float-corner{display:none!important}
/* Drag handle between editor and chat */
.editor-chat-resize{
  position:absolute;
  top:0;bottom:0;right:0;
  width:6px;
  z-index:5;
  cursor:col-resize;
  border:0;
  padding:0;
  background:transparent;
}
.editor-chat-resize:hover,
.editor-chat-resize:focus-visible{background:var(--accent)}
/* Viewer dock width via CSS var (resizable) — set on shell + .right-dock by canvas.js */
.right-dock.is-open.is-doc-only:has(.viewer-compact) .right-dock-panels{
  width:var(--viewer-side,min(42vw,560px));
  position:relative;
}
.yarnball-shell.dock-open:has(.right-dock.is-doc-only .viewer-compact){
  padding-right:calc(var(--viewer-side,min(42vw,560px)) + var(--dock-rail));
}
/* Thin drag seam as a flex column (never absolute — absolute fell out of layout and
   left an unstyled full-height grey button bar). */
.right-dock-panels > .viewer-dock-resize{
  order:3;
  flex:0 0 5px;
  width:5px;
  min-width:5px;
  max-width:5px;
  align-self:stretch;
  position:relative;
  z-index:5;
  cursor:col-resize;
  border:0;
  padding:0;
  margin:0;
  appearance:none;
  -webkit-appearance:none;
  background:var(--line);
  border-radius:0;
  box-shadow:none;
}
.right-dock-panels > .viewer-pane{
  order:4;
  flex:1 1 var(--viewer-side,520px);
  min-width:min(280px,var(--viewer-side,520px));
  width:auto;
}
.right-dock.is-split .right-dock-panels > .viewer-pane.viewer-compact{
  flex:1 1 var(--viewer-side,520px);
  min-width:240px;
}
.right-dock-panels > .viewer-dock-resize:hover,
.right-dock-panels > .viewer-dock-resize:focus-visible{background:var(--accent)}
.right-dock-panels > .viewer-dock-resize:focus{outline:none}
.right-dock.is-open.is-doc-only{position:fixed}
.right-dock.is-open.is-doc-only:has(.viewer-compact){position:fixed}

/* Compact viewer chrome */
.viewer-pane.viewer-compact{
  height:100%;
  min-height:0;
  display:grid;
  grid-template-rows:auto minmax(0,1fr);
}
.viewer-pane.viewer-compact .viewer-head{
  padding:4px 8px;min-height:36px;gap:6px;
  overflow:visible;
  position:relative;
  z-index:8;
}
.viewer-pane.viewer-compact .canvas-title{min-width:0;flex:1 1 auto}
.viewer-pane.viewer-compact .canvas-title strong{font-size:12.5px;font-weight:600}
.viewer-pane.viewer-compact .canvas-title small{font-size:10px;color:var(--mute)}
.viewer-pane.viewer-compact .dock-pane-actions{
  gap:2px;align-items:center;flex:none;
  position:relative;z-index:9;
  overflow:visible;
}
.viewer-pane.viewer-compact .viewer-body{
  padding:0;min-height:0;flex:1 1 auto;height:100%;
  overflow:auto;display:flex;flex-direction:column;
}
.viewer-pane.viewer-compact .office-preview-host,
.viewer-pane.viewer-compact .canvas-preview,
.viewer-pane.viewer-compact .pdf-pages-stack{
  flex:1 1 auto;min-height:0;height:100%;
}
/* YUM-503: design-aware markdown preview */
.canvas-preview-design[data-design="builtin-fresh-breeze"]{
  font-family:Georgia,"Times New Roman",serif;
  color:var(--ink);
  line-height:1.55;
}
.canvas-preview-design[data-design="builtin-fresh-breeze"] h1,
.canvas-preview-design[data-design="builtin-fresh-breeze"] h2,
.canvas-preview-design[data-design="builtin-fresh-breeze"] h3{color:var(--accent);font-weight:600}
.canvas-preview-design[data-design="builtin-yarnball"]{
  font-family:var(--sans,system-ui,sans-serif);
  color:var(--ink);
  line-height:1.45;
}
.viewer-pane.viewer-compact .canvas-preview,
.viewer-pane.viewer-compact .office-preview-host,
.viewer-pane.viewer-compact .pdf-pages-stack{padding:6px 8px}
.canvas-note-dense{font-size:11px;padding:4px 10px;margin:0;border-bottom:1px solid var(--line);background:var(--surface-2);color:var(--ink-2)}
/* Design select in viewer — compact so the toolbar stays icon-first */
.viewer-design-select{
  width:88px;
  max-width:88px;
  min-width:0;
  height:26px;
  border:1px solid var(--line);
  border-radius:var(--r-xs);
  background:var(--surface);
  color:var(--ink);
  font-family:inherit;
  font-size:10.5px;
  line-height:1.2;
  padding:0 4px;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  flex:none;
}
.viewer-design-select:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.viewer-design-select:disabled{opacity:.55}
/* CDS icon buttons in viewer toolbar */
.canvas-icon-btn{
  width:30px;height:30px;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);
  border-radius:var(--r-xs);
  background:var(--surface);
  color:var(--ink-2);
  padding:0;
  cursor:pointer;
  text-decoration:none;
  flex:none;
  position:relative;
  z-index:2;
}
.canvas-icon-btn:hover{border-color:var(--accent);color:var(--accent);z-index:12;background:var(--surface)}
.canvas-icon-btn.is-primary{background:var(--ink);border-color:var(--ink);color:var(--surface)}
.canvas-icon-btn.is-primary:hover{opacity:.9;color:var(--surface);z-index:12}
.canvas-icon-btn:disabled{opacity:.4;cursor:default}
/* Fill OO / canvas body to the dock edge (YUM-500) */
.right-dock.is-full .canvas-pane,
.right-dock.is-open.is-doc-only .canvas-pane,
.yarnball-shell.canvas-full.editor-chat-right .canvas-pane{
  height:100%!important;
  max-height:none!important;
  min-height:0!important;
}
.yarnball-shell.canvas-full.editor-chat-right .right-dock .canvas-body{
  height:100%!important;
  min-height:0!important;
  overflow:hidden;
}
.yarnball-shell.canvas-full.editor-chat-right .canvas-onlyoffice-wrap,
.yarnball-shell.canvas-full.editor-chat-right .canvas-onlyoffice-host,
.yarnball-shell.canvas-full.editor-chat-right .canvas-onlyoffice-mount{
  min-height:0!important;
  height:100%!important;
  flex:1 1 auto;
}
.yarnball-shell.canvas-full.editor-chat-right .canvas-onlyoffice-mount > iframe{
  min-height:0!important;
  height:100%!important;
}
/* Short Files tab — not full-height strip (Ben 2026-08-01) */
.dock-files-tab{
  position:absolute;
  top:56px;
  left:0;
  z-index:6;
  display:inline-flex;
  align-items:center;
  gap:6px;
  height:32px;
  width:auto;
  max-width:120px;
  padding:0 10px;
  border:1px solid var(--line);
  border-left:0;
  border-radius:0 var(--r-sm) var(--r-sm) 0;
  background:var(--surface-2);
  color:var(--ink-2);
  font-family:var(--mono);
  font-size:10px;
  letter-spacing:.04em;
  text-transform:uppercase;
  cursor:pointer;
  writing-mode:horizontal-tb;
  transform:none;
}
.dock-files-tab:hover{border-color:var(--accent);color:var(--accent)}
.right-dock.is-open.is-doc-only .dock-files-tab{left:0}
.right-dock.is-full .dock-files-tab{top:8px}
/* Short tab wins over full-height strip when both classes are present */
.right-dock .dock-min-strip.dock-files-tab{
  position:absolute;top:56px;left:0;z-index:6;
  height:32px;width:auto;max-width:120px;
  writing-mode:horizontal-tb;transform:none;
  flex:none;padding:0 10px;
  border-radius:0 var(--r-sm) var(--r-sm) 0;
}
.right-dock.is-full .dock-min-strip.dock-files-tab{top:8px}
/* Files tab alone (minimized, no document) — no empty white panel column */
.right-dock.is-files-tab-only{
  width:0!important;
  overflow:visible;
  pointer-events:none;
}
.right-dock.is-files-tab-only .right-dock-panels{
  width:0!important;
  border:0!important;
  overflow:hidden;
}
.right-dock.is-files-tab-only .dock-files-tab,
.right-dock.is-files-tab-only .dock-min-strip.dock-files-tab{
  pointer-events:auto;
  left:auto;
  right:0;
  border-left:1px solid var(--line);
  border-right:0;
  border-radius:var(--r-sm) 0 0 var(--r-sm);
}
.yarnball-shell.dock-open:has(.right-dock.is-files-tab-only):not(:has(.right-dock.is-doc-only)):not(:has(.right-dock.is-split)):not(:has(.right-dock.is-files-only)){
  padding-right:0;
}
.chat-float-bar{display:none}
.chat-float-corner{display:none}

/* ---- file-system drawer, left edge (YUM-342) ---------------------------------------- */
.tree-drawer{position:fixed;top:0;left:0;bottom:0;z-index:59;width:var(--tree-drawer,260px);overflow:auto;display:grid;gap:2px;align-content:start;background:var(--surface);border-right:1px solid var(--line);box-shadow:var(--shadow);padding:10px;font-size:13px;transition:width .26s ease,opacity .2s ease}
.tree-drawer.collapsing{width:0;padding-left:0;padding-right:0;opacity:0;overflow:hidden}
.tree-drawer button{cursor:pointer;font-family:inherit}

/* ---- file list drawer (YUM-342, sleek pass 2026-07-28) ---------------------------- */
.files-drawer{min-height:0;overflow:auto;background:var(--surface);border-left:1px solid var(--line);box-shadow:var(--shadow);padding:8px 10px;font-size:12.5px;display:flex;flex-direction:column;gap:4px}
.files-drawer-sleek{padding:6px 8px 10px;background:var(--bg)}
.files-drawer button{cursor:pointer;font-family:inherit}
.files-drawer-head{display:flex;align-items:center;justify-content:space-between;gap:6px;margin-bottom:4px;min-height:28px}
.files-drawer-head strong{font-size:11.5px;font-weight:650;letter-spacing:.01em}
.files-drawer .files-row{padding:4px 2px;gap:4px}
.files-drawer .files-row-name{font-size:12px;line-height:1.25}
.files-drawer .files-row-meta{font-size:10px}
.files-drawer .files-section-label{font-size:9.5px;margin:6px 0 2px;letter-spacing:.04em}
.files-drawer .files-filter{font-size:12px;padding:5px 8px;min-height:28px}
.files-drawer .files-toolbar{margin-bottom:2px}
/* YUM-207: folder glyph + file count sit together as the roster's identity, left of the
   quota battery and close/minimize actions in .dock-pane-actions. */
.files-drawer-head-title{display:flex;align-items:center;gap:6px;color:var(--ink)}
.files-drawer-head-title svg{color:var(--mute);flex:none}
.files-drawer-count{font-family:var(--mono);font-size:10.5px;color:var(--faint);letter-spacing:.02em}

/* ---- tips, at the control they explain (YUM-341) -------------------------------------
   The anchor is the control's own wrapper, so the bubble is placed by CSS against the thing
   it describes — no coordinates are ever written into the markup. The information mark stays
   for good: a dismissed tip is one click away, forever — but "stays for good" does not mean
   "at full contrast forever". A dozen solid little circles dotted across Save, Slide out,
   More and the whole dock rail was chrome competing with the controls it was meant to be
   quietly attached to. Resting state is a faint ghost dot; hovering the control (or the mark
   itself, or giving it keyboard focus) is what brings it up to a readable, clickable circle —
   discoverable, not decorative. */
.tip-anchor{position:relative;display:inline-flex;align-items:center;gap:1px}
.tip-info{width:13px;height:13px;flex:0 0 auto;border:1px solid var(--line-soft);border-radius:50%;background:transparent;color:transparent;font-family:var(--mono);font-size:9px;line-height:1;padding:0;cursor:pointer;align-self:flex-start;opacity:.45;transition:opacity .15s ease,border-color .15s ease,color .15s ease,background .15s ease}
.tip-anchor:hover .tip-info,.tip-info:hover,.tip-info:focus-visible{opacity:1;border-color:var(--line);color:var(--faint);background:var(--surface)}
.tip-info:hover{border-color:var(--accent);color:var(--accent)}
.tip-info.is-on{opacity:1;background:var(--accent);border-color:var(--accent);color:var(--surface)}
/* text-align/text-transform/font-weight are set explicitly on every line below (never left
   to inherit) — a tip can be anchored inside .hint or a mono uppercase label elsewhere in
   this file, and without its own explicit values here it silently inherited that ancestor's
   SHOUTING mono uppercase (the "TYPE HERE TO CHAT WITH YARNBALL" defect: .hint sets
   text-transform:uppercase, and .tip-bubble-text/-more had no value of their own to stop it
   cascading in). A tip's own text is never allowed to depend on what happens to contain it. */
.tip-bubble{position:absolute;z-index:67;pointer-events:none;display:grid;gap:3px;width:max-content;max-width:250px;border:1px solid var(--accent);border-left-width:3px;border-radius:var(--r-sm);background:var(--surface);box-shadow:var(--shadow);padding:7px 9px;cursor:pointer;text-align:left;text-transform:none;font-weight:400;--tip-arrow:var(--accent)}
.tip-bubble-text{font-size:12px;font-weight:500;color:var(--ink);line-height:1.35;text-transform:none}
.tip-bubble-more{font-size:11.5px;color:var(--ink-2);line-height:1.4;text-transform:none}
.tip-bubble-hint{font-family:var(--mono);font-size:9px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.tip-bubble.tip-quiet{border-color:var(--line);border-left-color:var(--line);--tip-arrow:var(--line)}
/* 2026-07-30 (YUM design audit): a tip had no connector to the control it explains — it just
   floated, indistinguishable from any other card on screen. One triangle-arrow treatment, added
   once here so every placement (below/below-end/above/left/right) and every tip everywhere gets
   it: ::before is the border-colored outer triangle, ::after is a 1px-smaller surface-colored
   inner triangle painted on top, which together read as a bordered pointer with a solid fill —
   the same border-triangle technique used for popover arrows generally. Persistence (tips never
   auto-expire) is unchanged, per Ben 2026-07-27 — this only adds the missing pointer. */
.tip-bubble::before,.tip-bubble::after{content:'';position:absolute;width:0;height:0;border:7px solid transparent;pointer-events:none}
.tip-bubble::after{border-width:6px}
.tip-below::before,.tip-below-end::before{bottom:100%;border-bottom-color:var(--tip-arrow)}
.tip-below::after,.tip-below-end::after{bottom:100%;border-bottom-color:var(--surface)}
.tip-below::before,.tip-below::after{left:14px}
.tip-below-end::before,.tip-below-end::after{left:auto;right:14px}
.tip-above::before{top:100%;left:14px;border-top-color:var(--tip-arrow)}
.tip-above::after{top:100%;left:14px;border-top-color:var(--surface)}
.tip-left::before{left:100%;top:10px;border-left-color:var(--tip-arrow)}
.tip-left::after{left:100%;top:10px;border-left-color:var(--surface)}
.tip-right::before{right:100%;top:10px;border-right-color:var(--tip-arrow)}
.tip-right::after{right:100%;top:10px;border-right-color:var(--surface)}
.tip-below{top:calc(100% + 7px);left:0}
.tip-below-end{top:calc(100% + 7px);right:0}
.tip-above{bottom:calc(100% + 7px);left:0}
.tip-left{right:calc(100% + 7px);top:0}
.tip-right{left:calc(100% + 7px);top:0}
@media (max-width:900px){
  .tip-bubble{max-width:min(250px,72vw)}
  .tip-below,.tip-above{left:auto;right:0}
}

/* ---- header ---------------------------------------------------------------------- */
.canvas-head{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line-soft)}
.canvas-title{display:grid;gap:2px;min-width:0}
/* Item 8: the name is an input that looks like a title until you touch it — renaming is
   typing, not a dialog. */
.canvas-title-input{width:100%;border:1px solid transparent;border-radius:var(--r-xs);background:transparent;color:var(--ink);font-family:inherit;font-size:13px;font-weight:600;line-height:1.25;padding:1px 4px;margin:-1px -4px}
.canvas-title-input:hover{border-color:var(--line)}
.canvas-title-input:focus{border-color:var(--accent);background:var(--surface);outline:none}
.canvas-title strong{font-size:13px;font-weight:600;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.canvas-title small{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
/* Header is now exactly three possible controls (Save, Slide out, More) — a single row
   that must never wrap; the overflow menu below is what keeps it that way. */
.canvas-actions{display:flex;align-items:center;gap:6px;flex-wrap:nowrap;flex:0 0 auto;justify-content:flex-end}
/* One button shape, three variants: quiet (default), primary, quiet-destructive. An anchor
   used as a button (Download) gets the identical shape — no underline, centered like every
   other control — instead of reading as a stray link next to its bordered neighbours. */
.canvas-action{display:inline-flex;align-items:center;justify-content:center;min-height:28px;border:1px solid var(--line);border-radius:var(--r-xs);background:transparent;color:var(--ink);padding:4px 10px;font-size:11.5px;font-weight:500;line-height:1.2;text-decoration:none}
.canvas-action:hover{background:var(--surface-2)}
/* The type-filter chips render <em>md</em>Notes and promise "the SAME kind-mark
   glyph" the file rows use (canvas.js). .canvas-node em delivered that for rows;
   nothing ever did for chips, so the mark came out as raw italic text jammed
   against the label — "mdNotes", "xlsxSheets", "pdfPDF". Same treatment as a row
   mark, minus the fixed 26px column a chip has no use for. */
.canvas-action em{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:.02em;color:var(--faint);text-transform:lowercase;margin-right:5px}
/* On the selected chip the surface is var(--ink), so a faint mark disappears into it. */
.canvas-action.primary em{color:var(--surface);opacity:.75}
.canvas-action[disabled]{opacity:.45;cursor:not-allowed}
.canvas-action.primary{background:var(--ink);color:var(--surface);border-color:var(--ink);font-weight:650}
.canvas-action.quiet-danger{color:var(--mute)}
.canvas-action.quiet-danger:hover{color:var(--accent);border-color:var(--accent)}
/* Item 2: a labelled control, not a bare glyph — a chevron that rotates to say which way it
   swings, plus the word it toggles. Replaces the old bare "<". */
.canvas-tree-toggle{font-size:11.5px;display:inline-flex;align-items:center;gap:6px;min-height:28px;border:1px solid var(--line);border-radius:var(--r-xs);background:transparent;color:var(--ink-2);padding:4px 9px}
.canvas-tree-toggle:hover{background:var(--surface-2);color:var(--ink)}
.canvas-tree-toggle span:last-child{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase}
.canvas-chevron{font-size:11.5px;display:inline-block;width:0;height:0;border:4px solid transparent;border-top-color:currentColor;margin-top:2px;transition:transform .18s ease}
.canvas-tree-toggle[aria-expanded="false"] .canvas-chevron{transform:rotate(-90deg)}
/* Overflow menu (items 5/6/8/9 + delete): everything that is not Save/Slide out lives here
   instead of competing as its own header button. The wrap is the positioning context only —
   it carries no width or padding of its own, so it never affects the header row's layout. */
.canvas-menu-wrap{position:relative;display:inline-flex}
.canvas-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:62;min-width:190px;display:grid;gap:1px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);box-shadow:var(--shadow);padding:4px;overflow:hidden}
.canvas-menu-item{display:flex;align-items:center;width:100%;min-height:26px;text-align:left;border:0;border-radius:var(--r-xs);background:transparent;color:var(--ink);padding:4px 9px;font-size:11.5px;text-decoration:none}
.canvas-menu-item:hover{background:var(--surface-2)}
.canvas-menu-item.quiet-danger{color:var(--mute)}
.canvas-menu-item.quiet-danger:hover{color:var(--accent);background:var(--surface-2)}

/* ---- body: the document (the tree is the left drawer now) --------------------------- */
/* Body fills the pane's 1fr row so editors inherit real height — not a 1px strip above a
   blank white void (2026-07-31: field-sizing:content + align-content:start collapsed empty
   md/docx surfaces to a thin line). */
.canvas-body{display:flex;flex-direction:column;min-height:0;height:100%;overflow:hidden}
/* A label plus three buttons in a 260px drawer (--tree-drawer). Without wrapping,
   "+ Folder" broke across two lines and "Close" ran into the drawer edge. The
   label takes the row, the actions wrap together beneath it when they must. */
.canvas-tree-head{display:flex;align-items:center;justify-content:space-between;gap:6px 8px;flex-wrap:wrap;padding:2px 4px 6px}
.canvas-tree-head .canvas-action{white-space:nowrap}
.canvas-tree-head span{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
/* A working file list, not a wall: filter first, then the documents themselves. */
.canvas-filter{width:100%;min-height:28px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);padding:4px 8px;font:inherit;font-size:12px;margin-bottom:6px}
.canvas-tree-empty{padding:8px 6px;font-size:12px;color:var(--mute)}
/* Three columns, because a row has three children: kind mark, name, and the
   version badge. The badge (.canvas-node-ver, added 2026-08-05 in #155) was put
   into a two-column grid, so it had nowhere to sit and wrapped onto an implicit
   second row — every versioned file rendered its "latest"/"older ·2" on a line of
   its own under the name. justify-self:end below was always written for a third
   column; this is the column it was waiting for. */
.canvas-node{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:6px;width:100%;min-height:26px;text-align:left;border:1px solid transparent;border-radius:var(--r-xs);background:transparent;color:var(--ink);padding:4px 6px;font-size:12px;line-height:1.3}
.canvas-node:hover{background:var(--surface-2)}
.canvas-node.active{border-color:var(--accent);background:var(--surface-2);font-weight:600}
.canvas-node span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.canvas-node-ver{justify-self:end;color:var(--mute);font-size:10px;font-family:var(--mono);font-weight:600}
.canvas-node em{font-style:normal;font-family:var(--mono);font-size:9px;letter-spacing:.02em;color:var(--faint);text-transform:lowercase;width:26px}
.canvas-node.folder{font-weight:600}
.canvas-node.nested{padding-left:18px}
.canvas-node.nested-2{padding-left:30px}
.canvas-doc{flex:1 1 auto;min-height:0;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:8px}

/* ---- editors --------------------------------------------------------------------- */
/* The source and its rendered preview are a pair (TextEditor, canvas.js). Side by side
   once the pane is wide enough; each column stretches to the same height and scrolls
   its own overflow. Floor height is always enough to type into — never a collapsed strip. */
.canvas-split{display:grid;grid-template-columns:minmax(0,1fr);gap:10px;min-height:min(52vh,480px);flex:1 1 auto;align-items:stretch}
@media (min-width:1000px){
  .canvas-split:not(.solo){grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:stretch}
}
.canvas-editor{width:100%;min-height:min(48vh,420px);height:100%;max-height:none;field-sizing:fixed;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);padding:10px 12px;font:inherit;font-size:13px;line-height:1.5;resize:vertical}
.canvas-split:not(.solo) .canvas-editor{max-height:none;resize:none;min-height:min(48vh,420px)}
.canvas-editor.mono{font-family:var(--mono);font-size:12.5px;line-height:1.5}
.canvas-editor-page{min-height:min(52vh,480px)}
.canvas-preview{border:1px solid var(--line);border-radius:var(--r-sm);padding:12px 14px;font-size:13px;line-height:1.5;overflow-wrap:anywhere;min-height:min(48vh,420px);overflow:auto}
.canvas-split:not(.solo) .canvas-preview,.canvas-split:not(.solo) .canvas-frame{max-height:none;min-height:min(48vh,420px);overflow:auto;height:100%}
.canvas-preview h1,.canvas-preview h2,.canvas-preview h3{margin:.6em 0 .3em;line-height:1.25}
/* Hierarchy through weight, the way the rest of the canvas does it — a 22px heading
   in a 13px surface reads as an accident, not a decision. */
.canvas-preview h1{font-size:16px;font-weight:650}.canvas-preview h2{font-size:14px;font-weight:600}.canvas-preview h3{font-size:13px;font-weight:600}
.canvas-preview p,.canvas-preview ul,.canvas-preview ol{margin:0 0 .8em}
.canvas-preview code{font-family:var(--mono);font-size:12.5px;background:var(--surface-2);border-radius:var(--r-xs);padding:1px 4px}
.canvas-preview pre{background:var(--surface-2);border:1px solid var(--line-soft);border-radius:var(--r-xs);padding:10px 12px;overflow:auto}
.canvas-preview pre code{background:transparent;padding:0}
.canvas-preview table{border-collapse:collapse;width:100%;font-size:13px}
.canvas-preview th,.canvas-preview td{border:1px solid var(--line);padding:6px 8px;text-align:left}
.canvas-preview th{background:var(--surface-2)}
.canvas-frame{width:100%;min-height:60vh;border:1px solid var(--line);border-radius:var(--r-sm);background:#fff}

/* spreadsheet grid — dense by default, real cells, no decoration */
.canvas-grid{border:1px solid var(--line);border-radius:var(--r-sm);overflow:auto;max-height:70vh}
.canvas-grid table{border-collapse:collapse;font-size:12.5px;width:max-content;min-width:100%}
.canvas-grid th,.canvas-grid td{border:1px solid var(--line-soft);padding:0;min-width:96px}
.canvas-grid thead th{background:var(--surface-2);font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--faint);padding:4px 6px;position:sticky;top:0;z-index:2}
.canvas-grid tbody th{background:var(--surface-2);font-family:var(--mono);font-size:10.5px;color:var(--faint);padding:4px 6px;text-align:right;position:sticky;left:0;z-index:1}
.canvas-grid-corner{position:sticky;left:0;top:0;z-index:3;background:var(--surface-2)}
.canvas-cell{width:100%;border:0;background:transparent;color:var(--ink);padding:5px 7px;font:inherit;font-size:12.5px;min-height:28px;box-sizing:border-box}
.canvas-cell.is-num{text-align:right;font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
.canvas-cell.is-date{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.canvas-cell.is-text{text-align:left}
.canvas-cell:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--surface-2)}
.canvas-cell.dirty{background:var(--surface-2);font-weight:600}
.canvas-cell[readonly]{cursor:default}
/* YUM-462 sheetgrid — tighter cells, fixed header already sticky above */
.canvas-grid-dense th,.canvas-grid-dense td{min-width:72px}
.canvas-grid-dense thead th{padding:2px 4px;font-size:10px}
.canvas-grid-dense tbody th{padding:2px 4px;font-size:10px}
.canvas-grid-dense .canvas-cell{padding:2px 4px;font-size:12px;min-height:22px}

/* pdf pages + page tools */
.canvas-pages{display:grid;gap:12px;justify-items:center}
.canvas-page{border:1px solid var(--line);border-radius:var(--r-xs);background:#fff;max-width:100%;box-shadow:var(--shadow)}
.canvas-page-row{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.canvas-page-row strong{font-size:12px;font-family:var(--mono);color:var(--faint);margin-right:2px}

/* the faithful office renderers write their own DOM inside this host */
.canvas-render{border:1px solid var(--line);border-radius:var(--r-sm);background:#fff;padding:8px;overflow:auto;max-height:70vh;min-height:min(40vh,320px)}
/* An office host holding nothing but the renderer's stylesheets is not a document: it
   takes no space at all, so a failed render leaves no empty white slab behind. The
   editable text area under it keeps a real floor height so the pane never collapses. */
.canvas-render:not(:has(section, canvas, img, table, p, article)){display:none}
/* docx-preview's generated sections carry this class (it is the library's class PREFIX).
   Defined unscoped so app code may legitimately name it and so the reset always applies.
   The page's own one-inch margins are written as INLINE styles, which is why they need
   !important here — without it a 410px pane rendered a ~200px column of hyphenated text
   inside a wide white frame. In the canvas, the pane IS the page. */
.docxdoc{width:auto!important;min-height:0!important;margin:0!important;padding:16px 18px!important;box-shadow:none}
.docxdoc p{margin:0 0 .6em}
.canvas-slides{display:grid;gap:10px}

/* ---- notes, errors, rewrite diff --------------------------------------------------- */
.canvas-note{display:flex;align-items:flex-start;gap:8px;border-left:2px solid var(--line);border-radius:0;padding:2px 0 2px 9px;font-size:11px;line-height:1.4;color:var(--mute)}
.canvas-note.error{border-left-color:var(--accent);color:var(--ink-2)}
.canvas-bar{display:flex;align-items:center;gap:4px;flex-wrap:wrap;font-size:12px;color:var(--mute)}
.canvas-bar strong{font-size:12px;color:var(--ink)}
.canvas-rewrite{display:grid;gap:8px;border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;background:var(--surface-2)}
.canvas-rewrite input{width:100%;min-height:32px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);padding:6px 9px;font:inherit;font-size:13px}
.canvas-diff{display:grid;gap:6px;font-size:12.5px;line-height:1.5}
.canvas-diff-row{border-radius:var(--r-xs);padding:6px 8px;border:1px solid var(--line-soft);overflow-wrap:anywhere;white-space:pre-wrap}
.canvas-diff-row.was{color:var(--mute);text-decoration:line-through;text-decoration-thickness:1px}
.canvas-diff-row.now{border-color:var(--accent)}
.canvas-versions{display:grid;gap:4px;max-height:40vh;overflow:auto}
.canvas-version{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:8px;border:1px solid var(--line-soft);border-radius:var(--r-xs);padding:5px 8px;font-size:12px}
.canvas-version.current{border-color:var(--accent)}
.canvas-version em{font-style:normal;font-family:var(--mono);font-size:10px;color:var(--faint)}

/* ---- chat-side affordance ---------------------------------------------------------- */
.canvas-card{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;text-align:left;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);padding:9px 11px;margin-top:8px}
.canvas-card:hover{border-color:var(--accent);background:var(--surface-2)}
.canvas-card strong{font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.canvas-card small{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.canvas-card-text{display:grid;gap:2px;min-width:0}

/* ---- design templates (items 5/6) ---------------------------------------------------
   A list, not a gallery: name, source file type, an Apply control, and a clear active
   marker using the same accent-border idiom as .canvas-node.active / .canvas-version.current. */
.canvas-templates{display:grid;gap:8px}
.canvas-file-input{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.canvas-template-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:8px;border:1px solid var(--line-soft);border-radius:var(--r-xs);padding:7px 9px;font-size:12px}
.canvas-template-row>span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px}
.canvas-template-row em{font-style:normal;font-family:var(--mono);font-size:9.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--faint);white-space:nowrap}
.canvas-template-actions{display:flex;gap:6px;flex:0 0 auto}
.canvas-template-active{border-color:var(--accent);background:var(--surface-2)}
.canvas-template-active em{color:var(--accent)}

/* These sit outside .canvas-pane, so they never saw .canvas-pane button{font-family:
   inherit} and would otherwise render in the browser's default Arial. */
.canvas-mobile-switch .canvas-action{font-family:inherit}

/* ---- mobile: full-screen sheet, never a squeezed column ---------------------------- */
@media (max-width:900px){
  /* The pane is position:fixed, so its own padding-right/left reservation for the desktop
     gutter must not survive down here — left uncorrected it was the exact width (min(48vw,
     860px)) by which the pane measured wider and taller than the viewport at 390x844: with
     it still in effect the shell's padding box, not the true viewport, was what "fixed" was
     resolving against. */
  .yarnball-shell.dock-rail,.yarnball-shell.dock-open,.yarnball-shell.tree-open,
  .yarnball-shell.canvas-full,.yarnball-shell.canvas-full.editor-chat-right{
    display:block;padding-left:0;padding-right:0;--chat-side:0px;height:auto;overflow:visible;
  }
  .yarnball-shell.canvas-full.editor-chat-right > .top{grid-column:auto;grid-row:auto}
  .yarnball-shell.canvas-full.editor-chat-right > .right-dock,
  .yarnball-shell.canvas-full.editor-chat-right > .yarnball-main,
  .yarnball-shell.canvas-full.editor-chat-right > main.yarnball-main,
  .yarnball-shell.canvas-full.editor-chat-right > .compwrap{
    grid-column:auto;grid-row:auto;position:static!important;width:auto!important;max-width:none;border:0;height:auto;
  }
  .right-dock.is-full{left:0;right:0;width:100%}
  .editor-chat-resize,.viewer-dock-resize{display:none}
  /* One drawer at a time on a phone: the dock is the screen, and its rail lies along the
     bottom edge where a thumb reaches it. YUM-513: all of this is OPEN-state geometry and
     must be scoped to .is-open — unscoped, the left:0 anchor plus a 100%-wide panel turned
     the CLOSED, empty dock into a fixed full-screen sheet of --surface white that sat over
     the whole app and swallowed every tap, including the composer's. */
  .right-dock.is-open{top:44px;left:0;right:0;bottom:0;flex-direction:column-reverse}
  .right-dock-rail{flex-direction:row;justify-content:center;width:100%;border-left:0;border-top:1px solid var(--line-soft);padding:6px}
  .dock-switch{writing-mode:horizontal-tb;min-height:30px;padding:4px 12px}
  .right-dock.is-open .right-dock-panels{width:100%}
  .tree-drawer{width:min(300px,86vw)}
  /* Full screen, but the composer keeps its place at the bottom: the canvas sits between the
     Chat/Canvas switch and the input, so a document can be read and acted on in one view. */
  /* Sized in viewport units rather than by top+bottom: the shell's containing block is
     taller and wider than the phone, so a `bottom` offset landed the pane's edge below the
     fold and straight over the composer. 44px switch + 107px composer strip are carved out here. */
  .canvas-pane{top:44px;right:auto;bottom:auto;left:0;width:100vw;height:calc(100dvh - 151px);max-width:100vw;max-height:none;margin:0;padding-top:0}
  /* Item 10: the switch moves between chat and canvas; while chat is shown the pane (with
     everything in it, including this switch) is parked off-screen, transform-based like
     every other move in this file. */
  .canvas-pane.mobile-behind{transform:translateX(100%);pointer-events:none}
  .yarnball-shell.dock-open .yarnball-main,.yarnball-shell.dock-open .chat-surface{padding-right:0;padding-left:0}
  .canvas-body{grid-template-columns:minmax(0,1fr)}
  /* Item 10: segmented Chat/Canvas control, pinned above everything else in the pane. */
  /* width:100vw, not left+right: the shell carries a min-width wider than a phone, and
     right:0 was resolving against THAT box — the switch measured 477px on a 390px screen
     and its second button hung off the edge. */
  .canvas-mobile-switch{position:fixed;top:0;left:0;width:100vw;max-width:100vw;z-index:66;height:44px;box-sizing:border-box;display:flex;gap:4px;padding:6px;background:var(--surface);border-bottom:1px solid var(--line-soft)}
  .canvas-mobile-switch .canvas-action{flex:1 1 0;min-width:0}
  /* A phone header has no room for a word that a chevron already says: the toggle keeps its
     arrow, and the title's meta line stays on one line instead of wrapping to three. */
  .canvas-tree-toggle span:last-child{display:none}
  .canvas-tree-toggle{padding:4px 7px}
  .canvas-title small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .canvas-head{padding:6px 8px;gap:6px}
  /* Item 10: the last chat line, overlaid just above the composer, translucent over the
     document beneath it — a single line, never wraps. */
  .canvas-mobile-recent{position:fixed;left:8px;width:calc(100vw - 16px);max-width:calc(100vw - 16px);top:calc(100dvh - 132px);bottom:auto;z-index:64;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;border:1px solid var(--line-soft);border-radius:var(--r-xs);background:color-mix(in srgb,var(--surface) 88%,transparent);color:var(--ink-2);padding:6px 10px;font-size:11px}
}

/* The coach sits clear ABOVE the composer with only its arrow reaching down to it — it is
   pointing at the input, not covering it. */

/* ---- bottom-left file confirmations ------------------------------------------------
   Quiet, out of the way, self-dismissing: it reports that something happened, it does not
   ask for anything. */
.file-toasts{position:fixed;left:16px;bottom:16px;z-index:70;display:grid;gap:6px;max-width:min(320px,70vw);pointer-events:none}
.file-toast{display:grid;gap:1px;border:1px solid var(--line);border-left:2px solid var(--accent);border-radius:var(--r-xs);background:var(--surface);box-shadow:var(--shadow);padding:7px 10px}
.file-toast strong{font-size:12.5px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-toast span{font-size:11px;color:var(--mute)}
@media (max-width:900px){.file-toasts{left:12px;bottom:84px}}

/* ---- reduced motion: no slide, no collapse animation for users who ask for none ----- */
@media (prefers-reduced-motion:reduce){
  .canvas-pane,.canvas-tree,.canvas-chevron{transition:none}
}

/* Item 6: page controls live on the page, named for what they do to it. */
.canvas-page-tools{display:grid;gap:6px}
.canvas-page-tool{display:flex;align-items:center;gap:6px}
.canvas-page-tool em{font-style:normal;font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);min-width:52px}

/* A deck without a faithful render still reads as slides, not as a wall of text. */
.canvas-slide-card{display:grid;gap:3px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);box-shadow:var(--shadow);padding:10px 12px}
.canvas-slide-card em{font-style:normal;font-family:var(--mono);font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.canvas-slide-card strong{font-size:13px;font-weight:650;line-height:1.3}
.canvas-slide-card span{font-size:12px;color:var(--ink-2);line-height:1.45}
/* Word on the regenerate path: page-like margins so it reads as a document. */
.canvas-editor-page{padding:18px 22px;background:var(--surface);max-width:none}

/* ---- files in this chat (Ben 2026-07-25) ---------------------------------------------
   Always visible above the composer: what is in this conversation, and the two switches —
   the canvas and the file picker — so neither is hidden behind an auto-open or a menu. */
.chat-files-bar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;max-width:1040px;margin:0 auto;padding:0 8px 6px}
.chat-files-switch{min-height:26px;border:1px solid var(--line);border-radius:var(--r-pill);background:transparent;color:var(--ink-2);padding:3px 10px;font-family:inherit;font-size:11.5px;cursor:pointer}
.chat-files-switch:hover{background:var(--surface-2);color:var(--ink)}
.chat-files-switch.is-on{background:var(--ink);color:var(--surface);border-color:var(--ink);font-weight:650}
.chat-files-switch[disabled]{opacity:.45;cursor:not-allowed}
.chat-files-chips{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
.chat-files-empty{font-size:11px;color:var(--faint)}

/* ---- file picker (sleek list 2026-07-28) --------------------------------------------- */
.files-toolbar{display:flex;align-items:center;gap:6px;margin-bottom:6px}
.files-filter{flex:1 1 auto;min-height:28px;border:1px solid var(--line-soft);border-radius:var(--r-sm);background:var(--surface);color:var(--ink);padding:4px 8px;font-family:inherit;font-size:12px}
.files-filter:focus{border-color:var(--accent);outline:none}
.files-count{font-family:var(--mono);font-size:10px;letter-spacing:.04em;color:var(--faint);min-width:1.5em;text-align:right}
.files-section-label{font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin:12px 0 4px;padding:0 2px}
.files-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;border:1px solid transparent;border-radius:var(--r-sm);padding:6px 6px;margin:0 -2px}
.files-row:hover{background:var(--surface);border-color:var(--line-soft)}
.files-row-main{display:grid;grid-template-columns:minmax(0,1fr);gap:2px;min-width:0}
.files-row-open{display:flex;align-items:center;gap:10px;min-width:0;border:0;background:transparent;color:var(--ink);font-family:inherit;font-size:13px;text-align:left;padding:0;cursor:pointer;border-radius:var(--r-xs);width:100%}
.files-row-open:hover{color:var(--accent)}
.files-type-icon{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;flex:0 0 auto;border-radius:10px;background:var(--accent-soft,var(--surface-2));color:var(--accent);border:1px solid color-mix(in srgb,var(--accent) 28%,var(--line-soft))}
.files-type-icon svg{width:28px;height:28px}
.files-row-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;min-width:0}
.files-row-rename{width:100%;min-width:0;border:1px solid var(--accent);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font:inherit;font-size:12.5px;padding:2px 6px}
.files-row-meta{font-family:var(--mono);font-size:10px;color:var(--faint);white-space:nowrap;padding-left:38px}
.files-row-actions{display:flex;align-items:center;gap:3px;flex:0 0 auto}
.files-row-action{min-height:26px;min-width:26px;border:1px solid var(--line-soft);border-radius:var(--r-xs);background:var(--surface);color:var(--ink-2);font-family:inherit;font-size:12px;padding:2px 6px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;text-decoration:none}
.files-row-action:hover{border-color:var(--accent);color:var(--accent)}
.files-row-action[disabled]{opacity:.5;cursor:not-allowed}
.files-row-icon{font-size:12px}
.files-empty{font-size:12px;color:var(--mute);padding:8px 4px}
.files-rename-confirm{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);padding:10px;margin:6px 0 8px;display:grid;gap:8px}
.files-rename-confirm-text{margin:0;font-size:13px;color:var(--ink)}
.files-rename-confirm-actions{display:flex;gap:6px;justify-content:flex-end}
.files-rename-confirm-ok{border-color:var(--ink);background:var(--ink);color:var(--surface)}
/* Storage usage as a battery-style symbol + percentage. */
/* YUM-505: storage icon + % instead of battery glyph */
.files-storage{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;color:var(--mute);font-family:var(--mono);font-size:10.5px}
.files-storage svg{color:var(--ink-2);flex:none}
.files-storage-pct{letter-spacing:.02em;color:var(--ink-2);min-width:2.2em}
.files-storage.is-mid svg,.files-storage.is-mid .files-storage-pct{color:var(--accent)}
.files-storage.is-high svg,.files-storage.is-high .files-storage-pct{color:var(--accent)}
.files-battery{display:none}
/* Legacy battery fill bands retained for CDS dynamic-prefix contract (files-battery-fill-*).
   Live UI uses .files-storage; battery chrome stays display:none. */
.files-battery-body{display:inline-block;width:28px;height:12px;border:1.5px solid var(--ink-2);border-radius:3px;padding:1px;position:relative;box-sizing:border-box;background:var(--surface)}
.files-battery-cap{display:inline-block;width:2px;height:6px;background:var(--ink-2);border-radius:0 1px 1px 0;margin-left:-4px}
.files-battery-fill{display:block;height:100%;border-radius:1px;background:var(--ink-2);transition:width .2s ease}
.files-battery-fill-0{width:0%}.files-battery-fill-1{width:10%}.files-battery-fill-2{width:20%}
.files-battery-fill-3{width:30%}.files-battery-fill-4{width:40%}.files-battery-fill-5{width:50%}
.files-battery-fill-6{width:60%}.files-battery-fill-7{width:70%}.files-battery-fill-8{width:80%}
.files-battery-fill-9{width:90%}.files-battery-fill-10{width:100%}
.files-battery-pct{font-family:var(--mono);font-size:10.5px;color:var(--ink-2)}

/* A file name in the conversation is a control: it opens the document in the canvas. Sized to
   sit inside a line of prose without breaking its rhythm. */
.file-mention-pill{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--surface);color:var(--ink);font-family:inherit;font-size:12.5px;line-height:1.3;padding:3px 10px 3px 6px;margin:1px 2px;cursor:pointer;vertical-align:baseline;max-width:100%}
.file-mention-pill:hover{border-color:var(--accent);background:var(--surface-2);color:var(--accent)}
.file-mention-pill-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:6px;background:var(--accent-soft,var(--surface-2));color:var(--accent);flex:0 0 auto}
.file-mention-pill-icon svg{display:block}
.file-mention-pill-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;min-width:0}
.file-mention-pill-me{color:var(--on-ink,var(--surface));border-color:color-mix(in srgb,var(--on-ink, #fff) 25%, transparent);background:color-mix(in srgb,var(--on-ink, #fff) 12%, transparent)}
.file-mention-pill-me .file-mention-pill-icon{background:color-mix(in srgb,var(--on-ink, #fff) 18%, transparent);color:var(--on-ink,var(--surface))}
.msg-prose .file-mention-pill{margin:2px 3px}

/* ---- the design a document is actually written in (YUM-345) --------------------------
   A preview that renders every line at the same size in the same grey is not a preview of a
   document — it shows none of the design the file will carry. `.design-yarnball` is the
   built-in brand system expressed for the screen: the serif display face for headings, the
   scarce accent on h1/h2 with its rule, real body measure. It is applied when the ACTIVE
   design system is the built-in one (canvas.js), so what the preview shows is what the
   generated docx/pdf/pptx will carry. A user's own uploaded template governs the generated
   file, and the canvas says so rather than pretending to render it. */
.canvas-preview.design-yarnball{font-family:var(--font-body-serif);color:var(--ink);font-size:13.5px;line-height:1.62;max-width:68ch}
.canvas-preview.design-yarnball h1,.canvas-preview.design-yarnball h2{color:var(--accent);font-family:var(--font-body-serif);font-weight:650;letter-spacing:-.01em}
.canvas-preview.design-yarnball h1{font-size:19px;border-bottom:1px solid var(--accent);padding-bottom:5px;margin-bottom:.5em}
.canvas-preview.design-yarnball h2{font-size:15.5px}
.canvas-preview.design-yarnball h3{font-size:13.5px;font-weight:650;color:var(--ink)}
.canvas-preview.design-yarnball th{background:var(--accent-soft,var(--surface-2));border-color:var(--accent);color:var(--ink)}
.canvas-preview.design-yarnball code{font-family:var(--mono);font-size:12px}
/* The active design system, named on the document it governs — one line, no panel. */
.canvas-design-line{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.canvas-design-line strong{font-family:inherit;font-size:10px;color:var(--accent)}

/* Dock chrome — unscoped semantic classes (must match app class names for the CDS gate). */
.dock-pane{min-height:0;min-width:0}
.dock-pane-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.dock-pane-actions{display:flex;align-items:center;gap:4px}
.dock-resize{flex:0 0 8px;width:8px;cursor:col-resize;border:0;background:var(--line-soft);padding:0;align-self:stretch}
.dock-resize:hover{background:var(--accent)}
.dock-min-strip{flex:0 0 36px;width:36px;border:0;border-left:1px solid var(--line);background:var(--surface-2);color:var(--ink-2);font-family:var(--mono);font-size:10px;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;writing-mode:vertical-rl;transform:rotate(180deg)}
.files-row-load{min-width:28px;padding:0 6px;border-color:var(--accent);color:var(--accent);font-weight:700}
.files-row-load-glyph{font-size:16px;line-height:1;font-weight:700}
.canvas-image{object-fit:contain;max-width:100%;max-height:100%;background:var(--bg)}
.secfact-plain-ev{margin-top:10px}
.secfact-tech{margin-top:8px}
/* PDF multi-page stack — scrolls inside viewer-body; pages full width. */
.pdf-pages-stack{display:flex;flex-direction:column;align-items:center;gap:14px;padding:10px 8px 32px;width:100%;min-height:min-content}
.pdf-page,.canvas-page{display:block;max-width:100%;width:auto;height:auto;box-shadow:var(--shadow);background:var(--surface);border:1px solid var(--line-soft)}
.viewer-pane{display:flex;flex-direction:column;min-height:0;height:100%;max-height:100%;overflow:hidden;background:var(--surface)}
.viewer-head{flex:0 0 auto}
.viewer-body,.viewer-pane .canvas-body{overflow:auto;min-height:0;flex:1 1 auto;-webkit-overflow-scrolling:touch}
.viewer-editor{min-height:50vh;max-height:none;height:100%;resize:none;field-sizing:fixed}
.dock-head-btn{min-width:28px;padding:4px 8px}
.dock-resize{touch-action:none}
.office-preview-host{min-height:120px;overflow:auto;width:100%}
.office-text-fallback{margin-top:8px;font-size:12px;color:var(--mute)}
.office-text-fallback summary{cursor:pointer;color:var(--accent)}
.nav-dock-ctrl{opacity:.85}
.files-row-meta{padding-left:46px}
.msg-prose{min-width:0}

/* ---- the design surface (YUM-457) ---------------------------------------------------
   Shows the ACTIVE design system inside the editor. Ben, 2026-07-30: the colour schemes and
   fonts "should not only be applied to them, but also shown in the editor in the preview,
   maybe even if not fully accurate. At least then it needs to be visible."

   This REPLACES `.canvas-preview.design-yarnball`, which had two defects it could not be
   patched out of: app code picked it whenever a design system was `builtin`, so the second
   built-in system (Fresh Breeze) rendered in Yarnball's brick red; and the rules themselves
   were written against the global CDS tokens (var(--accent), var(--font-body-serif)), so the
   class could only ever express Yarnball and never a user's uploaded template.

   The values below come from the design system itself, carried in as --ds-* custom properties
   by the DS component YarnballDS.DesignSurface (_ds_bundle.js). Setting them is the DS
   package's job, never app code's — app code only names this class. Every property falls back
   to the surrounding CDS token, so a partial or missing design system degrades to the app's
   own theme instead of collapsing to unstyled text. */
.design-surface{font-family:var(--ds-font-body,var(--font-body-serif));color:var(--ds-ink,var(--ink));background:var(--ds-surface,transparent);font-size:var(--ds-body-size,13.5px);line-height:1.62;max-width:72ch}
.design-surface h1,.design-surface h2{font-family:var(--ds-font-heading,var(--display));color:var(--ds-accent,var(--accent));font-weight:650;letter-spacing:-.01em;margin:0 0 .45em}
.design-surface h1{font-size:var(--ds-h1,19px);border-bottom:1px solid var(--ds-accent,var(--accent));padding-bottom:5px}
.design-surface h2{font-size:var(--ds-h2,15.5px);margin-top:1.1em}
.design-surface h3{font-family:var(--ds-font-heading,var(--display));font-size:var(--ds-h3,13.5px);font-weight:650;color:var(--ds-ink,var(--ink));margin:1em 0 .35em}
.design-surface p,.design-surface li{font-size:var(--ds-body-size,13.5px)}
.design-surface a{color:var(--ds-accent,var(--accent))}
.design-surface hr{border:0;border-top:1px solid var(--ds-line,var(--line))}
.design-surface table{border-collapse:collapse}
.design-surface th{background:var(--ds-surface-2,var(--surface-2));border:1px solid var(--ds-accent,var(--accent));color:var(--ds-ink,var(--ink));font-family:var(--ds-font-heading,var(--display))}
.design-surface td{border:1px solid var(--ds-line,var(--line))}
.design-surface code,.design-surface pre{font-family:var(--ds-font-mono,var(--mono));font-size:.86em}
.design-surface blockquote{border-left:2px solid var(--ds-accent,var(--accent));margin:0;padding-left:10px;color:var(--ds-ink,var(--ink-2))}
/* The editable half, tinted by the same system so the surface a user TYPES into is visibly
   the document's own design rather than a generic grey box. Kept deliberately mild: this is
   a working textarea, not a rendered page, and it must stay comfortable to read for hours. */
.design-editor{font-family:var(--ds-font-body,inherit);color:var(--ds-ink,var(--ink));background:var(--ds-surface,var(--surface))}
/* The one-line honest statement of WHICH design is in effect and how faithful the render is.
   Never claims fidelity it does not have — 'approximate' is a real value it displays. */
.design-badge{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.design-badge strong{font-family:inherit;font-size:10px;color:var(--ds-accent,var(--accent))}
.design-badge em{font-style:normal;color:var(--mute);text-transform:none;letter-spacing:0;font-size:10.5px}

/* ---- the PDF print-preview popup (YUM-458) ------------------------------------------
   Ben, 2026-07-30: "an option for any file type to render it as a PDF to have a preview of the
   design ... open it in a pop-up, and the whole entire design is properly visible."

   A print-preview surface, not a dialog with a document squeezed into it: the pages get the
   room, the chrome gets a single compact bar. Deliberately NOT built on .mcard — that is a
   480px-max centred card for short forms, and a document preview needs the viewport.
   Dismissible three ways (x, Esc, backdrop) via the shared modal-shell primitives, and it
   does NOT trap focus: Tab walks out of it, which is why there is no aria-modal here. */
.docpv{position:fixed;inset:0;z-index:80;background:rgba(8,10,14,.62);display:flex;align-items:center;justify-content:center;padding:18px}
.docpv-card{position:relative;display:flex;flex-direction:column;width:100%;max-width:960px;height:100%;max-height:94vh;min-height:0;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow);overflow:hidden}
.docpv-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:10px;padding:10px 12px;border-bottom:1px solid var(--line-soft);background:var(--surface)}
.docpv-titles{display:grid;gap:3px;min-width:0}
.docpv-name{display:flex;align-items:center;gap:8px;min-width:0;font-weight:650;font-size:13px;color:var(--ink)}
.docpv-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.docpv-sub{font-size:11px;line-height:1.45;color:var(--mute)}
/* The fidelity chip. 'Exact' means these are the file's own bytes; 'Design' means the content
   was re-drawn in the active template and is NOT a conversion of the original's own styling.
   The distinction is the whole honesty story of this feature, so it is the first thing read. */
.docpv-chip{flex:0 0 auto;font-family:var(--mono);font-size:9.5px;letter-spacing:.07em;text-transform:uppercase;padding:2px 7px;border-radius:var(--r-pill);border:1px solid var(--line);color:var(--mute)}
.docpv-chip.exact{border-color:var(--trust-green);color:var(--trust-green)}
.docpv-chip.design{border-color:var(--accent);color:var(--accent)}
.docpv-tools{display:flex;align-items:center;gap:6px;flex:0 0 auto}
/* The page surround — a darker field so a white page reads as paper, exactly like a print
   preview. This is the only element that scrolls. */
.docpv-body{flex:1 1 auto;min-height:0;overflow:auto;background:var(--bg);padding:14px 10px 22px;overscroll-behavior:contain}
.docpv-stack{display:flex;flex-direction:column;align-items:center;gap:14px;min-height:min-content}
.docpv-page{display:block;max-width:100%;width:auto;height:auto;background:#fff;border:1px solid var(--line-soft);box-shadow:var(--shadow)}
.docpv-img{display:block;max-width:100%;max-height:100%;height:auto;object-fit:contain;background:var(--surface-2);border:1px solid var(--line-soft)}
.docpv-msg{display:flex;align-items:center;justify-content:center;gap:8px;padding:36px 16px;font-size:12px;color:var(--mute);text-align:center}
.docpv-msg.error{color:var(--ink-2)}
.docpv-count{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
/* C1 (2026-08-26): the Save-to-OneDrive error, shown under the popup's own header rather
   than in the large centred .docpv-msg body state — this is a small inline failure of one
   header action, not the whole preview failing. */
.docpv-onedrive-error{padding:2px 12px 8px;font-size:11px;color:var(--accent)}
@media (max-width:900px){
  /* Narrow: the popup takes the whole screen — a 380px-wide viewport has no room to waste on
     a scrim margin, and the page must still be fully visible without the body scrolling
     sideways. */
  .docpv{padding:0}
  .docpv-card{max-height:100vh;border:0;border-radius:0}
  .docpv-head{grid-template-columns:minmax(0,1fr) auto;padding:8px 10px}
  .docpv-body{padding:10px 6px 18px}
  .docpv-stack{gap:10px}
}

/* YUM-460/463 — rich toolbar + engine frames + honest range sliders */
.canvas-rich-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.canvas-style-select {
  font: inherit; font-size: 12px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 4px; padding: 4px 8px; height: 28px;
}
.canvas-swatch-row { display: inline-flex; gap: 4px; align-items: center; margin-left: 4px; }
.canvas-swatch {
  width: 16px; height: 16px; border-radius: 50%; border: 1px solid var(--line);
  padding: 0; cursor: pointer;
}
.canvas-u { text-decoration: underline; }
.canvas-rich-surface {
  min-height: 280px; max-height: 100%; overflow: auto;
  padding: 16px 18px; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px;
  outline: none; line-height: 1.5;
}
.canvas-rich-surface:focus { border-color: var(--ink-2); }
.canvas-strike { text-decoration: line-through; }
/* YUM-462 TipTap host + ProseMirror surface (semantic classes only) */
.canvas-tiptap-host {
  min-height: 280px; max-height: 100%; overflow: auto;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface);
}
.canvas-tiptap-surface {
  min-height: 280px; outline: none; padding: 16px 18px;
  color: var(--ink); line-height: 1.5; font: inherit;
}
.canvas-tiptap-surface:focus { outline: none; }
.canvas-tiptap-surface p { margin: 0 0 0.6em; }
.canvas-tiptap-surface h1 { font-size: 1.5em; margin: 0 0 0.5em; font-weight: 600; }
.canvas-tiptap-surface h2 { font-size: 1.25em; margin: 0 0 0.45em; font-weight: 600; }
.canvas-tiptap-surface h3 { font-size: 1.1em; margin: 0 0 0.4em; font-weight: 600; }
.canvas-tiptap-surface ul, .canvas-tiptap-surface ol { margin: 0 0 0.6em; padding-left: 1.4em; }
.canvas-tiptap-surface pre {
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: 4px; padding: 8px 10px; overflow: auto; font-family: var(--mono); font-size: 12.5px;
}
.canvas-tiptap-surface code { font-family: var(--mono); font-size: 0.92em; }
/* OnlyOffice must own the full dock pane height — align-content:start on the dock
   otherwise leaves a short strip and the PDF editor looks broken (Ben 2026-07-31). */
.right-dock-panels {
  height: 100%;
  align-items: stretch;
}
.right-dock.is-open .right-dock-panels {
  min-height: 100%;
}
.right-dock-panels > .canvas-pane {
  height: 100%;
  min-height: 0;
  align-self: stretch;
}
.canvas-pane:has(.canvas-onlyoffice-wrap),
.canvas-pane:has(.canvas-onlyoffice-host) {
  grid-template-rows: auto minmax(0, 1fr);
  height: 100%;
  min-height: min(80vh, 720px);
}
.canvas-body:has(.canvas-onlyoffice-wrap),
.canvas-body:has(.canvas-onlyoffice-host) {
  flex: 1 1 auto;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}
.canvas-onlyoffice-wrap, .canvas-onlyoffice-host, .canvas-onlyoffice-mount {
  width: 100%;
  height: 100%;
  min-height: min(72vh, 680px);
  flex: 1 1 auto;
  position: relative;
  display: flex;
  flex-direction: column;
}
.canvas-onlyoffice-mount,
.canvas-onlyoffice-mount > iframe {
  flex: 1 1 auto;
  width: 100% !important;
  height: 100% !important;
  min-height: min(72vh, 680px);
  border: 0;
}
/* Files row actions: real icons, not single-letter R/D chrome */
.files-row-action.files-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  min-height: 28px;
  padding: 4px;
}
.files-row-action.files-row-icon svg {
  display: block;
  width: 14px;
  height: 14px;
}
.canvas-engine-loading, .canvas-engine-fallback {
  padding: 16px; color: var(--mute); font-size: 13px;
}
[data-theme="night"] .canvas-tiptap-host,
[data-theme="enclave"] .canvas-tiptap-host,
[data-theme="night"] .canvas-tiptap-surface,
[data-theme="enclave"] .canvas-tiptap-surface {
  background: var(--surface); color: var(--ink);
}
/* Fixed range controls (zoom / split / opacity) — token-only, live, theme-aware (YUM-463) */
.canvas-range {
  -webkit-appearance: none; appearance: none;
  width: 96px; height: 4px; border-radius: 2px;
  background: var(--line); outline: none; vertical-align: middle;
  cursor: pointer; flex: 0 0 auto; margin: 0; padding: 0;
  accent-color: var(--ink);
}
.canvas-range:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.canvas-range::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px; background: var(--line);
}
.canvas-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--surface); cursor: pointer;
  margin-top: -4px; box-shadow: none;
}
.canvas-range::-moz-range-track {
  height: 4px; border-radius: 2px; background: var(--line); border: 0;
}
.canvas-range::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--ink); border: 2px solid var(--surface); cursor: pointer;
}
.canvas-range-label {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--mute); margin: 0;
}
.canvas-range-k {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--faint); flex: 0 0 auto;
}
.canvas-range-val {
  font-family: var(--mono); font-size: 10px; font-style: normal;
  color: var(--ink-2); min-width: 2.6em; text-align: right;
}
/* Dense office chrome: tighter action rows inherit .canvas-bar gap */
.dock-pane-actions{gap:3px}
.dock-split-ctrl{
  display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
  gap:4px; flex:0 0 40px; width:40px; padding:8px 4px;
  border-left:1px solid var(--line-soft); border-right:0;
  background:var(--surface-2);
}
.dock-split-ctrl .canvas-range{ width: 32px; }
.dock-split-ctrl .canvas-range-k{ font-size: 8.5px; }
/* Theme mirror on canvas chrome (inherits root tokens; keeps engines in sync) */
.canvas-chrome,
.canvas-chrome[data-theme="unison"],
.canvas-chrome[data-theme="night"],
.canvas-chrome[data-theme="enclave"],
[data-theme="night"] .canvas-rich-surface,
[data-theme="enclave"] .canvas-rich-surface,
[data-theme="night"] .canvas-tiptap-host,
[data-theme="enclave"] .canvas-tiptap-host {
  background: var(--surface); color: var(--ink);
}
[data-theme="night"] .canvas-range::-webkit-slider-thumb,
[data-theme="enclave"] .canvas-range::-webkit-slider-thumb,
.canvas-chrome[data-theme="night"] .canvas-range::-webkit-slider-thumb,
.canvas-chrome[data-theme="enclave"] .canvas-range::-webkit-slider-thumb {
  background: var(--ink); border-color: var(--surface);
}
[data-theme="night"] .canvas-range::-moz-range-thumb,
[data-theme="enclave"] .canvas-range::-moz-range-thumb {
  background: var(--ink); border-color: var(--surface);
}
/* Edit/preview split ratios (data-split; no inline grid styles) */
@media (min-width:720px){
  .canvas-split[data-split="40"]:not(.solo){grid-template-columns:minmax(0,4fr) minmax(0,6fr)}
  .canvas-split[data-split="45"]:not(.solo){grid-template-columns:minmax(0,45fr) minmax(0,55fr)}
  .canvas-split[data-split="50"]:not(.solo){grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .canvas-split[data-split="55"]:not(.solo){grid-template-columns:minmax(0,55fr) minmax(0,45fr)}
  .canvas-split[data-split="60"]:not(.solo){grid-template-columns:minmax(0,6fr) minmax(0,4fr)}
  .canvas-split[data-split="65"]:not(.solo){grid-template-columns:minmax(0,65fr) minmax(0,35fr)}
  .canvas-split[data-split="70"]:not(.solo){grid-template-columns:minmax(0,7fr) minmax(0,3fr)}
}
/* Image opacity steps (data-opacity — no dynamic className prefixes) */
.canvas-image[data-opacity="10"]{opacity:.10}.canvas-image[data-opacity="15"]{opacity:.15}
.canvas-image[data-opacity="20"]{opacity:.20}.canvas-image[data-opacity="25"]{opacity:.25}
.canvas-image[data-opacity="30"]{opacity:.30}.canvas-image[data-opacity="35"]{opacity:.35}
.canvas-image[data-opacity="40"]{opacity:.40}.canvas-image[data-opacity="45"]{opacity:.45}
.canvas-image[data-opacity="50"]{opacity:.50}.canvas-image[data-opacity="55"]{opacity:.55}
.canvas-image[data-opacity="60"]{opacity:.60}.canvas-image[data-opacity="65"]{opacity:.65}
.canvas-image[data-opacity="70"]{opacity:.70}.canvas-image[data-opacity="75"]{opacity:.75}
.canvas-image[data-opacity="80"]{opacity:.80}.canvas-image[data-opacity="85"]{opacity:.85}
.canvas-image[data-opacity="90"]{opacity:.90}.canvas-image[data-opacity="95"]{opacity:.95}
.canvas-image[data-opacity="100"]{opacity:1}

.canvas-swatch[data-i="0"] { background: #0E1116; }
.canvas-swatch[data-i="1"] { background: #2A2F36; }
.canvas-swatch[data-i="2"] { background: #B23A34; }
.canvas-swatch[data-i="3"] { background: #1B4D3E; }
.canvas-swatch[data-i="4"] { background: #1E3A5F; }
.canvas-swatch[data-i="5"] { background: #6B3A2A; }

/* YUM-509 visual polish — AFK production bar */
/* Short re-open tabs (not full-height vertical strips) */
.right-dock > .dock-files-tab.dock-min-strip,
.right-dock-panels > .dock-files-tab.dock-min-strip {
  position: absolute;
  top: 10px;
  left: -44px;
  z-index: 70;
  writing-mode: horizontal-tb;
  transform: none;
  width: auto;
  min-width: 40px;
  max-width: 72px;
  height: 36px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-right: 0;
  border-radius: var(--r-sm) 0 0 var(--r-sm);
  background: var(--surface);
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
  box-shadow: var(--shadow);
  cursor: pointer;
}
.right-dock > .dock-files-tab.dock-min-strip:hover,
.right-dock-panels > .dock-files-tab.dock-min-strip:hover {
  border-color: var(--accent);
  color: var(--accent);
}
/* Files-tab-only: no empty white column */
.right-dock.is-files-tab-only .right-dock-panels { width: 0 !important; border: 0; overflow: visible; }
.right-dock.is-files-tab-only { width: 0; overflow: visible; }
/* Thin resize seams — never a grey slab */
.right-dock-panels > .dock-resize {
  flex: 0 0 5px;
  width: 5px;
  min-width: 5px;
  max-width: 5px;
  background: var(--line-soft);
  border: 0;
  padding: 0;
  appearance: none;
  -webkit-appearance: none;
  cursor: col-resize;
  align-self: stretch;
}
.right-dock-panels > .dock-resize:hover,
.right-dock-panels > .dock-resize:focus-visible { background: var(--accent); }
/* Icon row actions denser + equal hit targets */
.files-row-actions { display: inline-flex; align-items: center; gap: 2px; flex: none; }
.files-row-action.files-row-icon,
.files-row-action.files-row-load {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  background: transparent;
  color: var(--mute);
  padding: 0;
  text-decoration: none;
}
.files-row-action.files-row-icon:hover,
.files-row-action.files-row-load:hover {
  border-color: var(--line);
  color: var(--ink);
  background: var(--surface);
}
/* Viewer head never clips toolbar hover */
.viewer-head, .dock-pane-head { overflow: visible; }
.viewer-pane.viewer-compact .dock-pane-actions .canvas-icon-btn:hover {
  z-index: 20;
  box-shadow: 0 2px 8px rgba(14,17,22,.12);
}
/* Range controls: denser, aligned with icon toolbar */
.viewer-pane .canvas-range-label {
  height: 30px;
  padding: 0 4px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-xs);
  background: var(--surface-2);
}
.viewer-pane .canvas-range { width: 72px; }
/* Files list density */
.files-drawer-sleek .files-row {
  padding: 6px 4px;
  gap: 6px;
  border-radius: var(--r-xs);
}
.files-drawer-sleek .files-row:hover { background: var(--surface); }
.files-section-label {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 10px 0 4px;
  padding: 0 2px;
}
/* Hide legacy battery entirely */
.files-battery { display: none !important; }

/* YUM-509: canvas+files split — prevent header smash */
.right-dock.is-split .canvas-head {
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 8px;
  min-height: 0;
}
.right-dock.is-split .canvas-title {
  flex: 1 1 100%;
  min-width: 0;
  order: -1;
}
.right-dock.is-split .canvas-title-input,
.right-dock.is-split .canvas-title strong {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
}
.right-dock.is-split .canvas-tree-toggle {
  display: none; /* Files drawer is the roster when both are open */
}
.right-dock.is-split .canvas-rail { display: none; }
.right-dock.is-split .canvas-actions {
  flex: 1 1 auto;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 4px;
}
/* Text editor split range: horizontal, never a vertical mystery gutter */
.canvas-split-ctrl,
.canvas-bar .canvas-range-label {
  flex-wrap: nowrap;
  align-items: center;
}
.right-dock.is-split .canvas-split[data-split] {
  min-height: 0;
}
/* Viewer + files: viewer column claims remaining space cleanly */
.right-dock.is-split .viewer-pane.viewer-compact {
  min-width: 240px;
}
.right-dock.is-split .right-dock-panels {
  align-items: stretch;
}

/* YUM-509 editor+files toolbar density */
.right-dock.is-split .canvas-action {
  min-height: 28px;
  padding: 4px 8px;
  font-size: 11.5px;
}
.right-dock.is-split .canvas-bar .canvas-range-label {
  max-width: 100%;
}
.right-dock.is-split .canvas-title-input {
  width: 100%;
  max-width: 100%;
  font-size: 13px;
  font-weight: 600;
}
.right-dock.is-split .canvas-head .canvas-tree-toggle,
.right-dock.is-split .canvas-pane-row > .canvas-rail { display: none !important; }
/* Hide the edit/preview SPLIT range when the pane is already cramped beside Files */
.right-dock.is-split .canvas-range-label,
.right-dock.is-split .canvas-range-k,
.right-dock.is-split .canvas-range-val {
  /* keep ranges usable but denser when dock is split — do not hide entirely */
  font-size: 9px;
}

/* YUM-509: coach tips must not cover dock chrome while files/viewer are open */
.yarnball-shell.dock-open .tip-bubble {
  display: none !important;
}

/* File browser list body: always scrollable so empty + dual-section layouts don't clip.
   Top-level .files-list is required by the design-system gate (scoped-only defs fail lint). */
.files-list{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:2px}
.files-drawer .files-list{flex:1 1 auto;min-height:0;overflow:auto}
/* Compact viewer spreadsheet grid fills the pane instead of collapsing to a blank note. */
.viewer-sheet-wrap{flex:1 1 auto;min-height:0;height:100%;overflow:auto;padding:4px 6px;display:flex;flex-direction:column;background:var(--bg)}
.viewer-sheet-wrap .canvas-grid{max-height:none;flex:1 1 auto;min-height:0;height:100%;border-radius:var(--r-xs)}
.viewer-sheet-wrap .canvas-grid table{min-width:100%}
.viewer-sheet-wrap .canvas-bar{flex:0 0 auto;flex-wrap:wrap;gap:6px}
.viewer-pane.viewer-compact .viewer-sheet-wrap{flex:1 1 auto;min-height:0;height:100%}
.viewer-pane.viewer-compact .viewer-body{display:flex;flex-direction:column;min-height:0}
/* Dense sheet in the viewer: slightly wider cells so values are readable while resizing. */
.viewer-sheet-wrap .canvas-grid-dense th,.viewer-sheet-wrap .canvas-grid-dense td{min-width:88px}
.viewer-sheet-wrap .canvas-grid-dense .canvas-cell{font-size:12.5px;min-height:26px;padding:3px 6px}

/* PR 332: mark desktop widgets & telepathy modal additions */
.mark-widget {
  display: flex;
  flex-direction: column;
}
.mark-desktop-container {
  display: grid;
}
.mark-widget-focus {
  outline: 2px solid var(--accent);
}
.telepathy-modal-body {}
.cds-card {}
.cds-badge {}
.cds-group {}
.form-input {}
/* ============================================================================
   PDF editing suite (doc-editors/pdf-suite.js, doc-editors/signature.js)

   ONE block. This replaces seventeen appended patches that had accumulated over
   a day of changes and were overriding each other — later rules undoing earlier
   ones, sizes set three times with different values, a portrait ratio fighting a
   min-height. That is why the layout came apart. Everything the two modules can
   render is defined here, once, in reading order: shell, tabs, toolbar, page
   column, inspector, page grid, opener, signature dialog.

   House rules: semantic classes only, existing tokens only, no inline styles in
   app code (scripts/lint-styles.mjs enforces it), and every class the JS names
   must exist here (scripts/cds-lint.mjs enforces that).
   ============================================================================ */

/* ---- shell ---- */
.pdfed{position:fixed;inset:0;z-index:120;display:flex;align-items:center;justify-content:center;padding:4vh 4vw;background:rgba(8,10,14,.62)}
.pdfed-card{position:relative;display:flex;flex-direction:column;width:100%;max-width:min(1040px,92vw);height:auto;max-height:86vh;min-height:0;overflow:hidden;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:var(--shadow)}
.pdfed-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:10px;flex:0 0 auto;padding:10px 12px;border-bottom:1px solid var(--line-soft);background:var(--surface)}
.pdfed-titles{display:grid;gap:3px;min-width:0}
.pdfed-name{display:flex;align-items:center;gap:8px;min-width:0;font-size:15px;font-weight:650;color:var(--ink)}
.pdfed-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pdfed-sub{font-size:12.5px;line-height:1.5;color:var(--mute)}
.pdfed-tools{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.pdfed-pending{flex:0 0 auto;padding:2px 7px;border:1px solid var(--accent);border-radius:var(--r-pill);font-family:var(--mono);font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--accent)}

/* ---- tabs ---- */
.pdfed-tabs{display:flex;align-items:center;gap:2px;flex:0 0 auto;padding:0 12px;border-bottom:1px solid var(--line-soft);background:var(--surface)}
.pdfed-tab{appearance:none;border:0;border-bottom:2px solid transparent;background:transparent;padding:9px 14px;font:inherit;font-size:13.5px;font-weight:600;line-height:1.2;color:var(--mute)}
.pdfed-tab:hover{color:var(--ink)}
.pdfed-tab[aria-selected="true"]{color:var(--ink);border-bottom-color:var(--accent)}

/* ---- toolbar ---- */
.pdfed-bar{display:flex;align-items:center;gap:4px;flex-wrap:wrap;flex:0 0 auto;padding:7px 12px;border-bottom:1px solid var(--line-soft);background:var(--surface-2)}
.pdfed-tool{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;box-sizing:border-box;padding:5px 12px;border:1px solid var(--line);border-radius:var(--r-xs);background:transparent;color:var(--ink);font:inherit;font-size:13px;font-weight:500;line-height:1.2;text-decoration:none}
.pdfed-tool:hover{background:var(--surface)}
.pdfed-tool[disabled]{opacity:.45;cursor:not-allowed}
.pdfed-tool.active{background:var(--ink);border-color:var(--ink);color:var(--surface);font-weight:650}
.pdfed-sep{width:1px;align-self:stretch;margin:0 4px;background:var(--line)}
.pdfed-zoom{display:inline-flex;align-items:center;gap:4px}
.pdfed-zoom-val{min-width:44px;font-family:var(--mono);font-size:12px;color:var(--faint);text-align:center}

/* ---- work area: page column + inspector ---- */
.pdfed-work{display:flex;flex:1 1 auto;min-height:0}
.pdfed-body{flex:1 1 auto;min-width:0;min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px;background:var(--bg);scrollbar-width:none;-ms-overflow-style:none}
.pdfed-body::-webkit-scrollbar{width:0;height:0;display:none}
.pdfed-msg{display:flex;align-items:center;justify-content:center;gap:8px;padding:36px 16px;font-size:12px;color:var(--mute);text-align:center}
.pdfed-msg.error{color:var(--ink-2)}

/* ---- the document, page after page ---- */
.pdfed-doc{display:flex;flex-direction:column;align-items:center;gap:16px;width:max-content;min-width:100%;padding-bottom:12px}
.pdfed-sheet{position:relative;display:grid;gap:5px;justify-items:center;scroll-margin-top:12px}
.pdfed-sheet.flash .pdfed-canvas{outline:2px solid var(--accent);outline-offset:2px}
.pdfed-sheet-label{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
/* The page image and the staged marks are two stacked canvases of identical size. */
.pdfed-canvas{position:relative;display:block;line-height:0}
.pdfed-canvas canvas{display:block;max-width:none;height:auto;background:#fff;border:1px solid var(--line-soft);box-shadow:var(--shadow)}
.pdfed-canvas canvas.pdfed-layer{position:absolute;left:0;top:0;background:transparent;border:0;box-shadow:none;pointer-events:none}
.pdfed-hold{min-height:min(70vh,760px);min-width:280px;border:1px solid var(--line-soft);background:var(--surface)}
.pdfed-sheet.placing .pdfed-canvas canvas{cursor:crosshair}
.pdfed-sheet.movable .pdfed-canvas canvas{cursor:grab}
.pdfed-sheet.grabbing .pdfed-canvas canvas{cursor:grabbing}

/* ---- inspector ---- */
.pdfed-side{flex:0 0 240px;display:flex;flex-direction:column;gap:10px;min-width:0;padding:12px;overflow:auto;overscroll-behavior:contain;border-left:1px solid var(--line-soft);background:var(--surface)}
.pdfed-side-title{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
.pdfed-side-note{font-size:12.5px;line-height:1.5;color:var(--mute)}
.pdfed-side-group{display:grid;gap:7px;min-width:0}
.pdfed-side-actions{display:flex;flex-wrap:wrap;gap:6px}
.pdfed-row{display:grid;gap:3px;min-width:0}
.pdfed-row>span{font-size:12px;color:var(--mute)}
.pdfed-row select,.pdfed-row input,.pdfed-row textarea{box-sizing:border-box;width:100%;max-width:100%;min-width:0;min-height:32px;padding:5px 8px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font:inherit;font-size:13px}
.pdfed-row textarea{min-height:64px;line-height:1.4;resize:vertical}
.pdfed-row input[type="color"]{height:32px;padding:2px}
.pdfed-pair{display:grid;grid-template-columns:1fr 1fr;gap:8px;min-width:0}
.pdfed-toggles{display:flex;gap:4px}

/* ---- Pages tab ---- */
.pdfed-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px;align-items:start}
.pdfed-page{position:relative;display:grid;gap:6px;justify-items:center;padding:8px;border:1px solid transparent;border-radius:var(--r-xs)}
.pdfed-page.selected{border-color:var(--accent)}
.pdfed-page.dragging{opacity:.4}
.pdfed-page canvas{display:block;max-width:100%;height:auto;background:#fff;border:1px solid var(--line-soft);box-shadow:var(--shadow)}
.pdfed-page-num{font-family:var(--mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.pdfed-page-acts{display:flex;align-items:center;gap:3px}
.pdfed-page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:24px;min-height:24px;padding:2px 5px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink-2);font:inherit;font-size:12px;line-height:1}
.pdfed-page-btn:hover{background:var(--surface-2);color:var(--ink)}
.pdfed-page-btn.danger:hover{border-color:var(--accent);color:var(--accent)}

/* ---- opener: pick a document by looking at it ---- */
.pdfed-start{display:flex;flex-direction:column;align-items:center;gap:16px;padding:4px 0 24px}
.pdfed-alert{width:100%;max-width:720px;padding:9px 12px;border:1px solid var(--accent);border-left-width:3px;border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font-size:12px;line-height:1.5}
.pdfed-doccards-title{width:100%;max-width:720px}
.pdfed-doccards{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:14px;width:100%;max-width:720px}
.pdfed-doccard{display:grid;gap:6px;justify-items:center;align-content:start;min-width:0;padding:0;border:0;background:transparent;font:inherit;color:var(--ink);text-align:center}
.pdfed-doccard-sheet{display:grid;place-items:center;width:100%;aspect-ratio:1/1.3;overflow:hidden;border:1px solid var(--line-soft);border-radius:8px;background:#fff;box-shadow:0 1px 3px rgba(8,10,14,.07);transition:border-color .16s ease,box-shadow .16s ease}
.pdfed-doccard:hover .pdfed-doccard-sheet{border-color:var(--accent);box-shadow:0 6px 16px rgba(8,10,14,.12)}
.pdfed-doccard:focus-visible .pdfed-doccard-sheet{outline:2px solid var(--accent);outline-offset:2px}
.pdfed-doccard-sheet canvas{display:block;max-width:100%;height:auto}
.pdfed-doccard-name{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11.5px;line-height:1.35;color:var(--ink)}
.pdfed-doccard-when{font-family:var(--mono);font-size:9px;letter-spacing:.03em;color:var(--faint)}
.pdfed-doccard-note{padding:0 8px;font-size:10px;line-height:1.4;color:var(--mute);text-align:center}
.pdfed-doccard-new .pdfed-doccard-sheet{border-width:2px;border-style:dashed;border-color:var(--line);background:var(--surface)}
.pdfed-doccard-new.over .pdfed-doccard-sheet{border-style:solid;border-color:var(--accent);background:var(--surface-2)}
.pdfed-doccard-plus{display:grid;place-items:center;width:42px;height:42px;border:1px solid var(--line-soft);border-radius:50%;background:var(--surface-2);color:var(--accent);font-size:22px;font-weight:300;line-height:1}
.pdfed-doccard-new:hover .pdfed-doccard-plus{background:var(--surface)}

/* ---- signature dialog ---- */
.pdfed-sig{position:fixed;inset:0;z-index:130;display:flex;align-items:center;justify-content:center;padding:18px;background:rgba(8,10,14,.55)}
.pdfed-sig-card{display:flex;flex-direction:column;gap:12px;width:100%;max-width:520px;max-height:90vh;overflow:auto;padding:16px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);box-shadow:var(--shadow)}
.pdfed-sig-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.pdfed-sig-title{font-size:13px;font-weight:650;color:var(--ink)}
.pdfed-sig-tabs{display:flex;gap:2px}
.pdfed-sig-pad{width:100%;height:150px;border:1px dashed var(--line);border-radius:var(--r-xs);background:#fff;touch-action:none;cursor:crosshair}
.pdfed-sig-preview{display:block;max-width:100%;height:64px;border:1px solid var(--line-soft);border-radius:var(--r-xs);background:#fff}
.pdfed-sig-saved{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px}
.pdfed-sig-item{display:grid;gap:4px;justify-items:center;padding:6px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface)}
.pdfed-sig-item:hover{border-color:var(--accent)}
.pdfed-sig-item img{display:block;max-width:100%;height:44px;object-fit:contain;background:#fff}
.pdfed-sig-item span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;color:var(--mute)}
.pdfed-sig-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pdfed-sig-row input[type="text"]{flex:1 1 180px;box-sizing:border-box;min-height:30px;padding:4px 8px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font:inherit;font-size:12.5px}
.pdfed-sig-note{font-size:11px;line-height:1.45;color:var(--mute)}

/* ---- narrow screens: the inspector becomes a strip, the editor fills the screen ---- */
@media (max-width:900px){
  .pdfed{padding:0}
  .pdfed-card{max-width:100vw;max-height:100vh;height:100%;border:0;border-radius:0}
  .pdfed-head{padding:8px 10px}
  .pdfed-body{padding:10px}
  .pdfed-work{flex-direction:column}
  .pdfed-side{flex:0 0 auto;max-height:44vh;border-left:0;border-top:1px solid var(--line-soft)}
  .pdfed-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px}
  .pdfed-doccards{grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:10px}
}

/* Two classes the JS names that the consolidation dropped.
   .pdfed-layer must ALSO exist unscoped: the style gate requires any class app code names to be
   defined on its own, so it still applies if the element is ever moved. The scoped rule above
   is what wins over `.pdfed-sheet canvas`, which paints canvases white. */
.pdfed-layer{position:absolute;left:0;top:0;background:transparent;border:0;box-shadow:none;pointer-events:none}
.pdfed-empty{display:flex;align-items:center;justify-content:center;padding:6px 16px 2px;font-size:11.5px;line-height:1.45;color:var(--mute);text-align:center}

/* The opener was a tall mostly-empty room with one small card floating in it, and type too
   small to read comfortably. It now sizes to what it holds and speaks up. */
.pdfed-start{gap:14px;padding:16px 0 20px;justify-content:flex-start}
.pdfed-card:has(.pdfed-start) .pdfed-body{min-height:0}
.pdfed-doccards-title .pdfed-side-title{font-size:11px;letter-spacing:.09em}
.pdfed-doccard-name{font-size:13px;line-height:1.4}
.pdfed-doccard-when{font-size:10px}
.pdfed-doccard-note{font-size:11.5px}
.pdfed-doccard-plus{width:48px;height:48px;font-size:26px}

/* A card for a kind with no first page to draw shows what it is instead of an empty sheet. */
.pdfed-doccard-kind{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}

/* ---- spreadsheet and deck panes ---------------------------------------------------------
   A workbook wants a dense grid you can tab through; a deck wants one text block per slide.
   Neither wants the PDF page chrome, so neither gets it. */
.pdfed-sheetpane{display:flex;flex-direction:column;gap:10px;min-width:0}
.pdfed-sheettabs{display:flex;gap:2px;flex-wrap:wrap;border-bottom:1px solid var(--line-soft)}
.pdfed-gridwrap{overflow:auto;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface)}
.pdfed-sheet-table{border-collapse:collapse;font-size:13px;color:var(--ink)}
.pdfed-sheet-table th{position:sticky;top:0;z-index:1;padding:5px 8px;border:1px solid var(--line-soft);background:var(--surface-2);font-family:var(--mono);font-size:11px;font-weight:500;color:var(--faint);text-align:center}
.pdfed-sheet-rownum{position:sticky;left:0;z-index:2}
.pdfed-sheet-corner{position:sticky;left:0;z-index:3}
.pdfed-sheet-table td{padding:0;border:1px solid var(--line-soft)}
.pdfed-sheet-table input{box-sizing:border-box;width:150px;min-width:150px;min-height:30px;padding:4px 8px;border:0;background:transparent;color:var(--ink);font:inherit;font-size:13px}
.pdfed-sheet-table input:focus{outline:2px solid var(--accent);outline-offset:-2px;background:var(--surface)}
.pdfed-slidepane{display:flex;flex-direction:column;gap:14px;width:100%;max-width:820px;margin:0 auto}
.pdfed-slide{display:grid;gap:6px}
.pdfed-slide-text{box-sizing:border-box;width:100%;min-height:150px;padding:12px 14px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font:inherit;font-size:14px;line-height:1.6;resize:vertical}
.pdfed-slide-text:focus{outline:2px solid var(--accent);outline-offset:-2px}

/* ---- spreadsheet extras: readable columns and a glance-at-it chart ---------------------- */
.pdfed-cell-num input{text-align:right;font-variant-numeric:tabular-nums}
.pdfed-sheet-headrow input{font-weight:650;background:var(--surface-2)}
.pdfed-chartwrap{padding:10px 12px;border:1px solid var(--line-soft);border-radius:var(--r-xs);background:var(--surface);overflow:auto}
.pdfed-chart{min-height:40px}
.pdfed-chart canvas{display:block;max-width:100%;height:auto}
.pdfed-field{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--mute)}
.pdfed-field select{box-sizing:border-box;min-height:32px;padding:4px 8px;border:1px solid var(--line);border-radius:var(--r-xs);background:var(--surface);color:var(--ink);font:inherit;font-size:13px}

/* ---- deck: real slide pictures beside the text they come from ---- */
.pdfed-slides{display:grid;gap:16px;width:100%;max-width:860px;margin:0 auto}
.pdfed-slide{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:start;padding:10px;border:1px solid transparent;border-radius:var(--r-sm)}
.pdfed-slide.selected{border-color:var(--accent);background:var(--surface)}
.pdfed-slide .pdfed-sheet-label{grid-column:1/-1}
.pdfed-slide-thumb{display:grid;place-items:center;width:260px;min-height:90px;overflow:hidden;border:1px solid var(--line-soft);border-radius:var(--r-xs);background:#fff;box-shadow:0 1px 3px rgba(8,10,14,.07)}
.pdfed-slide-thumb canvas{display:block;max-width:100%;height:auto}
@media (max-width:900px){
  .pdfed-slide{grid-template-columns:minmax(0,1fr)}
  .pdfed-slide-thumb{width:100%}
}

/* The deck rendered by the library that understands it — pictures included — above the
   per-slide text. .pdfed-slide-thumb is gone with the drawn-from-text strip it belonged to. */
.pdfed-deckpreview{display:grid;gap:8px;width:100%;max-width:880px;margin:0 auto}
.pdfed-deckhost{display:grid;gap:14px;justify-items:center;width:100%}
.pdfed-deckhost canvas,.pdfed-deckhost img{display:block;max-width:100%;height:auto;background:#fff;border:1px solid var(--line-soft);border-radius:var(--r-xs);box-shadow:0 1px 3px rgba(8,10,14,.08)}
.pdfed-slide{grid-template-columns:minmax(0,1fr)}
/* Full-screen in-app document editor popup modal (ben.yarnball web/desktop feature) */
.canvas-popup-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9990;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5vh 1.5vw;
  box-sizing: border-box;
}

.canvas-popup-dialog {
  width: 96vw;
  height: 94vh;
  /* Floor as well as ceiling: dragging the corner must not be able to shrink the dialog to
     a strip too small to hold a document. */
  min-width: 480px;
  min-height: 380px;
  max-width: 1720px;
  max-height: 1080px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md, 8px);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  /* hidden, not auto: the dialog is a flex column whose body scrolls on its own. `resize`
     renders its handle for any overflow other than `visible`, so this does not disable it. */
  overflow: hidden;
  position: relative;
  resize: both;
}

/* Maximized: fill the viewport exactly. max-width/max-height must be cleared explicitly or
   the 1720x1080 ceiling would silently cap "maximize" on a large display, and the dragged
   inline size is dropped by remounting the dialog (see FullScreenEditorModal's key). */
.canvas-popup-backdrop.is-maximized { padding: 0; }
.canvas-popup-dialog.is-maximized {
  width: 100vw;
  height: 100vh;
  max-width: none;
  max-height: none;
  border-radius: 0;
  border-width: 0;
  /* A resize handle while maximized would fight the maximized size on the next reflow. */
  resize: none;
}

.canvas-popup-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  background: var(--surface-2, #f5f5f5);
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}

.canvas-popup-title-area {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.canvas-popup-badge {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 4px;
  background: var(--accent-light, rgba(0, 100, 250, 0.1));
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.canvas-popup-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  position: relative;
}

.canvas-popup-body .canvas-pane {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  height: 100%;
  width: 100%;
}

.opendesign-editor {
  padding: 16px;
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 12px;
}

.opendesign-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px;
}

.opendesign-preview {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: auto;
  background: var(--surface);
  padding: 16px;
}

.opendesign-nest-tree {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: auto;
  background: #0f172a;
  color: #38bdf8;
  padding: 16px;
  font-family: var(--mono);
  font-size: 13px;
}

.canvas-tree-node {
  margin-bottom: 8px;
}

.canvas-tree-body {
  margin-top: 12px;
}

/* ---- YUM-907: composer "+" (attach+thinking) and mic states (Ben, 2026-08-22) -----------
   These belong next to .composer-icon-red / .attach-menu / .clip--sm in app-extensions.css —
   that file is under an active file claim right now (YUM-903, agent claude-opus5-ybspeed),
   so it cannot be touched from this branch without colliding. Housed here instead: canvas.css
   is a registered CDS stylesheet (scripts/cds-lint.mjs DS_STYLESHEETS), already linked from
   index.html, and free. Same token vocabulary as everywhere else in CDS 1.0.3 — move these
   rules into app-extensions.css next to their siblings once that claim releases; nothing
   about the rules themselves needs to change. */

/* The "+" control folds the deep-thinking toggle in with the attach menu, so thinking's
   on/off state loses its own dedicated (always-visible) icon. This quiet corner dot is the
   replacement — readable at a glance without opening the menu, deliberately smaller and less
   assertive than a full is-on fill so it reads as "a setting is on" rather than "this button
   is currently pressed". Sized and positioned like the other small state dots already in the
   system (conn-cap-item-dot, sync-status-row-dot); .attach-menu-anchor is already
   position:relative, so no extra wrapper is needed. */
.composer-plus-think-dot {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent, #B23A34);
  border: 1px solid var(--surface, #fff);
  pointer-events: none;
}

/* Mic "sticky" (double-press toggle-on) recording: layered on top of the existing .is-on
   fill (shared with every other composer icon toggle) so the button still reads as
   "recording", plus a dashed outline meaning specifically "and it will not stop when you let
   go" — distinct from a held push-to-talk press, which only ever shows the plain .is-on fill. */
.composer-icon-red.is-sticky {
  outline: 2px dashed var(--accent, #B23A34);
  outline-offset: 2px;
}

/* YUM-907: the new Apps-screen Browser row (appstore.js) is the one row in that list that
   carries a leading icon — a real, verified glyph ('globe', added 2026-08-21 for WS-17's
   language control; the old "no globe glyph" note on this feature predates that and was
   stale by the time this landed). .apps-row-name has no flex layout of its own (every
   other row in that list is icon-less text), so this is a plain inline nudge rather than a
   flex wrapper — cheaper than reshaping a class this branch does not own. */
.apps-row-icon { margin-right: 7px; vertical-align: -3px; color: var(--accent, #B23A34); }
