
/* Canvas image-card actions and directed connections. Preview-only, no global overrides. */
#connectionSvg .edge-path{
 stroke:var(--connection-color,#c7ccd2)!important;
 stroke-width:2.2px;stroke-linecap:round;transition:stroke .15s,filter .15s;
}
#connectionSvg .edge-path.selected{
 stroke:var(--accent,#edca68)!important;stroke-width:3.5px;
 filter:drop-shadow(0 0 4px rgba(250,205,73,.5));
}
#connectionSvg .edge-scissors{cursor:pointer;pointer-events:all}
#connectionSvg .edge-scissors rect{
 fill:var(--surface,#25282c);stroke:var(--accent,#edca68);stroke-width:1.4px;
 filter:drop-shadow(0 5px 12px rgba(0,0,0,.3));
}
#connectionSvg .edge-scissors text{
 pointer-events:none;fill:var(--text,#efefee);font-size:18px;font-family:sans-serif;
}
.canvas-node.selected.image-node{z-index:6!important}
.canvas-node.image-node .canvas-image-tools{
 display:none;position:absolute;left:50%;top:-51px;transform:translateX(-50%);
 align-items:center;gap:3px;white-space:nowrap;padding:6px 8px;z-index:11;
 border-radius:13px;border:1px solid var(--edge);
 background:color-mix(in srgb,var(--glass) 92%,transparent);
 -webkit-backdrop-filter:blur(24px) saturate(145%);
 backdrop-filter:blur(24px) saturate(145%);
 box-shadow:inset 0 1px 0 rgba(255,255,255,.09),0 12px 30px rgba(0,0,0,.23);
}
.canvas-node.selected.image-node .canvas-image-tools{display:flex}
.canvas-image-tools button{
 background:transparent;border:1px solid transparent;border-radius:9px;
 padding:6px 9px;color:var(--text);font:inherit;font-size:11px;
 cursor:pointer;transition:background .14s,border-color .14s,color .14s;
}
.canvas-image-tools button:hover{
 border-color:color-mix(in srgb,var(--accent) 53%,transparent);
 background:color-mix(in srgb,var(--accent) 16%,transparent);
 color:var(--accent);
}
.canvas-image-tools button:focus-visible{
 outline:2px solid var(--accent);outline-offset:2px;
}
.canvas-image-tools button[data-image-action="world"]{
 color:var(--accent);
 border-left:1px solid var(--edge);border-radius:4px 9px 9px 4px;
}
.canvas-image-tools .canvas-crop-cancel{display:none}
.canvas-image-tools.is-cropping button:not([data-image-action="crop"]):not(.canvas-crop-cancel){display:none}
.canvas-image-tools.is-cropping .canvas-crop-cancel{display:inline-block;color:var(--muted)}
.canvas-node.image-node .node-body{position:relative}
.canvas-crop-pane{
 position:absolute;z-index:9;touch-action:none;
 background:rgba(0,0,0,.28);cursor:crosshair;
 box-shadow:0 0 0 1px rgba(255,255,255,.26);
}
.canvas-crop-box{
 position:absolute;border:2px solid #f3ce5a;
 background:rgba(244,208,78,.09);
 box-shadow:0 0 0 9999px rgba(0,0,0,.27),0 0 0 1px rgba(0,0,0,.25);
 pointer-events:none;
}
.canvas-crop-box::before,.canvas-crop-box::after{
 content:"";position:absolute;top:0;bottom:0;width:1px;background:rgba(255,255,255,.38)
}
.canvas-crop-box::before{left:33.333%}
.canvas-crop-box::after{right:33.333%}
body[data-theme="light"] .canvas-node.image-node .canvas-image-tools{
 box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 10px 28px rgba(40,45,45,.15);
}


/* Keep cards and their yellow ports above the line hit layer, so the
 * wider hit target does not steal drags beginning/ending at a port. */
#canvasViewport .canvas-world{z-index:4!important}
#canvasViewport #nodesLayer .canvas-node{pointer-events:auto}

/* 2026-10-22: lines use viewport pixels, NOT zoomed node coordinates.
 * A full-size overlay fixes the old 1px SVG hit-testing failure. */
