/* ============================================================
   CANVAS BUILDER
   Scoped styles for the Fabric.js postcard editor.
   Matches the existing app button, panel, and tab patterns.
   ============================================================ */

#canvas-builder-section {
  position: relative;
  margin-top: 16px;
  padding-bottom: 96px;
  background: var(--ps-bg);
  border: 1px solid var(--ps-border);
  border-radius: 12px;
  color: var(--ps-dark);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}

.preview-image-container.canvas-builder-mode {
  display: flex;
  flex-direction: column;
  grid-column: 1 / -1;
  position: static;
}

.preview-image-container.canvas-builder-mode ~ .customize-panel {
  grid-column: 1 / -1;
}

.preview-image-container.canvas-builder-mode #canvas-builder-section {
  order: 1;
  margin-top: 0;
  margin-bottom: 0;
}

.preview-image-container.canvas-builder-mode .preview-tabs,
.preview-image-container.canvas-builder-mode #proof-wrapper {
  display: none;
}

#canvas-builder-toolbar {
  position: relative;
  /* 15 (was 5): the toolbar forms a stacking context, so its dropdowns
     (Insert Item, color menus — z-index:100 INSIDE this context) compete at
     the toolbar's own level against siblings. The Layers drawer sits at
     z-index:10; at 5 the drawer painted OVER any open toolbar dropdown and
     swallowed its clicks. 15 keeps open menus above the drawer while staying
     far below the hoisted HSV picker (1200). */
  z-index: 15;
  width: 100%;
  background: var(--ps-white);
  border-bottom: 1px solid var(--ps-border);
  border-radius: 12px 12px 0 0;
  /* Overlay the image toolbar onto the (always-present) text toolbar by
     placing both in the SAME grid cell. Total toolbar height is driven
     by the text toolbar at any width, so it stays CONSTANT whether or
     not an image is selected — the canvas below never reflows and no
     blank space is reserved. */
  display: grid;
  grid-template-columns: 1fr;
}

.cb-top-bar { grid-area: 1 / 1; }
#cb-text-toolbar { grid-area: 2 / 1; }
#cb-image-toolbar {
  grid-area: 2 / 1;
  background: var(--ps-white);
  z-index: 1;
}
#cb-object-toolbar { grid-area: 3 / 1; }

#cb-canvas-stage {
  display: block;
}

.cb-top-bar,
#cb-object-toolbar,
#cb-text-toolbar,
#cb-image-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 24px;
}

#cb-object-toolbar,
#cb-text-toolbar,
#cb-image-toolbar {
  border-top: 1px solid var(--ps-border);
  font-size: 13px;
}

#cb-object-toolbar-main,
#cb-crop-controls {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

#canvas-builder-toolbar button {
  background: var(--ps-white);
  border: 1px solid var(--ps-border);
  min-height: var(--ps-btn-height-sm);
  padding: 0 14px;
  border-radius: var(--ps-btn-radius);
  color: var(--ps-dark);
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}

#canvas-builder-toolbar button:hover {
  background: var(--ps-orange-hover);
  border-color: var(--ps-orange-hover);
  color: var(--ps-white);
}

#canvas-builder-toolbar button:active {
  background: var(--ps-orange-active);
  border-color: var(--ps-orange-active);
  color: var(--ps-white);
}

#canvas-builder-toolbar button.is-active {
  background: var(--ps-orange);
  border-color: var(--ps-orange);
  color: var(--ps-white);
}

#canvas-builder-toolbar button:disabled,
#canvas-builder-toolbar select:disabled,
#canvas-builder-toolbar input:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

#cb-object-toolbar button,
#cb-text-toolbar button,
#cb-image-toolbar button {
  padding: 0 12px;
  font-size: 13px;
}

#cb-object-toolbar label,
#cb-text-toolbar label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ps-gray);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.cb-typography-control {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ps-gray);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.cb-typography-control input[type="range"] {
  width: 80px;
  accent-color: var(--ps-orange);
}

.cb-typography-control output {
  min-width: 32px;
  font-size: 12px;
  font-weight: 700;
  color: var(--ps-dark);
  text-align: right;
}

.cb-toolbar-label {
  color: var(--ps-gray);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.cb-template-save-modal {
  max-width: 420px;
  text-align: left;
}

.cb-template-save-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
  color: var(--ps-dark);
  font-size: 13px;
  font-weight: 600;
}

.cb-template-save-note {
  margin-top: -4px;
  margin-bottom: 20px;
  color: var(--ps-gray);
  font-size: 13px;
  line-height: 1.5;
}

.cb-template-save-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

#canvas-builder-toolbar select {
  min-height: var(--ps-btn-height-sm);
  padding: 0 12px;
  border: 1px solid var(--ps-border);
  border-radius: 8px;
  background: var(--ps-white);
  color: var(--ps-dark);
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.2s, box-shadow 0.2s;
}

#canvas-builder-toolbar select:focus {
  outline: none;
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 3px rgba(18, 130, 146, 0.1);
}

#canvas-builder-toolbar .cb-fontsize-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}

#canvas-builder-toolbar #cb-font-size {
  width: 48px;
  min-height: var(--ps-btn-height-sm);
  padding: 0 8px;
  border: 1px solid var(--ps-border);
  border-radius: 8px;
  background: var(--ps-white);
  color: var(--ps-dark);
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  transition: border-color 0.2s, box-shadow 0.2s;
}

#canvas-builder-toolbar #cb-font-size:focus {
  outline: none;
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 3px rgba(18, 130, 146, 0.1);
}

#canvas-builder-toolbar #cb-font-size-preset {
  width: 34px;
  min-width: 34px;
  padding: 0 4px;
  cursor: pointer;
}

#canvas-builder-toolbar .cb-color-picker {
  width: 36px;
  min-width: 36px;
  height: 32px;
  padding: 2px;
  border: 1px solid var(--ps-border);
  border-radius: 8px;
  background: var(--ps-white);
  cursor: pointer;
}

#canvas-builder-toolbar .cb-color-picker::-webkit-color-swatch-wrapper {
  padding: 0;
}

#canvas-builder-toolbar .cb-color-picker::-webkit-color-swatch {
  border: none;
  border-radius: 5px;
}

