.empty,
.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--sb-branch-bar-height, 0px));
  font-family: var(--tc-font-stack, system-ui, -apple-system, sans-serif);
  color: var(--color-foreground-muted, #656d76);
  font-size: 16px;
}

.empty p,
.loading p {
  margin: 0;
}

.canvasScroll {
  position: relative;
  width: 100vw;
  height: calc(100vh - var(--sb-branch-bar-height, 0px));
  overflow: auto;
  background-color: var(--sb--canvas-bg, var(--color-background-muted, #f6f8fa));
  /* Allow single-finger pan, suppress browser pinch-zoom + double-tap
   * zoom on the canvas surface. The custom pinch-to-zoom handler on
   * document drives the canvas's own zoom transform instead — without
   * this, browser visual-viewport zoom would scale the entire UI
   * (toolbar, controls) along with the canvas content. */
  touch-action: pan-x pan-y;
}

/* Flow-layout mode — the canvas behaves like a normal document: it sizes
 * to its contents, supports natural page scrolling, and lets the consumer
 * style widgets with author CSS (including @media queries). The
 * absolute-mode chrome (fixed viewport sizing, zoom, marquee, pan) is
 * disabled in CanvasPage.jsx via the `isFlowLayout` branch. */
.canvasScroll[data-layout="flow"] {
  width: 100%;
  height: auto;
  min-height: calc(100vh - var(--sb-branch-bar-height, 0px));
  overflow: visible;
  background-color: transparent;
}

@media (prefers-color-scheme: dark) {
  .canvasScroll {
    background-color: var(--sb--canvas-bg, var(--color-background-muted, #161b22));
  }
  .canvasScroll[data-layout="flow"] {
    background-color: transparent;
  }
}

.canvasZoom {
  position: relative;
  min-width: 100%;
  min-height: 100%;
}

.canvasZoom[data-layout="flow"] {
  min-width: 0;
  min-height: 0;
  width: auto;
  height: auto;
  transform: none;
}

/* GPU compositing hint during active zoom gestures — applied imperatively
   via data-zooming attribute and removed on zoom-end to avoid permanent
   memory pressure on the large canvas surface. */
.canvasZoom[data-zooming] {
  will-change: transform;
}

/* Selection outline is now handled by WidgetChrome.module.css (.widgetSlotSelected) */

.canvasLogo {
  width: 32px;
  height: 32px;
  background: var(--color-background-emphasis, #313131);
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-foreground-on-emphasis, #fff);
  flex-shrink: 0;
  text-decoration: none;
  transform: rotate(-1deg);
}

.canvasTitle {
  position: fixed;
  top: calc(12px + var(--sb-branch-bar-height, 0px));
  left: 16px;
  height: min-content;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
}

.canvasTitleStatic {
  font-family: var(--tc-font-stack, system-ui, -apple-system, sans-serif);
  font-size: 14px;
  font-weight: 600;
  color: var(--color-foreground-muted, #656d76);
  margin: 0;
  padding: 4px 8px;
  white-space: nowrap;
}

.canvasTitleEditing {
  font-family: var(--tc-font-stack, system-ui, -apple-system, sans-serif);
  font-size: 14px;
  font-weight: 600;
  color: var(--color-foreground, #1f2328);
  margin: 0;
  padding: 3px 7px;
  white-space: nowrap;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.15));
  border-radius: 4px;
  background: var(--color-background, #fff);
  outline: none;
}

.canvasTitleEditing:focus {
  border-color: var(--color-border-accent-emphasis, #0969da);
  box-shadow: 0 0 0 2px rgba(9, 105, 218, 0.3);
}

/* Remove tiny-canvas wrapper clipping — widgets handle their own overflow/radius */
:global(.tc-draggable-inner) {
  overflow: visible;
}

/* Each widget gets its own stacking context so internal z-index
   (chrome toolbars, resize handles, overlays) never leaks to siblings.
   z-index: 2 keeps widgets above the ConnectorLayer (z-index: 1).
   Selected widgets are raised via z-index on the .tc-drag wrapper
   (data-widget-raised) instead of DOM reordering — this prevents
   iframe widgets from remounting when selection changes.
   The actively dragged widget (.tc-on from neodrag) floats above
   everything so it always passes over siblings during movement. */
:global(.tc-drag) {
  isolation: isolate;
  z-index: 2;
}

:global(.tc-drag:has([data-widget-raised])) {
  z-index: 3;
}

:global(.tc-drag:hover) {
  z-index: 3;
}

:global(.tc-drag.tc-on) {
  z-index: 4;
}

.ghInstallBanner {
  position: fixed;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  z-index: 15;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--color-border, #d1d9e0);
  background: color-mix(in srgb, var(--color-background, #ffffff) 88%, transparent);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.16);
  backdrop-filter: blur(8px);
  font-size: 12px;
  color: var(--color-foreground, #1f2328);
}

.ghInstallBannerText {
  white-space: nowrap;
}

.ghInstallBannerText code {
  font-size: 11px;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--color-background-muted, #f6f8fa);
}

.ghInstallBannerLink {
  color: var(--color-foreground-accent, #0969da);
  font-weight: 600;
  text-decoration: none;
}

.ghInstallBannerLink:hover {
  text-decoration: underline;
}

.ghInstallBannerDismiss {
  border: 1px solid var(--color-border, #d1d9e0);
  background: var(--color-background, #ffffff);
  color: var(--color-foreground, #1f2328);
  border-radius: 6px;
  font-size: 11px;
  padding: 4px 8px;
  cursor: pointer;
}

.ghInstallBannerDismiss:hover {
  background: var(--color-background-muted, #f6f8fa);
}

/* Marquee selection rectangle */
.marqueeRect {
  position: absolute;
  background: rgba(56, 132, 255, 0.12);
  border: 1.5px solid rgba(56, 132, 255, 0.6);
  border-radius: 2px;
  pointer-events: none;
  z-index: 9999;
}

/* Hide canvas nav when toolbars are hidden */
:global(html.storyboard-chrome-hidden) .canvasTitle {
  display: none;
}