#canvasViewport #connectionSvg.connection-svg{
 position:absolute!important;
 inset:0!important;
 width:100%!important;
 height:100%!important;
 overflow:hidden!important;
 z-index:3!important;
 pointer-events:none!important;
}
#canvasViewport #connectionSvg .edge-path{
 pointer-events:none!important;
 stroke-width:2.2px!important;
 vector-effect:non-scaling-stroke;
}
#canvasViewport #connectionSvg .edge-path.selected{
 pointer-events:none!important;
 stroke-width:3.5px!important;
}
#canvasViewport #connectionSvg .edge-hit{
 fill:none!important;
 stroke:rgba(0,0,0,.001)!important;
 stroke-width:16px!important;
 stroke-linecap:round;
 vector-effect:non-scaling-stroke;
 cursor:pointer!important;
 pointer-events:stroke!important;
}
#canvasViewport #connectionSvg .edge-scissors{
 cursor:pointer!important;
 pointer-events:all!important;
}
#canvasViewport #connectionSvg path.pending{
 pointer-events:none!important;
 stroke-width:2px!important;
}

/* Idle is the standard arrow, and panning has an active closed hand.
 * Both left- and middle-button dragging on empty grid pan the viewport. */
#canvasViewport.canvas-viewport{cursor:default!important}
#canvasViewport.canvas-viewport.panning{cursor:grabbing!important}
#canvasViewport.canvas-viewport .canvas-node .node-header{cursor:move}

/* Toolbar body remains normal CSS size; JS computes inverse zoom and
 * pixel-aligned offsets while keeping it attached above its image node. */
#canvasViewport .canvas-node.image-node .canvas-image-tools{
 transform-origin:top left;
 will-change:transform;
}

/* Same 35px height as existing status bar, but truly semicircular ends. */
html body:has(#editorView:not([hidden])) .topbar #boardHead.canvas-status-dock:not([hidden]),
html body[data-theme="light"]:has(#editorView:not([hidden])) .topbar #boardHead.canvas-status-dock:not([hidden]),
html body[data-theme="dark"]:has(#editorView:not([hidden])) .topbar #boardHead.canvas-status-dock:not([hidden]){
 border-radius:9999px!important;
}


/* 2026-10-22 follow-up: refined visual weight. The 16px invisible
   selection hit area stays wide, but the painted curve becomes delicate. */
#canvasViewport #connectionSvg .edge-path{
  stroke-width:1.3px!important;
  filter:none!important;
}
#canvasViewport #connectionSvg .edge-path.selected{
  stroke-width:1.9px!important;
  filter:drop-shadow(0 0 2px rgba(250,205,73,.18))!important;
}
#canvasViewport #connectionSvg path.pending{stroke-width:1.3px!important}

/* Port the ENTIRE toolbar into the untransformed viewport.
   Unlike 1/zoom scaling inside the canvas-world, this never raster-scales
   live glyphs or backdrop effects and remains sharp at every canvas zoom. */
#canvasViewport > #canvasImageToolbarLayer.canvas-image-toolbar-layer{
 position:absolute!important;inset:0!important;
 width:100%!important;height:100%!important;
 pointer-events:none!important;z-index:5!important;
 overflow:hidden!important;
}
#canvasViewport > #canvasImageToolbarLayer .canvas-image-tools{
 position:absolute!important;
 display:flex!important;align-items:center!important;gap:3px!important;
 white-space:nowrap!important;
 margin:0!important;padding:6px 8px!important;
 border-radius:13px!important;border:1px solid var(--edge)!important;
 background:color-mix(in srgb,var(--glass) 92%,transparent)!important;
 backdrop-filter:blur(24px) saturate(145%)!important;
 -webkit-backdrop-filter:blur(24px) saturate(145%)!important;
 box-shadow:inset 0 1px 0 rgba(255,255,255,.09),0 12px 30px rgba(0,0,0,.23)!important;
 transform:none!important;transform-origin:initial!important;
 will-change:auto!important;
 pointer-events:auto!important;
 z-index:1!important;
}
#canvasViewport > #canvasImageToolbarLayer .canvas-image-tools[hidden]{
 display:none!important;
}
body[data-theme="light"] #canvasViewport > #canvasImageToolbarLayer .canvas-image-tools{
 box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 10px 28px rgba(40,45,45,.15)!important;
}

/* Narrow the surrounding DOCKS only. Keep icon/label sizes, glass
   effects and all existing inspector and right-side layout calculations. */
html body:has(#editorView:not([hidden])) #editorView > .palette.glass{
 width:59px!important;
 padding:10px 5px!important;
 gap:3px!important;
}
html body:has(#editorView:not([hidden])) #editorView > .palette.glass > button:not(#canvasAddBtn){
 width:46px!important;
 min-height:46px!important;
 padding:5px 2px!important;
}
html body:has(#editorView:not([hidden])) #editorView > #canvasShell > .canvas-toptools.glass{
 padding:4px 6px!important;
 gap:2px!important;
}
html body:has(#editorView:not([hidden])) #editorView > #canvasShell > .canvas-toptools.glass button{
 padding-top:6px!important;
 padding-bottom:6px!important;
}