#canvas-builder-toolbar .cb-color-picker::-moz-color-swatch {
  border: none;
  border-radius: 5px;
}

#canvas-builder-toolbar .cb-color-picker:focus {
  outline: none;
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 3px rgba(18, 130, 146, 0.1);
}

#cb-object-toolbar input[type="range"] {
  width: 120px;
  accent-color: var(--ps-orange);
}

#cb-crop-controls {
  margin-left: auto;
}

#cb-crop-controls .cb-crop-apply {
  background: var(--ps-orange);
  border-color: var(--ps-orange);
  color: var(--ps-white);
}

#cb-crop-controls .cb-crop-apply:hover,
#cb-crop-controls .cb-crop-apply:active {
  background: var(--ps-orange-hover);
  border-color: var(--ps-orange-hover);
  color: var(--ps-white);
}

#cb-crop-controls .cb-crop-cancel {
  background: transparent;
  border-color: var(--ps-border);
  color: var(--ps-dark);
}

#cb-crop-controls .cb-crop-cancel:hover,
#cb-crop-controls .cb-crop-cancel:active {
  background: rgba(31, 41, 51, 0.06);
  border-color: var(--ps-border);
  color: var(--ps-dark);
}

/* Canvas Editor Figma-parity Slice 4 — top bar arrangement.
   DOM now provides two explicit wrappers (.cb-top-bar-left / -right);
   parent uses justify-content:space-between. Slice 1's flex-order hacks
   are removed because the DOM matches the visual order directly. */
.cb-top-bar {
  justify-content: space-between;
}

.cb-top-bar-left,
.cb-top-bar-right {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.cb-top-bar-left > .cb-side-toggle {
  /* Override the default margin-left:auto used when side-toggle sits
     directly in a single-row flex container. The left wrapper already
     anchors the toggle on the LEFT. */
  margin-left: 0;
}

.cb-dropdown {
  position: relative;
}

.cb-color-chip {
  width: 14px;
  height: 14px;
  border-radius: 999px;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.12);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.45);
}

.cb-color-menu {
  min-width: 248px;
  padding: 12px;
}

.cb-insert-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 6px;
}

.cb-insert-section + .cb-insert-section {
  border-top: 1px solid var(--ps-border);
}

.cb-insert-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ps-gray);
}

.cb-palette-grid,
.cb-palette-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.cb-palette-grid {
  margin-bottom: 12px;
}

.cb-color-cluster {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* ============================================================
   Canvas Editor Figma-parity Slice 4 — text toolbar layout
   - Single row: Font Family · Size · Style group · Color · badge
   - Group labels SIT ABOVE their controls (Figma layout):
     direct-child <label> of #cb-text-toolbar flips to column.
   - Style group = labeled pill cluster of B/I/U + popout triggers
     + Auto-fit, rendered as a single grouped pill.
   - Color cluster anchors to the RIGHT via margin-left:auto.
   - Popout anchoring is preserved: each .cb-inline-popout keeps
     position:relative (defined below), so absolutely-positioned
     menus inside still anchor to their own trigger even when
     nested inside .cb-style-group__buttons.
   ============================================================ */
#cb-text-toolbar {
  flex-wrap: nowrap;
  align-items: flex-end;
  row-gap: 4px;
  column-gap: 14px;
}

#cb-text-toolbar > label {
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

.cb-style-group {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

.cb-style-group__label {
  /* Inherits .cb-toolbar-label baseline; column layout above places it
     directly over the pill cluster, matching Figma "Style" group label. */
  display: inline-block;
  padding-left: 4px;
}

.cb-style-group__buttons {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--ps-border);
  border-radius: 999px;
  background: var(--ps-white);
}

/* Style-group buttons render borderless inside the grouped pill so the
   container's outer rounded border is the visual frame. The .is-active
   / hover / active states from the global toolbar button rules
   continue to drive the orange highlight. */
#canvas-builder-toolbar .cb-style-group__buttons > button,
#canvas-builder-toolbar .cb-style-group__buttons > .cb-inline-popout > button {
  border-color: transparent;
  background: transparent;
  min-height: 30px;
  padding: 0 10px;
}

/* Line-spacing trigger (replaces the dead .cb-popout-dot span).
   Size-match the other Style pills so it doesn't look smaller or
   clip the 16×16 glyph. */
#canvas-builder-toolbar .cb-style-group__buttons .cb-popout-dot-trigger {
  width: auto;
  min-width: 34px;
  height: 30px;
  padding: 0 8px;
  border-radius: 999px;
}

.cb-line-spacing-icon {
  display: block;
  width: 16px;
  height: 16px;
}

/* Color cluster anchors right; sits visually centered on the row. */
#cb-text-toolbar > .cb-color-cluster {
  margin-left: auto;
  align-self: center;
}

#cb-text-toolbar > #cb-text-overflow-badge {
  align-self: center;
}

/* ============================================================
   Slice 4 — top-bar pill polish.
   Light pill/rounded touches on Base Color, Insert Item triggers
   and the Dynamic Field select to match the Figma rounded pills.
   ============================================================ */
#canvas-builder-toolbar #cb-btn-bg-color,
#canvas-builder-toolbar #cb-btn-insert,
#canvas-builder-toolbar #cb-btn-preview {
  border-radius: 999px;
  padding: 0 16px;
}

#canvas-builder-toolbar #cb-token-control select {
  border-radius: 999px;
  padding: 0 14px;
}

/* ============================================================
   Slice 4 — image toolbar visual polish.
   Filter slider min/max/value mapping is UNCHANGED (handled by JS
   at canvas-builder.js ~2204–2218). Visual-only restyle: label
   layout above sliders + pill Reset.
   ============================================================ */
#cb-image-toolbar {
  align-items: flex-end;
  column-gap: 16px;
}

#cb-image-toolbar .cb-typography-control {
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

#cb-image-toolbar [data-action="reset-filters"] {
  border-radius: 999px;
  padding: 0 16px;
  align-self: center;
}

.cb-inline-popout {
  position: relative;
  display: inline-flex;
  align-items: center;
}

#canvas-builder-toolbar .cb-popout-dot-trigger,
#canvas-builder-toolbar .cb-align-trigger {
  min-width: 32px;
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 999px;
}

