/* ---------- Canvas viewport ---------- */
.viewport-card {
  background: var(--bg-surface);
  border: 1px solid var(--bd-1);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
}
.viewport-toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--bd-2);
}
.viewport-toolbar .vp-name {
  font-size: 14px; font-weight: 600; color: var(--fg-strong);
  letter-spacing: -0.2px;
}
.viewport-toolbar .vp-meta {
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  color: var(--fg-muted);
  display: inline-flex; align-items: center; gap: 6px;
}
.viewport-toolbar .vp-meta .dot { width: 6px; height: 6px; border-radius: 999px; background: var(--accent-2); }
.viewport-toolbar .spacer { flex: 1; }

.viewport {
  position: relative;
  background: var(--bg-app);
  flex: 1;
  overflow: hidden;
  min-height: 0;
}
[data-theme="dark"] .viewport {
  background: var(--bg-app);
}
.viewport-inner { position: absolute; inset: 0; overflow: hidden; }

.canvas-wrap {
  position: absolute;
  transform-origin: 0 0;
  /* NOTE: do NOT add will-change:transform here. It rasterises the entire
     canvas layer at logical-pixel resolution and then scales it up, which
     blurs every element and grid dot at zoom > 1.  Individual elements set
     will-change only while actively being dragged (cleared on pointerup). */
}

.canvas {
  position: relative;
  background: #ffffff;
  border: 1px solid var(--bd-1);
  border-radius: 6px;
  box-shadow: var(--shadow-pop);
  overflow: visible; /* elements may extend beyond canvas bounds */
  /* background-color only — gradient image must NOT be in the transition.
     A background-image transition prevents the browser from GPU-caching the
     gradient as a compositor texture, causing repaints on every drag frame. */
  transition: background-color 150ms;
}

/* Ghost-border indicator lines rendered at each canvas edge an element crosses.
   Four variants (top/right/bottom/left) are inset-positioned absolute divs
   that span only the portion of the edge where the element overlaps. */