/* The title/underline exactly follow the measured text width, not the
   old full-width right-aligned input. Blur on outside click is in JS. */
html body:has(#editorView:not([hidden])) .topbar #canvasTitleDock #boardTitle,
html body[data-theme="light"]:has(#editorView:not([hidden])) .topbar #canvasTitleDock #boardTitle,
html body[data-theme="dark"]:has(#editorView:not([hidden])) .topbar #canvasTitleDock #boardTitle{
 flex:0 1 auto!important;
 width:var(--canvas-title-text-width,110px)!important;
 max-width:min(238px,calc(100% - 34px))!important;
 height:27px!important;
 line-height:27px!important;
 padding:0 5px!important;
 text-align:center!important;
 border-bottom:1px solid transparent!important;
 box-shadow:none!important;
}
html body:has(#editorView:not([hidden])) .topbar #canvasTitleDock #boardTitle:focus,
html body:has(#editorView:not([hidden])) .topbar #canvasTitleDock #boardTitle.is-editing{
 border-bottom-color:var(--accent)!important;
 box-shadow:none!important;
}


/* 2026-10-22 · precise follow-up (test Canvas only).
   The visible curve gets thinner; keep the full 16px invisible edge hit
   target, so users can still select/cut the line without pixel hunting. */
#canvasViewport #connectionSvg .edge-path{
 stroke-width:1px!important;
}
#canvasViewport #connectionSvg .edge-path.selected{
 stroke-width:1.55px!important;
}
#canvasViewport #connectionSvg path.pending{stroke-width:1px!important}

/* Align the 35px capsule to the actual vertical centre of the zoom dock.
   canvas-dock-layout-v1.js measures this on viewport/inspector resize. */
html body:has(#editorView:not([hidden])) .topbar #boardHead.canvas-status-dock:not([hidden]){
 bottom:var(--canvas-dock-status-bottom,18px)!important;
}

/* Exact same base yellow as the upper-left DAAILOK brand mark. */
html body:has(#editorView:not([hidden])) #editorView #canvasAddBtn.canvas-add-button,
html body:has(#editorView:not([hidden])) #editorView #canvasAddBtn.canvas-add-button:hover,
html body:has(#editorView:not([hidden])) #editorView #canvasAddBtn.canvas-add-button[aria-expanded="true"]{
 background:#f1cb7d!important;
 background-image:none!important;
 color:#222014!important;
}

/* Palette selection color is uniform in both light/dark modes.
   Never use black or silver for an unselected icon on light backgrounds.
   The grid's pressed state and the Assets/Guide active states stay wired to
   their real functions. Frame/shot follows actual node selection. */
html body[data-theme="dark"]:has(#editorView:not([hidden])) #editorView>.palette.glass>button:not(#canvasAddBtn),
html body[data-theme="light"]:has(#editorView:not([hidden])) #editorView>.palette.glass>button:not(#canvasAddBtn){
 color:#fff!important;
 text-shadow:none!important;
}
html body:has(#editorView:not([hidden])) #editorView>.palette.glass>button:not(#canvasAddBtn) :is(small,span,svg),
html body:has(#editorView:not([hidden])) #editorView>.palette.glass>button:not(#canvasAddBtn) svg *{
 color:inherit!important;
}
html body[data-theme="dark"]:has(#editorView:not([hidden])) #editorView>.palette.glass>button:is(.is-active,[aria-pressed="true"],.canvas-click-gold,:active,:focus-visible):not(#canvasAddBtn),
html body[data-theme="light"]:has(#editorView:not([hidden])) #editorView>.palette.glass>button:is(.is-active,[aria-pressed="true"],.canvas-click-gold,:active,:focus-visible):not(#canvasAddBtn){
 color:#f6d65e!important;
}
html body:has(#editorView:not([hidden])) #editorView>.palette.glass>button:not(#canvasAddBtn):hover:not(.is-active):not([aria-pressed="true"]):not(.canvas-click-gold):not(:active){
 color:#fff!important;
}

/* Light image card corner regression: the padded GPU lens had squared
   transparent-gutter background corners; the header also had a straight
   rectangular film. Round BOTH surfaces while preserving overflow for the
   yellow connection ports and the resize grip. */
html body[data-theme="light"] #nodesLayer>.canvas-node.image-node{
 border-radius:14px!important;
}
html body[data-theme="light"] #nodesLayer>.canvas-node.image-node>.node-header{
 border-radius:13px 13px 0 0!important;
 background-clip:padding-box!important;
}
html body[data-theme="light"] #nodesLayer>.canvas-node.image-node[data-canvas-optics]>.canvas-glass-render,
html body[data-theme="light"] #nodesLayer>.canvas-node.image-node[data-canvas-optics-ready]>.canvas-glass-render{
 border-radius:14px!important;
 clip-path:inset(var(--canvas-node-optic-gutter,8px) round 14px)!important;
 -webkit-clip-path:inset(var(--canvas-node-optic-gutter,8px) round 14px)!important;
}


/* 2026-10-24: finer hairlines, unchanged 16px invisible hit geometry. */
#canvasViewport #connectionSvg .edge-path{
 stroke-width:.5px!important;
 filter:none!important;
}
#canvasViewport #connectionSvg .edge-path.selected{
 stroke-width:.9px!important;
 filter:none!important;
}
#canvasViewport #connectionSvg path.pending{stroke-width:.5px!important}

/* The new alignment control uses the same real toggled state/colors and
   existing liquid glass button materials as the Grid/Assets/Guide controls. */
html body:has(#editorView:not([hidden])) #editorView>.palette.glass #canvasAlignBtn .canvas-align-icon{
 display:block!important;
 width:22px!important;height:22px!important;flex:none!important;
}

/* Make zoom controls equal in OUTER height to the 35px status capsule.
   Keep buttons legible while shrinking vertical padding and separator. */
html body:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass,
html body[data-theme="light"]:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass,
html body[data-theme="dark"]:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass{
 box-sizing:border-box!important;
 height:35px!important;min-height:35px!important;max-height:35px!important;
 padding:3px 6px!important;
 display:flex!important;align-items:center!important;
}
html body:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass>button{
 box-sizing:border-box!important;
 height:27px!important;min-height:27px!important;max-height:27px!important;
 padding:0 8px!important;
 display:inline-flex!important;align-items:center!important;justify-content:center!important;
 line-height:27px!important;
}
html body:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass>.tool-separator{
 height:17px!important;
}
html body:has(#editorView:not([hidden])) #editorView>#canvasShell>.zoom-controls.glass>#zoomLabel{
 line-height:27px!important;
}


/* 2026-10-28: the floating node toolbar replaces the fixed top action bar.
 * Keep its buttons in the DOM for keyboard shortcuts and legacy hooks. */
html body #editorView > #canvasShell > .canvas-toptools.glass{display:none!important}
html body #canvasViewport{cursor:crosshair}
html body #canvasViewport.panning{cursor:grabbing}
html body #canvasViewport #marquee{border:1px solid #f0c633!important;background:rgba(240,198,51,.11)!important;border-radius:2px;box-shadow:0 0 0 1px rgba(240,198,51,.13);pointer-events:none}
#canvasViewport > #canvasImageToolbarLayer.canvas-image-toolbar-layer{z-index:20!important}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools{
 position:absolute!important;display:flex!important;align-items:center!important;
 gap:5px!important;padding:6px 8px!important;max-width:calc(100% - 16px);
 border:1px solid var(--edge)!important;border-radius:13px!important;
 background:color-mix(in srgb,var(--glass) 92%,transparent)!important;
 backdrop-filter:blur(24px) saturate(145%)!important;
 -webkit-backdrop-filter:blur(24px) saturate(145%)!important;
 box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 12px 30px rgba(0,0,0,.24)!important;
 pointer-events:auto!important;white-space:nowrap!important;z-index:21!important;
 font:12px/1.4 system-ui,sans-serif!important;color:var(--text)!important;
}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools[hidden]{display:none!important}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools .canvas-multi-count{
 color:var(--muted);font-size:11px;padding:4px 8px 4px 3px;border-right:1px solid var(--edge);
}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools button{
 color:var(--text);background:transparent;border:1px solid transparent;
 border-radius:8px;padding:7px 9px;font:inherit;cursor:pointer;
}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools button:hover,
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools.is-move-armed [data-multi-action="move"]{
 color:#f0c633;background:rgba(240,198,51,.1);border-color:rgba(240,198,51,.25);
}
#canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools button[hidden]{display:none!important}
body[data-theme="light"] #canvasViewport > #canvasImageToolbarLayer .canvas-multi-tools{
 box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 10px 28px rgba(40,45,45,.15)!important;
}

/* Crop drag: isolate repaints to selection box, not the entire glass canvas. */
.canvas-crop-pane{contain:layout style paint!important;touch-action:none!important}
.canvas-crop-box{will-change:left,top,width,height;pointer-events:none!important}
.node-port.port-in[hidden]{display:none!important}