.cb-inline-popout-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  display: flex;
  padding: 12px;
  border: 1px solid var(--ps-border);
  border-radius: 12px;
  background: var(--ps-white);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  transform: translateX(-50%);
  z-index: 120;
}

.cb-inline-popout-menu--typography {
  align-items: flex-end;
  gap: 16px;
}

.cb-vertical-slider-control {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--ps-gray);
  font-size: 12px;
  font-weight: 600;
}

.cb-vertical-slider-control > span {
  white-space: nowrap;
}

.cb-vertical-slider-control input[type="range"] {
  width: 18px;
  height: 120px;
  margin: 4px 0;
  accent-color: var(--ps-orange);
  -webkit-appearance: slider-vertical;
  appearance: slider-vertical;
  writing-mode: vertical-lr;
  direction: rtl;
}

.cb-vertical-slider-control output {
  min-width: 40px;
  color: var(--ps-dark);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
}

.cb-inline-popout-menu--align {
  flex-direction: column;
  gap: 4px;
  min-width: 56px;
  padding: 6px;
}

#canvas-builder-toolbar .cb-inline-popout-menu--align button {
  min-width: 0;
  width: 100%;
  padding: 8px 10px;
  justify-content: center;
}

#canvas-builder-toolbar .cb-swatch {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: var(--cb-swatch-color, var(--ps-white));
  position: relative;
  overflow: hidden;
  transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}

#canvas-builder-toolbar .cb-swatch:hover {
  background: var(--cb-swatch-color, var(--ps-white));
  border-color: rgba(31, 41, 51, 0.28);
  box-shadow: 0 0 0 2px rgba(31, 41, 51, 0.08);
  color: inherit;
}

#canvas-builder-toolbar .cb-swatch:active {
  background: var(--cb-swatch-color, var(--ps-white));
  border-color: rgba(31, 41, 51, 0.28);
  box-shadow: 0 0 0 2px rgba(31, 41, 51, 0.08);
  color: inherit;
}

#canvas-builder-toolbar .cb-swatch.is-selected {
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 2px rgba(18, 130, 146, 0.14);
}

.cb-swatch-fill {
  display: none;
}