.canvas-edge-indicator {
  position: absolute;
  pointer-events: none;
  z-index: 20;
  background: repeating-linear-gradient(
    90deg,
    rgba(237, 100, 60, 0.75) 0px,
    rgba(237, 100, 60, 0.75) 5px,
    transparent 5px,
    transparent 9px
  );
}
.canvas-edge-indicator.vertical {
  background: repeating-linear-gradient(
    180deg,
    rgba(237, 100, 60, 0.75) 0px,
    rgba(237, 100, 60, 0.75) 5px,
    transparent 5px,
    transparent 9px
  );
}
/* Background colours */
.canvas.bg-sand { background-color: #F3F1E4; }
.canvas.bg-dark { background-color: #0A0E1F; }

/* Grid overlays — layer on top of any background colour */
.canvas.grid-dot {
  background-image: radial-gradient(#c8c9d0 1px, transparent 1px);
  background-size: 16px 16px;
}
.canvas.grid-lined {
  background-image:
    linear-gradient(to right, #e0e1e6 1px, transparent 1px),
    linear-gradient(to bottom, #e0e1e6 1px, transparent 1px);
  background-size: 16px 16px;
}
/* Lighter grid on dark backgrounds */
.canvas.bg-dark.grid-dot {
  background-image: radial-gradient(rgba(255,255,255,0.18) 1px, transparent 1px);
  background-size: 16px 16px;
}
.canvas.bg-dark.grid-lined {
  background-image:
    linear-gradient(to right, rgba(255,255,255,0.09) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,0.09) 1px, transparent 1px);
  background-size: 16px 16px;
}
/* Backwards-compat: old serialised values that stored grid in background field */
.canvas.bg-dot  { background-image: radial-gradient(#c8c9d0 1px, transparent 1px); background-size: 16px 16px; }
.canvas.bg-grid {
  background-image:
    linear-gradient(to right, #e0e1e6 1px, transparent 1px),
    linear-gradient(to bottom, #e0e1e6 1px, transparent 1px);
  background-size: 16px 16px;
}

/* Rulers */
.ruler {
  position: absolute;
  background: var(--bg-surface-2);
  color: var(--fg-muted);
  font-size: 9px;
  border: 1px solid var(--bd-2);
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
}
.ruler.top { top: 0; left: 16px; right: 0; height: 16px; }
.ruler.left { top: 16px; left: 0; bottom: 0; width: 16px; }
.ruler-corner {
  position: absolute;
  top: 0; left: 0; width: 16px; height: 16px;
  background: var(--bg-surface-2);
  border: 1px solid var(--bd-2);
  z-index: 4;
  pointer-events: none;
}
.viewport.with-rulers .viewport-inner { top: 16px; left: 16px; }

/* Background swatch picker — floats at top-right corner of the canvas (positioned via inline style) */
.vp-bg-swatches {
  position: absolute;
  display: flex; gap: 5px; align-items: center;
  z-index: 6;
}
.vp-bg-label {
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.4px; text-transform: uppercase;
  color: var(--fg-muted); white-space: nowrap;
}
.vp-bg-swatch {
  width: 20px; height: 20px;
  border-radius: 999px;
  border: none; padding: 0;
  cursor: pointer; flex-shrink: 0;
  position: relative;
}
.vp-bg-swatch::after {
  content: ""; position: absolute; inset: 1px;
  border-radius: 999px; border: 1px solid rgba(0,0,0,0.07);
  pointer-events: none;
}
/* Dark swatch needs a visible outline when sitting on dark backgrounds */
.vp-bg-swatch[title="Dark"]::after { border-color: rgba(255,255,255,0.22); }
[data-theme="dark"] .vp-bg-swatch[title="Dark"]::after { border-color: rgba(255,255,255,0.45); }

/* Edge-to-edge viewport card inside the stage */
.stage > .viewport-card { border: none; border-radius: 0; }

/* Marquee (rubber-band) selection rectangle */
.marquee-rect {
  position: absolute;
  border: 1.5px solid var(--accent-1, #5AA7E5);
  background: rgba(90, 167, 229, 0.09);
  border-radius: 3px;
  pointer-events: none;
  z-index: 5;
}

/* Snap guide overlay */
.snap-guides-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 4; overflow: hidden; }
.snap-guide { position: absolute; background: var(--accent-1, #0D9EFF); opacity: 0.85; }
.snap-guide-v { top: 0; bottom: 0; width: 1px; transform: translateX(-0.5px); }
.snap-guide-h { left: 0; right: 0; height: 1px; transform: translateY(-0.5px); }
/* Canvas center guides get a distinct pink color so they're easy to spot */
.snap-guide.snap-guide-center { background: #F25CA2; opacity: 1; }

/* Zoom HUD */
.zoom-hud {
  position: absolute;
  bottom: 16px; right: 16px;
  display: flex; align-items: center; gap: 2px;
  background: rgb(255, 255, 255);
  border: 1px solid rgba(0,0,0,0.12);
  border-radius: var(--radius-pill);
  padding: 4px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.08);
  z-index: 6;
}
[data-theme="dark"] .zoom-hud {
  background: rgb(28, 30, 38);
  border-color: rgba(255,255,255,0.10);
  box-shadow: 0 2px 8px rgba(0,0,0,0.40), 0 1px 2px rgba(0,0,0,0.30);
}
.zoom-hud button {
  width: 28px; height: 28px;
  border: 0; background: transparent;
  border-radius: var(--radius-pill);
  color: var(--fg-default); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.zoom-hud button:hover { background: var(--bg-subtle); }
.zoom-hud-divider { width: 1px; height: 16px; background: var(--bd-1); margin: 0 2px; flex-shrink: 0; }
[data-theme="dark"] .zoom-hud-divider { background: rgba(255,255,255,0.10); }
.zoom-hud .pct {
  min-width: 52px; text-align: center;
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--fg-strong);
  padding: 0 6px;
}

/* ── Canvas selection ring ───────────────────────────────────────────────── */
/* Blue outline that frames the canvas in viewport-space when hovered.       */
.canvas-sel-ring {
  border: 2px solid var(--accent-1, #3b59ce);
  border-radius: 8px;
  box-shadow: var(--ring, 0 0 0 3px rgba(90,167,229,0.18));
}
[data-theme="dark"] .canvas-sel-ring {
  border-color: var(--accent-1, #5AA7E5);
  box-shadow: 0 0 0 3px rgba(90,167,229,0.22);
}

/* ── Canvas resize handles ───────────────────────────────────────────────── */
/* Hit zones sit in viewport space (same layer as vp-bg-swatches).          */
/* The .crh-pip matches the per-element selection corner / edge handles.     */
.crh {
  position: absolute;
  z-index: 200;
  pointer-events: auto;
}
.crh-pip {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 2px;
  opacity: 0;
  transition: opacity 140ms ease;
  pointer-events: none;
}
.crh:hover .crh-pip,
.crh.crh-active .crh-pip,
.crh.crh-show .crh-pip { opacity: 1; }

/* Edge pips — thin blue bars, no fill (matches sel-ring colour) */
.crh-right .crh-pip, .crh-left .crh-pip {
  width: 3px; height: 32px;
  background: var(--accent-1, #3b59ce);
  border-radius: 99px;
}
.crh-top .crh-pip, .crh-bottom .crh-pip {
  width: 32px; height: 3px;
  background: var(--accent-1, #3b59ce);
  border-radius: 99px;
}
/* Corner pips — white square with blue border (matches .el .handle exactly) */
.crh-tl .crh-pip, .crh-tr .crh-pip,
.crh-br .crh-pip, .crh-bl .crh-pip {
  width: 10px; height: 10px;
  background: var(--bg-surface, #fff);
  border: 2px solid var(--accent-1, #3b59ce);
  border-radius: 2px;
}
[data-theme="dark"] .crh-tl .crh-pip, [data-theme="dark"] .crh-tr .crh-pip,
[data-theme="dark"] .crh-br .crh-pip, [data-theme="dark"] .crh-bl .crh-pip {
  background: var(--bg-surface, #1c1e26);
}