.cb-swatch[data-bg-color="#ffffff"],
.cb-swatch[data-font-color="#ffffff"],
.cb-swatch[data-box-color="#ffffff"],
.cb-swatch[data-object-color="#ffffff"] { --cb-swatch-color: #ffffff; }

.cb-swatch[data-bg-color="#dbeaf6"],
.cb-swatch[data-font-color="#dbeaf6"],
.cb-swatch[data-box-color="#dbeaf6"],
.cb-swatch[data-object-color="#dbeaf6"] { --cb-swatch-color: #dbeaf6; }

.cb-swatch[data-bg-color="#2d84c6"],
.cb-swatch[data-font-color="#2d84c6"],
.cb-swatch[data-box-color="#2d84c6"],
.cb-swatch[data-object-color="#2d84c6"] { --cb-swatch-color: #2d84c6; }

.cb-swatch[data-bg-color="#1b5f92"],
.cb-swatch[data-font-color="#1b5f92"],
.cb-swatch[data-box-color="#1b5f92"],
.cb-swatch[data-object-color="#1b5f92"] { --cb-swatch-color: #1b5f92; }

.cb-swatch[data-bg-color="#c68b55"],
.cb-swatch[data-font-color="#c68b55"],
.cb-swatch[data-box-color="#c68b55"],
.cb-swatch[data-object-color="#c68b55"] { --cb-swatch-color: #c68b55; }

.cb-swatch[data-bg-color="#9b5d2d"],
.cb-swatch[data-font-color="#9b5d2d"],
.cb-swatch[data-box-color="#9b5d2d"],
.cb-swatch[data-object-color="#9b5d2d"] { --cb-swatch-color: #9b5d2d; }

.cb-swatch[data-bg-color="#6b3f1f"],
.cb-swatch[data-font-color="#6b3f1f"],
.cb-swatch[data-box-color="#6b3f1f"],
.cb-swatch[data-object-color="#6b3f1f"] { --cb-swatch-color: #6b3f1f; }

.cb-swatch[data-bg-color="#1f2933"],
.cb-swatch[data-font-color="#1f2933"],
.cb-swatch[data-box-color="#1f2933"],
.cb-swatch[data-object-color="#1f2933"] { --cb-swatch-color: #1f2933; }

.cb-color-custom {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  color: var(--ps-gray);
  font-size: 13px;
  font-weight: 600;
}

.cb-color-custom-inputs {
  display: inline-flex;
  align-items: center;
  gap: 0;
}

.cb-align-icon {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}

.cb-align-icon span {
  display: block;
  height: 2px;
  border-radius: 999px;
  background: currentColor;
}

.cb-align-icon span:nth-child(1) { width: 12px; }
.cb-align-icon span:nth-child(2) { width: 16px; }
.cb-align-icon span:nth-child(3) { width: 10px; }

.cb-align-center {
  align-items: center;
}

.cb-align-right {
  align-items: flex-end;
}

.cb-dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 360px;
  padding: 6px;
  background: var(--ps-white);
  border: 1px solid var(--ps-border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  z-index: 100;
}

.cb-dropdown-menu button:not(.cb-swatch) {
  width: 100%;
  justify-content: flex-start;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--ps-dark);
  padding: 0 12px;
}

.cb-dropdown-menu button:not(.cb-swatch):hover {
  background: var(--ps-bg);
  border-color: transparent;
  color: var(--ps-dark);
}

.cb-dropdown-menu button:not(.cb-swatch):active {
  background: rgba(18, 130, 146, 0.08);
  border-color: transparent;
  color: var(--ps-orange);
}

.cb-chip-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.cb-chip-grid--shapes {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

#canvas-builder-toolbar .cb-chip-btn {
  min-height: 34px;
  width: 100%;
  padding: 0 10px;
  justify-content: center;
  border: 1px solid var(--ps-border);
  border-radius: 999px;
  background: var(--ps-bg);
  color: var(--ps-dark);
}

#canvas-builder-toolbar .cb-chip-btn:hover {
  background: var(--ps-orange-hover);
  border-color: var(--ps-orange-hover);
  color: var(--ps-white);
}

.cb-chip-grid--emoji {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}

.cb-chip-btn--emoji {
  font-size: 20px !important;
  line-height: 1;
}

.cb-chip-btn--emoji-action {
  min-width: 112px;
}

.cb-emoji-entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
}

.cb-qr-entry {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
}

.cb-emoji-input {
  min-height: 36px;
  padding: 0 12px;
  border: 1px solid var(--ps-border);
  border-radius: 10px;
  background: var(--ps-white);
  color: var(--ps-dark);
  font-size: 14px;
  font-family: inherit;
}

.cb-emoji-input:focus {
  outline: none;
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 3px rgba(18, 130, 146, 0.1);
}

.cb-side-toggle {
  display: inline-flex;
  align-items: stretch;
  margin-left: auto;
  border: 1px solid var(--ps-border);
  border-radius: var(--ps-btn-radius);
  overflow: hidden;
  background: var(--ps-white);
}

.cb-side-toggle button {
  border: 0;
  border-right: 1px solid var(--ps-border);
  border-radius: 0;
}

.cb-side-toggle button:last-child {
  border-right: none;
}

.cb-side-toggle button.active {
  background: var(--ps-orange);
  color: var(--ps-white);
}

#canvas-front-wrap,
#canvas-back-wrap {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 24px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

#canvas-builder-section.cb-single-sided #canvas-front-wrap {
  align-items: flex-start;
}

#canvas-front-wrap > canvas,
#canvas-back-wrap > canvas,
#canvas-front-wrap .canvas-container,
#canvas-back-wrap .canvas-container {
  flex: 0 0 auto;
  margin: 0 auto;
  background: var(--ps-white);
  border: 1px solid rgba(223, 225, 228, 0.9);
  border-radius: 8px;
  box-shadow: 0 8px 20px rgba(61, 61, 61, 0.08);
}

#canvas-front-wrap.cb-crop-active .canvas-container,
#canvas-back-wrap.cb-crop-active .canvas-container {
  box-shadow: 0 0 0 2px rgba(18, 130, 146, 0.18), 0 8px 20px rgba(61, 61, 61, 0.08);
}

#canvas-builder-section.cb-preview-layout #cb-canvas-stage {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  padding: 24px;
  align-items: start;
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap {
  display: flex !important;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  gap: 10px;
  min-width: 0;
  padding: 0;
  overflow: visible;
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap::before,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap::before {
  display: block;
  padding: 0 4px;
  color: var(--ps-gray);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap::before {
  content: 'Front';
}

#canvas-builder-section.cb-preview-layout #canvas-back-wrap::before {
  content: 'Back';
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap > canvas,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap > canvas,
#canvas-builder-section.cb-preview-layout #canvas-front-wrap .canvas-container,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap .canvas-container {
  width: 100% !important;
  max-width: 100%;
  margin: 0;
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap .canvas-container,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap .canvas-container {
  height: auto !important;
  aspect-ratio: 600 / 408;
}

#canvas-builder-section.cb-preview-layout #canvas-front-wrap canvas,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap canvas,
#canvas-builder-section.cb-preview-layout #canvas-front-wrap .lower-canvas,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap .lower-canvas,
#canvas-builder-section.cb-preview-layout #canvas-front-wrap .upper-canvas,
#canvas-builder-section.cb-preview-layout #canvas-back-wrap .upper-canvas {
  width: 100% !important;
  height: 100% !important;
}

#canvas-builder-section canvas,
#canvas-builder-section .lower-canvas,
#canvas-builder-section .upper-canvas {
  display: block;
  border-radius: 8px;
}

.cb-guide-overlay {
  position: absolute;
  display: none;
  pointer-events: none;
  overflow: visible;
  z-index: 20;
}

.cb-guide-line {
  position: absolute;
  background: rgba(18, 130, 146, 0.9);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9);
}

.cb-guide-line--horizontal {
  height: 2px;
  transform: translateY(-1px);
}

.cb-guide-line--vertical {
  width: 2px;
  transform: translateX(-1px);
}

.cb-guide-line--snap {
  background: rgba(18, 130, 146, 0.6);
  box-shadow: none;
}

.cb-guide-line--snap.cb-guide-line--horizontal {
  height: 1px;
  transform: none;
}

.cb-guide-line--snap.cb-guide-line--vertical {
  width: 1px;
  transform: none;
}

.cb-guide-label {
  position: absolute;
  transform: translate(-50%, -50%);
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(18, 130, 146, 0.92);
  color: #ffffff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 4px 10px rgba(14, 51, 58, 0.18);
}

#cb-approval-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 24px;
  background: var(--ps-white);
  border-top: 1px solid var(--ps-border);
  box-shadow: 0 -6px 18px rgba(61, 61, 61, 0.08);
}

#cb-approval-bar span {
  flex: 1 1 320px;
  color: var(--ps-dark);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
}

#cb-approval-bar a {
  color: var(--ps-orange);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}

#cb-approval-bar a:hover {
  text-decoration: underline;
}

#cb-approval-bar button {
  min-height: var(--ps-btn-height);
  padding: 0 24px;
  border-radius: var(--ps-btn-radius);
  font-size: 18px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}

#cb-btn-revise {
  background: var(--ps-white);
  color: var(--ps-orange);
  border: 1px solid var(--ps-border);
}

#cb-btn-revise:hover {
  background: var(--ps-orange-hover);
  border-color: var(--ps-orange-hover);
  color: var(--ps-white);
}

#cb-btn-revise:active {
  background: var(--ps-orange-active);
  border-color: var(--ps-orange-active);
  color: var(--ps-white);
}

#cb-btn-approve {
  background: var(--ps-orange);
  color: var(--ps-white);
  border: 1px solid transparent;
}

#cb-btn-approve:hover {
  background: var(--ps-orange-hover);
}

#cb-btn-approve:active {
  background: var(--ps-orange-active);
  border-color: var(--ps-orange-active);
}

.cb-error {
  color: #c62828;
  font-weight: 600;
}

.product-card--saved {
  position: relative;
}

.product-card-delete {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.06);
  color: var(--ps-gray);
  font-size: 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, color 0.2s;
}

.product-card-delete:hover {
  background: #c62828;
  color: #ffffff;
}

.product-grid-empty {
  grid-column: 1 / -1;
  padding: 48px 24px;
  text-align: center;
  color: var(--ps-gray);
  font-size: 14px;
  line-height: 1.6;
}

.product-meta {
  font-size: 12px;
  color: var(--ps-gray);
  margin-top: 2px;
}

@media (max-width: 768px) {
  #canvas-builder-section {
    padding-bottom: 144px;
  }

  .cb-top-bar,
  #cb-object-toolbar,
  #cb-text-toolbar,
  #cb-approval-bar {
    padding: 12px 16px;
    gap: 8px;
  }

  /* Slice 4: desktop pins the text toolbar to one row via nowrap; on
     mobile we let it wrap so controls don't horizontal-scroll. */
  #cb-text-toolbar {
    flex-wrap: wrap;
  }

  .cb-side-toggle {
    margin-left: 0;
  }

  .cb-chip-grid--shapes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .cb-chip-grid--emoji {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  #canvas-front-wrap,
  #canvas-back-wrap {
    justify-content: flex-start;
    padding: 16px;
  }

  .cb-inline-popout-menu {
    left: 0;
    transform: none;
  }

  #canvas-builder-section.cb-preview-layout #cb-canvas-stage {
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 16px;
  }

  #cb-approval-bar span {
    flex-basis: 100%;
  }

  #cb-approval-bar button {
    width: 100%;
  }
}


/* =========================================================================
 * Canvas Layers / Elements panel — js/canvas-layers.js
 * ========================================================================= */

#cb-canvas-stage { position: relative; }

/* Loading state during product switch: hide previous product's canvas pixels
 * (visibility:hidden preserves layout space so wrappers don't collapse) and
 * show a centered spinner while the new template fetches + parses. Toggled
 * by showCanvasBuilder() in js/canvas-builder-view.js. */
#cb-canvas-stage.cb-canvas-stage--loading > #canvas-front-wrap,
#cb-canvas-stage.cb-canvas-stage--loading > #canvas-back-wrap {
  visibility: hidden;
}
#cb-canvas-stage.cb-canvas-stage--loading::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  border-radius: 50%;
  border: 3px solid #d7e9fb;
  border-top-color: #1565c0;
  animation: campaigns-spin 0.8s linear infinite;
  z-index: 1;
  pointer-events: none;
}

.cb-layers-drawer {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 300px;
  background: #ffffff;
  border-left: 1px solid #e5e7eb;
  display: flex;
  flex-direction: column;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 13px;
  color: #1f2937;
  z-index: 10;
  transition: transform 0.2s ease-out;
  overflow: hidden;
  max-height: calc(100vh - var(--cb-layers-viewport-top, 0px) - 16px);
}
.cb-layers-drawer.collapsed {
  /* Hide the drawer entirely when collapsed. The previous
     `transform: translateX(calc(100% - 6px))` slide-out assumed the
     drawer was anchored to viewport.right, but it's `position: absolute;
     right: 0` relative to #cb-canvas-stage, whose right edge is < viewport
     width on standard layouts. The translation pushed the drawer past the
     stage right and into off-viewport area, creating a horizontal page
     scrollbar and leaving ~130px of drawer visible on the wrong side.
     Reopen path: toolbar [data-layers-toggle] button (already wired). */
  display: none;
}

.cb-layers-header {
  padding: 10px 12px;
  border-bottom: 1px solid #e5e7eb;
  background: #f9fafb;
}
.cb-layers-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cb-layers-title {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: #111827;
}
.cb-layers-close {
  background: none;
  border: none;
  color: #6b7280;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.cb-layers-close:hover { background: #e5e7eb; color: #111827; }

.cb-layers-tabs {
  display: flex;
  gap: 12px;
  margin-top: 8px;
}
.cb-layers-tab {
  background: none;
  border: none;
  padding: 4px 0;
  color: #6b7280;
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  border-bottom: 2px solid transparent;
}
.cb-layers-tab[aria-selected="true"] {
  color: #128292;
  border-bottom-color: #128292;
}
.cb-layers-tab:hover { color: #111827; }

.cb-layers-search {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-size: 12px;
  margin-top: 8px;
  background: #ffffff;
  box-sizing: border-box;
}

.cb-layers-list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.cb-layers-empty {
  padding: 20px 16px;
  color: #9ca3af;
  font-size: 12px;
  text-align: center;
}

.cb-layer-row {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 8px 12px;
  min-height: 44px;
  border-bottom: 1px solid #f3f4f6;
  cursor: pointer;
  outline: none;
  position: relative;
}
.cb-layer-row:focus-visible {
  outline: 2px solid #128292;
  outline-offset: -2px;
}
.cb-layer-row:hover { background: #f9fafb; }
.cb-layer-row.is-selected {
  background: #e0f2f1;
  box-shadow: inset 3px 0 0 #128292;
}
.cb-layer-row.is-hidden .cb-layer-name,
.cb-layer-row.is-hidden .cb-layer-icon { opacity: 0.45; }
.cb-layer-row.is-locked { cursor: default; }
.cb-layer-row.is-locked .cb-layer-name { opacity: 0.6; }

.cb-layer-icon {
  font-size: 14px;
  text-align: center;
  color: #6b7280;
}
.cb-layer-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}
.cb-layer-rename {
  border: 1px solid #128292;
  border-radius: 4px;
  padding: 2px 6px;
  font-size: 13px;
  font-family: inherit;
  width: 100%;
  box-sizing: border-box;
}

.cb-layer-actions {
  display: none;
  gap: 2px;
}
.cb-layer-row:hover .cb-layer-actions,
.cb-layer-row:focus-within .cb-layer-actions,
.cb-layer-row.is-selected .cb-layer-actions,
.cb-layer-row.is-hidden .cb-layer-actions { display: flex; }
@media (hover: none) {
  .cb-layer-actions { display: flex; }
}
.cb-layer-btn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  width: 28px;
  height: 28px;
  padding: 0;
  font-size: 13px;
  cursor: pointer;
  color: #4b5563;
}
.cb-layer-btn:hover,
.cb-layer-btn:focus-visible {
  background: #f3f4f6;
  border-color: #d1d5db;
  outline: none;
  color: #111827;
}
.cb-layer-btn--danger:hover { color: #b91c1c; }

@media (hover: none) {
  .cb-layer-btn { width: 40px; height: 40px; font-size: 15px; }
}

.cb-layers-footer-btn {
  display: block;
  width: 100%;
  padding: 10px 12px;
  background: #f9fafb;
  border: none;
  border-top: 1px solid #e5e7eb;
  color: #128292;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  text-align: center;
}
.cb-layers-footer-btn:hover { background: #f3f4f6; }

.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* Context menu */
.cb-layers-context {
  position: fixed;
  list-style: none;
  margin: 0;
  padding: 4px 0;
  background: #ffffff;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
  font-size: 13px;
  min-width: 180px;
  z-index: 1000;
}
.cb-layers-context-item {
  padding: 8px 14px;
  cursor: pointer;
  color: #1f2937;
  white-space: nowrap;
}
.cb-layers-context-item:hover,
.cb-layers-context-item:focus-visible {
  background: #f3f4f6;
  outline: none;
}
.cb-layers-context-item.is-destructive { color: #b91c1c; }
.cb-layers-context-item.is-destructive:hover { background: #fee2e2; }
.cb-layers-context-divider {
  height: 1px;
  background: #e5e7eb;
  margin: 4px 0;
}

/* Toast */
.cb-layers-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: #1f2937;
  color: #ffffff;
  padding: 10px 16px 10px 18px;
  border-radius: 24px;
  display: flex;
  align-items: center;
  gap: 14px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  font-size: 13px;
  z-index: 1001;
  animation: cb-toast-slide 0.25s ease-out;
}
.cb-layers-toast button {
  background: #c68b55;
  color: #ffffff;
  border: none;
  padding: 5px 12px;
  border-radius: 14px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
}
.cb-layers-toast button:hover { background: #b17a48; }
@keyframes cb-toast-slide {
  from { transform: translate(-50%, 100%); opacity: 0; }
  to   { transform: translate(-50%, 0);    opacity: 1; }
}

/* Hidden-layer save modal */
.cb-layers-modal-backdrop {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}
.cb-layers-modal {
  background: #ffffff;
  border-radius: 10px;
  padding: 24px;
  max-width: 460px;
  width: calc(100% - 32px);
  box-shadow: 0 12px 40px rgba(0,0,0,0.25);
}
.cb-layers-modal h3 {
  margin: 0 0 10px;
  font-size: 16px;
  color: #111827;
}
.cb-layers-modal p {
  margin: 0 0 18px;
  font-size: 13px;
  color: #4b5563;
  line-height: 1.5;
}
.cb-layers-modal-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
}
.cb-layers-modal-btn {
  padding: 8px 14px;
  border: 1px solid #d1d5db;
  background: #ffffff;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
}
.cb-layers-modal-btn:hover { background: #f9fafb; }
.cb-layers-modal-btn.is-primary {
  background: #128292;
  color: #ffffff;
  border-color: #128292;
}
.cb-layers-modal-btn.is-primary:hover { background: #0e6b79; }

/* Mobile / iPad responsive */
@media (max-width: 768px) {
  .cb-layers-drawer {
    width: 100%;
    transform: translateX(100%);
  }
  .cb-layers-drawer.open { transform: translateX(0); }
  .cb-layer-row { min-height: 52px; padding: 10px 14px; }
}


/* =========================================================================
 * Canvas Layers v2 — Ryan's feedback 2026-04-18
 * SVG icons replace emoji chrome; click+drag replaces arrow buttons on desktop.
 * ========================================================================= */

/* SVG icons inside action buttons inherit color from button state */
.cb-layer-btn svg { width: 16px; height: 16px; pointer-events: none; vertical-align: middle; }
.cb-layer-icon svg { width: 16px; height: 16px; pointer-events: none; }
.cb-layers-footer-btn svg { width: 14px; height: 14px; vertical-align: middle; margin-left: 4px; }

/* Emoji-asset layers keep the user's actual emoji (user content, not chrome) */
.cb-layer-icon-emoji {
  font-size: 16px;
  line-height: 1;
  display: inline-block;
  text-align: center;
}

/* Toolbar Layers button icon */
[data-layers-toggle] svg {
  vertical-align: middle;
  margin-right: 2px;
}

/* Drag visual feedback */
.cb-layer-row.is-dragging { opacity: 0.4; cursor: grabbing; }
.cb-layer-row.drop-indicator-before {
  box-shadow: inset 0 2px 0 #128292;
}
.cb-layer-row.drop-indicator-after  {
  box-shadow: inset 0 -2px 0 #128292;
}
.cb-layer-row[draggable="true"] { cursor: grab; }
.cb-layer-row.is-locked[draggable="false"] { cursor: default; }
.cb-layer-row[draggable="true"]:active { cursor: grabbing; }

/* Arrow buttons: hidden on pointer-capable devices (drag replaces them per Ryan).
   Visible on touch (no hover) and in the Overlapping tab (where drag is disabled). */
.cb-layer-btn[data-layers-action="move-up"],
.cb-layer-btn[data-layers-action="move-down"] { display: none; }

@media (hover: none) {
  .cb-layer-btn[data-layers-action="move-up"],
  .cb-layer-btn[data-layers-action="move-down"] { display: inline-flex; align-items: center; justify-content: center; }
}

.cb-layers-drawer[data-active-tab="overlapping"] .cb-layer-btn[data-layers-action="move-up"],
.cb-layers-drawer[data-active-tab="overlapping"] .cb-layer-btn[data-layers-action="move-down"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ============================================================
   Build Your Own — blank canvas card + dialogs + callout
   ============================================================ */

.product-card--blank {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 20px 16px;
  /* #114 UX: neutral dashed border for the "create" affordance. The old teal
     dashed (rgba(18,130,146,.55)) read as an active/selected card because teal
     is the brand accent used by .product-card.selected. Gray dashed keeps the
     "blank/create" signal without looking pre-selected; hover still goes orange. */
  border: 2px dashed var(--ps-border);
  background: linear-gradient(135deg, #f3fafb 0%, #fff 100%);
  color: var(--ps-teal, #128292);
  text-align: center;
  font-family: inherit;
  cursor: pointer;
}

.product-card--blank:hover {
  border-color: var(--ps-orange);
  background: linear-gradient(135deg, #e9f6f8 0%, #fff 100%);
}

.product-card--blank:focus-visible {
  outline: 3px solid rgba(18, 130, 146, 0.55);
  outline-offset: 2px;
}

.product-card-illustration {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  color: var(--ps-teal, #128292);
}

.product-card-illustration svg {
  width: 56%;
  height: auto;
}

.product-card-illustration img {
  width: 56%;
  height: auto;
  object-fit: contain;
  display: block;
}

.product-card--blank .product-name {
  font-weight: 700;
  font-size: 15px;
  color: #0f3b44;
}

.product-card-subtitle {
  font-size: 13px;
  color: #4a6c72;
}

.product-card-helper {
  font-size: 12px;
  color: #6b8a90;
}

/* Native <dialog> common styling — Ryan shipped other modals as overlays, but
   the blank-canvas flow uses native dialog for focus-trap + ESC-close parity. */
.cb-blank-size-modal,
.cb-blank-swap-confirm,
.cb-blank-empty-warning {
  border: none;
  border-radius: 14px;
  padding: 28px 28px 24px;
  max-width: 420px;
  width: calc(100% - 32px);
  color: var(--ps-dark, #1c1c1c);
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.24);
  font-family: inherit;
  margin: auto;
}

.cb-blank-size-modal::backdrop,
.cb-blank-swap-confirm::backdrop,
.cb-blank-empty-warning::backdrop {
  background: rgba(15, 25, 30, 0.48);
}

.cb-blank-size-modal h2,
.cb-blank-swap-confirm h2,
.cb-blank-empty-warning h2 {
  margin: 0 0 8px;
  font-size: 20px;
  font-weight: 700;
}

.cb-blank-size-help {
  margin: 0 0 20px;
  color: var(--ps-gray, #6b7280);
  font-size: 13px;
}

.cb-blank-size-option {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--ps-border, #e5e7eb);
  border-radius: 10px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.cb-blank-size-option:hover {
  border-color: var(--ps-teal, #128292);
  background: #f6fbfc;
}

.cb-blank-size-option:has(input:checked) {
  border-color: var(--ps-teal, #128292);
  background: #e9f6f8;
}

.cb-blank-size-option input[type="radio"] {
  accent-color: var(--ps-teal, #128292);
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.cb-blank-size-label {
  font-weight: 600;
  flex: 1;
  text-align: left;
}

.cb-blank-size-price {
  font-size: 13px;
  color: var(--ps-gray, #6b7280);
}

.cb-blank-size-actions,
.cb-blank-swap-actions,
.cb-blank-empty-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

.cb-blank-swap-confirm p,
.cb-blank-empty-warning p {
  margin: 0 0 16px;
  color: var(--ps-dark, #1c1c1c);
  font-size: 14px;
  line-height: 1.5;
}

.cb-blank-callout {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 460px;
  margin: 12px auto;
  padding: 12px 16px;
  background: #fff8e1;
  border: 1px solid #f5d26a;
  border-radius: 10px;
  font-size: 14px;
  color: #5c4500;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
}

.cb-blank-callout-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}

.cb-blank-callout-icon {
  font-size: 18px;
}

.cb-blank-callout-dismiss {
  padding: 6px 12px;
  font-size: 13px;
}

@media (max-width: 480px) {
  .cb-blank-size-modal,
  .cb-blank-swap-confirm,
  .cb-blank-empty-warning {
    width: calc(100% - 24px);
    padding: 20px;
  }
}

/* ============================================================
   Slice 2 (#153) — Font Color / Box Color triggers + Custom HSV picker.
   Markup lives in index.html under .cb-color-cluster. The two triggers
   reuse the Base Color .cb-dropdown / .cb-color-menu / .cb-palette-grid
   patterns; only the new pieces below are slice-specific.
   ============================================================ */

/* Pill-shape triggers (parity with Base Color, css:508-513). */
#canvas-builder-toolbar #cb-btn-font-color,
#canvas-builder-toolbar #cb-btn-box-color {
  border-radius: 999px;
  padding: 0 16px;
}

/* Per-trigger chip variants. Inherits geometry from .cb-color-chip
   (css:362-369); per-instance background-color is written from JS in
   _syncToolbarState (CSP-safe runtime style). */
.cb-color-chip--font,
.cb-color-chip--box {
  background: #ffffff;
}

/* Custom row variant — used inside each Font/Box dropdown. */
.cb-color-custom--swatch {
  width: 100%;
  justify-content: space-between;
}

/* Current-swatch chip — shows the active custom color for the trigger. */
#canvas-builder-toolbar .cb-swatch--current {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  background: var(--cb-swatch-color, #ffffff);
  cursor: default;
}

/* "+" circular add button opens the singleton HSV picker. */
#canvas-builder-toolbar .cb-custom-add {
  width: 28px;
  height: 28px;
  min-width: 28px;
  border-radius: 999px;
  padding: 0;
  border: 1px solid var(--ps-border);
  background: var(--ps-white);
  color: var(--ps-dark);
  font-size: 18px;
  line-height: 1;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Singleton HSV picker is a direct child of #canvas-builder-section (already
   `position:relative`, css:7-8). It is HOISTED OUT of the toolbar because
   `#canvas-builder-toolbar` has `position:relative; z-index:15` and forms a
   stacking context — historically (z-index:5) any popout inside was trapped
   under the Layers panel (z-index:10, sibling-level context); the toolbar now
   sits above the drawer, but the picker stays hoisted for its JS positioning.
   `top`/`left` are written from JS (`_positionCustomPickerNearTrigger`) so
   the picker still appears near the Font/Box trigger the user clicked.
   `z-index: 1200` keeps it above the Layers panel and its context menu
   (z-index 1000-1100 range). */
.cb-custom-picker {
  position: absolute;
  top: 0;
  left: 0;
  width: 232px;
  padding: 14px;
  border: 1px solid var(--ps-border);
  border-radius: 12px;
  background: var(--ps-white);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.cb-custom-picker__close {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  background: transparent;
  font-size: 18px;
  line-height: 1;
  color: var(--ps-gray);
  cursor: pointer;
}

.cb-custom-picker__sv {
  position: relative;
  width: 100%;
  height: 140px;
  border-radius: 8px;
  cursor: crosshair;
  touch-action: none;
  /* Background gradient written from JS in _repaintCustomPicker. */
}

.cb-custom-picker__sv-thumb {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 999px;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.cb-custom-picker__hue {
  position: relative;
  width: 100%;
  height: 14px;
  border-radius: 999px;
  background: linear-gradient(
    to right,
    #ff0000 0%,
    #ffff00 17%,
    #00ff00 33%,
    #00ffff 50%,
    #0000ff 67%,
    #ff00ff 83%,
    #ff0000 100%
  );
  cursor: pointer;
  touch-action: none;
}

.cb-custom-picker__hue-thumb {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  border-radius: 999px;
  border: 2px solid #fff;
  background: transparent;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.cb-custom-picker__row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.cb-custom-picker__eyedrop {
  width: 30px;
  height: 30px;
  min-width: 30px;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--ps-border);
  background: var(--ps-white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.cb-custom-picker__rgb {
  flex: 1;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: var(--ps-gray);
  font-size: 11px;
  font-weight: 700;
}

.cb-custom-picker__rgb input {
  width: 100%;
  min-height: 28px;
  padding: 0 4px;
  border: 1px solid var(--ps-border);
  border-radius: 6px;
  background: var(--ps-white);
  color: var(--ps-dark);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
}

.cb-custom-picker__rgb input:focus {
  outline: none;
  border-color: var(--ps-orange);
  box-shadow: 0 0 0 3px rgba(18, 130, 146, 0.1);
}

/* ============================================================
   DESIGN YOUR OWN — guided placeholder zones (blank-canvas FRONT).
   DOM/CSS overlay framed to the front .canvas-container by
   syncDesignYourOwnZones(). Container is pointer-events:none so gaps
   between zones pass clicks through to the canvas; each zone button
   re-enables pointer events. Dashed outer frame = ::before. Refs #153
   ============================================================ */
.cb-dyo-overlay {
  position: absolute;
  pointer-events: none;
  z-index: 6;
}

.cb-dyo-overlay::before {
  content: '';
  position: absolute;
  inset: -6px;
  border: 1.5px dashed #7fa8bd;
  border-radius: 6px;
  pointer-events: none;
}

.cb-dyo-overlay .cb-dyo-zone {
  position: absolute;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  cursor: pointer;
  font-family: inherit;
  color: #5b6b78;
  background: rgba(255, 255, 255, 0.04);
  border: 1.5px solid #8a929b;
  border-radius: 4px;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.cb-dyo-overlay .cb-dyo-zone:hover,
.cb-dyo-overlay .cb-dyo-zone:focus-visible {
  border-color: #128292;
  background: rgba(18, 130, 146, 0.06);
  outline: none;
}

.cb-dyo-zone-label {
  pointer-events: none;
  font-size: 13px;
  font-weight: 500;
}

/* Specificity must match the base `.cb-dyo-overlay .cb-dyo-zone` (0,2,0) so the
   filled-gray, borderless Figma look actually wins; hover/focus (0,3,0) still
   overrides for interactive feedback. */
.cb-dyo-overlay .cb-dyo-zone--image {
  background: #e9edf0;
  border-color: transparent; /* Figma: filled image box, no border */
}

.cb-dyo-img-icon {
  width: 30px;
  height: 30px;
  color: #8a99a6;
  pointer-events: none;
}

/* Desktop-only guard: the Fabric canvas + toolbar are fixed-width (~936px min)
   and overflow below ~980px. Editor is desktop-only (product decision) — below
   the breakpoint show a notice instead of a silently-broken/overflowing editor.
   CSS-only, no JS: the media query only restyles children while
   #canvas-builder-section is shown by JS. Above the breakpoint nothing changes. */
#canvas-builder-section .cb-desktop-only-notice { display: none; }

@media (max-width: 979px) {
  #canvas-builder-section #canvas-builder-toolbar,
  #canvas-builder-section #cb-canvas-stage {
    display: none !important;
  }
  #canvas-builder-section .cb-desktop-only-notice {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 320px;
    padding: 24px;
  }
  .cb-desktop-only-inner {
    max-width: 420px;
    margin: 0 auto;
    text-align: center;
    background: #fff8e1;
    border: 1px solid #f5d26a;
    border-radius: 12px;
    padding: 28px 24px;
    color: #5c4500;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
  }
  .cb-desktop-only-icon { font-size: 40px; display: block; margin-bottom: 8px; }
  .cb-desktop-only-title { font-size: 18px; margin: 0 0 6px; }
  .cb-desktop-only-text { font-size: 14px; line-height: 1.5; margin: 0; }
}

/* ============================================================
   GUARD RAILS (Ryan 2026-08-06)
   Dashed cut-line frame on the safe area + persistent low-res banner.
   ============================================================ */

.cb-cutline-frame {
  position: absolute;
  /* Lighter than the first cut (Ryan 2026-08-07: "do they need to be quite
     that big?") — a guide, not a design element. */
  border: 1px dashed rgba(18, 130, 146, 0.6);
  border-radius: 2px;
  pointer-events: none;
  z-index: 3;
}

/* Clean preview: the frame is an editing aid, never part of the artwork. */
#canvas-builder-section.cb-preview-layout .cb-cutline-frame { display: none; }

.cb-lowres-banner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 12px;
  padding: 12px 16px;
  background: #37424c;
  color: #ffffff;
  border-radius: 8px;
}

.cb-lowres-banner-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13px;
  line-height: 1.45;
}

.cb-lowres-banner-text strong { font-size: 14px; }

.cb-lowres-banner-close {
  background: none;
  border: none;
  color: #ffffff;
  font-size: 16px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
  flex: 0 0 auto;
}

.cb-lowres-banner-close:hover { opacity: 0.75; }

.cb-lowres-banner--pulse { animation: cb-lowres-pulse 0.45s ease 2; }

@keyframes cb-lowres-pulse {
  50% {
    transform: scale(1.01);
    box-shadow: 0 0 0 3px rgba(198, 40, 40, 0.45);
  }
}
